| 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 |
const char *skip_lws(const char *s); |
const char *skip_lws(const char *s); |
| 53 |
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, |
| 54 |
void (*callback)(const char *s, regmatch_t pmatch[])); |
void (*callback)(const char *s, regmatch_t pmatch[])); |
| 206 |
regcomp_wrapper(&re_ugly, |
regcomp_wrapper(&re_ugly, |
| 207 |
"^[a-zA-Z0-9]+://[^/]+[/a-zA-Z0-9-_]*$", |
"^[a-zA-Z0-9]+://[^/]+[/a-zA-Z0-9-_]*$", |
| 208 |
REG_EXTENDED); |
REG_EXTENDED); |
| 209 |
|
regcomp_wrapper(&re_rfc1123, |
| 210 |
|
"^(Mon|Tue|Wed|Thu|Fri|Sat|Sun), ([0123][0-9]) " |
| 211 |
|
"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ([0-9]{4}) " |
| 212 |
|
"([012][0-9]):([0-5][0-9]):([0-5][0-9]) GMT$", |
| 213 |
|
REG_EXTENDED); |
| 214 |
|
regcomp_wrapper(&re_rfc1036, |
| 215 |
|
"^(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday), " |
| 216 |
|
"([0123][0-9])-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-" |
| 217 |
|
"([0-9][0-9]) ([012][0-9]):([0-5][0-9]):([0-5][0-9]) GMT$", |
| 218 |
|
REG_EXTENDED); |
| 219 |
|
regcomp_wrapper(&re_asctime, |
| 220 |
|
"^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) " |
| 221 |
|
"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ([ 12][0-9]) " |
| 222 |
|
"([012][0-9]):([0-5][0-9]):([0-5][0-9]) ([0-9]{4})$", |
| 223 |
|
REG_EXTENDED); |
| 224 |
} |
} |
| 225 |
|
|
| 226 |
|
|
| 407 |
*/ |
*/ |
| 408 |
bool parse_date(const char *s, struct tm *tm) |
bool parse_date(const char *s, struct tm *tm) |
| 409 |
{ |
{ |
| 410 |
char *r; |
int r; |
| 411 |
int len = strlen(s); |
int len = strlen(s); |
| 412 |
|
regmatch_t pmatch[20]; |
| 413 |
|
|
| 414 |
|
tm->tm_wday = 0; |
| 415 |
|
tm->tm_yday = 0; |
| 416 |
|
tm->tm_isdst = 0; |
| 417 |
|
tm->tm_gmtoff = 0; |
| 418 |
|
tm->tm_zone = "GMT"; |
| 419 |
|
|
| 420 |
if (len == 29) { |
if (len == 29) { |
| 421 |
/* RFC 1123 */ |
/* RFC 1123 */ |
| 422 |
r = strptime(s, "%a, %d %b %Y %H:%M:%S GMT", tm); |
r = regexec(&re_rfc1123, s, 20, pmatch, 0); |
| 423 |
if (r == s + len) |
if (r == 0) { |
| 424 |
|
tm->tm_mday = atoi(s + pmatch[2].rm_so); |
| 425 |
|
tm->tm_mon = month(s + pmatch[3].rm_so); |
| 426 |
|
tm->tm_year = atoi(s + pmatch[4].rm_so) - 1900; |
| 427 |
|
tm->tm_hour = atoi(s + pmatch[5].rm_so); |
| 428 |
|
tm->tm_min = atoi(s + pmatch[6].rm_so); |
| 429 |
|
tm->tm_sec = atoi(s + pmatch[7].rm_so); |
| 430 |
return true; |
return true; |
| 431 |
|
} |
| 432 |
|
|
| 433 |
} else if (len == 24) { |
} else if (len == 24) { |
| 434 |
/* asctime() format */ |
/* asctime() format */ |
| 435 |
r = strptime(s, "%a %b %d %H:%M:%S %Y", tm); |
r = regexec(&re_asctime, s, 20, pmatch, 0); |
| 436 |
if (r == s + len) { |
if (r == 0) { |
| 437 |
lookup("asctime"); |
if (s[pmatch[3].rm_so] == ' ') |
| 438 |
return true; |
tm->tm_mday = atoi(s + pmatch[3].rm_so + 1); |
| 439 |
} |
else |
| 440 |
r = strptime(s, "%a %b %d %H:%M:%S %Y", tm); |
tm->tm_mday = atoi(s + pmatch[3].rm_so); |
| 441 |
if (r == s + len) { |
tm->tm_mon = month(s + pmatch[2].rm_so); |
| 442 |
|
tm->tm_year = atoi(s + pmatch[7].rm_so) - 1900; |
| 443 |
|
tm->tm_hour = atoi(s + pmatch[4].rm_so); |
| 444 |
|
tm->tm_min = atoi(s + pmatch[5].rm_so); |
| 445 |
|
tm->tm_sec = atoi(s + pmatch[6].rm_so); |
| 446 |
lookup("asctime"); |
lookup("asctime"); |
| 447 |
return true; |
return true; |
| 448 |
} |
} |
| 449 |
|
|
| 450 |
} else { |
} else { |
| 451 |
/* RFC 1036 */ |
/* RFC 1036 */ |
| 452 |
r = strptime(s, "%a, %d-%b-%y %H:%M:%S GMT", tm); |
r = regexec(&re_rfc1036, s, 20, pmatch, 0); |
| 453 |
if (r == s + len) { |
if (r == 0) { |
| 454 |
|
tm->tm_mday = atoi(s + pmatch[2].rm_so); |
| 455 |
|
tm->tm_mon = month(s + pmatch[3].rm_so); |
| 456 |
|
tm->tm_year = 100 + atoi(s + pmatch[4].rm_so); |
| 457 |
|
tm->tm_hour = atoi(s + pmatch[5].rm_so); |
| 458 |
|
tm->tm_min = atoi(s + pmatch[6].rm_so); |
| 459 |
|
tm->tm_sec = atoi(s + pmatch[7].rm_so); |
| 460 |
lookup("rfc1036"); |
lookup("rfc1036"); |
| 461 |
return true; |
return true; |
| 462 |
} |
} |
| 468 |
} |
} |
| 469 |
|
|
| 470 |
|
|
| 471 |
|
/** |
| 472 |
|
* Convert a month name to the month number. |
| 473 |
|
*/ |
| 474 |
|
int month(const char *s) |
| 475 |
|
{ |
| 476 |
|
switch (s[0]) { |
| 477 |
|
case 'J': |
| 478 |
|
switch (s[1]) { |
| 479 |
|
case 'a': |
| 480 |
|
return 0; |
| 481 |
|
case 'u': |
| 482 |
|
return s[2] == 'n' ? 5 : 6; |
| 483 |
|
} |
| 484 |
|
case 'F': |
| 485 |
|
return 1; |
| 486 |
|
case 'M': |
| 487 |
|
return s[2] == 'r' ? 2 : 4; |
| 488 |
|
case 'A': |
| 489 |
|
return s[1] == 'p' ? 3 : 7; |
| 490 |
|
case 'S': |
| 491 |
|
return 8; |
| 492 |
|
case 'O': |
| 493 |
|
return 9; |
| 494 |
|
case 'N': |
| 495 |
|
return 10; |
| 496 |
|
case 'D': |
| 497 |
|
return 11; |
| 498 |
|
} |
| 499 |
|
return 0; |
| 500 |
|
} |
| 501 |
|
|
| 502 |
|
|
| 503 |
/** |
/** |
| 504 |
* Skip optional LWS (linear white space) [2.2] |
* Skip optional LWS (linear white space) [2.2] |
| 505 |
*/ |
*/ |