/pidgin/main: 8d0979967d05: HTTP: removing extra yahoo HTTP impl...

Tomasz Wasilczyk tomkiewicz at cpw.pidgin.im
Fri Aug 9 06:57:37 EDT 2013


Changeset: 8d0979967d05b0f05b12c44eafd3b105fe1731cb
Author:	 Tomasz Wasilczyk <tomkiewicz at cpw.pidgin.im>
Date:	 2013-08-09 12:57 +0200
Branch:	 default
URL: https://hg.pidgin.im/pidgin/main/rev/8d0979967d05

Description:

HTTP: removing extra yahoo HTTP implementations - file transfer (and small improvements to libpurple http and ft code)

diffstat:

 libpurple/ft.c                             |   113 +-
 libpurple/ft.h                             |    13 +
 libpurple/http.c                           |    51 +-
 libpurple/protocols/jabber/oob.c           |     1 +
 libpurple/protocols/yahoo/libyahoo.c       |     3 -
 libpurple/protocols/yahoo/libyahoojp.c     |     3 -
 libpurple/protocols/yahoo/libymsg.c        |     4 +-
 libpurple/protocols/yahoo/libymsg.h        |     1 -
 libpurple/protocols/yahoo/yahoo_filexfer.c |  1448 +++++----------------------
 libpurple/protocols/yahoo/yahoo_filexfer.h |     5 -
 libpurple/protocols/yahoo/yahoo_picture.c  |     5 +-
 11 files changed, 419 insertions(+), 1228 deletions(-)

diffs (truncated from 2128 to 300 lines):

diff --git a/libpurple/ft.c b/libpurple/ft.c
--- a/libpurple/ft.c
+++ b/libpurple/ft.c
@@ -1159,14 +1159,22 @@ purple_xfer_write_file(PurpleXfer *xfer,
 
 	if (fs_known && size > purple_xfer_get_bytes_remaining(xfer)) {
 		purple_debug_warning("filetransfer",
-			"Got too much data (truncating).\n");
+			"Got too much data (truncating at %" G_GOFFSET_FORMAT
+			").\n", purple_xfer_get_size(xfer));
 		size = purple_xfer_get_bytes_remaining(xfer);
 	}
 
 	if (ui_ops && ui_ops->ui_write)
 		wc = ui_ops->ui_write(xfer, buffer, size);
