@@ -523,7 +523,7 @@ static struct request_s *process_request (struct conn_s *connptr,
523523 * server headers can be processed.
524524 * - rjkaes
525525 */
526- static int pull_client_data (struct conn_s * connptr , long int length )
526+ static int pull_client_data (struct conn_s * connptr , long int length , int iehack )
527527{
528528 char * buffer ;
529529 ssize_t len ;
@@ -548,39 +548,75 @@ static int pull_client_data (struct conn_s *connptr, long int length)
548548 length -= len ;
549549 } while (length > 0 );
550550
551- /*
552- * BUG FIX: Internet Explorer will leave two bytes (carriage
553- * return and line feed) at the end of a POST message. These
554- * need to be eaten for tinyproxy to work correctly.
555- */
556- ret = socket_nonblocking (connptr -> client_fd );
557- if (ret != 0 ) {
558- log_message (LOG_ERR , "Failed to set the client socket "
559- "to non-blocking: %s" , strerror (errno ));
560- goto ERROR_EXIT ;
551+ if (iehack ) {
552+ /*
553+ * BUG FIX: Internet Explorer will leave two bytes (carriage
554+ * return and line feed) at the end of a POST message. These
555+ * need to be eaten for tinyproxy to work correctly.
556+ */
557+ ret = socket_nonblocking (connptr -> client_fd );
558+ if (ret != 0 ) {
559+ log_message (LOG_ERR , "Failed to set the client socket "
560+ "to non-blocking: %s" , strerror (errno ));
561+ goto ERROR_EXIT ;
562+ }
563+
564+ len = recv (connptr -> client_fd , buffer , 2 , MSG_PEEK );
565+
566+ ret = socket_blocking (connptr -> client_fd );
567+ if (ret != 0 ) {
568+ log_message (LOG_ERR , "Failed to set the client socket "
569+ "to blocking: %s" , strerror (errno ));
570+ goto ERROR_EXIT ;
571+ }
572+
573+ if (len < 0 && errno != EAGAIN )
574+ goto ERROR_EXIT ;
575+
576+ if ((len == 2 ) && CHECK_CRLF (buffer , len )) {
577+ ssize_t bytes_read ;
578+
579+ bytes_read = read (connptr -> client_fd , buffer , 2 );
580+ if (bytes_read == -1 ) {
581+ log_message
582+ (LOG_WARNING ,
583+ "Could not read two bytes from POST message" );
584+ }
585+ }
561586 }
562587
563- len = recv (connptr -> client_fd , buffer , 2 , MSG_PEEK );
588+ safefree (buffer );
589+ return 0 ;
564590
565- ret = socket_blocking (connptr -> client_fd );
566- if (ret != 0 ) {
567- log_message (LOG_ERR , "Failed to set the client socket "
568- "to blocking: %s" , strerror (errno ));
569- goto ERROR_EXIT ;
570- }
591+ ERROR_EXIT :
592+ safefree (buffer );
593+ return -1 ;
594+ }
571595
572- if (len < 0 && errno != EAGAIN )
573- goto ERROR_EXIT ;
596+ /* pull chunked client data */
597+ static int pull_client_data_chunked (struct conn_s * connptr ) {
598+ char * buffer = 0 ;
599+ ssize_t len ;
600+ long chunklen ;
601+
602+ while (1 ) {
603+ if (buffer ) safefree (buffer );
604+ len = readline (connptr -> client_fd , & buffer );
574605
575- if (( len == 2 ) && CHECK_CRLF ( buffer , len )) {
576- ssize_t bytes_read ;
606+ if ( len <= 0 )
607+ goto ERROR_EXIT ;
577608
578- bytes_read = read (connptr -> client_fd , buffer , 2 );
579- if (bytes_read == -1 ) {
580- log_message
581- (LOG_WARNING ,
582- "Could not read two bytes from POST message" );
609+ if (!connptr -> error_variables ) {
610+ if (safe_write (connptr -> server_fd , buffer , len ) < 0 )
611+ goto ERROR_EXIT ;
583612 }
613+
614+ chunklen = strtol (buffer , (char * * )0 , 16 );
615+
616+ if (pull_client_data (connptr , chunklen + 2 , 0 ) < 0 )
617+ goto ERROR_EXIT ;
618+
619+ if (!chunklen ) break ;
584620 }
585621
586622 safefree (buffer );
@@ -787,7 +823,7 @@ static int remove_connection_headers (orderedmap hashofheaders)
787823
788824/*
789825 * If there is a Content-Length header, then return the value; otherwise, return
790- * a negative number .
826+ * -1 .
791827 */
792828static long get_content_length (orderedmap hashofheaders )
793829{
@@ -802,6 +838,13 @@ static long get_content_length (orderedmap hashofheaders)
802838 return content_length ;
803839}
804840
841+ static int is_chunked_transfer (orderedmap hashofheaders )
842+ {
843+ char * data ;
844+ data = orderedmap_find (hashofheaders , "transfer-encoding" );
845+ return data ? !strcmp (data , "chunked" ) : 0 ;
846+ }
847+
805848/*
806849 * Search for Via header in a hash of headers and either write a new Via
807850 * header, or append our information to the end of an existing Via header.
@@ -896,6 +939,10 @@ process_client_headers (struct conn_s *connptr, orderedmap hashofheaders)
896939 */
897940 connptr -> content_length .client = get_content_length (hashofheaders );
898941
942+ /* Check whether client sends chunked data. */
943+ if (connptr -> content_length .client == -1 && is_chunked_transfer (hashofheaders ))
944+ connptr -> content_length .client = -2 ;
945+
899946 /*
900947 * See if there is a "Connection" header. If so, we need to do a bit
901948 * of processing. :)
@@ -960,8 +1007,9 @@ process_client_headers (struct conn_s *connptr, orderedmap hashofheaders)
9601007PULL_CLIENT_DATA :
9611008 if (connptr -> content_length .client > 0 ) {
9621009 ret = pull_client_data (connptr ,
963- connptr -> content_length .client );
964- }
1010+ connptr -> content_length .client , 1 );
1011+ } else if (connptr -> content_length .client == -2 )
1012+ ret = pull_client_data_chunked (connptr );
9651013
9661014 return ret ;
9671015}
0 commit comments