[evolution-rss] Bug 634478 - blocks main evolution process
- From: Lucian Langa <lucilanga src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-rss] Bug 634478 - blocks main evolution process
- Date: Wed, 2 Mar 2011 21:23:16 +0000 (UTC)
commit 95eae836187690ac81c0e1a750f5480efd8e57c5
Author: Lucian Langa <lucilanga gnome org>
Date: Wed Mar 2 23:19:30 2011 +0200
Bug 634478 - blocks main evolution process
src/network-soup.c | 196 +++++++++++++++++++++++++++++++++++++++++++------
src/network-soup.h | 18 +++++
src/network.h | 32 ++++----
src/rss-evo-common.c | 156 +++++++++++++++++++++++++++++++++++++++
src/rss-evo-common.h | 21 ++++++
src/rss.c | 36 ++++++---
6 files changed, 407 insertions(+), 52 deletions(-)
---
diff --git a/src/network-soup.c b/src/network-soup.c
index 3958a16..188c3d0 100644
--- a/src/network-soup.c
+++ b/src/network-soup.c
@@ -35,6 +35,7 @@
extern int rss_verbose_debug;
+#include "rss-evo-common.h"
#include "network.h"
#include "network-soup.h"
#include "rss.h"
@@ -68,8 +69,13 @@ typedef struct {
gpointer cb2;
gpointer cbdata2;
gchar *url;
+ gchar *host;
+ SoupAddress *addr;
} STNET;
+void proxify_session_async(EProxy *proxy, STNET *stnet);
+static void rss_webkit_resolve_callback (SoupAddress *addr, guint status, gpointer data);
+
#define DOWNLOAD_QUEUE_SIZE 15
guint net_qid = 0; // net queue dispatcher
guint net_queue_run_count = 0; //downloads in progress
@@ -161,12 +167,10 @@ recv_msg (SoupMessage *msg, gpointer user_data)
static gboolean
remove_if_match (gpointer key, gpointer value, gpointer user_data)
{
- if (value == user_data)
- {
+ if (value == user_data) {
g_hash_table_remove(rf->key_session, key);
return TRUE;
- }
- else
+ } else
return FALSE;
}
@@ -206,39 +210,62 @@ proxy_init(void)
return proxy;
}
+//this will insert proxy in the session
+//and queue loading of page
void
-proxify_webkit_session(EProxy *proxy, gchar *uri)
+proxify_webkit_session_async(EProxy *proxy, WEBKITNET *wknet)
{
- SoupURI *proxy_uri = NULL;
- gint ptype = gconf_client_get_int (rss_gconf, KEY_GCONF_EVO_PROXY_TYPE, NULL);
+ SoupURI *proxy_uri = NULL, *su;
+ gint ptype = gconf_client_get_int (
+ rss_gconf, KEY_GCONF_EVO_PROXY_TYPE, NULL);
switch (ptype) {
#ifndef HAVE_LIBSOUP_GNOME
case 0:
#endif
case 2:
- if (e_proxy_require_proxy_for_uri (proxy, uri)) {
+ su = soup_uri_new (wknet->base);
+ if (su) {
+ if (su->scheme == SOUP_URI_SCHEME_HTTPS) {
+ if (rss_ep_need_proxy_https (proxy, su->host)) {
#if (DATASERVER_VERSION >=2026000)
- proxy_uri = e_proxy_peek_uri_for (proxy, uri);
- d("webkit proxified %s with %s:%d\n", uri, proxy_uri->host, proxy_uri->port);
+ proxy_uri = e_proxy_peek_uri_for (proxy, wknet->base);
#else
- g_print("WARN: e_proxy_peek_uri_for() requires evolution-data-server 2.26\n");
- return;
+ g_print("WARN: e_proxy_peek_uri_for() requires evolution-data-server 2.26\n");
+ soup_uri_free(su);
+ return;
#endif
- } else {
- d("webkit no PROXY-%s\n", uri);
+ if (proxy_uri) {
+ d("proxified %s with %s:%d\n", wknet->base, proxy_uri->host, proxy_uri->port);
+ }
+ } else {
+ d("no PROXY-%s\n", wknet->base);
+ }
+ g_object_set (
+ G_OBJECT (webkit_session),
+ SOUP_SESSION_PROXY_URI,
+ proxy_uri, NULL);
+ soup_uri_free(su);
+ goto out;
+ } else {
+ wknet->addr = soup_address_new (su->host, 0);
+ soup_uri_free(su);
+ soup_address_resolve_async (wknet->addr, NULL, NULL,
+ rss_webkit_resolve_callback, wknet);
+ return;
+ }
}
break;
- g_object_set (
- G_OBJECT (webkit_session),
- SOUP_SESSION_PROXY_URI, proxy_uri, NULL);
+
#ifdef HAVE_LIBSOUP_GNOME
case 0:
soup_session_add_feature_by_type (
- webkit_session, SOUP_TYPE_PROXY_RESOLVER_GNOME);
+ webkit_session,
+ SOUP_TYPE_PROXY_RESOLVER_GNOME);
break;
#endif
}
+out: wknet->cb(wknet->str, wknet->base, wknet->encoding);
}
@@ -285,6 +312,122 @@ proxify_session(EProxy *proxy, SoupSession *session, gchar *uri)
}
#endif
+static void
+rss_resolve_callback (SoupAddress *addr, guint status, gpointer data)
+{
+ STNET *stnet = (STNET *)data;
+ SoupURI *proxy_uri = NULL;
+ if (status == SOUP_STATUS_OK) {
+ if (rss_ep_need_proxy_http (proxy, stnet->host, stnet->addr)) {
+#if (DATASERVER_VERSION >=2026000)
+ proxy_uri = e_proxy_peek_uri_for (proxy, stnet->url);
+#else
+ g_print("WARN: e_proxy_peek_uri_for() requires evolution-data-server 2.26\n");
+ return;
+#endif
+ if (proxy_uri) {
+ d("proxified %s with %s:%d\n", stnet->url, proxy_uri->host, proxy_uri->port);
+ }
+ }
+ } else {
+ d("no PROXY-%s\n", stnet->url);
+ }
+ g_object_set (
+ G_OBJECT (stnet->ss),
+ SOUP_SESSION_PROXY_URI,
+ proxy_uri, NULL);
+ soup_session_queue_message (stnet->ss, stnet->sm,
+ stnet->cb2, stnet->cbdata2);
+}
+
+static void
+rss_webkit_resolve_callback (SoupAddress *addr, guint status, gpointer data)
+{
+ WEBKITNET *wknet = (WEBKITNET *)data;
+ SoupURI *proxy_uri = NULL;
+ if (status == SOUP_STATUS_OK) {
+ if (rss_ep_need_proxy_http (proxy, wknet->host, wknet->addr)) {
+#if (DATASERVER_VERSION >=2026000)
+ proxy_uri = e_proxy_peek_uri_for (proxy, wknet->base);
+#else
+ g_print("WARN: e_proxy_peek_uri_for() requires evolution-data-server 2.26\n");
+ return;
+#endif
+ if (proxy_uri) {
+ dp("proxified %s with %s:%d\n", wknet->base, proxy_uri->host, proxy_uri->port);
+ }
+ }
+ } else {
+ d("no PROXY-%s\n", wknet->base);
+ }
+ g_object_set (
+ G_OBJECT (webkit_session),
+ SOUP_SESSION_PROXY_URI,
+ proxy_uri, NULL);
+ wknet->cb(wknet->str, wknet->base, wknet->encoding);
+}
+
+//this will insert proxy in the session
+//and queue the message to be sent
+void
+proxify_session_async(EProxy *proxy, STNET *stnet)
+{
+ SoupURI *proxy_uri = NULL, *su;
+ gint ptype = gconf_client_get_int (
+ rss_gconf, KEY_GCONF_EVO_PROXY_TYPE, NULL);
+
+ switch (ptype) {
+#ifndef HAVE_LIBSOUP_GNOME
+ case 0:
+#endif
+ case 2:
+ su = soup_uri_new (stnet->url);
+ stnet->host = su->host;
+ if (su) {
+ if (su->scheme == SOUP_URI_SCHEME_HTTPS) {
+ if (rss_ep_need_proxy_https (proxy, su->host)) {
+#if (DATASERVER_VERSION >=2026000)
+ proxy_uri = e_proxy_peek_uri_for (proxy, stnet->url);
+#else
+ g_print("WARN: e_proxy_peek_uri_for() requires evolution-data-server 2.26\n");
+ soup_uri_free(su);
+ return;
+#endif
+ if (proxy_uri) {
+ d("proxified %s with %s:%d\n", stnet->url, proxy_uri->host, proxy_uri->port);
+ }
+ } else {
+ d("no PROXY-%s\n", stnet->url);
+ }
+ g_object_set (
+ G_OBJECT (stnet->ss),
+ SOUP_SESSION_PROXY_URI,
+ proxy_uri, NULL);
+ soup_uri_free(su);
+ goto out;
+ } else {
+ stnet->addr = soup_address_new (su->host, 0);
+ soup_uri_free(su);
+ soup_address_resolve_async (stnet->addr, NULL, NULL,
+ rss_resolve_callback, stnet);
+ return;
+ }
+ }
+ break;
+
+#ifdef HAVE_LIBSOUP_GNOME
+ case 0:
+ soup_session_add_feature_by_type (
+ stnet->ss, SOUP_TYPE_PROXY_RESOLVER_GNOME);
+ break;
+#endif
+ }
+
+out: soup_session_queue_message (stnet->ss, stnet->sm,
+ stnet->cb2, stnet->cbdata2);
+
+}
+
guint
read_up(gpointer data)
{
@@ -598,6 +741,7 @@ net_get_unblocking(gchar *url,
gchar *agstr;
gchar *mainurl = NULL;
gchar **res;
+ STNET *stnet;
soup_sess = soup_session_async_new();
@@ -609,9 +753,6 @@ net_get_unblocking(gchar *url,
}
#endif
-#if (DATASERVER_VERSION >= 2023001)
- proxify_session(proxy, soup_sess, url);
-#endif
if (cb && data) {
info = g_new0(CallbackInfo, 1);
info->user_cb = cb;
@@ -638,7 +779,7 @@ net_get_unblocking(gchar *url,
/* Queue an async HTTP request */
msg = soup_message_new ("GET", url);
if (!msg) {
- g_free(info);
+ if (info) g_free(info);
g_set_error(err, NET_ERROR, NET_ERROR_GENERIC, "%s",
soup_status_get_phrase(2)); //invalid url
return FALSE;
@@ -672,8 +813,15 @@ net_get_unblocking(gchar *url,
soup_message_add_header_handler (msg, "got_body",
"Location", G_CALLBACK (redirect_handler), soup_sess);
- 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);
+
+ proxify_session_async(proxy, stnet);
+ //free stnet
//// g_object_add_weak_pointer (G_OBJECT(msg), (gpointer)info);
g_object_weak_ref (G_OBJECT(msg), unblock_free, soup_sess);
diff --git a/src/network-soup.h b/src/network-soup.h
index d64d963..41e63a3 100644
--- a/src/network-soup.h
+++ b/src/network-soup.h
@@ -22,6 +22,11 @@
#if (DATASERVER_VERSION >= 2023001)
#include <libedataserver/e-proxy.h>
#endif
+#include <libsoup/soup.h>
+#ifdef HAVE_LIBSOUP_GNOME
+#include <libsoup/soup-gnome.h>
+#include <libsoup/soup-gnome-features.h>
+#endif
void abort_all_soup(void);
gboolean abort_soup_sess(
@@ -55,6 +60,18 @@ GString *net_post_blocking(
gpointer data,
GError **err);
+typedef void (*wkCallback)(gchar *str, gchar *base, gchar *encoding);
+
+typedef struct {
+ gchar *str;
+ wkCallback cb;
+ gchar *base;
+ gchar *host;
+ gchar *encoding;
+ SoupAddress *addr;
+} WEBKITNET;
+
+
#define NET_ERROR net_error_quark()
int net_error_quark(void);
gboolean net_queue_dispatcher(void);
@@ -63,6 +80,7 @@ gboolean net_queue_dispatcher(void);
EProxy *proxy_init(void);
void proxify_webkit_session(EProxy *proxy, gchar *uri);
void proxify_session(EProxy *proxy, SoupSession *session, gchar *uri);
+void proxify_webkit_session_async(EProxy *proxy, WEBKITNET *wknet);
#endif
guint save_up(gpointer data);
diff --git a/src/network.h b/src/network.h
index ecf8790..05bcc17 100644
--- a/src/network.h
+++ b/src/network.h
@@ -85,10 +85,10 @@
#define GCONF_E_AUTOCONFIG_URL_KEY GCONF_E_SHELL_NETWORK_CONFIG_PATH "autoconfig_url"*/
enum ProxyType {
- PROXY_TYPE_SYSTEM = 0,
- PROXY_TYPE_NO_PROXY,
- PROXY_TYPE_MANUAL,
- PROXY_TYPE_AUTO_URL /* no auto-proxy at the moment */
+ PROXY_TYPE_SYSTEM = 0,
+ PROXY_TYPE_NO_PROXY,
+ PROXY_TYPE_MANUAL,
+ PROXY_TYPE_AUTO_URL /* no auto-proxy at the moment */
};
typedef enum {
@@ -98,24 +98,24 @@ typedef enum {
} NetErrorCode;
typedef enum {
- NET_STATUS_NULL,
- NET_STATUS_BEGIN,
- NET_STATUS_SUCCESS,
- NET_STATUS_ERROR,
- NET_STATUS_PROGRESS,
- NET_STATUS_DONE
+ NET_STATUS_NULL,
+ NET_STATUS_BEGIN,
+ NET_STATUS_SUCCESS,
+ NET_STATUS_ERROR,
+ NET_STATUS_PROGRESS,
+ NET_STATUS_DONE
} NetStatusType;
typedef struct {
- guint32 current;
- guint32 total;
- gchar *chunk;
- guint chunksize;
+ guint32 current;
+ guint32 total;
+ gchar *chunk;
+ guint chunksize;
} NetStatusProgress;
typedef void (*NetStatusCallback)(NetStatusType status,
- gpointer statusdata,
- gpointer data);
+ gpointer statusdata,
+ gpointer data);
#endif /* __NETWORK_H__ */
diff --git a/src/rss-evo-common.c b/src/rss-evo-common.c
index d6252d5..cb93f23 100644
--- a/src/rss-evo-common.c
+++ b/src/rss-evo-common.c
@@ -25,9 +25,45 @@
#include <mail/e-mail-local.h>
#include <mail/e-mail-reader.h>
#include <mail/em-folder-utils.h>
+#include <libedataserver/e-proxy.h>
+
+#ifdef HAVE_LIBSOUP_GNOME
+#include <libsoup/soup-gnome.h>
+#include <libsoup/soup-gnome-features.h>
+#endif
+
+#define d(x)
#include "rss-evo-common.h"
+enum ProxyType {
+ PROXY_TYPE_SYSTEM = 0,
+ PROXY_TYPE_NO_PROXY,
+ PROXY_TYPE_MANUAL,
+ PROXY_TYPE_AUTO_URL /* no auto-proxy at the moment */
+};
+
+/* Enum definition is copied from gnome-vfs/modules/http-proxy.c */
+typedef enum {
+ PROXY_IPV4 = 4,
+ PROXY_IPV6 = 6
+} ProxyAddrType;
+
+typedef struct {
+ ProxyAddrType type; /* Specifies whether IPV4 or IPV6 */
+ gpointer addr; /* Either in_addr* or in6_addr* */
+ gpointer mask; /* Either in_addr* or in6_addr* */
+} ProxyHostAddr;
+
+struct _EProxyPrivate {
+ SoupURI *uri_http, *uri_https;
+ guint notify_id_evo, notify_id_sys, notify_id_sys_http; /* conxn id of gconf_client_notify_add */
+ GSList* ign_hosts; /* List of hostnames. (Strings) */
+ GSList* ign_addrs; /* List of hostaddrs. (ProxyHostAddrs) */
+ gboolean use_proxy; /* Is our-proxy enabled? */
+ enum ProxyType type;
+};
+
gboolean
rss_emfu_is_special_local_folder (const gchar *name)
{
@@ -109,3 +145,123 @@ fail:
g_free (cfd);
}
+void
+rss_ipv6_network_addr (const struct in6_addr *addr, const struct in6_addr *mask,
+ struct in6_addr *res)
+{
+ gint i;
+
+ for (i = 0; i < 16; ++i) {
+ res->s6_addr[i] = addr->s6_addr[i] & mask->s6_addr[i];
+ }
+}
+
+gboolean
+rss_ep_need_proxy_http (EProxy* proxy, const gchar * host, SoupAddress *addr)
+{
+ EProxyPrivate *priv = proxy->priv;
+ ProxyHostAddr *p_addr = NULL;
+ GSList *l;
+ gint addr_len;
+ struct sockaddr* so_addr = NULL;
+
+ /* check for ignored first */
+ if (rss_ep_is_in_ignored (proxy, host))
+ return FALSE;
+
+ so_addr = soup_address_get_sockaddr (addr, &addr_len);
+
+ if (!so_addr)
+ return TRUE;
+
+ if (so_addr->sa_family == AF_INET) {
+ struct in_addr in, *mask, *addr_in;
+
+ in = ((struct sockaddr_in *)so_addr)->sin_addr;
+ for (l = priv->ign_addrs; l; l = l->next) {
+ p_addr = (ProxyHostAddr *)l->data;
+ if (p_addr->type == PROXY_IPV4) {
+ addr_in = ((struct in_addr *)p_addr->addr);
+ mask = ((struct in_addr *)p_addr->mask);
+ d(g_print ("ep_need_proxy:ipv4: in: %ul\t mask: %ul\t addr: %ul\n",
+ in.s_addr, mask->s_addr, addr_in->s_addr));
+ if ((in.s_addr & mask->s_addr) == addr_in->s_addr) {
+ d(g_print ("Host [%s] doesn't require proxy\n", host));
+ return FALSE;
+ }
+ }
+ }
+ } else {
+ struct in6_addr in6, net6;
+ struct in_addr *addr_in, *mask;
+
+ in6 = ((struct sockaddr_in6 *)so_addr)->sin6_addr;
+ for (l = priv->ign_addrs; l; l = l->next) {
+ p_addr = (ProxyHostAddr *)l->data;
+ rss_ipv6_network_addr (&in6, (struct in6_addr *)p_addr->mask, &net6);
+ if (p_addr->type == PROXY_IPV6) {
+ if (IN6_ARE_ADDR_EQUAL (&net6, (struct in6_addr *)p_addr->addr)) {
+ d(g_print ("Host [%s] doesn't require proxy\n", host));
+ return FALSE;
+ }
+ } else if (p_addr->type == PROXY_IPV6 &&
+ IN6_IS_ADDR_V4MAPPED (&net6)) {
+ guint32 v4addr;
+
+ addr_in = ((struct in_addr *)p_addr->addr);
+ mask = ((struct in_addr *)p_addr->mask);
+
+ v4addr = net6.s6_addr[12] << 24
+ | net6.s6_addr[13] << 16
+ | net6.s6_addr[14] << 8
+ | net6.s6_addr[15];
+ if ((v4addr & mask->s_addr) != addr_in->s_addr) {
+ d(g_print ("Host [%s] doesn't require proxy\n", host));
+ return FALSE;
+ }
+ }
+ }
+ }
+
+ d(g_print ("%s needs a proxy to connect to internet\n", host));
+ return TRUE;
+}
+
+gboolean
+rss_ep_need_proxy_https (EProxy* proxy, const gchar * host)
+{
+ /* Can we share ignore list from HTTP at all? */
+ return !rss_ep_is_in_ignored (proxy, host);
+}
+
+gboolean
+rss_ep_is_in_ignored (EProxy *proxy, const gchar *host)
+{
+ EProxyPrivate *priv;
+ GSList* l;
+ gchar *hn;
+
+ g_return_val_if_fail (proxy != NULL, FALSE);
+ g_return_val_if_fail (host != NULL, FALSE);
+
+ priv = proxy->priv;
+ if (!priv->ign_hosts)
+ return FALSE;
+
+ hn = g_ascii_strdown (host, -1);
+
+ for (l = priv->ign_hosts; l; l = l->next) {
+ if (*((gchar *)l->data) == '*') {
+ if (g_str_has_suffix (hn, ((gchar *)l->data)+1)) {
+ g_free (hn);
+ return TRUE;
+ }
+ } else if (strcmp (hn, l->data) == 0) {
+ g_free (hn);
+ return TRUE;
+ }
+ }
+ g_free (hn);
+
+ return FALSE;
+}
diff --git a/src/rss-evo-common.h b/src/rss-evo-common.h
index d55a720..3fbd5e1 100644
--- a/src/rss-evo-common.h
+++ b/src/rss-evo-common.h
@@ -19,11 +19,20 @@
#ifndef __RSS_EVO_COMMON_H_
#define __RSS_EVO_COMMON_H_
+#include <mail/e-mail-backend.h>
+#include <camel/camel.h>
+#include <libedataserver/e-proxy.h>
+
struct _copy_folder_data {
CamelFolderInfo *fi;
gboolean delete;
};
+void
+rss_ipv6_network_addr (const struct in6_addr *addr,
+ const struct in6_addr *mask,
+ struct in6_addr *res);
+
gboolean
rss_emfu_is_special_local_folder (const gchar *name);
@@ -32,5 +41,17 @@ rss_emfu_copy_folder_selected (EMailBackend *backend,
const gchar *uri,
gpointer data);
+gboolean
+rss_e_proxy_require_proxy_for_uri (EProxy* proxy, const gchar * uri);
+
+gboolean
+rss_ep_need_proxy_http (EProxy* proxy, const gchar * host, SoupAddress *addr);
+
+gboolean
+rss_ep_need_proxy_https (EProxy* proxy, const gchar * host);
+
+gboolean
+rss_ep_is_in_ignored (EProxy *proxy, const gchar *host);
+
#endif /*__RSS_EVO_COMMON_H_*/
diff --git a/src/rss.c b/src/rss.c
index e6b416b..d8bdba2 100644
--- a/src/rss.c
+++ b/src/rss.c
@@ -260,6 +260,7 @@ static void refresh_cb (GtkWidget *button, EMFormatHTMLPObject *pobject);
#ifdef HAVE_WEBKIT
void webkit_set_history(gchar *base);
+void rss_webkit_load_string(gchar *str, gchar *base, gchar *encoding);
#endif
gboolean show_webkit(GtkWidget *webkit);
void sync_folders(void);
@@ -405,6 +406,19 @@ update_progress_text(gchar *title)
}
void
+rss_webkit_load_string(gchar *str, gchar *base, gchar *encoding)
+{
+ webkit_web_view_load_string(
+ WEBKIT_WEB_VIEW(rf->mozembed),
+ str,
+ "text/html",
+ encoding,
+ base);
+ if (strncmp(base, "file:///fake", 12))
+ webkit_set_history(base);
+}
+
+void
update_progress_bar(guint current);
void
@@ -435,6 +449,7 @@ update_progress_bar(guint current)
void
browser_write(gchar *string, gint length, gchar *base)
{
+ WEBKITNET *wknet;
gchar *str = string;
guint engine = fallback_engine();
xmlDoc *src = (xmlDoc *)parse_html(base, string, length);
@@ -462,17 +477,14 @@ browser_write(gchar *string, gint length, gchar *base)
case 1:
#ifdef HAVE_WEBKIT
#if (DATASERVER_VERSION >= 2023001)
- proxify_webkit_session(proxy, base);
-#endif
- webkit_web_view_load_string(
- WEBKIT_WEB_VIEW(rf->mozembed),
- str,
- "text/html",
- encoding,
- base);
- if (strncmp(base, "file:///fake", 12))
- webkit_set_history(base);
+ wknet = g_new0(WEBKITNET, 1);
+ wknet->base = base;
+ wknet->encoding = encoding;
+ wknet->str = str;
+ wknet->cb = rss_webkit_load_string;
+ proxify_webkit_session_async(proxy, wknet);
+#endif
#endif
break;
}
@@ -3658,7 +3670,7 @@ finish_website (SoupSession *soup_sess, SoupMessage *msg, gpointer user_data)
browser_write(
tmsg, strlen(tmsg),
(gchar *)"file:///fakefile#index");
- g_free(tmsg);
+ //g_free(tmsg);
if (ub->create) {
//stream remove
#if (DATASERVER_VERSION >= 2033001)
@@ -3687,7 +3699,7 @@ finish_website (SoupSession *soup_sess, SoupMessage *msg, gpointer user_data)
camel_object_unref(ub->stream);
#endif
}
- str = (response->str);
+ str = g_strdup(response->str);
len = strlen(response->str);
*str+= browser_fill;
len-= browser_fill;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]