diff options
Diffstat (limited to 'ext/yahttp/yahttp/cookie.hpp')
-rw-r--r-- | ext/yahttp/yahttp/cookie.hpp | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/ext/yahttp/yahttp/cookie.hpp b/ext/yahttp/yahttp/cookie.hpp new file mode 100644 index 0000000..aa5359b --- /dev/null +++ b/ext/yahttp/yahttp/cookie.hpp @@ -0,0 +1,144 @@ +namespace YaHTTP { + /*! Implements a single cookie */ + class Cookie { + public: + Cookie() { + secure = false; + httponly = false; + name = value = ""; + expires = DateTime(); + }; //!< Set the cookie to empty value + + Cookie(const Cookie &rhs) { + name = rhs.name; + value = rhs.value; + domain = rhs.domain; + path = rhs.path; + secure = rhs.secure; + httponly = rhs.httponly; + expires = rhs.expires; + }; //<! Copy cookie values + + Cookie& operator=(const Cookie &rhs) { + name = rhs.name; + value = rhs.value; + domain = rhs.domain; + path = rhs.path; + secure = rhs.secure; + httponly = rhs.httponly; + expires = rhs.expires; + return *this; + } + + DateTime expires; /*!< Expiration date */ + std::string domain; /*!< Domain where cookie is valid */ + std::string path; /*!< Path where the cookie is valid */ + bool httponly; /*!< Whether the cookie is for server use only */ + bool secure; /*!< Whether the cookie is for HTTPS only */ + + std::string name; /*!< Cookie name */ + std::string value; /*!< Cookie value */ + + std::string str() const { + std::ostringstream oss; + oss << YaHTTP::Utility::encodeURL(name) << "=" << YaHTTP::Utility::encodeURL(value); + + if (expires.isSet) + oss << "; expires=" << expires.cookie_str(); + if (domain.size()>0) + oss << "; domain=" << domain; + if (path.size()>0) + oss << "; path=" << path; + if (secure) + oss << "; secure"; + if (httponly) + oss << "; httpOnly"; + return oss.str(); + }; //!< Stringify the cookie + }; + + /*! Implements a Cookie jar for storing multiple cookies */ + class CookieJar { + public: + std::map<std::string, Cookie, ASCIICINullSafeComparator> cookies; //<! cookie container + + CookieJar() {}; //<! constructs empty cookie jar + CookieJar(const CookieJar & rhs) { + this->cookies = rhs.cookies; + } //<! copy cookies from another cookie jar + CookieJar& operator=(const CookieJar & rhs) = default; + + void clear() { + this->cookies.clear(); + } + + void keyValuePair(const std::string &keyvalue, std::string &key, std::string &value) { + size_t pos; + pos = keyvalue.find("="); + if (pos == std::string::npos) throw ParseError("Not a Key-Value pair (cookie)"); + key = std::string(keyvalue.begin(), keyvalue.begin()+pos); + value = std::string(keyvalue.begin()+pos+1, keyvalue.end()); + } //<! key value pair parser + + void parseCookieHeader(const std::string &cookiestr) { + size_t pos, npos; + std::list<Cookie> lcookies; + Cookie c; + pos = 0; + while(pos < cookiestr.size()) { + if ((npos = cookiestr.find("; ", pos)) == std::string::npos) + npos = cookiestr.size(); + keyValuePair(cookiestr.substr(pos, npos-pos), c.name, c.value); + c.name = YaHTTP::Utility::decodeURL(c.name); + c.value = YaHTTP::Utility::decodeURL(c.value); + lcookies.push_back(c); + pos = npos+2; + } + for(std::list<Cookie>::iterator i = lcookies.begin(); i != lcookies.end(); i++) { + this->cookies[i->name] = *i; + } + } + + void parseSetCookieHeader(const std::string &cookiestr) { + Cookie c; + size_t pos,npos; + std::string k, v; + + if ((pos = cookiestr.find("; ", 0)) == std::string::npos) + pos = cookiestr.size(); + keyValuePair(cookiestr.substr(0, pos), c.name, c.value); + c.name = YaHTTP::Utility::decodeURL(c.name); + c.value = YaHTTP::Utility::decodeURL(c.value); + if (pos < cookiestr.size()) pos+=2; + + while(pos < cookiestr.size()) { + if ((npos = cookiestr.find("; ", pos)) == std::string::npos) + npos = cookiestr.size(); + std::string s = cookiestr.substr(pos, npos-pos); + if (s.find("=") != std::string::npos) + keyValuePair(s, k, v); + else + k = s; + if (k == "expires") { + DateTime dt; + dt.parseCookie(v); + c.expires = dt; + } else if (k == "domain") { + c.domain = v; + } else if (k == "path") { + c.path = v; + } else if (k == "httpOnly") { + c.httponly = true; + } else if (k == "secure") { + c.secure = true; + } else { + // ignore crap + break; + } + pos = npos+2; + } + + this->cookies[c.name] = c; + }; //<! Parse multiple cookies from header + }; +}; |