diff --git a/Source/kwsys/Registry.cxx b/Source/kwsys/Registry.cxx index 4330967f3..245e3ef2f 100644 --- a/Source/kwsys/Registry.cxx +++ b/Source/kwsys/Registry.cxx @@ -38,7 +38,7 @@ public: virtual ~RegistryHelper(); // Read a value from the registry. - virtual bool ReadValue(const char *key, char *value); + virtual bool ReadValue(const char *key, const char **value); // Delete a key from the registry. virtual bool DeleteKey(const char *key); @@ -68,6 +68,10 @@ public: void SetGlobalScope(bool b); bool GetGlobalScope(); + kwsys_stl::string EncodeKey(const char* str); + kwsys_stl::string EncodeValue(const char* str); + kwsys_stl::string DecodeValue(const char* str); + protected: bool m_Changed; kwsys_stl::string m_TopLevel; @@ -79,13 +83,14 @@ protected: // Strip trailing and ending spaces. char *Strip(char *str); void SetSubKey(const char* sk); - char *CreateKey(const char *key); + kwsys_stl::string CreateKey(const char *key); typedef kwsys_stl::map StringToStringMap; StringToStringMap EntriesMap; kwsys_stl::string m_SubKey; bool m_Empty; bool m_SubKeySpecified; + kwsys_stl::string m_HomeDirectory; Registry::RegistryType m_RegistryType; }; @@ -191,7 +196,7 @@ bool Registry::Close() //---------------------------------------------------------------------------- bool Registry::ReadValue(const char *subkey, const char *key, - char *value) + const char **value) { *value = 0; bool res = true; @@ -388,16 +393,21 @@ bool RegistryHelper::Open(const char *toplevel, const char *subkey, return (res != 0); } #endif - if ( m_RegistryType == Registry::UNIX_REGISTRY ) + if ( m_RegistryType == Registry::FILE_REGISTRY ) { bool res = false; int cc; kwsys_ios::ostringstream str; - if ( !getenv("HOME") ) + const char* homeDirectory; + if ( (homeDirectory = getenv("HOME")) == 0 ) { - return false; + if ( (homeDirectory = getenv("USERPROFILE")) == 0 ) + { + return false; + } } - str << getenv("HOME") << "/." << toplevel << "rc"; + m_HomeDirectory = homeDirectory; + str << m_HomeDirectory << "/." << toplevel << "rc"; if ( readonly == Registry::READWRITE ) { kwsys_ios::ofstream ofs( str.str().c_str(), kwsys_ios::ios::out|kwsys_ios::ios::app ); @@ -450,7 +460,7 @@ bool RegistryHelper::Open(const char *toplevel, const char *subkey, char *value = line + cc + 1; char *nkey = this->Strip(key); char *nvalue = this->Strip(value); - this->EntriesMap[nkey] = nvalue; + this->EntriesMap[nkey] = this->DecodeValue(nvalue); m_Empty = 0; delete [] key; found = 1; @@ -477,7 +487,7 @@ bool RegistryHelper::Close() return (res != 0); } #endif - if ( m_RegistryType == Registry::UNIX_REGISTRY ) + if ( m_RegistryType == Registry::FILE_REGISTRY ) { if ( !m_Changed ) { @@ -490,11 +500,7 @@ bool RegistryHelper::Close() } kwsys_ios::ostringstream str; - if ( !getenv("HOME") ) - { - return false; - } - str << getenv("HOME") << "/." << this->GetTopLevel() << "rc"; + str << m_HomeDirectory << "/." << this->GetTopLevel() << "rc"; kwsys_ios::ofstream *ofs = new kwsys_ios::ofstream(str.str().c_str(), kwsys_ios::ios::out); if ( !ofs ) { @@ -507,7 +513,7 @@ bool RegistryHelper::Close() } *ofs << "# This file is automatically generated by the application" << kwsys_ios::endl << "# If you change any lines or add new lines, note that all" << kwsys_ios::endl - << "# coments and empty lines will be deleted. Every line has" << kwsys_ios::endl + << "# comments and empty lines will be deleted. Every line has" << kwsys_ios::endl << "# to be in format: " << kwsys_ios::endl << "# key = value" << kwsys_ios::endl << "#" << kwsys_ios::endl; @@ -535,58 +541,76 @@ bool RegistryHelper::Close() } //---------------------------------------------------------------------------- -bool RegistryHelper::ReadValue(const char *skey, char *value) +bool RegistryHelper::ReadValue(const char *skey, const char **value) { #ifdef _WIN32 if ( m_RegistryType == Registry::WIN32_REGISTRY) { + kwsys_stl::string key = this->CreateKey( skey ); + if ( key.empty() ) + { + return false; + } int res = 1; DWORD dwType, dwSize; dwType = REG_SZ; dwSize = Registry_BUFFER_SIZE; + char buffer[1024]; // Replace with RegQueryInfoKey res = ( RegQueryValueEx(this->HKey, skey, NULL, &dwType, - (BYTE *)value, &dwSize) == ERROR_SUCCESS ); - return (res != 0); - } -#endif - if ( m_RegistryType == Registry::UNIX_REGISTRY ) - { - bool res = false; - char *key = this->CreateKey( skey ); - if ( !key ) + (BYTE *)buffer, &dwSize) == ERROR_SUCCESS ); + if ( !res ) { return false; } + this->EntriesMap[key] = buffer; + RegistryHelper::StringToStringMap::iterator it + = this->EntriesMap.find(key); + *value = it->second.c_str(); + return true; + } +#endif + if ( m_RegistryType == Registry::FILE_REGISTRY ) + { + bool res = false; + kwsys_stl::string key = this->CreateKey( skey ); + if ( key.empty() ) + { + return false; + } + RegistryHelper::StringToStringMap::iterator it = this->EntriesMap.find(key); if ( it != this->EntriesMap.end() ) { - strcpy(value, it->second.c_str()); + *value = it->second.c_str(); res = true; } - delete [] key; return res; } return false; } //---------------------------------------------------------------------------- -bool RegistryHelper::DeleteKey(const char* key) +bool RegistryHelper::DeleteKey(const char* skey) { #ifdef _WIN32 if ( m_RegistryType == Registry::WIN32_REGISTRY) { int res = 1; - res = ( RegDeleteKey( this->HKey, key ) == ERROR_SUCCESS ); + res = ( RegDeleteKey( this->HKey, skey ) == ERROR_SUCCESS ); return (res != 0); } #endif - if ( m_RegistryType == Registry::UNIX_REGISTRY ) + if ( m_RegistryType == Registry::FILE_REGISTRY ) { - (void)key; - bool res = false; - return res; + kwsys_stl::string key = this->CreateKey( skey ); + if ( key.empty() ) + { + return false; + } + this->EntriesMap.erase(key); + return true; } return false; } @@ -602,15 +626,14 @@ bool RegistryHelper::DeleteValue(const char *skey) return (res != 0); } #endif - if ( m_RegistryType == Registry::UNIX_REGISTRY ) + if ( m_RegistryType == Registry::FILE_REGISTRY ) { - char *key = this->CreateKey( skey ); - if ( !key ) + kwsys_stl::string key = this->CreateKey( skey ); + if ( key.empty() ) { return false; } this->EntriesMap.erase(key); - delete [] key; return true; } return false; @@ -630,34 +653,32 @@ bool RegistryHelper::SetValue(const char *skey, const char *value) return (res != 0); } #endif - if ( m_RegistryType == Registry::UNIX_REGISTRY ) + if ( m_RegistryType == Registry::FILE_REGISTRY ) { - char *key = this->CreateKey( skey ); - if ( !key ) + kwsys_stl::string key = this->CreateKey( skey ); + if ( key.empty() ) { return 0; } - this->EntriesMap[key] = value; - delete [] key; + this->EntriesMap[key] = this->EncodeValue(value); return 1; } return false; } //---------------------------------------------------------------------------- -char *RegistryHelper::CreateKey( const char *key ) +kwsys_stl::string RegistryHelper::CreateKey( const char *key ) { - char *newkey; if ( !m_SubKeySpecified || m_SubKey.empty() || !key ) { - return 0; + return ""; } - int len = strlen(this->m_SubKey.c_str()) + strlen(key) + 1; - newkey = new char[ len+1 ] ; - ::sprintf(newkey, "%s\\%s", this->m_SubKey.c_str(), key); - return newkey; + kwsys_ios::ostringstream ostr; + ostr << this->EncodeKey(this->m_SubKey.c_str()) << "\\" << this->EncodeKey(key); + return ostr.str(); } +//---------------------------------------------------------------------------- void RegistryHelper::SetSubKey(const char* sk) { if ( !sk ) @@ -715,4 +736,74 @@ bool RegistryHelper::GetGlobalScope() return m_GlobalScope; } +//---------------------------------------------------------------------------- +kwsys_stl::string RegistryHelper::EncodeKey(const char* str) +{ + kwsys_ios::ostringstream ostr; + while ( *str ) + { + switch ( *str ) + { + case '%': case '=': case '\n': case '\r': case '\t': case ' ': + char buffer[4]; + sprintf(buffer, "%%%02X", *str); + ostr << buffer; + break; + default: + ostr << *str; + } + str ++; + } + return ostr.str(); +} + +//---------------------------------------------------------------------------- +kwsys_stl::string RegistryHelper::EncodeValue(const char* str) +{ + kwsys_ios::ostringstream ostr; + while ( *str ) + { + switch ( *str ) + { + case '%': case '=': case '\n': case '\r': case '\t': + char buffer[4]; + sprintf(buffer, "%%%02X", *str); + ostr << buffer; + break; + default: + ostr << *str; + } + str ++; + } + return ostr.str(); +} + +//---------------------------------------------------------------------------- +kwsys_stl::string RegistryHelper::DecodeValue(const char* str) +{ + kwsys_ios::ostringstream ostr; + while ( *str ) + { + int val; + switch ( *str ) + { + case '%': + if ( *(str+1) && *(str+2) && sscanf(str+1, "%x", &val) == 1 ) + { + ostr << (char)val; + str += 2; + } + else + { + ostr << *str; + } + break; + default: + ostr << *str; + } + str ++; + } + return ostr.str(); +} + } // namespace KWSYS_NAMESPACE diff --git a/Source/kwsys/Registry.hxx.in b/Source/kwsys/Registry.hxx.in index e9ca1e5e4..c0590f588 100644 --- a/Source/kwsys/Registry.hxx.in +++ b/Source/kwsys/Registry.hxx.in @@ -39,19 +39,19 @@ public: #ifdef _WIN32 WIN32_REGISTRY, #endif - UNIX_REGISTRY + FILE_REGISTRY }; #ifdef _WIN32 Registry(RegistryType registryType = WIN32_REGISTRY); #else - Registry(RegistryType registryType = UNIX_REGISTRY); + Registry(RegistryType registryType = FILE_REGISTRY); #endif virtual ~Registry(); //! Read a value from the registry. - bool ReadValue(const char *subkey, const char *key, char *value); + bool ReadValue(const char *subkey, const char *key, const char **value); //! Delete a key from the registry. bool DeleteKey(const char *subkey, const char *key); diff --git a/Source/kwsys/testRegistry.cxx b/Source/kwsys/testRegistry.cxx index 4f304d849..6906dac6b 100644 --- a/Source/kwsys/testRegistry.cxx +++ b/Source/kwsys/testRegistry.cxx @@ -53,14 +53,14 @@ int main(int, char**) IFT(reg.SetValue("TestSubkey", "TestKey3", "Test Value 3"), res); IFT(reg.SetValue("TestSubkey2", "TestKey4", "Test Value 4"), res); - char buffer[1024]; - IFT(reg.ReadValue("TestSubkey", "TestKey1", buffer), res); + const char *buffer; + IFT(reg.ReadValue("TestSubkey", "TestKey1", &buffer), res); CHE(buffer, "Test Value 1", res); - IFT(reg.ReadValue("TestSubkey1", "TestKey2", buffer), res); + IFT(reg.ReadValue("TestSubkey1", "TestKey2", &buffer), res); CHE(buffer, "Test Value 2", res); - IFT(reg.ReadValue("TestSubkey", "TestKey3", buffer), res); + IFT(reg.ReadValue("TestSubkey", "TestKey3", &buffer), res); CHE(buffer, "Test Value 3", res); - IFT(reg.ReadValue("TestSubkey2", "TestKey4", buffer), res); + IFT(reg.ReadValue("TestSubkey2", "TestKey4", &buffer), res); CHE(buffer, "Test Value 4", res); IFT(reg.SetValue("TestSubkey", "TestKey1", "New Test Value 1"), res); @@ -68,23 +68,32 @@ int main(int, char**) IFT(reg.SetValue("TestSubkey", "TestKey3", "New Test Value 3"), res); IFT(reg.SetValue("TestSubkey2", "TestKey4", "New Test Value 4"), res); - IFT(reg.ReadValue("TestSubkey", "TestKey1", buffer), res); + IFT(reg.ReadValue("TestSubkey", "TestKey1", &buffer), res); CHE(buffer, "New Test Value 1", res); - IFT(reg.ReadValue("TestSubkey1", "TestKey2", buffer), res); + IFT(reg.ReadValue("TestSubkey1", "TestKey2", &buffer), res); CHE(buffer, "New Test Value 2", res); - IFT(reg.ReadValue("TestSubkey", "TestKey3", buffer), res); + IFT(reg.ReadValue("TestSubkey", "TestKey3", &buffer), res); CHE(buffer, "New Test Value 3", res); - IFT(reg.ReadValue("TestSubkey2", "TestKey4", buffer), res); + IFT(reg.ReadValue("TestSubkey2", "TestKey4", &buffer), res); CHE(buffer, "New Test Value 4", res); IFT( reg.DeleteValue("TestSubkey", "TestKey1"), res); - IFNT(reg.ReadValue( "TestSubkey", "TestKey1", buffer), res); + IFNT(reg.ReadValue( "TestSubkey", "TestKey1", &buffer), res); IFT( reg.DeleteValue("TestSubkey1", "TestKey2"), res); - IFNT(reg.ReadValue( "TestSubkey1", "TestKey2", buffer), res); + IFNT(reg.ReadValue( "TestSubkey1", "TestKey2", &buffer), res); IFT( reg.DeleteValue("TestSubkey", "TestKey3"), res); - IFNT(reg.ReadValue( "TestSubkey", "TestKey3", buffer), res); + IFNT(reg.ReadValue( "TestSubkey", "TestKey3", &buffer), res); IFT( reg.DeleteValue("TestSubkey2", "TestKey4"), res); - IFNT(reg.ReadValue( "TestSubkey2", "TestKey5", buffer), res); + IFNT(reg.ReadValue( "TestSubkey2", "TestKey5", &buffer), res); + + const char* longStringWithNewLines = "Value with embedded CR and LF characters CR='\015' LF='\012' CRLF='\015\012'"; + IFT(reg.SetValue("TestSubkeyWithVeryLongInFactSoLongItsHardToImagineAnybodyWouldReallyDoItLongName", "TestKey1", longStringWithNewLines), res); + IFT(reg.ReadValue("TestSubkeyWithVeryLongInFactSoLongItsHardToImagineAnybodyWouldReallyDoItLongName", "TestKey1", &buffer), res); + CHE(buffer, longStringWithNewLines, res); + + IFT(reg.SetValue("TestSubkeyWith = EqualSignChar", "TestKey = 1", "Some value"), res); + IFT(reg.ReadValue("TestSubkeyWith = EqualSignChar", "TestKey = 1", &buffer), res); + CHE(buffer, "Some value", res); if ( res ) {