+ 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 */
+
+/* {{{ proto int http_request_method_register(string method)
+ *
+ * Register a custom request method.
+ *
+ * Expects a string parameter containing the request method name to register.
+ *
+ * Returns the ID of the request method on success, or FALSE on failure.
+ */
+PHP_FUNCTION(http_request_method_register)
+{
+ char *method;
+ int method_len;
+ ulong existing;
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &method, &method_len)) {
+ RETURN_FALSE;
+ }
+ if ((existing = http_request_method_exists(1, 0, method))) {
+ RETURN_LONG((long) existing);
+ }
+
+ RETVAL_LONG((long) http_request_method_register(method, method_len));
+}
+/* }}} */
+
+/* {{{ proto bool http_request_method_unregister(mixed method)
+ *
+ * Unregister a previously registered custom request method.
+ *
+ * Expects either the request method name or ID.
+ *
+ * Returns TRUE on success, or FALSE on failure.
+ */
+PHP_FUNCTION(http_request_method_unregister)
+{
+ zval *method;