}
/* }}} */
-/* {{{ proto string http_build_url(mixed url[, mixed parts[, int flags = HTTP_URL_REPLACE[, array &new_url]]])
+/* {{{ proto string http_build_url([mixed url[, mixed parts[, int flags = HTTP_URL_REPLACE[, array &new_url]]]])
*
* Build an URL.
*
zval *z_old_url = NULL, *z_new_url = NULL, *z_composed_url = NULL;
php_url *old_url = NULL, *new_url = NULL, *composed_url = NULL;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/|z/lz", &z_old_url, &z_new_url, &flags, &z_composed_url) != SUCCESS) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z/z/lz", &z_old_url, &z_new_url, &flags, &z_composed_url) != SUCCESS) {
RETURN_FALSE;
}
}
}
- if (Z_TYPE_P(z_old_url) == IS_ARRAY || Z_TYPE_P(z_old_url) == IS_OBJECT) {
- old_url = array2url(HASH_OF(z_old_url));
- } else {
- convert_to_string(z_old_url);
- if (!(old_url = php_url_parse_ex(Z_STRVAL_P(z_old_url), Z_STRLEN_P(z_old_url)))) {
- if (new_url) {
- php_url_free(new_url);
+ if (z_old_url) {
+ if (Z_TYPE_P(z_old_url) == IS_ARRAY || Z_TYPE_P(z_old_url) == IS_OBJECT) {
+ old_url = array2url(HASH_OF(z_old_url));
+ } else {
+ convert_to_string(z_old_url);
+ if (!(old_url = php_url_parse_ex(Z_STRVAL_P(z_old_url), Z_STRLEN_P(z_old_url)))) {
+ if (new_url) {
+ php_url_free(new_url);
+ }
+ http_error_ex(HE_WARNING, HTTP_E_URL, "Could not parse URL (%s)", Z_STRVAL_P(z_old_url));
+ RETURN_FALSE;
}
- http_error_ex(HE_WARNING, HTTP_E_URL, "Could not parse URL (%s)", Z_STRVAL_P(z_old_url));
- RETURN_FALSE;
}
}
if (new_url) {
php_url_free(new_url);
}
- php_url_free(old_url);
+ if (old_url) {
+ php_url_free(old_url);
+ }
RETURN_STRINGL(url_str, url_len, 0);
}
zval **value; \
\
zend_hash_internal_pointer_reset(Z_ARRVAL_P(supported)); \
- if (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(supported), (void **) &value)) { \
+ if (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(supported), (void *) &value)) { \
RETVAL_ZVAL(*value, 1, 0); \
} else { \
RETVAL_NULL(); \
*/
PHP_FUNCTION(http_redirect)
{
- int url_len;
+ int url_len = 0;
size_t query_len = 0;
zend_bool session = 0, free_params = 0;
zval *params = NULL;
array_init(return_value);
if (SUCCESS != http_parse_headers(header, return_value)) {
zval_dtor(return_value);
+ http_error(HE_WARNING, HTTP_E_MALFORMED_HEADERS, "Failed to parse headers");
RETURN_FALSE;
}
}
zval **bodyonly; \
\
/* check if only the body should be returned */ \
- if (options && (SUCCESS == zend_hash_find(Z_ARRVAL_P(options), "bodyonly", sizeof("bodyonly"), (void **) &bodyonly)) && zval_is_true(*bodyonly)) { \
+ if (options && (SUCCESS == zend_hash_find(Z_ARRVAL_P(options), "bodyonly", sizeof("bodyonly"), (void *) &bodyonly)) && zval_is_true(*bodyonly)) { \
http_message *msg = http_message_parse(PHPSTR_VAL(&request.conv.response), PHPSTR_LEN(&request.conv.response)); \
\
if (msg) { \
* redirects to a different host
* - proxyhost: string, proxy host in "host[:port]" format
* - proxyport: int, use another proxy port as specified in proxyhost
+ * - proxytype: int, HTTP_PROXY_HTTP, SOCKS4 or SOCKS5
* - proxyauth: string, proxy credentials in "user:pass" format
* - proxyauthtype: int, HTTP_AUTH_BASIC and/or HTTP_AUTH_NTLM
* - httpauth: string, http credentials in "user:pass" format
* - encodecookies: bool, whether to urlencode the cookies (default: true)
* - resetcookies: bool, wheter to reset the cookies
* - cookiestore: string, path to a file where cookies are/will be stored
+ * - cookiesession: bool, accept (true) or reset (false) sessioncookies
* - resume: int, byte offset to start the download from;
* if the server supports ranges
+ * - range: array, array of arrays, each containing two integers,
+ * specifying the ranges to download if server support is
+ * given; only recognized if the resume option is empty
* - maxfilesize: int, maximum file size that should be downloaded;
* has no effect, if the size of the requested entity is not known
* - lastmodified: int, timestamp for If-(Un)Modified-Since header
* - timeout: int, seconds the request may take
* - connecttimeout: int, seconds the connect may take
* - onprogress: mixed, progress callback
+ * - interface: string, outgoing network interface (ifname, ip or hostname)
+ * - portrange: array, 2 integers specifying outgoing portrange to try
* - ssl: array, with the following options:
* cert: string, path to certificate
* certtype: string, type of certificate
RETURN_FALSE;
}
- if (!(stream = php_stream_open_wrapper(file, "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL))) {
+ if (!(stream = php_stream_open_wrapper_ex(file, "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL, HTTP_DEFAULT_STREAM_CONTEXT))) {
RETURN_FALSE;
}
if (php_stream_stat(stream, &ssb)) {
RETVAL_FALSE;
- body.type = HTTP_REQUEST_BODY_UPLOADFILE;
- body.data = stream;
- body.size = ssb.sb.st_size;
-
http_request_init_ex(&request, NULL, HTTP_PUT, URL);
- request.body = &body;
+ request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_UPLOADFILE, stream, ssb.sb.st_size, 1);
if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
http_request_exec(&request);
if (info) {
}
RETVAL_RESPONSE_OR_BODY(request);
}
- http_request_body_dtor(&body);
- request.body = NULL;
http_request_dtor(&request);
}
/* }}} */
* opened stream, from which the data to upload should be read.
* See http_get() for a full list of available options.
*
- * Returns the HTTP response(s) as string on success. or FALSE on failure.
+ * Returns the HTTP response(s) as string on success, or FALSE on failure.
*/
PHP_FUNCTION(http_put_stream)
{
RETVAL_FALSE;
- body.type = HTTP_REQUEST_BODY_UPLOADFILE;
- body.data = stream;
- body.size = ssb.sb.st_size;
+ http_request_init_ex(&request, NULL, HTTP_PUT, URL);
+ request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_UPLOADFILE, stream, ssb.sb.st_size, 0);
+ if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
+ http_request_exec(&request);
+ if (info) {
+ http_request_info(&request, Z_ARRVAL_P(info));
+ }
+ RETVAL_RESPONSE_OR_BODY(request);
+ }
+ http_request_dtor(&request);
+}
+/* }}} */
- http_request_init_ex(&request, NULL, HTTP_POST, URL);
- request.body = &body;
+/* {{{ proto string http_put_data(string url, string data[, array options[, array &info]])
+ *
+ * Performs an HTTP PUT request on the supplied url.
+ *
+ * Expects the second parameter to be a string containing the data to upload.
+ * See http_get() for a full list of available options.
+ *
+ * Returns the HTTP response(s) as string on success, or FALSE on failure.
+ */
+PHP_FUNCTION(http_put_data)
+{
+ char *URL, *data;
+ int URL_len, data_len;
+ zval *options = NULL, *info = NULL;
+ http_request_body body;
+ http_request request;
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!z", &URL, &URL_len, &data, &data_len, &options, &info)) {
+ RETURN_FALSE;
+ }
+
+ if (info) {
+ zval_dtor(info);
+ array_init(info);
+ }
+
+ RETVAL_FALSE;
+
+ http_request_init_ex(&request, NULL, HTTP_PUT, URL);
+ request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_CSTRING, data, data_len, 0);
if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
http_request_exec(&request);
if (info) {
}
RETVAL_RESPONSE_OR_BODY(request);
}
- request.body = NULL;
http_request_dtor(&request);
}
/* }}} */
+
+/* {{{ proto string http_request(int method, string url[, string body[, array options[, array &info]]])
+ *
+ * Performs a custom HTTP request on the supplied url.
+ *
+ * Expects the first parameter to be an integer specifying the request method to use.
+ * Accepts an optional third string parameter containing the raw request body.
+ * See http_get() for a full list of available options.
+ *
+ * Returns the HTTP response(s) as string on success, or FALSE on failure.
+ */
+PHP_FUNCTION(http_request)
+{
+ long meth;
+ char *URL, *data = NULL;
+ int URL_len, data_len = 0;
+ zval *options = NULL, *info = NULL;
+ http_request_body body;
+ http_request request;
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls|sa/!z", &meth, &URL, &URL_len, &data, &data_len, &options, &info)) {
+ RETURN_FALSE;
+ }
+
+ if (info) {
+ zval_dtor(info);
+ array_init(info);
+ }
+
+ RETVAL_FALSE;
+
+ http_request_init_ex(&request, NULL, meth, URL);
+ request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_CSTRING, data, data_len, 0);
+ if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
+ http_request_exec(&request);
+ if (info) {
+ http_request_info(&request, Z_ARRVAL_P(info));
+ }
+ RETVAL_RESPONSE_OR_BODY(request);
+ }
+ http_request_dtor(&request);
+}
+/* }}} */
+
+static char *file_get_contents(char *file, size_t *len TSRMLS_DC)
+{
+ php_stream *s = NULL;
+ char *buf = NULL;
+
+ if ((s = php_stream_open_wrapper_ex(file, "rb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL, HTTP_DEFAULT_STREAM_CONTEXT))) {
+ *len = php_stream_copy_to_mem(s, &buf, (size_t) -1, 0);
+ php_stream_close(s);
+ } else {
+ *len = 0;
+ }
+ return buf;
+}
+struct FormData {
+ struct FormData *next;
+ int type;
+ char *line;
+ size_t length;
+};
+CURLcode Curl_getFormData(struct FormData **, struct curl_httppost *post, curl_off_t *size);
+
+/* {{{ proto string http_request_body_encode(array fields, array files)
+ *
+ * Generate x-www-form-urlencoded resp. form-data encoded request body.
+ *
+ * Returns encoded string on success, or FALSE on failure.
+ */
+PHP_FUNCTION(http_request_body_encode)
+{
+ zval *fields = NULL, *files = NULL;
+ HashTable *fields_ht, *files_ht;
+ http_request_body body;
+ phpstr rbuf;
+ struct FormData *data, *ptr;
+ curl_off_t size;
+ char *fdata = NULL;
+ size_t fsize = 0;
+ CURLcode rc;
+ int fgc_error = 0;
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!a!", &fields, &files)) {
+ RETURN_FALSE;
+ }
+
+ fields_ht = (fields && Z_TYPE_P(fields) == IS_ARRAY) ? Z_ARRVAL_P(fields) : NULL;
+ files_ht = (files && Z_TYPE_P(files) == IS_ARRAY) ? Z_ARRVAL_P(files) : NULL;
+ if (!http_request_body_fill(&body, fields_ht, files_ht)) {
+ RETURN_FALSE;
+ }
+
+ switch (body.type)
+ {
+ case HTTP_REQUEST_BODY_CURLPOST:
+ if (CURLE_OK != (rc = Curl_getFormData(&data, body.data, &size))) {
+ http_error_ex(HE_WARNING, HTTP_E_RUNTIME, "Could not encode request body: %s", curl_easy_strerror(rc));
+ RETVAL_FALSE;
+ } else {
+ phpstr_init_ex(&rbuf, (size_t) size, PHPSTR_INIT_PREALLOC);
+ for (ptr = data; ptr; ptr = ptr->next) {
+ if (!fgc_error) {
+ if (ptr->type) {
+ if ((fdata = file_get_contents(ptr->line, &fsize TSRMLS_CC))) {
+ phpstr_append(&rbuf, fdata, fsize);
+ efree(fdata);
+ } else {
+ fgc_error = 1;
+ }
+ } else {
+ phpstr_append(&rbuf, ptr->line, ptr->length);
+ }
+ }
+ curl_free(ptr->line);
+ }
+ curl_free(data);
+ if (fgc_error) {
+ phpstr_dtor(&rbuf);
+ RETVAL_FALSE;
+ } else {
+ RETVAL_PHPSTR_VAL(&rbuf);
+ }
+ }
+ http_request_body_dtor(&body);
+ break;
+
+ case HTTP_REQUEST_BODY_CSTRING:
+ RETVAL_STRINGL(body.data, body.size, 0);
+ break;
+
+ default:
+ http_request_body_dtor(&body);
+ RETVAL_FALSE;
+ break;
+ }
+}
#endif /* HTTP_HAVE_CURL */
/* }}} HAVE_CURL */