comparison libpurple/protocols/jabber/si.c @ 32819:2c6510167895 default tip

propagate from branch 'im.pidgin.pidgin.2.x.y' (head 3315c5dfbd0ad16511bdcf865e5b07c02d07df24) to branch 'im.pidgin.pidgin' (head cbd1eda6bcbf0565ae7766396bb8f6f419cb6a9a)
author Elliott Sales de Andrade <qulogic@pidgin.im>
date Sat, 02 Jun 2012 02:30:49 +0000
parents fb5b5f6cf111
children
comparison
equal deleted inserted replaced
32818:01ff09d4a463 32819:2c6510167895
85 if(!sid || !from) 85 if(!sid || !from)
86 return NULL; 86 return NULL;
87 87
88 for(xfers = js->file_transfers; xfers; xfers = xfers->next) { 88 for(xfers = js->file_transfers; xfers; xfers = xfers->next) {
89 PurpleXfer *xfer = xfers->data; 89 PurpleXfer *xfer = xfers->data;
90 JabberSIXfer *jsx = xfer->data; 90 JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
91 if(jsx->stream_id && xfer->who && 91 if(jsx->stream_id && purple_xfer_get_remote_user(xfer) &&
92 !strcmp(jsx->stream_id, sid) && !strcmp(xfer->who, from)) 92 !strcmp(jsx->stream_id, sid) && !strcmp(purple_xfer_get_remote_user(xfer), from))
93 return xfer; 93 return xfer;
94 } 94 }
95 95
96 return NULL; 96 return NULL;
97 } 97 }
116 116
117 static void 117 static void
118 jabber_si_bytestreams_connect_cb(gpointer data, gint source, const gchar *error_message) 118 jabber_si_bytestreams_connect_cb(gpointer data, gint source, const gchar *error_message)
119 { 119 {
120 PurpleXfer *xfer = data; 120 PurpleXfer *xfer = data;
121 JabberSIXfer *jsx = xfer->data; 121 JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
122 JabberIq *iq; 122 JabberIq *iq;
123 xmlnode *query, *su; 123 xmlnode *query, *su;
124 JabberBytestreamsStreamhost *streamhost = jsx->streamhosts->data; 124 JabberBytestreamsStreamhost *streamhost = jsx->streamhosts->data;
125 125
126 purple_proxy_info_destroy(jsx->gpi); 126 purple_proxy_info_destroy(jsx->gpi);
141 jabber_si_bytestreams_attempt_connect(xfer); 141 jabber_si_bytestreams_attempt_connect(xfer);
142 return; 142 return;
143 } 143 }
144 144
145 /* unknown file transfer type is assumed to be RECEIVE */ 145 /* unknown file transfer type is assumed to be RECEIVE */
146 if(xfer->type == PURPLE_XFER_SEND) 146 if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND)
147 { 147 {
148 xmlnode *activate; 148 xmlnode *activate;
149 iq = jabber_iq_new_query(jsx->js, JABBER_IQ_SET, NS_BYTESTREAMS); 149 iq = jabber_iq_new_query(jsx->js, JABBER_IQ_SET, NS_BYTESTREAMS);
150 xmlnode_set_attrib(iq->node, "to", streamhost->jid); 150 xmlnode_set_attrib(iq->node, "to", streamhost->jid);
151 query = xmlnode_get_child(iq->node, "query"); 151 query = xmlnode_get_child(iq->node, "query");
152 xmlnode_set_attrib(query, "sid", jsx->stream_id); 152 xmlnode_set_attrib(query, "sid", jsx->stream_id);
153 activate = xmlnode_new_child(query, "activate"); 153 activate = xmlnode_new_child(query, "activate");
154 xmlnode_insert_data(activate, xfer->who, -1); 154 xmlnode_insert_data(activate, purple_xfer_get_remote_user(xfer), -1);
155 155
156 /* TODO: We need to wait for an activation result before starting */ 156 /* TODO: We need to wait for an activation result before starting */
157 } 157 }
158 else 158 else
159 { 159 {
160 iq = jabber_iq_new_query(jsx->js, JABBER_IQ_RESULT, NS_BYTESTREAMS); 160 iq = jabber_iq_new_query(jsx->js, JABBER_IQ_RESULT, NS_BYTESTREAMS);
161 xmlnode_set_attrib(iq->node, "to", xfer->who); 161 xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer));
162 jabber_iq_set_id(iq, jsx->iq_id); 162 jabber_iq_set_id(iq, jsx->iq_id);
163 query = xmlnode_get_child(iq->node, "query"); 163 query = xmlnode_get_child(iq->node, "query");
164 su = xmlnode_new_child(query, "streamhost-used"); 164 su = xmlnode_new_child(query, "streamhost-used");
165 xmlnode_set_attrib(su, "jid", streamhost->jid); 165 xmlnode_set_attrib(su, "jid", streamhost->jid);
166 } 166 }
172 172
173 static gboolean 173 static gboolean
174 connect_timeout_cb(gpointer data) 174 connect_timeout_cb(gpointer data)
175 { 175 {
176 PurpleXfer *xfer = data; 176 PurpleXfer *xfer = data;
177 JabberSIXfer *jsx = xfer->data; 177 JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
178 178
179 purple_debug_info("jabber", "Streamhost connection timeout of %d seconds exceeded.\n", STREAMHOST_CONNECT_TIMEOUT); 179 purple_debug_info("jabber", "Streamhost connection timeout of %d seconds exceeded.\n", STREAMHOST_CONNECT_TIMEOUT);
180 180
181 jsx->connect_timeout = 0; 181 jsx->connect_timeout = 0;
182 182
201 201
202 static gboolean 202 static gboolean
203 jabber_si_bytestreams_ibb_timeout_cb(gpointer data) 203 jabber_si_bytestreams_ibb_timeout_cb(gpointer data)
204 { 204 {
205 PurpleXfer *xfer = (PurpleXfer *) data; 205 PurpleXfer *xfer = (PurpleXfer *) data;
206 JabberSIXfer *jsx = xfer->data; 206 JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
207 207
208 if (jsx && !jsx->ibb_session) { 208 if (jsx && !jsx->ibb_session) {
209 purple_debug_info("jabber", 209 purple_debug_info("jabber",
210 "jabber_si_bytestreams_ibb_timeout called and IBB session not set " 210 "jabber_si_bytestreams_ibb_timeout called and IBB session not set "
211 " up yet, cancel transfer"); 211 " up yet, cancel transfer");
216 return FALSE; 216 return FALSE;
217 } 217 }
218 218
219 static void jabber_si_bytestreams_attempt_connect(PurpleXfer *xfer) 219 static void jabber_si_bytestreams_attempt_connect(PurpleXfer *xfer)
220 { 220 {
221 JabberSIXfer *jsx = xfer->data; 221 JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
222 JabberBytestreamsStreamhost *streamhost; 222 JabberBytestreamsStreamhost *streamhost;
223 JabberID *dstjid; 223 JabberID *dstjid;
224 224
225 if(!jsx->streamhosts) { 225 if(!jsx->streamhosts) {
226 JabberIq *iq = jabber_iq_new(jsx->js, JABBER_IQ_ERROR); 226 JabberIq *iq = jabber_iq_new(jsx->js, JABBER_IQ_ERROR);
227 xmlnode *error, *inf; 227 xmlnode *error, *inf;
228 228
229 if(jsx->iq_id) 229 if(jsx->iq_id)
230 jabber_iq_set_id(iq, jsx->iq_id); 230 jabber_iq_set_id(iq, jsx->iq_id);
231 231
232 xmlnode_set_attrib(iq->node, "to", xfer->who); 232 xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer));
233 error = xmlnode_new_child(iq->node, "error"); 233 error = xmlnode_new_child(iq->node, "error");
234 xmlnode_set_attrib(error, "code", "404"); 234 xmlnode_set_attrib(error, "code", "404");
235 xmlnode_set_attrib(error, "type", "cancel"); 235 xmlnode_set_attrib(error, "type", "cancel");
236 inf = xmlnode_new_child(error, "item-not-found"); 236 inf = xmlnode_new_child(error, "item-not-found");
237 xmlnode_set_namespace(inf, NS_XMPP_STANZAS); 237 xmlnode_set_namespace(inf, NS_XMPP_STANZAS);
269 jsx->connect_data = NULL; 269 jsx->connect_data = NULL;
270 if (jsx->gpi != NULL) 270 if (jsx->gpi != NULL)
271 purple_proxy_info_destroy(jsx->gpi); 271 purple_proxy_info_destroy(jsx->gpi);
272 jsx->gpi = NULL; 272 jsx->gpi = NULL;
273 273
274 dstjid = jabber_id_new(xfer->who); 274 dstjid = jabber_id_new(purple_xfer_get_remote_user(xfer));
275 275
276 /* TODO: Deal with zeroconf */ 276 /* TODO: Deal with zeroconf */
277 277
278 if(dstjid != NULL && streamhost->host && streamhost->port > 0) { 278 if(dstjid != NULL && streamhost->host && streamhost->port > 0) {
279 char *dstaddr, *hash; 279 char *dstaddr, *hash;
282 purple_proxy_info_set_type(jsx->gpi, PURPLE_PROXY_SOCKS5); 282 purple_proxy_info_set_type(jsx->gpi, PURPLE_PROXY_SOCKS5);
283 purple_proxy_info_set_host(jsx->gpi, streamhost->host); 283 purple_proxy_info_set_host(jsx->gpi, streamhost->host);
284 purple_proxy_info_set_port(jsx->gpi, streamhost->port); 284 purple_proxy_info_set_port(jsx->gpi, streamhost->port);
285 285
286 /* unknown file transfer type is assumed to be RECEIVE */ 286 /* unknown file transfer type is assumed to be RECEIVE */
287 if(xfer->type == PURPLE_XFER_SEND) 287 if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND)
288 dstaddr = g_strdup_printf("%s%s@%s/%s%s@%s/%s", jsx->stream_id, jsx->js->user->node, jsx->js->user->domain, 288 dstaddr = g_strdup_printf("%s%s@%s/%s%s@%s/%s", jsx->stream_id, jsx->js->user->node, jsx->js->user->domain,
289 jsx->js->user->resource, dstjid->node, dstjid->domain, dstjid->resource); 289 jsx->js->user->resource, dstjid->node, dstjid->domain, dstjid->resource);
290 else 290 else
291 dstaddr = g_strdup_printf("%s%s@%s/%s%s@%s/%s", jsx->stream_id, dstjid->node, dstjid->domain, dstjid->resource, 291 dstaddr = g_strdup_printf("%s%s@%s/%s%s@%s/%s", jsx->stream_id, dstjid->node, dstjid->domain, dstjid->resource,
292 jsx->js->user->node, jsx->js->user->domain, jsx->js->user->resource); 292 jsx->js->user->node, jsx->js->user->domain, jsx->js->user->resource);
300 jabber_si_bytestreams_connect_cb, xfer); 300 jabber_si_bytestreams_connect_cb, xfer);
301 g_free(hash); 301 g_free(hash);
302 g_free(dstaddr); 302 g_free(dstaddr);
303 303
304 /* When selecting a streamhost, timeout after STREAMHOST_CONNECT_TIMEOUT seconds, otherwise it takes forever */ 304 /* When selecting a streamhost, timeout after STREAMHOST_CONNECT_TIMEOUT seconds, otherwise it takes forever */
305 if (xfer->type != PURPLE_XFER_SEND && jsx->connect_data != NULL) 305 if (purple_xfer_get_type(xfer) != PURPLE_XFER_SEND && jsx->connect_data != NULL)
306 jsx->connect_timeout = purple_timeout_add_seconds( 306 jsx->connect_timeout = purple_timeout_add_seconds(
307 STREAMHOST_CONNECT_TIMEOUT, connect_timeout_cb, xfer); 307 STREAMHOST_CONNECT_TIMEOUT, connect_timeout_cb, xfer);
308 308
309 jabber_id_free(dstjid); 309 jabber_id_free(dstjid);
310 } 310 }
335 return; 335 return;
336 336
337 if(!(xfer = jabber_si_xfer_find(js, sid, from))) 337 if(!(xfer = jabber_si_xfer_find(js, sid, from)))
338 return; 338 return;
339 339
340 jsx = xfer->data; 340 jsx = purple_xfer_get_protocol_data(xfer);
341 341
342 if(!jsx->accepted) 342 if(!jsx->accepted)
343 return; 343 return;
344 344
345 if(jsx->iq_id) 345 if(jsx->iq_id)
373 static void 373 static void
374 jabber_si_xfer_bytestreams_send_read_again_resp_cb(gpointer data, gint source, 374 jabber_si_xfer_bytestreams_send_read_again_resp_cb(gpointer data, gint source,
375 PurpleInputCondition cond) 375 PurpleInputCondition cond)
376 { 376 {
377 PurpleXfer *xfer = data; 377 PurpleXfer *xfer = data;
378 JabberSIXfer *jsx = xfer->data; 378 JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
379 int len; 379 int len;
380 380
381 len = write(source, jsx->rxqueue + jsx->rxlen, jsx->rxmaxlen - jsx->rxlen); 381 len = write(source, jsx->rxqueue + jsx->rxlen, jsx->rxmaxlen - jsx->rxlen);
382 if (len < 0 && errno == EAGAIN) 382 if (len < 0 && errno == EAGAIN)
383 return; 383 return;
384 else if (len < 0) { 384 else if (len < 0) {
385 purple_input_remove(xfer->watcher);
386 xfer->watcher = 0;
387 g_free(jsx->rxqueue); 385 g_free(jsx->rxqueue);
388 jsx->rxqueue = NULL; 386 jsx->rxqueue = NULL;
389 close(source); 387 close(source);
390 purple_xfer_cancel_remote(xfer); 388 purple_xfer_cancel_remote(xfer);
391 return; 389 return;
393 jsx->rxlen += len; 391 jsx->rxlen += len;
394 392
395 if (jsx->rxlen < jsx->rxmaxlen) 393 if (jsx->rxlen < jsx->rxmaxlen)
396 return; 394 return;
397 395
398 purple_input_remove(xfer->watcher); 396 purple_input_remove(purple_xfer_get_watcher(xfer));
399 xfer->watcher = 0; 397 purple_xfer_set_watcher(xfer, 0);
400 g_free(jsx->rxqueue); 398 g_free(jsx->rxqueue);
401 jsx->rxqueue = NULL; 399 jsx->rxqueue = NULL;
402 400
403 /* Before actually starting sending the file, we need to wait until the 401 /* Before actually starting sending the file, we need to wait until the
404 * recipient sends the IQ result with <streamhost-used/> 402 * recipient sends the IQ result with <streamhost-used/>
410 static void 408 static void
411 jabber_si_xfer_bytestreams_send_read_again_cb(gpointer data, gint source, 409 jabber_si_xfer_bytestreams_send_read_again_cb(gpointer data, gint source,
412 PurpleInputCondition cond) 410 PurpleInputCondition cond)
413 { 411 {
414 PurpleXfer *xfer = data; 412 PurpleXfer *xfer = data;
415 JabberSIXfer *jsx = xfer->data; 413 JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
416 char buffer[42]; /* 40 for DST.ADDR + 2 bytes for port number*/ 414 char buffer[42]; /* 40 for DST.ADDR + 2 bytes for port number*/
417 int len; 415 int len;
418 char *dstaddr, *hash; 416 char *dstaddr, *hash;
419 const char *host; 417 const char *host;
420 418
424 purple_debug_info("jabber", "reading the first 5 bytes\n"); 422 purple_debug_info("jabber", "reading the first 5 bytes\n");
425 len = read(source, buffer, 5 - jsx->rxlen); 423 len = read(source, buffer, 5 - jsx->rxlen);
426 if(len < 0 && errno == EAGAIN) 424 if(len < 0 && errno == EAGAIN)
427 return; 425 return;
428 else if(len <= 0) { 426 else if(len <= 0) {
429 purple_input_remove(xfer->watcher);
430 xfer->watcher = 0;
431 close(source); 427 close(source);
432 purple_xfer_cancel_remote(xfer); 428 purple_xfer_cancel_remote(xfer);
433 return; 429 return;
434 } 430 }
435 jsx->rxqueue = g_realloc(jsx->rxqueue, len + jsx->rxlen); 431 jsx->rxqueue = g_realloc(jsx->rxqueue, len + jsx->rxlen);
439 } else if(jsx->rxqueue[0] != 0x05 || jsx->rxqueue[1] != 0x01 || 435 } else if(jsx->rxqueue[0] != 0x05 || jsx->rxqueue[1] != 0x01 ||
440 jsx->rxqueue[3] != 0x03 || jsx->rxqueue[4] != 40) { 436 jsx->rxqueue[3] != 0x03 || jsx->rxqueue[4] != 40) {
441 purple_debug_info("jabber", "Invalid socks5 conn req. header[0x%x,0x%x,0x%x,0x%x,0x%x]\n", 437 purple_debug_info("jabber", "Invalid socks5 conn req. header[0x%x,0x%x,0x%x,0x%x,0x%x]\n",
442 jsx->rxqueue[0], jsx->rxqueue[1], jsx->rxqueue[2], 438 jsx->rxqueue[0], jsx->rxqueue[1], jsx->rxqueue[2],
443 jsx->rxqueue[3], jsx->rxqueue[4]); 439 jsx->rxqueue[3], jsx->rxqueue[4]);
444 purple_input_remove(xfer->watcher);
445 xfer->watcher = 0;
446 close(source); 440 close(source);
447 purple_xfer_cancel_remote(xfer); 441 purple_xfer_cancel_remote(xfer);
448 return; 442 return;
449 } else if(jsx->rxlen - 5 < jsx->rxqueue[4] + 2) { 443 } else if(jsx->rxlen - 5 < jsx->rxqueue[4] + 2) {
450 /* Upper-bound of 257 (jsx->rxlen = 5, jsx->rxqueue[4] = 0xFF) */ 444 /* Upper-bound of 257 (jsx->rxlen = 5, jsx->rxqueue[4] = 0xFF) */
453 jsx->rxqueue[4] + 2, to_read); 447 jsx->rxqueue[4] + 2, to_read);
454 len = read(source, buffer, to_read); 448 len = read(source, buffer, to_read);
455 if(len < 0 && errno == EAGAIN) 449 if(len < 0 && errno == EAGAIN)
456 return; 450 return;
457 else if(len <= 0) { 451 else if(len <= 0) {
458 purple_input_remove(xfer->watcher);
459 xfer->watcher = 0;
460 close(source); 452 close(source);
461 purple_xfer_cancel_remote(xfer); 453 purple_xfer_cancel_remote(xfer);
462 return; 454 return;
463 } 455 }
464 jsx->rxqueue = g_realloc(jsx->rxqueue, len + jsx->rxlen); 456 jsx->rxqueue = g_realloc(jsx->rxqueue, len + jsx->rxlen);
468 460
469 /* Have we not read all of DST.ADDR and the following 2-byte port number? */ 461 /* Have we not read all of DST.ADDR and the following 2-byte port number? */
470 if(jsx->rxlen - 5 < jsx->rxqueue[4] + 2) 462 if(jsx->rxlen - 5 < jsx->rxqueue[4] + 2)
471 return; 463 return;
472 464
473 purple_input_remove(xfer->watcher); 465 purple_input_remove(purple_xfer_get_watcher(xfer));
474 xfer->watcher = 0; 466 purple_xfer_set_watcher(xfer, 0);
475 467
476 dstaddr = g_strdup_printf("%s%s@%s/%s%s", jsx->stream_id, 468 dstaddr = g_strdup_printf("%s%s@%s/%s%s", jsx->stream_id,
477 jsx->js->user->node, jsx->js->user->domain, 469 jsx->js->user->node, jsx->js->user->domain,
478 jsx->js->user->resource, xfer->who); 470 jsx->js->user->resource, purple_xfer_get_remote_user(xfer));
479 471
480 /* Per XEP-0065, the 'host' must be SHA1(SID + from JID + to JID) */ 472 /* Per XEP-0065, the 'host' must be SHA1(SID + from JID + to JID) */
481 hash = jabber_calculate_data_hash(dstaddr, strlen(dstaddr), "sha1"); 473 hash = jabber_calculate_data_hash(dstaddr, strlen(dstaddr), "sha1");
482 474
483 if(strncmp(hash, jsx->rxqueue + 5, 40) || 475 if(strncmp(hash, jsx->rxqueue + 5, 40) ||
514 jsx->rxqueue[4] = strlen(host); 506 jsx->rxqueue[4] = strlen(host);
515 memcpy(jsx->rxqueue + 5, host, strlen(host)); 507 memcpy(jsx->rxqueue + 5, host, strlen(host));
516 jsx->rxqueue[5+strlen(host)] = 0x00; 508 jsx->rxqueue[5+strlen(host)] = 0x00;
517 jsx->rxqueue[6+strlen(host)] = 0x00; 509 jsx->rxqueue[6+strlen(host)] = 0x00;
518 510
519 xfer->watcher = purple_input_add(source, PURPLE_INPUT_WRITE, 511 purple_xfer_set_watcher(xfer, purple_input_add(source, PURPLE_INPUT_WRITE,
520 jabber_si_xfer_bytestreams_send_read_again_resp_cb, xfer); 512 jabber_si_xfer_bytestreams_send_read_again_resp_cb, xfer));
521 jabber_si_xfer_bytestreams_send_read_again_resp_cb(xfer, source, 513 jabber_si_xfer_bytestreams_send_read_again_resp_cb(xfer, source,
522 PURPLE_INPUT_WRITE); 514 PURPLE_INPUT_WRITE);
523 } 515 }
524 516
525 static void 517 static void
526 jabber_si_xfer_bytestreams_send_read_response_cb(gpointer data, gint source, 518 jabber_si_xfer_bytestreams_send_read_response_cb(gpointer data, gint source,
527 PurpleInputCondition cond) 519 PurpleInputCondition cond)
528 { 520 {
529 PurpleXfer *xfer = data; 521 PurpleXfer *xfer = data;
530 JabberSIXfer *jsx = xfer->data; 522 JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
531 int len; 523 int len;
532 524
533 len = write(source, jsx->rxqueue + jsx->rxlen, jsx->rxmaxlen - jsx->rxlen); 525 len = write(source, jsx->rxqueue + jsx->rxlen, jsx->rxmaxlen - jsx->rxlen);
534 if (len < 0 && errno == EAGAIN) 526 if (len < 0 && errno == EAGAIN)
535 return; 527 return;
536 else if (len < 0) { 528 else if (len < 0) {
537 purple_input_remove(xfer->watcher);
538 xfer->watcher = 0;
539 g_free(jsx->rxqueue); 529 g_free(jsx->rxqueue);
540 jsx->rxqueue = NULL; 530 jsx->rxqueue = NULL;
541 close(source); 531 close(source);
542 purple_xfer_cancel_remote(xfer); 532 purple_xfer_cancel_remote(xfer);
543 return; 533 return;
545 jsx->rxlen += len; 535 jsx->rxlen += len;
546 536
547 if (jsx->rxlen < jsx->rxmaxlen) 537 if (jsx->rxlen < jsx->rxmaxlen)
548 return; 538 return;
549 539
550 purple_input_remove(xfer->watcher);
551 xfer->watcher = 0;
552
553 /* If we sent a "Success", wait for a response, otherwise give up and cancel */ 540 /* If we sent a "Success", wait for a response, otherwise give up and cancel */
554 if (jsx->rxqueue[1] == 0x00) { 541 if (jsx->rxqueue[1] == 0x00) {
555 xfer->watcher = purple_input_add(source, PURPLE_INPUT_READ, 542 purple_input_remove(purple_xfer_get_watcher(xfer));
556 jabber_si_xfer_bytestreams_send_read_again_cb, xfer); 543 purple_xfer_set_watcher(xfer, purple_input_add(source, PURPLE_INPUT_READ,
544 jabber_si_xfer_bytestreams_send_read_again_cb, xfer));
557 g_free(jsx->rxqueue); 545 g_free(jsx->rxqueue);
558 jsx->rxqueue = NULL; 546 jsx->rxqueue = NULL;
559 jsx->rxlen = 0; 547 jsx->rxlen = 0;
560 } else { 548 } else {
561 close(source); 549 close(source);
566 static void 554 static void
567 jabber_si_xfer_bytestreams_send_read_cb(gpointer data, gint source, 555 jabber_si_xfer_bytestreams_send_read_cb(gpointer data, gint source,
568 PurpleInputCondition cond) 556 PurpleInputCondition cond)
569 { 557 {
570 PurpleXfer *xfer = data; 558 PurpleXfer *xfer = data;
571 JabberSIXfer *jsx = xfer->data; 559 JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
572 int i; 560 int i;
573 int len; 561 int len;
574 char buffer[256]; 562 char buffer[256];
575 563
576 purple_debug_info("jabber", "in jabber_si_xfer_bytestreams_send_read_cb\n"); 564 purple_debug_info("jabber", "in jabber_si_xfer_bytestreams_send_read_cb\n");
577 565
578 xfer->fd = source; 566 purple_xfer_set_fd(xfer, source);
579 567
580 /** Try to read the SOCKS5 header */ 568 /** Try to read the SOCKS5 header */
581 if(jsx->rxlen < 2) { 569 if(jsx->rxlen < 2) {
582 purple_debug_info("jabber", "reading those first two bytes\n"); 570 purple_debug_info("jabber", "reading those first two bytes\n");
583 len = read(source, buffer, 2 - jsx->rxlen); 571 len = read(source, buffer, 2 - jsx->rxlen);
584 if(len < 0 && errno == EAGAIN) 572 if(len < 0 && errno == EAGAIN)
585 return; 573 return;
586 else if(len <= 0) { 574 else if(len <= 0) {
587 purple_input_remove(xfer->watcher);
588 xfer->watcher = 0;
589 close(source);
590 purple_xfer_cancel_remote(xfer); 575 purple_xfer_cancel_remote(xfer);
591 return; 576 return;
592 } 577 }
593 jsx->rxqueue = g_realloc(jsx->rxqueue, len + jsx->rxlen); 578 jsx->rxqueue = g_realloc(jsx->rxqueue, len + jsx->rxlen);
594 memcpy(jsx->rxqueue + jsx->rxlen, buffer, len); 579 memcpy(jsx->rxqueue + jsx->rxlen, buffer, len);
601 jsx->rxqueue[1], to_read); 586 jsx->rxqueue[1], to_read);
602 len = read(source, buffer, to_read); 587 len = read(source, buffer, to_read);
603 if(len < 0 && errno == EAGAIN) 588 if(len < 0 && errno == EAGAIN)
604 return; 589 return;
605 else if(len <= 0) { 590 else if(len <= 0) {
606 purple_input_remove(xfer->watcher);
607 xfer->watcher = 0;
608 close(source);
609 purple_xfer_cancel_remote(xfer); 591 purple_xfer_cancel_remote(xfer);
610 return; 592 return;
611 } 593 }
612 jsx->rxqueue = g_realloc(jsx->rxqueue, len + jsx->rxlen); 594 jsx->rxqueue = g_realloc(jsx->rxqueue, len + jsx->rxlen);
613 memcpy(jsx->rxqueue + jsx->rxlen, buffer, len); 595 memcpy(jsx->rxqueue + jsx->rxlen, buffer, len);
616 598
617 /* Have we not read all the auth. method bytes? */ 599 /* Have we not read all the auth. method bytes? */
618 if(jsx->rxlen -2 < jsx->rxqueue[1]) 600 if(jsx->rxlen -2 < jsx->rxqueue[1])
619 return; 601 return;
620 602
621 purple_input_remove(xfer->watcher);
622 xfer->watcher = 0;
623
624 purple_debug_info("jabber", "checking to make sure we're socks FIVE\n"); 603 purple_debug_info("jabber", "checking to make sure we're socks FIVE\n");
625 604
626 if(jsx->rxqueue[0] != 0x05) { 605 if(jsx->rxqueue[0] != 0x05) {
627 close(source);
628 purple_xfer_cancel_remote(xfer); 606 purple_xfer_cancel_remote(xfer);
629 return; 607 return;
630 } 608 }
631 609
632 purple_debug_info("jabber", "going to test %hhu different methods\n", jsx->rxqueue[1]); 610 purple_debug_info("jabber", "going to test %hhu different methods\n", jsx->rxqueue[1]);
639 jsx->rxlen = 0; 617 jsx->rxlen = 0;
640 jsx->rxmaxlen = 2; 618 jsx->rxmaxlen = 2;
641 jsx->rxqueue = g_malloc(jsx->rxmaxlen); 619 jsx->rxqueue = g_malloc(jsx->rxmaxlen);
642 jsx->rxqueue[0] = 0x05; 620 jsx->rxqueue[0] = 0x05;
643 jsx->rxqueue[1] = 0x00; 621 jsx->rxqueue[1] = 0x00;
644 xfer->watcher = purple_input_add(source, PURPLE_INPUT_WRITE, 622 purple_input_remove(purple_xfer_get_watcher(xfer));
623 purple_xfer_set_watcher(xfer, purple_input_add(source, PURPLE_INPUT_WRITE,
645 jabber_si_xfer_bytestreams_send_read_response_cb, 624 jabber_si_xfer_bytestreams_send_read_response_cb,
646 xfer); 625 xfer));
647 jabber_si_xfer_bytestreams_send_read_response_cb(xfer, 626 jabber_si_xfer_bytestreams_send_read_response_cb(xfer,
648 source, PURPLE_INPUT_WRITE); 627 source, PURPLE_INPUT_WRITE);
649 jsx->rxqueue = NULL; 628 jsx->rxqueue = NULL;
650 jsx->rxlen = 0; 629 jsx->rxlen = 0;
651 return; 630 return;
656 jsx->rxlen = 0; 635 jsx->rxlen = 0;
657 jsx->rxmaxlen = 2; 636 jsx->rxmaxlen = 2;
658 jsx->rxqueue = g_malloc(jsx->rxmaxlen); 637 jsx->rxqueue = g_malloc(jsx->rxmaxlen);
659 jsx->rxqueue[0] = 0x05; 638 jsx->rxqueue[0] = 0x05;
660 jsx->rxqueue[1] = 0xFF; 639 jsx->rxqueue[1] = 0xFF;
661 xfer->watcher = purple_input_add(source, PURPLE_INPUT_WRITE, 640 purple_input_remove(purple_xfer_get_watcher(xfer));
662 jabber_si_xfer_bytestreams_send_read_response_cb, xfer); 641 purple_xfer_set_watcher(xfer, purple_input_add(source, PURPLE_INPUT_WRITE,
642 jabber_si_xfer_bytestreams_send_read_response_cb, xfer));
663 jabber_si_xfer_bytestreams_send_read_response_cb(xfer, 643 jabber_si_xfer_bytestreams_send_read_response_cb(xfer,
664 source, PURPLE_INPUT_WRITE); 644 source, PURPLE_INPUT_WRITE);
665 } 645 }
666 646
667 static gint 647 static gint
678 static void 658 static void
679 jabber_si_xfer_bytestreams_send_connected_cb(gpointer data, gint source, 659 jabber_si_xfer_bytestreams_send_connected_cb(gpointer data, gint source,
680 PurpleInputCondition cond) 660 PurpleInputCondition cond)
681 { 661 {
682 PurpleXfer *xfer = data; 662 PurpleXfer *xfer = data;
683 JabberSIXfer *jsx = xfer->data; 663 JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
684 int acceptfd, flags; 664 int acceptfd, flags;
685 665
686 purple_debug_info("jabber", "in jabber_si_xfer_bytestreams_send_connected_cb\n"); 666 purple_debug_info("jabber", "in jabber_si_xfer_bytestreams_send_connected_cb\n");
687 667
688 acceptfd = accept(source, NULL, 0); 668 acceptfd = accept(source, NULL, 0);
692 purple_debug_warning("jabber", "accept: %s\n", g_strerror(errno)); 672 purple_debug_warning("jabber", "accept: %s\n", g_strerror(errno));
693 /* Don't cancel the ft - allow it to fall to the next streamhost.*/ 673 /* Don't cancel the ft - allow it to fall to the next streamhost.*/
694 return; 674 return;
695 } 675 }
696 676
697 purple_input_remove(xfer->watcher); 677 purple_input_remove(purple_xfer_get_watcher(xfer));
698 close(source); 678 close(source);
699 jsx->local_streamhost_fd = -1; 679 jsx->local_streamhost_fd = -1;
700 680
701 flags = fcntl(acceptfd, F_GETFL); 681 flags = fcntl(acceptfd, F_GETFL);
702 fcntl(acceptfd, F_SETFL, flags | O_NONBLOCK); 682 fcntl(acceptfd, F_SETFL, flags | O_NONBLOCK);
703 #ifndef _WIN32 683 #ifndef _WIN32
704 fcntl(acceptfd, F_SETFD, FD_CLOEXEC); 684 fcntl(acceptfd, F_SETFD, FD_CLOEXEC);
705 #endif 685 #endif
706 686
707 xfer->watcher = purple_input_add(acceptfd, PURPLE_INPUT_READ, 687 purple_xfer_set_watcher(xfer, purple_input_add(acceptfd, PURPLE_INPUT_READ,
708 jabber_si_xfer_bytestreams_send_read_cb, xfer); 688 jabber_si_xfer_bytestreams_send_read_cb, xfer));
709 } 689 }
710 690
711 static void 691 static void
712 jabber_si_connect_proxy_cb(JabberStream *js, const char *from, 692 jabber_si_connect_proxy_cb(JabberStream *js, const char *from,
713 JabberIqType type, const char *id, 693 JabberIqType type, const char *id,
725 if (!g_list_find(js->file_transfers, xfer)) { 705 if (!g_list_find(js->file_transfers, xfer)) {
726 purple_debug_error("jabber", "Got bytestreams response for no longer existing xfer (%p)\n", xfer); 706 purple_debug_error("jabber", "Got bytestreams response for no longer existing xfer (%p)\n", xfer);
727 return; 707 return;
728 } 708 }
729 709
710 jsx = purple_xfer_get_protocol_data(xfer);
711
730 /* In the case of a direct file transfer, this is expected to return */ 712 /* In the case of a direct file transfer, this is expected to return */
731 if(!xfer->data) 713 if(!jsx)
732 return; 714 return;
733
734 jsx = xfer->data;
735 715
736 if(type != JABBER_IQ_RESULT) { 716 if(type != JABBER_IQ_RESULT) {
737 purple_debug_info("jabber", 717 purple_debug_info("jabber",
738 "jabber_si_xfer_connect_proxy_cb: type = error\n"); 718 "jabber_si_xfer_connect_proxy_cb: type = error\n");
739 /* if IBB is available, open IBB session */ 719 /* if IBB is available, open IBB session */
779 { 759 {
780 gchar *my_jid = g_strdup_printf("%s@%s/%s", jsx->js->user->node, 760 gchar *my_jid = g_strdup_printf("%s@%s/%s", jsx->js->user->node,
781 jsx->js->user->domain, jsx->js->user->resource); 761 jsx->js->user->domain, jsx->js->user->resource);
782 if (!strcmp(jid, my_jid)) { 762 if (!strcmp(jid, my_jid)) {
783 purple_debug_info("jabber", "Got local SOCKS5 streamhost-used.\n"); 763 purple_debug_info("jabber", "Got local SOCKS5 streamhost-used.\n");
784 purple_xfer_start(xfer, xfer->fd, NULL, -1); 764 purple_xfer_start(xfer, purple_xfer_get_fd(xfer), NULL, -1);
785 } else { 765 } else {
786 /* if available, try to revert to IBB... */ 766 /* if available, try to revert to IBB... */
787 if (jsx->stream_method & STREAM_METHOD_IBB) { 767 if (jsx->stream_method & STREAM_METHOD_IBB) {
788 purple_debug_info("jabber", 768 purple_debug_info("jabber",
789 "jabber_si_connect_proxy_cb: trying to revert to IBB\n"); 769 "jabber_si_connect_proxy_cb: trying to revert to IBB\n");
803 g_free(my_jid); 783 g_free(my_jid);
804 return; 784 return;
805 } 785 }
806 786
807 /* Clean up the local streamhost - it isn't going to be used.*/ 787 /* Clean up the local streamhost - it isn't going to be used.*/
808 if (xfer->watcher > 0) { 788 if (purple_xfer_get_watcher(xfer) > 0) {
809 purple_input_remove(xfer->watcher); 789 purple_input_remove(purple_xfer_get_watcher(xfer));
810 xfer->watcher = 0; 790 purple_xfer_set_watcher(xfer, 0);
811 } 791 }
812 if (jsx->local_streamhost_fd >= 0) { 792 if (jsx->local_streamhost_fd >= 0) {
813 close(jsx->local_streamhost_fd); 793 close(jsx->local_streamhost_fd);
814 jsx->local_streamhost_fd = -1; 794 jsx->local_streamhost_fd = -1;
815 } 795 }
833 char port[6]; 813 char port[6];
834 GList *tmp; 814 GList *tmp;
835 JabberBytestreamsStreamhost *sh, *sh2; 815 JabberBytestreamsStreamhost *sh, *sh2;
836 int streamhost_count = 0; 816 int streamhost_count = 0;
837 817
838 jsx = xfer->data; 818 jsx = purple_xfer_get_protocol_data(xfer);
839 jsx->listen_data = NULL; 819 jsx->listen_data = NULL;
840 820
841 /* I'm not sure under which conditions this can happen 821 /* I'm not sure under which conditions this can happen
842 * (it seems like it shouldn't be possible */ 822 * (it seems like it shouldn't be possible */
843 if (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL) { 823 if (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL) {
846 } 826 }
847 827
848 purple_xfer_unref(xfer); 828 purple_xfer_unref(xfer);
849 829
850 iq = jabber_iq_new_query(jsx->js, JABBER_IQ_SET, NS_BYTESTREAMS); 830 iq = jabber_iq_new_query(jsx->js, JABBER_IQ_SET, NS_BYTESTREAMS);
851 xmlnode_set_attrib(iq->node, "to", xfer->who); 831 xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer));
852 query = xmlnode_get_child(iq->node, "query"); 832 query = xmlnode_get_child(iq->node, "query");
853 833
854 xmlnode_set_attrib(query, "sid", jsx->stream_id); 834 xmlnode_set_attrib(query, "sid", jsx->stream_id);
855 835
856 /* If we successfully started listening locally */ 836 /* If we successfully started listening locally */
863 843
864 jsx->local_streamhost_fd = sock; 844 jsx->local_streamhost_fd = sock;
865 845
866 jid = g_strdup_printf("%s@%s/%s", jsx->js->user->node, 846 jid = g_strdup_printf("%s@%s/%s", jsx->js->user->node,
867 jsx->js->user->domain, jsx->js->user->resource); 847 jsx->js->user->domain, jsx->js->user->resource);
868 xfer->local_port = purple_network_get_port_from_fd(sock); 848 purple_xfer_set_local_port(xfer, purple_network_get_port_from_fd(sock));
869 g_snprintf(port, sizeof(port), "%hu", xfer->local_port); 849 g_snprintf(port, sizeof(port), "%hu", purple_xfer_get_local_port(xfer));
870 850
871 public_ip = purple_network_get_my_ip(jsx->js->fd); 851 public_ip = purple_network_get_my_ip(jsx->js->fd);
872 852
873 /* Include the localhost's IPs (for in-network transfers) */ 853 /* Include the localhost's IPs (for in-network transfers) */
874 while (local_ips) { 854 while (local_ips) {
894 } 874 }
895 875
896 g_free(jid); 876 g_free(jid);
897 877
898 /* The listener for the local proxy */ 878 /* The listener for the local proxy */
899 xfer->watcher = purple_input_add(sock, PURPLE_INPUT_READ, 879 purple_xfer_set_watcher(xfer, purple_input_add(sock, PURPLE_INPUT_READ,
900 jabber_si_xfer_bytestreams_send_connected_cb, xfer); 880 jabber_si_xfer_bytestreams_send_connected_cb, xfer));
901 } 881 }
902 882
903 for (tmp = jsx->js->bs_proxies; tmp; tmp = tmp->next) { 883 for (tmp = jsx->js->bs_proxies; tmp; tmp = tmp->next) {
904 sh = tmp->data; 884 sh = tmp->data;
905 885
967 JabberSIXfer *jsx; 947 JabberSIXfer *jsx;
968 PurpleProxyType proxy_type; 948 PurpleProxyType proxy_type;
969 949
970 purple_xfer_ref(xfer); 950 purple_xfer_ref(xfer);
971 951
972 jsx = xfer->data; 952 jsx = purple_xfer_get_protocol_data(xfer);
973 953
974 /* TODO: This should probably be done with an account option instead of 954 /* TODO: This should probably be done with an account option instead of
975 * piggy-backing on the TOR proxy type. */ 955 * piggy-backing on the TOR proxy type. */
976 proxy_type = purple_proxy_info_get_type( 956 proxy_type = purple_proxy_info_get_type(
977 purple_proxy_get_setup(purple_connection_get_account(jsx->js->gc))); 957 purple_proxy_get_setup(purple_connection_get_account(jsx->js->gc)));
978 if (proxy_type == PURPLE_PROXY_TOR) { 958 if (proxy_type == PURPLE_PROXY_TOR) {
979 purple_debug_info("jabber", "Skipping attempting local streamhost.\n"); 959 purple_debug_info("jabber", "Skipping attempting local streamhost.\n");
980 jsx->listen_data = NULL; 960 jsx->listen_data = NULL;
981 } else 961 } else
982 jsx->listen_data = purple_network_listen_range(0, 0, SOCK_STREAM, 962 jsx->listen_data = purple_network_listen_range(0, 0, AF_UNSPEC, SOCK_STREAM, TRUE,
983 jabber_si_xfer_bytestreams_listen_cb, xfer); 963 jabber_si_xfer_bytestreams_listen_cb, xfer);
984 964
985 if (jsx->listen_data == NULL) { 965 if (jsx->listen_data == NULL) {
986 /* We couldn't open a local port. Perhaps we can use a proxy. */ 966 /* We couldn't open a local port. Perhaps we can use a proxy. */
987 jabber_si_xfer_bytestreams_listen_cb(-1, xfer); 967 jabber_si_xfer_bytestreams_listen_cb(-1, xfer);
1015 static void 995 static void
1016 jabber_si_xfer_ibb_recv_data_cb(JabberIBBSession *sess, gpointer data, 996 jabber_si_xfer_ibb_recv_data_cb(JabberIBBSession *sess, gpointer data,
1017 gsize size) 997 gsize size)
1018 { 998 {
1019 PurpleXfer *xfer = (PurpleXfer *) jabber_ibb_session_get_user_data(sess); 999 PurpleXfer *xfer = (PurpleXfer *) jabber_ibb_session_get_user_data(sess);
1020 JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; 1000 JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
1021 1001
1022 if (size <= purple_xfer_get_bytes_remaining(xfer)) { 1002 if (size <= purple_xfer_get_bytes_remaining(xfer)) {
1023 purple_debug_info("jabber", "about to write %" G_GSIZE_FORMAT " bytes from IBB stream\n", 1003 purple_debug_info("jabber", "about to write %" G_GSIZE_FORMAT " bytes from IBB stream\n",
1024 size); 1004 size);
1025 purple_circ_buffer_append(jsx->ibb_buffer, data, size); 1005 purple_circ_buffer_append(jsx->ibb_buffer, data, size);
1035 } 1015 }
1036 1016
1037 static gssize 1017 static gssize
1038 jabber_si_xfer_ibb_read(guchar **out_buffer, PurpleXfer *xfer) 1018 jabber_si_xfer_ibb_read(guchar **out_buffer, PurpleXfer *xfer)
1039 { 1019 {
1040 JabberSIXfer *jsx = xfer->data; 1020 JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
1041 guchar *buffer; 1021 guchar *buffer;
1042 gsize size; 1022 gsize size;
1043 gsize tmp; 1023 gsize tmp;
1044 1024
1045 size = jsx->ibb_buffer->bufused; 1025 size = jsx->ibb_buffer->bufused;
1058 xmlnode *open) 1038 xmlnode *open)
1059 { 1039 {
1060 const gchar *sid = xmlnode_get_attrib(open, "sid"); 1040 const gchar *sid = xmlnode_get_attrib(open, "sid");
1061 PurpleXfer *xfer = jabber_si_xfer_find(js, sid, who); 1041 PurpleXfer *xfer = jabber_si_xfer_find(js, sid, who);
1062 if (xfer) { 1042 if (xfer) {
1063 JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; 1043 JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
1064 JabberIBBSession *sess = 1044 JabberIBBSession *sess =
1065 jabber_ibb_session_create_from_xmlnode(js, who, id, open, xfer); 1045 jabber_ibb_session_create_from_xmlnode(js, who, id, open, xfer);
1066 1046
1067 jabber_si_bytestreams_ibb_timeout_remove(jsx); 1047 jabber_si_bytestreams_ibb_timeout_remove(jsx);
1068 1048
1103 } 1083 }
1104 1084
1105 static gssize 1085 static gssize
1106 jabber_si_xfer_ibb_write(const guchar *buffer, size_t len, PurpleXfer *xfer) 1086 jabber_si_xfer_ibb_write(const guchar *buffer, size_t len, PurpleXfer *xfer)
1107 { 1087 {
1108 JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; 1088 JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
1109 JabberIBBSession *sess = jsx->ibb_session; 1089 JabberIBBSession *sess = jsx->ibb_session;
1110 gsize packet_size = len < jabber_ibb_session_get_max_data_size(sess) ? 1090 gsize packet_size = len < jabber_ibb_session_get_max_data_size(sess) ?
1111 len : jabber_ibb_session_get_max_data_size(sess); 1091 len : jabber_ibb_session_get_max_data_size(sess);
1112 1092
1113 jabber_ibb_session_send_data(sess, buffer, packet_size); 1093 jabber_ibb_session_send_data(sess, buffer, packet_size);
1117 1097
1118 static void 1098 static void
1119 jabber_si_xfer_ibb_sent_cb(JabberIBBSession *sess) 1099 jabber_si_xfer_ibb_sent_cb(JabberIBBSession *sess)
1120 { 1100 {
1121 PurpleXfer *xfer = (PurpleXfer *) jabber_ibb_session_get_user_data(sess); 1101 PurpleXfer *xfer = (PurpleXfer *) jabber_ibb_session_get_user_data(sess);
1122 gsize remaining = purple_xfer_get_bytes_remaining(xfer); 1102 goffset remaining = purple_xfer_get_bytes_remaining(xfer);
1123 1103
1124 if (remaining == 0) { 1104 if (remaining == 0) {
1125 /* close the session */ 1105 /* close the session */
1126 jabber_ibb_session_close(sess); 1106 jabber_ibb_session_close(sess);
1127 purple_xfer_set_completed(xfer, TRUE); 1107 purple_xfer_set_completed(xfer, TRUE);
1147 } 1127 }
1148 1128
1149 static void 1129 static void
1150 jabber_si_xfer_ibb_send_init(JabberStream *js, PurpleXfer *xfer) 1130 jabber_si_xfer_ibb_send_init(JabberStream *js, PurpleXfer *xfer)
1151 { 1131 {
1152 JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; 1132 JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
1153 1133
1154 jsx->ibb_session = jabber_ibb_session_create(js, jsx->stream_id, 1134 jsx->ibb_session = jabber_ibb_session_create(js, jsx->stream_id,
1155 purple_xfer_get_remote_user(xfer), xfer); 1135 purple_xfer_get_remote_user(xfer), xfer);
1156 1136
1157 if (jsx->ibb_session) { 1137 if (jsx->ibb_session) {
1204 return; 1184 return;
1205 } 1185 }
1206 1186
1207 for(field = xmlnode_get_child(x, "field"); field; field = xmlnode_get_next_twin(field)) { 1187 for(field = xmlnode_get_child(x, "field"); field; field = xmlnode_get_next_twin(field)) {
1208 const char *var = xmlnode_get_attrib(field, "var"); 1188 const char *var = xmlnode_get_attrib(field, "var");
1209 JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; 1189 JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
1210 1190
1211 if(var && !strcmp(var, "stream-method")) { 1191 if(var && !strcmp(var, "stream-method")) {
1212 if((value = xmlnode_get_child(field, "value"))) { 1192 if((value = xmlnode_get_child(field, "value"))) {
1213 char *val = xmlnode_get_data(value); 1193 char *val = xmlnode_get_data(value);
1214 if(val && !strcmp(val, NS_BYTESTREAMS)) { 1194 if(val && !strcmp(val, NS_BYTESTREAMS)) {
1235 1215
1236 } 1216 }
1237 1217
1238 static void jabber_si_xfer_send_request(PurpleXfer *xfer) 1218 static void jabber_si_xfer_send_request(PurpleXfer *xfer)
1239 { 1219 {
1240 JabberSIXfer *jsx = xfer->data; 1220 JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
1241 JabberIq *iq; 1221 JabberIq *iq;
1242 xmlnode *si, *file, *feature, *x, *field, *option, *value; 1222 xmlnode *si, *file, *feature, *x, *field, *option, *value;
1243 char buf[32]; 1223 char buf[32];
1244 #if ENABLE_FT_THUMBNAILS 1224 #if ENABLE_FT_THUMBNAILS
1245 gconstpointer thumb; 1225 gconstpointer thumb;
1246 gsize thumb_size; 1226 gsize thumb_size;
1247 1227
1248 purple_xfer_prepare_thumbnail(xfer, "jpeg,png"); 1228 purple_xfer_prepare_thumbnail(xfer, "jpeg,png");
1249 #endif 1229 #endif
1250 xfer->filename = g_path_get_basename(xfer->local_filename); 1230 purple_xfer_set_filename(xfer, g_path_get_basename(purple_xfer_get_local_filename(xfer)));
1251 1231
1252 iq = jabber_iq_new(jsx->js, JABBER_IQ_SET); 1232 iq = jabber_iq_new(jsx->js, JABBER_IQ_SET);
1253 xmlnode_set_attrib(iq->node, "to", xfer->who); 1233 xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer));
1254 si = xmlnode_new_child(iq->node, "si"); 1234 si = xmlnode_new_child(iq->node, "si");
1255 xmlnode_set_namespace(si, "http://jabber.org/protocol/si"); 1235 xmlnode_set_namespace(si, "http://jabber.org/protocol/si");
1256 jsx->stream_id = jabber_get_next_id(jsx->js); 1236 jsx->stream_id = jabber_get_next_id(jsx->js);
1257 xmlnode_set_attrib(si, "id", jsx->stream_id); 1237 xmlnode_set_attrib(si, "id", jsx->stream_id);
1258 xmlnode_set_attrib(si, "profile", NS_SI_FILE_TRANSFER); 1238 xmlnode_set_attrib(si, "profile", NS_SI_FILE_TRANSFER);
1259 1239
1260 file = xmlnode_new_child(si, "file"); 1240 file = xmlnode_new_child(si, "file");
1261 xmlnode_set_namespace(file, NS_SI_FILE_TRANSFER); 1241 xmlnode_set_namespace(file, NS_SI_FILE_TRANSFER);
1262 xmlnode_set_attrib(file, "name", xfer->filename); 1242 xmlnode_set_attrib(file, "name", purple_xfer_get_filename(xfer));
1263 g_snprintf(buf, sizeof(buf), "%" G_GSIZE_FORMAT, xfer->size); 1243 g_snprintf(buf, sizeof(buf), "%" G_GOFFSET_FORMAT, purple_xfer_get_size(xfer));
1264 xmlnode_set_attrib(file, "size", buf); 1244 xmlnode_set_attrib(file, "size", buf);
1265 /* maybe later we'll do hash and date attribs */ 1245 /* maybe later we'll do hash and date attribs */
1266 1246
1267 #if ENABLE_FT_THUMBNAILS 1247 #if ENABLE_FT_THUMBNAILS
1268 /* add thumbnail, if appropriate */ 1248 /* add thumbnail, if appropriate */
1307 jabber_iq_send(iq); 1287 jabber_iq_send(iq);
1308 } 1288 }
1309 1289
1310 static void jabber_si_xfer_free(PurpleXfer *xfer) 1290 static void jabber_si_xfer_free(PurpleXfer *xfer)
1311 { 1291 {
1312 JabberSIXfer *jsx = xfer->data; 1292 JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
1313 1293
1314 if (jsx) { 1294 if (jsx) {
1315 JabberStream *js = jsx->js; 1295 JabberStream *js = jsx->js;
1316 1296
1317 js->file_transfers = g_list_remove(js->file_transfers, xfer); 1297 js->file_transfers = g_list_remove(js->file_transfers, xfer);
1322 purple_network_listen_cancel(jsx->listen_data); 1302 purple_network_listen_cancel(jsx->listen_data);
1323 if (jsx->iq_id != NULL) 1303 if (jsx->iq_id != NULL)
1324 jabber_iq_remove_callback_by_id(js, jsx->iq_id); 1304 jabber_iq_remove_callback_by_id(js, jsx->iq_id);
1325 if (jsx->local_streamhost_fd >= 0) 1305 if (jsx->local_streamhost_fd >= 0)
1326 close(jsx->local_streamhost_fd); 1306 close(jsx->local_streamhost_fd);
1327 if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND && 1307 if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND && purple_xfer_get_fd(xfer) >= 0) {
1328 xfer->fd >= 0) {
1329 purple_debug_info("jabber", "remove port mapping\n"); 1308 purple_debug_info("jabber", "remove port mapping\n");
1330 purple_network_remove_port_mapping(xfer->fd); 1309 purple_network_remove_port_mapping(purple_xfer_get_fd(xfer));
1331 } 1310 }
1332 if (jsx->connect_timeout > 0) 1311 if (jsx->connect_timeout > 0)
1333 purple_timeout_remove(jsx->connect_timeout); 1312 purple_timeout_remove(jsx->connect_timeout);
1334 if (jsx->ibb_timeout_handle > 0) 1313 if (jsx->ibb_timeout_handle > 0)
1335 purple_timeout_remove(jsx->ibb_timeout_handle); 1314 purple_timeout_remove(jsx->ibb_timeout_handle);
1354 g_free(jsx->stream_id); 1333 g_free(jsx->stream_id);
1355 g_free(jsx->iq_id); 1334 g_free(jsx->iq_id);
1356 /* XXX: free other stuff */ 1335 /* XXX: free other stuff */
1357 g_free(jsx->rxqueue); 1336 g_free(jsx->rxqueue);
1358 g_free(jsx); 1337 g_free(jsx);
1359 xfer->data = NULL; 1338 purple_xfer_set_protocol_data(xfer, NULL);
1360 } 1339 }
1361 } 1340 }
1362 1341
1363 /* 1342 /*
1364 * These four functions should only be called from the PurpleXfer functions 1343 * These four functions should only be called from the PurpleXfer functions
1365 * (typically purple_xfer_cancel_(remote|local), purple_xfer_end, or 1344 * (typically purple_xfer_cancel_(remote|local), purple_xfer_end, or
1366 * purple_xfer_request_denied. 1345 * purple_xfer_request_denied.
1367 */ 1346 */
1368 static void jabber_si_xfer_cancel_send(PurpleXfer *xfer) 1347 static void jabber_si_xfer_cancel_send(PurpleXfer *xfer)
1369 { 1348 {
1370 JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; 1349 JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
1371 1350
1372 /* if there is an IBB session active, send close on that */ 1351 /* if there is an IBB session active, send close on that */
1373 if (jsx->ibb_session) { 1352 if (jsx->ibb_session) {
1374 jabber_ibb_session_close(jsx->ibb_session); 1353 jabber_ibb_session_close(jsx->ibb_session);
1375 } 1354 }
1378 } 1357 }
1379 1358
1380 1359
1381 static void jabber_si_xfer_request_denied(PurpleXfer *xfer) 1360 static void jabber_si_xfer_request_denied(PurpleXfer *xfer)
1382 { 1361 {
1383 JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; 1362 JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
1384 JabberStream *js = jsx->js; 1363 JabberStream *js = jsx->js;
1385 1364
1386 /* 1365 /*
1387 * TODO: It's probably an error if jsx->iq_id == NULL. g_return_if_fail 1366 * TODO: It's probably an error if jsx->iq_id == NULL. g_return_if_fail
1388 * might be warranted. 1367 * might be warranted.
1389 */ 1368 */
1390 if (jsx->iq_id && !jsx->accepted) { 1369 if (jsx->iq_id && !jsx->accepted) {
1391 JabberIq *iq; 1370 JabberIq *iq;
1392 xmlnode *error, *child; 1371 xmlnode *error, *child;
1393 iq = jabber_iq_new(js, JABBER_IQ_ERROR); 1372 iq = jabber_iq_new(js, JABBER_IQ_ERROR);
1394 xmlnode_set_attrib(iq->node, "to", xfer->who); 1373 xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer));
1395 jabber_iq_set_id(iq, jsx->iq_id); 1374 jabber_iq_set_id(iq, jsx->iq_id);
1396 1375
1397 error = xmlnode_new_child(iq->node, "error"); 1376 error = xmlnode_new_child(iq->node, "error");
1398 xmlnode_set_attrib(error, "type", "cancel"); 1377 xmlnode_set_attrib(error, "type", "cancel");
1399 child = xmlnode_new_child(error, "forbidden"); 1378 child = xmlnode_new_child(error, "forbidden");
1410 } 1389 }
1411 1390
1412 1391
1413 static void jabber_si_xfer_cancel_recv(PurpleXfer *xfer) 1392 static void jabber_si_xfer_cancel_recv(PurpleXfer *xfer)
1414 { 1393 {
1415 JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; 1394 JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
1416 /* if there is an IBB session active, send close */ 1395 /* if there is an IBB session active, send close */
1417 if (jsx->ibb_session) { 1396 if (jsx->ibb_session) {
1418 jabber_ibb_session_close(jsx->ibb_session); 1397 jabber_ibb_session_close(jsx->ibb_session);
1419 } 1398 }
1420 jabber_si_xfer_free(xfer); 1399 jabber_si_xfer_free(xfer);
1430 1409
1431 static void jabber_si_xfer_send_disco_cb(JabberStream *js, const char *who, 1410 static void jabber_si_xfer_send_disco_cb(JabberStream *js, const char *who,
1432 JabberCapabilities capabilities, gpointer data) 1411 JabberCapabilities capabilities, gpointer data)
1433 { 1412 {
1434 PurpleXfer *xfer = (PurpleXfer *) data; 1413 PurpleXfer *xfer = (PurpleXfer *) data;
1435 JabberSIXfer *jsx = (JabberSIXfer *) xfer->data; 1414 JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
1436 1415
1437 if (capabilities & JABBER_CAP_IBB) { 1416 if (capabilities & JABBER_CAP_IBB) {
1438 purple_debug_info("jabber", 1417 purple_debug_info("jabber",
1439 "jabber_si_xfer_send_disco_cb: remote JID supports IBB\n"); 1418 "jabber_si_xfer_send_disco_cb: remote JID supports IBB\n");
1440 jsx->stream_method |= STREAM_METHOD_IBB; 1419 jsx->stream_method |= STREAM_METHOD_IBB;
1456 purple_xfer_cancel_local(xfer); 1435 purple_xfer_cancel_local(xfer);
1457 } 1436 }
1458 1437
1459 static void do_transfer_send(PurpleXfer *xfer, const char *resource) 1438 static void do_transfer_send(PurpleXfer *xfer, const char *resource)
1460 { 1439 {
1461 JabberSIXfer *jsx = xfer->data; 1440 JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
1462 char **who_v = g_strsplit(xfer->who, "/", 2); 1441 char **who_v = g_strsplit(purple_xfer_get_remote_user(xfer), "/", 2);
1463 char *who; 1442 char *who;
1464 JabberBuddy *jb; 1443 JabberBuddy *jb;
1465 JabberBuddyResource *jbr = NULL; 1444 JabberBuddyResource *jbr = NULL;
1466 1445
1467 jb = jabber_buddy_find(jsx->js, who_v[0], FALSE); 1446 jb = jabber_buddy_find(jsx->js, who_v[0], FALSE);
1506 do_transfer_send(xfer, selected_label); 1485 do_transfer_send(xfer, selected_label);
1507 } 1486 }
1508 1487
1509 static void jabber_si_xfer_init(PurpleXfer *xfer) 1488 static void jabber_si_xfer_init(PurpleXfer *xfer)
1510 { 1489 {
1511 JabberSIXfer *jsx = xfer->data; 1490 JabberSIXfer *jsx = purple_xfer_get_protocol_data(xfer);
1512 JabberIq *iq; 1491 JabberIq *iq;
1513 if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) { 1492 if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) {
1514 JabberBuddy *jb; 1493 JabberBuddy *jb;
1515 JabberBuddyResource *jbr = NULL; 1494 JabberBuddyResource *jbr = NULL;
1516 char *resource; 1495 char *resource;
1517 GList *resources = NULL; 1496 GList *resources = NULL;
1518 1497
1519 if(NULL != (resource = jabber_get_resource(xfer->who))) { 1498 if(NULL != (resource = jabber_get_resource(purple_xfer_get_remote_user(xfer)))) {
1520 /* they've specified a resource, no need to ask or 1499 /* they've specified a resource, no need to ask or
1521 * default or anything, just do it */ 1500 * default or anything, just do it */
1522 1501
1523 do_transfer_send(xfer, resource); 1502 do_transfer_send(xfer, resource);
1524 g_free(resource); 1503 g_free(resource);
1525 return; 1504 return;
1526 } 1505 }
1527 1506
1528 jb = jabber_buddy_find(jsx->js, xfer->who, TRUE); 1507 jb = jabber_buddy_find(jsx->js, purple_xfer_get_remote_user(xfer), TRUE);
1529 1508
1530 if (jb) { 1509 if (jb) {
1531 GList *l; 1510 GList *l;
1532 1511
1533 for (l = jb->resources ; l ; l = g_list_next(l)) { 1512 for (l = jb->resources ; l ; l = g_list_next(l)) {
1547 * whose presence we're not subscribed to, or 1526 * whose presence we're not subscribed to, or
1548 * someone who is offline. Let's inform the user */ 1527 * someone who is offline. Let's inform the user */
1549 char *msg; 1528 char *msg;
1550 1529
1551 if(!jb) { 1530 if(!jb) {
1552 msg = g_strdup_printf(_("Unable to send file to %s, invalid JID"), xfer->who); 1531 msg = g_strdup_printf(_("Unable to send file to %s, invalid JID"), purple_xfer_get_remote_user(xfer));
1553 } else if(jb->subscription & JABBER_SUB_TO) { 1532 } else if(jb->subscription & JABBER_SUB_TO) {
1554 msg = g_strdup_printf(_("Unable to send file to %s, user is not online"), xfer->who); 1533 msg = g_strdup_printf(_("Unable to send file to %s, user is not online"), purple_xfer_get_remote_user(xfer));
1555 } else { 1534 } else {
1556 msg = g_strdup_printf(_("Unable to send file to %s, not subscribed to user presence"), xfer->who); 1535 msg = g_strdup_printf(_("Unable to send file to %s, not subscribed to user presence"), purple_xfer_get_remote_user(xfer));
1557 } 1536 }
1558 1537
1559 purple_notify_error(jsx->js->gc, _("File Send Failed"), _("File Send Failed"), msg); 1538 purple_notify_error(jsx->js->gc, _("File Send Failed"), _("File Send Failed"), msg);
1560 g_free(msg); 1539 g_free(msg);
1561 } else if (g_list_length(resources) == 1) { 1540 } else if (g_list_length(resources) == 1) {
1564 jbr = resources->data; 1543 jbr = resources->data;
1565 do_transfer_send(xfer, jbr->name); 1544 do_transfer_send(xfer, jbr->name);
1566 } else { 1545 } else {
1567 /* we've got multiple resources, we need to pick one to send to */ 1546 /* we've got multiple resources, we need to pick one to send to */
1568 GList *l; 1547 GList *l;
1569 char *msg = g_strdup_printf(_("Please select the resource of %s to which you would like to send a file"), xfer->who); 1548 char *msg = g_strdup_printf(_("Please select the resource of %s to which you would like to send a file"), purple_xfer_get_remote_user(xfer));
1570 PurpleRequestFields *fields = purple_request_fields_new(); 1549 PurpleRequestFields *fields = purple_request_fields_new();
1571 PurpleRequestField *field = purple_request_field_choice_new("resource", _("Resource"), 0); 1550 PurpleRequestField *field = purple_request_field_choice_new("resource", _("Resource"), 0);
1572 PurpleRequestFieldGroup *group = purple_request_field_group_new(NULL); 1551 PurpleRequestFieldGroup *group = purple_request_field_group_new(NULL);
1573 1552
1574 for(l = resources; l; l = l->next) { 1553 for(l = resources; l; l = l->next) {
1580 1559
1581 purple_request_fields_add_group(fields, group); 1560 purple_request_fields_add_group(fields, group);
1582 1561
1583 purple_request_fields(jsx->js->gc, _("Select a Resource"), msg, NULL, fields, 1562 purple_request_fields(jsx->js->gc, _("Select a Resource"), msg, NULL, fields,
1584 _("Send File"), G_CALLBACK(resource_select_ok_cb), _("Cancel"), G_CALLBACK(resource_select_cancel_cb), 1563 _("Send File"), G_CALLBACK(resource_select_ok_cb), _("Cancel"), G_CALLBACK(resource_select_cancel_cb),
1585 jsx->js->gc->account, xfer->who, NULL, xfer); 1564 purple_connection_get_account(jsx->js->gc), purple_xfer_get_remote_user(xfer), NULL, xfer);
1586 1565
1587 g_free(msg); 1566 g_free(msg);
1588 } 1567 }
1589 1568
1590 g_list_free(resources); 1569 g_list_free(resources);
1591 } else { 1570 } else {
1592 xmlnode *si, *feature, *x, *field, *value; 1571 xmlnode *si, *feature, *x, *field, *value;
1593 1572
1594 iq = jabber_iq_new(jsx->js, JABBER_IQ_RESULT); 1573 iq = jabber_iq_new(jsx->js, JABBER_IQ_RESULT);
1595 xmlnode_set_attrib(iq->node, "to", xfer->who); 1574 xmlnode_set_attrib(iq->node, "to", purple_xfer_get_remote_user(xfer));
1596 if(jsx->iq_id) 1575 if(jsx->iq_id)
1597 jabber_iq_set_id(iq, jsx->iq_id); 1576 jabber_iq_set_id(iq, jsx->iq_id);
1598 else 1577 else
1599 purple_debug_error("jabber", "Sending SI result with new IQ id.\n"); 1578 purple_debug_error("jabber", "Sending SI result with new IQ id.\n");
1600 1579
1634 JabberStream *js; 1613 JabberStream *js;
1635 1614
1636 PurpleXfer *xfer; 1615 PurpleXfer *xfer;
1637 JabberSIXfer *jsx; 1616 JabberSIXfer *jsx;
1638 1617
1639 js = gc->proto_data; 1618 js = purple_connection_get_protocol_data(gc);
1640 1619
1641 xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who); 1620 xfer = purple_xfer_new(purple_connection_get_account(gc), PURPLE_XFER_SEND, who);
1642 if (xfer) 1621 if (xfer)
1643 { 1622 {
1644 xfer->data = jsx = g_new0(JabberSIXfer, 1); 1623 jsx = g_new0(JabberSIXfer, 1);
1624 purple_xfer_set_protocol_data(xfer, jsx);
1645 jsx->js = js; 1625 jsx->js = js;
1646 jsx->local_streamhost_fd = -1; 1626 jsx->local_streamhost_fd = -1;
1647 1627
1648 jsx->ibb_session = NULL; 1628 jsx->ibb_session = NULL;
1649 1629
1694 xmlnode *file, *feature, *x, *field, *option, *value; 1674 xmlnode *file, *feature, *x, *field, *option, *value;
1695 #if ENABLE_FT_THUMBNAILS 1675 #if ENABLE_FT_THUMBNAILS
1696 xmlnode *thumbnail; 1676 xmlnode *thumbnail;
1697 #endif 1677 #endif
1698 const char *stream_id, *filename, *filesize_c, *profile; 1678 const char *stream_id, *filename, *filesize_c, *profile;
1699 guint64 filesize_64 = 0; 1679 goffset filesize = 0;
1700 size_t filesize = 0;
1701 1680
1702 if(!(profile = xmlnode_get_attrib(si, "profile")) || 1681 if(!(profile = xmlnode_get_attrib(si, "profile")) ||
1703 strcmp(profile, NS_SI_FILE_TRANSFER)) 1682 strcmp(profile, NS_SI_FILE_TRANSFER))
1704 return; 1683 return;
1705 1684
1711 1690
1712 if(!(filename = xmlnode_get_attrib(file, "name"))) 1691 if(!(filename = xmlnode_get_attrib(file, "name")))
1713 return; 1692 return;
1714 1693
1715 if((filesize_c = xmlnode_get_attrib(file, "size"))) 1694 if((filesize_c = xmlnode_get_attrib(file, "size")))
1716 filesize_64 = g_ascii_strtoull(filesize_c, NULL, 10); 1695 filesize = g_ascii_strtoull(filesize_c, NULL, 10);
1717 /* TODO 3.0.0: When the core uses a guint64, this is redundant.
1718 * See #8477.
1719 */
1720 if (filesize_64 > G_MAXSIZE) {
1721 /* Should this pop up a warning? */
1722 purple_debug_warning("jabber", "Unable to transfer file (too large)"
1723 " -- see #8477 for more details.");
1724 return;
1725 }
1726 filesize = filesize_64;
1727 1696
1728 if(!(feature = xmlnode_get_child(si, "feature"))) 1697 if(!(feature = xmlnode_get_child(si, "feature")))
1729 return; 1698 return;
1730 1699
1731 if(!(x = xmlnode_get_child_with_namespace(feature, "x", "jabber:x:data"))) 1700 if(!(x = xmlnode_get_child_with_namespace(feature, "x", "jabber:x:data")))
1772 1741
1773 jsx->js = js; 1742 jsx->js = js;
1774 jsx->stream_id = g_strdup(stream_id); 1743 jsx->stream_id = g_strdup(stream_id);
1775 jsx->iq_id = g_strdup(id); 1744 jsx->iq_id = g_strdup(id);
1776 1745
1777 xfer = purple_xfer_new(js->gc->account, PURPLE_XFER_RECEIVE, from); 1746 xfer = purple_xfer_new(purple_connection_get_account(js->gc), PURPLE_XFER_RECEIVE, from);
1778 g_return_if_fail(xfer != NULL); 1747 g_return_if_fail(xfer != NULL);
1779 1748
1780 xfer->data = jsx; 1749 purple_xfer_set_protocol_data(xfer, jsx);
1781 1750
1782 purple_xfer_set_filename(xfer, filename); 1751 purple_xfer_set_filename(xfer, filename);
1783 if(filesize > 0) 1752 if(filesize > 0)
1784 purple_xfer_set_size(xfer, filesize); 1753 purple_xfer_set_size(xfer, filesize);
1785 1754