modules/ep/mail_parser.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. InitializeMailDescr
  2. EP_ParseMail
  3. EP_ParseText
  4. EP_MIMEParse
  5. EP_InitializeRootNode
  6. EP_InitializeNode
  7. EP_DefineNewNode
  8. EP_TreeCleanUp
  9. MailHeaderFieldCleanUp
  10. EP_MailDescrCleanUp
  11. EP_BuildFilename
  12. EP_ShowTree
  13. EP_DefineNewToken
  14. AddKeyInfo
  15. RemoveKeyInfo
  16. EP_GetTokens
  17. EP_PrintTokens
  18. EP_CleanTokens

   1 /***************************************
   2   $Revision: 1.27 $
   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.%d.", 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.%d.", 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 

/* [<][>][^][v][top][bottom][index][help] */