[evolution-rss] handle media extension properly



commit accaeab05a8c01307a34669046a060c3b19baaae
Author: Lucian Langa <lucilanga gnome org>
Date:   Sun Apr 18 18:12:23 2010 +0300

    handle media extension properly

 TODO               |    2 +-
 src/network-soup.c |   12 ++-
 src/parser.c       |   68 ++++++-----------
 src/parser.h       |   12 +++-
 src/rss.c          |  208 ++++++++++++++++++++++++++++++++++++++++++++++++---
 src/rss.h          |   14 +++-
 6 files changed, 251 insertions(+), 65 deletions(-)
---
diff --git a/TODO b/TODO
index 964da85..37e5971 100644
--- a/TODO
+++ b/TODO
@@ -36,4 +36,4 @@
 	* import without fetching (add without validate ?)
 	* do not mark folders as feeds (icon)
 	* require gtkhtml-editor separate package (?)
-	* option to download enclosures
+	* option to download enclosures (limit to certain size)
diff --git a/src/network-soup.c b/src/network-soup.c
index b3bd03e..73cafa1 100644
--- a/src/network-soup.c
+++ b/src/network-soup.c
@@ -658,7 +658,8 @@ download_unblocking(
 
 #if LIBSOUP_VERSION > 2024000
 	if (rss_soup_jar) {
-		soup_session_add_feature(soup_sess, SOUP_SESSION_FEATURE(rss_soup_jar));
+		soup_session_add_feature(soup_sess,
+			SOUP_SESSION_FEATURE(rss_soup_jar));
 	}
 #endif
 
@@ -674,11 +675,14 @@ download_unblocking(
 	}
 
 	if (!rf->session)
-		rf->session = g_hash_table_new(g_direct_hash, g_direct_equal);
+		rf->session = g_hash_table_new(
+				g_direct_hash, g_direct_equal);
 	if (!rf->abort_session)
-		rf->abort_session = g_hash_table_new(g_direct_hash, g_direct_equal);
+		rf->abort_session = g_hash_table_new(
+					g_direct_hash, g_direct_equal);
 	if (!rf->key_session)
-		rf->key_session = g_hash_table_new(g_direct_hash, g_direct_equal);
+		rf->key_session = g_hash_table_new(
+					g_direct_hash, g_direct_equal);
 
 	g_signal_connect (soup_sess, "authenticate",
 		G_CALLBACK (authenticate), (gpointer)url);
diff --git a/src/parser.c b/src/parser.c
index 7aaaed9..33fe267 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -29,7 +29,6 @@
 #else
 #include <camel/camel-url.h>
 #endif
-#include <e-util/e-mktemp.h>
 
 extern int rss_verbose_debug;
 
@@ -565,7 +564,7 @@ gchar*
 media_rss(xmlNode *node, gchar *search, gchar *fail)
 {
 	gchar *content;
-	g_print("media_rss()\n");
+	d("media_rss()\n");
 
 	content = (gchar *)xmlGetProp(node, (xmlChar *)search);
 	if (content)
@@ -577,14 +576,15 @@ media_rss(xmlNode *node, gchar *search, gchar *fail)
 const gchar *property_rss_modules[1][3] = {
 	{"media", "media", (gchar *)media_rss}};
 
-char *
+GList *
 layer_find_tag_prop (xmlNodePtr node,
-	char *match,
-	char *search,
-	char *fail)
+	const char *match,
+	const char *search)
 {
-	int i;
+	int i = 0;
 	char* (*func)();
+	gchar *tmp;
+	GList *result = NULL;
 
 	while (node!=NULL) {
 #ifdef RDF_DEBUG
@@ -592,18 +592,18 @@ layer_find_tag_prop (xmlNodePtr node,
 		printf("%s.\n", node->name);
 #endif
 		if (node->ns && node->ns->prefix) {
-			for (i=0; i < 1; i++) {
 				if (!strcasecmp ((char *)node->ns->prefix, property_rss_modules[i][1])) {
 					func = (gpointer)property_rss_modules[i][2];
 					if (strcasecmp ((char *)node->ns->prefix, match)==0) {
-						g_print("URL:%s\n", func(node, search, fail));
+						tmp =  func(node, search, NULL);
+						if (tmp)
+							result = g_list_append(result, tmp);
 					}
 				}
-			}
 		}
 		node = node->next;
 	}
-	return fail;
+	return result;
 }
 
 gchar *
@@ -870,6 +870,7 @@ parse_channel_line(xmlNode *top, gchar *feed_name, char *main_date)
 	guint size = 0;
 	GList *category = NULL;
 	create_feed *CF;
+	GList *attachments = NULL;
 
 	char *p = g_strdup(layer_find (top, "title", "Untitled article"));
 	//firstly try to parse as an ATOM author
@@ -970,14 +971,16 @@ parse_channel_line(xmlNode *top, gchar *feed_name, char *main_date)
 			g_free(encl);
 			encl = NULL;
 		}
-//		encl = layer_find_tag_prop(el->children, "media", "url",	// RSS 2.0 Enclosure
-//							NULL);		// ATOM Enclosure
+		//handle attatchments (can be multiple)
+		attachments = layer_find_tag_prop(top, "media", "url");
+
 		//we have to free this somehow
 		//<link></link>
 		link = g_strdup(layer_find (top, "link", NULL));		//RSS,
 		if (!link)								// <link href=>
-			link = (gchar *)layer_find_innerelement(top, "link", "href",
-							g_strdup(_("No Information")));	//ATOM
+			link = (gchar *)layer_find_innerelement(
+						top, "link", "href",
+						g_strdup(_("No Information")));	//ATOM
 
 //                char *comments = g_strdup(layer_find (top, "comments", NULL));	//RSS,
 		comments = (gchar *)layer_find_ns_tag(top, "wfw", "commentRss", NULL); //add slash:comments
@@ -998,15 +1001,15 @@ parse_channel_line(xmlNode *top, gchar *feed_name, char *main_date)
 		d("date:%s\n", d2);
 		d("body:%s\n", b);
 
-		//not very nice but prevents unnecessary long body processing
+		//not very nice but allows shortcutting
 		if (!feed_is_new(feed_name, feed)) {
 			ftotal++;
 			sp =  decode_html_entities (p);
-			tmp = decode_utf8_entities(b);
+			tmp = decode_utf8_entities (b);
 			g_free(b);
 
 			if (feed_name) {
-				xmlDoc *src = (xmlDoc *)parse_html_sux(tmp, strlen(tmp));
+				xmlDoc *src = (xmlDoc *)parse_html_sux (tmp, strlen(tmp));
 				if (src) {
 					xmlNode *doc = (xmlNode *)src;
 
@@ -1039,6 +1042,7 @@ parse_channel_line(xmlNode *top, gchar *feed_name, char *main_date)
 		CF->dcdate	= g_strdup(d2);
 		CF->website	= g_strdup(link);
 		CF->encl	= g_strdup(encl);
+		CF->attachments	= attachments;
 		CF->comments	= g_strdup(comments);
 		CF->feed_fname  = g_strdup(feed_name);	//feed file name
 		CF->feed_uri	= g_strdup(feed);	//feed uri (uid!)
@@ -1071,8 +1075,6 @@ update_channel(RDF *r)
 	GtkWidget *progress = r->progress;
 	gchar *buf, *safes, *feed_dir, *feed_name;
 	gchar *uid, *msg;
-	gchar *tmpdir, *name;
-	GError *err = NULL;
 
 	safes = encode_rfc2047(chn_name);
 	sender = g_strdup_printf("%s <%s>", safes, chn_name);
@@ -1128,29 +1130,9 @@ update_channel(RDF *r)
 		if (!feed_is_new(feed_name, CF->feed_uri)) {
 			ftotal++;
 			if (CF->encl) {
-				if (g_list_find_custom(rf->enclist, CF->encl,
-						(GCompareFunc)strcmp))
-					continue;
-				tmpdir = e_mkdtemp("evo-rss-XXXXXX");
-				if ( tmpdir == NULL)
-					continue;
-				name = g_build_filename(tmpdir,
-						g_path_get_basename(CF->encl),
-						NULL);
-				g_free(tmpdir);
-				CF->enclurl = CF->encl;
-				CF->encl = name;
-				d("enclosure file:%s\n", name)
-				CF->efile = fopen(name, "w");
-				if (!CF->efile) continue;
-				download_unblocking(
-					CF->enclurl,
-					download_chunk,
-					CF->efile,
-					(gpointer)finish_enclosure,
-					CF,
-					0,
-					&err);
+				process_enclosure(CF);
+			} else if (g_list_length(CF->attachments)) {
+				process_attachments(CF);
 			} else {
 				create_mail(CF);
 				write_feed_status_line(
diff --git a/src/parser.h b/src/parser.h
index fb6b96f..a62cd08 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -27,8 +27,16 @@ gchar *layer_find_innerhtml (xmlNodePtr node, const char *match, const char *sub
 xmlNodePtr layer_find_pos (xmlNodePtr node, const char *match, const char *submatch);
 const char *layer_find_tag (xmlNodePtr node, const char *match, const char *fail);
 char *layer_find_url (xmlNodePtr node, char *match, char *fail);
-char *layer_find_tag_prop (xmlNodePtr node, char *match, char *search, char *fail);
-const char *layer_find_ns_tag(xmlNodePtr node, const char *nsmatch, const char *match, const char *fail);
+GList*
+layer_find_tag_prop (xmlNodePtr node,
+				const char *match,
+				const char *search);
+
+const char *
+layer_find_ns_tag (xmlNodePtr node,
+			const char *nsmatch,
+			const char *match,
+			const char *fail);
 gchar *encode_html_entities(gchar *source);
 gchar *decode_entities(gchar *source);
 GList *layer_find_all (xmlNodePtr node, const char *match, const char *fail);
diff --git a/src/rss.c b/src/rss.c
index 269927b..5c8d7c9 100644
--- a/src/rss.c
+++ b/src/rss.c
@@ -45,6 +45,7 @@ int rss_verbose_debug = 0;
 
 #include <e-util/e-icon-factory.h>
 #include <e-util/e-util.h>
+#include <e-util/e-mktemp.h>
 
 
 #ifdef EVOLUTION_2_12
@@ -198,6 +199,10 @@ guint resize_pane_vsize = 0;
 guint resize_browser_hsize = 0;
 guint resize_browser_vsize = 0;
 
+extern guint net_queue_run_count;
+extern guint net_qid;
+
+
 static volatile int org_gnome_rss_controls_counter_id = 0;
 
 struct _org_gnome_rss_controls_pobject {
@@ -1618,7 +1623,7 @@ webkit_set_preferences(void)
 	g_object_set (settings, "enable-page-cache", TRUE, NULL);
 	//g_object_set (settings, "auto-resize-window", TRUE, NULL);
 #endif
-	webkit_web_view_set_full_content_zoom(rf->mozembed, TRUE);
+	webkit_web_view_set_full_content_zoom((WebKitWebView *)rf->mozembed, TRUE);
 	g_free(agstr);
 #endif
 #endif
@@ -1859,21 +1864,21 @@ static void
 embed_zoom_in_cb (EShellView *shell,
 			gpointer *data)
 {
-	webkit_web_view_zoom_in(rf->mozembed);
+	webkit_web_view_zoom_in((WebKitWebView*)rf->mozembed);
 }
 
 static void
 embed_zoom_out_cb (EShellView *shell,
 			gpointer *data)
 {
-	webkit_web_view_zoom_out(rf->mozembed);
+	webkit_web_view_zoom_out((WebKitWebView *)rf->mozembed);
 }
 
 static void
 embed_zoom_100_cb (EShellView *shell,
 			gpointer *data)
 {
-	webkit_web_view_set_zoom_level(rf->mozembed, 1);
+	webkit_web_view_set_zoom_level((WebKitWebView *)rf->mozembed, 1);
 }
 
 gboolean
@@ -1886,17 +1891,20 @@ webkit_click (GtkEntry *entry,
 	gtk_widget_show (separator);
 	gtk_menu_shell_insert (GTK_MENU_SHELL (menu), separator, 2);
 	menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_ZOOM_IN, NULL);
-	g_signal_connect(menuitem, "activate", embed_zoom_in_cb, NULL);
+	g_signal_connect(menuitem, "activate",
+		(GCallback)embed_zoom_in_cb, NULL);
 	gtk_widget_set_sensitive (menuitem, TRUE);
 	gtk_widget_show (menuitem);
 	gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 3);
 	menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_ZOOM_OUT, NULL);
-	g_signal_connect(menuitem, "activate", embed_zoom_out_cb, NULL);
+	g_signal_connect(menuitem, "activate",
+		(GCallback)embed_zoom_out_cb, NULL);
 	gtk_widget_set_sensitive (menuitem, TRUE);
 	gtk_widget_show (menuitem);
 	gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 4);
 	menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_ZOOM_100, NULL);
-	g_signal_connect(menuitem, "activate", embed_zoom_100_cb, NULL);
+	g_signal_connect(menuitem, "activate",
+		(GCallback)embed_zoom_100_cb, NULL);
 	gtk_widget_set_sensitive (menuitem, TRUE);
 	gtk_widget_show (menuitem);
 	gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 5);
@@ -1906,13 +1914,14 @@ webkit_click (GtkEntry *entry,
 	return TRUE;
 }
 
+void webkit_hook_actions(void);
 
 void
 webkit_hook_actions(void)
 {
 	EShellWindow *shell_window;
 	GtkAction *action;
-	gchar *action_name;
+	const char *action_name;
 
 	shell_window = e_shell_view_get_shell_window (rss_shell_view);
 
@@ -5685,7 +5694,7 @@ create_mail(create_feed *CF)
 	CamelMimePart *part, *msgp;
 	CamelMultipart *mp;
 	GString *cats;
-	GList *p;
+	GList *p, *l;
 	gchar *time_str, *buf;
 	gint offset;
 
@@ -5789,7 +5798,34 @@ create_mail(create_feed *CF)
 	camel_data_wrapper_construct_from_stream (rtext, stream);
 	camel_object_unref (stream);
 
-	if (CF->encl) {
+	if (CF->attachedfiles) {
+			mp = camel_multipart_new();
+			camel_multipart_set_boundary(mp, NULL);
+
+			part = camel_mime_part_new();
+#if EVOLUTION_VERSION >= 23100
+			camel_medium_set_content(
+				(CamelMedium *)part, (CamelDataWrapper *)rtext);
+#else
+			camel_medium_set_content_object(
+				(CamelMedium *)part, (CamelDataWrapper *)rtext);
+#endif
+			camel_multipart_add_part(mp, part);
+			camel_object_unref(part);
+		for (l = g_list_first(CF->attachedfiles); l != NULL; l = l->next) {
+			msgp = file_to_message(l->data);
+			if (msgp) {
+				camel_multipart_add_part(mp, msgp);
+				camel_object_unref(msgp);
+			}
+		}
+#if EVOLUTION_VERSION >= 23100
+		camel_medium_set_content((CamelMedium *)new, (CamelDataWrapper *)mp);
+#else
+		camel_medium_set_content_object((CamelMedium *)new, (CamelDataWrapper *)mp);
+#endif
+		camel_object_unref(mp);
+	} else	if (CF->encl) {
 		mp = camel_multipart_new();
 		camel_multipart_set_boundary(mp, NULL);
 
@@ -5827,7 +5863,10 @@ create_mail(create_feed *CF)
 	/* no point in filtering mails at import time as it just
 	 * wastes time, user can setup his own afterwards
 	 */
-	if (appended_uid != NULL && !rf->import && !CF->encl) {	//do not filter enclosure at this time
+	if (appended_uid != NULL
+		&& !rf->import
+		&& !CF->encl
+		&& !g_list_length(CF->attachments)) {	//do not filter enclosure at this time nor media files
 		filter_uids = g_ptr_array_sized_new(1);
 		g_ptr_array_add(filter_uids, appended_uid);
 		mail_filter_on_demand (mail_folder, filter_uids);
@@ -5947,11 +5986,154 @@ free_cf(create_feed *CF)
 		g_list_foreach(CF->category, (GFunc)g_free, NULL);
 		g_list_free(CF->category);
 	}
+	if (CF->attachments) {
+		g_list_foreach(CF->attachments, (GFunc)g_free, NULL);
+		g_list_free(CF->attachments);
+	}
+	if (CF->attachedfiles) {
+		g_list_foreach(CF->attachedfiles, (GFunc)g_free, NULL);
+		g_list_free(CF->attachedfiles);
+	}
 	g_free(CF);
 }
 
-extern guint net_queue_run_count;
-extern guint net_qid;
+typedef struct CFL {
+	gchar *url;
+	FILE *file;
+	create_feed *CF;
+} cfl;
+
+void
+#if LIBSOUP_VERSION < 2003000
+finish_attachment (
+	SoupMessage *msg,
+	create_feed *user_data);
+#else
+finish_attachment (
+	SoupSession *soup_sess,
+	SoupMessage *msg,
+	cfl *user_data);
+#endif
+
+void
+process_attachments(create_feed *CF)
+{
+	cfl *CFL;
+	GList *l = g_list_first(CF->attachments);
+
+	g_return_if_fail(CF->attachments != NULL);
+
+	do {
+		gchar *tmpdir, *name;
+
+		if (g_list_find_custom(rf->enclist, l->data,
+			(GCompareFunc)strcmp))
+			continue;
+		tmpdir = e_mkdtemp("evo-rss-XXXXXX");
+		if ( tmpdir == NULL)
+			continue;
+		name = g_build_filename(tmpdir,
+			g_path_get_basename(l->data),
+			NULL);
+		g_free(tmpdir);
+		CFL = g_new0(cfl, 1);
+		CFL->url = l->data;
+		CFL->CF = CF;
+		d("enclosure file:%s\n", name)
+		CF->attachedfiles = g_list_append(CF->attachedfiles, name);
+		CF->attachmentsqueue++;
+		CFL->file = fopen(name, "w");
+		if (!CFL->file) return;
+		download_unblocking(
+			CFL->url,
+			download_chunk,
+			CFL->file,
+			(gpointer)finish_attachment,
+			CFL,
+			0,
+			NULL);
+	} while ((l = l->next));
+}
+
+
+
+void
+#if LIBSOUP_VERSION < 2003000
+finish_attachment (SoupMessage *msg,
+		cfl *user_data)
+#else
+finish_attachment (SoupSession *soup_sess,
+		SoupMessage *msg,
+		cfl *user_data)
+#endif
+{
+#if LIBSOUP_VERSION < 2003000
+	fwrite(msg->response.body,
+		msg->response.length,
+		1,
+		user_data->file);
+#else
+	fwrite(msg->response_body->data,
+		msg->response_body->length,
+		1,
+		user_data->file);
+#endif
+	fclose(user_data->file);
+
+	rf->enclist = g_list_remove(rf->enclist, user_data->url);
+	//g_free(msg->response_body->data);
+	//g_object_unref(msg);
+	if (user_data->CF->attachmentsqueue)
+		user_data->CF->attachmentsqueue--;
+
+	if (!user_data->CF->attachmentsqueue) {
+		if (!feed_is_new(user_data->CF->feed_fname, user_data->CF->feed_uri)) {
+			create_mail(user_data->CF);
+			write_feed_status_line(
+				user_data->CF->feed_fname,
+				user_data->CF->feed_uri);
+			free_cf(user_data->CF);
+			g_free(user_data->url);
+			g_free(user_data);
+		}
+	}
+
+	if (net_queue_run_count) net_queue_run_count--;
+	if (!net_qid)
+		net_qid = g_idle_add(
+				(GSourceFunc)net_queue_dispatcher,
+				NULL);
+}
+
+void
+process_enclosure(create_feed *CF)
+{
+	gchar *tmpdir, *name;
+
+	if (g_list_find_custom(rf->enclist, CF->encl,
+			(GCompareFunc)strcmp))
+		return;
+	tmpdir = e_mkdtemp("evo-rss-XXXXXX");
+	if ( tmpdir == NULL)
+		return;
+	name = g_build_filename(tmpdir,
+		g_path_get_basename(CF->encl),
+		NULL);
+	g_free(tmpdir);
+	CF->enclurl = CF->encl;
+	CF->encl = name;
+	d("enclosure file:%s\n", name)
+	CF->efile = fopen(name, "w");
+	if (!CF->efile) return;
+	download_unblocking(
+		CF->enclurl,
+		download_chunk,
+		CF->efile,
+		(gpointer)finish_enclosure,
+		CF,
+		0,
+		NULL);
+}
 
 void
 #if LIBSOUP_VERSION < 2003000
diff --git a/src/rss.h b/src/rss.h
index 81119da..63b7697 100644
--- a/src/rss.h
+++ b/src/rss.h
@@ -300,8 +300,11 @@ typedef struct CREATE_FEED {	/* used by create_mail function when called by unbl
 	gchar	*feedid;
 	gchar	*feed_fname;	// feed name file
 	gchar	*feed_uri;
-	gchar *encl;
+	gchar *encl;		//feed enclosure
 	gchar *enclurl;
+	GList *attachments;	//feed media files
+	GList *attachedfiles;	//list of downloaded media files
+	guint attachmentsqueue;	//list of downloaded media files
 	FILE *efile;		//enclosure file
 	gchar *comments;
 	GList *category;	// list of categories article is posted under
@@ -432,9 +435,12 @@ finish_website (
 	SoupMessage *msg,
 	gpointer user_data);
 #endif
+
 void
 #if LIBSOUP_VERSION < 2003000
-finish_enclosure (SoupMessage *msg, create_feed *user_data);
+finish_enclosure (
+	SoupMessage *msg,
+	create_feed *user_data);
 #else
 finish_enclosure (
 	SoupSession *soup_sess,
@@ -460,6 +466,10 @@ void download_chunk(
 	NetStatusType status,
 	gpointer statusdata,
 	gpointer data);
+
+void process_enclosure(create_feed *CF);
+void process_attachments(create_feed *CF);
+
 #ifdef HAVE_GECKO
 void rss_mozilla_init(void);
 #endif



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