[evolution-rss] queue enclosure downloads (fixes #599528)



commit eed62d936179d56053277bfb936d42712d27a3d7
Author: Lucian Langa <lucilanga gnome org>
Date:   Wed Jan 27 23:42:11 2010 +0200

    queue enclosure downloads (fixes #599528)

 src/debug.h                  |    6 +-
 src/evolution-rss.schemas.in |   14 ++++
 src/misc.c                   |  154 +++++++++++++++++++-------------------
 src/network-soup.c           |   60 ++++++++++++++-
 src/network-soup.h           |    1 +
 src/network.h                |    1 +
 src/parser.c                 |   22 +++---
 src/rss.c                    |  173 ++++++++++++++++++++++++------------------
 src/rss.h                    |  153 +++++++++++++++++++------------------
 9 files changed, 340 insertions(+), 244 deletions(-)
---
diff --git a/src/debug.h b/src/debug.h
index 98f2a78..e44b622 100644
--- a/src/debug.h
+++ b/src/debug.h
@@ -19,11 +19,11 @@
 #ifndef __DEBUG_H__
 #define __DEBUG_H__ 1
 
-#define d(f, x...) if (rss_verbose_debug) { g_print("%s(%d) %s():", __FILE__, __LINE__, __FUNCTION__);\
-                        g_print(f, ## x);}
+#define d(f, x...) if (rss_verbose_debug) { g_print("%s(%d) in %s():", __FILE__, __LINE__, __FUNCTION__);\
+			g_print(f, ## x);}
 
 #define dp(f, x...) { g_print("%s(%d) %s():", __FILE__, __LINE__, __FUNCTION__);\
-                        g_print(f, ## x);}
+			g_print(f, ## x);}
 
 #endif /*__DEBUG_H__*/
 
diff --git a/src/evolution-rss.schemas.in b/src/evolution-rss.schemas.in
index bcf5f04..87d46cf 100644
--- a/src/evolution-rss.schemas.in
+++ b/src/evolution-rss.schemas.in
@@ -88,6 +88,20 @@
     </schema>
 
     <schema>
+      <key>/schemas/apps/evolution/evolution-rss/network_queue_size</key>
+      <applyto>/apps/evolution/evolution-rss/network_queue_size</applyto>
+      <owner>evolution-rss</owner>
+      <type>int</type>
+      <default>5</default>
+      <locale name="C">
+        <short>Network queue size</short>
+        <long>
+    	    How many simultaneous downloads.
+        </long>
+      </locale>
+    </schema>
+
+    <schema>
       <key>/schemas/apps/evolution/evolution-rss/html_js</key>
       <applyto>/apps/evolution/evolution-rss/html_js</applyto>
       <owner>evolution-rss</owner>
diff --git a/src/misc.c b/src/misc.c
index b985bcf..9038a20 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -1,5 +1,5 @@
 /*  Evoution RSS Reader Plugin
- *  Copyright (C) 2007-2009  Lucian Langa <cooly gnome eu org>
+ *  Copyright (C) 2007-2010  Lucian Langa <cooly gnome eu org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -66,35 +66,35 @@ void
 free_hash(gpointer key, gpointer value, gpointer user_data)
 {
 	g_print("FREE - key:%p, value:%p\n", (gchar *)key, (gchar *)value);
- //	xmlFreeDoc(key);
+//	xmlFreeDoc(key);
 }
 
 gboolean
 check_key_match (gpointer key, gpointer value, gpointer user_data)
 {
-        char *sf_href = (char *)key;
-        char *int_uri = (char *)user_data;
+	char *sf_href = (char *)key;
+	char *int_uri = (char *)user_data;
 
 	d("checking hay:%s for neddle:%s\n", sf_href, int_uri);
 
-        if (!strcmp (sf_href, int_uri))
-                return TRUE; /* Quit calling the callback */
+	if (!strcmp (sf_href, int_uri))
+		return TRUE; /* Quit calling the callback */
 
-        return FALSE; /* Continue calling the callback till end of table */
+	return FALSE; /* Continue calling the callback till end of table */
 }
 
 gboolean
 check_if_match (gpointer key, gpointer value, gpointer user_data)
 {
-        char *sf_href = (char *)value;
-        char *int_uri = (char *)user_data;
+	char *sf_href = (char *)value;
+	char *int_uri = (char *)user_data;
 
 	d("checking hay:%s for neddle:%s\n", sf_href, int_uri);
 
-        if (!strcmp (sf_href, int_uri))
-                return TRUE; /* Quit calling the callback */
+	if (!strcmp (sf_href, int_uri))
+		return TRUE; /* Quit calling the callback */
 
-        return FALSE; /* Continue calling the callback till end of table */
+	return FALSE; /* Continue calling the callback till end of table */
 }
 
 gchar *
@@ -208,9 +208,9 @@ get_port_from_uri(gchar *uri)
 	if (strstr(uri, "://") == NULL)
 		return NULL;
 	str = g_strsplit(uri, "://", 2);
-        str2 = g_strsplit(str[1], "/", 2);
-        str3 = g_strsplit(str2[0], ":", 2);
-        port = g_strdup(str3[1]);
+	str2 = g_strsplit(str[1], "/", 2);
+	str3 = g_strsplit(str2[0], ":", 2);
+	port = g_strdup(str3[1]);
 	g_strfreev(str);
 	g_strfreev(str2);
 	g_strfreev(str3);
@@ -227,8 +227,8 @@ get_server_from_uri(gchar *uri)
 	if (strstr(uri, "://") == NULL)
 		return NULL;
 	str = g_strsplit(uri, "://", 2);
-        str2 = g_strsplit(str[1], "/", 2);
-        server = g_strdup_printf("%s://%s", str[0], str2[0]);
+	str2 = g_strsplit(str[1], "/", 2);
+	server = g_strdup_printf("%s://%s", str[0], str2[0]);
 	g_strfreev(str);
 	g_strfreev(str2);
 	return server;
@@ -239,17 +239,17 @@ strplchr(gchar *source)
 {
 	GString *str = g_string_new(NULL);
 	gchar *string;
-        const unsigned char *s = (const unsigned char *)source;
-        guint len = strlen(source);
-        while (*s != 0 || len) {
-             if (*s == 0x3f) {
-                   g_string_append(str, "%3F");
-                   s++;
-             } else
-                   g_string_append_c (str, *s++);
-             len--;
-        }
-        g_string_append_c(str, 0);
+	const unsigned char *s = (const unsigned char *)source;
+	guint len = strlen(source);
+	while (*s != 0 || len) {
+		if (*s == 0x3f) {
+			g_string_append(str, "%3F");
+			s++;
+		} else
+			g_string_append_c (str, *s++);
+		len--;
+	}
+	g_string_append_c(str, 0);
 	string = str->str;
 	g_string_free(str, 0);
 	return string;
@@ -303,26 +303,26 @@ markup_decode (gchar *str)
 gchar *
 gen_crc(const char *msg)
 {
-         register unsigned long crc, poly;
-         uint32_t crc_tab[256];
-         int i,j;
-
-         poly = 0xEDB88320L;
-         for (i = 0; i < 256; i++) {
-                 crc = i;
-                 for (j = 8; j > 0; j--) {
-                         if (crc & 1)
-                                 crc = (crc >> 1) ^ poly;
-                         else
-                                 crc >>= 1;
-                 }
-                 crc_tab[i] = crc;
-         }
+	register unsigned long crc, poly;
+	uint32_t crc_tab[256];
+	int i,j;
+
+	poly = 0xEDB88320L;
+	for (i = 0; i < 256; i++) {
+		crc = i;
+		for (j = 8; j > 0; j--) {
+			if (crc & 1)
+				crc = (crc >> 1) ^ poly;
+			else
+				crc >>= 1;
+		}
+		crc_tab[i] = crc;
+	}
 
-         crc = 0xFFFFFFFF;
-         for (i = 0; i < strlen(msg); i++)
-                 crc = ((crc >> 8) & 0x00FFFFFF) ^ crc_tab[(crc ^ *msg++) & 0xFF];
-    return g_strdup_printf("%x", (unsigned int)(crc ^ 0xFFFFFFFF));
+	crc = 0xFFFFFFFF;
+	for (i = 0; i < strlen(msg); i++)
+		crc = ((crc >> 8) & 0x00FFFFFF) ^ crc_tab[(crc ^ *msg++) & 0xFF];
+	return g_strdup_printf("%x", (unsigned int)(crc ^ 0xFFFFFFFF));
 }
 
 gchar *
@@ -484,10 +484,10 @@ notrfc:	return 0;
 gchar *
 encode_rfc2047(gchar *str)
 {
-        gchar *tmp = decode_entities(str);
-        gchar *rfctmp = camel_header_encode_string((unsigned char*)tmp);
-        g_free(tmp);
-        return (gchar *)rfctmp;
+	gchar *tmp = decode_entities(str);
+	gchar *rfctmp = camel_header_encode_string((unsigned char*)tmp);
+	g_free(tmp);
+	return (gchar *)rfctmp;
 }
 
 //check if feed already exists in feed file
@@ -495,46 +495,46 @@ encode_rfc2047(gchar *str)
 gboolean
 feed_is_new(gchar *file_name, gchar *needle)
 {
-        gchar rfeed[513];
+	gchar rfeed[513];
 	FILE *fr;
 	int occ;
 	gchar *tmpneedle, *port, *tp;
 
-        memset(rfeed, 0, 512);
+	memset(rfeed, 0, 512);
 	fr = fopen(file_name, "r");
 	occ = 0;
 	tmpneedle = NULL;
 	port =  get_port_from_uri(needle);
-        if (port && atoi(port) == 80) {
+	if (port && atoi(port) == 80) {
 		tp = g_strconcat(":", port, NULL);
-                g_free(port);
-                tmpneedle = strextr(needle, tp);
-                g_free(tp);
-        } else
-                tmpneedle = g_strdup(needle);
-
-        if (fr) {
-            while (fgets(rfeed, 511, fr) != NULL) {
-                if (strstr(rfeed, tmpneedle)) {
-                        occ=1;
-                        break;
-                }
-            }
-            fclose(fr);
-        }
-        g_free(tmpneedle);
-        return occ;
+		g_free(port);
+		tmpneedle = strextr(needle, tp);
+		g_free(tp);
+	} else
+		tmpneedle = g_strdup(needle);
+
+	if (fr) {
+		while (fgets(rfeed, 511, fr) != NULL) {
+			if (strstr(rfeed, tmpneedle)) {
+				occ=1;
+				break;
+			}
+		}
+		fclose(fr);
+	}
+	g_free(tmpneedle);
+	return occ;
 }
 
 void
 write_feed_status_line(gchar *file, gchar *needle)
 {
-        FILE *fw = fopen(file, "a+");
-        if (fw) {
-                fputs(g_strstrip(needle), fw);
-                fputs("\n", fw);
-                fclose(fw);
-        }
+	FILE *fw = fopen(file, "a+");
+	if (fw) {
+		fputs(g_strstrip(needle), fw);
+		fputs("\n", fw);
+		fclose(fw);
+	}
 }
 
 #endif
diff --git a/src/network-soup.c b/src/network-soup.c
index 610f56c..312dcb4 100644
--- a/src/network-soup.c
+++ b/src/network-soup.c
@@ -1,5 +1,5 @@
 /*  Evolution RSS Reader Plugin
- *  Copyright (C) 2007-2009 Lucian Langa <cooly gnome eu org>
+ *  Copyright (C) 2007-2010 Lucian Langa <cooly gnome eu org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -62,6 +62,18 @@ typedef struct {
 	gchar *chunk;
 } CallbackInfo;
 
+typedef struct {
+	SoupSession *ss;
+	SoupMessage *sm;
+	gpointer cb2;
+	gpointer cbdata2;
+	gchar *url;
+} STNET;
+
+#define DOWNLOAD_QUEUE_SIZE 5
+guint net_qid = 0;		// net queue dispatcher
+guint net_queue_run_count = 0; //downloads in progress
+
 static void
 #if LIBSOUP_VERSION < 2003000
 got_chunk_blocking_cb(SoupMessage *msg, CallbackInfo *info) {
@@ -622,7 +634,9 @@ net_get_unblocking(gchar *url,
 	return TRUE;
 }
 
+
 // same stuff as net_get_* but without accumulating headers
+// push all donwloads to a customizable length queue
 gboolean
 download_unblocking(
 	gchar *url,
@@ -637,6 +651,7 @@ download_unblocking(
 	CallbackInfo *info = NULL;
 	SoupSession *soup_sess;
 	gchar *agstr;
+	STNET *stnet;
 
 	soup_sess = soup_session_async_new();
 
@@ -705,8 +720,16 @@ download_unblocking(
 	}
 
 	soup_message_body_set_accumulate (msg->response_body, FALSE);
-	soup_session_queue_message (soup_sess, msg,
-		cb2, cbdata2);
+	stnet = g_new0(STNET, 1);
+	stnet->ss = soup_sess;
+	stnet->sm = msg;
+	stnet->cb2 = cb2;
+	stnet->cbdata2 = cbdata2;
+	stnet->url = g_strdup(url);
+	g_queue_push_tail (rf->stqueue, stnet);
+	rf->enclist = g_list_append (rf->enclist, g_strdup(url));
+	if (!net_qid)
+		net_qid = g_idle_add((GSourceFunc)net_queue_dispatcher, NULL);
 
 ////	g_object_add_weak_pointer (G_OBJECT(msg), (gpointer)info);
 	g_object_weak_ref (G_OBJECT(msg), unblock_free, soup_sess);
@@ -716,6 +739,35 @@ download_unblocking(
 	return TRUE;
 }
 
+gboolean
+net_queue_dispatcher(void)
+{
+	STNET *_stnet;
+	guint qlen = g_queue_get_length(rf->stqueue);
+
+	dp("net queue size:%d messages processing:%d\n",
+		g_queue_get_length(rf->stqueue),
+		net_queue_run_count);
+
+	if (qlen && net_queue_run_count < gconf_client_get_int (
+						rss_gconf,
+						GCONF_KEY_DOWNLOAD_QUEUE_SIZE,
+						NULL)) {
+		net_queue_run_count++;
+		_stnet = g_queue_pop_head(rf->stqueue);
+		soup_session_queue_message (
+			_stnet->ss,
+			_stnet->sm,
+			_stnet->cb2,
+			_stnet->cbdata2);
+		g_free(_stnet);
+		return TRUE;
+	}
+	dp("workers full, disable queue run!\n");
+	net_qid = 0;
+	return FALSE;
+}
+
 GString*
 net_post_blocking(gchar *url,
 	GSList *headers,
@@ -911,6 +963,8 @@ rss_soup_init(void)
 		}
 		g_free(cookie_path);
 		g_free(moz_cookie_path);
+		if (!rf->stqueue)
+			rf->stqueue = g_queue_new();
 	}
 #endif
 }
diff --git a/src/network-soup.h b/src/network-soup.h
index c6c74a9..09df863 100644
--- a/src/network-soup.h
+++ b/src/network-soup.h
@@ -57,6 +57,7 @@ GString *net_post_blocking(
 
 #define NET_ERROR net_error_quark()
 int net_error_quark(void);
+gboolean net_queue_dispatcher(void);
 
 #if (DATASERVER_VERSION >= 2023001)
 EProxy *proxy_init(void);
diff --git a/src/network.h b/src/network.h
index e34fb36..ecf8790 100644
--- a/src/network.h
+++ b/src/network.h
@@ -30,6 +30,7 @@
 #define GCONF_KEY_USER_PROXY "/apps/evolution/evolution-rss/user_proxy"
 #define GCONF_KEY_PASS_PROXY "/apps/evolution/evolution-rss/pass_proxy"
 #define GCONF_KEY_NETWORK_TIMEOUT "/apps/evolution/evolution-rss/network_timeout"
+#define GCONF_KEY_DOWNLOAD_QUEUE_SIZE "/apps/evolution/evolution-rss/network_queue_size"
 
 /* GConf paths and keys from e-d-s e-proxy.c*/
 #define PATH_GCONF_EVO_NETWORK_CONFIG "/apps/evolution/shell/network_config"
diff --git a/src/parser.c b/src/parser.c
index 65373a6..45048b7 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -1062,7 +1062,7 @@ update_channel(RDF *r)
 	GtkWidget *progress = r->progress;
 	gchar *buf, *safes, *feed_dir, *feed_name;
 	gchar *uid, *msg;
-	gchar *tmpdir, *name, *enclurl;
+	gchar *tmpdir, *name;
 	GError *err = NULL;
 
 	safes = encode_rfc2047(chn_name);
@@ -1117,30 +1117,30 @@ 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);
+				name = g_build_filename(tmpdir,
+						g_path_get_basename(CF->encl),
+						NULL);
 				g_free(tmpdir);
-				enclurl = CF->encl;
-				//replace encl with filename generated
-				// this will be a weak ref and get feed by free_cf
+				CF->enclurl = CF->encl;
 				CF->encl = name;
-				dp("enclosure file:%s\n", name)
+				d("enclosure file:%s\n", name)
 				CF->efile = fopen(name, "w");
 				if (!CF->efile) continue;
-				//*************************************************************************//
-				//we need to disable mail filter for large enclosures as it burns cpu a lot//
-				//*************************************************************************//
 				download_unblocking(
-					enclurl,
+					CF->enclurl,
 					download_chunk,
 					CF->efile,
 					(gpointer)finish_enclosure,
 					CF,
 					0,
 					&err);
-				g_free(enclurl);
 			} else {
 				create_mail(CF);
 				write_feed_status_line(CF->feed_fname, CF->feed_uri);
diff --git a/src/rss.c b/src/rss.c
index 0d8528e..ec3d16d 100644
--- a/src/rss.c
+++ b/src/rss.c
@@ -1,5 +1,5 @@
 /*  Evoution RSS Reader Plugin
- *  Copyright (C) 2007-2009 Lucian Langa <cooly gnome eu org>
+ *  Copyright (C) 2007-2010 Lucian Langa <cooly gnome eu org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -541,7 +541,7 @@ create_user_pass_dialog(RSS_AUTH *auth)
 	GtkWidget *container, *container2;
 	GtkWidget *widget, *action_area;
 	GtkWidget *content_area, *password_dialog;
-        AtkObject *a11y;
+	AtkObject *a11y;
 	gchar *markup;
 
         widget = gtk_dialog_new_with_buttons (
@@ -593,32 +593,32 @@ create_user_pass_dialog(RSS_AUTH *auth)
                 GTK_TABLE (container), widget,
                 0, 1, 0, 3, GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
 
-        widget = gtk_label_new (NULL);
-        gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE);
+	widget = gtk_label_new (NULL);
+	gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE);
 
 	markup = g_markup_printf_escaped (_("Enter your username and password for:\n '%s'"), auth->url);
 	gtk_label_set_markup (GTK_LABEL (widget), markup);
 	g_free (markup);
-        gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
-        gtk_widget_show (widget);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_widget_show (widget);
 
         gtk_table_attach (
                 GTK_TABLE (container), widget,
                 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 0, 0);
 
-        container2 = gtk_table_new (2, 2, FALSE);
+	container2 = gtk_table_new (2, 2, FALSE);
 	gtk_widget_show (container2);
-        gtk_table_attach (
-                GTK_TABLE (container), container2,
-                1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 0, 0);
+	gtk_table_attach (
+		GTK_TABLE (container), container2,
+		1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 0, 0);
 
-        widget = gtk_label_new (NULL);
-        gtk_label_set_markup (GTK_LABEL (widget), _("Username: "));
-        gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
-        gtk_widget_show (widget);
-        gtk_table_attach (
-                GTK_TABLE (container2), widget,
-                0, 1, 0, 1, GTK_EXPAND | GTK_FILL, 0, 0, 0);
+	widget = gtk_label_new (NULL);
+	gtk_label_set_markup (GTK_LABEL (widget), _("Username: "));
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_widget_show (widget);
+	gtk_table_attach (
+		GTK_TABLE (container2), widget,
+		0, 1, 0, 1, GTK_EXPAND | GTK_FILL, 0, 0, 0);
 
         username = gtk_entry_new ();
         a11y = gtk_widget_get_accessible (username);
@@ -710,9 +710,9 @@ web_auth_dialog(RSS_AUTH *auth_info)
 		user_pass_cb(auth_info, response, dialog);
 	} else
 		g_signal_connect_swapped (dialog,
-                             "response",
-                             G_CALLBACK (user_pass_cb),
-                             auth_info);
+			"response",
+			G_CALLBACK (user_pass_cb),
+			auth_info);
 }
 
 gboolean
@@ -984,27 +984,27 @@ xml_set_prop (xmlNodePtr node, const char *name, char **val)
 static gboolean
 xml_set_bool (xmlNodePtr node, const char *name, gboolean *val)
 {
-        gboolean gbool;
-        char *buf;
+	gboolean gbool;
+	char *buf;
 
-        if ((buf = (char *)xmlGetProp (node, (xmlChar *)name))) {
-                gbool = (!strcmp (buf, "true") || !strcmp (buf, "yes"));
-                xmlFree (buf);
+	if ((buf = (char *)xmlGetProp (node, (xmlChar *)name))) {
+		gbool = (!strcmp (buf, "true") || !strcmp (buf, "yes"));
+		xmlFree (buf);
 
-                if (gbool != *val) {
-                        *val = gbool;
-                        return TRUE;
-                }
-        }
+		if (gbool != *val) {
+			*val = gbool;
+			return TRUE;
+		}
+	}
 
-        return FALSE;
+	return FALSE;
 }
 
 gboolean
 feed_new_from_xml(char *xml)
 {
 	xmlNodePtr node;
-        xmlDocPtr doc = NULL;
+	xmlDocPtr doc = NULL;
 	char *uid = NULL;
 	char *name = NULL;
 	char *url = NULL;
@@ -1040,7 +1040,7 @@ feed_new_from_xml(char *xml)
                 if (!strcmp ((char *)node->name, "url")) {
 			xml_set_content (node, &url);
 		}
-                if (!strcmp ((char *)node->name, "type")) {
+		if (!strcmp ((char *)node->name, "type")) {
 			xml_set_content (node, &type);
 		}
 		if (!strcmp ((char *)node->name, "delete")) {
@@ -1572,12 +1572,12 @@ webkit_click (GtkEntry *entry,
 {
 	GtkWidget *separator, *redo_menuitem;
 	redo_menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_REDO, NULL);
-        gtk_widget_set_sensitive (redo_menuitem, TRUE);
-        gtk_widget_show (redo_menuitem);
-        gtk_menu_shell_insert (GTK_MENU_SHELL (menu), redo_menuitem, 1);
+	gtk_widget_set_sensitive (redo_menuitem, TRUE);
+	gtk_widget_show (redo_menuitem);
+	gtk_menu_shell_insert (GTK_MENU_SHELL (menu), redo_menuitem, 1);
 	separator = gtk_separator_menu_item_new ();
-        gtk_widget_show (separator);
-        gtk_menu_shell_insert (GTK_MENU_SHELL (menu), separator, 2);
+	gtk_widget_show (separator);
+	gtk_menu_shell_insert (GTK_MENU_SHELL (menu), separator, 2);
 	return TRUE;
 }
 #endif
@@ -1624,23 +1624,25 @@ gecko_click(GtkMozEmbed *mozembed, gpointer dom_event, gpointer user_data)
 	GtkMenu *menu;
 	gchar *link = NULL;
 #if EVOLUTION_VERSION < 22900
-        EMPopup *emp = NULL;
-        GSList *menus = NULL;
+	EMPopup *emp = NULL;
+	GSList *menus = NULL;
 	gint i=0, menu_size;
 #endif
 
 	if (-1 == (button = gecko_get_mouse_event_button (dom_event))) {
-                g_warning ("Cannot determine mouse button!\n");
-                return FALSE;
-        }
+		g_warning ("Cannot determine mouse button!\n");
+		return FALSE;
+	}
 
 	link = gtk_moz_embed_get_link_message((GtkMozEmbed *)rf->mozembed);
 
 #if EVOLUTION_VERSION >= 22900
-	menu = e_popup_menu_create_with_domain (rss_menu_items,
-                                                0, (guint32)(strlen(link) ? 3:4),
-						link,
-						GETTEXT_PACKAGE);
+	menu = e_popup_menu_create_with_domain (
+			rss_menu_items,
+			0,
+			(guint32)(strlen(link) ? 3:4),
+			link,
+			GETTEXT_PACKAGE);
 	if (button == 2)
 		gtk_menu_popup (
 			GTK_MENU (menu),
@@ -1657,8 +1659,8 @@ gecko_click(GtkMozEmbed *mozembed, gpointer dom_event, gpointer user_data)
 	for (; i<menu_size; i++)
 		menus = g_slist_prepend(menus, &rss_menu_items[i]);
 
-        e_popup_add_items((EPopup *)emp, menus, NULL, rss_menu_items_free, link);
-        menu = e_popup_create_menu_once((EPopup *)emp, NULL, 0);
+	e_popup_add_items((EPopup *)emp, menus, NULL, rss_menu_items_free, link);
+	menu = e_popup_create_menu_once((EPopup *)emp, NULL, 0);
 
 	if (button == 2)
 		gtk_menu_popup(menu, NULL, NULL, NULL, NULL, button, gtk_get_current_event_time());
@@ -1690,7 +1692,7 @@ org_gnome_rss_browser (EMFormatHTML *efh, void *eb, EMFormatHTMLPObject *pobject
 	guint engine = fallback_engine();
 	moz = gtk_scrolled_window_new(NULL,NULL);
 	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(moz),
-                                       GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+		GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
 
 #ifdef HAVE_WEBKIT
 	if (engine == 1) {
@@ -1759,7 +1761,7 @@ org_gnome_rss_browser (EMFormatHTML *efh, void *eb, EMFormatHTMLPObject *pobject
 	if (engine == 2)
 		gtk_widget_show_all(moz);
 
-        gtk_container_add ((GtkContainer *) eb, moz);
+	gtk_container_add ((GtkContainer *) eb, moz);
 ///        gtk_container_check_resize ((GtkContainer *) eb);
 //	gtk_widget_set_size_request((GtkWidget *)rf->mozembed, 330, 330);
 //        gtk_container_add ((GtkContainer *) eb, rf->mozembed);
@@ -1776,7 +1778,7 @@ org_gnome_rss_browser (EMFormatHTML *efh, void *eb, EMFormatHTMLPObject *pobject
 static gboolean
 org_gnome_rss_rfrcomm (EMFormatHTML *efh, void *eb, EMFormatHTMLPObject *pobject)
 {
-        struct _org_gnome_rss_controls_pobject *po =
+	struct _org_gnome_rss_controls_pobject *po =
 			(struct _org_gnome_rss_controls_pobject *) pobject;
 	GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
 	GtkWidget *button;
@@ -3999,8 +4001,8 @@ check_feed_folder(gchar *folder_name)
 			} while (NULL != path[++i]);
 			g_strfreev(path);
 		}
-                mail_folder = camel_store_get_folder (store, real_name, 0, NULL);
-        }
+		mail_folder = camel_store_get_folder (store, real_name, 0, NULL);
+	}
 	g_free(real_name);
 	return mail_folder;
 
@@ -4009,9 +4011,9 @@ check_feed_folder(gchar *folder_name)
 void
 rss_delete_feed(gchar *full_path, gboolean folder)
 {
-        CamelException ex;
+	CamelException ex;
 	gchar *tmp, *tkey, *url;
-        CamelStore *store;
+	CamelStore *store;
 	gchar *name, *real_name, *buf, *feed_dir, *feed_name;
 
 	store = rss_component_peek_local_store();
@@ -4022,7 +4024,7 @@ rss_delete_feed(gchar *full_path, gboolean folder)
 	real_name = g_hash_table_lookup(rf->feed_folders, name);
 	if (!real_name)
 		real_name = name;
-        camel_exception_init (&ex);
+	camel_exception_init (&ex);
 	rss_delete_folders (store, full_path, &ex);
 	if (camel_exception_is_set (&ex)) {
 #if EVOLUTION_VERSION < 22904
@@ -4035,33 +4037,33 @@ rss_delete_feed(gchar *full_path, gboolean folder)
 #endif
 		camel_exception_clear (&ex);
 	}
-        //also remove status file
-        tkey = g_hash_table_lookup(rf->hrname, real_name);
+	//also remove status file
+	tkey = g_hash_table_lookup(rf->hrname, real_name);
 	if (!tkey)
 		return;
-        url =  g_hash_table_lookup(rf->hr, tkey);
+	url =  g_hash_table_lookup(rf->hr, tkey);
 	if (!url)
 		goto out;
-        buf = gen_md5(url);
+	buf = gen_md5(url);
 	feed_dir = rss_component_peek_base_directory();
-        feed_name = g_strdup_printf("%s/%s", feed_dir, buf);
-        g_free(feed_dir);
-        g_free(buf);
-        unlink(feed_name);
+	feed_name = g_strdup_printf("%s/%s", feed_dir, buf);
+	g_free(feed_dir);
+	g_free(buf);
+	unlink(feed_name);
 	tmp = g_strdup_printf("%s.img", feed_name);
-        unlink(tmp);
+	unlink(tmp);
 	g_free(tmp);
 	tmp = g_strdup_printf("%s.fav", feed_name);
-        unlink(tmp);
+	unlink(tmp);
 	g_free(tmp);
 out:	if (folder) {
 		d("print folder:%s\n", real_name);
 		remove_feed_hash(real_name);
 	}
-        delete_feed_folder_alloc(name);
+	delete_feed_folder_alloc(name);
 	g_free(name);
 	g_idle_add((GSourceFunc)store_redraw, GTK_TREE_VIEW(rf->treeview));
-        save_gconf_feed();
+	save_gconf_feed();
 }
 
 static void
@@ -5036,7 +5038,7 @@ 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) {
+	if (appended_uid != NULL && !rf->import && !CF->encl) {	//do not filter enclosure at this time
 		filter_uids = g_ptr_array_sized_new(1);
 		g_ptr_array_add(filter_uids, appended_uid);
 		mail_filter_on_demand (mail_folder, filter_uids);
@@ -5143,6 +5145,7 @@ free_cf(create_feed *CF)
 	g_free(CF->website);
 	g_free(CF->feedid);
 	g_free(CF->encl);
+	g_free(CF->enclurl);
 	g_free(CF->feed_fname);
 	g_free(CF->feed_uri);
 	if (CF->comments)
@@ -5154,27 +5157,47 @@ free_cf(create_feed *CF)
 	g_free(CF);
 }
 
+extern guint net_queue_run_count;
+extern guint net_qid;
+
 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, SoupMessage *msg, create_feed *user_data)
+finish_enclosure (SoupSession *soup_sess,
+		SoupMessage *msg,
+		create_feed *user_data)
 #endif
 {
 #if LIBSOUP_VERSION < 2003000
-	fwrite(msg->response.body, msg->response.length, 1, user_data->efile);
+	fwrite(msg->response.body,
+		msg->response.length,
+		1,
+		user_data->efile);
 #else
-	fwrite(msg->response_body->data, msg->response_body->length, 1, user_data->efile);
+	fwrite(msg->response_body->data,
+		msg->response_body->length,
+		1,
+		user_data->efile);
 #endif
 	fclose(user_data->efile);
 
 	if (!feed_is_new(user_data->feed_fname, user_data->feed_uri)) {
 		create_mail(user_data);
-		write_feed_status_line(user_data->feed_fname, user_data->feed_uri);
+		write_feed_status_line(
+				user_data->feed_fname,
+				user_data->feed_uri);
 	}
+	rf->enclist = g_list_remove(rf->enclist, user_data->enclurl);
 	free_cf(user_data);
 	//g_free(msg->response_body->data);
 	//g_object_unref(msg);
+	if (net_queue_run_count) net_queue_run_count--;
+	if (!net_qid)
+		net_qid = g_idle_add(
+				(GSourceFunc)net_queue_dispatcher,
+				NULL);
 }
 
 static void
diff --git a/src/rss.h b/src/rss.h
index 94d8151..f2054c7 100644
--- a/src/rss.h
+++ b/src/rss.h
@@ -1,5 +1,5 @@
 /*  Evoution RSS Reader Plugin
- *  Copyright (C) 2007-2009  Lucian Langa <cooly gnome eu org>
+ *  Copyright (C) 2007-2010  Lucian Langa <cooly gnome eu org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -65,14 +65,14 @@
 #define HTTP_CACHE_PATH "http"
 
 typedef struct _RDF {
-        char		*uri;
-        char		*html;
-        xmlDocPtr	cache;
-        gboolean	shown;
-        gchar		*type;		//char type
-        guint		type_id;	//num type
+	char		*uri;
+	char		*html;
+	xmlDocPtr	cache;
+	gboolean	shown;
+	gchar		*type;		//char type
+	guint		type_id;	//num type
 	gchar		*version;	//feed version
-        gchar		*feedid;	//md5 string id of feed
+	gchar		*feedid;	//md5 string id of feed
 	gchar		*title;		//title of the feed
 	gchar		*prefix;	//directory path
 	gchar		*maindate;	//channel date
@@ -81,8 +81,8 @@ typedef struct _RDF {
 	GtkWidget	*progress;
 	guint		total;		//total articles
 	guint		ttl;		//feed specified refresh interval
-        /* Soup stuff */
-        SoupMessage *message;
+	/* Soup stuff */
+	SoupMessage *message;
 	guint		error;		//invalid feed
 	char		*strerror;	//error msg
 	GArray		*uids;
@@ -108,56 +108,56 @@ typedef struct _hrfeed {
 } hrfeed;
 
 typedef struct _rssfeed {
-        GHashTable      *hrname;		//bind feed name to key
-        GHashTable      *hrname_r;		//and mirrored structure for faster lookups
-        GHashTable      *hrcrc;			//crc32 to key binding
-        GHashTable      *hr;			//feeds hash
-        GHashTable      *hn;			//feeds hash
-        GHashTable      *hre;			//enabled feeds hash
-        GHashTable      *hrt;			//feeds name hash
-        GHashTable      *hrh;			//fetch html flag
-        GHashTable      *hruser;		//auth user hash
-        GHashTable      *hrpass;		//auth pass hash
+	GHashTable      *hrname;		//bind feed name to key
+	GHashTable      *hrname_r;		//and mirrored structure for faster lookups
+	GHashTable      *hrcrc;			//crc32 to key binding
+	GHashTable      *hr;			//feeds hash
+	GHashTable      *hn;			//feeds hash
+	GHashTable      *hre;			//enabled feeds hash
+	GHashTable      *hrt;			//feeds name hash
+	GHashTable      *hrh;			//fetch html flag
+	GHashTable      *hruser;		//auth user hash
+	GHashTable      *hrpass;		//auth pass hash
 	gboolean	soup_auth_retry;	//wether to retry auth after an unsucessful auth
-        GHashTable      *hrdel_feed;		//option to delete messages in current feed
-        GHashTable      *hrdel_days;		//option to delete messages older then days
-        GHashTable      *hrdel_messages;	//option to keep last messages
-        GHashTable      *hrdel_unread;		//option to delete unread messages too
-        GHashTable      *hrttl;
-        GHashTable      *hrttl_multiply;
-        GHashTable      *hrupdate;		//feeds update method
-        GtkWidget       *feed_dialog;
-        GtkWidget       *progress_dialog;
-        GtkWidget       *progress_bar;
-        GtkWidget       *label;
-        GtkWidget       *sr_feed;		//s&r upper text (feed)
-        GtkWidget       *treeview;
-        GtkWidget       *edbutton;
+	GHashTable      *hrdel_feed;		//option to delete messages in current feed
+	GHashTable      *hrdel_days;		//option to delete messages older then days
+	GHashTable      *hrdel_messages;	//option to keep last messages
+	GHashTable      *hrdel_unread;		//option to delete unread messages too
+	GHashTable      *hrttl;
+	GHashTable      *hrttl_multiply;
+	GHashTable      *hrupdate;		//feeds update method
+	GtkWidget       *feed_dialog;
+	GtkWidget       *progress_dialog;
+	GtkWidget       *progress_bar;
+	GtkWidget       *label;
+	GtkWidget       *sr_feed;		//s&r upper text (feed)
+	GtkWidget       *treeview;
+	GtkWidget       *edbutton;
 	GtkWidget	*errdialog;
 	GtkWidget	*preferences;
 	gchar		*err;			//if using soup _unblocking error goes here
 	gchar		*err_feed;		//name of the feed that caused above err
-        gchar           *cfeed;			//current feed name
+	gchar           *cfeed;			//current feed name
 	gboolean	online;			//networkmanager dependant
 	gboolean	fe;			//feed enabled (at least one)
 #ifdef EVOLUTION_2_12
 	EMEventTargetSendReceive *t;
 #else
-        EMPopupTargetSelect *t;
+	EMPopupTargetSelect *t;
 #endif
-        gboolean        setup;
-        gboolean        pending;
-        gboolean        import;			//import going on
+	gboolean        setup;
+	gboolean        pending;
+	gboolean        import;			//import going on
 	gboolean	autoupdate;		//feed is currently auto fetched
 	guint		feed_queue;
-        gboolean        cancel;			//cancelation signal
-        gboolean        cancel_all;		//cancelation signal
-        GHashTable      *session;		//queue of active unblocking sessions
-        GHashTable      *abort_session;		//this is a hack to be able to iterate when
+	gboolean        cancel;			//cancelation signal
+	gboolean        cancel_all;		//cancelation signal
+	GHashTable      *session;		//queue of active unblocking sessions
+	GHashTable      *abort_session;		//this is a hack to be able to iterate when
 						//we remove keys from seesion with weak_ref
-        GHashTable      *key_session;		//queue of active unblocking sessions and keys linked
-        SoupSession     *b_session;		//active blocking session
-        SoupMessage     *b_msg_session;		//message running in the blocking session
+	GHashTable      *key_session;		//queue of active unblocking sessions and keys linked
+	SoupSession     *b_session;		//active blocking session
+	SoupMessage     *b_msg_session;		//message running in the blocking session
 	guint		rc_id;
 	struct _send_info *info;		//s&r data
 	struct userpass	*un;
@@ -173,6 +173,8 @@ typedef struct _rssfeed {
 	GHashTable	*error_hash;
 	guint		test;
 	char		*current_uid;		// currently read article
+	GQueue		*stqueue;		// network downloads tracking
+	GList		*enclist;		// network downloads tracking
 #if HAVE_DBUS
 	DBusConnection	*bus;			// DBUS
 #endif
@@ -230,51 +232,51 @@ typedef struct USERPASS {
 } userpass;
 
 struct _send_data {
-        GList *infos;
+	GList *infos;
 
-        GtkDialog *gd;
-        int cancelled;
+	GtkDialog *gd;
+	int cancelled;
 
-        CamelFolder *inbox;     /* since we're never asked to update this one, do it ourselves */
-        time_t inbox_update;
+	CamelFolder *inbox;     /* since we're never asked to update this one, do it ourselves */
+	time_t inbox_update;
 
-        GMutex *lock;
-        GHashTable *folders;
+	GMutex *lock;
+	GHashTable *folders;
 
-        GHashTable *active;     /* send_info's by uri */
+	GHashTable *active;     /* send_info's by uri */
 };
 
 typedef enum {
-        SEND_RECEIVE,           /* receiver */
-        SEND_SEND,              /* sender */
-        SEND_UPDATE,            /* imap-like 'just update folder info' */
-        SEND_INVALID
+	SEND_RECEIVE,           /* receiver */
+	SEND_SEND,              /* sender */
+	SEND_UPDATE,            /* imap-like 'just update folder info' */
+	SEND_INVALID
 } send_info_t ;
 
 typedef enum {
-        SEND_ACTIVE,
-        SEND_CANCELLED,
-        SEND_COMPLETE
+	SEND_ACTIVE,
+	SEND_CANCELLED,
+	SEND_COMPLETE
 } send_state_t;
 
 struct _send_info {
-        send_info_t type;               /* 0 = fetch, 1 = send */
-        CamelOperation *cancel;
-        char *uri;
-        int keep;
-        send_state_t state;
-        GtkWidget *progress_bar;
-        GtkWidget *cancel_button;
-        GtkWidget *status_label;
-
-        int again;              /* need to run send again */
-
-        int timeout_id;
-        char *what;
-        int pc;
-
-        /*time_t update;*/
-        struct _send_data *data;
+	send_info_t type;               /* 0 = fetch, 1 = send */
+	CamelOperation *cancel;
+	char *uri;
+	int keep;
+	send_state_t state;
+	GtkWidget *progress_bar;
+	GtkWidget *cancel_button;
+	GtkWidget *status_label;
+
+	int again;              /* need to run send again */
+
+	int timeout_id;
+	char *what;
+	int pc;
+
+	/*time_t update;*/
+	struct _send_data *data;
 };
 
 typedef struct CREATE_FEED {	/* used by create_mail function when called by unblocking fetch */
@@ -291,6 +293,7 @@ typedef struct CREATE_FEED {	/* used by create_mail function when called by unbl
 	gchar	*feed_fname;	// feed name file
 	gchar	*feed_uri;
 	gchar *encl;
+	gchar *enclurl;
 	FILE *efile;		//enclosure file
 	gchar *comments;
 	GList *category;	// list of categories article is posted under



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