home *** CD-ROM | disk | FTP | other *** search
/ Beijing Paradise BBS Backup / PARADISE.ISO / software / BBSDOORW / QWKREP.ZIP / MAIL.C < prev    next >
C/C++ Source or Header  |  1992-09-17  |  9KB  |  418 lines

  1. /*
  2.  * mail.c - parse a UUCP mail / news input data stream into messages
  3.  */
  4.  
  5. #include    <stdio.h>
  6. #include    <clib.h>
  7. #include    <time.h>
  8. #include    <string.h>
  9. #include    "callback.h"
  10.  
  11. extern char *mnam[];
  12.  
  13. static struct _ng_
  14.  {
  15.     char *_name;
  16.     char *_conf;
  17.  } ngs[] =
  18.  {
  19.     { "comp.os.cpm", "CPM" },
  20.     { "rec.humor.funny", "FUNNY" },
  21.     { "comp.protocols.kermit", "KERMIT" },
  22.  };
  23.  
  24. /*
  25.  * number of newsgroups
  26.  */
  27. #define NUMNG (sizeof(ngs) / sizeof(ngs[0]))
  28.  
  29. /*
  30.  * copy a token from bp to targ, padding to 25 characters with spaces
  31.  */
  32. static tokecpy(targ, bp)
  33. char *targ;
  34. char *bp;
  35.  {
  36.     int i;
  37.  
  38.     for (i = 0; i < 25 && *bp && *bp != ' ' && *bp != '\t'; i++)
  39.       *targ++ = *bp++;
  40.     *targ = 0;
  41.  }
  42.  
  43. /*
  44.  * parse either form of RFC 822 date
  45.  */
  46. static parsedate(bp)
  47. char *bp;
  48.  {
  49.     int r;
  50.     int i;
  51.     int j;
  52.     int k;
  53.     int hh, mm, ss;
  54.     int dd, mo, yy;
  55.     struct tm *tmp;
  56.     time_t now;
  57.     char mtmp[6];
  58.     char *bits[10];
  59.     char hold[80];
  60.  
  61.     r = 0;
  62.     /*
  63.      * get the current time
  64.      */
  65.     time(&now);
  66.     tmp = localtime(&now);
  67.  
  68.     /*
  69.      * install that in case we don't get anything useful
  70.      */
  71.     sprintf(m_date, "%02d-%02d-%02d", tmp->tm_mon + 1, tmp->tm_mday,
  72.                                                         tmp->tm_year % 100);
  73.     sprintf(m_time, "%02d:%02d", tmp->tm_hour, tmp->tm_min);
  74.  
  75.     /*
  76.      * local copy of what we're parsing
  77.      */
  78.     strncpy(hold, bp, 78);
  79.     (bp = hold)[78] = 0;
  80.  
  81.     /*
  82.      * chop it up into bits, dividing at the spaces
  83.      */
  84.     for (i = 0; *bp && i < 10; i++)
  85.      {
  86.         bits[i] = bp;
  87.         if (*(bp = unbyp(bp)))
  88.          {
  89.             *bp++ = 0;
  90.             bp = byp(bp);
  91.          }
  92.      }
  93.  
  94.     /*
  95.      * no date, month or year yet
  96.      */
  97.     dd = mo = yy = -1;
  98.     for (j = 0; j < i; j++)
  99.      {
  100.         /*
  101.          * nn:nn:nn is a time - process that
  102.          */
  103.         if (sscanf((bp = bits[j]), "%d:%d:%d", &hh, &mm, &ss) == 3)
  104.          {
  105.             sprintf(m_time, "%02d:%02d", hh, mm);
  106.             /*
  107.              * set time bit in result
  108.              */
  109.             r |= 1;
  110.          }
  111.         /*
  112.          * anything numeric is date or year
  113.          */
  114.         else if (*bp >= '0' && *bp <= '9')
  115.          {
  116.             if (dd == -1)
  117.               dd = atoi(bp);
  118.             else
  119.               yy = atoi(bp) % 100;
  120.          }
  121.         /*
  122.          * else see if we can find a month in it
  123.          */
  124.         else
  125.          {
  126.             strncpy(mtmp, bp, 3);
  127.             mtmp[3] = 0;
  128.             lower(mtmp);
  129.             for (k = 0; k < 12; k++)
  130.               if (strcmp(mtmp, mnam[k]) == 0)
  131.                 break;
  132.             if (k < 12)
  133.               mo = k + 1;
  134.          }
  135.      }
  136.     /*
  137.      * got year and month: we must have a full date
  138.      */
  139.     if (yy != -1 && mo != -1)
  140.      {
  141.         sprintf(m_date, "%02d-%02d-%02d", mo, dd, yy);
  142.         /*
  143.          * set the bit in the result
  144.          */
  145.         r |= 2;
  146.      }
  147.     return(r);
  148.  }
  149.  
  150. /*
  151.  * see if the current line is a valid From_ line - i.e. the start of a new
  152.  * message in mailbox format
  153.  */
  154. static validfrom(work)
  155. char *work;
  156.  {
  157.     int i;
  158.     char x_date[10];
  159.     char x_time[8];
  160.  
  161.     strcpy(x_date, m_date);
  162.     strcpy(x_time, m_time);
  163.     /*
  164.      * look for From_ and a date *AFTER* the address (that's what all the
  165.      * byp's and unbyp's do
  166.      */
  167.     i = strncmp(work, "From ", 5) == 0 &&
  168.                                 parsedate(byp(unbyp(byp(unbyp(work))))) == 3;
  169.     /*
  170.      * save the date and time
  171.      */
  172.     strcpy(m_date, x_date);
  173.     strcpy(m_time, x_time);
  174.     return(i);
  175.  }
  176.  
  177. /*
  178.  * pull the from name out of what we're given:
  179.  * (Name) address --> Name
  180.  * <address> Name --> Name
  181.  * <address> "Name" --> Name
  182.  * ...!...!userid --> userid
  183.  * userid@.... --> userid
  184.  * userid%.... --> userid
  185.  */
  186. static void getfrom(pbp)
  187. char *pbp;
  188.  {
  189.     char bp[240];
  190.     char *p1;
  191.     char *p2;
  192.  
  193.     strcpy(bp, pbp);
  194.     /*
  195.      * look for (..)
  196.      */
  197.     if ((p1 = strchr(bp, '(')) != (char *) NULL &&
  198.                     (p2 = strchr(bp, ')')) != (char *) NULL &&
  199.                     p1 < p2)
  200.      {
  201.         *p2 = 0;
  202.         /*
  203.          * pull it out
  204.          */
  205.         strncpy(from, ++p1, 25);
  206.         from[25] = 0;
  207.         return;
  208.      }
  209.     /*
  210.      * <...> name and <...> "name" forms
  211.      */
  212.     if ((p1 = strchr(bp, '<')) != (char *) NULL &&
  213.                     (p2 = strchr(bp, '>')) != (char *) NULL &&
  214.                     p1 < p2)
  215.      {
  216.         /*
  217.          * replace everything between < and > (inclusive) with spaces
  218.          */
  219.         do
  220.           *p1++ = ' ';
  221.          while (p1 < p2);
  222.         /*
  223.          * remove any quotes we might find
  224.          */
  225.         for (p1 = bp; *p1; p1++)
  226.           if (*p1 == '"')
  227.             *p1 = ' ';
  228.         /*
  229.          * and use whatever is left
  230.          */
  231.         p1 = byp(bp);
  232.         strncpy(from, p1, 25);
  233.         from[25] = 0;
  234.         return;
  235.      }
  236.     /*
  237.      * userid@.... and userid%.... forms
  238.      */
  239.     if ((p1 = strchr(bp, '%')) != (char *) NULL ||
  240.                 (p1 = strchr(bp, '@')) != (char *) NULL)
  241.      {
  242.         /*
  243.          * terminate at the @ or %
  244.          */
  245.         *p1 = 0;
  246.         p1 = byp(bp);
  247.         strncpy(from, p1, 25);
  248.         from[25] = 0;
  249.         return;
  250.      }
  251.     /*
  252.      * ....!userid form
  253.      */
  254.     if ((p1 = strrchr(bp, '!')) != (char *) NULL)
  255.      {
  256.         /*
  257.          * copy from the last ! onwards
  258.          */
  259.         strncpy(from, ++p1, 25);
  260.         from[25] = 0;
  261.         return;
  262.      }
  263.     /*
  264.      * else just use what we were given
  265.      */
  266.     p1 = byp(bp);
  267.     strncpy(from, p1, 25);
  268.     from[25] = 0;
  269.     return;
  270.  }
  271.  
  272. /*
  273.  * convert a newsgroup to it's "ECHO" name
  274.  */
  275. static char *ngcvt(bp)
  276. char *bp;
  277.  {
  278.     int i;
  279.  
  280.     for (i = 0; i < NUMNG; i++)
  281.       if (strstr(bp, ngs[i]._name) != (char *) NULL)
  282.         return(ngs[i]._conf);
  283.     return("JUNK");
  284.  }
  285.  
  286. /*
  287.  * main entry point
  288.  */
  289. int mail_split(line, whoami)
  290. char *line;
  291.  {
  292.     int i;
  293.     char *bp;
  294.     static int seen = 0;
  295.     static int state = 0;
  296.     char work[240];
  297.     char text[80];
  298.  
  299.     /*
  300.      * grab a local copy
  301.      */
  302.     strncpy(work, line, 238);
  303.     work[238] = 0;
  304.     strip(work);
  305.     /*
  306.      * skip over the first token
  307.      */
  308.     bp = byp(unbyp(work));
  309.     /*
  310.      * valid from line?
  311.      */
  312.     if (validfrom(work))
  313.      {
  314.         /*
  315.          * yes - this must be for us!
  316.          */
  317.         if (seen)
  318.           /*
  319.            * finish a message if we are already in one
  320.            */
  321.           finish_msg();
  322.         else
  323.          {
  324.             /*
  325.              * first time - set up
  326.              * firstly "claim" this packet
  327.              */
  328.             mine(whoami);
  329.              /*
  330.               * init things - note that my name is hard coded
  331.               */
  332.             strcpy(bbsname, "UUCP");
  333.             strcpy(bbstitle, "UUCP E-mail and news");
  334.             strcpy(bbsuser, "DAVID GOODENOUGH");
  335.             /*
  336.              * force a mail conference
  337.              */
  338.             addconf("MAIL");
  339.             /*
  340.              * flag we're off and going
  341.              */
  342.             seen = 1;
  343.          }
  344.         /*
  345.          * start a new message
  346.          */
  347.         newmsg();
  348.         /*
  349.          * grab the from address
  350.          */
  351.         tokecpy(from, bp);
  352.         /*
  353.          * and the date
  354.          */
  355.         parsedate(byp(unbyp(bp)));
  356.         /*
  357.          * fill in the other fields
  358.          */
  359.         strcpy(to, bbsuser);
  360.         strcpy(confname, "MAIL");
  361.         strcpy(subject, "X");
  362.         /*
  363.          * set state to 1: we're crunching headers
  364.          */
  365.         state = 1;
  366.      }
  367.     else if (strlen(work) == 0)
  368.       /*
  369.        * empty line finishes headers
  370.        */
  371.       state = 0;
  372.     if (state)
  373.      {
  374.         /*
  375.          * in headers
  376.          */
  377.         if (strncmp(work, "Subject: ", 9) == 0)
  378.          {
  379.             /*
  380.              * grab a subject
  381.              */
  382.             strncpy(subject, bp, 25);
  383.             subject[25] = 0;
  384.          }
  385.         else if (strncmp(work, "From: ", 6) == 0)
  386.           /*
  387.            * grab the from name
  388.            */
  389.           getfrom(bp);
  390.         else if (strncmp(work, "Date: ", 6) == 0)
  391.           /*
  392.            * get the date
  393.            */
  394.           parsedate(bp);
  395.         else if (strncmp(work, "Newsgroups: ", 12) == 0)
  396.          {
  397.             /*
  398.              * newsgroup - no To: user, and convert the newsgroup name
  399.              */
  400.             strcpy(to, "ALL");
  401.             strcpy(confname, ngcvt(bp));
  402.          }
  403.      }
  404.     if (seen)
  405.      {
  406.         /*
  407.          * if we're running send back the message 78 chars at a time
  408.          */
  409.         for (i = 0; strlen(&work[i]) > 78; i += 78)
  410.          {
  411.             strncpy(text, &work[i], 78);
  412.             text[78] = 0;
  413.             writemsg(text);
  414.          }
  415.         writemsg(&work[i]);
  416.      }
  417.  }
  418.