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.22 $
   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@ripe.net
  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 int  EP_TreeHeight;
  64 int  EP_Node_ID;
  65 int  EP_Debug;
  66 
  67 const char *vS_strRC[] = { "IS_VALID",
  68                            "IS_NOT_PGP",
  69                            "KO",
  70                            "CRC_ERROR",
  71                            "NO_PUBLIC_KEY",
  72                            "NO_OPENPGP_DATA",
  73                            "NO_IN_FILES",
  74                            "NO_OUT_FILES",
  75                            "TO_BE_PGPVERIFIED",
  76                            "UNABLE_TO_WRITE_FILE",
  77                            "UNMATCHED_PGP_DELIMITERS"
  78                          };
  79 
  80 #define EP_TREEMAXHEIGHT 10;
  81 
  82 EP_Mail_DescrPtr InitializeMailDescr( const char *inputFile ) {
     /* [<][>][^][v][top][bottom][index][help] */
  83 
  84   EP_Mail_DescrPtr ptr;
  85   /*  EPNodePtr rootNode; */
  86   int retcode;
  87   long debug = 0;
  88 
  89   ptr = malloc(sizeof(EP_Mail_Descr));
  90 
  91   ptr->from = ptr->subject = ptr->date = 
  92   ptr->message_id = ptr->reply_to = ptr->cc = 
  93   ptr->content_type = NULL ;
  94 
  95 
  96   /* Obtain headers */
  97   retcode = MM_get_headers(inputFile, ptr, debug);
  98 
  99   ptr->tree = EP_InitializeRootNode(inputFile);
 100   
 101   return ptr;
 102 }
 103 
 104 /* ------------------------------------------------- */
 105 
 106 EP_Mail_DescrPtr EP_ParseMail(const char *inputFile,
     /* [<][>][^][v][top][bottom][index][help] */
 107                               const char *outputPath,
 108                               const char *keyRing) {
 109   EP_Mail_DescrPtr ptr;
 110   char hostname[MAXHOSTNAMELEN];
 111   int retcode;
 112   long debug = 0;
 113   char mail_file[FILENAMELEN];
 114 
 115   EP_Debug = debug;
 116 
 117   gethostname(hostname, MAXHOSTNAMELEN);
 118   sprintf(EP_outputPrefix, "%s/EPMtmp.%s.%ld.", outputPath,
 119           hostname, getpid());
 120   strcpy(EP_keyRing, keyRing);
 121 
 122   sprintf (mail_file,"%sunprocessed", EP_outputPrefix);      /* the file where the mail message will be stored */
 123 
 124   /* if ((retcode = MM_store((char*)inputFile,mail_file, debug)) != 0)
 125     exit (retcode); */
 126 
 127   MM_store((char*)inputFile,mail_file, debug);
 128   
 129   ptr = InitializeMailDescr(mail_file);
 130   /* Invoke the MIME parser */
 131   retcode = MM_extract_mime(mail_file, NULL, ptr->tree, debug);
 132 
 133   return ptr;
 134 }
 135 
 136 /* ------------------------------------------------- */
 137 
 138 EPNodePtr EP_ParseText(const char *inputFile,
     /* [<][>][^][v][top][bottom][index][help] */
 139                        const char *outputPath,
 140                        const char *keyRing) {
 141   EPNodePtr ptr;
 142   char hostname[MAXHOSTNAMELEN];
 143 
 144   EP_Debug = 0;
 145 
 146   gethostname(hostname, MAXHOSTNAMELEN);
 147   sprintf(EP_outputPrefix, "%s/EPTtmp.%s.%ld.", outputPath,
 148           hostname, getpid());
 149 
 150   strcpy(EP_keyRing, keyRing);
 151 
 152   ptr = EP_InitializeRootNode(inputFile);
 153 
 154   return PA_ParseMessage(ptr);
 155 }
 156 
 157 
 158 /* ------------------------------------------------- */
 159 
 160 EPNodePtr EP_MIMEParse(const EPNodePtr p)
     /* [<][>][^][v][top][bottom][index][help] */
 161 {
 162   char mail_file[FILENAMELEN];
 163   int retcode;
 164   FILE * fin;
 165   char *strptr;
 166   int found = 0, headers_end = 0;
 167   char txt[MAX_LINE_BUF];
 168 
 169   sprintf (mail_file,"%s%d.unprocessed", EP_outputPrefix, p->nodeID);      /* the file where the mail message will be stored */
 170   
 171   /* Quest for a mail header:
 172      look for a mail header of type (content-type || mime version).
 173   */
 174 
 175   if ((fin = fopen(p->file, "r")) != NULL) { 
 176     while ( !headers_end && !found && 
 177             (strptr = fgets(txt, MAX_LINE_BUF, fin)) != NULL) {
 178       if ( do_regex_test("^Content-Type:", txt) || 
 179            do_regex_test("^MIME-Version:", txt)) {
 180         found = 1;
 181         fclose(fin);
 182         
 183         /* if ((retcode = MM_store((char*)p->file,mail_file, EP_Debug)) != 0) {
 184            fprintf(stderr, "Error on MM_Store: %d\n", retcode );
 185            } */
 186 
 187         MM_store((char*)p->file,mail_file, EP_Debug);
 188 
 189         /* Invoke the MIME parser */
 190         retcode = MM_extract_mime(mail_file, NULL, p, EP_Debug);
 191       } else
 192         if ( do_regex_test("^ *\n", txt) ) 
 193           headers_end = 1; 
 194     }
 195 
 196     if (!found) {
 197       fclose(fin);
 198       PA_ParseMessage(p);
 199     }
 200 
 201   } else {
 202     p->isValidPGPSignature = vS_NO_IN_FILES;
 203   }
 204 
 205   return p;
 206 }
 207 
 208 /* ------------------------------------------------- */
 209 
 210 EPNodePtr EP_InitializeRootNode( const char *inputFile ) {
     /* [<][>][^][v][top][bottom][index][help] */
 211   EPNodePtr rootNode;
 212 
 213   EP_TreeHeight = EP_Node_ID = 0;
 214 
 215   rootNode = malloc(sizeof(struct EPNode));
 216 
 217   rootNode->nodeID = 0;
 218   rootNode->isValidPGPSignature = vS_IS_NOT_PGP;
 219   rootNode->keyID = 0;
 220   rootNode->MIMEContentType = -1;
 221   rootNode->strMIMEContentType = NULL;
 222   rootNode->file = strdup(inputFile);
 223   rootNode->inner = NULL;
 224   rootNode->next = NULL;
 225 
 226   return rootNode; 
 227 }
 228 
 229 /* ------------------------------------------------- */
 230 
 231 EPNodePtr EP_InitializeNode( const char *inputFile, const int nodeID ) {
     /* [<][>][^][v][top][bottom][index][help] */
 232   EPNodePtr node;
 233 
 234   node = malloc(sizeof(struct EPNode));
 235 
 236   node->nodeID = nodeID;
 237   node->isValidPGPSignature = vS_IS_NOT_PGP;
 238   node->keyID = 0;
 239   node->MIMEContentType = -1;
 240   node->strMIMEContentType = NULL;
 241   node->file = strdup(inputFile);
 242   node->inner = NULL;
 243   node->next = NULL;
 244 
 245   return node; 
 246 }
 247 
 248 /* ------------------------------------------------- */
 249 
 250 EPNodePtr EP_DefineNewNode( const int nodeID,
     /* [<][>][^][v][top][bottom][index][help] */
 251                             const short isValidPGPSignature,
 252                             const t_MM_type MIMEContentType,
 253                             const char *strMIMEContentType,
 254                             const u32 keyID) {
 255   EPNodePtr node;
 256 
 257   node = (EPNodePtr) malloc(sizeof(EP_mail_node));
 258 
 259   /*  printf("node: %d, %p\n", nodeID, node); */
 260 
 261   node->nodeID = nodeID;
 262   node->isValidPGPSignature = isValidPGPSignature;
 263   node->keyID = keyID;
 264   node->MIMEContentType = MIMEContentType;
 265   node->strMIMEContentType = (strMIMEContentType == NULL ? NULL : 
 266                               strdup(strMIMEContentType) );
 267   node->inner = NULL;
 268   node->next = NULL;
 269   EP_BuildFilename(node);
 270 
 271   return node; 
 272 }
 273 
 274 /* ------------------------------------------------- */
 275 /* Deallocate parsing tree and remove files */
 276 
 277 void EP_TreeCleanUp(const EPNodePtr ptr) {
     /* [<][>][^][v][top][bottom][index][help] */
 278 
 279   if (ptr->file != NULL) {
 280     /*    unlink(ptr->file);   */
 281     /*    printf("node: %d, %p\n", ptr->nodeID, ptr); */
 282     free(ptr->file);
 283   }
 284   if (ptr->strMIMEContentType != NULL) {
 285     free(ptr->strMIMEContentType);
 286   }
 287 
 288   if (ptr->inner != NULL) EP_TreeCleanUp(ptr->inner);
 289   if (ptr->next != NULL) EP_TreeCleanUp(ptr->next);
 290 
 291   free(ptr);
 292 }
 293 
 294 /* ------------------------------------------------- */
 295 void MailHeaderFieldCleanUp(Mail_Header_FieldPtr p) {
     /* [<][>][^][v][top][bottom][index][help] */
 296   Mail_Header_FieldPtr ptmp = p, prev; 
 297 
 298   while (ptmp != NULL) {
 299     prev = ptmp;
 300     ptmp = ptmp->next;
 301     if (prev->field != NULL)
 302       free(prev->field);
 303     free(prev);
 304   }
 305 }
 306 
 307 
 308 /* ------------------------------------------------- */
 309 
 310 /* Deallocate parsing tree and remove files */
 311 
 312 void EP_MailDescrCleanUp(const EP_Mail_DescrPtr ptr) {
     /* [<][>][^][v][top][bottom][index][help] */
 313 
 314   if (ptr != NULL) {
 315 
 316     MailHeaderFieldCleanUp(ptr->from);
 317     MailHeaderFieldCleanUp(ptr->subject);
 318     MailHeaderFieldCleanUp(ptr->date);
 319     MailHeaderFieldCleanUp(ptr->message_id);
 320     MailHeaderFieldCleanUp(ptr->reply_to);
 321     MailHeaderFieldCleanUp(ptr->cc);
 322     MailHeaderFieldCleanUp(ptr->content_type);
 323 
 324     EP_TreeCleanUp(ptr->tree);
 325     free(ptr);
 326   }
 327 }
 328 
 329 /* ------------------------------------------------- */
 330 /* Build a node filename */
 331 
 332 void EP_BuildFilename(const EPNodePtr ptr) {
     /* [<][>][^][v][top][bottom][index][help] */
 333   char file[FILENAME_LENGTH];
 334 
 335   sprintf(file, "%s%d", EP_outputPrefix, ptr->nodeID);
 336   ptr->file = strdup(file);
 337 }
 338 
 339 /* ------------------------------------------------- */
 340 
 341 void EP_ShowTree(const EPNodePtr p) {
     /* [<][>][^][v][top][bottom][index][help] */
 342   if (p != NULL) {
 343     if (EP_HasContent(p)) {
 344       printf("Node ID: %d\n", p->nodeID);
 345       printf("isValidPGPSignature: %s\n",  vS_strRC[p->isValidPGPSignature]);  
 346       printf("MIMEContentType: %d\n", p->MIMEContentType);
 347       printf("Key ID: %0X\n", p->keyID);
 348       printf("file: %s\n\n\n", p->file);
 349     }
 350     if (p->inner != NULL)
 351       EP_ShowTree(p->inner);
 352     if (p->next != NULL)
 353       EP_ShowTree(p->next);
 354   }
 355 }
 356 
 357 /* ------------------------------------------------- */
 358 
 359 EPTokenPtr EP_DefineNewToken( const t_MM_type MIMEContentType,
     /* [<][>][^][v][top][bottom][index][help] */
 360                               const char *file,
 361                               const EPTokenKeysPtr keysList ) {
 362   EPTokenPtr token;
 363   EPTokenKeysPtr head = NULL, p = keysList, pnew, prev = NULL;
 364   
 365   token = (EPTokenPtr) malloc(sizeof(EPToken));
 366   token->file = (char*)file;
 367   token->MIMEContentType = MIMEContentType;
 368 
 369 
 370   /* generate head, and build the key list for this result node */
 371   if (p != NULL) {
 372     pnew = (EPTokenKeysPtr) malloc(sizeof(EPTokenKeys));
 373     pnew->isValidPGPSignature = p->isValidPGPSignature;
 374     pnew->keyID = p->keyID;
 375     pnew->next = NULL;
 376     head = prev = pnew;
 377     p = p->next;
 378   }
 379 
 380   while (p != NULL) {
 381     pnew = (EPTokenKeysPtr) malloc(sizeof(EPTokenKeys));
 382     pnew->isValidPGPSignature = p->isValidPGPSignature;
 383     pnew->keyID = p->keyID;
 384     pnew->next = NULL;
 385     prev->next = pnew;
 386     prev = pnew;
 387     p = p->next;
 388   }
 389 
 390   token->keys = head;
 391   token->next = token->prev = NULL;
 392 
 393   return token;   
 394 }
 395 
 396 /* ------------------------------------------------- */
 397 
 398 EPTokenKeysPtr AddKeyInfo( EPTokenKeysPtr keysList, const EPNodePtr p ){
     /* [<][>][^][v][top][bottom][index][help] */
 399   EPTokenKeysPtr ptk;
 400 
 401   ptk = (EPTokenKeysPtr) malloc(sizeof(EPTokenKeys));
 402   ptk->isValidPGPSignature = p->isValidPGPSignature;
 403   ptk->keyID = p->keyID;
 404   ptk->next = NULL;
 405   if (keysList == NULL)
 406     return ptk;
 407   else {
 408     ptk->next = keysList;
 409     return ptk;
 410   }
 411 }
 412 
 413 /* ------------------------------------------------- */
 414 
 415 EPTokenKeysPtr RemoveKeyInfo( const EPTokenKeysPtr keysHead ) {
     /* [<][>][^][v][top][bottom][index][help] */
 416   EPTokenKeysPtr tmp = keysHead->next;
 417 
 418   free(keysHead);
 419   return tmp;
 420 }
 421 /* ------------------------------------------------- */
 422 
 423 EPTokenPtr EP_GetTokens(const EPNodePtr p, const EPTokenPtr head, 
     /* [<][>][^][v][top][bottom][index][help] */
 424                         EPTokenKeysPtr keysList) {
 425   EPTokenPtr pt, ptmp = head;
 426   EPTokenKeysPtr kl = keysList;
 427   
 428   if (p != NULL) {
 429     if (p->isValidPGPSignature != vS_IS_NOT_PGP ) {
 430       kl = AddKeyInfo(kl, p);
 431     }
 432     if (EP_HasContent(p)) {
 433       pt = EP_DefineNewToken(p->MIMEContentType, p->file, kl);
 434       if (ptmp != NULL) {
 435         pt->next = ptmp;
 436         ptmp->prev = pt;
 437         ptmp = pt;
 438       } else 
 439         ptmp = pt;
 440     } else
 441       ptmp = EP_GetTokens(p->inner, ptmp, kl);
 442 
 443     if (p->isValidPGPSignature != vS_IS_NOT_PGP ) {
 444       kl = RemoveKeyInfo(kl);
 445     }
 446 
 447     ptmp = EP_GetTokens(p->next, ptmp, kl);
 448   }
 449   return ptmp;
 450 }
 451 
 452 /* ------------------------------------------------- */
 453 void EP_PrintTokens(EPTokenPtr head) {
     /* [<][>][^][v][top][bottom][index][help] */
 454   EPTokenPtr p = head;
 455   EPTokenKeysPtr ptk;
 456 
 457   while (p != NULL) {
 458     printf("Token: %s, MIMEtype: %d\n", p->file, p->MIMEContentType);
 459     ptk = p->keys;
 460     while (ptk != NULL) {
 461       printf("     key: %0X, isValid: %s\n", 
 462              ptk->keyID, vS_strRC[ptk->isValidPGPSignature]);
 463       ptk = ptk->next;
 464     }
 465     p = p->next;
 466   }
 467 }
 468 
 469 /* ------------------------------------------------- */
 470 
 471 void EP_CleanTokens(const EPTokenPtr head) {
     /* [<][>][^][v][top][bottom][index][help] */
 472   EPTokenPtr prevp, p = head;
 473   EPTokenKeysPtr ptk, prevptk;
 474 
 475   while (p != NULL) {
 476     ptk = p->keys;
 477     while (ptk != NULL) {
 478       prevptk = ptk;
 479       ptk = ptk->next;
 480       free(prevptk);
 481     }
 482     prevp = p;
 483     p = p->next;
 484     free(prevp);
 485   }
 486 }
 487 
 488 

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