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

Symbian

开发平台:

C/C++

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