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