memoserv.c

Go to the documentation of this file.
00001 /* MemoServ functions.
00002 *
00003 * (C) 2003-2007 Anope Team
00004 * Contact us at info@anope.org
00005 *
00006 * Please read COPYING and README for further details.
00007 *
00008 * Based on the original code of Epona by Lara.
00009 * Based on the original code of Services by Andy Church. 
00010 * 
00011 * $Id: memoserv.c 1270 2007-08-27 03:23:06Z drstein $
00012 *
00013 */
00014 
00015 #include "services.h"
00016 #include "pseudo.h"
00017 
00018 /*************************************************************************/
00019 /* *INDENT-OFF* */
00020 
00021 NickCore *nclists[1024];
00022 E void moduleAddMemoServCmds(void);
00023 static void new_memo_mail(NickCore *nc, Memo *m);
00024 E void rsend_notify(User *u, Memo *m, const char *chan);
00025 
00026 /*************************************************************************/
00027 
00028 void moduleAddMemoServCmds(void) {
00029     modules_core_init(MemoServCoreNumber, MemoServCoreModules);
00030 }
00031 
00032 /*************************************************************************/
00033 /*************************************************************************/
00034 /* *INDENT-ON* */
00035 
00040 void ms_init(void)
00041 {
00042     moduleAddMemoServCmds();
00043 }
00044 
00045 /*************************************************************************/
00046 
00056 void memoserv(User * u, char *buf)
00057 {
00058     char *cmd, *s;
00059 
00060     cmd = strtok(buf, " ");
00061     if (!cmd) {
00062         return;
00063     } else if (stricmp(cmd, "\1PING") == 0) {
00064         if (!(s = strtok(NULL, ""))) {
00065             s = "";
00066         }
00067         anope_cmd_ctcp(s_MemoServ, u->nick, "PING %s", s);
00068     } else if (skeleton) {
00069         notice_lang(s_MemoServ, u, SERVICE_OFFLINE, s_MemoServ);
00070     } else {
00071         if (!u->na && stricmp(cmd, "HELP") != 0)
00072             notice_lang(s_MemoServ, u, NICK_NOT_REGISTERED_HELP,
00073                         s_NickServ);
00074         else
00075             mod_run_cmd(s_MemoServ, u, MEMOSERV, cmd);
00076     }
00077 }
00078 
00079 /*************************************************************************/
00080 
00088 void check_memos(User * u)
00089 {
00090     NickCore *nc;
00091     int i, newcnt = 0;
00092 
00093     if (!u) {
00094         if (debug) {
00095             alog("debug: check_memos called with NULL values");
00096         }
00097         return;
00098     }
00099 
00100     if (!(nc = (u->na ? u->na->nc : NULL)) || !nick_recognized(u) ||
00101         !(nc->flags & NI_MEMO_SIGNON)) {
00102         return;
00103     }
00104 
00105     for (i = 0; i < nc->memos.memocount; i++) {
00106         if (nc->memos.memos[i].flags & MF_UNREAD)
00107             newcnt++;
00108     }
00109     if (newcnt > 0) {
00110         notice_lang(s_MemoServ, u,
00111                     newcnt == 1 ? MEMO_HAVE_NEW_MEMO : MEMO_HAVE_NEW_MEMOS,
00112                     newcnt);
00113         if (newcnt == 1 && (nc->memos.memos[i - 1].flags & MF_UNREAD)) {
00114             notice_lang(s_MemoServ, u, MEMO_TYPE_READ_LAST, s_MemoServ);
00115         } else if (newcnt == 1) {
00116             for (i = 0; i < nc->memos.memocount; i++) {
00117                 if (nc->memos.memos[i].flags & MF_UNREAD)
00118                     break;
00119             }
00120             notice_lang(s_MemoServ, u, MEMO_TYPE_READ_NUM, s_MemoServ,
00121                         nc->memos.memos[i].number);
00122         } else {
00123             notice_lang(s_MemoServ, u, MEMO_TYPE_LIST_NEW, s_MemoServ);
00124         }
00125     }
00126     if (nc->memos.memomax > 0 && nc->memos.memocount >= nc->memos.memomax) {
00127         if (nc->memos.memocount > nc->memos.memomax)
00128             notice_lang(s_MemoServ, u, MEMO_OVER_LIMIT, nc->memos.memomax);
00129         else
00130             notice_lang(s_MemoServ, u, MEMO_AT_LIMIT, nc->memos.memomax);
00131     }
00132 }
00133 
00134 /*************************************************************************/
00135 /*********************** MemoServ private routines ***********************/
00136 /*************************************************************************/
00137 
00146 MemoInfo *getmemoinfo(const char *name, int *ischan, int *isforbid)
00147 {
00148     if (*name == '#') {
00149         ChannelInfo *ci;
00150         if (ischan)
00151             *ischan = 1;
00152         ci = cs_findchan(name);
00153         if (ci) {
00154             if (!(ci->flags & CI_VERBOTEN)) {
00155                 *isforbid = 0;
00156                 return &ci->memos;
00157             } else {
00158                 *isforbid = 1;
00159                 return NULL;
00160             }
00161         } else {
00162             *isforbid = 0;
00163             return NULL;
00164         }
00165     } else {
00166         NickAlias *na;
00167         if (ischan)
00168             *ischan = 0;
00169         na = findnick(name);
00170         if (na) {
00171             if (!(na->status & NS_VERBOTEN)) {
00172                 *isforbid = 0;
00173                 return &na->nc->memos;
00174             } else {
00175                 *isforbid = 1;
00176                 return NULL;
00177             }
00178         } else {
00179             *isforbid = 0;
00180             return NULL;
00181         }
00182     }
00183 }
00184 
00185 /*************************************************************************/
00186 
00199 void memo_send(User * u, char *name, char *text, int z)
00200 {
00201     int ischan;
00202     int isforbid;
00203     Memo *m;
00204     MemoInfo *mi;
00205     time_t now = time(NULL);
00206     char *source = u->na->nc->display;
00207     int is_servoper = is_services_oper(u);
00208 
00209     if (readonly) {
00210         notice_lang(s_MemoServ, u, MEMO_SEND_DISABLED);
00211     } else if (checkDefCon(DEFCON_NO_NEW_MEMOS)) {
00212         notice_lang(s_MemoServ, u, OPER_DEFCON_DENIED);
00213         return;
00214     } else if (!text) {
00215         if (z == 0)
00216             syntax_error(s_MemoServ, u, "SEND", MEMO_SEND_SYNTAX);
00217 
00218         if (z == 3)
00219             syntax_error(s_MemoServ, u, "RSEND", MEMO_RSEND_SYNTAX);
00220 
00221     } else if (!nick_recognized(u)) {
00222         if (z == 0 || z == 3)
00223             notice_lang(s_MemoServ, u, NICK_IDENTIFY_REQUIRED, s_NickServ);
00224 
00225     } else if (!(mi = getmemoinfo(name, &ischan, &isforbid))) {
00226         if (z == 0 || z == 3) {
00227             if (isforbid) {
00228                 notice_lang(s_MemoServ, u,
00229                             ischan ? CHAN_X_FORBIDDEN :
00230                             NICK_X_FORBIDDEN, name);
00231             } else {
00232                 notice_lang(s_MemoServ, u,
00233                             ischan ? CHAN_X_NOT_REGISTERED :
00234                             NICK_X_NOT_REGISTERED, name);
00235             }
00236         }
00237     } else if (z != 2 && MSSendDelay > 0 &&
00238                u && u->lastmemosend + MSSendDelay > now && !is_servoper) {
00239         u->lastmemosend = now;
00240         if (z == 0)
00241             notice_lang(s_MemoServ, u, MEMO_SEND_PLEASE_WAIT, MSSendDelay);
00242 
00243         if (z == 3)
00244             notice_lang(s_MemoServ, u, MEMO_RSEND_PLEASE_WAIT,
00245                         MSSendDelay);
00246 
00247     } else if (mi->memomax == 0 && !is_servoper) {
00248         if (z == 0 || z == 3)
00249             notice_lang(s_MemoServ, u, MEMO_X_GETS_NO_MEMOS, name);
00250 
00251     } else if (mi->memomax > 0 && mi->memocount >= mi->memomax
00252                && !is_servoper) {
00253         if (z == 0 || z == 3)
00254             notice_lang(s_MemoServ, u, MEMO_X_HAS_TOO_MANY_MEMOS, name);
00255 
00256     } else {
00257         u->lastmemosend = now;
00258         mi->memocount++;
00259         mi->memos = srealloc(mi->memos, sizeof(Memo) * mi->memocount);
00260         m = &mi->memos[mi->memocount - 1];
00261         strscpy(m->sender, source, NICKMAX);
00262         m->moduleData = NULL;
00263         if (mi->memocount > 1) {
00264             m->number = m[-1].number + 1;
00265             if (m->number < 1) {
00266                 int i;
00267                 for (i = 0; i < mi->memocount; i++) {
00268                     mi->memos[i].number = i + 1;
00269                 }
00270             }
00271         } else {
00272             m->number = 1;
00273         }
00274         m->time = time(NULL);
00275         m->text = sstrdup(text);
00276         m->flags = MF_UNREAD;
00277         /* Set notify sent flag - DrStein */
00278         if (z == 2) {
00279             m->flags |= MF_NOTIFYS;
00280         }
00281         /* Set receipt request flag */
00282         if (z == 3)
00283             m->flags |= MF_RECEIPT;
00284         if (z == 0 || z == 3)
00285             notice_lang(s_MemoServ, u, MEMO_SENT, name);
00286         if (!ischan) {
00287             NickAlias *na;
00288             NickCore *nc = (findnick(name))->nc;
00289 
00290             if (MSNotifyAll) {
00291                 if ((nc->flags & NI_MEMO_RECEIVE)
00292                     && get_ignore(name) == NULL) {
00293                     int i;
00294 
00295                     for (i = 0; i < nc->aliases.count; i++) {
00296                         na = nc->aliases.list[i];
00297                         if (na->u && nick_identified(na->u))
00298                             notice_lang(s_MemoServ, na->u,
00299                                         MEMO_NEW_MEMO_ARRIVED, source,
00300                                         s_MemoServ, m->number);
00301                     }
00302                 } else {
00303                     if ((u = finduser(name)) && nick_identified(u)
00304                         && (nc->flags & NI_MEMO_RECEIVE))
00305                         notice_lang(s_MemoServ, u, MEMO_NEW_MEMO_ARRIVED,
00306                                     source, s_MemoServ, m->number);
00307                 }               /* if (flags & MEMO_RECEIVE) */
00308             }
00309             /* if (MSNotifyAll) */
00310             /* let's get out the mail if set in the nickcore - certus */
00311             if (nc->flags & NI_MEMO_MAIL)
00312                 new_memo_mail(nc, m);
00313         } else {
00314             struct c_userlist *cu, *next;
00315             Channel *c;
00316 
00317             if (MSNotifyAll && (c = findchan(name))) {
00318                 for (cu = c->users; cu; cu = next) {
00319                     next = cu->next;
00320                     if (check_access(cu->user, c->ci, CA_MEMO)) {
00321                         if (cu->user->na
00322                             && (cu->user->na->nc->flags & NI_MEMO_RECEIVE)
00323                             && get_ignore(cu->user->nick) == NULL) {
00324                             notice_lang(s_MemoServ, cu->user,
00325                                         MEMO_NEW_X_MEMO_ARRIVED,
00326                                         c->ci->name, s_MemoServ,
00327                                         c->ci->name, m->number);
00328                         }
00329                     }
00330                 }
00331             }                   /* MSNotifyAll */
00332         }                       /* if (!ischan) */
00333     }                           /* if command is valid */
00334 }
00335 
00336 /*************************************************************************/
00343 int delmemo(MemoInfo * mi, int num)
00344 {
00345     int i;
00346 
00347     for (i = 0; i < mi->memocount; i++) {
00348         if (mi->memos[i].number == num)
00349             break;
00350     }
00351     if (i < mi->memocount) {
00352         moduleCleanStruct(&mi->memos[i].moduleData);
00353         free(mi->memos[i].text);        /* Deallocate memo text memory */
00354         mi->memocount--;        /* One less memo now */
00355         if (i < mi->memocount)  /* Move remaining memos down a slot */
00356             memmove(mi->memos + i, mi->memos + i + 1,
00357                     sizeof(Memo) * (mi->memocount - i));
00358         if (mi->memocount == 0) {       /* If no more memos, free array */
00359             free(mi->memos);
00360             mi->memos = NULL;
00361         }
00362         return 1;
00363     } else {
00364         return 0;
00365     }
00366 }
00367 
00368 /*************************************************************************/
00369 
00370 static void new_memo_mail(NickCore * nc, Memo * m)
00371 {
00372     MailInfo *mail = NULL;
00373 
00374     if (!nc || !m)
00375         return;
00376 
00377     mail = MailMemoBegin(nc);
00378     if (!mail) {
00379         return;
00380     }
00381     fprintf(mail->pipe, getstring2(NULL, MEMO_MAIL_TEXT1), nc->display);
00382     fprintf(mail->pipe, "\n");
00383     fprintf(mail->pipe, getstring2(NULL, MEMO_MAIL_TEXT2), m->sender,
00384             m->number);
00385     fprintf(mail->pipe, "\n\n");
00386     fprintf(mail->pipe, getstring2(NULL, MEMO_MAIL_TEXT3));
00387     fprintf(mail->pipe, "\n\n");
00388     fprintf(mail->pipe, "%s", m->text);
00389     fprintf(mail->pipe, "\n");
00390     MailEnd(mail);
00391     return;
00392 }
00393 
00394 
00395 /*************************************************************************/
00396 /* Send receipt notification to sender. */
00397 
00398 void rsend_notify(User * u, Memo * m, const char *chan)
00399 {
00400     NickAlias *na;
00401     NickCore *nc;
00402     char text[256];
00403     const char *fmt;
00404 
00405     /* Only send receipt if memos are allowed */
00406     if ((!readonly) && (!checkDefCon(DEFCON_NO_NEW_MEMOS))) {
00407 
00408         /* Get nick alias for sender */
00409         na = findnick(m->sender);
00410 
00411         if (!na) {
00412             return;
00413         }
00414 
00415         /* Get nick core for sender */
00416         nc = na->nc;
00417 
00418         if (!nc) {
00419             return;
00420         }
00421 
00422         /* Text of the memo varies if the recepient was a
00423            nick or channel */
00424         if (chan) {
00425             fmt = getstring(na, MEMO_RSEND_CHAN_MEMO_TEXT);
00426             sprintf(text, fmt, chan);
00427         } else {
00428             fmt = getstring(na, MEMO_RSEND_NICK_MEMO_TEXT);
00429             sprintf(text, fmt);
00430         }
00431 
00432         /* Send notification */
00433         memo_send(u, m->sender, text, 2);
00434 
00435         /* Notify recepient of the memo that a notification has
00436            been sent to the sender */
00437         notice_lang(s_MemoServ, u, MEMO_RSEND_USER_NOTIFICATION,
00438                     nc->display);
00439     }
00440 
00441     /* Remove receipt flag from the original memo */
00442     m->flags &= ~MF_RECEIPT;
00443 
00444     return;
00445 }

Generated on Sun Dec 30 09:26:49 2007 for Anope by  doxygen 1.5.1-20070107