[libgrss] Major refactory on FeedsSubscriber
- From: Roberto Guido <rguido src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgrss] Major refactory on FeedsSubscriber
- Date: Tue, 27 Dec 2011 23:12:15 +0000 (UTC)
commit 50fc81b8bc1aa45f541b6b1b7f6a34fbb5a58ac2
Author: Roberto Guido <bob4mail gmail com>
Date: Fri Dec 23 03:48:51 2011 -0800
Major refactory on FeedsSubscriber
NEWS | 2 +-
doc/reference/libgrss-sections.txt | 241 +++++++++---------
examples/subscriber.c | 2 +-
src/Makefile.am | 80 ++++---
src/feed-atom-handler.c | 19 +--
src/feed-channel.c | 197 +++++++++++----
src/feed-channel.h | 7 +-
src/feed-handler.c | 40 ---
src/feed-pie-handler.c | 16 --
src/feed-rss-handler.c | 44 +++--
src/feeds-group-handler.c | 42 ---
src/feeds-opml-group-handler.c | 7 -
src/feeds-publisher.c | 6 +-
src/feeds-pubsubhubbub-subscriber.c | 244 ++++++++++++++++++
src/feeds-pubsubhubbub-subscriber.h | 49 ++++
src/feeds-rsscloud-subscriber.c | 206 +++++++++++++++
src/feeds-rsscloud-subscriber.h | 49 ++++
src/feeds-subscriber-handler.c | 103 ++++++++
src/feeds-subscriber-handler.h | 59 +++++
src/feeds-subscriber.c | 468 ++++++++++++-----------------------
src/feeds-subscriber.h | 6 +-
src/feeds-xbel-group-handler.c | 9 +-
src/feeds-xoxo-group-handler.c | 9 +-
src/ns-handler.c | 48 +----
24 files changed, 1233 insertions(+), 720 deletions(-)
---
diff --git a/NEWS b/NEWS
index 62392a5..6e386a4 100644
--- a/NEWS
+++ b/NEWS
@@ -3,7 +3,7 @@ libgrss 0.5 (UNRELEASED)
- Complete API break: all object and function names moved to "grss" namespace
- Added XOXO and XBEL files parsers
- Added FeedsPublisher to expose feeds contents as files or by local server
-- PubSubHub subscriber
+- PubSubHub and RSSCloud subscribers
- Added functions feed_channel_fetch_async() and feed_channel_new_from_file()
libgrss 0.4
diff --git a/doc/reference/libgrss-sections.txt b/doc/reference/libgrss-sections.txt
index 5959410..488af51 100644
--- a/doc/reference/libgrss-sections.txt
+++ b/doc/reference/libgrss-sections.txt
@@ -1,152 +1,159 @@
<SECTION>
<FILE>feed-enclosure</FILE>
-<TITLE>FeedEnclosure</TITLE>
-FeedEnclosure
-feed_enclosure_new
-feed_enclosure_get_url
-feed_enclosure_set_format
-feed_enclosure_get_format
-feed_enclosure_set_length
-feed_enclosure_get_length
+<TITLE>GrssFeedEnclosure</TITLE>
+GrssFeedEnclosure
+grss_feed_enclosure_new
+grss_feed_enclosure_get_url
+grss_feed_enclosure_set_format
+grss_feed_enclosure_get_format
+grss_feed_enclosure_set_length
+grss_feed_enclosure_get_length
</SECTION>
<SECTION>
<FILE>feeds-pool</FILE>
-<TITLE>FeedsPool</TITLE>
-FeedsPool
-feeds_pool_new
-feeds_pool_listen
-feeds_pool_get_listened
-feeds_pool_switch
-feeds_pool_get_session
+<TITLE>GrssFeedsPool</TITLE>
+GrssFeedsPool
+grss_feeds_pool_new
+grss_feeds_pool_listen
+grss_feeds_pool_get_listened
+grss_feeds_pool_switch
+grss_feeds_pool_get_session
</SECTION>
<SECTION>
<FILE>feeds-store</FILE>
-<TITLE>FeedsStore</TITLE>
-FeedsStore
-feeds_store_get_channels
-feeds_store_get_items_by_channel
-feeds_store_has_item
-feeds_store_add_item_in_channel
-feeds_store_switch
+<TITLE>GrssFeedsStore</TITLE>
+GrssFeedsStore
+grss_feeds_store_get_channels
+grss_feeds_store_get_items_by_channel
+grss_feeds_store_has_item
+grss_feeds_store_add_item_in_channel
+grss_feeds_store_switch
</SECTION>
<SECTION>
<FILE>feeds-subscriber</FILE>
-<TITLE>FeedsSubscriber</TITLE>
-FeedsSubscriber
-feeds_subscriber_new
-feeds_subscriber_listen
-feeds_subscriber_get_listened
-feeds_subscriber_set_port
-feeds_subscriber_set_hub
-feeds_subscriber_switch
+<TITLE>GrssFeedsSubscriber</TITLE>
+GrssFeedsSubscriber
+grss_feeds_subscriber_new
+grss_feeds_subscriber_listen
+grss_feeds_subscriber_get_listened
+grss_feeds_subscriber_set_port
+grss_feeds_subscriber_switch
+grss_feeds_subscriber_get_address
+grss_feeds_subscriber_get_port
+grss_feeds_subscriber_get_session
</SECTION>
<SECTION>
<FILE>feeds-publisher</FILE>
-<TITLE>FeedsPublisher</TITLE>
-FeedsPublisher
-feeds_publisher_new
-feeds_publisher_set_port
-feeds_publisher_set_topics
-feeds_publisher_switch
-feeds_publisher_publish
+<TITLE>GrssFeedsPublisher</TITLE>
+GrssFeedsPublisher
+grss_feeds_publisher_new
+grss_feeds_publisher_publish
+grss_feeds_publisher_publish_file
+grss_feeds_publisher_hub_set_port
+grss_feeds_publisher_hub_set_topics
+grss_feeds_publisher_hub_switch
</SECTION>
<SECTION>
<FILE>feed-item</FILE>
-<TITLE>FeedItem</TITLE>
-FeedItem
-feed_item_new
-feed_item_get_parent
-feed_item_set_id
-feed_item_get_id
-feed_item_set_title
-feed_item_get_title
-feed_item_set_description
-feed_item_get_description
-feed_item_add_category
-feed_item_get_categories
-feed_item_set_source
-feed_item_get_source
-feed_item_set_real_source
-feed_item_get_real_source
-feed_item_set_related
-feed_item_get_related
-feed_item_set_copyright
-feed_item_get_copyright
-feed_item_set_author
-feed_item_get_author
-feed_item_add_contributor
-feed_item_get_contributors
-feed_item_set_comments_url
-feed_item_get_comments_url
-feed_item_set_geo_point
-feed_item_get_geo_point
-feed_item_set_publish_time
-feed_item_get_publish_time
-feed_item_add_enclosure
-feed_item_get_enclosures
+<TITLE>GrssFeedItem</TITLE>
+GrssFeedItem
+grss_feed_item_new
+grss_feed_item_get_parent
+grss_feed_item_set_id
+grss_feed_item_get_id
+grss_feed_item_set_title
+grss_feed_item_get_title
+grss_feed_item_set_description
+grss_feed_item_get_description
+grss_feed_item_add_category
+grss_feed_item_get_categories
+grss_feed_item_set_source
+grss_feed_item_get_source
+grss_feed_item_set_real_source
+grss_feed_item_get_real_source
+grss_feed_item_set_related
+grss_feed_item_get_related
+grss_feed_item_set_copyright
+grss_feed_item_get_copyright
+grss_feed_item_set_author
+grss_feed_item_get_author
+grss_feed_item_add_contributor
+grss_feed_item_get_contributors
+grss_feed_item_set_comments_url
+grss_feed_item_get_comments_url
+grss_feed_item_set_geo_point
+grss_feed_item_get_geo_point
+grss_feed_item_set_publish_time
+grss_feed_item_get_publish_time
+grss_feed_item_add_enclosure
+grss_feed_item_get_enclosures
</SECTION>
<SECTION>
<FILE>feed-parser</FILE>
-<TITLE>FeedParser</TITLE>
-FeedParser
-feed_parser_new
-feed_parser_parse
+<TITLE>GrssFeedParser</TITLE>
+GrssFeedParser
+grss_feed_parser_new
+grss_feed_parser_parse
</SECTION>
<SECTION>
<FILE>feed-channel</FILE>
-<TITLE>FeedChannel</TITLE>
-FeedChannel
-feed_channel_new
-feed_channel_set_source
-feed_channel_get_source
-feed_channel_set_title
-feed_channel_get_title
-feed_channel_set_homepage
-feed_channel_get_homepage
-feed_channel_set_description
-feed_channel_get_description
-feed_channel_set_image
-feed_channel_get_image
-feed_channel_set_icon
-feed_channel_get_icon
-feed_channel_set_language
-feed_channel_get_language
-feed_channel_set_category
-feed_channel_get_category
-feed_channel_set_pubsubhub
-feed_channel_get_pubsubhub
-feed_channel_set_copyright
-feed_channel_get_copyright
-feed_channel_set_editor
-feed_channel_get_editor
-feed_channel_add_contributor
-feed_channel_get_contributors
-feed_channel_set_webmaster
-feed_channel_get_webmaster
-feed_channel_set_generator
-feed_channel_get_generator
-feed_channel_set_publish_time
-feed_channel_get_publish_time
-feed_channel_set_update_time
-feed_channel_get_update_time
-feed_channel_set_update_interval
-feed_channel_get_update_interval
-feed_channel_fetch
-feed_channel_fetch_async
+<TITLE>GrssFeedChannel</TITLE>
+GrssFeedChannel
+grss_feed_channel_new
+grss_feed_channel_new_from_source
+grss_feed_channel_new_from_file
+grss_feed_channel_set_source
+grss_feed_channel_get_source
+grss_feed_channel_set_title
+grss_feed_channel_get_title
+grss_feed_channel_set_homepage
+grss_feed_channel_get_homepage
+grss_feed_channel_set_description
+grss_feed_channel_get_description
+grss_feed_channel_set_image
+grss_feed_channel_get_image
+grss_feed_channel_set_icon
+grss_feed_channel_get_icon
+grss_feed_channel_set_language
+grss_feed_channel_get_language
+grss_feed_channel_set_category
+grss_feed_channel_get_category
+grss_feed_channel_set_pubsubhub
+grss_feed_channel_get_pubsubhub
+grss_feed_channel_set_rsscloud
+grss_feed_channel_get_rsscloud
+grss_feed_channel_set_copyright
+grss_feed_channel_get_copyright
+grss_feed_channel_set_editor
+grss_feed_channel_get_editor
+grss_feed_channel_add_contributor
+grss_feed_channel_get_contributors
+grss_feed_channel_set_webmaster
+grss_feed_channel_get_webmaster
+grss_feed_channel_set_generator
+grss_feed_channel_get_generator
+grss_feed_channel_set_publish_time
+grss_feed_channel_get_publish_time
+grss_feed_channel_set_update_time
+grss_feed_channel_get_update_time
+grss_feed_channel_set_update_interval
+grss_feed_channel_get_update_interval
+grss_feed_channel_fetch
+grss_feed_channel_fetch_async
</SECTION>
<SECTION>
<FILE>feeds-group</FILE>
-<TITLE>FeedsGroup</TITLE>
-FeedsGroup
-feeds_group_new
-feeds_group_parse_file
-feeds_group_export_file
+<TITLE>GrssFeedsGroup</TITLE>
+GrssFeedsGroup
+grss_feeds_group_new
+grss_feeds_group_parse_file
+grss_feeds_group_export_file
</SECTION>
diff --git a/examples/subscriber.c b/examples/subscriber.c
index 71f45cf..29789f9 100644
--- a/examples/subscriber.c
+++ b/examples/subscriber.c
@@ -45,7 +45,7 @@ main ()
gboolean ok;
gchar *example_feeds [] = {
"http://rss.slashdot.org/Slashdot/slashdot",
- "http://feeds.feedburner.com/Techcrunch",
+ "http://techcrunch.com/feed/",
NULL
};
GList *iter;
diff --git a/src/Makefile.am b/src/Makefile.am
index ff2afe2..7643455 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -11,49 +11,55 @@ INCLUDES = \
LDADD = $(LIBGRSS_LT_LDFLAGS) -export-dynamic -rpath $(libdir)
sources_private_h = \
- feed-atom-handler.h \
- feed-handler.h \
- feed-rss-handler.h \
- feed-pie-handler.h \
- feeds-group-handler.h \
- feeds-opml-group-handler.h \
- feeds-xbel-group-handler.h \
- feeds-xoxo-group-handler.h \
- ns-handler.h \
+ feed-atom-handler.h \
+ feed-handler.h \
+ feed-rss-handler.h \
+ feed-pie-handler.h \
+ feeds-group-handler.h \
+ feeds-opml-group-handler.h \
+ feeds-pubsubhubbub-subscriber.h \
+ feeds-rsscloud-subscriber.h \
+ feeds-subscriber-handler.h \
+ feeds-xbel-group-handler.h \
+ feeds-xoxo-group-handler.h \
+ ns-handler.h \
utils.h
sources_public_h = \
- libgrss.h \
- feed-channel.h \
- feed-enclosure.h \
- feed-item.h \
- feed-parser.h \
- feeds-group.h \
- feeds-pool.h \
- feeds-publisher.h \
- feeds-store.h \
+ libgrss.h \
+ feed-channel.h \
+ feed-enclosure.h \
+ feed-item.h \
+ feed-parser.h \
+ feeds-group.h \
+ feeds-pool.h \
+ feeds-publisher.h \
+ feeds-store.h \
feeds-subscriber.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-group.c \
- feeds-group-handler.c \
- feeds-opml-group-handler.c \
- feeds-pool.c \
- feeds-publisher.c \
- feeds-store.c \
- feeds-subscriber.c \
- feeds-xbel-group-handler.c \
- feeds-xoxo-group-handler.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-publisher.c \
+ feeds-store.c \
+ feeds-pubsubhubbub-subscriber.c \
+ feeds-rsscloud-subscriber.c \
+ feeds-subscriber.c \
+ feeds-subscriber-handler.c \
+ feeds-xbel-group-handler.c \
+ feeds-xoxo-group-handler.c \
+ ns-handler.c \
utils.c
marshal_source = \
diff --git a/src/feed-atom-handler.c b/src/feed-atom-handler.c
index e932802..acf05d4 100644
--- a/src/feed-atom-handler.c
+++ b/src/feed-atom-handler.c
@@ -32,14 +32,6 @@
#include "ns-handler.h"
#define FEED_ATOM_HANDLER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), FEED_ATOM_HANDLER_TYPE, FeedAtomHandlerPrivate))
-
-/**
- * SECTION: feed-atom-handler
- * @short_description: specialized parser for Atom feeds
- *
- * #FeedAtomHandler is a #FeedHandler specialized for feeds in Atom format
- */
-
#define FEED_ATOM_HANDLER_ERROR feed_atom_handler_error_quark()
#define ATOM10_NS BAD_CAST"http://www.w3.org/2005/Atom"
@@ -406,11 +398,11 @@ atom10_parse_link (xmlNodePtr cur, GrssFeedChannel *feed, GrssFeedItem *item)
}
else if (g_str_equal (relation, "hub")) {
if (feed != NULL)
- grss_feed_channel_set_pubsubhub (feed, url, NULL);
+ grss_feed_channel_set_pubsubhub (feed, url);
}
else if (g_str_equal (relation, "self")) {
if (feed != NULL)
- grss_feed_channel_set_pubsubhub (feed, NULL, url);
+ grss_feed_channel_set_source (feed, url);
}
xmlFree (title);
@@ -916,13 +908,6 @@ feed_atom_handler_init (FeedAtomHandler *object)
object->priv->entry_elements_hash = hash;
}
-/**
- * feed_atom_handler_new:
- *
- * Allocates a new #FeedAtomHandler
- *
- * Return value: a new #FeedAtomHandler
- */
FeedAtomHandler*
feed_atom_handler_new ()
{
diff --git a/src/feed-channel.c b/src/feed-channel.c
index a06e2b1..9be471f 100644
--- a/src/feed-channel.c
+++ b/src/feed-channel.c
@@ -35,30 +35,35 @@
typedef struct {
gchar *hub;
- gchar *self;
} PubSub;
+typedef struct {
+ gchar *path;
+ gchar *protocol;
+} RSSCloud;
+
struct _GrssFeedChannelPrivate {
- gchar *source;
-
- gchar *title;
- gchar *homepage;
- gchar *description;
- gchar *image;
- gchar *icon;
- gchar *language;
- gchar *category;
- PubSub pubsub;
-
- gchar *copyright;
- gchar *editor;
- GList *contributors;
- gchar *webmaster;
- gchar *generator;
-
- time_t pub_time;
- time_t update_time;
- int update_interval;
+ gchar *source;
+
+ gchar *title;
+ gchar *homepage;
+ gchar *description;
+ gchar *image;
+ gchar *icon;
+ gchar *language;
+ gchar *category;
+ PubSub pubsub;
+ RSSCloud rsscloud;
+
+ gchar *copyright;
+ gchar *editor;
+ GList *contributors;
+ gchar *webmaster;
+ gchar *generator;
+
+ time_t pub_time;
+ time_t update_time;
+ int update_interval;
};
enum {
@@ -88,7 +93,8 @@ grss_feed_channel_finalize (GObject *obj)
FREE_STRING (chan->priv->language);
FREE_STRING (chan->priv->category);
FREE_STRING (chan->priv->pubsub.hub);
- FREE_STRING (chan->priv->pubsub.self);
+ FREE_STRING (chan->priv->rsscloud.path);
+ FREE_STRING (chan->priv->rsscloud.protocol);
FREE_STRING (chan->priv->copyright);
FREE_STRING (chan->priv->editor);
FREE_STRING (chan->priv->webmaster);
@@ -133,6 +139,24 @@ grss_feed_channel_new ()
}
/**
+ * grss_feed_channel_new_from_source:
+ * @source: URL of the feed
+ *
+ * Allocates a new #GrssFeedChannel and assign it the given remote source
+ *
+ * Return value: a #GrssFeedChannel
+ */
+GrssFeedChannel*
+grss_feed_channel_new_from_source (gchar *source)
+{
+ GrssFeedChannel *ret;
+
+ ret = grss_feed_channel_new ();
+ grss_feed_channel_set_source (ret, source);
+ return ret;
+}
+
+/**
* grss_feed_channel_new_from_file:
* @path: path of the file to parse
*
@@ -408,38 +432,23 @@ grss_feed_channel_get_category (GrssFeedChannel *channel)
* grss_feed_channel_set_pubsubhub:
* @channel: a #GrssFeedChannel
* @hub: hub for the feed, or NULL
- * @self: target referencing the feed, or NULL
*
- * To set information about PubSubHubbub for the channel. Options can be set
- * alternatively, only with hub != %NULL or self != %NULL, and are saved
- * internally to the object: the hub is considered valid
- * (grss_feed_channel_get_pubsubhub() returns %TRUE) only when both parameters has
- * been set. To unset the hub, pass %NULL for both parameters
+ * To set information about PubSubHubbub for the channel. To unset the hub,
+ * pass %NULL as parameter
*/
void
-grss_feed_channel_set_pubsubhub (GrssFeedChannel *channel, gchar *hub, gchar *self)
+grss_feed_channel_set_pubsubhub (GrssFeedChannel *channel, gchar *hub)
{
- if (hub == NULL && self == NULL) {
- FREE_STRING (channel->priv->pubsub.hub);
- FREE_STRING (channel->priv->pubsub.self);
- }
- else {
- if (hub != NULL) {
- FREE_STRING (channel->priv->pubsub.hub);
- channel->priv->pubsub.hub = g_strdup (hub);
- }
- if (self != NULL) {
- FREE_STRING (channel->priv->pubsub.self);
- channel->priv->pubsub.self = g_strdup (self);
- }
- }
+ FREE_STRING (channel->priv->pubsub.hub);
+
+ if (hub != NULL)
+ channel->priv->pubsub.hub = g_strdup (hub);
}
/**
* grss_feed_channel_get_pubsubhub:
* @channel: a #GrssFeedChannel
* @hub: location for the hub string, or NULL
- * @self: location for the reference to the feed, or NULL
*
* Retrieves information about the PubSubHubbub hub of the channel
*
@@ -447,14 +456,55 @@ grss_feed_channel_set_pubsubhub (GrssFeedChannel *channel, gchar *hub, gchar *se
* @channel, %FALSE otherwise
*/
gboolean
-grss_feed_channel_get_pubsubhub (GrssFeedChannel *channel, gchar **hub, gchar **self)
+grss_feed_channel_get_pubsubhub (GrssFeedChannel *channel, gchar **hub)
{
if (hub != NULL)
*hub = channel->priv->pubsub.hub;
- if (self != NULL)
- *self = channel->priv->pubsub.self;
- return (channel->priv->pubsub.hub != NULL && channel->priv->pubsub.self != NULL);
+ return (channel->priv->pubsub.hub != NULL);
+}
+
+/**
+ * grss_feed_channel_set_rsscloud:
+ * @channel: a #GrssFeedChannel
+ * @path: complete references of the URL where to register subscription, e.g.
+ * http://example.com/rsscloudNotify
+ * @protocol: type of protocol used for notifications
+ *
+ * To set information about RSSCloud notifications for the channel
+ */
+void
+grss_feed_channel_set_rsscloud (GrssFeedChannel *channel, gchar *path, gchar *protocol)
+{
+ FREE_STRING (channel->priv->rsscloud.path);
+ FREE_STRING (channel->priv->rsscloud.protocol);
+
+ if (path != NULL && protocol != NULL) {
+ channel->priv->rsscloud.path = g_strdup (path);
+ channel->priv->rsscloud.protocol = g_strdup (protocol);
+ }
+}
+
+/**
+ * grss_feed_channel_get_rsscloud:
+ * @channel: a #GrssFeedChannel
+ * @path: location for the path string, or NULL
+ * @protocol: location for the protocol string, or NULL
+ *
+ * Retrieves information about the RSSCloud coordinates of the channel
+ *
+ * Return value: %TRUE if a valid RSSCloud path has been set for the
+ * @channel, %FALSE otherwise
+ */
+gboolean
+grss_feed_channel_get_rsscloud (GrssFeedChannel *channel, gchar **path, gchar **protocol)
+{
+ if (path != NULL)
+ *path = channel->priv->rsscloud.path;
+ if (protocol != NULL)
+ *protocol = channel->priv->rsscloud.protocol;
+
+ return (channel->priv->rsscloud.path != NULL && channel->priv->rsscloud.protocol != NULL);
}
/**
@@ -690,7 +740,7 @@ grss_feed_channel_get_update_interval (GrssFeedChannel *channel)
}
static gboolean
-quick_and_dirty_parse (GrssFeedChannel *channel, SoupMessage *msg)
+quick_and_dirty_parse (GrssFeedChannel *channel, SoupMessage *msg, GList **save_items)
{
GList *items;
GList *iter;
@@ -699,7 +749,8 @@ quick_and_dirty_parse (GrssFeedChannel *channel, SoupMessage *msg)
/*
TODO This function is quite inefficent because parses all
- the feed with a GrssFeedParser and them waste obtained
+ the feed with a GrssFeedParser also when not required
+ (save_items == NULL) and wastes time obtained
GrssFeedItems. Perhaps a more aimed function in
GrssFeedParser would help...
*/
@@ -710,11 +761,14 @@ quick_and_dirty_parse (GrssFeedChannel *channel, SoupMessage *msg)
parser = grss_feed_parser_new ();
items = grss_feed_parser_parse (parser, channel, doc, NULL);
- if (items != NULL) {
+ if (save_items == NULL && items != NULL) {
for (iter = items; iter; iter = g_list_next (iter))
g_object_unref (iter->data);
g_list_free (items);
}
+ else {
+ *save_items = items;
+ }
g_object_unref (parser);
xmlFreeDoc (doc);
@@ -750,7 +804,7 @@ grss_feed_channel_fetch (GrssFeedChannel *channel)
status = soup_session_send_message (session, msg);
if (status >= 200 && status <= 299) {
- ret = quick_and_dirty_parse (channel, msg);
+ ret = quick_and_dirty_parse (channel, msg, NULL);
}
else {
g_warning ("Unable to fetch feed from %s: %s", grss_feed_channel_get_source (channel), soup_status_get_phrase (status));
@@ -773,7 +827,7 @@ feed_downloaded (SoupSession *session, SoupMessage *msg, gpointer user_data) {
g_object_get (msg, "status-code", &status, NULL);
if (status >= 200 && status <= 299) {
- quick_and_dirty_parse (channel, msg);
+ quick_and_dirty_parse (channel, msg, NULL);
}
else {
g_simple_async_result_set_error (result, FEEDS_CHANNEL_ERROR, FEEDS_CHANNEL_FETCH_ERROR,
@@ -805,3 +859,40 @@ grss_feed_channel_fetch_async (GrssFeedChannel *channel, GAsyncReadyCallback cal
msg = soup_message_new ("GET", grss_feed_channel_get_source (channel));
soup_session_queue_message (session, msg, feed_downloaded, result);
}
+
+/**
+ * grss_feed_channel_fetch_all:
+ * @channel: a #GrssFeedChannel
+ *
+ * Utility to fetch and populate a #GrssFeedChannel, and retrieve all its
+ * items
+ *
+ * Return value: a GList of #GrssFeedItem, to be completely unreferenced and
+ * freed when no longer in use, or %NULL if an error occurs
+ */
+GList*
+grss_feed_channel_fetch_all (GrssFeedChannel *channel)
+{
+ gboolean ret;
+ guint status;
+ GList *items;
+ SoupMessage *msg;
+ SoupSession *session;
+
+ session = soup_session_sync_new ();
+ msg = soup_message_new ("GET", grss_feed_channel_get_source (channel));
+ status = soup_session_send_message (session, msg);
+ items = NULL;
+
+ if (status >= 200 && status <= 299) {
+ ret = quick_and_dirty_parse (channel, msg, &items);
+ }
+ else {
+ g_warning ("Unable to fetch feed from %s: %s", grss_feed_channel_get_source (channel), soup_status_get_phrase (status));
+ ret = FALSE;
+ }
+
+ g_object_unref (session);
+ g_object_unref (msg);
+ return items;
+}
diff --git a/src/feed-channel.h b/src/feed-channel.h
index dd69617..bb04ba7 100644
--- a/src/feed-channel.h
+++ b/src/feed-channel.h
@@ -63,8 +63,10 @@ void grss_feed_channel_set_language (GrssFeedChannel *channel, gchar *languag
const gchar* grss_feed_channel_get_language (GrssFeedChannel *channel);
void grss_feed_channel_set_category (GrssFeedChannel *channel, gchar *category);
const gchar* grss_feed_channel_get_category (GrssFeedChannel *channel);
-void grss_feed_channel_set_pubsubhub (GrssFeedChannel *channel, gchar *hub, gchar *self);
-gboolean grss_feed_channel_get_pubsubhub (GrssFeedChannel *channel, gchar **hub, gchar **self);
+void grss_feed_channel_set_pubsubhub (GrssFeedChannel *channel, gchar *hub);
+gboolean grss_feed_channel_get_pubsubhub (GrssFeedChannel *channel, gchar **hub);
+void grss_feed_channel_set_rsscloud (GrssFeedChannel *channel, gchar *path, gchar *protocol);
+gboolean grss_feed_channel_get_rsscloud (GrssFeedChannel *channel, gchar **path, gchar **protocol);
void grss_feed_channel_set_copyright (GrssFeedChannel *channel, gchar *copyright);
const gchar* grss_feed_channel_get_copyright (GrssFeedChannel *channel);
@@ -86,5 +88,6 @@ int grss_feed_channel_get_update_interval (GrssFeedChannel *channel);
gboolean grss_feed_channel_fetch (GrssFeedChannel *channel);
void grss_feed_channel_fetch_async (GrssFeedChannel *channel, GAsyncReadyCallback callback, gpointer user_data);
+GList* grss_feed_channel_fetch_all (GrssFeedChannel *channel);
#endif /* __FEED_CHANNEL_H__ */
diff --git a/src/feed-handler.c b/src/feed-handler.c
index 6b8c5a3..dc900b6 100644
--- a/src/feed-handler.c
+++ b/src/feed-handler.c
@@ -21,14 +21,6 @@
#include "utils.h"
#include "feed-handler.h"
-/**
- * SECTION: feed-handler
- * @short_description: interface for specialized parsers
- *
- * The #FeedHandler interface defines a unique API for all specialized
- * parsers implementations
- */
-
static void
feed_handler_base_init (gpointer g_class)
{
@@ -52,14 +44,6 @@ feed_handler_get_type ()
return iface_type;
}
-/**
- * feed_handler_set_ns_handler:
- * @self: a #FeedHandler
- * @handler: instance of #NSHandler
- *
- * Permits to assign a #NSHandler to the specified #FeedHandler, to expand
- * his parsing capabilities to the external managed tags
- */
void
feed_handler_set_ns_handler (FeedHandler *self, NSHandler *handler)
{
@@ -69,17 +53,6 @@ feed_handler_set_ns_handler (FeedHandler *self, NSHandler *handler)
return FEED_HANDLER_GET_INTERFACE (self)->set_ns_handler (self, handler);
}
-/**
- * feed_handler_check_format:
- * @self: a #FeedHandler
- * @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 feed parser
- *
- * Return value: %TRUE if the document can be parsed with the given
- * #FeedHandler, %FALSE otherwise
- */
gboolean
feed_handler_check_format (FeedHandler *self, xmlDocPtr doc, xmlNodePtr cur)
{
@@ -89,19 +62,6 @@ feed_handler_check_format (FeedHandler *self, xmlDocPtr doc, xmlNodePtr cur)
return FEED_HANDLER_GET_INTERFACE (self)->check_format (self, doc, cur);
}
-/**
- * feed_handler_parse:
- * @self: a #FeedHandler
- * @feed: feed to be parsed
- * @doc: XML document from the feed
- * @error: location for eventual errors
- *
- * Parses the given @doc (obtained fetching @feed) and extracts a list of
- * items
- *
- * Return value: a list of #GrssFeedItem, to be freed when no longer in use, or
- * %NULL if an error occours (and @error is set accordly)
- */
GList*
feed_handler_parse (FeedHandler *self, GrssFeedChannel *feed, xmlDocPtr doc, GError **error)
{
diff --git a/src/feed-pie-handler.c b/src/feed-pie-handler.c
index 824f8f4..056ffa2 100644
--- a/src/feed-pie-handler.c
+++ b/src/feed-pie-handler.c
@@ -34,15 +34,6 @@
#include "ns-handler.h"
#define FEED_PIE_HANDLER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), FEED_PIE_HANDLER_TYPE, FeedPieHandlerPrivate))
-
-/**
- * SECTION: feed-pie-handler
- * @short_description: specialized parser for PIE feeds
- *
- * #FeedPieHandler is a #FeedHandler specialized for feeds in PIE format, an
- * older specification of Atom
- */
-
#define FEED_PIE_HANDLER_ERROR feed_pie_handler_error_quark()
typedef void (*PieChannelParserFunc) (xmlNodePtr cur, GrssFeedChannel *feed);
@@ -493,13 +484,6 @@ feed_pie_handler_init (FeedPieHandler *object)
object->priv = FEED_PIE_HANDLER_GET_PRIVATE (object);
}
-/**
- * feed_pie_handler_new:
- *
- * Allocates a new #FeedPieHandler
- *
- * Return value: a new #FeedPieHandler
- */
FeedPieHandler*
feed_pie_handler_new ()
{
diff --git a/src/feed-rss-handler.c b/src/feed-rss-handler.c
index 7183919..bbcfa05 100644
--- a/src/feed-rss-handler.c
+++ b/src/feed-rss-handler.c
@@ -44,14 +44,6 @@
#define FEED_RSS_HANDLER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), FEED_RSS_HANDLER_TYPE, FeedRssHandlerPrivate))
-/**
- * SECTION: feed-rss-handler
- * @short_description: specialized parser for RSS feeds
- *
- * #FeedRssHandler is a #FeedHandler specialized for feeds in RSS format,
- * both 1.0 and 2.0
- */
-
#define FEED_RSS_HANDLER_ERROR feed_rss_handler_error_quark()
/* HTML output strings */
@@ -118,6 +110,32 @@ feed_rss_handler_check_format (FeedHandler *self, xmlDocPtr doc, xmlNodePtr cur)
}
static void
+parse_rss_cloud (GrssFeedChannel *feed, xmlNodePtr cur) {
+ gchar *domain;
+ gchar *path;
+ gchar *protocol;
+ gchar *completepath;
+
+ domain = (gchar*) xmlGetNsProp (cur, BAD_CAST"domain", NULL);
+ path = (gchar*) xmlGetNsProp (cur, BAD_CAST"path", NULL);
+ protocol = (gchar*) xmlGetNsProp (cur, BAD_CAST"protocol", NULL);
+
+ if (domain != NULL && path != NULL && protocol != NULL) {
+ if (strncmp (domain, "http://", 7) != 0)
+ completepath = g_strdup_printf ("http://%s%s", domain, path);
+ else
+ completepath = g_strdup_printf ("%s%s", domain, path);
+
+ grss_feed_channel_set_rsscloud (feed, completepath, protocol);
+
+ g_free (domain);
+ g_free (path);
+ g_free (protocol);
+ g_free (completepath);
+ }
+}
+
+static void
parse_channel (FeedRssHandler *parser, GrssFeedChannel *feed, xmlDocPtr doc, xmlNodePtr cur) {
gchar *tmp;
time_t t;
@@ -217,6 +235,9 @@ parse_channel (FeedRssHandler *parser, GrssFeedChannel *feed, xmlDocPtr doc, xml
g_free (tmp);
}
}
+ else if (!xmlStrcmp (cur->name, BAD_CAST"cloud")) {
+ parse_rss_cloud (feed, cur);
+ }
cur = cur->next;
}
@@ -538,13 +559,6 @@ feed_rss_handler_init (FeedRssHandler *object)
object->priv = FEED_RSS_HANDLER_GET_PRIVATE (object);
}
-/**
- * feed_rss_handler_new:
- *
- * Allocates a new #FeedRssHandler
- *
- * Return value: a new #FeedRssHandler
- */
FeedRssHandler*
feed_rss_handler_new ()
{
diff --git a/src/feeds-group-handler.c b/src/feeds-group-handler.c
index 26c97d2..0699954 100644
--- a/src/feeds-group-handler.c
+++ b/src/feeds-group-handler.c
@@ -21,14 +21,6 @@
#include "utils.h"
#include "feeds-group-handler.h"
-/**
- * SECTION: feeds-group-handler
- * @short_description: interface for specialized groups parsers
- *
- * The #GrssFeedsGroupHandler interface defines a unique API for all specialized
- * groups parsers implementations
- */
-
static void
grss_feeds_group_handler_base_init (gpointer g_class)
{
@@ -52,17 +44,6 @@ grss_feeds_group_handler_get_type ()
return iface_type;
}
-/**
- * grss_feeds_group_handler_check_format:
- * @self: a #GrssFeedsGroupHandler
- * @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
- * #GrssFeedsGroupHandler, %FALSE otherwise
- */
gboolean
grss_feeds_group_handler_check_format (GrssFeedsGroupHandler *self, xmlDocPtr doc, xmlNodePtr cur)
{
@@ -72,17 +53,6 @@ grss_feeds_group_handler_check_format (GrssFeedsGroupHandler *self, xmlDocPtr do
return FEEDS_GROUP_HANDLER_GET_INTERFACE (self)->check_format (self, doc, cur);
}
-/**
- * grss_feeds_group_handler_parse:
- * @self: a #GrssFeedsGroupHandler
- * @doc: XML document from the feed
- * @error: location for eventual errors
- *
- * Parses the given @doc and extracts a list of #GrssFeedChannels
- *
- * Return value: a list of #GrssFeedChannels, to be freed when no longer in use,
- * or %NULL if an error occours (and @error is set accordly)
- */
GList*
grss_feeds_group_handler_parse (GrssFeedsGroupHandler *self, xmlDocPtr doc, GError **error)
{
@@ -92,18 +62,6 @@ grss_feeds_group_handler_parse (GrssFeedsGroupHandler *self, xmlDocPtr doc, GErr
return FEEDS_GROUP_HANDLER_GET_INTERFACE (self)->parse (self, doc, error);
}
-/**
- * grss_feeds_group_handler_dump:
- * @self: a #GrssFeedsGroupHandler
- * @channels: list of #GrssFeedChannels
- * @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*
grss_feeds_group_handler_dump (GrssFeedsGroupHandler *self, GList *channels, GError **error)
{
diff --git a/src/feeds-opml-group-handler.c b/src/feeds-opml-group-handler.c
index 5a833d6..38c21ef 100644
--- a/src/feeds-opml-group-handler.c
+++ b/src/feeds-opml-group-handler.c
@@ -33,13 +33,6 @@
#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 #GrssFeedsGroupHandler specialized for OPML contents
- */
-
struct FeedsOpmlGroupHandlerPrivate {
int rfu;
};
diff --git a/src/feeds-publisher.c b/src/feeds-publisher.c
index 35bcd6d..6bc438a 100644
--- a/src/feeds-publisher.c
+++ b/src/feeds-publisher.c
@@ -31,7 +31,7 @@
/**
* SECTION: feeds-publisher
- * @short_description: feed writer and PubSubHubbub publisher
+ * @short_description: feed writer and PubSubHubBub publisher
*
* #GrssFeedsPublisher may be used to expose contents for any given #GrssFeedChannel,
* both writing a file to be dispatched by the local webserver or providing
@@ -515,7 +515,7 @@ grss_feeds_publisher_publish (GrssFeedsPublisher *pub, GrssFeedChannel *channel,
* @pub: a #GrssFeedsPublisher
* @channel: the #GrssFeedChannel to dump in the file
* @items: list of #GrssFeedItems to be added in the feed
- * @path: path of the file to write
+ * @uri: URI of the file to write
*
* Dump the given @channel in an Atom formatted file in @path. If the local
* PubSubHubbub hub has been activated (with grss_feeds_publisher_hub_switch())
@@ -619,7 +619,7 @@ verification_message_for_client (RemoteSubscriber *client)
break;
}
- body = g_strdup_printf ("%s?hub.mode=%s&hub.topic=%s&hub.challenge=%s&hub.lease_seconds=%ld",
+ body = g_strdup_printf ("%s?hub.mode=%s&hub.topic=%s&hub.challenge=%s&hub.lease_seconds=%lld",
client->callback, mode, client->topic, client->challenge, client->lease_interval);
ret = soup_message_new ("GET", body);
diff --git a/src/feeds-pubsubhubbub-subscriber.c b/src/feeds-pubsubhubbub-subscriber.c
new file mode 100644
index 0000000..5b38789
--- /dev/null
+++ b/src/feeds-pubsubhubbub-subscriber.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2011, 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 "feeds-pubsubhubbub-subscriber.h"
+#include "feeds-subscriber.h"
+#include "feeds-subscriber-handler.h"
+#include "utils.h"
+#include "feed-parser.h"
+
+#define FEEDS_SUBSCRIBER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GRSS_FEEDS_PUBSUBHUBBUB_SUBSCRIBER_TYPE, GrssFeedsPubsubhubbubSubscriberPrivate))
+
+struct _GrssFeedsPubsubhubbubSubscriberPrivate {
+ GrssFeedsSubscriber *parent;
+ GrssFeedParser *parser;
+};
+
+static void feeds_subscriber_handler_interface_init (GrssFeedsSubscriberHandlerInterface *iface);
+G_DEFINE_TYPE_WITH_CODE (GrssFeedsPubsubhubbubSubscriber, grss_feeds_pubsubhubbub_subscriber, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (GRSS_FEEDS_SUBSCRIBER_HANDLER_TYPE,
+ feeds_subscriber_handler_interface_init));
+
+static void
+grss_feeds_pubsubhubbub_subscriber_finalize (GObject *obj)
+{
+ GrssFeedsPubsubhubbubSubscriber *sub;
+
+ sub = GRSS_FEEDS_PUBSUBHUBBUB_SUBSCRIBER (obj);
+ g_object_unref (sub->priv->parser);
+}
+
+static void
+grss_feeds_pubsubhubbub_subscriber_class_init (GrssFeedsPubsubhubbubSubscriberClass *klass)
+{
+ GObjectClass *gobject_class;
+
+ g_type_class_add_private (klass, sizeof (GrssFeedsPubsubhubbubSubscriberPrivate));
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = grss_feeds_pubsubhubbub_subscriber_finalize;
+}
+
+static void
+grss_feeds_pubsubhubbub_subscriber_init (GrssFeedsPubsubhubbubSubscriber *node)
+{
+ node->priv = FEEDS_SUBSCRIBER_GET_PRIVATE (node);
+ memset (node->priv, 0, sizeof (GrssFeedsPubsubhubbubSubscriberPrivate));
+ node->priv->parser = grss_feed_parser_new ();
+}
+
+GrssFeedsPubsubhubbubSubscriber*
+grss_feeds_pubsubhubbub_subscriber_new ()
+{
+ return g_object_new (GRSS_FEEDS_PUBSUBHUBBUB_SUBSCRIBER_TYPE, NULL);
+}
+
+static void
+feeds_pubsubhubbub_subscriber_handler_set_parent (GrssFeedsSubscriberHandler *handler,
+ GrssFeedsSubscriber *parent)
+{
+ GrssFeedsPubsubhubbubSubscriber *myself;
+
+ myself = GRSS_FEEDS_PUBSUBHUBBUB_SUBSCRIBER (handler);
+ myself->priv->parent = parent;
+}
+
+static gboolean
+feeds_pubsubhubbub_subscriber_handler_check_format (GrssFeedsSubscriberHandler *handler,
+ GrssFeedChannel *channel)
+{
+ return grss_feed_channel_get_pubsubhub (channel, NULL);
+}
+
+static void
+subscribe_response_cb (SoupSession *session,
+ SoupMessage *msg,
+ gpointer user_data)
+{
+ guint status;
+
+ g_object_get (msg, "status-code", &status, NULL);
+ if (status < 200 || status > 299)
+ g_warning ("Unable to subscribe feed: %s", msg->response_body->data);
+}
+
+static void
+feeds_pubsubhubbub_subscriber_handler_subscribe (GrssFeedsSubscriberHandler *handler,
+ GrssFeedChannel *channel,
+ gchar *assigned_url)
+{
+ int local_port;
+ gchar *body;
+ gchar *pubsubhub;
+ const gchar *source;
+ GInetAddress *local_addr;
+ SoupMessage *msg;
+ GrssFeedsPubsubhubbubSubscriber *myself;
+
+ if (grss_feed_channel_get_pubsubhub (channel, &pubsubhub) == FALSE)
+ return;
+
+ myself = GRSS_FEEDS_PUBSUBHUBBUB_SUBSCRIBER (handler);
+
+ local_addr = grss_feeds_subscriber_get_address (myself->priv->parent);
+ local_port = grss_feeds_subscriber_get_port (myself->priv->parent);
+ source = grss_feed_channel_get_source (channel);
+
+ body = g_strdup_printf ("hub.mode=subscribe&hub.callback=http://%s:%d/%s&hub.topic=%s&hub.verify=sync",
+ g_inet_address_to_string (local_addr), local_port, assigned_url, source);
+
+ msg = soup_message_new ("POST", pubsubhub);
+ soup_message_set_request (msg, "application/x-www-form-urlencoded", SOUP_MEMORY_TAKE, body, strlen (body));
+
+ soup_session_queue_message (grss_feeds_subscriber_get_session (myself->priv->parent), msg, subscribe_response_cb, NULL);
+}
+
+static GList*
+feeds_pubsubhubbub_subscriber_handler_handle_message (GrssFeedsSubscriberHandler *handler,
+ GrssFeedChannel *channel,
+ FEED_SUBSCRIPTION_STATUS *status,
+ SoupServer *server,
+ SoupMessage *msg,
+ const char *path,
+ GHashTable *query,
+ SoupClientContext *client)
+{
+ gchar *mode;
+ gchar *challenge;
+ GList *items;
+ GError *error;
+ xmlDocPtr doc;
+ GrssFeedsPubsubhubbubSubscriber *myself;
+
+ items = NULL;
+
+ if (query != NULL) {
+ mode = (gchar*) g_hash_table_lookup (query, "hub.mode");
+
+ if (*status == FEED_SUBSCRIPTION_SUBSCRIBING && strcmp (mode, "subscribe") == 0) {
+ challenge = g_strdup ((gchar*) g_hash_table_lookup (query, "hub.challenge"));
+ soup_message_set_response (msg, "application/x-www-form-urlencoded", SOUP_MEMORY_TAKE, challenge, strlen (challenge));
+
+ soup_message_set_status (msg, 200);
+ }
+ else if (*status == FEED_SUBSCRIPTION_UNSUBSCRIBING && strcmp (mode, "unsubscribe") == 0) {
+ *status = FEED_SUBSCRIPTION_IDLE;
+
+ challenge = g_strdup ((gchar*) g_hash_table_lookup (query, "hub.challenge"));
+ soup_message_set_response (msg, "application/x-www-form-urlencoded", SOUP_MEMORY_TAKE, challenge, strlen (challenge));
+
+ soup_message_set_status (msg, 200);
+ }
+ }
+ else if (*status == FEED_SUBSCRIPTION_SUBSCRIBED) {
+ /*
+ TODO Parsing and notification has to be moved in a
+ g_idle_add() function, so to reply to the
+ server as soon as possible
+ */
+
+ myself = GRSS_FEEDS_PUBSUBHUBBUB_SUBSCRIBER (handler);
+ doc = content_to_xml (msg->request_body->data, strlen (msg->request_body->data));
+ error = NULL;
+ items = grss_feed_parser_parse (myself->priv->parser, channel, doc, &error);
+
+ if (items == NULL) {
+ g_warning ("Unable to parse notification from %s: %s", grss_feed_channel_get_source (channel), error->message);
+ g_error_free (error);
+ }
+
+ xmlFreeDoc (doc);
+ soup_message_set_status (msg, 202);
+ }
+ else {
+ soup_message_set_status (msg, 404);
+ }
+
+ return items;
+}
+
+static void
+unsubscribe_response_cb (SoupSession *session,
+ SoupMessage *msg,
+ gpointer user_data)
+{
+ /* dummy */
+}
+
+static void
+feeds_pubsubhubbub_subscriber_handler_unsubscribe (GrssFeedsSubscriberHandler *handler,
+ GrssFeedChannel *channel,
+ gchar *assigned_url)
+{
+ int local_port;
+ gchar *body;
+ gchar *pubsubhub;
+ const gchar *source;
+ GInetAddress *local_addr;
+ SoupMessage *msg;
+ GrssFeedsPubsubhubbubSubscriber *myself;
+
+ if (grss_feed_channel_get_pubsubhub (channel, &pubsubhub) == FALSE)
+ return;
+
+ myself = GRSS_FEEDS_PUBSUBHUBBUB_SUBSCRIBER (handler);
+
+ local_addr = grss_feeds_subscriber_get_address (myself->priv->parent);
+ local_port = grss_feeds_subscriber_get_port (myself->priv->parent);
+ source = grss_feed_channel_get_source (channel);
+
+ body = g_strdup_printf ("hub.mode=unsubscribe&hub.callback=http://%s:%d/%s&hub.topic=%s&hub.verify=sync",
+ g_inet_address_to_string (local_addr), local_port, assigned_url, source);
+
+ msg = soup_message_new ("POST", pubsubhub);
+ soup_message_set_request (msg, "application/x-www-form-urlencoded", SOUP_MEMORY_TAKE, body, strlen (body));
+
+ soup_session_queue_message (grss_feeds_subscriber_get_session (myself->priv->parent), msg, unsubscribe_response_cb, NULL);
+}
+
+static void
+feeds_subscriber_handler_interface_init (GrssFeedsSubscriberHandlerInterface *iface)
+{
+ iface->set_parent = feeds_pubsubhubbub_subscriber_handler_set_parent;
+ iface->check_format = feeds_pubsubhubbub_subscriber_handler_check_format;
+ iface->subscribe = feeds_pubsubhubbub_subscriber_handler_subscribe;
+ iface->handle_message = feeds_pubsubhubbub_subscriber_handler_handle_message;
+ iface->unsubscribe = feeds_pubsubhubbub_subscriber_handler_unsubscribe;
+}
diff --git a/src/feeds-pubsubhubbub-subscriber.h b/src/feeds-pubsubhubbub-subscriber.h
new file mode 100644
index 0000000..5154a86
--- /dev/null
+++ b/src/feeds-pubsubhubbub-subscriber.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2011, 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_PUBSUBHUBBUB_SUBSCRIBER_H__
+#define __FEEDS_PUBSUBHUBBUB_SUBSCRIBER_H__
+
+#include "libgrss.h"
+
+#define GRSS_FEEDS_PUBSUBHUBBUB_SUBSCRIBER_TYPE (grss_feeds_pubsubhubbub_subscriber_get_type())
+#define GRSS_FEEDS_PUBSUBHUBBUB_SUBSCRIBER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GRSS_FEEDS_PUBSUBHUBBUB_SUBSCRIBER_TYPE, GrssFeedsPubsubhubbubSubscriber))
+#define GRSS_FEEDS_PUBSUBHUBBUB_SUBSCRIBER_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GRSS_FEEDS_PUBSUBHUBBUB_SUBSCRIBER_TYPE, GrssFeedsPubsubhubbubSubscriberClass))
+#define GRSS_IS_FEEDS_PUBSUBHUBBUB_SUBSCRIBER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GRSS_FEEDS_PUBSUBHUBBUB_SUBSCRIBER_TYPE))
+#define GRSS_IS_FEEDS_PUBSUBHUBBUB_SUBSCRIBER_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), GRSS_FEEDS_PUBSUBHUBBUB_SUBSCRIBER_TYPE))
+#define GRSS_PUBSUBHUBBUB_SUBSCRIBER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GRSS_FEEDS_PUBSUBHUBBUB_SUBSCRIBER_TYPE, GrssFeedsPubsubhubbubSubscriberClass))
+
+typedef struct _GrssFeedsPubsubhubbubSubscriber GrssFeedsPubsubhubbubSubscriber;
+typedef struct _GrssFeedsPubsubhubbubSubscriberPrivate GrssFeedsPubsubhubbubSubscriberPrivate;
+
+struct _GrssFeedsPubsubhubbubSubscriber {
+ GObject parent;
+ GrssFeedsPubsubhubbubSubscriberPrivate *priv;
+};
+
+typedef struct {
+ GObjectClass parent;
+} GrssFeedsPubsubhubbubSubscriberClass;
+
+GType grss_feeds_pubsubhubbub_subscriber_get_type () G_GNUC_CONST;
+
+GrssFeedsPubsubhubbubSubscriber* grss_feeds_pubsubhubbub_subscriber_new ();
+
+#endif /* __FEEDS_PUBSUBHUBBUB_SUBSCRIBER_H__ */
diff --git a/src/feeds-rsscloud-subscriber.c b/src/feeds-rsscloud-subscriber.c
new file mode 100644
index 0000000..24c3445
--- /dev/null
+++ b/src/feeds-rsscloud-subscriber.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2011, 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 "feeds-rsscloud-subscriber.h"
+#include "feeds-subscriber.h"
+#include "feeds-subscriber-handler.h"
+#include "utils.h"
+#include "feed-parser.h"
+
+#define FEEDS_SUBSCRIBER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GRSS_FEEDS_RSSCLOUD_SUBSCRIBER_TYPE, GrssFeedsRsscloudSubscriberPrivate))
+
+struct _GrssFeedsRsscloudSubscriberPrivate {
+ GrssFeedsSubscriber *parent;
+};
+
+static void feeds_subscriber_handler_interface_init (GrssFeedsSubscriberHandlerInterface *iface);
+G_DEFINE_TYPE_WITH_CODE (GrssFeedsRsscloudSubscriber, grss_feeds_rsscloud_subscriber, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (GRSS_FEEDS_SUBSCRIBER_HANDLER_TYPE,
+ feeds_subscriber_handler_interface_init));
+
+static void
+grss_feeds_rsscloud_subscriber_finalize (GObject *obj)
+{
+ /* dummy */
+}
+
+static void
+grss_feeds_rsscloud_subscriber_class_init (GrssFeedsRsscloudSubscriberClass *klass)
+{
+ GObjectClass *gobject_class;
+
+ g_type_class_add_private (klass, sizeof (GrssFeedsRsscloudSubscriberPrivate));
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = grss_feeds_rsscloud_subscriber_finalize;
+}
+
+static void
+grss_feeds_rsscloud_subscriber_init (GrssFeedsRsscloudSubscriber *node)
+{
+ node->priv = FEEDS_SUBSCRIBER_GET_PRIVATE (node);
+ memset (node->priv, 0, sizeof (GrssFeedsRsscloudSubscriberPrivate));
+}
+
+GrssFeedsRsscloudSubscriber*
+grss_feeds_rsscloud_subscriber_new ()
+{
+ return g_object_new (GRSS_FEEDS_RSSCLOUD_SUBSCRIBER_TYPE, NULL);
+}
+
+static void
+feeds_rsscloud_subscriber_handler_set_parent (GrssFeedsSubscriberHandler *handler,
+ GrssFeedsSubscriber *parent)
+{
+ GrssFeedsRsscloudSubscriber *myself;
+
+ myself = GRSS_FEEDS_RSSCLOUD_SUBSCRIBER (handler);
+ myself->priv->parent = parent;
+}
+
+static void
+subscribe_response_cb (SoupSession *session,
+ SoupMessage *msg,
+ gpointer user_data)
+{
+ gboolean done;
+ const xmlChar *success;
+ guint status;
+ xmlDocPtr doc;
+ xmlNodePtr cur;
+
+ done = TRUE;
+
+ g_object_get (msg, "status-code", &status, NULL);
+
+ if (status < 200 || status > 299) {
+ done = FALSE;
+ }
+ else {
+ doc = content_to_xml (msg->response_body->data, strlen (msg->response_body->data));
+ success = NULL;
+
+ if ((cur = xmlDocGetRootElement (doc)) == NULL ||
+ xmlStrcmp (cur->name, BAD_CAST "notifyResult") != 0 ||
+ (success = xmlGetProp (cur, BAD_CAST"success")) == NULL ||
+ xmlStrcmp (success, BAD_CAST "true") != 0)
+ done = FALSE;
+
+ xmlFreeDoc (doc);
+
+ if (success != NULL)
+ xmlFree (success);
+ }
+
+ if (done == FALSE) {
+ g_warning ("Unable to subscribe feed: %s", msg->response_body->data);
+ }
+}
+
+gboolean
+feeds_rsscloud_subscriber_handler_check_format (GrssFeedsSubscriberHandler *handler,
+ GrssFeedChannel *channel)
+{
+ return grss_feed_channel_get_rsscloud (channel, NULL, NULL);
+}
+
+void
+feeds_rsscloud_subscriber_handler_subscribe (GrssFeedsSubscriberHandler *handler,
+ GrssFeedChannel *channel,
+ gchar *assigned_url)
+{
+ int local_port;
+ gchar *body;
+ gchar *path;
+ gchar *protocol;
+ const gchar *source;
+ SoupMessage *msg;
+ GInetAddress *local_addr;
+ GrssFeedsRsscloudSubscriber *myself;
+
+ if (grss_feed_channel_get_rsscloud (channel, &path, &protocol) == FALSE)
+ return;
+
+ myself = GRSS_FEEDS_RSSCLOUD_SUBSCRIBER (handler);
+
+ local_addr = grss_feeds_subscriber_get_address (myself->priv->parent);
+ local_port = grss_feeds_subscriber_get_port (myself->priv->parent);
+ source = grss_feed_channel_get_source (channel);
+
+ body = g_strdup_printf ("notifyProcedure=\"\"&protocol=%s&domain=%s&path=%s&port=%d&url1=%s",
+ protocol, g_inet_address_to_string (local_addr), assigned_url, local_port, source);
+
+ msg = soup_message_new ("POST", path);
+ soup_message_set_request (msg, "application/x-www-form-urlencoded", SOUP_MEMORY_TAKE, body, strlen (body));
+ soup_session_queue_message (grss_feeds_subscriber_get_session (myself->priv->parent), msg, subscribe_response_cb, NULL);
+}
+
+GList*
+feeds_rsscloud_subscriber_handler_handle_message (GrssFeedsSubscriberHandler *handler,
+ GrssFeedChannel *channel,
+ FEED_SUBSCRIPTION_STATUS *status,
+ SoupServer *server,
+ SoupMessage *msg,
+ const char *path,
+ GHashTable *query,
+ SoupClientContext *client)
+{
+ GList *ret;
+ gchar *challenge;
+
+ ret = NULL;
+
+ if (query != NULL) {
+ challenge = (gchar*) g_hash_table_lookup (query, "challenge");
+
+ if (*status == FEED_SUBSCRIPTION_SUBSCRIBING && challenge != NULL) {
+ challenge = g_strdup (challenge);
+ soup_message_set_response (msg, "application/x-www-form-urlencoded", SOUP_MEMORY_TAKE, challenge, strlen (challenge));
+ soup_message_set_status (msg, 200);
+ }
+ }
+ else if (*status == FEED_SUBSCRIPTION_SUBSCRIBED) {
+ ret = grss_feed_channel_fetch_all (channel);
+ soup_message_set_status (msg, 202);
+ }
+ else {
+ soup_message_set_status (msg, 404);
+ }
+
+ return ret;
+}
+
+void
+feeds_rsscloud_subscriber_handler_unsubscribe (GrssFeedsSubscriberHandler *handler,
+ GrssFeedChannel *channel,
+ gchar *assigned_url)
+{
+ /* dummy */
+}
+
+static void
+feeds_subscriber_handler_interface_init (GrssFeedsSubscriberHandlerInterface *iface)
+{
+ iface->set_parent = feeds_rsscloud_subscriber_handler_set_parent;
+ iface->check_format = feeds_rsscloud_subscriber_handler_check_format;
+ iface->subscribe = feeds_rsscloud_subscriber_handler_subscribe;
+ iface->handle_message = feeds_rsscloud_subscriber_handler_handle_message;
+ iface->unsubscribe = feeds_rsscloud_subscriber_handler_unsubscribe;
+}
diff --git a/src/feeds-rsscloud-subscriber.h b/src/feeds-rsscloud-subscriber.h
new file mode 100644
index 0000000..07ab3e3
--- /dev/null
+++ b/src/feeds-rsscloud-subscriber.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2011, 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_RSSCLOUD_SUBSCRIBER_H__
+#define __FEEDS_RSSCLOUD_SUBSCRIBER_H__
+
+#include "libgrss.h"
+
+#define GRSS_FEEDS_RSSCLOUD_SUBSCRIBER_TYPE (grss_feeds_rsscloud_subscriber_get_type())
+#define GRSS_FEEDS_RSSCLOUD_SUBSCRIBER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GRSS_FEEDS_RSSCLOUD_SUBSCRIBER_TYPE, GrssFeedsRsscloudSubscriber))
+#define GRSS_FEEDS_RSSCLOUD_SUBSCRIBER_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GRSS_FEEDS_RSSCLOUD_SUBSCRIBER_TYPE, GrssFeedsRsscloudSubscriberClass))
+#define GRSS_IS_RSSCLOUD_SUBSCRIBER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GRSS_FEEDS_RSSCLOUD_SUBSCRIBER_TYPE))
+#define GRSS_IS_FEEDS_RSSCLOUD_SUBSCRIBER_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), GRSS_FEEDS_RSSCLOUD_SUBSCRIBER_TYPE))
+#define GRSS_FEEDS_RSSCLOUD_SUBSCRIBER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GRSS_FEEDS_RSSCLOUD_SUBSCRIBER_TYPE, GrssFeedsRsscloudSubscriberClass))
+
+typedef struct _GrssFeedsRsscloudSubscriber GrssFeedsRsscloudSubscriber;
+typedef struct _GrssFeedsRsscloudSubscriberPrivate GrssFeedsRsscloudSubscriberPrivate;
+
+struct _GrssFeedsRsscloudSubscriber {
+ GObject parent;
+ GrssFeedsRsscloudSubscriberPrivate *priv;
+};
+
+typedef struct {
+ GObjectClass parent;
+} GrssFeedsRsscloudSubscriberClass;
+
+GType grss_feeds_rsscloud_subscriber_get_type () G_GNUC_CONST;
+
+GrssFeedsRsscloudSubscriber* grss_feeds_rsscloud_subscriber_new ();
+
+#endif /* __FEEDS_RSSCLOUD_SUBSCRIBER_H__ */
diff --git a/src/feeds-subscriber-handler.c b/src/feeds-subscriber-handler.c
new file mode 100644
index 0000000..54213ea
--- /dev/null
+++ b/src/feeds-subscriber-handler.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2011, 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-subscriber-handler.h"
+
+static void
+grss_feeds_subscriber_handler_base_init (gpointer g_class)
+{
+}
+
+GType
+grss_feeds_subscriber_handler_get_type ()
+{
+ static GType iface_type = 0;
+
+ if (iface_type == 0) {
+ static const GTypeInfo info = {
+ sizeof (GrssFeedsSubscriberHandlerInterface),
+ grss_feeds_subscriber_handler_base_init,
+ NULL,
+ };
+
+ iface_type = g_type_register_static (G_TYPE_INTERFACE, "GrssFeedsSubscriberHandler", &info, 0);
+ }
+
+ return iface_type;
+}
+
+void
+grss_feeds_subscriber_handler_set_parent (GrssFeedsSubscriberHandler *handler,
+ GrssFeedsSubscriber *parent)
+{
+ if (GRSS_IS_FEEDS_SUBSCRIBER_HANDLER (handler) == FALSE)
+ return;
+
+ return GRSS_FEEDS_SUBSCRIBER_HANDLER_GET_INTERFACE (handler)->set_parent (handler, parent);
+}
+
+gboolean
+grss_feeds_subscriber_handler_check_format (GrssFeedsSubscriberHandler *handler,
+ GrssFeedChannel *channel)
+{
+ if (GRSS_IS_FEEDS_SUBSCRIBER_HANDLER (handler) == FALSE)
+ return FALSE;
+
+ return GRSS_FEEDS_SUBSCRIBER_HANDLER_GET_INTERFACE (handler)->check_format (handler, channel);
+}
+
+void
+grss_feeds_subscriber_handler_subscribe (GrssFeedsSubscriberHandler *handler,
+ GrssFeedChannel *channel,
+ gchar *assigned_url)
+{
+ if (GRSS_IS_FEEDS_SUBSCRIBER_HANDLER (handler) == FALSE)
+ return;
+
+ GRSS_FEEDS_SUBSCRIBER_HANDLER_GET_INTERFACE (handler)->subscribe (handler, channel, assigned_url);
+}
+
+GList*
+grss_feeds_subscriber_handler_handle_incoming_message (GrssFeedsSubscriberHandler *handler,
+ GrssFeedChannel *channel,
+ FEED_SUBSCRIPTION_STATUS *status,
+ SoupServer *server,
+ SoupMessage *msg,
+ const char *path,
+ GHashTable *query,
+ SoupClientContext *client)
+{
+ if (GRSS_IS_FEEDS_SUBSCRIBER_HANDLER (handler) == FALSE)
+ return NULL;
+
+ return GRSS_FEEDS_SUBSCRIBER_HANDLER_GET_INTERFACE (handler)->handle_message (handler, channel, status, server, msg, path, query, client);
+}
+
+void
+grss_feeds_subscriber_handler_unsubscribe (GrssFeedsSubscriberHandler *handler,
+ GrssFeedChannel *channel,
+ gchar *assigned_url)
+{
+ if (GRSS_IS_FEEDS_SUBSCRIBER_HANDLER (handler) == FALSE)
+ return;
+
+ GRSS_FEEDS_SUBSCRIBER_HANDLER_GET_INTERFACE (handler)->unsubscribe (handler, channel, assigned_url);
+}
diff --git a/src/feeds-subscriber-handler.h b/src/feeds-subscriber-handler.h
new file mode 100644
index 0000000..4479317
--- /dev/null
+++ b/src/feeds-subscriber-handler.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2011, 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 __GRSS_FEEDS_SUBSCRIBER_HANDLER_H__
+#define __GRSS_FEEDS_SUBSCRIBER_HANDLER_H__
+
+#include "libgrss.h"
+
+#define GRSS_FEEDS_SUBSCRIBER_HANDLER_TYPE (grss_feeds_subscriber_handler_get_type ())
+#define GRSS_FEEDS_SUBSCRIBER_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GRSS_FEEDS_SUBSCRIBER_HANDLER_TYPE, GrssFeedsSubscriberHandler))
+#define GRSS_IS_FEEDS_SUBSCRIBER_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GRSS_FEEDS_SUBSCRIBER_HANDLER_TYPE))
+#define GRSS_FEEDS_SUBSCRIBER_HANDLER_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GRSS_FEEDS_SUBSCRIBER_HANDLER_TYPE, GrssFeedsSubscriberHandlerInterface))
+
+typedef struct _GrssFeedsSubscriberHandler GrssFeedsSubscriberHandler;
+typedef struct _GrssFeedsSubscriberHandlerInterface GrssFeedsSubscriberHandlerInterface;
+
+typedef enum {
+ FEED_SUBSCRIPTION_IDLE,
+ FEED_SUBSCRIPTION_SUBSCRIBING,
+ FEED_SUBSCRIPTION_SUBSCRIBED,
+ FEED_SUBSCRIPTION_UNSUBSCRIBING,
+} FEED_SUBSCRIPTION_STATUS;
+
+struct _GrssFeedsSubscriberHandlerInterface {
+ GTypeInterface parent_iface;
+
+ void (*set_parent) (GrssFeedsSubscriberHandler *handler, GrssFeedsSubscriber *parent);
+ gboolean (*check_format) (GrssFeedsSubscriberHandler *handler, GrssFeedChannel *channel);
+ void (*subscribe) (GrssFeedsSubscriberHandler *handler, GrssFeedChannel *channel, gchar *assigned_url);
+ GList* (*handle_message) (GrssFeedsSubscriberHandler *handler, GrssFeedChannel *channel, FEED_SUBSCRIPTION_STATUS *status, SoupServer *server, SoupMessage *msg, const char *path, GHashTable *query, SoupClientContext *client);
+ void (*unsubscribe) (GrssFeedsSubscriberHandler *handler, GrssFeedChannel *channel, gchar *assigned_url);
+};
+
+GType grss_feeds_subscriber_handler_get_type ();
+
+void grss_feeds_subscriber_handler_set_parent (GrssFeedsSubscriberHandler *handler, GrssFeedsSubscriber *parent);
+gboolean grss_feeds_subscriber_handler_check_format (GrssFeedsSubscriberHandler *handler, GrssFeedChannel *channel);
+void grss_feeds_subscriber_handler_subscribe (GrssFeedsSubscriberHandler *handler, GrssFeedChannel *channel, gchar *assigned_url);
+GList* grss_feeds_subscriber_handler_handle_incoming_message (GrssFeedsSubscriberHandler *handler, GrssFeedChannel *channel, FEED_SUBSCRIPTION_STATUS *status, SoupServer *server, SoupMessage *msg, const char *path, GHashTable *query, SoupClientContext *client);
+void grss_feeds_subscriber_handler_unsubscribe (GrssFeedsSubscriberHandler *handler, GrssFeedChannel *channel, gchar *assigned_url);
+
+#endif /* __GRSS_FEEDS_SUBSCRIBER_HANDLER_H__ */
diff --git a/src/feeds-subscriber.c b/src/feeds-subscriber.c
index 3aef7c2..df56694 100644
--- a/src/feeds-subscriber.c
+++ b/src/feeds-subscriber.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009, Roberto Guido <rguido src gnome org>
+ * Copyright (C) 2011, Roberto Guido <rguido src gnome org>
* Michele Tameni <michele amdplanet it>
*
* This library is free software; you can redistribute it and/or
@@ -19,6 +19,9 @@
*/
#include "feeds-subscriber.h"
+#include "feeds-subscriber-handler.h"
+#include "feeds-pubsubhubbub-subscriber.h"
+#include "feeds-rsscloud-subscriber.h"
#include "utils.h"
#include "feed-parser.h"
#include "feed-marshal.h"
@@ -29,16 +32,15 @@
/**
* SECTION: feeds-subscriber
- * @short_description: PubSubHubbub subscriber
+ * @short_description: feeds subscriber
*
* #GrssFeedsSubscriber is an alternative for #GrssFeedsPool, able to receive
- * real-time notifications by feeds managed by a PubSubHubbub hub.
+ * real-time notifications by feeds managed by one of the supported protocols.
* When the subscriber is executed (with grss_feeds_subscriber_switch()) it opens
* a server on a local port (configurable with grss_feeds_subscriber_set_port()),
* engage a subscription for each #GrssFeedChannel passed with
* grss_feeds_subscriber_listen(), and waits for direct notifications by the
- * remote hub.
- * For more information look at http://code.google.com/p/pubsubhubbub/
+ * remote server.
*/
/*
@@ -49,59 +51,34 @@
client side in case of problems by the server side
*/
-typedef enum {
- SUBSCRIBER_IS_IDLE,
- SUBSCRIBER_TRYING_LOCAL_IP,
- SUBSCRIBER_CHECKING_PUBLIC_IP
-} SUBSCRIBER_INIT_STATUS;
-
static void subscribe_feeds (GrssFeedsSubscriber *sub);
-static void try_another_subscription_policy (GrssFeedsSubscriber *sub);
-
-typedef void (*SubscriberJobCallback) (GrssFeedsSubscriber *subscriber);
struct _GrssFeedsSubscriberPrivate {
gboolean running;
- SUBSCRIBER_INIT_STATUS initing_status;
- gboolean has_errors_in_subscription;
int port;
SoupServer *server;
GInetAddress *local_addr;
- GInetAddress *external_addr;
+ GInetAddress *exposed_addr;
- gchar *hub;
SoupSession *soupsession;
GrssFeedParser *parser;
+ GList *handlers;
GList *feeds_list;
-
- guint refresh_scheduler;
};
-typedef enum {
- FEED_SUBSCRIPTION_IDLE,
- FEED_SUBSCRIPTION_SUBSCRIBING,
- FEED_SUBSCRIPTION_SUBSCRIBED,
- FEED_SUBSCRIPTION_UNSUBSCRIBING,
-} FEED_SUBSCRIPTION_STATUS;
-
typedef struct {
GrssFeedChannel *channel;
FEED_SUBSCRIPTION_STATUS status;
- int identifier;
+ gchar *identifier;
gchar *path;
- GrssFeedsSubscriber *sub;
+ GrssFeedsSubscriber *sub;
+ GrssFeedsSubscriberHandler *handler;
} GrssFeedChannelWrap;
-typedef struct {
- int counter;
- SubscriberJobCallback callback;
- GrssFeedsSubscriber *subscriber;
-} SubscriberJob;
-
enum {
NOTIFICATION_RECEIVED,
LAST_SIGNAL
@@ -143,7 +120,6 @@ grss_feeds_subscriber_finalize (GObject *obj)
sub = GRSS_FEEDS_SUBSCRIBER (obj);
grss_feeds_subscriber_switch (sub, FALSE);
remove_currently_listened (sub);
- FREE_STRING (sub->priv->hub);
g_object_unref (sub->priv->parser);
}
@@ -176,10 +152,22 @@ grss_feeds_subscriber_class_init (GrssFeedsSubscriberClass *klass)
static void
grss_feeds_subscriber_init (GrssFeedsSubscriber *node)
{
+ GrssFeedsSubscriberHandler *handler;
+
node->priv = FEEDS_SUBSCRIBER_GET_PRIVATE (node);
memset (node->priv, 0, sizeof (GrssFeedsSubscriberPrivate));
node->priv->parser = grss_feed_parser_new ();
node->priv->port = DEFAULT_SERVER_PORT;
+
+ node->priv->handlers = NULL;
+
+ handler = GRSS_FEEDS_SUBSCRIBER_HANDLER (grss_feeds_pubsubhubbub_subscriber_new ());
+ node->priv->handlers = g_list_prepend (node->priv->handlers, handler);
+ grss_feeds_subscriber_handler_set_parent (handler, node);
+
+ handler = GRSS_FEEDS_SUBSCRIBER_HANDLER (grss_feeds_rsscloud_subscriber_new ());
+ node->priv->handlers = g_list_prepend (node->priv->handlers, handler);
+ grss_feeds_subscriber_handler_set_parent (handler, node);
}
/**
@@ -195,6 +183,21 @@ grss_feeds_subscriber_new ()
return g_object_new (GRSS_FEEDS_SUBSCRIBER_TYPE, NULL);
}
+static GrssFeedsSubscriberHandler*
+retrieve_handler (GrssFeedsSubscriber *sub, GrssFeedChannel *feed)
+{
+ GList *iter;
+ GrssFeedsSubscriberHandler *handler;
+
+ for (iter = sub->priv->handlers; iter; iter = g_list_next (iter)) {
+ handler = (GrssFeedsSubscriberHandler*) iter->data;
+ if (grss_feeds_subscriber_handler_check_format (handler, feed) == TRUE)
+ return handler;
+ }
+
+ return NULL;
+}
+
static gboolean
create_listened (GrssFeedsSubscriber *sub, GList *feeds)
{
@@ -202,14 +205,14 @@ create_listened (GrssFeedsSubscriber *sub, GList *feeds)
GList *iter;
GrssFeedChannel *feed;
GrssFeedChannelWrap *wrap;
+ GrssFeedsSubscriberHandler *handler;
for (iter = feeds; iter; iter = g_list_next (iter)) {
feed = (GrssFeedChannel*) iter->data;
- if (grss_feed_channel_get_pubsubhub (feed, NULL, NULL) == FALSE) {
- g_warning ("Feed at %s has not PubSubHubbub capability", grss_feed_channel_get_source (feed));
+ handler = retrieve_handler (sub, feed);
+ if (handler == NULL)
return FALSE;
- }
}
list = NULL;
@@ -223,6 +226,7 @@ create_listened (GrssFeedsSubscriber *sub, GList *feeds)
wrap->path = NULL;
wrap->channel = feed;
wrap->sub = sub;
+ wrap->handler = retrieve_handler (sub, feed);
list = g_list_prepend (list, wrap);
}
@@ -242,7 +246,7 @@ create_listened (GrssFeedsSubscriber *sub, GList *feeds)
* are g_object_ref'd here
*
* Return value: %TRUE if all #GrssFeedChannels involved in @feeds are valid
- * (grss_feed_channel_get_pubsubhub() returns %TRUE), %FALSE otherwise
+ * and can be listened with one of the implemented procotols, %FALSE otherwise
*/
gboolean
grss_feeds_subscriber_listen (GrssFeedsSubscriber *sub, GList *feeds)
@@ -275,75 +279,19 @@ grss_feeds_subscriber_get_listened (GrssFeedsSubscriber *sub)
}
static void
-check_complete_job (SubscriberJob *job)
-{
- job->counter--;
-
- if (job->counter <= 0) {
- job->callback (job->subscriber);
- g_free (job);
- }
-}
-
-static void
handle_incoming_notification_cb (SoupServer *server, SoupMessage *msg, const char *path,
GHashTable *query, SoupClientContext *client, gpointer user_data)
{
- gchar *mode;
- gchar *challenge;
GList *iter;
GList *items;
- GError *error;
- xmlDocPtr doc;
GrssFeedChannelWrap *feed;
feed = (GrssFeedChannelWrap*) user_data;
+ items = grss_feeds_subscriber_handler_handle_incoming_message (feed->handler, feed->channel, &(feed->status), server, msg, path, query, client);
- if (query != NULL) {
- mode = (gchar*) g_hash_table_lookup (query, "hub.mode");
-
- if (feed->status == FEED_SUBSCRIPTION_SUBSCRIBING && strcmp (mode, "subscribe") == 0) {
- challenge = g_strdup ((gchar*) g_hash_table_lookup (query, "hub.challenge"));
- soup_message_set_response (msg, "application/x-www-form-urlencoded", SOUP_MEMORY_TAKE, challenge, strlen (challenge));
-
- soup_message_set_status (msg, 200);
- }
- else if (feed->status == FEED_SUBSCRIPTION_UNSUBSCRIBING && strcmp (mode, "unsubscribe") == 0) {
- feed->status = FEED_SUBSCRIPTION_IDLE;
-
- challenge = g_strdup ((gchar*) g_hash_table_lookup (query, "hub.challenge"));
- soup_message_set_response (msg, "application/x-www-form-urlencoded", SOUP_MEMORY_TAKE, challenge, strlen (challenge));
-
- soup_message_set_status (msg, 200);
- }
- }
- else if (feed->status == FEED_SUBSCRIPTION_SUBSCRIBED) {
- /*
- TODO Parsing and notification has to be moved in a
- g_idle_add() function, so to reply to the
- server as soon as possible
- */
-
- doc = content_to_xml (msg->request_body->data, strlen (msg->request_body->data));
- error = NULL;
- items = grss_feed_parser_parse (feed->sub->priv->parser, feed->channel, doc, &error);
-
- if (items == NULL) {
- g_warning ("Unable to parse notification from %s: %s", grss_feed_channel_get_source (feed->channel), error->message);
- g_error_free (error);
- }
- else {
- for (iter = items; iter; iter = g_list_next (iter))
- g_signal_emit (feed->sub, signals [NOTIFICATION_RECEIVED], 0, feed->channel, (GrssFeedItem*) iter->data, NULL);
- g_list_free (items);
- }
-
- xmlFreeDoc (doc);
- soup_message_set_status (msg, 202);
- }
- else {
- soup_message_set_status (msg, 404);
- }
+ for (iter = items; iter; iter = g_list_next (iter))
+ g_signal_emit (feed->sub, signals [NOTIFICATION_RECEIVED], 0, feed->channel, (GrssFeedItem*) iter->data, NULL);
+ g_list_free (items);
}
static void
@@ -367,11 +315,11 @@ register_handlers (GrssFeedsSubscriber *sub)
for (i = 1, iter = sub->priv->feeds_list; iter; iter = g_list_next (iter), i++) {
feed = (GrssFeedChannelWrap*) iter->data;
- feed->identifier = i;
+ feed->identifier = g_strdup_printf ("%d", i);
feed->status = FEED_SUBSCRIPTION_SUBSCRIBING;
FREE_STRING (feed->path);
- feed->path = g_strdup_printf ("/%d", feed->identifier);
+ feed->path = g_strdup_printf ("/%s", feed->identifier);
soup_server_add_handler (sub->priv->server, feed->path, handle_incoming_notification_cb, feed, NULL);
}
}
@@ -388,72 +336,17 @@ close_server (GrssFeedsSubscriber *sub)
}
static void
-feeds_subscribed_cb (GrssFeedsSubscriber *sub)
-{
- if (sub->priv->has_errors_in_subscription == TRUE)
- try_another_subscription_policy (sub);
-}
-
-static void
-subscribe_response_cb (SoupSession *session, SoupMessage *msg, gpointer user_data)
-{
- guint status;
- SubscriberJob *job;
-
- job = (SubscriberJob*) user_data;
-
- g_object_get (msg, "status-code", &status, NULL);
- if (status < 200 || status > 299) {
- g_warning ("Unable to subscribe feed: %s", msg->response_body->data);
- job->subscriber->priv->has_errors_in_subscription = TRUE;
- }
-
- check_complete_job (job);
-}
-
-static void
-subscribe_feed (GrssFeedsSubscriber *sub, GrssFeedChannelWrap *feed, SubscriberJob *job)
-{
- gchar *body;
- gchar *pubsubhub;
- gchar *feed_reference;
- SoupMessage *msg;
-
- if (grss_feed_channel_get_pubsubhub (feed->channel, &pubsubhub, &feed_reference) == FALSE)
- return;
-
- if (sub->priv->hub != NULL)
- pubsubhub = sub->priv->hub;
-
- body = g_strdup_printf ("hub.mode=subscribe&hub.callback=http://%s:%d/%d&hub.topic=%s&hub.verify=sync",
- g_inet_address_to_string (sub->priv->external_addr), sub->priv->port, feed->identifier, feed_reference);
-
- msg = soup_message_new ("POST", pubsubhub);
- soup_message_set_request (msg, "application/x-www-form-urlencoded", SOUP_MEMORY_TAKE, body, strlen (body));
-
- soup_session_queue_message (sub->priv->soupsession, msg, subscribe_response_cb, job);
-}
-
-static void
subscribe_feeds (GrssFeedsSubscriber *sub)
{
GList *iter;
GrssFeedChannelWrap *feed;
- SubscriberJob *job;
if (sub->priv->feeds_list == NULL)
return;
- job = g_new0 (SubscriberJob, 1);
- job->counter = g_list_length (sub->priv->feeds_list);
- job->callback = feeds_subscribed_cb;
- job->subscriber = sub;
-
- sub->priv->has_errors_in_subscription = FALSE;
-
for (iter = sub->priv->feeds_list; iter; iter = g_list_next (iter)) {
feed = (GrssFeedChannelWrap*) iter->data;
- subscribe_feed (sub, feed, job);
+ grss_feeds_subscriber_handler_subscribe (feed->handler, feed->channel, feed->identifier);
}
}
@@ -472,20 +365,26 @@ create_and_run_server (GrssFeedsSubscriber *sub)
gchar *ip;
struct sockaddr_in low_addr;
SoupAddress *soup_addr;
- GInetAddress *my_addr;
-
- my_addr = my_detect_internet_address (sub);
- if (my_addr == NULL)
- return;
low_addr.sin_family = AF_INET;
low_addr.sin_port = htons (sub->priv->port);
- ip = g_inet_address_to_string (my_addr);
+ ip = g_inet_address_to_string (sub->priv->local_addr);
+
inet_pton (AF_INET, ip, &low_addr.sin_addr);
g_free (ip);
soup_addr = soup_address_new_from_sockaddr ((struct sockaddr*) &low_addr, sizeof (low_addr));
- sub->priv->server = soup_server_new ("port", sub->priv->port, "interface", soup_addr, NULL);
+ if (soup_addr == NULL) {
+ g_warning ("Unable to use detected exposed IP");
+ return;
+ }
+
+ sub->priv->server = soup_server_new (SOUP_SERVER_INTERFACE, soup_addr, NULL);
+ if (sub->priv->server == NULL) {
+ g_warning ("Unable to open server on detected exposed IP");
+ return;
+ }
+
g_object_unref (soup_addr);
register_handlers (sub);
@@ -497,17 +396,43 @@ create_and_run_server (GrssFeedsSubscriber *sub)
static void
external_ip_received_cb (SoupSession *session, SoupMessage *msg, gpointer data)
{
+ int i;
+ int len;
+ gchar *tmp;
GrssFeedsSubscriber *sub;
- sub = (GrssFeedsSubscriber*) data;
+ if (msg->status_code == SOUP_STATUS_OK) {
+ sub = (GrssFeedsSubscriber*) data;
- sub->priv->external_addr = g_inet_address_new_from_string (msg->response_body->data);
- if (sub->priv->external_addr == NULL) {
- g_warning ("Unable to determine public IP");
- return;
- }
+ /*
+ Typical response from checkip.dyndns.org:
+
+ <html><head><title>Current IP Check</title></head><body>Current IP Address: X.X.X.X</body></html>
+ | |
+ +----------------------------------- 76 -----------------------------------+
+ */
+ tmp = g_strdup (msg->response_body->data + 76);
+ len = strlen (tmp);
+ for (i = 0; tmp [i] != '<' && i < len; i++);
+
+ if (i == len) {
+ g_warning ("Unable to determine public IP: %s", msg->response_body->data);
+ }
+ else {
+ tmp [i] = '\0';
- create_and_run_server (sub);
+ sub->priv->exposed_addr = g_inet_address_new_from_string (tmp);
+ if (sub->priv->exposed_addr == NULL)
+ g_warning ("Unable to determine public IP: %s", tmp);
+ else
+ create_and_run_server (sub);
+ }
+
+ g_free (tmp);
+ }
+ else {
+ g_warning ("Unable to determine public IP: %s", soup_status_get_phrase (msg->status_code));
+ }
}
static void
@@ -515,45 +440,19 @@ subscribe_with_external_ip (GrssFeedsSubscriber *sub)
{
SoupMessage *msg;
- sub->priv->initing_status = SUBSCRIBER_CHECKING_PUBLIC_IP;
-
/*
This method to determine public IP is quite odd, but no
better has been suggested by StackOverflow.com
*/
- msg = soup_message_new ("GET", "http://whatismyip.org");
+ msg = soup_message_new ("GET", "http://checkip.dyndns.org/");
soup_session_queue_message (sub->priv->soupsession, msg, external_ip_received_cb, sub);
}
static void
-try_another_subscription_policy (GrssFeedsSubscriber *sub)
-{
- switch (sub->priv->initing_status) {
- case SUBSCRIBER_TRYING_LOCAL_IP:
- close_server (sub);
- subscribe_with_external_ip (sub);
- break;
-
- default:
- close_server (sub);
- g_warning ("No way: subscription is failed");
- break;
- }
-}
-
-static void
init_run_server (GrssFeedsSubscriber *sub)
{
- gboolean done;
GInetAddress *addr;
- done = FALSE;
-
- if (sub->priv->external_addr != NULL) {
- g_object_unref (sub->priv->external_addr);
- sub->priv->external_addr = NULL;
- }
-
if (sub->priv->soupsession == NULL)
sub->priv->soupsession = soup_session_async_new ();
@@ -562,100 +461,31 @@ init_run_server (GrssFeedsSubscriber *sub)
BEGIN
|
- +---------------+ +--------------+
- | has fixed hub | ---- YES ---> | is hub local | ----- YES ---+
- +---------------+ +--------------+ |
- | | |
- NO <----------------------------+ |
- | |
- +-------------------+ +-----------------+ |
+ |
+ +-------------------+ +-----------------+
| host seems public | -- YES -> | subscribe works | ---- YES ---+
+-------------------+ +-----------------+ |
| | |
NO -----------------------------+ |
| |
- +-----------------+ |
- | check public IP | |
- +-----------------+ |
+ +-----------------+ +-----------------+ |
+ | check public IP | --- YES -> | subscribe works | ---- YES ---+
+ +-----------------+ +-----------------+ |
+ | | |
+ NO -----------------------------+ |
| |
- +-----------------+ +------+ |
- | subscribe works | --- YES --------> | DONE | <---------------+
- +-----------------+ +------+
- |
- NO
- |
- +--------+
- | NO WAY |
- +--------+
+ | |
+ NO WAY DONE
*/
- sub->priv->initing_status = SUBSCRIBER_IS_IDLE;
-
- if (sub->priv->hub != NULL) {
- addr = g_inet_address_new_from_string (sub->priv->hub);
- if (g_inet_address_get_is_link_local (addr) == TRUE) {
- sub->priv->external_addr = my_detect_internet_address (sub);
- done = TRUE;
- create_and_run_server (sub);
- }
+ addr = my_detect_internet_address (sub);
+ if (address_seems_public (addr) == TRUE) {
+ sub->priv->exposed_addr = sub->priv->local_addr;
+ create_and_run_server (sub);
}
-
- if (done == FALSE) {
- addr = my_detect_internet_address (sub);
- if (address_seems_public (addr) == TRUE) {
- sub->priv->external_addr = addr;
- done = TRUE;
- sub->priv->initing_status = SUBSCRIBER_TRYING_LOCAL_IP;
- create_and_run_server (sub);
- }
- }
-
- if (done == FALSE)
+ else {
subscribe_with_external_ip (sub);
-}
-
-static void
-feeds_unsubscribed_cb (GrssFeedsSubscriber *sub)
-{
- close_server (sub);
- g_object_unref (sub->priv->soupsession);
- sub->priv->soupsession = NULL;
-}
-
-static void
-unsubscribe_response_cb (SoupSession *session, SoupMessage *msg, gpointer user_data)
-{
- SubscriberJob *job;
-
- job = (SubscriberJob*) user_data;
- check_complete_job (job);
-}
-
-static void
-unsubscribe_feed (GrssFeedsSubscriber *sub, GrssFeedChannelWrap *feed, SubscriberJob *job)
-{
- gchar *body;
- gchar *pubsubhub;
- gchar *feed_reference;
- SoupMessage *msg;
-
- if (grss_feed_channel_get_pubsubhub (feed->channel, &pubsubhub, &feed_reference) == FALSE) {
- check_complete_job (job);
- return;
}
-
- feed->status = FEED_SUBSCRIPTION_UNSUBSCRIBING;
-
- if (sub->priv->hub != NULL)
- pubsubhub = sub->priv->hub;
-
- body = g_strdup_printf ("hub.mode=unsubscribe&hub.callback=http://%s:%d/%d&hub.topic=%s&hub.verify=sync",
- g_inet_address_to_string (sub->priv->external_addr), sub->priv->port, feed->identifier, feed_reference);
-
- msg = soup_message_new ("POST", pubsubhub);
- soup_message_set_request (msg, "application/x-www-form-urlencoded", SOUP_MEMORY_TAKE, body, strlen (body));
-
- soup_session_queue_message (sub->priv->soupsession, msg, unsubscribe_response_cb, job);
}
static void
@@ -663,16 +493,11 @@ unsubscribe_feeds (GrssFeedsSubscriber *sub)
{
GList *iter;
GrssFeedChannelWrap *wrap;
- SubscriberJob *job;
-
- job = g_new0 (SubscriberJob, 1);
- job->counter = g_list_length (sub->priv->feeds_list);
- job->callback = feeds_unsubscribed_cb;
- job->subscriber = sub;
for (iter = sub->priv->feeds_list; iter; iter = g_list_next (iter)) {
wrap = (GrssFeedChannelWrap*) iter->data;
- unsubscribe_feed (sub, wrap, job);
+ grss_feeds_subscriber_handler_unsubscribe (wrap->handler, wrap->channel, wrap->identifier);
+ wrap->status = FEED_SUBSCRIPTION_UNSUBSCRIBING;
}
sub->priv->feeds_list = NULL;
@@ -682,6 +507,7 @@ static void
stop_server (GrssFeedsSubscriber *sub)
{
unsubscribe_feeds (sub);
+ close_server (sub);
}
/**
@@ -709,22 +535,6 @@ grss_feeds_subscriber_set_port (GrssFeedsSubscriber *sub, int port)
}
/**
- * grss_feeds_subscriber_set_hub:
- * @sub: a #GrssFeedsSubscriber
- * @hub: URL of the custom hub
- *
- * To customize the default hub to which send subscriptions. If this value is
- * set, hubs from specific feeds are ignored
- */
-void
-grss_feeds_subscriber_set_hub (GrssFeedsSubscriber *sub, gchar *hub)
-{
- FREE_STRING (sub->priv->hub);
- if (hub != NULL)
- sub->priv->hub = g_strdup (hub);
-}
-
-/**
* grss_feeds_subscriber_switch:
* @sub: a #GrssFeedsSubscriber
* @run: TRUE to run the subscriber, FALSE to pause it
@@ -743,3 +553,51 @@ grss_feeds_subscriber_switch (GrssFeedsSubscriber *sub, gboolean run)
stop_server (sub);
}
}
+
+/**
+ * grss_feeds_subscriber_get_address:
+ * @sub: a #GrssFeedsSubscriber
+ *
+ * This function returns the Internet address where @sub is listening for
+ * external events. It is often required by #GrssFeedsSubscriberHandlers while
+ * subscribing contents to specify the local endpoint for communications
+ *
+ * Return value: the #GInetAddress used by @sub, or %NULL if the
+ * #GrssFeedsSubscriber is switched off
+ */
+GInetAddress*
+grss_feeds_subscriber_get_address (GrssFeedsSubscriber *sub)
+{
+ return sub->priv->exposed_addr;
+}
+
+/**
+ * grss_feeds_subscriber_get_port:
+ * @sub: a #GrssFeedsSubscriber
+ *
+ * This function returns the Internet port where @sub is listening for
+ * external events. It is often required by #GrssFeedsSubscriberHandlers while
+ * subscribing contents to specify the local endpoint for communications
+ *
+ * Return value: the port of the socket locally opened by @sub
+ */
+int
+grss_feeds_subscriber_get_port (GrssFeedsSubscriber *sub)
+{
+ return sub->priv->port;
+}
+
+/**
+ * grss_feeds_subscriber_get_session:
+ * @sub: a #GrssFeedsSubscriber
+ *
+ * To obtain the internal #SoupSession of a #GrssFeedsSubscriber, so to re-use
+ * it in #GrssFeedsSubscriberHandlers or similar tasks
+ *
+ * Return value: the #SoupSession used by the provided #GrssFeedsSubscriber
+ */
+SoupSession*
+grss_feeds_subscriber_get_session (GrssFeedsSubscriber *sub)
+{
+ return sub->priv->soupsession;
+}
diff --git a/src/feeds-subscriber.h b/src/feeds-subscriber.h
index bbb39c1..161ee06 100644
--- a/src/feeds-subscriber.h
+++ b/src/feeds-subscriber.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009, Roberto Guido <rguido src gnome org>
+ * Copyright (C) 2011, Roberto Guido <rguido src gnome org>
* Michele Tameni <michele amdplanet it>
*
* This library is free software; you can redistribute it and/or
@@ -51,7 +51,9 @@ GrssFeedsSubscriber* grss_feeds_subscriber_new ();
gboolean grss_feeds_subscriber_listen (GrssFeedsSubscriber *sub, GList *feeds);
GList* grss_feeds_subscriber_get_listened (GrssFeedsSubscriber *sub);
void grss_feeds_subscriber_set_port (GrssFeedsSubscriber *sub, int port);
-void grss_feeds_subscriber_set_hub (GrssFeedsSubscriber *sub, gchar *hub);
void grss_feeds_subscriber_switch (GrssFeedsSubscriber *sub, gboolean run);
+GInetAddress* grss_feeds_subscriber_get_address (GrssFeedsSubscriber *sub);
+int grss_feeds_subscriber_get_port (GrssFeedsSubscriber *sub);
+SoupSession* grss_feeds_subscriber_get_session (GrssFeedsSubscriber *sub);
#endif /* __FEEDS_SUBSCRIBER_H__ */
diff --git a/src/feeds-xbel-group-handler.c b/src/feeds-xbel-group-handler.c
index ba65d7b..1a57dee 100644
--- a/src/feeds-xbel-group-handler.c
+++ b/src/feeds-xbel-group-handler.c
@@ -25,13 +25,6 @@
#define FEEDS_XBEL_GROUP_HANDLER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), FEEDS_XBEL_GROUP_HANDLER_TYPE, FeedsXbelGroupHandlerPrivate))
-/**
- * SECTION: feeds-xbel-group-handler
- * @short_description: specialized parser for XBEL files
- *
- * #FeedsXbelGroupHandler is a #GrssFeedsGroupHandler specialized for XBEL contents
- */
-
struct FeedsXbelGroupHandlerPrivate {
int rfu;
};
@@ -77,7 +70,7 @@ feeds_xbel_group_handler_parse (GrssFeedsGroupHandler *self, xmlDocPtr doc, GErr
xpathCtx = xmlXPathNewContext (doc);
- /**
+ /*
TODO This XPath query may be improved to check only "bookmark" tags into the main "xbel"
*/
xpathObj = xmlXPathEvalExpression (BAD_CAST"//bookmark", xpathCtx);
diff --git a/src/feeds-xoxo-group-handler.c b/src/feeds-xoxo-group-handler.c
index c95add0..14fae46 100644
--- a/src/feeds-xoxo-group-handler.c
+++ b/src/feeds-xoxo-group-handler.c
@@ -25,13 +25,6 @@
#define FEEDS_XOXO_GROUP_HANDLER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), FEEDS_XOXO_GROUP_HANDLER_TYPE, FeedsXoxoGroupHandlerPrivate))
-/**
- * SECTION: feeds-xoxo-group-handler
- * @short_description: specialized parser for XOXO files
- *
- * #FeedsXoxoGroupHandler is a #GrssFeedsGroupHandler specialized for XOXO contents
- */
-
struct FeedsXoxoGroupHandlerPrivate {
int rfu;
};
@@ -94,7 +87,7 @@ feeds_xoxo_group_handler_parse (GrssFeedsGroupHandler *self, xmlDocPtr doc, GErr
xpathCtx = xmlXPathNewContext (doc);
xmlXPathRegisterNs (xpathCtx, BAD_CAST"xhtml", BAD_CAST"http://www.w3.org/1999/xhtml");
- /**
+ /*
TODO This XPath query may be improved to check only "a" tags into the main "ol"
*/
xpathObj = xmlXPathEvalExpression (BAD_CAST"//xhtml:a[ type='webfeed']", xpathCtx);
diff --git a/src/ns-handler.c b/src/ns-handler.c
index ec9c6d5..74bb9a3 100644
--- a/src/ns-handler.c
+++ b/src/ns-handler.c
@@ -23,17 +23,6 @@
#define NS_HANDLER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), NS_HANDLER_TYPE, NSHandlerPrivate))
-/**
- * SECTION: ns-handler
- * @short_description: namespaces handler
- *
- * The #NSHandler object is a special extension used by #FeedHandlers to
- * handle more tags in feeds. When unknow XML elements are found they are
- * filtered by the #NSHandler, which check if that rappresent a valid
- * extension and populates the specified #GrssFeedChannel (or #GrssFeedItem) with
- * more attributes
- */
-
struct _NSHandlerPrivate {
GHashTable *href_handlers;
GHashTable *prefix_handlers;
@@ -463,10 +452,6 @@ ns_wfw_item (GrssFeedItem *item, xmlNodePtr cur)
static gboolean
ns_atom10_channel (GrssFeedChannel *feed, xmlNodePtr cur)
{
- /*
- Used to manage PubSubHubbub information in RSS feeds
- */
-
gchar *href;
gchar *relation;
@@ -477,9 +462,9 @@ ns_atom10_channel (GrssFeedChannel *feed, xmlNodePtr cur)
href = (gchar*) xmlGetNsProp (cur, BAD_CAST "href", NULL);
if (strcmp (relation, "self") == 0)
- grss_feed_channel_set_pubsubhub (feed, NULL, href);
+ grss_feed_channel_set_source (feed, href);
else if (strcmp (relation, "hub") == 0)
- grss_feed_channel_set_pubsubhub (feed, href, NULL);
+ grss_feed_channel_set_pubsubhub (feed, href);
g_free (relation);
g_free (href);
@@ -616,13 +601,6 @@ ns_handler_init (NSHandler *node)
g_hash_table_insert (node->priv->href_handlers, "http://www.w3.org/2005/Atom", nsh);
}
-/**
- * ns_handler_new:
- *
- * Allocates a new #NSHandler
- *
- * Return value: a new #NSHandler
- */
NSHandler*
ns_handler_new ()
{
@@ -645,17 +623,6 @@ retrieve_internal_handler (NSHandler *handler, xmlNodePtr cur)
return nsh;
}
-/**
- * ns_handler_channel:
- * @handler: a #NSHandler
- * @feed: channel to which assign eventual values
- * @cur: XML tag to be analyzed
- *
- * Check a given tag for extended namespaces values
- *
- * Return value: %TRUE if a value has been assigned by the @handler, %FALSE
- * otherwise
- */
gboolean
ns_handler_channel (NSHandler *handler, GrssFeedChannel *feed, xmlNodePtr cur)
{
@@ -669,17 +636,6 @@ ns_handler_channel (NSHandler *handler, GrssFeedChannel *feed, xmlNodePtr cur)
return FALSE;
}
-/**
- * ns_handler_item:
- * @handler: a #NSHandler
- * @item: item to which assign eventual values
- * @cur: XML tag to be analyzed
- *
- * Check a given tag for extended namespaces values
- *
- * Return value: %TRUE if a value has been assigned by the @handler, %FALSE
- * otherwise
- */
gboolean
ns_handler_item (NSHandler *handler, GrssFeedItem *item, xmlNodePtr cur)
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]