home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / elm / elm2.4 / lib / realfrom.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-08  |  5.8 KB  |  211 lines

  1.  
  2. static char rcsid[] = "@(#)$Id: realfrom.c,v 5.3 1993/05/08 17:09:56 syd Exp $";
  3.  
  4. /*******************************************************************************
  5.  *  The Elm Mail System  -  $Revision: 5.3 $   $State: Exp $
  6.  *
  7.  *             Copyright (c) 1993 USENET Community Trust
  8.  *******************************************************************************
  9.  * Bug reports, patches, comments, suggestions should be sent to:
  10.  *
  11.  *    Syd Weinstein, Elm Coordinator
  12.  *    elm@DSI.COM            dsinc!elm
  13.  *
  14.  *******************************************************************************
  15.  * $Log: realfrom.c,v $
  16.  * Revision 5.3  1993/05/08  17:09:56  syd
  17.  * Fix problem where "<space>From" was recognized as a valid "From_" line.
  18.  * From: decwrl!decvax!gatech!WLK.COM!chip (Chip Rosenthal)
  19.  *
  20.  * Revision 5.2  1993/04/12  01:24:59  syd
  21.  * Have real_from() ignore bogus timezones in From_ lines
  22.  * rather than bailing out with an error.
  23.  * From: chip@chinacat.unicom.com (Chip Rosenthal)
  24.  *
  25.  * Revision 5.1  1993/01/19  04:46:21  syd
  26.  * Initial Checkin
  27.  *
  28.  *
  29.  ******************************************************************************/
  30.  
  31.  
  32. #include "headers.h"
  33. #include <ctype.h>
  34.  
  35. #ifdef BSD
  36. #undef tolower
  37. #endif
  38.  
  39.  
  40. extern long make_gmttime();
  41.  
  42.  
  43. int
  44. real_from(buffer, entry)
  45. char *buffer;
  46. struct header_rec *entry;
  47. {
  48.  
  49.     /*
  50.      * Breakup and validate the "From_" line in the "buffer".  If "entry"
  51.      * is not NULL then the structure is filled in with sender and time
  52.      * information.  Returns TRUE if the "From_" line is valid, otherwise
  53.      * FALSE.
  54.      *
  55.      * A valid from line will be in the following format:
  56.      *
  57.      *    From <user> <weekday> <month> <day> <hr:min:sec>
  58.      *        [TZ1 [TZ2]] <year> [remote from sitelist]
  59.      *
  60.      * We insist that all of the <angle bracket> fields are present.
  61.      * If two timezone fields are present, the first is used for date
  62.      * information.  We do not look at anything beyond the <year> field.
  63.      * We just insist that everything up to the <year> field is present
  64.      * and valid.
  65.      */
  66.  
  67.     char field[STRING];        /* buffer for current field of line    */
  68.     char save_tz[STRING];    /* extracted time zone field        */
  69.     int len;            /* length of current field        */
  70.     int month, day, year, hours, mins, secs, tz, i;
  71.  
  72.     /*
  73.      * Zero out the portions of the record we fill in.
  74.      */
  75.     if (entry != NULL) {
  76.     entry->time_zone[0] = '\0';
  77.     entry->from[0] = '\0';
  78.     entry->time_sent = 0;
  79.     entry->received_time = 0;
  80.     entry->tz_offset = 0;
  81.     }
  82.  
  83.     /* From */
  84.     if (strncmp(buffer, "From ", 5) != 0)
  85.     goto failed;
  86.     buffer += 5;
  87.     dprint(7, (debugfile, "real_from parsing %s", buffer));
  88.  
  89.     /* <user> */
  90.     if ((len = get_word(buffer, 0, field, sizeof(field))) < 0)
  91.     goto failed;
  92.     buffer += len;
  93.     if (entry != NULL)
  94.     strfcpy(entry->from, field, sizeof(entry->from));
  95.     dprint(7, (debugfile, "  user=%s\n", field));
  96.  
  97.     /* <weekday> */
  98.     if ((len = get_word(buffer, 0, field, sizeof(field))) < 0)
  99.     goto failed;
  100.     buffer += len;
  101.  
  102.     /* <month> */
  103.     if ((len = get_word(buffer, 0, field, sizeof(field))) < 0 ||
  104.         !cvt_monthname_to_monthnum(field, &month))
  105.     goto failed;
  106.     buffer += len;
  107.  
  108.     /* <day> */
  109.     if ((len = get_word(buffer, 0, field, sizeof(field))) < 0 ||
  110.         (day = atonum(field)) < 0 || day < 1 || day > 31)
  111.     goto failed;
  112.     buffer += len;
  113.  
  114.     /* <hr:min:sec> */
  115.     if ((len = get_word(buffer, 0, field, sizeof(field))) < 0 ||
  116.         !cvt_timestr_to_hhmmss(field, &hours, &mins, &secs))
  117.     goto failed;
  118.     buffer += len;
  119.     dprint(7, (debugfile, "  hours=%d mins=%d secs=%d\n", hours, mins, secs));
  120.  
  121.     /*
  122.      * [ <tz> ... ] <year>
  123.      *
  124.      * This is messy.  Not only is the timezone field optional, there
  125.      * might be multiple fields (e.g. "MET DST"), or it might be entirely
  126.      * bogus (e.g. some MTAs produce "0600" instead of "+0600".
  127.      */
  128.     tz = 0;
  129.     save_tz[0] = save_tz[1] = '\0';
  130.     for (;;) {
  131.  
  132.     if ((len = get_word(buffer, 0, field, sizeof(field))) < 0)
  133.         goto failed;
  134.     buffer += len;
  135.  
  136.     /*
  137.      * First check if this is a TZ field.  If so, pull in the info
  138.      * and continue onto the next field.
  139.      */
  140.     if (cvt_timezone_to_offset(field, &i)) {
  141.         tz += i;
  142.         i = strlen(save_tz);
  143.         (void) strfcpy(save_tz+i, " ", sizeof(save_tz)-i);
  144.         ++i;
  145.         (void) strfcpy(save_tz+i, field, sizeof(save_tz)-i);
  146.         continue;
  147.     }
  148.  
  149.     /*
  150.      * If this isn't a valid TZ then it should be a year.  If so
  151.      * then save off the year info and break out of this loop.
  152.      */
  153.     if (cvt_yearstr_to_yearnum(field, &year))
  154.         break;
  155.  
  156.     /*
  157.      * This isn't either a valid TZ or year.  Assume it is a bogus
  158.      * timezone we don't understand, and continue processing the line.
  159.      */
  160.     dprint(7, (debugfile,
  161.         "  assuming \"%s\" is a bogus timezone - skipping it\n", field));
  162.  
  163.     }
  164.     if (entry != NULL) {
  165.     entry->tz_offset = tz * 60;
  166.     (void) strfcpy(entry->time_zone, save_tz+1, sizeof(entry->time_zone));
  167.     entry->received_time = entry->time_sent =
  168.         make_gmttime(year, month, day, hours, mins-tz, secs);
  169.     }
  170.     dprint(7, (debugfile, "  tz=%s tz_offset=%d\n", save_tz+1, tz));
  171.     dprint(7, (debugfile, "  month=%d day=%d year=%d\n", month, day, year));
  172.  
  173.     /*
  174.      * The line is parsed and valid.  There might be more but we don't care.
  175.      */
  176.     dprint(7, (debugfile, "  return success\n"));
  177.     return TRUE;
  178.  
  179. failed:
  180.     dprint(4, (debugfile, "real_from failed at \"%s\"\n", 
  181.     (len <= 0 ? "<premature eol>" : field)));
  182.     return FALSE;
  183. }
  184.  
  185.  
  186. #ifdef _TEST
  187. int debug = 9999;
  188. FILE *debugfile = stdout;
  189. main()
  190. {
  191.     struct header_rec hdr;
  192.     char buf[1024];
  193.     extern char *ctime();
  194.  
  195.     while (gets(buf) != NULL) {
  196.     if (!real_from(buf, &hdr))
  197.         printf("FAIL %s\n", buf);
  198.     else {
  199.         printf("OK %s\n", buf);
  200.         printf("from=%s time_zone=%s tz_offset=%d\n",
  201.         hdr.from, hdr.time_zone, hdr.tz_offset);
  202.         printf("time_sent=%ld received_time=%ld %s",
  203.         hdr.time_sent, hdr.received_time, ctime(&hdr.received_time));
  204.     }
  205.     putchar('\n');
  206.     }
  207.     exit(0);
  208. }
  209. #endif
  210.  
  211.