[SF#614]Don't follow symlink ~/.icons/default or we can recurse inheritance.
[lxde/lxappearance.git] / src / lxappearance.c
index 272b23d..2993fe8 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <gtk/gtk.h>
 #include <glib/gi18n.h>
+#include <glib/gstdio.h>
 
 #include <X11/X.h>
 #include <X11/Xatom.h>
@@ -111,26 +112,76 @@ static GOptionEntry option_entries[] =
     { NULL }
 };
 
+static gboolean verify_cursor_theme(GKeyFile *kf, const char *cursor_theme,
+                                    const char *test)
+{
+    char *fpath;
+    gboolean ret;
+
+    /* get the inherited theme name. */
+    fpath = g_build_filename(g_get_home_dir(), ".icons", cursor_theme,
+                             "index.theme", NULL);
+    ret = g_key_file_load_from_file(kf, fpath, 0, NULL);
+    g_free(fpath);
+
+    fpath = g_build_filename("icons", cursor_theme, "index.theme", NULL);
+    if (!ret)
+        ret = g_key_file_load_from_data_dirs(kf, fpath, NULL, 0, NULL);
+    g_free(fpath);
+
+    if (ret)
+    {
+        fpath = g_key_file_get_string(kf, "Icon Theme", "Inherits", NULL);
+        if (fpath == NULL) /* end of chain, success */
+            return TRUE;
+        if (strcmp(fpath, test) == 0) /* recursion */
+            ret = FALSE;
+        else if (!verify_cursor_theme(kf, fpath, test)) /* recursion */
+            ret = FALSE;
+        else /* check recursion against this one too */
+            ret = verify_cursor_theme(kf, fpath, cursor_theme);
+        g_free(fpath);
+    }
+    return ret;
+}
+
 static void save_cursor_theme_name()
 {
     char* dir_path;
-    if(!app.cursor_theme || !g_strcmp0(app.cursor_theme, "default"))
+    GKeyFile* kf;
+
+    if (app.cursor_theme == NULL || strcmp(app.cursor_theme, "default") == 0)
         return;
 
     dir_path = g_build_filename(g_get_home_dir(), ".icons/default", NULL);
-    if(0 == g_mkdir_with_parents(dir_path, 0700))
+    kf = g_key_file_new();
+    /* test if cursor theme isn't recursed and don't use it otherwise */
+    if (!verify_cursor_theme(kf, app.cursor_theme, "default"))
+    {
+        g_free(app.cursor_theme);
+        app.cursor_theme = NULL; /* FIXME: replace with "default"? */
+        /* FIXME: show an error message */
+    }
+    /* SF bug #614: ~/.icons/default may be symlink so remove symlink */
+    else if (g_file_test(dir_path, G_FILE_TEST_IS_SYMLINK) &&
+                         g_unlink(dir_path) != 0)
+    {
+        /* FIXME: show an error message */
+    }
+    else if (0 == g_mkdir_with_parents(dir_path, 0700))
     {
         char* index_theme = g_build_filename(dir_path, "index.theme", NULL);
         char* content = g_strdup_printf(
-            "# This file is written by LXAppearance. Do not edit.\n"
-            "[Icon Theme]\n"
-            "Name=Default\n"
-            "Comment=Default Cursor Theme\n"
-            "Inherits=%s\n", app.cursor_theme ? app.cursor_theme : "");
+                        "# This file is written by LXAppearance. Do not edit.\n"
+                        "[Icon Theme]\n"
+                        "Name=Default\n"
+                        "Comment=Default Cursor Theme\n"
+                        "Inherits=%s\n", app.cursor_theme);
         g_file_set_contents(index_theme, content, -1, NULL);
         g_free(content);
         g_free(index_theme);
     }
+    g_key_file_free(kf);
     g_free(dir_path);
 
     /*
@@ -171,12 +222,6 @@ static void reload_all_programs()
 #endif
 }
 
-static const char* bool2str(gboolean val)
-{
-    return val ? "TRUE" : "FALSE";
-}
-
-
 static void lxappearance_save_gtkrc()
 {
     static const char* tb_styles[]={
@@ -271,65 +316,60 @@ static void lxappearance_save_gtkrc()
     /* Save also in GTK3 folder
        Content shold be different from the gtk2 one
     */
-    GString* content_gtk3 = g_string_sized_new(512);
+    GKeyFile *content_gtk3 = g_key_file_new();
     char* file_path_gtk3 = g_build_filename(g_get_user_config_dir(), "gtk-3.0", NULL);
-    char* file_path_settings = g_build_filename(g_get_user_config_dir(), "gtk-3.0", "settings.ini", NULL);
+    char* file_path_settings = g_build_filename(file_path_gtk3, "settings.ini", NULL);
 
     if (!g_file_test(file_path_gtk3, G_FILE_TEST_IS_DIR))
     {
         g_mkdir_with_parents(file_path_gtk3, 0755);
     }
 
-
-    g_string_append(content_gtk3, "[Settings] \n");
+    g_key_file_load_from_file(content_gtk3, file_path_settings, /* ignoring errors */
+                              G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, NULL);
 
     if(app.widget_theme)
-        g_string_append_printf(content_gtk3,
-            "gtk-theme-name=%s\n", app.widget_theme);
+        g_key_file_set_string(content_gtk3, "Settings",
+                              "gtk-theme-name", app.widget_theme);
     if(app.icon_theme)
-        g_string_append_printf(content_gtk3,
-            "gtk-icon-theme-name=%s\n", app.icon_theme);
+        g_key_file_set_string(content_gtk3, "Settings",
+                              "gtk-icon-theme-name", app.icon_theme);
     if(app.default_font)
