Changeset 8bd866f for lib/http_client.c
- Timestamp:
- 2012-11-10T22:25:58Z (12 years ago)
- Branches:
- master
- Children:
- ddc2de5
- Parents:
- 9e8c945
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
lib/http_client.c
r9e8c945 r8bd866f 193 193 } 194 194 195 static gboolean http_handle_headers( struct http_request *req ); 196 195 197 static gboolean http_incoming_data( gpointer data, int source, b_input_condition cond ) 196 198 { 197 199 struct http_request *req = data; 198 int evil_server = 0;199 200 char buffer[2048]; 200 char * end1, *end2, *s;201 char *s; 201 202 size_t content_length; 202 203 int st; … … 218 219 packets that abort connections! \o/ */ 219 220 220 goto got_reply;221 goto eof; 221 222 } 222 223 } 223 224 else if( st == 0 ) 224 225 { 225 goto got_reply;226 goto eof; 226 227 } 227 228 } … … 239 240 else if( st == 0 ) 240 241 { 241 goto got_reply;242 } 243 } 244 245 if( st > 0 )242 goto eof; 243 } 244 } 245 246 if( st > 0 && !req->sbuf ) 246 247 { 247 248 req->reply_headers = g_realloc( req->reply_headers, req->bytes_read + st + 1 ); 248 249 memcpy( req->reply_headers + req->bytes_read, buffer, st ); 249 250 req->bytes_read += st; 250 } 251 252 st = 0; 253 } 254 255 if( st >= 0 && ( req->flags & HTTPC_STREAMING ) ) 256 { 257 if( !req->reply_body && 258 ( strstr( req->reply_headers, "\r\n\r\n" ) || 259 strstr( req->reply_headers, "\n\n" ) ) ) 260 { 261 size_t hlen; 262 263 /* We've now received all headers, so process them once 264 before we start feeding back data. */ 265 if( !http_handle_headers( req ) ) 266 return FALSE; 267 268 hlen = req->reply_body - req->reply_headers; 269 270 req->sblen = req->bytes_read - hlen; 271 req->sbuf = g_memdup( req->reply_body, req->sblen + 1 ); 272 req->reply_headers = g_realloc( req->reply_headers, hlen + 1 ); 273 274 req->reply_body = req->sbuf; 275 } 276 277 if( st > 0 ) 278 { 279 int pos = req->reply_body - req->sbuf; 280 req->sbuf = g_realloc( req->sbuf, req->sblen + st + 1 ); 281 memcpy( req->sbuf + req->sblen, buffer, st ); 282 req->bytes_read += st; 283 req->sblen += st; 284 req->reply_body = req->sbuf + pos; 285 req->body_size = req->sblen - pos; 286 } 287 288 if( req->reply_body ) 289 req->func( req ); 290 } 291 292 if( ssl_pending( req->ssl ) ) 293 return http_incoming_data( data, source, cond ); 251 294 252 295 /* There will be more! */ … … 255 298 http_incoming_data, req ); 256 299 257 if( ssl_pending( req->ssl ) ) 258 return http_incoming_data( data, source, cond ); 259 else 260 return FALSE; 261 262 got_reply: 300 return FALSE; 301 302 eof: 263 303 /* Maybe if the webserver is overloaded, or when there's bad SSL 264 304 support... */ … … 269 309 } 270 310 311 if( !( req->flags & HTTPC_STREAMING ) ) 312 { 313 /* Returns FALSE if we were redirected, in which case we should abort 314 and not run any callback yet. */ 315 if( !http_handle_headers( req ) ) 316 return FALSE; 317 } 318 319 cleanup: 320 if( req->ssl ) 321 ssl_disconnect( req->ssl ); 322 else 323 closesocket( req->fd ); 324 325 if( ( s = get_rfc822_header( req->reply_headers, "Content-Length", 0 ) ) && 326 sscanf( s, "%zd", &content_length ) == 1 ) 327 { 328 if( content_length < req->body_size ) 329 { 330 req->status_code = -1; 331 g_free( req->status_string ); 332 req->status_string = g_strdup( "Response truncated" ); 333 } 334 } 335 g_free( s ); 336 337 if( getenv( "BITLBEE_DEBUG" ) && req ) 338 printf( "Finishing HTTP request with status: %s\n", 339 req->status_string ? req->status_string : "NULL" ); 340 341 req->func( req ); 342 http_free( req ); 343 return FALSE; 344 } 345 346 /* Splits headers and body. Checks result code, in case of 300s it'll handle 347 redirects. If this returns FALSE, don't call any callbacks! */ 348 static gboolean http_handle_headers( struct http_request *req ) 349 { 350 char *end1, *end2; 351 int evil_server = 0; 352 271 353 /* Zero termination is very convenient. */ 272 req->reply_headers[req->bytes_read] = 0;354 req->reply_headers[req->bytes_read] = '\0'; 273 355 274 356 /* Find the separation between headers and body, and keep stupid … … 289 371 { 290 372 req->status_string = g_strdup( "Malformed HTTP reply" ); 291 goto cleanup;373 return TRUE; 292 374 } 293 375 … … 306 388 if( ( end1 = strchr( req->reply_headers, ' ' ) ) != NULL ) 307 389 { 308 if( sscanf( end1 + 1, "% d", &req->status_code ) != 1 )390 if( sscanf( end1 + 1, "%hd", &req->status_code ) != 1 ) 309 391 { 310 392 req->status_string = g_strdup( "Can't parse status code" ); … … 349 431 { 350 432 req->status_string = g_strdup( "Can't locate Location: header" ); 351 goto cleanup;433 return TRUE; 352 434 } 353 435 … … 369 451 req->status_string = g_strdup( "Can't handle recursive redirects" ); 370 452 371 goto cleanup;453 return TRUE; 372 454 } 373 455 else … … 380 462 s = strstr( loc, "\r\n" ); 381 463 if( s == NULL ) 382 goto cleanup;464 return TRUE; 383 465 384 466 url = g_new0( url_t, 1 ); … … 389 471 req->status_string = g_strdup( "Malformed redirect URL" ); 390 472 g_free( url ); 391 goto cleanup;473 return TRUE; 392 474 } 393 475 … … 401 483 req->status_string = g_strdup( "Error while rebuilding request string" ); 402 484 g_free( url ); 403 goto cleanup;485 return TRUE; 404 486 } 405 487 … … 467 549 req->status_string = g_strdup( "Connection problem during redirect" ); 468 550 g_free( new_request ); 469 goto cleanup;551 return TRUE; 470 552 } 471 553 … … 480 562 } 481 563 482 /* Assume that a closed connection means we're finished, this indeed 483 breaks with keep-alive connections and faulty connections. */ 484 /* req->finished = 1; */ 485 486 cleanup: 487 if( req->ssl ) 488 ssl_disconnect( req->ssl ); 489 else 490 closesocket( req->fd ); 491 492 if( ( s = get_rfc822_header( req->reply_headers, "Content-Length", 0 ) ) && 493 sscanf( s, "%zd", &content_length ) == 1 ) 494 { 495 if( content_length < req->body_size ) 496 { 497 req->status_code = -1; 498 g_free( req->status_string ); 499 req->status_string = g_strdup( "Response truncated" ); 500 } 501 } 502 g_free( s ); 503 504 if( getenv( "BITLBEE_DEBUG" ) && req ) 505 printf( "Finishing HTTP request with status: %s\n", 506 req->status_string ? req->status_string : "NULL" ); 507 508 req->func( req ); 509 http_free( req ); 510 return FALSE; 564 return TRUE; 565 } 566 567 void http_flush_bytes( struct http_request *req, size_t len ) 568 { 569 if( len > 0 && len <= req->body_size ) 570 { 571 req->reply_body += len; 572 req->body_size -= len; 573 } 511 574 } 512 575 … … 516 579 g_free( req->reply_headers ); 517 580 g_free( req->status_string ); 581 g_free( req->sbuf ); 518 582 g_free( req ); 519 583 } 520
Note: See TracChangeset
for help on using the changeset viewer.