pidgin/pidgin

Port some of gg to libsoup3

19 months ago, Elliott Sales de Andrade
64e455cfb6b4
Parents 11e7400101d2
Children 6009bf441ef5
Port some of gg to libsoup3

This does not do the file transfer stuff as I'm not entirely sure of the flow yet, and also don't know how best to do libsoup3 for streaming uploads.

I did add a `cancellable` to the file transfer code though, to be used later.

Testing Done:
Compiled with soup2 and with soup3.

Reviewed at https://reviews.imfreedom.org/r/2011/
--- a/libpurple/protocols/gg/avatar.c Thu Nov 03 03:27:07 2022 -0500
+++ b/libpurple/protocols/gg/avatar.c Thu Nov 03 22:51:47 2022 -0500
@@ -48,6 +48,7 @@
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 @@
}
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 @@
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 @@
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 @@
*/
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 @@
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);
}
--- a/libpurple/protocols/gg/edisc.c Thu Nov 03 03:27:07 2022 -0500
+++ b/libpurple/protocols/gg/edisc.c Thu Nov 03 22:51:47 2022 -0500
@@ -65,6 +65,9 @@
struct _GGPXfer
{
PurpleXfer parent;
+#if SOUP_MAJOR_VERSION >= 3
+ GCancellable *cancellable;
+#endif
gchar *filename;
gchar *ticket_id;
@@ -1150,7 +1153,9 @@
static void
ggp_xfer_init(GGPXfer *xfer) {
-
+#if SOUP_MAJOR_VERSION >= 3
+ xfer->cancellable = g_cancellable_new();
+#endif
}
static void
@@ -1161,8 +1166,13 @@
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,
--- a/libpurple/protocols/gg/oauth/oauth-purple.c Thu Nov 03 03:27:07 2022 -0500
+++ b/libpurple/protocols/gg/oauth/oauth-purple.c Thu Nov 03 22:51:47 2022 -0500
@@ -41,6 +41,7 @@
typedef struct
{
+ SoupMessage *msg;
PurpleConnection *gc;
ggp_oauth_request_cb callback;
gpointer user_data;
@@ -52,6 +53,7 @@
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_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 @@
}
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 @@
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 @@
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 @@
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 @@
"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 @@
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);
}
--- a/libpurple/protocols/gg/pubdir-prpl.c Thu Nov 03 03:27:07 2022 -0500
+++ b/libpurple/protocols/gg/pubdir-prpl.c Thu Nov 03 22:51:47 2022 -0500
@@ -139,26 +139,37 @@
}
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 @@
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 @@
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 @@
******************************************************************************/
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 @@
"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);