Anope IRC Services  Version 1.8
memoserv.c
Go to the documentation of this file.
1 /* MemoServ functions.
2 *
3 * (C) 2003-2014 Anope Team
4 * Contact us at team@anope.org
5 *
6 * Please read COPYING and README for further details.
7 *
8 * Based on the original code of Epona by Lara.
9 * Based on the original code of Services by Andy Church.
10 *
11 *
12 */
13 
14 #include "services.h"
15 #include "pseudo.h"
16 
17 /*************************************************************************/
18 /* *INDENT-OFF* */
19 
20 E void moduleAddMemoServCmds(void);
21 static void new_memo_mail(NickCore *nc, Memo *m);
22 E void rsend_notify(User *u, Memo *m, const char *chan);
23 
24 /*************************************************************************/
25 
28 }
29 
30 /*************************************************************************/
31 /*************************************************************************/
32 /* *INDENT-ON* */
33 
38 void ms_init(void)
39 {
41 }
42 
43 /*************************************************************************/
44 
54 void memoserv(User * u, char *buf)
55 {
56  char *cmd, *s;
57 
58  cmd = strtok(buf, " ");
59  if (!cmd) {
60  return;
61  } else if (stricmp(cmd, "\1PING") == 0) {
62  if (!(s = strtok(NULL, ""))) {
63  s = "";
64  }
65  anope_cmd_ctcp(s_MemoServ, u->nick, "PING %s", s);
66  } else if (skeleton) {
67  notice_lang(s_MemoServ, u, SERVICE_OFFLINE, s_MemoServ);
68  } else {
69  if (!u->na && stricmp(cmd, "HELP") != 0)
70  notice_lang(s_MemoServ, u, NICK_NOT_REGISTERED_HELP,
71  s_NickServ);
72  else
74  }
75 }
76 
77 /*************************************************************************/
78 
86 void check_memos(User * u)
87 {
88  NickCore *nc;
89  int i, newcnt = 0;
90 
91  if (!u) {
92  if (debug) {
93  alog("debug: check_memos called with NULL values");
94  }
95  return;
96  }
97 
98  if (!(nc = (u->na ? u->na->nc : NULL)) || !nick_recognized(u) ||
99  !(nc->flags & NI_MEMO_SIGNON)) {
100  return;
101  }
102 
103  for (i = 0; i < nc->memos.memocount; i++) {
104  if (nc->memos.memos[i].flags & MF_UNREAD)
105  newcnt++;
106  }
107  if (newcnt > 0) {
109  newcnt == 1 ? MEMO_HAVE_NEW_MEMO : MEMO_HAVE_NEW_MEMOS,
110  newcnt);
111  if (newcnt == 1 && (nc->memos.memos[i - 1].flags & MF_UNREAD)) {
112  notice_lang(s_MemoServ, u, MEMO_TYPE_READ_LAST, s_MemoServ);
113  } else if (newcnt == 1) {
114  for (i = 0; i < nc->memos.memocount; i++) {
115  if (nc->memos.memos[i].flags & MF_UNREAD)
116  break;
117  }
118  notice_lang(s_MemoServ, u, MEMO_TYPE_READ_NUM, s_MemoServ,
119  nc->memos.memos[i].number);
120  } else {
121  notice_lang(s_MemoServ, u, MEMO_TYPE_LIST_NEW, s_MemoServ);
122  }
123  }
124  if (nc->memos.memomax > 0 && nc->memos.memocount >= nc->memos.memomax) {
125  if (nc->memos.memocount > nc->memos.memomax)
126  notice_lang(s_MemoServ, u, MEMO_OVER_LIMIT, nc->memos.memomax);
127  else
128  notice_lang(s_MemoServ, u, MEMO_AT_LIMIT, nc->memos.memomax);
129  }
130 }
131 
132 /*************************************************************************/
133 /*********************** MemoServ private routines ***********************/
134 /*************************************************************************/
135 
144 MemoInfo *getmemoinfo(const char *name, int *ischan, int *isforbid)
145 {
146  if (*name == '#') {
147  ChannelInfo *ci;
148  if (ischan)
149  *ischan = 1;
150  ci = cs_findchan(name);
151  if (ci) {
152  if (!(ci->flags & CI_VERBOTEN)) {
153  *isforbid = 0;
154  return &ci->memos;
155  } else {
156  *isforbid = 1;
157  return NULL;
158  }
159  } else {
160  *isforbid = 0;
161  return NULL;
162  }
163  } else {
164  NickAlias *na;
165  if (ischan)
166  *ischan = 0;
167  na = findnick(name);
168  if (na) {
169  if (!(na->status & NS_VERBOTEN)) {
170  *isforbid = 0;
171  return &na->nc->memos;
172  } else {
173  *isforbid = 1;
174  return NULL;
175  }
176  } else {
177  *isforbid = 0;
178  return NULL;
179  }
180  }
181 }
182 
183 /*************************************************************************/
184 
198 void memo_send(User * u, char *name, char *text, int z)
199 {
200  memo_send_from(u, name, text, z, u->na->nc->display);
201 }
202 
217 void memo_send_from(User * u, char *name, char *text, int z, char *source)
218 {
219  int ischan;
220  int isforbid;
221  Memo *m;
222  MemoInfo *mi;
223  time_t now = time(NULL);
224  int is_servoper = is_services_oper(u);
225 
226  if (readonly) {
227  notice_lang(s_MemoServ, u, MEMO_SEND_DISABLED);
228  } else if (checkDefCon(DEFCON_NO_NEW_MEMOS)) {
229  notice_lang(s_MemoServ, u, OPER_DEFCON_DENIED);
230  return;
231  } else if (!text) {
232  if (z == 0)
233  syntax_error(s_MemoServ, u, "SEND", MEMO_SEND_SYNTAX);
234 
235  if (z == 3)
236  syntax_error(s_MemoServ, u, "RSEND", MEMO_RSEND_SYNTAX);
237 
238  } else if (!nick_recognized(u)) {
239  if (z == 0 || z == 3)
240  notice_lang(s_MemoServ, u, NICK_IDENTIFY_REQUIRED, s_NickServ);
241 
242  } else if (!(mi = getmemoinfo(name, &ischan, &isforbid))) {
243  if (z == 0 || z == 3) {
244  if (isforbid) {
246  ischan ? CHAN_X_FORBIDDEN :
247  NICK_X_FORBIDDEN, name);
248  } else {
250  ischan ? CHAN_X_NOT_REGISTERED :
251  NICK_X_NOT_REGISTERED, name);
252  }
253  }
254  } else if (z != 2 && MSSendDelay > 0 &&
255  u && u->lastmemosend + MSSendDelay > now && !is_servoper) {
256  u->lastmemosend = now;
257  if (z == 0)
258  notice_lang(s_MemoServ, u, MEMO_SEND_PLEASE_WAIT, MSSendDelay);
259 
260  if (z == 3)
261  notice_lang(s_MemoServ, u, MEMO_RSEND_PLEASE_WAIT,
262  MSSendDelay);
263 
264  } else if (mi->memomax == 0 && !is_servoper) {
265  if (z == 0 || z == 3)
266  notice_lang(s_MemoServ, u, MEMO_X_GETS_NO_MEMOS, name);
267 
268  } else if (mi->memocount >= 32767 || (mi->memomax > 0 && mi->memocount >= mi->memomax
269  && !is_servoper)) {
270  if (z == 0 || z == 3)
271  notice_lang(s_MemoServ, u, MEMO_X_HAS_TOO_MANY_MEMOS, name);
272 
273  } else {
274  u->lastmemosend = now;
275  mi->memocount++;
276  mi->memos = srealloc(mi->memos, sizeof(Memo) * mi->memocount);
277  m = &mi->memos[mi->memocount - 1];
278  memset(m->sender, '\0', sizeof(m->sender));
279  strscpy(m->sender, source, NICKMAX);
280  m->moduleData = NULL;
281  if (mi->memocount > 1) {
282  m->number = m[-1].number + 1;
283  if (m->number < 1) {
284  int i;
285  for (i = 0; i < mi->memocount; i++) {
286  mi->memos[i].number = i + 1;
287  }
288  }
289  } else {
290  m->number = 1;
291  }
292  m->time = time(NULL);
293  m->text = sstrdup(text);
294  m->flags = MF_UNREAD;
295 #ifdef USE_MYSQL
296  m->id = 0;
297 #endif
298  /* Set notify sent flag - DrStein */
299  if (z == 2) {
300  m->flags |= MF_NOTIFYS;
301  }
302  /* Set receipt request flag */
303  if (z == 3)
304  m->flags |= MF_RECEIPT;
305  if (z == 0 || z == 3)
306  notice_lang(s_MemoServ, u, MEMO_SENT, name);
307  if (!ischan) {
308  NickAlias *na;
309  NickCore *nc = (findnick(name))->nc;
310 
311  if (MSNotifyAll) {
312  if ((nc->flags & NI_MEMO_RECEIVE)
313  && get_ignore(name) == NULL) {
314  int i;
315 
316  for (i = 0; i < nc->aliases.count; i++) {
317  na = nc->aliases.list[i];
318  if (na->u && nick_identified(na->u))
319  notice_lang(s_MemoServ, na->u,
320  MEMO_NEW_MEMO_ARRIVED, source,
321  s_MemoServ, m->number);
322  }
323  } else {
324  if ((u = finduser(name)) && nick_identified(u)
325  && (nc->flags & NI_MEMO_RECEIVE))
326  notice_lang(s_MemoServ, u, MEMO_NEW_MEMO_ARRIVED,
327  source, s_MemoServ, m->number);
328  } /* if (flags & MEMO_RECEIVE) */
329  }
330  /* if (MSNotifyAll) */
331  /* let's get out the mail if set in the nickcore - certus */
332  if (nc->flags & NI_MEMO_MAIL)
333  new_memo_mail(nc, m);
334  } else {
335  struct c_userlist *cu, *next;
336  Channel *c;
337 
338  if (MSNotifyAll && (c = findchan(name))) {
339  for (cu = c->users; cu; cu = next) {
340  next = cu->next;
341  if (check_access(cu->user, c->ci, CA_MEMO)) {
342  if (cu->user->na
343  && (cu->user->na->nc->flags & NI_MEMO_RECEIVE)
344  && get_ignore(cu->user->nick) == NULL) {
345  notice_lang(s_MemoServ, cu->user,
346  MEMO_NEW_X_MEMO_ARRIVED,
347  c->ci->name, s_MemoServ,
348  c->ci->name, m->number);
349  }
350  }
351  }
352  } /* MSNotifyAll */
353  } /* if (!ischan) */
354  } /* if command is valid */
355 }
356 
357 /*************************************************************************/
364 int delmemo(MemoInfo * mi, int num)
365 {
366  int i;
367 
368  for (i = 0; i < mi->memocount; i++) {
369  if (mi->memos[i].number == num)
370  break;
371  }
372  if (i < mi->memocount) {
374  free(mi->memos[i].text); /* Deallocate memo text memory */
375  mi->memocount--; /* One less memo now */
376  if (i < mi->memocount) /* Move remaining memos down a slot */
377  memmove(mi->memos + i, mi->memos + i + 1,
378  sizeof(Memo) * (mi->memocount - i));
379  if (mi->memocount == 0) { /* If no more memos, free array */
380  free(mi->memos);
381  mi->memos = NULL;
382  }
383  return 1;
384  } else {
385  return 0;
386  }
387 }
388 
389 /*************************************************************************/
390 
391 static void new_memo_mail(NickCore * nc, Memo * m)
392 {
393  MailInfo *mail = NULL;
394 
395  if (!nc || !m)
396  return;
397 
398  mail = MailMemoBegin(nc);
399  if (!mail) {
400  return;
401  }
402  fprintf(mail->pipe, getstring2(NULL, MEMO_MAIL_TEXT1), nc->display);
403  fprintf(mail->pipe, "\n");
404  fprintf(mail->pipe, getstring2(NULL, MEMO_MAIL_TEXT2), m->sender,
405  m->number);
406  fprintf(mail->pipe, "\n\n");
407  fprintf(mail->pipe, "%s", getstring2(NULL, MEMO_MAIL_TEXT3));
408  fprintf(mail->pipe, "\n\n");
409  fprintf(mail->pipe, "%s", m->text);
410  fprintf(mail->pipe, "\n");
411  MailEnd(mail);
412  return;
413 }
414 
415 
416 /*************************************************************************/
417 /* Send receipt notification to sender. */
418 
419 void rsend_notify(User * u, Memo * m, const char *chan)
420 {
421  NickAlias *na;
422  NickCore *nc;
423  char text[256];
424  const char *fmt;
425 
426  /* Only send receipt if memos are allowed */
427  if ((!readonly) && (!checkDefCon(DEFCON_NO_NEW_MEMOS))) {
428 
429  /* Get nick alias for sender */
430  na = findnick(m->sender);
431 
432  if (!na) {
433  return;
434  }
435 
436  /* Get nick core for sender */
437  nc = na->nc;
438 
439  if (!nc) {
440  return;
441  }
442 
443  /* Text of the memo varies if the recepient was a
444  nick or channel */
445  if (chan) {
446  fmt = getstring(na, MEMO_RSEND_CHAN_MEMO_TEXT);
447  snprintf(text, sizeof(text), fmt, chan);
448  } else {
449  fmt = getstring(na, MEMO_RSEND_NICK_MEMO_TEXT);
450  snprintf(text, sizeof(text), "%s", fmt);
451  }
452 
453  /* Send notification */
454  memo_send(u, m->sender, text, 2);
455 
456  /* Notify recepient of the memo that a notification has
457  been sent to the sender */
458  notice_lang(s_MemoServ, u, MEMO_RSEND_USER_NOTIFICATION,
459  nc->display);
460  }
461 
462  /* Remove receipt flag from the original memo */
463  m->flags &= ~MF_RECEIPT;
464 
465  return;
466 }
Command * next
Definition: modules.h:202
char sender[NICKMAX]
Definition: services.h:494
E int readonly
Definition: extern.h:776
char nick[NICKMAX]
Definition: services.h:875
E int snprintf(char *buf, size_t size, const char *fmt,...)
Definition: compat.c:37
E NickAlias * findnick(const char *nick)
Definition: db-merger.c:1857
static void new_memo_mail(NickCore *nc, Memo *m)
Definition: memoserv.c:391
void ms_init(void)
Definition: memoserv.c:38
E int checkDefCon(int level)
Definition: operserv.c:1608
void memoserv(User *u, char *buf)
Definition: memoserv.c:54
E int nick_identified(User *u)
Definition: nickserv.c:1111
E int check_access(User *user, ChannelInfo *ci, int what)
Definition: chanserv.c:1974
#define NI_MEMO_RECEIVE
Definition: services.h:1295
E int stricmp(const char *s1, const char *s2)
Definition: compat.c:58
E void modules_core_init(int number, char **list)
Definition: modules.c:127
E void moduleCleanStruct(ModuleData **moduleData)
Definition: modules.c:2439
#define NS_VERBOTEN
Definition: services.h:1273
#define CI_VERBOTEN
Definition: services.h:725
#define getstring(na, index)
Definition: extern.h:731
E int MSNotifyAll
Definition: extern.h:417
void memo_send(User *u, char *name, char *text, int z)
Definition: memoserv.c:198
#define getstring2(nc, index)
Definition: extern.h:733
MemoInfo memos
Definition: services.h:552
E char * strscpy(char *d, const char *s, size_t len)
Definition: db-merger.c:1886
int16 memocount
Definition: services.h:505
ChannelInfo * ci
Definition: services.h:1001
E void syntax_error(char *service, User *u, const char *command, int msgnum)
Definition: language.c:295
char name[CHANMAX]
Definition: services.h:654
E void notice_lang(char *source, User *dest, int message,...)
Definition: send.c:169
void check_memos(User *u)
Definition: memoserv.c:86
E int nick_recognized(User *u)
Definition: nickserv.c:1131
E Channel * findchan(const char *chan)
Definition: channels.c:394
E char * sstrdup(const char *s)
Definition: memory.c:105
NickCore * nc
Definition: services.h:533
char * display
Definition: services.h:542
uint16 flags
Definition: services.h:492
#define MF_NOTIFYS
Definition: services.h:1270
struct smtp_message mail
Definition: smtp.h:125
void ** list
Definition: slist.h:21
E char * s_MemoServ
Definition: extern.h:286
uint32 flags
Definition: services.h:669
ModuleData * moduleData
Definition: services.h:496
int16 memomax
Definition: services.h:505
int delmemo(MemoInfo *mi, int num)
Definition: memoserv.c:364
char * text
Definition: services.h:495
FILE * pipe
Definition: services.h:1068
int16 count
Definition: slist.h:23
void memo_send_from(User *u, char *name, char *text, int z, char *source)
Definition: memoserv.c:217
#define NI_MEMO_SIGNON
Definition: services.h:1294
E User * finduser(const char *nick)
Definition: users.c:323
uint16 status
Definition: services.h:532
Command * c
Definition: ns_recover.c:17
E MailInfo * MailMemoBegin(NickCore *nc)
Definition: mail.c:153
E int MemoServCoreNumber
Definition: extern.h:489
E void alog(const char *fmt,...) FORMAT(printf
uint32 number
Definition: services.h:491
MemoInfo * getmemoinfo(const char *name, int *ischan, int *isforbid)
Definition: memoserv.c:144
E int debug
Definition: extern.h:775
#define MF_RECEIPT
Definition: services.h:1269
#define E
Definition: extern.h:18
E void MailEnd(MailInfo *mail)
Definition: mail.c:206
#define DEFCON_NO_NEW_MEMOS
Definition: services.h:1263
E int skeleton
Definition: extern.h:778
#define MEMOSERV
Definition: modules.h:58
#define CA_MEMO
Definition: services.h:761
#define NICKMAX
Definition: config.h:62
E void moduleAddMemoServCmds(void)
Definition: memoserv.c:26
MemoInfo memos
Definition: services.h:690
E IgnoreData * get_ignore(const char *nick)
Definition: process.c:106
SList aliases
Definition: services.h:559
E ChannelInfo * cs_findchan(const char *chan)
Definition: db-merger.c:2000
E void * srealloc(void *oldptr, long newsize)
Definition: memory.c:80
E int is_services_oper(User *u)
Definition: operserv.c:606
E int MSSendDelay
Definition: extern.h:416
uint32 flags
Definition: services.h:548
E char ** MemoServCoreModules
Definition: extern.h:488
time_t time
Definition: services.h:493
Memo * memos
Definition: services.h:506
MDE void mod_run_cmd(char *service, User *u, CommandHash *cmdTable[], const char *cmd)
Definition: commands.c:67
User * u
Definition: services.h:536
E char * s_NickServ
Definition: extern.h:284
E void anope_cmd_ctcp(char *source, char *dest, const char *fmt,...)
Definition: ircd.c:672
#define MF_UNREAD
Definition: services.h:1268
time_t lastmemosend
Definition: services.h:912
E void rsend_notify(User *u, Memo *m, const char *chan)
Definition: memoserv.c:419
#define NI_MEMO_MAIL
Definition: services.h:1306
NickAlias * na
Definition: services.h:892
struct channel_::c_userlist * users