Improve XBEL format compatibility and support bookmark sharing

Loading of XBEL needs to handle title and desc children of the root
element. This is equal to using the according properties.

MicroB uses metadata without an owner and uses children rather than
properties. This is against the spec but we want to handle that.

A key value leak was plugged.

If the bookmark file is absolute, we assume it is a foreign file
and we shouldn't overwrite it.
This commit is contained in:
Christian Dywan 2009-11-29 23:50:59 +01:00
parent baaca9a061
commit 56b0a55a2d
2 changed files with 90 additions and 21 deletions

View file

@ -50,6 +50,12 @@
#include <signal.h> #include <signal.h>
#endif #endif
#if HAVE_HILDON
#define BOOKMARK_FILE "/home/user/.bookmarks/MyBookmarks.xml"
#else
#define BOOKMARK_FILE "bookmarks.xbel"
#endif
#define MIDORI_HISTORY_ERROR g_quark_from_string("MIDORI_HISTORY_ERROR") #define MIDORI_HISTORY_ERROR g_quark_from_string("MIDORI_HISTORY_ERROR")
typedef enum typedef enum
@ -62,7 +68,11 @@ typedef enum
static gchar* static gchar*
build_config_filename (const gchar* filename) build_config_filename (const gchar* filename)
{ {
const gchar* path = sokoke_set_config_dir (NULL); const gchar* path;
if (g_path_is_absolute (filename))
return g_strdup (filename);
path = sokoke_set_config_dir (NULL);
return g_build_filename (path, filename, NULL); return g_build_filename (path, filename, NULL);
} }
@ -805,7 +815,7 @@ midori_bookmarks_notify_item_cb (KatzeArray* folder,
gchar* config_file; gchar* config_file;
GError* error; GError* error;
config_file = build_config_filename ("bookmarks.xbel"); config_file = build_config_filename (BOOKMARK_FILE);
error = NULL; error = NULL;
if (!midori_array_to_file (bookmarks, config_file, "xbel", &error)) if (!midori_array_to_file (bookmarks, config_file, "xbel", &error))
{ {
@ -833,7 +843,7 @@ midori_bookmarks_add_item_cb (KatzeArray* folder,
gchar* config_file; gchar* config_file;
GError* error; GError* error;
config_file = build_config_filename ("bookmarks.xbel"); config_file = build_config_filename (BOOKMARK_FILE);
error = NULL; error = NULL;
if (!midori_array_to_file (bookmarks, config_file, "xbel", &error)) if (!midori_array_to_file (bookmarks, config_file, "xbel", &error))
{ {
@ -862,7 +872,7 @@ midori_bookmarks_remove_item_cb (KatzeArray* folder,
gchar* config_file; gchar* config_file;
GError* error; GError* error;
config_file = build_config_filename ("bookmarks.xbel"); config_file = build_config_filename (BOOKMARK_FILE);
error = NULL; error = NULL;
if (!midori_array_to_file (bookmarks, config_file, "xbel", &error)) if (!midori_array_to_file (bookmarks, config_file, "xbel", &error))
{ {
@ -1864,7 +1874,7 @@ main (int argc,
} }
bookmarks = katze_array_new (KATZE_TYPE_ARRAY); bookmarks = katze_array_new (KATZE_TYPE_ARRAY);
#if HAVE_LIBXML #if HAVE_LIBXML
katze_assign (config_file, build_config_filename ("bookmarks.xbel")); katze_assign (config_file, build_config_filename (BOOKMARK_FILE));
error = NULL; error = NULL;
if (!midori_array_from_file (bookmarks, config_file, "xbel", &error)) if (!midori_array_from_file (bookmarks, config_file, "xbel", &error))
{ {
@ -2016,8 +2026,9 @@ main (int argc,
G_CALLBACK (midori_search_engines_modify_cb), search_engines); G_CALLBACK (midori_search_engines_modify_cb), search_engines);
} }
} }
katze_assign (config_file, build_config_filename ("bookmarks.xbel")); katze_assign (config_file, build_config_filename (BOOKMARK_FILE));
if (1) /* Don't save bookmarks if they are not our own */
if (!g_path_is_absolute (BOOKMARK_FILE))
{ {
g_signal_connect_after (bookmarks, "add-item", g_signal_connect_after (bookmarks, "add-item",
G_CALLBACK (midori_bookmarks_add_item_cb), bookmarks); G_CALLBACK (midori_bookmarks_add_item_cb), bookmarks);

View file

@ -93,11 +93,13 @@ katze_array_from_xmlNodePtr (xmlNodePtr cur)
{ {
key = xmlNodeGetContent (cur); key = xmlNodeGetContent (cur);
katze_item_set_name (KATZE_ITEM (array), g_strstrip ((gchar*)key)); katze_item_set_name (KATZE_ITEM (array), g_strstrip ((gchar*)key));
xmlFree (key);
} }
else if (!xmlStrcmp (cur->name, (const xmlChar*)"desc")) else if (!xmlStrcmp (cur->name, (const xmlChar*)"desc"))
{ {
key = xmlNodeGetContent (cur); key = xmlNodeGetContent (cur);
katze_item_set_text (KATZE_ITEM (array), g_strstrip ((gchar*)key)); katze_item_set_text (KATZE_ITEM (array), g_strstrip ((gchar*)key));
xmlFree (key);
} }
else if (!xmlStrcmp (cur->name, (const xmlChar*)"folder")) else if (!xmlStrcmp (cur->name, (const xmlChar*)"folder"))
{ {
@ -129,19 +131,26 @@ katze_xbel_parse_info (KatzeItem* item,
if (!xmlStrcmp (cur->name, (const xmlChar*)"metadata")) if (!xmlStrcmp (cur->name, (const xmlChar*)"metadata"))
{ {
xmlChar* owner = xmlGetProp (cur, (xmlChar*)"owner"); xmlChar* owner = xmlGetProp (cur, (xmlChar*)"owner");
g_strstrip ((gchar*)owner); if (owner)
g_strstrip ((gchar*)owner);
else
/* Albeit required, "owner" is not set by MicroB */
owner = (xmlChar*)NULL;
/* FIXME: Save metadata from unknown owners */ /* FIXME: Save metadata from unknown owners */
if (!g_strcmp0 ((gchar*)owner, "http://www.twotoasts.de")) if (!owner || !strcmp ((gchar*)owner, "http://www.twotoasts.de"))
{ {
xmlAttrPtr properties = cur->properties; xmlAttrPtr properties = cur->properties;
xmlNodePtr children = cur->children;
while (properties) while (properties)
{ {
xmlChar* value;
if (!xmlStrcmp (properties->name, (xmlChar*)"owner")) if (!xmlStrcmp (properties->name, (xmlChar*)"owner"))
{ {
properties = properties->next; properties = properties->next;
continue; continue;
} }
xmlChar* value = xmlGetProp (cur, properties->name); value = xmlGetProp (cur, properties->name);
if (properties->ns && properties->ns->prefix) if (properties->ns && properties->ns->prefix)
{ {
gchar* ns_value = g_strdup_printf ("%s:%s", gchar* ns_value = g_strdup_printf ("%s:%s",
@ -156,6 +165,26 @@ katze_xbel_parse_info (KatzeItem* item,
xmlFree (value); xmlFree (value);
properties = properties->next; properties = properties->next;
} }
while (children)
{
xmlNodePtr grand_children = children->children;
while (grand_children)
{
xmlChar* value = grand_children->content;
gchar* ns_value;
if (!owner)
ns_value = g_strdup_printf (":%s", children->name);
else if (xmlStrEqual (owner, (xmlChar*)"http://www.twotoasts.de"))
ns_value = g_strdup_printf ("midori:%s", children->name);
else /* FIXME: Save metadata from unknown owners */
ns_value = g_strdup_printf (":%s", children->name);
katze_item_set_meta_string (item, ns_value, (gchar*)value);
g_free (ns_value);
grand_children = grand_children->next;
}
children = children->next;
}
} }
xmlFree (owner); xmlFree (owner);
} }
@ -211,6 +240,16 @@ katze_array_from_xmlDocPtr (KatzeArray* array,
item = katze_item_new (); item = katze_item_new ();
else if (!xmlStrcmp (cur->name, (const xmlChar*)"info")) else if (!xmlStrcmp (cur->name, (const xmlChar*)"info"))
katze_xbel_parse_info (KATZE_ITEM (array), cur); katze_xbel_parse_info (KATZE_ITEM (array), cur);
else if (!xmlStrcmp (cur->name, (xmlChar*)"title"))
{
xmlNodePtr node = cur->xmlChildrenNode;
katze_item_set_name (KATZE_ITEM (array), (gchar*)node->content);
}
else if (!xmlStrcmp (cur->name, (xmlChar*)"desc"))
{
xmlNodePtr node = cur->xmlChildrenNode;
katze_item_set_text (KATZE_ITEM (array), (gchar*)node->content);
}
if (item) if (item)
katze_array_add_item (array, item); katze_array_add_item (array, item);
cur = cur->next; cur = cur->next;
@ -480,28 +519,47 @@ katze_item_metadata_to_xbel (KatzeItem* item)
{ {
GList* keys = katze_item_get_meta_keys (item); GList* keys = katze_item_get_meta_keys (item);
GString* markup; GString* markup;
/* FIXME: Allow specifying an alternative namespace/ URI */ GString* markdown;
const gchar* namespace_uri = "http://www.twotoasts.de"; /* FIXME: Allow specifying an alternative default namespace */
const gchar* namespace = "midori"; /* FIXME: Support foreign namespaces with their own URI */
gchar* namespace = NULL;
const gchar* namespace_uri;
gsize i; gsize i;
const gchar* key; const gchar* key;
const gchar* value;
if (!keys) if (!keys)
return g_strdup (""); return g_strdup ("");
markup = g_string_new ("<info>\n<metadata owner=\""); markup = g_string_new ("<info>\n<metadata");
g_string_append_printf (markup, "%s\"", namespace_uri); markdown = g_string_new (NULL);
i = 0; i = 0;
while ((key = g_list_nth_data (keys, i++))) while ((key = g_list_nth_data (keys, i++)))
if (katze_item_get_meta_string (item, key)) if ((value = katze_item_get_meta_string (item, key)))
{ {
gchar* escaped = gchar* escaped = g_markup_escape_text (value, -1);
g_markup_escape_text (katze_item_get_meta_string (item, key), -1); namespace = strchr (key, ':');
g_string_append_printf (markup, " %s:%s=\"%s\"", namespace, key, if (key[0] == ':') /* MicroB uses un-namespaced children */
escaped); {
key = &key[1];
g_string_append_printf (markdown, "<%s>%s</%s>\n", key, escaped, key);
}
else if (namespace)
g_string_append_printf (markup, " %s=\"%s\"", key, escaped);
else
g_string_append_printf (markup, " midori:%s=\"%s\"", key, escaped);
g_free (escaped); g_free (escaped);
} }
g_string_append_printf (markup, "/>\n</info>\n"); if (!namespace)
{
namespace_uri = "http://www.twotoasts.de";
g_string_append_printf (markup, " owner=\"%s\"", namespace_uri);
}
if (markdown->len)
g_string_append_printf (markup, ">\n%s</metadata>\n</info>\n", markdown->str);
else
g_string_append_printf (markup, "/>\n</info>\n");
g_string_free (markdown, TRUE);
return g_string_free (markup, FALSE); return g_string_free (markup, FALSE);
} }