[nautilus] Add nautilus-convert-metadata tool



commit 1d14824dc8ab6f1f8573b07c11ce437ae22dc77b
Author: Alexander Larsson <alexl redhat com>
Date:   Mon Aug 17 17:50:03 2009 +0200

    Add nautilus-convert-metadata tool
    
    This can be used to convert old-style nautilus metafiles to gvfs
    metadata.

 src/Makefile.am                 |   10 +-
 src/nautilus-convert-metadata.c |  438 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 447 insertions(+), 1 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 3e9ace0..042caf6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -6,7 +6,11 @@ bin_PROGRAMS=					\
 	nautilus				\
 	nautilus-file-management-properties	\
 	nautilus-autorun-software		\
-	nautilus-connect-server			
+	nautilus-connect-server			\
+	$(NULL)
+
+libexec_PROGRAMS=				\
+	nautilus-convert-metadata		\
 	$(NULL)
 
 INCLUDES =							\
@@ -150,6 +154,10 @@ nautilus_connect_server_SOURCES= \
 	nautilus-location-entry.h		\
 	$(NULL)
 
+nautilus_convert_metadata_SOURCES= \
+	nautilus-convert-metadata.c	\
+	$(NULL)
+
 TESTS=check-nautilus
 
 @INTLTOOL_SERVER_RULE@
