summaryrefslogtreecommitdiff
path: root/src/caja-convert-metadata.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/caja-convert-metadata.c')
-rw-r--r--src/caja-convert-metadata.c492
1 files changed, 492 insertions, 0 deletions
diff --git a/src/caja-convert-metadata.c b/src/caja-convert-metadata.c
new file mode 100644
index 00000000..7571173d
--- /dev/null
+++ b/src/caja-convert-metadata.c
@@ -0,0 +1,492 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/* caja-convert-metadata.c - Convert old metadata format to gvfs metadata.
+ *
+ * Copyright (C) 2009 Alexander Larsson
+ *
+ * Caja is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Caja is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; see the file COPYING. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ * Alexander Larsson <[email protected]>
+ */
+
+#include <config.h>
+
+#include <glib.h>
+
+#include <gio/gio.h>
+#include <glib/gi18n.h>
+#include <string.h>
+#include <libxml/tree.h>
+#include <mateconf/mateconf-client.h>
+
+#include <libcaja-private/caja-metadata.h>
+
+#define CAJA_DESKTOP_METADATA_MATECONF_PATH "/apps/caja/desktop-metadata"
+
+static gboolean quiet = FALSE;
+static char *
+get_metadata_mateconf_path (const char *name,
+ const char *key)
+{
+ char *res, *escaped_name;
+
+ escaped_name = mateconf_escape_key (name, -1);
+ res = g_build_filename (CAJA_DESKTOP_METADATA_MATECONF_PATH, escaped_name, key + strlen ("metadata::"), NULL);
+ g_free (escaped_name);
+
+ return res;
+}
+
+static void
+desktop_set_metadata_string (GFile *file,
+ const char *key,
+ const char *string)
+{
+ MateConfClient *client;
+ char *mateconf_key;
+ GFile *parent;
+ char *name;
+
+ parent = g_file_get_parent (file);
+ if (parent == NULL)
+ {
+ name = g_strdup ("directory");
+ }
+ else
+ {
+ g_object_unref (parent);
+ name = g_file_get_basename (file);
+ }
+
+ client = mateconf_client_get_default ();
+ mateconf_key = get_metadata_mateconf_path (name, key);
+
+ mateconf_client_set_string (client, mateconf_key, string, NULL);
+
+ g_free (mateconf_key);
+ g_free (name);
+ g_object_unref (client);
+}
+
+static void
+desktop_set_metadata_stringv (GFile *file,
+ const char *key,
+ char **stringv)
+{
+ MateConfClient *client;
+ char *mateconf_key;
+ GSList *list;
+ int i;
+ GFile *parent;
+ char *name;
+
+ parent = g_file_get_parent (file);
+ if (parent == NULL)
+ {
+ name = g_strdup ("directory");
+ }
+ else
+ {
+ g_object_unref (parent);
+ name = g_file_get_basename (file);
+ }
+
+ client = mateconf_client_get_default ();
+ mateconf_key = get_metadata_mateconf_path (name, key);
+
+ list = NULL;
+ for (i = 0; stringv[i] != NULL; i++)
+ {
+ list = g_slist_prepend (list, stringv[i]);
+ }
+ list = g_slist_reverse (list);
+
+ mateconf_client_set_list (client, mateconf_key,
+ MATECONF_VALUE_STRING,
+ list, NULL);
+
+ g_slist_free (list);
+ g_free (mateconf_key);
+ g_free (name);
+ g_object_unref (client);
+}
+
+static xmlNodePtr
+xml_get_children (xmlNodePtr parent)
+{
+ if (parent == NULL)
+ {
+ return NULL;
+ }
+ return parent->children;
+}
+
+static xmlNodePtr
+xml_get_root_children (xmlDocPtr document)
+{
+ return xml_get_children (xmlDocGetRootElement (document));
+}
+
+
+static char *
+get_uri_from_caja_metafile_name (const char *filename)
+{
+ GString *s;
+ char c;
+ char *base_name, *p;
+ int len;
+
+ base_name = g_path_get_basename (filename);
+ len = strlen (base_name);
+ if (len <= 4 ||
+ strcmp (base_name + len - 4, ".xml") != 0)
+ {
+ g_free (base_name);
+ return NULL;
+ }
+ base_name[len-4] = 0;
+
+ s = g_string_new (NULL);
+
+ p = base_name;
+ while (*p)
+ {
+ c = *p++;
+ if (c == '%')
+ {
+ c = g_ascii_xdigit_value (p[0]) << 4 |
+ g_ascii_xdigit_value (p[1]);
+ p += 2;
+ }
+ g_string_append_c (s, c);
+ }
+ g_free (base_name);
+
+ return g_string_free (s, FALSE);
+}
+
+static struct
+{
+ const char *old_key;
+ const char *new_key;
+} metadata_keys[] =
+{
+ {"default_component", "metadata::" CAJA_METADATA_KEY_DEFAULT_VIEW},
+ {"background_color", "metadata::" CAJA_METADATA_KEY_LOCATION_BACKGROUND_COLOR},
+ {"background_tile_image", "metadata::" CAJA_METADATA_KEY_LOCATION_BACKGROUND_IMAGE},
+ {"icon_view_zoom_level", "metadata::" CAJA_METADATA_KEY_ICON_VIEW_ZOOM_LEVEL},
+ {"icon_view_auto_layout", "metadata::" CAJA_METADATA_KEY_ICON_VIEW_AUTO_LAYOUT},
+ {"icon_view_tighter_layout", "metadata::" CAJA_METADATA_KEY_ICON_VIEW_TIGHTER_LAYOUT},
+ {"icon_view_sort_by", "metadata::" CAJA_METADATA_KEY_ICON_VIEW_SORT_BY},
+ {"icon_view_sort_reversed", "metadata::" CAJA_METADATA_KEY_ICON_VIEW_SORT_REVERSED},
+ {"icon_view_keep_aligned", "metadata::" CAJA_METADATA_KEY_ICON_VIEW_KEEP_ALIGNED},
+ {"icon_view_layout_timestamp", "metadata::" CAJA_METADATA_KEY_ICON_VIEW_LAYOUT_TIMESTAMP},
+ {"list_view_zoom_level", "metadata::" CAJA_METADATA_KEY_LIST_VIEW_ZOOM_LEVEL},
+ {"list_view_sort_column", "metadata::" CAJA_METADATA_KEY_LIST_VIEW_SORT_COLUMN},
+ {"list_view_sort_reversed", "metadata::" CAJA_METADATA_KEY_LIST_VIEW_SORT_REVERSED},
+ {"list_view_visible_columns", "metadata::" CAJA_METADATA_KEY_LIST_VIEW_VISIBLE_COLUMNS},
+ {"list_view_column_order", "metadata::" CAJA_METADATA_KEY_LIST_VIEW_COLUMN_ORDER},
+ {"compact_view_zoom_level", "metadata::" CAJA_METADATA_KEY_COMPACT_VIEW_ZOOM_LEVEL},
+ {"window_geometry", "metadata::" CAJA_METADATA_KEY_WINDOW_GEOMETRY},
+ {"window_scroll_position", "metadata::" CAJA_METADATA_KEY_WINDOW_SCROLL_POSITION},
+ {"window_show_hidden_files", "metadata::" CAJA_METADATA_KEY_WINDOW_SHOW_HIDDEN_FILES},
+ {"window_maximized", "metadata::" CAJA_METADATA_KEY_WINDOW_MAXIMIZED},
+ {"window_sticky", "metadata::" CAJA_METADATA_KEY_WINDOW_STICKY},
+ {"window_keep_above", "metadata::" CAJA_METADATA_KEY_WINDOW_KEEP_ABOVE},
+ {"sidebar_background_color", "metadata::" CAJA_METADATA_KEY_SIDEBAR_BACKGROUND_COLOR},
+ {"sidebar_background_tile_image", "metadata::" CAJA_METADATA_KEY_SIDEBAR_BACKGROUND_IMAGE},
+ {"sidebar_buttons", "metadata::" CAJA_METADATA_KEY_SIDEBAR_BUTTONS},
+ {"annotation", "metadata::" CAJA_METADATA_KEY_ANNOTATION},
+ {"icon_position", "metadata::" CAJA_METADATA_KEY_ICON_POSITION},
+ {"icon_position_timestamp", "metadata::" CAJA_METADATA_KEY_ICON_POSITION_TIMESTAMP},
+ {"icon_scale", "metadata::" CAJA_METADATA_KEY_ICON_SCALE},
+ {"custom_icon", "metadata::" CAJA_METADATA_KEY_CUSTOM_ICON},
+ {"screen", "metadata::" CAJA_METADATA_KEY_SCREEN},
+ {"keyword", "metadata::" CAJA_METADATA_KEY_EMBLEMS},
+};
+
+static const char *
+convert_key_name (const char *old_key)
+{
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (metadata_keys); i++)
+ {
+ if (strcmp (metadata_keys[i].old_key, old_key) == 0)
+ {
+ return metadata_keys[i].new_key;
+ }
+ }
+
+ return NULL;
+}
+
+static void
+parse_xml_node (GFile *file,
+ xmlNodePtr filenode)
+{
+ xmlNodePtr node;
+ xmlAttrPtr attr;
+ xmlChar *property;
+ const char *new_key;
+ GHashTable *list_keys;
+ GList *keys, *l;
+ GHashTableIter iter;
+ GFileInfo *info;
+ int i;
+ char **strv;
+ GError *error;
+
+ info = NULL;
+ if (!g_file_has_uri_scheme (file, "x-caja-desktop"))
+ {
+ info = g_file_info_new ();
+ }
+
+ for (attr = filenode->properties; attr != NULL; attr = attr->next)
+ {
+ if (strcmp ((char *)attr->name, "name") == 0 ||
+ strcmp ((char *)attr->name, "timestamp") == 0)
+ {
+ continue;
+ }
+
+ new_key = convert_key_name (attr->name);
+ if (new_key)
+ {
+ property = xmlGetProp (filenode, attr->name);
+ if (property)
+ {
+ if (info)
+ {
+ g_file_info_set_attribute_string (info,
+ new_key,
+ property);
+ }
+ else
+ {
+ desktop_set_metadata_string (file, new_key, property);
+ }
+ xmlFree (property);
+ }
+ }
+ }
+
+ list_keys = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
+ for (node = filenode->children; node != NULL; node = node->next)
+ {
+ for (attr = node->properties; attr != NULL; attr = attr->next)
+ {
+ new_key = convert_key_name (node->name);
+ if (new_key)
+ {
+ property = xmlGetProp (node, attr->name);
+ if (property)
+ {
+ keys = g_hash_table_lookup (list_keys, new_key);
+ keys = g_list_append (keys, property);
+ g_hash_table_replace (list_keys, (char *)new_key, keys);
+ }
+ }
+ }
+ }
+
+ g_hash_table_iter_init (&iter, list_keys);
+ while (g_hash_table_iter_next (&iter, (void **)&new_key, (void **)&keys))
+ {
+ strv = g_new0 (char *, g_list_length (keys) + 1);
+
+ for (l = keys, i = 0; l != NULL; l = l->next, i++)
+ {
+ strv[i] = l->data;
+ }
+ if (info)
+ {
+ g_file_info_set_attribute_stringv (info,
+ new_key,
+ strv);
+ }
+ else
+ {
+ desktop_set_metadata_stringv (file, new_key, strv);
+ }
+ g_free (strv);
+ g_list_foreach (keys, (GFunc)xmlFree, NULL);
+ g_list_free (keys);
+ }
+ g_hash_table_destroy (list_keys);
+
+ if (info)
+ {
+ error = NULL;
+ if (!g_file_set_attributes_from_info (file,
+ info,
+ 0, NULL, &error))
+ {
+ char *uri;
+
+ uri = g_file_get_uri (file);
+ if (!quiet)
+ {
+ g_print ("error setting info for %s: %s\n", uri, error->message);
+ }
+ g_free (uri);
+ g_error_free (error);
+ }
+ g_object_unref (info);
+ }
+}
+
+static void
+convert_xml_file (xmlDocPtr xml,
+ GFile *dir)
+{
+ xmlNodePtr node;
+ xmlChar *name;
+ char *unescaped_name;
+ GFile *file;
+
+ for (node = xml_get_root_children (xml);
+ node != NULL; node = node->next)
+ {
+ if (strcmp ((char *)node->name, "file") == 0)
+ {
+ name = xmlGetProp (node, (xmlChar *)"name");
+ unescaped_name = g_uri_unescape_string ((char *)name, "/");
+ xmlFree (name);
+
+ if (unescaped_name == NULL)
+ {
+ continue;
+ }
+
+ if (strcmp (unescaped_name, ".") == 0)
+ {
+ file = g_object_ref (dir);
+ }
+ else
+ {
+ file = g_file_get_child (dir, unescaped_name);
+ }
+
+ parse_xml_node (file, node);
+ g_object_unref (file);
+ g_free (unescaped_name);
+ }
+ }
+}
+
+static void
+convert_caja_file (char *file)
+{
+ GFile *dir;
+ char *uri;
+ gchar *contents;
+ gsize length;
+ xmlDocPtr xml;
+
+ if (!g_file_get_contents (file, &contents, &length, NULL))
+ {
+ if (!quiet)
+ {
+ g_print ("failed to load %s\n", file);
+ }
+ return;
+ }
+
+ uri = get_uri_from_caja_metafile_name (file);
+ if (uri == NULL)
+ {
+ g_free (contents);
+ return;
+ }
+
+ dir = g_file_new_for_uri (uri);
+ g_free (uri);
+
+ xml = xmlParseMemory (contents, length);
+ g_free (contents);
+ if (xml == NULL)
+ {
+ return;
+ }
+
+ convert_xml_file (xml, dir);
+ xmlFreeDoc (xml);
+}
+
+static GOptionEntry entries[] =
+{
+ {
+ "quiet", 'q', 0, G_OPTION_ARG_NONE, &quiet,
+ "Don't show errors", NULL
+ },
+ { NULL }
+};
+
+int
+main (int argc, char *argv[])
+{
+ GOptionContext *context;
+ GError *error = NULL;
+ int i;
+
+ g_type_init ();
+
+ context = g_option_context_new ("<caja metadata files> - convert caja metadata");
+ g_option_context_add_main_entries (context, entries, NULL);
+ if (!g_option_context_parse (context, &argc, &argv, &error))
+ {
+ g_printerr ("option parsing failed: %s\n", error->message);
+ return 1;
+ }
+
+ if (argc < 2)
+ {
+ GDir *dir;
+ char *metafile_dir;
+ char *file;
+ const char *entry;
+
+ /* Convert all metafiles */
+
+ metafile_dir = g_build_filename (g_get_home_dir (), ".config", "caja", "metafiles", NULL);
+
+ dir = g_dir_open (metafile_dir, 0, NULL);
+ if (dir)
+ {
+ while ((entry = g_dir_read_name (dir)) != NULL)
+ {
+ file = g_build_filename (metafile_dir, entry, NULL);
+ if (g_str_has_suffix (file, ".xml"))
+ convert_caja_file (file);
+ g_free (file);
+ }
+ g_dir_close (dir);
+ }
+ g_free (metafile_dir);
+ }
+ else
+ {
+ for (i = 1; i < argc; i++)
+ {
+ convert_caja_file (argv[i]);
+ }
+ }
+
+ return 0;
+}