VWeb/Source/Cookie.cpp

107 lines
3.3 KiB
C++

#include "StringUtils.h"
#include <VWeb.h>
namespace VWeb {
void Cookies::Remove(const std::string &name) {
if (Data.contains(name))
Data.erase(name);
}
bool Cookies::Has(const std::string &name) const { return Data.contains(name); }
std::string Cookies::TransformToHeader() {
std::stringstream view{};
for (auto &cookie : Data) {
auto &realCookie = cookie.second;
if (!realCookie.IsOld && !realCookie.Name.empty() &&
!realCookie.Value.empty())
CookieToString(view, realCookie);
}
return view.str();
}
void Cookies::CreateCookieFromString(const std::string &data) {
auto params = String::Split(data, ";");
Cookie cookie{};
int i = 0;
for (auto &param : params) {
auto split = String::Split(param, "=");
if (split.size() == 1) {
// we have a bool parameter
if (split[0] == "HttpOnly")
cookie.HttpOnly = true;
else if (split[0] == "Secure")
cookie.Secure = true;
} else {
if (i == 0) {
cookie.Name = split[0];
cookie.Value = split[1];
} else {
if (split[0] == "SameSite") {
if (split[1] == "None")
cookie.SameSite = CookieSameSite::None;
else if (split[1] == "Lax")
cookie.SameSite = CookieSameSite::Lax;
else if (split[1] == "Strict")
cookie.SameSite = CookieSameSite::Strict;
} else if (split[0] == "Path")
cookie.Path = split[1];
else if (split[0] == "Domain")
cookie.Domain = split[1];
else if (split[0] == "Max-Age")
cookie.MaxAge = String::ToNumber(split[1], 0);
else if (split[0] == "Expires")
cookie.Expires = split[1];
}
}
i++;
}
if (!cookie.Name.empty() && !cookie.Value.empty())
Data[cookie.Name] = std::move(cookie);
}
void Cookies::CreateOld(const std::string &name, const std::string &value) {
auto& cookie = Data[name];
cookie.Name = name;
cookie.Value = value;
cookie.IsOld = true;
}
void Cookies::CookieToString(std::stringstream &stream, Cookie &cookie) {
if (cookie.Name.empty() || cookie.Value.empty())
return;
std::stringstream view{};
// Cookie names that are starting with __Secure or __Host are Secure only
// Cookies!
if (cookie.Name.starts_with("__Secure"))
cookie.Secure = true;
if (cookie.Name.starts_with("__Host")) {
cookie.Secure = true;
if (cookie.Path.empty())
cookie.Path = "/";
}
view << "Set-Cookie: " << cookie.Name << "=" << cookie.Value;
if (!cookie.Expires.empty())
view << "; Expires=" << cookie.Expires;
if (cookie.MaxAge)
view << "; Max-Age=" << cookie.MaxAge;
if (!cookie.Domain.empty())
view << "; Domain=" << cookie.Domain;
if (!cookie.Path.empty())
view << "; Path=" << cookie.Path;
if (cookie.Secure || cookie.SameSite == CookieSameSite::None)
view << "; Secure";
if (cookie.HttpOnly)
view << "; HttpOnly";
if (cookie.SameSite != CookieSameSite::Invalid) {
std::string sameSiteValue;
switch (cookie.SameSite) {
case CookieSameSite::None: sameSiteValue = "None"; break;
case CookieSameSite::Strict: sameSiteValue = "Strict"; break;
case CookieSameSite::Lax: sameSiteValue = "Lax"; break;
default: break;
}
view << "; SameSite=" << sameSiteValue;
}
view << "\n";
}
} // namespace VWeb