mimescan.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:8k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. #include "hlxclib/ctype.h"
  36. //#include "hlxclib/string.h"
  37. #if !defined(_WINDOWS) && !defined(_OPENWAVE)
  38. #include <unistd.h> // not supported by VC++
  39. #endif
  40. #include "mimescan.h"
  41. #include "hxheap.h"
  42. #ifdef _DEBUG
  43. #undef HX_THIS_FILE
  44. static const char HX_THIS_FILE[] = __FILE__;
  45. #endif
  46. MIMEInputStream::MIMEInputStream(const char* pBuf, UINT32 nBufSize):
  47.     m_nBufSize(nBufSize),
  48.     m_nCurOffset(0),
  49.     m_bUndoValid(FALSE),
  50.     m_nUndo(-1)
  51. {
  52.     m_pBuffer = new char[m_nBufSize];
  53.     memcpy(m_pBuffer, pBuf, HX_SAFESIZE_T(m_nBufSize)); /* Flawfinder: ignore */
  54. }
  55. MIMEInputStream::MIMEInputStream(const CHXString& str)
  56. {
  57.     const char* pBuf = (const char*)str;
  58.     m_nCurOffset = 0;
  59.     m_nBufSize = str.GetLength();
  60.     m_pBuffer = new char[m_nBufSize];
  61.     memcpy(m_pBuffer, pBuf, HX_SAFESIZE_T(m_nBufSize)); /* Flawfinder: ignore */
  62.     m_bUndoValid = FALSE;
  63.     m_nUndo = -1;
  64. }
  65. MIMEInputStream::~MIMEInputStream()
  66. {
  67.     delete[] m_pBuffer;
  68. }
  69. int 
  70. MIMEInputStream::read()
  71. {
  72.     if(m_bUndoValid)
  73.     {
  74. int rc = m_nUndo;
  75. m_bUndoValid = FALSE;
  76. m_nUndo = -1;
  77. return rc;
  78.     }
  79.     if(m_nCurOffset < m_nBufSize)
  80.     {
  81. int chRet = m_pBuffer[m_nCurOffset];
  82. //XXXkshoop treat a EOF in the string as an end of file.
  83. // never read beyond it. don't inc the offset.
  84. if(chRet != -1)
  85. {
  86.     ++m_nCurOffset;
  87.     return chRet;
  88. }
  89.     }
  90.     return -1;
  91. }
  92. int
  93. MIMEInputStream::peek()
  94. {
  95.     if(m_bUndoValid)
  96.     {
  97. return m_nUndo;
  98.     }
  99.     //XXXkshoop ignore whether the location contains EOF 
  100.     // since we don't inc the offset.
  101.     if(m_nCurOffset < m_nBufSize)
  102.     {
  103. return m_pBuffer[m_nCurOffset];
  104.     }
  105.     return -1;
  106. }
  107. int 
  108. MIMEInputStream::read(char* pBuf, UINT32 nLen)
  109. {
  110.     UINT32 offset = 0;
  111.     int ch;
  112.     while((offset < nLen) && (ch = read()) >= 0)
  113. pBuf[offset++] = ch;
  114.     return HX_SAFEINT(offset);
  115. }
  116. UINT32 
  117. MIMEInputStream::available()
  118. {
  119.     return m_nBufSize - m_nCurOffset;
  120. }
  121. UINT32
  122. MIMEInputStream::max_distance_to(char* p)
  123. {
  124.     UINT32 ulDist = 0;
  125.     if (m_bUndoValid)
  126.     {
  127. if (strchr(p, m_nUndo) || m_nUndo == -1)
  128. {
  129.     return 0;
  130. }
  131. ulDist++;
  132.     }
  133.     UINT32 ulTempIndex = m_nCurOffset;
  134.     while (ulTempIndex < m_nBufSize &&
  135. !strchr(p, m_pBuffer[ulTempIndex]) &&
  136. m_pBuffer[ulTempIndex] != -1)
  137.     {
  138. ulDist++;
  139. ulTempIndex++;
  140.     }
  141.     return  ulDist;
  142. }
  143. MIMEScanner::MIMEScanner(MIMEInputStream& input): m_input(input)
  144. {
  145. }
  146. MIMEScanner::~MIMEScanner()
  147. {
  148. }
  149. static const char* const tspecials = " t=:;,-";
  150. MIMEToken 
  151. MIMEScanner::nextToken(char* upTo)
  152. {
  153.     int bInQuote = 0; // are we in a quoted string?
  154.     m_tokstr = "";
  155.     skipWS();
  156.     /*
  157.      * if a token end character is specified, ignore
  158.      * the tspecials, handle 'n' as a special case
  159.      * since lines can be continued by using leading
  160.      * white space on the next line.
  161.      */ 
  162.     if(upTo)
  163.     {
  164. m_tokstr.SetMinBufSize(m_input.max_distance_to(upTo));
  165. int ch = m_input.read();
  166. while(ch != -1)
  167. {
  168.     if(strchr(upTo, ch) && (ch != 'n'))
  169. break;
  170.     if(ch == 'r')
  171.     {
  172. ch = m_input.read();
  173. if(ch == 'n')
  174. {
  175.     ch = m_input.read();
  176.     if(ch == ' ' || ch == 't')
  177.     {
  178. if (m_tokstr == "")
  179. {
  180.     // If a line is blank, we will not allow it to be
  181.     // continued on the next line, since this is 
  182.     // probably the dividing line between headers and
  183.     // content. The content may have whitespace at
  184.     // the beginning (PR #23661) which we want to
  185.     // treat as content and not part of the headers.
  186.     m_input.putBack(ch);
  187.     return MIMEToken(m_tokstr, MIMEToken::T_EOL);
  188. }
  189. else
  190. {
  191.     skipWS();
  192. }
  193.     }
  194.     else
  195.     {
  196. m_input.putBack(ch);
  197. return MIMEToken(m_tokstr, MIMEToken::T_EOL);
  198.     }
  199. }
  200. else if(ch == ' ' || ch == 't')
  201. {
  202.     skipWS();
  203. }
  204. else
  205. {
  206.     m_input.putBack(ch);
  207.     return MIMEToken(m_tokstr, MIMEToken::T_EOL);
  208. }
  209.     }
  210.     else if(ch == 'n')
  211.     {
  212. ch = m_input.read();
  213. if(ch == 'r')
  214. {
  215.     ch = m_input.read();
  216.     if(ch == ' ' || ch == 't')
  217.     {
  218. if (m_tokstr == "")
  219. {
  220.     // If a line is blank, we will not allow it to be
  221.     // continued on the next line, since this is 
  222.     // probably the dividing line between headers and
  223.     // content. The content may have whitespace at
  224.     // the beginning (PR #23661) which we want to
  225.     // treat as content and not part of the headers.
  226.     m_input.putBack(ch);
  227.     return MIMEToken(m_tokstr, MIMEToken::T_EOL);
  228. }
  229. else
  230. {
  231.     skipWS();
  232. }
  233.     }
  234.     else
  235.     {
  236. m_input.putBack(ch);
  237. return MIMEToken(m_tokstr, MIMEToken::T_EOL);
  238.     }
  239. }
  240. else if(ch == ' ' || ch == 't')
  241. {
  242.     skipWS();
  243. }
  244. else
  245. {
  246.     m_input.putBack(ch);
  247.     return MIMEToken(m_tokstr, MIMEToken::T_EOL);
  248. }
  249.     }
  250.     else
  251.     {
  252. m_tokstr += ch;
  253.     }
  254.     ch = m_input.read();
  255. }
  256. return MIMEToken(m_tokstr, ch);
  257.     }
  258.     int ch = m_input.read();
  259.     switch(ch)
  260.     {
  261. case -1:
  262.     return MIMEToken(MIMEToken::T_EOF);
  263.     break;
  264. case 'r':
  265.     if((ch = m_input.read()) != 'n')
  266. m_input.putBack(ch);
  267.     return MIMEToken(MIMEToken::T_EOL);
  268.     break;
  269. case 'n':
  270.     if((ch = m_input.read()) != 'r')
  271. m_input.putBack(ch);
  272.     return MIMEToken(MIMEToken::T_EOL);
  273. case '"':
  274.     bInQuote = 1;
  275.     ch = m_input.read(); // get to next char
  276.     break;
  277. default:
  278.     break; // assume T_STRING - need more error processing here
  279.     }
  280.     // read string
  281.     while(ch != MIMEToken::T_EOF) 
  282.     {
  283. if(bInQuote)
  284. {
  285.     if(ch == '"')
  286.     {
  287. ch = m_input.read(); // next char to be put back
  288. bInQuote = 0;
  289. break;
  290.     }
  291. }
  292. else
  293. {
  294.     if(strchr(tspecials, ch) || iscntrl(ch))
  295. break;
  296. }
  297. /*
  298.  * Handle escaped double quotes
  299.  */
  300. if(ch == '\')
  301. {
  302.     ch = m_input.peek();
  303.     if(ch == '"')
  304.     {
  305. ch = m_input.read();
  306.     }
  307. }
  308.     
  309. m_tokstr += ch;
  310. ch = m_input.read();
  311.     }
  312.     m_input.putBack(ch);
  313.     return MIMEToken(m_tokstr, ch);
  314. }
  315. void 
  316. MIMEScanner::skipWS()
  317. {
  318.     int ch = m_input.read();
  319.     while(ch == ' ' || ch == 't')
  320. ch = m_input.read();
  321.     m_input.putBack(ch);
  322. }