modules/ep/mail_parser.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- InitializeMailDescr
- EP_ParseMail
- EP_ParseText
- EP_MIMEParse
- EP_InitializeRootNode
- EP_InitializeNode
- EP_DefineNewNode
- EP_TreeCleanUp
- MailHeaderFieldCleanUp
- EP_MailDescrCleanUp
- EP_BuildFilename
- EP_ShowTree
- EP_DefineNewToken
- AddKeyInfo
- RemoveKeyInfo
- EP_GetTokens
- EP_PrintTokens
- EP_CleanTokens
1 /***************************************
2 $Revision: 1.26 $
3
4 Email Parser module (ep) - wrapping functions to parse email,
5 calling MM and PA.
6
7 Status: NOT REVUED, TESTED
8
9 ******************/ /******************
10 Filename : mail_parser.c
11 Authors : Filippo Portera, Daniele Arena
12 OSs Tested : Solaris 7
13 ******************/ /******************
14 Copyright (c) 2000 RIPE NCC
15
16 All Rights Reserved
17
18 Permission to use, copy, modify, and distribute this software and its
19 documentation for any purpose and without fee is hereby granted,
20 provided that the above copyright notice appear in all copies and that
21 both that copyright notice and this permission notice appear in
22 supporting documentation, and that the name of the author not be
23 used in advertising or publicity pertaining to distribution of the
24 software without specific, written prior permission.
25
26 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
27 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
28 AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
29 DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
30 AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
31 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
32 ***************************************/
33
34 #include <stdio.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #include <netdb.h>
38 #include <sys/param.h>
39
40 #include "mm.h"
41 #include "gpg.h"
42 #include "mail_parser.h"
43
44 /* Parse the mail message stored in inputFile and develop it
45 in distinct text files, writing them on the outputPath
46 directory and using the variable keyRing to read public
47 keys needed for the verification process.
48
49 The common use of this parse should look like this:
50
51 p = EP_ParseMessage("mail.001", "/tmp", "~/.gnupg/pubring.gpg");
52
53 < parse the tree: p->tree >
54
55 EP_TreeCleanUp(p);
56
57 */
58
59 /* Globals to store shared data for tree nodes */
60
61 char EP_outputPrefix[FILENAME_LENGTH];
62 char EP_keyRing[FILENAME_LENGTH];
63 char EP_gpgcmd[FILENAME_LENGTH];
64 int EP_TreeHeight;
65 int EP_Node_ID;
66 int EP_Debug;
67
68 const char *vS_strRC[] = { "IS_VALID",
69 "IS_NOT_PGP",
70 "KO",
71 "CRC_ERROR",
72 "NO_PUBLIC_KEY",
73 "NO_OPENPGP_DATA",
74 "NO_IN_FILES",
75 "NO_OUT_FILES",
76 "TO_BE_PGPVERIFIED",
77 "UNABLE_TO_WRITE_FILE",
78 "UNMATCHED_PGP_DELIMITERS"
79 };
80
81 #define EP_TREEMAXHEIGHT 10;
82
83 EP_Mail_DescrPtr InitializeMailDescr( const char *inputFile ) {
/* [<][>][^][v][top][bottom][index][help] */
84
85 EP_Mail_DescrPtr ptr;
86 /* EPNodePtr rootNode; */
87 int retcode;
88 long debug = 0;
89
90 ptr = UT_malloc(sizeof(EP_Mail_Descr));
91
92 ptr->from = ptr->subject = ptr->date =
93 ptr->message_id = ptr->reply_to = ptr->cc =
94 ptr->content_type = NULL ;
95
96
97 /* Obtain headers */
98 retcode = MM_get_headers(inputFile, ptr, debug);
99
100 ptr->tree = EP_InitializeRootNode(inputFile);
101
102 return ptr;
103 }
104
105 /* ------------------------------------------------- */
106
107 EP_Mail_DescrPtr EP_ParseMail(const char *inputFile,
/* [<][>][^][v][top][bottom][index][help] */
108 const char *outputPath,
109 const char *keyRing,
110 const char *gpgcmd) {
111 EP_Mail_DescrPtr ptr;
112 char hostname[MAXHOSTNAMELEN];
113 int retcode;
114 long debug = 0;
115 char mail_file[FILENAMELEN];
116
117 EP_Debug = debug;
118
119 gethostname(hostname, MAXHOSTNAMELEN);
120 sprintf(EP_outputPrefix, "%s/EPMtmp.%s.%ld.", outputPath,
121 hostname, getpid());
122 strcpy(EP_keyRing, keyRing);
123 strcpy(EP_gpgcmd, gpgcmd);
124
125 sprintf (mail_file,"%sunprocessed", EP_outputPrefix); /* the file where the mail message will be stored */
126
127 /* if ((retcode = MM_store((char*)inputFile,mail_file, debug)) != 0)
128 exit (retcode); */
129
130 MM_store((char*)inputFile,mail_file, debug);
131
132 ptr = InitializeMailDescr(mail_file);
133 /* Invoke the MIME parser */
134 retcode = MM_extract_mime(mail_file, NULL, ptr->tree, debug);
135
136 return ptr;
137 }
138
139 /* ------------------------------------------------- */
140
141 EPNodePtr EP_ParseText(const char *inputFile,
/* [<][>][^][v][top][bottom][index][help] */
142 const char *outputPath,
143 const char *keyRing,
144 const char *gpgcmd) {
145 EPNodePtr ptr;
146 char hostname[MAXHOSTNAMELEN];
147
148 EP_Debug = 0;
149
150 gethostname(hostname, MAXHOSTNAMELEN);
151 sprintf(EP_outputPrefix, "%s/EPTtmp.%s.%ld.", outputPath,
152 hostname, getpid());
153
154 strcpy(EP_keyRing, keyRing);
155 strcpy(EP_gpgcmd, gpgcmd);
156
157 ptr = EP_InitializeRootNode(inputFile);
158
159 return PA_ParseMessage(ptr);
160 }
161
162
163 /* ------------------------------------------------- */
164
165 EPNodePtr EP_MIMEParse(const EPNodePtr p)
/* [<][>][^][v][top][bottom][index][help] */
166 {
167 char mail_file[FILENAMELEN];
168 int retcode;
169 FILE * fin;
170 char *strptr;
171 int found = 0, headers_end = 0;
172 char txt[MAX_LINE_BUF];
173
174 sprintf (mail_file,"%s%d.unprocessed", EP_outputPrefix, p->nodeID); /* the file where the mail message will be stored */
175
176 /* Quest for a mail header:
177 look for a mail header of type (content-type || mime version).
178 */
179
180 if ((fin = fopen(p->file, "r")) != NULL) {
181 while ( !headers_end && !found &&
182 (strptr = fgets(txt, MAX_LINE_BUF, fin)) != NULL) {
183 if ( do_regex_test("^Content-Type:", txt) ||
184 do_regex_test("^MIME-Version:", txt)) {
185 found = 1;
186 fclose(fin);
187
188 /* if ((retcode = MM_store((char*)p->file,mail_file, EP_Debug)) != 0) {
189 fprintf(stderr, "Error on MM_Store: %d\n", retcode );
190 } */
191
192 MM_store((char*)p->file,mail_file, EP_Debug);
193
194 /* Invoke the MIME parser */
195 retcode = MM_extract_mime(mail_file, NULL, p, EP_Debug);
196 } else
197 if ( do_regex_test("^ *\n", txt) )
198 headers_end = 1;
199 }
200
201 if (!found) {
202 fclose(fin);
203 PA_ParseMessage(p);
204 }
205
206 } else {
207 p->isValidPGPSignature = vS_NO_IN_FILES;
208 }
209
210 return p;
211 }
212
213 /* ------------------------------------------------- */
214
215 EPNodePtr EP_InitializeRootNode( const char *inputFile ) {
/* [<][>][^][v][top][bottom][index][help] */
216 EPNodePtr rootNode;
217
218 EP_TreeHeight = EP_Node_ID = 0;
219
220 rootNode = UT_malloc(sizeof(struct EPNode));
221
222 rootNode->nodeID = 0;
223 rootNode->isValidPGPSignature = vS_IS_NOT_PGP;
224 rootNode->keyID = 0;
225 rootNode->MIMEContentType = -1;
226 rootNode->strMIMEContentType = NULL;
227 rootNode->file = strdup(inputFile);
228 rootNode->inner = NULL;
229 rootNode->next = NULL;
230
231 return rootNode;
232 }
233
234 /* ------------------------------------------------- */
235
236 EPNodePtr EP_InitializeNode( const char *inputFile, const int nodeID ) {
/* [<][>][^][v][top][bottom][index][help] */
237 EPNodePtr node;
238
239 node = UT_malloc(sizeof(struct EPNode));
240
241 node->nodeID = nodeID;
242 node->isValidPGPSignature = vS_IS_NOT_PGP;
243 node->keyID = 0;
244 node->MIMEContentType = -1;
245 node->strMIMEContentType = NULL;
246 node->file = strdup(inputFile);
247 node->inner = NULL;
248 node->next = NULL;
249
250 return node;
251 }
252
253 /* ------------------------------------------------- */
254
255 EPNodePtr EP_DefineNewNode( const int nodeID,
/* [<][>][^][v][top][bottom][index][help] */
256 const short isValidPGPSignature,
257 const t_MM_type MIMEContentType,
258 const char *strMIMEContentType,
259 const u32 keyID) {
260 EPNodePtr node;
261
262 node = (EPNodePtr) UT_malloc(sizeof(EP_mail_node));
263
264 /* printf("node: %d, %p\n", nodeID, node); */
265
266 node->nodeID = nodeID;
267 node->isValidPGPSignature = isValidPGPSignature;
268 node->keyID = keyID;
269 node->MIMEContentType = MIMEContentType;
270 node->strMIMEContentType = (strMIMEContentType == NULL ? NULL :
271 strdup(strMIMEContentType) );
272 node->inner = NULL;
273 node->next = NULL;
274 EP_BuildFilename(node);
275
276 return node;
277 }
278
279 /* ------------------------------------------------- */
280 /* Deallocate parsing tree and remove files */
281
282 void EP_TreeCleanUp(const EPNodePtr ptr) {
/* [<][>][^][v][top][bottom][index][help] */
283
284 if (ptr->file != NULL) {
285 unlink(ptr->file);
286 /* printf("node: %d, %p\n", ptr->nodeID, ptr); */
287 free(ptr->file);
288 }
289 if (ptr->strMIMEContentType != NULL) {
290 free(ptr->strMIMEContentType);
291 }
292
293 if (ptr->inner != NULL) EP_TreeCleanUp(ptr->inner);
294 if (ptr->next != NULL) EP_TreeCleanUp(ptr->next);
295
296 free(ptr);
297 }
298
299 /* ------------------------------------------------- */
300 void MailHeaderFieldCleanUp(Mail_Header_FieldPtr p) {
/* [<][>][^][v][top][bottom][index][help] */
301 Mail_Header_FieldPtr ptmp = p, prev;
302
303 while (ptmp != NULL) {
304 prev = ptmp;
305 ptmp = ptmp->next;
306 if (prev->field != NULL)
307 free(prev->field);
308 free(prev);
309 }
310 }
311
312
313 /* ------------------------------------------------- */
314
315 /* Deallocate parsing tree and remove files */
316
317 void EP_MailDescrCleanUp(const EP_Mail_DescrPtr ptr) {
/* [<][>][^][v][top][bottom][index][help] */
318
319 if (ptr != NULL) {
320
321 MailHeaderFieldCleanUp(ptr->from);
322 MailHeaderFieldCleanUp(ptr->subject);
323 MailHeaderFieldCleanUp(ptr->date);
324 MailHeaderFieldCleanUp(ptr->message_id);
325 MailHeaderFieldCleanUp(ptr->reply_to);
326 MailHeaderFieldCleanUp(ptr->cc);
327 MailHeaderFieldCleanUp(ptr->content_type);
328
329 EP_TreeCleanUp(ptr->tree);
330 free(ptr);
331 }
332 }
333
334 /* ------------------------------------------------- */
335 /* Build a node filename */
336
337 void EP_BuildFilename(const EPNodePtr ptr) {
/* [<][>][^][v][top][bottom][index][help] */
338 char file[FILENAME_LENGTH];
339
340 sprintf(file, "%s%d", EP_outputPrefix, ptr->nodeID);
341 ptr->file = strdup(file);
342 }
343
344 /* ------------------------------------------------- */
345
346 void EP_ShowTree(const EPNodePtr p) {
/* [<][>][^][v][top][bottom][index][help] */
347 if (p != NULL) {
348 /* if (EP_HasContent(p)) { */
349 printf("Node ID: %d\n", p->nodeID);
350 printf("isValidPGPSignature: %s\n", vS_strRC[p->isValidPGPSignature]);
351 printf("MIMEContentType: %d\n", p->MIMEContentType);
352 printf("Key ID: %0X\n", p->keyID);
353 printf("file: %s\n\n\n", p->file);
354 /* } */
355 if (p->inner != NULL)
356 EP_ShowTree(p->inner);
357 if (p->next != NULL)
358 EP_ShowTree(p->next);
359 }
360 }
361
362 /* ------------------------------------------------- */
363
364 EPTokenPtr EP_DefineNewToken( const t_MM_type MIMEContentType,
/* [<][>][^][v][top][bottom][index][help] */
365 const char *file,
366 const EPTokenKeysPtr keysList ) {
367 EPTokenPtr token;
368 EPTokenKeysPtr head = NULL, p = keysList, pnew, prev = NULL;
369
370 token = (EPTokenPtr) UT_malloc(sizeof(EPToken));
371 token->file = (char*)file;
372 token->MIMEContentType = MIMEContentType;
373
374
375 /* generate head, and build the key list for this result node */
376 if (p != NULL) {
377 pnew = (EPTokenKeysPtr) UT_malloc(sizeof(EPTokenKeys));
378 pnew->isValidPGPSignature = p->isValidPGPSignature;
379 pnew->keyID = p->keyID;
380 pnew->next = NULL;
381 head = prev = pnew;
382 p = p->next;
383 }
384
385 while (p != NULL) {
386 pnew = (EPTokenKeysPtr) UT_malloc(sizeof(EPTokenKeys));
387 pnew->isValidPGPSignature = p->isValidPGPSignature;
388 pnew->keyID = p->keyID;
389 pnew->next = NULL;
390 prev->next = pnew;
391 prev = pnew;
392 p = p->next;
393 }
394
395 token->keys = head;
396 token->next = token->prev = NULL;
397
398 return token;
399 }
400
401 /* ------------------------------------------------- */
402
403 EPTokenKeysPtr AddKeyInfo( EPTokenKeysPtr keysList, const EPNodePtr p ){
/* [<][>][^][v][top][bottom][index][help] */
404 EPTokenKeysPtr ptk;
405
406 ptk = (EPTokenKeysPtr) UT_malloc(sizeof(EPTokenKeys));
407 ptk->isValidPGPSignature = p->isValidPGPSignature;
408 ptk->keyID = p->keyID;
409 ptk->next = NULL;
410 if (keysList == NULL)
411 return ptk;
412 else {
413 ptk->next = keysList;
414 return ptk;
415 }
416 }
417
418 /* ------------------------------------------------- */
419
420 EPTokenKeysPtr RemoveKeyInfo( const EPTokenKeysPtr keysHead ) {
/* [<][>][^][v][top][bottom][index][help] */
421 EPTokenKeysPtr tmp = keysHead->next;
422
423 free(keysHead);
424 return tmp;
425 }
426 /* ------------------------------------------------- */
427
428 EPTokenPtr EP_GetTokens(const EPNodePtr p, const EPTokenPtr head,
/* [<][>][^][v][top][bottom][index][help] */
429 EPTokenKeysPtr keysList) {
430 EPTokenPtr pt, ptmp = head;
431 EPTokenKeysPtr kl = keysList;
432
433 if (p != NULL) {
434 if (p->isValidPGPSignature != vS_IS_NOT_PGP ) {
435 kl = AddKeyInfo(kl, p);
436 }
437 if (EP_HasContent(p)) {
438 pt = EP_DefineNewToken(p->MIMEContentType, p->file, kl);
439 if (ptmp != NULL) {
440 pt->next = ptmp;
441 ptmp->prev = pt;
442 ptmp = pt;
443 } else
444 ptmp = pt;
445 } else
446 ptmp = EP_GetTokens(p->inner, ptmp, kl);
447
448 if (p->isValidPGPSignature != vS_IS_NOT_PGP ) {
449 kl = RemoveKeyInfo(kl);
450 }
451
452 ptmp = EP_GetTokens(p->next, ptmp, kl);
453 }
454 return ptmp;
455 }
456
457 /* ------------------------------------------------- */
458 void EP_PrintTokens(EPTokenPtr head) {
/* [<][>][^][v][top][bottom][index][help] */
459 EPTokenPtr p = head;
460 EPTokenKeysPtr ptk;
461
462 while (p != NULL) {
463 printf("Token: %s, MIMEtype: %d\n", p->file, p->MIMEContentType);
464 ptk = p->keys;
465 while (ptk != NULL) {
466 printf(" key: %0X, isValid: %s\n",
467 ptk->keyID, vS_strRC[ptk->isValidPGPSignature]);
468 ptk = ptk->next;
469 }
470 p = p->next;
471 }
472 }
473
474 /* ------------------------------------------------- */
475
476 void EP_CleanTokens(const EPTokenPtr head) {
/* [<][>][^][v][top][bottom][index][help] */
477 EPTokenPtr prevp, p = head;
478 EPTokenKeysPtr ptk, prevptk;
479
480 while (p != NULL) {
481 ptk = p->keys;
482 while (ptk != NULL) {
483 prevptk = ptk;
484 ptk = ptk->next;
485 free(prevptk);
486 }
487 prevp = p;
488 p = p->next;
489 free(prevp);
490 }
491 }
492
493