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

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 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 RealNetworks Community Source License 
  8.  * Version 1.0 (the "License"). You may not use this file except in 
  9.  * compliance with the License executed by both you and RealNetworks.  You 
  10.  * may obtain a copy of the License at  
  11.  * http://www.helixcommunity.org/content/rcsl.  You may also obtain a 
  12.  * copy of the License by contacting RealNetworks directly.  Please see the 
  13.  * License for the rights, obligations and limitations governing use of the 
  14.  * contents of the file. 
  15.  *  
  16.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  17.  * developer of the Original Code and owns the copyrights in the portions 
  18.  * it created. 
  19.  *  
  20.  * This file, and the files included with this file, is distributed and made 
  21.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  22.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  23.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  24.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.  
  25.  * 
  26.  * Technology Compatibility Kit Test Suite(s) Location: 
  27.  *    http://www.helixcommunity.org/content/tck 
  28.  * 
  29.  * Contributor(s): 
  30.  *  
  31.  * ***** END LICENSE BLOCK ***** */ 
  32. //   $Id: xmlesc.cpp,v 1.8 2003/11/21 20:13:14 bobclark Exp $
  33. /*******************************************************************
  34.  *
  35.  *  NAME: xmlesc.cpp
  36.  *
  37.  *  CLASS
  38.  * CEscapeXMLtoHTML
  39.  *
  40.  *  DESCRIPTION:
  41.  * The implmentation for a class that escapes all the XML characters
  42.  * that are not printable in HTML.  A IHXBuffer is passed into the
  43.  * class on throgh the Convert Method. This is a pure virtual class.
  44.  * The CheckTag, and OnTag functions must be implemented in a child
  45.  * class.
  46.  *
  47.  *  NOTES:
  48.  * Started with Mozilla's ColorHTML function
  49.  *
  50.  *******************************************************************/
  51. #include "hxcom.h"     /* IUnknown */
  52. #include "hxtypes.h" 
  53. #include "hxbuffer.h"
  54. #include "hxiids.h"
  55. #include "hxstrutl.h"
  56. #include "hxstring.h"
  57. #include "perplex.h"
  58. #include "rtsputil.h"
  59. #include "growingq.h"
  60. #include "xmlesc.h"
  61. #include "vsrcinfo.h"
  62. #include "hlxclib/string.h"
  63. /*___________________________________________________________________________
  64.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  65.  * Static variable declarations
  66.  *___________________________________________________________________________
  67.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  68. const char* const
  69. CEscapeXMLtoHTML::m_pDefaultTags[20] = 
  70. {
  71.      tag_BEGIN_TAG
  72.     ,tag_END_TAG
  73.     ,tag_BEGIN_TAG_NAME
  74.     ,tag_END_TAG_NAME
  75.     ,tag_BEGIN_ATTRIBUTE
  76.     ,tag_END_ATTRIBUTE
  77.     ,tag_BEGIN_BROKEN_ATT
  78.     ,tag_END_BROKEN_ATT
  79.     ,tag_BEGIN_COMMENT
  80.     ,tag_END_COMMENT
  81.     ,tag_BEGIN_AMPERSAND
  82.     ,tag_END_AMPERSAND
  83.     ,tag_BEGIN_HREF
  84.     ,tag_END_HREF
  85.     ,tag_PROCESSING_INSTRUCTIONS
  86.     ,tag_END_PI
  87.     ,tag_BEGIN_CDATA
  88.     ,tag_END_CDATA
  89.     ,tag_BEGIN_DTD
  90.     ,tag_END_DTD
  91. };
  92. const char* const
  93. CEscapeXMLtoHTML::m_pStyleTags[20] =
  94. {
  95.      style_BEGIN_TAG
  96.     ,style_END_TAG
  97.     ,style_BEGIN_TAG_NAME
  98.     ,style_END_TAG_NAME
  99.     ,style_BEGIN_ATTRIBUTE
  100.     ,style_END_ATTRIBUTE
  101.     ,style_BEGIN_BROKEN_ATT
  102.     ,style_END_BROKEN_ATT
  103.     ,style_BEGIN_COMMENT
  104.     ,style_END_COMMENT
  105.     ,style_BEGIN_AMPERSAND
  106.     ,style_END_AMPERSAND
  107.     ,style_BEGIN_HREF
  108.     ,style_END_HREF
  109.     ,style_PROCESSING_INSTRUCTIONS
  110.     ,style_END_PI
  111.     ,style_BEGIN_CDATA
  112.     ,style_END_CDATA
  113.     ,style_BEGIN_DTD
  114.     ,style_END_DTD
  115. };
  116. /*___________________________________________________________________________
  117.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  118.  * Public Methods
  119.  *___________________________________________________________________________
  120.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  121. /*___________________________________________________________________________
  122.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  123.  *  CEscapeXMLtoHTML(pServerUrl, pOurPath)
  124.  *
  125.  *  PARAMETERS:
  126.  * pServerUrl  Full url to the server including the template file. 
  127.  * pOurPath    The Relative path of the file currently being parsed
  128.  *     no trailing "/"
  129.  * bMangleLinks    - to mangle or not
  130.  * bUseStyles - output in styles or regular HTML
  131.  * pHotTags - The tags that we will call OnTag For.
  132.  * pDefaultView    - The default viewsource to use for remote rstp
  133.  *   links ":port/viewmount/viewfile"
  134.  *  DESCRIPTION:
  135.  * Constructor.
  136.  * This is the primary means of creating an instance of CEscapeXMLtoHTML.
  137.  *___________________________________________________________________________
  138.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  139. CEscapeXMLtoHTML::CEscapeXMLtoHTML(IHXValues* pOptions, const char** pHotTags) 
  140. : m_pEscapeStrings(NULL)
  141. , m_pServerUrl(NULL)
  142. , m_pOurPath(NULL)
  143. , m_pHotTags(NULL)
  144. , m_pDefaultView(NULL)
  145. , m_pFileName(NULL)
  146. , m_pRamGen(NULL)
  147. , m_ulModDate(0)
  148. , m_ulFileSize(0)
  149. {
  150.     m_pHotTags = pHotTags;
  151.     IHXBuffer* pViewURL = NULL;
  152.     IHXBuffer* pCurrentPath = NULL;
  153.     IHXBuffer* pRemoteView = NULL;
  154.     IHXBuffer* pFileName = NULL;
  155.     UINT32 ulMangle = 0;
  156.     UINT32 ulStyles = 0;
  157.     if ( FAILED(pOptions->GetPropertyCString("ViewSourceURL", pViewURL)) ||
  158.  FAILED(pOptions->GetPropertyCString("CurrentPath", pCurrentPath)) ||
  159.  FAILED(pOptions->GetPropertyULONG32("HidePaths", ulMangle)) ||
  160.  FAILED(pOptions->GetPropertyULONG32("UseStyles", ulStyles)) ||
  161.  FAILED(pOptions->GetPropertyCString("RemoteViewSourceURL", pRemoteView)) ||
  162.  FAILED(pOptions->GetPropertyCString("FileName", pFileName)) ||
  163.  FAILED(pOptions->GetPropertyULONG32("ModificationTime", m_ulModDate)) ||
  164.  FAILED(pOptions->GetPropertyULONG32("FileSize", m_ulFileSize)) )
  165.     {
  166. HX_ASSERT(FALSE);
  167. // return HXR_INVALID_PARAMETER;
  168.     }
  169.     m_bMangleLinks = ulMangle ? TRUE : FALSE;
  170.     BOOL bUseStyles = ulStyles ? TRUE : FALSE;
  171.     m_pServerUrl = new char[pViewURL->GetSize()+1];
  172.     strcpy(m_pServerUrl, (char*)pViewURL->GetBuffer()); /* Flawfinder: ignore */
  173.     m_pOurPath = new char[pCurrentPath->GetSize()+1];
  174.     strcpy(m_pOurPath, (char*)pCurrentPath->GetBuffer()); /* Flawfinder: ignore */
  175.     m_pDefaultView = new char[pRemoteView->GetSize()+1];
  176.     strcpy(m_pDefaultView, (char*)pRemoteView->GetBuffer()); /* Flawfinder: ignore */
  177.     m_pFileName = new char[pFileName->GetSize()+1];
  178.     strcpy(m_pFileName, (char*)pFileName->GetBuffer()); /* Flawfinder: ignore */
  179.     IHXBuffer* pRamGen = NULL;
  180.     if ( SUCCEEDED(pOptions->GetPropertyCString("RamGenURL", pRamGen)) )
  181.     {
  182. m_pRamGen = new char[pRamGen->GetSize()+1];
  183. strcpy(m_pRamGen, (char*)pRamGen->GetBuffer()); /* Flawfinder: ignore */
  184.     }
  185.     HX_RELEASE(pRamGen);
  186.     HX_RELEASE(pRemoteView);
  187.     HX_RELEASE(pViewURL);
  188.     HX_RELEASE(pCurrentPath);
  189.     HX_RELEASE(pFileName);
  190.     if ( bUseStyles )
  191.     {
  192. m_pEscapeStrings = (const char**) m_pStyleTags;
  193.     }
  194.     else
  195.     {
  196. m_pEscapeStrings = (const char**) m_pDefaultTags;
  197.     }
  198. }
  199. /*___________________________________________________________________________
  200.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  201.  *  ~CEscapeXMLtoHTML()
  202.  *
  203.  *  PARAMETERS:
  204.  * none
  205.  *
  206.  *  DESCRIPTION:
  207.  * Destructor.
  208.  *
  209.  *___________________________________________________________________________
  210.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  211. CEscapeXMLtoHTML::~CEscapeXMLtoHTML()
  212. {
  213.     HX_VECTOR_DELETE(m_pRamGen);
  214.     HX_VECTOR_DELETE(m_pServerUrl);
  215.     HX_VECTOR_DELETE(m_pOurPath);
  216.     HX_VECTOR_DELETE(m_pDefaultView);
  217.     HX_VECTOR_DELETE(m_pFileName);
  218. }
  219. /*___________________________________________________________________________
  220.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  221.  *  Convert(pXMLsrc, pOutBuffer)
  222.  *
  223.  *  PARAMETERS:
  224.  * pXMLsrc Pointer to a IHXBuffer containing the src of xml to 
  225.  * be converted
  226.  * pOutBuffer A new IHXBuffer containing the parsed XML data ready
  227.  * to be displayed in an HTML browser.
  228.  *
  229.  *  DESCRIPTION:
  230.  * Creates a growing queue, copies the buffers to a cstring, then calls 
  231.  * the Parse(...) function to parse the string.  Next the outputed is 
  232.  * dequeued Off the growing queue and put in a new IHXBuffer and 
  233.  * returned
  234.  *
  235.  *  RETURNS
  236.  *
  237.  *___________________________________________________________________________
  238.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  239. STDMETHODIMP CEscapeXMLtoHTML::Convert(IHXBuffer* pXMLsrc,
  240.        REF(IHXBuffer*) pOutBuffer)
  241. {
  242.     // TODO: UTF-16
  243.     UCHAR* pIn = NULL;
  244.     UINT32 ulLen;
  245.     
  246.     HX_ASSERT(pXMLsrc != NULL);
  247.     pXMLsrc->Get(pIn, ulLen);
  248.     
  249.     CBigByteGrowingQueue* pQueue = NULL;
  250.     
  251.     if ( ulLen )
  252.     {
  253. pQueue = new CBigByteGrowingQueue(ulLen*4);
  254. if ( !pQueue )
  255. {
  256.     // panic
  257.     HX_RELEASE(pXMLsrc);
  258.     return HXR_OUTOFMEMORY;
  259. }
  260. DataObject StateObj;
  261. StateObj.state = IN_CONTENT;
  262. StateObj.bPushChar = TRUE;
  263.     
  264. PushHeader(pQueue);
  265. pQueue->EnQueue("<pre><!--  Begin Source  -->n");
  266. Parse(pIn, ulLen, pQueue, &StateObj);
  267. pQueue->EnQueue("n<!--  End Source  --></pre>n");
  268. UINT32 ulOutLen;
  269. ulOutLen =  pQueue->GetQueuedItemCount();
  270. HX_RELEASE(pOutBuffer);
  271. pOutBuffer = new CHXBuffer();
  272. pOutBuffer->AddRef();
  273. if ( pOutBuffer->SetSize(ulOutLen) != HXR_OK )
  274. {
  275.     HX_RELEASE(pXMLsrc);
  276.     return HXR_OUTOFMEMORY;
  277. }
  278. UCHAR* pOut = pOutBuffer->GetBuffer();
  279. pQueue->DeQueue(pOut, ulOutLen);
  280.     }
  281.     else
  282.     { // just return an empty buffer.
  283. HX_RELEASE(pOutBuffer);
  284. pOutBuffer = new CHXBuffer();
  285. pOutBuffer->AddRef();
  286.     }
  287.     HX_DELETE(pQueue);
  288.     return HXR_OK;
  289. }
  290. /*___________________________________________________________________________
  291.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  292.  *  PushCommonHeader(queue)
  293.  *
  294.  *  PARAMETERS:
  295.  *
  296.  *  queue The queue to push the output to.
  297.  *
  298.  *  DESCRIPTION:
  299.  *
  300.  * Pushes the common information onto the queue.
  301.  *
  302.  *  RETURNS
  303.  *
  304.  *___________________________________________________________________________
  305.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  306. void CEscapeXMLtoHTML::PushCommonHeader(CBigByteGrowingQueue* queue)
  307. {
  308.     queue->EnQueue(z_pFileName);
  309.     queue->EnQueue(m_pFileName);
  310.     queue->EnQueue(z_pEndLine);
  311.     
  312.     QueueModificationTime(queue, m_ulModDate);
  313.     QueueFileSize(queue, m_ulFileSize);
  314.     if ( m_pRamGen )
  315.     {
  316. queue->EnQueue(z_pRamLink);
  317. queue->EnQueue("<a href="");
  318. queue->EnQueue(m_pRamGen);
  319. const char* p = m_pOurPath;
  320. if ( *p == '/' )
  321. {
  322.     p++;
  323. }
  324. queue->EnQueue(p);
  325. queue->EnQueue("/");
  326. queue->EnQueue(m_pFileName);
  327. queue->EnQueue("">");
  328. queue->EnQueue(m_pRamGen);
  329. queue->EnQueue(p);
  330. queue->EnQueue("/");
  331. queue->EnQueue(m_pFileName);
  332. queue->EnQueue("</a>");
  333. queue->EnQueue(z_pEndLine);
  334.     }
  335. }
  336. /*___________________________________________________________________________
  337.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  338.  * Protected Methods
  339.  *___________________________________________________________________________
  340.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  341. /*___________________________________________________________________________
  342.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  343.  *  WrapAttributeWithHREF (pPositionPointer, ulLen, pObj, pQueue, pAttribute)
  344.  *
  345.  *  PARAMETERS:
  346.  *
  347.  *  pPositionPointer Pointer to a character string.  It points to the first
  348.  * whitespace after the tagname
  349.  *  ulLen Length to end of pPositionPointer so we don't overrun the buffer
  350.  *  pObj The current state of the Parse Function, this can be used
  351.  * to continue parsing.
  352.  *  queue The queue to push the output to.
  353.  *  pAttribute The attribute we want to wrap.
  354.  *
  355.  *  DESCRIPTION:
  356.  * This method will take the given pPositionPointer and wrap the given attribute
  357.  * with an HREF
  358.  *
  359.  *  RETURNS
  360.  * UINT32
  361.  *     number of characters used off pPositionPointer, thus the position can be
  362.  *     adjusted after the function returns
  363.  *___________________________________________________________________________
  364.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  365. UINT32 CEscapeXMLtoHTML::WrapAttributeWithHREF(const UCHAR* pPositionPointer, 
  366. UINT32 ulLen,
  367. DataObject* pObj,
  368. CBigByteGrowingQueue* pQueue, 
  369. const char* pAttribute)
  370. {
  371.     // we need to find two things
  372.     // 1 - the end of the tag
  373.     // 2 - the beggining of the attribute
  374.     const UCHAR* pBeginAttribute = NULL;
  375.     const UCHAR* pEndTag = NULL;
  376.     const char* walker = (const char*)pPositionPointer;
  377.     BOOL bInComment = FALSE;
  378.     UINT32 ulEscLen = 0;
  379.     UINT16 uAttribLen = strlen(pAttribute);
  380.     while ( (!pEndTag || bInComment) && ulEscLen < ulLen)
  381.     {
  382. if ( !bInComment )
  383. {
  384.     if ( *walker == '>')
  385.     {
  386. pEndTag = (const UCHAR*)walker;
  387. ++pEndTag;
  388.     }
  389.     else if ( ulEscLen + uAttribLen < ulLen &&
  390. isspace(*(walker-1)) &&
  391. !strncmp(walker, pAttribute, uAttribLen) )
  392.     {
  393. walker += uAttribLen;
  394. ulEscLen += uAttribLen;
  395. // eat ws.
  396. while ( isspace(*walker) && ulEscLen < ulLen )
  397. {
  398.     ++walker;
  399.     ++ulEscLen;
  400. }
  401. // assert for =
  402. HX_ASSERT(*walker == '=');
  403. if ( *walker == '=' )
  404. {
  405.     ++walker;
  406.     ++ulEscLen;
  407.     while ( isspace(*walker) && ulEscLen < ulLen )
  408.     {
  409. ++walker;
  410. ++ulEscLen;
  411.     }
  412.     // eat ws assert for " '
  413.     HX_ASSERT(*walker == '"' || *walker == ''');
  414.     if ( *walker == '"' || *walker == ''' )
  415.     {
  416. ++walker;
  417. ++ulEscLen;
  418. pBeginAttribute = (const UCHAR*)walker;
  419.     }
  420. }
  421.     }
  422.     else if ( ulEscLen + 4 < ulLen && !strncmp(walker, "<!--", 4) )
  423.     {
  424. bInComment = TRUE;
  425. walker += 3;
  426. ulEscLen += 3;
  427.     }
  428. }
  429. else
  430. {
  431.     if ( ulEscLen + 3 < ulLen && !strncmp(walker, "-->", 3) )
  432.     {
  433. bInComment = FALSE;
  434. walker += 2;
  435. ulEscLen += 2;
  436.     }
  437. }
  438. ++walker;
  439. ++ulEscLen;
  440.     }
  441.     UINT32 pos = 0;
  442.     if ( pBeginAttribute ) {
  443. // parse until the end of the attribute tag.
  444. pos = pBeginAttribute - pPositionPointer;
  445. Parse(pPositionPointer, pos, pQueue, pObj);
  446. // advance the character pointer by how much we parsed.
  447. pPositionPointer += pos;
  448. // push our wrapper on
  449. BOOL bPushed = PushOpenningHREF(pPositionPointer, pQueue, pObj->cQuote);
  450. // push mangled filename on
  451. UINT32 ulPathLen = PushMangledDisplayedPath(pPositionPointer, pQueue, pObj->cQuote);
  452. // advancd pPositionPointer by path length
  453. pPositionPointer += ulPathLen;
  454. pos += ulPathLen;
  455. // push ending HREF
  456. if ( bPushed )
  457. {
  458.     PushEndingHREF(pQueue);
  459. }
  460. // parse to end of tag
  461. Parse(pPositionPointer, ulEscLen - pos, pQueue, pObj);
  462. pObj->bPushChar = FALSE;
  463. // We want to return pointing to the last '>', therefore we can
  464. // catch anything that is imediatly following our tag.
  465. return ulEscLen - 1;
  466.     }
  467.     pObj->bPushChar = TRUE;
  468.     return 0;
  469. }
  470. /*___________________________________________________________________________
  471.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  472.  *  WrapHREF (pPositionPointer, ulLen, pObj, pQueue)
  473.  *
  474.  *  PARAMETERS:
  475.  *
  476.  *  pPositionPointer Pointer to a character string.  It points to the first
  477.  * whitespace after the tagname
  478.  *  ulLen Length to end of pPositionPointer so we don't overrun the buffer
  479.  *  pObj The current state of the Parse Function, this can be used
  480.  * to continue parsing.
  481.  *  queue The queue to push the output to.
  482.  *  pAttribute The attribute we want to wrap.
  483.  *
  484.  *  DESCRIPTION:
  485.  * This method will take the given pPositionPointer and wrap an HREF=
  486.  *  With a link to itself.
  487.  *
  488.  *  RETURNS
  489.  * UINT32
  490.  *     number of characters used off pPositionPointer, thus the position can be
  491.  *     adjusted after the function returns
  492.  *___________________________________________________________________________
  493.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  494. #ifdef HYPER_LINKING_HREFS_XML
  495. UINT32 CEscapeXMLtoHTML::LinkHREF(const UCHAR* pPositionPointer, 
  496. UINT32 ulLen,
  497. DataObject* pObj,
  498. CBigByteGrowingQueue* pQueue)
  499. {
  500.     const UCHAR* pBeginHREF = NULL;
  501.     const UCHAR* pEndHREF = NULL;
  502.     const UCHAR* pEndTag = NULL;
  503.     const char* walker = (const char*)pPositionPointer;
  504.     BOOL bInComment = FALSE;
  505.     BOOL bInString = FALSE;
  506.     UINT32 ulEscLen = 0;
  507.     while ( (!pEndTag) && ulEscLen < ulLen)
  508.     {
  509. if ( bInString )
  510. {
  511.     if ( *walker == '"' || *walker == ''')
  512.     {
  513. bInString = FALSE;
  514. pEndHREF = (const UCHAR*)walker;
  515.     }
  516. }
  517. else if ( !bInComment )
  518. {
  519.     if ( *walker == '>')
  520.     {
  521. pEndTag = (const UCHAR*)walker;
  522. ++pEndTag;
  523.     }
  524.     else if ( ulEscLen + 6 < ulLen && 
  525. isspace(*(walker-1)) && 
  526. !strncmp(walker, "href", 4) &&
  527. (*(walker+4) == '=' || isspace(*(walker+4))) )
  528.     {
  529. walker += 4;
  530. ulEscLen += 4;
  531. while ( *walker != '"' && *walker != ''' && ulEscLen < ulLen &&
  532. (isspace(*walker) || *walker == '='))
  533. {
  534.     ++walker;
  535.     ++ulEscLen;
  536. }
  537. HX_ASSERT(*walker == '"' || *walker == ''');
  538. if ( *walker == '"' || *walker == ''')
  539. {
  540.     pBeginHREF = (const UCHAR*)walker + 1;
  541.     bInString = TRUE;
  542. }
  543.     }
  544.     else if ( ulEscLen + 4 < ulLen && 
  545. !strncmp(walker, "<!--", 4) )
  546.     {
  547. bInComment = TRUE;
  548. walker += 3;
  549. ulEscLen += 3;
  550.     }
  551. }
  552. else
  553. {
  554.     if ( ulEscLen + 3 < ulLen && !strncmp(walker, "-->", 3) )
  555.     {
  556. bInComment = FALSE;
  557. walker += 2;
  558. ulEscLen += 2;
  559.     }
  560. }
  561. ++walker;
  562. ++ulEscLen;
  563.     }
  564.     if ( pEndTag == NULL || pBeginHREF == NULL || pEndHREF == NULL )
  565.     {
  566. return 0;
  567.     }
  568.     else
  569.     {
  570. const UCHAR* cp = pPositionPointer;
  571. Parse(pPositionPointer, pBeginHREF - cp, pQueue, pObj);
  572. cp += pBeginHREF - cp;
  573. pQueue->EnQueue(m_pEscapeStrings[BeginHREF]);
  574. pQueue->EnQueue((void*)pBeginHREF, pEndHREF - pBeginHREF);
  575. pQueue->EnQueue("">");
  576. Parse(cp, pEndHREF - pBeginHREF, pQueue, pObj);
  577. cp += pEndHREF - pBeginHREF;
  578. pQueue->EnQueue(m_pEscapeStrings[EndHREF]);
  579. // parse to end of tag
  580. Parse(cp, pEndTag - cp, pQueue, pObj);
  581. pObj->bPushChar = FALSE;
  582. // We want to return pointing to the last '>', therefore we can
  583. // catch anything that is imediatly following our tag.
  584. return pEndTag - pPositionPointer - 1;
  585.     }
  586. }
  587. #endif //HYPER_LINKING_HREFS_XML
  588. /*___________________________________________________________________________
  589.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  590.  *  Parse(pIn, ulLen, pQueue, pObj)
  591.  *
  592.  *  PARAMETERS:
  593.  * pIn The string to be parsed.
  594.  * ulLen How far to parse through pIn
  595.  * pQueue The output Queue to push onto
  596.  * pObj The state object.  This is used to start the queue from a
  597.  * given state.
  598.  *
  599.  *  DESCRIPTION:
  600.  * This function walks through the string one character at a time.  
  601.  * Every tag is checked with the CheckTag(...) function to see if it 
  602.  * needs special attention.  If so the OnTag(...) function is called.  
  603.  * This function will be implemented in a child class that will replace 
  604.  * the tag with parsed imput returning how far along pIn it made it.
  605.  * This function is designed such that Inherited classes can recusivly 
  606.  * call it to parse thier stream from the given state.
  607.  *
  608.  *  RETURNS
  609.  * void
  610.  *___________________________________________________________________________
  611.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  612. void
  613. CEscapeXMLtoHTML::Parse(const UCHAR* pIn, UINT32 ulLen, 
  614. CBigByteGrowingQueue* pQueue,
  615. DataObject* pObj)
  616. {
  617.     HX_ASSERT(pIn);
  618.     
  619.     const UCHAR* pPositionPointer;
  620.     UINT32 uPositionOffset;
  621.     for ( uPositionOffset = 0, pPositionPointer = pIn;
  622. uPositionOffset < ulLen; uPositionOffset++, pPositionPointer++ )
  623.     {
  624.         switch(pObj->state)
  625.         {
  626.             case IN_CONTENT:
  627.     {
  628.                 /* do nothing until you find a '<' "<!--" or '&' */
  629.                 if ( *pPositionPointer == '<' )
  630.                 {
  631.                     /* XXX we can miss a comment spanning a block boundary */
  632.     pObj->bPushChar = FALSE;
  633.                     if ( uPositionOffset + 4 <= ulLen && 
  634. !strncmp((char*)pPositionPointer, "<!--", 4) )
  635.                     {
  636.                         pQueue->EnQueue(m_pEscapeStrings[BeginCommentMarkup]);
  637.                         pQueue->EnQueue("&lt;");
  638.                         pObj->state = IN_COMMENT;
  639.                     }
  640.                    else if ( uPositionOffset + 2 <= ulLen && 
  641.        !strncmp((char*)pPositionPointer, "<?", 2) )
  642.                    {
  643.                        pQueue->EnQueue(m_pEscapeStrings[BeginTagMarkup]);
  644.        pQueue->EnQueue("&lt;");
  645.        pQueue->EnQueue(m_pEscapeStrings[EndTagMarkup]);
  646.                        pQueue->EnQueue(m_pEscapeStrings[BeginProcessingInstructions]);
  647.                        pQueue->EnQueue("?");
  648.                        pQueue->EnQueue(m_pEscapeStrings[BeginTagNameMarkup]);
  649.                        // increment pPositionPointer & uPositionOffset one because of ?
  650.                        ++pPositionPointer;
  651.                        ++uPositionOffset;
  652.                        pObj->bInProcessingInstructions = TRUE;
  653.                        pObj->bPushChar = FALSE;
  654.                        pObj->state = ABOUT_TO_BEGIN_TAG;
  655.                    }
  656.                    else if ( uPositionOffset + 9 <= ulLen && 
  657.        !strncmp((char*)pPositionPointer, "<![CDATA[", 9) )
  658.                    {
  659.        pQueue->EnQueue(m_pEscapeStrings[BeginTagMarkup]);
  660.                        pQueue->EnQueue("&lt;");
  661.                        pQueue->EnQueue(m_pEscapeStrings[BeginTagNameMarkup]);
  662.                        pQueue->EnQueue("![CDATA[");
  663.                        pQueue->EnQueue(m_pEscapeStrings[EndTagNameMarkup]);
  664.        pQueue->EnQueue(m_pEscapeStrings[EndTagMarkup]);
  665.                        pQueue->EnQueue(m_pEscapeStrings[BeginCDATA]);
  666.                        pObj->bPushChar = FALSE;
  667.                        pPositionPointer += 8;
  668.                        uPositionOffset += 8;
  669.                        pObj->state = IN_CDATA;
  670.                    }
  671.                    else if ( uPositionOffset + 2 <= ulLen && 
  672.        !strncmp((char*)pPositionPointer, "<!", 2) )
  673.                    {
  674.        pQueue->EnQueue(m_pEscapeStrings[BeginTagMarkup]);
  675.                        pQueue->EnQueue("&lt;");
  676.                        pQueue->EnQueue(m_pEscapeStrings[BeginTagNameMarkup]);
  677.                        pObj->state = IN_DOC_TYPE_DEC_TAG;
  678.                    }
  679.                     else
  680.                     {
  681.                         BeginColorTag(pQueue, pObj);
  682.                     }
  683.                 }
  684.                 else if ( *pPositionPointer == '&' )
  685.                 {
  686.                     pObj->bPushChar = FALSE;
  687.     pQueue->EnQueue(m_pEscapeStrings[BeginAmpersandThingyMarkup]);
  688.                     pQueue->EnQueue("&amp;");
  689.                     pObj->state = IN_AMPERSAND_THINGY;
  690.                 }
  691.     }
  692.             break;
  693.            case IN_DOC_TYPE_DEC_TAG:
  694.            {
  695.                 if ( IS_SPACE(*pPositionPointer) )
  696.                 {
  697.                     pQueue->EnQueue(m_pEscapeStrings[EndTagNameMarkup]);
  698.     pQueue->EnQueue(m_pEscapeStrings[EndTagMarkup]);
  699.     pQueue->EnQueue(m_pEscapeStrings[BeginDTD]);
  700.     pObj->bPushChar = TRUE; // we want to still push it
  701.                     pObj->state = IN_DOC_TYPE_DEC;
  702.                 }
  703.                 else if ( *pPositionPointer == '>' )
  704.                 {
  705.                     pQueue->EnQueue(m_pEscapeStrings[EndTagNameMarkup]);
  706.                     pQueue->EnQueue(m_pEscapeStrings[EndDTD]);
  707.                     pQueue->EnQueue("&gt;");
  708.                     pObj->bPushChar = FALSE;
  709.     pObj->state = IN_CONTENT;
  710.                 }
  711.            }
  712.            break;
  713.            case IN_DOC_TYPE_DEC:
  714.            {
  715.                if ( pObj->bInDataSection )
  716.                {
  717.                    if ( pObj->bInInternalComment )
  718.                    {
  719.                        /* do nothing until you find a closing '-->' */
  720.                        if ( !strncmp((char*)pPositionPointer, "-->", 3) )
  721.                        {
  722.                            pObj->bPushChar = FALSE;
  723.                            pObj->bInInternalComment = FALSE;
  724.                            pQueue->EnQueue("--&gt;");
  725.                            pPositionPointer += 2;
  726.                            uPositionOffset += 2;
  727.                            pQueue->EnQueue(m_pEscapeStrings[EndCommentMarkup]);
  728.                        }
  729.                    }
  730.                    else if ( !strncmp((char*)pPositionPointer, "<!--", 4) )
  731.                    {
  732.                         pQueue->EnQueue(m_pEscapeStrings[BeginCommentMarkup]);
  733.                         pQueue->EnQueue("&lt;");
  734.                         pObj->bPushChar = FALSE;
  735.                         pObj->bInInternalComment = TRUE;
  736.                    }
  737.                    else if ( *pPositionPointer == ']' )
  738.                    {
  739.                        pObj->bInDataSection = FALSE;
  740.                    }
  741.                }
  742.                else if ( *pPositionPointer == '[' )
  743.                {
  744.                    pObj->bInDataSection = TRUE;
  745.                }
  746.                else if ( *pPositionPointer == '>' )
  747.                {
  748.                    pObj->bPushChar = FALSE;
  749.                    pQueue->EnQueue(m_pEscapeStrings[EndDTD]);
  750.    pQueue->EnQueue(m_pEscapeStrings[BeginTagMarkup]);
  751.                    pQueue->EnQueue("&gt;");
  752.    pQueue->EnQueue(m_pEscapeStrings[EndTagMarkup]);
  753.                    pObj->state = IN_CONTENT;
  754.                }
  755.                if ( pObj->bPushChar )
  756.                {
  757.                    if ( *pPositionPointer == '<' )
  758.                    {
  759.                        pObj->bPushChar = FALSE;
  760.                        /* protect ourselves from markup */
  761.                        pQueue->EnQueue("&lt;");
  762.                    }
  763.                    else if ( *pPositionPointer == '&' )
  764.                    {
  765.                        /* protect ourselves from markup */
  766.                        pQueue->EnQueue("&amp;");
  767.                        pObj->bPushChar = FALSE;
  768.                    }
  769.                }
  770.            }
  771.            break;
  772.            case IN_CDATA:
  773.            {
  774.                if ( !strncmp((char*)pPositionPointer, "]]>", 3) )
  775.                {
  776.                    pQueue->EnQueue(m_pEscapeStrings[EndCDATA]);
  777.    pQueue->EnQueue(m_pEscapeStrings[BeginTagMarkup]);
  778.                    pQueue->EnQueue(m_pEscapeStrings[BeginTagNameMarkup]);
  779.                    pQueue->EnQueue("]]");
  780.                    pQueue->EnQueue(m_pEscapeStrings[EndTagNameMarkup]);
  781.                    pQueue->EnQueue("&gt;");
  782.    pQueue->EnQueue(m_pEscapeStrings[EndTagMarkup]);
  783.                    pPositionPointer += 2;
  784.                    uPositionOffset += 2;
  785.                    pObj->bPushChar = FALSE;
  786.                    pObj->state = IN_CONTENT;
  787.                }
  788.                if ( *pPositionPointer == '<' )
  789.                 {
  790.                    pObj->bPushChar = FALSE;
  791.                     /* protect ourselves from markup */
  792.                     pQueue->EnQueue("&lt;");
  793.                 }
  794.                else if ( *pPositionPointer == '&' )
  795.                {
  796.                     /* protect ourselves from markup */
  797.                    pQueue->EnQueue("&amp;");
  798.                    pObj->bPushChar = FALSE;
  799.                }
  800.            }
  801.            break;
  802.             case ABOUT_TO_BEGIN_TAG:
  803.     {
  804.                 /* we have seen the first '<'
  805.                  * once we see a non-whitespace character
  806.                  * we will be in the tag identifier
  807.                  */
  808.                 if ( *pPositionPointer == '>' )
  809.                 {
  810.     pQueue->EnQueue(m_pEscapeStrings[EndTagNameMarkup]);
  811.                     EndColorTag(pQueue, pObj);
  812.                 }
  813.                 else if ( !IS_SPACE(*pPositionPointer) )
  814.                 {
  815.                     pObj->state = IN_BEGIN_TAG;
  816.                     pObj->tag_index = 0;
  817.                     pObj->tag[pObj->tag_index++] = *pPositionPointer;
  818.                     
  819.          if ( *pPositionPointer == '<' )
  820.     {
  821.                         pObj->bPushChar = FALSE;
  822. pQueue->EnQueue("&lt;");
  823.     }
  824.                 }
  825.     }
  826.             break;
  827.             case IN_BEGIN_TAG:
  828.     {
  829.                 /* go to the IN_TAG state when we see
  830.                  * the first whitespace
  831.                  */
  832.                 if ( IS_SPACE(*pPositionPointer) )
  833.                 {
  834.                     pQueue->EnQueue(m_pEscapeStrings[EndTagNameMarkup]);
  835.     pObj->bPushChar = TRUE; // we want to still push it
  836.                     pObj->state = IN_TAG;
  837.                     if (pObj->tag_index < MAXTAGLEN) pObj->tag[pObj->tag_index] = '';
  838.     if ( CheckTag(pObj) )
  839.     {
  840. UINT32 pos = OnTag(pPositionPointer, ulLen - uPositionOffset, pObj, pQueue);
  841. pPositionPointer += pos;
  842. uPositionOffset += pos;
  843.     }
  844.                 }
  845.                 else if ( *pPositionPointer == '>' )
  846.                 {
  847.                     pQueue->EnQueue(m_pEscapeStrings[EndTagNameMarkup]);
  848.                     EndColorTag(pQueue, pObj);
  849.                 }
  850.                 else if ( *pPositionPointer == '<' )
  851.                 {
  852.     pObj->bPushChar = FALSE;
  853.                     /* protect ourselves from markup */
  854.                     if ( !pObj->bInBrokenXML )
  855.                     {
  856.                         pObj->bInBrokenXML = TRUE;
  857.                         pQueue->EnQueue(m_pEscapeStrings[BeginBrokenAttributeMarkup]);
  858.                         pQueue->EnQueue("&lt;");
  859.                     }
  860.                     else
  861.                     {
  862.                         pQueue->EnQueue("&lt;");
  863.                     }
  864.                 }
  865.                 else
  866.                 {
  867.                     if (pObj->tag_index < MAXTAGLEN)
  868.     {
  869.                         pObj->tag[pObj->tag_index++] = *pPositionPointer;
  870.     }
  871.                 }
  872.     }
  873.             break;
  874.             case IN_TAG:
  875.     {
  876.                 /* do nothing until you find a opening '=' or end '>' */
  877. if ( *pPositionPointer == '=' )
  878.                 {
  879.     pObj->bPushChar = FALSE;
  880.                     pQueue->EnQueue("=");
  881.                     pQueue->EnQueue(m_pEscapeStrings[BeginAttributeValueMarkup]);
  882.                     pObj->state = BEGIN_ATTRIBUTE_VALUE;
  883.                 }
  884.                 else if ( *pPositionPointer == '>' )
  885.                 {
  886.                     EndColorTag(pQueue, pObj);
  887.                 }
  888.                 else if ( *pPositionPointer == '<' )
  889.                 {
  890.     pObj->bPushChar = FALSE;
  891.                     /* protect ourselves from markup */
  892.                     pQueue->EnQueue("&lt;");
  893.                 }
  894.     }
  895.             break;
  896.             case BEGIN_ATTRIBUTE_VALUE:
  897.     {
  898.                 /* when we reach the first non-whitespace
  899.                  * we will enter the UNQUOTED or the QUOTED
  900.                  * ATTRIBUTE state
  901.                  */
  902.                 if ( !IS_SPACE(*pPositionPointer) )
  903.                 {
  904.                     if ( *pPositionPointer == '"' || *pPositionPointer == ''')
  905.                     {
  906. pObj->cQuote = *pPositionPointer;
  907.                         pObj->state = IN_QUOTED_ATTRIBUTE_VALUE;
  908.                         /* no need to jump to the quoted attr handler
  909.                          * since this char can't be a dangerous char
  910.                          */
  911.                     }
  912.                     else
  913.                     {
  914.                         pObj->state = IN_UNQUOTED_ATTRIBUTE_VALUE;
  915.                         /* need to jump to the unquoted attr handler
  916.                          * since this char can be a dangerous character
  917.                          */
  918.                         goto unquoted_attribute_jump_point;
  919.                     }
  920.                 }
  921.                 else if ( *pPositionPointer == '>' )
  922.                 {
  923.     pQueue->EnQueue(m_pEscapeStrings[EndAttributeValueMarkup]);
  924.                     EndColorTag(pQueue, pObj);
  925.                 }
  926.                 else if ( *pPositionPointer == '<' )
  927.                 {
  928.                     /* protect ourselves from markup */
  929.                     pObj->bPushChar = FALSE;
  930.     pQueue->EnQueue("&lt;");
  931.                 }
  932.     }
  933.             break;
  934.             case IN_UNQUOTED_ATTRIBUTE_VALUE:
  935.     {
  936. unquoted_attribute_jump_point:
  937.                 /* do nothing until you find a whitespace */
  938.                 if ( IS_SPACE(*pPositionPointer) )
  939.                 {
  940.                     pQueue->EnQueue(m_pEscapeStrings[EndAttributeValueMarkup]);
  941.                     pObj->state = IN_TAG;
  942.                 }
  943.                 else if ( *pPositionPointer == '>' )
  944.                 {
  945.     pQueue->EnQueue(m_pEscapeStrings[EndAttributeValueMarkup]);
  946.     EndColorTag(pQueue, pObj);
  947.                 }
  948.                 else if ( *pPositionPointer == '<' )
  949.                 {
  950.     pObj->bPushChar = FALSE;
  951.                     /* protect ourselves from markup */
  952.                     pQueue->EnQueue("&lt;");
  953.                 }
  954.                 else if ( *pPositionPointer == '&' )
  955.                 {
  956.     pObj->bPushChar = FALSE;
  957.                     /* protect ourselves from markup */
  958.                     pQueue->EnQueue("&amp;");
  959.                 }
  960.                 break;
  961.     }
  962.             case IN_QUOTED_ATTRIBUTE_VALUE:
  963.     {
  964.                 /* do nothing until you find a closing '"' */
  965. if ( *pPositionPointer == pObj->cQuote )
  966.                 {
  967.     pObj->bPushChar = FALSE;
  968.                     if ( pObj->bInBrokenXML )
  969.                     {
  970.                         pQueue->EnQueue(m_pEscapeStrings[EndBrokenAttributeMarkup]);
  971.                         pObj->bInBrokenXML = FALSE;
  972.                     }
  973.                     pQueue->EnQueue((void*)&pObj->cQuote, 1);
  974.                     pQueue->EnQueue(m_pEscapeStrings[EndAttributeValueMarkup]);
  975.                     pObj->state = IN_TAG;
  976.                 }
  977.                 else if ( *pPositionPointer == '<' )
  978.                 {
  979.     pObj->bPushChar = FALSE;
  980.                     /* protect ourselves from markup */
  981.                     pQueue->EnQueue("&lt;");
  982.                 }
  983.                 else if ( *pPositionPointer == '&' )
  984.                 {
  985.     pObj->bPushChar = FALSE;
  986.                     /* protect ourselves from markup */
  987.                     pQueue->EnQueue("&amp;");
  988.                 }
  989.                 else if ( *pPositionPointer == '>' )
  990.                 {
  991.     pObj->bPushChar = FALSE;
  992.                     /* probably a broken attribute value */
  993.                     if ( !pObj->bInBrokenXML )
  994.                     {
  995.                         pObj->bInBrokenXML = TRUE;
  996.                         pQueue->EnQueue(m_pEscapeStrings[BeginBrokenAttributeMarkup]);
  997.                         pQueue->EnQueue(">");
  998.                     }
  999.                 }
  1000.     }
  1001.             break;
  1002.             case IN_COMMENT:
  1003.     {
  1004.                 /* do nothing until you find a closing '-->' */
  1005.                 if ( !strncmp((char*)pPositionPointer, "-->", 3) )
  1006.                 {
  1007.     pObj->bPushChar = FALSE;
  1008.                     pQueue->EnQueue("--&gt;");
  1009.                     pPositionPointer += 2;
  1010.                     uPositionOffset += 2;
  1011.                     pQueue->EnQueue(m_pEscapeStrings[EndCommentMarkup]);
  1012.                     pObj->state = IN_CONTENT;
  1013.                 }
  1014.                 else if ( *pPositionPointer == '<' )
  1015.                 {
  1016.     pObj->bPushChar = FALSE;
  1017.                     /* protect ourselves from markup */
  1018.                     pQueue->EnQueue("&lt;");
  1019.                 }
  1020.                 else if ( *pPositionPointer == '&' )
  1021.                 {
  1022.                      /* protect ourselves from markup */
  1023.                     pQueue->EnQueue("&amp;");
  1024.                     pObj->bPushChar = FALSE;
  1025.                 }
  1026.     }
  1027.             break;
  1028.             case IN_AMPERSAND_THINGY:
  1029.     {
  1030.                 /* do nothing until you find a ';' or space */
  1031.                 if ( *pPositionPointer == ';' || IS_SPACE(*pPositionPointer) )
  1032.                 {
  1033.     pObj->bPushChar = FALSE;
  1034.                     pQueue->EnQueue((char*)pPositionPointer, 1);
  1035.                     pQueue->EnQueue(m_pEscapeStrings[EndAmpersandThingyMarkup]);
  1036.                     pObj->state = IN_CONTENT;
  1037.                 }
  1038.                 else if ( *pPositionPointer == '<' )
  1039.                 {
  1040.     pObj->bPushChar = FALSE;
  1041.                     /* protect ourselves from markup */
  1042.                     pQueue->EnQueue("&lt;");
  1043.                 }
  1044.     }
  1045.             break;
  1046.             default:
  1047.                 HX_ASSERT(0);
  1048.             break;
  1049.         }
  1050. if ( pObj->bPushChar )
  1051. {
  1052.     pQueue->EnQueue((char*)pPositionPointer, 1);
  1053. }
  1054. pObj->bPushChar = TRUE;
  1055.     }
  1056. }
  1057. /*___________________________________________________________________________
  1058.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1059.  * Private Methods
  1060.  *___________________________________________________________________________
  1061.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1062. /*___________________________________________________________________________
  1063.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1064.  *  PushMangledDisplayedPath(pIn, pQueue, cEndQuote)
  1065.  *
  1066.  *  PARAMETERS:
  1067.  * pIn Pointer to a character string.  It is positioned
  1068.  * inside a quote right infront of the path or file to
  1069.  * to be mangled
  1070.  * pQueue A pointer to a CBigByteGrowingQueue that is used for queuing up 
  1071.  * the parsered output.
  1072.  *      cEndQuote - the character which ends the quote (either ' or ")
  1073.  *
  1074.  *  DESCRIPTION:
  1075.  * This Method replaces any path after a protocol with a /.../.
  1076.  * If there is no protocol, then it just replaces any relative path with
  1077.  * /.../
  1078.  *
  1079.  *  RETURNS:
  1080.  * The Number of characters off pIn that it pushed onto the queue
  1081.  *___________________________________________________________________________
  1082.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1083. UINT32
  1084. CEscapeXMLtoHTML::PushMangledDisplayedPath(const UCHAR*          pIn, 
  1085.    CBigByteGrowingQueue* pQueue,
  1086.                                            char                  cEndQuote)
  1087. {
  1088.     const char* pszQuote = strchr((const char*) pIn, cEndQuote);
  1089.     if (pszQuote)
  1090.     {
  1091.         UINT32 ulLen = ((const UCHAR*) pszQuote) - pIn;
  1092.         UINT32 ulPos = 0;
  1093.         if ( m_bMangleLinks )
  1094.         {
  1095.     const UCHAR* pProtocolEnd = (const UCHAR*)strnstr((const char*)pIn, 
  1096.         "://", (int)ulLen);
  1097.     if ( pProtocolEnd )  // we have protocol
  1098.     {
  1099.         pProtocolEnd += 2; // only push one slash
  1100.         UINT32 ulLenOfProtocol = pProtocolEnd - pIn;
  1101.         pQueue->EnQueue((void*)pIn, ulLenOfProtocol);
  1102.         pIn += ulLenOfProtocol;
  1103.         ulPos += ulLenOfProtocol;
  1104.     }
  1105.     // find last '/'
  1106.     while ( strnchr((const char*)pIn, '/', ulLen - ulPos) ) 
  1107.     {
  1108.         UINT32 temp = ulPos;
  1109.         temp += (const UCHAR*)strnchr((const char*)pIn, '/', ulLen - ulPos) 
  1110.         - pIn + 1;
  1111.         pIn  = (const UCHAR*)strnchr((const char*)pIn, '/', ulLen - ulPos) 
  1112.         + 1;
  1113.         ulPos = temp;
  1114.         
  1115.     }
  1116.     pQueue->EnQueue("/.../");
  1117.         }
  1118.         // else we just do the whole thing...
  1119.         pQueue->EnQueue((void*)pIn, ulLen - ulPos);
  1120.         return ulLen;
  1121.     }
  1122.     return 0;
  1123. }
  1124. /*___________________________________________________________________________
  1125.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1126.  *  PushOpenningHREF(pPositionPointer, pQueue, cEndQuote)
  1127.  *
  1128.  *  PARAMETERS:
  1129.  * pPositionPointer Pointer to a character string.  It is positioned
  1130.  * inside a quote right infront of the path or file to
  1131.  * to be referenced to.
  1132.  * This contains the absolute url if that is needed, or it
  1133.  * is used in the call to GetParameter(...).
  1134.  * pQueue A pointer to a CBigByteGrowingQueue that is used for queuing up 
  1135.  * the output.
  1136.  *      cEndQuote - the character to end the quote (either ' or ")
  1137.  *
  1138.  *  DESCRIPTION:
  1139.  * This Method pushes HREF onto the output queue.  It must build the
  1140.  * Url from the m_pServerUrl and the parameter (GetParameter).
  1141.  *
  1142.  *
  1143.  *  RETURNS:
  1144.  * void
  1145.  *___________________________________________________________________________
  1146.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1147. BOOL
  1148. CEscapeXMLtoHTML::PushOpenningHREF(const UCHAR* pPositionPointer, CBigByteGrowingQueue* pQueue, char cEndQuote)
  1149. {
  1150.     // if relative path
  1151.     // TODO: else we need to take care of full paths - 
  1152.     //     pPositionPointer or if m_pOurPath has a protocol as well.
  1153.     const char* pszQuote = strchr((const char*) pPositionPointer, cEndQuote);
  1154.     if (pszQuote)
  1155.     {
  1156.         UINT32 ulLen = ((const UCHAR*) pszQuote) - pPositionPointer;
  1157.         if ( strncmp((const char*)pPositionPointer, "rtsp://", 7) == 0 )
  1158.         {
  1159.     const char* p = (const char*)pPositionPointer;
  1160.     const char* pEnd = p + ulLen;
  1161.     p += 7;
  1162.     // move p to the end of server name find the first : or /
  1163.     while ( *p != ':' && *p != '/' && ++p != pEnd) {} ;
  1164.     pQueue->EnQueue(m_pEscapeStrings[BeginHREF]);
  1165.     // replacing rtsp with http
  1166.     
  1167.     //XXXJHUG  -- If the server in m_pServerUrl is the same as the 
  1168.     // server we are about queue we will use m_pServerUrl
  1169.     // instead of the default port and mountpoint.
  1170.     
  1171.     // mover past http://
  1172.     char* pBeginServer = m_pServerUrl + 7;
  1173.     
  1174.     UINT32 ulServerLen = 0;
  1175.     char* pServerPort = strchr(pBeginServer, ':');
  1176.     // m_pServerURL will always have a port.
  1177.     HX_ASSERT(pServerPort);
  1178.     if ( pServerPort )
  1179.     {
  1180.         ulServerLen = pServerPort - pBeginServer;
  1181.     }
  1182.     // 7 for rtsp://
  1183.     UINT32 ulXMLServerLen = p - (const char*)pPositionPointer - 7;
  1184.     if ( ulServerLen == ulXMLServerLen &&
  1185.         strncmp(pBeginServer, (const char*)pPositionPointer + 7, ulServerLen) == 0 )
  1186.     {
  1187.         // use m_pServerURL
  1188.         pQueue->EnQueue(m_pServerUrl);
  1189.     }
  1190.     else
  1191.     {
  1192.         // use the Default Port
  1193.         pQueue->EnQueue("http");
  1194.         pQueue->EnQueue((void*)(pPositionPointer + 4), p - (const char*)pPositionPointer - 4);
  1195.         pQueue->EnQueue(m_pDefaultView);
  1196.     }
  1197.     while ( *p != '/' && ++p != pEnd) {} ;
  1198.     UCHAR* pParam = GetParameter((const UCHAR*)p, pEnd - p);
  1199.     pQueue->EnQueue("?");
  1200.     pQueue->EnQueue((const char*)pParam);
  1201.     HX_VECTOR_DELETE(pParam);
  1202.     pQueue->EnQueue("">");
  1203.         }
  1204.         else if ( strnchr((const char*)pPositionPointer, ':', min(6, ulLen)) )
  1205.         {
  1206.     if ( strncmp((const char*)pPositionPointer, "pnm://", 6) != 0 &&
  1207.         (strncmp(m_pServerUrl, "http://localhost", sizeof("http://localhost") - 1) == 0 ||
  1208.         strncmp(m_pServerUrl, "http://127.0.0.1", sizeof("http://127.0.0.1") - 1) == 0) )
  1209.     {
  1210.         pQueue->EnQueue(m_pEscapeStrings[BeginHREF]);
  1211.         pQueue->EnQueue(m_pServerUrl);
  1212.         pQueue->EnQueue("?");
  1213.         UCHAR* pParam = GetParameter(pPositionPointer, ulLen, TRUE);
  1214.         pQueue->EnQueue((const char*)pParam);
  1215.         HX_VECTOR_DELETE(pParam);
  1216.         pQueue->EnQueue("">");
  1217.     }
  1218.     else
  1219.     {
  1220.         return FALSE;
  1221.     }
  1222.         }
  1223.         else
  1224.         {
  1225.     pQueue->EnQueue(m_pEscapeStrings[BeginHREF]);
  1226.     pQueue->EnQueue(m_pServerUrl);
  1227.     pQueue->EnQueue("?");
  1228.     UCHAR* pParam = GetParameter(pPositionPointer, ulLen);
  1229.     pQueue->EnQueue((const char*)pParam);
  1230.     HX_VECTOR_DELETE(pParam);
  1231.     pQueue->EnQueue("">");
  1232.         }
  1233.     }
  1234.     return TRUE;
  1235. }
  1236. /*___________________________________________________________________________
  1237.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1238.  *  PushEndingHREF(pQueue)
  1239.  *
  1240.  *  PARAMETERS:
  1241.  * pQueue A pointer to a CBigByteGrowingQueue that is used for queuing up 
  1242.  * the parsered output.
  1243.  *
  1244.  *  DESCRIPTION:
  1245.  * Pushes end of HREF onto the output queue.
  1246.  *
  1247.  *  RETURNS
  1248.  * void
  1249.  *___________________________________________________________________________
  1250.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1251. void
  1252. CEscapeXMLtoHTML::PushEndingHREF(CBigByteGrowingQueue* pQueue)
  1253. {
  1254.     pQueue->EnQueue(m_pEscapeStrings[EndHREF]);
  1255. }
  1256. /*___________________________________________________________________________
  1257.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1258.  *  GetParameter(pPositionPointer, ulNameLen)
  1259.  *
  1260.  *  PARAMETERS:
  1261.  * pPositionPointer Pointer to a character string.  It is positioned
  1262.  * inside a quote right infront of the path or file to
  1263.  * to be referenced to.
  1264.  * ulNameLen The length of the name.  It is not zero terminated.
  1265.  *
  1266.  *  DESCRIPTION:
  1267.  * This method builds a relative path and paramiterizes it.  Then the
  1268.  * parameter is encrypted with a call to EncryptParameter().  A string 
  1269.  * is allocated to be returned
  1270.  *
  1271.  *  RETURNS
  1272.  * a pointer to a new string that is to be used after the ? for an 
  1273.  * option in a url
  1274.  *___________________________________________________________________________
  1275.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1276. UCHAR*
  1277. CEscapeXMLtoHTML::GetParameter(const UCHAR* pPositionPointer, UINT32 ulNameLen, 
  1278.        BOOL bFullPath)
  1279. {
  1280.     // allocate longest possible string
  1281.     char* pReturnBuffer = new char[(strlen(m_pOurPath) + ulNameLen) + 10]; 
  1282.     //  2 for a possible starting '/' and a null terminator
  1283.     // 4 for the starting src=
  1284.     // 4 for extra bytes in case we have to pad the buffer when we encypt it.
  1285.     strcpy(pReturnBuffer, "src="); /* Flawfinder: ignore */
  1286.     char* pLinkPath = pReturnBuffer + 4;
  1287.     
  1288.     // if it starts with '/' then it is a full path
  1289.     if ( *pPositionPointer == '/' || bFullPath )
  1290.     {
  1291. strncpy(pLinkPath, (const char*)pPositionPointer, ulNameLen); /* Flawfinder: ignore */
  1292. pLinkPath[ulNameLen] = '';
  1293.     }
  1294.     // if it is alpha it is simply a file name
  1295.     else if ( isalnum(*pPositionPointer) )
  1296.     {
  1297. // 1 for "/"
  1298. UINT32 len = strlen(m_pOurPath) + ulNameLen + 1;
  1299. strcpy(pLinkPath, m_pOurPath); /* Flawfinder: ignore */
  1300. strcat(pLinkPath, "/"); /* Flawfinder: ignore */
  1301. strncat(pLinkPath, (const char*)pPositionPointer, ulNameLen); /* Flawfinder: ignore */
  1302. pLinkPath[len] = '';
  1303.     }
  1304.     else if ( !strncmp((const char*)pPositionPointer, "./", 2) )
  1305.     {
  1306. // -1 for .
  1307. UINT32 len = strlen(m_pOurPath) + ulNameLen - 1;
  1308. strcpy(pLinkPath, m_pOurPath); /* Flawfinder: ignore */
  1309. pPositionPointer += 1;
  1310. strncat(pLinkPath, (const char*)pPositionPointer, ulNameLen - 1); /* Flawfinder: ignore */
  1311. pLinkPath[len] = '';
  1312.     }
  1313.     else if ( !strncmp((const char*)pPositionPointer, "../", 3 ) )
  1314.     {
  1315. int count = 0;
  1316. // copy m_pOurPath into pLinkPath ourselves cause we need to be at
  1317. // the end anyway.
  1318. const char* pSrc = m_pOurPath;
  1319. char* pCurrentEndOfPath = pLinkPath;
  1320. const char* pRelativePath = (const char*)pPositionPointer;
  1321. // Walk to take care of any ../ that might be in the path...
  1322. char* pDest = pCurrentEndOfPath;
  1323. while ( *pSrc )
  1324. {
  1325.     while ( *pSrc == '.' && *(pSrc + 1) == '.' && *(pSrc + 2) == '/' )
  1326.     {
  1327. --pDest;
  1328. while ( *(pDest-1) != '/' && (pDest-1) >= pLinkPath )
  1329. {
  1330.     --pDest;
  1331. }
  1332. pSrc += 3;
  1333.     }
  1334.     *pDest = *pSrc;
  1335.     ++pDest;
  1336.     ++pSrc;
  1337. }
  1338. *pDest = '';
  1339. pCurrentEndOfPath += strlen(pCurrentEndOfPath);
  1340. // back up a directory off of the file path for
  1341. // every ../ we find
  1342. while (!strncmp((const char*)pRelativePath, "../", 3 ))
  1343. {
  1344.     // we found a ../ so back up a directory on the path,
  1345.     // walk backwards to the previous / and set it to null
  1346.     while (*pCurrentEndOfPath != '/' && 
  1347. pCurrentEndOfPath >= pLinkPath)
  1348.     {
  1349. pCurrentEndOfPath--;
  1350.     }
  1351.     // watch to make sure we don't have more ../ than directories
  1352.     if ( pCurrentEndOfPath < pLinkPath)
  1353.     {
  1354. ++pCurrentEndOfPath;
  1355.     }
  1356.     *pCurrentEndOfPath = '';
  1357.     pRelativePath +=3;
  1358. }
  1359.         UINT32 len = (pCurrentEndOfPath - pLinkPath) + 
  1360.     ulNameLen - (pRelativePath - (const char*)pPositionPointer) + 1;
  1361. // back 1 off of pRelativePath so we get the / that's there.
  1362. strncat(pLinkPath, (const char*)pRelativePath - 1, /* Flawfinder: ignore */
  1363.     ulNameLen - (pRelativePath - (const char*)pPositionPointer) + 1);
  1364. pLinkPath[len] = '';
  1365.     }
  1366.     else
  1367.     {
  1368. HX_ASSERT(FALSE);
  1369. pLinkPath = '';
  1370.     }
  1371.     char* pParam = EncryptParameter(pReturnBuffer);
  1372.     HX_VECTOR_DELETE(pReturnBuffer);
  1373.     return (UCHAR*)pParam;
  1374. }
  1375. /*___________________________________________________________________________
  1376.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1377.  *  EncryptParameter(pPath)
  1378.  *
  1379.  *  PARAMETERS:
  1380.  * pPath Pointer to a string to be parameterized and encrypted.
  1381.  *
  1382.  *  DESCRIPTION:
  1383.  * First it is assigned to a variable (src), and then the parameter is
  1384.  * encrypted
  1385.  *
  1386.  *  RETURNS
  1387.  * a pointer to a new string that is to be used after the ? for an 
  1388.  * option in a url
  1389.  *___________________________________________________________________________
  1390.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1391. char*
  1392. CEscapeXMLtoHTML::EncryptParameter(char* pPath)
  1393. {
  1394.     UINT32 FinalLen;     // length of encoded data
  1395.     UINT32 Offset = strlen(pPath);
  1396.     UINT32 nAlign = Offset % sizeof(ULONG32);
  1397.     if (nAlign > 0)
  1398.     {
  1399. for (; nAlign < sizeof(ULONG32); nAlign++)
  1400. {
  1401.     pPath[Offset++] = 0;
  1402. }
  1403.     }
  1404.     FinalLen = (Offset) * Perplex_PER_ULONG32 / sizeof(ULONG32);
  1405.     // calc size of the outout (Perplexed) buffer.
  1406.     // alloc mem for final perplexed buffer
  1407.     // Add one to length 'cause low level perplex adds
  1408.     // a '' to the resulting string
  1409.     char* output = new char[FinalLen+1];
  1410.     CHXPerplex::DumpToPerplex((char*)output,FinalLen+1,(UCHAR*) pPath, Offset);
  1411.     return output;
  1412. }
  1413. /*___________________________________________________________________________
  1414.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1415.  *  CheckTag (pObj)
  1416.  *
  1417.  *  PARAMETERS:
  1418.  * pObj current state
  1419.  *
  1420.  *  DESCRIPTION:
  1421.  * This method pushes the begging of a color tag onto the queue
  1422.  *
  1423.  *  RETURNS
  1424.  * void
  1425.  *___________________________________________________________________________
  1426.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1427. BOOL
  1428. CEscapeXMLtoHTML::CheckTag(DataObject* pObj)
  1429. {
  1430.     if ( m_pHotTags ) 
  1431.     {
  1432. for ( INT32 i = 0; m_pHotTags[i]; i++ )
  1433. {
  1434.     if ( !strcmp(pObj->tag, m_pHotTags[i]) )
  1435.     {
  1436.     return TRUE;
  1437.     }
  1438. }
  1439.     }
  1440.     return FALSE;
  1441. }
  1442. /*___________________________________________________________________________
  1443.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1444.  *  BeginColorTag (CBigByteGrowingQueue* qu, DataObject *pObj)
  1445.  *
  1446.  *  PARAMETERS:
  1447.  * qu queue to output to
  1448.  * pObj current state
  1449.  *  DESCRIPTION:
  1450.  * This method pushes the begging of a color tag onto the queue
  1451.  * RETURNS
  1452.  * void
  1453.  *___________________________________________________________________________
  1454.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1455. void
  1456. CEscapeXMLtoHTML::BeginColorTag (CBigByteGrowingQueue* qu, DataObject *pObj)
  1457. {
  1458.     qu->EnQueue(m_pEscapeStrings[BeginTagMarkup]);
  1459.     qu->EnQueue("&lt;");
  1460.     qu->EnQueue(m_pEscapeStrings[BeginTagNameMarkup]);
  1461.     pObj->state = ABOUT_TO_BEGIN_TAG;
  1462.     pObj->bPushChar = FALSE;
  1463. }
  1464. /*___________________________________________________________________________
  1465.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1466.  *  EndColorTag (CBigByteGrowingQueue* qu, DataObject *pObj)
  1467.  *
  1468.  *  PARAMETERS:
  1469.  * qu queue to output to
  1470.  * pObj current state
  1471.  *
  1472.  *  DESCRIPTION:
  1473.  * This method pushes the end of a color tag onto the queue
  1474.  *
  1475.  *  RETURNS
  1476.  * void
  1477.  *___________________________________________________________________________
  1478.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1479. void
  1480. CEscapeXMLtoHTML::EndColorTag (CBigByteGrowingQueue* qu, DataObject *pObj)
  1481. {
  1482.     if ( pObj->bInBrokenXML )
  1483.     {
  1484.         qu->EnQueue(m_pEscapeStrings[EndBrokenAttributeMarkup]);
  1485.         pObj->bInBrokenXML = FALSE;
  1486.     }
  1487.     if ( pObj->bInProcessingInstructions )
  1488.     {
  1489.        qu->EnQueue(m_pEscapeStrings[EndProcessingInstructions]);
  1490.        qu->EnQueue(m_pEscapeStrings[BeginTagMarkup]);
  1491.        qu->EnQueue("&gt;");
  1492.        qu->EnQueue(m_pEscapeStrings[EndTagMarkup]);
  1493.        pObj->bInProcessingInstructions = FALSE;
  1494.     }
  1495.     else
  1496.     {
  1497.        qu->EnQueue("&gt;");
  1498.        qu->EnQueue(m_pEscapeStrings[EndTagMarkup]);
  1499.     }
  1500.     pObj->state = IN_CONTENT;
  1501.     pObj->bPushChar = FALSE;
  1502. }