00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "copyright.h"
00011 #include "config.h"
00012 #include <sys/time.h>
00013 #include <sys/types.h>
00014 #include "config.h"
00015 #include "db.h"
00016 #include "interface.h"
00017 #include "attrs.h"
00018 #include "externs.h"
00019 #include "mail.h"
00020 #include "alloc.h"
00021 #include "htab.h"
00022
00023 char msgbuff[LBUF_SIZE + (LBUF_SIZE >> 1) + 1];
00024
00025 extern char *getstring_noalloc(FILE *, int);
00026 extern void init_match(dbref player, const char *name, int type);
00027 extern void match_absolute(void);
00028 extern dbref match_result(void);
00029 extern void putstring(FILE * f, const char *s);
00030 extern int do_convtime(char *str, struct tm *ttm);
00031
00032 static int sign(int);
00033 static void do_mail_flags(dbref, char *, mail_flag, int);
00034 static void send_mail(dbref, dbref, const char *, const char *, int,
00035 mail_flag, int);
00036 static int player_folder(dbref);
00037 static int parse_msglist(char *, struct mail_selector *, dbref);
00038 static int mail_match(struct mail *, struct mail_selector, int);
00039 static int parse_folder(dbref, char *);
00040 static char *status_chars(struct mail *);
00041 static char *status_string(struct mail *);
00042 void add_folder_name(dbref, int, char *);
00043 static int get_folder_number(dbref, char *);
00044 void check_mail(dbref, int, int);
00045 static char *get_folder_name(dbref, int);
00046 static char *mail_list_time(const char *);
00047 static char *make_numlist(dbref, char *);
00048 static char *make_namelist(dbref, char *);
00049 static void mail_to_list(dbref, char *, char *, char *, int, int);
00050 static void do_edit_msg(dbref, char *, char *);
00051 static void do_mail_proof(dbref);
00052 void do_mail_cc(dbref, char *);
00053 void do_expmail_abort(dbref);
00054
00055 #define MALIAS_LEN 100
00056
00057 struct malias {
00058 int owner;
00059 char *name;
00060 char *desc;
00061 int numrecep;
00062 dbref list[MALIAS_LEN];
00063 };
00064
00065 int ma_size = 0;
00066 int ma_top = 0;
00067
00068 struct malias **malias;
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 static void mail_db_grow(int newtop)
00080 {
00081 int newsize, i;
00082 MENT *newdb;
00083
00084 if(newtop <= mudstate.mail_db_top) {
00085 return;
00086 }
00087 if(newtop <= mudstate.mail_db_size) {
00088 for(i = mudstate.mail_db_top; i < newtop; i++) {
00089 mudstate.mail_list[i].count = 0;
00090 mudstate.mail_list[i].message = NULL;
00091 }
00092 mudstate.mail_db_top = newtop;
00093 return;
00094 }
00095 if(newtop <= mudstate.mail_db_size + 100) {
00096 newsize = mudstate.mail_db_size + 100;
00097 } else {
00098 newsize = newtop;
00099 }
00100
00101 newdb = (MENT *) malloc((newsize + 1) * sizeof(MENT));
00102
00103 if(!newdb)
00104 abort();
00105
00106 if(mudstate.mail_list) {
00107 mudstate.mail_list -= 1;
00108 bcopy((char *) mudstate.mail_list, (char *) newdb,
00109 (mudstate.mail_db_top + 1) * sizeof(MENT));
00110 free(mudstate.mail_list);
00111 }
00112 mudstate.mail_list = newdb + 1;
00113 newdb = NULL;
00114
00115 for(i = mudstate.mail_db_top; i < newtop; i++) {
00116 mudstate.mail_list[i].count = 0;
00117 mudstate.mail_list[i].message = NULL;
00118 }
00119 mudstate.mail_db_top = newtop;
00120 mudstate.mail_db_size = newsize;
00121 }
00122
00123
00124
00125
00126
00127
00128 static void make_mail_freelist()
00129 {
00130 int i;
00131
00132 for(i = 0; i < mudstate.mail_db_top; i++) {
00133 if(mudstate.mail_list[i].message == NULL) {
00134 mudstate.mail_freelist = i;
00135 return;
00136 }
00137 }
00138
00139 mail_db_grow(i + 1);
00140 mudstate.mail_freelist = i;
00141 }
00142
00143
00144
00145
00146
00147
00148 static int add_mail_message(dbref player, char *message)
00149 {
00150 int number;
00151
00152 char *atrstr, *execstr, *msg, *bp, *str;
00153 int aflags;
00154 dbref aowner;
00155
00156 if(!strcasecmp(message, "clear")) {
00157 notify(player,
00158 "MAIL: You probably don't wanna send mail saying 'clear'.");
00159 return -1;
00160 }
00161 if(!mudstate.mail_list) {
00162 mail_db_grow(1);
00163 }
00164
00165
00166
00167 while (mudstate.mail_list[mudstate.mail_freelist].message != NULL) {
00168 make_mail_freelist();
00169 }
00170 number = mudstate.mail_freelist;
00171
00172 atrstr = atr_get(player, A_SIGNATURE, &aowner, &aflags);
00173 execstr = bp = alloc_lbuf("add_mail_message");
00174 str = atrstr;
00175 exec(execstr, &bp, 0, player, player, EV_STRIP | EV_FCHECK | EV_EVAL,
00176 &str, (char **) NULL, 0);
00177 *bp = '\0';
00178 msg = bp = alloc_lbuf("add_mail_message.2");
00179 str = message;
00180 exec(msg, &bp, 0, player, player, EV_EVAL | EV_FCHECK | EV_NO_COMPRESS,
00181 &str, (char **) NULL, 0);
00182 *bp = '\0';
00183
00184 mudstate.mail_list[number].message =
00185 (char *) strdup(tprintf("%s %s", msg, execstr));
00186 free_lbuf(atrstr);
00187 free_lbuf(execstr);
00188 free_lbuf(msg);
00189 make_mail_freelist();
00190 return number;
00191 }
00192
00193
00194
00195
00196
00197 static int add_mail_message_nosig(char *message)
00198 {
00199 int number;
00200
00201 number = mudstate.mail_freelist;
00202 if(!mudstate.mail_list) {
00203 mail_db_grow(1);
00204 }
00205 mudstate.mail_list[number].message = (char *) strdup(message);
00206
00207 make_mail_freelist();
00208 return number;
00209 }
00210
00211
00212
00213
00214
00215
00216 static void new_mail_message(char *message, int number)
00217 {
00218 mudstate.mail_list[number].message = (char *) strdup(message);
00219 }
00220
00221
00222
00223
00224
00225 static INLINE void add_count(int number)
00226 {
00227 mudstate.mail_list[number].count++;
00228 }
00229
00230
00231
00232
00233
00234
00235 static void delete_mail_message(int number)
00236 {
00237 mudstate.mail_list[number].count--;
00238
00239 if(mudstate.mail_list[number].count < 1) {
00240 free(mudstate.mail_list[number].message);
00241 mudstate.mail_list[number].message = NULL;
00242 mudstate.mail_list[number].count = 0;
00243 }
00244 }
00245
00246
00247
00248
00249
00250
00251 INLINE char *get_mail_message(int number)
00252 {
00253 static char buff[LBUF_SIZE];
00254
00255 if(mudstate.mail_list[number].message != NULL) {
00256 return mudstate.mail_list[number].message;
00257 } else {
00258 delete_mail_message(number);
00259 StringCopy(buff,
00260 "MAIL: This mail message does not exist in the database. Please alert your admin.");
00261 return buff;
00262 }
00263 }
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 extern char *upcasestr(char *);
00280
00281
00282
00283
00284 void do_mail_change_folder(dbref player, char *fld, char *newname)
00285 {
00286 int pfld;
00287 char *p;
00288
00289 if(!fld || !*fld) {
00290
00291
00292
00293 for(pfld = MAX_FOLDERS; pfld >= 0; pfld--)
00294 check_mail(player, pfld, 1);
00295
00296 pfld = player_folder(player);
00297 notify_printf(player, "MAIL: Current folder is %d [%s].", pfld,
00298 get_folder_name(player, pfld));
00299
00300 return;
00301 }
00302 pfld = parse_folder(player, fld);
00303 if(pfld < 0) {
00304 notify(player, "MAIL: What folder is that?");
00305 return;
00306 }
00307 if(newname && *newname) {
00308
00309
00310
00311 if(strlen(newname) > FOLDER_NAME_LEN) {
00312 notify(player, "MAIL: Folder name too long");
00313 return;
00314 }
00315 for(p = newname; p && *p; p++) {
00316 if(!isalnum(*p)) {
00317 notify(player, "MAIL: Illegal folder name");
00318 return;
00319 }
00320 }
00321
00322 add_folder_name(player, pfld, newname);
00323 notify_printf(player, "MAIL: Folder %d now named '%s'", pfld,
00324 newname);
00325 } else {
00326
00327
00328
00329 set_player_folder(player, pfld);
00330 notify_printf(player, "MAIL: Current folder set to %d [%s].",
00331 pfld, get_folder_name(player, pfld));
00332 }
00333 }
00334
00335 void do_mail_tag(dbref player, char *msglist)
00336 {
00337 do_mail_flags(player, msglist, M_TAG, 0);
00338 }
00339
00340 void do_mail_safe(dbref player, char *msglist)
00341 {
00342 do_mail_flags(player, msglist, M_SAFE, 0);
00343 }
00344
00345 void do_mail_clear(dbref player, char *msglist)
00346 {
00347 do_mail_flags(player, msglist, M_CLEARED, 0);
00348 }
00349
00350 void do_mail_untag(dbref player, char *msglist)
00351 {
00352 do_mail_flags(player, msglist, M_TAG, 1);
00353 }
00354
00355 void do_mail_unclear(dbref player, char *msglist)
00356 {
00357 do_mail_flags(player, msglist, M_CLEARED, 1);
00358 }
00359
00360
00361
00362
00363
00364
00365 static void do_mail_flags(dbref player, char *msglist, mail_flag flag,
00366 int negate)
00367 {
00368 struct mail *mp;
00369 struct mail_selector ms;
00370 int i = 0, j = 0, folder;
00371
00372 if(!parse_msglist(msglist, &ms, player)) {
00373 return;
00374 }
00375 folder = player_folder(player);
00376 for(mp = (struct mail *) nhashfind((int) player, &mudstate.mail_htab);
00377 mp; mp = mp->next) {
00378 if(All(ms) || (Folder(mp) == folder)) {
00379 i++;
00380 if(mail_match(mp, ms, i)) {
00381 j++;
00382 if(negate) {
00383 mp->read &= ~flag;
00384 } else {
00385 mp->read |= flag;
00386 }
00387
00388 switch (flag) {
00389 case M_TAG:
00390 notify_printf(player, "MAIL: Msg #%d %s.", i,
00391 negate ? "untagged" : "tagged");
00392 break;
00393 case M_CLEARED:
00394 if(Unread(mp) && !negate) {
00395 notify_printf(player,
00396 "MAIL: Unread Msg #%d cleared! Use @mail/unclear %d to recover.",
00397 i, i);
00398 } else {
00399 notify_printf(player, "MAIL: Msg #%d %s.", i,
00400 negate ? "uncleared" : "cleared");
00401 }
00402 break;
00403 case M_SAFE:
00404 notify_printf(player, "MAIL: Msg #%d marked safe.", i);
00405 break;
00406 }
00407 }
00408 }
00409 }
00410
00411 if(!j) {
00412
00413
00414
00415 notify(player, "MAIL: You don't have any matching messages!");
00416 }
00417 }
00418
00419
00420
00421
00422
00423 void do_mail_file(dbref player, char *msglist, char *folder)
00424 {
00425 struct mail *mp;
00426 struct mail_selector ms;
00427 int foldernum, origfold;
00428 int i = 0, j = 0;
00429
00430 if(!parse_msglist(msglist, &ms, player)) {
00431 return;
00432 }
00433 if((foldernum = parse_folder(player, folder)) == -1) {
00434 notify(player, "MAIL: Invalid folder specification");
00435 return;
00436 }
00437 origfold = player_folder(player);
00438 for(mp = (struct mail *) nhashfind((int) player, &mudstate.mail_htab);
00439 mp; mp = mp->next) {
00440 if(All(ms) || (Folder(mp) == origfold)) {
00441 i++;
00442 if(mail_match(mp, ms, i)) {
00443 j++;
00444 mp->read &= M_FMASK;
00445
00446
00447 mp->read |= FolderBit(foldernum);
00448 notify_printf(player, "MAIL: Msg %d filed in folder %d",
00449 i, foldernum);
00450 }
00451 }
00452 }
00453
00454 if(!j) {
00455
00456
00457
00458 notify(player, "MAIL: You don't have any matching messages!");
00459 }
00460 }
00461
00462
00463
00464
00465
00466 void do_mail_read(dbref player, char *msglist)
00467 {
00468 struct mail *mp;
00469 char *tbuf1, *buff, *status, *names;
00470 struct mail_selector ms;
00471 int i = 0, j = 0, folder;
00472
00473 tbuf1 = alloc_lbuf("do_mail_read");
00474
00475 if(!parse_msglist(msglist, &ms, player)) {
00476 free_lbuf(tbuf1);
00477 return;
00478 }
00479 folder = player_folder(player);
00480 for(mp = (struct mail *) nhashfind((int) player, &mudstate.mail_htab);
00481 mp; mp = mp->next) {
00482 if(Folder(mp) == folder) {
00483 i++;
00484 if(mail_match(mp, ms, i)) {
00485
00486
00487
00488 j++;
00489 buff = alloc_lbuf("do_mail_read");
00490 StringCopy(buff, get_mail_message(mp->number));
00491 notify(player, DASH_LINE);
00492 status = status_string(mp);
00493 names = make_namelist(player, (char *) mp->tolist);
00494 notify_printf(player,
00495 "%-3d From: %-*s At: %-25s %s\r\nFldr : %-2d Status: %s\r\nTo : %-65s\r\nSubject: %-65s",
00496 i, PLAYER_NAME_LIMIT - 6, Name(mp->from),
00497 mp->time, (Connected(mp->from)
00498 && (!Hidden(mp->from)
00499 || Hasprivs(player))) ? " (Conn)"
00500 : " ", folder, status, names, mp->subject);
00501 free_lbuf(names);
00502 free_lbuf(status);
00503 notify(player, DASH_LINE);
00504 StringCopy(tbuf1, buff);
00505 notify(player, tbuf1);
00506 notify(player, DASH_LINE);
00507 free_lbuf(buff);
00508 if(Unread(mp))
00509 mp->read |= M_ISREAD;
00510
00511
00512
00513
00514
00515
00516 }
00517 }
00518 }
00519
00520 if(!j) {
00521
00522
00523
00524 notify(player, "MAIL: You don't have that many matching messages!");
00525 }
00526 free_lbuf(tbuf1);
00527 }
00528
00529 void do_mail_retract(dbref player, char *name, char *msglist)
00530 {
00531 dbref target;
00532 struct mail *mp, *nextp;
00533 struct mail_selector ms;
00534 int i = 0, j = 0;
00535
00536 target = lookup_player(player, name, 1);
00537 if(target == NOTHING) {
00538 notify(player, "MAIL: No such player.");
00539 return;
00540 }
00541 if(!parse_msglist(msglist, &ms, target)) {
00542 return;
00543 }
00544 for(mp = (struct mail *) nhashfind((int) target, &mudstate.mail_htab);
00545 mp; mp = nextp) {
00546 if(mp->from == player) {
00547 i++;
00548 if(mail_match(mp, ms, i)) {
00549 j++;
00550 if(Unread(mp)) {
00551 if(mp->prev == NULL)
00552 nhashrepl((int) target, (int *) mp->next,
00553 &mudstate.mail_htab);
00554 else if(mp->next == NULL)
00555 mp->prev->next = NULL;
00556
00557 if(mp->prev != NULL)
00558 mp->prev->next = mp->next;
00559 if(mp->next != NULL)
00560 mp->next->prev = mp->prev;
00561
00562 nextp = mp->next;
00563 free((char *) mp->subject);
00564 delete_mail_message(mp->number);
00565 free((char *) mp->time);
00566 free((char *) mp->tolist);
00567 free(mp);
00568 notify(player, "MAIL: Mail retracted.");
00569 } else {
00570 notify(player, "MAIL: That message has been read.");
00571 nextp = mp->next;
00572 }
00573 } else {
00574 nextp = mp->next;
00575 }
00576 } else {
00577 nextp = mp->next;
00578 }
00579 }
00580
00581 if(!j) {
00582
00583
00584
00585 notify(player, "MAIL: No matching messages.");
00586 }
00587 }
00588
00589 void do_mail_review(dbref player, char *name, char *msglist)
00590 {
00591 struct mail *mp;
00592 struct mail_selector ms;
00593 int i = 0, j = 0;
00594 dbref target;
00595 char *tbuf1, *msg, *status, *bp, *str;
00596
00597 target = lookup_player(player, name, 1);
00598 if(target == NOTHING) {
00599 notify(player, "MAIL: No such player.");
00600 return;
00601 }
00602 if(!msglist || !*msglist) {
00603 notify_printf(player,
00604 "-------------------- MAIL: %-25s ------------------",
00605 Name(target));
00606 for(mp =
00607 (struct mail *) nhashfind((int) target, &mudstate.mail_htab);
00608 mp; mp = mp->next) {
00609 if(mp->from == player) {
00610 i++;
00611
00612
00613
00614 notify_printf(player,
00615 "[%s] %-3d (%4d) From: %-*s Sub: %.25s",
00616 status_chars(mp), i,
00617 strlen(get_mail_message(mp->number)),
00618 PLAYER_NAME_LIMIT - 6, Name(mp->from),
00619 mp->subject);
00620 }
00621 }
00622 notify(player, DASH_LINE);
00623 } else {
00624 tbuf1 = alloc_lbuf("do_mail_read");
00625
00626 if(!parse_msglist(msglist, &ms, target)) {
00627 free_lbuf(tbuf1);
00628 return;
00629 }
00630 for(mp =
00631 (struct mail *) nhashfind((int) target, &mudstate.mail_htab);
00632 mp; mp = mp->next) {
00633 if(mp->from == player) {
00634 i++;
00635 if(mail_match(mp, ms, i)) {
00636
00637
00638
00639 j++;
00640 status = status_string(mp);
00641 strcpy(msgbuff, get_mail_message(mp->number));
00642 msg = bp = alloc_lbuf("do_mail_review");
00643 str = msgbuff;
00644 exec(msg, &bp, 0, player, player,
00645 EV_EVAL | EV_FCHECK | EV_NO_COMPRESS, &str,
00646 (char **) NULL, 0);
00647 *bp = '\0';
00648 notify(player, DASH_LINE);
00649 notify_printf(player,
00650 "%-3d From: %-*s At: %-25s %s\r\nFldr : %-2d Status: %s\r\nSubject: %-65s",
00651 i, PLAYER_NAME_LIMIT - 6, Name(mp->from),
00652 mp->time, (Connected(mp->from) &&
00653 (!Hidden(mp->from) ||
00654 Hasprivs(player))) ? " (Conn)" :
00655 " ", 0, status, mp->subject);
00656 free_lbuf(status);
00657 notify(player, DASH_LINE);
00658 StringCopy(tbuf1, msg);
00659 notify(player, tbuf1);
00660 notify(player, DASH_LINE);
00661 free_lbuf(msg);
00662 }
00663 }
00664 }
00665
00666 if(!j) {
00667
00668
00669
00670
00671 notify(player,
00672 "MAIL: You don't have that many matching messages!");
00673 }
00674 free_lbuf(tbuf1);
00675 }
00676 }
00677
00678 void do_mail_list(dbref player, char *msglist, int sub)
00679 {
00680 struct mail *mp;
00681 struct mail_selector ms;
00682 int i = 0, folder;
00683 char *time;
00684
00685 if(!parse_msglist(msglist, &ms, player)) {
00686 return;
00687 }
00688 folder = player_folder(player);
00689
00690 notify_printf(player,
00691 "--------------------------- MAIL: Folder %d ----------------------------",
00692 folder);
00693
00694 for(mp = (struct mail *) nhashfind((int) player, &mudstate.mail_htab);
00695 mp; mp = mp->next) {
00696 if(Folder(mp) == folder) {
00697 i++;
00698 if(mail_match(mp, ms, i)) {
00699
00700
00701
00702
00703 time = mail_list_time(mp->time);
00704 if(sub)
00705 notify_printf(player,
00706 "[%s] %-3d (%4d) From: %-*s Sub: %.25s",
00707 status_chars(mp), i,
00708 strlen(get_mail_message(mp->number)),
00709 PLAYER_NAME_LIMIT - 6, Name(mp->from),
00710 mp->subject);
00711 else
00712 notify_printf(player,
00713 "[%s] %-3d (%4d) From: %-*s At: %s %s",
00714 status_chars(mp), i,
00715 strlen(get_mail_message(mp->number)),
00716 PLAYER_NAME_LIMIT - 6, Name(mp->from), time,
00717 ((Connected(mp->from)
00718 && (!Hidden(mp->from)
00719 || Hasprivs(player))) ? "Conn" :
00720 " "));
00721 free_lbuf(time);
00722 }
00723 }
00724 }
00725 notify(player, DASH_LINE);
00726 }
00727
00728 static char *mail_list_time(const char *the_time)
00729 {
00730 char *new;
00731 char *p, *q;
00732 int i;
00733
00734 p = (char *) the_time;
00735 q = new = alloc_lbuf("mail_list_time");
00736 if(!p || !*p) {
00737 *new = '\0';
00738 return new;
00739 }
00740
00741
00742
00743
00744
00745
00746 for(i = 0; i < 16; i++) {
00747 if(*p)
00748 *q++ = *p++;
00749 }
00750
00751 for(i = 0; i < 3; i++) {
00752 if(*p)
00753 p++;
00754 }
00755
00756 for(i = 0; i < 5; i++) {
00757 if(*p)
00758 *q++ = *p++;
00759 }
00760
00761 *q = '\0';
00762 return new;
00763 }
00764
00765 void do_mail_purge(dbref player)
00766 {
00767 struct mail *mp, *nextp;
00768
00769
00770
00771
00772 for(mp = (struct mail *) nhashfind((int) player, &mudstate.mail_htab);
00773 mp; mp = nextp) {
00774 if(Cleared(mp)) {
00775
00776
00777
00778
00779
00780
00781 if(mp->prev == NULL)
00782 nhashrepl((int) player, (int *) mp->next,
00783 &mudstate.mail_htab);
00784 else if(mp->next == NULL)
00785 mp->prev->next = NULL;
00786
00787
00788
00789
00790 if(mp->prev != NULL)
00791 mp->prev->next = mp->next;
00792 if(mp->next != NULL)
00793 mp->next->prev = mp->prev;
00794
00795
00796
00797
00798 nextp = mp->next;
00799
00800
00801 if(mp->prev == NULL && mp->next == NULL)
00802 nhashdelete((int) player, &mudstate.mail_htab);
00803
00804
00805
00806
00807 free((char *) mp->subject);
00808 delete_mail_message(mp->number);
00809 free((char *) mp->time);
00810 free((char *) mp->tolist);
00811 free(mp);
00812 } else {
00813 nextp = mp->next;
00814 }
00815 }
00816 notify(player, "MAIL: Mailbox purged.");
00817 }
00818
00819 void do_mail_fwd(dbref player, char *msg, char *tolist)
00820 {
00821 struct mail *mp;
00822 int num;
00823
00824 if(!msg || !*msg) {
00825 notify(player, "MAIL: No message list.");
00826 return;
00827 }
00828 if(!tolist || !*tolist) {
00829 notify(player, "MAIL: To whom should I forward?");
00830 return;
00831 }
00832 num = atoi(msg);
00833 if(!num) {
00834 notify(player, "MAIL: I don't understand that message number.");
00835 return;
00836 }
00837 mp = mail_fetch(player, num);
00838 if(!mp) {
00839 notify(player, "MAIL: You can't forward non-existent messages.");
00840 return;
00841 }
00842 do_expmail_start(player, tolist, tprintf("%s (fwd from %s)",
00843 mp->subject, Name(mp->from)));
00844 atr_add_raw(player, A_MAILMSG, get_mail_message(mp->number));
00845 atr_add_raw(player, A_MAILFLAGS, tprintf("%d",
00846 (atoi
00847 (atr_get_raw
00848 (player,
00849 A_MAILFLAGS)) | M_FORWARD)));
00850 }
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863 struct mail *mail_fetch(dbref player, int num)
00864 {
00865 struct mail *mp;
00866 int i = 0;
00867
00868 for(mp = (struct mail *) nhashfind((int) player, &mudstate.mail_htab);
00869 mp; mp = mp->next) {
00870 if(Folder(mp) == player_folder(player)) {
00871 i++;
00872 if(i == num)
00873 return mp;
00874 }
00875 }
00876 return NULL;
00877 }
00878
00879
00880
00881
00882
00883
00884 void count_mail(dbref player, int folder, int *rcount,
00885 int *ucount, int *ccount)
00886 {
00887 struct mail *mp;
00888 int rc, uc, cc;
00889
00890 cc = rc = uc = 0;
00891 for(mp = (struct mail *) nhashfind((int) player, &mudstate.mail_htab);
00892 mp; mp = mp->next) {
00893 if(Folder(mp) == folder) {
00894 if(Read(mp))
00895 rc++;
00896 else
00897 uc++;
00898
00899 if(Cleared(mp))
00900 cc++;
00901 }
00902 }
00903 *rcount = rc;
00904 *ucount = uc;
00905 *ccount = cc;
00906 }
00907
00908 void urgent_mail(dbref player, int folder, int *ucount)
00909 {
00910 struct mail *mp;
00911 int uc;
00912
00913 uc = 0;
00914
00915 for(mp = (struct mail *) nhashfind((int) player, &mudstate.mail_htab);
00916 mp; mp = mp->next) {
00917 if(Folder(mp) == folder) {
00918 if(!(Read(mp)) && (Urgent(mp)))
00919 uc++;
00920 }
00921 }
00922 *ucount = uc;
00923 }
00924
00925 static void send_mail(dbref player, dbref target, const char *tolist,
00926 const char *subject, int number, mail_flag flags,
00927 int silent)
00928 {
00929 struct mail *newp;
00930 struct mail *mp;
00931 time_t tt;
00932 char tbuf1[30];
00933
00934 if(Typeof(target) != TYPE_PLAYER) {
00935 notify(player, "MAIL: You cannot send mail to non-existent people.");
00936 delete_mail_message(number);
00937 return;
00938 }
00939 tt = time(NULL);
00940 StringCopy(tbuf1, ctime(&tt));
00941 tbuf1[strlen(tbuf1) - 1] = '\0';
00942
00943
00944
00945
00946
00947
00948 newp = (struct mail *) malloc(sizeof(struct mail));
00949
00950 newp->to = target;
00951 newp->from = player;
00952 newp->tolist = (char *) strdup((char *) tolist);
00953
00954 newp->number = number;
00955 add_count(number);
00956
00957 newp->time = (char *) strdup(tbuf1);
00958 newp->subject = (char *) strdup(subject);
00959 newp->read = flags & M_FMASK;
00960
00961
00962
00963
00964
00965
00966 if(!nhashfind((int) target, &mudstate.mail_htab)) {
00967 nhashadd((int) target, (int *) newp, &mudstate.mail_htab);
00968 newp->next = NULL;
00969 newp->prev = NULL;
00970 } else {
00971 for(mp =
00972 (struct mail *) nhashfind((int) target, &mudstate.mail_htab);
00973 mp->next; mp = mp->next);
00974
00975 mp->next = newp;
00976 newp->next = NULL;
00977 newp->prev = mp;
00978 }
00979
00980
00981
00982
00983 if(!silent)
00984 notify_printf(player, "MAIL: You sent your message to %s.",
00985 Name(target));
00986
00987 notify_printf(target, "MAIL: You have a new message from %s.",
00988 Name(player));
00989 did_it(player, target, A_MAIL, NULL, (int) NULL, NULL, A_AMAIL, NULL,
00990 NOTHING);
00991 return;
00992 }
00993
00994 void do_mail_nuke(dbref player)
00995 {
00996 struct mail *mp, *nextp;
00997 dbref thing;
00998
00999 if(!God(player)) {
01000 notify(player,
01001 "The postal service issues a warrant for your arrest.");
01002 return;
01003 }
01004
01005
01006
01007 MAIL_ITER_SAFE(mp, thing, nextp) {
01008 nextp = mp->next;
01009 delete_mail_message(mp->number);
01010 free((char *) mp->subject);
01011 free((char *) mp->tolist);
01012 free((char *) mp->time);
01013 free(mp);
01014 }
01015
01016 log_text(tprintf("** MAIL PURGE ** done by %s(#%d).", Name(player),
01017 (int) player));
01018
01019 notify(player, "You annihilate the post office. All messages cleared.");
01020 }
01021
01022 void do_mail_debug(dbref player, char *action, char *victim)
01023 {
01024 dbref target, thing;
01025 struct mail *mp, *nextp;
01026
01027 if(!Wizard(player)) {
01028 notify(player, "Go get some bugspray.");
01029 return;
01030 }
01031 if(string_prefix("clear", action)) {
01032 target = lookup_player(player, victim, 1);
01033 if(target == NOTHING) {
01034 init_match(player, victim, NOTYPE);
01035 match_absolute();
01036 target = match_result();
01037 }
01038 if(target == NOTHING) {
01039 notify_printf(player, "%s: no such player.", victim);
01040 return;
01041 }
01042 do_mail_clear(target, NULL);
01043 do_mail_purge(target);
01044 notify_printf(player, "Mail cleared for %s(#%d).", Name(target),
01045 target);
01046 return;
01047 } else if(string_prefix("sanity", action)) {
01048 MAIL_ITER_ALL(mp, thing) {
01049 if(!Good_obj(mp->to))
01050 notify_printf(player, "Bad object #%d has mail.", mp->to);
01051 else if(Typeof(mp->to) != TYPE_PLAYER)
01052 notify_printf(player,
01053 "%s(#%d) has mail but is not a player.",
01054 Name(mp->to), mp->to);
01055 }
01056 notify(player, "Mail sanity check completed.");
01057 } else if(string_prefix("fix", action)) {
01058 MAIL_ITER_SAFE(mp, thing, nextp) {
01059 if(!Good_obj(mp->to) || (Typeof(mp->to) != TYPE_PLAYER)) {
01060 notify_printf(player, "Fixing mail for #%d.", mp->to);
01061
01062
01063
01064
01065
01066
01067 if(mp->prev == NULL)
01068 nhashrepl((int) player, (int *) mp->next,
01069 &mudstate.mail_htab);
01070 else if(mp->next == NULL)
01071 mp->prev->next = NULL;
01072
01073
01074
01075 if(mp->prev != NULL)
01076 mp->prev->next = mp->next;
01077 if(mp->next != NULL)
01078 mp->next->prev = mp->prev;
01079
01080
01081
01082 nextp = mp->next;
01083
01084
01085
01086 free((char *) mp->subject);
01087 delete_mail_message(mp->number);
01088 free((char *) mp->time);
01089 free((char *) mp->tolist);
01090 free(mp);
01091 } else
01092 nextp = mp->next;
01093 }
01094 notify(player, "Mail sanity fix completed.");
01095 } else {
01096 notify(player, "That is not a debugging option.");
01097 return;
01098 }
01099 }
01100
01101 void do_mail_stats(dbref player, char *name, int full)
01102 {
01103 dbref target, thing;
01104 int fc, fr, fu, tc, tr, tu, fchars, tchars, cchars, count;
01105 char last[50];
01106 struct mail *mp;
01107
01108 fc = fr = fu = tc = tr = tu = cchars = fchars = tchars = count = 0;
01109
01110
01111
01112
01113
01114 if((*name == '\0') || !name) {
01115 if(Wizard(player))
01116 target = AMBIGUOUS;
01117 else
01118 target = player;
01119 } else if(*name == NUMBER_TOKEN) {
01120 target = atoi(&name[1]);
01121 if(!Good_obj(target) || (Typeof(target) != TYPE_PLAYER))
01122 target = NOTHING;
01123 } else if(!strcasecmp(name, "me")) {
01124 target = player;
01125 } else {
01126 target = lookup_player(player, name, 1);
01127 }
01128
01129 if(target == NOTHING) {
01130 init_match(player, name, NOTYPE);
01131 match_absolute();
01132 target = match_result();
01133 }
01134 if(target == NOTHING) {
01135 notify_printf(player, "%s: No such player.", name);
01136 return;
01137 }
01138 if(!Wizard(player) && (target != player)) {
01139 notify(player, "The post office protects privacy!");
01140 return;
01141 }
01142
01143
01144
01145
01146 if(!payfor(player, mudconf.searchcost)) {
01147 notify_printf(player, "Finding mail stats costs %d %s.",
01148 mudconf.searchcost,
01149 (mudconf.searchcost ==
01150 1) ? mudconf.one_coin : mudconf.many_coins);
01151 return;
01152 }
01153 if(target == AMBIGUOUS) {
01154
01155
01156 if(full == 0) {
01157 MAIL_ITER_ALL(mp, thing) {
01158 count++;
01159 }
01160 notify_printf(player,
01161 "There are %d messages in the mail spool.", count);
01162 return;
01163 } else if(full == 1) {
01164 MAIL_ITER_ALL(mp, thing) {
01165 if(Cleared(mp))
01166 fc++;
01167 else if(Read(mp))
01168 fr++;
01169 else
01170 fu++;
01171 }
01172 notify_printf(player,
01173 "MAIL: There are %d msgs in the mail spool, %d unread, %d cleared.",
01174 fc + fr + fu, fu, fc);
01175 return;
01176 } else {
01177 MAIL_ITER_ALL(mp, thing) {
01178
01179 if(Cleared(mp)) {
01180 fc++;
01181 cchars += strlen(get_mail_message(mp->number));
01182 } else if(Read(mp)) {
01183 fr++;
01184 fchars += strlen(get_mail_message(mp->number));
01185 } else {
01186 fu++;
01187 tchars += strlen(get_mail_message(mp->number));
01188 }
01189 }
01190 notify_printf(player,
01191 "MAIL: There are %d old msgs in the mail spool, totalling %d characters.",
01192 fr, fchars);
01193 notify_printf(player,
01194 "MAIL: There are %d new msgs in the mail spool, totalling %d characters.",
01195 fu, tchars);
01196 notify_printf(player,
01197 "MAIL: There are %d cleared msgs in the mail spool, totalling %d characters.",
01198 fc, cchars);
01199 return;
01200 }
01201 }
01202
01203
01204
01205
01206 if(full == 0) {
01207
01208
01209
01210 MAIL_ITER_ALL(mp, thing) {
01211 if(mp->from == target)
01212 fr++;
01213 if(mp->to == target)
01214 tr++;
01215 }
01216 notify_printf(player, "%s sent %d messages.", Name(target), fr);
01217 notify_printf(player, "%s has %d messages.", Name(target), tr);
01218 return;
01219 }
01220
01221
01222
01223 MAIL_ITER_ALL(mp, thing) {
01224 if(mp->from == target) {
01225 if(Cleared(mp))
01226 fc++;
01227 else if(Read(mp))
01228 fr++;
01229 else
01230 fu++;
01231 if(full == 2)
01232 fchars += strlen(get_mail_message(mp->number));
01233 }
01234 if(mp->to == target) {
01235 if(!tr && !tu) {
01236 StringCopy(last, mp->time);
01237 }
01238 if(Cleared(mp))
01239 tc++;
01240 else if(Read(mp))
01241 tr++;
01242 else
01243 tu++;
01244 if(full == 2) {
01245 tchars += strlen(get_mail_message(mp->number));
01246 }
01247 }
01248 }
01249
01250 notify_printf(player, "Mail statistics for %s:", Name(target));
01251
01252 if(full == 1) {
01253 notify_printf(player, "%d messages sent, %d unread, %d cleared.",
01254 fc + fr + fu, fu, fc);
01255 notify_printf(player,
01256 "%d messages received, %d unread, %d cleared.",
01257 tc + tr + tu, tu, tc);
01258 } else {
01259 notify_printf(player,
01260 "%d messages sent, %d unread, %d cleared, totalling %d characters.",
01261 fc + fr + fu, fu, fc, fchars);
01262 notify_printf(player,
01263 "%d messages received, %d unread, %d cleared, totalling %d characters.",
01264 tc + tr + tu, tu, tc, tchars);
01265 }
01266
01267 if(tc + tr + tu > 0)
01268 notify_printf(player, "Last is dated %s", last);
01269 return;
01270 }
01271
01272
01273
01274
01275
01276 void do_mail_stub(dbref player, char *arg1, char *arg2)
01277 {
01278
01279 if(Typeof(player) != TYPE_PLAYER) {
01280 notify(player, "MAIL: Only players may send and receive mail.");
01281 return;
01282 }
01283 if(!arg1 || !*arg1) {
01284 if(arg2 && *arg2) {
01285 notify(player, "MAIL: Invalid mail command.");
01286 return;
01287 }
01288
01289
01290
01291 do_mail_list(player, arg1, 1);
01292 return;
01293 }
01294
01295
01296
01297 if(!strcasecmp(arg1, "purge")) {
01298 do_mail_purge(player);
01299 return;
01300 }
01301
01302
01303
01304 if(!strcasecmp(arg1, "clear")) {
01305 do_mail_clear(player, arg2);
01306 return;
01307 }
01308 if(!strcasecmp(arg1, "unclear")) {
01309 do_mail_unclear(player, arg2);
01310 return;
01311 }
01312 if(arg2 && *arg2) {
01313
01314
01315
01316 do_expmail_start(player, arg1, arg2);
01317 return;
01318 } else {
01319
01320
01321
01322 if(isdigit(*arg1) && !index(arg1, '-'))
01323 do_mail_read(player, arg1);
01324 else
01325 do_mail_list(player, arg1, 1);
01326 return;
01327 }
01328
01329 }
01330
01331 void do_mail(dbref player, dbref cause, int key, char *arg1, char *arg2)
01332 {
01333 if(!mudconf.have_mailer) {
01334 notify(player, "Mailer is disabled.");
01335 return;
01336 }
01337 switch (key) {
01338 case 0:
01339 do_mail_stub(player, arg1, arg2);
01340 break;
01341 case MAIL_STATS:
01342 do_mail_stats(player, arg1, 0);
01343 break;
01344 case MAIL_DSTATS:
01345 do_mail_stats(player, arg1, 1);
01346 break;
01347 case MAIL_FSTATS:
01348 do_mail_stats(player, arg1, 2);
01349 break;
01350 case MAIL_DEBUG:
01351 do_mail_debug(player, arg1, arg2);
01352 break;
01353 case MAIL_NUKE:
01354 do_mail_nuke(player);
01355 break;
01356 case MAIL_FOLDER:
01357 do_mail_change_folder(player, arg1, arg2);
01358 break;
01359 case MAIL_LIST:
01360 do_mail_list(player, arg1, 0);
01361 break;
01362 case MAIL_READ:
01363 do_mail_read(player, arg1);
01364 break;
01365 case MAIL_CLEAR:
01366 do_mail_clear(player, arg1);
01367 break;
01368 case MAIL_UNCLEAR:
01369 do_mail_unclear(player, arg1);
01370 break;
01371 case MAIL_PURGE:
01372 do_mail_purge(player);
01373 break;
01374 case MAIL_FILE:
01375 do_mail_file(player, arg1, arg2);
01376 break;
01377 case MAIL_TAG:
01378 do_mail_tag(player, arg1);
01379 break;
01380 case MAIL_UNTAG:
01381 do_mail_untag(player, arg1);
01382 break;
01383 case MAIL_FORWARD:
01384 do_mail_fwd(player, arg1, arg2);
01385 break;
01386 case MAIL_SEND:
01387 do_expmail_stop(player, 0);
01388 break;
01389 case MAIL_EDIT:
01390 do_edit_msg(player, arg1, arg2);
01391 break;
01392 case MAIL_URGENT:
01393 do_expmail_stop(player, M_URGENT);
01394 break;
01395 case MAIL_ALIAS:
01396 do_malias_create(player, arg1, arg2);
01397 break;
01398 case MAIL_ALIST:
01399 do_malias_list_all(player);
01400 break;
01401 case MAIL_PROOF:
01402 do_mail_proof(player);
01403 break;
01404 case MAIL_ABORT:
01405 do_expmail_abort(player);
01406 break;
01407 case MAIL_QUICK:
01408 do_mail_quick(player, arg1, arg2);
01409 break;
01410 case MAIL_REVIEW:
01411 do_mail_review(player, arg1, arg2);
01412 break;
01413 case MAIL_RETRACT:
01414 do_mail_retract(player, arg1, arg2);
01415 break;
01416 case MAIL_CC:
01417 do_mail_cc(player, arg1);
01418 break;
01419 case MAIL_SAFE:
01420 do_mail_safe(player, arg1);
01421 break;
01422 }
01423 }
01424
01425 int dump_mail(FILE * fp)
01426 {
01427 struct mail *mp, *mptr;
01428 dbref thing;
01429 int count = 0, i;
01430
01431
01432
01433
01434 fprintf(fp, "+V5\n");
01435 putref(fp, mudstate.mail_db_top);
01436 DO_WHOLE_DB(thing) {
01437 if(isPlayer(thing)) {
01438 mptr =
01439 (struct mail *) nhashfind((int) thing, &mudstate.mail_htab);
01440 if(mptr != NULL)
01441 for(mp = mptr; mp; mp = mp->next) {
01442 putref(fp, mp->to);
01443 putref(fp, mp->from);
01444 putref(fp, mp->number);
01445 putstring(fp, mp->tolist);
01446 putstring(fp, mp->time);
01447 putstring(fp, mp->subject);
01448 putref(fp, mp->read);
01449 count++;
01450 }
01451 }
01452 }
01453
01454 fprintf(fp, "*** END OF DUMP ***\n");
01455
01456
01457
01458
01459 for(i = 0; i < mudstate.mail_db_top; i++) {
01460 if(mudstate.mail_list[i].count > 0) {
01461 putref(fp, i);
01462 putstring(fp, get_mail_message(i));
01463 }
01464 }
01465 fprintf(fp, "+++ END OF DUMP +++\n");
01466
01467 save_malias(fp);
01468 fflush(fp);
01469
01470 return (count);
01471 }
01472
01473 int load_mail(FILE * fp)
01474 {
01475 char nbuf1[8];
01476 int mail_top = 0;
01477 int new = 0;
01478 int pennsub = 0;
01479 int read_tolist = 0;
01480 int read_newdb = 0;
01481 int read_new_strings = 0;
01482 int number = 0;
01483
01484 struct mail *mp, *mptr;
01485
01486
01487
01488
01489 fgets(nbuf1, sizeof(nbuf1), fp);
01490
01491 if(!strncmp(nbuf1, "+V2", 3)) {
01492 new = 1;
01493 } else if(!strncmp(nbuf1, "+V3", 3)) {
01494 new = 1;
01495 read_tolist = 1;
01496 } else if(!strncmp(nbuf1, "+V4", 3)) {
01497 new = 1;
01498 read_tolist = 1;
01499 read_newdb = 1;
01500 } else if(!strncmp(nbuf1, "+V5", 3)) {
01501 new = 1;
01502 read_tolist = 1;
01503 read_newdb = 1;
01504 read_new_strings = 1;
01505 } else if(!strncmp(nbuf1, "+1", 2)) {
01506 pennsub = 1;
01507 }
01508 if(pennsub)
01509 fgets(nbuf1, sizeof(nbuf1), fp);
01510
01511
01512
01513
01514 if(read_newdb) {
01515 mail_top = getref(fp);
01516 mail_db_grow(mail_top + 1);
01517 } else {
01518 mail_db_grow(1);
01519 }
01520
01521 fgets(nbuf1, sizeof(nbuf1), fp);
01522
01523 while (strncmp(nbuf1, "***", 3)) {
01524 mp = (struct mail *) malloc(sizeof(struct mail));
01525
01526 mp->to = atoi(nbuf1);
01527
01528 if(!nhashfind((int) mp->to, &mudstate.mail_htab)) {
01529 nhashadd((int) mp->to, (int *) mp, &mudstate.mail_htab);
01530 mp->prev = NULL;
01531 mp->next = NULL;
01532 } else {
01533 for(mptr =
01534 (struct mail *) nhashfind((int) mp->to,
01535 &mudstate.mail_htab);
01536 mptr->next != NULL; mptr = mptr->next);
01537 mptr->next = mp;
01538 mp->prev = mptr;
01539 mp->next = NULL;
01540 }
01541
01542 mp->from = getref(fp);
01543
01544 if(read_newdb) {
01545 mp->number = getref(fp);
01546 add_count(mp->number);
01547 }
01548 if(read_tolist)
01549 mp->tolist =
01550 (char *) strdup(getstring_noalloc(fp, read_new_strings));
01551 else
01552 mp->tolist = (char *) strdup(tprintf("%d", mp->to));
01553
01554 mp->time = (char *) strdup(getstring_noalloc(fp, read_new_strings));
01555 if(pennsub)
01556 mp->subject =
01557 (char *) strdup(getstring_noalloc(fp, read_new_strings));
01558 else if(!new)
01559 mp->subject = (char *) strdup("No subject");
01560
01561 if(!read_newdb) {
01562 number =
01563 add_mail_message_nosig(getstring_noalloc(fp,
01564 read_new_strings));
01565 add_count(number);
01566 mp->number = number;
01567 }
01568 if(new)
01569 mp->subject =
01570 (char *) strdup(getstring_noalloc(fp, read_new_strings));
01571 else if(!pennsub)
01572 mp->subject = (char *) strdup("No subject");
01573 mp->read = getref(fp);
01574 fgets(nbuf1, sizeof(nbuf1), fp);
01575 }
01576
01577 if(read_newdb) {
01578 fgets(nbuf1, sizeof(nbuf1), fp);
01579
01580 while (strncmp(nbuf1, "+++", 3)) {
01581 number = atoi(nbuf1);
01582 new_mail_message(getstring_noalloc(fp, read_new_strings), number);
01583 fgets(nbuf1, sizeof(nbuf1), fp);
01584 }
01585 }
01586 load_malias(fp);
01587 return (1);
01588 }
01589
01590 static int get_folder_number(dbref player, char *name)
01591 {
01592 int aflags;
01593 dbref aowner;
01594 char *atrstr;
01595 char *str, *pat, *res, *p, *bp;
01596
01597
01598
01599 atrstr = atr_get(player, A_MAILFOLDERS, &aowner, &aflags);
01600 if(!*atrstr) {
01601 free_lbuf(atrstr);
01602 return -1;
01603 }
01604 str = alloc_lbuf("get_folder_num_str");
01605 bp = pat = alloc_lbuf("get_folder_num_pat");
01606
01607 strcpy(str, atrstr);
01608 safe_tprintf_str(pat, &bp, ":%s:", upcasestr(name));
01609 res = (char *) strstr(str, pat);
01610 if(!res) {
01611 free_lbuf(str);
01612 free_lbuf(pat);
01613 free_lbuf(atrstr);
01614 return -1;
01615 }
01616 res += 2 + strlen(name);
01617 p = res;
01618 while (!isspace(*p))
01619 p++;
01620 p = '\0';
01621 free_lbuf(atrstr);
01622 free_lbuf(str);
01623 free_lbuf(pat);
01624 return atoi(res);
01625 }
01626
01627 static char *get_folder_name(dbref player, int fld)
01628 {
01629 static char str[LBUF_SIZE];
01630 char *pat;
01631 static char *old;
01632 char *r, *atrstr;
01633 int flags, len;
01634
01635
01636
01637
01638 pat = alloc_lbuf("get_folder_name");
01639 sprintf(pat, "%d:", fld);
01640 old = NULL;
01641 atrstr = atr_get(player, A_MAILFOLDERS, &player, &flags);
01642 if(!*atrstr) {
01643 StringCopy(str, "unnamed");
01644 free_lbuf(pat);
01645 free_lbuf(atrstr);
01646 return str;
01647 }
01648 StringCopy(str, atrstr);
01649 old = (char *) string_match(str, pat);
01650 free_lbuf(atrstr);
01651 if(old) {
01652 r = old + strlen(pat);
01653 while (*r != ':')
01654 r++;
01655 *r = '\0';
01656 len = strlen(pat);
01657 free_lbuf(pat);
01658 return old + len;
01659 } else {
01660 StringCopy(str, "unnamed");
01661 free_lbuf(pat);
01662 return str;
01663 }
01664 }
01665
01666 void add_folder_name(dbref player, int fld, char *name)
01667 {
01668 char *old, *res, *r, *atrstr;
01669 char *new, *pat, *str, *tbuf;
01670 int aflags;
01671
01672
01673
01674
01675
01676
01677
01678
01679 new = alloc_lbuf("add_folder_name.new");
01680 pat = alloc_lbuf("add_folder_name.pat");
01681 str = alloc_lbuf("add_folder_name.str");
01682 tbuf = alloc_lbuf("add_folder_name.tbuf");
01683
01684 sprintf(new, "%d:%s:%d ", fld, upcasestr(name), fld);
01685 sprintf(pat, "%d:", fld);
01686
01687
01688
01689 old = NULL;
01690
01691 atrstr = atr_get(player, A_MAILFOLDERS, &player, &aflags);
01692 if(*atrstr) {
01693 StringCopy(str, atrstr);
01694 old = (char *) string_match(str, pat);
01695 }
01696 if(old && *old) {
01697 StringCopy(tbuf, str);
01698 r = old;
01699 while (!isspace(*r))
01700 r++;
01701 *r = '\0';
01702 res = (char *) replace_string(old, new, tbuf);
01703 } else {
01704 r = res = alloc_lbuf("mail_folders");
01705 if(*atrstr)
01706 safe_str(str, res, &r);
01707 safe_str(new, res, &r);
01708 *r = '\0';
01709 }
01710
01711
01712
01713 atr_add(player, A_MAILFOLDERS, res, player,
01714 AF_MDARK | AF_WIZARD | AF_NOPROG | AF_LOCK);
01715 free_lbuf(str);
01716 free_lbuf(pat);
01717 free_lbuf(new);
01718 free_lbuf(tbuf);
01719 free_lbuf(atrstr);
01720 free_lbuf(res);
01721 }
01722
01723 static int player_folder(dbref player)
01724 {
01725
01726
01727
01728
01729
01730 int flags, number;
01731 char *atrstr;
01732
01733 atrstr = atr_pget(player, A_MAILCURF, &player, &flags);
01734 if(!*atrstr) {
01735 free_lbuf(atrstr);
01736 set_player_folder(player, 0);
01737 return 0;
01738 }
01739 number = atoi(atrstr);
01740 free_lbuf(atrstr);
01741 return number;
01742 }
01743
01744 void set_player_folder(dbref player, int fnum)
01745 {
01746
01747
01748
01749 ATTR *a;
01750 char *tbuf1;
01751
01752 tbuf1 = alloc_lbuf("set_player_folder");
01753 sprintf(tbuf1, "%d", fnum);
01754 a = (ATTR *) atr_num(A_MAILCURF);
01755 if(a)
01756 atr_add(player, A_MAILCURF, tbuf1, GOD, a->flags);
01757 else {
01758
01759
01760 atr_add(player, A_MAILCURF, tbuf1, GOD,
01761 AF_ODARK | AF_WIZARD | AF_NOPROG | AF_LOCK);
01762 }
01763 free_lbuf(tbuf1);
01764 }
01765
01766 static int parse_folder(dbref player, char *folder_string)
01767 {
01768 int fnum;
01769
01770
01771
01772
01773
01774
01775 if(!folder_string || !*folder_string)
01776 return -1;
01777 if(isdigit(*folder_string)) {
01778 fnum = atoi(folder_string);
01779 if((fnum < 0) || (fnum > MAX_FOLDERS))
01780 return -1;
01781 else
01782 return fnum;
01783 }
01784
01785
01786
01787 return get_folder_number(player, folder_string);
01788 }
01789
01790 static int mail_match(struct mail *mp, struct mail_selector ms, int num)
01791 {
01792 time_t now, msgtime, diffdays;
01793 char *msgtimestr;
01794 struct tm *msgtm;
01795 mail_flag mpflag;
01796
01797
01798
01799
01800 if(ms.low && num < ms.low)
01801 return 0;
01802 if(ms.high && num > ms.high)
01803 return 0;
01804 if(ms.player && mp->from != ms.player)
01805 return 0;
01806 mpflag = Read(mp) ? mp->read : (mp->read | M_MSUNREAD);
01807 if(!(ms.flags & M_ALL) && !(ms.flags & mpflag))
01808 return 0;
01809 if(ms.days != -1) {
01810
01811
01812
01813
01814 time(&now);
01815 msgtm = (struct tm *) malloc(sizeof(struct tm));
01816
01817 if(!msgtm) {
01818
01819
01820
01821 log_text("MAIL: Couldn't malloc struct tm!");
01822 return 0;
01823 }
01824 msgtimestr = alloc_lbuf("mail_match");
01825 StringCopy(msgtimestr, mp->time);
01826 if(do_convtime(msgtimestr, msgtm)) {
01827 msgtime = timelocal(msgtm);
01828 free(msgtm);
01829 diffdays = (now - msgtime) / 86400;
01830 free_lbuf(msgtimestr);
01831 if(sign(diffdays - ms.days) != ms.day_comp) {
01832 return 0;
01833 }
01834 } else {
01835 free(msgtm);
01836 free_lbuf(msgtimestr);
01837 return 0;
01838 }
01839 }
01840 return 1;
01841 }
01842
01843 static int parse_msglist(char *msglist, struct mail_selector *ms,
01844 dbref player)
01845 {
01846 char *p, *q;
01847 char tbuf1[LBUF_SIZE];
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858 ms->low = 0;
01859 ms->high = 0;
01860 ms->flags = 0x0FFF | M_MSUNREAD;
01861 ms->player = 0;
01862 ms->days = -1;
01863 ms->day_comp = 0;
01864
01865
01866
01867 if(!msglist || !*msglist) {
01868
01869
01870
01871 return 1;
01872 }
01873
01874
01875
01876 StringCopyTrunc(tbuf1, msglist, LBUF_SIZE - 1);
01877 p = tbuf1;
01878 while (p && *p && isspace(*p))
01879 p++;
01880 if(!p || !*p) {
01881 return 1;
01882
01883
01884 }
01885 if(isdigit(*p)) {
01886
01887
01888
01889 q = seek_char(p, '-');
01890 if(*q) {
01891
01892
01893
01894
01895
01896 *q++ = '\0';
01897 ms->low = atoi(p);
01898 if(ms->low <= 0) {
01899 notify(player, "MAIL: Invalid message range");
01900 return 0;
01901 }
01902 if(!q || !*q) {
01903
01904
01905
01906 ms->high = 0;
01907 } else {
01908 ms->high = atoi(q);
01909 if((ms->low > ms->high) || (ms->high <= 0)) {
01910 notify(player, "MAIL: Invalid message range");
01911 return 0;
01912 }
01913 }
01914 } else {
01915
01916
01917
01918 ms->low = ms->high = atoi(p);
01919 }
01920 } else {
01921 switch (*p) {
01922 case '-':
01923
01924
01925 p++;
01926 if(!p || !*p) {
01927 notify(player, "MAIL: Invalid message range");
01928 return 0;
01929 }
01930 ms->high = atoi(p);
01931 if(ms->high <= 0) {
01932 notify(player, "MAIL: Invalid message range");
01933 return 0;
01934 }
01935 break;
01936 case '~':
01937
01938
01939 p++;
01940 if(!p || !*p) {
01941 notify(player, "MAIL: Invalid age");
01942 return 0;
01943 }
01944 ms->day_comp = 0;
01945 ms->days = atoi(p);
01946 if(ms->days < 0) {
01947 notify(player, "MAIL: Invalid age");
01948 return 0;
01949 }
01950 break;
01951 case '<':
01952
01953
01954 p++;
01955 if(!p || !*p) {
01956 notify(player, "MAIL: Invalid age");
01957 return 0;
01958 }
01959 ms->day_comp = -1;
01960 ms->days = atoi(p);
01961 if(ms->days < 0) {
01962 notify(player, "MAIL: Invalid age");
01963 return 0;
01964 }
01965 break;
01966 case '>':
01967
01968
01969 p++;
01970 if(!p || !*p) {
01971 notify(player, "MAIL: Invalid age");
01972 return 0;
01973 }
01974 ms->day_comp = 1;
01975 ms->days = atoi(p);
01976 if(ms->days < 0) {
01977 notify(player, "MAIL: Invalid age");
01978 return 0;
01979 }
01980 break;
01981 case '#':
01982
01983
01984 p++;
01985 if(!p || !*p) {
01986 notify(player, "MAIL: Invalid dbref #");
01987 return 0;
01988 }
01989 ms->player = atoi(p);
01990 if(!Good_obj(ms->player) || !(ms->player)) {
01991 notify(player, "MAIL: Invalid dbref #");
01992 return 0;
01993 }
01994 break;
01995 case '*':
01996
01997
01998 p++;
01999 if(!p || !*p) {
02000 notify(player, "MAIL: Invalid player");
02001 return 0;
02002 }
02003 ms->player = lookup_player(player, p, 1);
02004 if(ms->player == NOTHING) {
02005 notify(player, "MAIL: Invalid player");
02006 return 0;
02007 }
02008 break;
02009
02010
02011
02012
02013
02014 ms->flags = M_ALL;
02015 break;
02016
02017
02018 case 'u':
02019
02020
02021 case 'U':
02022 p++;
02023 if(!p || !*p) {
02024 notify(player, "MAIL: U is ambiguous (urgent or unread?)");
02025 return 0;
02026 }
02027 switch (*p) {
02028 case 'r':
02029
02030
02031 case 'R':
02032 ms->flags = M_URGENT;
02033 break;
02034 case 'n':
02035
02036
02037 case 'N':
02038 ms->flags = M_MSUNREAD;
02039 break;
02040 default:
02041
02042
02043 notify(player, "MAIL: Invalid message specification");
02044 return 0;
02045 break;
02046 }
02047 break;
02048 case 'r':
02049
02050
02051 case 'R':
02052 ms->flags = M_ISREAD;
02053 break;
02054 case 'c':
02055
02056
02057 case 'C':
02058 ms->flags = M_CLEARED;
02059 break;
02060 case 't':
02061
02062
02063 case 'T':
02064 ms->flags = M_TAG;
02065 break;
02066 case 'm':
02067 case 'M':
02068
02069
02070 p++;
02071 if(!p || !*p) {
02072 notify(player, "MAIL: M is ambiguous (mass or me?)");
02073 return 0;
02074 }
02075 switch (*p) {
02076 case 'a':
02077 case 'A':
02078 ms->flags = M_MASS;
02079 break;
02080 case 'e':
02081 case 'E':
02082 ms->player = player;
02083 break;
02084 default:
02085 notify(player, "MAIL: Invalid message specification");
02086 return 0;
02087 break;
02088 }
02089 break;
02090 default:
02091
02092
02093 notify(player, "MAIL: Invalid message specification");
02094 return 0;
02095 break;
02096 }
02097 }
02098 return 1;
02099 }
02100
02101 void check_mail_expiration()
02102 {
02103 struct mail *mp, *nextp;
02104 struct tm then_tm = { 0 };
02105 time_t then, now = time(0);
02106 time_t expire_secs = mudconf.mail_expiration * 86400;
02107 dbref thing;
02108
02109
02110
02111
02112 if(0 > mudconf.mail_expiration)
02113 return;
02114
02115 MAIL_ITER_SAFE(mp, thing, nextp) {
02116 if(do_convtime((char *) mp->time, &then_tm)) {
02117 then = timelocal(&then_tm);
02118 if(((now - then) > expire_secs) && !(M_Safe(mp))) {
02119
02120
02121
02122
02123
02124
02125 if(mp->prev == NULL)
02126 nhashrepl((int) mp->to, (int *) mp->next,
02127 &mudstate.mail_htab);
02128 else if(mp->next == NULL)
02129 mp->prev->next = NULL;
02130
02131
02132
02133 if(mp->prev != NULL)
02134 mp->prev->next = mp->next;
02135 if(mp->next != NULL)
02136 mp->next->prev = mp->prev;
02137
02138
02139
02140 nextp = mp->next;
02141
02142
02143
02144 free((char *) mp->subject);
02145 delete_mail_message(mp->number);
02146 free((char *) mp->tolist);
02147 free((char *) mp->time);
02148 free(mp);
02149 } else
02150 nextp = mp->next;
02151 } else
02152 nextp = mp->next;
02153 }
02154 }
02155
02156 static char *status_chars(struct mail *mp)
02157 {
02158
02159
02160
02161 static char res[10];
02162 char *p;
02163
02164 StringCopy(res, "");
02165 p = res;
02166 *p++ = Read(mp) ? '-' : 'N';
02167 *p++ = M_Safe(mp) ? 'S' : '-';
02168 *p++ = Cleared(mp) ? 'C' : '-';
02169 *p++ = Urgent(mp) ? 'U' : '-';
02170 *p++ = Mass(mp) ? 'M' : '-';
02171 *p++ = Forward(mp) ? 'F' : '-';
02172 *p++ = Tagged(mp) ? '+' : '-';
02173 *p = '\0';
02174 return res;
02175 }
02176
02177 static char *status_string(struct mail *mp)
02178 {
02179
02180
02181
02182 char *tbuf1;
02183
02184 tbuf1 = alloc_lbuf("status_string");
02185 StringCopy(tbuf1, "");
02186 if(Read(mp))
02187 strcat(tbuf1, "Read ");
02188 else
02189 strcat(tbuf1, "Unread ");
02190 if(Cleared(mp))
02191 strcat(tbuf1, "Cleared ");
02192 if(Urgent(mp))
02193 strcat(tbuf1, "Urgent ");
02194 if(Mass(mp))
02195 strcat(tbuf1, "Mass ");
02196 if(Forward(mp))
02197 strcat(tbuf1, "Fwd ");
02198 if(Tagged(mp))
02199 strcat(tbuf1, "Tagged ");
02200 if(M_Safe(mp))
02201 strcat(tbuf1, "Safe");
02202 return tbuf1;
02203 }
02204
02205 void check_mail(dbref player, int folder, int silent)
02206 {
02207
02208
02209
02210
02211 int rc;
02212
02213
02214
02215 int uc;
02216
02217
02218
02219 int cc;
02220
02221
02222
02223 int gc;
02224
02225
02226
02227
02228
02229
02230
02231 count_mail(player, folder, &rc, &uc, &cc);
02232 urgent_mail(player, folder, &gc);
02233 #ifdef MAIL_ALL_FOLDERS
02234 notify_printf(player,
02235 "MAIL: %d messages in folder %d [%s] (%d unread, %d cleared).\r\n",
02236 rc + uc, folder, get_folder_name(player, folder), uc, cc);
02237 #else
02238 if(rc + uc > 0)
02239 notify_printf(player,
02240 "MAIL: %d messages in folder %d [%s] (%d unread, %d cleared).",
02241 rc + uc, folder, get_folder_name(player, folder), uc,
02242 cc);
02243 else if(!silent)
02244 notify(player, "\r\nMAIL: You have no mail.\r\n");
02245 if(gc > 0)
02246 notify_printf(player,
02247 "URGENT MAIL: You have %d urgent messages in folder %d [%s].",
02248 gc, folder, get_folder_name(player, folder));
02249 #endif
02250 return;
02251 }
02252
02253 static int sign(int x)
02254 {
02255 if(x == 0) {
02256 return 0;
02257 } else if(x < 0) {
02258 return -1;
02259 } else {
02260 return 1;
02261 }
02262 }
02263
02264 void do_malias_switch(dbref player, char *a1, char *a2)
02265 {
02266 if((!a2 || !*a2) && !(!a1 || !*a1))
02267 do_malias_list(player, a1);
02268 else if((!*a1 || !a1) && (!*a2 || !a2))
02269 do_malias_list_all(player);
02270 else
02271 do_malias_create(player, a1, a2);
02272 }
02273
02274 void do_malias(dbref player, dbref cause, int key, char *arg1, char *arg2)
02275 {
02276 if(!mudconf.have_mailer) {
02277 notify(player, "Mailer is disabled.");
02278 return;
02279 }
02280 switch (key) {
02281 case 0:
02282 do_malias_switch(player, arg1, arg2);
02283 break;
02284 case 1:
02285 do_malias_desc(player, arg1, arg2);
02286 break;
02287 case 2:
02288 do_malias_chown(player, arg1, arg2);
02289 break;
02290 case 3:
02291 do_malias_add(player, arg1, arg2);
02292 break;
02293 case 4:
02294 do_malias_remove(player, arg1, arg2);
02295 break;
02296 case 5:
02297 do_malias_delete(player, arg1);
02298 break;
02299 case 6:
02300 do_malias_rename(player, arg1, arg2);
02301 break;
02302 case 7:
02303
02304
02305
02306 break;
02307 case 8:
02308 do_malias_adminlist(player);
02309 break;
02310 case 9:
02311 do_malias_status(player);
02312 }
02313 }
02314
02315 void do_malias_send(dbref player, char *tolist, char *listto, char *subject,
02316 int number, mail_flag flags, int silent)
02317 {
02318 int k;
02319 dbref vic;
02320 struct malias *m;
02321
02322 if(!tolist || !*tolist) {
02323 notify(player, "MAIL: I can't figure out who you want to mail to.");
02324 return;
02325 }
02326 m = get_malias(player, tolist);
02327
02328 if(!m) {
02329 notify_printf(player, "MAIL: Mail alias %s not found.", tolist);
02330 return;
02331 }
02332
02333
02334
02335
02336 for(k = 0; k < m->numrecep; k++) {
02337 vic = m->list[k];
02338
02339 if(Typeof(vic) == TYPE_PLAYER) {
02340 send_mail(player, m->list[k], listto, subject, number, flags,
02341 silent);
02342 } else
02343 send_mail(GOD, GOD, listto, subject,
02344
02345
02346
02347 add_mail_message(player,
02348 tprintf
02349 ("Alias Error: Bad Player %d for %s",
02350 (dbref) vic, tolist)), 0, silent);
02351 }
02352 }
02353
02354 struct malias *get_malias(dbref player, char *alias)
02355 {
02356 char *mal;
02357 struct malias *m;
02358 int i = 0;
02359 int x = 0;
02360
02361 if((*alias == '#') && ExpMail(player)) {
02362 x = atoi(alias + 1);
02363 if(x < 0 || x >= ma_top)
02364 return NULL;
02365 else
02366 return malias[x];
02367 } else {
02368 if(*alias != '*')
02369 return NULL;
02370
02371 mal = alias + 1;
02372
02373 for(i = 0; i < ma_top; i++) {
02374 m = malias[i];
02375 if((m->owner == player) || (m->owner == GOD)) {
02376 if(!strcmp(mal, m->name))
02377
02378
02379 return m;
02380 }
02381 }
02382 }
02383 return NULL;
02384 }
02385
02386 void do_malias_create(dbref player, char *alias, char *tolist)
02387 {
02388 char *head, *tail, spot;
02389 struct malias *m;
02390 struct malias **nm;
02391 char *na, *buff;
02392 int i = 0;
02393 dbref target;
02394
02395 if(Typeof(player) != TYPE_PLAYER) {
02396 notify(player, "MAIL: Only players may create mail aliases.");
02397 return;
02398 }
02399 if(!alias || !*alias || !tolist || !*tolist) {
02400 notify(player, "MAIL: What alias do you want to create?.");
02401 return;
02402 }
02403 if(*alias != '*') {
02404 notify(player, "MAIL: All Mail aliases must begin with '*'.");
02405 return;
02406 }
02407 m = get_malias(player, alias);
02408 if(m) {
02409 notify_printf(player, "MAIL: Mail Alias '%s' already exists.", alias);
02410 return;
02411 }
02412 if(!ma_size) {
02413 ma_size = MA_INC;
02414 malias = (struct malias **) malloc(sizeof(struct malias *) * ma_size);
02415 } else if(ma_top >= ma_size) {
02416 ma_size += MA_INC;
02417 nm = (struct malias **) malloc(sizeof(struct malias *) * (ma_size));
02418
02419 for(i = 0; i < ma_top; i++)
02420 nm[i] = malias[i];
02421 free(malias);
02422 malias = nm;
02423 }
02424 malias[ma_top] = (struct malias *) malloc(sizeof(struct malias));
02425
02426 i = 0;
02427
02428
02429
02430
02431 head = (char *) tolist;
02432 while (head && *head && (i < (MALIAS_LEN - 1))) {
02433 while (*head == ' ')
02434 head++;
02435 tail = head;
02436 while (*tail && (*tail != ' ')) {
02437 if(*tail == '"') {
02438 head++;
02439 tail++;
02440 while (*tail && (*tail != '"'))
02441 tail++;
02442 }
02443 if(*tail)
02444 tail++;
02445 }
02446 tail--;
02447 if(*tail != '"')
02448 tail++;
02449 spot = *tail;
02450 *tail = '\0';
02451
02452
02453
02454 if(!strcasecmp(head, "me"))
02455 target = player;
02456 else if(*head == '#') {
02457 target = atoi(head + 1);
02458 if(!Good_obj(target))
02459 target = NOTHING;
02460 } else
02461 target = lookup_player(player, head, 1);
02462 if((target == NOTHING) || (Typeof(target) != TYPE_PLAYER)) {
02463 notify(player, "MAIL: No such player.");
02464 } else {
02465 buff = unparse_object(player, target, 0);
02466 notify_printf(player, "MAIL: %s added to alias %s", buff, alias);
02467 malias[ma_top]->list[i] = target;
02468 i++;
02469 free_lbuf(buff);
02470 }
02471
02472
02473
02474 *tail = spot;
02475 head = tail;
02476 if(*head == '"')
02477 head++;
02478 }
02479 malias[ma_top]->list[i] = NOTHING;
02480
02481 na = alias + 1;
02482 malias[ma_top]->name = (char *) malloc(strlen(na) + 1);
02483 malias[ma_top]->numrecep = i;
02484 malias[ma_top]->owner = player;
02485 StringCopy(malias[ma_top]->name, na);
02486 malias[ma_top]->desc = (char *) malloc(strlen(na) + 1);
02487 StringCopy(malias[ma_top]->desc, na);
02488
02489
02490 ma_top++;
02491
02492 notify_printf(player, "MAIL: Alias set '%s' defined.", alias);
02493 }
02494
02495 void do_malias_list(dbref player, char *alias)
02496 {
02497 struct malias *m;
02498 int i = 0;
02499 char *buff, *bp;
02500
02501 m = get_malias(player, alias);
02502
02503 if(!m) {
02504 notify_printf(player, "MAIL: Alias '%s' not found.", alias);
02505 return;
02506 }
02507 if(!ExpMail(player) && (player != m->owner) && !(God(m->owner))) {
02508 notify(player, "MAIL: Permission denied.");
02509 return;
02510 }
02511 bp = buff = alloc_lbuf("do_malias_list");
02512 safe_tprintf_str(buff, &bp, "MAIL: Alias *%s: ", m->name);
02513 for(i = m->numrecep - 1; i > -1; i--) {
02514 safe_str(Name(m->list[i]), buff, &bp);
02515 safe_chr(' ', buff, &bp);
02516 }
02517 *bp = '\0';
02518
02519 notify(player, buff);
02520 free_lbuf(buff);
02521 }
02522
02523 void do_malias_list_all(dbref player)
02524 {
02525 struct malias *m;
02526 int i = 0;
02527 int notified = 0;
02528
02529 for(i = 0; i < ma_top; i++) {
02530 m = malias[i];
02531 if((m->owner == GOD) || (m->owner == player) || God(player)) {
02532 if(!notified) {
02533 notify(player,
02534 "Name Description Owner");
02535 notified++;
02536 }
02537 notify_printf(player, "%-12.12s %-35.35s %-15.15s", m->name,
02538 m->desc, Name(m->owner));
02539 }
02540 }
02541
02542 notify(player, "***** End of Mail Aliases *****");
02543 }
02544
02545 void load_malias(FILE * fp)
02546 {
02547 char buffer[200];
02548
02549 (void) getref(fp);
02550 if(fscanf(fp, "*** Begin %s ***\n", buffer) == 1 &&
02551 !strcmp(buffer, "MALIAS")) {
02552 malias_read(fp);
02553 } else {
02554 fprintf(stderr, "ERROR: Couldn't find Begin MALIAS.\n");
02555 return;
02556
02557 }
02558 }
02559
02560 void save_malias(FILE * fp)
02561 {
02562
02563 fprintf(fp, "*** Begin MALIAS ***\n");
02564 malias_write(fp);
02565 }
02566
02567 void malias_read(FILE * fp)
02568 {
02569 int i, j;
02570 char buffer[1000];
02571 struct malias *m;
02572
02573 fscanf(fp, "%d\n", &ma_top);
02574
02575 ma_size = ma_top;
02576
02577 if(ma_top > 0)
02578 malias = (struct malias **) malloc(sizeof(struct malias *) * ma_size);
02579
02580 else
02581 malias = NULL;
02582
02583 for(i = 0; i < ma_top; i++) {
02584 malias[i] = (struct malias *) malloc(sizeof(struct malias));
02585
02586 m = (struct malias *) malias[i];
02587
02588 fscanf(fp, "%d %d\n", &(m->owner), &(m->numrecep));
02589
02590 fscanf(fp, "%[^\n]\n", buffer);
02591 m->name = (char *) malloc(strlen(buffer) - 1);
02592 StringCopy(m->name, buffer + 2);
02593 fscanf(fp, "%[^\n]\n", buffer);
02594 m->desc = (char *) malloc(strlen(buffer) - 1);
02595 StringCopy(m->desc, buffer + 2);
02596
02597 if(m->numrecep > 0) {
02598
02599 for(j = 0; j < m->numrecep; j++) {
02600 m->list[j] = getref(fp);
02601
02602 }
02603 } else
02604 m->list[0] = 0;
02605
02606 }
02607
02608 for(i = 0; i < ma_top; i++)
02609 if(!Good_obj(malias[i]->owner) || !Alive(malias[i]->owner)) {
02610 if(i != ma_top - 1)
02611 memcpy(malias[i], malias[ma_top - 1], sizeof(struct malias));;
02612 ma_top--;
02613 }
02614 }
02615
02616 void malias_write(FILE * fp)
02617 {
02618 int i, j;
02619 struct malias *m;
02620
02621 fprintf(fp, "%d\n", ma_top);
02622
02623 for(i = 0; i < ma_top; i++) {
02624 m = malias[i];
02625 fprintf(fp, "%d %d\n", m->owner, m->numrecep);
02626 fprintf(fp, "N:%s\n", m->name);
02627 fprintf(fp, "D:%s\n", m->desc);
02628 for(j = 0; j < m->numrecep; j++)
02629 fprintf(fp, "%d\n", m->list[j]);
02630 }
02631 }
02632
02633 void do_expmail_start(dbref player, char *arg, char *subject)
02634 {
02635 char *tolist, *names;
02636
02637 if(!arg || !*arg) {
02638 notify(player, "MAIL: I do not know whom you want to mail.");
02639 return;
02640 }
02641 if(!subject || !*subject) {
02642 notify(player, "MAIL: No subject.");
02643 return;
02644 }
02645 if(Flags2(player) & PLAYER_MAILS) {
02646 notify(player, "MAIL: Mail message already in progress.");
02647 return;
02648 }
02649 if(!(tolist = make_numlist(player, arg))) {
02650 return;
02651 }
02652 atr_add_raw(player, A_MAILTO, tolist);
02653 atr_add_raw(player, A_MAILSUB, subject);
02654 atr_add_raw(player, A_MAILFLAGS, "0");
02655 atr_clr(player, A_MAILMSG);
02656 Flags2(player) |= PLAYER_MAILS;
02657 names = make_namelist(player, tolist);
02658 notify_printf(player, "MAIL: You are sending mail to '%s'.", names);
02659 free_lbuf(names);
02660 free_lbuf(tolist);
02661 }
02662
02663 void do_mail_cc(dbref player, char *arg)
02664 {
02665 char *tolist, *fulllist, *bp;
02666 char *names;
02667
02668 if(!(Flags2(player) & PLAYER_MAILS)) {
02669 notify(player, "MAIL: No mail message in progress.");
02670 return;
02671 }
02672 if(!arg || !*arg) {
02673 notify(player, "MAIL: I do not know whom you want to mail.");
02674 return;
02675 }
02676 if(!(tolist = make_numlist(player, arg))) {
02677 return;
02678 }
02679 fulllist = alloc_lbuf("do_mail_cc");
02680 bp = fulllist;
02681
02682 safe_str(tolist, fulllist, &bp);
02683 if(atr_get_raw(player, A_MAILTO)) {
02684 safe_chr(' ', fulllist, &bp);
02685 safe_str(atr_get_raw(player, A_MAILTO), fulllist, &bp);
02686 }
02687 *bp = '\0';
02688
02689 atr_add_raw(player, A_MAILTO, fulllist);
02690 names = make_namelist(player, fulllist);
02691 notify_printf(player, "MAIL: You are sending mail to '%s'.", names);
02692 free_lbuf(names);
02693 free_lbuf(tolist);
02694 free_lbuf(fulllist);
02695 }
02696
02697 static char *make_namelist(dbref player, char *arg)
02698 {
02699 char *names, *oldarg;
02700 char *bp, *p;
02701
02702 oldarg = alloc_lbuf("make_namelist.oldarg");
02703 names = alloc_lbuf("make_namelist.names");
02704 bp = names;
02705
02706 StringCopy(oldarg, arg);
02707
02708 for(p = (char *) strtok(oldarg, " "); p != NULL;
02709 p = (char *) strtok(NULL, " ")) {
02710 if(*p == '*') {
02711 safe_str(p, names, &bp);
02712 safe_str(", ", names, &bp);
02713 } else {
02714 safe_str(Name(atoi(p)), names, &bp);
02715 safe_str(", ", names, &bp);
02716 }
02717 }
02718 *(bp - 2) = '\0';
02719 free_lbuf(oldarg);
02720 return names;
02721 }
02722
02723 static char *make_numlist(dbref player, char *arg)
02724 {
02725 char *head, *tail, spot;
02726 static char *numbuf;
02727 static char buf[MBUF_SIZE];
02728 char *numbp;
02729 struct malias *m;
02730 struct mail *temp;
02731 dbref target;
02732 int num;
02733
02734 numbuf = alloc_lbuf("make_numlist");
02735 numbp = numbuf;
02736 *numbp = '\0';
02737
02738 head = (char *) arg;
02739 while (head && *head) {
02740 while (*head == ' ')
02741 head++;
02742
02743 tail = head;
02744 while (*tail && (*tail != ' ')) {
02745 if(*tail == '"') {
02746 head++;
02747 tail++;
02748 while (*tail && (*tail != '"'))
02749 tail++;
02750 }
02751 if(*tail)
02752 tail++;
02753 }
02754 tail--;
02755 if(*tail != '"')
02756 tail++;
02757 spot = *tail;
02758 *tail = 0;
02759
02760 num = atoi(head);
02761 if(num) {
02762 temp = mail_fetch(player, num);
02763 if(!temp) {
02764 notify(player, "MAIL: You can't reply to nonexistent mail.");
02765 free_lbuf(numbuf);
02766 return NULL;
02767 }
02768 sprintf(buf, "%d ", temp->from);
02769 safe_str(buf, numbuf, &numbp);
02770 } else if(*head == '*') {
02771 m = get_malias(player, head);
02772 if(!m) {
02773 notify_printf(player, "MAIL: Alias '%s' does not exist.",
02774 head);
02775 free_lbuf(numbuf);
02776 return NULL;
02777 }
02778 safe_str(head, numbuf, &numbp);
02779 safe_chr(' ', numbuf, &numbp);
02780 } else {
02781 target = lookup_player(player, head, 1);
02782 if(target != NOTHING) {
02783 sprintf(buf, "%d ", target);
02784 safe_str(buf, numbuf, &numbp);
02785 } else {
02786 notify_printf(player, "MAIL: '%s' does not exist.", head);
02787 free_lbuf(numbuf);
02788 return NULL;
02789 }
02790 }
02791
02792
02793
02794
02795 *tail = spot;
02796 head = tail;
02797 if(*head == '"')
02798 head++;
02799 }
02800
02801 if(!*numbuf) {
02802 notify(player, "MAIL: No players specified.");
02803 free_lbuf(numbuf);
02804 return NULL;
02805 } else {
02806 *(numbp - 1) = '\0';
02807 return numbuf;
02808 }
02809 }
02810
02811 void do_mail_quick(dbref player, char *arg1, char *arg2)
02812 {
02813 char *buf, *bp;
02814
02815 if(!arg1 || !*arg1) {
02816 notify(player, "MAIL: I don't know who you want to mail.");
02817 return;
02818 }
02819 if(!arg2 || !*arg2) {
02820 notify(player, "MAIL: No message.");
02821 return;
02822 }
02823 if(Flags2(player) & PLAYER_MAILS) {
02824 notify(player, "MAIL: Mail message already in progress.");
02825 return;
02826 }
02827 buf = alloc_lbuf("do_mail_quick");
02828 bp = buf;
02829 StringCopy(bp, arg1);
02830
02831 parse_to(&bp, '/', 1);
02832
02833 if(!bp) {
02834 notify(player, "MAIL: No subject.");
02835 free_lbuf(buf);
02836 return;
02837 }
02838 mail_to_list(player, make_numlist(player, buf), bp, arg2, 0, 0);
02839 free_lbuf(buf);
02840 }
02841
02842 void mail_to_list(dbref player, char *list, char *subject, char *message,
02843 int flags, int silent)
02844 {
02845 char *head, *tail, spot, *tolist;
02846 struct malias *m;
02847 dbref target;
02848 int number;
02849
02850 if(!list) {
02851 return;
02852 }
02853 if(!*list) {
02854 free_lbuf(list);
02855 return;
02856 }
02857 tolist = alloc_lbuf("mail_to_list");
02858 StringCopy(tolist, list);
02859
02860 number = add_mail_message(player, message);
02861
02862 head = (char *) list;
02863 while (head && *head) {
02864 while (*head == ' ')
02865 head++;
02866
02867 tail = head;
02868 while (*tail && (*tail != ' ')) {
02869 if(*tail == '"') {
02870 head++;
02871 tail++;
02872 while (*tail && (*tail != '"'))
02873 tail++;
02874 }
02875 if(*tail)
02876 tail++;
02877 }
02878 tail--;
02879 if(*tail != '"')
02880 tail++;
02881 spot = *tail;
02882 *tail = 0;
02883
02884 if(*head == '*') {
02885 m = get_malias(player, head);
02886 if(!m) {
02887 free_lbuf(list);
02888 free_lbuf(tolist);
02889 return;
02890 }
02891 do_malias_send(player, head, tolist, subject, number, flags,
02892 silent);
02893 } else {
02894 target = atoi(head);
02895 if(target != NOTHING) {
02896 send_mail(player, target, tolist, subject, number, flags,
02897 silent);
02898 }
02899 }
02900
02901
02902
02903
02904 *tail = spot;
02905 head = tail;
02906 if(*head == '"')
02907 head++;
02908 }
02909 free_lbuf(tolist);
02910 free_lbuf(list);
02911 }
02912
02913 void do_expmail_stop(dbref player, int flags)
02914 {
02915 char *tolist, *mailsub, *mailmsg, *mailflags;
02916 dbref aowner;
02917 dbref aflags;
02918
02919 tolist = atr_get(player, A_MAILTO, &aowner, &aflags);
02920 mailmsg = atr_get(player, A_MAILMSG, &aowner, &aflags);
02921 mailsub = atr_get(player, A_MAILSUB, &aowner, &aflags);
02922 mailflags = atr_get(player, A_MAILFLAGS, &aowner, &aflags);
02923
02924 if(!*tolist || !*mailmsg || !(Flags2(player) & PLAYER_MAILS)) {
02925 notify(player, "MAIL: No such message to send.");
02926 free_lbuf(tolist);
02927 } else {
02928 mail_to_list(player, tolist, mailsub, mailmsg,
02929 flags | atoi(mailflags), 0);
02930 }
02931 free_lbuf(mailflags);
02932 free_lbuf(mailmsg);
02933 free_lbuf(mailsub);
02934 Flags2(player) &= ~PLAYER_MAILS;
02935 }
02936
02937 void do_expmail_abort(dbref player)
02938 {
02939 Flags2(player) &= ~PLAYER_MAILS;
02940 notify(player, "MAIL: Message aborted.");
02941 }
02942
02943 void do_prepend(dbref player, dbref cause, int key, char *text)
02944 {
02945 char *oldmsg, *newmsg, *bp, *attr;
02946 dbref aowner;
02947 int aflags;
02948
02949 if(!mudconf.have_mailer) {
02950 wait_que(player, cause, 0, NOTHING, 0, text, (char **) NULL, 0,
02951 (char **) NULL);
02952 return;
02953 };
02954
02955 if(Flags2(player) & PLAYER_MAILS) {
02956 oldmsg = atr_get(player, A_MAILMSG, &aowner, &aflags);
02957 if(*oldmsg) {
02958 bp = newmsg = alloc_lbuf("do_prepend");
02959 safe_str(text + 1, newmsg, &bp);
02960 safe_chr(' ', newmsg, &bp);
02961 safe_str(oldmsg, newmsg, &bp);
02962 *bp = '\0';
02963 atr_add_raw(player, A_MAILMSG, newmsg);
02964 free_lbuf(newmsg);
02965 } else
02966 atr_add_raw(player, A_MAILMSG, text + 1);
02967
02968 free_lbuf(oldmsg);
02969 attr = atr_get_raw(player, A_MAILMSG);
02970 notify_printf(player, "%d/%d characters prepended.",
02971 attr ? strlen(attr) : 0, LBUF_SIZE);
02972 } else {
02973 notify(player, "MAIL: No message in progress.");
02974 }
02975
02976 }
02977
02978 void do_postpend(dbref player, dbref cause, int key, char *text)
02979 {
02980 char *oldmsg, *newmsg, *bp, *attr;
02981 dbref aowner;
02982 int aflags;
02983
02984 if(!mudconf.have_mailer) {
02985 wait_que(player, cause, 0, NOTHING, 0, text, (char **) NULL, 0,
02986 (char **) NULL);
02987 return;
02988 };
02989
02990 if((*(text + 1) == '-') && !(*(text + 2))) {
02991 do_expmail_stop(player, 0);
02992 return;
02993 }
02994 if(Flags2(player) & PLAYER_MAILS) {
02995 oldmsg = atr_get(player, A_MAILMSG, &aowner, &aflags);
02996 if(*oldmsg) {
02997 bp = newmsg = alloc_lbuf("do_postpend");
02998 safe_str(oldmsg, newmsg, &bp);
02999 safe_chr(' ', newmsg, &bp);
03000 safe_str(text + 1, newmsg, &bp);
03001 *bp = '\0';
03002 atr_add_raw(player, A_MAILMSG, newmsg);
03003 free_lbuf(newmsg);
03004 } else
03005 atr_add_raw(player, A_MAILMSG, text + 1);
03006
03007 free_lbuf(oldmsg);
03008 attr = atr_get_raw(player, A_MAILMSG);
03009 notify_printf(player, "%d/%d characters added.",
03010 attr ? strlen(attr) : 0, LBUF_SIZE);
03011 } else {
03012 notify(player, "MAIL: No message in progress.");
03013 }
03014 }
03015
03016 static void do_edit_msg(dbref player, char *from, char *to)
03017 {
03018 char *result, *msg;
03019 dbref aowner;
03020 int aflags;
03021
03022 if(Flags2(player) & PLAYER_MAILS) {
03023 msg = atr_get(player, A_MAILMSG, &aowner, &aflags);
03024 result = replace_string(from, to, msg);
03025 atr_add(player, A_MAILMSG, result, aowner, aflags);
03026 notify(player, "Text edited.");
03027 free_lbuf(result);
03028 free_lbuf(msg);
03029 } else {
03030 notify(player, "MAIL: No message in progress.");
03031 }
03032 }
03033
03034 static void do_mail_proof(dbref player)
03035 {
03036 char *mailto, *names;
03037 char *mailmsg, *msg, *bp, *str;
03038 dbref aowner;
03039 int aflags;
03040
03041 mailto = atr_get(player, A_MAILTO, &aowner, &aflags);
03042
03043 if(!atr_get_raw(player, A_MAILMSG)) {
03044 notify(player, "MAIL: No text.");
03045 free_lbuf(mailto);
03046 return;
03047 } else {
03048 str = mailmsg = atr_get(player, A_MAILMSG, &aowner, &aflags);
03049 bp = msg = alloc_lbuf("do_mail_proof");
03050 exec(msg, &bp, 0, player, player, EV_EVAL | EV_FCHECK, &str,
03051 (char **) NULL, 0);
03052 *bp = '\0';
03053 free_lbuf(mailmsg);
03054 }
03055
03056 if(Flags2(player) & PLAYER_MAILS) {
03057 names = make_namelist(player, mailto);
03058 notify(player, DASH_LINE);
03059 notify_printf(player, "From: %-*s Subject: %-35s\nTo: %s",
03060 PLAYER_NAME_LIMIT - 6, Name(player), atr_get_raw(player,
03061 A_MAILSUB),
03062 names);
03063 notify(player, DASH_LINE);
03064 notify(player, msg);
03065 notify(player, DASH_LINE);
03066 free_lbuf(names);
03067 } else {
03068 notify(player, "MAIL: No message in progress.");
03069 }
03070 free_lbuf(mailto);
03071 free_lbuf(msg);
03072 }
03073
03074 void do_malias_desc(dbref player, char *alias, char *desc)
03075 {
03076 struct malias *m;
03077
03078 if(!(m = get_malias(player, alias))) {
03079 notify_printf(player, "MAIL: Alias %s not found.", alias);
03080 return;
03081 } else if((m->owner != GOD) || ExpMail(player)) {
03082 free(m->desc);
03083
03084
03085 m->desc = (char *) malloc(sizeof(char *) * strlen(desc));
03086
03087 StringCopy(m->desc, desc);
03088 notify(player, "MAIL: Description changed.");
03089 } else
03090 notify(player, "MAIL: Permission denied.");
03091 return;
03092 }
03093
03094 void do_malias_chown(dbref player, char *alias, char *owner)
03095 {
03096 struct malias *m;
03097 dbref no = NOTHING;
03098
03099 if(!(m = get_malias(player, alias))) {
03100 notify_printf(player, "MAIL: Alias %s not found.", alias);
03101 return;
03102 } else {
03103 if(!ExpMail(player)) {
03104 notify(player, "MAIL: You cannot do that!");
03105 return;
03106 } else {
03107 if((no = lookup_player(player, owner, 1)) == NOTHING) {
03108 notify(player, "MAIL: I do not see that here.");
03109 return;
03110 }
03111 m->owner = no;
03112 notify(player, "MAIL: Owner changed for alias.");
03113 }
03114 }
03115 }
03116
03117 void do_malias_add(dbref player, char *alias, char *person)
03118 {
03119 int i = 0;
03120 dbref thing;
03121 struct malias *m;
03122
03123 thing = NOTHING;
03124
03125 if(!(m = get_malias(player, alias))) {
03126 notify_printf(player, "MAIL: Alias %s not found.", alias);
03127 return;
03128 }
03129 if(*person == '#') {
03130 thing = parse_dbref(person + 1);
03131 if(!isPlayer(thing)) {
03132 notify(player, "MAIL: Only players may be added.");
03133 return;
03134 }
03135 }
03136
03137 if(thing == NOTHING)
03138 thing = lookup_player(player, person, 1);
03139
03140 if(thing == NOTHING) {
03141 notify(player, "MAIL: I do not see that person here.");
03142 return;
03143 }
03144
03145 if((m->owner == GOD) && !ExpMail(player)) {
03146 notify(player, "MAIL: Permission denied.");
03147 return;
03148 }
03149 for(i = 0; i < m->numrecep; i++) {
03150 if(m->list[i] == thing) {
03151 notify(player, "MAIL: That person is already on the list.");
03152 return;
03153 }
03154 }
03155
03156 if(i >= (MALIAS_LEN - 1)) {
03157 notify(player, "MAIL: The list is full.");
03158 return;
03159 }
03160
03161 m->list[m->numrecep] = thing;
03162 m->numrecep = m->numrecep + 1;
03163 notify_printf(player, "MAIL: %s added to %s", Name(thing), m->name);
03164 }
03165
03166 void do_malias_remove(dbref player, char *alias, char *person)
03167 {
03168 int i, ok = 0;
03169 dbref thing;
03170 struct malias *m;
03171
03172 thing = NOTHING;
03173
03174 if(!(m = get_malias(player, alias))) {
03175 notify(player, "MAIL: Alias not found.");
03176 return;
03177 }
03178 if((m->owner == GOD) && !ExpMail(player)) {
03179 notify(player, "MAIL: Permission denied.");
03180 return;
03181 }
03182
03183 if(*person == '#')
03184 thing = parse_dbref(person + 1);
03185
03186 if(thing == NOTHING)
03187 thing = lookup_player(player, person, 1);
03188
03189 if(thing == NOTHING) {
03190 notify(player, "MAIL: I do not see that person here.");
03191 return;
03192 }
03193
03194 for(i = 0; i < m->numrecep; i++) {
03195 if(ok)
03196 m->list[i] = m->list[i + 1];
03197 else if((m->list[i] == thing) && !ok) {
03198 m->list[i] = m->list[i + 1];
03199 ok = 1;
03200 }
03201 }
03202
03203 if(ok)
03204 m->numrecep--;
03205
03206 notify_printf(player, "MAIL: %s removed from alias %s.", Name(thing),
03207 alias);
03208 }
03209
03210 void do_malias_rename(dbref player, char *alias, char *newname)
03211 {
03212 struct malias *m;
03213
03214 if(get_malias(player, newname) != NULL) {
03215 notify(player, "MAIL: That name already exists!");
03216 return;
03217 }
03218 if((m = get_malias(player, alias)) == NULL) {
03219 notify(player, "MAIL: I cannot find that alias!");
03220 return;
03221 }
03222 if(*newname != '*') {
03223 notify(player, "MAIL: Bad alias.");
03224 return;
03225 }
03226 if(!ExpMail(player) && !(m->owner == player)) {
03227 notify(player, "MAIL: Permission denied.");
03228 return;
03229 }
03230 free(m->name);
03231 m->name = (char *) malloc(sizeof(char) * strlen(newname));
03232
03233 StringCopy(m->name, newname + 1);
03234
03235 notify(player, "MAIL: Mailing Alias renamed.");
03236 }
03237
03238 void do_malias_delete(dbref player, char *alias)
03239 {
03240 int i = 0;
03241 int done = 0;
03242 struct malias *m;
03243
03244 m = get_malias(player, alias);
03245
03246 if(!m) {
03247 notify(player,
03248 "MAIL: Not a valid alias. Remember to prefix the alias name with *.");
03249 return;
03250 }
03251
03252 for(i = 0; i < ma_top; i++) {
03253 if(done)
03254 malias[i] = malias[i + 1];
03255 else {
03256 if((m->owner == player) || ExpMail(player))
03257 if(m == malias[i]) {
03258 done = 1;
03259 notify(player, "MAIL: Alias Deleted.");
03260 malias[i] = malias[i + 1];
03261 }
03262 }
03263 }
03264
03265 if(!done)
03266 notify(player, "MAIL: Alias not found.");
03267 else
03268 ma_top--;
03269 }
03270
03271 void do_malias_adminlist(dbref player)
03272 {
03273 struct malias *m;
03274 int i;
03275
03276 if(!ExpMail(player)) {
03277 do_malias_list_all(player);
03278 return;
03279 }
03280 notify(player,
03281 "Num Name Description Owner");
03282
03283 for(i = 0; i < ma_top; i++) {
03284 m = malias[i];
03285 notify_printf(player, "%-4d %-10.10s %-40.40s %-11.11s", i,
03286 m->name, m->desc, Name(m->owner));
03287 }
03288
03289 notify(player, "***** End of Mail Aliases *****");
03290 }
03291
03292 void do_malias_status(dbref player)
03293 {
03294 if(!ExpMail(player))
03295 notify(player, "MAIL: Permission denied.");
03296 else {
03297 notify_printf(player, "MAIL: Number of mail aliases defined: %d",
03298 ma_top);
03299 notify_printf(player, "MAIL: Allocated slots %d", ma_size);
03300 }
03301 }