/[james]/httplint/httplint.c
ViewVC logotype

Diff of /httplint/httplint.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 40 by james, Mon Dec 15 15:07:31 2003 UTC revision 44 by james, Thu Dec 18 00:52:50 2003 UTC
# Line 36  CURL *curl; Line 36  CURL *curl;
36  int status_code;  int status_code;
37  char error_buffer[CURL_ERROR_SIZE];  char error_buffer[CURL_ERROR_SIZE];
38  regex_t re_status_line, re_token, re_token_value, re_content_type, re_ugly,  regex_t re_status_line, re_token, re_token_value, re_content_type, re_ugly,
39      re_absolute_uri, re_etag, re_server, re_transfer_coding, re_upgrade;      re_absolute_uri, re_etag, re_server, re_transfer_coding, re_upgrade,
40        re_rfc1123, re_rfc1036, re_asctime;
41    
42    
43  void init(void);  void init(void);
# Line 47  size_t data_callback(void *ptr, size_t s Line 48  size_t data_callback(void *ptr, size_t s
48  void check_status_line(const char *s);  void check_status_line(const char *s);
49  void check_header(const char *name, const char *value);  void check_header(const char *name, const char *value);
50  bool parse_date(const char *s, struct tm *tm);  bool parse_date(const char *s, struct tm *tm);
51    int month(const char *s);
52    time_t mktime_from_utc(struct tm *t);
53  const char *skip_lws(const char *s);  const char *skip_lws(const char *s);
54  bool parse_list(const char *s, regex_t *preg, unsigned int n, unsigned int m,  bool parse_list(const char *s, regex_t *preg, unsigned int n, unsigned int m,
55      void (*callback)(const char *s, regmatch_t pmatch[]));      void (*callback)(const char *s, regmatch_t pmatch[]));
# Line 174  void init(void) Line 177  void init(void)
177        "^HTTP/([0-9]+)[.]([0-9]+) ([0-9][0-9][0-9]) ([\t -~€-ÿ]*)$",        "^HTTP/([0-9]+)[.]([0-9]+) ([0-9][0-9][0-9]) ([\t -~€-ÿ]*)$",
178        REG_EXTENDED);        REG_EXTENDED);
179    regcomp_wrapper(&re_token,    regcomp_wrapper(&re_token,
180        "^([-0-9a-zA-Z_.]+)",        "^([-0-9a-zA-Z_.!]+)",
181        REG_EXTENDED);        REG_EXTENDED);
182    regcomp_wrapper(&re_token_value,    regcomp_wrapper(&re_token_value,
183        "^([-0-9a-zA-Z_.]+)(=([-0-9a-zA-Z_.]+|\"([^\"]|[\\].)*\"))?",        "^([-0-9a-zA-Z_.!]+)(=([-0-9a-zA-Z_.!]+|\"([^\"]|[\\].)*\"))?",
184        REG_EXTENDED);        REG_EXTENDED);
185    regcomp_wrapper(&re_content_type,    regcomp_wrapper(&re_content_type,
186        "^([-0-9a-zA-Z_.]+)/([-0-9a-zA-Z_.]+)[ \t]*"        "^([-0-9a-zA-Z_.]+)/([-0-9a-zA-Z_.]+)[ \t]*"
# Line 191  void init(void) Line 194  void init(void)
194        "^(W/[ \t]*)?\"([^\"]|[\\].)*\"$",        "^(W/[ \t]*)?\"([^\"]|[\\].)*\"$",
195        REG_EXTENDED);        REG_EXTENDED);
196    regcomp_wrapper(&re_server,    regcomp_wrapper(&re_server,
197        "^((([-0-9a-zA-Z_.]+(/[-0-9a-zA-Z_.]+)?)|(\\(.*\\)))[ \t]*)+$",        "^((([-0-9a-zA-Z_.!]+(/[-0-9a-zA-Z_.]+)?)|(\\(.*\\)))[ \t]*)+$",
198        REG_EXTENDED);        REG_EXTENDED);
199    regcomp_wrapper(&re_transfer_coding,    regcomp_wrapper(&re_transfer_coding,
200        "^([-0-9a-zA-Z_.]+)[ \t]*"        "^([-0-9a-zA-Z_.]+)[ \t]*"
# Line 202  void init(void) Line 205  void init(void)
205        "^([-0-9a-zA-Z_.](/[-0-9a-zA-Z_.])?)+$",        "^([-0-9a-zA-Z_.](/[-0-9a-zA-Z_.])?)+$",
206        REG_EXTENDED);        REG_EXTENDED);
207    regcomp_wrapper(&re_ugly,    regcomp_wrapper(&re_ugly,
208        "^[a-zA-Z0-9]+://[^/]+[/a-zA-Z0-9-_]*$",        "^[a-zA-Z0-9]+://[^/]+[-/a-zA-Z0-9_]*$",
209          REG_EXTENDED);
210      regcomp_wrapper(&re_rfc1123,
211          "^(Mon|Tue|Wed|Thu|Fri|Sat|Sun), ([0123][0-9]) "
212          "(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ([0-9]{4}) "
213          "([012][0-9]):([0-5][0-9]):([0-5][0-9]) GMT$",
214          REG_EXTENDED);
215      regcomp_wrapper(&re_rfc1036,
216          "^(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday), "
217          "([0123][0-9])-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-"
218          "([0-9][0-9]) ([012][0-9]):([0-5][0-9]):([0-5][0-9]) GMT$",
219          REG_EXTENDED);
220      regcomp_wrapper(&re_asctime,
221          "^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) "
222          "(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ([ 12][0-9]) "
223          "([012][0-9]):([0-5][0-9]):([0-5][0-9]) ([0-9]{4})$",
224        REG_EXTENDED);        REG_EXTENDED);
225  }  }
226    
# Line 380  void check_header(const char *name, cons Line 398  void check_header(const char *name, cons
398    if (header) {    if (header) {
399      header->count++;      header->count++;
400      header->handler(value);      header->handler(value);
401    } else    } else if ((name[0] == 'X' || name[0] == 'x') && name[1] == '-') {
402        lookup("xheader");
403      } else {
404      lookup("nonstandard");      lookup("nonstandard");
405      }
406  }  }
407    
408    
# Line 390  void check_header(const char *name, cons Line 411  void check_header(const char *name, cons
411   */   */
412  bool parse_date(const char *s, struct tm *tm)  bool parse_date(const char *s, struct tm *tm)
413  {  {
414    char *r;    int r;
415    int len = strlen(s);    int len = strlen(s);
416      regmatch_t pmatch[20];
417    
418    if (len == 29) {    if (len == 29) {
419      /* RFC 1123 */      /* RFC 1123 */
420      r = strptime(s, "%a, %d %b %Y %H:%M:%S GMT", tm);      r = regexec(&re_rfc1123, s, 20, pmatch, 0);
421      if (r == s + len)      if (r == 0) {
422          tm->tm_mday = atoi(s + pmatch[2].rm_so);
423          tm->tm_mon = month(s + pmatch[3].rm_so);
424          tm->tm_year = atoi(s + pmatch[4].rm_so) - 1900;
425          tm->tm_hour = atoi(s + pmatch[5].rm_so);
426          tm->tm_min = atoi(s + pmatch[6].rm_so);
427          tm->tm_sec = atoi(s + pmatch[7].rm_so);
428        return true;        return true;
429        }
430    
431    } else if (len == 24) {    } else if (len == 24) {
432      /* asctime() format */      /* asctime() format */
433      r = strptime(s, "%a %b %d %H:%M:%S %Y", tm);      r = regexec(&re_asctime, s, 20, pmatch, 0);
434      if (r == s + len) {      if (r == 0) {
435        lookup("asctime");        if (s[pmatch[3].rm_so] == ' ')
436        return true;          tm->tm_mday = atoi(s + pmatch[3].rm_so + 1);
437      }        else
438      r = strptime(s, "%a %b  %d %H:%M:%S %Y", tm);          tm->tm_mday = atoi(s + pmatch[3].rm_so);
439      if (r == s + len) {        tm->tm_mon = month(s + pmatch[2].rm_so);
440          tm->tm_year = atoi(s + pmatch[7].rm_so) - 1900;
441          tm->tm_hour = atoi(s + pmatch[4].rm_so);
442          tm->tm_min = atoi(s + pmatch[5].rm_so);
443          tm->tm_sec = atoi(s + pmatch[6].rm_so);
444        lookup("asctime");        lookup("asctime");
445        return true;        return true;
446      }      }
447    
448    } else {    } else {
449      /* RFC 1036 */      /* RFC 1036 */
450      r = strptime(s, "%a, %d-%b-%y %H:%M:%S GMT", tm);      r = regexec(&re_rfc1036, s, 20, pmatch, 0);
451      if (r == s + len) {      if (r == 0) {
452          tm->tm_mday = atoi(s + pmatch[2].rm_so);
453          tm->tm_mon = month(s + pmatch[3].rm_so);
454          tm->tm_year = 100 + atoi(s + pmatch[4].rm_so);
455          tm->tm_hour = atoi(s + pmatch[5].rm_so);
456          tm->tm_min = atoi(s + pmatch[6].rm_so);
457          tm->tm_sec = atoi(s + pmatch[7].rm_so);
458        lookup("rfc1036");        lookup("rfc1036");
459        return true;        return true;
460      }      }
# Line 428  bool parse_date(const char *s, struct tm Line 467  bool parse_date(const char *s, struct tm
467    
468    
469  /**  /**
470     * Convert a month name to the month number.
471     */
472    int month(const char *s)
473    {
474      switch (s[0]) {
475        case 'J':
476          switch (s[1]) {
477            case 'a':
478              return 0;
479            case 'u':
480              return s[2] == 'n' ? 5 : 6;
481          }
482        case 'F':
483          return 1;
484        case 'M':
485          return s[2] == 'r' ? 2 : 4;
486        case 'A':
487          return s[1] == 'p' ? 3 : 7;
488        case 'S':
489          return 8;
490        case 'O':
491          return 9;
492        case 'N':
493          return 10;
494        case 'D':
495          return 11;
496      }
497      return 0;
498    }
499    
500    
501    /**
502     * UTC version of mktime, from
503     *   http://lists.debian.org/deity/2002/deity-200204/msg00082.html
504     */
505    time_t mktime_from_utc(struct tm *t)
506    {
507      time_t tl, tb;
508      struct tm *tg;
509    
510      tl = mktime (t);
511      if (tl == -1)
512        {
513          t->tm_hour--;
514          tl = mktime (t);
515          if (tl == -1)
516            return -1; /* can't deal with output from strptime */
517          tl += 3600;
518        }
519      tg = gmtime (&tl);
520      tg->tm_isdst = 0;
521      tb = mktime (tg);
522      if (tb == -1)
523        {
524          tg->tm_hour--;
525          tb = mktime (tg);
526          if (tb == -1)
527            return -1; /* can't deal with output from gmtime */
528          tb += 3600;
529        }
530      return (tl - (tb - tl));
531    }
532    
533    
534    /**
535   * Skip optional LWS (linear white space) [2.2]   * Skip optional LWS (linear white space) [2.2]
536   */   */
537  const char *skip_lws(const char *s)  const char *skip_lws(const char *s)
# Line 681  void header_date(const char *s) Line 785  void header_date(const char *s)
785    time0 = time(0);    time0 = time(0);
786    if (!parse_date(s, &tm))    if (!parse_date(s, &tm))
787      return;      return;
788    time1 = mktime(&tm);    time1 = mktime_from_utc(&tm);
789    
790    diff = difftime(time0, time1);    diff = difftime(time0, time1);
791    if (10 < fabs(diff))    if (10 < fabs(diff))
# Line 716  void header_last_modified(const char *s) Line 820  void header_last_modified(const char *s)
820    time0 = time(0);    time0 = time(0);
821    if (!parse_date(s, &tm))    if (!parse_date(s, &tm))
822      return;      return;
823    time1 = mktime(&tm);    time1 = mktime_from_utc(&tm);
824    
825    diff = difftime(time1, time0);    diff = difftime(time1, time0);
826    if (10 < diff)    if (10 < diff)
# Line 985  struct message_entry { Line 1089  struct message_entry {
1089    { "via", "This header was added by a proxy, cache or gateway." },    { "via", "This header was added by a proxy, cache or gateway." },
1090    { "wrongdate", "Warning: The server date-time differs from this system's "    { "wrongdate", "Warning: The server date-time differs from this system's "
1091                   "date-time by more than 10 seconds. Check that both the "                   "date-time by more than 10 seconds. Check that both the "
1092                   "system clocks are correct." }                   "system clocks are correct." },
1093      { "xheader", "This is an extension header. I don't know how to check it." }
1094  };  };
1095    
1096    

Legend:
Removed from v.40  
changed lines
  Added in v.44

  ViewVC Help
Powered by ViewVC 1.1.26