| 1419 | #undef DM_HTTPCLIENT_RESULT_TO_STRING_CASE |
| 1420 | |
| 1421 | ParseResult ParseHeader(char* header_str, |
| 1422 | void* user_data, |
| 1423 | bool end_of_receive, |
| 1424 | void (*version)(void* user_data, int major, int minor, int status, const char* status_str), |
| 1425 | void (*header)(void* user_data, const char* key, const char* value), |
| 1426 | void (*body)(void* user_data, int offset)) |
| 1427 | { |
| 1428 | // Check if we have a body section by searching for two new-lines, do this before parsing version since we do destructive string termination |
| 1429 | char* body_start = strstr(header_str, "\r\n\r\n"); |
| 1430 | |
| 1431 | // Always try to parse version and status |
| 1432 | char* version_str = header_str; |
| 1433 | char* end_version = strstr(header_str, "\r\n"); |
| 1434 | if (end_version == 0) |
| 1435 | return PARSE_RESULT_NEED_MORE_DATA; |
| 1436 | |
| 1437 | char store_end_version = *end_version; |
| 1438 | *end_version = '\0'; |
| 1439 | |
| 1440 | int major, minor, status; |
| 1441 | int count = sscanf(version_str, "HTTP/%d.%d %d", &major, &minor, &status); |
| 1442 | if (count != 3) |
| 1443 | { |
| 1444 | return PARSE_RESULT_SYNTAX_ERROR; |
| 1445 | } |
| 1446 | |
| 1447 | if (body_start != 0) |
| 1448 | { |
| 1449 | // Skip \r\n\r\n |
| 1450 | body_start += 4; |
| 1451 | } |
| 1452 | else |
| 1453 | { |
| 1454 | // According to the HTTP spec, all responses should end with double line feed to indicate end of headers |
| 1455 | // Unfortunately some server implementations only end with one linefeed if the response is '204 No Content' so we take special measures |
| 1456 | // to force parsing of headers if we have received no more data and the we get a 204 status |
| 1457 | if(end_of_receive && status == 204) |
| 1458 | { |
| 1459 | // Treat entire input as just headers |
| 1460 | body_start = (end_version + 1) + strlen(end_version + 1); |
| 1461 | } |
| 1462 | else |
| 1463 | { |
| 1464 | // Restore string termination since we need more data and will likely try again |
| 1465 | *end_version = store_end_version; |
| 1466 | return PARSE_RESULT_NEED_MORE_DATA; |
| 1467 | } |
| 1468 | } |
| 1469 | |
| 1470 | // Find status string, ie "OK" in "HTTP/1.1 200 OK" |
| 1471 | char* status_string = strchr(version_str, ' '); |
| 1472 | status_string = status_string ? strchr(status_string + 1, ' ') : 0; |
| 1473 | if (status_string == 0) |
| 1474 | return PARSE_RESULT_SYNTAX_ERROR; |
| 1475 | |
| 1476 | version(user_data, major, minor, status, status_string + 1); |
| 1477 | |
| 1478 | char store_body_start = *body_start; |