Currently libcompizconfig saves lists of values using semicolon as a separator. Thus, if there are values { "first;", "second\\" }, they are saved as "first;;second\\". Parsing incorrectly restores values {"first", "", "second\\" }. The proposed solution is to use escape character - the backslash ('\\'). It is placed before semicolons and backslashes. Thus, if there are values { "first;", "second\\" }, they are saved as "first\\;;second\\\\". The .ini file would contain a line like:
s0_bg_image = first\;;second\\
Parsing restores original values correctly.
The patch contains a new function:

static char *
strsepesc (char **stringp,
      const char *delim,
      char esc)

It follows strsep interface, but adds a new parameter esc - the character used to escape values. As was noticed above, I use backslash as escape character.
diff -Naur libcompizconfig-0.8.4.orig/src/ini.c libcompizconfig-0.8.4/src/ini.c
--- libcompizconfig-0.8.4.orig/src/ini.c        2009-10-14 03:36:04.000000000 
+0300
+++ libcompizconfig-0.8.4/src/ini.c     2011-03-06 17:27:52.000000000 +0200
@@ -302,6 +302,41 @@
     return TRUE;
 }
 
+static char *
+strsepesc (char **stringp,
+           const char *delim,
+           char esc)
+{
+    char *p, *token;
+    
+    if (*stringp == NULL)
+       return NULL;
+    token = *stringp;
+    if (strchr (delim, esc) != NULL)
+    {
+       *stringp = NULL;
+       return token;
+    }
+    p = token;
+    while (**stringp != '\0' && strchr (delim, **stringp) == NULL) 
+    {          
+       if (**stringp == esc)
+       {
+           ++*stringp;
+           if (**stringp == '\0')
+               break;
+       }
+        *p++ = **stringp;                      
+       ++(*stringp);
+    }  
+    if (**stringp == '\0')
+       *stringp = NULL;
+    else
+       ++(*stringp);
+    *p = '\0';
+    return token;
+}
+
 Bool
 ccsIniGetList (IniDictionary       *dictionary,
               const char          *section,
@@ -312,7 +347,7 @@
     CCSSettingValueList list = NULL;
     char                *valueString, *valueStart, *valString;
     char                *token;
-    int                 nItems = 1, i = 0, len;
+    int                 nItems = 0, i = 0, len;
 
     valString = getIniString (dictionary, section, entry);
     if (!valString)
@@ -333,14 +368,18 @@
     if (valueString[len - 1] == ';')
        valueString[len - 1] = 0;
 
-    token = strchr (valueString, ';');
+    token = strsepesc (&valueString, ";", '\\');
     while (token)
     {
-       token = strchr (token + 1, ';');
+       token = strsepesc (&valueString, ";", '\\');
        nItems++;
     }
 
-    token = strsep (&valueString, ";");
+    valueString = valueStart;
+    strcpy(valueString, valString);
+    if (valueString[len - 1] == ';')
+        valueString[len - 1] = 0;
+    token = strsepesc (&valueString, ";", '\\');
     switch (parent->info.forList.listType)
     {
     case TypeString:
@@ -353,7 +392,7 @@
            while (token)
            {
                array[i++] = strdup (token);
-               token = strsep (&valueString, ";");
+               token = strsepesc (&valueString, ";", '\\');
            }
 
            list = ccsGetValueListFromStringArray (array, nItems, parent);
@@ -375,7 +414,7 @@
            {
                memset (&array[i], 0, sizeof (CCSSettingColorValue));
                ccsStringToColor (token, &array[i]);
-               token = strsep (&valueString, ";");
+               token = strsepesc (&valueString, ";", '\\');
                i++;
            }
 
@@ -396,7 +435,7 @@
                          token[0] == '1' ||
                          token[0] == 't' || token[0] == 'T');
                array[i++] = isTrue;
-               token = strsep (&valueString, ";");
+               token = strsepesc (&valueString, ";", '\\');
            }
 
            list = ccsGetValueListFromBoolArray (array, nItems, parent);
