Source File mm/mm.c

    1    | /***************************************
    2    |   $Revision: 2.32 $
    3    |
    4    |   mm - MIME Parser module. Functions to parse a mail message part,
    5    |   find if it is MIME-encapsulated, dispatch the part to the
    6    |   appropriate drivers (also included) and return tree nodes
    7    |   with all MIME information.
    8    |
    9    |   Status: COMPLETE, NOT REVUED, TESTED
    10   |
    11   |   Design and implementation by: daniele@ripe.net
    12   |
    13   |   ******************/ /******************
    14   |   Copyright (c) 2000,2001,2002                       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   | /* Pieces of this code stolen and/or adapted from mtest.c,
    35   |  * part of the IMAP toolkit by Mark Crispin:
    36   |  */
    37   |
    38   | /* Original version Copyright 1988 by The Leland Stanford Junior University
    39   |  * Copyright 1999 by the University of Washington
    40   |  *
    41   |  *  Permission to use, copy, modify, and distribute this software and its
    42   |  * documentation for any purpose and without fee is hereby granted, provided
    43   |  * that the above copyright notices appear in all copies and that both the
    44   |  * above copyright notices and this permission notice appear in supporting
    45   |  * documentation, and that the name of the University of Washington or The
    46   |  * Leland Stanford Junior University not be used in advertising or publicity
    47   |  * pertaining to distribution of the software without specific, written prior
    48   |  * permission.  This software is made available "as is", and
    49   |  * THE UNIVERSITY OF WASHINGTON AND THE LELAND STANFORD JUNIOR UNIVERSITY
    50   |  * DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE,
    51   |  * INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
    52   |  * FITNESS FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE UNIVERSITY OF
    53   |  * WASHINGTON OR THE LELAND STANFORD JUNIOR UNIVERSITY BE LIABLE FOR ANY
    54   |  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
    55   |  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
    56   |  * CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF
    57   |  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    58   |  *
    59   |  */
    60   |
    61   |
    62   |
    63   | /**************************
    64   |
    65   |
    66   | "Every program attempts to expand until it can read mail.
    67   |  Those programs which cannot so expand are replaced by
    68   |  ones which can."
    69   | 		(Jamie Zawinski)
    70   |
    71   |
    72   | **************************/
    73   |
    74   |
    75   | #include "rip.h"
    76   |
    77   | /* Standard headers */
    78   | #include <stdio.h>
    79   | #include <signal.h>
    80   | #include <string.h>
    81   | #include <sys/time.h>
    82   | #include <sys/types.h>
    83   | /* #include <sys/param.h> */
    84   | #include <netdb.h>
    85   | #include <regex.h>
    86   | #include <unistd.h>
    87   |
    88   | /* c-client headers */
    89   | #include "misc.h"
    90   |
    91   |
    92   | /*
    93   |  * Globals to store shared data for tree nodes
    94   |  * These variables come from EP
    95   |  */
    96   |
    97   | extern char EP_outputPrefix[FILENAME_LENGTH];
    98   | extern char EP_keyRing[FILENAME_LENGTH];
    99   | extern int EP_TreeHeight;
    100  | extern int  EP_Node_ID;
    101  |
    102  | /* Global variables to be used in this module */
    103  | long debug = DEFAULT_DEBUG;
    104  |
    105  | char *supported_MIME_types[MAXSUPPTYPES] = {
    106  |   "UNKNOWN/UNKNOWN", "TEXT/PLAIN", "APPLICATION/PGP", "MULTIPART/SIGNED",
    107  |   "MULTIPART/MIXED", "MULTIPART/ALTERNATIVE", "MULTIPART/DIGEST",
    108  |   "MESSAGE/RFC822"
    109  | };
    110  |
    111  | long pass = 0;
    112  |
    113  |
    114  | /*
    115  |    FIXMEs:
    116  |    - Revise the whole debug system, debug messages etc. - right now
    117  |      an enormous and globally useless quantity of information is dumped.
    118  | */
    119  |
    120  |
    121  | /*+++++++++++++++++++++++++++++++++++++++
    122  |
    123  |   API functions
    124  |
    125  |   +++++++++++++++++++++++++++++++++++++++*/
    126  |
    127  |
    128  |
    129  | /*++++++++++
    130  |  *
    131  |  * MM_store(). Stores a file (or stdin) in another file,
    132  |  * "escaping" the lines starting with "From " by adding
    133  |  * a ">" sign. This is necessary because we need to deal
    134  |  * with files that are "unix mailboxes".
    135  |  *
    136  |  * This function puts a limit to the line size that a mail
    137  |  * message may have; officially, there is no limit to this size,
    138  |  * but we prefer to add this limit to avoid buffer overflow.
    139  |  * The line size limit is MAXBUFSIZE, defined in mm.h .
    140  |  *
    141  |  ++++++++++*/
    142  |
    143  |
    144  | int MM_store (char *source_file, char *destination_file,
    145  |               long custom_debug, int networkupdate)
    146  | {
    147  |
    148  |
    149  | /* The regexp we will be looking for */
    150  | #define REGEXP "^From "
    151  |
    152  |
    153  |   char line[MAXBUFSIZE];
    154  |   FILE *ifp;
    155  |   FILE *ofp;
    156  |   FILE *actualfile; /* Actual "file" to be opened (can be stdin) */
    157  |   char *tmpstr;
    158  |   short using_file = 0;
    159  |   long numlines = 0;
    160  |   time_t ti = time (0);
    161  |
    162  |
    163  |
    164  |   if (custom_debug)
    165  |     debug = custom_debug;
    166  |
    167  |   /* Check if we need to parse a file or stdin.
    168  |    * We parse stdin if source_file is "-" .
    169  |    */
    170  |
    171  |   if (strcmp(source_file,"-"))
    172  |     {
    173  |       if ((ifp = fopen(source_file,"r")) != NULL)
    174  |         {
    175  |           ER_dbg_va (FAC_MM, ASP_MM_GEN, "MM_store: input file %s",source_file);
    176  |           actualfile = ifp;
    177  |           using_file = 1;
    178  |         }
    179  |       else
    180  |         {
    181  |           /* XXX Use perror to state reason? */
    182  |           ER_perror(FAC_MM, MM_CANTOPEN, "%s for reading", source_file);
    183  |           die;
    184  |         }
    185  |     }
    186  |   else
    187  |     {
    188  |       ER_dbg_va (FAC_MM, ASP_MM_GEN, "MM_store: input from stdin");
    189  |       actualfile = stdin;
    190  |     }
    191  |
    192  |   if ((ofp = fopen(destination_file,"w")) != NULL)
    193  |     {
    194  |       while ((tmpstr = fgets(line, MAXBUFSIZE, actualfile)) != NULL)
    195  |         {
    196  |           numlines++;
    197  |           if (strlen(line) >= MAXBUFSIZE - 1)
    198  |             {
    199  |               ER_inf_va(FAC_MM, ASP_MM_SEC, "Line too long error. Possible buffer overflow attempt.");
    200  |               ER_perror(FAC_MM, MM_LINETOOLONG, "%ld",numlines);
    201  |               /* XXX Should be handled better - report line too long to caller,
    202  |                  so that a failed ack can be sent */
    203  |               die;
    204  |             }
    205  |           if (numlines == 1)
    206  |             {
    207  |               /* If the first line is not a "^From " line, put a fake one */
    208  |               if (!do_regex_test(REGEXP,(char *)line))
    209  |                   fprintf (ofp,"From dbase@whois.ripe.net %s",ctime (&ti));
    210  |               fputs (line,ofp);
    211  |               if (networkupdate) {
    212  |                   fprintf (ofp,"\n",ctime (&ti));
    213  |                   fputs (line,ofp);
    214  |               }
    215  |             }
    216  |           else
    217  |             {
    218  |               if (do_regex_test(REGEXP,(char *)line)) fprintf (ofp,">");
    219  |               fputs (line,ofp);
    220  |             }
    221  |         }
    222  |       fclose(ofp);
    223  |       if (using_file) fclose(ifp);
    224  |       return(0);
    225  |     }
    226  |   else
    227  |     {
    228  |       /* XXX Use perror to state reason? */
    229  |       ER_perror(FAC_MM, MM_CANTOPEN, "%s for writing", destination_file);
    230  |       die;
    231  |     }
    232  |
    233  |   /* Even though we should never get here... */
    234  |   return(0);
    235  |
    236  | } /* MM_store() */
    237  |
    238  |
    239  |
    240  | /**********
    241  |  *
    242  |  * MM_get_msg_headers(). Get the headers of a mail contained in a file.
    243  |  *
    244  |  **********/
    245  |
    246  | int MM_get_msg_headers(
    247  | 		   const char *mail_file,			/* Input mail file */
    248  | 		   EP_Mail_Descr *mail_descr,		/* Structure containing the headers */
    249  | 		   long mesgno,				/* msg number in the input file */
    250  | 		   long custom_debug			/* debug level */
    251  | 		   )
    252  | {
    253  |   MAILSTREAM *stream = NULL;		/* MAILSTREAM is defined in c-client */
    254  |   char tmp[MAILTMPLEN];			/* MAILTMPLEN is set in c-client */
    255  |   int retcode;			        /* return code of the subroutine */
    256  |   STRINGLIST *lines;			/* STRINGLIST is defined in c-client */
    257  |   STRINGLIST *cur;
    258  |   BODY *body;
    259  |
    260  | #include "linkage.c"		/* c-client requires it to be included... */
    261  |
    262  |
    263  |   /* If the supplied debug level is not null, then the global debug level
    264  |    * takes that value
    265  |    */
    266  |   if (custom_debug)
    267  |     debug = custom_debug;
    268  |
    269  |
    270  |   /* open mailbox and get the mail stream */
    271  |   sprintf (tmp, "%s", mail_file);
    272  |   stream = mail_open (stream,tmp,debug ? OP_DEBUG : NIL);
    273  |
    274  |   /* Process the stream */
    275  |   if (!stream)
    276  |     {
    277  |       ER_perror(FAC_MM, MM_INVMBX, "%s", mail_file);
    278  |       die;
    279  |     }
    280  |   else
    281  |     {
    282  |       ER_inf_va (FAC_MM, ASP_MM_GEN, "Getting message headers.");
    283  |       ER_dbg_va (FAC_MM, ASP_MM_GEN, "Message status:");
    284  |       status (stream);			/* report message status */
    285  |       ER_dbg_va (FAC_MM, ASP_MM_GEN, "End of message status.");
    286  |
    287  |       /* Get the headers */
    288  |
    289  |       lines = mail_newstringlist ();
    290  |       cur = lines;
    291  |
    292  |       /* Get information about the mentioned lines in the header */
    293  |
    294  |
    295  |       mail_descr->from = get_mail_hdr_field(stream, mesgno, cur, "From");
    296  |
    297  |       mail_descr->subject = get_mail_hdr_field(stream, mesgno, cur, "Subject");
    298  |
    299  |       mail_descr->date = get_mail_hdr_field(stream, mesgno, cur, "Date");
    300  |
    301  |       mail_descr->message_id = get_mail_hdr_field(stream, mesgno, cur, "Message-Id");
    302  |
    303  |       mail_descr->reply_to = get_mail_hdr_field(stream, mesgno, cur, "Reply-To");
    304  |
    305  |       mail_descr->cc = get_mail_hdr_field(stream, mesgno, cur, "Cc");
    306  |
    307  |
    308  |
    309  |       mail_descr->content_type = (Mail_Header_Field *)UT_malloc(sizeof(Mail_Header_Field));
    310  |       /* This gets all the line (with encoding etc.) */
    311  |       /* mail_descr->content_type = get_mail_hdr_field(stream,mesgno,cur,"Content-Type"); */
    312  |
    313  |       /* This only gets the content-type itself in canonized form: */
    314  |       mail_fetchstructure(stream,mesgno,&body);
    315  |       if (body)
    316  | 	{
    317  | 	  mail_descr->content_type->field = (char *)UT_malloc(STR_M);
    318  | 	  mail_descr->content_type->next = NULL;
    319  | 	  sprintf(mail_descr->content_type->field,"%s",body_types[body->type]);
    320  | 	  if (body->subtype)
    321  | 	    sprintf(mail_descr->content_type->field+strlen(mail_descr->content_type->field),"/%s",body->subtype);
    322  | 	  sprintf(mail_descr->content_type->field+strlen(mail_descr->content_type->field),"\n\n");
    323  | 	}
    324  |
    325  |       mail_free_stringlist (&lines);
    326  |
    327  |       ER_inf_va (FAC_MM, ASP_MM_GEN, "Got message headers.");
    328  |
    329  |
    330  |
    331  |       mail_close(stream);
    332  |
    333  |       retcode = 0;
    334  |
    335  |
    336  |     }
    337  |
    338  |
    339  |   return(retcode);
    340  |
    341  | } /* MM_get_msg_headers() */
    342  |
    343  |
    344  |
    345  | /*
    346  |  * MM_extract_mime(): extract MIME information
    347  |  * This function was inspired by display_body() in mtest.c,
    348  |  * in the IMAP distribution. It has been largely re-engineered
    349  |  * to support MIME, and be modular.
    350  |  * It now only acts as an initializer of the mail stream,
    351  |  * sending then the stream to be dispatched to the appropriate
    352  |  * MIME drivers.
    353  |  */
    354  |
    355  |
    356  |
    357  |
    358  | int MM_extract_mime (
    359  | 		     const char *sourcefile,			/* Input file containing the mail */
    360  | 		     char *pfx,				/* "prefix": this can be NULL at the
    361  | 							 * first call of the function */
    362  | 		     EP_mail_node *mailnode,		/* initialized node where to stock info */
    363  | 		     long custom_debug			/* debug level */
    364  | 		     )
    365  | {
    366  |
    367  |   MAILSTREAM *stream = NULL;		/* MAILSTREAM is defined in c-client */
    368  |   BODY *body;				/* BODY is defined in c-client */
    369  |   char tmp[MAILTMPLEN];			/* MAILTMPLEN is set in c-client */
    370  |   int retcode = 0;			/* return code of the subroutine */
    371  |   long mesgno = 1;
    372  |
    373  |
    374  | #include "linkage.c"		/* c-client requires it to be included... */
    375  |
    376  |   /*
    377  |    * This (global) variable counts the number of times we pass through
    378  |    * MM_extract_mime().
    379  |    * It is useful in generating unique temporary files (see below).
    380  |    */
    381  |
    382  |   pass++;
    383  |   ER_inf_va (FAC_MM, ASP_MM_GEN, "MM_extract_mime, pass %ld",pass);
    384  |
    385  |   if (custom_debug)
    386  |     debug = custom_debug;
    387  |
    388  |   /* ER_dbg_va (FAC_MM, ASP_MM_GEN, " EP_outputPrefix: %s",EP_outputPrefix);
    389  |      ER_dbg_va (FAC_MM, ASP_MM_GEN, " EP_keyRing: %s",EP_keyRing); */
    390  |
    391  |
    392  |   /* open file and get the mail stream from there*/
    393  |
    394  |   sprintf (tmp, "%s", sourcefile);
    395  |
    396  |   stream = mail_open (stream,tmp,debug ? OP_DEBUG : NIL);
    397  |
    398  |   /* Process the stream */
    399  |   if (!stream)
    400  |     {
    401  |       ER_perror(FAC_MM, MM_INVMBX, "%s", sourcefile);
    402  |       die;
    403  |     }
    404  |   else
    405  |     {
    406  |       if (debug >=2)
    407  | 	{
    408  | 	  ER_inf_va (FAC_MM, ASP_MM_GEN, "Getting message headers.");
    409  | 	  ER_dbg_va (FAC_MM, ASP_MM_GEN, "Message status:");
    410  | 	  status (stream);			/* report message status */
    411  | 	  ER_dbg_va (FAC_MM, ASP_MM_GEN, "End of message status.");
    412  | 	}
    413  |       if (debug >= 2)
    414  | 	ER_dbg_va (FAC_MM, ASP_MM_GEN, "Calling mail_fetchstructure...");
    415  |       mail_fetchstructure (stream,mesgno,&body);
    416  |
    417  |       if (body)
    418  | 	{
    419  | 	  ER_dbg_va (FAC_MM, ASP_MM_GEN, "Got body, dispatching to drivers...");
    420  | 	  dispatch_to_driver(stream, body, pfx, mailnode);
    421  | 	}
    422  |
    423  |     }
    424  |
    425  |   ER_dbg_va (FAC_MM, ASP_MM_GEN, "Closing the stream %s...",stream->mailbox);
    426  |   mail_close(stream);
    427  |   ER_dbg_va (FAC_MM, ASP_MM_GEN, "Stream Closed.");
    428  |
    429  |
    430  |   return(retcode);
    431  |
    432  | } /* MM_extract_mime() */
    433  |
    434  |
    435  |
    436  | /*********************************************/
    437  |
    438  | /***************************************
    439  |  *
    440  |  * End of API functions
    441  |  *
    442  |  ***************************************/
    443  |
    444  |
    445  |
    446  | /* Internal functions */
    447  |
    448  | t_MM_type is_supported_MIMEtype (BODY *body)
    449  | {
    450  |
    451  |   char *mimetype_string;
    452  |   char tmpstr[STR_S];
    453  |   char *tmptype = tmpstr;
    454  |   int i;
    455  |   t_MM_type mtypecode = 0;
    456  |
    457  |
    458  |   /* mimetype_string is the MIME type of the message */
    459  |   mimetype_string = (char *)UT_malloc(STR_S);
    460  |   sprintf (mimetype_string,"%s",body_types[body->type]);
    461  |   if (body->subtype)
    462  |     sprintf (mimetype_string + strlen(mimetype_string),"/%s",body->subtype);
    463  |
    464  |   /*
    465  |    * We cycle to compare the MIME type of the message
    466  |    * to each of the MIME types we support
    467  |    */
    468  |   i = 0;
    469  |   tmptype = supported_MIME_types[i];
    470  |
    471  |   while ((i < MAXSUPPTYPES) && (tmptype))
    472  |     {
    473  |       if (!strcmp(tmptype,mimetype_string))
    474  | 	{
    475  | 	  mtypecode = i;
    476  | 	  break;
    477  | 	}
    478  |       tmptype = supported_MIME_types[++i];
    479  |     }
    480  |
    481  |   UT_free(mimetype_string);
    482  |
    483  |   return(mtypecode);
    484  |
    485  | } /* is_supported_MIMEtype() */
    486  |
    487  |
    488  |
    489  | /****
    490  |  *
    491  |  * dispatch_to_driver()
    492  |  * This function dispatches a message to the proper driver
    493  |  * which will parse it, following the MIME type
    494  |  *
    495  |  ****/
    496  |
    497  | void dispatch_to_driver(MAILSTREAM *stream, BODY *body, char *pfx, EP_mail_node *mailnode)
    498  | {
    499  |
    500  |   t_MM_type is_supported;
    501  |
    502  |   is_supported = is_supported_MIMEtype(body);
    503  |   /* We assign the given MIME Type to the node */
    504  |   mailnode->MIMEContentType = is_supported;
    505  |
    506  |
    507  |   ER_dbg_va (FAC_MM, ASP_MM_GEN, " mailnode->MIMEContentType: %s",supported_MIME_types[mailnode->MIMEContentType]);
    508  |
    509  |   if (!strcmp(supported_MIME_types[is_supported],"TEXT/PLAIN"))
    510  |     {
    511  |       parse_text_plain(stream, body, pfx, mailnode);
    512  |     }
    513  |   else if (!strcmp(supported_MIME_types[is_supported],"APPLICATION/PGP"))
    514  |     {
    515  |       parse_application_pgp(stream, body, pfx, mailnode);
    516  |     }
    517  |   else if (!strcmp(supported_MIME_types[is_supported],"MULTIPART/ALTERNATIVE"))
    518  |     {
    519  |       parse_multipart_alternative(stream, body, pfx, mailnode);
    520  |     }
    521  |   else if (!strcmp(supported_MIME_types[is_supported],"MULTIPART/MIXED"))
    522  |     {
    523  |       parse_multipart_mixed(stream, body, pfx, mailnode);
    524  |     }
    525  |   else if (!strcmp(supported_MIME_types[is_supported],"MULTIPART/SIGNED"))
    526  |     {
    527  |       parse_multipart_signed(stream, body, pfx, mailnode);
    528  |     }
    529  |   else if (!strcmp(supported_MIME_types[is_supported],"MULTIPART/DIGEST"))
    530  |     {
    531  |       parse_multipart_digest(stream, body, pfx, mailnode);
    532  |     }
    533  |   else if (!strcmp(supported_MIME_types[is_supported],"MESSAGE/RFC822"))
    534  |     {
    535  |       parse_message_rfc822(stream, body, pfx, mailnode);
    536  |     }
    537  |   else
    538  |     {
    539  |       /* It's not a supported MIMEtype... */
    540  |       parse_unknown_unknown(stream, body, pfx, mailnode);
    541  |     }
    542  |
    543  | } /* dispatch_to_driver() */
    544  |
    545  |
    546  | void parse_text_plain(MAILSTREAM *stream, BODY *body, char *pfx, EP_mail_node *mailnode)
    547  | {
    548  |
    549  |   char tmp[MAILTMPLEN];
    550  |   char *mailtext;
    551  |
    552  |
    553  |   if (debug >= 2)
    554  |     ER_dbg_va (FAC_MM, ASP_MM_GEN, " Lines: %lu",body->size.lines);
    555  |
    556  |   if (pfx == NULL)			/* If top level, is not inside a multipart */
    557  |     {
    558  |       if (debug >= 2) ER_dbg_va (FAC_MM, ASP_MM_GEN, "MAILNODE->FILE: %s",mailnode->file);
    559  |       /* The filename of the root node has to be redefined to the processed file */
    560  |       /* remove(mailnode->file); */ /* This causes complaints by mail_close() */
    561  |       UT_free(mailnode->file);
    562  |       mailnode->file = (char *)UT_malloc(FILENAME_LENGTH);
    563  |       sprintf(mailnode->file,"%s%d",EP_outputPrefix,mailnode->nodeID);
    564  |       if (debug >= 2) ER_dbg_va (FAC_MM, ASP_MM_GEN, "MAILNODE->FILE: %s",mailnode->file);
    565  |     }
    566  |   else
    567  |
    568  |   ER_dbg_va (FAC_MM, ASP_MM_GEN, " mailnode->file: %s",mailnode->file);
    569  |
    570  |   /* Get the plain text contents of the message */
    571  |   mailtext = tmp;
    572  |   mailtext = mail_fetchtext(stream, 1);
    573  |
    574  |   if (debug >= 2)
    575  |     {
    576  |       ER_dbg_va (FAC_MM, ASP_MM_GEN, "Message contents:");
    577  |       ER_dbg_va (FAC_MM, ASP_MM_GEN, "\n\n%s\n",mailtext);
    578  |     }
    579  |
    580  |
    581  |   /* Place the results in the file pointed by the node*/
    582  |   write_file(mailnode->file,mailtext,strlen(mailtext));
    583  |
    584  |   PA_ParseMessage(mailnode);
    585  |
    586  |   /* if (debug) printf ("mailnode->nodeID: %d\n",mailnode->nodeID); */
    587  |   /* if (debug) printf ("mailnode->MIMEContentType: %d\n",mailnode->MIMEContentType); */
    588  |
    589  | }
    590  |
    591  | void parse_message_rfc822(MAILSTREAM *stream, BODY *body, char *pfx, EP_mail_node *mailnode)
    592  | {
    593  |
    594  |   /* The idea here is to strip the message/rfc822 part from its mail headers,
    595  |    * and store it in a file to resend to MM_extract_mime().
    596  |    */
    597  |
    598  |   char tmp[MAILTMPLEN];
    599  |   char *mailtext;
    600  |   char *content;
    601  |   char tmpfile[FILENAMELEN];
    602  |   time_t ti = time (0);
    603  |
    604  |
    605  |   if (pfx == NULL)			/* If top level, is not inside a multipart */
    606  |     {
    607  |       /* pfx = (char *)UT_malloc(STR_L);
    608  |       pfx = "";		*/	/* Dummy prefix */
    609  |       /* The filename of the root node has to be redefined to the processed file */
    610  |       mailnode->file = (char *)UT_malloc(FILENAME_LENGTH);
    611  |       sprintf(mailnode->file,"%s%d",EP_outputPrefix,mailnode->nodeID);
    612  |       if (debug >= 2) ER_dbg_va (FAC_MM, ASP_MM_GEN, "MAILNODE->FILE: %s",mailnode->file);
    613  |     }
    614  |
    615  |   /* Get the plain text contents of the message */
    616  |   mailtext = tmp;
    617  |   mailtext = mail_fetchtext(stream, 1);
    618  |
    619  |
    620  |   /* This buffer has to be dumped in a file from where it will be read by MM_extract_mime():
    621  |    * another stream will be opened, so the format of the file must be correct.
    622  |    * The LINELENGTH is to take the first 2 lines into account.
    623  |    */
    624  |
    625  |   content = (char *)UT_malloc(2*LINELENGTH + strlen(mailtext) + 2);
    626  |   sprintf (content,"From dbase@whois.ripe.net %s",ctime (&ti));
    627  |   sprintf (content+strlen(content), "%s\n", mailtext);
    628  |
    629  |
    630  |   /* Generation of a temporary file:
    631  |    * The file must be unique inside the process. If we rewrite
    632  |    * on the same tmp file, which is used as a mailbox by c-client,
    633  |    * the c-client library has problems because it sees the mailbox changes
    634  |    * (I had problems with multipart/digest and message/rfc822).
    635  |    * "pass" is a global variable which increases every time we pass
    636  |    * through MM_extract_mime(): it should hence be unique each time
    637  |    * we call a driver.
    638  |    */
    639  |   sprintf (tmpfile,"%s.tmp.%ld",mailnode->file,pass);
    640  |   write_file(tmpfile,content,strlen(content));
    641  |
    642  |   MM_extract_mime(tmpfile, pfx, mailnode, debug);
    643  |
    644  |   /* Clean up... */
    645  |   UT_free(content);
    646  |   remove(tmpfile);
    647  |
    648  | }
    649  |
    650  | void parse_multipart_alternative (MAILSTREAM *stream, BODY *body, char *pfx, EP_mail_node *mailnode)
    651  | {
    652  |
    653  |   char tmppfx[MAILTMPLEN];
    654  |   char childpfx[MAILTMPLEN];
    655  |   char tmppart[MAILTMPLEN];
    656  |   /*   char *s = tmppfx; */
    657  |   EP_mail_node *newnode;
    658  |   EP_mail_node *parsednode;
    659  |   EP_mail_node *nextnode;
    660  |   long i;
    661  |   PART *part;
    662  |   char *result;
    663  |   char *content;
    664  |   unsigned long length;
    665  |   time_t ti = time (0);
    666  |   char tmpfile[FILENAMELEN];
    667  |   char nodefile[FILENAMELEN];
    668  |
    669  |
    670  |   if (debug >= 2)
    671  |     ER_dbg_va (FAC_MM, ASP_MM_GEN, "Bytes: %lu",body->size.bytes);
    672  |
    673  |   /* if not first time, extend prefix */
    674  |   if (pfx == NULL)
    675  |     {
    676  |       tmppfx[0] = '\0';
    677  |       pfx = tmppfx;
    678  |     }
    679  |
    680  |
    681  |   /* Initialize the first node: it is an inner node */
    682  |
    683  |   /* The tree height increases */
    684  |   EP_TreeHeight++;
    685  |
    686  |   /* The number of nodes increases */
    687  |   EP_Node_ID++;
    688  |
    689  |   sprintf (nodefile,"%s%d",EP_outputPrefix,EP_Node_ID);
    690  |   if (debug >= 2) ER_dbg_va (FAC_MM, ASP_MM_GEN, "inner-nodefile: %s",nodefile);
    691  |
    692  |   newnode = EP_InitializeNode(nodefile, EP_Node_ID);
    693  |   mailnode->inner = newnode;
    694  |
    695  |   for (i = 1,part = body->nested.part; part; part = part->next)
    696  |     {
    697  |       if (debug >= 2) ER_dbg_va (FAC_MM, ASP_MM_GEN, "i: %ld, pfx: %s",i,pfx);
    698  |       if (debug >= 3) ER_dbg_va (FAC_MM, ASP_MM_GEN, "MYDEBUG: pfx=%s, tmppfx=%s,",pfx,tmppfx);
    699  |       sprintf (tmppart,"%ld",i);
    700  |       result = mail_fetch_mime(stream, (long)1, tmppart, &length, (long)0);
    701  |       if (debug >= 3)
    702  | 	{
    703  | 	  ER_dbg_va (FAC_MM, ASP_MM_GEN, "body->size.bytes: %lu",body->size.bytes);
    704  | 	  ER_dbg_va (FAC_MM, ASP_MM_GEN, "(&part->body)->size.bytes: %lu",(&part->body)->size.bytes);
    705  | 	  ER_dbg_va (FAC_MM, ASP_MM_GEN, "length: %lu",length);
    706  | 	}
    707  |
    708  |
    709  |       /* This buffer has to be dumped in a file from where it will be read by MM_extract_mime():
    710  |        * another stream will be opened, so the format of the file must be correct.
    711  |        * The LINELENGTH is to take the first 2 lines into account
    712  |        */
    713  |       content = (char *)UT_malloc(2*LINELENGTH + length + (&part->body)->size.bytes + 2);
    714  |       sprintf (content,"From dbase@whois.ripe.net %sMIME-Version: 1.0\n",ctime (&ti));
    715  |       /* snprintf (content+strlen(content), (size_t)(length + (&part->body)->size.bytes) + 2, "%s\n", result); */
    716  |       g_snprintf ((gchar *)(content+strlen(content)), (gulong)(length + (&part->body)->size.bytes) + 2, "%s\n", result);
    717  |
    718  |       if (debug >= 2) ER_dbg_va (FAC_MM, ASP_MM_GEN, "Result: \n---\n%s\n---\nEnd results.\n", content);
    719  |
    720  |       /* Generation of a temporary file:
    721  |        * The file must be unique inside the process. If we rewrite
    722  |        * on the same tmp file, which is used as a mailbox by c-client,
    723  |        * the c-client library has problems because it sees it changes
    724  |        * (I had problems with multipart/digest and message/rfc822).
    725  |        * "pass" is a global variable which increases every time we pass
    726  |        * through MM_extract_mime(): it should hence be unique each time
    727  |        * we call a driver.
    728  |        */
    729  |       sprintf (tmpfile,"%s.tmp.%ld",newnode->file,pass);
    730  |       write_file(tmpfile,content,strlen(content));
    731  |
    732  |       /* This is needed to extend the prefix */
    733  |       sprintf (childpfx,"%s%ld.",pfx,i);
    734  |       if (debug >= 2) ER_dbg_va (FAC_MM, ASP_MM_GEN, "childpfx: %s",childpfx);
    735  |       MM_extract_mime(tmpfile, childpfx, newnode, debug);
    736  |
    737  |       /* Clean up... */
    738  |       UT_free(content);
    739  |       remove(tmpfile);
    740  |
    741  |       /* Initialize the next node (if it exists) */
    742  |
    743  |       if (part->next != NULL)
    744  | 	{
    745  | 	  EP_Node_ID++;
    746  | 	  sprintf (nodefile,"%s%d",EP_outputPrefix,EP_Node_ID);
    747  | 	  if (debug >= 2) ER_dbg_va (FAC_MM, ASP_MM_GEN, "next-nodefile: %s",nodefile);
    748  | 	  nextnode = EP_InitializeNode(nodefile, EP_Node_ID);
    749  | 	  parsednode = newnode;
    750  | 	  newnode = nextnode;
    751  | 	  parsednode->next = newnode;
    752  | 	}
    753  |
    754  |       i++;
    755  |
    756  |     }
    757  |
    758  | } /* parse_multipart_alternative() */
    759  |
    760  |
    761  | void parse_multipart_signed (MAILSTREAM *stream, BODY *body, char *pfx, EP_mail_node *mailnode)
    762  | {
    763  |
    764  |   char tmppfx[MAILTMPLEN];
    765  |   char tmppart[MAILTMPLEN];
    766  |   EP_mail_node *newnode;
    767  |   PART *part;
    768  |   char *result;
    769  |   char *content;
    770  |   unsigned long length;
    771  |   char tmpfile[FILENAMELEN];
    772  |   char nodefile[FILENAMELEN];
    773  |   struct VerifySignObject vSO;
    774  |   /*  int retcode; */
    775  |
    776  |   if (debug >= 2)
    777  |     ER_dbg_va (FAC_MM, ASP_MM_GEN, "Bytes: %lu",body->size.bytes);
    778  |
    779  |
    780  |   /* if not first time, extend prefix */
    781  |   if (pfx == NULL)
    782  |     {
    783  |       tmppfx[0] = '\0';
    784  |       pfx = tmppfx;
    785  |     }
    786  |
    787  |
    788  |   /* Initialize the inner node */
    789  |
    790  |   /* The tree height increases */
    791  |   EP_TreeHeight++;
    792  |
    793  |   /* The number of nodes increases */
    794  |   EP_Node_ID++;
    795  |
    796  |   sprintf (nodefile,"%s%d",EP_outputPrefix,EP_Node_ID);
    797  |   if (debug >= 2) ER_dbg_va (FAC_MM, ASP_MM_GEN, "inner-nodefile: %s",nodefile);
    798  |
    799  |   newnode = EP_InitializeNode(nodefile, EP_Node_ID);
    800  |   mailnode->inner = newnode;
    801  |
    802  |   /* We give the same content-type to the child so as not to leave the default
    803  |      value (-1) */
    804  |   newnode->MIMEContentType = mailnode->MIMEContentType;
    805  |
    806  |   /* We must get the two parts of the message. The signed part
    807  |    * and the signature. There can't be more than two parts
    808  |    * (see RFC2015).
    809  |    */
    810  |
    811  |   if (debug >= 2) ER_dbg_va (FAC_MM, ASP_MM_GEN, "pfx: %s",pfx);
    812  |
    813  |   /* Signed part: it is the first part of the message. */
    814  |
    815  |   part = body->nested.part;
    816  |
    817  |   sprintf (tmppart,"%s1",tmppfx);
    818  |   if (debug >= 2) ER_dbg_va (FAC_MM, ASP_MM_GEN, "tmppart: %s",tmppart);
    819  |
    820  |   result = mail_fetch_mime(stream, (long)1, tmppart, &length, (long)0);
    821  |   if (debug >= 3)
    822  |     {
    823  |       ER_dbg_va (FAC_MM, ASP_MM_GEN, "body->size.bytes: %lu",body->size.bytes);
    824  |       ER_dbg_va (FAC_MM, ASP_MM_GEN, "(&part->body)->size.bytes: %lu",(&part->body)->size.bytes);
    825  |       ER_dbg_va (FAC_MM, ASP_MM_GEN, "length: %lu",length);
    826  |     }
    827  |
    828  |   /* The signed part must be dumped in a file together with the MIME headers */
    829  |
    830  |   content = (char *)UT_malloc(length + (&part->body)->size.bytes + 2);
    831  |   snprintf (content,(size_t)(length + (&part->body)->size.bytes) + 2, "%s\n", result);
    832  |
    833  |   if (debug >= 2) ER_dbg_va (FAC_MM, ASP_MM_GEN, "Result: \n---\n%s\n---\nEnd results.\n", content);
    834  |
    835  |   if (debug) ER_dbg_va (FAC_MM, ASP_MM_GEN, "MSG file: %s",newnode->file);
    836  |   write_file(newnode->file,content,strlen(content));
    837  |
    838  |
    839  |   UT_free(content);
    840  |
    841  |   /* Signature */
    842  |
    843  |   part = part->next;
    844  |   sprintf (tmppart,"%s2",tmppfx);
    845  |   if (debug >= 2) ER_dbg_va (FAC_MM, ASP_MM_GEN, "tmppart: %s",tmppart);
    846  |
    847  |   result = mail_fetch_mime(stream, (long)1, tmppart, &length, (long)0);
    848  |   if (debug >= 2)
    849  |     {
    850  |       ER_dbg_va (FAC_MM, ASP_MM_GEN, "body->size.bytes: %lu\n",body->size.bytes);
    851  |       ER_dbg_va (FAC_MM, ASP_MM_GEN, "(&part->body)->size.bytes: %lu\n",(&part->body)->size.bytes);
    852  |       ER_dbg_va (FAC_MM, ASP_MM_GEN, "length: %lu\n",length);
    853  |     }
    854  |
    855  |   /* The signature must be dumped _without_ MIME headers instead!
    856  |    * Check where is the "length" variable...
    857  |    */
    858  |
    859  |   content = (char *)UT_malloc((&part->body)->size.bytes + 2);
    860  |
    861  |   snprintf (content,(size_t)((&part->body)->size.bytes) + 2, "%s\n", result + length);
    862  |
    863  |   if (debug >= 2) ER_dbg_va (FAC_MM, ASP_MM_GEN, "Result: \n---\n%s\n---\nEnd results.\n", content);
    864  |
    865  |   sprintf (tmpfile,"%s.sig",newnode->file);
    866  |   if (debug) ER_dbg_va (FAC_MM, ASP_MM_GEN, "SIG file: %s",tmpfile);
    867  |   write_file(tmpfile,content,strlen(content));
    868  |
    869  |   /* Calling the verification procedure */
    870  |
    871  |   strcpy(vSO.iDocSigFilename, newnode->file);
    872  |   strcpy(vSO.iSigFilename, tmpfile);
    873  |   //strcpy(vSO.keyRing, EP_keyRing);
    874  |
    875  |   PA_VerifySignature(&vSO);
    876  |
    877  |   newnode->isValidPGPSignature = vSO.isValid;
    878  |   newnode->keyID= vSO.keyID;
    879  |
    880  |   EP_MIMEParse(newnode);
    881  |
    882  |   UT_free(content);
    883  |   remove(tmpfile);
    884  |
    885  |
    886  | } /* parse_multipart_signed */
    887  |
    888  |
    889  |
    890  | /* MM status report
    891  |  * Accepts: MAIL stream
    892  |  */
    893  |
    894  | void status (MAILSTREAM *stream)
    895  | {
    896  |   long i;
    897  |   char date[MAILTMPLEN];
    898  |   rfc822_date (date);
    899  |   ER_dbg_va (FAC_MM, ASP_MM_GEN, "%s",date);
    900  |   if (stream)
    901  |     {
    902  |       if (stream->mailbox)
    903  | 	{
    904  | 	  ER_dbg_va (FAC_MM, ASP_MM_GEN, " %s mailbox: %s",
    905  | 		     stream->dtb->name,stream->mailbox);
    906  | 	  ER_dbg_va (FAC_MM, ASP_MM_GEN, " %lu messages, %lu recent",
    907  | 		     stream->nmsgs,stream->recent);
    908  | 	}
    909  |       else  ER_dbg_va (FAC_MM, ASP_MM_GEN, "% No mailbox is open on this stream");
    910  |       if (stream->user_flags[0])
    911  | 	{
    912  | 	   ER_dbg_va (FAC_MM, ASP_MM_GEN, "Keywords: %s",stream->user_flags[0]);
    913  | 	  for (i = 1; i < NUSERFLAGS && stream->user_flags[i]; ++i)
    914  | 	   ER_dbg_va (FAC_MM, ASP_MM_GEN,", %s",stream->user_flags[i]);
    915  | 	  /* puts (""); */
    916  | 	}
    917  |     }
    918  | } /* status() */
    919  |
    920  |
    921  | Mail_Header_Field *get_mail_hdr_field (MAILSTREAM *stream,
    922  | 				       long mesgno,
    923  | 				       STRINGLIST *cur,
    924  | 				       const char *hdr_title)
    925  | {
    926  |
    927  |   char *tmphdr;
    928  |   char tmpline[MAXBUFSIZE];
    929  |   int i, j, k, c, tmpsize, titlesize;
    930  |   int continuation = 0;
    931  |   Mail_Header_Field *hdr_field;
    932  |   Mail_Header_Field *mhfp;
    933  |   Mail_Header_Field *newmhfp;
    934  |
    935  |   mhfp = hdr_field = newmhfp = NULL;
    936  |
    937  |   tmphdr = get_header_line(stream,mesgno,cur,hdr_title);
    938  |
    939  |   tmpsize = strlen(tmphdr);
    940  |
    941  |   /* Length of the header title plus ":" */
    942  |   titlesize = strlen(hdr_title) + 1;
    943  |
    944  |   continuation = 0;   /* to detect continuation lines */
    945  |   j = 0;
    946  |   /* also initialize tmpline */
    947  |   for(i = 0; i < MAXBUFSIZE; i++){
    948  |     tmpline[i] = '\0';
    949  |   }
    950  |
    951  |   /* Get one line at a time, and put the header lines in the Mail Header Field */
    952  |
    953  |   for (i = 0; i < tmpsize; i++)
    954  |     {
    955  |       c = tmphdr[i];
    956  |       if (c == 10) /* EOL */
    957  | 	  {
    958  | 	    if ((j > 1) || ((mhfp == NULL) && (i == tmpsize - 1))) /* j>1 and not j>0 because "\r" is always read;
    959  | 								    * The second option is needed for
    960  | 								    * the empty headers */
    961  | 	    {
    962  | 	        newmhfp = (Mail_Header_Field *)UT_malloc(sizeof(Mail_Header_Field));
    963  | 	        newmhfp->next = NULL;
    964  | 	        newmhfp->field = (char *)UT_malloc(j + 2);
    965  | 	        if (j > 1)
    966  |             {
    967  |               if ( ! continuation )
    968  | 		        /* We do not copy the header title from the first line */
    969  | 		        sprintf (newmhfp->field,"%s\n",tmpline + titlesize);
    970  |               else
    971  | 		        /* There is no header title on continuation lines */
    972  | 		        sprintf (newmhfp->field,"%s\n",tmpline);
    973  |             }
    974  | 	        else
    975  | 		      sprintf (newmhfp->field,"\n");
    976  |
    977  | 	        if (mhfp == NULL)
    978  | 		    {
    979  | 		      mhfp = newmhfp;
    980  | 		      hdr_field = newmhfp;
    981  | 		    }
    982  | 	        else
    983  | 		    {
    984  | 		      mhfp->next = newmhfp;
    985  | 		      mhfp = newmhfp;
    986  | 		    }
    987  | 	    }
    988  |         continuation = 1;   /* next time we are reading continuation lines */
    989  | 	    j = 0;
    990  |         /* re-initialize tmpline */
    991  |         for (k = 0; k < MAXBUFSIZE; k++)
    992  |         {
    993  |           tmpline[k] = '\0';
    994  |         }
    995  | 	  }
    996  |       else
    997  | 	  {
    998  | 	    sprintf (tmpline + j++,"%c", c);
    999  | 	  }
    1000 |     }
    1001 |
    1002 |   UT_free(tmphdr);
    1003 |
    1004 |   return (hdr_field);
    1005 |
    1006 | } /* get_mail_hdr_field() */
    1007 |
    1008 |
    1009 |
    1010 | char *get_header_line (MAILSTREAM *stream, long mesgno, STRINGLIST *cur, const char *hdr_title)
    1011 | {
    1012 |
    1013 |   unsigned long offset;
    1014 |   size_t tmplength;
    1015 |   char *curtmp;
    1016 |   char *hdr_attr;
    1017 |   long a,b;
    1018 |
    1019 |
    1020 |   /* We need to insert the header title into a STRINGLIST structure, as
    1021 |    * this is the type that must be supplied to mail_fetchheader_full.
    1022 |    */
    1023 |
    1024 |   cur->text.size = strlen ((char *) (cur->text.data = (unsigned char *)
    1025 | 				     cpystr (hdr_title)));
    1026 |
    1027 |   /* If we don't want to return the header title, but only the contents,
    1028 |    * this offset allows us to strip the header title. The "magic number" 2
    1029 |    * is the string ": " of the header.
    1030 |    * This method is uneffective for multiple headers (ex. Cc, Reply-To, etc.).
    1031 |    */
    1032 |
    1033 |   offset = cur->text.size + 2;
    1034 |
    1035 |   /* Get the header line, if it exists */
    1036 |
    1037 |   curtmp = mail_fetchheader_full (stream,mesgno,cur,NIL,NIL);
    1038 |
    1039 |   tmplength = strlen(curtmp);
    1040 |   hdr_attr = (char *)UT_malloc(tmplength + 4);
    1041 |
    1042 |   /* cur contains the header title string, like "From:", "Subject:" etc.
    1043 |    * tmplength is the length of the corresponding header line extracted
    1044 |    * from the message. If a real line is returned, the header title
    1045 |    * ("From:", "Subject:" etc.) will be contained within, hence
    1046 |    * tmplength >= cur->text.size . This means that if
    1047 |    * (cur->text.size > tmplength), no such header is present in the mail:
    1048 |    * we must return an (almost) empty string.
    1049 |    */
    1050 |
    1051 |   a = (long)tmplength;
    1052 |   b = (long)cur->text.size;
    1053 |   if (a > b)
    1054 |     {
    1055 |       /* If we want to strip the header */
    1056 |       /*sprintf (hdr_attr,"%s",curtmp + offset); */
    1057 |       sprintf (hdr_attr,"%s",curtmp);
    1058 |       /* printf ("%s",hdr_attr); */
    1059 |     }
    1060 |   else
    1061 |     {
    1062 |       sprintf (hdr_attr,"\n\n");
    1063 |     }
    1064 |
    1065 |   return (hdr_attr);
    1066 | } /* get_header_line() */
    1067 |
    1068 |
    1069 |
    1070 |
    1071 | /* Subroutine for writing in a file */
    1072 |
    1073 | void write_file (char *filename, char *text, size_t text_size)
    1074 | {
    1075 |
    1076 |   FILE *fd;
    1077 |   size_t i;
    1078 |
    1079 |   /* printf ("%s\n",filename); */
    1080 |
    1081 |   if ((fd = fopen(filename,"w")) != NULL)
    1082 |     {
    1083 |       for (i = 0; i < text_size; i++)
    1084 | 	if (text[i] != 13)
    1085 | 	  fprintf (fd, "%c",text[i]);
    1086 |       fclose(fd);
    1087 |     }
    1088 |   else
    1089 |     {
    1090 |       ER_perror(FAC_MM, MM_CANTOPEN, "%s for writing\n",filename);
    1091 |       die;
    1092 |     }
    1093 |
    1094 | } /* write_file() */
    1095 |
    1096 |
    1097 | void read_file (const char *filename)
    1098 | {
    1099 |
    1100 |   FILE *fd;
    1101 |   int c;
    1102 |
    1103 |   if ((fd = fopen (filename,"r")) != NULL)
    1104 |     {
    1105 |       while ((c = getc(fd)) != EOF)
    1106 | 	putc (c, stdout);
    1107 |       fclose (fd);
    1108 |     }
    1109 |   else
    1110 |     {
    1111 |       ER_perror(FAC_MM, MM_CANTOPEN, "%s for reading\n",filename);
    1112 |       die;
    1113 |     }
    1114 |
    1115 | } /* read_file() */
    1116 |
    1117 |
    1118 | void put_in_file (char *fileprefix, char *extension, char *text, size_t text_size)
    1119 | {
    1120 |
    1121 |   char filename[FILENAMELEN];
    1122 |
    1123 |
    1124 |   /* Write in a file */
    1125 |
    1126 |   sprintf (filename,"%s-%s",fileprefix,extension);
    1127 |   /* printf ("%s\n",filename); */
    1128 |
    1129 |   write_file(filename,text,text_size);
    1130 |
    1131 | }/* put_in_file() */
    1132 |
    1133 |
    1134 | /* Stolen from which_keytypes.c and converted to use regex.h instead of libgen.h */
    1135 |
    1136 |
    1137 | int do_regex_test (const char *pattern, char *string)
    1138 | {
    1139 |
    1140 |   int match = 0;
    1141 |
    1142 |   /* These are not used, since REG_NOSUB is specified in regcomp() */
    1143 |   size_t nmatch = 0;
    1144 |   regmatch_t pmatch[1];
    1145 |
    1146 |   regex_t *re;
    1147 |
    1148 |   re = (regex_t *)UT_malloc(STR_XL);
    1149 |
    1150 |   regcomp(re, pattern, REG_NOSUB || REG_NEWLINE);
    1151 |   if (regexec(re, string, nmatch, pmatch, 0))
    1152 |     match = 0;
    1153 |   else
    1154 |     match = 1;
    1155 |
    1156 |   regfree(re);
    1157 |
    1158 |   /* Caution! regfree() does not do this job... */
    1159 |   UT_free(re);
    1160 |
    1161 |   return(match);
    1162 |
    1163 | } /* do_regex_test() */
    1164 |
    1165 |
    1166 | /* Interfaces to c-client.
    1167 |  * They must be here for the code to be compiled,
    1168 |  * but most can stay empty.
    1169 |  */
    1170 |
    1171 | void mm_searched (MAILSTREAM *stream,unsigned long number)
    1172 | {
    1173 | }
    1174 |
    1175 |
    1176 | void mm_exists (MAILSTREAM *stream,unsigned long number)
    1177 | {
    1178 | }
    1179 |
    1180 |
    1181 | void mm_expunged (MAILSTREAM *stream,unsigned long number)
    1182 | {
    1183 | }
    1184 |
    1185 |
    1186 | void mm_flags (MAILSTREAM *stream,unsigned long number)
    1187 | {
    1188 | }
    1189 |
    1190 | void mm_notify (MAILSTREAM *stream,char *string,long errflg)
    1191 | {
    1192 | }
    1193 |
    1194 | void mm_list (MAILSTREAM *stream,int delimiter,char *mailbox,long attributes)
    1195 | {
    1196 | }
    1197 |
    1198 | void mm_lsub (MAILSTREAM *stream,int delimiter,char *mailbox,long attributes)
    1199 | {
    1200 | }
    1201 |
    1202 | void mm_status (MAILSTREAM *stream,char *mailbox,MAILSTATUS *status)
    1203 | {
    1204 | }
    1205 |
    1206 | void mm_log (char *string,long errflg)
    1207 | {
    1208 |   switch ((short) errflg) {
    1209 |   case NIL:
    1210 |     ER_dbg_va (FAC_MM, ASP_MM_GEN, "[%s]",string);
    1211 |     break;
    1212 |   case PARSE:
    1213 |   case WARN:
    1214 |     ER_perror (FAC_MM, MM_WARNCCL, "%%%s",string);
    1215 |     break;
    1216 |   case ERROR:
    1217 |     ER_perror (FAC_MM, MM_ERRCCL, "%s",string);
    1218 |     break;
    1219 |   }
    1220 | }
    1221 |
    1222 | void mm_dlog (char *string)
    1223 | {
    1224 |   puts (string);
    1225 | }
    1226 |
    1227 | void mm_login (NETMBX *mb,char *user,char *pwd,long trial)
    1228 | {
    1229 | }
    1230 |
    1231 | void mm_critical (MAILSTREAM *stream)
    1232 | {
    1233 | }
    1234 |
    1235 | void mm_nocritical (MAILSTREAM *stream)
    1236 | {
    1237 | }
    1238 |
    1239 | long mm_diskerror (MAILSTREAM *stream,long errcode,long serious)
    1240 | {
    1241 | #if UNIXLIKE
    1242 |   kill (getpid (),SIGSTOP);
    1243 | #else
    1244 |   abort ();
    1245 | #endif
    1246 |   return NIL;
    1247 | }
    1248 |
    1249 | void mm_fatal (char *string)
    1250 | {
    1251 |   ER_perror(FAC_MM, MM_FATCCL, "%s\n",string);
    1252 |   die;
    1253 | }
    1254 |