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

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: unix_pref.cpp,v 1.7.18.3 2004/07/09 01:47:39 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. #ifdef _BEOS
  50. #include <Path.h>
  51. #include <FindDirectory.h>
  52. #endif
  53. #include <string.h>
  54. #include <unistd.h>
  55. #ifndef _VXWORKS
  56. #include <strings.h>
  57. #include <sys/uio.h> 
  58. #include <sys/file.h>
  59. #endif
  60. #include <stdlib.h>
  61. #include <stdio.h>
  62. #include <fcntl.h>
  63. #include <limits.h>
  64. #include <sys/stat.h>
  65. #include <ctype.h>
  66. #include <errno.h>
  67. #include "hxslist.h"
  68. #include "hxmap.h"
  69. #include "hxtypes.h"
  70. #include "hxresult.h"
  71. #include "hxheap.h"
  72. #include "hxstrutl.h"
  73. #include "hxcom.h"
  74. #include "ihxpckts.h"
  75. #include "chxpckts.h"
  76. #include "unix_pref.h"
  77. #include "dbcs.h"  // HXReverseFindChar prototype
  78. #include "unix_misc.h"
  79. #include "cunixprefutils.h"
  80. #define ARE_PREFS_LOADED_PREF "ArePrefsLoaded"
  81. extern char** environ;
  82. static CHXString FixupCompany (const char *pCompany)
  83. {
  84.     char *pTmpCompany = new_string(pCompany);
  85.     char *pos  = strchr(pTmpCompany, ',');
  86.     if (pos) *pos = 0;
  87.     strlwr(pTmpCompany);
  88.     CHXString ret = pTmpCompany;
  89.     HX_VECTOR_DELETE(pTmpCompany);
  90.     return ret;
  91. }
  92. static char *CIGetenv(const char *pKey)
  93. {
  94.     UINT32 keylen = strlen(pKey);
  95.     char *pArr = new char[keylen + 2];
  96.     sprintf(pArr, "%s=", pKey); /* Flawfinder: ignore */
  97.     for (char **ppEnv = environ ; *ppEnv ; ++ppEnv)
  98.     {
  99. if (!strnicmp(*ppEnv, pArr, keylen +1))
  100. {
  101.     HX_VECTOR_DELETE(pArr);
  102.     return *ppEnv + keylen + 1;
  103. }
  104.     }
  105.     HX_VECTOR_DELETE(pArr);
  106.     return NULL;
  107. }
  108. static int CIPutenv(const char *pKey)
  109. {
  110.     char *pNewVal = new_string(pKey);
  111.     char *pEquals = strchr(pNewVal, '=');
  112.     HX_ASSERT(pEquals);
  113.     if (pEquals)
  114.     {
  115.         *pEquals = '';
  116.         strlwr(pNewVal);
  117.         *pEquals = '=';
  118.     }
  119.     return putenv(pNewVal);
  120. }
  121. static void CIUnsetEnv(const char *pKey)
  122. {
  123.     unsigned int keylen = strlen(pKey);
  124.     char *pArr = new char[keylen + 2];
  125.     sprintf(pArr, "%s=", pKey); /* Flawfinder: ignore */
  126.     for (char **ppEnv = environ ; *ppEnv ; ++ppEnv)
  127.     {
  128.         if (!strnicmp(*ppEnv, pArr, keylen +1))
  129.         {
  130.             //delete [] *ppEnv;  // pjg all uses of this delete the string
  131.             while (*ppEnv)
  132.             {
  133.                 *ppEnv = *(ppEnv+1);
  134.                 ppEnv++;
  135.             }
  136.             HX_VECTOR_DELETE(pArr);
  137.             return;
  138.         }
  139.     }
  140.     HX_VECTOR_DELETE(pArr);
  141. }
  142. void CUnixPref::ConstructFamily(CHXString &ret)
  143. {
  144.     HX_ASSERT(!strchr(m_pCompany, 'n'));
  145.     HX_ASSERT(!strchr(m_pCompany, ' '));
  146.     HX_ASSERT(!strchr(m_pCompany, 't'));
  147.     HX_ASSERT(!strchr(m_pCompany, '='));
  148.     HX_ASSERT(!strchr(m_pProduct, 'n'));
  149.     HX_ASSERT(!strchr(m_pProduct, ' '));
  150.     HX_ASSERT(!strchr(m_pProduct, 't'));
  151.     HX_ASSERT(!strchr(m_pProduct, '='));
  152.     
  153.     UINT32 nEstimatedSize = strlen ("HXPref_") + 
  154. 6 * 1 +   // for underscores
  155. strlen(m_pCompany) +
  156. strlen(m_pProduct) +
  157. 30; // 2 ints + fudge;
  158.     char *pTmp = new char[nEstimatedSize];
  159.     SafeSprintf(pTmp, nEstimatedSize, "HXPref_%s_%s_%d_%d_", 
  160.     (const char *)m_pCompany, (const char *)m_pProduct, m_nMajor, m_nMinor);
  161.     ret = pTmp;
  162.     HX_VECTOR_DELETE(pTmp);
  163. }
  164. void CUnixPref::ConstructPref(const char *pref,
  165.       CHXString &ret)
  166. {
  167.     HX_ASSERT(!strchr(m_pCompany, 'n'));
  168.     HX_ASSERT(!strchr(m_pCompany, ' '));
  169.     HX_ASSERT(!strchr(m_pCompany, 't'));
  170.     HX_ASSERT(!strchr(m_pCompany, '='));
  171.     HX_ASSERT(!strchr(m_pProduct, 'n'));
  172.     HX_ASSERT(!strchr(m_pProduct, ' '));
  173.     HX_ASSERT(!strchr(m_pProduct, 't'));
  174.     HX_ASSERT(!strchr(m_pProduct, '='));
  175.     
  176.     UINT32 nEstimatedSize = strlen ("HXPref_") + 
  177. 6 * 1 +   // for underscores
  178. strlen(m_RootKeyName) +
  179. strlen(m_pCompany) +
  180. strlen(m_pProduct) +
  181. strlen(pref) + 
  182. 30; // 2 ints + fudge;
  183.     char *pTmp = new char[nEstimatedSize];
  184.     if (strlen(m_RootKeyName))
  185.     {
  186. SafeSprintf(pTmp, nEstimatedSize, "HXPref_%s_%s_%s_%d_%d_%s", 
  187. m_RootKeyName, (const char *)m_pCompany, (const char *)m_pProduct, 
  188. m_nMajor, m_nMinor, pref);
  189.     }
  190.     else
  191.     {
  192. SafeSprintf(pTmp, nEstimatedSize, "HXPref_%s_%s_%d_%d_%s", 
  193. (const char *)m_pCompany, (const char *)m_pProduct, 
  194. m_nMajor, m_nMinor, pref);
  195.     }
  196.     ret = pTmp;
  197.     HX_VECTOR_DELETE(pTmp);
  198. }
  199. void CUnixPref::ConstructPrefAssignment(const char *pref,
  200. const char *pValue,
  201. CHXString &ret,
  202.                                         BOOL bEscapeValue)
  203. {
  204.     HX_ASSERT(!strchr(m_pCompany, 'n'));
  205.     HX_ASSERT(!strchr(m_pCompany, ' '));
  206.     HX_ASSERT(!strchr(m_pCompany, 't'));
  207.     HX_ASSERT(!strchr(m_pCompany, '='));
  208.     HX_ASSERT(!strchr(m_pProduct, 'n'));
  209.     HX_ASSERT(!strchr(m_pProduct, ' '));
  210.     HX_ASSERT(!strchr(m_pProduct, 't'));
  211.     HX_ASSERT(!strchr(m_pProduct, '='));
  212.     char *pEscapedValue = NULL;
  213.     
  214.     if (bEscapeValue)
  215.     {
  216.         EscapeNewLine(pValue, pEscapedValue);
  217.     }
  218.     UINT32 nEstimatedSize = strlen ("HXPref_") + 
  219. 6 * 1 +   // for underscores
  220. strlen(m_RootKeyName) +
  221. strlen(m_pCompany) +
  222. strlen(m_pProduct) +
  223. strlen(pref) + 
  224. strlen(pEscapedValue ? pEscapedValue : pValue) +
  225. 30; // 2 ints + fudge;
  226.     char *pTmp = new char[nEstimatedSize];
  227.     if (strlen (m_RootKeyName))
  228.     {
  229. SafeSprintf(pTmp, nEstimatedSize, "HXPref_%s_%s_%s_%d_%d_%s=%s", 
  230. m_RootKeyName, (const char *)m_pCompany, (const char *)m_pProduct, 
  231. m_nMajor, m_nMinor, pref, 
  232. pEscapedValue? pEscapedValue :pValue);
  233.     }
  234.     else
  235.     {
  236. SafeSprintf(pTmp, nEstimatedSize, "HXPref_%s_%s_%d_%d_%s=%s", 
  237. (const char *)m_pCompany, (const char *)m_pProduct, 
  238. m_nMajor, m_nMinor, pref, 
  239. pEscapedValue? pEscapedValue :pValue);
  240.     }
  241.     ret = pTmp;
  242.     HX_VECTOR_DELETE(pTmp);
  243.     HX_VECTOR_DELETE(pEscapedValue);
  244. }
  245. HX_RESULT CUnixPref::read_pref(const char* pPrefKey, IHXBuffer*& pBuffer)
  246. {
  247.     pBuffer = NULL;
  248.     CHXString key;
  249.     ConstructPref(pPrefKey, key);
  250.     char *value;
  251.     if ((value = (char*)CIGetenv(key)))
  252.     {
  253. char *pUnescapedValue = NULL;
  254. UnescapeNewLine(value, pUnescapedValue);
  255. pBuffer = new CHXBuffer();
  256. pBuffer->AddRef();
  257. if (pUnescapedValue)
  258. {
  259.     pBuffer->Set((UCHAR*)pUnescapedValue, strlen(pUnescapedValue) + 1);
  260. }
  261. else
  262. {
  263.     pBuffer->Set((UCHAR*)value, strlen(value) + 1);
  264. }
  265. HX_VECTOR_DELETE(pUnescapedValue);
  266.     }
  267.     return pBuffer ? HXR_OK : HXR_FAIL;
  268. }
  269. HX_RESULT CUnixPref::write_pref(const char* pPrefKey, IHXBuffer* pBuffer)
  270. {
  271.     m_bWrite = TRUE;
  272.     CHXString key;
  273.     ConstructPref(pPrefKey, key);
  274.     key += "=";
  275.     char *pStringToBeDeleted = NULL;
  276.     
  277.     for (char ** ppEnv = environ ; *ppEnv ; ++ppEnv)
  278.     {
  279. if (!strnicmp(*ppEnv, key, strlen(key)))
  280. {
  281.     pStringToBeDeleted = *ppEnv;
  282.     break;
  283. }
  284.     }
  285.     
  286.     if (pBuffer)
  287.     {
  288. CHXString pValue = (const char *)(pBuffer->GetBuffer());
  289. ConstructPrefAssignment(pPrefKey, pValue, key, TRUE);
  290.         CIPutenv(key);
  291.     }
  292.     else
  293.     {
  294. CHXString oldKey;
  295. ConstructPref(pPrefKey, oldKey);
  296. CIUnsetEnv(oldKey);  
  297.     }
  298.     
  299.     if (pStringToBeDeleted)
  300.     {
  301. HX_VECTOR_DELETE(pStringToBeDeleted);
  302.     }
  303.     return HXR_OK;
  304. }
  305.     
  306. /* commit_prefs saves all changes to the prefs to disk (e.g. on Unix) */ 
  307. HX_RESULT CUnixPref::commit_prefs()
  308. {
  309.     if (!m_bWrite)
  310.     {
  311. return HXR_OK;
  312.     }
  313. #ifndef _VXWORKS
  314.     // if any new prefs were written, write prefs
  315.     // open for writing
  316.     mFile =  ::fopen ( m_pPath, "w");
  317.     if (!mFile)
  318.     {
  319. mFile = ::fopen( m_pPath, "w+");
  320.     }
  321.     
  322.     // try to create it
  323.     if (mFile)
  324.     {
  325. /* change permissions to allow everyone to read the file 
  326.  * and owner/group to write only if I have to create this file
  327.  */
  328. /* PJG:  why does everyone get the right to read my prefs?  What about my MRU list? :) */
  329. #if !defined(_VXWORKS) && !defined(_BEOS)
  330. mFileID = fileno(mFile);
  331. fchmod( mFileID, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP );
  332. #endif
  333.     }
  334.     
  335.     if (mFile)
  336.     {
  337. mFileID = fileno(mFile);
  338. CHXString prefFamily;
  339. CHXString areLoadedPref;
  340. ConstructPref(ARE_PREFS_LOADED_PREF, areLoadedPref);
  341. UINT32 nAreLoadedPrefLen = strlen(areLoadedPref);
  342. ConstructFamily(prefFamily);
  343. UINT32 nPrefFamilyLen = strlen(prefFamily);
  344. for (char **ppEnv = environ ; *ppEnv ; ++ppEnv)
  345. {
  346.     if (!strnicmp(prefFamily, *ppEnv, nPrefFamilyLen))
  347.     {
  348. if (strnicmp(areLoadedPref, *ppEnv, nAreLoadedPrefLen)) // don't write out the placeholder
  349. {
  350.     fprintf(mFile, "%sn", *ppEnv + nPrefFamilyLen);
  351. }
  352.     }
  353. }
  354.     }
  355.     else
  356.     {
  357. #ifdef _DEBUG
  358. fprintf(stderr,"Can't open file to write prefs: %s.n", m_pPath);
  359. #endif
  360.     }
  361.     
  362.     if (mFile > 0) 
  363.     {
  364. ::fclose(mFile);       
  365. mFile = NULL;
  366. mFileID = -1;
  367.     }
  368.     // Remove file if it has zero length
  369.     struct stat stat_buf;
  370.     int err = stat(m_pPath, &stat_buf);
  371.     if ( !err && stat_buf.st_size == 0 )
  372.     {
  373. // if file is empty, delete the file.
  374. unlink(m_pPath);
  375.     }
  376. #endif
  377.     m_bWrite = FALSE;
  378.     return HXR_OK;
  379. }
  380. /////////////////////////////////////////////////////////////////////////////
  381. //  call open_pref() to automatically create the correct UNIX specific 
  382. // preference object.    
  383. //
  384. CUnixPref * CUnixPref::open_pref(
  385. const char* pCompanyName, 
  386. const char* pProductName, 
  387. int nProdMajorVer, 
  388. int nProdMinorVer)
  389. {
  390.     CUnixPref *cp =  new CUnixPref(
  391. pCompanyName, 
  392. pProductName, 
  393. nProdMajorVer, 
  394. nProdMinorVer);
  395.     if (!SUCCEEDED(cp->last_error())) {
  396. delete cp;
  397. cp = NULL;
  398.     }
  399.     return cp;
  400. }
  401. /////////////////////////////////////////////////////////////////////////////
  402. //  Constructor NOTE: use open_pref() to create an instance of this class
  403. //
  404. CUnixPref::CUnixPref(
  405.     const char* pCompanyName, 
  406.     const char* pProductName, 
  407.     int nProdMajorVer, 
  408.     int nProdMinorVer)
  409. {   
  410.     m_pPath = NULL;
  411.     mFile = NULL;
  412.     mFileID = -1;
  413.     mLastError = HXR_OK;
  414.     m_bWrite = FALSE;
  415.     m_RootKeyName[0] = '';
  416.     init_pref( pCompanyName,pProductName,nProdMajorVer,nProdMinorVer);          
  417. }
  418. /////////////////////////////////////////////////////////////////////////////
  419. //  class destructor 
  420. CUnixPref::~CUnixPref (void)
  421. {
  422.     commit_prefs();
  423.     HX_VECTOR_DELETE(m_pPath);
  424. }
  425. /*  delete_pref deletes the preference specified by Key from the Buffer. */                                                                             
  426. HX_RESULT CUnixPref::delete_pref(const char* pPrefKey)
  427. {   
  428.     return write_pref(pPrefKey, NULL);
  429. }
  430. /////////////////////////////////////////////////////////////////////////////
  431. //   init opens pref file if found, otherwise it creates it;
  432. //   reads the pref file into an internal buffer.
  433. //
  434. HX_RESULT CUnixPref::init_pref( 
  435.             const char* pCompanyName, 
  436.             const char* pProductName, 
  437.             int nProdMajorVer, 
  438.             int nProdMinorVer)
  439. {
  440.     m_nMajor = nProdMajorVer;
  441.     m_nMinor = nProdMinorVer;
  442.     m_pCompany = FixupCompany(pCompanyName);
  443.     m_pProduct = pProductName;
  444.     
  445.     HX_RESULT theErr = HXR_OK;
  446.     char  stmp[32]; /* Flawfinder: ignore */
  447. #if defined(_SUN) || defined(_HPUX)
  448.     char        rcPath[ _POSIX_PATH_MAX ]; /* Flawfinder: ignore */
  449.     CUnixPrefUtils::GetPrefPath(rcPath, PATH_MAX, pCompanyName);
  450. #else
  451.     char        rcPath[ PATH_MAX ]; /* Flawfinder: ignore */
  452.     CUnixPrefUtils::GetPrefPath(rcPath, PATH_MAX, pCompanyName);
  453. #endif
  454. #ifndef _VXWORKS
  455. #if defined(_BEOS)
  456.     SafeStrCat( rcPath, "/", sizeof(rcPath));
  457. #else
  458.     //::strcat( rcPath, "/." );
  459.     SafeStrCat( rcPath, "/", sizeof(rcPath));  //Note that the "." has been removed. Files no longuer start with "."
  460. #endif /* _BEOS */
  461.     if ( pProductName )
  462.     {
  463. SafeStrCat( rcPath, pProductName, sizeof(rcPath));
  464. // remove any , or space
  465.      char * pComa = (char*) HXFindChar(rcPath, ',');
  466.      if(pComa)
  467.      {
  468.            *pComa = 0;
  469.      }
  470.      pComa = (char*) HXFindChar(rcPath, ' ');
  471.      if(pComa)
  472.      {
  473.            *pComa = 0;
  474.      }
  475. SafeStrCat( rcPath, "_", sizeof(rcPath));
  476.     }
  477.     ::sprintf(stmp, "%d_%d", nProdMajorVer,nProdMinorVer); /* Flawfinder: ignore */
  478.     SafeStrCat(rcPath, stmp, sizeof(rcPath));
  479.     m_pPath = new char[ ::strlen( rcPath ) + 1 ];
  480.     strcpy( m_pPath, rcPath ); /* Flawfinder: ignore */
  481.     // we're done now if the environment has been primed
  482.     CHXString prefTester ;
  483.     ConstructPref("ArePrefsLoaded", prefTester);
  484.     if (CIGetenv(prefTester))
  485.     {
  486. return HXR_OK; // already loaded :)
  487.     }
  488.     // open pref file for reading and writing; if it doesn't exist
  489.     // create one.
  490.     if ( (mFile = fopen ( m_pPath, "r"))  == NULL )
  491.     {
  492. #ifdef _DEBUG
  493. fprintf(stderr,"Can't open file: %s.n", m_pPath);
  494. #endif
  495.     }
  496.     else
  497.     {
  498. mFileID = fileno(mFile);
  499.     }
  500. #endif /* _VXWORKS */
  501.     
  502.     IHXBuffer* buf = new CHXBuffer((UCHAR*)(new_string("1")), 2);
  503.     buf->AddRef();
  504.     write_pref(ARE_PREFS_LOADED_PREF, buf);
  505.     buf->Release();
  506. #ifndef _VXWORKS
  507.     if (!theErr && mFile > 0)
  508.     {
  509. // Read the contents of the file into memory.
  510. size_t lNumTotalRead = 0;
  511. struct stat stat_buf;
  512. char* pfile_data = 0;
  513. int err = stat(m_pPath, &stat_buf);
  514. if ( !err && stat_buf.st_size > 0 )
  515. {
  516.     pfile_data = new char [ stat_buf.st_size + 10];
  517.     size_t  lNumRead = 1;
  518.     while (!feof(mFile))
  519.     {
  520. lNumRead =  fread(pfile_data+lNumTotalRead, 1, 16000, mFile);
  521. if (lNumRead > 0)
  522. {
  523.     lNumTotalRead += lNumRead;
  524. }
  525. else
  526. {
  527.     break;
  528. }
  529.     }
  530.             pfile_data[lNumTotalRead] = '';
  531.     HX_ASSERT(lNumTotalRead <= stat_buf.st_size);
  532. }
  533. // Now break the data into lines delimited by newlines, and then
  534. // break those strings up into name/value pairs.
  535. if ( lNumTotalRead > 0 && stat_buf.st_size > 0 )
  536. {
  537.     char* snl = 0;
  538.     char* seq = 0;
  539.     char* sname= 0;
  540.     char* svalue= 0;
  541.     char* stmp = pfile_data;
  542.     int name_len = 0;
  543.     snl = strtok( stmp, "n");
  544.     while( snl )
  545.     {
  546. // now break up each line into name/value pairs...
  547. seq = strstr( snl, "=" );
  548. if(seq)
  549. {
  550.     name_len = seq-snl;
  551.     char* keyname = new char [name_len+1];
  552.     strncpy( keyname, snl, name_len); /* Flawfinder: ignore */
  553.     keyname[name_len] = '';
  554.     char* lwr = new char[strlen(keyname) + 1];
  555.     strcpy(lwr, keyname); /* Flawfinder: ignore */
  556.     seq++;
  557.     
  558.     // if we find in environ already, ignore
  559.     IHXBuffer *pBuffer = NULL;
  560.     if (HXR_OK ==read_pref(lwr, pBuffer))
  561.     {
  562. pBuffer->Release();
  563.     }
  564.     else
  565.     {
  566. CHXString assn;
  567. ConstructPrefAssignment(lwr, seq, assn, FALSE);
  568. HX_VERIFY(-1 != CIPutenv(assn));
  569.     }
  570.     HX_VECTOR_DELETE(keyname);
  571.     HX_VECTOR_DELETE(lwr);
  572. }
  573. snl = strtok( NULL, "n");
  574.     }
  575. }
  576. HX_VECTOR_DELETE(pfile_data);
  577.     }
  578.     if ( mFile )
  579.     {
  580. // unlock the file 
  581.         ::fclose( mFile );
  582.         mFile = NULL;
  583. mFileID = -1;
  584.     }
  585. #endif /* _VXWORKS */
  586.     m_bWrite = FALSE;      // we use write_pref internally, but we don't want to consider our
  587.                            // database to be modified at this point.
  588.     mLastError = theErr;
  589.     return theErr;      
  590. }
  591. HX_RESULT CUnixPref::remove_pref(const char* pPrefKey)
  592. {
  593.     return write_pref(pPrefKey, NULL);
  594. }
  595. HX_RESULT CUnixPref::remove_indexed_pref(const char* pPrefKey)
  596. {
  597.     return HXR_NOTIMPL;
  598. }
  599. //
  600. // Access a preferences file subtree by appending a string to the Root
  601. // Key.  
  602. //
  603. HX_RESULT CUnixPref::BeginSubPref(const char* szSubPref)
  604. {
  605.     HX_ASSERT((strlen(m_RootKeyName) + 1 + strlen(szSubPref) + 1) <= _MAX_KEY);
  606.     // Just add sub-pref to the root key name
  607.     SafeStrCat(m_RootKeyName,"\", _MAX_KEY);
  608.     SafeStrCat(m_RootKeyName,szSubPref, _MAX_KEY);
  609.     return HXR_OK;
  610. }
  611. HX_RESULT CUnixPref::EndSubPref()
  612. {
  613.     // Find the  character from the end of the string
  614.     char* pSlash = HXReverseFindChar(m_RootKeyName,'\');
  615.     // if we find the  character we NULL terminate at this point removing the last sub-pref added
  616.     if (pSlash)
  617.     {
  618. *pSlash = '';
  619. return HXR_OK;
  620.     }
  621.     else
  622. return HXR_FAIL;
  623. }
  624. //
  625. // Return the value of subkey number nIndex under the current m_RootKeyName.
  626. //
  627. HX_RESULT CUnixPref::GetPrefKey(UINT32 nIndex, IHXBuffer*& pBuffer)
  628. {
  629.     UINT32  i;         // index of the current subkey
  630.     POSITION mapPosition = NULL;
  631.     CHXString key;
  632.     HX_RESULT result = HXR_FAIL;
  633.     CHXString prefFamily;
  634.     ConstructFamily(prefFamily);
  635.     UINT32 nPrefFamilyLen = strlen(prefFamily);
  636.     
  637.     UINT32 counter = 0;
  638.     
  639.     for (char **ppEnv = environ ; *ppEnv ; ++ppEnv)
  640.     {
  641. if (!strnicmp(prefFamily, *ppEnv, nPrefFamilyLen))
  642. {
  643.     // make sure this isn't the head of the family
  644.     if ('=' == (*ppEnv)[nPrefFamilyLen])
  645. continue;
  646.     
  647.     if (counter == nIndex)
  648.     {
  649. char *value = (*ppEnv) + nPrefFamilyLen + 1;
  650.                 char *ueValue = NULL;
  651.                 UnescapeNewLine(value, ueValue); 
  652. pBuffer = new CHXBuffer;
  653. pBuffer->AddRef();
  654. pBuffer->Set((UCHAR*)(ueValue? ueValue : value), strlen(ueValue ? ueValue : value) + 1);
  655.                 HX_VECTOR_DELETE(ueValue);
  656. return HXR_OK;
  657.     }
  658.     counter++;
  659. }
  660.     }
  661.     
  662.     return HXR_FAIL;
  663. }
  664. BOOL
  665. CUnixPref::EscapeNewLine(const char* pLine, char*& pTmpOutLine)
  666. {
  667.     char    hexBuf[3] = {0}; /* Flawfinder: ignore */
  668.     pTmpOutLine = NULL;
  669.     char* pOutLine = NULL;
  670.     const char* pInputLine = pLine;
  671.     while (*pLine)
  672.     {
  673. // escape n, = and %
  674.         if (*pLine == 'n' || *pLine == '=' || *pLine == '%')
  675.         {
  676.     if (!pOutLine)
  677.     {
  678.         pTmpOutLine = pOutLine = new char[strlen(pInputLine) * 3 + 1];
  679. *pOutLine = '';
  680. strncpy(pOutLine, pInputLine, pLine - pInputLine); /* Flawfinder: ignore */
  681. pOutLine += pLine - pInputLine;
  682.     }
  683.     sprintf(hexBuf,"%02x", (UCHAR)*pLine); /* Flawfinder: ignore */
  684.     *pOutLine++ = '%';
  685.     *pOutLine++ = hexBuf[0];
  686.     *pOutLine++ = hexBuf[1];
  687.         }
  688. else if (pOutLine)
  689. {
  690.     *pOutLine++ = *pLine;
  691. }
  692. pLine++;
  693.     }
  694.     if (pOutLine) *pOutLine = '';
  695.     return (pOutLine ? TRUE : FALSE);
  696. }
  697. BOOL
  698. CUnixPref::UnescapeNewLine(const char* pLine, char*& pTmpOutLine)
  699. {
  700.     char    hexBuf[3] = {0}; /* Flawfinder: ignore */
  701.     pTmpOutLine = NULL;
  702.     char* pOutLine = NULL;
  703.     const char* pInputLine = pLine;
  704.     while (*pLine)
  705.     {
  706.         if (*pLine == '%')
  707.         {
  708.     if (!pOutLine)
  709.     {
  710.         pTmpOutLine = pOutLine = new char[strlen(pInputLine)+1];
  711. *pOutLine = '';
  712. strncpy(pOutLine, pInputLine, pLine - pInputLine); /* Flawfinder: ignore */
  713. pOutLine += pLine - pInputLine;
  714.     }
  715.             char hexBuf[3]; /* Flawfinder: ignore */
  716.     if(pLine[1] &&    // check for overbound condition
  717.        pLine[2])
  718.     {
  719.         pLine++;  // walk past '%'
  720.         hexBuf[0] = *pLine++;
  721.         hexBuf[1] = *pLine;
  722.         hexBuf[2] = '';
  723.         *pOutLine++ = (char)strtol(hexBuf, NULL, 16);
  724.        }
  725.         }
  726. else if (pOutLine)
  727. {
  728.     *pOutLine++ = *pLine;
  729. }
  730. pLine++;
  731.     }
  732.     if (pOutLine) *pOutLine = '';
  733.     return (pOutLine ? TRUE : FALSE);
  734. }