Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Class Members | File Members | Related Pages

memoserv.c

Go to the documentation of this file.
00001 /* $Id: memoserv.c,v 1.3 2003/08/23 02:03:24 Mysid Exp $ */
00002 
00003 /*
00004  * Copyright (c) 1996-1997 Chip Norkus
00005  * Copyright (c) 1997 Max Byrd
00006  * Copyright (c) 1997 Greg Poma
00007  * Copyright (c) 2000 James Hess
00008  * Copyright (c) 1999 Portions Copyright
00009  * All rights reserved.
00010  *
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted provided that the following conditions
00013  * are met:
00014  * 1. Redistributions of source code must retain the above copyright
00015  *    notice, this list of conditions and the following disclaimer.
00016  * 2. Redistributions in binary form must reproduce the above copyright
00017  *    notice, this list of conditions and the following disclaimer in the
00018  *    documentation and/or other materials provided with the distribution.
00019  * 3. Neither the name of the authors nor the names of its contributors
00020  *    may be used to endorse or promote products derived from this software
00021  *    without specific prior written permission.
00022  *
00023  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
00024  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00025  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00026  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
00027  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00028  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00029  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00030  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00032  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00033  * SUCH DAMAGE.
00034  */
00035 
00048 #include "services.h"
00049 #include "memoserv.h"
00050 #include "nickserv.h"
00051 #include "chanserv.h"
00052 #include "queue.h"
00053 #include "macro.h"
00054 #include "log.h"
00055 #include "hash/md5pw.h"
00056 
00057 // *INDENT-OFF*
00058 MCMD(ms_help);
00059 MCMD(ms_read);
00060 MCMD(ms_savememo);
00061 MCMD(ms_send);
00062 MCMD(ms_forward);
00063 MCMD(ms_nomemo);
00064 MCMD(ms_clean);
00065 MCMD(ms_delete);
00066 MCMD(ms_list);
00067 MCMD(ms_unsend);
00068 MCMD(ms_mblock);
00069 
00070 int  ms_sendMemo(char *, char *, RegNickList *, const char *, char *, UserList *);
00071 static cmd_return ms_AddMemoBlock(UserList *, char *);
00072 static cmd_return ms_DelMemoBlock(UserList *, char *);
00073 char NickGetEnc(RegNickList *);
00074 
00076 #define CMD_REGIDENT (CMD_REG|CMD_IDENT)
00077 
00079 interp::service_cmd_t memoserv_commands[] = {
00080   /* string             function         Flags      L */
00081    { "help",        ms_help,    0, LOG_NO,  0, 3 },
00082    { "read",        ms_read,    0, LOG_NO,  CMD_REGIDENT, 7 },
00083    { "save",        ms_savememo,    0, LOG_NO,  CMD_REGIDENT, 7 },
00084    { "list",        ms_list,    0, LOG_NO,  CMD_REGIDENT, 7 },
00085    { "send",        ms_send,    0, LOG_NO,  CMD_REGIDENT, 9 },
00086    { "sendaop",     ms_send,    0, LOG_NO,  CMD_REGIDENT, 9 },
00087    { "sendsop",     ms_send,    0, LOG_NO,  CMD_REGIDENT, 9 },
00088    { "sendvop",     ms_send,    0, LOG_NO,  CMD_REGIDENT, 9 },
00089    { "del",         ms_delete,  0, LOG_NO,  CMD_REGIDENT, 5 },
00090    { "delete",      ms_delete,  0, LOG_NO,  CMD_REGIDENT, 5 },
00091    { "purge",       ms_clean,   0, LOG_NO,  CMD_REGIDENT, 5 },
00092    { "clean",       ms_clean,   0, LOG_NO,  CMD_REGIDENT, 5 },
00093    { "forward",     ms_forward, 0, LOG_NO,  CMD_REGIDENT, 5 },
00094    { "nomemo",      ms_nomemo,  0, LOG_NO,  CMD_REGIDENT, 5 },
00095    { "unsend",      ms_unsend,  0, LOG_NO,  CMD_REGIDENT, 5 },
00096    { "mblock",      ms_mblock,  0, LOG_NO,  CMD_REGIDENT, 5 },
00097    { NULL,      NULL,       0, LOG_NO,  0, 0 }
00098 };
00099 // *INDENT-ON*
00100 
00110 void sendToMemoServ(UserList * nick, char **args, int numargs)
00111 {
00112     interp::parser * cmd;
00113 
00114     cmd = new interp::parser(MemoServ, getOpFlags(nick),
00115                              memoserv_commands, args[0]);
00116     if (!cmd)
00117         return;
00118 
00119     if ((cmd->getCmdFlags() & CMD_REG) && !nick->reg) {
00120         PutReply(MemoServ, nick, ERR_SERVICE_NEEDREGNICK_1ARG, MemoServ, 0, 0);
00121         return;
00122     }
00123 
00124     if (nick->reg && !nick->reg->memos)
00125         ADD_MEMO_BOX(nick->reg);
00126 
00127     switch (cmd->run(nick, args, numargs)) {
00128     default:
00129         break;
00130     case RET_FAIL:
00131         PutReply(MemoServ, nick, ERR_IS_UNKNOWNCMD_1ARG, args[0], 0, 0);
00132         PutHelpInfo(MemoServ, nick, "HELP");
00133         break;
00134     case RET_OK_DB:
00135         PutReply(MemoServ, nick, RPL_DBSAVE_1ARG,
00136             (long)((nextMsync - CTime) / 60), 0, 0);
00137         break;
00138     }
00139     return;
00140 }
00141 
00146 MCMD(ms_help)
00147 {
00148     help(nick->nick, MemoServ, args, numargs);
00149     return RET_OK;
00150 }
00151 
00157 MCMD(ms_read)
00158 {
00159     char *from = nick->nick;
00160     int i;
00161     int idx;
00162     MemoList *tmp;
00163     struct tm *tm;
00164     char temp[30];
00165     RegNickList *sender;
00166 
00167     if (numargs < 2) {
00168         PutReply(MemoServ, nick, ERR_NEEDMEMONUM_1ARG, "read", 0, 0);
00169         return RET_SYNTAX;
00170     }
00171 
00172     idx = 0;
00173     if (!strcasecmp(args[1], "all")) {
00174         for (tmp = LIST_FIRST(&nick->reg->memos->mb_memos);
00175              tmp; tmp = LIST_NEXT(tmp, ml_lst)) {
00176             idx++;
00177             PutReply(MemoServ, nick, RPL_MEMO_HEADER1_3ARG,
00178                   idx, tmp->from, tmp->to);
00179             tm = localtime(&tmp->sent);
00180             strftime(temp, 30, "%a %Y-%b-%d %T %Z", tm);
00181             sSend(":%s NOTICE %s :Sent at: %-30s  Flagged %c%c%c%c%c",
00182                   MemoServ, from, temp,
00183                   (tmp->flags & MEMO_UNREAD ? '*' : ' '),
00184                   (tmp->flags & MEMO_DELETE ? 'D' : ' '),
00185                   (tmp->flags & MEMO_SAVE ? 'S' : ' '),
00186                   (tmp->flags & MEMO_FWD ? 'f' : ' '),
00187                   (tmp->flags & MEMO_REPLY ? 'r' : ' '));
00188             sSend(":%s NOTICE %s :%s", MemoServ, from, tmp->memotxt);
00189             if (tmp->flags & MEMO_UNREAD) {
00190                 tmp->flags &= ~MEMO_UNREAD;
00191                 sender = getRegNickData(tmp->from);
00192                 if (sender)
00193                     LIST_REMOVE(tmp, ml_sent);
00194             }
00195         }
00196         return RET_OK;
00197     }
00198 
00199     i = atoi(args[1]);
00200 
00201     if (i > nick->reg->memos->memocnt || i <= 0) {
00202         PutReply(MemoServ, nick, ERR_NOSUCH_MEMO_1ARG, i, 0, 0);
00203         return RET_NOTARGET;
00204     }
00205 
00206     idx = 0;
00207     for (tmp = LIST_FIRST(&nick->reg->memos->mb_memos);
00208          tmp; tmp = LIST_NEXT(tmp, ml_lst)) {
00209         idx++;
00210         if (idx == i)
00211             break;
00212     }
00213 
00214     if (tmp == NULL) {
00215         sSend(":%s NOTICE %s :%s internal error",
00216               MemoServ, from, MemoServ);
00217         return RET_FAIL;
00218     }
00219 
00220     /* Memo (XXX) from YYYY to ZZZZ  */
00221     PutReply(MemoServ, nick, RPL_MEMO_HEADER1_3ARG, idx, tmp->from, tmp->to);
00222     tm = localtime(&tmp->sent);
00223     strftime(temp, 30, "%a %Y-%b-%d %T %Z", tm);
00224     sSend(":%s NOTICE %s :Sent at: %-30s  Flagged %c%c%c%c%c",
00225           MemoServ, from, temp,
00226           (tmp->flags & MEMO_UNREAD ? '*' : ' '),
00227           (tmp->flags & MEMO_DELETE ? 'D' : ' '),
00228           (tmp->flags & MEMO_SAVE ? 'S' : ' '),
00229           (tmp->flags & MEMO_FWD ? 'f' : ' '),
00230           (tmp->flags & MEMO_REPLY ? 'r' : ' '));
00231     sSend(":%s NOTICE %s :%s", MemoServ, from, tmp->memotxt);
00232 
00233     if (tmp->flags & MEMO_UNREAD) {
00234         tmp->flags &= ~MEMO_UNREAD;
00235         sender = getRegNickData(tmp->from);
00236         if (sender)
00237             LIST_REMOVE(tmp, ml_sent);
00238     }
00239     return RET_OK;
00240 }
00241 
00247 MCMD(ms_savememo)
00248 {
00249     char *from = nick->nick;
00250     int i, idx;
00251     MemoList *tmp;
00252 
00253     if (numargs < 2) {
00254         PutReply(MemoServ, nick, ERR_NEEDMEMONUM_1ARG, "save", 0, 0);
00255         return RET_SYNTAX;
00256     }
00257 
00258     idx = 0;
00259     i = atoi(args[1]);
00260 
00261     if (i > nick->reg->memos->memocnt || i <= 0) {
00262         PutReply(MemoServ, nick, ERR_NOSUCH_MEMO_1ARG, i, 0, 0);
00263         return RET_NOTARGET;
00264     }
00265 
00266     for (tmp = LIST_FIRST(&nick->reg->memos->mb_memos);
00267          tmp; tmp = LIST_NEXT(tmp, ml_lst)) {
00268         idx++;
00269         if (idx == i)
00270             break;
00271     }
00272 
00273     if (tmp == NULL) {
00274         sSend(":%s NOTICE %s :%s internal error",
00275               MemoServ, from, MemoServ);
00276         return RET_FAIL;
00277     }
00278 
00279     tmp->flags |= MEMO_SAVE;
00280 
00281     PutReply(MemoServ, nick, RPL_MEMO_SAVED_1ARG, idx, 0, 0);
00282     return RET_OK_DB;
00283 }
00284 
00290 MCMD(ms_list)
00291 {
00292     char *from = nick->nick;
00293     MemoList *tmp;
00294     struct tm *tm;
00295     int idx;
00296     char temp[30];
00297     char search[NICKLEN + 2];
00298 
00299     idx = 0;
00300 
00301     memset(search, 0, NICKLEN + 2);
00302     if (numargs >= 2)
00303         strncpyzt(search, args[1], NICKLEN);
00304 
00305     if (LIST_FIRST(&nick->reg->memos->mb_memos) == NULL) {
00306         PutReply(MemoServ, nick, ERR_NOMEMOS, 0, 0, 0);
00307         return RET_OK;
00308     }
00309 
00310     PutReply(MemoServ, nick, RPL_MS_LIST_HEAD1, 0, 0, 0);
00311     PutReply(MemoServ, nick, RPL_MS_LIST_HEAD2, 0, 0, 0);
00312 
00313     for (tmp = LIST_FIRST(&nick->reg->memos->mb_memos);
00314          tmp; tmp = LIST_NEXT(tmp, ml_lst)) {
00315         idx++;
00316         if (search[0]) {
00317             if (!match(search, tmp->from)) {
00318                 tm = localtime(&tmp->sent);
00319                 strftime(temp, 30, "%a %Y-%b-%d %T %Z", tm);
00320                 sSend(":%s NOTICE %s :%3u %-26s %c%c%c%c%c %s",
00321                       MemoServ, from, idx, temp,
00322                       (tmp->flags & MEMO_UNREAD ? '*' : ' '),
00323                       (tmp->flags & MEMO_DELETE ? 'D' : ' '),
00324                       (tmp->flags & MEMO_SAVE ? 'S' : ' '),
00325                       (tmp->flags & MEMO_FWD ? 'f' : ' '),
00326                       (tmp->flags & MEMO_REPLY ? 'r' : ' '), tmp->from);
00327             }
00328         } else {
00329             tm = localtime(&tmp->sent);
00330             strftime(temp, 30, "%a %Y-%b-%d %T %Z", tm);
00331             sSend(":%s NOTICE %s :%3u %-26s %c%c%c%c%c %s",
00332                   MemoServ, from, idx, temp,
00333                   (tmp->flags & MEMO_UNREAD ? '*' : ' '),
00334                   (tmp->flags & MEMO_DELETE ? 'D' : ' '),
00335                   (tmp->flags & MEMO_SAVE ? 'S' : ' '),
00336                   (tmp->flags & MEMO_FWD ? 'f' : ' '),
00337                   (tmp->flags & MEMO_REPLY ? 'r' : ' '), tmp->from);
00338         }
00339     }
00340     PutReply(MemoServ, nick, RPL_MS_LIST_FOOT, 0, 0, 0);
00341     return RET_OK;
00342 }
00343 
00345 cmd_return ui_ms_send(UserList *nick, int numargs, char *args[], int level)
00346 {
00347     char *from = nick->nick, *memo;
00348     RegNickList *sendto;
00349     RegChanList *chan;
00350     cAccessList *tmp;
00351     const char *tmpName;
00352     int i, len, fIsChannel;
00353 
00354     sendto = NULL;
00355     chan = NULL;
00356 
00357     if (numargs < 3) {
00358         PutReply(MemoServ, nick, ERR_MS_NEEDNICKCHANMEMO, 0, 0, 0);
00359         return RET_SYNTAX;
00360     }
00361 
00362     if (args[1][0] == '#')
00363         fIsChannel = 1;
00364     else
00365     {
00366         fIsChannel = 0;
00367         sendto = getRegNickData(args[1]);
00368         if (sendto == NULL) {
00369             PutReply(MemoServ, nick, ERR_NOTREG_1ARG, args[1], 0, 0);
00370             return RET_NOTARGET;
00371         }
00372     }
00373 
00374 
00375     /*
00376      * If sending to a channel, make certain it exists, and they are
00377      * a channel operator of the correct level
00378      */
00379     if (fIsChannel) {
00380         chan = getRegChanData(args[1]);
00381         if (chan == NULL) {
00382             PutReply(MemoServ, nick, ERR_CHANNOTREG_1ARG, args[1], 0, 0);
00383             return RET_NOTARGET;
00384         }
00385         if ((getChanOp(chan, from) < chan->memolevel)) {
00386             PutReply(MemoServ, nick, ERR_MS_NOACCESS_1ARG, chan->name, 0, 0);
00387             return RET_NOPERM;
00388         }
00389     }
00390 
00391     /*
00392      * Count up the total length of the memo they intend to send.  If
00393      * it is going to be too long, complain.
00394      */
00395     len = strlen(args[2]);
00396     if (3 < numargs)
00397         len++;
00398     for (i = 3; i < numargs; i++) {
00399         len += strlen(args[i]); 
00400         if (i+1 < numargs)
00401             len++; /* plus the trailing space */
00402     }
00403     len++;                      /* The terminating null */
00404 
00405     if (len >= MEMOLEN) {
00406         PutReply(MemoServ, nick, ERR_MS_TOOLONG_2ARG, len, MEMOLEN - 1, 0);
00407         return RET_EFAULT;
00408     }
00409 
00410     /*
00411      * generate the memo string
00412      */
00413     memo = (char *)oalloc(len+1);
00414     strcpy(memo, args[2]);      /* strcpy is safe */
00415     for (i = 3; i < numargs; i++) {
00416         strcat(memo, " ");      /* strcat is safe */
00417         strcat(memo, args[i]);  /* strcat is safe */
00418     }
00419 
00420     /*
00421      * send the thing (user)
00422      */
00423     if (fIsChannel == 0) {
00424         if (ms_sendMemo(from, memo, sendto, args[1], NULL, nick) == -1)
00425         {
00426             if (memo)
00427                 FREE(memo);
00428             return RET_FAIL;
00429         }
00430         return RET_OK_DB;
00431     }
00432 
00433 
00434     /*
00435      * send the thing (channel)
00436      */
00437     for (tmp = chan->firstOp; tmp != NULL; tmp = tmp->next) {
00438         char *memocpy;
00439 
00440         if (tmp->uflags < level)
00441             continue;
00442 
00443         tmpName = tmp->nickId.getNick();
00444 
00445         if (tmpName == NULL)
00446             continue;
00447 
00448         sendto = getRegNickData(tmpName);
00449 
00450         if (sendto == NULL || memo == NULL)
00451             continue;
00452 
00453         memocpy = strdup(memo); 
00455         if (ms_sendMemo(from, memocpy, sendto, tmpName, chan->name, nick)
00456             == -1 && memocpy)
00457             FREE(memocpy);
00458     }
00459 
00460     FREE(memo);
00461     return RET_OK_DB;
00462 }
00463 
00471 MCMD(ms_send) {
00472     int ulev_send = 0;
00473 
00474     if (numargs < 1)
00475         return RET_FAIL;
00476 
00477     if (!str_cmp(args[0], "sendaop"))
00478         ulev_send = AOP;
00479     else if (!str_cmp(args[0], "sendsop"))
00480         ulev_send = MSOP;
00481     else if (!str_cmp(args[0], "sendvop"))
00482         ulev_send = MAOP;
00483 
00484     return ui_ms_send(nick, numargs, args, ulev_send);
00485 }
00486 
00488 MCMD(ms_sendsop) {
00489     return ui_ms_send(nick, numargs, args, MSOP);
00490 }
00491 
00503 int
00504 ms_sendMemo(char *sender, char *memo, RegNickList * sendto,
00505             const char *to, char *tochan, UserList * senderptr)
00506 {
00507     MemoList *newmemo;
00508     UserList *nick = NULL;
00509     RegNickList *reg_sender;
00510     MemoBlock *mblock;
00511 
00516     if (sendto == NULL) {
00517         sSend(":%s NOTICE %s :%s is not registered.",
00518               MemoServ, sender, to);
00519         return -1;
00520     }
00521 
00522     reg_sender = getRegNickData(sender);
00523 
00524     /*
00525      * if the memo is NULL, we are in deep trouble
00526      */
00527     if (memo == NULL) {
00528         sSend(":%s GLOBOP :Invalid call to send a memo from %s",
00529               MemoServ, sender);
00530         return -1;
00531     }
00532 
00533     /*
00534      * If the receiver has no memo box, create one.  We will check
00535      * this again if we switch to a new recepient later...
00536      */
00537     if (sendto->memos == NULL)
00538         ADD_MEMO_BOX(sendto);
00539 
00540     /*
00541      * allocate a new memo entry, and fill in the details
00542      */
00543     newmemo = (MemoList *) oalloc(sizeof(MemoList));
00544     strcpy(newmemo->from, sender);
00545     newmemo->sent = CTime;
00546     newmemo->flags |= MEMO_UNREAD;
00547     if (tochan == NULL)
00548         strcpy(newmemo->to, to);
00549     else
00550         strcpy(newmemo->to, tochan);
00551     newmemo->memotxt = memo;    /* allocated by caller */
00552     newmemo->realto = sendto;
00553 
00554     /*
00555      * If the user has memos forwarded, send it there instead
00556      */
00557     if (((sendto->memos->flags & MFORWARDED) == MFORWARDED)
00558         && (sendto->memos->forward != NULL)) {
00559         if (senderptr && isOper(senderptr))
00560             sSend(":%s NOTICE %s :Forwarding memo from %s to %s",
00561                   MemoServ, sender, sendto->nick,
00562                   sendto->memos->forward->nick);
00563         newmemo->flags |= MEMO_FWD;
00564         sendto = sendto->memos->forward;
00565         if (sendto->memos == NULL)  /* gotta check _again_ */
00566             ADD_MEMO_BOX(sendto);
00567 
00568     }
00569 
00570     if (sender)
00571         nick = getNickData(sender);
00572 
00573     /*
00574      * Make certain that user can receive memos
00575      */
00576     if ((sendto->memos->flags & MNOMEMO)
00577         && (!nick || !opFlagged(nick, OVERRIDE))) {
00578         sSend(":%s NOTICE %s :%s does not allow memos to be sent to them",
00579               MemoServ, sender, sendto->nick);
00580         FREE(newmemo);
00581         return -1;
00582     }
00583 
00584     /*
00585      * Make sure user isn't being blocked
00586      */
00587     if (reg_sender)
00588     {
00589         mblock = getMemoBlockData(sendto->memos, reg_sender);
00590 
00591         if (mblock != NULL) {
00592             sSend
00593                 (":%s NOTICE %s :Unable to send memo to recipient %s. This user has chosen to block your memos.",
00594                  MemoServ, sender, sendto->nick);
00595             FREE(newmemo);
00596             return -1;
00597         }
00598     }
00599 
00600     /*
00601      * Check to see if the user has too many memos.  If so, this one
00602      * cannot be sent.
00603      */
00604     if (sendto->memos->memocnt >= sendto->memos->max
00605         && !opFlagged(nick, OVERRIDE | OSERVOP)) {
00606         sSend(":%s NOTICE %s :%s has received too many memos.", MemoServ,
00607               sender, sendto->nick);
00608         FREE(newmemo);
00609         return -1;
00610     }
00611 
00612     /*
00613      * Add the memo to the user's memo list, and if they are online,
00614      * let them know they have a new memo waiting.
00615      */
00616     LIST_ENTRY_INIT(newmemo, ml_lst);
00617     LIST_INSERT_HEAD(&sendto->memos->mb_memos, newmemo, ml_lst);
00618     sendto->memos->memocnt++;
00619     if (getNickData(sendto->nick))
00620         sSend(":%s NOTICE %s :You have a new memo from %s.",
00621               MemoServ, to, sender);
00622     sSend(":%s NOTICE %s :Memo has been sent to %s",
00623           MemoServ, sender, sendto->nick);
00624     if (reg_sender)
00625         LIST_INSERT_HEAD(&reg_sender->memos->mb_sent, newmemo, ml_sent);
00626     return 0;
00627 }
00628 
00634 
00635 MCMD(ms_delete)
00636 {
00637     MemoList *tmp;
00638     MemoList *tmp_next;
00639     int i;
00640     int idx;
00641 
00642     if (numargs < 2) {
00643         PutReply(MemoServ, nick, ERR_MS_DEL_SPECIFYMEMO, 0, 0, 0);
00644         return RET_SYNTAX;
00645     }
00646 
00647     if (nick->reg->memos->memocnt == 0) {
00648         PutReply(MemoServ, nick, ERR_NOMEMOS, 0, 0, 0);
00649         return RET_OK;
00650     }
00651 
00652     if (!strcasecmp(args[1], "all")) {
00653         tmp = LIST_FIRST(&nick->reg->memos->mb_memos);
00654         while (tmp) {
00655             tmp_next = LIST_NEXT(tmp, ml_lst);
00656             tmp->flags |= MEMO_DELETE;
00657             if (tmp->flags & MEMO_UNREAD)
00658                 LIST_REMOVE(tmp, ml_sent);
00659             tmp = tmp_next;
00660         }
00661         PutReply(MemoServ, nick, RPL_MS_ALLDELETED_1ARG, "", 0, 0);
00662         return RET_OK_DB;
00663     }
00664 
00665     if (!strcasecmp(args[1], "new")) {
00666         tmp = LIST_FIRST(&nick->reg->memos->mb_memos);
00667         while (tmp) {
00668             tmp_next = LIST_NEXT(tmp, ml_lst);
00669             if (tmp->flags & MEMO_UNREAD) {
00670                 tmp->flags |= MEMO_DELETE;
00671                 LIST_REMOVE(tmp, ml_sent);
00672             }
00673             tmp = tmp_next;
00674         }
00675 
00676         PutReply(MemoServ, nick, RPL_MS_ALLDELETED_1ARG, " unread", 0, 0);
00677         return RET_OK_DB;
00678     }
00679 
00680     if (!strcasecmp(args[1], "old") || !strcasecmp(args[1], "read")) {
00681         tmp = LIST_FIRST(&nick->reg->memos->mb_memos);
00682         while (tmp) {
00683             tmp_next = LIST_NEXT(tmp, ml_lst);
00684             if (!(tmp->flags & MEMO_UNREAD))
00685                 tmp->flags |= MEMO_DELETE;
00686 
00687             tmp = tmp_next;
00688         }
00689 
00690         PutReply(MemoServ, nick, RPL_MS_ALLDELETED_1ARG, " read", 0, 0);
00691         return RET_OK_DB;
00692     }
00693 
00694     i = atoi(args[1]);
00695 
00696     if (i <= 0 || i > nick->reg->memos->memocnt) {
00697         PutReply(MemoServ, nick, ERR_MS_BADINDEXNUMBER, 0, 0, 0);
00698         return RET_SYNTAX;
00699     }
00700 
00701     idx = 0;
00702     for (tmp = LIST_FIRST(&nick->reg->memos->mb_memos);
00703          tmp; tmp = LIST_NEXT(tmp, ml_lst)) {
00704         idx++;
00705         if (idx == i) {
00706             tmp->flags |= MEMO_DELETE;
00707             if (tmp->flags & MEMO_UNREAD)
00708                 LIST_REMOVE(tmp, ml_sent);
00709             break;
00710         }
00711     }
00712     PutReply(MemoServ, nick, RPL_MS_DELETED_1ARG, i, 0, 0);
00713     return RET_OK_DB;
00714 }
00715 
00721 /* ARGSUSED1 */
00722 MCMD(ms_clean)
00723 {
00724     MemoList *tmp;
00725     MemoList *tmp_next;
00726     u_int i;
00727     u_int x;
00728 
00729     i = x = 0;
00730 
00731     tmp = LIST_FIRST(&nick->reg->memos->mb_memos);
00732     while (tmp != NULL) {
00733         tmp_next = LIST_NEXT(tmp, ml_lst);
00734         x++;
00735         if (tmp->flags & MEMO_DELETE) {
00736             delMemo(nick->reg->memos, tmp);
00737             i++;
00738         }
00739         tmp = tmp_next;
00740     }
00741 
00742     PutReply(MemoServ, nick, RPL_MS_CLEAN_2ARG, i, x, 0);
00743     return RET_OK_DB;
00744 }
00745 
00754 
00755 MCMD(ms_forward)
00756 {
00757     RegNickList *from, *to;
00758 
00759     if (!nick->reg) {
00760         PutReply(MemoServ, nick, ERR_NEEDREGNICK_1ARG, nick->nick, 0, 0);
00761         return RET_FAIL;
00762     }
00763 
00764     from = nick->reg;
00765 
00766     if (numargs <= 1) {
00767         if (!from->memos)
00768             ADD_MEMO_BOX(from);
00769 
00770         if (!from->memos->forward) {
00771             PutReply(MemoServ, nick, ERR_MS_NOTFORWARD, 0, 0, 0);
00772             return RET_FAIL;
00773         }
00774 
00775         from->memos->forward = 0;
00776         from->memos->flags &= ~MFORWARDED;
00777         PutReply(MemoServ, nick, RPL_MS_FORWARD_OFF, 0, 0, 0);
00778         return RET_OK_DB;
00779     }
00780 
00781     if (numargs == 2) {
00782         PutReply(MemoServ, nick, ERR_MS_FORWARD_SYNTAX_1ARG, "forward", 0, 0);
00783         PutHelpInfo(MemoServ, nick, "HELP FORWARD");
00784         return RET_SYNTAX;
00785     }
00786 
00787     to = getRegNickData(args[1]);
00788     if (to == NULL) {
00789         PutReply(MemoServ, nick, ERR_NICKNOTREG_1ARG, args[1], 0, 0);
00790         return RET_NOTARGET;
00791     }
00792 
00793     if (Valid_pw(args[2], to->password, NickGetEnc(to)) == 0) {
00794         PutReply(MemoServ, nick, ERR_BADPW_NICK_1ARG, to->nick, 0, 0);
00795         return RET_BADPW;
00796     }
00797 
00798     if (from->memos == NULL)
00799         ADD_MEMO_BOX(from);
00800 
00801     from->memos->forward = to;
00802     from->memos->flags |= MFORWARDED;
00803 
00804     PutReply(MemoServ, nick, RPL_MS_FORWARD_ON_1ARG, args[1], 0, 0);
00805     return RET_OK_DB;
00806 }
00807 
00813 MCMD(ms_nomemo)
00814 {
00815     if (!nick->reg) {
00816         PutReply(MemoServ, nick, ERR_NEEDREGNICK_1ARG, nick->nick, 0, 0);
00817         return RET_FAIL;
00818     }
00819 
00820     if (numargs < 2) {
00821         PutReply(MemoServ, nick, ERR_MS_NOMEMO_NEEDONOFF, 0, 0, 0);
00822         return RET_SYNTAX;
00823     }
00824 
00825     if (!strcasecmp(args[1], "on")) {
00826         nick->reg->memos->flags |= MNOMEMO;
00827         PutReply(MemoServ, nick, RPL_MS_NOMEMO_ON, 0, 0, 0);
00828     } else if (!strcasecmp(args[1], "off")) {
00829         nick->reg->memos->flags &= ~MNOMEMO;
00830         PutReply(MemoServ, nick, RPL_MS_NOMEMO_OFF, 0, 0, 0);
00831     } else {
00832         PutReply(MemoServ, nick, ERR_MS_NOMEMO_BADPARAM, 0, 0, 0);
00833         return RET_SYNTAX;
00834     }
00835     return RET_OK_DB;
00836 }
00837 
00848 MCMD(ms_unsend)
00849 {
00850     RegNickList *to;
00851     RegNickList *from;
00852     int idx = 0;
00853     struct tm *tm;
00854     MemoList *memos;
00855     MemoList *memos_next;
00856     char temp[30];
00857     int i;
00858 
00859     from = nick->reg;
00860 
00861     if (numargs < 2) {
00862         PutReply(MemoServ, nick, RPL_MS_UNSEND_HEAD1, 0, 0, 0);
00863         PutReply(MemoServ, nick, RPL_MS_UNSEND_HEAD2, 0, 0, 0);
00864 
00865         for (memos = LIST_FIRST(&from->memos->mb_sent);
00866              memos; memos = LIST_NEXT(memos, ml_sent)) {
00867             idx++;
00868             tm = localtime(&memos->sent);
00869             strftime(temp, 30, "%a %Y-%b-%d %T %Z", tm);
00870             sSend(":%s NOTICE %s :%3u %-26s %c%c%c%c%c %s",
00871                   MemoServ, from->nick, idx, temp,
00872                   (memos->flags & MEMO_UNREAD ? '*' : ' '),
00873                   (memos->flags & MEMO_DELETE ? 'D' : ' '),
00874                   (memos->flags & MEMO_SAVE ? 'S' : ' '),
00875                   (memos->flags & MEMO_FWD ? 'f' : ' '),
00876                   (memos->flags & MEMO_REPLY ? 'r' : ' '),
00877                   memos->realto->nick);
00878         }
00879 
00880         return RET_OK;
00881     }
00882 
00883     if (!strcasecmp(args[1], "all")) {
00884         memos = LIST_FIRST(&from->memos->mb_sent);
00885         while (memos != NULL) {
00886             memos_next = LIST_NEXT(memos, ml_sent);
00887             to = memos->realto;
00888             if (!to)
00889                 return RET_OK_DB;
00890             LIST_REMOVE(memos, ml_sent);
00891             delMemo(to->memos, memos);
00892             memos = memos_next;
00893         }
00894         PutReply(MemoServ, nick, RPL_MS_UNSENT_ALL, 0, 0, 0);
00895         return RET_OK_DB;
00896     }
00897 
00898     i = atoi(args[1]);
00899     idx = 0;
00900     for (memos = LIST_FIRST(&from->memos->mb_sent);
00901          memos; memos = LIST_NEXT(memos, ml_sent)) {
00902         idx++;
00903         if (i == idx) {
00904             to = memos->realto;
00905             if (!to)
00906                 return RET_OK;
00907             PutReply(MemoServ, nick, RPL_MS_UNSENT_1ARG, i, 0, 0);
00908             LIST_REMOVE(memos, ml_sent);
00909             delMemo(to->memos, memos);
00910             return RET_OK_DB;
00911         }
00912     }
00913 
00914     PutReply(MemoServ, nick, ERR_MS_UNSEND_NOSUCH_1ARG, i, 0, 0);
00915     return RET_FAIL;
00916 }
00917 
00922 void cleanMemos(UserList * nick)
00923 {
00924     MemoList *tmp;
00925     MemoList *tmp_next;
00926 
00927     if (nick->reg->memos == NULL)
00928         return;
00929 
00930     if (nick->reg->memos->flags & MSELFCLEAN) {
00931         tmp = LIST_FIRST(&nick->reg->memos->mb_memos);
00932         while (tmp != NULL) {
00933             tmp_next = LIST_NEXT(tmp, ml_lst);
00934             if (tmp->flags & MEMO_DELETE)
00935                 delMemo(nick->reg->memos, tmp);
00936             tmp = tmp_next;
00937         }
00938     }
00939 }
00940 
00946 void delMemo(MemoBox * mbox, MemoList * memo)
00947 {
00948     LIST_REMOVE(memo, ml_lst);
00949     mbox->memocnt--;
00950     FREE(memo->memotxt);
00951     FREE(memo);
00952 }
00953 
00958 void checkMemos(UserList * nick)
00959 {
00960     MemoList *tmp;
00961     char *from;
00962     int fwd = 0;
00963     int del = 0;
00964     int save = 0;
00965     int reply_ct = 0;
00966     int unread = 0;
00967     int nummemos = 0;
00968 
00969     /* If the user isn't, if the user isn't registered, or if the user
00970      * has no memo box
00971      */
00972     if (nick == NULL)
00973         return;
00974     if (nick->reg == NULL)
00975         return;
00976     if (nick->reg->memos == NULL)
00977         return;
00978 
00979     /* Make sure the user is identified, or matches an access list */
00980     if (!checkAccess(nick->user, nick->host, nick->reg)
00981         && !isIdentified(nick, nick->reg))
00982         return;
00983 
00984     /* Just to make things easier, from = the sending user */
00985     from = nick->nick;
00986 
00987     /* Step through the list of memos, generate stats for the user */
00988     for (tmp = LIST_FIRST(&nick->reg->memos->mb_memos);
00989          tmp; tmp = LIST_NEXT(tmp, ml_lst)) {
00990         nummemos++;
00991         if (tmp->flags & MEMO_UNREAD)
00992             unread++;
00993         if (tmp->flags & MEMO_SAVE)
00994             save++;
00995         if (tmp->flags & MEMO_FWD)
00996             fwd++;
00997         if (tmp->flags & MEMO_DELETE)
00998             del++;
00999         if (tmp->flags & MEMO_REPLY)
01000             reply_ct++;
01001     }
01002 
01003     if (nummemos > 0) {
01004         if (nummemos == 1)
01005             PutReply(MemoServ, nick, RPL_MS_MEMOWAITING, 0, 0, 0);
01006         else
01007             PutReply(MemoServ, nick, RPL_MS_MEMOWAITING_1ARG, nummemos, 0, 0);
01008         if (unread != 0 || save != 0)
01009             PutReply(MemoServ, nick, RPL_MS_MEMO2_2ARG, unread, save, 0);
01010         if (fwd != 0 || reply_ct != 0)
01011             PutReply(MemoServ, nick, RPL_MS_MEMO3_2ARG, fwd, reply_ct, 0);
01012         if (del != 0)
01013             PutReply(MemoServ, nick, RPL_MS_MEMO4n_2ARG, del, MemoServ, 0);
01014     }
01015 }
01016 
01022 MemoBlock *getMemoBlockData(MemoBox * box, RegNickList *senderRnl)
01023 {
01024     MemoBlock *tmp;
01025 
01026     if (box == NULL || senderRnl == NULL)
01027         return NULL;
01028 
01029     for (tmp = box->firstMblock; tmp; tmp = tmp->next) {
01030         if (tmp->blockId == senderRnl->regnum)
01031             return tmp;
01032     }
01033     return NULL;
01034 }
01035 
01046 
01047 MCMD(ms_mblock)
01048 {
01049     MemoBlock *list;
01050     const char *tmpNickName;
01051 
01052 
01053     if (!nick)
01054         return RET_FAIL;
01055 
01056     if (!nick->reg) {
01057         PutReply(MemoServ, nick, ERR_NEEDREGNICK_1ARG, nick->nick, 0, 0);
01058         return RET_FAIL;
01059     }
01060 
01061     if ((!strcasecmp(args[1], "LIST")) || (numargs < 2)) {
01062         if (!nick->reg->memos->firstMblock) {
01063             PutReply(MemoServ, nick, ERR_MS_MBLOCK_NONE, 0, 0, 0);
01064             return RET_OK;
01065         }
01066 
01067         PutReply(MemoServ, nick, RPL_MS_MBLOCK_HEAD, 0, 0, 0);
01068         for (list = nick->reg->memos->firstMblock; list; list = list->next)
01069         {
01070             tmpNickName = list->blockId.getNick();
01071 
01072             if (tmpNickName)
01073                 sSend(":%s NOTICE %s :%s", MemoServ, nick->nick,
01074                       tmpNickName);
01075         }
01076         return RET_OK;
01077     }
01078 
01079     if (!strcasecmp(args[1], "ADD") && numargs != 3)
01080         return ms_AddMemoBlock(nick, args[2]);
01081     else if (*args[1] == '+')
01082         return ms_AddMemoBlock(nick, args[1] + 1);
01083     else if (!strcasecmp(args[1], "DEL") && numargs != 3)
01084         return ms_DelMemoBlock(nick, args[2]);
01085     else if (*args[1] == '-')
01086         return ms_DelMemoBlock(nick, args[1] + 1);
01087     else
01088 #ifndef STRICT_MBLOCK_SYNTAX
01089         return ms_AddMemoBlock(nick, args[1]);
01090 #else
01091         PutReply(MemoServ, nick, ERR_MS_MBLOCK_BADPARAM, MemoServ, 0, 0);
01092 #endif
01093 
01094     return RET_OK;
01095 }
01096 
01102 static cmd_return ms_DelMemoBlock(UserList * nick, char *text)
01103 {
01104     char *from = nick->nick;
01105     MemoBlock *olditem = NULL;
01106     RegNickList *rnl, *rnlTarget;
01107 
01108     if (!nick || !text) {
01109         logDump(corelog, "ms_delmemoblock: %s%s is NULL",
01110                 !nick ? " nick" : "", !text ? " text" : "");
01111         return RET_FAIL;
01112     }
01113 
01114     if (!(rnl = nick->reg)) {
01115         PutReply(MemoServ, nick, ERR_NICKNOTREG_1ARG, from, 0, 0);
01116         PutReply(MemoServ, nick, ERR_MS_MBLOCK_NOCHANGE, 0, 0, 0);
01117 
01118         return RET_FAIL;
01119     }
01120 
01121     if ((rnlTarget = getRegNickData(text)) != NULL)
01122         olditem = getMemoBlockData(rnl->memos, rnlTarget);
01123 
01124     if (rnlTarget == NULL || olditem == NULL) {
01125         PutReply(MemoServ, nick, ERR_MS_MBLOCK_NOSUCH_1ARG, text, 0, 0);
01126 
01127         return RET_FAIL;
01128     }
01129     delMemoBlock(rnl->memos, olditem);
01130 
01131     PutReply(MemoServ, nick, RPL_MS_MBLOCK_DELETED_1ARG, text, 0, 0);
01132     return RET_OK_DB;
01133 }
01134 
01140 static cmd_return ms_AddMemoBlock(UserList * nick, char *text)
01141 {
01142     char *from = nick->nick;
01143     MemoBlock *newitem;
01144     RegNickList *rnl, *targetRnl;
01145     int count_mblocks = 0;
01146 
01147     if (!nick || !text) {
01148         logDump(corelog, "ms_addmemoblock: %s%s is NULL",
01149                 !nick ? " nick" : "", !text ? " text" : "");
01150         return RET_FAIL;
01151     }
01152 
01153 
01154     if (!(rnl = nick->reg) || !rnl->memos) {
01155         PutReply(MemoServ, nick, ERR_NEEDREGNICK_1ARG, from, 0, 0);
01156         PutReply(MemoServ, nick, ERR_MS_MBLOCK_NOCHANGE, 0, 0, 0);
01157 
01158         return RET_FAIL;
01159     }
01160     if ((targetRnl = getRegNickData(text)) == NULL) {
01161         PutReply(MemoServ, nick, ERR_NICKNOTREG_1ARG, text, 0, 0);
01162         PutReply(MemoServ, nick, ERR_MS_MBLOCK_NOCHANGE, 0, 0, 0);
01163 
01164         return RET_NOTARGET;
01165     }
01166     for (newitem = nick->reg->memos->firstMblock; newitem;
01167          newitem = newitem->next) count_mblocks++;
01168     if (count_mblocks >= MS_MAX_MBLOCK) {
01169         PutReply(MemoServ, nick, ERR_MS_MBLOCK_TOOMANY, 0, 0, 0);
01170 
01171         return RET_FAIL;
01172     }
01173     if (getMemoBlockData(rnl->memos, targetRnl)) {
01174         PutReply(MemoServ, nick, ERR_MS_MBLOCK_ALREADY_1ARG, text, 0, 0);
01175 
01176         return RET_FAIL;
01177     }
01178 
01179     newitem = (MemoBlock *) oalloc(sizeof(MemoBlock));
01180     newitem->blockId = targetRnl->regnum;
01181     addMemoBlock(rnl->memos, newitem);
01182 
01183     PutReply(MemoServ, nick, RPL_MS_MBLOCK_ADDED_1ARG, text, 0, 0);
01184     return RET_OK_DB;
01185 }
01186 
01193 void delMemoBlock(MemoBox * box, MemoBlock * zap)
01194 {
01195     MemoBlock *mblock, *tmp, *mnext;
01196 
01197     if (!box || !zap || !box->firstMblock)
01198         return;
01199     for (tmp = NULL, mblock = box->firstMblock; mblock; mblock = mnext) {
01200         mnext = mblock->next;
01201         if (zap == mblock) {
01202             if (tmp)
01203                 tmp->next = mnext;
01204             else
01205                 box->firstMblock = mnext;
01206             FREE(zap);
01207             return;
01208         } else
01209             tmp = mblock;
01210     }
01211 }
01212 
01218 void addMemoBlock(MemoBox * box, MemoBlock * mblock)
01219 {
01220     MemoBlock *tmp;
01221     if (!box || !mblock)
01222         return;
01223     for (tmp = box->firstMblock; tmp; tmp = tmp->next)
01224         if (tmp == mblock)
01225             return;
01226     mblock->next = box->firstMblock;
01227     box->firstMblock = mblock;
01228 }
01229 
01231 int ShouldMemoExpire(MemoList *memo, int vacationPlus)
01232 {
01233     time_t x;
01234 
01235     if (memo->flags & MEMO_DELETE)
01236         return 1;
01237     if (memo->flags & MEMO_SAVE)
01238         return 0;
01239 
01240     if ((memo->flags & MEMO_UNREAD) == 0)
01241         x = MEMODROPTIME;
01242     else if (vacationPlus == 0)
01243         x = NICKDROPTIME;
01244     else
01245         x = NICKDROPTIME * 3;
01246 
01247     if ((time(NULL) - memo->sent) >= x)
01248         return 1;
01249     return 0;
01250 }
01251 

Generated at Sat Oct 25 20:56:08 2003 for Services using Doxygen.
Services Copyr. 1996-2001 Chip Norkus, Max Byrd, Greg Poma, Michael Graff, James Hess, Dafydd James. All rights reserved See LICENSE for licensing information.