# HG changeset patch
# Node ID 580515195dd7
# Parent  83ade55715e2
diff --git a/libpurple/protocols/gg/avatar.c b/libpurple/protocols/gg/avatar.c
--- a/libpurple/protocols/gg/avatar.c
+++ b/libpurple/protocols/gg/avatar.c
@@ -48,6 +48,7 @@ typedef struct
 	uin_t uin;
 	time_t timestamp;
 	PurpleConnection *gc;
+	SoupMessage *msg;
 } ggp_avatar_buddy_update_req;
 
 #define GGP_AVATAR_BUDDY_URL "http://avatars.gg.pl/%u/s,big"
@@ -100,26 +101,37 @@ void ggp_avatar_buddy_remove(PurpleConne
 }
 
 static void
-ggp_avatar_buddy_update_received(G_GNUC_UNUSED SoupSession *session,
-                                 SoupMessage *msg, gpointer _pending_update)
+ggp_avatar_buddy_update_received(GObject *source, GAsyncResult *result,
+                                 gpointer data)
 {
-	ggp_avatar_buddy_update_req *pending_update = _pending_update;
+	ggp_avatar_buddy_update_req *pending_update = data;
+	GBytes *response_body = NULL;
+	GError *error = NULL;
+	const char *error_message = NULL;
 	PurpleBuddy *buddy;
 	PurpleAccount *account;
 	PurpleConnection *gc = pending_update->gc;
 	gchar timestamp_str[20];
-	const gchar *got_data;
-	size_t got_len;
+	char *got_data = NULL;
+	gsize got_len = 0;
 
 	PURPLE_ASSERT_CONNECTION_IS_VALID(gc);
 
-	if (!SOUP_STATUS_IS_SUCCESSFUL(soup_message_get_status(msg))) {
+	if(SOUP_STATUS_IS_SUCCESSFUL(soup_message_get_status(pending_update->msg))) {
+		response_body = soup_session_send_and_read_finish(SOUP_SESSION(source),
+		                                                  result, &error);
+		error_message = error != NULL ? error->message : "unknown";
+	} else {
+		error_message = soup_message_get_reason_phrase(pending_update->msg);
+	}
+	if(response_body == NULL) {
 		purple_debug_error("gg",
 		                   "ggp_avatar_buddy_update_received: bad response "
 		                   "while getting avatar for %u: %s",
-		                   pending_update->uin,
-		                   soup_message_get_reason_phrase(msg));
+		                   pending_update->uin, error_message);
+		g_object_unref(pending_update->msg);
 		g_free(pending_update);
+		g_clear_error(&error);
 		return;
 	}
 
@@ -131,22 +143,22 @@ ggp_avatar_buddy_update_received(G_GNUC_
 		purple_debug_warning(
 		        "gg", "ggp_avatar_buddy_update_received: buddy %u disappeared",
 		        pending_update->uin);
+		g_object_unref(pending_update->msg);
 		g_free(pending_update);
 		return;
 	}
 
 	g_snprintf(timestamp_str, sizeof(timestamp_str), "%lu",
 	           pending_update->timestamp);
-	got_data = msg->response_body->data;
-	got_len = msg->response_body->length;
+	got_data = g_bytes_unref_to_data(response_body, &got_len);
 	purple_buddy_icons_set_for_user(account, purple_buddy_get_name(buddy),
-	                                g_memdup2(got_data, got_len), got_len,
-	                                timestamp_str);
+	                                got_data, got_len, timestamp_str);
 
 	purple_debug_info("gg",
 	                  "ggp_avatar_buddy_update_received: got avatar for buddy "
 	                  "%u [ts=%lu]",
 	                  pending_update->uin, pending_update->timestamp);
+	g_object_unref(pending_update->msg);
 	g_free(pending_update);
 }
 
@@ -214,13 +226,14 @@ ggp_avatar_buddy_update(PurpleConnection
 	pending_update->gc = gc;
 
 	url = g_strdup_printf(GGP_AVATAR_BUDDY_URL, pending_update->uin);
-	req = soup_message_new("GET", url);
+	pending_update->msg = req = soup_message_new("GET", url);
 	g_free(url);
 	soup_message_headers_replace(soup_message_get_request_headers(req),
 	                             "User-Agent", GGP_AVATAR_USERAGENT);
 	// purple_http_request_set_max_len(req, GGP_AVATAR_SIZE_MAX);
-	soup_session_queue_message(
-	        info->http, req, ggp_avatar_buddy_update_received, pending_update);
+	soup_session_send_and_read_async(info->http, req, G_PRIORITY_DEFAULT, NULL,
+	                                 ggp_avatar_buddy_update_received,
+	                                 pending_update);
 }
 
 /*******************************************************************************
@@ -236,20 +249,33 @@ ggp_avatar_buddy_update(PurpleConnection
  */
 
 static void
