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:
parent
baaca9a061
commit
56b0a55a2d
2 changed files with 90 additions and 21 deletions
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue