Changeset 5ebff60 for protocols/jabber/si.c
- Timestamp:
- 2015-02-20T22:50:54Z (9 years ago)
- Branches:
- master
- Children:
- 0b9daac, 3d45471, 7733b8c
- Parents:
- af359b4
- git-author:
- Indent <please@…> (19-02-15 05:47:20)
- git-committer:
- dequis <dx@…> (20-02-15 22:50:54)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
protocols/jabber/si.c
raf359b4 r5ebff60 25 25 #include "sha1.h" 26 26 27 void jabber_si_answer_request( file_transfer_t *ft);28 int jabber_si_send_request(struct im_connection *ic, char *who, struct jabber_transfer *tf 27 void jabber_si_answer_request(file_transfer_t *ft); 28 int jabber_si_send_request(struct im_connection *ic, char *who, struct jabber_transfer *tf); 29 29 30 30 /* file_transfer free() callback */ 31 void jabber_si_free_transfer( 31 void jabber_si_free_transfer(file_transfer_t *ft) 32 32 { 33 33 struct jabber_transfer *tf = ft->data; 34 34 struct jabber_data *jd = tf->ic->proto_data; 35 35 36 if ( tf->watch_in ) 37 { 38 b_event_remove( tf->watch_in ); 36 if (tf->watch_in) { 37 b_event_remove(tf->watch_in); 39 38 tf->watch_in = 0; 40 39 } 41 40 42 jd->filetransfers = g_slist_remove( jd->filetransfers, tf ); 43 44 if( tf->fd != -1 ) 45 { 46 closesocket( tf->fd ); 41 jd->filetransfers = g_slist_remove(jd->filetransfers, tf); 42 43 if (tf->fd != -1) { 44 closesocket(tf->fd); 47 45 tf->fd = -1; 48 46 } 49 47 50 if( tf->disco_timeout ) 51 b_event_remove( tf->disco_timeout ); 52 53 g_free( tf->ini_jid ); 54 g_free( tf->tgt_jid ); 55 g_free( tf->iq_id ); 56 g_free( tf->sid ); 57 g_free( tf ); 48 if (tf->disco_timeout) { 49 b_event_remove(tf->disco_timeout); 50 } 51 52 g_free(tf->ini_jid); 53 g_free(tf->tgt_jid); 54 g_free(tf->iq_id); 55 g_free(tf->sid); 56 g_free(tf); 58 57 } 59 58 60 59 /* file_transfer canceled() callback */ 61 void jabber_si_canceled( file_transfer_t *ft, char *reason)60 void jabber_si_canceled(file_transfer_t *ft, char *reason) 62 61 { 63 62 struct jabber_transfer *tf = ft->data; 64 63 struct xt_node *reply, *iqnode; 65 64 66 if ( tf->accepted )65 if (tf->accepted) { 67 66 return; 68 69 iqnode = jabber_make_packet( "iq", "error", tf->ini_jid, NULL ); 70 xt_add_attr( iqnode, "id", tf->iq_id ); 71 reply = jabber_make_error_packet( iqnode, "forbidden", "cancel", "403" ); 72 xt_free_node( iqnode ); 73 74 if( !jabber_write_packet( tf->ic, reply ) ) 75 imcb_log( tf->ic, "WARNING: Error generating reply to file transfer request" ); 76 xt_free_node( reply ); 77 78 } 79 80 int jabber_si_check_features( struct jabber_transfer *tf, GSList *features ) { 67 } 68 69 iqnode = jabber_make_packet("iq", "error", tf->ini_jid, NULL); 70 xt_add_attr(iqnode, "id", tf->iq_id); 71 reply = jabber_make_error_packet(iqnode, "forbidden", "cancel", "403"); 72 xt_free_node(iqnode); 73 74 if (!jabber_write_packet(tf->ic, reply)) { 75 imcb_log(tf->ic, "WARNING: Error generating reply to file transfer request"); 76 } 77 xt_free_node(reply); 78 79 } 80 81 int jabber_si_check_features(struct jabber_transfer *tf, GSList *features) 82 { 81 83 int foundft = FALSE, foundbt = FALSE, foundsi = FALSE; 82 84 83 while ( features ) 84 { 85 if( !strcmp( features->data, XMLNS_FILETRANSFER ) ) 85 while (features) { 86 if (!strcmp(features->data, XMLNS_FILETRANSFER)) { 86 87 foundft = TRUE; 87 if( !strcmp( features->data, XMLNS_BYTESTREAMS ) ) 88 } 89 if (!strcmp(features->data, XMLNS_BYTESTREAMS)) { 88 90 foundbt = TRUE; 89 if( !strcmp( features->data, XMLNS_SI ) ) 91 } 92 if (!strcmp(features->data, XMLNS_SI)) { 90 93 foundsi = TRUE; 94 } 91 95 92 96 features = g_slist_next(features); 93 97 } 94 98 95 if( !foundft ) 96 imcb_file_canceled( tf->ic, tf->ft, "Buddy's client doesn't feature file transfers" ); 97 else if( !foundbt ) 98 imcb_file_canceled( tf->ic, tf->ft, "Buddy's client doesn't feature byte streams (required)" ); 99 else if( !foundsi ) 100 imcb_file_canceled( tf->ic, tf->ft, "Buddy's client doesn't feature stream initiation (required)" ); 101 99 if (!foundft) { 100 imcb_file_canceled(tf->ic, tf->ft, "Buddy's client doesn't feature file transfers"); 101 } else if (!foundbt) { 102 imcb_file_canceled(tf->ic, tf->ft, "Buddy's client doesn't feature byte streams (required)"); 103 } else if (!foundsi) { 104 imcb_file_canceled(tf->ic, tf->ft, "Buddy's client doesn't feature stream initiation (required)"); 105 } 106 102 107 return foundft && foundbt && foundsi; 103 108 } 104 109 105 void jabber_si_transfer_start( struct jabber_transfer *tf ) { 106 107 if( !jabber_si_check_features( tf, tf->bud->features ) ) 110 void jabber_si_transfer_start(struct jabber_transfer *tf) 111 { 112 113 if (!jabber_si_check_features(tf, tf->bud->features)) { 108 114 return; 109 115 } 116 110 117 /* send the request to our buddy */ 111 jabber_si_send_request( tf->ic, tf->bud->full_jid, tf);118 jabber_si_send_request(tf->ic, tf->bud->full_jid, tf); 112 119 113 120 /* and start the receive logic */ 114 imcb_file_recv_start( tf->ic, tf->ft);115 116 } 117 118 gboolean jabber_si_waitfor_disco( gpointer data, gint fd, b_input_condition cond)121 imcb_file_recv_start(tf->ic, tf->ft); 122 123 } 124 125 gboolean jabber_si_waitfor_disco(gpointer data, gint fd, b_input_condition cond) 119 126 { 120 127 struct jabber_transfer *tf = data; … … 123 130 tf->disco_timeout_fired++; 124 131 125 if ( tf->bud->features && jd->have_streamhosts==1) {132 if (tf->bud->features && jd->have_streamhosts == 1) { 126 133 tf->disco_timeout = 0; 127 jabber_si_transfer_start( tf);134 jabber_si_transfer_start(tf); 128 135 return FALSE; 129 136 } 130 137 131 138 /* 8 seconds should be enough for server and buddy to respond */ 132 if ( tf->disco_timeout_fired < 16 )139 if (tf->disco_timeout_fired < 16) { 133 140 return TRUE; 134 135 if( !tf->bud->features && jd->have_streamhosts!=1 ) 136 imcb_log( tf->ic, "Couldn't get buddy's features nor discover all services of the server" ); 137 else if( !tf->bud->features ) 138 imcb_log( tf->ic, "Couldn't get buddy's features" ); 139 else 140 imcb_log( tf->ic, "Couldn't discover some of the server's services" ); 141 141 } 142 143 if (!tf->bud->features && jd->have_streamhosts != 1) { 144 imcb_log(tf->ic, "Couldn't get buddy's features nor discover all services of the server"); 145 } else if (!tf->bud->features) { 146 imcb_log(tf->ic, "Couldn't get buddy's features"); 147 } else { 148 imcb_log(tf->ic, "Couldn't discover some of the server's services"); 149 } 150 142 151 tf->disco_timeout = 0; 143 jabber_si_transfer_start( tf);152 jabber_si_transfer_start(tf); 144 153 return FALSE; 145 154 } 146 155 147 void jabber_si_transfer_request( struct im_connection *ic, file_transfer_t *ft, char *who )156 void jabber_si_transfer_request(struct im_connection *ic, file_transfer_t *ft, char *who) 148 157 { 149 158 struct jabber_transfer *tf; … … 152 161 char *server = jd->server, *s; 153 162 154 if ( ( s = strchr( who, '=' ) ) && jabber_chat_by_jid( ic, s + 1 ) )155 bud = jabber_buddy_by_ext_jid( ic, who, 0);156 else157 bud = jabber_buddy_by_jid( ic, who, 0);158 159 if( bud == NULL ) 160 {161 imcb_file_canceled( ic, ft, "Couldn't find buddy (BUG?)");163 if ((s = strchr(who, '=')) && jabber_chat_by_jid(ic, s + 1)) { 164 bud = jabber_buddy_by_ext_jid(ic, who, 0); 165 } else { 166 bud = jabber_buddy_by_jid(ic, who, 0); 167 } 168 169 if (bud == NULL) { 170 imcb_file_canceled(ic, ft, "Couldn't find buddy (BUG?)"); 162 171 return; 163 172 } 164 165 imcb_log( ic, "Trying to send %s(%zd bytes) to %s", ft->file_name, ft->file_size, who);166 167 tf = g_new0( struct jabber_transfer, 1);173 174 imcb_log(ic, "Trying to send %s(%zd bytes) to %s", ft->file_name, ft->file_size, who); 175 176 tf = g_new0(struct jabber_transfer, 1); 168 177 169 178 tf->ic = ic; … … 175 184 ft->write = jabber_bs_send_write; 176 185 177 jd->filetransfers = g_slist_prepend( jd->filetransfers, tf);186 jd->filetransfers = g_slist_prepend(jd->filetransfers, tf); 178 187 179 188 /* query buddy's features and server's streaming proxies if neccessary */ 180 189 181 if( !tf->bud->features ) 182 jabber_iq_query_features( ic, bud->full_jid ); 190 if (!tf->bud->features) { 191 jabber_iq_query_features(ic, bud->full_jid); 192 } 183 193 184 194 /* If <auto> is not set don't check for proxies */ 185 if ( ( jd->have_streamhosts!=1 ) && ( jd->streamhosts==NULL) &&186 ( strstr( set_getstr( &ic->acc->set, "proxy" ), "<auto>" ) != NULL )) {195 if ((jd->have_streamhosts != 1) && (jd->streamhosts == NULL) && 196 (strstr(set_getstr(&ic->acc->set, "proxy"), "<auto>") != NULL)) { 187 197 jd->have_streamhosts = 0; 188 jabber_iq_query_server( ic, server, XMLNS_DISCO_ITEMS);189 } else if ( jd->streamhosts!=NULL )198 jabber_iq_query_server(ic, server, XMLNS_DISCO_ITEMS); 199 } else if (jd->streamhosts != NULL) { 190 200 jd->have_streamhosts = 1; 191 192 /* if we had to do a query, wait for the result. 201 } 202 203 /* if we had to do a query, wait for the result. 193 204 * Otherwise fire away. */ 194 if( !tf->bud->features || jd->have_streamhosts!=1 ) 195 tf->disco_timeout = b_timeout_add( 500, jabber_si_waitfor_disco, tf ); 196 else 197 jabber_si_transfer_start( tf ); 205 if (!tf->bud->features || jd->have_streamhosts != 1) { 206 tf->disco_timeout = b_timeout_add(500, jabber_si_waitfor_disco, tf); 207 } else { 208 jabber_si_transfer_start(tf); 209 } 198 210 } 199 211 … … 205 217 * Then we wait for imcb to call the accept or cancel callbacks. 206 218 */ 207 int jabber_si_handle_request( 219 int jabber_si_handle_request(struct im_connection *ic, struct xt_node *node, struct xt_node *sinode) 208 220 { 209 221 struct xt_node *c, *d, *reply; … … 216 228 struct jabber_data *jd = ic->proto_data; 217 229 file_transfer_t *ft; 218 230 219 231 /* All this means we expect something like this: ( I think ) 220 232 * <iq from=... to=... id=...> 221 * 222 * 223 * 224 * 225 * 233 * <si id=id xmlns=si profile=ft> 234 * <file xmlns=ft/> 235 * <feature xmlns=feature> 236 * <x xmlns=xdata type=submit> 237 * <field var=stream-method> 226 238 * 227 239 */ 228 if( !( ini_jid = xt_find_attr( node, "from" ) ) || 229 !( tgt_jid = xt_find_attr( node, "to" ) ) || 230 !( iq_id = xt_find_attr( node, "id" ) ) || 231 !( sid = xt_find_attr( sinode, "id" ) ) || 232 !( cmp = xt_find_attr( sinode, "profile" ) ) || 233 !( 0 == strcmp( cmp, XMLNS_FILETRANSFER ) ) || 234 !( d = xt_find_node( sinode->children, "file" ) ) || 235 !( cmp = xt_find_attr( d, "xmlns" ) ) || 236 !( 0 == strcmp( cmp, XMLNS_FILETRANSFER ) ) || 237 !( name = xt_find_attr( d, "name" ) ) || 238 !( size_s = xt_find_attr( d, "size" ) ) || 239 !( 1 == sscanf( size_s, "%zd", &size ) ) || 240 !( d = xt_find_node( sinode->children, "feature" ) ) || 241 !( cmp = xt_find_attr( d, "xmlns" ) ) || 242 !( 0 == strcmp( cmp, XMLNS_FEATURE ) ) || 243 !( d = xt_find_node( d->children, "x" ) ) || 244 !( cmp = xt_find_attr( d, "xmlns" ) ) || 245 !( 0 == strcmp( cmp, XMLNS_XDATA ) ) || 246 !( cmp = xt_find_attr( d, "type" ) ) || 247 !( 0 == strcmp( cmp, "form" ) ) || 248 !( d = xt_find_node( d->children, "field" ) ) || 249 !( cmp = xt_find_attr( d, "var" ) ) || 250 !( 0 == strcmp( cmp, "stream-method" ) ) ) 251 { 252 imcb_log( ic, "WARNING: Received incomplete Stream Initiation request" ); 253 } 254 else 255 { 240 if (!(ini_jid = xt_find_attr(node, "from")) || 241 !(tgt_jid = xt_find_attr(node, "to")) || 242 !(iq_id = xt_find_attr(node, "id")) || 243 !(sid = xt_find_attr(sinode, "id")) || 244 !(cmp = xt_find_attr(sinode, "profile")) || 245 !(0 == strcmp(cmp, XMLNS_FILETRANSFER)) || 246 !(d = xt_find_node(sinode->children, "file")) || 247 !(cmp = xt_find_attr(d, "xmlns")) || 248 !(0 == strcmp(cmp, XMLNS_FILETRANSFER)) || 249 !(name = xt_find_attr(d, "name")) || 250 !(size_s = xt_find_attr(d, "size")) || 251 !(1 == sscanf(size_s, "%zd", &size)) || 252 !(d = xt_find_node(sinode->children, "feature")) || 253 !(cmp = xt_find_attr(d, "xmlns")) || 254 !(0 == strcmp(cmp, XMLNS_FEATURE)) || 255 !(d = xt_find_node(d->children, "x")) || 256 !(cmp = xt_find_attr(d, "xmlns")) || 257 !(0 == strcmp(cmp, XMLNS_XDATA)) || 258 !(cmp = xt_find_attr(d, "type")) || 259 !(0 == strcmp(cmp, "form")) || 260 !(d = xt_find_node(d->children, "field")) || 261 !(cmp = xt_find_attr(d, "var")) || 262 !(0 == strcmp(cmp, "stream-method"))) { 263 imcb_log(ic, "WARNING: Received incomplete Stream Initiation request"); 264 } else { 256 265 /* Check if we support one of the options */ 257 266 258 267 c = d->children; 259 while( ( c = xt_find_node( c, "option" ) ) ) 260 if( ( d = xt_find_node( c->children, "value" ) ) && 261 ( d->text != NULL ) && 262 ( strcmp( d->text, XMLNS_BYTESTREAMS ) == 0 ) ) 263 { 268 while ((c = xt_find_node(c, "option"))) { 269 if ((d = xt_find_node(c->children, "value")) && 270 (d->text != NULL) && 271 (strcmp(d->text, XMLNS_BYTESTREAMS) == 0)) { 264 272 requestok = TRUE; 265 273 break; 266 } 267 else 268 { 274 } else { 269 275 c = c->next; 270 276 } 271 272 if ( !requestok ) 273 imcb_log( ic, "WARNING: Unsupported file transfer request from %s", ini_jid); 274 } 275 276 if( requestok ) 277 { 277 } 278 279 if (!requestok) { 280 imcb_log(ic, "WARNING: Unsupported file transfer request from %s", ini_jid); 281 } 282 } 283 284 if (requestok) { 278 285 /* Figure out who the transfer should come frome... */ 279 286 280 287 ext_jid = ini_jid; 281 if( ( s = strchr( ini_jid, '/' ) ) ) 282 { 283 if( ( bud = jabber_buddy_by_jid( ic, ini_jid, GET_BUDDY_EXACT ) ) ) 284 { 285 bud->last_msg = time( NULL ); 288 if ((s = strchr(ini_jid, '/'))) { 289 if ((bud = jabber_buddy_by_jid(ic, ini_jid, GET_BUDDY_EXACT))) { 290 bud->last_msg = time(NULL); 286 291 ext_jid = bud->ext_jid ? : bud->bare_jid; 292 } else { 293 *s = 0; /* We need to generate a bare JID now. */ 287 294 } 288 else 289 *s = 0; /* We need to generate a bare JID now. */ 290 } 291 292 if( !( ft = imcb_file_send_start( ic, ext_jid, name, size ) ) ) 293 { 294 imcb_log( ic, "WARNING: Error handling transfer request from %s", ini_jid); 295 } 296 297 if (!(ft = imcb_file_send_start(ic, ext_jid, name, size))) { 298 imcb_log(ic, "WARNING: Error handling transfer request from %s", ini_jid); 295 299 requestok = FALSE; 296 300 } 297 301 298 if ( s )302 if (s) { 299 303 *s = '/'; 300 } 301 302 if( !requestok ) 303 { 304 reply = jabber_make_error_packet( node, "item-not-found", "cancel", NULL ); 305 if (!jabber_write_packet( ic, reply )) 306 imcb_log( ic, "WARNING: Error generating reply to file transfer request" ); 307 xt_free_node( reply ); 304 } 305 } 306 307 if (!requestok) { 308 reply = jabber_make_error_packet(node, "item-not-found", "cancel", NULL); 309 if (!jabber_write_packet(ic, reply)) { 310 imcb_log(ic, "WARNING: Error generating reply to file transfer request"); 311 } 312 xt_free_node(reply); 308 313 return XT_HANDLED; 309 314 } … … 311 316 /* Request is fine. */ 312 317 313 tf = g_new0( struct jabber_transfer, 1);314 315 tf->ini_jid = g_strdup( ini_jid);316 tf->tgt_jid = g_strdup( tgt_jid);317 tf->iq_id = g_strdup( iq_id);318 tf->sid = g_strdup( sid);318 tf = g_new0(struct jabber_transfer, 1); 319 320 tf->ini_jid = g_strdup(ini_jid); 321 tf->tgt_jid = g_strdup(tgt_jid); 322 tf->iq_id = g_strdup(iq_id); 323 tf->sid = g_strdup(sid); 319 324 tf->ic = ic; 320 325 tf->ft = ft; … … 325 330 tf->ft->canceled = jabber_si_canceled; 326 331 327 jd->filetransfers = g_slist_prepend( jd->filetransfers, tf);332 jd->filetransfers = g_slist_prepend(jd->filetransfers, tf); 328 333 329 334 return XT_HANDLED; … … 336 341 * (currently that can only be a SOCKS5 bytestream) 337 342 */ 338 void jabber_si_answer_request( file_transfer_t *ft ) { 343 void jabber_si_answer_request(file_transfer_t *ft) 344 { 339 345 struct jabber_transfer *tf = ft->data; 340 346 struct xt_node *node, *sinode, *reply; 341 347 342 348 /* generate response, start with the SI tag */ 343 sinode = xt_new_node( "si", NULL, NULL);344 xt_add_attr( sinode, "xmlns", XMLNS_SI);345 xt_add_attr( sinode, "profile", XMLNS_FILETRANSFER);346 xt_add_attr( sinode, "id", tf->sid);349 sinode = xt_new_node("si", NULL, NULL); 350 xt_add_attr(sinode, "xmlns", XMLNS_SI); 351 xt_add_attr(sinode, "profile", XMLNS_FILETRANSFER); 352 xt_add_attr(sinode, "id", tf->sid); 347 353 348 354 /* now the file tag */ 349 node = xt_new_node( "file", NULL, NULL);350 xt_add_attr( node, "xmlns", XMLNS_FILETRANSFER);351 352 xt_add_child( sinode, node);355 node = xt_new_node("file", NULL, NULL); 356 xt_add_attr(node, "xmlns", XMLNS_FILETRANSFER); 357 358 xt_add_child(sinode, node); 353 359 354 360 /* and finally the feature tag */ 355 node = xt_new_node( "field", NULL, NULL);356 xt_add_attr( node, "var", "stream-method");357 xt_add_attr( node, "type", "list-single");361 node = xt_new_node("field", NULL, NULL); 362 xt_add_attr(node, "var", "stream-method"); 363 xt_add_attr(node, "type", "list-single"); 358 364 359 365 /* Currently all we can do. One could also implement in-band (IBB) */ 360 xt_add_child( node, xt_new_node( "value", XMLNS_BYTESTREAMS, NULL ));361 362 node = xt_new_node( "x", NULL, node);363 xt_add_attr( node, "xmlns", XMLNS_XDATA);364 xt_add_attr( node, "type", "submit");365 366 node = xt_new_node( "feature", NULL, node);367 xt_add_attr( node, "xmlns", XMLNS_FEATURE);368 369 xt_add_child( sinode, node);370 371 reply = jabber_make_packet( "iq", "result", tf->ini_jid, sinode);372 xt_add_attr( reply, "id", tf->iq_id);373 374 if ( !jabber_write_packet( tf->ic, reply ) )375 imcb_log( tf->ic, "WARNING: Error generating reply to file transfer request");376 else366 xt_add_child(node, xt_new_node("value", XMLNS_BYTESTREAMS, NULL)); 367 368 node = xt_new_node("x", NULL, node); 369 xt_add_attr(node, "xmlns", XMLNS_XDATA); 370 xt_add_attr(node, "type", "submit"); 371 372 node = xt_new_node("feature", NULL, node); 373 xt_add_attr(node, "xmlns", XMLNS_FEATURE); 374 375 xt_add_child(sinode, node); 376 377 reply = jabber_make_packet("iq", "result", tf->ini_jid, sinode); 378 xt_add_attr(reply, "id", tf->iq_id); 379 380 if (!jabber_write_packet(tf->ic, reply)) { 381 imcb_log(tf->ic, "WARNING: Error generating reply to file transfer request"); 382 } else { 377 383 tf->accepted = TRUE; 378 xt_free_node( reply ); 379 } 380 381 static xt_status jabber_si_handle_response(struct im_connection *ic, struct xt_node *node, struct xt_node *orig ) 384 } 385 xt_free_node(reply); 386 } 387 388 static xt_status jabber_si_handle_response(struct im_connection *ic, struct xt_node *node, struct xt_node *orig) 382 389 { 383 390 struct xt_node *c, *d; 384 391 char *ini_jid = NULL, *tgt_jid, *iq_id, *cmp; 385 392 GSList *tflist; 386 struct jabber_transfer *tf =NULL;393 struct jabber_transfer *tf = NULL; 387 394 struct jabber_data *jd = ic->proto_data; 388 395 389 if( !( tgt_jid = xt_find_attr( node, "from" ) ) || 390 !( ini_jid = xt_find_attr( node, "to" ) ) ) 391 { 392 imcb_log( ic, "Invalid SI response from=%s to=%s", tgt_jid, ini_jid ); 396 if (!(tgt_jid = xt_find_attr(node, "from")) || 397 !(ini_jid = xt_find_attr(node, "to"))) { 398 imcb_log(ic, "Invalid SI response from=%s to=%s", tgt_jid, ini_jid); 393 399 return XT_HANDLED; 394 400 } 395 401 396 402 /* All this means we expect something like this: ( I think ) 397 403 * <iq from=... to=... id=...> 398 * 399 * 400 * 401 * 402 * 403 * 404 * <si xmlns=si> 405 * [ <file xmlns=ft/> ] <-- not neccessary 406 * <feature xmlns=feature> 407 * <x xmlns=xdata type=submit> 408 * <field var=stream-method> 409 * <value> 404 410 */ 405 if( !( tgt_jid = xt_find_attr( node, "from" ) ) || 406 !( ini_jid = xt_find_attr( node, "to" ) ) || 407 !( iq_id = xt_find_attr( node, "id" ) ) || 408 !( c = xt_find_node( node->children, "si" ) ) || 409 !( cmp = xt_find_attr( c, "xmlns" ) ) || 410 !( strcmp( cmp, XMLNS_SI ) == 0 ) || 411 !( d = xt_find_node( c->children, "feature" ) ) || 412 !( cmp = xt_find_attr( d, "xmlns" ) ) || 413 !( strcmp( cmp, XMLNS_FEATURE ) == 0 ) || 414 !( d = xt_find_node( d->children, "x" ) ) || 415 !( cmp = xt_find_attr( d, "xmlns" ) ) || 416 !( strcmp( cmp, XMLNS_XDATA ) == 0 ) || 417 !( cmp = xt_find_attr( d, "type" ) ) || 418 !( strcmp( cmp, "submit" ) == 0 ) || 419 !( d = xt_find_node( d->children, "field" ) ) || 420 !( cmp = xt_find_attr( d, "var" ) ) || 421 !( strcmp( cmp, "stream-method" ) == 0 ) || 422 !( d = xt_find_node( d->children, "value" ) ) ) 423 { 424 imcb_log( ic, "WARNING: Received incomplete Stream Initiation response" ); 411 if (!(tgt_jid = xt_find_attr(node, "from")) || 412 !(ini_jid = xt_find_attr(node, "to")) || 413 !(iq_id = xt_find_attr(node, "id")) || 414 !(c = xt_find_node(node->children, "si")) || 415 !(cmp = xt_find_attr(c, "xmlns")) || 416 !(strcmp(cmp, XMLNS_SI) == 0) || 417 !(d = xt_find_node(c->children, "feature")) || 418 !(cmp = xt_find_attr(d, "xmlns")) || 419 !(strcmp(cmp, XMLNS_FEATURE) == 0) || 420 !(d = xt_find_node(d->children, "x")) || 421 !(cmp = xt_find_attr(d, "xmlns")) || 422 !(strcmp(cmp, XMLNS_XDATA) == 0) || 423 !(cmp = xt_find_attr(d, "type")) || 424 !(strcmp(cmp, "submit") == 0) || 425 !(d = xt_find_node(d->children, "field")) || 426 !(cmp = xt_find_attr(d, "var")) || 427 !(strcmp(cmp, "stream-method") == 0) || 428 !(d = xt_find_node(d->children, "value"))) { 429 imcb_log(ic, "WARNING: Received incomplete Stream Initiation response"); 425 430 return XT_HANDLED; 426 431 } 427 432 428 if ( !( strcmp( d->text, XMLNS_BYTESTREAMS ) == 0 ) ) {433 if (!(strcmp(d->text, XMLNS_BYTESTREAMS) == 0)) { 429 434 /* since we should only have advertised what we can do and the peer should 430 435 * only have chosen what we offered, this should never happen */ 431 imcb_log( ic, "WARNING: Received invalid Stream Initiation response, method %s", d->text);432 436 imcb_log(ic, "WARNING: Received invalid Stream Initiation response, method %s", d->text); 437 433 438 return XT_HANDLED; 434 439 } 435 440 436 441 /* Let's see if we can find out what this bytestream should be for... */ 437 442 438 for( tflist = jd->filetransfers ; tflist; tflist = g_slist_next(tflist) ) 439 { 443 for (tflist = jd->filetransfers; tflist; tflist = g_slist_next(tflist)) { 440 444 struct jabber_transfer *tft = tflist->data; 441 if( ( strcmp( tft->iq_id, iq_id ) == 0 ) ) 442 { 443 tf = tft; 445 if ((strcmp(tft->iq_id, iq_id) == 0)) { 446 tf = tft; 444 447 break; 445 448 } 446 449 } 447 450 448 if (!tf) 449 { 450 imcb_log( ic, "WARNING: Received bytestream request from %s that doesn't match an SI request", ini_jid ); 451 if (!tf) { 452 imcb_log(ic, "WARNING: Received bytestream request from %s that doesn't match an SI request", ini_jid); 451 453 return XT_HANDLED; 452 454 } 453 455 454 tf->ini_jid = g_strdup( ini_jid);455 tf->tgt_jid = g_strdup( tgt_jid);456 457 imcb_log( ic, "File %s: %s accepted the transfer!", tf->ft->file_name, tgt_jid);458 459 jabber_bs_send_start( tf);456 tf->ini_jid = g_strdup(ini_jid); 457 tf->tgt_jid = g_strdup(tgt_jid); 458 459 imcb_log(ic, "File %s: %s accepted the transfer!", tf->ft->file_name, tgt_jid); 460 461 jabber_bs_send_start(tf); 460 462 461 463 return XT_HANDLED; 462 464 } 463 465 464 int jabber_si_send_request(struct im_connection *ic, char *who, struct jabber_transfer *tf 466 int jabber_si_send_request(struct im_connection *ic, char *who, struct jabber_transfer *tf) 465 467 { 466 468 struct xt_node *node, *sinode; … … 468 470 469 471 /* who knows how many bits the future holds :) */ 470 char filesizestr[ 1 + ( int ) ( 0.301029995663981198f * sizeof( size_t ) * 8) ];471 472 const char *methods[] = 473 { 472 char filesizestr[ 1 + ( int ) (0.301029995663981198f * sizeof(size_t) * 8) ]; 473 474 const char *methods[] = 475 { 474 476 XMLNS_BYTESTREAMS, 475 477 //XMLNS_IBB, 476 NULL 478 NULL 477 479 }; 478 480 const char **m; … … 480 482 481 483 /* Maybe we should hash this? */ 482 tf->sid = g_strdup_printf( "BitlBeeJabberSID%d", tf->ft->local_id ); 483 484 if( ( s = strchr( who, '=' ) ) && jabber_chat_by_jid( ic, s + 1 ) ) 485 bud = jabber_buddy_by_ext_jid( ic, who, 0 ); 486 else 487 bud = jabber_buddy_by_jid( ic, who, 0 ); 484 tf->sid = g_strdup_printf("BitlBeeJabberSID%d", tf->ft->local_id); 485 486 if ((s = strchr(who, '=')) && jabber_chat_by_jid(ic, s + 1)) { 487 bud = jabber_buddy_by_ext_jid(ic, who, 0); 488 } else { 489 bud = jabber_buddy_by_jid(ic, who, 0); 490 } 488 491 489 492 /* start with the SI tag */ 490 sinode = xt_new_node( "si", NULL, NULL);491 xt_add_attr( sinode, "xmlns", XMLNS_SI);492 xt_add_attr( sinode, "profile", XMLNS_FILETRANSFER);493 xt_add_attr( sinode, "id", tf->sid);494 495 /* if( mimetype ) 496 493 sinode = xt_new_node("si", NULL, NULL); 494 xt_add_attr(sinode, "xmlns", XMLNS_SI); 495 xt_add_attr(sinode, "profile", XMLNS_FILETRANSFER); 496 xt_add_attr(sinode, "id", tf->sid); 497 498 /* if( mimetype ) 499 xt_add_attr( node, "mime-type", mimetype ); */ 497 500 498 501 /* now the file tag */ 499 502 /* if( desc ) 500 501 node = xt_new_node( "range", NULL, NULL);502 503 sprintf( filesizestr, "%zd", tf->ft->file_size);504 node = xt_new_node( "file", NULL, node);505 xt_add_attr( node, "xmlns", XMLNS_FILETRANSFER);506 xt_add_attr( node, "name", tf->ft->file_name);507 xt_add_attr( node, "size", filesizestr);503 node = xt_new_node( "desc", descr, NULL ); */ 504 node = xt_new_node("range", NULL, NULL); 505 506 sprintf(filesizestr, "%zd", tf->ft->file_size); 507 node = xt_new_node("file", NULL, node); 508 xt_add_attr(node, "xmlns", XMLNS_FILETRANSFER); 509 xt_add_attr(node, "name", tf->ft->file_name); 510 xt_add_attr(node, "size", filesizestr); 508 511 /* if (hash) 509 510 511 512 513 xt_add_child( sinode, node);512 xt_add_attr( node, "hash", hash ); 513 if (date) 514 xt_add_attr( node, "date", date ); */ 515 516 xt_add_child(sinode, node); 514 517 515 518 /* and finally the feature tag */ 516 node = xt_new_node( "field", NULL, NULL ); 517 xt_add_attr( node, "var", "stream-method" ); 518 xt_add_attr( node, "type", "list-single" ); 519 520 for ( m = methods ; *m ; m ++ ) 521 xt_add_child( node, xt_new_node( "option", NULL, xt_new_node( "value", (char *)*m, NULL ) ) ); 522 523 node = xt_new_node( "x", NULL, node ); 524 xt_add_attr( node, "xmlns", XMLNS_XDATA ); 525 xt_add_attr( node, "type", "form" ); 526 527 node = xt_new_node( "feature", NULL, node ); 528 xt_add_attr( node, "xmlns", XMLNS_FEATURE ); 529 530 xt_add_child( sinode, node ); 519 node = xt_new_node("field", NULL, NULL); 520 xt_add_attr(node, "var", "stream-method"); 521 xt_add_attr(node, "type", "list-single"); 522 523 for (m = methods; *m; m++) { 524 xt_add_child(node, xt_new_node("option", NULL, xt_new_node("value", (char *) *m, NULL))); 525 } 526 527 node = xt_new_node("x", NULL, node); 528 xt_add_attr(node, "xmlns", XMLNS_XDATA); 529 xt_add_attr(node, "type", "form"); 530 531 node = xt_new_node("feature", NULL, node); 532 xt_add_attr(node, "xmlns", XMLNS_FEATURE); 533 534 xt_add_child(sinode, node); 531 535 532 536 /* and we are there... */ 533 node = jabber_make_packet( "iq", "set", bud ? bud->full_jid : who, sinode);534 jabber_cache_add( ic, node, jabber_si_handle_response);535 tf->iq_id = g_strdup( xt_find_attr( node, "id" ));536 537 return jabber_write_packet( ic, node);538 } 537 node = jabber_make_packet("iq", "set", bud ? bud->full_jid : who, sinode); 538 jabber_cache_add(ic, node, jabber_si_handle_response); 539 tf->iq_id = g_strdup(xt_find_attr(node, "id")); 540 541 return jabber_write_packet(ic, node); 542 }
Note: See TracChangeset
for help on using the changeset viewer.