// global functions declarations
// ----------------------------------------------------------------------------
-// is 'c' a valid character in group name?
-// NB: wxCONFIG_IMMUTABLE_PREFIX and wxCONFIG_PATH_SEPARATOR must be valid chars,
-// but _not_ ']' (group name delimiter)
-inline bool IsValid(char c) { return isalnum(c) || strchr("@_/-!.*%", c); }
-
// compare functions for sorting the arrays
static int CompareEntries(ConfigEntry *p1, ConfigEntry *p2);
static int CompareGroups(ConfigGroup *p1, ConfigGroup *p2);
// filter strings
-static wxString FilterIn(const wxString& str);
-static wxString FilterOut(const wxString& str);
+static wxString FilterInValue(const wxString& str);
+static wxString FilterOutValue(const wxString& str);
+
+static wxString FilterInEntryName(const wxString& str);
+static wxString FilterOutEntryName(const wxString& str);
// ============================================================================
// implementation
strDir = "/etc/";
#elif defined(__WXSTUBS__)
wxASSERT_MSG( FALSE, "TODO" ) ;
+ #elif defined(__WXMAC__)
+ wxASSERT_MSG( FALSE, "TODO" ) ;
#else // Windows
char szWinDir[MAX_PATH];
::GetWindowsDirectory(szWinDir, MAX_PATH);
pEnd = pStart;
while ( *++pEnd != ']' ) {
- if ( !IsValid(*pEnd) && *pEnd != ' ' ) // allow spaces in group names
- break;
+ if ( *pEnd == '\n' || *pEnd == '\0' )
+ break;
}
if ( *pEnd != ']' ) {
// group name here is always considered as abs path
wxString strGroup;
pStart++;
- strGroup << wxCONFIG_PATH_SEPARATOR << wxString(pStart, pEnd - pStart);
+ strGroup << wxCONFIG_PATH_SEPARATOR
+ << FilterInEntryName(wxString(pStart, pEnd - pStart));
// will create it if doesn't yet exist
SetPath(strGroup);
}
else { // a key
const char *pEnd = pStart;
- while ( IsValid(*pEnd) )
+ while ( !isspace(*pEnd) ) {
+ if ( *pEnd == '\\' ) {
+ // next character may be space or not - still take it because it's
+ // quoted
+ pEnd++;
+ }
+
pEnd++;
+ }
- wxString strKey(pStart, pEnd);
+ wxString strKey(FilterInEntryName(wxString(pStart, pEnd)));
// skip whitespace
while ( isspace(*pEnd) )
while ( isspace(*pEnd) )
pEnd++;
- pEntry->SetValue(FilterIn(pEnd), FALSE /* read from file */);
+ pEntry->SetValue(FilterInValue(pEnd), FALSE /* read from file */);
}
}
}
wxString strName = path.Name();
if ( strName.IsEmpty() ) {
// setting the value of a group is an error
- wxASSERT_MSG( IsEmpty(szValue), _("can't set value of a group!") );
+ wxASSERT_MSG( IsEmpty(szValue), "can't set value of a group!" );
// ... except if it's empty in which case it's a way to force it's creation
m_pCurrentGroup->SetDirty();
// check that the name is reasonable
if ( strName[0u] == wxCONFIG_IMMUTABLE_PREFIX ) {
- wxLogError(_("Entry name can't start with '%c'."),
+ wxLogError(_("Config entry name cannot start with '%c'."),
wxCONFIG_IMMUTABLE_PREFIX);
return FALSE;
}
- for ( const char *pc = strName; *pc != '\0'; pc++ ) {
- if ( !IsValid(*pc) ) {
- wxLogError(_("Character '%c' is invalid in a config entry name."),
- *pc);
- return FALSE;
- }
- }
+ strName = FilterOutEntryName(strName);
ConfigEntry *pEntry = m_pCurrentGroup->FindEntry(strName);
if ( pEntry == NULL )
m_strValue = strValue;
if ( bUser ) {
- wxString strVal = FilterOut(strValue);
+ wxString strVal = FilterOutValue(strValue);
wxString strLine;
strLine << m_strName << " = " << strVal;
// filter functions
// ----------------------------------------------------------------------------
-// undo FilterOut
-wxString FilterIn(const wxString& str)
+// undo FilterOutValue
+static wxString FilterInValue(const wxString& str)
{
wxString strResult;
strResult.Alloc(str.Len());
}
// quote the string before writing it to file
-wxString FilterOut(const wxString& str)
+static wxString FilterOutValue(const wxString& str)
{
- if(str.IsEmpty())
+ if ( !str )
return str;
wxString strResult;
return strResult;
}
+// undo FilterOutEntryName
+static wxString FilterInEntryName(const wxString& str)
+{
+ wxString strResult;
+ strResult.Alloc(str.Len());
+ for ( const char *pc = str.c_str(); *pc != '\0'; pc++ ) {
+ if ( *pc == '\\' )
+ pc++;
+ strResult += *pc;
+ }
+ return strResult;
+}
+// sanitize entry or group name: insert '\\' before any special characters
+static wxString FilterOutEntryName(const wxString& str)
+{
+ wxString strResult;
+ strResult.Alloc(str.Len());
+ for ( const char *pc = str.c_str(); *pc != '\0'; pc++ ) {
+ char c = *pc;
+
+ // we explicitly allow some of "safe" chars and 8bit ASCII characters
+ // which will probably never have special meaning
+ // NB: note that wxCONFIG_IMMUTABLE_PREFIX and wxCONFIG_PATH_SEPARATOR
+ // should *not* be quoted
+ if ( !isalnum(c) && !strchr("@_/-!.*%", c) && ((c & 0x80) == 0) )
+ strResult += '\\';
+
+ strResult += c;
+ }
+
+ return strResult;
+}