xmlesc.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:54k
源码类别:

Symbian

开发平台:

Visual C++

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