parseurl.cpp
Upload User: zhongxx05
Upload Date: 2007-06-06
Package Size: 33641k
Code Size: 28k
Category:

Symbian

Development Platform:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. // From include
  36. #include <ctype.h>
  37. #include "hxtypes.h"
  38. #include "hxwintyp.h"
  39. #include "hxcom.h"
  40. #include "hxresult.h"
  41. #include "ihxpckts.h"
  42. #include "hxcomm.h"
  43. // From hxcont
  44. #include "hxstring.h"
  45. #include "chxpckts.h"
  46. // From hxmisc
  47. #include "hxurl.h"
  48. #include "unkimp.h"
  49. #include "baseobj.h"
  50. #include "hxparse.h"
  51. // From pxcomlib
  52. #include "gstring.h"
  53. #include "pxutil.h"
  54. #include "pxcolor.h"
  55. #include "pxrect.h"
  56. #include "pxeffect.h"
  57. #include "buffutil.h"
  58. #include "parseurl.h"
  59. #ifdef _MACINTOSH
  60. #include <ctype.h>  // For toupper on the Macintosh.
  61. #include <stdlib.h> // for atol
  62. #endif
  63. // hxdebug
  64. #include "hxheap.h"
  65. #ifdef _DEBUG
  66. #undef HX_THIS_FILE
  67. static char HX_THIS_FILE[] = __FILE__;
  68. #endif
  69. HX_RESULT ParseURLEncoding(IHXCommonClassFactory *pFactory, const char *pszURL, IHXValues **ppValues)
  70. {
  71.     // Check for input errors
  72.     if (!pFactory || !pszURL)
  73.     {
  74.         return HXR_FAIL;
  75.     }
  76.     // Create an IHXValues object
  77.     IHXValues *pValues = NULL;
  78.     HX_RESULT retVal    = pFactory->CreateInstance(CLSID_IHXValues, (void **) &pValues);
  79.     if (retVal != HXR_OK)
  80.     {
  81.         return retVal;
  82.     }
  83.     *ppValues = pValues;
  84.     // Get a string class with the URL in it
  85.     GString cURL = pszURL;
  86.     // Get the length
  87.     INT32 lURLLen = strlen(pszURL);
  88.     // Look for the beginning of the parameter string
  89.     INT32 lPos = cURL.find('?');
  90.     if (lPos < 0)
  91.     {
  92.         return HXR_OK;
  93.     }
  94.     // Now we go into a loop looking for attribute/value pairs
  95.     for(;;)
  96.     {
  97.         // Set the beginning of the attribute
  98.         INT32 lAttributeLeftPos = lPos + 1;
  99.         // Look for the end of the attribute
  100.         lPos = cURL.find('=', lPos);
  101.         if (lPos < 0)
  102.         {
  103.             break;
  104.         }
  105.         // Set the inclusive end of the attribute
  106.         INT32 lAttributeRightPos = lPos - 1;
  107.         INT32 lValueLeftPos      = lPos + 1;
  108.         INT32 lValueRightPos;
  109. // Make sure we don't have a situation like "foo.jpg?bitrate="
  110. if (lValueLeftPos >= lURLLen)
  111. {
  112.     break;
  113. }
  114.         // Now look for the separator
  115.         lPos = cURL.find('&', lPos);
  116.         if (lPos < 0)
  117.         {
  118.             // We didn't find the separator, so we assume the end of
  119.             // the string is the end of the value
  120.             lValueRightPos = cURL.length() - 1;
  121.             lPos           = lValueRightPos;
  122.         }
  123.         else
  124.         {
  125.             lValueRightPos = lPos - 1;
  126.         }
  127.         // Check to see if we have valid strings for our attribute and value
  128.         if (lAttributeRightPos >= lAttributeLeftPos &&
  129.             lValueRightPos     >= lValueLeftPos)
  130.         {
  131.             GString cAttribute = cURL.substr(lAttributeLeftPos, lAttributeRightPos);
  132.             GString cValue     = cURL.substr(lValueLeftPos,     lValueRightPos);
  133.             // Create an IHXBuffer
  134.             IHXBuffer *pBuffer = NULL;
  135.             retVal              = pFactory->CreateInstance(CLSID_IHXBuffer, (void **) &pBuffer);
  136.             if (retVal != HXR_OK)
  137.             {
  138.                 HX_RELEASE(pValues);
  139.                 *ppValues = NULL;
  140.                 return retVal;
  141.             }
  142.             // Set value string into the buffer
  143.             retVal = pBuffer->Set((const BYTE *) cValue.c_str(), cValue.length() + 1);
  144.             if (retVal != HXR_OK)
  145.             {
  146.                 HX_RELEASE(pBuffer);
  147.                 HX_RELEASE(pValues);
  148.                 *ppValues = NULL;
  149.                 return retVal;
  150.             }
  151.             // Set the attribute/value pair
  152.             retVal = pValues->SetPropertyCString(cAttribute.c_str(), pBuffer);
  153.             if (retVal != HXR_OK)
  154.             {
  155.                 HX_RELEASE(pBuffer);
  156.                 HX_RELEASE(pValues);
  157.                 *ppValues = NULL;
  158.                 return retVal;
  159.             }
  160.             // Release our reference on the buffer
  161.             HX_RELEASE(pBuffer);
  162.         }
  163.     }
  164.     return HXR_OK;
  165. }
  166. HX_RESULT ExtractValueTime(IHXValues *pValues, const char *pszAttr, UINT32 ulDefault, UINT32 &rulValue)
  167. {
  168.     IHXBuffer *pStringBuf = NULL;
  169.     HX_RESULT retVal = pValues->GetPropertyCString(pszAttr, pStringBuf);
  170.     if (retVal != HXR_OK)
  171.     {
  172.         // No attribute was specified, so take the default
  173.         rulValue = ulDefault;
  174.         return HXR_OK;
  175.     }
  176.     // An attribute was specified so use it
  177.     char   *pszStr   = (char *) pStringBuf->GetBuffer();
  178.     UINT32  ulStrLen = strlen(pszStr);
  179.     BOOL bRet        = ConvertTimeStringToULONG32(pszStr, ulStrLen, rulValue);
  180.     if (bRet == FALSE)
  181.     {
  182.         HX_RELEASE(pStringBuf);
  183.         return HXR_FAIL;
  184.     }
  185.     HX_RELEASE(pStringBuf);
  186.     return HXR_OK;
  187. }
  188. HX_RESULT ExtractValueUINT32(IHXValues *pValues, const char *pszAttr, UINT32 ulDefault, UINT32 &rulValue)
  189. {
  190.     IHXBuffer *pStringBuf = NULL;
  191.     HX_RESULT retVal = pValues->GetPropertyCString(pszAttr, pStringBuf);
  192.     if (retVal != HXR_OK)
  193.     {
  194.         // No attribute was specified, so take the default
  195.         rulValue = ulDefault;
  196.         return HXR_OK;
  197.     }
  198.     // An attribute was specified so use it
  199.     rulValue = (UINT32) atol((char *) pStringBuf->GetBuffer());
  200.     // Release the buffer
  201.     HX_RELEASE(pStringBuf);
  202.     return HXR_OK;
  203. }
  204. HX_RESULT ExtractValueBOOL(IHXValues *pValues, const char *pszAttr, BOOL bDefault, BOOL &rbValue)
  205. {
  206.     IHXBuffer *pStringBuf = NULL;
  207.     HX_RESULT   retVal     = pValues->GetPropertyCString(pszAttr, pStringBuf);
  208.     if (retVal != HXR_OK)
  209.     {
  210.         // No attribute was specified, so take the default
  211.         rbValue = bDefault;
  212.         return HXR_OK;
  213.     }
  214.     // An attribute was specified so use it
  215.     char *pVal = (char *) pStringBuf->GetBuffer();
  216.     if (!strcmp(pVal, "true"))
  217.     {
  218.         rbValue = TRUE;
  219.     }
  220.     else if (!strcmp(pVal, "false"))
  221.     {
  222.         rbValue = FALSE;
  223.     }
  224.     else
  225.     {
  226.         rbValue = bDefault;
  227.         HX_RELEASE(pStringBuf);
  228.         return HXR_FAIL;
  229.     }
  230.     // Release the buffer
  231.     HX_RELEASE(pStringBuf);
  232.     return HXR_OK;
  233. }
  234. HX_RESULT ExtractValueString(IHXValues *pValues, const char *pszAttr, const char *pszDefault, CHXString &rcValue)
  235. {
  236.     IHXBuffer* pStringBuf = NULL;
  237.     HX_RESULT retVal = pValues->GetPropertyCString(pszAttr, pStringBuf);
  238.     if (retVal != HXR_OK)
  239.     {
  240.         // No attribute was specified, so take the default
  241.         if (pszDefault)
  242.         {
  243.             rcValue = pszDefault;
  244.         }
  245.         return HXR_OK;
  246.     }
  247.     // An attribute was specified so use it
  248.     rcValue = (const char*) pStringBuf->GetBuffer();
  249.     // Release the value buffer
  250.     HX_RELEASE(pStringBuf);
  251.     return HXR_OK;
  252. }
  253. HX_RESULT ExtractValueString(IHXValues *pValues, const char *pszAttr, const char *pszDefault, GString &rcValue)
  254. {
  255.     IHXBuffer *pStringBuf = NULL;
  256.     HX_RESULT retVal = pValues->GetPropertyCString(pszAttr, pStringBuf);
  257.     if (retVal != HXR_OK)
  258.     {
  259.         // No attribute was specified, so take the default
  260.         if (pszDefault)
  261.         {
  262.             rcValue = pszDefault;
  263.         }
  264.         else
  265.         {
  266.             rcValue = "";
  267.         }
  268.         return HXR_OK;
  269.     }
  270.     // An attribute was specified so use it
  271.     rcValue.CopyN(pStringBuf->GetBuffer(), pStringBuf->GetSize());
  272.     // Release the value buffer
  273.     HX_RELEASE(pStringBuf);
  274.     return HXR_OK;
  275. }
  276. HX_RESULT ExtractValueColor(IHXValues *pValues, const char *pszAttr, const char *pszDefault, PXColor &rcValue)
  277. {
  278.     IHXBuffer *pStringBuf = NULL;
  279.     HX_RESULT   retVal = pValues->GetPropertyCString(pszAttr, pStringBuf);
  280.     GString     cColor;
  281.     if (retVal != HXR_OK)
  282.     {
  283.         cColor = pszDefault;
  284.     }
  285.     else
  286.     {
  287.         // An attribute was specified so use it
  288.         cColor.CopyN(pStringBuf->GetBuffer(), pStringBuf->GetSize());
  289.         // Release the value buffer
  290.         HX_RELEASE(pStringBuf);
  291.     }
  292.     // Now convert the color
  293.     retVal = rcValue.InitFromString(cColor.c_str());
  294.     if (retVal != HXR_OK)
  295.     {
  296.         return retVal;
  297.     }
  298.     return HXR_OK;
  299. }
  300. HX_RESULT ExtractValueColor(IHXValues *pValues, const char *pszAttr, UINT32 ulDefault, UINT32& rulValue)
  301. {
  302.     IHXBuffer* pStringBuf = NULL;
  303.     HX_RESULT   retVal = pValues->GetPropertyCString(pszAttr, pStringBuf);
  304.     if (retVal != HXR_OK)
  305.     {
  306.         rulValue = ulDefault;
  307.     }
  308.     else
  309.     {
  310.         UINT32 ulTmp = ulDefault;
  311.         retVal = HXParseColorUINT32((const char*) pStringBuf->GetBuffer(),
  312.                                     ulTmp);
  313.         if (SUCCEEDED(retVal))
  314.         {
  315.             rulValue = ulTmp;
  316.         }
  317.         else
  318.         {
  319.             rulValue = ulDefault;
  320.         }
  321.         // Release the value buffer
  322.         HX_RELEASE(pStringBuf);
  323.     }
  324.     return HXR_OK;
  325. }
  326. HX_RESULT ExtractValueOpacity(IHXValues *pValues, const char *pszAttr, UINT32 ulDefault, UINT32& rulValue)
  327. {
  328.     IHXBuffer *pStringBuf = NULL;
  329.     HX_RESULT retVal = pValues->GetPropertyCString(pszAttr, pStringBuf);
  330.     if (retVal != HXR_OK)
  331.     {
  332.         // No attribute was specified, so take the default
  333.         rulValue = ulDefault;
  334.         return HXR_OK;
  335.     }
  336.     // An attribute was specified so use it
  337.     INT32  lOpacity  = 0;
  338.     char*  pEndPtr   = NULL;
  339.     double dVal      = strtod((const char*) pStringBuf->GetBuffer(), &pEndPtr);
  340.     if (pEndPtr && *pEndPtr == '%')
  341.     {
  342.         // Value is a percent
  343.         lOpacity = (INT32) ((dVal * 255.0 / 100.0) + 0.5);
  344.     }
  345.     else
  346.     {
  347.         lOpacity = (INT32) (dVal + 0.5);
  348.     }
  349.     // Range check
  350.     if (lOpacity < 0)
  351.     {
  352.         lOpacity = 0;
  353.     }
  354.     if (lOpacity > 255)
  355.     {
  356.         lOpacity = 255;
  357.     }
  358.     // Assign the out parameter
  359.     rulValue = (UINT32) lOpacity;
  360.     // Release the buffer
  361.     HX_RELEASE(pStringBuf);
  362.     return HXR_OK;
  363. }
  364. BOOL ConvertTimeStringToULONG32(char *pTimeBuf, ULONG32 timeBufLen, ULONG32 &timeValInMillisec)
  365. {
  366.     char   *pTimeBuffer            = pTimeBuf;
  367.     ULONG32 timeBufferLen          = timeBufLen;
  368.     char    savedEndChar           = '';   //for restoring '"' char at end, if found.
  369.     LONG32  bufIndx                = 0L;
  370.     BOOL    bDotEncounteredAlready = FALSE;
  371.     LONG32  indexOfDot             = -1;
  372.     BOOL    endCharWasChanged      = FALSE;
  373.     ULONG32 days_;
  374.     ULONG32 hours_;
  375.     ULONG32 minutes_;
  376.     ULONG32 seconds_;
  377.     ULONG32 milliseconds_;
  378.     // Initialize
  379.     days_ = hours_ = minutes_ = seconds_ = milliseconds_ = 0L;
  380.     timeValInMillisec=0;
  381.     // Check for input error
  382.     if(!pTimeBuffer  ||  timeBufLen < MIN_TIMEBUFFERLENGTH)
  383.     {
  384.         return FALSE;
  385.     }
  386.     savedEndChar = pTimeBuffer[timeBufferLen-1];
  387.     //Get rid of start & terminating quotation mark, if they exist:
  388.     if(pTimeBuffer[0] == '"')
  389.     {
  390.         pTimeBuffer++;
  391.         timeBufferLen--;
  392.         //Added this check to kill bug if (pTimeBuffer==")
  393.         // and got shortened to an empty string:
  394.         if(!timeBufferLen)
  395.         {
  396.             return FALSE;
  397.         }
  398.     }
  399.     if(pTimeBuffer[timeBufferLen - 1] == '"')
  400.     {
  401.         pTimeBuffer[timeBufferLen - 1] = ''; //get rid of end '"'.
  402.         timeBufferLen--;
  403.         endCharWasChanged = TRUE;
  404.     }
  405.     
  406.     // Work from right to left, searching first for milliseconds and then for
  407.     // seconds (or seconds only if no '.' found):
  408.     BOOL bColonWasFound = FALSE;
  409.     for(bufIndx=timeBufferLen-1; 0L<=bufIndx; bufIndx--)
  410.     {
  411.         char ch = toupper(pTimeBuffer[bufIndx]);
  412.         if('0' > ch  ||  '9' < ch)
  413.         {
  414.             if(' '==ch  ||  't'==ch  ||  'n'==ch  ||  'r'==ch)
  415.             {
  416.                 //Added everything up to "break;" to
  417.                 // handle (valid) strings with leading space(s) like " 39":
  418.                 //previous found was seconds_, so translate into ULONG:
  419.                 seconds_ = atol(&pTimeBuffer[bufIndx+1L]);
  420.                 timeValInMillisec += seconds_*1000; //converts seconds to ms.
  421.                 break; //we're done; we found seconds only.
  422.             }
  423.             else if('.' == ch)
  424.             {
  425.                 if(bDotEncounteredAlready)
  426.                 {
  427.                     //Make sure pTimeBuffer is in original state:
  428.                     if(endCharWasChanged)
  429.                     {
  430.                         timeBufferLen++;
  431.                         pTimeBuffer[timeBufferLen-1] = savedEndChar;
  432.                     }
  433.                     if(indexOfDot >= 0)
  434.                     {
  435.                         pTimeBuffer[indexOfDot] = '.';
  436.                     }
  437.                     //this second '.' is unexpected, so return with
  438.                     //  timeValInMillisec set to whatever was read so far:
  439.                     return FALSE;
  440.                 }
  441.                 bDotEncounteredAlready = TRUE;
  442.                 indexOfDot = bufIndx;
  443.                 pTimeBuffer[bufIndx] = ''; //end the buffr at the '.' .
  444.                 //previously-read #'s are milliseconds, so count them:
  445.                 //added "-1" to fix bug if buf ends with ".":
  446.                 if(1L > timeBufferLen-bufIndx - 1)
  447.                 {
  448.                     milliseconds_ = 0L;
  449.                 }
  450.                 else
  451.                 {
  452.                     //Now, make sure that more than three digits (base 10)
  453.                     //  are not present, e.g., reduce "46371" to "463" since
  454.                     //  we only allow millisecond precision (3 digits past
  455.                     //  the decimal point:
  456.                     char    chTmp = '';
  457.                     ULONG32 ulNumDecimalDigitsFound = timeBufferLen-1 - bufIndx;
  458.                     if(NUM_DECIMAL_DIGITS_OF_SECONDS < ulNumDecimalDigitsFound)
  459.                     {
  460.                         chTmp                                                = pTimeBuffer[bufIndx + 1L];
  461.                         pTimeBuffer[bufIndx+NUM_DECIMAL_DIGITS_OF_SECONDS+1] = '';
  462.                     }
  463.                     milliseconds_ = atol(&pTimeBuffer[bufIndx+1L]);
  464.                     //Added this to fix "y.x" being converted
  465.                     // to y00x instead of yx00 milliseconds:
  466.                     if(ulNumDecimalDigitsFound < NUM_DECIMAL_DIGITS_OF_SECONDS)
  467.                     {
  468.                         for(ULONG32 ulDiff= NUM_DECIMAL_DIGITS_OF_SECONDS - ulNumDecimalDigitsFound; ulDiff > 0; ulDiff--)
  469.                         {
  470.                             milliseconds_ *= 10;
  471.                         }
  472.                     }
  473.                     if(NUM_DECIMAL_DIGITS_OF_SECONDS < ulNumDecimalDigitsFound)
  474.                     {
  475.                         //restore the changed char in the pTimeBuffer:
  476.                         pTimeBuffer[bufIndx+ NUM_DECIMAL_DIGITS_OF_SECONDS + 1] = chTmp;
  477.                     }
  478.                 }
  479.         
  480.                 timeValInMillisec = milliseconds_;
  481.             }
  482.             else if(':' == ch)
  483.             {
  484.                 bColonWasFound = TRUE;
  485.                 //previous found was seconds_, so translate into ULONG:
  486.                 seconds_           = atol(&pTimeBuffer[bufIndx + 1L]);
  487.                 timeValInMillisec += seconds_ * 1000; //converts seconds to ms.
  488.                 break; //done with "seconds_[.milliseconds_]" part.
  489.             }
  490.             else  //unexpected char found, so quit parsing:
  491.             {
  492.                 //Make sure pTimeBuffer is in original state:
  493.                 if(endCharWasChanged)
  494.                 {
  495.                     timeBufferLen++;
  496.                     pTimeBuffer[timeBufferLen - 1] = savedEndChar;
  497.                 }
  498.                 if(indexOfDot >= 0)
  499.                 {
  500.                     pTimeBuffer[indexOfDot] = '.';
  501.                 }
  502.                 //this char is unexpected, so return FALSE with
  503.                 //  timeValInMillisec set to whatever was read so far:
  504.                 return FALSE;
  505.             }
  506.         }
  507.         else if(0L == bufIndx) //we're done with the buffer:
  508.         {
  509.             //previous found was seconds_, so translate into ULONG:
  510.             seconds_           = atol(pTimeBuffer);
  511.             timeValInMillisec += seconds_*1000; //converts seconds to ms.
  512.             break; //done with "seconds_[.milliseconds_]" part.
  513.         }
  514.     }
  515.     if(bColonWasFound) //then get the "minutes" part:
  516.     {
  517.         bColonWasFound = FALSE;
  518.         // We've got the ":seconds.msecs" part, so lets get the hours part:
  519.         for(bufIndx--; 0L<=bufIndx; bufIndx--)
  520.         {
  521.             char ch = toupper(pTimeBuffer[bufIndx]);
  522.             if('0' > ch  ||  '9' < ch)
  523.             {
  524.                 if(' ' == ch  ||  '.' == ch)
  525.                 {
  526.                     break;
  527.                 }
  528.                 else if(':' == ch)
  529.                 {
  530.                     bColonWasFound = TRUE;
  531.                     //previous found was seconds_, so translate into ULONG:
  532.                     // (Note: this will do atol("min:sec") which ignores
  533.                     // everything at & beyond the first non-num (":") char):
  534.                     minutes_           = atol(&pTimeBuffer[bufIndx+1L]);
  535.                     timeValInMillisec += minutes_*60000; //minutes to msec
  536.                     break; //done w/ "minutes_:seconds_[milliseconds_]" part.
  537.                 }
  538.                 else  //unexpected char found, so quit parsing:
  539.                 {
  540.                     //Make sure pTimeBuffer is in original state:
  541.                     if(endCharWasChanged)
  542.                     {
  543.                         timeBufferLen++;
  544.                         pTimeBuffer[timeBufferLen-1] = savedEndChar;
  545.                     }
  546.                     if(indexOfDot >= 0)
  547.                     {
  548.                         pTimeBuffer[indexOfDot] = '.';
  549.                     }
  550.                     //this char is unexpected, so return FALSE with
  551.                     //  timeValInMillisec set to whatever was read so far:
  552.                     return FALSE;
  553.                 }
  554.             }
  555.             else if(0L == bufIndx) //we're done with the buffer:
  556.             {
  557.                 //previous found was seconds_, so translate into ULONG:
  558.                 minutes_           = atol(pTimeBuffer);
  559.                 timeValInMillisec += minutes_*60000; //minutes to msec
  560.                 break; //done w/ "minutes_:seconds_[milliseconds_]" part.
  561.             }
  562.         }
  563.     }
  564.     if(bColonWasFound) //then get the "hours" part:
  565.     {
  566.         bColonWasFound = FALSE;
  567.         //We've got the ":minutes.seconds.msec" part, so lets get the hours:
  568.         for(bufIndx--; 0L <= bufIndx; bufIndx--)
  569.         {
  570.             char ch = toupper(pTimeBuffer[bufIndx]);
  571.             if('0' > ch  ||  '9' < ch)
  572.             {
  573.                 if(' ' == ch  ||  '.' == ch)
  574.                 {
  575.                     break;
  576.                 }
  577.                 else if(':' == ch)
  578.                 {
  579.                     bColonWasFound = TRUE;
  580.                     //previous found was minutes_, so translate into ULONG:
  581.                     // (Note: this will do atol("hrs:min:sec") which ignores
  582.                     // everything at & beyond the first non-num (":") char):
  583.                     hours_             = atol(&pTimeBuffer[bufIndx + 1L]);
  584.                     timeValInMillisec += hours_ * 3600000; //hours to msec
  585.                     break;//done w/ "hours_:minutes_:seconds_[milliseconds_]"
  586.                 }
  587.                 else  //unexpected char found, so quit parsing:
  588.                 {
  589.                     //Make sure pTimeBuffer is in original state:
  590.                     if(endCharWasChanged)
  591.                     {
  592.                         timeBufferLen++;
  593.                         pTimeBuffer[timeBufferLen-1] = savedEndChar;
  594.                     }
  595.                     if(indexOfDot >= 0)
  596.                     {
  597.                         pTimeBuffer[indexOfDot] = '.';
  598.                     }
  599.                     //this char is unexpected, so return FALSE with
  600.                     //  timeValInMillisec set to whatever was read so far:
  601.                     return FALSE;
  602.                 }
  603.             }
  604.             else if(0L == bufIndx) //we're done with the buffer:
  605.             {
  606.                 //previous found was seconds_, so translate into ULONG:
  607.                 hours_             = atol(pTimeBuffer);
  608.                 timeValInMillisec += hours_ * 3600000; //hours to msec
  609.                 break; //done w/ "hours_:minutes_:seconds_[milliseconds_]".
  610.             }
  611.         }
  612.     }
  613.     if(bColonWasFound) //then get the "days" part:
  614.     {
  615.         bColonWasFound = FALSE;
  616.         //We've got the "hours:minutes.seconds.msec" part, so lets get the days:
  617.         for(bufIndx--; 0L <= bufIndx; bufIndx--)
  618.         {
  619.             char ch = toupper(pTimeBuffer[bufIndx]);
  620.             if('0' > ch  ||  '9' < ch)
  621.             {
  622.                 if(' ' == ch  ||  '.' == ch)
  623.                 {
  624.                     break;
  625.                 }
  626.                 else if(':' == ch)
  627.                 {
  628.                     bColonWasFound = TRUE;
  629.                     //previous found was minutes_, so translate into ULONG:
  630.                     // (Note: this will do atol("hrs:min:sec") which ignores
  631.                     // everything at & beyond the first non-num (":") char):
  632.                     days_              = atol(&pTimeBuffer[bufIndx+1L]);
  633.                     timeValInMillisec += days_ * 86400000; //days to msec
  634.                     break;//done w/ "days_:hours_:minutes_:seconds_[msecs_]"
  635.                 }
  636.                 else  //unexpected char found, so quit parsing:
  637.                 {
  638.                     //Make sure pTimeBuffer is in original state:
  639.                     if(endCharWasChanged)
  640.                     {
  641.                         timeBufferLen++;
  642.                         pTimeBuffer[timeBufferLen - 1] = savedEndChar;
  643.                     }
  644.                     if(indexOfDot >= 0)
  645.                     {
  646.                         pTimeBuffer[indexOfDot] = '.';
  647.                     }
  648.                     //this char is unexpected, so return FALSE with
  649.                     //  timeValInMillisec set to whatever was read so far:
  650.                     return FALSE;
  651.                 }
  652.             }
  653.             else if(0L == bufIndx) //we're done with the buffer:
  654.             {
  655.                 //previous found was seconds_, so translate into ULONG:
  656.                 hours_             = atol(pTimeBuffer);
  657.                 timeValInMillisec += hours_ * 86400000; //days to msec
  658.                 break; //done w/ "days_:hours_:minutes_:seconds_[msec_]".
  659.             }
  660.         }
  661.     }
  662.     if(endCharWasChanged)
  663.     {
  664.         timeBufferLen++;
  665.         //Restore the orignial pTimeBuffer, in case end quote char was removed:
  666.         pTimeBuffer[timeBufferLen - 1] = savedEndChar;
  667.     }
  668.     if(indexOfDot >= 0)
  669.     {
  670.         pTimeBuffer[indexOfDot] = '.';
  671.     }
  672.     return TRUE;
  673. }
  674. BOOL IsURLRelative(const char* pszURL)
  675. {
  676.     BOOL   bRelative = TRUE;
  677.     CHXURL cFullURL(pszURL);
  678.     if (cFullURL.GetLastError() == HXR_OK)
  679.     {
  680.         IHXValues* pHeader = cFullURL.GetProperties();
  681.         if (pHeader)
  682.         {
  683.             IHXBuffer *pDummy = NULL;
  684.             HX_RESULT   retVal = pHeader->GetPropertyBuffer(PROPERTY_SCHEME, pDummy);
  685.             if (retVal != HXR_OK)
  686.             {
  687.                 // If we do NOT have a PROPERTY_SCHEME property, then we are relative.
  688.                 bRelative = TRUE;
  689.             }
  690.             else
  691.             {
  692.                 bRelative = FALSE;
  693.             }
  694.             HX_RELEASE(pDummy);
  695.         }
  696.         HX_RELEASE(pHeader);
  697.     }
  698.     return bRelative;
  699. }
  700. HX_RESULT MakeAbsoluteURL(const CHXString& rOrigURL, const CHXString& rRelURL, CHXString& rAbsURL)
  701. {
  702.     // Create the CHXURL object
  703.     CHXURL     cURLObj((const char*) rOrigURL);
  704.     IHXValues* pHeader = cURLObj.GetProperties();
  705.     if(!pHeader)
  706.     {
  707.         return HXR_FAIL;
  708.     }
  709.     // Initialize the output string
  710.     rAbsURL.Empty();
  711.     // Get the scheme
  712.     IHXBuffer* pBuffer = NULL;
  713.     HX_RESULT   retVal = pHeader->GetPropertyBuffer(PROPERTY_SCHEME, pBuffer);
  714.     if (retVal == HXR_OK)
  715.     {
  716.         rAbsURL = (const char*) pBuffer->GetBuffer();
  717.         rAbsURL += "://";
  718.         HX_RELEASE(pBuffer);
  719.     }
  720.     // Get the host
  721.     BOOL bHasHost = FALSE;
  722.     retVal        = pHeader->GetPropertyBuffer(PROPERTY_HOST, pBuffer);
  723.     if (retVal == HXR_OK)
  724.     {
  725.         rAbsURL += (const char*) pBuffer->GetBuffer();
  726.         HX_RELEASE(pBuffer);
  727.         bHasHost = TRUE;
  728.     }
  729.     
  730.     // Get the port
  731.     UINT32 ulPort;
  732.     retVal = pHeader->GetPropertyULONG32(PROPERTY_PORT, ulPort);
  733.     if (retVal == HXR_OK)
  734.     {
  735.         char szTemp[16]; /* Flawfinder: ignore */
  736.         sprintf(szTemp, ":%d", (UINT16) ulPort); /* Flawfinder: ignore */
  737.         rAbsURL += szTemp;
  738.     }
  739.     if(bHasHost)
  740.     {
  741.         rAbsURL += "/";
  742.     }
  743.     retVal = pHeader->GetPropertyBuffer(PROPERTY_RESOURCE, pBuffer);
  744.     if (retVal == HXR_OK)
  745.     {
  746.         const char* pResource   = (const char*)pBuffer->GetBuffer();
  747.         const char  cDelimiter1 = '/';
  748.         const char  cDelimiter2 = '\';
  749.         CHXString   strURLWork = pResource; 
  750.         char*       pFirstChar = strURLWork.GetBuffer(strURLWork.GetLength());
  751.         char*       pLastChar  = NULL;
  752.         char*       pOptions   = NULL;
  753.         char*       pFragment  = NULL;
  754.         pOptions = strchr(pFirstChar, '?');
  755.         if (pOptions)
  756.         {
  757.             pLastChar = pOptions - 1;
  758.         }
  759.         else
  760.         {
  761.             pLastChar = pFirstChar + strlen(pFirstChar) - 1;
  762.         }
  763.         while ((pLastChar > pFirstChar) && (*pLastChar != cDelimiter1) && (*pLastChar != cDelimiter2))
  764.         {
  765.             pLastChar--;
  766.         }
  767.         // If we hit a delimiter before hitting the end, back up one character!
  768.         if(pLastChar > pFirstChar) 
  769.         {
  770.             *(++pLastChar) = '';
  771.             rAbsURL += pFirstChar;
  772.         }
  773.         HX_RELEASE(pBuffer);
  774.     }
  775.     HX_RELEASE(pHeader);
  776.     // Now tack on the relative URL
  777.     rAbsURL += rRelURL;
  778.     return HXR_OK;
  779. }
  780. HX_RESULT AddURLOrRequestParam(IHXRequest* pRequest, const char* pszParamName,
  781.                                IUnknown* pContext, IHXValues* pValues)
  782. {
  783.     HX_RESULT retVal = HXR_OK;
  784.     if (pRequest && pszParamName && pValues)
  785.     {
  786.         IHXBuffer* pBuf = NULL;
  787.         HX_RESULT rv = PXUtilities::GetURLOrRequestParam(pRequest, FALSE, pContext,
  788.                                                          pszParamName, pBuf);
  789.         if (SUCCEEDED(rv))
  790.         {
  791.             retVal = pValues->SetPropertyCString(pszParamName, pBuf);
  792.         }
  793.         HX_RELEASE(pBuf);
  794.     }
  795.     else
  796.     {
  797.         retVal = HXR_FAIL;
  798.     }
  799.     return retVal;
  800. }