Source File mm/mm.c

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