SBinetCookie.cpp
上传用户:xqtpzdz
上传日期:2022-05-21
资源大小:1764k
文件大小:13k
源码类别:

xml/soap/webservice

开发平台:

Visual C++

  1. /****************License************************************************
  2.  * Vocalocity OpenVXI
  3.  * Copyright (C) 2004-2005 by Vocalocity, Inc. All Rights Reserved.
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (at your option) any later version.
  8.  *  
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17.  * Vocalocity, the Vocalocity logo, and VocalOS are trademarks or 
  18.  * registered trademarks of Vocalocity, Inc. 
  19.  * OpenVXI is a trademark of Scansoft, Inc. and used under license 
  20.  * by Vocalocity.
  21.  ***********************************************************************/
  22. #ifndef _SB_USE_STD_NAMESPACE
  23. #define _SB_USE_STD_NAMESPACE
  24. #endif
  25. #include "SBinetCookie.h"
  26. #include "SBinetURL.h"
  27. #include "HttpUtils.hpp"
  28. #include "util_date.h"
  29. #include "ap_ctype.h"
  30. #include "SWIutilLogger.hpp"
  31. #include "SBinetLog.h"
  32. #include "SBinetUtils.hpp"
  33. /*****************************************************************************
  34.  *****************************************************************************
  35.  * SBinetCookie Implementation
  36.  *****************************************************************************
  37.  *****************************************************************************
  38.  */
  39. bool SBinetCookie::matchExact(const SBinetCookie *cookie) const
  40. {
  41.   if (strcasecmp(_Name.c_str(), cookie->_Name.c_str())) return(false);
  42.   if (strcasecmp(_Domain.c_str(), cookie->_Domain.c_str())) return(false);
  43.   if (strcasecmp(_Path.c_str(), cookie->_Path.c_str())) return(false);
  44.   return(true);
  45. }
  46. bool SBinetCookie::matchDomain(const char *cdomain,
  47.                                const char *domain,
  48.                                const SWIutilLogger *logger)
  49. {
  50.   bool match = true;
  51.   // Domain name must belong to the domain for the cookie.  The rule is that
  52.   // the cookie's domain must be a suffix of domain.
  53.   int cDomLen = cdomain == NULL ? 0 : strlen(cdomain);
  54.   int domlen = domain == NULL ? 0 : strlen(domain);
  55.   if (cDomLen > domlen)
  56.     match = false;
  57.   else if (cDomLen > 0 &&
  58.            strcasecmp(domain + (domlen - cDomLen), cdomain) != 0)
  59.     match = false;
  60.   if (logger && logger->DiagIsEnabled(MODULE_SBINET_COOKIE_TAGID))
  61.   {
  62.     logger->Diag(MODULE_SBINET_COOKIE_TAGID,
  63.                  L"SBinetCookie::matchDomain",
  64.                  L"cdomain: '%S', domain: '%S', match = '%s'",
  65.                  cdomain, domain, match ? L"true" : L"false");
  66.   }
  67.   return match;
  68. }
  69. bool SBinetCookie::matchPath(const char *cpath,
  70.                              const char *path,
  71.                              const SWIutilLogger *logger)
  72. {
  73.   bool match = true;
  74.   // If the cookie path does not start with a /, then there is no possible
  75.   // match.
  76.   if (!cpath || *cpath != '/')
  77.     match = false;
  78.   // Idem for the path.
  79.   else if (!path || *path != '/')
  80.     match = false;
  81.   else
  82.   {
  83.     const char *p = path + 1;
  84.     const char *cp = cpath + 1;
  85.     // First determine where the first difference is.
  86.     while (*p && *cp &&
  87.            SBinetHttpUtils::toLower(*p) == SBinetHttpUtils::toLower(*cp))
  88.     {
  89.       p++;
  90.       cp++;
  91.     }
  92.     switch (*cp)
  93.     {
  94.      case '':
  95.        // The first mismatch is at the end of the cookie-path, if the previous
  96.        // character is a slash, this a match.  Otherwise, we have to make sure
  97.        // that the mismatch char on the path is an anchor, a slash or a query
  98.        // arg delimiter.
  99.        if (*(cp - 1) != '/' && *p && *p != '/' && *p != '?' && *p != '#')
  100.          match = false;
  101.        break;
  102.      case '/':
  103.        // The first mismatch is / on the cookie-path.  If we did not get till
  104.        // the end of the path, the cookie-path is not a prefix of the path.
  105.        // However, if the mismatch character on the path is an anchor or a
  106.        // query argument delimiter, then cookie-path is a prefix of path.
  107.        if (*p && *p != '?' && *p != '#')
  108.          match = false;
  109.        break;
  110.      default:
  111.        match = false;
  112.        break;
  113.     }
  114.   }
  115.   if (logger && logger->DiagIsEnabled(MODULE_SBINET_COOKIE_TAGID))
  116.   {
  117.     logger->Diag(MODULE_SBINET_COOKIE_TAGID, L"SBinetCookie::matchPath",
  118.                  L"cpath: '%S', path: '%S', match = '%s'",
  119.                  cpath, path, match ? L"true" : L"false");
  120.   }
  121.   return match;
  122. }
  123. bool SBinetCookie::matchRequest(const char *domain,
  124.                                 const char *path,
  125.                                 const SWIutilLogger* logger) const
  126. {
  127.   bool match = true;
  128.   if (!matchDomain(_Domain.c_str(), domain, logger))
  129.   {
  130.     match = false;
  131.   }
  132.   else if (!matchPath(_Path.c_str(), path, logger))
  133.   {
  134.     match = false;
  135.   }
  136.   // TBD, if port was specified by the remote web server for the
  137.   // cookie, the port must be included in the list of ports of the
  138.   // cookie's port attribute. We aren't returning that information yet
  139.   // so we don't even have a port stored in our cookies.
  140.   if (logger && logger->DiagIsEnabled(MODULE_SBINET_COOKIE_TAGID))
  141.   {
  142.     char expStr[64];
  143.     logger->Diag(MODULE_SBINET_COOKIE_TAGID, L"SBinetCookie::matchRequest",
  144.  L"match: %s, (domain = '%S', path = '%S') compared to "
  145.  L"(name = '%S', value = '%S', domain = '%S', "
  146.  L"path = '%S', expires = %S (%d), secure = %s)",
  147.  (match ? L"true" : L"false"), domain, path, _Name.c_str(),
  148.  _Value.c_str(), _Domain.c_str(), _Path.c_str(),
  149.  SBinetUtils::getTimeStampStr(_nExpires, expStr),
  150.  _nExpires, (_fSecure ? L"true" : L"false"));
  151.   }
  152.   return match;
  153. }
  154. SBinetCookie* SBinetCookie::parse(const SBinetURL *url,
  155.                                   const char *&cookiespec,
  156.                                   const SWIutilLogger *logger)
  157. {
  158.   const char *p = cookiespec;
  159.   for (;;)
  160.   {
  161.     while (*p && ap_isspace(*p)) p++;
  162.     if (!*p)
  163.     {
  164.       cookiespec = p;
  165.       return NULL;
  166.     }
  167.     if (*p == ',')
  168.     {
  169.       // empty header.
  170.       p++;
  171.     }
  172.     else
  173.       break;
  174.   }
  175.   SBinetCookie *cookie = new SBinetCookie();
  176.   cookiespec = p;
  177.   p = SBinetHttpUtils::getToken(p, cookie->_Name);
  178.   if (p == NULL)
  179.   {
  180.     if (logger) logger->Error(252, L"%s%S", L"cookiespec", cookiespec);
  181.     goto failure;
  182.   }
  183.   if ((p = SBinetHttpUtils::expectChar(p,"=")) == NULL || !*p)
  184.   {
  185.     if (logger) logger->Error(253, L"%s%S", L"cookiespec", cookiespec);
  186.     goto failure;
  187.   }
  188.   p++;
  189.   if ((p = SBinetHttpUtils::getCookieValue(p, cookie->_Value)) == NULL)
  190.   {
  191.     if (logger) logger->Error(254, L"%s%S", L"cookiespec", cookiespec);
  192.     goto failure;
  193.   }
  194.   p = SBinetHttpUtils::expectChar(p, ",;");
  195.   if (p == NULL)
  196.   {
  197.     if (logger) logger->Error(255, L"%s%S", L"cookiespec", cookiespec);
  198.     goto failure;
  199.   }
  200.   if (*p)
  201.   {
  202.     p = cookie->parseAttributes(p, logger);
  203.     if (p == NULL)
  204.       goto failure;
  205.   }
  206.   if (cookie->_Domain.length() == 0)
  207.     cookie->_Domain = url->getHost();
  208.   if (cookie->_Path.length() == 0)
  209.   {
  210.     const VXIchar *urlPath = url->getPath();
  211.     const VXIchar *lastSlash = wcsrchr(urlPath, L'/');
  212.     if (!lastSlash || lastSlash == urlPath)
  213.     {
  214.       cookie->_Path = "/";
  215.     }
  216.     else
  217.     {
  218.       cookie->_Path.clear();
  219.       cookie->_Path.append(urlPath, lastSlash - urlPath);
  220.     }
  221.   }
  222.   if (logger && logger->DiagIsEnabled(MODULE_SBINET_COOKIE_TAGID))
  223.   {
  224.     char expStr[64];
  225.     logger->Diag(MODULE_SBINET_COOKIE_TAGID, L"SBinetCookie::parse",
  226.  L"cookie-spec = '%S', name = '%S', value = '%S', "
  227.  L"domain = '%S', path = '%S', expires = %S (%d), "
  228.  L"secure = %s",
  229.  cookiespec, cookie->_Name.c_str(), cookie->_Value.c_str(),
  230.  cookie->_Domain.c_str(), cookie->_Path.c_str(),
  231.  SBinetUtils::getTimeStampStr(cookie->_nExpires, expStr),
  232.  cookie->_nExpires, (cookie->_fSecure ? L"true" : L"false"));
  233.   }
  234.   cookiespec = p;
  235.   return cookie;
  236.  failure:
  237.   delete cookie;
  238.   cookiespec = NULL;
  239.   return NULL;
  240. }
  241. SBinetCookie::AttributeInfo SBinetCookie::attributeInfoMap[] = {
  242.   { "path", true, pathHandler },
  243.   { "domain", true, domainHandler },
  244.   { "expires", true, expiresHandler },
  245.   { "secure", false, secureHandler },
  246.   { "max-age", true, maxAgeHandler }
  247. };
  248. void SBinetCookie::domainHandler(AttributeInfo *info, const char *value,
  249.                                  SBinetCookie *cookie,
  250.                                  const SWIutilLogger *logger)
  251. {
  252.   cookie->_Domain = value;
  253. }
  254. void SBinetCookie::pathHandler(AttributeInfo *info, const char *value,
  255.                                SBinetCookie *cookie,
  256.                                const SWIutilLogger *logger)
  257. {
  258.   cookie->_Path = value;
  259.   // remove trailing slash if not the only character in the path.
  260.   int len = cookie->_Path.length();
  261.   if (len == 0)
  262.     cookie->_Path = "/";
  263.   else if (--len > 0 && cookie->_Path[len] == '/')
  264.     cookie->_Path.resize(len);
  265. }
  266. void SBinetCookie::expiresHandler(AttributeInfo *info, const char *value,
  267.                                   SBinetCookie *cookie,
  268.                                   const SWIutilLogger *logger)
  269. {
  270.   cookie->_nExpires = ap_parseHTTPdate(value);
  271. }
  272. void SBinetCookie::secureHandler(AttributeInfo *info, const char *value,
  273.                                  SBinetCookie *cookie,
  274.                                  const SWIutilLogger *logger)
  275. {
  276.   cookie->_fSecure = true;
  277. }
  278. void SBinetCookie::maxAgeHandler(AttributeInfo *info, const char *value,
  279.                                  SBinetCookie *cookie,
  280.                                  const SWIutilLogger *logger)
  281. {
  282.   cookie->_nExpires = time(NULL) + atoi(value);
  283. }
  284. const char *SBinetCookie::parseAttributes(const char *attributeSpec,
  285.                                           const SWIutilLogger *logger)
  286. {
  287.   const char *p = attributeSpec;
  288.   for (;;)
  289.   {
  290.     while (*p && ap_isspace(*p)) p++;
  291.     // end of cookie string.
  292.     if (!*p || *p == ',') break;
  293.     if (*p == ';')
  294.     {
  295.       // empty attribute.
  296.       p++;
  297.       continue;
  298.     }
  299.     attributeSpec = p;
  300.     SBinetNString attributeNStr;
  301.     if ((p = SBinetHttpUtils::getToken(p, attributeNStr)) == NULL)
  302.     {
  303.       if (logger)
  304.         logger->Error(256, L"%s%S", L"attributeSpec", attributeSpec);
  305.       return NULL;
  306.     }
  307.     const char *attribute = attributeNStr.c_str();
  308.     AttributeInfo *info = NULL;
  309.     for (int i = (sizeof (attributeInfoMap)) / (sizeof (attributeInfoMap[0])) - 1; i >= 0; i--)
  310.     {
  311.       if (strcasecmp(attributeInfoMap[i].name, attribute) == 0)
  312.       {
  313.         info = &attributeInfoMap[i];
  314.         break;
  315.       }
  316.     }
  317.     // If we haven't found a matching attributeInfo, we assume that the
  318.     // attribute has a value.
  319.     bool hasValue = info != NULL ? info->hasValue : true;
  320.     SBinetNString valueNStr;
  321.     const char *value = NULL;
  322.     if (hasValue)
  323.     {
  324.       // Now we have to deal with attributes of the form x=y
  325.       if ((p = SBinetHttpUtils::expectChar(p,"=")) == NULL || !*p)
  326.       {
  327.         if (logger)
  328.           logger->Error(257, L"%s%S%s%S", L"attributeSpec", attributeSpec,
  329.                         L"attribute", attribute);
  330.         return NULL;
  331.       }
  332.       p++;
  333.       if ((p = SBinetHttpUtils::getCookieValue(p, valueNStr)) == NULL)
  334.       {
  335.         if (logger)
  336.           logger->Error(258, L"%s%S%s%S", L"attributeSpec", attributeSpec,
  337.                         L"attribute", attribute);
  338.         return NULL;
  339.       }
  340.       p = SBinetHttpUtils::expectChar(p, ",;");
  341.       value = valueNStr.c_str();
  342.       if (p == NULL)
  343.       {
  344.         if (logger)
  345.           logger->Error(259, L"%s%S%s%S%s%S",
  346.                         L"attributeSpec", attributeSpec,
  347.                         L"attribute", attribute, L"value", value);
  348.         return NULL;
  349.       }
  350.       if (logger)
  351.         logger->Diag(MODULE_SBINET_COOKIE_TAGID,
  352.                      L"SBinetCookie::parseAttributes",
  353.                      L"attribute = <%S>. value = <%S>", attribute, value);
  354.     }
  355.     else
  356.     {
  357.       p = SBinetHttpUtils::expectChar(p, ",;");
  358.       if (p == NULL)
  359.       {
  360.         if (logger)
  361.           logger->Error(260, L"%s%S%s%S",
  362.                         L"attributeSpec", attributeSpec,
  363.                         L"attribute", attribute);
  364.         return NULL;
  365.       }
  366.       if (*p && *p != ',' && *p != ';' && logger)
  367.       {
  368.         logger->Error(261, L"%s%S%s%S", L"attributeSpec", attributeSpec,
  369.                       L"attribute", attribute);
  370.       }
  371.     }
  372.     if (info != NULL)
  373.     {
  374.       info->handler(info, value, this, logger);
  375.     }
  376.   }
  377.   return p;
  378. }