diff --git a/src/nautilus-convert-metadata.c b/src/nautilus-convert-metadata.c
new file mode 100644
index 0000000..84e398b
--- /dev/null
+++ b/src/nautilus-convert-metadata.c
@@ -0,0 +1,438 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+
+/* nautilus-convert-metadata.c - Convert old metadata format to gvfs metadata.
+ *
+ * Copyright (C) 2009 Alexander Larsson
+ *
+ * Nautilus 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.
+ *
+ * Nautilus 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 <alexl redhat com>
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+#include <glib/gi18n.h>
+#include <string.h>
+#include <libxml/tree.h>
+#include <gconf/gconf-client.h>
+
+#include <libnautilus-private/nautilus-metadata.h>
+
+#define NAUTILUS_DESKTOP_METADATA_GCONF_PATH "/apps/nautilus/desktop-metadata"
+
+static gboolean quiet = FALSE;
+static char *
+get_metadata_gconf_path (const char *name,
+			 const char *key)
+{
+	char *res, *escaped_name;
+
+	escaped_name = gconf_escape_key (name, -1);
+	res = g_build_filename (NAUTILUS_DESKTOP_METADATA_GCONF_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)
+{
+	GConfClient *client;
+	char *gconf_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 = gconf_client_get_default ();
+	gconf_key = get_metadata_gconf_path (name, key);
+
+	gconf_client_set_string (client, gconf_key, string, NULL);
+
+	g_free (gconf_key);
+	g_free (name);
+	g_object_unref (client);
+}
+
+static void
+desktop_set_metadata_stringv (GFile *file,
+			      const char *key,
+			      char **stringv)
+{
+	GConfClient *client;
+	char *gconf_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 = gconf_client_get_default ();
+	gconf_key = get_metadata_gconf_path (name, key);
+
+	list = NULL;
+	for (i = 0; stringv[i] != NULL; i++) {
+		list = g_slist_prepend (list, stringv[i]);
+	}
+	list = g_slist_reverse (list);
+
+	gconf_client_set_list (client, gconf_key,
+			       GCONF_VALUE_STRING,
+			       list, NULL);
+
+	g_slist_free (list);
+	g_free (gconf_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_nautilus_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::" NAUTILUS_METADATA_KEY_DEFAULT_VIEW},
+	{"background_color", "metadata::" NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_COLOR},
+	{"background_tile_image", "metadata::" NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_IMAGE},
+	{"icon_view_zoom_level", "metadata::" NAUTILUS_METADATA_KEY_ICON_VIEW_ZOOM_LEVEL},
+	{"icon_view_auto_layout", "metadata::" NAUTILUS_METADATA_KEY_ICON_VIEW_AUTO_LAYOUT},
+	{"icon_view_tighter_layout", "metadata::" NAUTILUS_METADATA_KEY_ICON_VIEW_TIGHTER_LAYOUT},
+	{"icon_view_sort_by", "metadata::" NAUTILUS_METADATA_KEY_ICON_VIEW_SORT_BY},
+	{"icon_view_sort_reversed", "metadata::" NAUTILUS_METADATA_KEY_ICON_VIEW_SORT_REVERSED},
+	{"icon_view_keep_aligned", "metadata::" NAUTILUS_METADATA_KEY_ICON_VIEW_KEEP_ALIGNED},
+	{"icon_view_layout_timestamp", "metadata::" NAUTILUS_METADATA_KEY_ICON_VIEW_LAYOUT_TIMESTAMP},
+	{"list_view_zoom_level", "metadata::" NAUTILUS_METADATA_KEY_LIST_VIEW_ZOOM_LEVEL},
+	{"list_view_sort_column", "metadata::" NAUTILUS_METADATA_KEY_LIST_VIEW_SORT_COLUMN},
+	{"list_view_sort_reversed", "metadata::" NAUTILUS_METADATA_KEY_LIST_VIEW_SORT_REVERSED},
+	{"list_view_visible_columns", "metadata::" NAUTILUS_METADATA_KEY_LIST_VIEW_VISIBLE_COLUMNS},
+	{"list_view_column_order", "metadata::" NAUTILUS_METADATA_KEY_LIST_VIEW_COLUMN_ORDER},
+	{"compact_view_zoom_level", "metadata::" NAUTILUS_METADATA_KEY_COMPACT_VIEW_ZOOM_LEVEL},
+	{"window_geometry", "metadata::" NAUTILUS_METADATA_KEY_WINDOW_GEOMETRY},
+	{"window_scroll_position", "metadata::" NAUTILUS_METADATA_KEY_WINDOW_SCROLL_POSITION},
+	{"window_show_hidden_files", "metadata::" NAUTILUS_METADATA_KEY_WINDOW_SHOW_HIDDEN_FILES},
+	{"window_maximized", "metadata::" NAUTILUS_METADATA_KEY_WINDOW_MAXIMIZED},
+	{"window_sticky", "metadata::" NAUTILUS_METADATA_KEY_WINDOW_STICKY},
+	{"window_keep_above", "metadata::" NAUTILUS_METADATA_KEY_WINDOW_KEEP_ABOVE},
+	{"sidebar_background_color", "metadata::" NAUTILUS_METADATA_KEY_SIDEBAR_BACKGROUND_COLOR},
+	{"sidebar_background_tile_image", "metadata::" NAUTILUS_METADATA_KEY_SIDEBAR_BACKGROUND_IMAGE},
+	{"sidebar_buttons", "metadata::" NAUTILUS_METADATA_KEY_SIDEBAR_BUTTONS},
+	{"annotation", "metadata::" NAUTILUS_METADATA_KEY_ANNOTATION},
+	{"icon_position", "metadata::" NAUTILUS_METADATA_KEY_ICON_POSITION},
+	{"icon_position_timestamp", "metadata::" NAUTILUS_METADATA_KEY_ICON_POSITION_TIMESTAMP},
+	{"icon_scale", "metadata::" NAUTILUS_METADATA_KEY_ICON_SCALE},
+	{"custom_icon", "metadata::" NAUTILUS_METADATA_KEY_CUSTOM_ICON},
+	{"screen", "metadata::" NAUTILUS_METADATA_KEY_SCREEN},
+	{"keyword", "metadata::" NAUTILUS_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-nautilus-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_nautilus_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_nautilus_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 ("<nautilus metadata files> - convert nautilus 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 (),
+						 ".nautilus/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_nautilus_file (file);
+				g_free (file);
+			}
+			g_dir_close (dir);
+		}
+		g_free (metafile_dir);
+	} else {
+		for (i = 1; i < argc; i++) {
+			convert_nautilus_file (argv[i]);
+		}
+	}
+
+	return 0;
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]