home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / hyprmail.zip / string.c < prev    next >
Text File  |  1994-08-01  |  11KB  |  497 lines

  1. /*
  2. ** Copyright (C) 1994, Enterprise Integration Technologies Corp.        
  3. ** All Rights Reserved.
  4. ** Kevin Hughes, kevinh@eit.com 
  5. ** 7/31/94
  6. */
  7.  
  8. /* All the nasty string functions live here.
  9. */
  10.  
  11. #include "hypermail.h"
  12. #include "string.h"
  13.  
  14. /* Malloc() out a string, give it to whoever asked for it.
  15. */
  16.  
  17. char *strdup(s)
  18.      char *s;
  19. {
  20.     char *p;
  21.  
  22.     p = (char *) emalloc(strlen(s) + 1);
  23.     strcpy(p, s);
  24.     return p;
  25. }
  26.  
  27. /* Strips the timezone information from long date strings, so more correct
  28. ** comparisons can be made between dates when looking for article replies.
  29. */
  30.  
  31. char *stripzone(date)
  32.      char *date;
  33. {
  34.     int num;
  35.     static char tmpdate[DATESTRLEN];
  36.  
  37.     if (!strcmp(date, NODATE))
  38.         return date;
  39.     strcpy(tmpdate, date);
  40.     num = strlen(tmpdate);
  41.     while (tmpdate[num] != ':')
  42.         num--;
  43.     num += 3;
  44.     while (tmpdate[num])
  45.         tmpdate[num++] = '\0';
  46.  
  47.     return tmpdate;
  48. }
  49.  
  50. /* How many times does the character c appear in string s?
  51. */
  52.  
  53. int numstrchr(s, c)
  54.      char *s;
  55.      char c;
  56. {
  57.     int i;
  58.  
  59.     for (i = 0; *s != '\0'; s++)
  60.         if (*s == c)
  61.             i++;
  62.     return i;
  63. }
  64.  
  65. /* This is pretty cruddy and needs to be cleaned up and fixed!
  66. ** Converts URLs, email addresses, and message IDs in a line to links,
  67. ** mail commands, and articles respectively.
  68. */
  69.  
  70. char *convurls(line, mailid, mailsubject)
  71.      char *line;
  72.      char *mailid;
  73.      char *mailsubject;
  74. {
  75.     int i, j, k, limit, status, subjmatch;
  76.     char *c, anchor[URLSTRLEN], inreply[REPYSTRLEN], name[NAMESTRLEN],
  77.         subject[SUBJSTRLEN];
  78.     static char tmpline[MAXLINE], tmpline2[MAXLINE], tmpline3[MAXLINE],
  79.         tmpline4[MAXLINE];
  80.  
  81.     if (!strncmp(line, "In-Reply-To:", 12) ||
  82.     !strncmp(line, "References:", 11) ||
  83.     ((!strncmp(line, "    ", 4) || line[0] == '\t')
  84.     && strchr(line, '<') && strchr(line, '>') && strchr(line, '@'))) {
  85.         strcpy(inreply, (char *) getreply(line));
  86.         strcpy(tmpline4, convchars(line));
  87.         if (inreply[0] != '\0') {
  88.             status = hashreplylookup(inreply, name, subject,
  89.             &subjmatch);
  90.             if (status != -1) {
  91.                 for (i = j = 0; tmpline4[i] != ' ' &&
  92.                 j < MAXLINE && tmpline4[i] != '\t'; i++)
  93.                     tmpline3[j++] = tmpline4[i];
  94.                 while (isspace(tmpline4[i])) {
  95.                     tmpline3[j++] = ' ';
  96.                     i++;
  97.                 }
  98.                 tmpline3[j] = '\0';
  99.                 sprintf(tmpline3, "%s<a href=\"%.3d.html\">",
  100.                 tmpline3, status);
  101.                 for (j = strlen(tmpline3); tmpline4[i] &&
  102.                 tmpline4[i] != '\n' && j < MAXLINE; i++)
  103.                     tmpline3[j++] = tmpline4[i];
  104.                 tmpline3[j] = '\0';
  105.                 strcat(tmpline3, "</a>\n");
  106.                 return tmpline3;
  107.             }
  108.         }
  109.         return tmpline4;
  110.     }
  111.  
  112.     strcpy(tmpline3, convchars(line));
  113.  
  114.     for (i = 0; urls[i] != NULL; i++)
  115.         if ((c = (char *) strstr(tmpline3, urls[i])) != NULL) {
  116.             limit = c - tmpline3;
  117.             for (j = k = 0; j < limit && j < MAXLINE; j++)
  118.                 tmpline[k++] = tmpline3[j];
  119.             tmpline[k] = '\0';
  120.             j = 0;
  121.             while (*c && *c != ' ' && *c != ')' &&
  122.             *c != '>' && *c != '&' && *c != '\n' &&
  123.             *c != '\"'  && *c != ',' && *c != ']' &&
  124.             *c != '[' && *c != '\t' && *c != '\\' &&
  125.             j < URLSTRLEN) {
  126.                 anchor[j++] = *c;
  127.                 c++;
  128.             }
  129.             if (anchor[j - 1] == '.' ||
  130.             anchor[j - 1] == '*') {
  131.                 anchor[j - 1] = '\0';
  132.                 c--;
  133.             }
  134.             anchor[j] = '\0';
  135.             sprintf(tmpline2, "%s<a href=\"%s\">%s</a>",
  136.             tmpline, anchor, anchor);
  137.             k = strlen(tmpline2);
  138.             while (*c && k < MAXLINE) {
  139.                 tmpline2[k++] = *c;
  140.                 c++;
  141.             }
  142.             tmpline2[k] = '\0';
  143.             strcpy(tmpline3, tmpline2);
  144.             if (!strncmp(urls[i], "mailto:", 7))
  145.                 return tmpline3;
  146.         }
  147.  
  148. #ifdef MAILCOMMAND
  149.     if (strstr(tmpline3, "message") || strstr(tmpline3, "-Id"))
  150.         return tmpline3;
  151.  
  152.     if ((c = (char *) strchr(tmpline3, '@')) != NULL) {
  153.         while (c != tmpline3 && *c != ' ' && *c != ','
  154.         && *c != '<' && *c != ';' && *c != '(' &&
  155.         *c != '\t' && *c != '=')
  156.             c--;
  157.         if (c != tmpline3 || (c == tmpline3 && *c == '\t'))
  158.             c++;
  159.         limit = c - tmpline3;
  160.         for (j = k = 0; j < limit && j < MAXLINE; j++)
  161.             tmpline[k++] = tmpline3[j];
  162.         tmpline[k] = '\0';
  163.         j = 0;
  164.         while (*c && *c != ' ' && *c != ')' &&
  165.         *c != '>' && *c != '&' && *c != '\n' &&
  166.         *c != '\"'  && *c != ',' && *c != ']' &&
  167.         *c != '[' && *c != '=' && *c != '\t' &&
  168.         j < URLSTRLEN) {
  169.             anchor[j++] = *c;
  170.             c++;
  171.         }
  172.         if (anchor[j - 1] == '.' || anchor[j - 1] == '*') {
  173.             anchor[j - 1] = '\0';
  174.             c--;
  175.         }
  176.         anchor[j] = '\0';
  177.         if (anchor[0] == '@' || anchor[j - 1] == '@' ||
  178.         !strchr(anchor, '.'))
  179.             return tmpline3;
  180.         sprintf(tmpline2, "%s<a href=\"%s\">%s</a>",
  181.             tmpline, makemailcommand(MAILCOMMAND, anchor,
  182.             mailid, mailsubject), anchor);
  183.         k = strlen(tmpline2);
  184.         while (*c && k < MAXLINE) {
  185.             tmpline2[k++] = *c;
  186.             c++;
  187.         }
  188.         tmpline2[k] = '\0';
  189.         strcpy(tmpline3, tmpline2);
  190.     }
  191. #endif
  192.  
  193.     return tmpline3;
  194. }
  195.  
  196. /* Converts <, >, and & to <, > and &.
  197. ** It's ugly because it's fast.
  198. */
  199.  
  200. char *convchars(line)
  201.      char *line;
  202. {
  203.     int i, j;
  204.     static char tmpline[MAXLINE];
  205.  
  206.     for (i = j = 0; line[i] && i < MAXLINE; i++) {
  207.         if (line[i] == '<') {
  208.             tmpline[j++] = '&';
  209.             tmpline[j++] = 'l';
  210.             tmpline[j++] = 't';
  211.             tmpline[j++] = ';';
  212.         }
  213.         else if (line[i] == '>') {
  214.             tmpline[j++] = '&';
  215.             tmpline[j++] = 'g';
  216.             tmpline[j++] = 't';
  217.             tmpline[j++] = ';';
  218.         }
  219.         else if (line[i] == '&') {
  220.             tmpline[j++] = '&';
  221.             tmpline[j++] = 'a';
  222.             tmpline[j++] = 'm';
  223.             tmpline[j++] = 'p';
  224.             tmpline[j++] = ';';
  225.         }
  226.         else
  227.             tmpline[j++] = line[i];
  228.     }
  229.     tmpline[j] = '\0';
  230.  
  231.     return tmpline;
  232. }
  233.  
  234. /* Just the opposite of convchars().
  235. ** It's ugly because it's also fast.
  236. */
  237.  
  238. char *unconvchars(line)
  239.      char *line;
  240. {
  241.     static char tmpline[MAXLINE];
  242.     int i, j;
  243.  
  244.     for (i = j = 0; line[i]; i++)
  245.         if (line[i] == '&') {
  246.             if (line[i + 1] && line[i + 1] == 'l') {
  247.                 if (line[i + 2] && line[i + 2] == 't')
  248.                     if (line[i + 3] && line[i + 3] == ';') {
  249.                         tmpline[j++] = '<';
  250.                         i += 3;
  251.                     }
  252.             }
  253.             else if (line[i + 1] && line[i + 1] == 'g') {
  254.                 if (line[i + 2] && line[i + 2] == 't')
  255.                     if (line[i + 3] && line[i + 3] == ';') {
  256.                         tmpline[j++] = '>';
  257.                         i += 3;
  258.                     }
  259.             }
  260.             else if (line[i + 1] && line[i + 1] == 'a') {
  261.                 if (line[i + 2] && line[i + 2] == 'm')
  262.                     if (line[i + 3] && line[i + 3] == 'p')
  263.                     if (line[i + 4] && line[i + 4] == ';') {
  264.                         tmpline[j++] = '&';
  265.                         i += 4;
  266.                     }
  267.             }
  268.             else
  269.                 tmpline[j++] = line[i];
  270.         }
  271.         else
  272.             tmpline[j++] = line[i];
  273.     tmpline[j] = '\0';
  274.  
  275.     return tmpline;
  276. }
  277.  
  278. /* Grabs whatever happens to be between the outermost double quotes in a line.
  279. ** This is for grabbing the values in comments.
  280. */
  281.  
  282. char *getvalue(line)
  283.      char *line;
  284. {
  285.     int i;
  286.     char *c, *d;
  287.     static char tmpline[MAXLINE];
  288.  
  289.     tmpline[0] = '\0';
  290.     c = (char *) strchr(line, '\"');
  291.     d = (char *) strrchr(line, '\"');
  292.     if (c == NULL)
  293.         return tmpline;
  294.     for (c++, i = 0; *c && c != d && i < MAXLINE; c++)
  295.         tmpline[i++] = *c;
  296.     tmpline[i] = '\0';
  297.  
  298.     return tmpline;
  299. }
  300.  
  301. /* Grabs the value for a particular variable in a line - really,
  302. ** just about anything after an equals sign.
  303. */
  304.  
  305. char *getconfvalue(line, var, value)
  306.      char *line;
  307.      char *var;
  308.      char *value;
  309. {
  310.     int i;
  311.     char *c;
  312.     static char tmpvalue[MAXLINE];
  313.  
  314.     if (strstr(line, var) != NULL) {
  315.         if ((c = (char *) strchr(line, '=')) == NULL)
  316.             return NULL;
  317.         c++;
  318.         while (isspace(*c) || *c == '\"')
  319.             c++;
  320.         if (*c == '\0')
  321.             return NULL;
  322.         for (i = 0; *c != '\0' && *c != '\"' && *c != '\n' &&
  323.         i < MAXLINE; c++)
  324.             tmpvalue[i++] = *c;
  325.         tmpvalue[i] = '\0';
  326.         strcpy(value, tmpvalue);
  327.         return tmpvalue;
  328.     }
  329.     else
  330.         return NULL;
  331. }
  332.  
  333. /* Recursively gets rid of re:'s in a subject and strips spaces at the
  334. ** end of subjects. Makes the subject index much less cluttered...
  335. */
  336.  
  337. char *unre(subject)
  338.     char *subject;
  339. {
  340.     int i;
  341.     char *c;
  342.     static char tmpsubject[SUBJSTRLEN], tmpsubject2[SUBJSTRLEN];
  343.  
  344.     if (!strstr(subject, "Re:") && !strstr(subject, "re:"))
  345.         return subject;
  346.  
  347.     c = (char *) strstr(subject, "Re:");
  348.     if (c == NULL)
  349.         c = (char *) strstr(subject, "re:");
  350.     c += 3;
  351.     while (isspace(*c))
  352.         c++;
  353.     i = 0;
  354.     while (*c && i < SUBJSTRLEN) {
  355.         tmpsubject[i++] = *c;
  356.         c++;
  357.     }
  358.     i--;
  359.     while (isspace(tmpsubject[i]) || tmpsubject[i] == '\n') {
  360.         tmpsubject[i] = '\0';
  361.         i--;
  362.     }
  363.     i++;
  364.     tmpsubject[i] = '\0';
  365.  
  366.     while (strstr(tmpsubject, "Re:") || strstr(tmpsubject, "re:")) {
  367.         strcpy(tmpsubject2, unre(tmpsubject));
  368.         strcpy(tmpsubject, tmpsubject2);
  369.     }
  370.  
  371.     return tmpsubject;
  372. }
  373.  
  374. /* Only gets rid of one re: in a subject, so messages the subject is a reply to
  375. ** can be guessed.
  376. */
  377.  
  378. void oneunre(inreply, subject)
  379.      char *inreply;
  380.      char *subject;
  381. {
  382.         int i;
  383.         char *c;
  384.  
  385.         if (strstr(subject, "Re: ") || strstr(subject, "re: ")) {
  386.                 c = (char *) strchr(subject, ':') + 2;
  387.                 if (*c && *c == ' ')
  388.                         c++;
  389.                 for (i = 0; *c && *c != '\n' && i < MAXLINE; c++)
  390.                         inreply[i++] = *c;
  391.                 inreply[i] = '\0';
  392.         }
  393. }
  394.  
  395. /* Removes the last carriage return from a line.
  396. */
  397.  
  398. char *rmcr(line)
  399.      char *line;
  400. {
  401.     int i;
  402.     static char tmpline[MAXLINE];
  403.  
  404.     i = 0;
  405.     while (*line && i < MAXLINE) {
  406.         if (*line == '\n')
  407.             *line = '\0';
  408.         tmpline[i++] = *line;
  409.         line++;
  410.     }
  411.     tmpline[i] = '\0';
  412.  
  413.     return tmpline;
  414. }
  415.  
  416. /* Is a line in an article body part of a quoted passage?
  417. */
  418.  
  419. int isquote(line)
  420.      char *line;
  421. {
  422.     while (*line && isspace(*line)) {
  423.         line++;
  424.     }
  425.     if (!(*line))
  426.         return 0;
  427.     if (*line == '|' || *line == ']' || *line == '>')
  428.         return 1;
  429.  
  430.     return 0;
  431. }
  432.  
  433. /* Generates the mail command to use from the default mail command,
  434. ** the current recipient's email address, the current ID of the
  435. ** message, and the current subject.
  436. */
  437.  
  438. char *makemailcommand(mailcommand, email, id, subject)
  439.      char *mailcommand;
  440.      char *email;
  441.      char *id;
  442.      char *subject;
  443. {
  444.     int hasre;
  445.     static char tmpsubject[SUBJSTRLEN], tmpstring[MAXLINE];
  446.  
  447.     if (!strncmp(subject, "Re:", 3) || !strncmp(subject, "re:", 3))
  448.         hasre = 1;
  449.     else
  450.         hasre = 0;
  451.  
  452.     sprintf(tmpsubject, "%s%s", (hasre) ? "" : "Re: ", subject);
  453.  
  454.     strcpy(tmpstring, replace(mailcommand, "$TO", email));
  455.     strcpy(tmpstring, replace(tmpstring, "$ID", id));
  456.     strcpy(tmpstring, replace(tmpstring, "$SUBJECT", tmpsubject));
  457.     strcpy(tmpstring, replace(tmpstring, " ", "%20"));
  458.     strcpy(tmpstring, replace(tmpstring, "+", "%22"));
  459.  
  460.     return tmpstring;
  461. }
  462.  
  463. /* Given a string, replaces all instances of "oldpiece" with "newpiece".
  464. */
  465.  
  466. char *replace(string, oldpiece, newpiece)
  467.      char *string;
  468.      char *oldpiece;
  469.      char *newpiece;
  470. {
  471.     int i, j, limit;
  472.     char *c;
  473.     char beforestring[MAXLINE], afterstring[MAXLINE];
  474.     static char newstring[MAXLINE];
  475.  
  476.     if ((c = (char *) strstr(string, oldpiece)) == NULL)
  477.         return string;
  478.     limit = c - string;
  479.  
  480.     for (i = 0; i < limit; i++)
  481.         beforestring[i] = string[i];
  482.     beforestring[i] = '\0';
  483.  
  484.     i += strlen(oldpiece);
  485.  
  486.     for (j = 0; string[i] != '\0'; i++)
  487.         afterstring[j++] = string[i];
  488.     afterstring[j] = '\0';
  489.  
  490.     sprintf(newstring, "%s%s%s", beforestring, newpiece, afterstring);
  491.  
  492.     while (strstr(newstring, oldpiece))
  493.         strcpy(newstring, replace(newstring, oldpiece, newpiece));
  494.  
  495.     return newstring;
  496. }
  497.