@@ -412,7 +451,7 @@
            while (token)
            {
                array[i++] = strtoul (token, NULL, 10);
-               token = strsep (&valueString, ";");
+               token = strsepesc (&valueString, ";", '\\');
            }
 
            list = ccsGetValueListFromIntArray (array, nItems, parent);
@@ -428,7 +467,7 @@
            while (token)
            {
                array[i++] = strtod (token, NULL);
-               token = strsep (&valueString, ";");
+               token = strsepesc (&valueString, ";", '\\');
            }
 
            list = ccsGetValueListFromFloatArray (array, nItems, parent);
@@ -449,7 +488,7 @@
                    list = ccsSettingValueListAppend (list, val);
                else
                    free (val);
-               token = strsep (&valueString, ";");
+               token = strsepesc (&valueString, ";", '\\');
            }
        }
        break;
@@ -467,7 +506,7 @@
                    list = ccsSettingValueListAppend (list, val);
                else
                    free (val);
-               token = strsep (&valueString, ";");
+               token = strsepesc (&valueString, ";", '\\');
            }
        }
        break;
@@ -483,7 +522,7 @@
                    break;
                val->value.asEdge = ccsStringToEdges (token);
                list = ccsSettingValueListAppend (list, val);
-               token = strsep (&valueString, ";");
+               token = strsepesc (&valueString, ";", '\\');
            }
        }
        break;
@@ -505,7 +544,7 @@
                
                val->value.asBell = isTrue;
                list = ccsSettingValueListAppend (list, val);
-               token = strsep (&valueString, ";");
+               token = strsepesc (&valueString, ";", '\\');
            }
        }
        break;
@@ -650,9 +689,9 @@
               CCSSettingValueList value,
               CCSSettingType      listType)
 {
-    char         *stringBuffer, *valueString;
+    char         *stringBuffer, *valueString, *valueChar;
     char         valueBuffer[100];
-    unsigned int bufferSize = 1024, fill;
+    unsigned int bufferSize = 1024, fill = 0, valueSize, neededSize;
 
     stringBuffer = calloc (1, bufferSize);
     if (!stringBuffer)
@@ -707,24 +746,35 @@
        if (!valueString)
            return;
 
-       fill = strlen (stringBuffer);
+       valueSize = 0;
+       for (valueChar = valueString; *valueChar; ++valueChar)
+       {
+           if (*valueChar == ';' || *valueChar == '\\')
+               ++valueSize;
+           ++valueSize;
+       }
+       
        /* the + 1 is the semicolon we're going to add */
-       if ((fill + strlen (valueString) + 1) >= bufferSize)
+       neededSize = fill + valueSize + 1; 
+       if (neededSize >= bufferSize) 
        {
-           /* buffer is too small, make it larger */
-           bufferSize *= 2;
+           do
+               bufferSize *= 2;
+           while (neededSize >= bufferSize);
+       
            stringBuffer = realloc (stringBuffer, bufferSize);
            if (!stringBuffer)
                return;
-
-           /* properly NULL terminate it */
-           stringBuffer[fill] = 0;
        }
 
-       /* we made sure that the buffer is large enough before, so
-          there is no need for strncat */
-       strcat (stringBuffer, valueString);
-       strcat (stringBuffer, ";");
+       for (valueChar = valueString; *valueChar; ++valueChar)
+       {
+           if (*valueChar == ';' || *valueChar == '\\')
+               stringBuffer[fill++] = '\\';
+            stringBuffer[fill++] = *valueChar;
+       }
+       stringBuffer[fill++] = ';';
+       stringBuffer[fill + 1] = '\0';
 
        if (listType == TypeColor  || listType == TypeKey ||
            listType == TypeButton || listType == TypeEdge)
_______________________________________________
dev mailing list
[email protected]
http://lists.compiz.org/mailman/listinfo/dev

Reply via email to