19
19
| Sara Golemon <[email protected] > |
20
20
+----------------------------------------------------------------------+
21
21
*/
22
- /* $Id$ */
22
+ /* $Id$ */
23
23
24
24
#include "php.h"
25
25
#include "php_globals.h"
@@ -152,7 +152,7 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path,
152
152
}
153
153
154
154
if (strncasecmp (resource -> scheme , "http" , sizeof ("http" )) && strncasecmp (resource -> scheme , "https" , sizeof ("https" ))) {
155
- if (!context ||
155
+ if (!context ||
156
156
php_stream_context_get_option (context , wrapper -> wops -> label , "proxy" , & tmpzval ) == FAILURE ||
157
157
Z_TYPE_PP (tmpzval ) != IS_STRING ||
158
158
Z_STRLEN_PP (tmpzval ) <= 0 ) {
@@ -168,7 +168,7 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path,
168
168
transport_string = estrndup (Z_STRVAL_PP (tmpzval ), Z_STRLEN_PP (tmpzval ));
169
169
} else {
170
170
/* Normal http request (possibly with proxy) */
171
-
171
+
172
172
if (strpbrk (mode , "awx+" )) {
173
173
php_stream_wrapper_log_error (wrapper , options TSRMLS_CC , "HTTP wrapper does not support writeable connections" );
174
174
php_url_free (resource );
@@ -207,11 +207,11 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path,
207
207
stream = php_stream_xport_create (transport_string , transport_len , options ,
208
208
STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT ,
209
209
NULL , & timeout , context , & errstr , NULL );
210
-
210
+
211
211
if (stream ) {
212
212
php_stream_set_option (stream , PHP_STREAM_OPTION_READ_TIMEOUT , 0 , & timeout );
213
213
}
214
-
214
+
215
215
if (errstr ) {
216
216
php_stream_wrapper_log_error (wrapper , options TSRMLS_CC , "%s" , errstr );
217
217
efree (errstr );
@@ -328,7 +328,7 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path,
328
328
/* avoid buffering issues while reading header */
329
329
if (options & STREAM_WILL_CAST )
330
330
chunk_size = php_stream_set_chunk_size (stream , 1 );
331
-
331
+
332
332
/* avoid problems with auto-detecting when reading the headers -> the headers
333
333
* are always in canonical \r\n format */
334
334
eol_detect = stream -> flags & (PHP_STREAM_FLAG_DETECT_EOL | PHP_STREAM_FLAG_EOL_MAC );
@@ -359,7 +359,7 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path,
359
359
}
360
360
}
361
361
}
362
-
362
+
363
363
if (context && php_stream_context_get_option (context , "http" , "protocol_version" , & tmpzval ) == SUCCESS ) {
364
364
SEPARATE_ZVAL (tmpzval );
365
365
convert_to_double_ex (tmpzval );
@@ -420,7 +420,7 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path,
420
420
421
421
if (context && php_stream_context_get_option (context , "http" , "header" , & tmpzval ) == SUCCESS ) {
422
422
tmp = NULL ;
423
-
423
+
424
424
if (Z_TYPE_PP (tmpzval ) == IS_ARRAY ) {
425
425
HashPosition pos ;
426
426
zval * * tmpheader = NULL ;
@@ -460,42 +460,42 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path,
460
460
strip_header (user_headers , tmp , "content-type:" );
461
461
}
462
462
463
- if ((s = strstr (tmp , "user-agent:" )) &&
464
- (s == tmp || * (s - 1 ) == '\r' || * (s - 1 ) == '\n' ||
463
+ if ((s = strstr (tmp , "user-agent:" )) &&
464
+ (s == tmp || * (s - 1 ) == '\r' || * (s - 1 ) == '\n' ||
465
465
* (s - 1 ) == '\t' || * (s - 1 ) == ' ' )) {
466
466
have_header |= HTTP_HEADER_USER_AGENT ;
467
467
}
468
468
if ((s = strstr (tmp , "host:" )) &&
469
- (s == tmp || * (s - 1 ) == '\r' || * (s - 1 ) == '\n' ||
469
+ (s == tmp || * (s - 1 ) == '\r' || * (s - 1 ) == '\n' ||
470
470
* (s - 1 ) == '\t' || * (s - 1 ) == ' ' )) {
471
471
have_header |= HTTP_HEADER_HOST ;
472
472
}
473
473
if ((s = strstr (tmp , "from:" )) &&
474
- (s == tmp || * (s - 1 ) == '\r' || * (s - 1 ) == '\n' ||
474
+ (s == tmp || * (s - 1 ) == '\r' || * (s - 1 ) == '\n' ||
475
475
* (s - 1 ) == '\t' || * (s - 1 ) == ' ' )) {
476
476
have_header |= HTTP_HEADER_FROM ;
477
477
}
478
478
if ((s = strstr (tmp , "authorization:" )) &&
479
- (s == tmp || * (s - 1 ) == '\r' || * (s - 1 ) == '\n' ||
479
+ (s == tmp || * (s - 1 ) == '\r' || * (s - 1 ) == '\n' ||
480
480
* (s - 1 ) == '\t' || * (s - 1 ) == ' ' )) {
481
481
have_header |= HTTP_HEADER_AUTH ;
482
482
}
483
483
if ((s = strstr (tmp , "content-length:" )) &&
484
- (s == tmp || * (s - 1 ) == '\r' || * (s - 1 ) == '\n' ||
484
+ (s == tmp || * (s - 1 ) == '\r' || * (s - 1 ) == '\n' ||
485
485
* (s - 1 ) == '\t' || * (s - 1 ) == ' ' )) {
486
486
have_header |= HTTP_HEADER_CONTENT_LENGTH ;
487
487
}
488
488
if ((s = strstr (tmp , "content-type:" )) &&
489
- (s == tmp || * (s - 1 ) == '\r' || * (s - 1 ) == '\n' ||
489
+ (s == tmp || * (s - 1 ) == '\r' || * (s - 1 ) == '\n' ||
490
490
* (s - 1 ) == '\t' || * (s - 1 ) == ' ' )) {
491
491
have_header |= HTTP_HEADER_TYPE ;
492
492
}
493
493
/* remove Proxy-Authorization header */
494
494
if (use_proxy && use_ssl && (s = strstr (tmp , "proxy-authorization:" )) &&
495
- (s == tmp || * (s - 1 ) == '\r' || * (s - 1 ) == '\n' ||
495
+ (s == tmp || * (s - 1 ) == '\r' || * (s - 1 ) == '\n' ||
496
496
* (s - 1 ) == '\t' || * (s - 1 ) == ' ' )) {
497
497
char * p = s + sizeof ("proxy-authorization:" ) - 1 ;
498
-
498
+
499
499
while (s > tmp && (* (s - 1 ) == ' ' || * (s - 1 ) == '\t' )) s -- ;
500
500
while (* p != 0 && * p != '\r' && * p != '\n' ) p ++ ;
501
501
while (* p == '\r' || * p == '\n' ) p ++ ;
@@ -534,7 +534,7 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path,
534
534
}
535
535
536
536
tmp = (char * )php_base64_encode ((unsigned char * )scratch , strlen (scratch ), NULL );
537
-
537
+
538
538
if (snprintf (scratch , scratch_len , "Authorization: Basic %s\r\n" , tmp ) > 0 ) {
539
539
php_stream_write (stream , scratch , strlen (scratch ));
540
540
php_stream_notify_info (context , PHP_STREAM_NOTIFY_AUTH_REQUIRED , NULL , 0 );
@@ -552,7 +552,7 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path,
552
552
553
553
/* Send Host: header so name-based virtual hosts work */
554
554
if ((have_header & HTTP_HEADER_HOST ) == 0 ) {
555
- if ((use_ssl && resource -> port != 443 && resource -> port != 0 ) ||
555
+ if ((use_ssl && resource -> port != 443 && resource -> port != 0 ) ||
556
556
(!use_ssl && resource -> port != 80 && resource -> port != 0 )) {
557
557
if (snprintf (scratch , scratch_len , "Host: %s:%i\r\n" , resource -> host , resource -> port ) > 0 )
558
558
php_stream_write (stream , scratch , strlen (scratch ));
@@ -563,7 +563,7 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path,
563
563
}
564
564
}
565
565
566
- if (context &&
566
+ if (context &&
567
567
php_stream_context_get_option (context , "http" , "user_agent" , & ua_zval ) == SUCCESS &&
568
568
Z_TYPE_PP (ua_zval ) == IS_STRING ) {
569
569
ua_str = Z_STRVAL_PP (ua_zval );
@@ -575,9 +575,9 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path,
575
575
#define _UA_HEADER "User-Agent: %s\r\n"
576
576
char * ua ;
577
577
size_t ua_len ;
578
-
578
+
579
579
ua_len = sizeof (_UA_HEADER ) + strlen (ua_str );
580
-
580
+
581
581
/* ensure the header is only sent if user_agent is not blank */
582
582
if (ua_len > sizeof (_UA_HEADER )) {
583
583
ua = emalloc (ua_len + 1 );
@@ -591,7 +591,7 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path,
591
591
if (ua ) {
592
592
efree (ua );
593
593
}
594
- }
594
+ }
595
595
}
596
596
597
597
if (user_headers ) {
@@ -649,8 +649,12 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path,
649
649
650
650
{
651
651
zval * * rh ;
652
- zend_hash_find (EG (active_symbol_table ), "http_response_header" , sizeof ("http_response_header" ), (void * * ) & rh );
652
+ if (zend_hash_find (EG (active_symbol_table ), "http_response_header" , sizeof ("http_response_header" ), (void * * ) & rh ) != SUCCESS || Z_TYPE_PP (rh ) != IS_ARRAY ) {
653
+ php_stream_wrapper_log_error (wrapper , options TSRMLS_CC , "HTTP request failed, http_response_header overwritten" );
654
+ goto out ;
655
+ }
653
656
response_header = * rh ;
657
+ Z_ADDREF_P (response_header );
654
658
}
655
659
656
660
if (!php_stream_eof (stream )) {
@@ -706,9 +710,9 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path,
706
710
php_stream_wrapper_log_error (wrapper , options TSRMLS_CC , "HTTP request failed, unexpected end of socket!" );
707
711
goto out ;
708
712
}
709
-
713
+
710
714
/* read past HTTP headers */
711
-
715
+
712
716
http_header_line = emalloc (HTTP_HEADER_BLOCK_SIZE );
713
717
714
718
while (!body && !php_stream_eof (stream )) {
@@ -738,7 +742,7 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path,
738
742
follow_location = Z_LVAL_PP (tmpzval );
739
743
} else if (!(response_code >= 300 && response_code < 304 || 307 == response_code || 308 == response_code )) {
740
744
/* we shouldn't redirect automatically
741
- if follow_location isn't set and response_code not in (300, 301, 302, 303 and 307)
745
+ if follow_location isn't set and response_code not in (300, 301, 302, 303 and 307)
742
746
see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.1
743
747
RFC 7238 defines 308: http://tools.ietf.org/html/rfc7238 */
744
748
follow_location = 0 ;
@@ -778,7 +782,7 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path,
778
782
MAKE_STD_ZVAL (http_header );
779
783
780
784
ZVAL_STRINGL (http_header , http_header_line , http_header_line_length , 1 );
781
-
785
+
782
786
zend_hash_next_index_insert (Z_ARRVAL_P (response_header ), & http_header , sizeof (zval * ), NULL );
783
787
}
784
788
} else {
@@ -803,10 +807,10 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path,
803
807
char loc_path [HTTP_HEADER_BLOCK_SIZE ];
804
808
805
809
* new_path = '\0' ;
806
- if (strlen (location )< 8 || (strncasecmp (location , "http://" , sizeof ("http://" )- 1 ) &&
807
- strncasecmp (location , "https://" , sizeof ("https://" )- 1 ) &&
808
- strncasecmp (location , "ftp://" , sizeof ("ftp://" )- 1 ) &&
809
- strncasecmp (location , "ftps://" , sizeof ("ftps://" )- 1 )))
810
+ if (strlen (location )< 8 || (strncasecmp (location , "http://" , sizeof ("http://" )- 1 ) &&
811
+ strncasecmp (location , "https://" , sizeof ("https://" )- 1 ) &&
812
+ strncasecmp (location , "ftp://" , sizeof ("ftp://" )- 1 ) &&
813
+ strncasecmp (location , "ftps://" , sizeof ("ftps://" )- 1 )))
810
814
{
811
815
if (* location != '/' ) {
812
816
if (* (location + 1 ) != '\0' && resource -> path ) {
@@ -820,7 +824,7 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path,
820
824
* s = '/' ;
821
825
}
822
826
}
823
- s [1 ] = '\0' ;
827
+ s [1 ] = '\0' ;
824
828
if (resource -> path && * (resource -> path ) == '/' && * (resource -> path + 1 ) == '\0' ) {
825
829
snprintf (loc_path , sizeof (loc_path ) - 1 , "%s%s" , resource -> path , location );
826
830
} else {
@@ -893,18 +897,21 @@ php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path,
893
897
894
898
if (stream ) {
895
899
if (header_init ) {
896
- zval_add_ref (& response_header );
897
900
stream -> wrapperdata = response_header ;
901
+ } else {
902
+ if (response_header ) {
903
+ Z_DELREF_P (response_header );
904
+ }
898
905
}
899
906
php_stream_notify_progress_init (context , 0 , file_size );
900
-
907
+
901
908
/* Restore original chunk size now that we're done with headers */
902
909
if (options & STREAM_WILL_CAST )
903
910
php_stream_set_chunk_size (stream , chunk_size );
904
911
905
912
/* restore the users auto-detect-line-endings setting */
906
913
stream -> flags |= eol_detect ;
907
-
914
+
908
915
/* as far as streams are concerned, we are now at the start of
909
916
* the stream */
910
917
stream -> position = 0 ;
0 commit comments