Mercurial
comparison seobeo/s_web.c @ 231:09a96dcb2b4c hg-web
[merge] Join existing hg-web branch head
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Sun, 02 Aug 2026 16:50:48 -0700 |
| parents | 0e7b9464248d |
| children | 543df0fe7168 |
comparison
equal
deleted
inserted
replaced
| 217:7ef4c9d2a72d | 231:09a96dcb2b4c |
|---|---|
| 49 const char *status_text; | 49 const char *status_text; |
| 50 switch(status) | 50 switch(status) |
| 51 { | 51 { |
| 52 case HTTP_OK: status_text = "OK"; break; | 52 case HTTP_OK: status_text = "OK"; break; |
| 53 case HTTP_CREATED: status_text = "Created"; break; | 53 case HTTP_CREATED: status_text = "Created"; break; |
| 54 case HTTP_NO_CONTENT: status_text = "No Content"; break; | |
| 54 case HTTP_MOVED_PERMANENTLY: status_text = "Moved Permanently"; break; | 55 case HTTP_MOVED_PERMANENTLY: status_text = "Moved Permanently"; break; |
| 55 case HTTP_FOUND: status_text = "Found"; break; | 56 case HTTP_FOUND: status_text = "Found"; break; |
| 56 case HTTP_BAD_REQUEST: status_text = "Bad Request"; break; | 57 case HTTP_BAD_REQUEST: status_text = "Bad Request"; break; |
| 57 case HTTP_UNAUTHORIZED: status_text = "Unauthorized"; break; | 58 case HTTP_UNAUTHORIZED: status_text = "Unauthorized"; break; |
| 58 case HTTP_FORBIDDEN: status_text = "Forbidden"; break; | 59 case HTTP_FORBIDDEN: status_text = "Forbidden"; break; |
| 59 case HTTP_NOT_FOUND: status_text = "Not Found"; break; | 60 case HTTP_NOT_FOUND: status_text = "Not Found"; break; |
| 60 case HTTP_INTERNAL_ERROR: status_text = "Internal Server Error"; break; | 61 case HTTP_INTERNAL_ERROR: status_text = "Internal Server Error"; break; |
| 62 case 502: status_text = "Bad Gateway"; break; | |
| 63 case 504: status_text = "Gateway Timeout"; break; | |
| 61 default: status_text = "Unknown"; break; | 64 default: status_text = "Unknown"; break; |
| 62 } | 65 } |
| 63 | 66 |
| 64 sprintf( | 67 snprintf( |
| 65 buffer, | 68 (char*)buffer, 1024, |
| 66 "HTTP/1.1 %d %s\r\n" | 69 "HTTP/1.1 %d %s\r\n" |
| 67 "Content-Type: %s\r\n" | 70 "Content-Type: %s\r\n" |
| 68 "Content-Length: %d\r\n" | 71 "Content-Length: %d\r\n" |
| 69 "Connection: %s\r\n" | 72 "Connection: %s\r\n" |
| 70 "\r\n", | 73 "\r\n", |
| 772 Dowa_Arena *p_arena) | 775 Dowa_Arena *p_arena) |
| 773 { | 776 { |
| 774 Seobeo_Router_Send_Response_KeepAlive(p_handle, p_response_map, p_arena, FALSE); | 777 Seobeo_Router_Send_Response_KeepAlive(p_handle, p_response_map, p_arena, FALSE); |
| 775 } | 778 } |
| 776 | 779 |
| 780 static boolean Seobeo_Response_Header_Value_Is_Safe(const char *value) | |
| 781 { | |
| 782 return value && strchr(value, '\r') == NULL && strchr(value, '\n') == NULL; | |
| 783 } | |
| 784 | |
| 777 void Seobeo_Router_Send_Response_KeepAlive( | 785 void Seobeo_Router_Send_Response_KeepAlive( |
| 778 Seobeo_Handle *p_handle, | 786 Seobeo_Handle *p_handle, |
| 779 Seobeo_Request_Entry *p_response_map, | 787 Seobeo_Request_Entry *p_response_map, |
| 780 Dowa_Arena *p_arena, | 788 Dowa_Arena *p_arena, |
| 781 boolean keep_alive) | 789 boolean keep_alive) |
| 817 body_length = atoi(content_length_str); | 825 body_length = atoi(content_length_str); |
| 818 } | 826 } |
| 819 else | 827 else |
| 820 body_length = strlen(body); | 828 body_length = strlen(body); |
| 821 | 829 |
| 822 char *header = Dowa_Arena_Allocate(p_arena, 4096); | 830 size_t header_capacity = 1024; |
| 823 Seobeo_Web_Header_Generate_KeepAlive(header, status, content_type, body_length, keep_alive); | |
| 824 for (int i = 0; i < Dowa_Array_Length(p_response_map); i++) | 831 for (int i = 0; i < Dowa_Array_Length(p_response_map); i++) |
| 825 { | 832 { |
| 833 const char *key = p_response_map[i].key; | |
| 834 const char *value = p_response_map[i].value; | |
| 826 if ( | 835 if ( |
| 827 strstr(p_response_map[i].key, "status") || | 836 strcasecmp(key, "status") == 0 || |
| 828 strstr(p_response_map[i].key, "body") || | 837 strcasecmp(key, "body") == 0 || |
| 829 strstr(p_response_map[i].key, "content-type") || | 838 strcasecmp(key, "content-type") == 0 || |
| 830 strstr(p_response_map[i].key, "content-length") | 839 strcasecmp(key, "content-length") == 0 |
| 831 ) | 840 ) |
| 832 continue; | 841 continue; |
| 833 | 842 if (Seobeo_Response_Header_Value_Is_Safe(key) && |
| 834 int32 current_header_len = strlen(header); | 843 Seobeo_Response_Header_Value_Is_Safe(value)) |
| 835 char *temp = malloc(sizeof(char) * 1024); | 844 header_capacity += strlen(key) + strlen(value) + 4; |
| 836 sprintf(temp, "%s: %s\r\n\r\n", p_response_map[i].key, p_response_map[i].value); | 845 } |
| 837 memcpy(&header[current_header_len - 2 /* \r\n */], temp, strlen(temp)); | 846 |
| 838 free(temp); | 847 char *header = Dowa_Arena_Allocate(p_arena, header_capacity); |
| 839 } | 848 Seobeo_Web_Header_Generate_KeepAlive(header, status, content_type, body_length, keep_alive); |
| 840 | 849 size_t header_length = strlen(header); |
| 841 printf("hEADER %s\n", header); | 850 if (header_length < 2) |
| 851 return; | |
| 852 header_length -= 2; | |
| 853 | |
| 854 for (int i = 0; i < Dowa_Array_Length(p_response_map); i++) | |
| 855 { | |
| 856 const char *key = p_response_map[i].key; | |
| 857 const char *value = p_response_map[i].value; | |
| 858 if ( | |
| 859 strcasecmp(key, "status") == 0 || | |
| 860 strcasecmp(key, "body") == 0 || | |
| 861 strcasecmp(key, "content-type") == 0 || | |
| 862 strcasecmp(key, "content-length") == 0 | |
| 863 ) | |
| 864 continue; | |
| 865 | |
| 866 if (!Seobeo_Response_Header_Value_Is_Safe(key) || | |
| 867 !Seobeo_Response_Header_Value_Is_Safe(value)) | |
| 868 { | |
| 869 Seobeo_Log(SEOBEO_WARNING, "Skipping unsafe response header\n"); | |
| 870 continue; | |
| 871 } | |
| 872 | |
| 873 int written = snprintf( | |
| 874 header + header_length, | |
| 875 header_capacity - header_length, | |
| 876 "%s: %s\r\n", | |
| 877 key, | |
| 878 value); | |
| 879 if (written < 0 || (size_t)written >= header_capacity - header_length) | |
| 880 { | |
| 881 Seobeo_Log(SEOBEO_ERROR, "Response header exceeded allocated capacity\n"); | |
| 882 return; | |
| 883 } | |
| 884 header_length += (size_t)written; | |
| 885 } | |
| 886 memcpy(header + header_length, "\r\n", 3); | |
| 842 | 887 |
| 843 Seobeo_Handle_Queue(p_handle, (uint8_t*)header, strlen(header)); | 888 Seobeo_Handle_Queue(p_handle, (uint8_t*)header, strlen(header)); |
| 844 Seobeo_Handle_Queue(p_handle, (uint8_t*)body, body_length); | 889 Seobeo_Handle_Queue(p_handle, (uint8_t*)body, body_length); |
| 845 Seobeo_Handle_Flush(p_handle); | 890 Seobeo_Handle_Flush(p_handle); |
| 846 } | 891 } |