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 #define MODULE_NAME "notes"
00030 #define MAKING_NOTES
00031
00032 #include <fcntl.h>
00033 #include <sys/stat.h>
00034 #include "src/mod/module.h"
00035 #include "src/tandem.h"
00036 #include "notes.h"
00037
00038
00039 static int maxnotes = 50;
00040
00041 static int note_life = 60;
00042 static char notefile[121];
00043 static int allow_fwd = 0;
00044 static int notify_users = 0;
00045 static int notify_onjoin = 1;
00046
00047
00048 #undef global
00049 static Function *global = NULL;
00050
00051 static struct user_entry_type USERENTRY_FWD = {
00052 NULL,
00053 NULL,
00054 NULL,
00055 NULL,
00056 NULL,
00057 NULL,
00058 NULL,
00059 NULL,
00060 NULL,
00061 NULL,
00062 NULL,
00063 NULL,
00064 fwd_display,
00065 "FWD"
00066 };
00067
00068 #include "cmdsnote.c"
00069
00070
00071 static void fwd_display(int idx, struct user_entry *e)
00072 {
00073 if (dcc[idx].user && (dcc[idx].user->flags & USER_BOTMAST))
00074 dprintf(idx, NOTES_FORWARD_TO, e->u.string);
00075 }
00076
00077
00078
00079 static int num_notes(char *user)
00080 {
00081 int tot = 0;
00082 FILE *f;
00083 char s[513], *to, *s1;
00084
00085 if (!notefile[0])
00086 return 0;
00087 f = fopen(notefile, "r");
00088 if (f == NULL)
00089 return 0;
00090 while (!feof(f)) {
00091 fgets(s, 512, f);
00092 if (!feof(f)) {
00093 if (s[strlen(s) - 1] == '\n')
00094 s[strlen(s) - 1] = 0;
00095 rmspace(s);
00096 if ((s[0]) && (s[0] != '#') && (s[0] != ';')) {
00097 s1 = s;
00098 to = newsplit(&s1);
00099 if (!egg_strcasecmp(to, user))
00100 tot++;
00101 }
00102 }
00103 }
00104 fclose(f);
00105 return tot;
00106 }
00107
00108
00109
00110 static void notes_change(char *oldnick, char *newnick)
00111 {
00112 FILE *f, *g;
00113 char s[513], *to, *s1;
00114 int tot = 0;
00115
00116 if (!egg_strcasecmp(oldnick, newnick))
00117 return;
00118 if (!notefile[0])
00119 return;
00120 f = fopen(notefile, "r");
00121 if (f == NULL)
00122 return;
00123 sprintf(s, "%s~new", notefile);
00124 g = fopen(s, "w");
00125 if (g == NULL) {
00126 fclose(f);
00127 return;
00128 }
00129 chmod(s, userfile_perm);
00130 while (!feof(f)) {
00131 fgets(s, 512, f);
00132 if (!feof(f)) {
00133 if (s[strlen(s) - 1] == '\n')
00134 s[strlen(s) - 1] = 0;
00135 rmspace(s);
00136 if ((s[0]) && (s[0] != '#') && (s[0] != ';')) {
00137 s1 = s;
00138 to = newsplit(&s1);
00139 if (!egg_strcasecmp(to, oldnick)) {
00140 tot++;
00141 fprintf(g, "%s %s\n", newnick, s1);
00142 } else
00143 fprintf(g, "%s %s\n", to, s1);
00144 } else
00145 fprintf(g, "%s\n", s);
00146 }
00147 }
00148 fclose(f);
00149 fclose(g);
00150 unlink(notefile);
00151 sprintf(s, "%s~new", notefile);
00152 movefile(s, notefile);
00153 putlog(LOG_MISC, "*", NOTES_SWITCHED_NOTES, tot, tot == 1 ? "" : "s",
00154 oldnick, newnick);
00155 }
00156
00157
00158
00159 static void expire_notes()
00160 {
00161 FILE *f, *g;
00162 char s[513], *to, *from, *ts, *s1;
00163 int tot = 0, lapse;
00164
00165 if (!notefile[0])
00166 return;
00167 f = fopen(notefile, "r");
00168 if (f == NULL)
00169 return;
00170 sprintf(s, "%s~new", notefile);
00171 g = fopen(s, "w");
00172 if (g == NULL) {
00173 fclose(f);
00174 return;
00175 }
00176 chmod(s, userfile_perm);
00177 while (!feof(f)) {
00178 fgets(s, 512, f);
00179 if (!feof(f)) {
00180 if (s[strlen(s) - 1] == '\n')
00181 s[strlen(s) - 1] = 0;
00182 rmspace(s);
00183 if ((s[0]) && (s[0] != '#') && (s[0] != ';')) {
00184 s1 = s;
00185 to = newsplit(&s1);
00186 from = newsplit(&s1);
00187 ts = newsplit(&s1);
00188 lapse = (now - (time_t) atoi(ts)) / 86400;
00189 if (lapse > note_life)
00190 tot++;
00191 else if (!get_user_by_handle(userlist, to))
00192 tot++;
00193 else
00194 fprintf(g, "%s %s %s %s\n", to, from, ts, s1);
00195 } else
00196 fprintf(g, "%s\n", s);
00197 }
00198 }
00199 fclose(f);
00200 fclose(g);
00201 unlink(notefile);
00202 sprintf(s, "%s~new", notefile);
00203 movefile(s, notefile);
00204 if (tot > 0)
00205 putlog(LOG_MISC, "*", NOTES_EXPIRED, tot, tot == 1 ? "" : "s");
00206 }
00207
00208
00209
00210 static int tcl_storenote STDVAR
00211 {
00212 FILE *f;
00213 int idx;
00214 char u[20], *f1, *to = NULL, work[1024];
00215 struct userrec *ur;
00216 struct userrec *ur2;
00217
00218 BADARGS(5, 5, " from to msg idx");
00219
00220 idx = findanyidx(atoi(argv[4]));
00221 ur = get_user_by_handle(userlist, argv[2]);
00222 if (ur && allow_fwd && (f1 = get_user(&USERENTRY_FWD, ur))) {
00223 char fwd[161], fwd2[161], *f2, *p, *q, *r;
00224 int ok = 1;
00225
00226
00227 strcpy(fwd, f1);
00228 p = strchr(fwd, '@');
00229 if (p && !egg_strcasecmp(p + 1, botnetnick)) {
00230 *p = 0;
00231 if (!egg_strcasecmp(fwd, argv[2]))
00232
00233 ok = 0;
00234 strcpy(fwd2, fwd);
00235 splitc(fwd2, fwd2, '@');
00236
00237 ur2 = get_user_by_handle(userlist, fwd2);
00238 if (!ur2)
00239 ok = 0;
00240 if ((f2 = get_user(&USERENTRY_FWD, ur2))) {
00241 strcpy(fwd2, f2);
00242 splitc(fwd2, fwd2, '@');
00243 if (!egg_strcasecmp(fwd2, argv[2]))
00244
00245 ok = 0;
00246 }
00247 p = NULL;
00248 }
00249 if ((argv[1][0] != '@') && ((argv[3][0] == '<') || (argv[3][0] == '>')))
00250 ok = 0;
00251
00252 if (ok && (!p || in_chain(p + 1))) {
00253 if (p)
00254 p++;
00255 q = argv[3];
00256 while (ok && q && (q = strchr(q, '<'))) {
00257 q++;
00258 if ((r = strchr(q, ' '))) {
00259 *r = 0;
00260 if (!egg_strcasecmp(fwd, q))
00261 ok = 0;
00262 *r = ' ';
00263 }
00264 }
00265 if (ok) {
00266 if (p && strchr(argv[1], '@')) {
00267 simple_sprintf(work, "<%s@%s >%s %s", argv[2], botnetnick,
00268 argv[1], argv[3]);
00269 simple_sprintf(u, "@%s", botnetnick);
00270 p = u;
00271 } else {
00272 simple_sprintf(work, "<%s@%s %s", argv[2], botnetnick, argv[3]);
00273 p = argv[1];
00274 }
00275 }
00276 } else
00277 ok = 0;
00278 if (ok) {
00279 if ((add_note(fwd, p, work, idx, 0) == NOTE_OK) && (idx >= 0))
00280 dprintf(idx, NOTES_FORWARD_NOTONLINE, f1);
00281 Tcl_AppendResult(irp, f1, NULL);
00282 to = NULL;
00283 } else {
00284 strcpy(work, argv[3]);
00285 to = argv[2];
00286 }
00287 } else
00288 to = argv[2];
00289 if (to) {
00290 if (notefile[0] == 0) {
00291 if (idx >= 0)
00292 dprintf(idx, "%s\n", NOTES_UNSUPPORTED);
00293 } else if (num_notes(to) >= maxnotes) {
00294 if (idx >= 0)
00295 dprintf(idx, "%s\n", NOTES_NOTES2MANY);
00296 } else {
00297 f = fopen(notefile, "a");
00298 if (f == NULL)
00299 f = fopen(notefile, "w");
00300 if (f == NULL) {
00301 if (idx >= 0)
00302 dprintf(idx, "%s\n", NOTES_NOTEFILE_FAILED);
00303 putlog(LOG_MISC, "*", "%s", NOTES_NOTEFILE_UNREACHABLE);
00304 } else {
00305 char *p, *blah = argv[3], *from = argv[1];
00306 int l = 0;
00307
00308 chmod(notefile, userfile_perm);
00309 while ((blah[0] == '<') || (blah[0] == '>')) {
00310 p = newsplit(&blah);
00311 if (*p == '<')
00312 l += simple_sprintf(work + l, "via %s, ", p + 1);
00313 else if (argv[1][0] == '@')
00314 from = p + 1;
00315 }
00316 fprintf(f, "%s %s %li %s%s\n", to, from, (long) now,
00317 l ? work : "", blah);
00318 fclose(f);
00319 if (idx >= 0)
00320 dprintf(idx, "%s.\n", NOTES_STORED_MESSAGE);
00321 }
00322 }
00323 }
00324 return TCL_OK;
00325 }
00326
00327
00328
00329
00330 static void notes_parse(int dl[], char *s)
00331 {
00332 int i = 0;
00333 int idl = 0;
00334
00335 do {
00336 while (s[i] == ';')
00337 i++;
00338 if (s[i]) {
00339 if (s[i] == '-')
00340 dl[idl] = 1;
00341 else
00342 dl[idl] = atoi(s + i);
00343 idl++;
00344 while ((s[i]) && (s[i] != '-') && (s[i] != ';'))
00345 i++;
00346 if (s[i] == '-') {
00347 dl[idl] = atoi(s + i + 1);
00348 if (dl[idl] == 0)
00349 dl[idl] = maxnotes;
00350 } else
00351 dl[idl] = dl[idl - 1];
00352 idl++;
00353 while ((s[i]) && (s[i] != ';'))
00354 i++;
00355 }
00356 }
00357 while ((s[i]) && (idl < 124));
00358 dl[idl] = -1;
00359 }
00360
00361
00362
00363 static int notes_in(int dl[], int in)
00364 {
00365 int i = 0;
00366
00367 while (dl[i] != -1) {
00368 if ((dl[i] <= in) && (in <= dl[i + 1]))
00369 return 1;
00370 i += 2;
00371 }
00372 return 0;
00373 }
00374
00375 static int tcl_erasenotes STDVAR
00376 {
00377 FILE *f, *g;
00378 char s[601], *to, *s1;
00379 int read, erased;
00380 int nl[128];
00381
00382 BADARGS(3, 3, " handle noteslist#");
00383
00384 if (!get_user_by_handle(userlist, argv[1])) {
00385 Tcl_AppendResult(irp, "-1", NULL);
00386 return TCL_OK;
00387 }
00388 if (!notefile[0]) {
00389 Tcl_AppendResult(irp, "-2", NULL);
00390 return TCL_OK;
00391 }
00392 f = fopen(notefile, "r");
00393 if (f == NULL) {
00394 Tcl_AppendResult(irp, "-2", NULL);
00395 return TCL_OK;
00396 }
00397 sprintf(s, "%s~new", notefile);
00398 g = fopen(s, "w");
00399 if (g == NULL) {
00400 fclose(f);
00401 Tcl_AppendResult(irp, "-2", NULL);
00402 return TCL_OK;
00403 }
00404 chmod(s, userfile_perm);
00405 read = 0;
00406 erased = 0;
00407 notes_parse(nl, (argv[2][0] == 0) ? "-" : argv[2]);
00408 while (!feof(f) && fgets(s, 600, f)) {
00409 if (s[strlen(s) - 1] == '\n')
00410 s[strlen(s) - 1] = 0;
00411 if (!feof(f)) {
00412 rmspace(s);
00413 if ((s[0]) && (s[0] != '#') && (s[0] != ';')) {
00414 s1 = s;
00415 to = newsplit(&s1);
00416 if (!egg_strcasecmp(to, argv[1])) {
00417 read++;
00418 if (!notes_in(nl, read))
00419 fprintf(g, "%s %s\n", to, s1);
00420 else
00421 erased++;
00422 } else
00423 fprintf(g, "%s %s\n", to, s1);
00424 }
00425 }
00426 }
00427 sprintf(s, "%d", erased);
00428 Tcl_AppendResult(irp, s, NULL);
00429 fclose(f);
00430 fclose(g);
00431 unlink(notefile);
00432 sprintf(s, "%s~new", notefile);
00433 movefile(s, notefile);
00434 return TCL_OK;
00435 }
00436
00437 static int tcl_listnotes STDVAR
00438 {
00439 int i, numnotes;
00440 int ln[128];
00441 char s[8];
00442
00443 BADARGS(3, 3, " handle noteslist#");
00444
00445 if (!get_user_by_handle(userlist, argv[1])) {
00446 Tcl_AppendResult(irp, "-1", NULL);
00447 return TCL_OK;
00448 }
00449 numnotes = num_notes(argv[1]);
00450
00451 notes_parse(ln, argv[2]);
00452 for (i = 1; i <= numnotes; i++) {
00453 if (notes_in(ln, i)) {
00454 sprintf(s, "%d", i);
00455 Tcl_AppendElement(irp, s);
00456 }
00457 }
00458 return TCL_OK;
00459 }
00460
00461
00462
00463
00464
00465
00466
00467 static void notes_read(char *hand, char *nick, char *srd, int idx)
00468 {
00469 FILE *f;
00470 char s[601], *to, *dt, *from, *s1, wt[100];
00471 time_t tt;
00472 int ix = 1;
00473 int ir = 0;
00474 int rd[128];
00475 int i;
00476
00477 if (srd[0] == 0)
00478 srd = "-";
00479 if (!notefile[0]) {
00480 if (idx >= 0)
00481 dprintf(idx, "%s.\n", NOTES_NO_MESSAGES);
00482 else
00483 dprintf(DP_HELP, "NOTICE %s :%s.\n", nick, NOTES_NO_MESSAGES);
00484 return;
00485 }
00486 f = fopen(notefile, "r");
00487 if (f == NULL) {
00488 if (idx >= 0)
00489 dprintf(idx, "%s.\n", NOTES_NO_MESSAGES);
00490 else
00491 dprintf(DP_HELP, "NOTICE %s :%s.\n", nick, NOTES_NO_MESSAGES);
00492 return;
00493 }
00494 notes_parse(rd, srd);
00495 while (!feof(f) && fgets(s, 600, f)) {
00496 i = strlen(s);
00497 if (i > 0 && s[i - 1] == '\n')
00498 s[i - 1] = 0;
00499 if (!feof(f)) {
00500 rmspace(s);
00501 if ((s[0]) && (s[0] != '#') && (s[0] != ';')) {
00502 s1 = s;
00503 to = newsplit(&s1);
00504 if (!egg_strcasecmp(to, hand)) {
00505 int lapse;
00506
00507 from = newsplit(&s1);
00508 dt = newsplit(&s1);
00509 tt = atoi(dt);
00510 egg_strftime(wt, 14, "%b %d %H:%M", localtime(&tt));
00511 dt = wt;
00512 lapse = (int) ((now - tt) / 86400);
00513 if (lapse > note_life - 7) {
00514 if (lapse >= note_life)
00515 strcat(dt, NOTES_EXPIRE_TODAY);
00516 else
00517 sprintf(&dt[strlen(dt)], NOTES_EXPIRE_XDAYS, note_life - lapse,
00518 (note_life - lapse) == 1 ? "" : "S");
00519 }
00520 if (srd[0] == '+') {
00521 if (idx >= 0) {
00522 if (ix == 1)
00523 dprintf(idx, "### %s:\n", NOTES_WAITING);
00524 dprintf(idx, " %2d. %s (%s)\n", ix, from, dt);
00525 } else
00526 dprintf(DP_HELP, "NOTICE %s :%2d. %s (%s)\n", nick, ix, from,
00527 dt);
00528 } else if (notes_in(rd, ix)) {
00529 if (idx >= 0)
00530 dprintf(idx, "%2d. %s (%s): %s\n", ix, from, dt, s1);
00531 else
00532 dprintf(DP_HELP, "NOTICE %s :%2d. %s (%s): %s\n", nick, ix, from,
00533 dt, s1);
00534 ir++;
00535 }
00536 ix++;
00537 }
00538 }
00539 }
00540 }
00541 fclose(f);
00542 if ((srd[0] != '+') && (ir == 0) && (ix > 1)) {
00543 if (idx >= 0)
00544 dprintf(idx, "%s.\n", NOTES_NOT_THAT_MANY);
00545 else
00546 dprintf(DP_HELP, "NOTICE %s :%s.\n", nick, NOTES_NOT_THAT_MANY);
00547 }
00548 if (srd[0] == '+') {
00549 if (ix == 1) {
00550 if (idx >= 0)
00551 dprintf(idx, "%s.\n", NOTES_NO_MESSAGES);
00552 else
00553 dprintf(DP_HELP, "NOTICE %s :%s.\n", nick, NOTES_NO_MESSAGES);
00554 } else {
00555 if (idx >= 0)
00556 dprintf(idx, "### %s\n", (ix != 2) ? NOTES_DCC_USAGE_READ : NOTES_DCC_USAGE_READ2);
00557 else
00558 dprintf(DP_HELP, "NOTICE %s :%s: %d\n", nick, MISC_TOTAL, ix - 1);
00559 }
00560 } else if ((ir == 0) && (ix == 1)) {
00561 if (idx >= 0)
00562 dprintf(idx, "%s.\n", NOTES_NO_MESSAGES);
00563 else
00564 dprintf(DP_HELP, "NOTICE %s :%s.\n", nick, NOTES_NO_MESSAGES);
00565 }
00566 }
00567
00568
00569
00570
00571
00572
00573 static void notes_del(char *hand, char *nick, char *sdl, int idx)
00574 {
00575 FILE *f, *g;
00576 char s[513], *to, *s1;
00577 int in = 1;
00578 int er = 0;
00579 int dl[128];
00580
00581 if (sdl[0] == 0)
00582 sdl = "-";
00583 if (!notefile[0]) {
00584 if (idx >= 0)
00585 dprintf(idx, "%s.\n", NOTES_NO_MESSAGES);
00586 else
00587 dprintf(DP_HELP, "NOTICE %s :%s.\n", nick, NOTES_NO_MESSAGES);
00588 return;
00589 }
00590 f = fopen(notefile, "r");
00591 if (f == NULL) {
00592 if (idx >= 0)
00593 dprintf(idx, "%s.\n", NOTES_NO_MESSAGES);
00594 else
00595 dprintf(DP_HELP, "NOTICE %s :%s.\n", nick, NOTES_NO_MESSAGES);
00596 return;
00597 }
00598 sprintf(s, "%s~new", notefile);
00599 g = fopen(s, "w");
00600 if (g == NULL) {
00601 if (idx >= 0)
00602 dprintf(idx, "%s. :(\n", NOTES_FAILED_CHMOD);
00603 else
00604 dprintf(DP_HELP, "NOTICE %s :%s. :(\n", nick, NOTES_FAILED_CHMOD);
00605 fclose(f);
00606 return;
00607 }
00608 chmod(s, userfile_perm);
00609 notes_parse(dl, sdl);
00610 while (!feof(f)) {
00611 fgets(s, 512, f);
00612 if (s[strlen(s) - 1] == '\n')
00613 s[strlen(s) - 1] = 0;
00614 if (!feof(f)) {
00615 rmspace(s);
00616 if ((s[0]) && (s[0] != '#') && (s[0] != ';')) {
00617 s1 = s;
00618 to = newsplit(&s1);
00619 if (!egg_strcasecmp(to, hand)) {
00620 if (!notes_in(dl, in))
00621 fprintf(g, "%s %s\n", to, s1);
00622 else
00623 er++;
00624 in++;
00625 } else
00626 fprintf(g, "%s %s\n", to, s1);
00627 } else
00628 fprintf(g, "%s\n", s);
00629 }
00630 }
00631 fclose(f);
00632 fclose(g);
00633 unlink(notefile);
00634 sprintf(s, "%s~new", notefile);
00635 movefile(s, notefile);
00636 if ((er == 0) && (in > 1)) {
00637 if (idx >= 0)
00638 dprintf(idx, "%s.\n", NOTES_NOT_THAT_MANY);
00639 else
00640 dprintf(DP_HELP, "NOTICE %s :%s.\n", nick, NOTES_NOT_THAT_MANY);
00641 } else if (in == 1) {
00642 if (idx >= 0)
00643 dprintf(idx, "%s.\n", NOTES_NO_MESSAGES);
00644 else
00645 dprintf(DP_HELP, "NOTICE %s :%s.\n", nick, NOTES_NO_MESSAGES);
00646 } else {
00647 if (er == (in - 1)) {
00648 if (idx >= 0)
00649 dprintf(idx, "%s.\n", NOTES_ERASED_ALL);
00650 else
00651 dprintf(DP_HELP, "NOTICE %s :%s.\n", nick, NOTES_ERASED_ALL);
00652 } else {
00653 if (idx >= 0)
00654 dprintf(idx, "%s %d note%s; %d %s.\n", NOTES_ERASED, er,
00655 (er != 1) ? "s" : "", in - 1 - er, NOTES_LEFT);
00656 else
00657 dprintf(DP_HELP, "NOTICE %s :%s %d note%s; %d %s.\n", nick, MISC_ERASED,
00658 er, (er != 1) ? "s" : "", in - 1 - er, NOTES_LEFT);
00659 }
00660 }
00661 }
00662
00663 static int tcl_notes STDVAR
00664 {
00665 int count, read, nl[128];
00666 char s[601], *to, *from, *dt, *s1, *p;
00667 EGG_CONST char *list[3];
00668 FILE *f;
00669
00670 BADARGS(2, 3, " handle ?noteslist#?");
00671
00672 if (!get_user_by_handle(userlist, argv[1])) {
00673 Tcl_AppendResult(irp, "-1", NULL);
00674 return TCL_OK;
00675 }
00676 if (argc == 2) {
00677 sprintf(s, "%d", num_notes(argv[1]));
00678 Tcl_AppendResult(irp, s, NULL);
00679 return TCL_OK;
00680 }
00681 if (!notefile[0]) {
00682 Tcl_AppendResult(irp, "-2", NULL);
00683 return TCL_OK;
00684 }
00685 f = fopen(notefile, "r");
00686 if (f == NULL) {
00687 Tcl_AppendResult(irp, "-2", NULL);
00688 return TCL_OK;
00689 }
00690 count = 0;
00691 read = 0;
00692 notes_parse(nl, (argv[2][0] == 0) ? "-" : argv[2]);
00693 while (!feof(f) && fgets(s, 600, f)) {
00694 if (s[strlen(s) - 1] == '\n')
00695 s[strlen(s) - 1] = 0;
00696 if (!feof(f)) {
00697 rmspace(s);
00698 if ((s[0]) && (s[0] != '#') && (s[0] != ';')) {
00699 s1 = s;
00700 to = newsplit(&s1);
00701 if (!egg_strcasecmp(to, argv[1])) {
00702 read++;
00703 if (notes_in(nl, read)) {
00704 count++;
00705 from = newsplit(&s1);
00706 dt = newsplit(&s1);
00707 list[0] = from;
00708 list[1] = dt;
00709 list[2] = s1;
00710 p = Tcl_Merge(3, list);
00711 Tcl_AppendElement(irp, p);
00712 Tcl_Free((char *) p);
00713 }
00714 }
00715 }
00716 }
00717 }
00718 if (count == 0)
00719 Tcl_AppendResult(irp, "0", NULL);
00720 fclose(f);
00721 return TCL_OK;
00722 }
00723
00724
00725
00726
00727 static int msg_notes(char *nick, char *host, struct userrec *u, char *par)
00728 {
00729 char *pwd, *fcn;
00730
00731 if (!u)
00732 return 0;
00733
00734 if (u->flags & (USER_BOT | USER_COMMON))
00735 return 1;
00736
00737 if (!par[0]) {
00738 dprintf(DP_HELP, "NOTICE %s :%s: NOTES <pass> INDEX\n", nick, NOTES_USAGE);
00739 dprintf(DP_HELP, "NOTICE %s :NOTES <pass> TO <hand> <msg>\n", nick);
00740 dprintf(DP_HELP, "NOTICE %s :NOTES <pass> READ <# or ALL>\n", nick);
00741 dprintf(DP_HELP, "NOTICE %s :NOTES <pass> ERASE <# or ALL>\n", nick);
00742 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, NOTES_MAYBE);
00743 dprintf(DP_HELP, "NOTICE %s :Ex: NOTES mypass ERASE 2-4;8;16-\n", nick);
00744 return 1;
00745 }
00746
00747 if (!u_pass_match(u, "-")) {
00748 pwd = newsplit(&par);
00749 if (!u_pass_match(u, pwd))
00750 return 0;
00751 }
00752
00753 fcn = newsplit(&par);
00754 if (!egg_strcasecmp(fcn, "INDEX"))
00755 notes_read(u->handle, nick, "+", -1);
00756 else if (!egg_strcasecmp(fcn, "READ")) {
00757 if (!egg_strcasecmp(par, "ALL"))
00758 notes_read(u->handle, nick, "-", -1);
00759 else
00760 notes_read(u->handle, nick, par, -1);
00761 } else if (!egg_strcasecmp(fcn, "ERASE")) {
00762 if (!egg_strcasecmp(par, "ALL"))
00763 notes_del(u->handle, nick, "-", -1);
00764 else
00765 notes_del(u->handle, nick, par, -1);
00766 } else if (!egg_strcasecmp(fcn, "TO")) {
00767 char *to;
00768 int i;
00769 FILE *f;
00770 struct userrec *u2;
00771
00772 to = newsplit(&par);
00773 if (!par[0]) {
00774 dprintf(DP_HELP, "NOTICE %s :%s: NOTES <pass> TO <hand> <message>\n",
00775 nick, NOTES_USAGE);
00776 return 0;
00777 }
00778 u2 = get_user_by_handle(userlist, to);
00779 if (!u2) {
00780 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, NOTES_USERF_UNKNOWN);
00781 return 1;
00782 } else if (is_bot(u2)) {
00783 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, NOTES_NOTTO_BOT);
00784 return 1;
00785 }
00786 for (i = 0; i < dcc_total; i++) {
00787 if ((!egg_strcasecmp(dcc[i].nick, to)) &&
00788 (dcc[i].type->flags & DCT_GETNOTES)) {
00789 int aok = 1;
00790
00791 if (dcc[i].type->flags & DCT_CHAT)
00792 if (dcc[i].u.chat->away != NULL)
00793 aok = 0;
00794 if (!(dcc[i].type->flags & DCT_CHAT))
00795 aok = 0;
00796
00797 if (aok) {
00798 dprintf(i, "\007%s [%s]: %s\n", u->handle, NOTES_OUTSIDE, par);
00799 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, NOTES_DELIVERED);
00800 return 1;
00801 }
00802 }
00803 }
00804 if (notefile[0] == 0) {
00805 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, NOTES_UNSUPPORTED);
00806 return 1;
00807 }
00808 f = fopen(notefile, "a");
00809 if (f == NULL)
00810 f = fopen(notefile, "w");
00811 if (f == NULL) {
00812 dprintf(DP_HELP, "NOTICE %s :%s", nick, NOTES_NOTEFILE_FAILED);
00813 putlog(LOG_MISC, "*", "* %s", NOTES_NOTEFILE_UNREACHABLE);
00814 return 1;
00815 }
00816 chmod(notefile, userfile_perm);
00817 fprintf(f, "%s %s %li %s\n", to, u->handle, (long) now, par);
00818 fclose(f);
00819 dprintf(DP_HELP, "NOTICE %s :%s\n", nick, NOTES_DELIVERED);
00820 return 1;
00821 } else
00822 dprintf(DP_HELP, "NOTICE %s :%s: NOTES <pass> INDEX, READ, ERASE, TO\n",
00823 nick, NOTES_USAGE);
00824 putlog(LOG_CMDS, "*", "(%s!%s) !%s! NOTES %s %s", nick, host, u->handle, fcn,
00825 par[0] ? "..." : "");
00826 return 1;
00827 }
00828
00829 static void notes_hourly()
00830 {
00831 expire_notes();
00832 if (notify_users) {
00833 register struct chanset_t *chan;
00834 register memberlist *m;
00835 int k;
00836 register int l;
00837 char s1[256];
00838 struct userrec *u;
00839
00840 for (chan = chanset; chan; chan = chan->next) {
00841 for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
00842 sprintf(s1, "%s!%s", m->nick, m->userhost);
00843 u = get_user_by_host(s1);
00844 if (u) {
00845 k = num_notes(u->handle);
00846 for (l = 0; l < dcc_total; l++)
00847 if ((dcc[l].type->flags & DCT_CHAT) &&
00848 !egg_strcasecmp(dcc[l].nick, u->handle)) {
00849 k = 0;
00850 break;
00851 }
00852 if (k) {
00853 dprintf(DP_HELP, "NOTICE %s :You have %d note%s waiting on %s.\n",
00854 m->nick, k, k == 1 ? "" : "s", botname);
00855 dprintf(DP_HELP, "NOTICE %s :%s /MSG %s NOTES <pass> INDEX\n",
00856 m->nick, NOTES_FORLIST, botname);
00857 }
00858 }
00859 }
00860 }
00861 for (l = 0; l < dcc_total; l++) {
00862 k = num_notes(dcc[l].nick);
00863 if ((k > 0) && (dcc[l].type->flags & DCT_CHAT)) {
00864 dprintf(l, NOTES_WAITING2, k, (k == 1) ? "" : "s");
00865 dprintf(l, "### %s\n", (k != 1) ? NOTES_DCC_USAGE_READ : NOTES_DCC_USAGE_READ2);
00866 }
00867 }
00868 }
00869 }
00870
00871 static void away_notes(char *bot, int sock, char *msg)
00872 {
00873 int idx = findanyidx(sock);
00874
00875 if (egg_strcasecmp(bot, botnetnick))
00876 return;
00877 if (msg && msg[0])
00878 dprintf(idx, "%s\n", NOTES_STORED);
00879 else
00880 notes_read(dcc[idx].nick, 0, "+", idx);
00881 }
00882
00883 static int chon_notes(char *nick, int idx)
00884 {
00885 if (dcc[idx].type == &DCC_CHAT)
00886 notes_read(nick, 0, "+", idx);
00887 return 0;
00888 }
00889
00890 static void join_notes(char *nick, char *uhost, char *handle, char *par)
00891 {
00892 int i = -1, j;
00893 struct chanset_t *chan = chanset;
00894
00895 if (notify_onjoin) {
00896 for (j = 0; j < dcc_total; j++)
00897 if ((dcc[j].type->flags & DCT_CHAT) &&
00898 (!egg_strcasecmp(dcc[j].nick, handle)))
00899 return;
00900
00901 while (chan) {
00902 if (ismember(chan, nick))
00903 return;
00904 chan = chan->next;
00905 }
00906
00907 i = num_notes(handle);
00908 if (i) {
00909 dprintf(DP_HELP, NOTES_WAITING_NOTICE, nick, i, (i == 1) ? "" : "s", botname);
00910 dprintf(DP_HELP, "NOTICE %s :%s /MSG %s NOTES <pass> INDEX\n",
00911 nick, NOTES_FORLIST, botname);
00912 }
00913 }
00914 }
00915
00916
00917
00918
00919 static struct xtra_key *getnotesentry(struct userrec *u)
00920 {
00921 struct user_entry *ue = find_user_entry(&USERENTRY_XTRA, u);
00922 struct xtra_key *xk, *nxk = NULL;
00923
00924 if (!ue)
00925 return NULL;
00926
00927 for (xk = ue->u.extra; xk; xk = xk->next)
00928 if (xk->key && !egg_strcasecmp(xk->key, NOTES_IGNKEY)) {
00929 nxk = xk;
00930 break;
00931 }
00932 if (!nxk || !nxk->data || !(nxk->data[0]))
00933 return NULL;
00934 return nxk;
00935 }
00936
00937
00938
00939
00940 int get_note_ignores(struct userrec *u, char ***ignores)
00941 {
00942 struct xtra_key *xk;
00943 char *buf, *p;
00944 int ignoresn;
00945
00946
00947 if (!u)
00948 return 0;
00949 xk = getnotesentry(u);
00950 if (!xk)
00951 return 0;
00952
00953 rmspace(xk->data);
00954 buf = user_malloc(strlen(xk->data) + 1);
00955 strcpy(buf, xk->data);
00956 p = buf;
00957
00958
00959 *ignores = nmalloc(sizeof(char *) + 100);
00960 **ignores = p;
00961 ignoresn = 1;
00962 while ((p = strchr(p, ' ')) != NULL) {
00963 *ignores = nrealloc(*ignores, sizeof(char *) * (ignoresn + 1));
00964 (*ignores)[ignoresn] = p + 1;
00965 ignoresn++;
00966 *p = 0;
00967 p++;
00968 }
00969 return ignoresn;
00970 }
00971
00972 int add_note_ignore(struct userrec *u, char *mask)
00973 {
00974 struct xtra_key *xk;
00975 char **ignores;
00976 int ignoresn, i;
00977
00978 ignoresn = get_note_ignores(u, &ignores);
00979 if (ignoresn > 0) {
00980
00981 for (i = 0; i < ignoresn; i++)
00982 if (!strcmp(ignores[i], mask)) {
00983 nfree(ignores[0]);
00984 nfree(ignores);
00985
00986 return 0;
00987 }
00988 nfree(ignores[0]);
00989 nfree(ignores);
00990 }
00991
00992 xk = getnotesentry(u);
00993
00994 if (!xk) {
00995 struct xtra_key *mxk = user_malloc(sizeof(struct xtra_key));
00996 struct user_entry *ue = find_user_entry(&USERENTRY_XTRA, u);
00997
00998 if (!ue)
00999 return 0;
01000 mxk->next = 0;
01001 mxk->data = user_malloc(strlen(mask) + 1);
01002 strcpy(mxk->data, mask);
01003 mxk->key = user_malloc(strlen(NOTES_IGNKEY) + 1);
01004 strcpy(mxk->key, NOTES_IGNKEY);
01005 xtra_set(u, ue, mxk);
01006 } else {
01007 xk->data = user_realloc(xk->data, strlen(xk->data) + strlen(mask) + 2);
01008 strcat(xk->data, " ");
01009 strcat(xk->data, mask);
01010 }
01011 return 1;
01012 }
01013
01014 int del_note_ignore(struct userrec *u, char *mask)
01015 {
01016 struct user_entry *ue;
01017 struct xtra_key *xk;
01018 char **ignores, *buf = NULL;
01019 int ignoresn, i, size = 0, foundit = 0;
01020
01021 ignoresn = get_note_ignores(u, &ignores);
01022 if (!ignoresn)
01023 return 0;
01024
01025 buf = user_malloc(1);
01026 buf[0] = 0;
01027 for (i = 0; i < ignoresn; i++) {
01028 if (strcmp(ignores[i], mask)) {
01029 size += strlen(ignores[i]);
01030 if (buf[0])
01031 size++;
01032 buf = user_realloc(buf, size + 1);
01033 if (buf[0])
01034 strcat(buf, " ");
01035 strcat(buf, ignores[i]);
01036 } else
01037 foundit = 1;
01038 }
01039 nfree(ignores[0]);
01040 nfree(ignores);
01041
01042 if (!foundit) {
01043 nfree(buf);
01044 return 0;
01045 }
01046 ue = find_user_entry(&USERENTRY_XTRA, u);
01047
01048
01049 xk = user_malloc(sizeof(struct xtra_key));
01050 xk->key = user_malloc(strlen(NOTES_IGNKEY) + 1);
01051 xk->next = 0;
01052
01053 if (!buf[0]) {
01054 nfree(buf);
01055 strcpy(xk->key, NOTES_IGNKEY);
01056 xk->data = 0;
01057 } else {
01058 xk->data = buf;
01059 strcpy(xk->key, NOTES_IGNKEY);
01060 }
01061 xtra_set(u, ue, xk);
01062 return 1;
01063 }
01064
01065
01066
01067
01068 int match_note_ignore(struct userrec *u, char *from)
01069 {
01070 char **ignores;
01071 int ignoresn, i;
01072
01073 ignoresn = get_note_ignores(u, &ignores);
01074 if (!ignoresn)
01075 return 0;
01076 for (i = 0; i < ignoresn; i++)
01077 if (wild_match(ignores[i], from)) {
01078 nfree(ignores[0]);
01079 nfree(ignores);
01080 return 1;
01081 }
01082 nfree(ignores[0]);
01083 nfree(ignores);
01084 return 0;
01085 }
01086
01087
01088 static cmd_t notes_join[] = {
01089 {"*", "", (IntFunc) join_notes, "notes"},
01090 {NULL, NULL, NULL, NULL}
01091 };
01092
01093 static cmd_t notes_nkch[] = {
01094 {"*", "", (IntFunc) notes_change, "notes"},
01095 {NULL, NULL, NULL, NULL}
01096 };
01097
01098 static cmd_t notes_away[] = {
01099 {"*", "", (IntFunc) away_notes, "notes"},
01100 {NULL, NULL, NULL, NULL}
01101 };
01102
01103 static cmd_t notes_chon[] = {
01104 {"*", "", (IntFunc) chon_notes, "notes"},
01105 {NULL, NULL, NULL, NULL}
01106 };
01107
01108 static cmd_t notes_msgs[] = {
01109 {"notes", "", (IntFunc) msg_notes, NULL},
01110 {NULL, NULL, NULL, NULL}
01111 };
01112
01113 static tcl_ints notes_ints[] = {
01114 {"note-life", ¬e_life},
01115 {"max-notes", &maxnotes},
01116 {"allow-fwd", &allow_fwd},
01117 {"notify-users", ¬ify_users},
01118 {"notify-onjoin", ¬ify_onjoin},
01119 {NULL, NULL}
01120 };
01121
01122 static tcl_strings notes_strings[] = {
01123 {"notefile", notefile, 120, 0},
01124 {NULL, NULL, 0, 0}
01125 };
01126
01127 static tcl_cmds notes_tcls[] = {
01128 {"notes", tcl_notes},
01129 {"erasenotes", tcl_erasenotes},
01130 {"listnotes", tcl_listnotes},
01131 {"storenote", tcl_storenote},
01132 {NULL, NULL}
01133 };
01134
01135 static int notes_irc_setup(char *mod)
01136 {
01137 p_tcl_bind_list H_temp;
01138
01139 if ((H_temp = find_bind_table("join")))
01140 add_builtins(H_temp, notes_join);
01141 return 0;
01142 }
01143
01144 static int notes_server_setup(char *mod)
01145 {
01146 p_tcl_bind_list H_temp;
01147
01148 if ((H_temp = find_bind_table("msg")))
01149 add_builtins(H_temp, notes_msgs);
01150 return 0;
01151 }
01152
01153 static cmd_t notes_load[] = {
01154 {"server", "", notes_server_setup, "notes:server"},
01155 {"irc", "", notes_irc_setup, "notes:irc"},
01156 {NULL, NULL, NULL, NULL}
01157 };
01158
01159 static char *notes_close()
01160 {
01161 p_tcl_bind_list H_temp;
01162
01163 rem_tcl_ints(notes_ints);
01164 rem_tcl_strings(notes_strings);
01165 rem_tcl_commands(notes_tcls);
01166 if ((H_temp = find_bind_table("msg")))
01167 rem_builtins(H_temp, notes_msgs);
01168 if ((H_temp = find_bind_table("join")))
01169 rem_builtins(H_temp, notes_join);
01170 rem_builtins(H_dcc, notes_cmds);
01171 rem_builtins(H_chon, notes_chon);
01172 rem_builtins(H_away, notes_away);
01173 rem_builtins(H_nkch, notes_nkch);
01174 rem_builtins(H_load, notes_load);
01175 rem_help_reference("notes.help");
01176 del_hook(HOOK_MATCH_NOTEREJ, (Function) match_note_ignore);
01177 del_hook(HOOK_HOURLY, (Function) notes_hourly);
01178 del_entry_type(&USERENTRY_FWD);
01179 del_lang_section("notes");
01180 module_undepend(MODULE_NAME);
01181 return NULL;
01182 }
01183
01184 static int notes_expmem()
01185 {
01186 return 0;
01187 }
01188
01189 static void notes_report(int idx, int details)
01190 {
01191 if (details) {
01192 int size = notes_expmem();
01193
01194 if (notefile[0])
01195 dprintf(idx, " Notes can be stored in: %s\n", notefile);
01196 else
01197 dprintf(idx, " Notes can not be stored.\n");
01198 dprintf(idx, " Using %d byte%s of memory\n", size,
01199 (size != 1) ? "s" : "");
01200 }
01201 }
01202
01203 EXPORT_SCOPE char *notes_start();
01204
01205 static Function notes_table[] = {
01206 (Function) notes_start,
01207 (Function) notes_close,
01208 (Function) notes_expmem,
01209 (Function) notes_report,
01210 (Function) cmd_note,
01211 };
01212
01213 char *notes_start(Function *global_funcs)
01214 {
01215
01216 global = global_funcs;
01217
01218 notefile[0] = 0;
01219 module_register(MODULE_NAME, notes_table, 2, 1);
01220 if (!module_depend(MODULE_NAME, "eggdrop", 106, 0)) {
01221 module_undepend(MODULE_NAME);
01222 return "This module requires Eggdrop 1.6.0 or later.";
01223 }
01224 add_hook(HOOK_HOURLY, (Function) notes_hourly);
01225 add_hook(HOOK_MATCH_NOTEREJ, (Function) match_note_ignore);
01226 add_tcl_ints(notes_ints);
01227 add_tcl_strings(notes_strings);
01228 add_tcl_commands(notes_tcls);
01229 add_builtins(H_dcc, notes_cmds);
01230 add_builtins(H_chon, notes_chon);
01231 add_builtins(H_away, notes_away);
01232 add_builtins(H_nkch, notes_nkch);
01233 add_builtins(H_load, notes_load);
01234 add_help_reference("notes.help");
01235 add_lang_section("notes");
01236 notes_server_setup(0);
01237 notes_irc_setup(0);
01238 my_memcpy(&USERENTRY_FWD, &USERENTRY_INFO, sizeof(void *) * 12);
01239 add_entry_type(&USERENTRY_FWD);
01240 return NULL;
01241 }