00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
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
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
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
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
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
00377
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
00393
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++;
00402 }
00403 len++;
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
00412
00413 memo = (char *)oalloc(len+1);
00414 strcpy(memo, args[2]);
00415 for (i = 3; i < numargs; i++) {
00416 strcat(memo, " ");
00417 strcat(memo, args[i]);
00418 }
00419
00420
00421
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
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
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
00535
00536
00537 if (sendto->memos == NULL)
00538 ADD_MEMO_BOX(sendto);
00539
00540
00541
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;
00552 newmemo->realto = sendto;
00553
00554
00555
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)
00566 ADD_MEMO_BOX(sendto);
00567
00568 }
00569
00570 if (sender)
00571 nick = getNickData(sender);
00572
00573
00574
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
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
00602
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
00614
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(®_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
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
00970
00971
00972 if (nick == NULL)
00973 return;
00974 if (nick->reg == NULL)
00975 return;
00976 if (nick->reg->memos == NULL)
00977 return;
00978
00979
00980 if (!checkAccess(nick->user, nick->host, nick->reg)
00981 && !isIdentified(nick, nick->reg))
00982 return;
00983
00984
00985 from = nick->nick;
00986
00987
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