-        g_string_append_printf(content_gtk3,
-            "gtk-font-name=%s\n", app.default_font);
+        g_key_file_set_string(content_gtk3, "Settings",
+                              "gtk-font-name", app.default_font);
     if(app.cursor_theme)
-        g_string_append_printf(content_gtk3,
-            "gtk-cursor-theme-name=%s\n", app.cursor_theme);
+        g_key_file_set_string(content_gtk3, "Settings",
+                              "gtk-cursor-theme-name", app.cursor_theme);
     save_cursor_theme_name();
 
-    g_string_append_printf(content_gtk3,
-        "gtk-cursor-theme-size=%d\n"
-        "gtk-toolbar-style=%s\n"
-        "gtk-toolbar-icon-size=%s\n"
-        "gtk-button-images=%d\n"
-        "gtk-menu-images=%d\n"
-#if GTK_CHECK_VERSION(2, 14, 0)
-        "gtk-enable-event-sounds=%d\n"
-        "gtk-enable-input-feedback-sounds=%d\n"
-#endif
-        "gtk-xft-antialias=%d\n"
-        "gtk-xft-hinting=%d\n"
-
-        , app.cursor_theme_size,
-        tb_styles[app.toolbar_style],
-        tb_icon_sizes[app.toolbar_icon_size],
-        app.button_images ? 1 : 0,
-        app.menu_images ? 1 : 0,
+    g_key_file_set_integer(content_gtk3, "Settings",
+                           "gtk-cursor-theme-size", app.cursor_theme_size);
+    g_key_file_set_string(content_gtk3, "Settings",
+                          "gtk-toolbar-style", tb_styles[app.toolbar_style]);
+    g_key_file_set_string(content_gtk3, "Settings",
+                          "gtk-toolbar-icon-size", tb_icon_sizes[app.toolbar_icon_size]);
+    g_key_file_set_boolean(content_gtk3, "Settings",
+                           "gtk-button-images", app.button_images);
+    g_key_file_set_boolean(content_gtk3, "Settings",
+                           "gtk-menu-images", app.menu_images);
 #if GTK_CHECK_VERSION(2, 14, 0)
-        app.enable_event_sound ? 1 : 0,
-        app.enable_input_feedback ? 1 : 0,
+    g_key_file_set_boolean(content_gtk3, "Settings",
+                           "gtk-enable-event-sounds", app.enable_event_sound);
+    g_key_file_set_boolean(content_gtk3, "Settings",
+                           "gtk-enable-input-feedback-sounds", app.enable_input_feedback);
 #endif
-        app.enable_antialising ? 1 : 0,
-        app.enable_hinting ? 1 : 0
-        );
+    g_key_file_set_boolean(content_gtk3, "Settings",
+                           "gtk-xft-antialias", app.enable_antialising);
+    g_key_file_set_boolean(content_gtk3, "Settings",
+                           "gtk-xft-hinting", app.enable_hinting);
 
     if(app.hinting_style)
-        g_string_append_printf(content_gtk3,
-            "gtk-xft-hintstyle=%s\n", app.hinting_style);
+        g_key_file_set_string(content_gtk3, "Settings",
+                              "gtk-xft-hintstyle", app.hinting_style);
 
     if(app.font_rgba)
-        g_string_append_printf(content_gtk3,
-            "gtk-xft-rgba=%s\n", app.font_rgba);
+        g_key_file_set_string(content_gtk3, "Settings",
+                              "gtk-xft-rgba", app.font_rgba);
 
 #if 0
     /* unfortunately we cannot set colors without XSETTINGS daemon,
@@ -345,10 +385,22 @@ static void lxappearance_save_gtkrc()
     }
 #endif
 
-    g_file_set_contents(file_path_settings, content_gtk3->str, content_gtk3->len, NULL);
+#if GLIB_CHECK_VERSION(2, 40, 0)
+    g_key_file_save_to_file(content_gtk3, file_path_settings, NULL);
+#else
+    char *contents;
+    gsize s;
+
+    contents = g_key_file_to_data(content_gtk3, &s, NULL);
+    if (contents)
+        g_file_set_contents(file_path_settings, contents, s, NULL);
+    g_free(contents);
+#endif
 
+    g_free(file_path_gtk3);
+    g_free(file_path_settings);
     g_string_free(content, TRUE);
-    g_string_free(content_gtk3, TRUE);
+    g_key_file_free(content_gtk3);
     g_free(file_path);
 }
 
@@ -357,7 +409,7 @@ static void lxappearance_save_lxsession()
     char* rel_path = g_strconcat("lxsession/", lxsession_name, "/desktop.conf", NULL);
     char* user_config_file = g_build_filename(g_get_user_config_dir(), rel_path, NULL);
     char* buf;
-    int len;
+    gsize len;
     GKeyFile* kf = g_key_file_new();
 
     if(!g_key_file_load_from_file(kf, user_config_file, G_KEY_FILE_KEEP_COMMENTS|G_KEY_FILE_KEEP_TRANSLATIONS, NULL))
@@ -542,7 +594,9 @@ int main(int argc, char** argv)
     textdomain ( GETTEXT_PACKAGE );
 #endif
 
+#if !GLIB_CHECK_VERSION(2, 32, 0)
     g_thread_init(NULL);
+#endif
     /* initialize GTK+ and parse the command line arguments */
     if( G_UNLIKELY( ! gtk_init_with_args( &argc, &argv, "", option_entries, GETTEXT_PACKAGE, &err ) ) )
     {