cpw.malu.xmpp.ibb_ft: b8684313: Trigger error callbacks when receiving a...
malu at pidgin.im
malu at pidgin.im
Tue Dec 16 14:20:57 EST 2008
-----------------------------------------------------------------
Revision: b86843136452cd6bd27f4efc1457e53e54108e6b
Ancestor: abd6f6bf550dcb19b801698437d489c72bc57e8f
Author: paul at aurich.com
Date: 2008-12-16T19:16:10
Branch: im.pidgin.cpw.malu.xmpp.ibb_ft
URL: http://d.pidgin.im/viewmtn/revision/info/b86843136452cd6bd27f4efc1457e53e54108e6b
Modified files:
libpurple/protocols/jabber/ibb.c
libpurple/protocols/jabber/ibb.h
libpurple/protocols/jabber/si.c
ChangeLog:
Trigger error callbacks when receiving a malformed-ish packet.
Clean up a few pieces of code. Use G_GSIZE_FORMAT like KingAnt showed me.
Don't crash if an iq packet doesn't contain the seq attribute.
Error check g_fopen()
Don't unref the PurpleXfer until after we've called some functions with it.
Not sure that could ever actually crash it (I didn't bother to run through
the ref-counts in my head to see if it would fail).
-------------- next part --------------
============================================================
--- libpurple/protocols/jabber/ibb.c 42480c415e75296057224652a814a660f766ea41
+++ libpurple/protocols/jabber/ibb.c 7886d3adb8b89894c2424858bf1727812f5d45db
@@ -14,9 +14,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301, USA
*/
-#include <glib.h>
-#include <string.h>
-
#include "internal.h"
#include "ibb.h"
#include "debug.h"
@@ -32,17 +29,11 @@ jabber_ibb_session_create(JabberStream *
gpointer user_data)
{
JabberIBBSession *sess = g_new0(JabberIBBSession, 1);
-
- if (!sess) {
- purple_debug_error("jabber", "Could not allocate IBB session object\n");
- return NULL;
- }
-
sess->js = js;
if (sid) {
sess->sid = g_strdup(sid);
} else {
- sess->sid = g_strdup(jabber_get_next_id(js));
+ sess->sid = jabber_get_next_id(js);
}
sess->who = g_strdup(who);
sess->block_size = JABBER_IBB_SESSION_DEFAULT_BLOCK_SIZE;
@@ -63,39 +54,26 @@ jabber_ibb_session_create_from_xmlnode(J
XEP_0047_NAMESPACE);
const gchar *sid = xmlnode_get_attrib(open, "sid");
const gchar *block_size = xmlnode_get_attrib(open, "block-size");
- gsize block_size_int;
if (!open) {
return NULL;
}
-
- sess = g_new0(JabberIBBSession, 1);
-
- if (!sess) {
- purple_debug_error("jabber", "Could not allocate IBB session object\n");
- return NULL;
- }
-
+
if (!sid || !block_size) {
purple_debug_error("jabber",
"IBB session open tag requires sid and block-size attributes\n");
g_free(sess);
return NULL;
}
-
- block_size_int = atoi(block_size);
- sess->js = js;
- sess->sid = g_strdup(sid);
+
+ sess = jabber_ibb_session_create(js, sid,
+ xmlnode_get_attrib(packet, "from"), user_data);
sess->id = g_strdup(xmlnode_get_attrib(packet, "id"));
- sess->who = g_strdup(xmlnode_get_attrib(packet, "from"));
- sess->block_size = block_size_int;
+ sess->block_size = atoi(block_size);
/* if we create a session from an incoming <open/> request, it means the
session is immediatly open... */
sess->state = JABBER_IBB_SESSION_OPENED;
- sess->user_data = user_data;
- g_hash_table_insert(jabber_ibb_sessions, sess->sid, sess);
-
return sess;
}
@@ -119,6 +97,7 @@ jabber_ibb_session_destroy(JabberIBBSess
}
g_hash_table_remove(jabber_ibb_sessions, sess->sid);
+ g_free(sess->id);
g_free(sess->sid);
g_free(sess->who);
g_free(sess);
@@ -248,7 +227,7 @@ jabber_ibb_session_open(JabberIBBSession
xmlnode_set_attrib(set->node, "to", jabber_ibb_session_get_who(sess));
xmlnode_set_namespace(open, XEP_0047_NAMESPACE);
xmlnode_set_attrib(open, "sid", jabber_ibb_session_get_sid(sess));
- g_snprintf(block_size, sizeof(block_size), "%ld",
+ g_snprintf(block_size, sizeof(block_size), "%" G_GSIZE_FORMAT,
jabber_ibb_session_get_block_size(sess));
xmlnode_set_attrib(open, "block-size", block_size);
xmlnode_insert_child(set->node, open);
@@ -327,11 +306,12 @@ void
}
void
-jabber_ibb_session_send_data(JabberIBBSession *sess, gpointer data, gsize size)
+jabber_ibb_session_send_data(JabberIBBSession *sess, gconstpointer data,
+ gsize size)
{
JabberIBBSessionState state = jabber_ibb_session_get_state(sess);
- purple_debug_info("jabber", "sending data block of %ld bytes on IBB stream\n",
+ purple_debug_info("jabber", "sending data block of %" G_GSIZE_FORMAT " bytes on IBB stream\n",
size);
if (state != JABBER_IBB_SESSION_OPENED) {
@@ -346,13 +326,13 @@ jabber_ibb_session_send_data(JabberIBBSe
xmlnode *data_element = xmlnode_new("data");
char *base64 = purple_base64_encode(data, size);
char seq[10];
- g_snprintf(seq, sizeof(seq), "%d", jabber_ibb_session_get_send_seq(sess));
+ g_snprintf(seq, sizeof(seq), "%u", jabber_ibb_session_get_send_seq(sess));
xmlnode_set_attrib(set->node, "to", jabber_ibb_session_get_who(sess));
xmlnode_set_namespace(data_element, XEP_0047_NAMESPACE);
xmlnode_set_attrib(data_element, "sid", jabber_ibb_session_get_sid(sess));
xmlnode_set_attrib(data_element, "seq", seq);
- xmlnode_insert_data(data_element, base64, strlen(base64));
+ xmlnode_insert_data(data_element, base64, -1);
xmlnode_insert_child(set->node, data_element);
@@ -361,8 +341,8 @@ jabber_ibb_session_send_data(JabberIBBSe
sess->sid);
jabber_iq_set_callback(set, jabber_ibb_session_send_acknowledge_cb, sess);
sess->last_iq_id = g_strdup(xmlnode_get_attrib(set->node, "id"));
- purple_debug_info("jabber", "IBB: set sess->last_iq_id: %s %s\n",
- sess->last_iq_id, xmlnode_get_attrib(set->node, "id"));
+ purple_debug_info("jabber", "IBB: set sess->last_iq_id: %s\n",
+ sess->last_iq_id);
jabber_iq_send(set);
g_free(base64);
@@ -414,11 +394,13 @@ jabber_ibb_parse(JabberStream *js, xmlno
purple_debug_error("jabber",
"Got IBB iq from wrong JID, ignoring\n");
} else if (data) {
- guint16 seq = atoi(xmlnode_get_attrib(data, "seq"));
-
+ const gchar *seq_attr = xmlnode_get_attrib(data, "seq");
+ guint16 seq = 0;
+
/* reject the data, and set the session in error if we get an
out-of-order packet */
- if (seq == jabber_ibb_session_get_recv_seq(sess)) {
+ if (seq_attr && (seq = atoi(seq_attr)) &&
+ seq == jabber_ibb_session_get_recv_seq(sess)) {
/* sequence # is the expected... */
JabberIq *result = jabber_iq_new(js, JABBER_IQ_RESULT);
@@ -435,10 +417,15 @@ jabber_ibb_parse(JabberStream *js, xmlno
if (rawdata) {
purple_debug_info("jabber",
- "got %ld bytes of data on IBB stream\n", size);
+ "got %" G_GSIZE_FORMAT " bytes of data on IBB stream\n",
+ size);
if (size > jabber_ibb_session_get_block_size(sess)) {
purple_debug_error("jabber",
"IBB: received a too large packet\n");
+ if (sess->error_cb)
+ sess->error_cb(sess);
+ g_free(rawdata);
+ return;
} else {
purple_debug_info("jabber",
"calling IBB callback for received data\n");
@@ -448,6 +435,10 @@ jabber_ibb_parse(JabberStream *js, xmlno
} else {
purple_debug_error("jabber",
"IBB: invalid BASE64 data received\n");
+ if (sess->error_cb)
+ sess->error_cb(sess);
+ return;
+
}
}
@@ -456,7 +447,7 @@ jabber_ibb_parse(JabberStream *js, xmlno
} else {
purple_debug_error("jabber",
- "Received an out-of-order IBB packet\n");
+ "Received an out-of-order/invalid IBB packet\n");
sess->state = JABBER_IBB_SESSION_ERROR;
if (sess->error_cb) {
@@ -483,7 +474,7 @@ jabber_ibb_parse(JabberStream *js, xmlno
/* run all open handlers registered until one returns true */
for (iterator = open_handlers ; iterator ;
iterator = g_list_next(iterator)) {
- JabberIBBOpenHandler *handler = (JabberIBBOpenHandler *) iterator->data;
+ JabberIBBOpenHandler *handler = iterator->data;
if (handler(js, packet)) {
result = jabber_iq_new(js, JABBER_IQ_RESULT);
@@ -529,5 +520,3 @@ jabber_ibb_uninit(void)
open_handlers = NULL;
}
-
-
============================================================
--- libpurple/protocols/jabber/ibb.h 79243d416a89295e16e8aee88f213e9412680d98
+++ libpurple/protocols/jabber/ibb.h a0be7e6921670f53dbd3576ea55dc113d368eaca
@@ -14,12 +14,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301, USA
*/
+#ifndef _PURPLE_JABBER_IBB_H_
+#define _PURPLE_JABBER_IBB_H_
+
#include "jabber.h"
#include "iq.h"
-#ifndef JABBER_IBB_SESSION
-#define JABBER_IBB_SESSION
-
#define XEP_0047_NAMESPACE "http://jabber.org/protocol/ibb"
typedef struct _JabberIBBSession JabberIBBSession;
@@ -89,7 +89,7 @@ void jabber_ibb_session_accept(JabberIBB
void jabber_ibb_session_open(JabberIBBSession *sess);
void jabber_ibb_session_close(JabberIBBSession *sess);
void jabber_ibb_session_accept(JabberIBBSession *sess);
-void jabber_ibb_session_send_data(JabberIBBSession *sess, gpointer data,
+void jabber_ibb_session_send_data(JabberIBBSession *sess, gconstpointer data,
gsize size);
const gchar *jabber_ibb_session_get_sid(const JabberIBBSession *sess);
@@ -116,4 +116,4 @@ void jabber_ibb_uninit(void);
void jabber_ibb_init(void);
void jabber_ibb_uninit(void);
-#endif /* JABBER_IBB_SESSION */
+#endif /* _PURPLE_JABBER_IBB_H_ */
============================================================
--- libpurple/protocols/jabber/si.c 20bbf1af0e116f9ecb4b1e8cfdcc67eb68378f9e
+++ libpurple/protocols/jabber/si.c 15e4fb8a07347b931b228393052c2181bdb7b399
@@ -32,9 +32,9 @@
#include "buddy.h"
#include "disco.h"
#include "jabber.h"
+#include "ibb.h"
#include "iq.h"
#include "si.h"
-#include "ibb.h"
#define STREAMHOST_CONNECT_TIMEOUT 15
@@ -999,7 +999,7 @@ jabber_si_xfer_ibb_recv_data_cb(JabberIB
JabberSIXfer *jsx = (JabberSIXfer *) xfer->data;
if (size <= purple_xfer_get_bytes_remaining(xfer)) {
- purple_debug_info("jabber", "about to write %lu bytes from IBB stream\n",
+ purple_debug_info("jabber", "about to write %" G_GSIZE_FORMAT " bytes from IBB stream\n",
size);
if(!fwrite(data, size, 1, jsx->fp)) {
purple_debug_error("jabber", "error writing to file\n");
@@ -1018,7 +1018,7 @@ jabber_si_xfer_ibb_recv_data_cb(JabberIB
/* trying to write past size of file transfers negotiated size,
reject transfer to protect against malicious behaviour */
purple_debug_error("jabber",
- "IBB file transfer, trying to write past end of file\n");
+ "IBB file transfer send more data than expected\n");
jabber_si_xfer_cancel_recv(xfer);
purple_xfer_end(xfer);
}
@@ -1036,8 +1036,19 @@ jabber_si_xfer_ibb_open_cb(JabberStream
JabberSIXfer *jsx = (JabberSIXfer *) xfer->data;
JabberIBBSession *sess =
jabber_ibb_session_create_from_xmlnode(js, packet, xfer);
-
+ const char *filename;
+
if (sess) {
+ /* open the file to write to */
+ filename = purple_xfer_get_local_filename(xfer);
+ jsx->fp = g_fopen(filename, "wb");
+ if (jsx->fp == NULL) {
+ purple_debug_error("jabber", "failed to open file %s for writing: %s\n",
+ filename, g_strerror(errno));
+ purple_xfer_cancel_remote(xfer);
+ return FALSE;
+ }
+
/* setup callbacks here...*/
jabber_ibb_session_set_data_received_callback(sess,
jabber_si_xfer_ibb_recv_data_cb);
@@ -1046,9 +1057,6 @@ jabber_si_xfer_ibb_open_cb(JabberStream
jabber_ibb_session_set_error_callback(sess,
jabber_si_xfer_ibb_error_cb);
- /* open the file to write to */
- jsx->fp = g_fopen(purple_xfer_get_local_filename(xfer), "wb");
-
jsx->ibb_session = sess;
/* start the transfer */
@@ -1082,7 +1090,7 @@ jabber_si_xfer_ibb_send_data(JabberIBBSe
gpointer data = g_malloc(packet_size);
int res;
- purple_debug_info("jabber", "IBB: about to read %lu bytes from file %p\n",
+ purple_debug_info("jabber", "IBB: about to read %" G_GSIZE_FORMAT " bytes from file %p\n",
packet_size, jsx->fp);
res = fread(data, packet_size, 1, jsx->fp);
@@ -1121,18 +1129,30 @@ jabber_si_xfer_ibb_opened_cb(JabberIBBSe
{
PurpleXfer *xfer = (PurpleXfer *) jabber_ibb_session_get_user_data(sess);
JabberSIXfer *jsx = (JabberSIXfer *) xfer->data;
-
+ JabberStream *js = jabber_ibb_session_get_js(sess);
+ PurpleConnection *gc = js->gc;
+ PurpleAccount *account = purple_connection_get_account(gc);
+
if (jabber_ibb_session_get_state(sess) == JABBER_IBB_SESSION_OPENED) {
- purple_xfer_start(xfer, 0, NULL, 0);
- purple_xfer_set_bytes_sent(xfer, 0);
- purple_xfer_update_progress(xfer);
- jsx->fp = g_fopen(purple_xfer_get_local_filename(xfer), "rb");
- jabber_si_xfer_ibb_send_data(sess);
+ const char *filename = purple_xfer_get_local_filename(xfer);
+ jsx->fp = g_fopen(filename, "rb");
+ if (jsx->fp == NULL) {
+ purple_debug_error("jabber", "Failed to open file %s for reading: %s\n",
+ filename, g_strerror(errno));
+ jabber_si_xfer_free(xfer);
+ purple_xfer_error(purple_xfer_get_type(xfer), account,
+ jabber_ibb_session_get_who(sess),
+ _("Failed to open the file"));
+ purple_xfer_end(xfer);
+ } else {
+ /* XXX: Shouldn't this specify a valid file descriptor? */
+ purple_xfer_start(xfer, 0, NULL, 0);
+ purple_xfer_set_bytes_sent(xfer, 0);
+ purple_xfer_update_progress(xfer);
+ jabber_si_xfer_ibb_send_data(sess);
+ }
} else {
/* error */
- JabberStream *js = jabber_ibb_session_get_js(sess);
- PurpleConnection *gc = js->gc;
- PurpleAccount *account = purple_connection_get_account(gc);
jabber_si_xfer_free(xfer);
purple_xfer_error(purple_xfer_get_type(xfer), account,
jabber_ibb_session_get_who(sess),
@@ -1167,10 +1187,10 @@ jabber_si_xfer_ibb_send_init(JabberStrea
} else {
/* failed to create IBB session */
- purple_xfer_unref(xfer);
purple_debug_error("jabber",
"failed to initiate IBB session for file transfer\n");
jabber_si_xfer_cancel_send(xfer);
+ purple_xfer_unref(xfer);
}
}
More information about the Commits
mailing list