audacia/libraries/lib-network-manager/CookiesList.cpp

216 lines
5.0 KiB
C++

/*!********************************************************************
Audacity: A Digital Audio Editor
@file CookiesList.cpp
@brief Define HTTP cookies list class.
Dmitry Vedenko
**********************************************************************/
/*!********************************************************************
@class Cookie
@brief A struct, representing a Cookie object.
**********************************************************************/
/*!********************************************************************
@class CookiesList
@brief A class, representing a list of HTTP cookies.
**********************************************************************/
#include "CookiesList.h"
#include <sstream>
#include <cstring>
#include <algorithm>
#include "DateTimeConversions.h"
namespace audacity
{
namespace network_manager
{
Cookie Cookie::Parse (const std::string& cookieString)
{
const size_t equalsPosition = cookieString.find ('=');
if (equalsPosition == std::string::npos)
return { cookieString, std::string () };
std::string name = cookieString.substr (0, equalsPosition);
const size_t firstValueIndex = equalsPosition + 1;
const size_t semicolonPosition = cookieString.find (';', firstValueIndex);
Cookie cookie;
cookie.Name = std::move (name);
cookie.Value = semicolonPosition == std::string::npos ?
cookieString.substr (firstValueIndex) :
cookieString.substr (firstValueIndex, semicolonPosition - firstValueIndex);
size_t expiresPosition = cookieString.find("Expires=");
if (expiresPosition != std::string::npos)
{
expiresPosition += std::strlen ("Expires=");
const size_t trailingSemicolon = cookieString.find (';', expiresPosition);
std::string expiresValue =
trailingSemicolon == std::string::npos ?
cookieString.substr (expiresPosition) :
cookieString.substr (expiresPosition, trailingSemicolon - expiresPosition);
// Hack around Yandex violating RFC
std::replace (expiresValue.begin(), expiresValue.end(), '-', ' ');
ParseRFC822Date (expiresValue, &cookie.Expires);
}
return cookie;
}
bool Cookie::isSession () const noexcept
{
return Expires == ExpiresTime {};
}
std::string Cookie::toString (bool fullString) const
{
std::ostringstream stream;
stream << Name << "=" << Value;
if (fullString)
{
if (!isSession())
stream << "; " << "Expires=" << SerializeRFC822Date(Expires);
}
return stream.str ();
}
bool Cookie::isExpired () const noexcept
{
return !isSession() &&
std::chrono::system_clock::now() >= Expires;
}
void CookiesList::setCookie (const Cookie& cookie)
{
setCookie (cookie.Name, cookie.Value);
}
void CookiesList::setCookie (const std::string& cookieName, std::string cookieValue)
{
Cookie* item = getCookie (cookieName);
if (item != nullptr)
item->Value = std::move (cookieValue);
else
mCookies.push_back ({ cookieName, std::move (cookieValue) });
}
void CookiesList::addCookie (Cookie cookie)
{
addCookie (std::move (cookie.Name), std::move (cookie.Value));
}
void CookiesList::addCookie (std::string cookieName, std::string cookieValue)
{
mCookies.push_back ({ std::move (cookieName), std::move (cookieValue) });
}
bool CookiesList::hasCookie (const std::string& cookieName) const noexcept
{
return getCookie (cookieName) != nullptr;
}
std::string CookiesList::getCookieValue (const std::string& cookieName) const
{
const Cookie* item = getCookie (cookieName);
if (item != nullptr)
return item->Value;
return {};
}
const Cookie* CookiesList::getCookie (size_t idx) const noexcept
{
return const_cast<CookiesList*>(this)->getCookie(idx);
}
const Cookie* CookiesList::getCookie (const std::string& name) const noexcept
{
return const_cast<CookiesList*>(this)->getCookie (name);
}
size_t CookiesList::getCookiesCount () const noexcept
{
return mCookies.size ();
}
std::string CookiesList::getCookiesString () const
{
std::string result;
for (const Cookie& cookie : mCookies)
{
if (!result.empty ())
result.push_back (';');
result += cookie.Name + "=" + cookie.Value;
}
return result;
}
CookiesList::CookiesIterator CookiesList::begin () noexcept
{
return mCookies.begin ();
}
CookiesList::CookiesIterator CookiesList::end () noexcept
{
return mCookies.end ();
}
CookiesList::CookiesConstIterator CookiesList::begin () const noexcept
{
return mCookies.begin ();
}
CookiesList::CookiesConstIterator CookiesList::end () const noexcept
{
return mCookies.end ();
}
Cookie* CookiesList::getCookie (size_t idx) noexcept
{
if (idx < mCookies.size ())
return &mCookies[idx];
return nullptr;
}
Cookie* CookiesList::getCookie (const std::string& cookieName) noexcept
{
for (Cookie& cookie : mCookies)
{
if (cookie.Name == cookieName)
return &cookie;
}
return nullptr;
}
}
}