home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / hyprmail.zip / struct.c < prev    next >
C/C++ Source or Header  |  1997-03-16  |  11KB  |  427 lines

  1. /*
  2. ** Copyright (C) 1994, Enterprise Integration Technologies Corp.        
  3. ** All Rights Reserved.
  4. ** Kevin Hughes, kevinh@eit.com 
  5. ** 7/21/94
  6. */
  7.  
  8. #include "hypermail.h"
  9. #include "struct.h"
  10.  
  11. /* Ladies and gentlemen - the hash function.
  12. */
  13.  
  14. unsigned hash(s)
  15.      char *s;
  16. {
  17.     unsigned hashval;
  18.  
  19.     for (hashval = 0; *s != '\0'; s++)
  20.         hashval = *s + 31 * hashval;
  21.     return hashval % HASHSIZE;
  22. }
  23.  
  24. /* The structure most of everything else depends on.
  25. ** Hashes a message - header info, pointer to a list of body lines -
  26. ** by number, message ID, date, and subject, so an article can be
  27. ** handily looked up and retrieved using any of these criteria.
  28. */
  29.  
  30. void addhash(num, date, name, email, msgid, subject, inreply, fromdate, bp)
  31.      int num;
  32.      char *date;
  33.      char *name;
  34.      char *email;
  35.      char *msgid;
  36.      char *subject;
  37.      char *inreply;
  38.      char *fromdate;
  39.      struct body *bp;
  40. {
  41.     struct email *ep;
  42.     struct body *sp;
  43.     unsigned hashval;
  44.     char numstr[NUMSTRLEN];
  45.  
  46.     sp = bp;
  47.  
  48.     ep = (struct email *) emalloc(sizeof(*ep));
  49.     ep->msgnum = num;
  50.     ep->name = (char *) strdup(name);
  51.     ep->emailaddr = (char *) strdup(email);
  52.     ep->fromdatestr = (char *) strdup(fromdate);
  53.     ep->datestr = (char *) strdup(date);
  54.     ep->msgid = (char *) strdup(msgid);
  55.     ep->subject = (char *) strdup(subject);
  56.     ep->inreplyto = (char *) strdup(inreply);
  57.     ep->bodylist = sp;
  58.  
  59.     hashval = hash(stripzone(date));
  60.     ep->next = etable[hashval];
  61.     etable[hashval] = ep;
  62.  
  63.     ep = (struct email *) emalloc(sizeof(*ep));
  64.     ep->msgnum = num;
  65.     ep->name = (char *) strdup(name);
  66.     ep->emailaddr = (char *) strdup(email);
  67.     ep->fromdatestr = (char *) strdup(fromdate);
  68.     ep->datestr = (char *) strdup(date);
  69.     ep->msgid = (char *) strdup(msgid);
  70.     ep->subject = (char *) strdup(subject);
  71.     ep->inreplyto = (char *) strdup(inreply);
  72.     ep->bodylist = sp;
  73.  
  74.     hashval = hash(msgid);
  75.     ep->next = etable[hashval];
  76.     etable[hashval] = ep;
  77.  
  78.     ep = (struct email *) emalloc(sizeof(*ep));
  79.     ep->msgnum = num;
  80.     ep->name = (char *) strdup(name);
  81.     ep->emailaddr = (char *) strdup(email);
  82.     ep->fromdatestr = (char *) strdup(fromdate);
  83.     ep->datestr = (char *) strdup(date);
  84.     ep->msgid = (char *) strdup(msgid);
  85.     ep->subject = (char *) strdup(subject);
  86.     ep->inreplyto = (char *) strdup(inreply);
  87.     ep->bodylist = sp;
  88.  
  89.     hashval = hash(subject);
  90.     ep->next = etable[hashval];
  91.     etable[hashval] = ep;
  92.  
  93.     ep = (struct email *) emalloc(sizeof(*ep));
  94.     ep->msgnum = num;
  95.     ep->name = (char *) strdup(name);
  96.     ep->emailaddr = (char *) strdup(email);
  97.     ep->fromdatestr = (char *) strdup(fromdate);
  98.     ep->datestr = (char *) strdup(date);
  99.     ep->msgid = (char *) strdup(msgid);
  100.     ep->subject = (char *) strdup(subject);
  101.     ep->inreplyto = (char *) strdup(inreply);
  102.     ep->bodylist = sp;
  103.  
  104.     sprintf(numstr, "%d", num);
  105.     hashval = hash(numstr);
  106.     ep->next = etable[hashval];
  107.     etable[hashval] = ep;
  108. }
  109.  
  110. /* Given an "in-reply-to:" field, this tries to retrieve information
  111. ** about the article that is a reply. If all else fails but a reply is
  112. ** found by comparing subjects, issubjmatch is set to 1.
  113. */
  114.  
  115. int hashreplylookup(inreply, name, subject, issubjmatch)
  116.      char *inreply;
  117.      char *name;
  118.      char *subject;
  119.      int *issubjmatch;
  120. {
  121.     struct email *ep;
  122.  
  123.     *issubjmatch = 0;
  124.     if (numstrchr(inreply, ':') == 2)
  125.         ep = etable[hash(stripzone(inreply))];
  126.     else
  127.         ep = etable[hash(inreply)];
  128.     while (ep != NULL) {
  129.         if (strcmp(inreply, ep->msgid) == 0) {
  130.             strcpy(name, ep->name);
  131.             strcpy(subject, ep->subject);
  132.             return ep->msgnum;
  133.         }
  134.         ep = ep->next;
  135.     }
  136.  
  137.     if (numstrchr(inreply, ':') == 2)
  138.         ep = etable[hash(stripzone(inreply))];
  139.     else
  140.         ep = etable[hash(inreply)];
  141.     while (ep != NULL) {
  142.         if (strstr(inreply, stripzone(ep->datestr))) {
  143.             strcpy(name, ep->name);
  144.             strcpy(subject, ep->subject);
  145.             return ep->msgnum;
  146.         }
  147.         ep = ep->next;
  148.     }
  149.  
  150.     if (numstrchr(inreply, ':') == 2)
  151.         ep = etable[hash(stripzone(inreply))];
  152.     else
  153.         ep = etable[hash(inreply)];
  154.     while (ep != NULL) {
  155.         if (strcmp(inreply, ep->subject) == 0) {
  156.             strcpy(name, ep->name);
  157.             strcpy(subject, ep->subject);
  158.             *issubjmatch = 1;
  159.             return ep->msgnum;
  160.         }
  161.         ep = ep->next;
  162.     }
  163.  
  164.     return -1;
  165. }
  166.  
  167. /* Same as the above function, but only returns the article number.
  168. */
  169.  
  170. int hashreplynumlookup(inreply, maybereply)
  171.      int *maybereply;
  172.      char *inreply;
  173. {
  174.     struct email *ep;
  175.  
  176.     *maybereply = 0;
  177.  
  178.     if (numstrchr(inreply, ':') == 2)
  179.         ep = etable[hash(stripzone(inreply))];
  180.     else
  181.         ep = etable[hash(inreply)];
  182.     while (ep != NULL) {
  183.         if (strcmp(inreply, ep->msgid) == 0)
  184.             return ep->msgnum;
  185.         ep = ep->next;
  186.     }
  187.  
  188.     if (numstrchr(inreply, ':') == 2)
  189.         ep = etable[hash(stripzone(inreply))];
  190.     else
  191.         ep = etable[hash(inreply)];
  192.     while (ep != NULL) {
  193.         if (strstr(inreply, stripzone(ep->datestr)))
  194.             return ep->msgnum;
  195.         ep = ep->next;
  196.     }
  197.  
  198.     if (numstrchr(inreply, ':') == 2)
  199.         ep = etable[hash(stripzone(inreply))];
  200.     else
  201.         ep = etable[hash(inreply)];
  202.     while (ep != NULL) {
  203.         if (strcmp(inreply, ep->subject) == 0) {
  204.             *maybereply = 1;
  205.             return ep->msgnum;
  206.         }
  207.         ep = ep->next;
  208.     }
  209.  
  210.     return -1;
  211. }
  212.  
  213. /* From an article's number, retrieve all information associated with
  214. ** that article.
  215. */
  216.  
  217. struct body *hashnumlookup(num, name, email, subject, reply, date, fromdate,
  218. msgid)
  219.      int num;
  220.      char *name;
  221.      char *email;
  222.      char *subject;
  223.      char *reply;
  224.      char *date;
  225.      char *fromdate;
  226.      char *msgid;
  227. {
  228.     struct email *ep;
  229.     char numstr[NUMSTRLEN];
  230.  
  231.     sprintf(numstr, "%d", num);
  232.     for (ep = etable[hash(numstr)]; ep != NULL; ep = ep->next)
  233.         if (num == ep->msgnum) {
  234.             strcpy(name, ep->name);
  235.             strcpy(email, ep->emailaddr);
  236.             strcpy(subject, ep->subject);
  237.             strcpy(reply, ep->inreplyto);
  238.             strcpy(date, ep->datestr);
  239.             strcpy(fromdate, ep->fromdatestr);
  240.             strcpy(msgid, ep->msgid);
  241.             return ep->bodylist;
  242.         }
  243.     return NULL;
  244. }
  245.  
  246. /* Add a line to a linked list that makes up an article's body.
  247. */
  248.  
  249. struct body *addbody(bp, line)
  250.      struct body *bp;
  251.      char *line;
  252. {
  253.         struct body *tempnode, *newnode;
  254.  
  255.         newnode = (struct body *) emalloc(sizeof(struct body));
  256.     newnode->line = (char *) strdup(line);
  257.         newnode->next = NULL;
  258.  
  259.         if (bp == NULL)
  260.                 bp = newnode;
  261.         else {
  262.                 for (tempnode = bp; tempnode->next != NULL; tempnode =
  263.                 tempnode->next)
  264.                         ;
  265.                 tempnode->next = newnode;
  266.         }
  267.  
  268.         return bp;
  269. }
  270.  
  271. /* Remove the last empty lines, if any, from an article body's linked list.
  272. */
  273.  
  274. int rmlastlines(bp)
  275.      struct body *bp;
  276. {
  277.     struct body *tempnode;
  278.  
  279.     for (tempnode = bp; tempnode->next != NULL &&
  280.     (tempnode->next->line)[0] != '\0'; tempnode = tempnode->next)
  281.         ;
  282.     if ((tempnode->line)[0] == '\n') {
  283.         (tempnode->line)[0] = '\0';
  284.         return 1;
  285.     }
  286.     return 0;
  287. }
  288.  
  289. /* If a message is a reply to another, that message's number and the
  290. ** number of the message it may be referring to is put in this list.
  291. */
  292.  
  293. struct reply *addreply(rp, num, fromnum, name, subject, maybereply)
  294.      struct reply *rp;
  295.      int num;
  296.      int fromnum;
  297.      char *name;
  298.      char *subject;
  299.      int maybereply;
  300. {
  301.     struct reply *tempnode, *newnode;
  302.  
  303.         newnode = (struct reply *) emalloc(sizeof(struct reply));
  304.         newnode->msgnum = num;
  305.         newnode->frommsgnum = fromnum;
  306.         newnode->name = (char *) strdup(name);
  307.         newnode->subject = (char *) strdup(subject);
  308.     newnode->maybereply = maybereply;
  309.         newnode->next = NULL;
  310.  
  311.         if (rp == NULL)
  312.                 rp = newnode;
  313.         else {
  314.                 for (tempnode = rp; tempnode->next != NULL; tempnode =
  315.                 tempnode->next)
  316.                         ;
  317.                 tempnode->next = newnode;
  318.         }
  319.  
  320.         return rp;
  321. }
  322.  
  323. /* Mark an article number as having been printed.
  324. */
  325.  
  326. struct printed *markasprinted(pp, num)
  327.      struct printed *pp;
  328.      int num;
  329. {
  330.     struct printed *tempnode, *newnode;
  331.  
  332.         newnode = (struct printed *) emalloc(sizeof(struct printed));
  333.         newnode->msgnum = num;
  334.         newnode->next = NULL;
  335.  
  336.         if (pp == NULL)
  337.                 pp = newnode;
  338.         else {
  339.                 for (tempnode = pp; tempnode->next != NULL; tempnode =
  340.                 tempnode->next)
  341.                         ;
  342.                 tempnode->next = newnode;
  343.         }
  344.  
  345.         return pp;
  346. }
  347.  
  348. /* Has an article already been printed?
  349. */
  350.  
  351. int wasprinted(list, num)
  352.      struct printed *list;
  353.      int num;
  354. {
  355.     struct printed *pp;
  356.  
  357.     for (pp = list; pp != NULL; pp = pp->next)
  358.         if (pp->msgnum == num)
  359.             return 1;
  360.     return 0;
  361. }
  362.  
  363. /* Add article header information to a binary tree and sort by date,
  364. ** subject, or author. This is necessary for printing the index files.
  365. */
  366.  
  367. struct header *addheader(hp, num, name, subject, date, sorttype)
  368.      struct header *hp;
  369.      int num;
  370.      char *name;
  371.      char *subject;
  372.      char *date;
  373.      int sorttype;
  374. {
  375.         int isbigger, yearsecs;
  376.  
  377.         isbigger = 0;
  378.         if (hp == NULL) {
  379.                 hp = (struct header *) emalloc(sizeof(struct header));
  380.                 hp->msgnum = num;
  381.         hp->name = (char *) strdup(name);
  382.         hp->subject = (char *) strdup(subject);
  383.         hp->datestr = (char *) strdup(date);
  384.         if (sorttype == 2) {
  385.             yearsecs = convtoyearsecs(date);
  386.             if (!yearsecs)
  387.                 yearsecs = getlocaltime();
  388.             hp->datenum = yearsecs;
  389.             if (!firstdatenum || yearsecs < firstdatenum)
  390.                 firstdatenum = yearsecs;
  391.             if (yearsecs > lastdatenum)
  392.                 lastdatenum = yearsecs;
  393.         }
  394.         else
  395.             hp->datenum = 0;
  396.                 hp->left = hp->right = NULL;
  397.                 return hp;
  398.         }
  399.  
  400.     if (sorttype == 1)
  401.             isbigger = (stricmp(name, hp->name) > 0) ? 0 : 1;
  402.     else if (sorttype == 0)
  403.             isbigger = (stricmp(subject, hp->subject) > 0) ? 0 : 1;
  404.     else if (sorttype == 2) {
  405.         yearsecs = convtoyearsecs(date);
  406.         if (!yearsecs)
  407.             yearsecs = getlocaltime();
  408.         if (reverse)
  409.                 isbigger = (yearsecs < hp->datenum) ? 0 : 1;
  410.         else
  411.                 isbigger = (yearsecs >= hp->datenum) ? 0 : 1;
  412.         if (!firstdatenum || yearsecs < firstdatenum)
  413.             firstdatenum = yearsecs;
  414.         if (yearsecs > lastdatenum)
  415.             lastdatenum = yearsecs;
  416.     }
  417.  
  418.         if (isbigger)
  419.                 hp->left = addheader(hp->left, num, name, subject, date,
  420.         sorttype);
  421.         else
  422.                 hp->right = addheader(hp->right, num, name, subject, date,
  423.         sorttype);
  424.  
  425.         return hp;
  426. }
  427.