[evolution-rss] handle media extension properly
- From: Lucian Langa <lucilanga src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-rss] handle media extension properly
- Date: Sun, 18 Apr 2010 19:41:45 +0000 (UTC)
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]