-	else
+	else {
+		if (xfer->dest_fp == NULL) {
+			purple_debug_error("filetransfer",
+				"File is not opened for writing\n");
+			purple_xfer_cancel_local(xfer);
+			return FALSE;
+		}
 		wc = fwrite(buffer, 1, size, xfer->dest_fp);
+	}
 
 	if (wc != size) {
 		purple_debug_error("filetransfer",
@@ -1181,6 +1189,57 @@ purple_xfer_write_file(PurpleXfer *xfer,
 	return TRUE;
 }
 
+gssize
+purple_xfer_read_file(PurpleXfer *xfer, guchar *buffer, gsize size)
+{
+	PurpleXferUiOps *ui_ops;
+	gssize got_len;
+
+	g_return_val_if_fail(xfer != NULL, FALSE);
+	g_return_val_if_fail(buffer != NULL, FALSE);
+
+	ui_ops = purple_xfer_get_ui_ops(xfer);
+
+	if (ui_ops && ui_ops->ui_read) {
+		guchar *buffer_got = NULL;
+
+		got_len = ui_ops->ui_read(xfer, &buffer_got, size);
+
+		if (got_len > size) {
+			g_free(buffer_got);
+			purple_debug_error("filetransfer",
+				"Got too much data from UI.\n");
+			purple_xfer_cancel_local(xfer);
+			return -1;
+		}
+
+		if (got_len > 0)
+			memcpy(buffer, buffer_got, got_len);
+		g_free(buffer_got);
+	} else {
+		if (xfer->dest_fp == NULL) {
+			purple_debug_error("filetransfer",
+				"File is not opened for reading\n");
+			purple_xfer_cancel_local(xfer);
+			return -1;
+		}
+		got_len = fread(buffer, 1, size, xfer->dest_fp);
+		if (got_len != size && ferror(xfer->dest_fp)) {
+			purple_debug_error("filetransfer",
+				"Unable to read file.\n");
+			purple_xfer_cancel_local(xfer);
+			return -1;
+		}
+	}
+
+	if (got_len > 0) {
+		purple_xfer_set_bytes_sent(xfer,
+			purple_xfer_get_bytes_sent(xfer) + got_len);
+	}
+
+	return got_len;
+}
+
 static void
 do_transfer(PurpleXfer *xfer)
 {
@@ -1207,7 +1266,7 @@ do_transfer(PurpleXfer *xfer)
 			return;
 		}
 	} else if (xfer->type == PURPLE_XFER_SEND) {
-		size_t result = 0;
+		gssize result = 0;
 		size_t s = MIN(purple_xfer_get_bytes_remaining(xfer), xfer->current_buffer_size);
 		PurpleXferPrivData *priv = g_hash_table_lookup(xfers_data, xfer);
 		gboolean read = TRUE;
@@ -1232,40 +1291,26 @@ do_transfer(PurpleXfer *xfer)
 		}
 
 		if (read) {
-			if (ui_ops && ui_ops->ui_read) {
-				gssize tmp = ui_ops->ui_read(xfer, &buffer, s);
-				if (tmp == 0) {
-					/*
-					 * The UI claimed it was ready, but didn't have any data for
-					 * us...  It will call purple_xfer_ui_ready when ready, which
-					 * sets back up this watcher.
-					 */
-					if (xfer->watcher != 0) {
-						purple_input_remove(xfer->watcher);
-						xfer->watcher = 0;
-					}
-
-					/* Need to indicate the prpl is still ready... */
-					priv->ready |= PURPLE_XFER_READY_PRPL;
-
-					g_return_if_reached();
-				} else if (tmp < 0) {
-					purple_debug_error("filetransfer", "Unable to read whole buffer.\n");
-					purple_xfer_cancel_local(xfer);
-					return;
+			buffer = g_new(guchar, s);
+			result = purple_xfer_read_file(xfer, buffer, s);
+			if (result == 0) {
+				/*
+				 * The UI claimed it was ready, but didn't have any data for
+				 * us...  It will call purple_xfer_ui_ready when ready, which
+				 * sets back up this watcher.
+				 */
+				if (xfer->watcher != 0) {
+					purple_input_remove(xfer->watcher);
+					xfer->watcher = 0;
 				}
 
-				result = tmp;
-			} else {
-				buffer = g_malloc(s);
-				result = fread(buffer, 1, s, xfer->dest_fp);
-				if (result != s) {
-					purple_debug_error("filetransfer", "Unable to read whole buffer.\n");
-					purple_xfer_cancel_local(xfer);
-					g_free(buffer);
-					return;
-				}
+				/* Need to indicate the prpl is still ready... */
+				priv->ready |= PURPLE_XFER_READY_PRPL;
+
+				g_return_if_reached();
 			}
+			if (result < 0)
+				return;
 		}
 
 		if (priv->buffer) {
diff --git a/libpurple/ft.h b/libpurple/ft.h
--- a/libpurple/ft.h
+++ b/libpurple/ft.h
@@ -641,6 +641,19 @@ gboolean
 purple_xfer_write_file(PurpleXfer *xfer, const guchar *buffer, gsize size);
 
 /**
+ * Writes chunk of file being sent.
+ *
+ * @param xfer   The file transfer.
+ * @param buffer The buffer to write the data to.
+ * @param size   The size of buffer.
+ *
+ * @return Number of bytes written (0 means, the device is busy), or -1 on
+ *         failure.
+ */
+gssize
+purple_xfer_read_file(PurpleXfer *xfer, guchar *buffer, gsize size);
+
+/**
  * Starts a file transfer.
  *
  * Either @a fd must be specified <i>or</i> @a ip and @a port on a
diff --git a/libpurple/http.c b/libpurple/http.c
--- a/libpurple/http.c
+++ b/libpurple/http.c
@@ -868,18 +868,18 @@ static gboolean _purple_http_recv_header
 		hdrline[hdrline_len] = '\0';
 
 		if (hdrline[0] == '\0') {
-			if (!hc->main_header_got && hc->is_keepalive) {
-				if (purple_debug_is_verbose()) {
+			if (!hc->main_header_got) {
+				if (purple_debug_is_verbose() &&
+					hc->is_keepalive)
+				{
 					purple_debug_misc("http", "Got keep-"
 						"alive terminator from previous"
 						" request\n");
+				} else {
+					purple_debug_warning("http", "Got empty"
+						" line at the beginning - this "
+						"may be a HTTP server quirk\n");
 				}
-			} else if (!hc->main_header_got) {
-				hc->response->code = 0;
-				purple_debug_warning("http",
-					"Main header not present\n");
-				_purple_http_error(hc, _("Error parsing HTTP"));
-				return FALSE;
 			} else /* hc->main_header_got */ {
 				hc->headers_got = TRUE;
 				if (purple_debug_is_verbose()) {
@@ -939,6 +939,8 @@ static gboolean _purple_http_recv_body_d
 	}
 	if (hc->request->max_length >= 0) {
 		if (hc->length_got + len > hc->request->max_length) {
+			purple_debug_warning("http",
+				"Maximum length exceeded, truncating\n");
 			len = hc->request->max_length - hc->length_got;
 			hc->length_expected = hc->request->max_length;
 		}
@@ -1086,6 +1088,12 @@ static gboolean _purple_http_recv_loopbo
 
 	/* EOF */
 	if (len == 0) {
+		if (hc->request->max_length == 0) {
+			/* It's definitely YHttpServer quirk. */
+			purple_debug_warning("http", "Got EOF, but no data was "
+				"expected (this may be a server quirk)\n");
+			hc->length_expected = hc->length_got;
+		}
 		if (hc->length_expected >= 0 &&
 			hc->length_got < hc->length_expected) {
 			purple_debug_warning("http", "No more data while reading"
@@ -1101,10 +1109,21 @@ static gboolean _purple_http_recv_loopbo
 			purple_http_conn_retry(hc);
 			return FALSE;
 		} else {
-			purple_debug_warning("http", "No more data while "
-				"parsing headers\n");
-			_purple_http_error(hc, _("Error parsing HTTP"));
-			return FALSE;
+			if (g_ascii_strcasecmp(purple_http_headers_get(
+				hc->response->headers, "Server"),
+				"YHttpServer") == 0)
+			{
+				purple_debug_warning("http", "No more data "
+					"while parsing headers (YHttpServer "
+					"quirk)\n");
+				hc->headers_got = TRUE;
+				hc->length_expected = hc->length_got = 0;
+			} else {
+				purple_debug_warning("http", "No more data "
+					"while parsing headers\n");
+				_purple_http_error(hc, _("Error parsing HTTP"));
+				return FALSE;
+			}
 		}
 	}
 
@@ -2252,13 +2271,17 @@ purple_http_keepalive_pool_release(Purpl
 	hs->is_busy = FALSE;
 	host = hs->host;
 
+	if (host == NULL) {
+		purple_http_socket_close_free(hs);
+		return;
+	}
+
 	if (invalidate) {
 		host->sockets = g_slist_remove(host->sockets, hs);
 		purple_http_socket_close_free(hs);
 	}
 
-	if (host != NULL)
-		purple_http_keepalive_host_process_queue(host);
+	purple_http_keepalive_host_process_queue(host);
 }
 
 void
diff --git a/libpurple/protocols/jabber/oob.c b/libpurple/protocols/jabber/oob.c
--- a/libpurple/protocols/jabber/oob.c
+++ b/libpurple/protocols/jabber/oob.c
@@ -122,6 +122,7 @@ static void jabber_oob_xfer_start(Purple
 	JabberOOBXfer *jox = purple_xfer_get_protocol_data(xfer);
 
 	req = purple_http_request_new(jox->url);
+	purple_http_request_set_timeout(req, -1);
 	purple_http_request_set_max_len(req, -1);
 	purple_http_request_set_response_writer(req, jabber_oob_xfer_writer,
 		xfer);
diff --git a/libpurple/protocols/yahoo/libyahoo.c b/libpurple/protocols/yahoo/libyahoo.c
--- a/libpurple/protocols/yahoo/libyahoo.c
+++ b/libpurple/protocols/yahoo/libyahoo.c
@@ -312,9 +312,6 @@ init_plugin(PurplePlugin *plugin)
 	option = purple_account_option_string_new(_("File transfer server"), "xfer_host", YAHOO_XFER_HOST);
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
 
-	option = purple_account_option_int_new(_("File transfer port"), "xfer_port", YAHOO_XFER_PORT);
-	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
-
 	option = purple_account_option_string_new(_("Chat room locale"), "room_list_locale", YAHOO_ROOMLIST_LOCALE);
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
 
diff --git a/libpurple/protocols/yahoo/libyahoojp.c b/libpurple/protocols/yahoo/libyahoojp.c
--- a/libpurple/protocols/yahoo/libyahoojp.c



More information about the Commits mailing list