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); |
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[])); |
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 |
|
|
408 |
*/ |
*/ |
409 |
bool parse_date(const char *s, struct tm *tm) |
bool parse_date(const char *s, struct tm *tm) |
410 |
{ |
{ |
411 |
char *r; |
int r; |
412 |
int len = strlen(s); |
int len = strlen(s); |
413 |
|
regmatch_t pmatch[20]; |
414 |
|
|
415 |
if (len == 29) { |
if (len == 29) { |
416 |
/* RFC 1123 */ |
/* RFC 1123 */ |
417 |
r = strptime(s, "%a, %d %b %Y %H:%M:%S GMT", tm); |
r = regexec(&re_rfc1123, s, 20, pmatch, 0); |
418 |
if (r == s + len) |
if (r == 0) { |
419 |
|
tm->tm_mday = atoi(s + pmatch[2].rm_so); |
420 |
|
tm->tm_mon = month(s + pmatch[3].rm_so); |
421 |
|
tm->tm_year = atoi(s + pmatch[4].rm_so) - 1900; |
422 |
|
tm->tm_hour = atoi(s + pmatch[5].rm_so); |
423 |
|
tm->tm_min = atoi(s + pmatch[6].rm_so); |
424 |
|
tm->tm_sec = atoi(s + pmatch[7].rm_so); |
425 |
return true; |
return true; |
426 |
|
} |
427 |
|
|
428 |
} else if (len == 24) { |
} else if (len == 24) { |
429 |
/* asctime() format */ |
/* asctime() format */ |
430 |
r = strptime(s, "%a %b %d %H:%M:%S %Y", tm); |
r = regexec(&re_asctime, s, 20, pmatch, 0); |
431 |
if (r == s + len) { |
if (r == 0) { |
432 |
lookup("asctime"); |
if (s[pmatch[3].rm_so] == ' ') |
433 |
return true; |
tm->tm_mday = atoi(s + pmatch[3].rm_so + 1); |
434 |
} |
else |
435 |
r = strptime(s, "%a %b %d %H:%M:%S %Y", tm); |
tm->tm_mday = atoi(s + pmatch[3].rm_so); |
436 |
if (r == s + len) { |
tm->tm_mon = month(s + pmatch[2].rm_so); |
437 |
|
tm->tm_year = atoi(s + pmatch[7].rm_so) - 1900; |
438 |
|
tm->tm_hour = atoi(s + pmatch[4].rm_so); |
439 |
|
tm->tm_min = atoi(s + pmatch[5].rm_so); |
440 |
|
tm->tm_sec = atoi(s + pmatch[6].rm_so); |
441 |
lookup("asctime"); |
lookup("asctime"); |
442 |
return true; |
return true; |
443 |
} |
} |
444 |
|
|
445 |
} else { |
} else { |
446 |
/* RFC 1036 */ |
/* RFC 1036 */ |
447 |
r = strptime(s, "%a, %d-%b-%y %H:%M:%S GMT", tm); |
r = regexec(&re_rfc1036, s, 20, pmatch, 0); |
448 |
if (r == s + len) { |
if (r == 0) { |
449 |
|
tm->tm_mday = atoi(s + pmatch[2].rm_so); |
450 |
|
tm->tm_mon = month(s + pmatch[3].rm_so); |
451 |
|
tm->tm_year = 100 + atoi(s + pmatch[4].rm_so); |
452 |
|
tm->tm_hour = atoi(s + pmatch[5].rm_so); |
453 |
|
tm->tm_min = atoi(s + pmatch[6].rm_so); |
454 |
|
tm->tm_sec = atoi(s + pmatch[7].rm_so); |
455 |
lookup("rfc1036"); |
lookup("rfc1036"); |
456 |
return true; |
return true; |
457 |
} |
} |
464 |
|
|
465 |
|
|
466 |
/** |
/** |
467 |
|
* Convert a month name to the month number. |
468 |
|
*/ |
469 |
|
int month(const char *s) |
470 |
|
{ |
471 |
|
switch (s[0]) { |
472 |
|
case 'J': |
473 |
|
switch (s[1]) { |
474 |
|
case 'a': |
475 |
|
return 0; |
476 |
|
case 'u': |
477 |
|
return s[2] == 'n' ? 5 : 6; |
478 |
|
} |
479 |
|
case 'F': |
480 |
|
return 1; |
481 |
|
case 'M': |
482 |
|
return s[2] == 'r' ? 2 : 4; |
483 |
|
case 'A': |
484 |
|
return s[1] == 'p' ? 3 : 7; |
485 |
|
case 'S': |
486 |
|
return 8; |
487 |
|
case 'O': |
488 |
|
return 9; |
489 |
|
case 'N': |
490 |
|
return 10; |
491 |
|
case 'D': |
492 |
|
return 11; |
493 |
|
} |
494 |
|
return 0; |
495 |
|
} |
496 |
|
|
497 |
|
|
498 |
|
/** |
499 |
|
* UTC version of mktime, from |
500 |
|
* http://lists.debian.org/deity/2002/deity-200204/msg00082.html |
501 |
|
*/ |
502 |
|
time_t mktime_from_utc(struct tm *t) |
503 |
|
{ |
504 |
|
time_t tl, tb; |
505 |
|
struct tm *tg; |
506 |
|
|
507 |
|
tl = mktime (t); |
508 |
|
if (tl == -1) |
509 |
|
{ |
510 |
|
t->tm_hour--; |
511 |
|
tl = mktime (t); |
512 |
|
if (tl == -1) |
513 |
|
return -1; /* can't deal with output from strptime */ |
514 |
|
tl += 3600; |
515 |
|
} |
516 |
|
tg = gmtime (&tl); |
517 |
|
tg->tm_isdst = 0; |
518 |
|
tb = mktime (tg); |
519 |
|
if (tb == -1) |
520 |
|
{ |
521 |
|
tg->tm_hour--; |
522 |
|
tb = mktime (tg); |
523 |
|
if (tb == -1) |
524 |
|
return -1; /* can't deal with output from gmtime */ |
525 |
|
tb += 3600; |
526 |
|
} |
527 |
|
return (tl - (tb - tl)); |
528 |
|
} |
529 |
|
|
530 |
|
|
531 |
|
/** |
532 |
* Skip optional LWS (linear white space) [2.2] |
* Skip optional LWS (linear white space) [2.2] |
533 |
*/ |
*/ |
534 |
const char *skip_lws(const char *s) |
const char *skip_lws(const char *s) |
782 |
time0 = time(0); |
time0 = time(0); |
783 |
if (!parse_date(s, &tm)) |
if (!parse_date(s, &tm)) |
784 |
return; |
return; |
785 |
time1 = mktime(&tm); |
time1 = mktime_from_utc(&tm); |
786 |
|
|
787 |
diff = difftime(time0, time1); |
diff = difftime(time0, time1); |
788 |
if (10 < fabs(diff)) |
if (10 < fabs(diff)) |