📄 sbinetcookie.cpp
字号:
/****************License************************************************ * * Copyright 2000-2003. ScanSoft, Inc. * * Use of this software is subject to notices and obligations set forth * in the SpeechWorks Public License - Software Version 1.2 which is * included with this software. * * ScanSoft is a registered trademark of ScanSoft, Inc., and OpenSpeech, * SpeechWorks and the SpeechWorks logo are registered trademarks or * trademarks of SpeechWorks International, Inc. in the United States * and other countries. * ***********************************************************************/ #ifndef _SB_USE_STD_NAMESPACE #define _SB_USE_STD_NAMESPACE #endif #include "SBinetCookie.h" #include "SBinetURL.h" #include "HttpUtils.hpp" #include "util_date.h" #include "ap_ctype.h" #include "SWIutilLogger.hpp" #include "SBinetLog.h" #include "SBinetUtils.hpp" /***************************************************************************** ***************************************************************************** * SBinetCookie Implementation ***************************************************************************** ***************************************************************************** */ bool SBinetCookie::matchExact(const SBinetCookie *cookie) const { if (strcasecmp(_Name.c_str(), cookie->_Name.c_str())) return(false); if (strcasecmp(_Domain.c_str(), cookie->_Domain.c_str())) return(false); if (strcasecmp(_Path.c_str(), cookie->_Path.c_str())) return(false); return(true); } bool SBinetCookie::matchDomain(const char *cdomain, const char *domain, const SWIutilLogger *logger) { bool match = true; // Domain name must belong to the domain for the cookie. The rule is that // the cookie's domain must be a suffix of domain. int cDomLen = cdomain == NULL ? 0 : strlen(cdomain); int domlen = domain == NULL ? 0 : strlen(domain); if (cDomLen > domlen) match = false; else if (cDomLen > 0 && strcasecmp(domain + (domlen - cDomLen), cdomain) != 0) match = false; if (logger && logger->DiagIsEnabled(MODULE_SBINET_COOKIE_TAGID)) { logger->Diag(MODULE_SBINET_COOKIE_TAGID, L"SBinetCookie::matchDomain", L"cdomain: '%S', domain: '%S', match = '%s'", cdomain, domain, match ? L"true" : L"false"); } return match; } bool SBinetCookie::matchPath(const char *cpath, const char *path, const SWIutilLogger *logger) { bool match = true; // If the cookie path does not start with a /, then there is no possible // match. if (!cpath || *cpath != '/') match = false; // Idem for the path. else if (!path || *path != '/') match = false; else { const char *p = path + 1; const char *cp = cpath + 1; // First determine where the first difference is. while (*p && *cp && SBinetHttpUtils::toLower(*p) == SBinetHttpUtils::toLower(*cp)) { p++; cp++; } switch (*cp) { case '\0': // The first mismatch is at the end of the cookie-path, if the previous // character is a slash, this a match. Otherwise, we have to make sure // that the mismatch char on the path is an anchor, a slash or a query // arg delimiter. if (*(cp - 1) != '/' && *p && *p != '/' && *p != '?' && *p != '#') match = false; break; case '/': // The first mismatch is / on the cookie-path. If we did not get till // the end of the path, the cookie-path is not a prefix of the path. // However, if the mismatch character on the path is an anchor or a // query argument delimiter, then cookie-path is a prefix of path. if (*p && *p != '?' && *p != '#') match = false; break; default: match = false; break; } } if (logger && logger->DiagIsEnabled(MODULE_SBINET_COOKIE_TAGID)) { logger->Diag(MODULE_SBINET_COOKIE_TAGID, L"SBinetCookie::matchPath", L"cpath: '%S', path: '%S', match = '%s'", cpath, path, match ? L"true" : L"false"); } return match; } bool SBinetCookie::matchRequest(const char *domain, const char *path, const SWIutilLogger* logger) const { bool match = true; if (!matchDomain(_Domain.c_str(), domain, logger)) { match = false; } else if (!matchPath(_Path.c_str(), path, logger)) { match = false; } // TBD, if port was specified by the remote web server for the // cookie, the port must be included in the list of ports of the // cookie's port attribute. We aren't returning that information yet // so we don't even have a port stored in our cookies. if (logger && logger->DiagIsEnabled(MODULE_SBINET_COOKIE_TAGID)) { char expStr[64]; logger->Diag(MODULE_SBINET_COOKIE_TAGID, L"SBinetCookie::matchRequest", L"match: %s, (domain = '%S', path = '%S') compared to " L"(name = '%S', value = '%S', domain = '%S', " L"path = '%S', expires = %S (%d), secure = %s)", (match ? L"true" : L"false"), domain, path, _Name.c_str(), _Value.c_str(), _Domain.c_str(), _Path.c_str(), SBinetUtils::getTimeStampStr(_nExpires, expStr), _nExpires, (_fSecure ? L"true" : L"false")); } return match; } SBinetCookie* SBinetCookie::parse(const SBinetURL *url, const char *&cookiespec, const SWIutilLogger *logger) { const char *p = cookiespec; for (;;) { while (*p && ap_isspace(*p)) p++; if (!*p) { cookiespec = p; return NULL; } if (*p == ',') { // empty header. p++; } else break; } SBinetCookie *cookie = new SBinetCookie(); cookiespec = p; p = SBinetHttpUtils::getToken(p, cookie->_Name); if (p == NULL) { if (logger) logger->Error(252, L"%s%S", L"cookiespec", cookiespec); goto failure; } if ((p = SBinetHttpUtils::expectChar(p,"=")) == NULL || !*p) { if (logger) logger->Error(253, L"%s%S", L"cookiespec", cookiespec); goto failure; } p++; if ((p = SBinetHttpUtils::getCookieValue(p, cookie->_Value)) == NULL) { if (logger) logger->Error(254, L"%s%S", L"cookiespec", cookiespec); goto failure; } p = SBinetHttpUtils::expectChar(p, ",;"); if (p == NULL) { if (logger) logger->Error(255, L"%s%S", L"cookiespec", cookiespec); goto failure; } if (*p) { p = cookie->parseAttributes(p, logger); if (p == NULL) goto failure; } if (cookie->_Domain.length() == 0) cookie->_Domain = url->getHost(); if (cookie->_Path.length() == 0) { const VXIchar *urlPath = url->getPath(); const VXIchar *lastSlash = wcsrchr(urlPath, L'/'); if (!lastSlash || lastSlash == urlPath) { cookie->_Path = "/"; } else { cookie->_Path.clear(); cookie->_Path.append(urlPath, lastSlash - urlPath); } } if (logger && logger->DiagIsEnabled(MODULE_SBINET_COOKIE_TAGID)) { char expStr[64]; logger->Diag(MODULE_SBINET_COOKIE_TAGID, L"SBinetCookie::parse", L"cookie-spec = '%S', name = '%S', value = '%S', " L"domain = '%S', path = '%S', expires = %S (%d), " L"secure = %s", cookiespec, cookie->_Name.c_str(), cookie->_Value.c_str(), cookie->_Domain.c_str(), cookie->_Path.c_str(), SBinetUtils::getTimeStampStr(cookie->_nExpires, expStr), cookie->_nExpires, (cookie->_fSecure ? L"true" : L"false")); } cookiespec = p; return cookie; failure: delete cookie; cookiespec = NULL; return NULL; } SBinetCookie::AttributeInfo SBinetCookie::attributeInfoMap[] = { { "path", true, pathHandler }, { "domain", true, domainHandler }, { "expires", true, expiresHandler }, { "secure", false, secureHandler }, { "max-age", true, maxAgeHandler } }; void SBinetCookie::domainHandler(AttributeInfo *info, const char *value, SBinetCookie *cookie, const SWIutilLogger *logger) { cookie->_Domain = value; } void SBinetCookie::pathHandler(AttributeInfo *info, const char *value, SBinetCookie *cookie, const SWIutilLogger *logger) { cookie->_Path = value; // remove trailing slash if not the only character in the path. int len = cookie->_Path.length(); if (len == 0) cookie->_Path = "/"; else if (--len > 0 && cookie->_Path[len] == '/') cookie->_Path.resize(len); } void SBinetCookie::expiresHandler(AttributeInfo *info, const char *value, SBinetCookie *cookie, const SWIutilLogger *logger) { cookie->_nExpires = ap_parseHTTPdate(value); } void SBinetCookie::secureHandler(AttributeInfo *info, const char *value, SBinetCookie *cookie, const SWIutilLogger *logger) { cookie->_fSecure = true; } void SBinetCookie::maxAgeHandler(AttributeInfo *info, const char *value, SBinetCookie *cookie, const SWIutilLogger *logger) { cookie->_nExpires = time(NULL) + atoi(value); } const char *SBinetCookie::parseAttributes(const char *attributeSpec, const SWIutilLogger *logger) { const char *p = attributeSpec; for (;;) { while (*p && ap_isspace(*p)) p++; // end of cookie string. if (!*p || *p == ',') break; if (*p == ';') { // empty attribute. p++; continue; } attributeSpec = p; SBinetNString attributeNStr; if ((p = SBinetHttpUtils::getToken(p, attributeNStr)) == NULL) { if (logger) logger->Error(256, L"%s%S", L"attributeSpec", attributeSpec); return NULL; } const char *attribute = attributeNStr.c_str(); AttributeInfo *info = NULL; for (int i = (sizeof (attributeInfoMap)) / (sizeof (attributeInfoMap[0])) - 1; i >= 0; i--) { if (strcasecmp(attributeInfoMap[i].name, attribute) == 0) { info = &attributeInfoMap[i]; break; } } // If we haven't found a matching attributeInfo, we assume that the // attribute has a value. bool hasValue = info != NULL ? info->hasValue : true; SBinetNString valueNStr; const char *value = NULL; if (hasValue) { // Now we have to deal with attributes of the form x=y if ((p = SBinetHttpUtils::expectChar(p,"=")) == NULL || !*p) { if (logger) logger->Error(257, L"%s%S%s%S", L"attributeSpec", attributeSpec, L"attribute", attribute); return NULL; } p++; if ((p = SBinetHttpUtils::getCookieValue(p, valueNStr)) == NULL) { if (logger) logger->Error(258, L"%s%S%s%S", L"attributeSpec", attributeSpec, L"attribute", attribute); return NULL; } p = SBinetHttpUtils::expectChar(p, ",;"); value = valueNStr.c_str(); if (p == NULL) { if (logger) logger->Error(259, L"%s%S%s%S%s%S", L"attributeSpec", attributeSpec, L"attribute", attribute, L"value", value); return NULL; } if (logger) logger->Diag(MODULE_SBINET_COOKIE_TAGID, L"SBinetCookie::parseAttributes", L"attribute = <%S>. value = <%S>", attribute, value); } else { p = SBinetHttpUtils::expectChar(p, ",;"); if (p == NULL) { if (logger) logger->Error(260, L"%s%S%s%S", L"attributeSpec", attributeSpec, L"attribute", attribute); return NULL; } if (*p && *p != ',' && *p != ';' && logger) { logger->Error(261, L"%s%S%s%S", L"attributeSpec", attributeSpec, L"attribute", attribute); } } if (info != NULL) { info->handler(info, value, this, logger); } } return p; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -