Skip to content
This repository was archived by the owner on Sep 15, 2025. It is now read-only.

Commit fbbd4b1

Browse files
committed
Fix some memory leaks and premature transfer closure
1 parent 34779d7 commit fbbd4b1

File tree

1 file changed

+58
-42
lines changed

1 file changed

+58
-42
lines changed

src/jabber_http_file_upload.c

Lines changed: 58 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ typedef struct {
3636
gchar *passwd;
3737
} PurpleHttpURL;
3838

39-
4039
static inline PurpleHttpURL *purple_http_url_parse(const gchar *url) {
4140
PurpleHttpURL *ret = g_new0(PurpleHttpURL, 1);
4241
purple_url_parse(url, &(ret->host), &(ret->port), &(ret->path), &(ret->user), &(ret->passwd));
@@ -56,24 +55,41 @@ static inline void purple_http_url_free(PurpleHttpURL *phl) { g_free(phl->host);
5655

5756
static void jabber_hfu_http_read(gpointer user_data, PurpleSslConnection *ssl_connection, PurpleInputCondition cond)
5857
{
59-
gchar buf[1024];
58+
PurpleXfer *xfer = user_data;
59+
gchar buf[1024] = {0};
60+
61+
//Read the server buffer
62+
size_t rl = purple_ssl_read(ssl_connection, buf, 1024);
63+
purple_debug_info("jabber_http_upload", "Server file send response was %ld bytes: %s\n", rl, buf);
64+
65+
if(rl == (size_t)-1)
66+
return;
6067

61-
//Flush the server buffer
62-
purple_ssl_read(ssl_connection, buf, 1024);
63-
purple_debug_info("jabber_http_upload", "Server file send response was %s\n", buf);
68+
if ((purple_xfer_get_bytes_sent(xfer)) >= purple_xfer_get_size(xfer)) {
69+
// Looking for HTTP/1.1 201
70+
if(rl > 12 && g_str_has_prefix(buf, "HTTP/1.") && g_str_has_prefix(buf+8, " 20")) {
71+
// 20x statuses are good, should be 201 but who knows those servers
72+
purple_xfer_set_completed(xfer, TRUE);
73+
purple_xfer_end(xfer);
74+
return;
75+
}
76+
}
77+
// We've read everything it seems but didn't understand a word
78+
purple_xfer_cancel_remote(xfer);
79+
g_return_if_reached();
6480
}
6581

6682
static void jabber_hfu_http_send_connect_cb(gpointer data, PurpleSslConnection *ssl_connection, PurpleInputCondition cond)
6783
{
6884
PurpleHttpURL *httpurl;
69-
gchar *headers, *host, *path, *auth = NULL, *expire = NULL, *cookie = NULL;
85+
g_autofree gchar *headers, *auth = NULL, *expire = NULL, *cookie = NULL;
7086

7187
PurpleXfer *xfer = data;
7288
HFUXfer *hfux = purple_xfer_get_protocol_data(xfer);
7389
HFUJabberStreamData *js_data = hfux->js_data;
90+
g_autofree char *filemime = file_get_mime(purple_xfer_get_local_filename(xfer));
7491

7592
httpurl = purple_http_url_parse(hfux->put_url);
76-
path = purple_http_url_get_path(httpurl);
7793

7894
if (str_equal(js_data->ns, NS_HTTP_FILE_UPLOAD_V0)) {
7995
char *a = g_hash_table_lookup(hfux->put_headers, "Authorisation");
@@ -86,35 +102,30 @@ static void jabber_hfu_http_send_connect_cb(gpointer data, PurpleSslConnection *
86102
if(e)
87103
expire = g_strdup_printf("Expires: %s\r\n", e);
88104
}
89-
host = purple_http_url_get_host(httpurl);
90-
91105

92106
headers = g_strdup_printf("PUT /%s HTTP/1.0\r\n"
93107
"Connection: close\r\n"
94108
"Host: %s\r\n"
95109
"Content-Length: %" G_GSIZE_FORMAT "\r\n"
96-
"Content-Type: application/octet-stream\r\n"
110+
"Content-Type: %s\r\n"
97111
"User-Agent: libpurple\r\n"
98112
"%s%s%s\r\n",
99-
path, host, (gsize) purple_xfer_get_size(xfer),
113+
purple_http_url_get_path(httpurl),
114+
purple_http_url_get_host(httpurl),
115+
(gsize) purple_xfer_get_size(xfer),
116+
(filemime?:"application/octet-stream"),
100117
(auth?:""), (expire?:""), (cookie?:""));
101118

102-
g_free(auth);
103-
g_free(expire);
104-
g_free(cookie);
105-
106-
purple_ssl_write(ssl_connection, headers, strlen(headers));
107-
108119
hfux->ssl_conn = ssl_connection;
109120
purple_ssl_input_add(ssl_connection, jabber_hfu_http_read, xfer);
110121

122+
purple_ssl_write(ssl_connection, headers, strlen(headers));
123+
111124
purple_xfer_ref(xfer);
112125
purple_xfer_start(xfer, ssl_connection->fd, NULL, 0);
113126

114127
purple_xfer_prpl_ready(xfer);
115-
116-
g_free(headers);
117-
128+
purple_http_url_free(httpurl);
118129
}
119130

120131
static void jabber_hfu_http_error_connect_cb(PurpleSslConnection *ssl_connection, PurpleSslErrorType *error_type, gpointer data)
@@ -129,13 +140,13 @@ static void jabber_hfu_request_cb(JabberStream *js, const char *from,
129140
PurpleAccount *account;
130141
xmlnode *slot, *put, *get, *header = NULL;
131142
PurpleHttpURL *put_httpurl;
132-
gchar *put_host;
133143

134144
PurpleXfer *xfer = data;
135145
HFUXfer *hfux = purple_xfer_get_protocol_data(xfer);
136146
HFUJabberStreamData *js_data = hfux->js_data;
137147
account = purple_connection_get_account(js->gc);
138148

149+
139150
if(!(slot = xmlnode_get_child_with_namespace(packet, "slot", js_data->ns)))
140151
{
141152
purple_xfer_cancel_remote(xfer);
@@ -151,7 +162,7 @@ static void jabber_hfu_request_cb(JabberStream *js, const char *from,
151162
for (header = xmlnode_get_child(put, "header") ; header;
152163
header = xmlnode_get_next_twin(header))
153164
{
154-
g_hash_table_insert(hfux->put_headers, g_strdup(xmlnode_get_attrib(header, "name")), g_strdup(xmlnode_get_data(header)));
165+
g_hash_table_insert(hfux->put_headers, g_strdup(xmlnode_get_attrib(header, "name")), xmlnode_get_data(header));
155166
}
156167

157168
hfux->put_url = g_strdup(xmlnode_get_attrib(put, "url"));
@@ -164,9 +175,10 @@ static void jabber_hfu_request_cb(JabberStream *js, const char *from,
164175
}
165176

166177
put_httpurl = purple_http_url_parse(hfux->put_url);
167-
put_host = purple_http_url_get_host(put_httpurl);
168178

169-
purple_ssl_connect(account, put_host, purple_http_url_get_port(put_httpurl), jabber_hfu_http_send_connect_cb, (PurpleSslErrorFunction)jabber_hfu_http_error_connect_cb, xfer);
179+
g_debug("Connecting to %s:%d for %s", purple_http_url_get_host(put_httpurl), purple_http_url_get_port(put_httpurl), hfux->put_url);
180+
purple_ssl_connect(account, purple_http_url_get_host(put_httpurl), purple_http_url_get_port(put_httpurl),
181+
jabber_hfu_http_send_connect_cb, (PurpleSslErrorFunction)jabber_hfu_http_error_connect_cb, xfer);
170182

171183
purple_http_url_free(put_httpurl);
172184
}
@@ -177,15 +189,11 @@ static void jabber_hfu_xfer_free(PurpleXfer *xfer)
177189

178190
g_return_if_fail(hfux != NULL);
179191

180-
if (hfux->put_url)
181-
{
182-
g_free(hfux->put_url);
183-
}
192+
g_free(hfux->put_url);
193+
g_free(hfux->get_url);
184194

185-
if (hfux->get_url)
186-
{
187-
g_free(hfux->get_url);
188-
}
195+
if(hfux->put_headers)
196+
g_hash_table_destroy(hfux->put_headers);
189197

190198
if (hfux->ssl_conn)
191199
{
@@ -261,7 +269,8 @@ jabber_hfu_xmlnode_send_cb(PurpleConnection *gc, xmlnode **packet, gpointer null
261269
if (g_strcmp0 ((*packet)->name, "message") == 0) {
262270
xmlnode *node_body = xmlnode_get_child (*packet, "body");
263271
if (node_body) {
264-
HFUXfer *hfux = g_hash_table_lookup(ht_hfu_sending, xmlnode_get_data(node_body));
272+
g_autofree char *url = xmlnode_get_data(node_body);
273+
HFUXfer *hfux = g_hash_table_lookup(ht_hfu_sending, url);
265274
if(hfux) {
266275
xmlnode *x, *url;
267276
x = xmlnode_new_child (*packet, "x");
@@ -313,6 +322,7 @@ static void jabber_hfu_send_url_to_conv(PurpleXfer *xfer)
313322

314323
static void jabber_hfu_xfer_end(PurpleXfer *xfer)
315324
{
325+
g_debug("This is the end.");
316326
jabber_hfu_send_url_to_conv(xfer);
317327

318328
jabber_hfu_xfer_free(xfer);
@@ -336,21 +346,22 @@ static gssize jabber_hfu_xfer_write(const guchar *buffer, size_t len, PurpleXfer
336346

337347
if (tlen == -1)
338348
{
339-
if (purple_xfer_get_bytes_sent(xfer) >= purple_xfer_get_size(xfer))
340-
purple_xfer_set_completed(xfer, TRUE);
341-
342349
if ((errno != EAGAIN) && (errno != EINTR))
343350
return -1;
344351

345352
return 0;
346-
}
347-
348-
if ((purple_xfer_get_bytes_sent(xfer) + tlen) >= purple_xfer_get_size(xfer))
349-
purple_xfer_set_completed(xfer, TRUE);
353+
} else if ((purple_xfer_get_bytes_sent(xfer)+tlen) >= purple_xfer_get_size(xfer))
354+
xfer->status = PURPLE_XFER_STATUS_DONE; // sneaky cheat
350355

351356
return tlen;
352357
}
353358

359+
static void jabber_hfu_xfer_ack(PurpleXfer *xfer, const guchar *buffer, size_t len)
360+
{
361+
if (purple_xfer_is_completed(xfer))
362+
xfer->status = PURPLE_XFER_STATUS_STARTED; // hideous uncheat
363+
}
364+
354365
static void jabber_hfu_xfer_init(PurpleXfer *xfer)
355366
{
356367
HFUXfer *hfux = purple_xfer_get_protocol_data(xfer);
@@ -386,7 +397,6 @@ static void jabber_hfu_xfer_init(PurpleXfer *xfer)
386397
}
387398

388399

389-
390400
PurpleXfer *jabber_hfu_new_xfer(PurpleConnection *gc, const char *who)
391401
{
392402
JabberStream *js;
@@ -403,8 +413,9 @@ PurpleXfer *jabber_hfu_new_xfer(PurpleConnection *gc, const char *who)
403413

404414
purple_xfer_set_init_fnc(xfer, jabber_hfu_xfer_init);
405415
purple_xfer_set_cancel_send_fnc(xfer, jabber_hfu_xfer_cancel_send);
406-
purple_xfer_set_end_fnc(xfer, jabber_hfu_xfer_end);
407416
purple_xfer_set_write_fnc(xfer, jabber_hfu_xfer_write);
417+
purple_xfer_set_ack_fnc(xfer, jabber_hfu_xfer_ack);
418+
purple_xfer_set_end_fnc(xfer, jabber_hfu_xfer_end);
408419

409420
return xfer;
410421
}
@@ -498,6 +509,11 @@ static GList *jabber_hfu_blist_node_menu(PurpleBlistNode *node)
498509

499510
gboolean plugin_unload(PurplePlugin *plugin)
500511
{
512+
PurplePlugin *jabber_plugin = purple_plugins_find_with_id(JABBER_PLUGIN_ID);
513+
514+
PurplePluginProtocolInfo *jabber_protocol_info = PURPLE_PLUGIN_PROTOCOL_INFO(jabber_plugin);
515+
jabber_protocol_info->blist_node_menu = old_blist_node_menu;
516+
501517
purple_signals_disconnect_by_handle(plugin);
502518
g_hash_table_destroy(ht_hfu_sending);
503519
g_hash_table_destroy(HFUJabberStreamDataTable);

0 commit comments

Comments
 (0)