GCC Code Coverage Report


Directory: src/gate/
File: src/gate/net/httptypes.c
Date: 2026-09-21 06:26:40
Exec Total Coverage
Lines: 264 310 85.2%
Functions: 14 15 93.3%
Branches: 150 200 75.0%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright (c) 2018-2026, 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 3 gate_result_t gate_http_request_init_str(gate_http_request_t* request, char const* method, char const* host, char const* path)
35 {
36 gate_result_t ret;
37 gate_string_t str_method, str_path, str_host;
38
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 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 3 times.
3 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/2
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if (NULL == gate_string_create(&str_host, host, gate_str_length(host)))
48 {
49 gate_string_release(&str_method);
50 gate_string_release(&str_path);
51 return GATE_RESULT_OUTOFMEMORY;
52 }
53 3 ret = gate_http_request_init(request, &str_method, &str_host, &str_path);
54 3 gate_string_release(&str_host);
55 3 gate_string_release(&str_path);
56 3 gate_string_release(&str_method);
57 3 return ret;
58 }
59
60
61 28 gate_result_t gate_http_request_init(gate_http_request_t* request, gate_string_t const* method, gate_string_t const* host, gate_string_t const* path)
62 {
63 28 gate_mem_clear(request, sizeof(gate_http_request_t));
64
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 4 times.
28 if (method != NULL)
65 {
66
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
24 if (NULL == gate_string_clone(&request->method, method))
67 {
68 return GATE_RESULT_OUTOFMEMORY;
69 }
70 }
71
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 4 times.
28 if (path != NULL)
72 {
73
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
24 if (NULL == gate_string_clone(&request->path, path))
74 {
75 gate_http_request_release(request);
76 return GATE_RESULT_OUTOFMEMORY;
77 }
78 }
79
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 4 times.
28 if (host != NULL)
80 {
81
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 24 times.
24 if (NULL == gate_string_clone(&request->host, host))
82 {
83 gate_http_request_release(request);
84 return GATE_RESULT_OUTOFMEMORY;
85 }
86 }
87
88
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
28 if (NULL == gate_util_stringmap_create_ex(&request->headers, true, true))
89 {
90 gate_http_request_release(request);
91 return GATE_RESULT_OUTOFMEMORY;
92 }
93
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
28 if (NULL == gate_util_stringset_create(&request->accept_types))
94 {
95 gate_http_request_release(request);
96 return GATE_RESULT_OUTOFMEMORY;
97 }
98 28 return GATE_RESULT_OK;
99 }
100
101 1 gate_result_t gate_http_request_init_uri(gate_http_request_t* request, gate_string_t const* method, gate_uri_t const* uri)
102 {
103 gate_result_t ret;
104 1 gate_string_t path = GATE_STRING_INIT_EMPTY;
105
106 do
107 {
108 1 gate_mem_clear(request, sizeof(gate_http_request_t));
109
110 1 ret = gate_uri_to_string(uri, &path, true);
111
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
112
113 1 ret = gate_http_request_init(request, method, &uri->host, &path);
114
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
115
116
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (!gate_string_is_empty(&uri->user_info))
117 {
118 ret = gate_uri_parse_user_info(&uri->user_info, &request->auth_user, &request->auth_pass);
119 GATE_BREAK_IF_FAILED(ret);
120 }
121
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (!gate_string_is_empty(&uri->host))
122 {
123 static const gate_string_t host_key = GATE_STRING_INIT_STATIC(GATE_HTTP_HEADER_HOST);
124 1 gate_util_stringmap_add_string(&request->headers, &host_key, &uri->host);
125 }
126
127 } while (0);
128
129 1 gate_string_release(&path);
130
131 1 return ret;
132 }
133
134
135
136 8 gate_result_t gate_http_request_copy(gate_http_request_t* request, gate_http_request_t const* src)
137 {
138 8 gate_result_t ret = GATE_RESULT_OUTOFMEMORY;
139 8 gate_mem_clear(request, sizeof(gate_http_request_t));
140 do
141 {
142
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!gate_string_clone(&request->method, &src->method)) break;
143
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!gate_string_clone(&request->path, &src->path)) break;
144
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!gate_string_clone(&request->version, &src->version)) break;
145
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!gate_string_clone(&request->host, &src->host)) break;
146
147
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!gate_string_clone(&request->auth_user, &src->auth_user)) break;
148
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!gate_string_clone(&request->auth_pass, &src->auth_pass)) break;
149
150
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!gate_map_copy(&request->headers, &src->headers)) break;
151
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!gate_set_copy(&request->accept_types, &src->accept_types)) break;
152
153
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!gate_string_clone(&request->proxy_server, &src->proxy_server)) break;
154
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!gate_string_clone(&request->proxy_user, &src->proxy_user)) break;
155
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (!gate_string_clone(&request->proxy_pass, &src->proxy_pass)) break;
156
157 8 request->upload_stream = src->upload_stream;
158
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
8 if (request->upload_stream)
159 {
160 5 gate_object_retain(request->upload_stream);
161 }
162
163 8 request->connect_timeout_ms = src->connect_timeout_ms;
164 8 request->send_timeout_ms = src->send_timeout_ms;
165 8 request->receive_timeout_ms = src->receive_timeout_ms;
166 8 request->proxy_port = src->proxy_port;
167
168 8 ret = GATE_RESULT_OK;
169
170 } while (0);
171
172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (GATE_FAILED(ret))
173 {
174 gate_http_request_release(request);
175 }
176 8 return ret;
177 }
178
179 36 gate_result_t gate_http_request_release(gate_http_request_t* request)
180 {
181 36 gate_string_release(&request->method);
182 36 gate_string_release(&request->path);
183 36 gate_string_release(&request->version);
184 36 gate_string_release(&request->host);
185
186 36 gate_string_release(&request->auth_user);
187 36 gate_string_release(&request->auth_pass);
188
189 36 gate_map_destroy(&request->headers);
190 36 gate_set_destroy(&request->accept_types);
191
192 36 gate_string_release(&request->proxy_server);
193 36 gate_string_release(&request->proxy_user);
194 36 gate_string_release(&request->proxy_pass);
195
196
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 25 times.
36 if (request->upload_stream != NULL)
197 {
198 11 gate_object_release(request->upload_stream);
199 }
200
201 36 gate_mem_clear(request, sizeof(gate_http_request_t));
202 36 return GATE_RESULT_OK;
203 }
204
205 static gate_string_t const default_http_version = GATE_STRING_INIT_STATIC("1.1");
206
207 3 gate_result_t gate_http_request_build_header(gate_http_request_t* request, gate_stream_t* stream)
208 {
209 3 gate_result_t ret = GATE_RESULT_FAILED;
210
211 do
212 {
213 3 gate_int64_t content_length = -1;
214 gate_map_iterator_t iter, iterend;
215 gate_controlstream_t* ptr_upload;
216 gate_result_t result;
217 3 gate_bool_t keep_alive = false;
218
219
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 gate_stream_print(stream,
220 GATE_PRINT_STRING, &request->method,
221 GATE_PRINT_CSTR, " ",
222 GATE_PRINT_STRING, &request->path,
223 GATE_PRINT_CSTR, " HTTP/",
224 3 GATE_PRINT_STRING, (gate_string_is_empty(&request->version) ? &default_http_version : &request->version),
225 GATE_PRINT_CRLF,
226 GATE_PRINT_END);
227
228 3 gate_stream_print(stream,
229 GATE_PRINT_CSTR, GATE_HTTP_HEADER_HOST,
230 GATE_PRINT_CSTR, ": ",
231 GATE_PRINT_STRING, &request->host,
232 GATE_PRINT_CRLF, GATE_PRINT_END);
233
234
235
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
3 if (!gate_set_is_empty(&request->accept_types))
236 {
237 1 gate_stream_print_cstr(stream, "Accept: ");
238 1 iter = gate_set_first(&request->accept_types);
239 1 iterend = gate_set_end(&request->accept_types);
240
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 while (iter != iterend)
241 {
242 1 gate_string_t const* ptr_key = (gate_string_t const*)gate_map_iterator_key(iter);
243 1 gate_stream_print_string(stream, ptr_key);
244 1 iter = gate_set_iterator_next(iter);
245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (iter != iterend)
246 {
247 gate_stream_print_cstr(stream, ", ");
248 }
249 }
250 1 gate_stream_print(stream, GATE_PRINT_CRLF, GATE_PRINT_END);
251 }
252
253 3 iter = gate_map_first(&request->headers);
254 3 iterend = gate_map_end(&request->headers);
255
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 3 times.
8 for (; iter != iterend; iter = gate_map_iterator_next(iter))
256 {
257 5 gate_string_t const* ptr_key = (gate_string_t const*)gate_map_iterator_key(iter);
258 5 gate_string_t const* ptr_value = (gate_string_t const*)gate_map_iterator_value(iter);
259
260
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 4 times.
5 if (gate_string_equals_str_ic(ptr_key, GATE_HTTP_HEADER_CONNECTION))
261 {
262
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (gate_string_equals_str_ic(ptr_value, GATE_HTTP_HEADERVALUE_CONNECTION_KEEPALIVE))
263 {
264 1 keep_alive = true;
265 }
266 1 continue;
267 }
268
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
4 if (gate_string_equals_str_ic(ptr_key, GATE_HTTP_HEADER_CONTENTLENGTH))
269 {
270 1 gate_string_parse_int(ptr_value, &content_length);
271 1 continue;
272 }
273 3 gate_stream_print(stream,
274 GATE_PRINT_STRING, ptr_key,
275 GATE_PRINT_CSTR, ": ",
276 GATE_PRINT_STRING, gate_map_iterator_value(iter),
277 GATE_PRINT_CRLF,
278 GATE_PRINT_END);
279 }
280
281
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (request->upload_stream)
282 {
283 1 content_length = -1; /* no content length */
284 }
285
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (request->upload_stream)
286 {
287
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (gate_object_implements_interface((gate_object_t*)request->upload_stream, GATE_INTERFACE_NAME_CONTROLSTREAM))
288 {
289 ptr_upload = (gate_controlstream_t*)request->upload_stream;
290 result = gate_stream_get_size(ptr_upload, &content_length);
291 if (GATE_FAILED(result))
292 {
293 content_length = -1; /* no content length */
294 keep_alive = false;
295 }
296 }
297 else
298 {
299
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (content_length >= 0)
300 {
301 /* content length was user-specified -> trust it */
302 }
303 else
304 {
305 /* end of stream == end of content, no keep alive possible */
306 1 keep_alive = false;
307 }
308 }
309 }
310
311
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (content_length >= 0)
312 {
313 1 gate_stream_print(stream,
314 GATE_PRINT_CSTR, GATE_HTTP_HEADER_CONTENTLENGTH,
315 GATE_PRINT_CSTR, ": ",
316 GATE_PRINT_I64, content_length,
317 GATE_PRINT_CRLF, GATE_PRINT_END);
318 }
319
320
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 gate_stream_print(stream,
321 GATE_PRINT_CSTR, GATE_HTTP_HEADER_CONNECTION,
322 GATE_PRINT_CSTR, ": ",
323 GATE_PRINT_CSTR, (keep_alive ? GATE_HTTP_HEADERVALUE_CONNECTION_KEEPALIVE : GATE_HTTP_HEADERVALUE_CONNECTION_CLOSE),
324 GATE_PRINT_CRLF,
325 GATE_PRINT_END);
326
327
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 gate_util_stringmap_add(&request->headers,
328 GATE_HTTP_HEADER_CONNECTION,
329 keep_alive ? GATE_HTTP_HEADERVALUE_CONNECTION_KEEPALIVE : GATE_HTTP_HEADERVALUE_CONNECTION_CLOSE);
330
331 /* finish HTTP header */
332 3 gate_stream_print(stream,
333 GATE_PRINT_CRLF,
334 GATE_PRINT_END);
335
336 /* generate output string */
337 3 ret = GATE_RESULT_OK;
338 } while (0);
339
340 3 return ret;
341 }
342
343 2 gate_result_t gate_http_request_build_upload_chunk(gate_http_request_t const* request, gate_stream_t* stream, gate_size_t chunk_size, gate_size_t* ptr_transferred)
344 {
345 gate_result_t ret;
346 2 gate_uint64_t transferred = 0;
347
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (chunk_size == 0)
348 {
349 2 chunk_size = GATE_MAX_COPYBUFFER_LENGTH;
350 }
351 2 ret = gate_stream_transfer_limit(request->upload_stream, chunk_size, stream, &transferred);
352 2 *ptr_transferred = (gate_size_t)transferred;
353 2 return ret;
354 }
355
356
357 27 gate_result_t gate_http_response_init(gate_http_response_t* response)
358 {
359 27 gate_result_t ret = GATE_RESULT_FAILED;
360 do
361 {
362 27 gate_mem_clear(response, sizeof(gate_http_response_t));
363
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
27 if (NULL == gate_util_stringmap_create_ex(&response->headers, true, true))
364 {
365 ret = GATE_RESULT_OUTOFMEMORY;
366 break;
367 }
368 } while (0);
369 27 return GATE_RESULT_OK;
370 }
371
372 2 gate_result_t gate_http_response_copy(gate_http_response_t* response, gate_http_response_t const* src)
373 {
374 2 gate_result_t ret = GATE_RESULT_OK;
375 do
376 {
377 2 gate_mem_clear(response, sizeof(gate_http_response_t));
378
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (NULL == gate_map_copy(&response->headers, &src->headers))
379 {
380 ret = GATE_RESULT_OUTOFMEMORY;
381 break;
382 }
383 2 response->response_stream = src->response_stream;
384
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (response->response_stream)
385 {
386 gate_object_retain(response->response_stream);
387 }
388 2 response->status_code = src->status_code;
389 2 ret = GATE_RESULT_OK;
390 } while (0);
391 2 return ret;
392 }
393
394 25 gate_result_t gate_http_response_release(gate_http_response_t* response)
395 {
396 25 gate_map_destroy(&response->headers);
397
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 4 times.
25 if (NULL != response->response_stream)
398 {
399 21 gate_object_release(response->response_stream);
400 }
401 25 gate_mem_clear(response, sizeof(gate_http_response_t));
402 25 return GATE_RESULT_OK;
403 }
404
405 69 char const* gate_http_response_status_text(gate_uint32_t status_code)
406 {
407
65/66
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 1 times.
✓ Branch 12 taken 1 times.
✓ Branch 13 taken 1 times.
✓ Branch 14 taken 1 times.
✓ Branch 15 taken 1 times.
✓ Branch 16 taken 1 times.
✓ Branch 17 taken 1 times.
✓ Branch 18 taken 1 times.
✓ Branch 19 taken 1 times.
✓ Branch 20 taken 1 times.
✓ Branch 21 taken 1 times.
✓ Branch 22 taken 1 times.
✓ Branch 23 taken 1 times.
✓ Branch 24 taken 1 times.
✓ Branch 25 taken 1 times.
✓ Branch 26 taken 1 times.
✓ Branch 27 taken 1 times.
✓ Branch 28 taken 1 times.
✓ Branch 29 taken 1 times.
✓ Branch 30 taken 1 times.
✓ Branch 31 taken 1 times.
✓ Branch 32 taken 1 times.
✓ Branch 33 taken 1 times.
✓ Branch 34 taken 1 times.
✓ Branch 35 taken 1 times.
✓ Branch 36 taken 1 times.
✓ Branch 37 taken 1 times.
✓ Branch 38 taken 1 times.
✓ Branch 39 taken 1 times.
✓ Branch 40 taken 1 times.
✓ Branch 41 taken 1 times.
✓ Branch 42 taken 1 times.
✓ Branch 43 taken 1 times.
✓ Branch 44 taken 1 times.
✓ Branch 45 taken 1 times.
✓ Branch 46 taken 1 times.
✓ Branch 47 taken 1 times.
✓ Branch 48 taken 1 times.
✓ Branch 49 taken 1 times.
✓ Branch 50 taken 1 times.
✓ Branch 51 taken 1 times.
✓ Branch 52 taken 1 times.
✓ Branch 53 taken 1 times.
✓ Branch 54 taken 1 times.
✓ Branch 55 taken 1 times.
✓ Branch 56 taken 1 times.
✓ Branch 57 taken 1 times.
✓ Branch 58 taken 1 times.
✓ Branch 59 taken 1 times.
✓ Branch 60 taken 1 times.
✓ Branch 61 taken 1 times.
✓ Branch 62 taken 1 times.
✓ Branch 63 taken 1 times.
✓ Branch 64 taken 1 times.
✗ Branch 65 not taken.
69 switch (status_code)
408 {
409 1 case 100: return "Continue";
410 1 case 101: return "Switching Protocols";
411 1 case 102: return "Processing";
412 1 case 103: return "Early Hints";
413 5 case 200: return "OK";
414 1 case 201: return "Created";
415 1 case 202: return "Accepted";
416 1 case 203: return "Non-Authoritative Information";
417 1 case 204: return "No Content";
418 1 case 205: return "Reset Content";
419 1 case 206: return "Partial Content";
420 1 case 207: return "Multi-Status";
421 1 case 208: return "Already Reported";
422 1 case 226: return "IM Used";
423 1 case 300: return "Multiple Choices";
424 1 case 301: return "Moved Permanently";
425 1 case 302: return "Found";
426 1 case 303: return "See Other";
427 1 case 304: return "Not Modified";
428 1 case 305: return "Use Proxy";
429 1 case 306: return "Switch Proxy";
430 1 case 307: return "Temporary Redirect";
431 1 case 308: return "Permanent Redirect";
432 1 case 400: return "Bad Request";
433 1 case 401: return "Unauthorized";
434 1 case 402: return "Payment Required";
435 1 case 403: return "Forbidden";
436 1 case 404: return "Not Found";
437 1 case 405: return "Method Not Allowed";
438 1 case 406: return "Not Acceptable";
439 1 case 407: return "Proxy Authentication Required";
440 1 case 408: return "Request Time-out";
441 1 case 409: return "Conflict";
442 1 case 410: return "Gone";
443 1 case 411: return "Length Required";
444 1 case 412: return "Precondition Failed";
445 1 case 413: return "Request Entity Too Large";
446 1 case 414: return "Request-URL Too Long";
447 1 case 415: return "Unsupported Media Type";
448 1 case 416: return "Requested range not satisfiable";
449 1 case 417: return "Expectation Failed";
450 1 case 418: return "I'm a teapot";
451 1 case 420: return "Policy Not Fulfilled";
452 1 case 421: return "Misdirected Request";
453 1 case 422: return "Unprocessable Entity";
454 1 case 423: return "Locked";
455 1 case 424: return "Failed Dependency";
456 1 case 425: return "Too Early";
457 1 case 426: return "Upgrade Required";
458 1 case 428: return "Precondition Required";
459 1 case 429: return "Too Many Requests";
460 1 case 431: return "Request Header Fields Too Large";
461 1 case 451: return "Unavailable For Legal Reasons";
462 1 case 500: return "Internal Server Error";
463 1 case 501: return "Not Implemented";
464 1 case 502: return "Bad Gateway";
465 1 case 503: return "Service Unavailable";
466 1 case 504: return "Gateway Timeout";
467 1 case 505: return "HTTP Version not supported";
468 1 case 506: return "Variant Also Negotiates";
469 1 case 507: return "Insufficient Storage";
470 1 case 508: return "Loop Detected";
471 1 case 509: return "Bandwidth Limit Exceeded";
472 1 case 510: return "Not Extended";
473 1 case 511: return "Network Authentication Required";
474
475 }
476 return NULL;
477 }
478
479 1 gate_result_t gate_http_parse_urlencoded_content(gate_string_t const* content,
480 gate_flatmap_t* append_to_stringmap)
481 {
482 1 gate_result_t ret = GATE_RESULT_OK;
483 1 gate_size_t start = 0;
484 1 gate_size_t pos = 0;
485 1 gate_string_t pair = GATE_STRING_INIT_EMPTY;
486 1 gate_string_t raw_key = GATE_STRING_INIT_EMPTY;
487 1 gate_string_t raw_value = GATE_STRING_INIT_EMPTY;
488 1 gate_string_t key = GATE_STRING_INIT_EMPTY;
489 1 gate_string_t value = GATE_STRING_INIT_EMPTY;
490 1 gate_size_t len = gate_string_length(content);
491
492
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (gate_flatmap_count(append_to_stringmap))
493 {
494 if (NULL == gate_flatmap_create(append_to_stringmap, &gate_compare_string,
495 sizeof(gate_string_t), &gate_string_copy_constructor, &gate_string_destructor,
496 sizeof(gate_string_t), &gate_string_copy_constructor, &gate_string_destructor))
497 {
498 return GATE_RESULT_OUTOFMEMORY;
499 }
500 }
501
502
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
4 while ((start < len) && GATE_SUCCEEDED(ret))
503 {
504 3 pos = gate_string_char_pos(content, '&', start);
505
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (GATE_STR_NPOS == pos)
506 {
507 1 gate_string_substr(&pair, content, start, GATE_STR_NPOS);
508 1 start = len;
509 }
510 else
511 {
512 2 gate_string_substr(&pair, content, start, pos - start);
513 2 start = pos + 1;
514 }
515
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
3 if (!gate_string_is_empty(&pair))
516 {
517 2 pos = gate_string_char_pos(&pair, '=', 0);
518
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (GATE_STR_NPOS == pos)
519 {
520 gate_uri_unescape(&pair, &key);
521 }
522 else
523 {
524 2 gate_string_substr(&raw_key, &pair, 0, pos);
525 2 gate_string_substr(&raw_value, &pair, pos + 1, GATE_STR_NPOS);
526 2 gate_uri_unescape(&raw_key, &key);
527 2 gate_uri_unescape(&raw_value, &value);
528 2 gate_string_release(&raw_value);
529 2 gate_string_release(&raw_key);
530 }
531
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (!gate_string_is_empty(&key))
532 {
533
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (NULL == gate_flatmap_add(append_to_stringmap, &key, &value))
534 {
535 ret = GATE_RESULT_OUTOFMEMORY;
536 }
537 }
538 2 gate_string_release(&value);
539 2 gate_string_release(&key);
540 }
541 3 gate_string_release(&pair);
542 }
543 1 return ret;
544 }
545
546 1 gate_result_t gate_http_build_urlencoded_content(gate_flatmap_t const* stringmap,
547 gate_strbuilder_t* append_to_builder)
548 {
549 1 gate_result_t ret = GATE_RESULT_OK;
550 gate_enumerator_t en;
551
552
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (NULL == gate_flatmap_enumerate(stringmap, &en))
553 {
554 return GATE_RESULT_OUTOFMEMORY;
555 }
556
557
2/2
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
3 for (; gate_enumerator_valid(&en); gate_enumerator_next(&en))
558 {
559 2 gate_mapping_t const* m = (gate_mapping_t const*)gate_enumerator_get(&en);
560 gate_string_t const* ptr_key;
561 gate_string_t const* ptr_value;
562 2 gate_string_t key = GATE_STRING_INIT_EMPTY;
563 2 gate_string_t value = GATE_STRING_INIT_EMPTY;
564
565
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (NULL == m)
566 {
567 continue;
568 }
569 2 ptr_key = (gate_string_t const*)m->key;
570 2 ptr_value = (gate_string_t const*)m->value;
571
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (gate_string_is_empty(ptr_key))
572 {
573 continue;
574 }
575 2 gate_uri_escape(ptr_key, &key);
576 2 gate_uri_escape(ptr_value, &value);
577 2 gate_strbuilder_append(append_to_builder,
578 GATE_PRINT_CSTR, "&",
579 GATE_PRINT_STRING, &key,
580 GATE_PRINT_CSTR, "=",
581 GATE_PRINT_STRING, &value);
582 2 gate_string_release(&key);
583 2 gate_string_release(&value);
584 }
585 1 return ret;
586 }
587
588
589 typedef struct gate_http_mime_mapping_class
590 {
591 char const* file_ext;
592 gate_string_t const* mime_type;
593 } gate_http_mime_mapping_t;
594
595 static gate_string_t const mimetype_text_plain = GATE_STRING_INIT_STATIC("text/plain");
596 static gate_string_t const mimetype_text_html = GATE_STRING_INIT_STATIC("text/html");
597 static gate_string_t const mimetype_text_richtext = GATE_STRING_INIT_STATIC("text/richtext");
598 static gate_string_t const mimetype_text_css = GATE_STRING_INIT_STATIC("text/css");
599 static gate_string_t const mimetype_text_xml = GATE_STRING_INIT_STATIC("text/xml");
600 static gate_string_t const mimetype_text_js = GATE_STRING_INIT_STATIC("text/javascript");
601 static gate_string_t const mimetype_text_tsv = GATE_STRING_INIT_STATIC("text/tab-separated-values");
602 static gate_string_t const mimetype_text_setext = GATE_STRING_INIT_STATIC("text/x-setext");
603 static gate_string_t const mimetype_text_sgml = GATE_STRING_INIT_STATIC("text/x-sgml");
604 static gate_string_t const mimetype_text_jad = GATE_STRING_INIT_STATIC("text/vnd.sun.j2me.app-descriptor");
605 static gate_string_t const mimetype_text_wml = GATE_STRING_INIT_STATIC("text/vnd.wap.wml");
606
607
608 static gate_string_t const mimetype_image_gif = GATE_STRING_INIT_STATIC("image/gif");
609 static gate_string_t const mimetype_image_jpeg = GATE_STRING_INIT_STATIC("image/jpeg");
610 static gate_string_t const mimetype_image_tiff = GATE_STRING_INIT_STATIC("image/tiff");
611 static gate_string_t const mimetype_image_cmu_raster = GATE_STRING_INIT_STATIC("image/cmu-raster");
612 static gate_string_t const mimetype_image_freehand = GATE_STRING_INIT_STATIC("image/x-freehand");
613 static gate_string_t const mimetype_image_ief = GATE_STRING_INIT_STATIC("image/ief");
614 static gate_string_t const mimetype_image_anymap = GATE_STRING_INIT_STATIC("image/x-portable-anymap");
615 static gate_string_t const mimetype_image_graymap = GATE_STRING_INIT_STATIC("image/x-portable-graymap");
616 static gate_string_t const mimetype_image_pixmap = GATE_STRING_INIT_STATIC("image/x-portable-pixmap");
617 static gate_string_t const mimetype_image_rgb = GATE_STRING_INIT_STATIC("image/x-rgb");
618 static gate_string_t const mimetype_image_windowdump = GATE_STRING_INIT_STATIC("image/x-windowdump");
619 static gate_string_t const mimetype_image_wbmp = GATE_STRING_INIT_STATIC("image/vnd.wap.wbmp");
620
621
622 static gate_string_t const mimetype_app_octet_stream = GATE_STRING_INIT_STATIC("application/octet-stream");
623 static gate_string_t const mimetype_app_zip = GATE_STRING_INIT_STATIC("application/zip");
624 static gate_string_t const mimetype_app_pdf = GATE_STRING_INIT_STATIC("application/pdf");
625 static gate_string_t const mimetype_app_postscript = GATE_STRING_INIT_STATIC("application/postscript");
626 static gate_string_t const mimetype_app_autoconfig = GATE_STRING_INIT_STATIC("application/x-ns-proxy-autoconfig");
627 static gate_string_t const mimetype_app_acad = GATE_STRING_INIT_STATIC("application/acad");
628 static gate_string_t const mimetype_app_dxf = GATE_STRING_INIT_STATIC("application/dxf");
629 static gate_string_t const mimetype_app_mif = GATE_STRING_INIT_STATIC("application/mif");
630 static gate_string_t const mimetype_app_msword = GATE_STRING_INIT_STATIC("application/msword");
631 static gate_string_t const mimetype_app_mspowerpoint = GATE_STRING_INIT_STATIC("application/mspowerpoint");
632 static gate_string_t const mimetype_app_msexcel = GATE_STRING_INIT_STATIC("application/msexcel");
633 static gate_string_t const mimetype_app_mshelp = GATE_STRING_INIT_STATIC("application/mshelp");
634 static gate_string_t const mimetype_app_rtf = GATE_STRING_INIT_STATIC("application/rtf");
635 static gate_string_t const mimetype_app_sh = GATE_STRING_INIT_STATIC("application/x-sh");
636 static gate_string_t const mimetype_app_csh = GATE_STRING_INIT_STATIC("application/x-csh");
637 static gate_string_t const mimetype_app_latex = GATE_STRING_INIT_STATIC("application/x-latex");
638 static gate_string_t const mimetype_app_tar = GATE_STRING_INIT_STATIC("application/x-tar");
639 static gate_string_t const mimetype_app_bcpio = GATE_STRING_INIT_STATIC("application/x-bcpio");
640 static gate_string_t const mimetype_app_cpio = GATE_STRING_INIT_STATIC("application/x-cpio");
641 static gate_string_t const mimetype_app_sv4cpio = GATE_STRING_INIT_STATIC("application/x-sv4cpio");
642 static gate_string_t const mimetype_app_sv4crc = GATE_STRING_INIT_STATIC("application/x-sv4crc");
643 static gate_string_t const mimetype_app_hdf = GATE_STRING_INIT_STATIC("application/x-hdf");
644 static gate_string_t const mimetype_app_ustar = GATE_STRING_INIT_STATIC("application/x-ustar");
645 static gate_string_t const mimetype_app_shar = GATE_STRING_INIT_STATIC("application/x-shar");
646 static gate_string_t const mimetype_app_tcl = GATE_STRING_INIT_STATIC("application/x-tcl");
647 static gate_string_t const mimetype_app_dvi = GATE_STRING_INIT_STATIC("application/x-dvi");
648 static gate_string_t const mimetype_app_texinfo = GATE_STRING_INIT_STATIC("application/x-texinfo");
649 static gate_string_t const mimetype_app_troff = GATE_STRING_INIT_STATIC("application/x-troff");
650 static gate_string_t const mimetype_app_troff_man = GATE_STRING_INIT_STATIC("application/x-troff-man");
651 static gate_string_t const mimetype_app_troff_me = GATE_STRING_INIT_STATIC("application/x-troff-me");
652 static gate_string_t const mimetype_app_troff_ms = GATE_STRING_INIT_STATIC("application/x-troff-ms");
653 static gate_string_t const mimetype_app_netcdf = GATE_STRING_INIT_STATIC("application/x-netcdf");
654 static gate_string_t const mimetype_app_wais_source = GATE_STRING_INIT_STATIC("application/x-wais-source");
655 static gate_string_t const mimetype_app_jar = GATE_STRING_INIT_STATIC("application/x-jar");
656 static gate_string_t const mimetype_app_jnlp = GATE_STRING_INIT_STATIC("application/x-java-jnlp-file");
657 static gate_string_t const mimetype_app_wmlc = GATE_STRING_INIT_STATIC("application/vnd.wap.wmlc");
658 static gate_string_t const mimetype_app_wrl = GATE_STRING_INIT_STATIC("application/x-wrl+xml");
659
660
661 static gate_string_t const mimetype_audio_basic = GATE_STRING_INIT_STATIC("audio/basic");
662 static gate_string_t const mimetype_audio_aiff = GATE_STRING_INIT_STATIC("audio/x-aiff");
663 static gate_string_t const mimetype_audio_dspeeh = GATE_STRING_INIT_STATIC("audio/x-dspeeh");
664 static gate_string_t const mimetype_audio_midi = GATE_STRING_INIT_STATIC("audio/x-midi");
665 static gate_string_t const mimetype_audio_realaudio = GATE_STRING_INIT_STATIC("audio/x-pn-realaudio");
666 static gate_string_t const mimetype_audio_realaudio_plugin = GATE_STRING_INIT_STATIC("audio/x-pn-realaudio-plugin");
667
668 static gate_string_t const mimetype_video_mpeg = GATE_STRING_INIT_STATIC("video/mpeg");
669 static gate_string_t const mimetype_video_quicktime = GATE_STRING_INIT_STATIC("video/quicktime");
670 static gate_string_t const mimetype_video_msvideo = GATE_STRING_INIT_STATIC("video/x-msvideo");
671 static gate_string_t const mimetype_video_sgi_movie = GATE_STRING_INIT_STATIC("video/x-sgi-movie");
672
673
674
675
676 static gate_http_mime_mapping_t gate_http_default_mime_types[] =
677 {
678 { ".txt", &mimetype_text_plain },
679 { ".c", &mimetype_text_plain },
680 { ".cc", &mimetype_text_plain },
681 { ".cpp", &mimetype_text_plain },
682 { ".g", &mimetype_text_plain },
683 { ".h", &mimetype_text_plain },
684 { ".hh", &mimetype_text_plain },
685 { ".hpp", &mimetype_text_plain },
686 { ".m", &mimetype_text_plain },
687 { ".f90", &mimetype_text_plain },
688 { ".rtx", &mimetype_text_richtext },
689 { ".css", &mimetype_text_css },
690 { ".xml", &mimetype_text_xml },
691 { ".htm", &mimetype_text_html },
692 { ".html", &mimetype_text_html },
693 { ".shtm", &mimetype_text_html },
694 { ".shtml", &mimetype_text_html },
695 { ".js", &mimetype_text_js },
696 { ".tsv", &mimetype_text_tsv },
697 { ".etx", &mimetype_text_setext },
698 { ".sgm", &mimetype_text_sgml },
699 { ".sgml", &mimetype_text_sgml },
700 { ".jad", &mimetype_text_jad },
701 { ".wml", &mimetype_text_wml },
702
703
704 { ".gif", &mimetype_image_gif },
705 { ".jpeg", &mimetype_image_jpeg },
706 { ".jpg", &mimetype_image_jpeg },
707 { ".jpe", &mimetype_image_jpeg },
708 { ".tiff", &mimetype_image_tiff },
709 { ".tif", &mimetype_image_tiff },
710 { ".ras", &mimetype_image_cmu_raster },
711 { ".fh4", &mimetype_image_freehand },
712 { ".fh5", &mimetype_image_freehand },
713 { ".fhc", &mimetype_image_freehand },
714 { ".ief", &mimetype_image_ief },
715 { ".pnm", &mimetype_image_anymap },
716 { ".PBM", &mimetype_image_anymap },
717 { ".pgm", &mimetype_image_graymap },
718 { ".ppm", &mimetype_image_pixmap },
719 { ".rgb", &mimetype_image_rgb },
720 { ".xwd", &mimetype_image_windowdump },
721 { ".wbmp", &mimetype_image_wbmp },
722
723
724 { ".exe", &mimetype_app_octet_stream },
725 { ".com", &mimetype_app_octet_stream },
726 { ".dll", &mimetype_app_octet_stream },
727 { ".bin", &mimetype_app_octet_stream },
728 { ".class", &mimetype_app_octet_stream },
729 { ".zip", &mimetype_app_zip },
730 { ".pdf", &mimetype_app_pdf },
731 { ".ps", &mimetype_app_postscript },
732 { ".ai", &mimetype_app_postscript },
733 { ".eps", &mimetype_app_postscript },
734 { ".pac", &mimetype_app_autoconfig },
735 { ".dwg", &mimetype_app_acad },
736 { ".dxf", &mimetype_app_dxf },
737 { ".mif", &mimetype_app_mif },
738 { ".doc", &mimetype_app_msword },
739 { ".dot", &mimetype_app_msword },
740 { ".ppt", &mimetype_app_mspowerpoint },
741 { ".ppz", &mimetype_app_mspowerpoint },
742 { ".pps", &mimetype_app_mspowerpoint },
743 { ".pot", &mimetype_app_mspowerpoint },
744 { ".xls", &mimetype_app_msexcel },
745 { ".xla", &mimetype_app_msexcel },
746 { ".hlp", &mimetype_app_mshelp },
747 { ".chm", &mimetype_app_mshelp },
748 { ".rtf", &mimetype_app_rtf },
749 { ".sh", &mimetype_app_sh },
750 { ".csh", &mimetype_app_csh },
751 { ".latex", &mimetype_app_latex },
752 { ".tar", &mimetype_app_tar },
753 { ".bcpio", &mimetype_app_bcpio },
754 { ".cpio", &mimetype_app_cpio },
755 { ".sv4cpio", &mimetype_app_sv4cpio },
756 { ".sv4crc", &mimetype_app_sv4crc },
757 { ".hdf", &mimetype_app_hdf },
758 { ".ustar", &mimetype_app_ustar },
759 { ".shar", &mimetype_app_shar },
760 { ".tcl", &mimetype_app_tcl },
761 { ".dvi", &mimetype_app_dvi },
762 { ".texinfo", &mimetype_app_texinfo },
763 { ".texi", &mimetype_app_texinfo },
764 { ".t", &mimetype_app_troff },
765 { ".tr", &mimetype_app_troff },
766 { ".roff", &mimetype_app_troff },
767 { ".man", &mimetype_app_troff_man },
768 { ".me", &mimetype_app_troff_me },
769 { ".ms", &mimetype_app_troff_ms },
770 { ".nc", &mimetype_app_netcdf },
771 { ".cdf", &mimetype_app_netcdf },
772 { ".src", &mimetype_app_wais_source },
773 { ".jar", &mimetype_app_jar },
774 { ".jnlp", &mimetype_app_jnlp },
775 { ".wmlc", &mimetype_app_wmlc },
776 { ".wrl", &mimetype_app_wrl },
777
778
779 { ".au", &mimetype_audio_basic },
780 { ".snd", &mimetype_audio_basic },
781 { ".aif", &mimetype_audio_aiff },
782 { ".aiff", &mimetype_audio_aiff },
783 { ".aifc", &mimetype_audio_aiff },
784 { ".dus", &mimetype_audio_dspeeh },
785 { ".cht", &mimetype_audio_dspeeh },
786 { ".midi", &mimetype_audio_midi },
787 { ".mid", &mimetype_audio_midi },
788 { ".ram", &mimetype_audio_realaudio },
789 { ".ra", &mimetype_audio_realaudio },
790 { ".rpm", &mimetype_audio_realaudio_plugin },
791
792 { ".mpeg", &mimetype_video_mpeg },
793 { ".mpg", &mimetype_video_mpeg },
794 { ".mpe", &mimetype_video_mpeg },
795 { ".qt", &mimetype_video_quicktime },
796 { ".mov", &mimetype_video_quicktime },
797 { ".avi", &mimetype_video_msvideo },
798 { ".movie", &mimetype_video_sgi_movie }
799 };
800
801 static gate_size_t const gate_http_default_mime_types_count = sizeof(gate_http_default_mime_types) / sizeof(gate_http_default_mime_types[0]);
802
803
804 2 gate_result_t gate_http_resolve_mime_type(gate_string_t const* file_ext, gate_string_t* mine_type)
805 {
806 gate_size_t ndx;
807
808
1/2
✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
58 for (ndx = 0; ndx != gate_http_default_mime_types_count; ++ndx)
809 {
810
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 56 times.
58 if (gate_string_ends_with_str_ic(file_ext, gate_http_default_mime_types[ndx].file_ext))
811 {
812 2 gate_string_duplicate(mine_type, gate_http_default_mime_types[ndx].mime_type);
813 2 return GATE_RESULT_OK;
814 }
815 }
816 gate_string_duplicate(mine_type, &mimetype_app_octet_stream);
817 return GATE_RESULT_OK;
818 }
819
820 char const* gate_http_resolve_mime_type_str(char const* file_ext)
821 {
822 gate_result_t result;
823 gate_string_t ext;
824 gate_string_t mime = GATE_STRING_INIT_EMPTY;
825 gate_string_create_static(&ext, file_ext);
826 result = gate_http_resolve_mime_type(&ext, &mime);
827 if (GATE_FAILED(result))
828 {
829 return NULL;
830 }
831 else
832 {
833 return mime.str;
834 }
835 }
836