#define HTTP_HEADER_BLOCK_SIZE 1024
#define PHP_URL_REDIRECT_MAX 20
-
+#define HTTP_HEADER_USER_AGENT 1
+#define HTTP_HEADER_HOST 2
+#define HTTP_HEADER_AUTH 4
+#define HTTP_HEADER_FROM 8
php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context, int redirect_max STREAMS_DC TSRMLS_DC)
{
char *scratch = NULL;
char *tmp = NULL;
char *ua_str = NULL;
- zval **ua_zval = NULL;
+ zval **ua_zval = NULL, **tmpzval = NULL;
int scratch_len = 0;
int body = 0;
char location[HTTP_HEADER_BLOCK_SIZE];
size_t chunk_size = 0, file_size = 0;
int eol_detect;
char *transport_string, *errstr = NULL;
- int transport_len;
+ int transport_len, have_header = 0;
if (redirect_max < 1) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Circular redirect, aborting.");
scratch_len = strlen(path) + 32;
scratch = emalloc(scratch_len);
- strcpy(scratch, "GET ");
+ if (context &&
+ php_stream_context_get_option(context, "http", "method", &tmpzval) == SUCCESS &&
+ Z_STRLEN_PP(tmpzval) > 0 &&
+ strncasecmp(Z_STRVAL_PP(tmpzval), "POST", Z_STRLEN_PP(tmpzval)) == 0) {
+ strcpy(scratch, "POST ");
+ } else {
+ strcpy(scratch, "GET ");
+ }
/* file */
if (resource->path && *resource->path)
strlcat(scratch, resource->path, scratch_len);
else
strlcat(scratch, "/", scratch_len);
-
+
/* query string */
if (resource->query) {
strlcat(scratch, "?", scratch_len);
/* send it */
php_stream_write(stream, scratch, strlen(scratch));
+ if (context &&
+ php_stream_context_get_option(context, "http", "header", &tmpzval) == SUCCESS &&
+ Z_STRLEN_PP(tmpzval)) {
+ /* Remove newlines and spaces from start and end,
+ php_trim will estrndup() */
+ tmp = php_trim(Z_STRVAL_PP(tmpzval), Z_STRLEN_PP(tmpzval), NULL, 0, NULL, 3 TSRMLS_CC);
+ if (strlen(tmp) > 0) {
+ /* Output trimmed headers with \r\n at the end */
+ php_stream_write(stream, tmp, strlen(tmp));
+ php_stream_write(stream, "\r\n", sizeof("\r\n") - 1);
+
+ /* Make lowercase for easy comparison against 'standard' headers */
+ php_strtolower(tmp, strlen(tmp));
+ if (strstr(tmp, "user-agent:")) {
+ have_header |= HTTP_HEADER_USER_AGENT;
+ }
+ if (strstr(tmp, "host:")) {
+ have_header |= HTTP_HEADER_HOST;
+ }
+ if (strstr(tmp, "from:")) {
+ have_header |= HTTP_HEADER_FROM;
+ }
+ if (strstr(tmp, "authorization:")) {
+ have_header |= HTTP_HEADER_AUTH;
+ }
+ }
+ efree(tmp);
+ }
+
/* auth header if it was specified */
- if (resource->user && resource->pass) {
+ if (((have_header & HTTP_HEADER_AUTH) == 0) && resource->user && resource->pass) {
/* decode the strings first */
php_url_decode(resource->user, strlen(resource->user));
php_url_decode(resource->pass, strlen(resource->pass));
}
/* if the user has configured who they are, send a From: line */
- if (cfg_get_string("from", &tmp) == SUCCESS) {
+ if (((have_header & HTTP_HEADER_FROM) == 0) && cfg_get_string("from", &tmp) == SUCCESS) {
if (snprintf(scratch, scratch_len, "From: %s\r\n", tmp) > 0)
php_stream_write(stream, scratch, strlen(scratch));
}
/* Send Host: header so name-based virtual hosts work */
- if ((use_ssl && resource->port != 443) || (!use_ssl && resource->port != 80)) {
- if (snprintf(scratch, scratch_len, "Host: %s:%i\r\n", resource->host, resource->port) > 0)
- php_stream_write(stream, scratch, strlen(scratch));
+ if ((have_header & HTTP_HEADER_HOST) == 0) {
+ if ((use_ssl && resource->port != 443) || (!use_ssl && resource->port != 80)) {
+ if (snprintf(scratch, scratch_len, "Host: %s:%i\r\n", resource->host, resource->port) > 0)
+ php_stream_write(stream, scratch, strlen(scratch));
+ } else {
+ if (snprintf(scratch, scratch_len, "Host: %s\r\n", resource->host) > 0) {
+ php_stream_write(stream, scratch, strlen(scratch));
+ }
+ }
}
- else if (snprintf(scratch, scratch_len, "Host: %s\r\n", resource->host) > 0)
- php_stream_write(stream, scratch, strlen(scratch));
if (context &&
php_stream_context_get_option(context, "http", "user_agent", &ua_zval) == SUCCESS) {
ua_str = FG(user_agent);
}
- if (ua_str) {
+ if (((have_header & HTTP_HEADER_USER_AGENT) == 0) && ua_str) {
#define _UA_HEADER "User-Agent: %s\r\n"
char *ua;
size_t ua_len;
php_stream_write(stream, "\r\n", sizeof("\r\n")-1);
+ /* Request content, such as for POST requests */
+ if (context &&
+ php_stream_context_get_option(context, "http", "content", &tmpzval) == SUCCESS &&
+ Z_STRLEN_PP(tmpzval) > 0) {
+ php_stream_write(stream, Z_STRVAL_PP(tmpzval), Z_STRLEN_PP(tmpzval));
+ php_stream_write(stream, "\r\n\r\n", sizeof("\r\n\r\n")-1);
+ }
+
location[0] = '\0';
MAKE_STD_ZVAL(response_header);