* split into more reasonable modules
[m6w6/ext-http] / http_curl_api.c
1 /*
2 +----------------------------------------------------------------------+
3 | PECL :: http |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.0 of the PHP license, that |
6 | is bundled with this package in the file LICENSE, and is available |
7 | through the world-wide-web at http://www.php.net/license/3_0.txt. |
8 | If you did not receive a copy of the PHP license and are unable to |
9 | obtain it through the world-wide-web, please send a note to |
10 | license@php.net so we can mail you a copy immediately. |
11 +----------------------------------------------------------------------+
12 | Copyright (c) 2004-2005 Michael Wallner <mike@php.net> |
13 +----------------------------------------------------------------------+
14 */
15
16 /* $Id$ */
17
18 #ifdef HAVE_CONFIG_H
19 # include "config.h"
20 #endif
21
22 #ifdef PHP_WIN32
23 # define _WINSOCKAPI_
24 # define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
25 # include <winsock2.h>
26 # include <sys/types.h>
27 #endif
28
29 #include <curl/curl.h>
30 #include <curl/easy.h>
31
32 #include "php.h"
33 #include "php_http.h"
34 #include "php_http_api.h"
35 #include "php_http_curl_api.h"
36
37 #include "ext/standard/php_smart_str.h"
38
39 ZEND_DECLARE_MODULE_GLOBALS(http)
40
41 #define http_curl_initbuf() _http_curl_initbuf_ex(0 TSRMLS_CC)
42 #define http_curl_initbuf_ex(s) _http_curl_initbuf_ex((s) TSRMLS_CC)
43 static inline void _http_curl_initbuf_ex(size_t chunk_size TSRMLS_DC);
44
45 #define http_curl_freebuf() _http_curl_freebuf(TSRMLS_C)
46 static inline void _http_curl_freebuf(TSRMLS_D);
47 #define http_curl_sizebuf(l) _http_curl_sizebuf((l) TSRMLS_CC)
48 static inline void _http_curl_sizebuf(size_t len TSRMLS_DC);
49 #define http_curl_movebuf(d, l) _http_curl_movebuf((d), (l) TSRMLS_CC)
50 static inline void _http_curl_movebuf(char **data, size_t *data_len TSRMLS_DC);
51 #define http_curl_copybuf(d, l) _http_curl_copybuf((d), (l) TSRMLS_CC)
52 static inline void _http_curl_copybuf(char **data, size_t *data_len TSRMLS_DC);
53 #define http_curl_setopts(c, u, o) _http_curl_setopts((c), (u), (o) TSRMLS_CC)
54 static inline void _http_curl_setopts(CURL *ch, const char *url, HashTable *options TSRMLS_DC);
55
56 #define http_curl_getopt(o, k) _http_curl_getopt((o), (k) TSRMLS_CC, 0)
57 #define http_curl_getopt1(o, k, t1) _http_curl_getopt((o), (k) TSRMLS_CC, 1, (t1))
58 #define http_curl_getopt2(o, k, t1, t2) _http_curl_getopt((o), (k) TSRMLS_CC, 2, (t1), (t2))
59 static inline zval *_http_curl_getopt(HashTable *options, char *key TSRMLS_DC, int checks, ...);
60
61 static size_t http_curl_body_callback(char *, size_t, size_t, void *);
62 static size_t http_curl_hdrs_callback(char *, size_t, size_t, void *);
63
64 #define http_curl_getinfo(c, h) _http_curl_getinfo((c), (h) TSRMLS_CC)
65 static inline void _http_curl_getinfo(CURL *ch, HashTable *info TSRMLS_DC);
66 #define http_curl_getinfo_ex(c, i, a) _http_curl_getinfo_ex((c), (i), (a) TSRMLS_CC)
67 static inline void _http_curl_getinfo_ex(CURL *ch, CURLINFO i, zval *array TSRMLS_DC);
68 #define http_curl_getinfoname(i) _http_curl_getinfoname((i) TSRMLS_CC)
69 static inline char *_http_curl_getinfoname(CURLINFO i TSRMLS_DC);
70
71 /* {{{ static inline void http_curl_initbuf(size_t chunk_size) */
72 static inline void _http_curl_initbuf_ex(size_t chunk_size TSRMLS_DC)
73 {
74 size_t size = (chunk_size > 0) ? chunk_size : HTTP_CURLBUF_SIZE;
75
76 http_curl_freebuf();
77
78 HTTP_G(curlbuf).data = emalloc(size);
79 HTTP_G(curlbuf).free = size;
80 HTTP_G(curlbuf).size = size;
81 }
82 /* }}} */
83
84 /* {{{ static inline void http_curl_freebuf(void) */
85 static inline void _http_curl_freebuf(TSRMLS_D)
86 {
87 if (HTTP_G(curlbuf).data) {
88 efree(HTTP_G(curlbuf).data);
89 HTTP_G(curlbuf).data = NULL;
90 }
91 HTTP_G(curlbuf).used = 0;
92 HTTP_G(curlbuf).free = 0;
93 HTTP_G(curlbuf).size = 0;
94 }
95 /* }}} */
96
97 /* {{{ static inline void http_curl_copybuf(char **, size_t *) */
98 static inline void _http_curl_copybuf(char **data, size_t *data_len TSRMLS_DC)
99 {
100 *data_len = HTTP_G(curlbuf).used;
101
102 *data = ecalloc(1, HTTP_G(curlbuf).used + 1);
103 memcpy(*data, HTTP_G(curlbuf).data, *data_len);
104 }
105 /* }}} */
106
107 /* {{{ static inline void http_curl_movebuf(char **, size_t *) */
108 static inline void _http_curl_movebuf(char **data, size_t *data_len TSRMLS_DC)
109 {
110 http_curl_copybuf(data, data_len);
111 http_curl_freebuf();
112 }
113 /* }}} */
114
115 /* {{{ static inline void http_curl_sizebuf(size_t len) */
116 static inline void _http_curl_sizebuf(size_t len TSRMLS_DC)
117 {
118 if (len > HTTP_G(curlbuf).free) {
119 size_t bsize = HTTP_G(curlbuf).size;
120 while (bsize < len) {
121 bsize *= 2;
122 }
123 HTTP_G(curlbuf).data = erealloc(HTTP_G(curlbuf).data, HTTP_G(curlbuf).used + bsize);
124 HTTP_G(curlbuf).free += bsize;
125 }
126 }
127 /* }}} */
128
129 /* {{{ static size_t http_curl_body_callback(char *, size_t, size_t, void *) */
130 static size_t http_curl_body_callback(char *buf, size_t len, size_t n, void *s)
131 {
132 TSRMLS_FETCH();
133
134 http_curl_sizebuf(len *= n);
135
136 memcpy(HTTP_G(curlbuf).data + HTTP_G(curlbuf).used, buf, len);
137 HTTP_G(curlbuf).free -= len;
138 HTTP_G(curlbuf).used += len;
139 return len;
140 }
141 /* }}} */
142
143 /* {{{ static size_t http_curl_hdrs_callback(char *, size_t, size_t, void *) */
144 static size_t http_curl_hdrs_callback(char *buf, size_t len, size_t n, void *s)
145 {
146 TSRMLS_FETCH();
147
148 /* discard previous headers */
149 if ((HTTP_G(curlbuf).used) && (!strncmp(buf, "HTTP/1.", sizeof("HTTP/1.") - 1))) {
150 http_curl_initbuf();
151 }
152 http_curl_sizebuf(len *= n);
153
154 memcpy(HTTP_G(curlbuf).data + HTTP_G(curlbuf).used, buf, len);
155 HTTP_G(curlbuf).free -= len;
156 HTTP_G(curlbuf).used += len;
157 return len;
158 }
159 /* }}} */
160
161 /* {{{ static inline zval *http_curl_getopt(HashTable *, char *, int, ...) */
162 static inline zval *_http_curl_getopt(HashTable *options, char *key TSRMLS_DC, int checks, ...)
163 {
164 zval **zoption;
165 va_list types;
166 int i;
167
168 if (SUCCESS != zend_hash_find(options, key, strlen(key) + 1, (void **) &zoption)) {
169 return NULL;
170 }
171 if (checks < 1) {
172 return *zoption;
173 }
174
175 va_start(types, checks);
176 for (i = 0; i < checks; ++i) {
177 if ((va_arg(types, int)) == (Z_TYPE_PP(zoption))) {
178 va_end(types);
179 return *zoption;
180 }
181 }
182 va_end(types);
183 return NULL;
184 }
185 /* }}} */
186
187 /* {{{ static inline void http_curl_setopts(CURL *, char *, HashTable *) */
188 static inline void _http_curl_setopts(CURL *ch, const char *url, HashTable *options TSRMLS_DC)
189 {
190 zval *zoption;
191
192 /* standard options */
193 curl_easy_setopt(ch, CURLOPT_URL, url);
194 curl_easy_setopt(ch, CURLOPT_HEADER, 0);
195 curl_easy_setopt(ch, CURLOPT_NOPROGRESS, 1);
196 curl_easy_setopt(ch, CURLOPT_AUTOREFERER, 1);
197 curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, http_curl_body_callback);
198 curl_easy_setopt(ch, CURLOPT_HEADERFUNCTION, http_curl_hdrs_callback);
199 #if defined(ZTS) && (LIBCURL_VERSION_NUM >= 0x070a00)
200 curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1);
201 #endif
202
203 if ((!options) || (1 > zend_hash_num_elements(options))) {
204 return;
205 }
206
207 /* redirects, defaults to 0 */
208 if (zoption = http_curl_getopt1(options, "redirect", IS_LONG)) {
209 curl_easy_setopt(ch, CURLOPT_FOLLOWLOCATION, Z_LVAL_P(zoption) ? 1 : 0);
210 curl_easy_setopt(ch, CURLOPT_MAXREDIRS, Z_LVAL_P(zoption));
211 if (zoption = http_curl_getopt2(options, "unrestrictedauth", IS_LONG, IS_BOOL)) {
212 curl_easy_setopt(ch, CURLOPT_UNRESTRICTED_AUTH, Z_LVAL_P(zoption));
213 }
214 } else {
215 curl_easy_setopt(ch, CURLOPT_FOLLOWLOCATION, 0);
216 }
217
218 /* proxy */
219 if (zoption = http_curl_getopt1(options, "proxyhost", IS_STRING)) {
220 curl_easy_setopt(ch, CURLOPT_PROXY, Z_STRVAL_P(zoption));
221 /* port */
222 if (zoption = http_curl_getopt1(options, "proxyport", IS_LONG)) {
223 curl_easy_setopt(ch, CURLOPT_PROXYPORT, Z_LVAL_P(zoption));
224 }
225 /* user:pass */
226 if (zoption = http_curl_getopt1(options, "proxyauth", IS_STRING)) {
227 curl_easy_setopt(ch, CURLOPT_PROXYUSERPWD, Z_STRVAL_P(zoption));
228 }
229 #if LIBCURL_VERSION_NUM > 0x070a06
230 /* auth method */
231 if (zoption = http_curl_getopt1(options, "proxyauthtype", IS_LONG)) {
232 curl_easy_setopt(ch, CURLOPT_PROXYAUTH, Z_LVAL_P(zoption));
233 }
234 #endif
235 }
236
237 /* auth */
238 if (zoption = http_curl_getopt1(options, "httpauth", IS_STRING)) {
239 curl_easy_setopt(ch, CURLOPT_USERPWD, Z_STRVAL_P(zoption));
240 }
241 #if LIBCURL_VERSION_NUM > 0x070a05
242 if (zoption = http_curl_getopt1(options, "httpauthtype", IS_LONG)) {
243 curl_easy_setopt(ch, CURLOPT_HTTPAUTH, Z_LVAL_P(zoption));
244 }
245 #endif
246
247 /* compress, enabled by default (empty string enables deflate and gzip) */
248 if (zoption = http_curl_getopt2(options, "compress", IS_LONG, IS_BOOL)) {
249 if (Z_LVAL_P(zoption)) {
250 curl_easy_setopt(ch, CURLOPT_ENCODING, "");
251 }
252 } else {
253 curl_easy_setopt(ch, CURLOPT_ENCODING, "");
254 }
255
256 /* another port */
257 if (zoption = http_curl_getopt1(options, "port", IS_LONG)) {
258 curl_easy_setopt(ch, CURLOPT_PORT, Z_LVAL_P(zoption));
259 }
260
261 /* referer */
262 if (zoption = http_curl_getopt1(options, "referer", IS_STRING)) {
263 curl_easy_setopt(ch, CURLOPT_REFERER, Z_STRVAL_P(zoption));
264 }
265
266 /* useragent, default "PECL::HTTP/version (PHP/version)" */
267 if (zoption = http_curl_getopt1(options, "useragent", IS_STRING)) {
268 curl_easy_setopt(ch, CURLOPT_USERAGENT, Z_STRVAL_P(zoption));
269 } else {
270 curl_easy_setopt(ch, CURLOPT_USERAGENT,
271 "PECL::HTTP/" PHP_EXT_HTTP_VERSION " (PHP/" PHP_VERSION ")");
272 }
273
274 /* cookies, array('name' => 'value') */
275 if (zoption = http_curl_getopt1(options, "cookies", IS_ARRAY)) {
276 char *cookie_key;
277 zval **cookie_val;
278 int key_type;
279 smart_str qstr = {0};
280
281 zend_hash_internal_pointer_reset(Z_ARRVAL_P(zoption));
282 while (HASH_KEY_NON_EXISTANT != (key_type = zend_hash_get_current_key_type(Z_ARRVAL_P(zoption)))) {
283 if (key_type == HASH_KEY_IS_STRING) {
284 zend_hash_get_current_key(Z_ARRVAL_P(zoption), &cookie_key, NULL, 0);
285 zend_hash_get_current_data(Z_ARRVAL_P(zoption), (void **) &cookie_val);
286 smart_str_appends(&qstr, cookie_key);
287 smart_str_appendl(&qstr, "=", 1);
288 smart_str_appendl(&qstr, Z_STRVAL_PP(cookie_val), Z_STRLEN_PP(cookie_val));
289 smart_str_appendl(&qstr, "; ", 2);
290 zend_hash_move_forward(Z_ARRVAL_P(zoption));
291 }
292 }
293 smart_str_0(&qstr);
294
295 if (qstr.c) {
296 curl_easy_setopt(ch, CURLOPT_COOKIE, qstr.c);
297 /* FIXXXME: mem-leak */
298 }
299 }
300
301 /* cookiestore */
302 if (zoption = http_curl_getopt1(options, "cookiestore", IS_STRING)) {
303 curl_easy_setopt(ch, CURLOPT_COOKIEFILE, Z_STRVAL_P(zoption));
304 curl_easy_setopt(ch, CURLOPT_COOKIEJAR, Z_STRVAL_P(zoption));
305 }
306
307 /* additional headers, array('name' => 'value') */
308 if (zoption = http_curl_getopt1(options, "headers", IS_ARRAY)) {
309 int key_type;
310 char *header_key, header[1024] = {0};
311 zval **header_val;
312 struct curl_slist *headers = NULL;
313
314 zend_hash_internal_pointer_reset(Z_ARRVAL_P(zoption));
315 while (HASH_KEY_NON_EXISTANT != (key_type = zend_hash_get_current_key_type(Z_ARRVAL_P(zoption)))) {
316 if (key_type == HASH_KEY_IS_STRING) {
317 zend_hash_get_current_key(Z_ARRVAL_P(zoption), &header_key, NULL, 0);
318 zend_hash_get_current_data(Z_ARRVAL_P(zoption), (void **) &header_val);
319 snprintf(header, 1023, "%s: %s", header_key, Z_STRVAL_PP(header_val));
320 headers = curl_slist_append(headers, header);
321 zend_hash_move_forward(Z_ARRVAL_P(zoption));
322 }
323 }
324 if (headers) {
325 curl_easy_setopt(ch, CURLOPT_HTTPHEADER, headers);
326 }
327 }
328 }
329 /* }}} */
330
331 /* {{{ static inline char *http_curl_getinfoname(CURLINFO) */
332 static inline char *_http_curl_getinfoname(CURLINFO i TSRMLS_DC)
333 {
334 #define CASE(I) case CURLINFO_ ##I : { static char I[] = #I; return pretty_key(I, sizeof(#I)-1, 0, 0); }
335 switch (i)
336 {
337 /* CURLINFO_EFFECTIVE_URL = CURLINFO_STRING +1, */
338 CASE(EFFECTIVE_URL);
339 /* CURLINFO_RESPONSE_CODE = CURLINFO_LONG +2, */
340 #if LIBCURL_VERSION_NUM > 0x070a06
341 CASE(RESPONSE_CODE);
342 #else
343 CASE(HTTP_CODE);
344 #endif
345 /* CURLINFO_TOTAL_TIME = CURLINFO_DOUBLE +3, */
346 CASE(TOTAL_TIME);
347 /* CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE +4, */
348 CASE(NAMELOOKUP_TIME);
349 /* CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE +5, */
350 CASE(CONNECT_TIME);
351 /* CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE +6, */
352 CASE(PRETRANSFER_TIME);
353 /* CURLINFO_SIZE_UPLOAD = CURLINFO_DOUBLE +7, */
354 CASE(SIZE_UPLOAD);
355 /* CURLINFO_SIZE_DOWNLOAD = CURLINFO_DOUBLE +8, */
356 CASE(SIZE_DOWNLOAD);
357 /* CURLINFO_SPEED_DOWNLOAD = CURLINFO_DOUBLE +9, */
358 CASE(SPEED_DOWNLOAD);
359 /* CURLINFO_SPEED_UPLOAD = CURLINFO_DOUBLE +10, */
360 CASE(SPEED_UPLOAD);
361 /* CURLINFO_HEADER_SIZE = CURLINFO_LONG +11, */
362 CASE(HEADER_SIZE);
363 /* CURLINFO_REQUEST_SIZE = CURLINFO_LONG +12, */
364 CASE(REQUEST_SIZE);
365 /* CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG +13, */
366 CASE(SSL_VERIFYRESULT);
367 /* CURLINFO_FILETIME = CURLINFO_LONG +14, */
368 CASE(FILETIME);
369 /* CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE +15, */
370 CASE(CONTENT_LENGTH_DOWNLOAD);
371 /* CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE +16, */
372 CASE(CONTENT_LENGTH_UPLOAD);
373 /* CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE +17, */
374 CASE(STARTTRANSFER_TIME);
375 /* CURLINFO_CONTENT_TYPE = CURLINFO_STRING +18, */
376 CASE(CONTENT_TYPE);
377 /* CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE +19, */
378 CASE(REDIRECT_TIME);
379 /* CURLINFO_REDIRECT_COUNT = CURLINFO_LONG +20, */
380 CASE(REDIRECT_COUNT);
381 /* CURLINFO_PRIVATE = CURLINFO_STRING +21, * (mike) /
382 CASE(PRIVATE);
383 /* CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG +22, */
384 CASE(HTTP_CONNECTCODE);
385 #if LIBCURL_VERSION_NUM > 0x070a07
386 /* CURLINFO_HTTPAUTH_AVAIL = CURLINFO_LONG +23, */
387 CASE(HTTPAUTH_AVAIL);
388 /* CURLINFO_PROXYAUTH_AVAIL = CURLINFO_LONG +24, */
389 CASE(PROXYAUTH_AVAIL);
390 #endif
391 }
392 #undef CASE
393 return NULL;
394 }
395 /* }}} */
396
397 /* {{{ static inline void http_curl_getinfo_ex(CURL, CURLINFO, zval *) */
398 static inline void _http_curl_getinfo_ex(CURL *ch, CURLINFO i, zval *array TSRMLS_DC)
399 {
400 char *key;
401 if (key = http_curl_getinfoname(i)) {
402 switch (i & ~CURLINFO_MASK)
403 {
404 case CURLINFO_STRING:
405 {
406 char *c;
407 if (CURLE_OK == curl_easy_getinfo(ch, i, &c)) {
408 add_assoc_string(array, key, c ? c : "", 1);
409 }
410 }
411 break;
412
413 case CURLINFO_DOUBLE:
414 {
415 double d;
416 if (CURLE_OK == curl_easy_getinfo(ch, i, &d)) {
417 add_assoc_double(array, key, d);
418 }
419 }
420 break;
421
422 case CURLINFO_LONG:
423 {
424 long l;
425 if (CURLE_OK == curl_easy_getinfo(ch, i, &l)) {
426 add_assoc_long(array, key, l);
427 }
428 }
429 break;
430 }
431 }
432 }
433 /* }}} */
434
435 /* {{{ static inline http_curl_getinfo(CURL, HashTable *) */
436 static inline void _http_curl_getinfo(CURL *ch, HashTable *info TSRMLS_DC)
437 {
438 zval array;
439 Z_ARRVAL(array) = info;
440
441 #define INFO(I) http_curl_getinfo_ex(ch, CURLINFO_ ##I , &array)
442 /* CURLINFO_EFFECTIVE_URL = CURLINFO_STRING +1, */
443 INFO(EFFECTIVE_URL);
444 #if LIBCURL_VERSION_NUM > 0x070a06
445 /* CURLINFO_RESPONSE_CODE = CURLINFO_LONG +2, */
446 INFO(RESPONSE_CODE);
447 #else
448 INFO(HTTP_CODE);
449 #endif
450 /* CURLINFO_TOTAL_TIME = CURLINFO_DOUBLE +3, */
451 INFO(TOTAL_TIME);
452 /* CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE +4, */
453 INFO(NAMELOOKUP_TIME);
454 /* CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE +5, */
455 INFO(CONNECT_TIME);
456 /* CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE +6, */
457 INFO(PRETRANSFER_TIME);
458 /* CURLINFO_SIZE_UPLOAD = CURLINFO_DOUBLE +7, */
459 INFO(SIZE_UPLOAD);
460 /* CURLINFO_SIZE_DOWNLOAD = CURLINFO_DOUBLE +8, */
461 INFO(SIZE_DOWNLOAD);
462 /* CURLINFO_SPEED_DOWNLOAD = CURLINFO_DOUBLE +9, */
463 INFO(SPEED_DOWNLOAD);
464 /* CURLINFO_SPEED_UPLOAD = CURLINFO_DOUBLE +10, */
465 INFO(SPEED_UPLOAD);
466 /* CURLINFO_HEADER_SIZE = CURLINFO_LONG +11, */
467 INFO(HEADER_SIZE);
468 /* CURLINFO_REQUEST_SIZE = CURLINFO_LONG +12, */
469 INFO(REQUEST_SIZE);
470 /* CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG +13, */
471 INFO(SSL_VERIFYRESULT);
472 /* CURLINFO_FILETIME = CURLINFO_LONG +14, */
473 INFO(FILETIME);
474 /* CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE +15, */
475 INFO(CONTENT_LENGTH_DOWNLOAD);
476 /* CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE +16, */
477 INFO(CONTENT_LENGTH_UPLOAD);
478 /* CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE +17, */
479 INFO(STARTTRANSFER_TIME);
480 /* CURLINFO_CONTENT_TYPE = CURLINFO_STRING +18, */
481 INFO(CONTENT_TYPE);
482 /* CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE +19, */
483 INFO(REDIRECT_TIME);
484 /* CURLINFO_REDIRECT_COUNT = CURLINFO_LONG +20, */
485 INFO(REDIRECT_COUNT);
486 /* CURLINFO_PRIVATE = CURLINFO_STRING +21, */
487 INFO(PRIVATE);
488 /* CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG +22, */
489 INFO(HTTP_CONNECTCODE);
490 #if LIBCURL_VERSION_NUM > 0x070a07
491 /* CURLINFO_HTTPAUTH_AVAIL = CURLINFO_LONG +23, */
492 INFO(HTTPAUTH_AVAIL);
493 /* CURLINFO_PROXYAUTH_AVAIL = CURLINFO_LONG +24, */
494 INFO(PROXYAUTH_AVAIL);
495 #endif
496 #undef INFO
497 }
498 /* }}} */
499
500
501
502 /* {{{ STATUS http_get(char *, HashTable *, HashTable *, char **, size_t *) */
503 PHP_HTTP_API STATUS _http_get(const char *URL, HashTable *options,
504 HashTable *info, char **data, size_t *data_len TSRMLS_DC)
505 {
506 STATUS rs;
507 CURL *ch = curl_easy_init();
508
509 if (!ch) {
510 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not initialize curl");
511 return FAILURE;
512 }
513
514 rs = http_get_ex(ch, URL, options, info, data, data_len);
515 curl_easy_cleanup(ch);
516 return rs;
517 }
518 /* }}} */
519
520 /* {{{ STATUS http_get_ex(CURL *, char *, HashTable *, HashTable *, char **, size_t *) */
521 PHP_HTTP_API STATUS _http_get_ex(CURL *ch, const char *URL, HashTable *options,
522 HashTable *info, char **data, size_t *data_len TSRMLS_DC)
523 {
524 http_curl_initbuf();
525 http_curl_setopts(ch, URL, options);
526 curl_easy_setopt(ch, CURLOPT_NOBODY, 0);
527 curl_easy_setopt(ch, CURLOPT_POST, 0);
528
529 if (CURLE_OK != curl_easy_perform(ch)) {
530 http_curl_freebuf();
531 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not perform request");
532 return FAILURE;
533 }
534 if (info) {
535 http_curl_getinfo(ch, info);
536 }
537 http_curl_movebuf(data, data_len);
538 return SUCCESS;
539 }
540
541 /* {{{ STATUS http_head(char *, HashTable *, HashTable *, char **data, size_t *) */
542 PHP_HTTP_API STATUS _http_head(const char *URL, HashTable *options,
543 HashTable *info, char **data, size_t *data_len TSRMLS_DC)
544 {
545 STATUS rs;
546 CURL *ch = curl_easy_init();
547
548 if (!ch) {
549 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not initialize curl");
550 return FAILURE;
551 }
552
553 rs = http_head_ex(ch, URL, options, info, data, data_len);
554 curl_easy_cleanup(ch);
555 return rs;
556 }
557 /* }}} */
558
559 /* {{{ STATUS http_head_ex(CURL *, char *, HashTable *, HashTable *, char **data, size_t *) */
560 PHP_HTTP_API STATUS _http_head_ex(CURL *ch, const char *URL, HashTable *options,
561 HashTable *info, char **data, size_t *data_len TSRMLS_DC)
562 {
563 http_curl_initbuf();
564 http_curl_setopts(ch, URL, options);
565 curl_easy_setopt(ch, CURLOPT_NOBODY, 1);
566 curl_easy_setopt(ch, CURLOPT_POST, 0);
567
568 if (CURLE_OK != curl_easy_perform(ch)) {
569 http_curl_freebuf();
570 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not perform request");
571 return FAILURE;
572 }
573 if (info) {
574 http_curl_getinfo(ch, info);
575 }
576 http_curl_movebuf(data, data_len);
577 return SUCCESS;
578 }
579
580 /* {{{ STATUS http_post_data(char *, char *, size_t, HashTable *, HashTable *, char **, size_t *) */
581 PHP_HTTP_API STATUS _http_post_data(const char *URL, char *postdata,
582 size_t postdata_len, HashTable *options, HashTable *info, char **data,
583 size_t *data_len TSRMLS_DC)
584 {
585 STATUS rs;
586 CURL *ch = curl_easy_init();
587
588 if (!ch) {
589 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not initialize curl");
590 return FAILURE;
591 }
592 rs = http_post_data_ex(ch, URL, postdata, postdata_len, options, info, data, data_len);
593 curl_easy_cleanup(ch);
594 return rs;
595 }
596 /* }}} */
597
598 /* {{{ STATUS http_post_data_ex(CURL *, char *, char *, size_t, HashTable *, HashTable *, char **, size_t *) */
599 PHP_HTTP_API STATUS _http_post_data_ex(CURL *ch, const char *URL, char *postdata,
600 size_t postdata_len, HashTable *options, HashTable *info, char **data,
601 size_t *data_len TSRMLS_DC)
602 {
603 http_curl_initbuf();
604 http_curl_setopts(ch, URL, options);
605 curl_easy_setopt(ch, CURLOPT_POST, 1);
606 curl_easy_setopt(ch, CURLOPT_POSTFIELDS, postdata);
607 curl_easy_setopt(ch, CURLOPT_POSTFIELDSIZE, postdata_len);
608
609 if (CURLE_OK != curl_easy_perform(ch)) {
610 http_curl_freebuf();
611 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not perform request");
612 return FAILURE;
613 }
614 if (info) {
615 http_curl_getinfo(ch, info);
616 }
617 http_curl_movebuf(data, data_len);
618 return SUCCESS;
619 }
620 /* }}} */
621
622 /* {{{ STATUS http_post_array_ex(CURL *, char *, HashTable *, HashTable *, HashTable *, char **, size_t *) */
623 PHP_HTTP_API STATUS _http_post_array_ex(CURL *ch, const char *URL, HashTable *postarray,
624 HashTable *options, HashTable *info, char **data, size_t *data_len TSRMLS_DC)
625 {
626 smart_str qstr = {0};
627 STATUS status;
628
629 HTTP_URL_ARGSEP_OVERRIDE;
630 if (php_url_encode_hash_ex(postarray, &qstr, NULL,0,NULL,0,NULL,0,NULL TSRMLS_CC) != SUCCESS) {
631 if (qstr.c) {
632 efree(qstr.c);
633 }
634 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not encode post data");
635 HTTP_URL_ARGSEP_RESTORE;
636 return FAILURE;
637 }
638 smart_str_0(&qstr);
639 HTTP_URL_ARGSEP_RESTORE;
640
641 if (ch) {
642 status = http_post_data_ex(ch, URL, qstr.c, qstr.len, options, info, data, data_len);
643 } else {
644 status = http_post_data(URL, qstr.c, qstr.len, options, info, data, data_len);
645 }
646
647 if (qstr.c) {
648 efree(qstr.c);
649 }
650 return status;
651 }
652 /* }}} */
653
654 /* {{{ STATUS http_post_curldata_ex(CURL *, char *, curl_httppost *, HashTable *, HashTable *, char **, size_t *) */
655 PHP_HTTP_API STATUS _http_post_curldata_ex(CURL *ch, const char *URL,
656 struct curl_httppost *curldata, HashTable *options, HashTable *info,
657 char **data, size_t *data_len TSRMLS_DC)
658 {
659 http_curl_initbuf();
660 http_curl_setopts(ch, URL, options);
661 curl_easy_setopt(ch, CURLOPT_POST, 1);
662 curl_easy_setopt(ch, CURLOPT_HTTPPOST, curldata);
663
664 if (CURLE_OK != curl_easy_perform(ch)) {
665 http_curl_freebuf();
666 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not perform request");
667 return FAILURE;
668 }
669 if (info) {
670 http_curl_getinfo(ch, info);
671 }
672 http_curl_movebuf(data, data_len);
673 return SUCCESS;}
674 /* }}} */
675
676
677 /*
678 * Local variables:
679 * tab-width: 4
680 * c-basic-offset: 4
681 * End:
682 * vim600: noet sw=4 ts=4 fdm=marker
683 * vim<600: noet sw=4 ts=4
684 */