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

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. #include "SBinetString.hpp"
  23. #include "HttpUtils.hpp"
  24. #include <ctype.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include "ap_ctype.h"
  28. #ifdef WIN32
  29. #define WIN32_LEAN_AND_MEAN
  30. #include <windows.h>
  31. #include <stdlib.h>
  32. #else
  33. #include <time.h>
  34. #include <sys/types.h>
  35. #include <sys/time.h>
  36. #include <sys/times.h>
  37. #include <unistd.h>
  38. #include <sys/select.h>
  39. #endif
  40. static void escapeDataIntern(const VXIbyte *data,
  41.                              VXIulong size,
  42.                              SBinetHttpUtils::HttpUriEncoding mask,
  43.                              SBinetNString &result)
  44. {
  45.   /*
  46.    * Bit 0 xalpha
  47.    * Bit 1 xpalpha -- as xalpha but with plus.
  48.    * Bit 2 ... path -- as xpalpha but with /
  49.    */
  50.   static const VXIbyte isAcceptable[96] =
  51.     /*0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xA 0xB 0xC 0xD 0xE 0xF */
  52.   {
  53.     0x0,0x0,0x0,0x0,0x0,0xE,0x0,0x0,0x0,0x0,0xF,0xE,0x0,0xF,0xF,0xC, /* 2x  !"#$%&'()*+,-./   */
  54.     0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0x8,0x0,0x0,0x0,0x0,0x0, /* 3x 0123456789:;<=>?   */
  55.     0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF, /* 4x @ABCDEFGHIJKLMNO   */
  56.     0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0x0,0x0,0x0,0x0,0xF, /* 5X PQRSTUVWXYZ[]^_   */
  57.     0x0,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF, /* 6x `abcdefghijklmno   */
  58.     0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0x0,0x0,0x0,0x0,0x0  /* 7X pqrstuvwxyz{}~DEL */
  59.   };
  60.   static const char *hexChar = "0123456789ABCDEF";
  61.   // Now perform the actual conversion
  62.   const VXIbyte *p;
  63.   VXIulong i;
  64.   for (i = 0, p = data; i < size; i++, p++)
  65.   {
  66.     VXIbyte a = *p;
  67.     if (a < 32 || a >= 128 || !(isAcceptable[a-32] & mask))
  68.     {
  69.       result += '%';
  70.       result += hexChar[a >> 4];
  71.       result += hexChar[a & 15];
  72.     }
  73.     else
  74.       result += static_cast<char>(*p);
  75.   }
  76. }
  77. void SBinetHttpUtils::escapeString(const char *str, HttpUriEncoding mask, SBinetNString &result)
  78. {
  79.   result.clear();
  80.   if (str == NULL) return;
  81.   escapeDataIntern((const VXIbyte *) str, strlen(str), mask, result);
  82. }
  83. void SBinetHttpUtils::escapeData(const void *data,
  84.                                  const int size,
  85.                                  HttpUriEncoding mask,
  86.                                  SBinetNString& result)
  87. {
  88.   result.clear();
  89.   if (data == NULL) return;
  90.   escapeDataIntern((const VXIbyte *) data, size, mask, result);
  91. }
  92. void SBinetHttpUtils::utf8encode(const VXIchar *str, SBinetNString& result)
  93. {
  94.   result.clear();
  95.   if (str == NULL) return;
  96.   //  firstByteMark
  97.   //      A list of values to mask onto the first byte of an encoded sequence,
  98.   //      indexed by the number of bytes used to create the sequence.
  99.   static const char firstByteMark[7] = {  char(0x00), char(0x00), char(0xC0), char(0xE0),
  100.                                           char(0xF0), char(0xF8), char(0xFC) };
  101.   for (const VXIchar *p = str; *p; p++)
  102.   {
  103.     VXIchar c = *p;
  104.     if (c >= 0xD800 && c <= 0xDBFF)
  105.       break;
  106.     unsigned int encodedBytes;
  107.     if (c < 0x80)
  108.       encodedBytes = 1;
  109.     else if (c < 0x800)
  110.       encodedBytes = 2;
  111.     else if (c < 0x10000)
  112.       encodedBytes = 3;
  113.     else if (c < 0x200000)
  114.       encodedBytes = 4;
  115.     else if (c < 0x4000000)
  116.       encodedBytes = 5;
  117.     else if (c <= 0x7FFFFFFF)
  118.       encodedBytes = 6;
  119.     else
  120.     {
  121.       result.clear();
  122.       break;
  123.     }
  124.     //  And spit out the bytes. We spit them out in reverse order
  125.     //  here, so bump up the output pointer and work down as we go.
  126.     char buffer[7] = { 0, 0, 0, 0, 0, 0, 0 };
  127.     char * outPtr = buffer + encodedBytes;
  128.     switch (encodedBytes)
  129.     {
  130.      case 6 :
  131.        *--outPtr = char((c | 0x80) & 0xBF);
  132.       c >>= 6;
  133.      case 5 :
  134.        *--outPtr = char((c | 0x80) & 0xBF);
  135.       c >>= 6;
  136.      case 4 :
  137.        *--outPtr = char((c | 0x80) & 0xBF);
  138.       c >>= 6;
  139.      case 3 :
  140.        *--outPtr = char((c | 0x80) & 0xBF);
  141.       c >>= 6;
  142.      case 2 :
  143.        *--outPtr = char((c | 0x80) & 0xBF);
  144.       c >>= 6;
  145.      case 1 :
  146.        *--outPtr = char(c | firstByteMark[encodedBytes]);
  147.     }
  148.     for (int i = 0; buffer[i] != 0; i++)
  149.       result += buffer[i];
  150.   }
  151. }
  152. const char *SBinetHttpUtils::getToken(const char *str, SBinetNString& token)
  153. {
  154.   static const char *tspecials = "()<>@,;:\"/[]?={} t";
  155.   const char *beg = str;
  156.   while (*beg && ap_isspace(*beg)) beg++;
  157.   if (!*beg) return NULL;
  158.   const char *end = beg;
  159.   while (*end && !strchr(tspecials, *end) && !ap_iscntrl(*end)) end++;
  160.   if (end == beg)
  161.   {
  162.     return NULL;
  163.   }
  164.   token.clear();
  165.   token.append(beg, end - beg);
  166.   return end;
  167. }
  168. const char *SBinetHttpUtils::getQuotedString(const char *str,
  169.      SBinetNString& value)
  170. {
  171.   // skip leading '"'
  172.   ++str;
  173.   value.clear();
  174.   while (*str && *str != '"')
  175.   {
  176.     switch (*str)
  177.     {
  178.      case '\':
  179.        str++;
  180.        if (*str) value += *str;
  181.        break;
  182.      default:
  183.        value += *str;
  184.        break;
  185.     }
  186.     str++;
  187.   }
  188.   if (*str == '"')
  189.     return ++str;
  190.   return NULL;
  191. }
  192. const char *SBinetHttpUtils::getValue(const char *str, SBinetNString& value)
  193. {
  194.   const char *beg = str;
  195.   while (*beg && ap_isspace(*beg)) beg++;
  196.   if (!*beg) return NULL;
  197.   if (*beg == '"')
  198.   {
  199.     return getQuotedString(beg, value);
  200.   }
  201.   else
  202.   {
  203.     return getToken(beg, value);
  204.   }
  205. }
  206. const char *SBinetHttpUtils::getCookieValue(const char *str,
  207.     SBinetNString& value)
  208. {
  209.   const char *beg = str;
  210.   while (*beg && ap_isspace(*beg)) beg++;
  211.   if (!*beg) return NULL;
  212.   if (*beg == '"')
  213.   {
  214.     return getQuotedString(beg, value);
  215.   }
  216.   else
  217.   {
  218.     // The specification says that a value is either a token or a quoted
  219.     // string.  However, a lot of broken servers just don't quote string
  220.     // containing blanks.  We have to include everything up to the semicolon.
  221. #ifdef NO_BROKEN_SERVER
  222.     return getToken(beg, value);
  223. #else
  224.     while (*beg && ap_isspace(*beg)) beg++;
  225.     if (!*beg) return NULL;
  226.     const char *end = beg;
  227.     while (*end && *end != ';')
  228.     {
  229.       // some really broken servers even put a comma in the value.  In this
  230.       // case, we scan the string to find the first occurence of a semi-colon
  231.       // or an equal sign.  If we find the semi-colon first, we assume that
  232.       // the comma is part of the value and the value terminates at the
  233.       // semi-colon location.  Otherwise, the value terminates with the comma.
  234.       if (*end == ',')
  235.       {
  236.         const char *orig_end = end;
  237.         while (*end && *end != ';' && *end != '=') end++;
  238.         if (*end == '=') end = orig_end;
  239.         break;
  240.       }
  241.       end++;
  242.     }
  243.     // removing trailing blanks.
  244.     const char *lastChar = end - 1;
  245.     while (lastChar >= beg && ap_isspace(*lastChar)) lastChar--;
  246.     lastChar++;
  247.     value.clear();
  248.     value.append(beg, lastChar - beg);
  249.     return end;
  250. #endif
  251.   }
  252. }
  253. const char *SBinetHttpUtils::expectChar(const char *start, const char *delim)
  254. {
  255.   while (*start && ap_isspace(*start)) start++;
  256.   if (!*start || strchr(delim, *start))
  257.     return start;
  258.   return NULL;
  259. }
  260. // Sleep with a duration in microseconds
  261. void SBinetHttpUtils::usleep(unsigned long microsecs)
  262. {
  263. #ifdef WIN32
  264.   Sleep (microsecs / 1000);
  265. #else
  266.   fd_set fdset;
  267.   struct timeval timeout;
  268.   FD_ZERO(&fdset);
  269.   timeout.tv_sec = microsecs / 1000000;
  270.   timeout.tv_usec = microsecs % 1000000;
  271.   select(0, &fdset, &fdset, &fdset, &timeout);
  272. #endif
  273. }
  274. // Case insensitive compare
  275. int SBinetHttpUtils::casecmp(const wchar_t *s1, const wchar_t *s2)
  276. {
  277.   register unsigned int u1, u2;
  278.   for (;;) {
  279.     u1 = (unsigned int) *s1++;
  280.     u2 = (unsigned int) *s2++;
  281.     if (toUpper(u1) != toUpper(u2)) {
  282.       return toUpper(u1) - toUpper(u2);
  283.     }
  284.     if (u1 == '') {
  285.       break;
  286.     }
  287.   }
  288.   return 0;
  289. }
  290. int SBinetHttpUtils::casecmp(const wchar_t *s1, const wchar_t *s2,
  291.      register size_t n)
  292. {
  293.   register unsigned int u1, u2;
  294.   for (; n != 0; --n) {
  295.     u1 = (unsigned int) *s1++;
  296.     u2 = (unsigned int) *s2++;
  297.     if (toUpper(u1) != toUpper(u2)) {
  298.       return toUpper(u1) - toUpper(u2);
  299.     }
  300.     if (u1 == '') {
  301.       break;
  302.     }
  303.   }
  304.   return 0;
  305. }