From 33b7df96e9481e054c0f813840f299dd9118b77f Mon Sep 17 00:00:00 2001 From: Christian Persch Date: Wed, 3 Sep 2003 12:16:19 +0000 Subject: Rewrote xbel bookmarks importer using xmlreader api. Should fix bug 2003-09-03 Christian Persch * src/bookmarks/ephy-bookmarks-import.c: (xbel_parse_single_bookmark), (xbel_parse_bookmark), (xbel_parse_folder), (xbel_parse_bookmarks), (ephy_bookmarks_import_xbel): Rewrote xbel bookmarks importer using xmlreader api. Should fix bug 120803. * configure.in: Require libxml2 >= 2.5.9 --- ChangeLog | 13 ++ configure.in | 4 +- src/bookmarks/ephy-bookmarks-import.c | 339 ++++++++++++++++++++++++++-------- 3 files changed, 274 insertions(+), 82 deletions(-) diff --git a/ChangeLog b/ChangeLog index 025550f3e..8a63d033c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2003-09-03 Christian Persch + + * src/bookmarks/ephy-bookmarks-import.c: (xbel_parse_single_bookmark), + (xbel_parse_bookmark), (xbel_parse_folder), (xbel_parse_bookmarks), + (ephy_bookmarks_import_xbel): + + Rewrote xbel bookmarks importer using xmlreader api. Should fix + bug 120803. + + * configure.in: + + Require libxml2 >= 2.5.9 + 2003-09-03 Christian Persch * src/bookmarks/ephy-bookmarks-editor.c: (add_bookmarks_source_menu), diff --git a/configure.in b/configure.in index fcc09bdc4..94639a035 100644 --- a/configure.in +++ b/configure.in @@ -16,9 +16,11 @@ ACLOCAL="$ACLOCAL $ACLOCAL_FLAGS" GTK_REQUIRED=2.3 LIBBONOBOUI_REQUIRED=2.1.1 +LIBXML_REQUIRED=2.5.9 AC_SUBST(LIBBONOBOUI_REQUIRED) AC_SUBST(GTK_REQUIRED) +AC_SUBST(LIBXML_REQUIRED) AC_ENABLE_SHARED(yes) AC_ENABLE_STATIC(no) @@ -66,7 +68,7 @@ fi AC_MSG_RESULT($enable_nautilus_view) AM_CONDITIONAL(ENABLE_NAUTILUS_VIEW, test "x$enable_nautilus_view" = "xyes") -PKG_CHECK_MODULES(EPIPHANY_DEPENDENCY, gtk+-2.0 >= $GTK_REQUIRED libxml-2.0 libgnomeui-2.0 libglade-2.0 bonobo-activation-2.0 libbonoboui-2.0 >= $LIBBONOBOUI_REQUIRED ORBit-2.0 libglade-2.0 gnome-vfs-2.0 gnome-vfs-module-2.0 gconf-2.0 $nautilusview_pkgs) +PKG_CHECK_MODULES(EPIPHANY_DEPENDENCY, gtk+-2.0 >= $GTK_REQUIRED libxml-2.0 >= $LIBXML_REQUIRED libgnomeui-2.0 libglade-2.0 bonobo-activation-2.0 libbonoboui-2.0 >= $LIBBONOBOUI_REQUIRED ORBit-2.0 libglade-2.0 gnome-vfs-2.0 gnome-vfs-module-2.0 gconf-2.0 $nautilusview_pkgs) AC_SUBST(EPIPHANY_DEPENDENCY_CFLAGS) AC_SUBST(EPIPHANY_DEPENDENCY_LIBS) diff --git a/src/bookmarks/ephy-bookmarks-import.c b/src/bookmarks/ephy-bookmarks-import.c index 3ebffe624..1310ef0f8 100644 --- a/src/bookmarks/ephy-bookmarks-import.c +++ b/src/bookmarks/ephy-bookmarks-import.c @@ -14,13 +14,22 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Id$ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include +#include #include #include +#include + #include "ephy-bookmarks-import.h" #include "ephy-debug.h" @@ -37,12 +46,6 @@ typedef enum NS_UNKNOWN } NSItemType; -typedef struct _XbelInfo -{ - char *title; - char *smarturl; -} XbelInfo; - static EphyNode * bookmark_add (EphyBookmarks *bookmarks, const char *title, @@ -103,113 +106,285 @@ ephy_bookmarks_import (EphyBookmarks *bookmarks, return FALSE; } -static void -xbel_parse_single_bookmark (EphyBookmarks *bookmarks, - xmlNodePtr node, XbelInfo *xbel) +/* XBEL import */ + +typedef enum { - xmlNodePtr child = node; + STATE_FOLDER, + STATE_BOOKMARK, + STATE_TITLE, + STATE_DESC, + STATE_INFO, + STATE_METADATA, + STATE_SMARTURL +} EphyXBELImporterState; - while (child != NULL) +static EphyNode * +xbel_parse_bookmark (EphyBookmarks *eb, xmlTextReaderPtr reader) +{ + EphyXBELImporterState state = STATE_BOOKMARK; + EphyNode *node; + xmlChar *title = NULL; + xmlChar *address = NULL; + int ret = 1; + + while (ret == 1) { - if (xmlStrEqual (child->name, "title")) + xmlChar *tag; + xmlReaderTypes type; + + tag = xmlTextReaderName (reader); + g_return_val_if_fail (tag != NULL, NULL); + + type = xmlTextReaderNodeType (reader); + + if (xmlStrEqual (tag, "#text")) + { + if (state == STATE_TITLE && title == NULL) + { + title = xmlTextReaderValue (reader); + } + else if (state == STATE_SMARTURL) + { + xmlFree (address); + address = xmlTextReaderValue (reader); + } + else + { + /* eat it */ + } + } + else if (xmlStrEqual (tag, "bookmark")) + { + if (type == XML_READER_TYPE_ELEMENT && state == STATE_BOOKMARK && address == NULL) + { + address = xmlTextReaderGetAttribute (reader, "href"); + } + else if (type == XML_READER_TYPE_END_ELEMENT && state == STATE_BOOKMARK) + { + /* we're done */ + + break; + } + } + else if (xmlStrEqual (tag, "title")) + { + if (type == XML_READER_TYPE_ELEMENT && state == STATE_BOOKMARK && title == NULL) + { + state = STATE_TITLE; + } + else if (type == XML_READER_TYPE_END_ELEMENT && state == STATE_TITLE) + { + state = STATE_BOOKMARK; + } + } + else if (xmlStrEqual (tag, "desc")) { - xbel->title = xmlNodeGetContent (child); + if (type == XML_READER_TYPE_ELEMENT && state == STATE_BOOKMARK) + { + state = STATE_DESC; + } + else if (type == XML_READER_TYPE_END_ELEMENT && state == STATE_DESC) + { + state = STATE_BOOKMARK; + } } - else if (xmlStrEqual (child->name, "info")) + else if (xmlStrEqual (tag, "info")) { - xbel_parse_single_bookmark (bookmarks, - child->children, - xbel); + if (type == XML_READER_TYPE_ELEMENT && state == STATE_BOOKMARK) + { + state = STATE_INFO; + } + else if (type == XML_READER_TYPE_END_ELEMENT && state == STATE_INFO) + { + state = STATE_BOOKMARK; + } } - else if (xmlStrEqual (child->name, "metadata")) + else if (xmlStrEqual (tag, "metadata")) { - xbel_parse_single_bookmark (bookmarks, - child->children, - xbel); + if (type == XML_READER_TYPE_ELEMENT && state == STATE_INFO) + { + state = STATE_METADATA; + } + else if (type == XML_READER_TYPE_END_ELEMENT && state == STATE_METADATA) + { + state = STATE_INFO; + } } - else if (xmlStrEqual (child->name, "smarturl")) + else if (xmlStrEqual (tag, "smarturl")) { - xbel->smarturl = xmlNodeGetContent (child); + if (type == XML_READER_TYPE_ELEMENT && state == STATE_METADATA) + { + state = STATE_SMARTURL; + } + else if (type == XML_READER_TYPE_END_ELEMENT && state == STATE_SMARTURL) + { + state = STATE_METADATA; + } } - child = child->next; + xmlFree (tag); + + /* next one, please */ + ret = xmlTextReaderRead (reader); + } + + g_return_val_if_fail (address != NULL, NULL); + + if (title == NULL) + { + title = xmlStrdup (_("Untitled")); } + + node = bookmark_add (eb, title, address, NULL); + if (node == NULL) + { + /* probably a duplicate */ + node = ephy_bookmarks_find_bookmark (eb, address); + } + + xmlFree (title); + xmlFree (address); + + return node; } -static void -xbel_parse_folder (EphyBookmarks *bookmarks, - xmlNodePtr node) +static GList * +xbel_parse_folder (EphyBookmarks *eb, xmlTextReaderPtr reader) { - xmlNodePtr child = node; - xmlChar *keyword = NULL; + EphyXBELImporterState state = STATE_FOLDER; + EphyNode *keyword; + GList *list = NULL, *l; + xmlChar *title = NULL; + int ret; - while (child != NULL) + ret = xmlTextReaderRead (reader); + + while (ret == 1) { - if (xmlStrEqual (child->name, "title")) + xmlChar *tag; + xmlReaderTypes type; + + tag = xmlTextReaderName (reader); + type = xmlTextReaderNodeType (reader); + + if (tag == NULL) { - keyword = xmlNodeGetContent (child); + /* shouldn't happen but does anyway :) */ } - else if (xmlStrEqual (child->name, "bookmark")) + else if (xmlStrEqual (tag, "#text")) { - XbelInfo *xbel; - xmlChar *url; - - xbel = g_new0 (XbelInfo, 1); - xbel->title = NULL; - xbel->smarturl = NULL; - - url = xmlGetProp (child, "href"); - - xbel_parse_single_bookmark (bookmarks, - child->children, - xbel); + if (state == STATE_TITLE && title == NULL) + { + title = xmlTextReaderValue (reader); + } + else + { + /* eat it */ + } + } + else if (xmlStrEqual (tag, "bookmark") && type == 1 && state == STATE_FOLDER) + { + EphyNode *node; - bookmark_add (bookmarks, xbel->title, url, keyword); + node = xbel_parse_bookmark (eb, reader); - xmlFree (url); + if (EPHY_IS_NODE (node)) + { + list = g_list_prepend (list, node); + } + } + else if ((xmlStrEqual (tag, "folder") || xmlStrEqual (tag, "xbel")) + && state == STATE_FOLDER) + { + if (type == XML_READER_TYPE_ELEMENT) + { + GList *sublist; - if (xbel && xbel->title) - xmlFree (xbel->title); + sublist = xbel_parse_folder (eb, reader); - if (xbel && xbel->smarturl) - xmlFree (xbel->smarturl); + list = g_list_concat (list, sublist); + } + else if (type == XML_READER_TYPE_END_ELEMENT) + { + /* we're done */ - g_free (xbel); + break; + } } - else if (xmlStrEqual (child->name, "folder")) + else if (xmlStrEqual (tag, "title")) { - xbel_parse_folder (bookmarks, - child->children); - - g_free (keyword); - keyword = NULL; + if (type == XML_READER_TYPE_ELEMENT && state == STATE_FOLDER) + { + state = STATE_TITLE; + } + else if (type == XML_READER_TYPE_END_ELEMENT && state == STATE_TITLE) + { + state = STATE_FOLDER; + } + } + else if (xmlStrEqual (tag, "info")) + { + if (type == XML_READER_TYPE_ELEMENT && state == STATE_FOLDER) + { + state = STATE_INFO; + } + else if (type == XML_READER_TYPE_END_ELEMENT && state == STATE_INFO) + { + state = STATE_FOLDER; + } + } + else if (xmlStrEqual (tag, "desc")) + { + if (type == XML_READER_TYPE_ELEMENT && state == STATE_FOLDER) + { + state = STATE_DESC; + } + else if (type == XML_READER_TYPE_END_ELEMENT && state == STATE_DESC) + { + state = STATE_FOLDER; + } + } + else + { + /* eat it */ } - child = child->next; + xmlFree (tag); + + /* next one, please */ + ret = xmlTextReaderRead (reader); } - g_free (keyword); -} + /* tag all bookmarks in the list with keyword %title */ + if (title == NULL) + { + title = xmlStrdup (_("Untitled")); + } + keyword = ephy_bookmarks_find_keyword (eb, title, FALSE); -static void -xbel_parse_bookmarks (EphyBookmarks *bookmarks, - xmlNodePtr node) -{ - xmlNodePtr child = node; + if (keyword == NULL) + { + keyword = ephy_bookmarks_add_keyword (eb, title); + } - while (child != NULL) + xmlFree (title); + + g_return_val_if_fail (EPHY_IS_NODE (keyword), list); + + for (l = list; l != NULL; l = l->next) { - if (xmlStrEqual (child->name, "xbel")) - { - xbel_parse_folder (bookmarks, - child->children); - } + EphyNode *node = (EphyNode *) l->data; - child = child->next; + ephy_bookmarks_set_keyword (eb, keyword, node); } + + return list; } +/* Mozilla/Netscape import */ + static gchar * gul_general_read_line_from_file (FILE *f) { @@ -430,19 +605,21 @@ gboolean ephy_bookmarks_import_xbel (EphyBookmarks *bookmarks, const char *filename) { - xmlDocPtr doc; - xmlNodePtr child; + xmlTextReaderPtr reader; + GList *list; if (g_file_test (filename, G_FILE_TEST_EXISTS) == FALSE) + { return FALSE; + } + + reader = xmlNewTextReaderFilename (filename); + g_return_val_if_fail (reader != NULL, FALSE); - doc = xmlParseFile (filename); - g_assert (doc != NULL); - - child = doc->children; - xbel_parse_bookmarks (bookmarks, child); + list = xbel_parse_folder (bookmarks, reader); - xmlFreeDoc (doc); + g_list_free (list); + xmlFreeTextReader (reader); return TRUE; } -- cgit v1.2.3