[libgrss] New "FeedsGroup" object, to parse and produce groups of feeds Added OPML files parser



commit 0ed8c4843434e53438db4b797851664ea4fa58a2
Author: Roberto Guido <bob4mail gmail com>
Date:   Sun Mar 28 17:31:53 2010 +0200

    New "FeedsGroup" object, to parse and produce groups of feeds
    Added OPML files parser

 src/Makefile.am                |   58 +++++----
 src/feed-atom-handler.c        |    6 +-
 src/feed-channel.c             |    2 +-
 src/feed-parser.c              |    2 +-
 src/feeds-group-handler.c      |  114 +++++++++++++++++
 src/feeds-group-handler.h      |   49 ++++++++
 src/feeds-group.c              |  193 +++++++++++++++++++++++++++++
 src/feeds-group.h              |   52 ++++++++
 src/feeds-opml-group-handler.c |  267 ++++++++++++++++++++++++++++++++++++++++
 src/feeds-opml-group-handler.h |   50 ++++++++
 src/feeds-pool.c               |    2 +-
 src/feeds-subscriber.c         |    2 +-
 src/libgrss.h                  |    1 +
 src/utils.c                    |    2 +-
 src/utils.h                    |    2 +-
 15 files changed, 767 insertions(+), 35 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 93c9be7..e3d8afb 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -14,35 +14,41 @@ sources_private_h = \
 	utils.h
 
 sources_public_h = \
-	common.h            \
-	libgrss.h           \
-	feed-atom-handler.h \
-	feed-channel.h      \
-	feed-enclosure.h    \
-	feed-handler.h      \
-	feed-item.h         \
-	feed-parser.h       \
-	feed-rss-handler.h  \
-	feed-pie-handler.h  \
-	feeds-pool.h        \
-	feeds-store.h       \
-	feeds-subscriber.h  \
+	common.h                   \
+	libgrss.h                  \
+	feed-atom-handler.h        \
+	feed-channel.h             \
+	feed-enclosure.h           \
+	feed-handler.h             \
+	feed-item.h                \
+	feed-parser.h              \
+	feed-rss-handler.h         \
+	feed-pie-handler.h         \
+	feeds-group.h              \
+	feeds-group-handler.h      \
+	feeds-opml-group-handler.h \
+	feeds-pool.h               \
+	feeds-store.h              \
+	feeds-subscriber.h         \
 	ns-handler.h
 
 sources_c = \
-	$(marshal_source)   \
-	feed-atom-handler.c \
-	feed-channel.c      \
-	feed-enclosure.c    \
-	feed-handler.c      \
-	feed-item.c         \
-	feed-parser.c       \
-	feed-rss-handler.c  \
-	feed-pie-handler.c  \
-	feeds-pool.c        \
-	feeds-store.c       \
-	feeds-subscriber.c  \
-	ns-handler.c        \
+	$(marshal_source)          \
+	feed-atom-handler.c        \
+	feed-channel.c             \
+	feed-enclosure.c           \
+	feed-handler.c             \
+	feed-item.c                \
+	feed-parser.c              \
+	feed-rss-handler.c         \
+	feed-pie-handler.c         \
+	feeds-group.c              \
+	feeds-group-handler.c      \
+	feeds-opml-group-handler.c \
+	feeds-pool.c               \
+	feeds-store.c              \
+	feeds-subscriber.c         \
+	ns-handler.c               \
 	utils.c
 
 marshal_source = \
diff --git a/src/feed-atom-handler.c b/src/feed-atom-handler.c
index 3ec23d5..72247ee 100644
--- a/src/feed-atom-handler.c
+++ b/src/feed-atom-handler.c
@@ -305,13 +305,13 @@ atom10_parse_person_construct (xmlNodePtr cur)
 			if (xmlStrEqual (cur->name, BAD_CAST"email")) {
 				if (email)
 					invalid = TRUE;
-				g_free(email);
+				g_free (email);
 				tmp = (gchar *)xmlNodeListGetString(cur->doc, cur->xmlChildrenNode, 1);
 				email = g_strdup_printf(" - <a href=\"mailto:%s\";>%s</a>", tmp, tmp);
 				g_free(tmp);
 			}
 
