📄 unix_pref.cpp
字号:
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
*
* The contents of this file, and the files included with this file, are
* subject to the current version of the RealNetworks Public Source License
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
* in which case the RCSL will apply. You may also obtain the license terms
* directly from RealNetworks. You may not use this file except in
* compliance with the RPSL or, if you have a valid RCSL with RealNetworks
* applicable to this file, the RCSL. Please see the applicable RPSL or
* RCSL for the rights, obligations and limitations governing use of the
* contents of the file.
*
* This file is part of the Helix DNA Technology. RealNetworks is the
* developer of the Original Code and owns the copyrights in the portions
* it created.
*
* This file, and the files included with this file, is distributed and made
* available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
*
* Technology Compatibility Kit Test Suite(s) Location:
* http://www.helixcommunity.org/content/tck
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
#ifdef _BEOS
#include <Path.h>
#include <FindDirectory.h>
#endif
#include <string.h>
#include <unistd.h>
#ifndef _VXWORKS
#include <strings.h>
#include <sys/uio.h>
#include <sys/file.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/stat.h>
#include <ctype.h>
#include <errno.h>
#include "hxslist.h"
#include "hxmap.h"
#include "hxtypes.h"
#include "hxresult.h"
#include "hxheap.h"
#include "hxstrutl.h"
#include "hxcom.h"
#include "ihxpckts.h"
#include "chxpckts.h"
#include "unix_pref.h"
#include "dbcs.h" // HXReverseFindChar prototype
#include "unix_misc.h"
#include "cunixprefutils.h"
#define ARE_PREFS_LOADED_PREF "ArePrefsLoaded"
extern char** environ;
static CHXString FixupCompany (const char *pCompany)
{
char *pTmpCompany = new_string(pCompany);
char *pos = strchr(pTmpCompany, ',');
if (pos) *pos = 0;
strlwr(pTmpCompany);
CHXString ret = pTmpCompany;
HX_VECTOR_DELETE(pTmpCompany);
return ret;
}
static char *CIGetenv(const char *pKey)
{
UINT32 keylen = strlen(pKey);
char *pArr = new char[keylen + 2];
sprintf(pArr, "%s=", pKey); /* Flawfinder: ignore */
for (char **ppEnv = environ ; *ppEnv ; ++ppEnv)
{
if (!strnicmp(*ppEnv, pArr, keylen +1))
{
HX_VECTOR_DELETE(pArr);
return *ppEnv + keylen + 1;
}
}
HX_VECTOR_DELETE(pArr);
return NULL;
}
static int CIPutenv(const char *pKey)
{
char *pNewVal = new_string(pKey);
char *pEquals = strchr(pNewVal, '=');
HX_ASSERT(pEquals);
if (pEquals)
{
*pEquals = '\0';
strlwr(pNewVal);
*pEquals = '=';
}
return putenv(pNewVal);
}
static void CIUnsetEnv(const char *pKey)
{
unsigned int keylen = strlen(pKey);
char *pArr = new char[keylen + 2];
sprintf(pArr, "%s=", pKey); /* Flawfinder: ignore */
for (char **ppEnv = environ ; *ppEnv ; ++ppEnv)
{
if (!strnicmp(*ppEnv, pArr, keylen +1))
{
//delete [] *ppEnv; // pjg all uses of this delete the string
while (*ppEnv)
{
*ppEnv = *(ppEnv+1);
ppEnv++;
}
HX_VECTOR_DELETE(pArr);
return;
}
}
HX_VECTOR_DELETE(pArr);
}
void CUnixPref::ConstructFamily(CHXString &ret)
{
HX_ASSERT(!strchr(m_pCompany, '\n'));
HX_ASSERT(!strchr(m_pCompany, ' '));
HX_ASSERT(!strchr(m_pCompany, '\t'));
HX_ASSERT(!strchr(m_pCompany, '='));
HX_ASSERT(!strchr(m_pProduct, '\n'));
HX_ASSERT(!strchr(m_pProduct, ' '));
HX_ASSERT(!strchr(m_pProduct, '\t'));
HX_ASSERT(!strchr(m_pProduct, '='));
UINT32 nEstimatedSize = strlen ("HXPref_") +
6 * 1 + // for underscores
strlen(m_pCompany) +
strlen(m_pProduct) +
30; // 2 ints + fudge;
char *pTmp = new char[nEstimatedSize];
SafeSprintf(pTmp, nEstimatedSize, "HXPref_%s_%s_%d_%d_",
(const char *)m_pCompany, (const char *)m_pProduct, m_nMajor, m_nMinor);
ret = pTmp;
HX_VECTOR_DELETE(pTmp);
}
void CUnixPref::ConstructPref(const char *pref,
CHXString &ret)
{
HX_ASSERT(!strchr(m_pCompany, '\n'));
HX_ASSERT(!strchr(m_pCompany, ' '));
HX_ASSERT(!strchr(m_pCompany, '\t'));
HX_ASSERT(!strchr(m_pCompany, '='));
HX_ASSERT(!strchr(m_pProduct, '\n'));
HX_ASSERT(!strchr(m_pProduct, ' '));
HX_ASSERT(!strchr(m_pProduct, '\t'));
HX_ASSERT(!strchr(m_pProduct, '='));
UINT32 nEstimatedSize = strlen ("HXPref_") +
6 * 1 + // for underscores
strlen(m_RootKeyName) +
strlen(m_pCompany) +
strlen(m_pProduct) +
strlen(pref) +
30; // 2 ints + fudge;
char *pTmp = new char[nEstimatedSize];
if (strlen(m_RootKeyName))
{
SafeSprintf(pTmp, nEstimatedSize, "HXPref_%s_%s_%s_%d_%d_%s",
m_RootKeyName, (const char *)m_pCompany, (const char *)m_pProduct,
m_nMajor, m_nMinor, pref);
}
else
{
SafeSprintf(pTmp, nEstimatedSize, "HXPref_%s_%s_%d_%d_%s",
(const char *)m_pCompany, (const char *)m_pProduct,
m_nMajor, m_nMinor, pref);
}
ret = pTmp;
HX_VECTOR_DELETE(pTmp);
}
void CUnixPref::ConstructPrefAssignment(const char *pref,
const char *pValue,
CHXString &ret,
BOOL bEscapeValue)
{
HX_ASSERT(!strchr(m_pCompany, '\n'));
HX_ASSERT(!strchr(m_pCompany, ' '));
HX_ASSERT(!strchr(m_pCompany, '\t'));
HX_ASSERT(!strchr(m_pCompany, '='));
HX_ASSERT(!strchr(m_pProduct, '\n'));
HX_ASSERT(!strchr(m_pProduct, ' '));
HX_ASSERT(!strchr(m_pProduct, '\t'));
HX_ASSERT(!strchr(m_pProduct, '='));
char *pEscapedValue = NULL;
if (bEscapeValue)
{
EscapeNewLine(pValue, pEscapedValue);
}
UINT32 nEstimatedSize = strlen ("HXPref_") +
6 * 1 + // for underscores
strlen(m_RootKeyName) +
strlen(m_pCompany) +
strlen(m_pProduct) +
strlen(pref) +
strlen(pEscapedValue ? pEscapedValue : pValue) +
30; // 2 ints + fudge;
char *pTmp = new char[nEstimatedSize];
if (strlen (m_RootKeyName))
{
SafeSprintf(pTmp, nEstimatedSize, "HXPref_%s_%s_%s_%d_%d_%s=%s",
m_RootKeyName, (const char *)m_pCompany, (const char *)m_pProduct,
m_nMajor, m_nMinor, pref,
pEscapedValue? pEscapedValue :pValue);
}
else
{
SafeSprintf(pTmp, nEstimatedSize, "HXPref_%s_%s_%d_%d_%s=%s",
(const char *)m_pCompany, (const char *)m_pProduct,
m_nMajor, m_nMinor, pref,
pEscapedValue? pEscapedValue :pValue);
}
ret = pTmp;
HX_VECTOR_DELETE(pTmp);
HX_VECTOR_DELETE(pEscapedValue);
}
HX_RESULT CUnixPref::read_pref(const char* pPrefKey, IHXBuffer*& pBuffer)
{
pBuffer = NULL;
CHXString key;
ConstructPref(pPrefKey, key);
char *value;
if ((value = (char*)CIGetenv(key)))
{
char *pUnescapedValue = NULL;
UnescapeNewLine(value, pUnescapedValue);
pBuffer = new CHXBuffer();
pBuffer->AddRef();
if (pUnescapedValue)
{
pBuffer->Set((UCHAR*)pUnescapedValue, strlen(pUnescapedValue) + 1);
}
else
{
pBuffer->Set((UCHAR*)value, strlen(value) + 1);
}
HX_VECTOR_DELETE(pUnescapedValue);
}
return pBuffer ? HXR_OK : HXR_FAIL;
}
HX_RESULT CUnixPref::write_pref(const char* pPrefKey, IHXBuffer* pBuffer)
{
m_bWrite = TRUE;
CHXString key;
ConstructPref(pPrefKey, key);
key += "=";
char *pStringToBeDeleted = NULL;
for (char ** ppEnv = environ ; *ppEnv ; ++ppEnv)
{
if (!strnicmp(*ppEnv, key, strlen(key)))
{
pStringToBeDeleted = *ppEnv;
break;
}
}
if (pBuffer)
{
CHXString pValue = (const char *)(pBuffer->GetBuffer());
ConstructPrefAssignment(pPrefKey, pValue, key, TRUE);
CIPutenv(key);
}
else
{
CHXString oldKey;
ConstructPref(pPrefKey, oldKey);
CIUnsetEnv(oldKey);
}
if (pStringToBeDeleted)
{
HX_VECTOR_DELETE(pStringToBeDeleted);
}
return HXR_OK;
}
/* commit_prefs saves all changes to the prefs to disk (e.g. on Unix) */
HX_RESULT CUnixPref::commit_prefs()
{
if (!m_bWrite)
{
return HXR_OK;
}
#ifndef _VXWORKS
// if any new prefs were written, write prefs
// open for writing
mFile = ::fopen ( m_pPath, "w");
if (!mFile)
{
mFile = ::fopen( m_pPath, "w+");
}
// try to create it
if (mFile)
{
/* change permissions to allow everyone to read the file
* and owner/group to write only if I have to create this file
*/
/* PJG: why does everyone get the right to read my prefs? What about my MRU list? :) */
#if !defined(_VXWORKS) && !defined(_BEOS)
mFileID = fileno(mFile);
fchmod( mFileID, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP );
#endif
}
if (mFile)
{
mFileID = fileno(mFile);
CHXString prefFamily;
CHXString areLoadedPref;
ConstructPref(ARE_PREFS_LOADED_PREF, areLoadedPref);
UINT32 nAreLoadedPrefLen = strlen(areLoadedPref);
ConstructFamily(prefFamily);
UINT32 nPrefFamilyLen = strlen(prefFamily);
for (char **ppEnv = environ ; *ppEnv ; ++ppEnv)
{
if (!strnicmp(prefFamily, *ppEnv, nPrefFamilyLen))
{
if (strnicmp(areLoadedPref, *ppEnv, nAreLoadedPrefLen)) // don't write out the placeholder
{
fprintf(mFile, "%s\n", *ppEnv + nPrefFamilyLen);
}
}
}
}
else
{
#ifdef _DEBUG
fprintf(stderr,"Can't open file to write prefs: %s.\n", m_pPath);
#endif
}
if (mFile > 0)
{
::fclose(mFile);
mFile = NULL;
mFileID = -1;
}
// Remove file if it has zero length
struct stat stat_buf;
int err = stat(m_pPath, &stat_buf);
if ( !err && stat_buf.st_size == 0 )
{
// if file is empty, delete the file.
unlink(m_pPath);
}
#endif
m_bWrite = FALSE;
return HXR_OK;
}
/////////////////////////////////////////////////////////////////////////////
// call open_pref() to automatically create the correct UNIX specific
// preference object.
//
CUnixPref * CUnixPref::open_pref(
const char* pCompanyName,
const char* pProductName,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -