From 3dc7fc54a008eb64b799656b296e0fd09b48c7ff Mon Sep 17 00:00:00 2001 From: Zeev Suraski Date: Sat, 28 Oct 2000 01:31:56 +0000 Subject: [PATCH] - URL-opened files now store the HTTP response header in $http_response_header - Some layout updates --- NEWS | 2 + ext/standard/basic_functions.c | 10 ++-- ext/standard/fsock.c | 3 +- ext/standard/http_fopen_wrapper.c | 94 ++++++++++++++++++++++++++----- main/fopen_wrappers.c | 14 +++-- 5 files changed, 97 insertions(+), 26 deletions(-) diff --git a/NEWS b/NEWS index ef0a3ce29de..c3f479ff8cf 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,8 @@ PHP 4.0 NEWS ?? ??? 2000, Version 4.0.4 +- URL-opened files now store the HTTP response header in $http_response_header + (Zeev) - Fixed array_rand() to shuffle results when the number of requested elements is the same as the number of elements in the array. (Andrei) - Added replace parameter to header() (Sascha) diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 880f6b63f03..0ee9ae00120 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -724,14 +724,14 @@ PHP_MINIT_FUNCTION(basic) #endif if(PG(allow_url_fopen)) { - if(FAILURE==php_register_url_wrapper("http",php_fopen_url_wrap_http)) { + if (FAILURE==php_register_url_wrapper("http", php_fopen_url_wrap_http)) { return FAILURE; } - if(FAILURE==php_register_url_wrapper("ftp",php_fopen_url_wrap_ftp)) { - return FAILURE; + if (FAILURE==php_register_url_wrapper("ftp", php_fopen_url_wrap_ftp)) { + return FAILURE; } - if(FAILURE==php_register_url_wrapper("php",php_fopen_url_wrap_php)) { - return FAILURE; + if (FAILURE==php_register_url_wrapper("php", php_fopen_url_wrap_php)) { + return FAILURE; } } diff --git a/ext/standard/fsock.c b/ext/standard/fsock.c index fa5fb96d020..dd273a4e1d2 100644 --- a/ext/standard/fsock.c +++ b/ext/standard/fsock.c @@ -649,8 +649,9 @@ char *php_sock_fgets(char *buf, size_t maxlen, int socket) /* signal error only, if we don't return data from this call and if there is no data to read and if the eof flag is set */ - if(amount || TOREAD(sock) || !sock->eof) + if(amount || TOREAD(sock) || !sock->eof) { ret = buf; + } return ret; } diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c index 400695f2f1d..8dab72a0c12 100644 --- a/ext/standard/http_fopen_wrapper.c +++ b/ext/standard/http_fopen_wrapper.c @@ -64,11 +64,13 @@ #include "php_fopen_wrappers.h" +#define HTTP_HEADER_BLOCK_SIZE 128 + FILE *php_fopen_url_wrap_http(char *path, char *mode, int options, int *issock, int *socketd, char **opened_path) { FILE *fp=NULL; php_url *resource=NULL; - char tmp_line[512]; + char tmp_line[128]; char location[512]; char hdr_line[8192]; int body = 0; @@ -76,6 +78,9 @@ FILE *php_fopen_url_wrap_http(char *path, char *mode, int options, int *issock, unsigned char *tmp; int len; int reqok = 0; + zval *response_header; + char *http_header_line; + int http_header_line_length, http_header_line_size; resource = url_parse((char *) path); if (resource == NULL) { @@ -84,8 +89,9 @@ FILE *php_fopen_url_wrap_http(char *path, char *mode, int options, int *issock, return NULL; } /* use port 80 if one wasn't specified */ - if (resource->port == 0) + if (resource->port == 0) { resource->port = 80; + } *socketd = php_hostconnect(resource->host, resource->port, SOCK_STREAM, 0); if (*socketd == -1) { @@ -171,37 +177,97 @@ FILE *php_fopen_url_wrap_http(char *path, char *mode, int options, int *issock, body = 0; location[0] = '\0'; + + MAKE_STD_ZVAL(response_header); + array_init(response_header); + if (!SOCK_FEOF(*socketd)) { /* get response header */ if (SOCK_FGETS(tmp_line, sizeof(tmp_line)-1, *socketd) != NULL) { + zval *http_response; + + MAKE_STD_ZVAL(http_response); if (strncmp(tmp_line + 8, " 200 ", 5) == 0) { reqok = 1; } + Z_STRLEN_P(http_response) = strlen(tmp_line); + Z_STRVAL_P(http_response) = estrndup(tmp_line, Z_STRLEN_P(http_response)); + if (Z_STRVAL_P(http_response)[Z_STRLEN_P(http_response)-1]=='\n') { + Z_STRVAL_P(http_response)[Z_STRLEN_P(http_response)-1]=0; + Z_STRLEN_P(http_response)--; + if (Z_STRVAL_P(http_response)[Z_STRLEN_P(http_response)-1]=='\r') { + Z_STRVAL_P(http_response)[Z_STRLEN_P(http_response)-1]=0; + Z_STRLEN_P(http_response)--; + } + } + Z_TYPE_P(http_response) = IS_STRING; + zend_hash_next_index_insert(Z_ARRVAL_P(response_header), &http_response, sizeof(zval *), NULL); } } + + /* Read past HTTP headers */ while (!body && !SOCK_FEOF(*socketd)) { - if (SOCK_FGETS(tmp_line, sizeof(tmp_line)-1, *socketd) != NULL) { - char *p = tmp_line; + http_header_line = emalloc(HTTP_HEADER_BLOCK_SIZE); + http_header_line_size = HTTP_HEADER_BLOCK_SIZE; + http_header_line_length = 0; + if (SOCK_FGETS(http_header_line, HTTP_HEADER_BLOCK_SIZE-1, *socketd) != NULL) { + char *p; + zend_bool found_eol=0; + zval *http_header; - tmp_line[sizeof(tmp_line)-1] = '\0'; + http_header_line[HTTP_HEADER_BLOCK_SIZE-1] = '\0'; - while (*p) { - if (*p == '\n' || *p == '\r') { - *p = '\0'; + do { + p = http_header_line+http_header_line_length; + while (*p) { + while (*p == '\n' || *p == '\r') { + *p = '\0'; + p--; + found_eol=1; + } + if (found_eol) { + break; + } + p++; } - p++; + if (!found_eol) { + http_header_line_size += HTTP_HEADER_BLOCK_SIZE; + http_header_line_length += HTTP_HEADER_BLOCK_SIZE-1; + http_header_line = erealloc(http_header_line, http_header_line_size); + if (SOCK_FGETS(http_header_line+http_header_line_length, HTTP_HEADER_BLOCK_SIZE-1, *socketd)==NULL) { + http_header_line[http_header_line_length] = 0; + break; + } + } else { + http_header_line_length = p-http_header_line+1; + } + } while (!found_eol); + + if (!strncasecmp(http_header_line, "Location: ", 10)) { + strlcpy(location, http_header_line + 10, sizeof(location)); } - if (!strncasecmp(tmp_line, "Location: ", 10)) { - strlcpy(location, tmp_line + 10, sizeof(location)); + if (http_header_line[0] == '\0') { + body = 1; } - - if (tmp_line[0] == '\0') { - body = 1; + + if (http_header_line_length>0) { + MAKE_STD_ZVAL(http_header); + Z_STRVAL_P(http_header) = http_header_line; + Z_STRLEN_P(http_header) = http_header_line_length; + Z_TYPE_P(http_header) = IS_STRING; + zend_hash_next_index_insert(Z_ARRVAL_P(response_header), &http_header, sizeof(zval *), NULL); + } else { + efree(http_header_line); } } } + { + ELS_FETCH(); + + zend_hash_update(EG(active_symbol_table), "http_response_header", sizeof("http_response_header"), (void **) &response_header, sizeof(zval *), NULL); + } if (!reqok) { SOCK_FCLOSE(*socketd); *socketd = 0; diff --git a/main/fopen_wrappers.c b/main/fopen_wrappers.c index 6aaa1bd5ad7..0ec968d887e 100644 --- a/main/fopen_wrappers.c +++ b/main/fopen_wrappers.c @@ -431,24 +431,26 @@ static FILE *php_fopen_url_wrapper(const char *path, char *mode, int options, in int n=0; - for(p=path;isalnum((int)*p);p++) + for (p=path; isalnum((int)*p); p++) { n++; - if((*p==':')&&(n>1)) { + } + if ((*p==':')&&(n>1)) { protocol=path; } - if(protocol) { + if (protocol) { php_fopen_url_wrapper_t *wrapper=NULL; - if(FAILURE==zend_hash_find(&fopen_url_wrappers_hash, (char *)protocol, n, (void **)&wrapper)) { + if (FAILURE==zend_hash_find(&fopen_url_wrappers_hash, (char *) protocol, n, (void **)&wrapper)) { wrapper=NULL; protocol=NULL; } - if(wrapper) + if (wrapper) { return (*wrapper)(path, mode, options, issock, socketd, opened_path); + } } - if( !protocol || !strncasecmp(protocol, "file",n)){ + if (!protocol || !strncasecmp(protocol, "file",n)){ PLS_FETCH(); *issock = 0;