1 2 // C++ class to manage a mail message 3 4 #ifndef _mailmsg_h 5 #define _mailmsg_h 6 7 extern "C" { 8 #include <sys/types.h> 9 #include <stdio.h> 10 } 11 12 #include "my_regex.h" 13 #include "fifo.tmpl" 14 #include "iobottle.h" 15 #include "mime.h" 16 17 #define CACHED_HEADER "CACHED HEADER" 18 19 /* Notes on the thread structure: 20 21 All messages have next and previous pointers that point to the 22 indexed messages before and after them. They also have thread 23 next and previous pointers that point to the logical messages 24 before and after them, following threads. Messages within a 25 thread have "threaded" and "thread_next" set. Messages heading 26 a thread have "thread_next" set, but "threaded" is not set. 27 */ 28 #define NO_THREADS 0 29 #define HIDE_THREADS 1 30 #define SHOW_THREADS 2 31 32 /* Forward declaration mailbox data */ 33 class mailmsg; 34 struct mbox_data { 35 mbox_data(IObottle *mailfile); 36 37 IObottle *MailFile; 38 mailmsg *head; 39 mailmsg *tail; 40 int nmessages; 41 int showthreads; 42 bool aborted; 43 bool saveall; 44 }; 45 46 class buflen; 47 class mailmsg { 48 49 public: 50 mailmsg(mbox_data *MBox); 51 mailmsg(mbox_data *MBox, FILE *cache); 52 void Add(mailmsg *msg); Abort()53 void Abort() { mbox->aborted = true; } Aborted()54 bool Aborted() { return(mbox->aborted); } SetSave(bool doit)55 void SetSave(bool doit) { mbox->saveall = doit; } Saving(void)56 bool Saving(void) { return(mbox->saveall); } MBox()57 mbox_data *MBox() { return mbox; } 58 ~mailmsg(); 59 60 /* Mailbox stuff */ 61 void ThreadPass1(); 62 void ThreadPass2(); 63 int ThreadedOn(mailmsg *msg); ShowThreads(int showthem)64 void ShowThreads(int showthem) { 65 mbox->showthreads = showthem; 66 } ShowThreads(void)67 int ShowThreads(void) { 68 return(mbox->showthreads); 69 } NumMessages(void)70 int NumMessages(void) { 71 return(mbox->nmessages); 72 } 73 /* Thread navigation stuff */ 74 mailmsg *ByIndex(int the_index); 75 mailmsg *ByStatus(const char *the_status); 76 mailmsg *ByMessageID(const char *messageID); 77 int ThreadSize(void); 78 int ThreadIndex(void); ThreadNext(void)79 mailmsg *ThreadNext(void) { 80 return(thread_next); 81 } RawNext(void)82 mailmsg *RawNext(void) { return privnext; } 83 mailmsg *Next(void); 84 mailmsg *Next(int howmany); RawPrev(void)85 mailmsg *RawPrev(void) { return privprev; } 86 mailmsg *Prev(void); 87 mailmsg *Prev(int howmany); First(void)88 mailmsg *First(void) { 89 return mbox->head; 90 } Last(void)91 mailmsg *Last(void) { 92 return mbox->tail; 93 } SetNext(mailmsg * newnext)94 void SetNext(mailmsg *newnext) { 95 next = newnext; 96 } SetPrev(mailmsg * newprev)97 void SetPrev(mailmsg *newprev) { 98 prev = newprev; 99 } ReOrder(void)100 void ReOrder(void) { 101 next = privnext; 102 prev = privprev; 103 } 104 105 /* Header fields */ 106 char *GetHeader(char **keyholder); 107 const char *GetField(const char *str); MessageID(void)108 const char *MessageID(void) { 109 return messageID; 110 } Importance(void)111 char Importance(void) { 112 return importance; 113 } From(void)114 const char *From(void) { 115 const char *from; 116 117 from = GetField("From"); 118 if ( from == NULL ) { 119 from = GetField("Reply-To"); 120 } 121 return(from ? from : "Unknown"); 122 } To(void)123 const char *To(void) { 124 const char *to; 125 126 to = GetField("To"); 127 if ( to == NULL ) { 128 to = GetField("Apparently-To"); 129 } 130 if ( to == NULL ) { 131 to = GetField("X-Apparently-To"); 132 } 133 if ( to == NULL ) { 134 to = GetField("Cc"); 135 } 136 return(to ? to : "Unknown"); 137 } 138 /* Extract a human name from an email address, if possible */ 139 const char *Author(); 140 const char *Recipient(); 141 /* Return the message's subject */ Subject(void)142 const char *Subject(void) { 143 const char *subject = GetField("Subject"); 144 return(subject ? subject : "<no subject>"); 145 } Subject_Key(void)146 const char *Subject_Key(void) { 147 return(subject_key ? subject_key : ""); 148 } 149 /* Return the message's date in "Month Day" format */ 150 char *MonthDay(void); 151 SetIndex(int newindex)152 void SetIndex(int newindex) { 153 index = newindex; 154 } Index(void)155 int Index(void) { 156 return(index); 157 } 158 159 /* See/Set the status of the message */ 160 const char *Status(bool in_listing = false); 161 const char *DiskStatus(void); 162 void Status(const char *newstatus); Changed(void)163 bool Changed(void) { 164 return(changed); 165 } NoChange(void)166 void NoChange(void) { 167 changed = false; 168 } 169 mailmsg *SkipDeleted(int *nrows); 170 171 /* Get the body of the message */ 172 MIME_body *Body(void); 173 /* Make sure the body hasn't changed */ 174 bool Verify(void); 175 /* Save the message to a file */ 176 int Save(char *filename); 177 /* Save the status to the mailfile */ 178 int SaveStatus(); 179 /* Save the message to the mailfile */ 180 int SaveToDisk(Fifo<buflen> *ringbuf, int &gap); 181 /* Save the header to the cache */ 182 int SaveToCache(FILE *cache); 183 184 /* Get the message offset in the mailfile */ SetOffset(long offset)185 void SetOffset(long offset) { mstart = offset; } SetLength(long length)186 void SetLength(long length) { mlength = length; } Offset(void)187 long Offset(void) { return mstart; } Length(void)188 long Length(void) { return mlength; } 189 190 private: 191 static char *boundary[]; /* The message separator */ 192 193 /* Real variables. :-) */ 194 int index; 195 IObottle *MailFile; 196 mbox_data *mbox; 197 const char *messageID; 198 char *status; 199 long mstart; /* Offset of mail message */ 200 long mlength; /* Length of message */ 201 char checksum[33]; /* header checksum (text) */ 202 Hash<char *> fieldtab; /* Header fields */ 203 MIME_body *body; 204 bool changed; 205 206 /* String of messages stuff */ 207 mailmsg *privnext, *privprev; 208 mailmsg *next, *prev; 209 mailmsg *thread_next, *thread_prev; 210 const char *thread_key; 211 char importance; 212 char *author; 213 char *recipient; 214 char *subject_key; 215 int subject_hash; 216 int threaded; 217 int thread_size; 218 int threaded_to; 219 char *NormalizeSubject(const char *subject); 220 int HashString(char *str); 221 222 /* Return a translation of the given status string */ TranslateStatus(const char * str)223 const char *TranslateStatus(const char *str) { 224 if ( ! str ) 225 str = "N"; 226 else if ( *str == 'R' ) 227 str = " "; 228 return(str); 229 } 230 void FinishInit(); 231 void ThreadMe(mailmsg *msg); 232 void NewField(const char *name, const char *value); 233 }; 234 235 #endif /* _mailmsg_h */ 236