/************************************************************************** * File: mail.c Part of tbaMUD * * Usage: Internal funcs and player spec-procs of mudmail system. * * * * All rights reserved. See license for complete information. * * * * Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University * * CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991. * * By Jeremy Elson. Rewritten by Welcor and Jamdog * **************************************************************************/ #include #include #include "conf.h" #include "sysdep.h" #include "structs.h" #include "utils.h" #include "comm.h" #include "db.h" #include "interpreter.h" #include "handler.h" #include "modify.h" #include "act.h" #include "genolc.h" #include "dg_scripts.h" #include "mail.h" #include "screen.h" /* Local Global Variables */ struct mail_index *mail_table = NULL; /* mail_table is index - mails are loaded as necessary */ int top_of_mail_table=-1; int top_mail_idnum=-1; /* Also need an adjustment to perform_send_to_groups below */ const struct mail_group mail_groups[NUM_MAIL_GROUPS+1] = { {"immortals", MAIL_TO_IMMS}, {"all", MAIL_TO_ALL}, {"\n", MAIL_TO_NOBODY}}; /* build_mail_index: loads the mudmail index */ bool build_mail_index(void) { int rec_count = 0, i, count=0; FILE *ml_index; char index_name[40], line[256], bits[64]; char subj[80], *strptr; sprintf(index_name, "%s%s", LIB_MLFILES, INDEX_FILE); if (!(ml_index = fopen(index_name, "r"))) { top_of_mail_table = -1; log("No mail index file! Creating new one!"); return (save_mail_index()); } while (get_line(ml_index, line)) if (*line != '~' && *line != '$' && *line != '#') /* Index file can end in ~ or $ */ rec_count++; rewind(ml_index); if (rec_count == 0) { mail_table = NULL; top_of_mail_table = -1; return TRUE; } CREATE(mail_table, struct mail_index, rec_count); for (i = 0; i < rec_count; i++) { get_line(ml_index, line); while (*line && *line == '#') get_line(ml_index, line); /* Skip comments */ if ((sscanf(line, "%ld %s %ld %ld %ld %s", &mail_table[i].mail_id, bits, &mail_table[i].sender, &mail_table[i].recipient, &mail_table[i].sent_time, subj)) != 6) { } if (!strcmp(subj, "(null)")) { mail_table[i].subject = NULL; } else { count = 0; /* sscanf only grabs the first word of the subject, get it all! */ for (strptr=line; strptr && *strptr && count<5; strptr++) if (*strptr == ' ') count++; if (strptr && *strptr) { mail_table[i].subject = strdup(strptr); } else { mail_table[i].subject = NULL; } } mail_table[i].flags = asciiflag_conv(bits); top_mail_idnum = MAX(top_mail_idnum, mail_table[i].mail_id); } fclose(ml_index); top_of_mail_table = i - 1; return TRUE; } /* Find an usused unique mail ID */ long new_mail_id(void) { int i,j; /* Have we allocated all mail numbers yet? */ if (top_mail_idnum < MAX_MAIL_ID) { top_mail_idnum++; return (top_mail_idnum); } /* Oops, we reached the max! check through all the other numbers to find one that has been deleted */ for (i=0; isubject) free(mail->subject); if (mail->body) free(mail->body); /* Extract all attached objects */ if (mail->attachment) { obj = mail->attachment; next_obj = obj->next_content; while (obj) { extract_obj(obj); obj = next_obj; } } free(mail); } int find_mail_by_id(long mail_id) { int i; for (i=0; i<=top_of_mail_table; i++) if (mail_table[i].mail_id == mail_id) return i; /* Not found */ return NO_MAIL; } void copy_mail_index_entry(struct mail_index *to, struct mail_index *from) { // to->mail_id = from->mail_id; to->recipient = from->recipient; to->sender = from->sender; to->sent_time = from->sent_time; to->flags = from->flags; if (from->subject) to->subject = strdup(from->subject); else to->subject = NULL; } void copy_mail(struct mail_data *to, struct mail_data *from, int copy_mode) { int i; char new_subject[MAX_STRING_LENGTH]; // to->mail_id = from->mail_id; to->recipient = from->recipient; to->sender = from->sender; to->sent_time = from->sent_time; switch (copy_mode) { case MAIL_COPY_NORMAL : if (from->subject) sprintf(new_subject, "%s", from->subject); else *new_subject='\0'; break; case MAIL_COPY_FORWARD : if (from->subject) sprintf(new_subject, "FW: %s", from->subject); else sprintf(new_subject, "FW: - No Subject -"); break; case MAIL_COPY_REPLY : if (from->subject) sprintf(new_subject, "RE: %s", from->subject); else sprintf(new_subject, "RE: - No Subject -"); break; default: log("Invalid copy mode passed to mail_copy."); *new_subject = '\0'; break; } for (i=0; imail_flags[i] = from->mail_flags[i]; if (*new_subject) to->subject = strdup(new_subject); else to->subject = NULL; if (from->body) to->body = strdup(from->body); else to->body = NULL; /* Attachments cannot be copied */ to->attachment = NULL; to->coins = 0; } int create_mail_index_entry(struct mail_data *mail) { int i, pos; /* Is this mail already listed? */ if (mail->mail_id != NO_MAIL && find_mail_by_id(mail->mail_id) != NO_MAIL) { log("SYSERR: create_mail_index_entry called for mail that already has an index entry (id=%ld)", mail->mail_id); return NO_MAIL; } if (top_of_mail_table < 0) { /* no table */ pos = top_of_mail_table = 0; CREATE(mail_table, struct mail_index, 1); } else { /* add mail */ i = ++top_of_mail_table + 1; RECREATE(mail_table, struct mail_index, i); pos = top_of_mail_table; } /* Allocate a new ID number */ if ((mail_table[pos].mail_id = mail->mail_id = new_mail_id()) == NO_MAIL) { log("SYSERR: Unable to allocate a unique mail ID for new mudmails"); return NO_MAIL; } /* copy subject and other vars */ if (mail->subject && *(mail->subject)) { mail_table[pos].subject = strdup(mail->subject); } else { mail_table[pos].subject = NULL; } mail_table[pos].recipient = mail->recipient; mail_table[pos].sender = mail->sender; mail_table[pos].sent_time = mail->sent_time; /* clear the bitflag in case we have garbage data */ mail_table[pos].flags = 0; /* set urgent or deleted flag if required, and flag if object or gold attached */ if (IS_SET_AR(mail->mail_flags, MAIL_URGENT)) SET_BIT(mail_table[pos].flags, MINDEX_URGENT); if (IS_SET_AR(mail->mail_flags, MAIL_DELETED)) SET_BIT(mail_table[pos].flags, MINDEX_DELETED); if (IS_SET_AR(mail->mail_flags, MAIL_COD)) SET_BIT(mail_table[pos].flags, MINDEX_IS_COD); if (mail->attachment != NULL) SET_BIT(mail_table[pos].flags, MINDEX_HAS_OBJ); if (mail->coins > 0) SET_BIT(mail_table[pos].flags, MINDEX_HAS_GOLD); return (pos); } bool delete_mail_index_entry(int mail_id) { int i, found=0; struct mail_index *temp_mail; bool ret; if (top_of_mail_table == -1 || mail_table == NULL) { /* no table */ /* There is no table - this function shouldn't even have been called */ log("SYSERR: Attempt to delete mail id %d, but no mail index exists", mail_id); return FALSE; } else { /* create a new smaller table */ CREATE(temp_mail, struct mail_index, top_of_mail_table); } /* Copy all index entries to new table */ for (i=0; i<=top_of_mail_table; i++) { /* Is this the one to be removed? */ if (mail_table[i].mail_id == mail_id) { /* Do not copy - just mark as 'found' */ found++; } else { /* Not the one to be removed - copy over the data */ copy_mail_index_entry(&(temp_mail[i-found]), &(mail_table[i])); } } /* Freeing the index loses other vars, so back them up now */ i = top_of_mail_table - 1; found = top_mail_idnum; /* All done - free up the old index, and then set the new index as the current one */ free_mail_index(); mail_table = temp_mail; /* Restore vars */ top_of_mail_table = i; top_mail_idnum = found; /* And save the new index */ ret = save_mail_index(); return ret; } /* This function necessary to save a seperate ASCII mail index */ bool save_mail_index(void) { int i; char index_name[50], bits[64]; FILE *index_file; sprintf(index_name, "%s%s", LIB_MLFILES, INDEX_FILE); if (!(index_file = fopen(index_name, "w"))) { log("SYSERR: Could not write mudmail index file (%s)", index_name); return FALSE; } fprintf(index_file, "# tbaMUD mail index\n"); fprintf(index_file, "# Format: