#include "CookieJar.h"
namespace panda { namespace protocol { namespace http {
#define CURSTR (buffer.substr(mark, p - ps - mark))
%%{
machine jar_parser;
Q = '"';
N = "\n";
action mark {
mark = fpc - ps;
}
action origin {
v.origin(new URI(CURSTR));
}
action expires {
string str(CURSTR);
uint64_t val;
auto res = panda::from_chars(str.data(), str.data() + str.size(), val);
if (res.ec == std::errc()) {
v.expires(Date(val));
}
}
action same_site {
auto s(CURSTR);
SameSite val{SameSite::disabled};
if (s == "N") val = SameSite::None;
else if (s == "S") val = SameSite::Strict;
else if (s == "L") val = SameSite::Lax;
v.same_site(val);
}
action push_cookie {
string idomain = canonize(v.domain());
auto& cookies = dest[idomain];
cookies.emplace_back(std::move(v));
v = CookieJar::Cookie();
}
key_av = Q "key" Q ":" Q (any - Q)+ >mark %{ v.name(CURSTR); } Q;
value_av = Q "value" Q ":" Q (any - Q)+ >mark %{ v.value(CURSTR); } Q;
domain_av = Q "domain" Q ":" Q (any - Q)+ >mark %{ v.domain(CURSTR); } Q;
path_av = Q "path" Q ":" Q (any - Q)+ >mark %{ v.path(CURSTR); } Q;
host_only_av = Q "host_only" Q ":" Q (any - Q)+ >mark %{ v.host_only(true); } Q;
secure_av = Q "secure" Q ":" Q (any - Q)+ >mark %{ v.secure(true); } Q;
http_only_av = Q "http_only" Q ":" Q (any - Q)+ >mark %{ v.http_only(true); } Q;
expires_av = Q "expires" Q ":" Q (any - Q)+ >mark %expires Q;
same_site_av = Q "same_site" Q ":" Q (any - Q)+ >mark %same_site Q;
origin_av = Q "origin" Q ":" Q (any - Q)+ >mark %origin Q;
cookie_val = key_av | value_av | domain_av | path_av | host_only_av |secure_av | http_only_av | expires_av | same_site_av | origin_av;
cookie = "{" cookie_val (", " cookie_val)* %push_cookie "}";
cookies_coll = "[" N (cookie (",\n" cookie)*)? N? "]";
main := cookies_coll;
write data;
}%%
std::error_code CookieJar::parse_cookies(const string& buffer, DomainCookies& dest) noexcept {
using SameSite = Response::Cookie::SameSite;
const char* ps = buffer.data();
const char* p = ps;
const char* pe = ps + buffer.size();
int cs = jar_parser_start;
size_t mark;
CookieJar::Cookie v;
%% write exec;
if (p == pe) return {};
else return make_error_code(errc::corrupted_cookie_jar);
}
}}}