No issues found
Tool | Failure ID | Location | Function | Message | Data |
---|---|---|---|---|---|
clang-analyzer | no-output-found | nautilus-convert-metadata.c | Message(text='Unable to locate XML output from invoke-clang-analyzer') | None |
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3 /* nautilus-convert-metadata.c - Convert old metadata format to gvfs metadata.
4 *
5 * Copyright (C) 2009 Alexander Larsson
6 *
7 * Nautilus is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version.
11 *
12 * Nautilus is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public
18 * License along with this program; see the file COPYING. If not,
19 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 *
22 * Authors:
23 * Alexander Larsson <alexl@redhat.com>
24 */
25
26 #include <config.h>
27
28 #include <glib.h>
29 #include <gio/gio.h>
30 #include <glib/gi18n.h>
31 #include <string.h>
32 #include <libxml/tree.h>
33
34 #include <libnautilus-private/nautilus-metadata.h>
35
36 static gboolean quiet = FALSE;
37
38 static xmlNodePtr
39 xml_get_children (xmlNodePtr parent)
40 {
41 if (parent == NULL) {
42 return NULL;
43 }
44 return parent->children;
45 }
46
47 static xmlNodePtr
48 xml_get_root_children (xmlDocPtr document)
49 {
50 return xml_get_children (xmlDocGetRootElement (document));
51 }
52
53
54 static char *
55 get_uri_from_nautilus_metafile_name (const char *filename)
56 {
57 GString *s;
58 char c;
59 char *base_name, *p;
60 int len;
61
62 base_name = g_path_get_basename (filename);
63 len = strlen (base_name);
64 if (len <= 4 ||
65 strcmp (base_name + len - 4, ".xml") != 0) {
66 g_free (base_name);
67 return NULL;
68 }
69 base_name[len-4] = 0;
70
71 s = g_string_new (NULL);
72
73 p = base_name;
74 while (*p) {
75 c = *p++;
76 if (c == '%') {
77 c = g_ascii_xdigit_value (p[0]) << 4 |
78 g_ascii_xdigit_value (p[1]);
79 p += 2;
80 }
81 g_string_append_c (s, c);
82 }
83 g_free (base_name);
84
85 return g_string_free (s, FALSE);
86 }
87
88 static struct {
89 const char *old_key;
90 const char *new_key;
91 } metadata_keys[] = {
92 {"background_color", "metadata::" NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_COLOR},
93 {"background_tile_image", "metadata::" NAUTILUS_METADATA_KEY_LOCATION_BACKGROUND_IMAGE},
94 {"icon_view_auto_layout", "metadata::" NAUTILUS_METADATA_KEY_ICON_VIEW_AUTO_LAYOUT},
95 {"icon_view_sort_by", "metadata::" NAUTILUS_METADATA_KEY_ICON_VIEW_SORT_BY},
96 {"icon_view_sort_reversed", "metadata::" NAUTILUS_METADATA_KEY_ICON_VIEW_SORT_REVERSED},
97 {"icon_view_keep_aligned", "metadata::" NAUTILUS_METADATA_KEY_ICON_VIEW_KEEP_ALIGNED},
98 {"icon_view_layout_timestamp", "metadata::" NAUTILUS_METADATA_KEY_ICON_VIEW_LAYOUT_TIMESTAMP},
99 {"list_view_sort_column", "metadata::" NAUTILUS_METADATA_KEY_LIST_VIEW_SORT_COLUMN},
100 {"list_view_sort_reversed", "metadata::" NAUTILUS_METADATA_KEY_LIST_VIEW_SORT_REVERSED},
101 {"list_view_visible_columns", "metadata::" NAUTILUS_METADATA_KEY_LIST_VIEW_VISIBLE_COLUMNS},
102 {"list_view_column_order", "metadata::" NAUTILUS_METADATA_KEY_LIST_VIEW_COLUMN_ORDER},
103 {"window_geometry", "metadata::" NAUTILUS_METADATA_KEY_WINDOW_GEOMETRY},
104 {"window_scroll_position", "metadata::" NAUTILUS_METADATA_KEY_WINDOW_SCROLL_POSITION},
105 {"window_show_hidden_files", "metadata::" NAUTILUS_METADATA_KEY_WINDOW_SHOW_HIDDEN_FILES},
106 {"window_maximized", "metadata::" NAUTILUS_METADATA_KEY_WINDOW_MAXIMIZED},
107 {"window_sticky", "metadata::" NAUTILUS_METADATA_KEY_WINDOW_STICKY},
108 {"window_keep_above", "metadata::" NAUTILUS_METADATA_KEY_WINDOW_KEEP_ABOVE},
109 {"sidebar_background_color", "metadata::" NAUTILUS_METADATA_KEY_SIDEBAR_BACKGROUND_COLOR},
110 {"sidebar_background_tile_image", "metadata::" NAUTILUS_METADATA_KEY_SIDEBAR_BACKGROUND_IMAGE},
111 {"sidebar_buttons", "metadata::" NAUTILUS_METADATA_KEY_SIDEBAR_BUTTONS},
112 {"annotation", "metadata::" NAUTILUS_METADATA_KEY_ANNOTATION},
113 {"icon_position", "metadata::" NAUTILUS_METADATA_KEY_ICON_POSITION},
114 {"icon_position_timestamp", "metadata::" NAUTILUS_METADATA_KEY_ICON_POSITION_TIMESTAMP},
115 {"icon_scale", "metadata::" NAUTILUS_METADATA_KEY_ICON_SCALE},
116 {"custom_icon", "metadata::" NAUTILUS_METADATA_KEY_CUSTOM_ICON},
117 {"screen", "metadata::" NAUTILUS_METADATA_KEY_SCREEN},
118 {"keyword", "metadata::" NAUTILUS_METADATA_KEY_EMBLEMS},
119 };
120
121 static const char *
122 convert_key_name (const char *old_key)
123 {
124 int i;
125
126 for (i = 0; i < G_N_ELEMENTS (metadata_keys); i++) {
127 if (strcmp (metadata_keys[i].old_key, old_key) == 0) {
128 return metadata_keys[i].new_key;
129 }
130 }
131
132 return NULL;
133 }
134
135 static void
136 parse_xml_node (GFile *file,
137 xmlNodePtr filenode)
138 {
139 xmlNodePtr node;
140 xmlAttrPtr attr;
141 xmlChar *property;
142 const char *new_key;
143 GHashTable *list_keys;
144 GList *keys, *l;
145 GHashTableIter iter;
146 GFileInfo *info;
147 int i;
148 char **strv;
149 GError *error;
150
151 info = g_file_info_new ();
152
153 for (attr = filenode->properties; attr != NULL; attr = attr->next) {
154 if (strcmp ((char *)attr->name, "name") == 0 ||
155 strcmp ((char *)attr->name, "timestamp") == 0) {
156 continue;
157 }
158
159 new_key = convert_key_name ((const gchar *) attr->name);
160 if (new_key) {
161 property = xmlGetProp (filenode, attr->name);
162 if (property) {
163 g_file_info_set_attribute_string (info,
164 new_key,
165 (const gchar *) property);
166 xmlFree (property);
167 }
168 }
169 }
170
171 list_keys = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
172 for (node = filenode->children; node != NULL; node = node->next) {
173 for (attr = node->properties; attr != NULL; attr = attr->next) {
174 new_key = convert_key_name ((const gchar *) node->name);
175 if (new_key) {
176 property = xmlGetProp (node, attr->name);
177 if (property) {
178 keys = g_hash_table_lookup (list_keys, new_key);
179 keys = g_list_append (keys, property);
180 g_hash_table_replace (list_keys, (char *)new_key, keys);
181 }
182 }
183 }
184 }
185
186 g_hash_table_iter_init (&iter, list_keys);
187 while (g_hash_table_iter_next (&iter, (void **)&new_key, (void **)&keys)) {
188 strv = g_new0 (char *, g_list_length (keys) + 1);
189
190 for (l = keys, i = 0; l != NULL; l = l->next, i++) {
191 strv[i] = l->data;
192 }
193 g_file_info_set_attribute_stringv (info,
194 new_key,
195 strv);
196 g_free (strv);
197 g_list_foreach (keys, (GFunc)xmlFree, NULL);
198 g_list_free (keys);
199 }
200 g_hash_table_destroy (list_keys);
201
202 if (info) {
203 error = NULL;
204 if (!g_file_set_attributes_from_info (file,
205 info,
206 0, NULL, &error)) {
207 char *uri;
208
209 uri = g_file_get_uri (file);
210 if (!quiet) {
211 g_print ("error setting info for %s: %s\n", uri, error->message);
212 }
213 g_free (uri);
214 g_error_free (error);
215 }
216 g_object_unref (info);
217 }
218 }
219
220 static void
221 convert_xml_file (xmlDocPtr xml,
222 GFile *dir)
223 {
224 xmlNodePtr node;
225 xmlChar *name;
226 char *unescaped_name;
227 GFile *file;
228
229 for (node = xml_get_root_children (xml);
230 node != NULL; node = node->next) {
231 if (strcmp ((char *)node->name, "file") == 0) {
232 name = xmlGetProp (node, (xmlChar *)"name");
233 unescaped_name = g_uri_unescape_string ((char *)name, "/");
234 xmlFree (name);
235
236 if (unescaped_name == NULL) {
237 continue;
238 }
239
240 if (strcmp (unescaped_name, ".") == 0) {
241 file = g_object_ref (dir);
242 } else {
243 file = g_file_get_child (dir, unescaped_name);
244 }
245
246 parse_xml_node (file, node);
247 g_object_unref (file);
248 g_free (unescaped_name);
249 }
250 }
251 }
252
253 static void
254 convert_nautilus_file (char *file)
255 {
256 GFile *dir;
257 char *uri;
258 gchar *contents;
259 gsize length;
260 xmlDocPtr xml;
261
262 if (!g_file_get_contents (file, &contents, &length, NULL)) {
263 if (!quiet) {
264 g_print ("failed to load %s\n", file);
265 }
266 return;
267 }
268
269 uri = get_uri_from_nautilus_metafile_name (file);
270 if (uri == NULL) {
271 g_free (contents);
272 return;
273 }
274
275 dir = g_file_new_for_uri (uri);
276 g_free (uri);
277
278 xml = xmlParseMemory (contents, length);
279 g_free (contents);
280 if (xml == NULL) {
281 return;
282 }
283
284 convert_xml_file (xml, dir);
285 xmlFreeDoc (xml);
286 }
287
288 static GOptionEntry entries[] =
289 {
290 { "quiet", 'q', 0, G_OPTION_ARG_NONE, &quiet,
291 "Don't show errors", NULL },
292 { NULL }
293 };
294
295 int
296 main (int argc, char *argv[])
297 {
298 GOptionContext *context;
299 GError *error = NULL;
300 int i;
301
302 g_type_init ();
303
304 context = g_option_context_new ("<nautilus metadata files> - convert nautilus metadata");
305 g_option_context_add_main_entries (context, entries, NULL);
306 if (!g_option_context_parse (context, &argc, &argv, &error)) {
307 g_printerr ("option parsing failed: %s\n", error->message);
308 return 1;
309 }
310
311 if (argc < 2) {
312 GDir *dir;
313 char *metafile_dir;
314 char *file;
315 const char *entry;
316
317 /* Convert all metafiles */
318
319 metafile_dir = g_build_filename (g_get_home_dir (),
320 ".nautilus/metafiles", NULL);
321
322 dir = g_dir_open (metafile_dir, 0, NULL);
323 if (dir) {
324 while ((entry = g_dir_read_name (dir)) != NULL) {
325 file = g_build_filename (metafile_dir, entry, NULL);
326 if (g_str_has_suffix (file, ".xml"))
327 convert_nautilus_file (file);
328 g_free (file);
329 }
330 g_dir_close (dir);
331 }
332 g_free (metafile_dir);
333 } else {
334 for (i = 1; i < argc; i++) {
335 convert_nautilus_file (argv[i]);
336 }
337 }
338
339 return 0;
340 }