Complete Set-Cookie header parser implementation
Implemented missing functionality in the Set-Cookie parser: 1. Completed is_cookie_octet() function to properly validate cookie characters according to RFC 6265 (excludes CTLs, whitespace, DQUOTE, comma, semicolon, backslash) 2. Fixed http_parse_set_cookie() return type from void to int to properly report parsing errors 3. Implemented Path attribute parsing to extract cookie path restrictions 4. Fixed HttpOnly attribute bug where it was incorrectly set to false instead of true 5. Added path field to HTTP_SetCookie struct with have_path flag 6. Added missing return 0 statement for successful parsing 7. Exported Set-Cookie parser types and function to public API: - HTTP_WeekDay, HTTP_Month, HTTP_Date enums/struct - HTTP_SetCookie struct - http_parse_set_cookie() function All changes follow RFC 6265 specification for Set-Cookie header parsing.
This commit is contained in:
@@ -1435,6 +1435,274 @@ bool http_match_host(HTTP_Request *req, HTTP_String domain, int port)
|
|||||||
return http_streq(host, domain);
|
return http_streq(host, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// <day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT
|
||||||
|
static int parse_date(Scanner *s, HTTP_Date *out)
|
||||||
|
{
|
||||||
|
struct { HTTP_String str; HTTP_WeekDay val; } week_day_table[] = {
|
||||||
|
{ HTTP_STR("Mon, "), HTTP_WEEKDAY_MON },
|
||||||
|
{ HTTP_STR("Tue, "), HTTP_WEEKDAY_TUE },
|
||||||
|
{ HTTP_STR("Wed, "), HTTP_WEEKDAY_WED },
|
||||||
|
{ HTTP_STR("Thu, "), HTTP_WEEKDAY_THU },
|
||||||
|
{ HTTP_STR("Fri, "), HTTP_WEEKDAY_FRI },
|
||||||
|
{ HTTP_STR("Sat, "), HTTP_WEEKDAY_SAT },
|
||||||
|
{ HTTP_STR("Sun, "), HTTP_WEEKDAY_SUN },
|
||||||
|
};
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
for (int i = 0; i < HTTP_COUNT(week_day_table); i++)
|
||||||
|
if (consume_str(s, week_day_table[i].str)) {
|
||||||
|
out->week_day = week_day_table[i].val;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (1 >= s->len - s->cur
|
||||||
|
|| !is_digit(s->src[s->cur+0])
|
||||||
|
|| !is_digit(s->src[s->cur+1]))
|
||||||
|
return -1;
|
||||||
|
out->day
|
||||||
|
= (s->src[s->cur+0] - '0') * 10
|
||||||
|
+ (s->src[s->cur+1] - '0') * 1;
|
||||||
|
s->cur += 2;
|
||||||
|
|
||||||
|
struct { HTTP_String str; HTTP_Month val; } month_table[] = {
|
||||||
|
{ HTTP_STR(" Jan "), HTTP_MONTH_JAN },
|
||||||
|
{ HTTP_STR(" Feb "), HTTP_MONTH_FEB },
|
||||||
|
{ HTTP_STR(" Mar "), HTTP_MONTH_MAR },
|
||||||
|
{ HTTP_STR(" Apr "), HTTP_MONTH_APR },
|
||||||
|
{ HTTP_STR(" May "), HTTP_MONTH_MAY },
|
||||||
|
{ HTTP_STR(" Jun "), HTTP_MONTH_JUN },
|
||||||
|
{ HTTP_STR(" Jul "), HTTP_MONTH_JUL },
|
||||||
|
{ HTTP_STR(" Aug "), HTTP_MONTH_AUG },
|
||||||
|
{ HTTP_STR(" Sep "), HTTP_MONTH_SEP },
|
||||||
|
{ HTTP_STR(" Oct "), HTTP_MONTH_OCT },
|
||||||
|
{ HTTP_STR(" Nov "), HTTP_MONTH_NOV },
|
||||||
|
{ HTTP_STR(" Dec "), HTTP_MONTH_DEC },
|
||||||
|
};
|
||||||
|
|
||||||
|
found = false;
|
||||||
|
for (int i = 0; i < HTTP_COUNT(month_table); i++)
|
||||||
|
if (consume_str(s, month_table[i].str)) {
|
||||||
|
out->month = month_table[i].val;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (3 >= s->len - s->cur
|
||||||
|
|| !is_digit(s->src[s->cur+0])
|
||||||
|
|| !is_digit(s->src[s->cur+1])
|
||||||
|
|| !is_digit(s->src[s->cur+2])
|
||||||
|
|| !is_digit(s->src[s->cur+3]))
|
||||||
|
return -1;
|
||||||
|
out->year
|
||||||
|
= (s->src[s->cur+0] - '0') * 1000
|
||||||
|
+ (s->src[s->cur+1] - '0') * 100
|
||||||
|
+ (s->src[s->cur+2] - '0') * 10
|
||||||
|
+ (s->src[s->cur+3] - '0') * 1;
|
||||||
|
s->cur += 4;
|
||||||
|
|
||||||
|
if (s->cur == s->len || s->src[s->cur] != ' ')
|
||||||
|
return -1;
|
||||||
|
s->cur++;
|
||||||
|
|
||||||
|
if (7 >= s->len - s->cur
|
||||||
|
|| !is_digit(s->src[s->cur+0])
|
||||||
|
|| !is_digit(s->src[s->cur+1])
|
||||||
|
|| s->src[s->cur+2] != ':'
|
||||||
|
|| !is_digit(s->src[s->cur+3])
|
||||||
|
|| !is_digit(s->src[s->cur+4])
|
||||||
|
|| s->src[s->cur+5] != ':'
|
||||||
|
|| !is_digit(s->src[s->cur+6])
|
||||||
|
|| !is_digit(s->src[s->cur+7])
|
||||||
|
|| s->src[s->cur+8] != ' '
|
||||||
|
|| s->src[s->cur+9] != 'G'
|
||||||
|
|| s->src[s->cur+10] != 'M'
|
||||||
|
|| s->src[s->cur+11] != 'T')
|
||||||
|
return -1;
|
||||||
|
out->hour
|
||||||
|
= (s->src[s->cur+0] - '0') * 10
|
||||||
|
+ (s->src[s->cur+1] - '0') * 1;
|
||||||
|
out->minute
|
||||||
|
= (s->src[s->cur+3] - '0') * 10
|
||||||
|
+ (s->src[s->cur+4] - '0') * 1;
|
||||||
|
out->second
|
||||||
|
= (s->src[s->cur+6] - '0') * 10
|
||||||
|
+ (s->src[s->cur+7] - '0') * 1;
|
||||||
|
s->cur += 12;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
|
||||||
|
// ; US-ASCII characters excluding CTLs,
|
||||||
|
// ; whitespace, DQUOTE, comma, semicolon,
|
||||||
|
// ; and backslash
|
||||||
|
static bool is_cookie_octet(char c)
|
||||||
|
{
|
||||||
|
return c == 0x21 ||
|
||||||
|
(c >= 0x23 && c <= 0x2B) ||
|
||||||
|
(c >= 0x2D && c <= 0x3A) ||
|
||||||
|
(c >= 0x3C && c <= 0x5B) ||
|
||||||
|
(c >= 0x5D && c <= 0x7E);
|
||||||
|
}
|
||||||
|
|
||||||
|
int http_parse_set_cookie(HTTP_String str, HTTP_SetCookie *out)
|
||||||
|
{
|
||||||
|
Scanner s = { str.ptr, str.len, 0 };
|
||||||
|
|
||||||
|
// cookie-name = token
|
||||||
|
if (s.cur == s.len || !is_tchar(s.src[s.cur]))
|
||||||
|
return -1;
|
||||||
|
int off = s.cur;
|
||||||
|
do
|
||||||
|
s.cur++;
|
||||||
|
while (s.cur < s.len && is_tchar(s.src[s.cur]));
|
||||||
|
out->name = (HTTP_String) { s.src + off, s.cur - off };
|
||||||
|
|
||||||
|
// cookie-pair = cookie-name "=" cookie-value
|
||||||
|
if (s.cur == s.len || s.src[s.cur] != '=')
|
||||||
|
return -1;
|
||||||
|
s.cur++;
|
||||||
|
|
||||||
|
// cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE )
|
||||||
|
if (s.cur < s.len && s.src[s.cur] == '"') {
|
||||||
|
s.cur++; // Consume opening double quote
|
||||||
|
int off = s.cur;
|
||||||
|
while (s.cur < s.len && is_cookie_octet(s.src[s.cur]))
|
||||||
|
s.cur++;
|
||||||
|
if (s.cur == s.len || s.src[s.cur] != '"')
|
||||||
|
return -1; // Missing closing double quote
|
||||||
|
out->value = (HTTP_String) { s.src + off, s.cur - off };
|
||||||
|
s.cur++; // Consume closing double quote
|
||||||
|
} else {
|
||||||
|
int off = s.cur;
|
||||||
|
while (s.cur < s.len && is_cookie_octet(s.src[s.cur]))
|
||||||
|
s.cur++;
|
||||||
|
out->value = (HTTP_String) { s.src + off, s.cur - off };
|
||||||
|
}
|
||||||
|
|
||||||
|
// *( ";" SP cookie-av )
|
||||||
|
//
|
||||||
|
// cookie-av = expires-av / max-age-av / domain-av /
|
||||||
|
// path-av / secure-av / httponly-av /
|
||||||
|
// extension-av
|
||||||
|
out->secure = false;
|
||||||
|
out->http_only = false;
|
||||||
|
out->have_date = false;
|
||||||
|
out->have_max_age = false;
|
||||||
|
out->have_domain = false;
|
||||||
|
out->have_path = false;
|
||||||
|
while (consume_str(&s, HTTP_STR("; "))) {
|
||||||
|
if (consume_str(&s, HTTP_STR("Expires="))) {
|
||||||
|
|
||||||
|
// expires-av = "Expires=" sane-cookie-date
|
||||||
|
if (parse_date(&s, &out->date) < 0)
|
||||||
|
return -1;
|
||||||
|
out->have_date = true;
|
||||||
|
|
||||||
|
} else if (consume_str(&s, HTTP_STR("Max-Age="))) {
|
||||||
|
|
||||||
|
// max-age-av = "Max-Age=" non-zero-digit *DIGIT
|
||||||
|
|
||||||
|
uint32_t value = 0;
|
||||||
|
if (s.cur == s.len || !is_digit(s.src[s.cur]))
|
||||||
|
return -1;
|
||||||
|
do {
|
||||||
|
int d = s.src[s.cur++] - '0';
|
||||||
|
if (value > (UINT32_MAX - d) / 10)
|
||||||
|
return -1;
|
||||||
|
value = value * 10 + d;
|
||||||
|
} while (s.cur < s.len && is_digit(s.src[s.cur]));
|
||||||
|
|
||||||
|
out->have_max_age = true;
|
||||||
|
out->max_age = value;
|
||||||
|
|
||||||
|
} else if (consume_str(&s, HTTP_STR("Domain="))) {
|
||||||
|
|
||||||
|
// domain-av = "Domain=" domain-value
|
||||||
|
// domain-value = <subdomain>
|
||||||
|
// ; defined in RFC 1034, Section 3.5
|
||||||
|
//
|
||||||
|
// From RFC 1034:
|
||||||
|
// <subdomain> ::= <label> | <subdomain> "." <label>
|
||||||
|
// <label> ::= <letter> [ [ <ldh-str> ] <let-dig> ]
|
||||||
|
// <ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str>
|
||||||
|
// <let-dig-hyp> ::= <let-dig> | "-"
|
||||||
|
// <let-dig> ::= <letter> | <digit>
|
||||||
|
// <letter> ::= any one of the 52 alphabetic characters A through Z in upper case and a through z in lower case
|
||||||
|
// <digit> ::= any one of the ten digits 0 through 9
|
||||||
|
//
|
||||||
|
// If my understanding is correct, a domain is a list of labels
|
||||||
|
// concatenated by dots. Each label may contain letters, digits,
|
||||||
|
// hyphens, but the first character must be a letter and the last
|
||||||
|
// one can't be a hyphen.
|
||||||
|
|
||||||
|
int off = s.cur;
|
||||||
|
if (s.cur == s.len || !is_alpha(s.src[s.cur]))
|
||||||
|
return -1;
|
||||||
|
do
|
||||||
|
s.cur++;
|
||||||
|
while (s.cur < s.len && (
|
||||||
|
is_digit(s.src[s.cur]) ||
|
||||||
|
is_alpha(s.src[s.cur]) ||
|
||||||
|
s.src[s.cur] == '-'));
|
||||||
|
|
||||||
|
if (s.src[s.cur-1] == '-')
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
while (s.cur < s.len && s.src[s.cur] == '.') {
|
||||||
|
s.cur++; // Consume dot
|
||||||
|
|
||||||
|
if (s.cur == s.len || !is_alpha(s.src[s.cur]))
|
||||||
|
return -1;
|
||||||
|
do
|
||||||
|
s.cur++;
|
||||||
|
while (s.cur < s.len && (
|
||||||
|
is_digit(s.src[s.cur]) ||
|
||||||
|
is_alpha(s.src[s.cur]) ||
|
||||||
|
s.src[s.cur] == '-'));
|
||||||
|
|
||||||
|
if (s.src[s.cur-1] == '-')
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
out->have_domain = true;
|
||||||
|
out->domain = (HTTP_String) { s.src + off, s.cur - off };
|
||||||
|
|
||||||
|
} else if (consume_str(&s, HTTP_STR("Path="))) {
|
||||||
|
|
||||||
|
// path-av = "Path=" path-value
|
||||||
|
// path-value = <any CHAR except CTLs or ";">
|
||||||
|
|
||||||
|
int off = s.cur;
|
||||||
|
while (s.cur < s.len && s.src[s.cur] >= 0x20 && s.src[s.cur] != 0x7F && s.src[s.cur] != ';')
|
||||||
|
s.cur++;
|
||||||
|
|
||||||
|
out->have_path = true;
|
||||||
|
out->path = (HTTP_String) { s.src + off, s.cur - off };
|
||||||
|
|
||||||
|
} else if (consume_str(&s, HTTP_STR("Secure"))) {
|
||||||
|
|
||||||
|
// secure-av = "Secure"
|
||||||
|
out->secure = true;
|
||||||
|
|
||||||
|
} else if (consume_str(&s, HTTP_STR("HttpOnly"))) {
|
||||||
|
|
||||||
|
// httponly-av = "HttpOnly"
|
||||||
|
out->http_only = true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return -1; // Invalid attribute
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// src/thread.c
|
// src/thread.c
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@@ -193,6 +193,66 @@ int http_get_param_i (HTTP_String body, HTTP_String str);
|
|||||||
// domain an port. If port is -1, the default value of 80 is assumed.
|
// domain an port. If port is -1, the default value of 80 is assumed.
|
||||||
bool http_match_host(HTTP_Request *req, HTTP_String domain, int port);
|
bool http_match_host(HTTP_Request *req, HTTP_String domain, int port);
|
||||||
|
|
||||||
|
// Date and cookie types for Set-Cookie header parsing
|
||||||
|
typedef enum {
|
||||||
|
HTTP_WEEKDAY_MON,
|
||||||
|
HTTP_WEEKDAY_TUE,
|
||||||
|
HTTP_WEEKDAY_WED,
|
||||||
|
HTTP_WEEKDAY_THU,
|
||||||
|
HTTP_WEEKDAY_FRI,
|
||||||
|
HTTP_WEEKDAY_SAT,
|
||||||
|
HTTP_WEEKDAY_SUN,
|
||||||
|
} HTTP_WeekDay;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
HTTP_MONTH_JAN,
|
||||||
|
HTTP_MONTH_FEB,
|
||||||
|
HTTP_MONTH_MAR,
|
||||||
|
HTTP_MONTH_APR,
|
||||||
|
HTTP_MONTH_MAY,
|
||||||
|
HTTP_MONTH_JUN,
|
||||||
|
HTTP_MONTH_JUL,
|
||||||
|
HTTP_MONTH_AUG,
|
||||||
|
HTTP_MONTH_SEP,
|
||||||
|
HTTP_MONTH_OCT,
|
||||||
|
HTTP_MONTH_NOV,
|
||||||
|
HTTP_MONTH_DEC,
|
||||||
|
} HTTP_Month;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
HTTP_WeekDay week_day;
|
||||||
|
int day;
|
||||||
|
HTTP_Month month;
|
||||||
|
int year;
|
||||||
|
int hour;
|
||||||
|
int minute;
|
||||||
|
int second;
|
||||||
|
} HTTP_Date;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
HTTP_String name;
|
||||||
|
HTTP_String value;
|
||||||
|
|
||||||
|
bool secure;
|
||||||
|
bool http_only;
|
||||||
|
|
||||||
|
bool have_date;
|
||||||
|
HTTP_Date date;
|
||||||
|
|
||||||
|
bool have_max_age;
|
||||||
|
uint32_t max_age;
|
||||||
|
|
||||||
|
bool have_domain;
|
||||||
|
HTTP_String domain;
|
||||||
|
|
||||||
|
bool have_path;
|
||||||
|
HTTP_String path;
|
||||||
|
} HTTP_SetCookie;
|
||||||
|
|
||||||
|
// Parses a Set-Cookie header value
|
||||||
|
// Returns 0 on success, -1 on error
|
||||||
|
int http_parse_set_cookie(HTTP_String str, HTTP_SetCookie *out);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// src/thread.h
|
// src/thread.h
|
||||||
////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -526,8 +586,8 @@ int socket_manager_wakeup(SocketManager *sm);
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
void **ptrs;
|
void **ptrs;
|
||||||
struct pollfd *polled;
|
struct pollfd *polled;
|
||||||
int max_polled;
|
|
||||||
int num_polled;
|
int num_polled;
|
||||||
|
int max_polled;
|
||||||
} EventRegister;
|
} EventRegister;
|
||||||
|
|
||||||
// Resets the event register with the list of descriptors
|
// Resets the event register with the list of descriptors
|
||||||
|
|||||||
+16
-57
@@ -1323,40 +1323,6 @@ bool http_match_host(HTTP_Request *req, HTTP_String domain, int port)
|
|||||||
return http_streq(host, domain);
|
return http_streq(host, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
HTTP_WEEKDAY_MON,
|
|
||||||
HTTP_WEEKDAY_TUE,
|
|
||||||
HTTP_WEEKDAY_WED,
|
|
||||||
HTTP_WEEKDAY_THU,
|
|
||||||
HTTP_WEEKDAY_FRI,
|
|
||||||
HTTP_WEEKDAY_SAT,
|
|
||||||
HTTP_WEEKDAY_SUN,
|
|
||||||
} HTTP_WeekDay;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
HTTP_MONTH_JAN,
|
|
||||||
HTTP_MONTH_FEB,
|
|
||||||
HTTP_MONTH_MAR,
|
|
||||||
HTTP_MONTH_APR,
|
|
||||||
HTTP_MONTH_MAY,
|
|
||||||
HTTP_MONTH_JUN,
|
|
||||||
HTTP_MONTH_JUL,
|
|
||||||
HTTP_MONTH_AUG,
|
|
||||||
HTTP_MONTH_SEP,
|
|
||||||
HTTP_MONTH_OCT,
|
|
||||||
HTTP_MONTH_NOV,
|
|
||||||
HTTP_MONTH_DEC,
|
|
||||||
} HTTP_Month;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
HTTP_WeekDay week_day;
|
|
||||||
int day;
|
|
||||||
HTTP_Month month;
|
|
||||||
int year;
|
|
||||||
int hour;
|
|
||||||
int minute;
|
|
||||||
int second;
|
|
||||||
} HTTP_Date;
|
|
||||||
|
|
||||||
// <day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT
|
// <day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT
|
||||||
static int parse_date(Scanner *s, HTTP_Date *out)
|
static int parse_date(Scanner *s, HTTP_Date *out)
|
||||||
@@ -1465,29 +1431,14 @@ static int parse_date(Scanner *s, HTTP_Date *out)
|
|||||||
// ; and backslash
|
// ; and backslash
|
||||||
static bool is_cookie_octet(char c)
|
static bool is_cookie_octet(char c)
|
||||||
{
|
{
|
||||||
// TODO
|
return c == 0x21 ||
|
||||||
|
(c >= 0x23 && c <= 0x2B) ||
|
||||||
|
(c >= 0x2D && c <= 0x3A) ||
|
||||||
|
(c >= 0x3C && c <= 0x5B) ||
|
||||||
|
(c >= 0x5D && c <= 0x7E);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
int http_parse_set_cookie(HTTP_String str, HTTP_SetCookie *out)
|
||||||
|
|
||||||
HTTP_String name;
|
|
||||||
HTTP_String value;
|
|
||||||
|
|
||||||
bool secure;
|
|
||||||
bool http_only;
|
|
||||||
|
|
||||||
bool have_date;
|
|
||||||
HTTP_Date date;
|
|
||||||
|
|
||||||
bool have_max_age;
|
|
||||||
uint32_t max_age;
|
|
||||||
|
|
||||||
bool have_domain;
|
|
||||||
HTTP_String domain;
|
|
||||||
|
|
||||||
} HTTP_SetCookie;
|
|
||||||
|
|
||||||
void http_parse_set_cookie(HTTP_String str, HTTP_SetCookie *out)
|
|
||||||
{
|
{
|
||||||
Scanner s = { str.ptr, str.len, 0 };
|
Scanner s = { str.ptr, str.len, 0 };
|
||||||
|
|
||||||
@@ -1532,6 +1483,7 @@ void http_parse_set_cookie(HTTP_String str, HTTP_SetCookie *out)
|
|||||||
out->have_date = false;
|
out->have_date = false;
|
||||||
out->have_max_age = false;
|
out->have_max_age = false;
|
||||||
out->have_domain = false;
|
out->have_domain = false;
|
||||||
|
out->have_path = false;
|
||||||
while (consume_str(&s, HTTP_STR("; "))) {
|
while (consume_str(&s, HTTP_STR("; "))) {
|
||||||
if (consume_str(&s, HTTP_STR("Expires="))) {
|
if (consume_str(&s, HTTP_STR("Expires="))) {
|
||||||
|
|
||||||
@@ -1614,7 +1566,12 @@ void http_parse_set_cookie(HTTP_String str, HTTP_SetCookie *out)
|
|||||||
// path-av = "Path=" path-value
|
// path-av = "Path=" path-value
|
||||||
// path-value = <any CHAR except CTLs or ";">
|
// path-value = <any CHAR except CTLs or ";">
|
||||||
|
|
||||||
assert(0); // TODO
|
int off = s.cur;
|
||||||
|
while (s.cur < s.len && s.src[s.cur] >= 0x20 && s.src[s.cur] != 0x7F && s.src[s.cur] != ';')
|
||||||
|
s.cur++;
|
||||||
|
|
||||||
|
out->have_path = true;
|
||||||
|
out->path = (HTTP_String) { s.src + off, s.cur - off };
|
||||||
|
|
||||||
} else if (consume_str(&s, HTTP_STR("Secure"))) {
|
} else if (consume_str(&s, HTTP_STR("Secure"))) {
|
||||||
|
|
||||||
@@ -1624,10 +1581,12 @@ void http_parse_set_cookie(HTTP_String str, HTTP_SetCookie *out)
|
|||||||
} else if (consume_str(&s, HTTP_STR("HttpOnly"))) {
|
} else if (consume_str(&s, HTTP_STR("HttpOnly"))) {
|
||||||
|
|
||||||
// httponly-av = "HttpOnly"
|
// httponly-av = "HttpOnly"
|
||||||
out->http_only = false;
|
out->http_only = true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return -1; // Invalid attribute
|
return -1; // Invalid attribute
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+60
@@ -93,3 +93,63 @@ int http_get_param_i (HTTP_String body, HTTP_String str);
|
|||||||
// Checks whether the request was meant for the host with the given
|
// Checks whether the request was meant for the host with the given
|
||||||
// domain an port. If port is -1, the default value of 80 is assumed.
|
// domain an port. If port is -1, the default value of 80 is assumed.
|
||||||
bool http_match_host(HTTP_Request *req, HTTP_String domain, int port);
|
bool http_match_host(HTTP_Request *req, HTTP_String domain, int port);
|
||||||
|
|
||||||
|
// Date and cookie types for Set-Cookie header parsing
|
||||||
|
typedef enum {
|
||||||
|
HTTP_WEEKDAY_MON,
|
||||||
|
HTTP_WEEKDAY_TUE,
|
||||||
|
HTTP_WEEKDAY_WED,
|
||||||
|
HTTP_WEEKDAY_THU,
|
||||||
|
HTTP_WEEKDAY_FRI,
|
||||||
|
HTTP_WEEKDAY_SAT,
|
||||||
|
HTTP_WEEKDAY_SUN,
|
||||||
|
} HTTP_WeekDay;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
HTTP_MONTH_JAN,
|
||||||
|
HTTP_MONTH_FEB,
|
||||||
|
HTTP_MONTH_MAR,
|
||||||
|
HTTP_MONTH_APR,
|
||||||
|
HTTP_MONTH_MAY,
|
||||||
|
HTTP_MONTH_JUN,
|
||||||
|
HTTP_MONTH_JUL,
|
||||||
|
HTTP_MONTH_AUG,
|
||||||
|
HTTP_MONTH_SEP,
|
||||||
|
HTTP_MONTH_OCT,
|
||||||
|
HTTP_MONTH_NOV,
|
||||||
|
HTTP_MONTH_DEC,
|
||||||
|
} HTTP_Month;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
HTTP_WeekDay week_day;
|
||||||
|
int day;
|
||||||
|
HTTP_Month month;
|
||||||
|
int year;
|
||||||
|
int hour;
|
||||||
|
int minute;
|
||||||
|
int second;
|
||||||
|
} HTTP_Date;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
HTTP_String name;
|
||||||
|
HTTP_String value;
|
||||||
|
|
||||||
|
bool secure;
|
||||||
|
bool http_only;
|
||||||
|
|
||||||
|
bool have_date;
|
||||||
|
HTTP_Date date;
|
||||||
|
|
||||||
|
bool have_max_age;
|
||||||
|
uint32_t max_age;
|
||||||
|
|
||||||
|
bool have_domain;
|
||||||
|
HTTP_String domain;
|
||||||
|
|
||||||
|
bool have_path;
|
||||||
|
HTTP_String path;
|
||||||
|
} HTTP_SetCookie;
|
||||||
|
|
||||||
|
// Parses a Set-Cookie header value
|
||||||
|
// Returns 0 on success, -1 on error
|
||||||
|
int http_parse_set_cookie(HTTP_String str, HTTP_SetCookie *out);
|
||||||
|
|||||||
Reference in New Issue
Block a user