home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mm / mm-0.90 / headers.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-18  |  7.2 KB  |  337 lines

  1. /*
  2.  * Copyright (c) 1986, 1990 by The Trustees of Columbia University in
  3.  * the City of New York.  Permission is granted to any individual or
  4.  * institution to use, copy, or redistribute this software so long as it
  5.  * is not sold for profit, provided this copyright notice is retained.
  6.  */
  7.  
  8. #ifndef lint
  9. static char *rcsid = "$Header: /f/src2/encore.bin/cucca/mm/tarring-it-up/RCS/headers.c,v 2.1 90/10/04 18:24:24 melissa Exp $";
  10. #endif
  11.  
  12. /*
  13.  * headers.c - header manipulation stuff
  14.  *
  15.  */
  16.  
  17. #include "mm.h"
  18. #include "parse.h"
  19.  
  20. /*
  21.  * compare two strings, ignoring case.  returns true if the strings match
  22.  * or if s1 is a leading substring of s2 and that substring in s2 ends with 
  23.  * a ':'.  Note, s1 may or may not be colon terminated, so check both cases.
  24.  */
  25.  
  26. hdrcmp (s1, s2)
  27. register char *s1, *s2;
  28. {
  29.     register char c1, c2;
  30.  
  31.     while (1) {
  32.     c1 = *s1++;
  33.     c2 = *s2++;
  34.     if (c2 == '\0') return false;    /* header line shorter than name */
  35.     if (c1 == '\0' && c2 == ':') return true; /* a match w/o ':' */
  36.     if (c1 == ':' && c2 == ':') return true; /* a match w/ ':'  */
  37.     if (((isascii (c1) && isupper (c1)) ? tolower (c1) : c1) !=
  38.         ((isascii (c2) && isupper (c2)) ? tolower (c2) : c2))
  39.         return false;
  40.     }
  41. }
  42.  
  43.  
  44. /*
  45.  * return a pointer to the first char following a (possibly folded) line.
  46.  */
  47. char *
  48. skipheader (s)
  49. register char *s;
  50. {
  51.     for (;;) {
  52.     while (*s && (*s != '\n'))
  53.         ++s;
  54.     if (*s == '\0')
  55.         return s;
  56.     /* s now points to a linefeed */
  57.     ++s;
  58.     if (isblank (*s))
  59.         continue;
  60.     return s;
  61.     }
  62. }
  63.  
  64. char *
  65. next_header(s,next) 
  66. register char **s;
  67. int *next;
  68. {
  69.     char *s1, *s2;
  70.     int len;
  71.     
  72.     s1 = skipheader(*s);
  73.     if (s1) {
  74.     len = s1 - *s;
  75.     s2 = malloc(len+1);
  76.     bcopy(*s,s2,len);
  77.     s2[len] = '\0';
  78.     *s = s1;
  79.     }
  80.     else 
  81.     return(NULL);
  82.  
  83.     if (*s1 == '\n') {
  84.     *next = false;
  85.     }
  86.     else 
  87.     *next = true;
  88.     return(s2);
  89. }
  90.  
  91. /*
  92.  * htext:
  93.  * Return the body of the first header "h" in string at "s".  The return
  94.  * value is allocated with malloc and should be freed when no longer needed.
  95.  */
  96. char *
  97. htext(h, s)
  98. char *h, *s;
  99. {
  100.     char *findheader();
  101.     return (findheader (h, s, true));    /* malloc the text string */
  102. }
  103.  
  104. /*
  105.  * hfind:
  106.  * Return a pointer to the first header "h" in message text "s".  The
  107.  * return value is a pointer right into the message text.
  108.  */
  109. char *
  110. hfind(h, s)
  111. char *h, *s;
  112. {
  113.     return (findheader (h, s, false));    /* don't malloc it */
  114. }
  115.  
  116. /*
  117.  * findheader:
  118.  * do the real work of htext and hfind
  119.  * Don't call this routine, okay?  Just call one of those up there ^^^.
  120.  */
  121. char *
  122. findheader(h, s, mallocp)
  123. char *h, *s;
  124. int mallocp;                /* should we malloc up the space? */
  125. {
  126.     int size;
  127.     char *head;
  128.     int len;
  129.  
  130.     while (1) {
  131.     if (s == nil || *s == '\0' || *s == '\n')
  132.         return nil;
  133.     if (hdrcmp (h, s)) {
  134.         if (!mallocp)
  135.         return (s);        /* here it is! */
  136.         len = strlen(h);
  137.         if (h[len-1] == ':')
  138.         s += len;
  139.         else
  140.         s += len+1;
  141.         for (;;) {
  142.         switch (*s) {        /* skip past whitespace, ':' etc */
  143.           case 0:
  144.             return nil;
  145.           case ' ':
  146.           case '\t':
  147.             ++s;
  148.             break;
  149.           case '\r':
  150.           case '\n':
  151.             ++s;
  152.             if (!isblank(*s))
  153.               return(nil);
  154.             break;
  155.           default:
  156.             /* s now points to the beginning of the header text,
  157.                so find the end and copy it */
  158.             size = (int) (skipheader (s) - s - 1); /* -1 for lf */
  159.             head = malloc (size + 1);
  160.             if (head == nil)
  161.             return nil;
  162.             strncpy(head, s, size);
  163.             head[size] = '\0';     /* make sure it's null-terminated */
  164.             return head;
  165.         }
  166.         }
  167.     }
  168.     else
  169.         s = skipheader (s);
  170.     }
  171. }    
  172.  
  173. /*
  174.  * strip out multiple spaces and folded lines in place.  any substring that
  175.  * can be interpreted as a run of whitespace (tabs, spaces, or line-folding
  176.  * sequences) is collapsed to a single space.
  177.  */
  178. char *
  179. stripspaces(s)
  180. register char *s;
  181. {
  182.     register char *cp = s, *p = s;
  183.  
  184.     while (*cp) {
  185.     if (isascii(*cp) && isspace(*cp)) {
  186.         if (cp != s)
  187.         *p++ = ' ';
  188.         while (isascii(*cp) && isspace(*++cp))
  189.         ;
  190.     }
  191.     else
  192.         *p++ = *cp++;
  193.     }
  194.     *p++ = '\0';
  195.     return s;
  196. }
  197.  
  198. /*
  199.  * header_summary:
  200.  * print out a little summary of this message, with the author and subject
  201.  * assume we have 79 columns to print:
  202. NFADK123) 21-Aug Melissa Metz    12345678901234567890123456789 (10000000 chars)
  203.  */
  204. #define BIGNUM 10000000            /* 8 characters worth */
  205. #define BIGNAME "10M"            /* a short string to name that */
  206. int
  207. header_summary (n, fp, longfmt)
  208. int n, longfmt;
  209. FILE *fp;
  210. {
  211.     buffer line;
  212.     message *m;
  213.     char *cp = line;
  214.     char *p;
  215.     char *freeme;            /* somebody forgot to free this! */
  216.     char *angle;            /* location of angle bracket */
  217.  
  218.     if (fp == NULL)            /* print to stdout if output */
  219.     fp = stdout;            /* descriptor is NULL */
  220.  
  221.     m = &cf->msgs[n];
  222.  
  223.     if (!(m->flags & M_SEEN))
  224.     if (m->flags & M_RECENT)
  225.         *cp++ = 'N';
  226.     else
  227.         *cp++ = 'U';
  228.     else
  229.     if (m->flags & M_RECENT)
  230.         *cp++ = 'R';
  231.     else
  232.         *cp++ = ' ';
  233.     *cp++ = (m->flags & M_FLAGGED) ? 'F' : ' ';
  234.     *cp++ = (m->flags & M_ANSWERED) ? 'A' : ' ';
  235.     *cp++ = (m->flags & M_DELETED) ? 'D' : ' ';
  236.     *cp++ = (m->keywords) ? 'K' : ' ';
  237.     (void) sprintf (cp, "%3d) %s ", n, hdate (m->date));
  238.     cp += strlen (cp);
  239.     freeme = htext ("from", m->text);
  240.     if (freeme) {
  241.     char *b, *z;
  242.     if (angle = index(freeme, '<')) {
  243.         if (angle != freeme) /* some text before <foo>? */
  244.         *angle = '\0';        /* print "foo" not "foo <foo>" */
  245.         sprintf (cp, "%-15.15s ", freeme); /* XXX should be smarter */
  246.     }
  247.     else if ((b = index(freeme, '(')) && (z = index(b + 1, ')'))) {
  248.         ++b;
  249.         *z = 0;
  250.         sprintf (cp, "%-15.15s ", b);
  251.     }
  252.     else
  253.         sprintf (cp, "%-15.15s ", freeme);
  254.  
  255.     safe_free (freeme);
  256.     }
  257.     else
  258.     sprintf (cp, "%-15.15s ", "???");
  259.  
  260.     cp += strlen (cp);
  261.  
  262.     freeme = htext ("subject", m->text);
  263.     if (longfmt) {
  264.     /* use the rest of the line for the Subject: header */
  265.     if (freeme)
  266.         sprintf (cp, "%.*s", cmcsb._cmcmx - (cp - line), freeme);
  267.     else
  268.         sprintf (cp, "(No subject)");
  269.     }
  270.     else {
  271.     if (freeme) {
  272.         sprintf (cp, "%.*s", cmcsb._cmcmx - 1 - 50, freeme); /* XXX */
  273.         cp += strlen (cp);
  274.     }
  275.     if (m->size > BIGNUM)
  276.         sprintf (cp, " (>%s chars)", BIGNAME);
  277.     else
  278.         sprintf (cp, " (%ld chars)", m->size);
  279.     cp += strlen (cp);
  280.     }
  281.     safe_free (freeme);
  282.     for (p = line; p && *p != NULL; p++) /* convert newlines to spaces */
  283.     if (*p == '\n')            /* to make sure things stay on one */
  284.         *p = ' ';            /* line.  could be done more */
  285.     fprintf (fp, "%s\n", line);        /* elegantly... */
  286. }
  287.  
  288. /*
  289.  * search:
  290.  * find string "s" in string "t", return pointer to where it starts, or nil
  291.  */
  292. char *
  293. search (s, t)
  294. char *s, *t;
  295. {
  296.     register char c = s[0];
  297.  
  298.     if (isupper (c))
  299.     c = tolower (c);
  300.  
  301.     do {
  302.     while (*t && (c != (isupper (*t) ? tolower (*t) : *t))) /* XXX ugh */
  303.         ++t;
  304.     if (*t && !ustrncmp(s, t, strlen(s)))
  305.         return t;
  306.     } while (*t++);
  307.     return nil;
  308. }
  309.  
  310. /*
  311.  * is the string "s" in the "h" header of this message (m)?
  312.  * returns a boolean (which only superficially resembles a pointer)
  313.  */
  314. search_header (h, s, m)
  315. char *h, *s;
  316. message *m;
  317. {
  318.     int q;
  319.     char *p = htext (h, m->text);
  320.     if (p == nil)
  321.     return (nil);
  322.     q = (int) search (s, p);
  323.     safe_free (p);
  324.     return (q);
  325. }
  326.  
  327. /*
  328.  * is the string "s" anywhere (including the headers) in message m?  
  329.  * this too is a boolean
  330.  */
  331. search_text (s, m)
  332. char *s;
  333. message *m;
  334. {
  335.     return ((int) search (s, m->text));
  336. }
  337.