Update chttp.c/.h
This commit is contained in:
@@ -1,4 +1,6 @@
|
|||||||
|
#ifndef HTTP_NOINCLUDE
|
||||||
#include "chttp.h"
|
#include "chttp.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// src/sec.h
|
// src/sec.h
|
||||||
@@ -1517,6 +1519,159 @@ int http_parse_response(char *src, int len, HTTP_Response *res)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HTTP_String http_get_cookie(HTTP_Request *req, HTTP_String name)
|
||||||
|
{
|
||||||
|
// TODO: best-effort implementation
|
||||||
|
|
||||||
|
for (int i = 0; i < req->num_headers; i++) {
|
||||||
|
|
||||||
|
if (!http_streqcase(req->headers[i].name, HTTP_STR("Cookie")))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
char *src = req->headers[i].value.ptr;
|
||||||
|
int len = req->headers[i].value.len;
|
||||||
|
int cur = 0;
|
||||||
|
|
||||||
|
// Cookie: name1=value1; name2=value2; name3=value3
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
|
||||||
|
while (cur < len && src[cur] == ' ')
|
||||||
|
cur++;
|
||||||
|
|
||||||
|
int off = cur;
|
||||||
|
while (cur < len && src[cur] != '=')
|
||||||
|
cur++;
|
||||||
|
|
||||||
|
HTTP_String cookie_name = { src + off, cur - off };
|
||||||
|
|
||||||
|
if (cur == len)
|
||||||
|
break;
|
||||||
|
cur++;
|
||||||
|
|
||||||
|
off = cur;
|
||||||
|
while (cur < len && src[cur] != ';')
|
||||||
|
cur++;
|
||||||
|
|
||||||
|
HTTP_String cookie_value = { src + off, cur - off };
|
||||||
|
|
||||||
|
if (http_streq(name, cookie_name))
|
||||||
|
return cookie_value;
|
||||||
|
|
||||||
|
if (cur == len)
|
||||||
|
break;
|
||||||
|
cur++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return HTTP_STR("");
|
||||||
|
}
|
||||||
|
|
||||||
|
HTTP_String http_get_param(HTTP_String body, HTTP_String str, char *mem, int cap)
|
||||||
|
{
|
||||||
|
// This is just a best-effort implementation
|
||||||
|
|
||||||
|
char *src = body.ptr;
|
||||||
|
int len = body.len;
|
||||||
|
int cur = 0;
|
||||||
|
|
||||||
|
if (cur < len && src[cur] == '?')
|
||||||
|
cur++;
|
||||||
|
|
||||||
|
while (cur < len) {
|
||||||
|
|
||||||
|
HTTP_String name;
|
||||||
|
{
|
||||||
|
int off = cur;
|
||||||
|
while (cur < len && src[cur] != '=' && src[cur] != '&')
|
||||||
|
cur++;
|
||||||
|
name = (HTTP_String) { src + off, cur - off };
|
||||||
|
}
|
||||||
|
|
||||||
|
HTTP_String body = HTTP_STR("");
|
||||||
|
if (cur < len) {
|
||||||
|
cur++;
|
||||||
|
if (src[cur-1] == '=') {
|
||||||
|
int off = cur;
|
||||||
|
while (cur < len && src[cur] != '&')
|
||||||
|
cur++;
|
||||||
|
body = (HTTP_String) { src + off, cur - off };
|
||||||
|
|
||||||
|
if (cur < len)
|
||||||
|
cur++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (http_streq(str, name)) {
|
||||||
|
|
||||||
|
bool percent_encoded = false;
|
||||||
|
for (int i = 0; i < body.len; i++)
|
||||||
|
if (body.ptr[i] == '+' || body.ptr[i] == '%') {
|
||||||
|
percent_encoded = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!percent_encoded)
|
||||||
|
return body;
|
||||||
|
|
||||||
|
if (body.len > cap)
|
||||||
|
return (HTTP_String) { NULL, 0 };
|
||||||
|
|
||||||
|
HTTP_String decoded = { mem, 0 };
|
||||||
|
for (int i = 0; i < body.len; i++) {
|
||||||
|
|
||||||
|
char c = body.ptr[i];
|
||||||
|
if (c == '+')
|
||||||
|
c = ' ';
|
||||||
|
else {
|
||||||
|
if (body.ptr[i] == '%') {
|
||||||
|
if (body.len - i < 3
|
||||||
|
|| !is_hex_digit(body.ptr[i+1])
|
||||||
|
|| !is_hex_digit(body.ptr[i+2]))
|
||||||
|
return (HTTP_String) { NULL, 0 };
|
||||||
|
|
||||||
|
int h = hex_digit_to_int(body.ptr[i+1]);
|
||||||
|
int l = hex_digit_to_int(body.ptr[i+2]);
|
||||||
|
c = (h << 4) | l;
|
||||||
|
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
decoded.ptr[decoded.len++] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
return decoded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return HTTP_STR("");
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_digit(char c)
|
||||||
|
{
|
||||||
|
return c >= '0' && c <= '9';
|
||||||
|
}
|
||||||
|
|
||||||
|
int http_get_param_i(HTTP_String body, HTTP_String str)
|
||||||
|
{
|
||||||
|
char buf[128];
|
||||||
|
HTTP_String out = http_get_param(body, str, buf, SIZEOF(buf));
|
||||||
|
if (out.len == 0 || !is_digit(out.ptr[0]))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
int cur = 0;
|
||||||
|
int res = 0;
|
||||||
|
do {
|
||||||
|
int d = out.ptr[cur++] - '0';
|
||||||
|
if (res > (INT_MAX - d) / 10)
|
||||||
|
return -1;
|
||||||
|
res = res * 10 + d;
|
||||||
|
} while (cur < out.len && is_digit(out.ptr[cur]));
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// src/engine.c
|
// src/engine.c
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@@ -189,6 +189,11 @@ int http_parse_response (char *src, int len, HTTP_Response *res);
|
|||||||
|
|
||||||
int http_find_header (HTTP_Header *headers, int num_headers, HTTP_String name);
|
int http_find_header (HTTP_Header *headers, int num_headers, HTTP_String name);
|
||||||
|
|
||||||
|
HTTP_String http_get_cookie (HTTP_Request *req, HTTP_String name);
|
||||||
|
HTTP_String http_get_param (HTTP_String body, HTTP_String str, char *mem, int cap);
|
||||||
|
int http_get_param_i (HTTP_String body, HTTP_String str);
|
||||||
|
|
||||||
|
|
||||||
#endif // PARSE_INCLUDED
|
#endif // PARSE_INCLUDED
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
Reference in New Issue
Block a user