-ggp_avatar_own_sent(G_GNUC_UNUSED SoupSession *session, SoupMessage *msg,
-                    gpointer user_data)
-{
-	PurpleConnection *gc = user_data;
-
-	PURPLE_ASSERT_CONNECTION_IS_VALID(gc);
+ggp_avatar_own_sent(GObject *source, GAsyncResult *result, gpointer data) {
+	SoupMessage *msg = data;
+	GBytes *response_body = NULL;
+	GError *error = NULL;
+	const char *buffer = NULL;
+	gsize size = 0;
 
 	if (!SOUP_STATUS_IS_SUCCESSFUL(soup_message_get_status(msg))) {
-		purple_debug_error("gg", "ggp_avatar_own_sent: avatar not sent. %s\n",
+		purple_debug_error("gg", "ggp_avatar_own_sent: avatar not sent. %s",
 		                   soup_message_get_reason_phrase(msg));
+		g_object_unref(msg);
 		return;
 	}
-	purple_debug_info("gg", "ggp_avatar_own_sent: %s\n",
-	                  msg->response_body->data);
+	g_clear_object(&msg);
+
+	response_body = soup_session_send_and_read_finish(SOUP_SESSION(source),
+	                                                  result, &error);
+	if(response_body == NULL) {
+		purple_debug_error("gg", "ggp_avatar_own_sent: avatar not sent. %s",
+		                   error->message);
+		g_error_free(error);
+		return;
+	}
+
+	buffer = g_bytes_get_data(response_body, &size);
+	purple_debug_info("gg", "ggp_avatar_own_sent: %*s", (int)size, buffer);
+	g_bytes_unref(response_body);
 }
 
 static void
@@ -286,7 +312,8 @@ ggp_avatar_own_got_token(PurpleConnectio
 	headers = soup_message_get_request_headers(req);
 	soup_message_headers_replace(headers, "Authorization", token);
 	soup_message_headers_replace(headers, "From", "avatars to avatars");
-	soup_session_queue_message(info->http, req, ggp_avatar_own_sent, gc);
+	soup_session_send_and_read_async(info->http, req, G_PRIORITY_DEFAULT, NULL,
+	                                 ggp_avatar_own_sent, req);
 	g_free(img_data);
 	g_free(uin_str);
 }
diff --git a/libpurple/protocols/gg/edisc.c b/libpurple/protocols/gg/edisc.c
--- a/libpurple/protocols/gg/edisc.c
+++ b/libpurple/protocols/gg/edisc.c
@@ -65,6 +65,9 @@ struct _ggp_edisc_session_data
 struct _GGPXfer
 {
 	PurpleXfer parent;
+#if SOUP_MAJOR_VERSION >= 3
+	GCancellable *cancellable;
+#endif
 
 	gchar *filename;
 	gchar *ticket_id;
@@ -1150,7 +1153,9 @@ ggp_xfer_start(PurpleXfer *xfer) {
 
 static void
 ggp_xfer_init(GGPXfer *xfer) {
-
+#if SOUP_MAJOR_VERSION >= 3
+	xfer->cancellable = g_cancellable_new();
+#endif
 }
 
 static void
@@ -1161,8 +1166,13 @@ ggp_xfer_finalize(GObject *obj) {
 	sdata = ggp_edisc_get_sdata(edisc_xfer->gc);
 
 	g_free(edisc_xfer->filename);
+#if SOUP_MAJOR_VERSION >= 3
+	g_cancellable_cancel(edisc_xfer->cancellable);
+	g_clear_object(&edisc_xfer->cancellable);
+#else
 	soup_session_cancel_message(sdata->session, edisc_xfer->msg,
 	                            SOUP_STATUS_CANCELLED);
+#endif
 
 	if (edisc_xfer->ticket_id != NULL) {
 		g_hash_table_remove(sdata->xfers_initialized,
diff --git a/libpurple/protocols/gg/oauth/oauth-purple.c b/libpurple/protocols/gg/oauth/oauth-purple.c
--- a/libpurple/protocols/gg/oauth/oauth-purple.c
+++ b/libpurple/protocols/gg/oauth/oauth-purple.c
@@ -41,6 +41,7 @@
 
 typedef struct
 {
+	SoupMessage *msg;
 	PurpleConnection *gc;
 	ggp_oauth_request_cb callback;
 	gpointer user_data;
@@ -52,6 +53,7 @@ typedef struct
 
 static void ggp_oauth_data_free(ggp_oauth_data *data)
 {
+	g_object_unref(data->msg);
 	g_free(data->token);
 	g_free(data->token_secret);
 	g_free(data->sign_method);
@@ -60,16 +62,32 @@ static void ggp_oauth_data_free(ggp_oaut
 }
 
 static void
-ggp_oauth_access_token_got(G_GNUC_UNUSED SoupSession *session, SoupMessage *msg,
+ggp_oauth_access_token_got(GObject *source, GAsyncResult *result,
                            gpointer user_data)
 {
 	ggp_oauth_data *data = user_data;
+	GBytes *response_body = NULL;
+	const char *buffer = NULL;
+	gsize size = 0;
 	gchar *token = NULL, *token_secret = NULL;
 	PurpleXmlNode *xml;
 	gboolean succ = TRUE;
+	GError *error = NULL;
 
-	xml = purple_xmlnode_from_str(msg->response_body->data,
-	                              msg->response_body->length);
+	response_body = soup_session_send_and_read_finish(SOUP_SESSION(source),
+	                                                  result, &error);
+	if(response_body == NULL) {
+		purple_debug_error("gg", "ggp_oauth_access_token_got: failed: %s",
+		                   error->message);
+		ggp_oauth_data_free(data);
+		g_error_free(error);
+		return;
+	}
+
+	buffer = g_bytes_get_data(response_body, &size);
+	xml = purple_xmlnode_from_str(buffer, size);
+	g_bytes_unref(response_body);
+
 	if (xml == NULL) {
 		purple_debug_error("gg", "ggp_oauth_access_token_got: invalid xml");
 		ggp_oauth_data_free(data);
@@ -114,13 +132,14 @@ ggp_oauth_access_token_got(G_GNUC_UNUSED
 }
 
 static void
-ggp_oauth_authorization_done(SoupSession *session, SoupMessage *msg,
+ggp_oauth_authorization_done(GObject *source, GAsyncResult *result,
                              gpointer user_data)
 {
 	ggp_oauth_data *data = user_data;
 	PurpleAccount *account;
 	SoupStatus status_code;
 	char *auth;
+	SoupMessage *msg = NULL;
 	const char *method = "POST";
 	const char *url = "http://api.gadu-gadu.pl/access_token";
 
@@ -128,7 +147,7 @@ ggp_oauth_authorization_done(SoupSession
 
 	account = purple_connection_get_account(data->gc);
 
-	status_code = soup_message_get_status(msg);
+	status_code = soup_message_get_status(data->msg);
 	if (status_code != 302) {
 		purple_debug_error("gg",
 		                   "ggp_oauth_authorization_done: failed (code = %d)",
@@ -145,42 +164,62 @@ ggp_oauth_authorization_done(SoupSession
 	                                purple_connection_get_password(data->gc),
 	                                data->token, data->token_secret);
 
-	msg = soup_message_new(method, url);
+	g_clear_object(&data->msg);
+	data->msg = msg = soup_message_new(method, url);
 	// purple_http_request_set_max_len(req, GGP_OAUTH_RESPONSE_MAX);
 	soup_message_headers_replace(soup_message_get_request_headers(msg),
 	                             "Authorization", auth);
-	soup_session_queue_message(session, msg, ggp_oauth_access_token_got, data);
+	soup_session_send_and_read_async(SOUP_SESSION(source), msg,
+	                                 G_PRIORITY_DEFAULT, NULL,
+	                                 ggp_oauth_access_token_got, data);
 
 	g_free(auth);
 }
 
 static void
-ggp_oauth_request_token_got(SoupSession *session, SoupMessage *msg,
+ggp_oauth_request_token_got(GObject *source, GAsyncResult *result,
                             gpointer user_data)
 {
+	SoupSession *session = SOUP_SESSION(source);
 	ggp_oauth_data *data = user_data;
+	GBytes *response_body = NULL;
+	const char *buffer = NULL;
+	gsize size = 0;
 	PurpleAccount *account;
 	PurpleXmlNode *xml;
+	SoupMessage *msg = NULL;
 	gchar *request_data;
 	GBytes *body = NULL;
 	gboolean succ = TRUE;
+	GError *error = NULL;
 
 	PURPLE_ASSERT_CONNECTION_IS_VALID(data->gc);
 
 	account = purple_connection_get_account(data->gc);
 
-	if (!SOUP_STATUS_IS_SUCCESSFUL(soup_message_get_status(msg))) {
+	if(!SOUP_STATUS_IS_SUCCESSFUL(soup_message_get_status(data->msg))) {
 		purple_debug_error("gg", "ggp_oauth_request_token_got: "
 			"requested token not received\n");
 		ggp_oauth_data_free(data);
 		return;
 	}
 
+	response_body = soup_session_send_and_read_finish(session, result, &error);
+	if(response_body == NULL) {
+		purple_debug_error("gg", "ggp_oauth_access_token_got: failed: %s",
+		                   error->message);
+		ggp_oauth_data_free(data);
+		g_error_free(error);
+		return;
+	}
+
 	purple_debug_misc("gg", "ggp_oauth_request_token_got: "
 		"got request token, doing authorization...\n");
 
-	xml = purple_xmlnode_from_str(msg->response_body->data,
-	                              msg->response_body->length);
+	buffer = g_bytes_get_data(response_body, &size);
+	xml = purple_xmlnode_from_str(buffer, size);
+	g_bytes_unref(response_body);
+
 	if (xml == NULL) {
 		purple_debug_error("gg", "ggp_oauth_request_token_got: "
 			"invalid xml\n");
@@ -205,7 +244,9 @@ ggp_oauth_request_token_got(SoupSession 
 		purple_account_get_username(account),
 		purple_connection_get_password(data->gc));
 
-	msg = soup_message_new("POST", "https://login.gadu-gadu.pl/authorize");
+	g_clear_object(&data->msg);
+	data->msg = msg = soup_message_new("POST",
+	                                   "https://login.gadu-gadu.pl/authorize");
 	// purple_http_request_set_max_len(msg, GGP_OAUTH_RESPONSE_MAX);
 	/* we don't need any results, nor 302 redirection */
 	soup_message_set_flags(msg, SOUP_MESSAGE_NO_REDIRECT);
@@ -214,8 +255,8 @@ ggp_oauth_request_token_got(SoupSession 
 	                                         "application/x-www-form-urlencoded",
 	                                         body);
 	g_bytes_unref(body);
-	soup_session_queue_message(session, msg, ggp_oauth_authorization_done,
-	                           data);
+	soup_session_send_and_read_async(session, msg, G_PRIORITY_DEFAULT, NULL,
+	                                 ggp_oauth_authorization_done, data);
 }
 
 void
@@ -244,12 +285,12 @@ ggp_oauth_request(PurpleConnection *gc, 
 	data->sign_method = g_strdup(sign_method);
 	data->sign_url = g_strdup(sign_url);
 
-	msg = soup_message_new(method, url);
+	data->msg = msg = soup_message_new(method, url);
 	// purple_http_request_set_max_len(req, GGP_OAUTH_RESPONSE_MAX);
 	soup_message_headers_replace(soup_message_get_request_headers(msg),
 	                             "Authorization", auth);
-	soup_session_queue_message(info->http, msg, ggp_oauth_request_token_got,
-	                           data);
+	soup_session_send_and_read_async(info->http, msg, G_PRIORITY_DEFAULT, NULL,
+	                                 ggp_oauth_request_token_got, data);
 
 	g_free(auth);
 }
diff --git a/libpurple/protocols/gg/pubdir-prpl.c b/libpurple/protocols/gg/pubdir-prpl.c
--- a/libpurple/protocols/gg/pubdir-prpl.c
+++ b/libpurple/protocols/gg/pubdir-prpl.c
@@ -139,26 +139,37 @@ ggp_pubdir_request_free(ggp_pubdir_reque
 }
 
 static void
-ggp_pubdir_got_data(G_GNUC_UNUSED SoupSession *session, SoupMessage *msg,
-                    gpointer _request)
-{
-	ggp_pubdir_request *request = _request;
+ggp_pubdir_got_data(GObject *source, GAsyncResult *result, gpointer data) {
+	ggp_pubdir_request *request = data;
 	PurpleConnection *gc = request->gc;
+	GBytes *response_body = NULL;
 	gboolean succ = TRUE;
 	PurpleXmlNode *xml;
-	const gchar *xml_raw;
+	const char *xml_raw = NULL;
+	gsize xml_size = 0;
 	unsigned int status, next_offset;
 	int record_count, i;
 	ggp_pubdir_record *records;
+	GError *error = NULL;
 
-	xml_raw = msg->response_body->data;
+	response_body = soup_session_send_and_read_finish(SOUP_SESSION(source),
+	                                                  result, &error);
+	if (response_body == NULL) {
+		purple_debug_error("gg", "ggp_pubdir_got_data: %s", error->message);
+		request->cb(gc, -1, NULL, 0, request->user_data);
+		ggp_pubdir_request_free(request);
+		g_error_free(error);
+		return;
+	}
+
+	xml_raw = g_bytes_unref_to_data(response_body, &xml_size);
 
 	if (purple_debug_is_verbose() && purple_debug_is_unsafe()) {
-		purple_debug_misc("gg", "ggp_pubdir_got_data: xml=[%s]\n",
-			xml_raw);
+		purple_debug_misc("gg", "ggp_pubdir_got_data: xml=[%*s]",
+		                  (int)xml_size, xml_raw);
 	}
 
-	xml = purple_xmlnode_from_str(xml_raw, -1);
+	xml = purple_xmlnode_from_str(xml_raw, xml_size);
 	if (xml == NULL) {
 		purple_debug_error("gg", "ggp_pubdir_got_data: "
 			"invalid xml\n");
@@ -299,7 +310,9 @@ ggp_pubdir_get_info_got_token(PurpleConn
 	g_free(url);
 	soup_message_headers_replace(soup_message_get_request_headers(msg),
 	                             "Authorization", token);
-	soup_session_queue_message(info->http, msg, ggp_pubdir_got_data, request);
+	soup_session_send_and_read_async(info->http, msg, G_PRIORITY_DEFAULT, NULL,
+	                                 ggp_pubdir_got_data, request);
+	g_object_unref(msg);
 }
 
 void
@@ -540,8 +553,10 @@ static void ggp_pubdir_search_got_token(
 	msg = soup_message_new("GET", url);
 	soup_message_headers_replace(soup_message_get_request_headers(msg),
 	                             "Authorization", token);
-	soup_session_queue_message(info->http, msg, ggp_pubdir_got_data, request);
+	soup_session_send_and_read_async(info->http, msg, G_PRIORITY_DEFAULT, NULL,
+	                                 ggp_pubdir_got_data, request);
 
+	g_object_unref(msg);
 	g_free(url);
 	g_free(query);
 }
@@ -764,19 +779,40 @@ ggp_pubdir_search(PurpleConnection *gc, 
  ******************************************************************************/
 
 static void
-ggp_pubdir_set_info_got_response(G_GNUC_UNUSED SoupSession *session,
-                                 SoupMessage *msg, gpointer user_data)
+ggp_pubdir_set_info_got_response(GObject *source, GAsyncResult *result,
+                                 gpointer data)
 {
+	SoupMessage *msg = data;
+	GBytes *response_body = NULL;
+	const char *buffer = NULL;
+	gsize size = 0;
+	GError *error = NULL;
+
 	if (!SOUP_STATUS_IS_SUCCESSFUL(soup_message_get_status(msg))) {
 		purple_debug_error("gg", "ggp_pubdir_set_info_got_response: failed");
+		g_object_unref(msg);
+		return;
+	}
+	g_clear_object(&msg);
+
+	response_body = soup_session_send_and_read_finish(SOUP_SESSION(source),
+	                                                  result, &error);
+	if (response_body == NULL) {
+		purple_debug_error("gg",
+		                   "ggp_pubdir_set_info_got_response: failed: %s",
+		                   error->message);
+		g_error_free(error);
 		return;
 	}
 
-	purple_debug_info("gg", "ggp_pubdir_set_info_got_response: [%s]",
-	                  msg->response_body->data);
+	buffer = g_bytes_get_data(response_body, &size);
+	purple_debug_info("gg", "ggp_pubdir_set_info_got_response: [%*s]",
+	                  (int)size, buffer);
 	/* <result><status>0</status></result> */
 
 	/* TODO: notify about failure */
+
+	g_bytes_unref(response_body);
 }
 
 static void ggp_pubdir_set_info_got_token(PurpleConnection *gc,
@@ -841,8 +877,8 @@ static void ggp_pubdir_set_info_got_toke
 	                                         "application/x-www-form-urlencoded",
 	                                         body);
 	g_bytes_unref(body);
-	soup_session_queue_message(info->http, msg,
-	                           ggp_pubdir_set_info_got_response, NULL);
+	soup_session_send_and_read_async(info->http, msg, G_PRIORITY_DEFAULT, NULL,
+	                                 ggp_pubdir_set_info_got_response, msg);
 
 	g_free(url);
 	ggp_pubdir_record_free(record, 1);
