PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/curl - streams.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 172 204 84.3 %
Date: 2014-04-19 Functions: 8 10 80.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 5                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1997-2014 The PHP Group                                |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 3.01 of the PHP license,      |
       8             :    | that is bundled with this package in the file LICENSE, and is        |
       9             :    | available through the world-wide-web at the following url:           |
      10             :    | http://www.php.net/license/3_01.txt                                  |
      11             :    | If you did not receive a copy of the PHP license and are unable to   |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@php.net so we can mail you a copy immediately.               |
      14             :    +----------------------------------------------------------------------+
      15             :    | Author: Wez Furlong <wez@thebrainroom.com>                           |
      16             :    +----------------------------------------------------------------------+
      17             : */
      18             : 
      19             : /* $Id$ */
      20             : 
      21             : /* This file implements cURL based wrappers.
      22             :  * NOTE: If you are implementing your own streams that are intended to
      23             :  * work independently of wrappers, this is not a good example to follow!
      24             :  **/
      25             : 
      26             : #ifdef HAVE_CONFIG_H
      27             : #include "config.h"
      28             : #endif
      29             : 
      30             : #include "php.h"
      31             : #include "php_memory_streams.h"
      32             : 
      33             : #if HAVE_CURL
      34             : 
      35             : #include <stdio.h>
      36             : #include <string.h>
      37             : 
      38             : #ifdef PHP_WIN32
      39             : #include <winsock2.h>
      40             : #include <sys/types.h>
      41             : #endif
      42             : 
      43             : #include <curl/curl.h>
      44             : #include <curl/easy.h>
      45             : 
      46             : #define SMART_STR_PREALLOC 4096
      47             : 
      48             : #include "ext/standard/php_smart_str.h"
      49             : #include "ext/standard/info.h"
      50             : #include "ext/standard/file.h"
      51             : #include "ext/standard/php_string.h"
      52             : #include "php_curl.h"
      53             : 
      54          23 : static size_t on_data_available(char *data, size_t size, size_t nmemb, void *ctx)
      55             : {
      56          23 :         php_stream *stream = (php_stream *) ctx;
      57          23 :         php_curl_stream *curlstream = (php_curl_stream *) stream->abstract;
      58             :         size_t wrote;
      59             :         TSRMLS_FETCH();
      60             : 
      61             :         /* TODO: I'd like to deprecate this.
      62             :          * This code is here because until we start getting real data, we don't know
      63             :          * if we have had all of the headers 
      64             :          * */
      65          23 :         if (curlstream->readbuffer.writepos == 0) {
      66             :                 zval *sym;
      67             : 
      68          13 :                 if (!EG(active_symbol_table)) {
      69           8 :                         zend_rebuild_symbol_table(TSRMLS_C);
      70             :                 }
      71          13 :                 MAKE_STD_ZVAL(sym);
      72          13 :                 *sym = *curlstream->headers;
      73          13 :                 zval_copy_ctor(sym);
      74          42 :                 ZEND_SET_SYMBOL(EG(active_symbol_table), "http_response_header", sym);
      75             :         }
      76             :         
      77          23 :         php_stream_seek(curlstream->readbuffer.buf, curlstream->readbuffer.writepos, SEEK_SET);
      78          23 :         wrote = php_stream_write(curlstream->readbuffer.buf, data, size * nmemb);
      79          23 :         curlstream->readbuffer.writepos = php_stream_tell(curlstream->readbuffer.buf);
      80             : 
      81          23 :         return wrote;
      82             : }
      83             : 
      84             : /* cURL guarantees that headers are written as complete lines, with this function
      85             :  * called once for each header */
      86          92 : static size_t on_header_available(char *data, size_t size, size_t nmemb, void *ctx)
      87             : {
      88          92 :         size_t length = size * nmemb;
      89             :         zval *header;
      90          92 :         php_stream *stream = (php_stream *) ctx;
      91          92 :         php_curl_stream *curlstream = (php_curl_stream *) stream->abstract;
      92             :         TSRMLS_FETCH();
      93             : 
      94          92 :         if (length < 2) {
      95             :                 /* invalid header ? */
      96           0 :                 return length;
      97             :         }
      98             : 
      99          92 :         if (!(length == 2 && data[0] == '\r' && data[1] == '\n')) {
     100          67 :                 MAKE_STD_ZVAL(header);
     101          67 :                 Z_STRLEN_P(header) = length;
     102          67 :                 Z_STRVAL_P(header) = estrndup(data, length);
     103          67 :                 if (Z_STRVAL_P(header)[length-1] == '\n') {
     104          67 :                         Z_STRVAL_P(header)[length-1] = '\0';
     105          67 :                         Z_STRLEN_P(header)--;
     106             :                         
     107          67 :                         if (Z_STRVAL_P(header)[length-2] == '\r') {
     108          67 :                                 Z_STRVAL_P(header)[length-2] = '\0';
     109          67 :                                 Z_STRLEN_P(header)--;
     110             :                         }
     111             :                 }
     112          67 :                 Z_TYPE_P(header) = IS_STRING;
     113          67 :                 zend_hash_next_index_insert(Z_ARRVAL_P(curlstream->headers), &header, sizeof(zval *), NULL);
     114             :                 
     115             :                 /* based on the header, we might need to trigger a notification */
     116          67 :                 if (!strncasecmp(data, "Location: ", 10)) {
     117          13 :                         php_stream_notify_info(stream->context, PHP_STREAM_NOTIFY_REDIRECTED, data + 10, 0);
     118          54 :                 } else if (!strncasecmp(data, "Content-Type: ", 14)) {
     119           2 :                         php_stream_notify_info(stream->context, PHP_STREAM_NOTIFY_MIME_TYPE_IS, data + 14, 0);
     120          52 :                 } else if (!strncasecmp(data, "Context-Length: ", 16)) {
     121           0 :                         php_stream_notify_file_size(stream->context, atoi(data + 16), data, 0);
     122           0 :                         php_stream_notify_progress_init(stream->context, 0, 0);
     123             :                 }
     124             :         }
     125          92 :         return length;
     126             :         
     127             : }
     128             : 
     129         162 : static int on_progress_avail(php_stream *stream, double dltotal, double dlnow, double ultotal, double ulnow)
     130             : {
     131             :         TSRMLS_FETCH();
     132             : 
     133             :         /* our notification system only works in a single direction; we should detect which
     134             :          * direction is important and use the correct values in this call */
     135         162 :         php_stream_notify_progress(stream->context, (size_t) dlnow, (size_t) dltotal);
     136         162 :         return 0;
     137             : }
     138             : 
     139           0 : static size_t php_curl_stream_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
     140             : {
     141           0 :         php_curl_stream *curlstream = (php_curl_stream *) stream->abstract;
     142             : 
     143           0 :         if (curlstream->writebuffer.buf) {
     144           0 :                 return php_stream_write(curlstream->writebuffer.buf, buf, count);
     145             :         }
     146             :         
     147           0 :         return 0;
     148             : }
     149             : 
     150          52 : static size_t php_curl_stream_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
     151             : {
     152          52 :         php_curl_stream *curlstream = (php_curl_stream *) stream->abstract;
     153          52 :         size_t didread = 0;
     154             :         
     155          52 :         if (curlstream->readbuffer.readpos >= curlstream->readbuffer.writepos && curlstream->pending) {
     156             :                 /* we need to read some more data */
     157             :                 struct timeval tv;
     158             : 
     159             :                 /* fire up the connection */
     160          38 :                 if (curlstream->readbuffer.writepos == 0) {
     161          18 :                         while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(curlstream->multi, &curlstream->pending));
     162             :                 }
     163             :                 
     164             :                 do {
     165          53 :                         FD_ZERO(&curlstream->readfds);
     166          53 :                         FD_ZERO(&curlstream->writefds);
     167          53 :                         FD_ZERO(&curlstream->excfds);
     168             : 
     169             :                         /* get the descriptors from curl */
     170          53 :                         curl_multi_fdset(curlstream->multi, &curlstream->readfds, &curlstream->writefds, &curlstream->excfds, &curlstream->maxfd);
     171             : 
     172             :                         /* if we are in blocking mode, set a timeout */
     173          53 :                         tv.tv_usec = 0;
     174          53 :                         tv.tv_sec = 15; /* TODO: allow this to be configured from the script */
     175             : 
     176             :                         /* wait for data */
     177             :                         switch ((curlstream->maxfd < 0) ? 1 : 
     178          53 :                                         select(curlstream->maxfd + 1, &curlstream->readfds, &curlstream->writefds, &curlstream->excfds, &tv)) {
     179             :                                 case -1:
     180             :                                         /* error */
     181           0 :                                         return 0;
     182             :                                 case 0:
     183             :                                         /* no data yet: timed-out */
     184           0 :                                         return 0;
     185             :                                 default:
     186             :                                         /* fetch the data */
     187             :                                         do {
     188         112 :                                                 curlstream->mcode = curl_multi_perform(curlstream->multi, &curlstream->pending);
     189         112 :                                         } while (curlstream->mcode == CURLM_CALL_MULTI_PERFORM);
     190             :                         }
     191          53 :                 } while (curlstream->maxfd >= 0 &&
     192          53 :                                 curlstream->readbuffer.readpos >= curlstream->readbuffer.writepos && curlstream->pending > 0);
     193             : 
     194             :         }
     195             : 
     196             :         /* if there is data in the buffer, try and read it */
     197          52 :         if (curlstream->readbuffer.writepos > 0 && curlstream->readbuffer.readpos < curlstream->readbuffer.writepos) {
     198          33 :                 php_stream_seek(curlstream->readbuffer.buf, curlstream->readbuffer.readpos, SEEK_SET);
     199          33 :                 didread = php_stream_read(curlstream->readbuffer.buf, buf, count);
     200          33 :                 curlstream->readbuffer.readpos = php_stream_tell(curlstream->readbuffer.buf);
     201             :         }
     202             : 
     203          52 :         if (didread == 0) {
     204          19 :                 stream->eof = 1;
     205             :         }
     206             :         
     207          52 :         return didread;
     208             : }
     209             : 
     210          40 : static int php_curl_stream_close(php_stream *stream, int close_handle TSRMLS_DC)
     211             : {
     212          40 :         php_curl_stream *curlstream = (php_curl_stream *) stream->abstract;
     213             : 
     214             :         /* TODO: respect the close_handle flag here, so that casting to a FILE* on
     215             :          * systems without fopencookie will work properly */
     216             :         
     217          40 :         curl_multi_remove_handle(curlstream->multi, curlstream->curl);
     218          40 :         curl_easy_cleanup(curlstream->curl); 
     219          40 :         curl_multi_cleanup(curlstream->multi);       
     220             : 
     221          40 :         if (curlstream->headers_slist) {
     222          10 :                 curl_slist_free_all(curlstream->headers_slist);
     223             :         }
     224             :         
     225             :         /* we are not closing curlstream->readbuf here, because we export
     226             :          * it as a zval with the wrapperdata - the engine will garbage collect it */
     227             : 
     228          40 :         efree(curlstream->url);
     229          40 :         efree(curlstream);
     230             :         
     231          40 :         return 0;
     232             : }
     233             : 
     234          40 : static int php_curl_stream_flush(php_stream *stream TSRMLS_DC)
     235             : {
     236             : #ifdef ilia_0
     237             :         php_curl_stream *curlstream = (php_curl_stream *) stream->abstract;
     238             : #endif
     239          40 :         return 0;
     240             : }
     241             : 
     242          16 : static int php_curl_stream_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC)
     243             : {
     244             :         /* TODO: fill in details based on Data: and Content-Length: headers, and/or data
     245             :          * from curl_easy_getinfo().
     246             :          * For now, return -1 to indicate that it doesn't make sense to stat this stream */
     247          16 :         return -1;
     248             : }
     249             : 
     250           0 : static int php_curl_stream_cast(php_stream *stream, int castas, void **ret TSRMLS_DC)
     251             : {
     252           0 :         php_curl_stream *curlstream = (php_curl_stream *) stream->abstract;
     253             :         /* delegate to the readbuffer stream */
     254           0 :         return php_stream_cast(curlstream->readbuffer.buf, castas, ret, 0);
     255             : }
     256             : 
     257             : php_stream_ops php_curl_stream_ops = {
     258             :         php_curl_stream_write,
     259             :         php_curl_stream_read,
     260             :         php_curl_stream_close,
     261             :         php_curl_stream_flush,
     262             :         "cURL",
     263             :         NULL, /* seek */
     264             :         php_curl_stream_cast, /* cast */
     265             :         php_curl_stream_stat  /* stat */
     266             : };
     267             : 
     268             : 
     269          40 : php_stream *php_curl_stream_opener(php_stream_wrapper *wrapper, char *filename, char *mode,
     270             :                 int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
     271             : {
     272             :         php_stream *stream;
     273             :         php_curl_stream *curlstream;
     274          40 :         zval *tmp, **ctx_opt = NULL;
     275             : 
     276          40 :         curlstream = emalloc(sizeof(php_curl_stream));
     277          40 :         memset(curlstream, 0, sizeof(php_curl_stream));
     278             : 
     279          40 :         stream = php_stream_alloc(&php_curl_stream_ops, curlstream, 0, mode);
     280          40 :         php_stream_context_set(stream, context);
     281             : 
     282          40 :         curlstream->curl = curl_easy_init();
     283          40 :         curlstream->multi = curl_multi_init();
     284          40 :         curlstream->pending = 1;
     285          40 :         curlstream->headers_slist = NULL;
     286             : 
     287             :         /* if opening for an include statement, ensure that the local storage will
     288             :          * have a FILE* associated with it.
     289             :          * Otherwise, use the "smart" memory stream that will turn itself into a file
     290             :          * when it gets large */
     291             : #ifndef HAVE_FOPENCOOKIE
     292             :         if (options & STREAM_WILL_CAST) {
     293             :                 curlstream->readbuffer.buf = php_stream_fopen_tmpfile();
     294             :         } else
     295             : #endif
     296             :         {
     297          40 :                 curlstream->readbuffer.buf = php_stream_temp_new();
     298             :         }
     299             :         
     300             :         /* curl requires the URL to be valid throughout it's operation, so dup it */
     301          40 :         curlstream->url = estrdup(filename);
     302          40 :         curl_easy_setopt(curlstream->curl, CURLOPT_URL, curlstream->url);
     303             : 
     304             :         /* feed curl data into our read buffer */       
     305          40 :         curl_easy_setopt(curlstream->curl, CURLOPT_WRITEFUNCTION, on_data_available);
     306          40 :         curl_easy_setopt(curlstream->curl, CURLOPT_FILE, stream);
     307             :         
     308             :         /* feed headers */
     309          40 :         curl_easy_setopt(curlstream->curl, CURLOPT_HEADERFUNCTION, on_header_available);
     310          40 :         curl_easy_setopt(curlstream->curl, CURLOPT_WRITEHEADER, stream);
     311             : 
     312          40 :         curl_easy_setopt(curlstream->curl, CURLOPT_ERRORBUFFER, curlstream->errstr);
     313          40 :         curl_easy_setopt(curlstream->curl, CURLOPT_VERBOSE, 0);
     314             : 
     315             :         /* enable progress notification */
     316          40 :         curl_easy_setopt(curlstream->curl, CURLOPT_PROGRESSFUNCTION, on_progress_avail);
     317          40 :         curl_easy_setopt(curlstream->curl, CURLOPT_PROGRESSDATA, stream);
     318          40 :         curl_easy_setopt(curlstream->curl, CURLOPT_NOPROGRESS, 0);
     319             : 
     320          40 :         curl_easy_setopt(curlstream->curl, CURLOPT_USERAGENT, FG(user_agent) ? FG(user_agent) : "PHP/" PHP_VERSION);
     321             :         
     322             :         /* TODO: read cookies and options from context */
     323          80 :         if (context && !strncasecmp(filename, "http", sizeof("http")-1)) {
     324             :                 /* Protocol version */
     325          40 :                 if (SUCCESS == php_stream_context_get_option(context, "http", "protocol_version", &ctx_opt) && Z_TYPE_PP(ctx_opt) == IS_DOUBLE) {
     326           1 :                         if (Z_DVAL_PP(ctx_opt) == 1.1) {
     327           1 :                                 curl_easy_setopt(curlstream->curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
     328             :                         } else {
     329           0 :                                 curl_easy_setopt(curlstream->curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
     330             :                         }
     331             :                 }
     332             : 
     333          40 :                 if (SUCCESS == php_stream_context_get_option(context, "http", "curl_verify_ssl_host", &ctx_opt) && Z_TYPE_PP(ctx_opt) == IS_BOOL && Z_LVAL_PP(ctx_opt) == 1) {
     334           0 :                         curl_easy_setopt(curlstream->curl, CURLOPT_SSL_VERIFYHOST, 2);
     335             :                 } else {
     336          40 :                         curl_easy_setopt(curlstream->curl, CURLOPT_SSL_VERIFYHOST, 0);
     337             :                 }
     338          40 :                 if (SUCCESS == php_stream_context_get_option(context, "http", "curl_verify_ssl_peer", &ctx_opt) && Z_TYPE_PP(ctx_opt) == IS_BOOL && Z_LVAL_PP(ctx_opt) == 1) {
     339           0 :                         curl_easy_setopt(curlstream->curl, CURLOPT_SSL_VERIFYPEER, 1);
     340             :                 } else {
     341          40 :                         curl_easy_setopt(curlstream->curl, CURLOPT_SSL_VERIFYPEER, 0);
     342             :                 }
     343             : 
     344             :                 /* HTTP(S) */
     345          40 :                 if (SUCCESS == php_stream_context_get_option(context, "http", "user_agent", &ctx_opt) && Z_TYPE_PP(ctx_opt) == IS_STRING) {
     346           0 :                         curl_easy_setopt(curlstream->curl, CURLOPT_USERAGENT, Z_STRVAL_PP(ctx_opt));
     347             :                 }
     348          40 :                 if (SUCCESS == php_stream_context_get_option(context, "http", "header", &ctx_opt)) {
     349          10 :                         if (Z_TYPE_PP(ctx_opt) == IS_ARRAY) {
     350             :                                 HashPosition pos;
     351           1 :                                 zval **header = NULL;
     352             :                         
     353           4 :                                 for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(ctx_opt), &pos);
     354           3 :                                         SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(ctx_opt), (void *)&header, &pos);
     355           2 :                                         zend_hash_move_forward_ex(Z_ARRVAL_PP(ctx_opt), &pos)
     356           2 :                                 ) {
     357           2 :                                         if (Z_TYPE_PP(header) == IS_STRING) {
     358           2 :                                                 curlstream->headers_slist = curl_slist_append(curlstream->headers_slist, Z_STRVAL_PP(header));
     359             :                                         }
     360             :                                 }
     361           9 :                         } else if (Z_TYPE_PP(ctx_opt) == IS_STRING && Z_STRLEN_PP(ctx_opt)) {
     362             :                                 char *p, *token, *trimmed, *copy_ctx_opt;
     363             : 
     364           9 :                                 copy_ctx_opt = php_trim(Z_STRVAL_PP(ctx_opt), Z_STRLEN_PP(ctx_opt), NULL, 0, NULL, 3 TSRMLS_CC);
     365           9 :                                 p = php_strtok_r(copy_ctx_opt, "\r\n", &token);
     366          42 :                                 while (p) {
     367          24 :                                         trimmed = php_trim(p, strlen(p), NULL, 0, NULL, 3 TSRMLS_CC);
     368          24 :                                         curlstream->headers_slist = curl_slist_append(curlstream->headers_slist, trimmed);
     369          24 :                                         efree(trimmed);
     370          24 :                                         p = php_strtok_r(NULL, "\r\n", &token);
     371             :                                 }
     372           9 :                                 efree(copy_ctx_opt);
     373             :                         }
     374          10 :                         if (curlstream->headers_slist) {
     375          10 :                                 curl_easy_setopt(curlstream->curl, CURLOPT_HTTPHEADER, curlstream->headers_slist);
     376             :                         }
     377             :                 }
     378          40 :                 if (SUCCESS == php_stream_context_get_option(context, "http", "method", &ctx_opt) && Z_TYPE_PP(ctx_opt) == IS_STRING) {
     379           8 :                         if (strcasecmp(Z_STRVAL_PP(ctx_opt), "get")) {
     380           8 :                                 if (!strcasecmp(Z_STRVAL_PP(ctx_opt), "head")) {
     381           0 :                                         curl_easy_setopt(curlstream->curl, CURLOPT_NOBODY, 1);
     382             :                                 } else {
     383           8 :                                         if (!strcasecmp(Z_STRVAL_PP(ctx_opt), "post")) {
     384           8 :                                                 curl_easy_setopt(curlstream->curl, CURLOPT_POST, 1);
     385             :                                         } else {
     386           0 :                                                 curl_easy_setopt(curlstream->curl, CURLOPT_CUSTOMREQUEST, Z_STRVAL_PP(ctx_opt));
     387             :                                         }
     388           8 :                                         if (SUCCESS == php_stream_context_get_option(context, "http", "content", &ctx_opt) && Z_TYPE_PP(ctx_opt) == IS_STRING) {
     389           2 :                                                 curl_easy_setopt(curlstream->curl, CURLOPT_POSTFIELDS, Z_STRVAL_PP(ctx_opt));
     390           2 :                                                 curl_easy_setopt(curlstream->curl, CURLOPT_POSTFIELDSIZE, (long)Z_STRLEN_PP(ctx_opt));
     391             :                                         }
     392             :                                 }
     393             :                         }
     394             :                 }
     395          40 :                 if (SUCCESS == php_stream_context_get_option(context, "http", "proxy", &ctx_opt) && Z_TYPE_PP(ctx_opt) == IS_STRING) {
     396           0 :                         curl_easy_setopt(curlstream->curl, CURLOPT_PROXY, Z_STRVAL_PP(ctx_opt));
     397             :                 }
     398          40 :                 if (SUCCESS == php_stream_context_get_option(context, "http", "max_redirects", &ctx_opt)) {
     399           6 :                         long mr = 20;
     400           6 :                         if (Z_TYPE_PP(ctx_opt) != IS_STRING || !is_numeric_string(Z_STRVAL_PP(ctx_opt), Z_STRLEN_PP(ctx_opt), &mr, NULL, 1)) {
     401           6 :                                 if (Z_TYPE_PP(ctx_opt) == IS_LONG) {
     402           6 :                                         mr = Z_LVAL_PP(ctx_opt);
     403             :                                 }
     404             :                         }
     405           6 :                         if (mr > 1) {
     406           2 :                                 if (PG(open_basedir) && *PG(open_basedir)) {
     407           0 :                                         curl_easy_setopt(curlstream->curl, CURLOPT_FOLLOWLOCATION, 0);
     408             :                                 } else {
     409           2 :                                         curl_easy_setopt(curlstream->curl, CURLOPT_FOLLOWLOCATION, 1);
     410             :                                 }
     411           2 :                                 curl_easy_setopt(curlstream->curl, CURLOPT_MAXREDIRS, mr);
     412             :                         }
     413             :                 } else {
     414          34 :                         if (PG(open_basedir) && *PG(open_basedir)) {
     415           0 :                                 curl_easy_setopt(curlstream->curl, CURLOPT_FOLLOWLOCATION, 0);
     416             :                         } else {
     417          34 :                                 curl_easy_setopt(curlstream->curl, CURLOPT_FOLLOWLOCATION, 1);
     418             :                         }
     419          34 :                         curl_easy_setopt(curlstream->curl, CURLOPT_MAXREDIRS, 20L);
     420             :                 }
     421           0 :         } else if (context && !strncasecmp(filename, "ftps", sizeof("ftps")-1)) {
     422           0 :                 if (SUCCESS == php_stream_context_get_option(context, "ftp", "curl_verify_ssl_host", &ctx_opt) && Z_TYPE_PP(ctx_opt) == IS_BOOL && Z_LVAL_PP(ctx_opt) == 1) {
     423           0 :                         curl_easy_setopt(curlstream->curl, CURLOPT_SSL_VERIFYHOST, 2);
     424             :                 } else {
     425           0 :                         curl_easy_setopt(curlstream->curl, CURLOPT_SSL_VERIFYHOST, 0);
     426             :                 }
     427           0 :                 if (SUCCESS == php_stream_context_get_option(context, "ftp", "curl_verify_ssl_peer", &ctx_opt) && Z_TYPE_PP(ctx_opt) == IS_BOOL && Z_LVAL_PP(ctx_opt) == 1) {
     428           0 :                         curl_easy_setopt(curlstream->curl, CURLOPT_SSL_VERIFYPEER, 1);
     429             :                 } else {
     430           0 :                         curl_easy_setopt(curlstream->curl, CURLOPT_SSL_VERIFYPEER, 0);
     431             :                 }
     432             :         }
     433             : 
     434             :         /* prepare for "pull" mode */
     435          40 :         curl_multi_add_handle(curlstream->multi, curlstream->curl);
     436             : 
     437             :         /* Prepare stuff for file_get_wrapper_data: the data is an array:
     438             :          *
     439             :          * data = array(
     440             :          *   "headers" => array("Content-Type: text/html", "Xxx: Yyy"),
     441             :          *   "readbuf" => resource (equivalent to curlstream->readbuffer)
     442             :          * );
     443             :          * */
     444          40 :         MAKE_STD_ZVAL(stream->wrapperdata);
     445          40 :         array_init(stream->wrapperdata);
     446             :         
     447          40 :         MAKE_STD_ZVAL(curlstream->headers);
     448          40 :         array_init(curlstream->headers);
     449             :         
     450          40 :         add_assoc_zval(stream->wrapperdata, "headers", curlstream->headers);
     451             :         
     452          40 :         MAKE_STD_ZVAL(tmp);
     453          40 :         php_stream_to_zval(curlstream->readbuffer.buf, tmp);
     454          40 :         add_assoc_zval(stream->wrapperdata, "readbuf", tmp);
     455             : 
     456             : #ifndef HAVE_FOPENCOOKIE
     457             :         if (options & STREAM_WILL_CAST) {
     458             :                 /* we will need to download the whole resource now,
     459             :                  * since we cannot get the actual FD for the download,
     460             :                  * so we won't be able to drive curl via stdio. */
     461             : 
     462             : /* TODO: this needs finishing */
     463             :                 
     464             :                 curl_easy_perform(curlstream->curl);
     465             :         }
     466             :         else
     467             : #endif
     468             :         {
     469             :                 /* fire up the connection; we need to detect a connection error here,
     470             :                  * otherwise the curlstream we return ends up doing nothing useful. */
     471             :                 CURLMcode m;
     472             :                 CURLMsg *msg;
     473          40 :                 int msgs_left, msg_found = 0;
     474             : 
     475         200 :                 while (CURLM_CALL_MULTI_PERFORM == (m = curl_multi_perform(curlstream->multi, &curlstream->pending))) {
     476             :                         ; /* spin */
     477             :                 }
     478             : 
     479          40 :                 if (m != CURLM_OK) {
     480             : #if HAVE_CURL_MULTI_STRERROR
     481           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", curl_multi_strerror(m));
     482             : #else 
     483             :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "There was an error mcode=%d", m);
     484             : #endif
     485           0 :                         goto exit_fail;
     486             :                 }
     487             :                 
     488             :                 /* we have only one curl handle here, even though we use multi syntax, 
     489             :                  * so it's ok to fail on any error */
     490          84 :                 while ((msg = curl_multi_info_read(curlstream->multi, &msgs_left))) {
     491           4 :                         if (msg->data.result == CURLE_OK) {
     492           0 :                                 continue;
     493             :                         } else {
     494             : #if HAVE_CURL_EASY_STRERROR
     495           4 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", curl_easy_strerror(msg->data.result));
     496             : #else
     497             :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "There was an error mcode=%d", msg->data.result);
     498             : #endif
     499           4 :                                 msg_found++;
     500             :                         }
     501             :                 }
     502          40 :                 if (msg_found) {
     503           4 :                         goto exit_fail;
     504             :                 }
     505             :         }
     506             : 
     507          36 :         return stream;
     508             : 
     509             : exit_fail:
     510           4 :         php_stream_close(stream);
     511           4 :         return NULL;
     512             : }
     513             : 
     514             : static php_stream_wrapper_ops php_curl_wrapper_ops = {
     515             :         php_curl_stream_opener,
     516             :         NULL, /* stream_close: curl streams know how to clean themselves up */
     517             :         NULL, /* stream_stat: curl streams know how to stat themselves */
     518             :         NULL, /* stat url */
     519             :         NULL, /* opendir */
     520             :         "cURL", /* label */
     521             :         NULL, /* unlink */
     522             :         NULL, /* rename */
     523             :         NULL, /* mkdir */
     524             :         NULL  /* rmdir */
     525             : };
     526             : 
     527             : php_stream_wrapper php_curl_wrapper = {
     528             :         &php_curl_wrapper_ops,
     529             :         NULL,
     530             :         1 /* is_url */
     531             : };
     532             : 
     533             : #endif
     534             : 
     535             : /*
     536             :  * Local variables:
     537             :  * tab-width: 4
     538             :  * c-basic-offset: 4
     539             :  * End:
     540             :  * vim600: noet sw=4 ts=4 fdm=marker
     541             :  * vim<600: noet sw=4 ts=4
     542             :  */

Generated by: LCOV version 1.10

Generated at Sun, 20 Apr 2014 03:52:06 +0000 (4 hours ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.