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

LTP GCOV extension - code coverage report
Current view: directory - curl - streams.c
Test: PHP Code Coverage
Date: 2009-11-23 Instrumented lines: 203
Code covered: 77.3 % Executed lines: 157
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 6                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2009 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: streams.c 290796 2009-11-15 20:30:57Z felipe $ */
      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                 : static size_t on_data_available(char *data, size_t size, size_t nmemb, void *ctx)
      55              78 : {
      56              78 :         php_stream *stream = (php_stream *) ctx;
      57              78 :         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              78 :         if (curlstream->readbuffer.writepos == 0) {
      66                 :                 zval *sym;
      67                 : 
      68              24 :                 if (!EG(active_symbol_table)) {
      69               8 :                         zend_rebuild_symbol_table(TSRMLS_C);
      70                 :                 }
      71              24 :                 MAKE_STD_ZVAL(sym);
      72              24 :                 *sym = *curlstream->headers;
      73              24 :                 zval_copy_ctor(sym);
      74              24 :                 ZEND_SET_SYMBOL(EG(active_symbol_table), "http_response_header", sym);
      75                 :         }
      76                 :         
      77              78 :         php_stream_seek(curlstream->readbuffer.buf, curlstream->readbuffer.writepos, SEEK_SET);
      78              78 :         wrote = php_stream_write(curlstream->readbuffer.buf, data, size * nmemb);
      79              78 :         curlstream->readbuffer.writepos = php_stream_tell(curlstream->readbuffer.buf);
      80                 : 
      81              78 :         return wrote;
      82                 : }
      83                 : 
      84                 : /* cURL guarantees that headers are written as complete lines, with this function
      85                 :  * called once for each header */
      86                 : static size_t on_header_available(char *data, size_t size, size_t nmemb, void *ctx)
      87             243 : {
      88             243 :         size_t length = size * nmemb;
      89                 :         zval *header;
      90             243 :         php_stream *stream = (php_stream *) ctx;
      91             243 :         php_curl_stream *curlstream = (php_curl_stream *) stream->abstract;
      92                 :         TSRMLS_FETCH();
      93                 : 
      94             243 :         if (length < 2) {
      95                 :                 /* invalid header ? */
      96               0 :                 return length;
      97                 :         }
      98                 : 
      99             243 :         if (!(length == 2 && data[0] == '\r' && data[1] == '\n')) {
     100             210 :                 MAKE_STD_ZVAL(header);
     101             210 :                 Z_STRLEN_P(header) = length;
     102             210 :                 Z_STRVAL_P(header) = estrndup(data, length);
     103             210 :                 if (Z_STRVAL_P(header)[length-1] == '\n') {
     104             210 :                         Z_STRVAL_P(header)[length-1] = '\0';
     105             210 :                         Z_STRLEN_P(header)--;
     106                 :                         
     107             210 :                         if (Z_STRVAL_P(header)[length-2] == '\r') {
     108             210 :                                 Z_STRVAL_P(header)[length-2] = '\0';
     109             210 :                                 Z_STRLEN_P(header)--;
     110                 :                         }
     111                 :                 }
     112             210 :                 Z_TYPE_P(header) = IS_STRING;
     113             210 :                 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             210 :                 if (!strncasecmp(data, "Location: ", 10)) {
     117              13 :                         php_stream_notify_info(stream->context, PHP_STREAM_NOTIFY_REDIRECTED, data + 10, 0);
     118             197 :                 } else if (!strncasecmp(data, "Content-Type: ", 14)) {
     119              13 :                         php_stream_notify_info(stream->context, PHP_STREAM_NOTIFY_MIME_TYPE_IS, data + 14, 0);
     120             184 :                 } 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             243 :         return length;
     126                 :         
     127                 : }
     128                 : 
     129                 : static int on_progress_avail(php_stream *stream, double dltotal, double dlnow, double ultotal, double ulnow)
     130              73 : {
     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              73 :         php_stream_notify_progress(stream->context, (size_t) dlnow, (size_t) dltotal);
     136              73 :         return 0;
     137                 : }
     138                 : 
     139                 : static size_t php_curl_stream_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
     140               0 : {
     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                 : static size_t php_curl_stream_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
     151             107 : {
     152             107 :         php_curl_stream *curlstream = (php_curl_stream *) stream->abstract;
     153             107 :         size_t didread = 0;
     154                 :         
     155             107 :         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              75 :                 if (curlstream->readbuffer.writepos == 0) {
     161              25 :                         while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(curlstream->multi, &curlstream->pending));
     162                 :                 }
     163                 :                 
     164                 :                 do {
     165                 :                         /* get the descriptors from curl */
     166           57205 :                         curl_multi_fdset(curlstream->multi, &curlstream->readfds, &curlstream->writefds, &curlstream->excfds, &curlstream->maxfd);
     167                 : 
     168                 :                         /* if we are in blocking mode, set a timeout */
     169           57205 :                         tv.tv_usec = 0;
     170           57205 :                         tv.tv_sec = 15; /* TODO: allow this to be configured from the script */
     171                 : 
     172                 :                         /* wait for data */
     173                 :                         switch ((curlstream->maxfd < 0) ? 1 : 
     174           57205 :                                         select(curlstream->maxfd + 1, &curlstream->readfds, &curlstream->writefds, &curlstream->excfds, &tv)) {
     175                 :                                 case -1:
     176                 :                                         /* error */
     177               0 :                                         return 0;
     178                 :                                 case 0:
     179                 :                                         /* no data yet: timed-out */
     180               0 :                                         return 0;
     181                 :                                 default:
     182                 :                                         /* fetch the data */
     183                 :                                         do {
     184           57273 :                                                 curlstream->mcode = curl_multi_perform(curlstream->multi, &curlstream->pending);
     185           57273 :                                         } while (curlstream->mcode == CURLM_CALL_MULTI_PERFORM);
     186                 :                         }
     187                 :                 } while (curlstream->maxfd >= 0 &&
     188           57205 :                                 curlstream->readbuffer.readpos >= curlstream->readbuffer.writepos && curlstream->pending > 0);
     189                 : 
     190                 :         }
     191                 : 
     192                 :         /* if there is data in the buffer, try and read it */
     193             107 :         if (curlstream->readbuffer.writepos > 0 && curlstream->readbuffer.readpos < curlstream->readbuffer.writepos) {
     194              75 :                 php_stream_seek(curlstream->readbuffer.buf, curlstream->readbuffer.readpos, SEEK_SET);
     195              75 :                 didread = php_stream_read(curlstream->readbuffer.buf, buf, count);
     196              75 :                 curlstream->readbuffer.readpos = php_stream_tell(curlstream->readbuffer.buf);
     197                 :         }
     198                 : 
     199             107 :         if (didread == 0) {
     200              32 :                 stream->eof = 1;
     201                 :         }
     202                 :         
     203             107 :         return didread;
     204                 : }
     205                 : 
     206                 : static int php_curl_stream_close(php_stream *stream, int close_handle TSRMLS_DC)
     207              30 : {
     208              30 :         php_curl_stream *curlstream = (php_curl_stream *) stream->abstract;
     209                 : 
     210                 :         /* TODO: respect the close_handle flag here, so that casting to a FILE* on
     211                 :          * systems without fopencookie will work properly */
     212                 :         
     213              30 :         curl_multi_remove_handle(curlstream->multi, curlstream->curl);
     214              30 :         curl_easy_cleanup(curlstream->curl); 
     215              30 :         curl_multi_cleanup(curlstream->multi);       
     216                 : 
     217                 :         /* we are not closing curlstream->readbuf here, because we export
     218                 :          * it as a zval with the wrapperdata - the engine will garbage collect it */
     219                 : 
     220              30 :         efree(curlstream->url);
     221              30 :         efree(curlstream);
     222                 :         
     223              30 :         return 0;
     224                 : }
     225                 : 
     226                 : static int php_curl_stream_flush(php_stream *stream TSRMLS_DC)
     227              30 : {
     228                 : #ifdef ilia_0
     229                 :         php_curl_stream *curlstream = (php_curl_stream *) stream->abstract;
     230                 : #endif
     231              30 :         return 0;
     232                 : }
     233                 : 
     234                 : static int php_curl_stream_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC)
     235              15 : {
     236                 :         /* TODO: fill in details based on Data: and Content-Length: headers, and/or data
     237                 :          * from curl_easy_getinfo().
     238                 :          * For now, return -1 to indicate that it doesn't make sense to stat this stream */
     239              15 :         return -1;
     240                 : }
     241                 : 
     242                 : static int php_curl_stream_cast(php_stream *stream, int castas, void **ret TSRMLS_DC)
     243               0 : {
     244               0 :         php_curl_stream *curlstream = (php_curl_stream *) stream->abstract;
     245                 :         /* delegate to the readbuffer stream */
     246               0 :         return php_stream_cast(curlstream->readbuffer.buf, castas, ret, 0);
     247                 : }
     248                 : 
     249                 : php_stream_ops php_curl_stream_ops = {
     250                 :         php_curl_stream_write,
     251                 :         php_curl_stream_read,
     252                 :         php_curl_stream_close,
     253                 :         php_curl_stream_flush,
     254                 :         "cURL",
     255                 :         NULL, /* seek */
     256                 :         php_curl_stream_cast, /* cast */
     257                 :         php_curl_stream_stat  /* stat */
     258                 : };
     259                 : 
     260                 : 
     261                 : php_stream *php_curl_stream_opener(php_stream_wrapper *wrapper, char *filename, char *mode,
     262                 :                 int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
     263              30 : {
     264                 :         php_stream *stream;
     265                 :         php_curl_stream *curlstream;
     266              30 :         zval *tmp, **ctx_opt = NULL;
     267              30 :         struct curl_slist *slist = NULL;
     268                 : 
     269              30 :         curlstream = emalloc(sizeof(php_curl_stream));
     270              30 :         memset(curlstream, 0, sizeof(php_curl_stream));
     271                 : 
     272              30 :         stream = php_stream_alloc(&php_curl_stream_ops, curlstream, 0, mode);
     273              30 :         php_stream_context_set(stream, context TSRMLS_CC);
     274                 : 
     275              30 :         curlstream->curl = curl_easy_init();
     276              30 :         curlstream->multi = curl_multi_init();
     277              30 :         curlstream->pending = 1;
     278                 : 
     279                 :         /* if opening for an include statement, ensure that the local storage will
     280                 :          * have a FILE* associated with it.
     281                 :          * Otherwise, use the "smart" memory stream that will turn itself into a file
     282                 :          * when it gets large */
     283                 : #if !HAVE_FOPENCOOKIE
     284                 :         if (options & STREAM_WILL_CAST) {
     285                 :                 curlstream->readbuffer.buf = php_stream_fopen_tmpfile();
     286                 :         } else
     287                 : #endif
     288                 :         {
     289              30 :                 curlstream->readbuffer.buf = php_stream_temp_new();
     290                 :         }
     291                 :         
     292                 :         /* curl requires the URL to be valid throughout it's operation, so dup it */
     293              30 :         curlstream->url = estrdup(filename);
     294              30 :         curl_easy_setopt(curlstream->curl, CURLOPT_URL, curlstream->url);
     295                 : 
     296                 :         /* feed curl data into our read buffer */       
     297              30 :         curl_easy_setopt(curlstream->curl, CURLOPT_WRITEFUNCTION, on_data_available);
     298              30 :         curl_easy_setopt(curlstream->curl, CURLOPT_FILE, stream);
     299                 :         
     300                 :         /* feed headers */
     301              30 :         curl_easy_setopt(curlstream->curl, CURLOPT_HEADERFUNCTION, on_header_available);
     302              30 :         curl_easy_setopt(curlstream->curl, CURLOPT_WRITEHEADER, stream);
     303                 : 
     304              30 :         curl_easy_setopt(curlstream->curl, CURLOPT_ERRORBUFFER, curlstream->errstr);
     305              30 :         curl_easy_setopt(curlstream->curl, CURLOPT_VERBOSE, 0);
     306                 : 
     307                 :         /* enable progress notification */
     308              30 :         curl_easy_setopt(curlstream->curl, CURLOPT_PROGRESSFUNCTION, on_progress_avail);
     309              30 :         curl_easy_setopt(curlstream->curl, CURLOPT_PROGRESSDATA, stream);
     310              30 :         curl_easy_setopt(curlstream->curl, CURLOPT_NOPROGRESS, 0);
     311                 : 
     312              30 :         curl_easy_setopt(curlstream->curl, CURLOPT_USERAGENT, FG(user_agent) ? FG(user_agent) : "PHP/" PHP_VERSION);
     313                 :         
     314                 :         /* TODO: read cookies and options from context */
     315              51 :         if (context && !strncasecmp(filename, "http", sizeof("http")-1)) {
     316                 :                 /* Protocol version */
     317              21 :                 if (SUCCESS == php_stream_context_get_option(context, "http", "protocol_version", &ctx_opt) && Z_TYPE_PP(ctx_opt) == IS_DOUBLE) {
     318               1 :                         if (Z_DVAL_PP(ctx_opt) == 1.1) {
     319               1 :                                 curl_easy_setopt(curlstream->curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
     320                 :                         } else {
     321               0 :                                 curl_easy_setopt(curlstream->curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
     322                 :                         }
     323                 :                 }
     324                 : 
     325              21 :                 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) {
     326               0 :                         curl_easy_setopt(curlstream->curl, CURLOPT_SSL_VERIFYHOST, 1);
     327                 :                 } else {
     328              21 :                         curl_easy_setopt(curlstream->curl, CURLOPT_SSL_VERIFYHOST, 0);
     329                 :                 }
     330              21 :                 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) {
     331               0 :                         curl_easy_setopt(curlstream->curl, CURLOPT_SSL_VERIFYPEER, 1);
     332                 :                 } else {
     333              21 :                         curl_easy_setopt(curlstream->curl, CURLOPT_SSL_VERIFYPEER, 0);
     334                 :                 }
     335                 : 
     336                 :                 /* HTTP(S) */
     337              21 :                 if (SUCCESS == php_stream_context_get_option(context, "http", "user_agent", &ctx_opt) && Z_TYPE_PP(ctx_opt) == IS_STRING) {
     338               0 :                         curl_easy_setopt(curlstream->curl, CURLOPT_USERAGENT, Z_STRVAL_PP(ctx_opt));
     339                 :                 }
     340              21 :                 if (SUCCESS == php_stream_context_get_option(context, "http", "header", &ctx_opt)) {
     341               3 :                         if (Z_TYPE_PP(ctx_opt) == IS_ARRAY) {
     342                 :                                 HashPosition pos;
     343               1 :                                 zval **header = NULL;
     344                 :                         
     345               1 :                                 for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(ctx_opt), &pos);
     346               4 :                                         SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(ctx_opt), (void *)&header, &pos);
     347                 :                                         zend_hash_move_forward_ex(Z_ARRVAL_PP(ctx_opt), &pos)
     348               2 :                                 ) {
     349               2 :                                         if (Z_TYPE_PP(header) == IS_STRING) {
     350               0 :                                                 slist = curl_slist_append(slist, Z_STRVAL_PP(header));
     351                 :                                         }
     352                 :                                 }
     353               2 :                         } else if (Z_TYPE_PP(ctx_opt) == IS_STRING && Z_STRLEN_PP(ctx_opt)) {
     354                 :                                 char *p, *token, *trimmed, *copy_ctx_opt;
     355                 : 
     356               1 :                                 copy_ctx_opt = php_trim(Z_STRVAL_PP(ctx_opt), Z_STRLEN_PP(ctx_opt), NULL, 0, NULL, 3 TSRMLS_CC);
     357               1 :                                 p = php_strtok_r(copy_ctx_opt, "\r\n", &token);
     358               3 :                                 while (p) {
     359               1 :                                         trimmed = php_trim(p, strlen(p), NULL, 0, NULL, 3 TSRMLS_CC);
     360               1 :                                         slist = curl_slist_append(slist, trimmed);
     361               1 :                                         efree(trimmed);
     362               1 :                                         p = php_strtok_r(NULL, "\r\n", &token);
     363                 :                                 }
     364               1 :                                 efree(copy_ctx_opt);
     365                 :                         }
     366               3 :                         if (slist) {
     367               1 :                                 curl_easy_setopt(curlstream->curl, CURLOPT_HTTPHEADER, slist);
     368                 :                         }
     369                 :                 }
     370              21 :                 if (SUCCESS == php_stream_context_get_option(context, "http", "method", &ctx_opt) && Z_TYPE_PP(ctx_opt) == IS_STRING) {
     371               0 :                         if (strcasecmp(Z_STRVAL_PP(ctx_opt), "get")) {
     372               0 :                                 if (!strcasecmp(Z_STRVAL_PP(ctx_opt), "head")) {
     373               0 :                                         curl_easy_setopt(curlstream->curl, CURLOPT_NOBODY, 1);
     374                 :                                 } else {
     375               0 :                                         if (!strcasecmp(Z_STRVAL_PP(ctx_opt), "post")) {
     376               0 :                                                 curl_easy_setopt(curlstream->curl, CURLOPT_POST, 1);
     377                 :                                         } else {
     378               0 :                                                 curl_easy_setopt(curlstream->curl, CURLOPT_CUSTOMREQUEST, Z_STRVAL_PP(ctx_opt));
     379                 :                                         }
     380               0 :                                         if (SUCCESS == php_stream_context_get_option(context, "http", "content", &ctx_opt) && Z_TYPE_PP(ctx_opt) == IS_STRING) {
     381               0 :                                                 curl_easy_setopt(curlstream->curl, CURLOPT_POSTFIELDS, Z_STRVAL_PP(ctx_opt));
     382               0 :                                                 curl_easy_setopt(curlstream->curl, CURLOPT_POSTFIELDSIZE, (long)Z_STRLEN_PP(ctx_opt));
     383                 :                                         }
     384                 :                                 }
     385                 :                         }
     386                 :                 }
     387              21 :                 if (SUCCESS == php_stream_context_get_option(context, "http", "proxy", &ctx_opt) && Z_TYPE_PP(ctx_opt) == IS_STRING) {
     388               0 :                         curl_easy_setopt(curlstream->curl, CURLOPT_PROXY, Z_STRVAL_PP(ctx_opt));
     389                 :                 }
     390              21 :                 if (SUCCESS == php_stream_context_get_option(context, "http", "max_redirects", &ctx_opt)) {
     391               6 :                         long mr = 20;
     392               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)) {
     393               6 :                                 if (Z_TYPE_PP(ctx_opt) == IS_LONG) {
     394               6 :                                         mr = Z_LVAL_PP(ctx_opt);
     395                 :                                 }
     396                 :                         }
     397               6 :                         if (mr > 1) {
     398               2 :                                 if (PG(open_basedir) && *PG(open_basedir)) {
     399               0 :                                         curl_easy_setopt(curlstream->curl, CURLOPT_FOLLOWLOCATION, 0);
     400                 :                                 } else {
     401               2 :                                         curl_easy_setopt(curlstream->curl, CURLOPT_FOLLOWLOCATION, 1);
     402                 :                                 }
     403               2 :                                 curl_easy_setopt(curlstream->curl, CURLOPT_MAXREDIRS, mr);
     404                 :                         }
     405                 :                 } else {
     406              15 :                         if (PG(open_basedir) && *PG(open_basedir)) {
     407               0 :                                 curl_easy_setopt(curlstream->curl, CURLOPT_FOLLOWLOCATION, 0);
     408                 :                         } else {
     409              15 :                                 curl_easy_setopt(curlstream->curl, CURLOPT_FOLLOWLOCATION, 1);
     410                 :                         }
     411              15 :                         curl_easy_setopt(curlstream->curl, CURLOPT_MAXREDIRS, 20L);
     412                 :                 }
     413               9 :         } else if (context && !strncasecmp(filename, "ftps", sizeof("ftps")-1)) {
     414               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) {
     415               0 :                         curl_easy_setopt(curlstream->curl, CURLOPT_SSL_VERIFYHOST, 1);
     416                 :                 } else {
     417               0 :                         curl_easy_setopt(curlstream->curl, CURLOPT_SSL_VERIFYHOST, 0);
     418                 :                 }
     419               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) {
     420               0 :                         curl_easy_setopt(curlstream->curl, CURLOPT_SSL_VERIFYPEER, 1);
     421                 :                 } else {
     422               0 :                         curl_easy_setopt(curlstream->curl, CURLOPT_SSL_VERIFYPEER, 0);
     423                 :                 }
     424                 :         }
     425                 : 
     426                 :         /* prepare for "pull" mode */
     427              30 :         curl_multi_add_handle(curlstream->multi, curlstream->curl);
     428                 : 
     429                 :         /* Prepare stuff for file_get_wrapper_data: the data is an array:
     430                 :          *
     431                 :          * data = array(
     432                 :          *   "headers" => array("Content-Type: text/html", "Xxx: Yyy"),
     433                 :          *   "readbuf" => resource (equivalent to curlstream->readbuffer)
     434                 :          * );
     435                 :          * */
     436              30 :         MAKE_STD_ZVAL(stream->wrapperdata);
     437              30 :         array_init(stream->wrapperdata);
     438                 :         
     439              30 :         MAKE_STD_ZVAL(curlstream->headers);
     440              30 :         array_init(curlstream->headers);
     441                 :         
     442              30 :         add_assoc_zval(stream->wrapperdata, "headers", curlstream->headers);
     443                 :         
     444              30 :         MAKE_STD_ZVAL(tmp);
     445              30 :         php_stream_to_zval(curlstream->readbuffer.buf, tmp);
     446              30 :         add_assoc_zval(stream->wrapperdata, "readbuf", tmp);
     447                 : 
     448                 : #if !HAVE_FOPENCOOKIE
     449                 :         if (options & STREAM_WILL_CAST) {
     450                 :                 /* we will need to download the whole resource now,
     451                 :                  * since we cannot get the actual FD for the download,
     452                 :                  * so we won't be able to drive curl via stdio. */
     453                 : 
     454                 : /* TODO: this needs finishing */
     455                 :                 
     456                 :                 curl_easy_perform(curlstream->curl);
     457                 :         }
     458                 :         else
     459                 : #endif
     460                 :         {
     461                 :                 /* fire up the connection; we need to detect a connection error here,
     462                 :                  * otherwise the curlstream we return ends up doing nothing useful. */
     463                 :                 CURLMcode m;
     464                 :                 CURLMsg *msg;
     465              30 :                 int msgs_left, msg_found = 0;
     466                 : 
     467             110 :                 while (CURLM_CALL_MULTI_PERFORM == (m = curl_multi_perform(curlstream->multi, &curlstream->pending))) {
     468                 :                         ; /* spin */
     469                 :                 }
     470                 : 
     471              30 :                 if (m != CURLM_OK) {
     472                 : #if HAVE_CURL_MULTI_STRERROR
     473               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", curl_multi_strerror(m));
     474                 : #else 
     475                 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "There was an error mcode=%d", m);
     476                 : #endif
     477               0 :                         goto exit_fail;
     478                 :                 }
     479                 :                 
     480                 :                 /* we have only one curl handle here, even though we use multi syntax, 
     481                 :                  * so it's ok to fail on any error */
     482              61 :                 while ((msg = curl_multi_info_read(curlstream->multi, &msgs_left))) {
     483               1 :                         if (msg->data.result == CURLE_OK) {
     484               1 :                                 continue;
     485                 :                         } else {
     486                 : #if HAVE_CURL_EASY_STRERROR
     487               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", curl_easy_strerror(msg->data.result));
     488                 : #else
     489                 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "There was an error mcode=%d", msg->data.result);
     490                 : #endif
     491               0 :                                 msg_found++;
     492                 :                         }
     493                 :                 }
     494              30 :                 if (msg_found) {
     495               0 :                         goto exit_fail;
     496                 :                 }
     497                 :         }
     498                 : 
     499                 :         /* context headers are not needed anymore */
     500              30 :         if (slist) {
     501               1 :                 curl_easy_setopt(curlstream->curl, CURLOPT_HTTPHEADER, NULL);
     502               1 :                 curl_slist_free_all(slist);
     503                 :         }
     504              30 :         return stream;
     505                 : 
     506               0 : exit_fail:
     507               0 :         php_stream_close(stream);
     508               0 :         if (slist) {
     509               0 :                 curl_slist_free_all(slist);
     510                 :         }
     511               0 :         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: LTP GCOV extension version 1.5

Generated at Mon, 23 Nov 2009 17:39:28 +0000 (36 hours ago)

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