## 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] */