1 2 #ifndef _mime_h 3 #define _mime_h 4 5 /* This is a simple general MIME parsing/interpreting structure. 6 7 Given an iostream, we can parse out the header, and recursively 8 create the MIME entity datastructures. 9 */ 10 11 #include "md5.h" 12 #include "list.tmpl" 13 #include "hash.tmpl" 14 #include "iobottle.h" 15 16 17 /* This class encapsulates a MIME entity */ 18 class MIME_body { 19 20 public: 21 MIME_body(IObottle *RawFile, char *endstrings[], 22 MIME_body *lineage = NULL); 23 ~MIME_body(); 24 25 /* Decode a raw header line */ 26 static char *DecodeLine(const char *line); 27 28 /* Tell the native character set */ 29 static void MIME_Charset(char *charset); 30 31 /* Tell which MIME content-types to ignore */ 32 static void MIME_Ignore(char *ignorelist); 33 Parent(void)34 MIME_body *Parent(void) { 35 return(parent); 36 } Content(void)37 const char *Content(void) { 38 return(content); 39 } IsHTML()40 bool IsHTML() { 41 return (strstr(content, "text/html") != NULL); 42 } Encoding(void)43 const char *Encoding(void) { 44 return(encoding); 45 } Name(void)46 const char *Name(void) { 47 return(name); 48 } NumParts(void)49 int NumParts(void) { 50 return(multipart ? 1+multipart->Size() : 1); 51 } 52 int AddPart(const char *file, int is_mime = 0); GetPart(unsigned int which)53 MIME_body *GetPart(unsigned int which) { 54 MIME_body **retptr = NULL; 55 56 /* We ARE the first part */ 57 if ( which <= 1 ) 58 return(this); 59 60 if ( ! multipart ) 61 return(NULL); 62 63 multipart->InitIterator(); 64 while ( --which ) { 65 if ( ! (retptr=multipart->Iterate()) ) 66 break; 67 } 68 return(retptr ? *retptr : (MIME_body *)0); 69 } 70 int CurrentPart(int which = -1) { 71 if ( (which > 0) && 72 (which <= (1+(multipart ? multipart->Size() : 0))) ) { 73 currentpart = (which-1); 74 } 75 return(currentpart+1); 76 } ByName(char * whatname)77 MIME_body *ByName(char *whatname) { 78 MIME_body **retptr; 79 MIME_body *okay; 80 81 /* Base case -- ourselves */ 82 if ( name && (strcmp(name, whatname) == 0) ) 83 return(this); 84 85 /* Depth first recursive search on our bodies */ 86 if ( ! multipart ) 87 return(NULL); 88 89 multipart->InitIterator(); 90 okay = NULL; 91 while ( (retptr=multipart->Iterate()) ) { 92 okay = *retptr; 93 if ( (okay=okay->ByName(whatname)) ) 94 break; 95 } 96 return(okay ? okay : (MIME_body *)0); 97 } RawPath(void)98 const char *RawPath(void) { 99 return(rawfile->Path()); 100 } File(void)101 char *File(void) { 102 if ( decoded == NULL ) 103 (void) Open(); 104 ++bodyref; 105 return(decoded); 106 } FreeFile(void)107 int FreeFile(void) { 108 MIME_body **retptr; 109 110 /* Decrement reference count on file */ 111 --bodyref; 112 if ( bodyref > 0 ) { /* File is still in use */ 113 return(0); 114 } 115 bodyref = 0; 116 117 /* Unlink it */ 118 if ( decoded ) { 119 (void) unlink(decoded); 120 decoded = NULL; 121 } 122 if ( ! multipart ) 123 return(1); 124 125 multipart->InitIterator(); 126 while ( (retptr=multipart->Iterate()) ) { 127 while ( (*retptr)->FreeFile() == 0 ) { 128 /* Force the multipart body to close */; 129 } 130 } 131 return(1); 132 } 133 int Save(char *filename, int overwrite); 134 135 /* Header stuff */ 136 char *GetHeader(char **keyholder); 137 const char *GetField(const char *str); 138 void NewField(const char *name, const char *value); 139 140 /* Allow searching of MIME bodies */ 141 MIME_body *Search(const char *pattern); 142 143 /* Two MIME bodies are equivalent iff they have the same MD5 checksum */ 144 int operator == (MIME_body &other) { 145 for ( int i=0; i<16; ++i ) { 146 if ( md5sum[i] != other.md5sum[i] ) 147 return(0); 148 } 149 return(1); 150 } 151 int operator != (MIME_body &other) { 152 return( ! (*this == other)); 153 } 154 155 private: 156 static char *mime_charset; 157 static char **mime_ignore; 158 IObottle *rawfile; /* The raw MIME data file */ 159 MIME_body *parent; /* The body of our parent */ 160 Hash<char *> fieldtab; /* Header fields */ 161 const char *version; /* MIME version header info */ 162 const char *content; /* MIME content header info */ 163 const char *encoding; /* MIME encoding header info */ 164 char *name; /* Name associated with MIME body */ 165 long hstart; /* Offset of header in file */ 166 long bstart; /* Offset of body in file */ 167 char **endstrings; /* MIME body boundaries */ 168 int *endlens; /* Boundary lengths */ 169 int numends; /* Number of boundaries */ 170 171 unsigned char md5sum[16]; /* MD5 Checksum of the MIME body */ 172 char *decoded; /* The name of the decoded file */ 173 int bodyref; /* Reference count on decoded file */ 174 List<MIME_body *> *multipart; 175 List<IObottle *> *addedparts; /* Temp files of parts added */ 176 int currentpart; /* The "current" MIME body part */ 177 178 /* Decode a message creating the 'multipart' list */ 179 int ParseMulti(MD5_CTX *md5ctx); 180 void GetWord(const char *src, char **dst); 181 182 /* Change this MIME body into a multipart message */ 183 int MultipartMe(char **boundaryptr); 184 185 /* Decode the raw body to 'decoded' */ 186 int Open(void); 187 }; 188 189 #endif /* _mime_h */ 190