/*!******************************************************************** 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 #include #include #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(this)->getCookie(idx); } const Cookie* CookiesList::getCookie (const std::string& name) const noexcept { return const_cast(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; } } }