107 lines
3.3 KiB
C++
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 ¶m : 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
|