-			if (xmlStrEqual(cur->name, BAD_CAST"uri")) {
+			if (xmlStrEqual (cur->name, BAD_CAST"uri")) {
 				if (!uri)
 					invalid = TRUE;
 				g_free (uri);
@@ -599,7 +599,7 @@ atom10_parse_entry (FeedHandler *self, FeedChannel *feed, xmlNodePtr cur)
 		}
 
 
-		if (xmlStrcmp(cur->ns->href, ATOM10_NS)) {
+		if (xmlStrcmp (cur->ns->href, ATOM10_NS)) {
 			cur = cur->next;
 			continue;
 		}
diff --git a/src/feed-channel.c b/src/feed-channel.c
index c68c1c6..6535edd 100644
--- a/src/feed-channel.c
+++ b/src/feed-channel.c
@@ -667,7 +667,7 @@ feed_channel_fetch (FeedChannel *channel)
 	status = soup_session_send_message (session, msg);
 
 	if (status >= 200 && status <= 299) {
-		doc = feed_content_to_xml (msg->response_body->data, msg->response_body->length);
+		doc = content_to_xml (msg->response_body->data, msg->response_body->length);
 
 		if (doc != NULL) {
 			parser = feed_parser_new ();
diff --git a/src/feed-parser.c b/src/feed-parser.c
index 7e237f3..d95d381 100644
--- a/src/feed-parser.c
+++ b/src/feed-parser.c
@@ -86,7 +86,7 @@ feed_parser_init (FeedParser *object)
 	object->priv = FEED_PARSER_GET_PRIVATE (object);
 }
 
-static GSList *
+static GSList*
 feed_parsers_get_list (FeedParser *parser)
 {
 	FeedHandler *feed;
diff --git a/src/feeds-group-handler.c b/src/feeds-group-handler.c
new file mode 100644
index 0000000..eea04a1
--- /dev/null
+++ b/src/feeds-group-handler.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2010, Roberto Guido <rguido src gnome org>
+ *                     Michele Tameni <michele amdplanet it>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#include "utils.h"
+#include "feeds-group-handler.h"
+
+/**
+ * SECTION: feeds-group-handler
+ * @short_description: interface for specialized groups parsers
+ *
+ * The #FeedsGroupHandler interface defines a unique API for all specialized
+ * groups parsers implementations
+ */
+
+static void
+feeds_group_handler_base_init (gpointer g_class)
+{
+}
+
+GType
+feeds_group_handler_get_type ()
+{
+	static GType iface_type = 0;
+
+	if (iface_type == 0) {
+		static const GTypeInfo info = {
+			sizeof (FeedsGroupHandlerInterface),
+			feeds_group_handler_base_init,
+			NULL,
+		};
+
+		iface_type = g_type_register_static (G_TYPE_INTERFACE, "FeedsGroupHandler", &info, 0);
+	}
+
+	return iface_type;
+}
+
+/**
+ * feeds_group_handler_check_format:
+ * @self: a #FeedsGroupHandler
+ * @doc: XML document from a parsed feed
+ * @cur: first valid  node into the XML document
+ *
+ * Used to check validity of an XML document against the given group parser
+ *
+ * Return value: %TRUE if the document can be parsed with the given
+ * #FeedsGroupHandler, %FALSE otherwise
+ */
+gboolean
+feeds_group_handler_check_format (FeedsGroupHandler *self, xmlDocPtr doc, xmlNodePtr cur)
+{
+	if (IS_FEEDS_GROUP_HANDLER (self) == FALSE)
+		return FALSE;
+
+	return FEEDS_GROUP_HANDLER_GET_INTERFACE (self)->check_format (self, doc, cur);
+}
+
+/**
+ * feeds_group_handler_parse:
+ * @self: a #FeedsGroupHandler
+ * @doc: XML document from the feed
+ * @error: location for eventual errors
+ *
+ * Parses the given @doc and extracts a list of #FeedChannels
+ *
+ * Return value: a list of #FeedChannels, to be freed when no longer in use,
+ * or %NULL if an error occours (and @error is set accordly)
+ */
+GList*
+feeds_group_handler_parse (FeedsGroupHandler *self, xmlDocPtr doc, GError *error)
+{
+	if (IS_FEEDS_GROUP_HANDLER (self) == FALSE)
+		return FALSE;
+
+	return FEEDS_GROUP_HANDLER_GET_INTERFACE (self)->parse (self, doc, error);
+}
+
+/**
+ * feeds_group_handler_dump:
+ * @self: a #FeedsGroupHandler
+ * @channels: list of #FeedChannels
+ * @error: location for eventual errors
+ *
+ * Builds a rappresentation of the given list of @channels for the managed
+ * group type
+ *
+ * Return value: a text to be dump on a file or transmitted, to be freed when
+ * no longer in use, or %NULL if an error occours (and @error is set accordly)
+ */
+gchar*
+feeds_group_handler_dump (FeedsGroupHandler *self, GList *channels, GError *error)
+{
+	if (IS_FEEDS_GROUP_HANDLER (self) == FALSE)
+		return FALSE;
+
+	return FEEDS_GROUP_HANDLER_GET_INTERFACE (self)->dump (self, channels, error);
+}
diff --git a/src/feeds-group-handler.h b/src/feeds-group-handler.h
new file mode 100644
index 0000000..7eb82d8
--- /dev/null
+++ b/src/feeds-group-handler.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2010, Roberto Guido <rguido src gnome org>
+ *                     Michele Tameni <michele amdplanet it>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __FEEDS_GROUP_HANDLER_H__
+#define __FEEDS_GROUP_HANDLER_H__
+
+#include "common.h"
+#include "feed-channel.h"
+
+#define FEEDS_GROUP_HANDLER_TYPE		(feeds_group_handler_get_type ())
+#define FEEDS_GROUP_HANDLER(obj)		(G_TYPE_CHECK_INSTANCE_CAST ((obj), FEEDS_GROUP_HANDLER_TYPE, FeedsGroupHandler))
+#define IS_FEEDS_GROUP_HANDLER(obj)		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), FEEDS_GROUP_HANDLER_TYPE))
+#define FEEDS_GROUP_HANDLER_GET_INTERFACE(inst)	(G_TYPE_INSTANCE_GET_INTERFACE ((inst), FEEDS_GROUP_HANDLER_TYPE, FeedsGroupHandlerInterface))
+
+typedef struct _FeedsGroupHandler		FeedsGroupHandler;
+typedef struct _FeedsGroupHandlerInterface	FeedsGroupHandlerInterface;
+
+struct _FeedsGroupHandlerInterface {
+	GTypeInterface parent_iface;
+
+	gboolean (*check_format) (FeedsGroupHandler *self, xmlDocPtr doc, xmlNodePtr cur);
+	GList* (*parse) (FeedsGroupHandler *self, xmlDocPtr doc, GError *error);
+	gchar* (*dump) (FeedsGroupHandler *self, GList *channels, GError *error);
+};
+
+GType		feeds_group_handler_get_type		();
+
+gboolean	feeds_group_handler_check_format	(FeedsGroupHandler *self, xmlDocPtr doc, xmlNodePtr cur);
+GList*		feeds_group_handler_parse		(FeedsGroupHandler *self, xmlDocPtr doc, GError *error);
+gchar*		feeds_group_handler_dump		(FeedsGroupHandler *self, GList *channels, GError *error);
+
+#endif /* __FEEDS_GROUP_HANDLER_H__ */
diff --git a/src/feeds-group.c b/src/feeds-group.c
new file mode 100644
index 0000000..5ecd173
--- /dev/null
+++ b/src/feeds-group.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2010, Roberto Guido <rguido src gnome org>
+ *                     Michele Tameni <michele amdplanet it>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#include "utils.h"
+#include "feeds-group.h"
+#include "feeds-group-handler.h"
+
+#include "feeds-opml-group-handler.h"
+
+#define FEEDS_GROUP_GET_PRIVATE(o)	(G_TYPE_INSTANCE_GET_PRIVATE ((o), FEEDS_GROUP_TYPE, FeedsGroupPrivate))
+
+/**
+ * SECTION: feeds-group
+ * @short_description: import and export group of channels
+ *
+ * #FeedsGroup is an utility to import and export list of #FeedChannels in
+ * different formats, such as OPML
+ */
+
+#define FEEDS_GROUP_ERROR		feeds_group_error_quark()
+
+struct _FeedsGroupPrivate {
+	GSList *handlers;
+};
+
+enum {
+	FEEDS_GROUP_PARSE_ERROR,
+};
+
+G_DEFINE_TYPE (FeedsGroup, feeds_group, G_TYPE_OBJECT)
+
+static GQuark
+feeds_group_error_quark ()
+{
+	return g_quark_from_static_string ("feeds_group_error");
+}
+
+static void
+feeds_group_finalize (GObject *object)
+{
+	FeedsGroup *group;
+
+	group = FEEDS_GROUP (object);
+	G_OBJECT_CLASS (feeds_group_parent_class)->finalize (object);
+}
+
+static void
+feeds_group_class_init (FeedsGroupClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (object_class, sizeof (FeedsGroupPrivate));
+	object_class->finalize = feeds_group_finalize;
+}
+
+static void
+feeds_group_init (FeedsGroup *object)
+{
+	object->priv = FEEDS_GROUP_GET_PRIVATE (object);
+}
+
+static GSList*
+feeds_groups_get_list (FeedsGroup *group)
+{
+	FeedsGroupHandler *parser;
+
+	if (group->priv->handlers == NULL) {
+		/*
+			TODO	Parsers may be dinamically loaded and managed as external plugins
+		*/
+
+		parser = FEEDS_GROUP_HANDLER (feeds_opml_group_handler_new ());
+		group->priv->handlers = g_slist_append (group->priv->handlers, parser);
+	}
+
+	return group->priv->handlers;
+}
+
+/**
+ * feeds_group_new:
+ *
+ * Allocates a new #FeedsGroup
+ *
+ * Return value: a new #FeedsGroup
+ */
+FeedsGroup*
+feeds_group_new ()
+{
+	FeedsGroup *group;
+
+	group = g_object_new (FEEDS_GROUP_TYPE, NULL);
+	return group;
+}
+
+static FeedsGroupHandler*
+retrieve_group_handler (FeedsGroup *group, xmlDocPtr doc, xmlNodePtr cur)
+{
+	GSList *iter;
+	FeedsGroupHandler *handler;
+
+	iter = feeds_groups_get_list (group);
+
+	while (iter) {
+		handler = (FeedsGroupHandler*) (iter->data);
+
+		if (handler && feeds_group_handler_check_format (handler, doc, cur))
+			return handler;
+
+		iter = g_slist_next (iter);
+	}
+
+	return NULL;
+}
+
+GList*
+feeds_group_parse_file (FeedsGroup *groups, const gchar *path, GError *error)
+{
+	gchar *contents;
+	gsize len;
+	GList *items;
+	GError *err;
+	xmlDocPtr doc;
+	xmlNodePtr cur;
+	FeedsGroupHandler *handler;
+
+	items = NULL;
+	doc = NULL;
+	contents = NULL;
+
+	do {
+		err = NULL;
+		if (g_file_get_contents (path, &contents, &len, &err) == FALSE) {
+			g_propagate_error (&error, err);
+			break;
+		}
+
+		doc = content_to_xml (contents, len);
+
+		g_set_error (&error, FEEDS_GROUP_ERROR, FEEDS_GROUP_PARSE_ERROR, "Empty document");
+
+		if ((cur = xmlDocGetRootElement (doc)) == NULL)
+			break;
+
+		while (cur && xmlIsBlankNode (cur))
+			cur = cur->next;
+
+		if (!cur)
+			break;
+
+		if (!cur->name) {
+			g_set_error (&error, FEEDS_GROUP_ERROR, FEEDS_GROUP_PARSE_ERROR, "Invalid XML");
+			break;
+		}
+
+		handler = retrieve_group_handler (groups, doc, cur);
+		if (handler == NULL)
+			break;
+
+		items = feeds_group_handler_parse (handler, doc, error);
+
+	} while (0);
+
+	if (doc != NULL)
+		xmlFreeDoc (doc);
+
+	if (contents != NULL)
+		g_free (contents);
+
+	return items;
+}
+
+gboolean
+feeds_group_export_file (FeedsGroup *groups, GList *channels, const gchar *path, GError *error)
+{
+	return FALSE;
+}
diff --git a/src/feeds-group.h b/src/feeds-group.h
new file mode 100644
index 0000000..dfa5a6d
--- /dev/null
+++ b/src/feeds-group.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2010, Roberto Guido <rguido src gnome org>
+ *                     Michele Tameni <michele amdplanet it>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __FEEDS_GROUP_H__
+#define __FEEDS_GROUP_H__
+
+#include "common.h"
+
+#define FEEDS_GROUP_TYPE		(feeds_group_get_type())
+#define FEEDS_GROUP(o)			(G_TYPE_CHECK_INSTANCE_CAST ((o), FEEDS_GROUP_TYPE, FeedsGroup))
+#define FEEDS_GROUP_CLASS(c)		(G_TYPE_CHECK_CLASS_CAST ((c), FEEDS_GROUP_TYPE, FeedsGroupClass))
+#define IS_FEEDS_GROUP(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), FEEDS_GROUP_TYPE))
+#define IS_FEEDS_GROUP_CLASS(c)		(G_TYPE_CHECK_CLASS_TYPE ((c),  FEEDS_GROUP_TYPE))
+#define FEEDS_GROUP_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), FEEDS_GROUP_TYPE, FeedsGroupClass))
+
+typedef struct _FeedsGroup		FeedsGroup;
+typedef struct _FeedsGroupPrivate	FeedsGroupPrivate;
+
+struct _FeedsGroup {
+	GObject parent;
+	FeedsGroupPrivate *priv;
+};
+
+typedef struct {
+	GObjectClass parent;
+} FeedsGroupClass;
+
+GType		feeds_group_get_type		() G_GNUC_CONST;
+
+FeedsGroup*	feeds_group_new			();
+
+GList*		feeds_group_parse_file		(FeedsGroup *groups, const gchar *path, GError *error);
+gboolean	feeds_group_export_file		(FeedsGroup *groups, GList *channels, const gchar *path, GError *error);
+
+#endif /* __FEEDS_GROUP_H__ */
diff --git a/src/feeds-opml-group-handler.c b/src/feeds-opml-group-handler.c
new file mode 100644
index 0000000..4c84f2a
--- /dev/null
+++ b/src/feeds-opml-group-handler.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2010, Roberto Guido <rguido src gnome org>
+ *                     Michele Tameni <michele amdplanet it>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+/*
+ * Original code is from Liferea:
+ *
+ * opml_source.c  OPML Planet/Blogroll feed list source
+ *
+ * Copyright (C) 2006-2010 Lars Lindner <lars lindner gmail com>
+ */
+
+#include "feeds-opml-group-handler.h"
+#include "utils.h"
+#include "feed-channel.h"
+
+#define FEEDS_OPML_GROUP_HANDLER_GET_PRIVATE(o)	(G_TYPE_INSTANCE_GET_PRIVATE ((o), FEEDS_OPML_GROUP_HANDLER_TYPE, FeedsOpmlGroupHandlerPrivate))
+
+/**
+ * SECTION: feeds-opml-group-handler
+ * @short_description: specialized parser for OPML files
+ *
+ * #FeedsOpmlGroupHandler is a #FeedsGroupHandler specialized for OPML contents
+ */
+
+struct FeedsOpmlGroupHandlerPrivate {
+	int	rfu;
+};
+
+static void feeds_group_handler_interface_init (FeedsGroupHandlerInterface *iface);
+G_DEFINE_TYPE_WITH_CODE (FeedsOpmlGroupHandler, feeds_opml_group_handler, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (FEEDS_GROUP_HANDLER_TYPE,
+                                                feeds_group_handler_interface_init));
+
+static GQuark
+feeds_opml_group_handler_error_quark ()
+{
+	return g_quark_from_static_string ("feeds_opml_group_handler_error");
+}
+
+static void
+feeds_opml_group_handler_finalize (GObject *object)
+{
+	FeedsOpmlGroupHandler *parser;
+
+	parser = FEEDS_OPML_GROUP_HANDLER (object);
+	G_OBJECT_CLASS (feeds_opml_group_handler_parent_class)->finalize (object);
+}
+
+static gboolean
+feeds_opml_group_handler_check_format (FeedsGroupHandler *self, xmlDocPtr doc, xmlNodePtr cur)
+{
+	if (!xmlStrcmp (cur->name, BAD_CAST"opml"))
+		return TRUE;
+	else
+		return FALSE;
+}
+
+static xmlChar*
+get_source_url (xmlNodePtr cur)
+{
+	xmlChar *tmp;
+
+	tmp = xmlGetProp (cur, BAD_CAST "xmlUrl");
+	if (!tmp)
+		tmp = xmlGetProp (cur, BAD_CAST "xmlurl");	/* e.g. for AmphetaDesk */
+	if (!tmp)
+		tmp = xmlGetProp (cur, BAD_CAST"xmlURL");	/* e.g. for LiveJournal */
+
+	return tmp;
+}
+
+static FeedChannel*
+import_parse_outline (xmlNodePtr cur)
+{
+	xmlChar *tmp;
+	FeedChannel *channel;
+
+	channel = feed_channel_new ();
+
+	tmp = xmlGetProp (cur, BAD_CAST"title");
+	if (!tmp || !xmlStrcmp (tmp, BAD_CAST"")) {
+		if (tmp)
+			xmlFree (tmp);
+		tmp = xmlGetProp (cur, BAD_CAST"text");
+	}
+
+	if (tmp) {
+		feed_channel_set_title (channel, (gchar*) tmp);
+		xmlFree (tmp);
+	}
+
+	tmp = get_source_url (cur);
+
+	if (tmp) {
+		feed_channel_set_source (channel, (gchar*) tmp);
+		xmlFree (tmp);
+
+		tmp = xmlGetProp (cur, BAD_CAST"htmlUrl");
+		if (tmp && xmlStrcmp (tmp, BAD_CAST""))
+			feed_channel_set_homepage (channel, (gchar*) tmp);
+		xmlFree (tmp);
+	}
+
+	return channel;
+}
+
+static GList*
+import_parse_body (xmlNodePtr n)
+{
+	xmlChar *type;
+	xmlChar *tmp;
+	GList *items;
+	GList *subitems;
+	FeedChannel *outline;
+	xmlNodePtr cur;
+
+	cur = n->xmlChildrenNode;
+	items = NULL;
+
+	while (cur) {
+		if (!xmlStrcmp (cur->name, BAD_CAST"outline")) {
+			outline = NULL;
+			subitems = NULL;
+			type = xmlGetProp (cur, BAD_CAST"type");
+
+			if (type) {
+				if (xmlStrcasecmp (type, BAD_CAST"rss") == 0 || xmlStrcasecmp (type, BAD_CAST"atom") == 0)
+					outline = import_parse_outline (cur);
+				else if (xmlStrcasecmp (type, BAD_CAST"folder") == 0)
+					subitems = import_parse_body (cur);
+
+				xmlFree (type);
+			}
+			else {
+				/* if we didn't find a type attribute we use heuristics */
+
+				tmp = get_source_url (cur);
+
+				if (tmp) {
+					outline = import_parse_outline (cur);
+					xmlFree (tmp);
+				}
+				else {
+					subitems = import_parse_body (cur);
+				}
+			}
+
+			if (outline != NULL)
+				items = g_list_prepend (items, outline);
+			else if (subitems != NULL)
+				items = g_list_concat (items, subitems);
+		}
+
+		cur = cur->next;
+	}
+
+	return items;
+}
+
+static GList*
+import_parse_OPML (xmlNodePtr n)
+{
+	GList *items;
+	xmlNodePtr cur;
+
+	cur = n->xmlChildrenNode;
+	items = NULL;
+
+	while (cur) {
+		if (!xmlStrcmp (cur->name, BAD_CAST"body")) {
+			items = import_parse_body (cur);
+			break;
+		}
+
+		cur = cur->next;
+	}
+
+	return items;
+}
+
+static GList*
+feeds_opml_group_handler_parse (FeedsGroupHandler *self, xmlDocPtr doc, GError *error)
+{
+	xmlNodePtr cur;
+	GList *items;
+	FeedsOpmlGroupHandler *parser;
+
+	items = NULL;
+	parser = FEEDS_OPML_GROUP_HANDLER (self);
+	cur = xmlDocGetRootElement (doc);
+
+	while (cur) {
+		if (!xmlIsBlankNode (cur))
+			if (!xmlStrcmp (cur->name, BAD_CAST"opml")) {
+				items = import_parse_OPML (cur);
+				break;
+			}
+
+		cur = cur->next;
+	}
+
+	if (items != NULL)
+		items = g_list_reverse (items);
+	return items;
+}
+
+static gchar*
+feeds_opml_group_handler_dump (FeedsGroupHandler *self, GList *channels, GError *error)
+{
+	return NULL;
+}
+
+static void
+feeds_group_handler_interface_init (FeedsGroupHandlerInterface *iface)
+{
+	iface->check_format = feeds_opml_group_handler_check_format;
+	iface->parse = feeds_opml_group_handler_parse;
+	iface->dump = feeds_opml_group_handler_dump;
+}
+
+static void
+feeds_opml_group_handler_class_init (FeedsOpmlGroupHandlerClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (object_class, sizeof (FeedsOpmlGroupHandlerPrivate));
+	object_class->finalize = feeds_opml_group_handler_finalize;
+}
+
+static void
+feeds_opml_group_handler_init (FeedsOpmlGroupHandler *object)
+{
+	object->priv = FEEDS_OPML_GROUP_HANDLER_GET_PRIVATE (object);
+}
+
+/**
+ * feeds_opml_group_handler_new:
+ *
+ * Allocates a new #FeedsOpmlGroupHandler
+ *
+ * Return value: a new #FeedsOpmlGroupHandler
+ */
+FeedsOpmlGroupHandler*
+feeds_opml_group_handler_new ()
+{
+	FeedsOpmlGroupHandler *parser;
+
+	parser = g_object_new (FEEDS_OPML_GROUP_HANDLER_TYPE, NULL);
+	return parser;
+}
diff --git a/src/feeds-opml-group-handler.h b/src/feeds-opml-group-handler.h
new file mode 100644
index 0000000..39c341d
--- /dev/null
+++ b/src/feeds-opml-group-handler.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010, Roberto Guido <rguido src gnome org>
+ *                     Michele Tameni <michele amdplanet it>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __FEEDS_OPML_GROUP_HANDLER_H__
+#define __FEEDS_OPML_GROUP_HANDLER_H__
+
+#include "common.h"
+#include "feeds-group-handler.h"
+
+#define FEEDS_OPML_GROUP_HANDLER_TYPE		(feeds_opml_group_handler_get_type())
+#define FEEDS_OPML_GROUP_HANDLER(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), FEEDS_OPML_GROUP_HANDLER_TYPE, FeedsOpmlGroupHandler))
+#define FEEDS_OPML_GROUP_HANDLER_CLASS(c)	(G_TYPE_CHECK_CLASS_CAST ((c), FEEDS_OPML_GROUP_HANDLER_TYPE, FeedsOpmlGroupHandlerClass))
+#define IS_FEEDS_OPML_GROUP_HANDLER(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), FEEDS_OPML_GROUP_HANDLER_TYPE))
+#define IS_FEEDS_OPML_GROUP_HANDLER_CLASS(c)	(G_TYPE_CHECK_CLASS_TYPE ((c),  FEEDS_OPML_GROUP_HANDLER_TYPE))
+#define FEEDS_OPML_GROUP_HANDLER_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), FEEDS_OPML_GROUP_HANDLER_TYPE, FeedsOpmlGroupHandlerClass))
+
+typedef struct FeedsOpmlGroupHandler        FeedsOpmlGroupHandler;
+typedef struct FeedsOpmlGroupHandlerPrivate FeedsOpmlGroupHandlerPrivate;
+
+struct FeedsOpmlGroupHandler {
+	GObject parent;
+	FeedsOpmlGroupHandlerPrivate *priv;
+};
+
+typedef struct {
+	GObjectClass parent;
+} FeedsOpmlGroupHandlerClass;
+
+GType			feeds_opml_group_handler_get_type	(void) G_GNUC_CONST;
+
+FeedsOpmlGroupHandler*	feeds_opml_group_handler_new		();
+
+#endif /* __FEEDS_OPML_GROUP_HANDLER_H__ */
diff --git a/src/feeds-pool.c b/src/feeds-pool.c
index a8cd612..154fddb 100644
--- a/src/feeds-pool.c
+++ b/src/feeds-pool.c
@@ -275,7 +275,7 @@ feed_downloaded (SoupSession *session, SoupMessage *msg, gpointer user_data)
 		g_warning ("Unable to download from %s", feed_channel_get_source (feed->channel));
 	}
 	else {
-		doc = feed_content_to_xml ((const gchar*) msg->response_body->data, msg->response_body->length);
+		doc = content_to_xml ((const gchar*) msg->response_body->data, msg->response_body->length);
 
 		if (doc != NULL) {
 			error = NULL;
diff --git a/src/feeds-subscriber.c b/src/feeds-subscriber.c
index 9bba100..6653f88 100644
--- a/src/feeds-subscriber.c
+++ b/src/feeds-subscriber.c
@@ -322,7 +322,7 @@ handle_incoming_notification_cb (SoupServer *server, SoupMessage *msg, const cha
 				server as soon as possible
 		*/
 
-		doc = feed_content_to_xml (msg->request_body->data, strlen (msg->request_body->data));
+		doc = content_to_xml (msg->request_body->data, strlen (msg->request_body->data));
 		error = NULL;
 		items = feed_parser_parse (feed->sub->priv->parser, feed->channel, doc, &error);
 
diff --git a/src/libgrss.h b/src/libgrss.h
index 822c42b..6e4c966 100644
--- a/src/libgrss.h
+++ b/src/libgrss.h
@@ -27,5 +27,6 @@
 #include "feeds-store.h"
 #include "feeds-pool.h"
 #include "feeds-subscriber.h"
+#include "feeds-group.h"
 
 #endif /* __LIBGRSS_H__ */
diff --git a/src/utils.c b/src/utils.c
index 2735efb..2224a8d 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -285,7 +285,7 @@ xml_process_entities (void *ctxt, const xmlChar *name)
 }
 
 xmlDocPtr
-feed_content_to_xml (const gchar *contents, gsize size)
+content_to_xml (const gchar *contents, gsize size)
 {
 	xmlParserCtxtPtr ctxt;
 	xmlDocPtr doc;
diff --git a/src/utils.h b/src/utils.h
index 9affff5..77ac6b3 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -32,7 +32,7 @@ gchar*		unhtmlize		(gchar *string);
 gchar*		unxmlize		(gchar * string);
 gchar*		xhtml_extract		(xmlNodePtr xml, gint xhtmlMode, const gchar *defaultBase);
 
-xmlDocPtr	feed_content_to_xml	(const gchar *contents, gsize size);
+xmlDocPtr	content_to_xml		(const gchar *contents, gsize size);
 
 time_t		date_parse_RFC822	(const gchar *date);
 time_t		date_parse_ISO8601	(const gchar *date);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]