mirror of https://gitee.com/openkylin/gvfs.git
221 lines
4.5 KiB
C
221 lines
4.5 KiB
C
#include <string.h>
|
|
#include "metabuilder.h"
|
|
#include <libxml/tree.h>
|
|
|
|
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 void
|
|
parse_xml_node (MetaFile *metafile,
|
|
xmlNodePtr filenode)
|
|
{
|
|
xmlChar *data;
|
|
guint64 timestamp;
|
|
xmlNodePtr node;
|
|
xmlAttrPtr attr;
|
|
xmlChar *property;
|
|
char *combined_key;
|
|
|
|
data = xmlGetProp (filenode, (xmlChar *)"timestamp");
|
|
if (data)
|
|
{
|
|
timestamp = g_ascii_strtoll ((char *)data, NULL, 10);
|
|
if (timestamp != 0)
|
|
metafile->last_changed = timestamp;
|
|
}
|
|
|
|
for (attr = filenode->properties; attr != NULL; attr = attr->next)
|
|
{
|
|
if (strcmp ((char *)attr->name, "name") == 0 ||
|
|
strcmp ((char *)attr->name, "timestamp") == 0)
|
|
continue;
|
|
|
|
property = xmlGetProp (filenode, attr->name);
|
|
if (property)
|
|
metafile_key_set_value (metafile, (char *)attr->name, (char *)property);
|
|
xmlFree (property);
|
|
}
|
|
|
|
for (node = filenode->children; node != NULL; node = node->next)
|
|
{
|
|
for (attr = node->properties; attr != NULL; attr = attr->next)
|
|
{
|
|
property = xmlGetProp (node, attr->name);
|
|
if (property)
|
|
{
|
|
combined_key = g_strconcat ((char *)node->name,
|
|
"-",
|
|
(char *)attr->name,
|
|
NULL);
|
|
metafile_key_list_add (metafile, combined_key, (char *)property);
|
|
g_free (combined_key);
|
|
}
|
|
xmlFree (property);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
parse_xml_file (MetaBuilder *builder,
|
|
xmlDocPtr xml,
|
|
char *dir)
|
|
{
|
|
xmlNodePtr node;
|
|
xmlChar *name;
|
|
char *unescaped_name;
|
|
MetaFile *dir_metafile, *metafile;
|
|
|
|
dir_metafile = meta_builder_lookup (builder, dir, TRUE);
|
|
|
|
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 (strcmp (unescaped_name, ".") == 0)
|
|
metafile = dir_metafile;
|
|
else
|
|
metafile = metafile_lookup_child (dir_metafile, unescaped_name, TRUE);
|
|
|
|
parse_xml_node (metafile, node);
|
|
g_free (unescaped_name);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
parse_nautilus_file (MetaBuilder *builder,
|
|
char *file)
|
|
{
|
|
char *uri;
|
|
char *dir;
|
|
gchar *contents;
|
|
gsize length;
|
|
xmlDocPtr xml;
|
|
|
|
if (!g_file_get_contents (file, &contents, &length, NULL))
|
|
{
|
|
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_filename_from_uri (uri, NULL, NULL);
|
|
g_free (uri);
|
|
if (dir == NULL)
|
|
{
|
|
g_free (contents);
|
|
return;
|
|
}
|
|
|
|
xml = xmlParseMemory (contents, length);
|
|
g_free (contents);
|
|
if (xml == NULL)
|
|
return;
|
|
|
|
parse_xml_file (builder, xml, dir);
|
|
xmlFreeDoc (xml);
|
|
}
|
|
|
|
/*static gboolean recursive = FALSE;*/
|
|
static char *filename = NULL;
|
|
static GOptionEntry entries[] =
|
|
{
|
|
{ "out", 'o', 0, G_OPTION_ARG_FILENAME, &filename, "Output filename", NULL },
|
|
{ NULL }
|
|
};
|
|
|
|
int
|
|
main (int argc, char *argv[])
|
|
{
|
|
GOptionContext *context;
|
|
MetaBuilder *builder;
|
|
GError *error = NULL;
|
|
int i;
|
|
|
|
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)
|
|
{
|
|
g_print ("No files specified\n");
|
|
return 1;
|
|
}
|
|
|
|
builder = meta_builder_new ();
|
|
for (i = 1; i < argc; i++)
|
|
parse_nautilus_file (builder, argv[i]);
|
|
if (filename)
|
|
meta_builder_write (builder, filename);
|
|
else
|
|
meta_builder_print (builder);
|
|
|
|
return 0;
|
|
}
|