| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* GATE PROJECT LICENSE: | ||
| 2 | +----------------------------------------------------------------------------+ | ||
| 3 | | Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> | | ||
| 4 | | All rights reserved. | | ||
| 5 | | | | ||
| 6 | | Redistribution and use in source and binary forms, with or without | | ||
| 7 | | modification, are permitted provided that the following conditions are met:| | ||
| 8 | | | | ||
| 9 | | 1. Redistributions of source code must retain the above copyright notice, | | ||
| 10 | | this list of conditions and the following disclaimer. | | ||
| 11 | | 2. Redistributions in binary form must reproduce the above copyright | | ||
| 12 | | notice, this list of conditions and the following disclaimer in the | | ||
| 13 | | documentation and/or other materials provided with the distribution. | | ||
| 14 | | | | ||
| 15 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"| | ||
| 16 | | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | ||
| 17 | | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | ||
| 18 | | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | | ||
| 19 | | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | ||
| 20 | | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | ||
| 21 | | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | ||
| 22 | | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | ||
| 23 | | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | ||
| 24 | | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | | ||
| 25 | | THE POSSIBILITY OF SUCH DAMAGE. | | ||
| 26 | +----------------------------------------------------------------------------+ | ||
| 27 | */ | ||
| 28 | #include "gate/net/httptypes.h" | ||
| 29 | |||
| 30 | #include "gate/results.h" | ||
| 31 | #include "gate/utilities.h" | ||
| 32 | #include "gate/uris.h" | ||
| 33 | |||
| 34 | 1 | gate_result_t gate_http_request_init_str(gate_http_request_t* request, char const* method, char const* path) | |
| 35 | { | ||
| 36 | gate_result_t ret; | ||
| 37 | gate_string_t str_method, str_path; | ||
| 38 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | if (NULL == gate_string_create(&str_method, method, gate_str_length(method))) |
| 39 | { | ||
| 40 | ✗ | return GATE_RESULT_OUTOFMEMORY; | |
| 41 | } | ||
| 42 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | if (NULL == gate_string_create(&str_path, path, gate_str_length(path))) |
| 43 | { | ||
| 44 | ✗ | gate_string_release(&str_method); | |
| 45 | ✗ | return GATE_RESULT_OUTOFMEMORY; | |
| 46 | } | ||
| 47 | 1 | ret = gate_http_request_init(request, &str_method, &str_path); | |
| 48 | 1 | gate_string_release(&str_path); | |
| 49 | 1 | gate_string_release(&str_method); | |
| 50 | 1 | return ret; | |
| 51 | } | ||
| 52 | |||
| 53 | |||
| 54 | 10 | gate_result_t gate_http_request_init(gate_http_request_t* request, gate_string_t const* method, gate_string_t const* path) | |
| 55 | { | ||
| 56 | 10 | gate_mem_clear(request, sizeof(gate_http_request_t)); | |
| 57 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
|
10 | if (method != NULL) |
| 58 | { | ||
| 59 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
8 | if (NULL == gate_string_clone(&request->method, method)) |
| 60 | { | ||
| 61 | ✗ | return GATE_RESULT_OUTOFMEMORY; | |
| 62 | } | ||
| 63 | } | ||
| 64 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
|
10 | if (path != NULL) |
| 65 | { | ||
| 66 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
8 | if (NULL == gate_string_clone(&request->path, path)) |
| 67 | { | ||
| 68 | ✗ | gate_http_request_release(request); | |
| 69 | ✗ | return GATE_RESULT_OUTOFMEMORY; | |
| 70 | } | ||
| 71 | } | ||
| 72 | |||
| 73 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
|
10 | if (NULL == gate_util_stringmap_create_ex(&request->headers, true, true)) |
| 74 | { | ||
| 75 | ✗ | gate_http_request_release(request); | |
| 76 | ✗ | return GATE_RESULT_OUTOFMEMORY; | |
| 77 | } | ||
| 78 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
|
10 | if (NULL == gate_util_stringset_create(&request->accept_types)) |
| 79 | { | ||
| 80 | ✗ | gate_http_request_release(request); | |
| 81 | ✗ | return GATE_RESULT_OUTOFMEMORY; | |
| 82 | } | ||
| 83 | 10 | return GATE_RESULT_OK; | |
| 84 | } | ||
| 85 | |||
| 86 | ✗ | gate_result_t gate_http_request_init_uri(gate_http_request_t* request, gate_string_t const* method, gate_uri_t* uri) | |
| 87 | { | ||
| 88 | gate_result_t ret; | ||
| 89 | ✗ | gate_string_t path = GATE_STRING_INIT_EMPTY; | |
| 90 | |||
| 91 | do | ||
| 92 | { | ||
| 93 | ✗ | ret = gate_uri_to_string(uri, &path, true); | |
| 94 | ✗ | GATE_BREAK_IF_FAILED(ret); | |
| 95 | |||
| 96 | ✗ | ret = gate_http_request_init(request, method, &path); | |
| 97 | ✗ | GATE_BREAK_IF_FAILED(ret); | |
| 98 | |||
| 99 | ✗ | if (!gate_string_is_empty(&uri->user_info)) | |
| 100 | { | ||
| 101 | ✗ | ret = gate_uri_parse_user_info(&uri->user_info, &request->auth_user, &request->auth_pass); | |
| 102 | ✗ | GATE_BREAK_IF_FAILED(ret); | |
| 103 | } | ||
| 104 | |||
| 105 | } while (0); | ||
| 106 | |||
| 107 | ✗ | gate_string_release(&path); | |
| 108 | |||
| 109 | ✗ | return ret; | |
| 110 | } | ||
| 111 | |||
| 112 | |||
| 113 | |||
| 114 | 4 | gate_result_t gate_http_request_copy(gate_http_request_t* request, gate_http_request_t const* src) | |
| 115 | { | ||
| 116 | 4 | gate_result_t ret = GATE_RESULT_OUTOFMEMORY; | |
| 117 | 4 | gate_mem_clear(request, sizeof(gate_http_request_t)); | |
| 118 | do | ||
| 119 | { | ||
| 120 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
4 | if (!gate_string_clone(&request->method, &src->method)) break; |
| 121 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
4 | if (!gate_string_clone(&request->path, &src->path)) break; |
| 122 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
4 | if (!gate_string_clone(&request->version, &src->version)) break; |
| 123 | |||
| 124 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
4 | if (!gate_string_clone(&request->auth_user, &src->auth_user)) break; |
| 125 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
4 | if (!gate_string_clone(&request->auth_pass, &src->auth_pass)) break; |
| 126 | |||
| 127 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
4 | if (!gate_map_copy(&request->headers, &src->headers)) break; |
| 128 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
4 | if (!gate_set_copy(&request->accept_types, &src->accept_types)) break; |
| 129 | |||
| 130 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
4 | if (!gate_string_clone(&request->proxy_server, &src->proxy_server)) break; |
| 131 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
4 | if (!gate_string_clone(&request->proxy_user, &src->proxy_user)) break; |
| 132 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
4 | if (!gate_string_clone(&request->proxy_pass, &src->proxy_pass)) break; |
| 133 | |||
| 134 | 4 | request->upload_stream = src->upload_stream; | |
| 135 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
|
4 | if (request->upload_stream) |
| 136 | { | ||
| 137 | 2 | gate_object_retain(request->upload_stream); | |
| 138 | } | ||
| 139 | |||
| 140 | 4 | request->connect_timeout_ms = src->connect_timeout_ms; | |
| 141 | 4 | request->send_timeout_ms = src->send_timeout_ms; | |
| 142 | 4 | request->receive_timeout_ms = src->receive_timeout_ms; | |
| 143 | 4 | request->proxy_port = src->proxy_port; | |
| 144 | |||
| 145 | 4 | ret = GATE_RESULT_OK; | |
| 146 | |||
| 147 | } while (0); | ||
| 148 | |||
| 149 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (GATE_FAILED(ret)) |
| 150 | { | ||
| 151 | ✗ | gate_http_request_release(request); | |
| 152 | } | ||
| 153 | 4 | return ret; | |
| 154 | } | ||
| 155 | |||
| 156 | 14 | gate_result_t gate_http_request_release(gate_http_request_t* request) | |
| 157 | { | ||
| 158 | 14 | gate_string_release(&request->method); | |
| 159 | 14 | gate_string_release(&request->path); | |
| 160 | 14 | gate_string_release(&request->version); | |
| 161 | |||
| 162 | 14 | gate_string_release(&request->auth_user); | |
| 163 | 14 | gate_string_release(&request->auth_pass); | |
| 164 | |||
| 165 | 14 | gate_map_destroy(&request->headers); | |
| 166 | 14 | gate_set_destroy(&request->accept_types); | |
| 167 | |||
| 168 | 14 | gate_string_release(&request->proxy_server); | |
| 169 | 14 | gate_string_release(&request->proxy_user); | |
| 170 | 14 | gate_string_release(&request->proxy_pass); | |
| 171 | |||
| 172 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 9 times.
|
14 | if (request->upload_stream != NULL) |
| 173 | { | ||
| 174 | 5 | gate_object_release(request->upload_stream); | |
| 175 | } | ||
| 176 | |||
| 177 | 14 | gate_mem_clear(request, sizeof(gate_http_request_t)); | |
| 178 | 14 | return GATE_RESULT_OK; | |
| 179 | } | ||
| 180 | |||
| 181 | |||
| 182 | 10 | gate_result_t gate_http_response_init(gate_http_response_t* response) | |
| 183 | { | ||
| 184 | 10 | gate_result_t ret = GATE_RESULT_FAILED; | |
| 185 | do | ||
| 186 | { | ||
| 187 | 10 | gate_mem_clear(response, sizeof(gate_http_response_t)); | |
| 188 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
|
10 | if (NULL == gate_util_stringmap_create_ex(&response->headers, true, true)) |
| 189 | { | ||
| 190 | ✗ | ret = GATE_RESULT_OUTOFMEMORY; | |
| 191 | ✗ | break; | |
| 192 | } | ||
| 193 | } while (0); | ||
| 194 | 10 | return GATE_RESULT_OK; | |
| 195 | } | ||
| 196 | |||
| 197 | 2 | gate_result_t gate_http_response_copy(gate_http_response_t* response, gate_http_response_t const* src) | |
| 198 | { | ||
| 199 | 2 | gate_result_t ret = GATE_RESULT_OK; | |
| 200 | do | ||
| 201 | { | ||
| 202 | 2 | gate_mem_clear(response, sizeof(gate_http_response_t)); | |
| 203 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | if (NULL == gate_map_copy(&response->headers, &src->headers)) |
| 204 | { | ||
| 205 | ✗ | ret = GATE_RESULT_OUTOFMEMORY; | |
| 206 | ✗ | break; | |
| 207 | } | ||
| 208 | 2 | response->response_stream = src->response_stream; | |
| 209 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (response->response_stream) |
| 210 | { | ||
| 211 | ✗ | gate_object_retain(response->response_stream); | |
| 212 | } | ||
| 213 | 2 | response->status_code = src->status_code; | |
| 214 | 2 | ret = GATE_RESULT_OK; | |
| 215 | } while (0); | ||
| 216 | 2 | return ret; | |
| 217 | } | ||
| 218 | |||
| 219 | 10 | gate_result_t gate_http_response_release(gate_http_response_t* response) | |
| 220 | { | ||
| 221 | 10 | gate_map_destroy(&response->headers); | |
| 222 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 4 times.
|
10 | if (NULL != response->response_stream) |
| 223 | { | ||
| 224 | 6 | gate_object_release(response->response_stream); | |
| 225 | } | ||
| 226 | 10 | gate_mem_clear(response, sizeof(gate_http_response_t)); | |
| 227 | 10 | return GATE_RESULT_OK; | |
| 228 | } | ||
| 229 | |||
| 230 | 2 | char const* gate_http_response_status_text(gate_uint32_t status_code) | |
| 231 | { | ||
| 232 |
1/66✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
|
2 | switch (status_code) |
| 233 | { | ||
| 234 | ✗ | case 100: return "Continue"; | |
| 235 | ✗ | case 101: return "Switching Protocols"; | |
| 236 | ✗ | case 102: return "Processing"; | |
| 237 | ✗ | case 103: return "Early Hints"; | |
| 238 | 2 | case 200: return "OK"; | |
| 239 | ✗ | case 201: return "Created"; | |
| 240 | ✗ | case 202: return "Accepted"; | |
| 241 | ✗ | case 203: return "Non-Authoritative Information"; | |
| 242 | ✗ | case 204: return "No Content"; | |
| 243 | ✗ | case 205: return "Reset Content"; | |
| 244 | ✗ | case 206: return "Partial Content"; | |
| 245 | ✗ | case 207: return "Multi-Status"; | |
| 246 | ✗ | case 208: return "Already Reported"; | |
| 247 | ✗ | case 226: return "IM Used"; | |
| 248 | ✗ | case 300: return "Multiple Choices"; | |
| 249 | ✗ | case 301: return "Moved Permanently"; | |
| 250 | ✗ | case 302: return "Found"; | |
| 251 | ✗ | case 303: return "See Other"; | |
| 252 | ✗ | case 304: return "Not Modified"; | |
| 253 | ✗ | case 305: return "Use Proxy"; | |
| 254 | ✗ | case 306: return "Switch Proxy"; | |
| 255 | ✗ | case 307: return "Temporary Redirect"; | |
| 256 | ✗ | case 308: return "Permanent Redirect"; | |
| 257 | ✗ | case 400: return "Bad Request"; | |
| 258 | ✗ | case 401: return "Unauthorized"; | |
| 259 | ✗ | case 402: return "Payment Required"; | |
| 260 | ✗ | case 403: return "Forbidden"; | |
| 261 | ✗ | case 404: return "Not Found"; | |
| 262 | ✗ | case 405: return "Method Not Allowed"; | |
| 263 | ✗ | case 406: return "Not Acceptable"; | |
| 264 | ✗ | case 407: return "Proxy Authentication Required"; | |
| 265 | ✗ | case 408: return "Request Time-out"; | |
| 266 | ✗ | case 409: return "Conflict"; | |
| 267 | ✗ | case 410: return "Gone"; | |
| 268 | ✗ | case 411: return "Length Required"; | |
| 269 | ✗ | case 412: return "Precondition Failed"; | |
| 270 | ✗ | case 413: return "Request Entity Too Large"; | |
| 271 | ✗ | case 414: return "Request-URL Too Long"; | |
| 272 | ✗ | case 415: return "Unsupported Media Type"; | |
| 273 | ✗ | case 416: return "Requested range not satisfiable"; | |
| 274 | ✗ | case 417: return "Expectation Failed"; | |
| 275 | ✗ | case 418: return "I'm a teapot"; | |
| 276 | ✗ | case 420: return "Policy Not Fulfilled"; | |
| 277 | ✗ | case 421: return "Misdirected Request"; | |
| 278 | ✗ | case 422: return "Unprocessable Entity"; | |
| 279 | ✗ | case 423: return "Locked"; | |
| 280 | ✗ | case 424: return "Failed Dependency"; | |
| 281 | ✗ | case 425: return "Too Early"; | |
| 282 | ✗ | case 426: return "Upgrade Required"; | |
| 283 | ✗ | case 428: return "Precondition Required"; | |
| 284 | ✗ | case 429: return "Too Many Requests"; | |
| 285 | ✗ | case 431: return "Request Header Fields Too Large"; | |
| 286 | ✗ | case 451: return "Unavailable For Legal Reasons"; | |
| 287 | ✗ | case 500: return "Internal Server Error"; | |
| 288 | ✗ | case 501: return "Not Implemented"; | |
| 289 | ✗ | case 502: return "Bad Gateway"; | |
| 290 | ✗ | case 503: return "Service Unavailable"; | |
| 291 | ✗ | case 504: return "Gateway Timeout"; | |
| 292 | ✗ | case 505: return "HTTP Version not supported"; | |
| 293 | ✗ | case 506: return "Variant Also Negotiates"; | |
| 294 | ✗ | case 507: return "Insufficient Storage"; | |
| 295 | ✗ | case 508: return "Loop Detected"; | |
| 296 | ✗ | case 509: return "Bandwidth Limit Exceeded"; | |
| 297 | ✗ | case 510: return "Not Extended"; | |
| 298 | ✗ | case 511: return "Network Authentication Required"; | |
| 299 | |||
| 300 | } | ||
| 301 | ✗ | return NULL; | |
| 302 | } | ||
| 303 | |||
| 304 | ✗ | gate_result_t gate_http_parse_urlencoded_content(gate_string_t const* content, | |
| 305 | gate_flatmap_t* append_to_stringmap) | ||
| 306 | { | ||
| 307 | ✗ | gate_result_t ret = GATE_RESULT_OK; | |
| 308 | ✗ | gate_size_t start = 0; | |
| 309 | ✗ | gate_size_t pos = 0; | |
| 310 | ✗ | gate_string_t pair = GATE_STRING_INIT_EMPTY; | |
| 311 | ✗ | gate_string_t raw_key = GATE_STRING_INIT_EMPTY; | |
| 312 | ✗ | gate_string_t raw_value = GATE_STRING_INIT_EMPTY; | |
| 313 | ✗ | gate_string_t key = GATE_STRING_INIT_EMPTY; | |
| 314 | ✗ | gate_string_t value = GATE_STRING_INIT_EMPTY; | |
| 315 | ✗ | gate_size_t len = gate_string_length(content); | |
| 316 | |||
| 317 | ✗ | if (gate_flatmap_count(append_to_stringmap)) | |
| 318 | { | ||
| 319 | ✗ | if (NULL == gate_flatmap_create(append_to_stringmap, &gate_compare_string, | |
| 320 | sizeof(gate_string_t), &gate_string_copy_constructor, &gate_string_destructor, | ||
| 321 | sizeof(gate_string_t), &gate_string_copy_constructor, &gate_string_destructor)) | ||
| 322 | { | ||
| 323 | ✗ | return GATE_RESULT_OUTOFMEMORY; | |
| 324 | } | ||
| 325 | } | ||
| 326 | |||
| 327 | ✗ | while ((start < len) && GATE_SUCCEEDED(ret)) | |
| 328 | { | ||
| 329 | ✗ | pos = gate_string_char_pos(content, '&', start); | |
| 330 | ✗ | if (GATE_STR_NPOS == pos) | |
| 331 | { | ||
| 332 | ✗ | gate_string_substr(&pair, content, start, GATE_STR_NPOS); | |
| 333 | ✗ | start = len; | |
| 334 | } | ||
| 335 | else | ||
| 336 | { | ||
| 337 | ✗ | gate_string_substr(&pair, content, start, pos - start); | |
| 338 | ✗ | start = pos + 1; | |
| 339 | } | ||
| 340 | ✗ | if (!gate_string_is_empty(&pair)) | |
| 341 | { | ||
| 342 | ✗ | pos = gate_string_char_pos(&pair, '=', 0); | |
| 343 | ✗ | if (GATE_STR_NPOS == pos) | |
| 344 | { | ||
| 345 | ✗ | gate_uri_unescape(&pair, &key); | |
| 346 | } | ||
| 347 | else | ||
| 348 | { | ||
| 349 | ✗ | gate_string_substr(&raw_key, &pair, 0, pos); | |
| 350 | ✗ | gate_string_substr(&raw_value, &pair, pos + 1, GATE_STR_NPOS); | |
| 351 | ✗ | gate_uri_unescape(&raw_key, &key); | |
| 352 | ✗ | gate_uri_unescape(&raw_value, &value); | |
| 353 | ✗ | gate_string_release(&raw_value); | |
| 354 | ✗ | gate_string_release(&raw_key); | |
| 355 | } | ||
| 356 | ✗ | if (!gate_string_is_empty(&key)) | |
| 357 | { | ||
| 358 | ✗ | if (NULL == gate_flatmap_add(append_to_stringmap, &key, &value)) | |
| 359 | { | ||
| 360 | ✗ | ret = GATE_RESULT_OUTOFMEMORY; | |
| 361 | } | ||
| 362 | } | ||
| 363 | ✗ | gate_string_release(&value); | |
| 364 | ✗ | gate_string_release(&key); | |
| 365 | } | ||
| 366 | ✗ | gate_string_release(&pair); | |
| 367 | } | ||
| 368 | ✗ | return ret; | |
| 369 | } | ||
| 370 | |||
| 371 | ✗ | gate_result_t gate_http_build_urlencoded_content(gate_flatmap_t const* stringmap, | |
| 372 | gate_strbuilder_t* append_to_builder) | ||
| 373 | { | ||
| 374 | ✗ | gate_result_t ret = GATE_RESULT_OK; | |
| 375 | gate_enumerator_t en; | ||
| 376 | |||
| 377 | ✗ | if (NULL == gate_flatmap_enumerate(stringmap, &en)) | |
| 378 | { | ||
| 379 | ✗ | return GATE_RESULT_OUTOFMEMORY; | |
| 380 | } | ||
| 381 | |||
| 382 | ✗ | for (; gate_enumerator_valid(&en); gate_enumerator_next(&en)) | |
| 383 | { | ||
| 384 | ✗ | gate_mapping_t const* m = (gate_mapping_t const*)gate_enumerator_get(&en); | |
| 385 | gate_string_t const* ptr_key; | ||
| 386 | gate_string_t const* ptr_value; | ||
| 387 | ✗ | gate_string_t key = GATE_STRING_INIT_EMPTY; | |
| 388 | ✗ | gate_string_t value = GATE_STRING_INIT_EMPTY; | |
| 389 | |||
| 390 | ✗ | if (NULL == m) | |
| 391 | { | ||
| 392 | ✗ | continue; | |
| 393 | } | ||
| 394 | ✗ | ptr_key = (gate_string_t const*)m->key; | |
| 395 | ✗ | ptr_value = (gate_string_t const*)m->value; | |
| 396 | ✗ | if (gate_string_is_empty(ptr_key)) | |
| 397 | { | ||
| 398 | ✗ | continue; | |
| 399 | } | ||
| 400 | ✗ | gate_uri_escape(ptr_key, &key); | |
| 401 | ✗ | gate_uri_escape(ptr_value, &value); | |
| 402 | ✗ | gate_strbuilder_append(append_to_builder, | |
| 403 | GATE_PRINT_CSTR, "&", | ||
| 404 | GATE_PRINT_STRING, &key, | ||
| 405 | GATE_PRINT_CSTR, "=", | ||
| 406 | GATE_PRINT_STRING, &value); | ||
| 407 | ✗ | gate_string_release(&key); | |
| 408 | ✗ | gate_string_release(&value); | |
| 409 | } | ||
| 410 | ✗ | return ret; | |
| 411 | } | ||
| 412 | |||
| 413 | |||
| 414 | typedef struct gate_http_mime_mapping_class | ||
| 415 | { | ||
| 416 | char const* file_ext; | ||
| 417 | gate_string_t const* mime_type; | ||
| 418 | } gate_http_mime_mapping_t; | ||
| 419 | |||
| 420 | static gate_string_t const mimetype_text_plain = GATE_STRING_INIT_STATIC("text/plain"); | ||
| 421 | static gate_string_t const mimetype_text_html = GATE_STRING_INIT_STATIC("text/html"); | ||
| 422 | static gate_string_t const mimetype_text_richtext = GATE_STRING_INIT_STATIC("text/richtext"); | ||
| 423 | static gate_string_t const mimetype_text_css = GATE_STRING_INIT_STATIC("text/css"); | ||
| 424 | static gate_string_t const mimetype_text_xml = GATE_STRING_INIT_STATIC("text/xml"); | ||
| 425 | static gate_string_t const mimetype_text_js = GATE_STRING_INIT_STATIC("text/javascript"); | ||
| 426 | static gate_string_t const mimetype_text_tsv = GATE_STRING_INIT_STATIC("text/tab-separated-values"); | ||
| 427 | static gate_string_t const mimetype_text_setext = GATE_STRING_INIT_STATIC("text/x-setext"); | ||
| 428 | static gate_string_t const mimetype_text_sgml = GATE_STRING_INIT_STATIC("text/x-sgml"); | ||
| 429 | static gate_string_t const mimetype_text_jad = GATE_STRING_INIT_STATIC("text/vnd.sun.j2me.app-descriptor"); | ||
| 430 | static gate_string_t const mimetype_text_wml = GATE_STRING_INIT_STATIC("text/vnd.wap.wml"); | ||
| 431 | |||
| 432 | |||
| 433 | static gate_string_t const mimetype_image_gif = GATE_STRING_INIT_STATIC("image/gif"); | ||
| 434 | static gate_string_t const mimetype_image_jpeg = GATE_STRING_INIT_STATIC("image/jpeg"); | ||
| 435 | static gate_string_t const mimetype_image_tiff = GATE_STRING_INIT_STATIC("image/tiff"); | ||
| 436 | static gate_string_t const mimetype_image_cmu_raster = GATE_STRING_INIT_STATIC("image/cmu-raster"); | ||
| 437 | static gate_string_t const mimetype_image_freehand = GATE_STRING_INIT_STATIC("image/x-freehand"); | ||
| 438 | static gate_string_t const mimetype_image_ief = GATE_STRING_INIT_STATIC("image/ief"); | ||
| 439 | static gate_string_t const mimetype_image_anymap = GATE_STRING_INIT_STATIC("image/x-portable-anymap"); | ||
| 440 | static gate_string_t const mimetype_image_graymap = GATE_STRING_INIT_STATIC("image/x-portable-graymap"); | ||
| 441 | static gate_string_t const mimetype_image_pixmap = GATE_STRING_INIT_STATIC("image/x-portable-pixmap"); | ||
| 442 | static gate_string_t const mimetype_image_rgb = GATE_STRING_INIT_STATIC("image/x-rgb"); | ||
| 443 | static gate_string_t const mimetype_image_windowdump = GATE_STRING_INIT_STATIC("image/x-windowdump"); | ||
| 444 | static gate_string_t const mimetype_image_wbmp = GATE_STRING_INIT_STATIC("image/vnd.wap.wbmp"); | ||
| 445 | |||
| 446 | |||
| 447 | static gate_string_t const mimetype_app_octet_stream = GATE_STRING_INIT_STATIC("application/octet-stream"); | ||
| 448 | static gate_string_t const mimetype_app_zip = GATE_STRING_INIT_STATIC("application/zip"); | ||
| 449 | static gate_string_t const mimetype_app_pdf = GATE_STRING_INIT_STATIC("application/pdf"); | ||
| 450 | static gate_string_t const mimetype_app_postscript = GATE_STRING_INIT_STATIC("application/postscript"); | ||
| 451 | static gate_string_t const mimetype_app_autoconfig = GATE_STRING_INIT_STATIC("application/x-ns-proxy-autoconfig"); | ||
| 452 | static gate_string_t const mimetype_app_acad = GATE_STRING_INIT_STATIC("application/acad"); | ||
| 453 | static gate_string_t const mimetype_app_dxf = GATE_STRING_INIT_STATIC("application/dxf"); | ||
| 454 | static gate_string_t const mimetype_app_mif = GATE_STRING_INIT_STATIC("application/mif"); | ||
| 455 | static gate_string_t const mimetype_app_msword = GATE_STRING_INIT_STATIC("application/msword"); | ||
| 456 | static gate_string_t const mimetype_app_mspowerpoint = GATE_STRING_INIT_STATIC("application/mspowerpoint"); | ||
| 457 | static gate_string_t const mimetype_app_msexcel = GATE_STRING_INIT_STATIC("application/msexcel"); | ||
| 458 | static gate_string_t const mimetype_app_mshelp = GATE_STRING_INIT_STATIC("application/mshelp"); | ||
| 459 | static gate_string_t const mimetype_app_rtf = GATE_STRING_INIT_STATIC("application/rtf"); | ||
| 460 | static gate_string_t const mimetype_app_sh = GATE_STRING_INIT_STATIC("application/x-sh"); | ||
| 461 | static gate_string_t const mimetype_app_csh = GATE_STRING_INIT_STATIC("application/x-csh"); | ||
| 462 | static gate_string_t const mimetype_app_latex = GATE_STRING_INIT_STATIC("application/x-latex"); | ||
| 463 | static gate_string_t const mimetype_app_tar = GATE_STRING_INIT_STATIC("application/x-tar"); | ||
| 464 | static gate_string_t const mimetype_app_bcpio = GATE_STRING_INIT_STATIC("application/x-bcpio"); | ||
| 465 | static gate_string_t const mimetype_app_cpio = GATE_STRING_INIT_STATIC("application/x-cpio"); | ||
| 466 | static gate_string_t const mimetype_app_sv4cpio = GATE_STRING_INIT_STATIC("application/x-sv4cpio"); | ||
| 467 | static gate_string_t const mimetype_app_sv4crc = GATE_STRING_INIT_STATIC("application/x-sv4crc"); | ||
| 468 | static gate_string_t const mimetype_app_hdf = GATE_STRING_INIT_STATIC("application/x-hdf"); | ||
| 469 | static gate_string_t const mimetype_app_ustar = GATE_STRING_INIT_STATIC("application/x-ustar"); | ||
| 470 | static gate_string_t const mimetype_app_shar = GATE_STRING_INIT_STATIC("application/x-shar"); | ||
| 471 | static gate_string_t const mimetype_app_tcl = GATE_STRING_INIT_STATIC("application/x-tcl"); | ||
| 472 | static gate_string_t const mimetype_app_dvi = GATE_STRING_INIT_STATIC("application/x-dvi"); | ||
| 473 | static gate_string_t const mimetype_app_texinfo = GATE_STRING_INIT_STATIC("application/x-texinfo"); | ||
| 474 | static gate_string_t const mimetype_app_troff = GATE_STRING_INIT_STATIC("application/x-troff"); | ||
| 475 | static gate_string_t const mimetype_app_troff_man = GATE_STRING_INIT_STATIC("application/x-troff-man"); | ||
| 476 | static gate_string_t const mimetype_app_troff_me = GATE_STRING_INIT_STATIC("application/x-troff-me"); | ||
| 477 | static gate_string_t const mimetype_app_troff_ms = GATE_STRING_INIT_STATIC("application/x-troff-ms"); | ||
| 478 | static gate_string_t const mimetype_app_netcdf = GATE_STRING_INIT_STATIC("application/x-netcdf"); | ||
| 479 | static gate_string_t const mimetype_app_wais_source = GATE_STRING_INIT_STATIC("application/x-wais-source"); | ||
| 480 | static gate_string_t const mimetype_app_jar = GATE_STRING_INIT_STATIC("application/x-jar"); | ||
| 481 | static gate_string_t const mimetype_app_jnlp = GATE_STRING_INIT_STATIC("application/x-java-jnlp-file"); | ||
| 482 | static gate_string_t const mimetype_app_wmlc = GATE_STRING_INIT_STATIC("application/vnd.wap.wmlc"); | ||
| 483 | static gate_string_t const mimetype_app_wrl = GATE_STRING_INIT_STATIC("application/x-wrl+xml"); | ||
| 484 | |||
| 485 | |||
| 486 | static gate_string_t const mimetype_audio_basic = GATE_STRING_INIT_STATIC("audio/basic"); | ||
| 487 | static gate_string_t const mimetype_audio_aiff = GATE_STRING_INIT_STATIC("audio/x-aiff"); | ||
| 488 | static gate_string_t const mimetype_audio_dspeeh = GATE_STRING_INIT_STATIC("audio/x-dspeeh"); | ||
| 489 | static gate_string_t const mimetype_audio_midi = GATE_STRING_INIT_STATIC("audio/x-midi"); | ||
| 490 | static gate_string_t const mimetype_audio_realaudio = GATE_STRING_INIT_STATIC("audio/x-pn-realaudio"); | ||
| 491 | static gate_string_t const mimetype_audio_realaudio_plugin = GATE_STRING_INIT_STATIC("audio/x-pn-realaudio-plugin"); | ||
| 492 | |||
| 493 | static gate_string_t const mimetype_video_mpeg = GATE_STRING_INIT_STATIC("video/mpeg"); | ||
| 494 | static gate_string_t const mimetype_video_quicktime = GATE_STRING_INIT_STATIC("video/quicktime"); | ||
| 495 | static gate_string_t const mimetype_video_msvideo = GATE_STRING_INIT_STATIC("video/x-msvideo"); | ||
| 496 | static gate_string_t const mimetype_video_sgi_movie = GATE_STRING_INIT_STATIC("video/x-sgi-movie"); | ||
| 497 | |||
| 498 | |||
| 499 | |||
| 500 | |||
| 501 | static gate_http_mime_mapping_t gate_http_default_mime_types[] = | ||
| 502 | { | ||
| 503 | { ".txt", &mimetype_text_plain }, | ||
| 504 | { ".c", &mimetype_text_plain }, | ||
| 505 | { ".cc", &mimetype_text_plain }, | ||
| 506 | { ".g", &mimetype_text_plain }, | ||
| 507 | { ".h", &mimetype_text_plain }, | ||
| 508 | { ".hh", &mimetype_text_plain }, | ||
| 509 | { ".m", &mimetype_text_plain }, | ||
| 510 | { ".f90", &mimetype_text_plain }, | ||
| 511 | { ".rtx", &mimetype_text_richtext }, | ||
| 512 | { ".css", &mimetype_text_css }, | ||
| 513 | { ".xml", &mimetype_text_xml }, | ||
| 514 | { ".htm", &mimetype_text_html }, | ||
| 515 | { ".html", &mimetype_text_html }, | ||
| 516 | { ".shtm", &mimetype_text_html }, | ||
| 517 | { ".shtml", &mimetype_text_html }, | ||
| 518 | { ".js", &mimetype_text_js }, | ||
| 519 | { ".tsv", &mimetype_text_tsv }, | ||
| 520 | { ".etx", &mimetype_text_setext }, | ||
| 521 | { ".sgm", &mimetype_text_sgml }, | ||
| 522 | { ".sgml", &mimetype_text_sgml }, | ||
| 523 | { ".jad", &mimetype_text_jad }, | ||
| 524 | { ".wml", &mimetype_text_wml }, | ||
| 525 | |||
| 526 | |||
| 527 | { ".gif", &mimetype_image_gif }, | ||
| 528 | { ".jpeg", &mimetype_image_jpeg }, | ||
| 529 | { ".jpg", &mimetype_image_jpeg }, | ||
| 530 | { ".jpe", &mimetype_image_jpeg }, | ||
| 531 | { ".tiff", &mimetype_image_tiff }, | ||
| 532 | { ".tif", &mimetype_image_tiff }, | ||
| 533 | { ".ras", &mimetype_image_cmu_raster }, | ||
| 534 | { ".fh4", &mimetype_image_freehand }, | ||
| 535 | { ".fh5", &mimetype_image_freehand }, | ||
| 536 | { ".fhc", &mimetype_image_freehand }, | ||
| 537 | { ".ief", &mimetype_image_ief }, | ||
| 538 | { ".pnm", &mimetype_image_anymap }, | ||
| 539 | { ".PBM", &mimetype_image_anymap }, | ||
| 540 | { ".pgm", &mimetype_image_graymap }, | ||
| 541 | { ".ppm", &mimetype_image_pixmap }, | ||
| 542 | { ".rgb", &mimetype_image_rgb }, | ||
| 543 | { ".xwd", &mimetype_image_windowdump }, | ||
| 544 | { ".wbmp", &mimetype_image_wbmp }, | ||
| 545 | |||
| 546 | |||
| 547 | { ".exe", &mimetype_app_octet_stream }, | ||
| 548 | { ".com", &mimetype_app_octet_stream }, | ||
| 549 | { ".dll", &mimetype_app_octet_stream }, | ||
| 550 | { ".bin", &mimetype_app_octet_stream }, | ||
| 551 | { ".class", &mimetype_app_octet_stream }, | ||
| 552 | { ".zip", &mimetype_app_zip }, | ||
| 553 | { ".pdf", &mimetype_app_pdf }, | ||
| 554 | { ".ps", &mimetype_app_postscript }, | ||
| 555 | { ".ai", &mimetype_app_postscript }, | ||
| 556 | { ".eps", &mimetype_app_postscript }, | ||
| 557 | { ".pac", &mimetype_app_autoconfig }, | ||
| 558 | { ".dwg", &mimetype_app_acad }, | ||
| 559 | { ".dxf", &mimetype_app_dxf }, | ||
| 560 | { ".mif", &mimetype_app_mif }, | ||
| 561 | { ".doc", &mimetype_app_msword }, | ||
| 562 | { ".dot", &mimetype_app_msword }, | ||
| 563 | { ".ppt", &mimetype_app_mspowerpoint }, | ||
| 564 | { ".ppz", &mimetype_app_mspowerpoint }, | ||
| 565 | { ".pps", &mimetype_app_mspowerpoint }, | ||
| 566 | { ".pot", &mimetype_app_mspowerpoint }, | ||
| 567 | { ".xls", &mimetype_app_msexcel }, | ||
| 568 | { ".xla", &mimetype_app_msexcel }, | ||
| 569 | { ".hlp", &mimetype_app_mshelp }, | ||
| 570 | { ".chm", &mimetype_app_mshelp }, | ||
| 571 | { ".rtf", &mimetype_app_rtf }, | ||
| 572 | { ".sh", &mimetype_app_sh }, | ||
| 573 | { ".csh", &mimetype_app_csh }, | ||
| 574 | { ".latex", &mimetype_app_latex }, | ||
| 575 | { ".tar", &mimetype_app_tar }, | ||
| 576 | { ".bcpio", &mimetype_app_bcpio }, | ||
| 577 | { ".cpio", &mimetype_app_cpio }, | ||
| 578 | { ".sv4cpio", &mimetype_app_sv4cpio }, | ||
| 579 | { ".sv4crc", &mimetype_app_sv4crc }, | ||
| 580 | { ".hdf", &mimetype_app_hdf }, | ||
| 581 | { ".ustar", &mimetype_app_ustar }, | ||
| 582 | { ".shar", &mimetype_app_shar }, | ||
| 583 | { ".tcl", &mimetype_app_tcl }, | ||
| 584 | { ".dvi", &mimetype_app_dvi }, | ||
| 585 | { ".texinfo", &mimetype_app_texinfo }, | ||
| 586 | { ".texi", &mimetype_app_texinfo }, | ||
| 587 | { ".t", &mimetype_app_troff }, | ||
| 588 | { ".tr", &mimetype_app_troff }, | ||
| 589 | { ".roff", &mimetype_app_troff }, | ||
| 590 | { ".man", &mimetype_app_troff_man }, | ||
| 591 | { ".me", &mimetype_app_troff_me }, | ||
| 592 | { ".ms", &mimetype_app_troff_ms }, | ||
| 593 | { ".nc", &mimetype_app_netcdf }, | ||
| 594 | { ".cdf", &mimetype_app_netcdf }, | ||
| 595 | { ".src", &mimetype_app_wais_source }, | ||
| 596 | { ".jar", &mimetype_app_jar }, | ||
| 597 | { ".jnlp", &mimetype_app_jnlp }, | ||
| 598 | { ".wmlc", &mimetype_app_wmlc }, | ||
| 599 | { ".wrl", &mimetype_app_wrl }, | ||
| 600 | |||
| 601 | |||
| 602 | { ".au", &mimetype_audio_basic }, | ||
| 603 | { ".snd", &mimetype_audio_basic }, | ||
| 604 | { ".aif", &mimetype_audio_aiff }, | ||
| 605 | { ".aiff", &mimetype_audio_aiff }, | ||
| 606 | { ".aifc", &mimetype_audio_aiff }, | ||
| 607 | { ".dus", &mimetype_audio_dspeeh }, | ||
| 608 | { ".cht", &mimetype_audio_dspeeh }, | ||
| 609 | { ".midi", &mimetype_audio_midi }, | ||
| 610 | { ".mid", &mimetype_audio_midi }, | ||
| 611 | { ".ram", &mimetype_audio_realaudio }, | ||
| 612 | { ".ra", &mimetype_audio_realaudio }, | ||
| 613 | { ".rpm", &mimetype_audio_realaudio_plugin }, | ||
| 614 | |||
| 615 | { ".mpeg", &mimetype_video_mpeg }, | ||
| 616 | { ".mpg", &mimetype_video_mpeg }, | ||
| 617 | { ".mpe", &mimetype_video_mpeg }, | ||
| 618 | { ".qt", &mimetype_video_quicktime }, | ||
| 619 | { ".mov", &mimetype_video_quicktime }, | ||
| 620 | { ".avi", &mimetype_video_msvideo }, | ||
| 621 | { ".movie", &mimetype_video_sgi_movie } | ||
| 622 | }; | ||
| 623 | |||
| 624 | static gate_size_t const gate_http_default_mime_types_count = sizeof(gate_http_default_mime_types) / sizeof(gate_http_default_mime_types[0]); | ||
| 625 | |||
| 626 | |||
| 627 | ✗ | gate_result_t gate_http_resolve_mime_type(gate_string_t const* file_ext, gate_string_t* mine_type) | |
| 628 | { | ||
| 629 | gate_size_t ndx; | ||
| 630 | |||
| 631 | ✗ | for (ndx = 0; ndx != gate_http_default_mime_types_count; ++ndx) | |
| 632 | { | ||
| 633 | ✗ | if (gate_string_ends_with_str_ic(file_ext, gate_http_default_mime_types[ndx].file_ext)) | |
| 634 | { | ||
| 635 | ✗ | gate_string_duplicate(mine_type, gate_http_default_mime_types[ndx].mime_type); | |
| 636 | ✗ | return GATE_RESULT_OK; | |
| 637 | } | ||
| 638 | } | ||
| 639 | ✗ | gate_string_duplicate(mine_type, &mimetype_app_octet_stream); | |
| 640 | ✗ | return GATE_RESULT_OK; | |
| 641 | } | ||
| 642 | |||
| 643 | ✗ | char const* gate_http_resolve_mime_type_str(char const* file_ext) | |
| 644 | { | ||
| 645 | gate_result_t result; | ||
| 646 | gate_string_t ext; | ||
| 647 | ✗ | gate_string_t mime = GATE_STRING_INIT_EMPTY; | |
| 648 | ✗ | gate_string_create_static(&ext, file_ext); | |
| 649 | ✗ | result = gate_http_resolve_mime_type(&ext, &mime); | |
| 650 | ✗ | if (GATE_FAILED(result)) | |
| 651 | { | ||
| 652 | ✗ | return NULL; | |
| 653 | } | ||
| 654 | else | ||
| 655 | { | ||
| 656 | ✗ | return mime.str; | |
| 657 | } | ||
| 658 | } | ||
| 659 |