2 /* CURL Extension Emulation Library (Native PHP)
3 * Copyright 2004-2005, Steve Blinch
4 * http://code.blitzaffe.com
5 * ============================================================================
9 * Provides a pure-PHP implementation of the PHP CURL extension, for use on
10 * systems which do not already have the CURL extension installed. It emulates
11 * all of the curl_* functions normally provided by the CURL extension itself,
12 * and uses an internal, native-PHP HTTP library to make requests.
14 * This library will automatically detect whether or not the "real" CURL
15 * extension is installed, and if so, it will not interfere. Thus, it can be
16 * used to ensure that, one way or another, the CURL functions are available
19 * Note that this is only a *rough* emulation of CURL; it is not exact, and
20 * many of CURL's options are not implemented. For a more precise emulation of
21 * CURL, you may want to try our other libcurlexternal library which is based on
22 * the CURL console binary (and is virtually identical to the CURL extension).
27 * Please see the PHP documentation under the "CURL, Client URL Library
28 * Functions" section for information about using this library. Almost all of
29 * the documentation and examples in the PHP manual should work with this
35 * This script is free software; you can redistribute it and/or modify it under the
36 * terms of the GNU General Public License as published by the Free Software
37 * Foundation; either version 2 of the License, or (at your option) any later
40 * This script is distributed in the hope that it will be useful, but WITHOUT ANY
41 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
42 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
45 * You should have received a copy of the GNU General Public License along
46 * with this script; if not, write to the Free Software Foundation, Inc.,
47 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
50 // if the real CURL PHP extension is installed, exit without doing anything;
51 // if libcurlemu is installed and providing a wrapper for the CURL binary,
52 // exit without doing anything
53 if (!extension_loaded("curl") && !function_exists("curl_init")) {
56 // if the CURL binary was not found, do one of the following:
57 // - if CURLNAT_MISSING_ABORT was defined, then exit without
58 // implementing the CURL functions
59 // - otherwise, raise a fatal error and halt the script
60 if (!class_exists("HTTPRetriever")) {
61 if (is_readable(dirname(__FILE__
)."/class_HTTPRetriever.php")) {
62 define("HTTPR_NO_REDECLARE_CURL",true);
63 require_once(dirname(__FILE__
)."/class_HTTPRetriever.php");
65 if (defined("CURLNAT_MISSING_ABORT") && CURLNAT_MISSING_ABORT
) {
68 trigger_error("CURL extension is not loaded, libcurlemu is not loaded, and the HTTPRetriever class is unavailable",E_USER_ERROR
);
73 define("CURLNAT_VERSION","1.0.0");
75 define('CURLOPT_NOTHING',0);
76 define('CURLOPT_FILE',10001);
77 define('CURLOPT_URL',10002);
78 define('CURLOPT_PORT',3);
79 define('CURLOPT_PROXY',10004);
80 define('CURLOPT_USERPWD',10005);
81 define('CURLOPT_PROXYUSERPWD',10006);
82 define('CURLOPT_RANGE',10007);
83 define('CURLOPT_INFILE',10009);
84 define('CURLOPT_ERRORBUFFER',10010);
85 define('CURLOPT_WRITEFUNCTION',20011);
86 define('CURLOPT_READFUNCTION',20012);
87 define('CURLOPT_TIMEOUT',13);
88 define('CURLOPT_INFILESIZE',14);
89 define('CURLOPT_POSTFIELDS',10015);
90 define('CURLOPT_REFERER',10016);
91 define('CURLOPT_FTPPORT',10017);
92 define('CURLOPT_USERAGENT',10018);
93 define('CURLOPT_LOW_SPEED_LIMIT',19);
94 define('CURLOPT_LOW_SPEED_TIME',20);
95 define('CURLOPT_RESUME_FROM',21);
96 define('CURLOPT_COOKIE',10022);
97 define('CURLOPT_HTTPHEADER',10023);
98 define('CURLOPT_HTTPPOST',10024);
99 define('CURLOPT_SSLCERT',10025);
100 define('CURLOPT_SSLCERTPASSWD',10026);
101 define('CURLOPT_SSLKEYPASSWD',10026);
102 define('CURLOPT_CRLF',27);
103 define('CURLOPT_QUOTE',10028);
104 define('CURLOPT_WRITEHEADER',10029);
105 define('CURLOPT_COOKIEFILE',10031);
106 define('CURLOPT_SSLVERSION',32);
107 define('CURLOPT_TIMECONDITION',33);
108 define('CURLOPT_TIMEVALUE',34);
109 define('CURLOPT_HTTPREQUEST',10035);
110 define('CURLOPT_CUSTOMREQUEST',10036);
111 define('CURLOPT_STDERR',10037);
112 define('CURLOPT_POSTQUOTE',10039);
113 define('CURLOPT_WRITEINFO',10040);
114 define('CURLOPT_VERBOSE',41);
115 define('CURLOPT_HEADER',42);
116 define('CURLOPT_NOPROGRESS',43);
117 define('CURLOPT_NOBODY',44);
118 define('CURLOPT_FAILONERROR',45);
119 define('CURLOPT_UPLOAD',46);
120 define('CURLOPT_POST',47);
121 define('CURLOPT_FTPLISTONLY',48);
122 define('CURLOPT_FTPAPPEND',50);
123 define('CURLOPT_NETRC',51);
124 define('CURLOPT_FOLLOWLOCATION',52);
125 define('CURLOPT_FTPASCII',53);
126 define('CURLOPT_TRANSFERTEXT',53);
127 define('CURLOPT_PUT',54);
128 define('CURLOPT_MUTE',55);
129 define('CURLOPT_PROGRESSFUNCTION',20056);
130 define('CURLOPT_PROGRESSDATA',10057);
131 define('CURLOPT_AUTOREFERER',58);
132 define('CURLOPT_PROXYPORT',59);
133 define('CURLOPT_POSTFIELDSIZE',60);
134 define('CURLOPT_HTTPPROXYTUNNEL',61);
135 define('CURLOPT_INTERFACE',10062);
136 define('CURLOPT_KRB4LEVEL',10063);
137 define('CURLOPT_SSL_VERIFYPEER',64);
138 define('CURLOPT_CAINFO',10065);
139 define('CURLOPT_PASSWDFUNCTION',20066);
140 define('CURLOPT_PASSWDDATA',10067);
141 define('CURLOPT_MAXREDIRS',68);
142 define('CURLOPT_FILETIME',10069);
143 define('CURLOPT_TELNETOPTIONS',10070);
144 define('CURLOPT_MAXCONNECTS',71);
145 define('CURLOPT_CLOSEPOLICY',72);
146 define('CURLOPT_CLOSEFUNCTION',20073);
147 define('CURLOPT_FRESH_CONNECT',74);
148 define('CURLOPT_FORBID_REUSE',75);
149 define('CURLOPT_RANDOM_FILE',10076);
150 define('CURLOPT_EGDSOCKET',10077);
151 define('CURLOPT_CONNECTTIMEOUT',78);
152 define('CURLOPT_HEADERFUNCTION',20079);
153 define('CURLOPT_HTTPGET',80);
154 define('CURLOPT_SSL_VERIFYHOST',81);
155 define('CURLOPT_COOKIEJAR',10082);
156 define('CURLOPT_SSL_CIPHER_LIST',10083);
157 define('CURLOPT_HTTP_VERSION',84);
158 define('CURLOPT_FTP_USE_EPSV',85);
159 define('CURLOPT_SSLCERTTYPE',10086);
160 define('CURLOPT_SSLKEY',10087);
161 define('CURLOPT_SSLKEYTYPE',10088);
162 define('CURLOPT_SSLENGINE',10089);
163 define('CURLOPT_SSLENGINE_DEFAULT',90);
164 define('CURLOPT_DNS_USE_GLOBAL_CACHE',91);
165 define('CURLOPT_DNS_CACHE_TIMEOUT',92);
166 define('CURLOPT_PREQUOTE',10093);
167 define('CURLOPT_RETURNTRANSFER', 19913);//moodlefix
169 define('CURLINFO_EFFECTIVE_URL',1);
170 define('CURLINFO_HTTP_CODE',2);
171 define('CURLINFO_FILETIME',14);
172 define('CURLINFO_TOTAL_TIME',3);
173 define('CURLINFO_NAMELOOKUP_TIME',4);
174 define('CURLINFO_CONNECT_TIME',5);
175 define('CURLINFO_PRETRANSFER_TIME',6);
176 define('CURLINFO_STARTTRANSFER_TIME',17);
177 define('CURLINFO_REDIRECT_TIME',19);
178 define('CURLINFO_REDIRECT_COUNT',20);
179 define('CURLINFO_SIZE_UPLOAD',7);
180 define('CURLINFO_SIZE_DOWNLOAD',8);
181 define('CURLINFO_SPEED_DOWNLOAD',9);
182 define('CURLINFO_SPEED_UPLOAD',10);
183 define('CURLINFO_HEADER_SIZE',11);
184 define('CURLINFO_REQUEST_SIZE',12);
185 define('CURLINFO_SSL_VERIFYRESULT',13);
186 define('CURLINFO_CONTENT_LENGTH_DOWNLOAD',15);
187 define('CURLINFO_CONTENT_LENGTH_UPLOAD',16);
188 define('CURLINFO_CONTENT_TYPE',18);
191 define("TIMECOND_ISUNMODSINCE",1);
192 define("TIMECOND_IFMODSINCE",2);
195 function _curlopt_name($curlopt) {
196 foreach (get_defined_constants() as $k=>$v) {
197 if ( (substr($k,0,8)=="CURLOPT_") && ($v==$curlopt)) return $k;
202 // Initialize a CURL emulation session
203 function curl_init($url=false) {
204 if(!isset($GLOBALS["_CURLNAT_OPT"])) {//moodlefix
205 $GLOBALS["_CURLNAT_OPT"] = array();//moodlefix
206 $GLOBALS["_CURLNAT_OPT"]["index"] = 0;//moodlefix
208 $i = $GLOBALS["_CURLNAT_OPT"]["index"]++
;
209 $GLOBALS["_CURLNAT_OPT"][$i] = array("url"=>$url, "fail_on_error"=>false);//moodlefix
210 $GLOBALS["_CURLNAT_OPT"][$i]["http"] = &new HTTPRetriever();
211 $GLOBALS["_CURLNAT_OPT"][$i]["include_body"] = true;
212 $GLOBALS["_CURLNAT_OPT"][$i]["args"] = array();//moodlefix
213 $GLOBALS["_CURLNAT_OPT"][$i]["settings"] = array();//moodlefix
217 // Set an option for a CURL emulation transfer
218 function curl_setopt($ch,$option,$value) {
220 $opt = &$GLOBALS["_CURLNAT_OPT"][$ch];
221 $args = &$opt["args"];
222 $settings = &$opt["settings"];
223 $http = &$opt["http"];
227 $opt["url"] = $value;
229 case CURLOPT_CUSTOMREQUEST
:
230 $opt["method"] = $value;
232 case CURLOPT_REFERER
:
233 $http->headers
["Referer"] = $value;
236 $opt["include_body"] = $value==0;
238 case CURLOPT_FAILONERROR
:
239 $opt["fail_on_error"] = $value>0;
241 case CURLOPT_USERAGENT
:
242 $http->headers
["User-Agent"] = $value;
245 $opt["include_headers"] = $value>0;
247 case CURLOPT_RETURNTRANSFER
:
248 $opt["return_transfer"] = $value>0;
250 case CURLOPT_TIMEOUT
:
251 $opt["max-time"] = (int) $value;
253 case CURLOPT_HTTPHEADER
:
255 foreach ($value as $k=>$header) {
256 list($headername,$headervalue) = explode(":",$header);
257 $http->headers
[$headername] = ltrim($headervalue);
261 $opt["post"] = $value>0;
263 case CURLOPT_POSTFIELDS
:
264 $opt["postdata"] = $value;
267 // we're already mute, no?
270 if (is_resource($value)) {
271 $opt["output_handle"] = $value;
273 trigger_error("CURLOPT_FILE must specify a valid file resource",E_USER_WARNING
);
276 case CURLOPT_WRITEHEADER
:
277 if (is_resource($value)) {
278 $opt["header_handle"] = $value;
280 trigger_error("CURLOPT_WRITEHEADER must specify a valid file resource",E_USER_WARNING
);
284 // not implemented for now - not really relevant
287 case CURLOPT_SSL_VERIFYPEER
:
288 case CURLOPT_SSL_VERIFYHOST
:
289 // these are automatically disabled using ssl:// anyway
292 case CURLOPT_USERPWD
:
293 list($curl_user,$curl_pass) = explode(':',$value,2);
294 $http->auth_username
= $curl_user;
295 $http->auth_password
= $curl_pass;
298 // Important stuff not implemented (as it's not yet supported by HTTPRetriever)
301 case CURLOPT_FOLLOWLOCATION
:
302 case CURLOPT_PROXYUSERPWD
:
304 case CURLOPT_COOKIEFILE
:
307 case CURLOPT_RESUME_FROM
:
309 // Things that cannot (reasonably) be implemented here
310 case CURLOPT_LOW_SPEED_LIMIT
:
311 case CURLOPT_LOW_SPEED_TIME
:
312 case CURLOPT_KRB4LEVEL
:
313 case CURLOPT_SSLCERT
:
314 case CURLOPT_SSLCERTPASSWD
:
315 case CURLOPT_SSLVERSION
:
316 case CURLOPT_INTERFACE
:
318 case CURLOPT_TIMECONDITION
:
319 case CURLOPT_TIMEVALUE
:
321 // FTP stuff not implemented
323 case CURLOPT_POSTQUOTE
:
325 case CURLOPT_FTPLISTONLY
:
326 case CURLOPT_FTPAPPEND
:
327 case CURLOPT_FTPPORT
:
329 // Other stuff not implemented
330 case CURLOPT_VERBOSE
:
333 trigger_error("CURL emulation does not implement CURL option "._curlopt_name($option),E_USER_WARNING
);
338 // Perform a CURL emulation session
339 function curl_exec($ch) {
340 $opt = &$GLOBALS["_CURLNAT_OPT"][$ch];
343 $http = &$opt["http"];
344 $http->disable_curl
= true; // avoid problems with recursion, since we *ARE* CURL
345 $http->error
= false;//moodlefix
347 // set time limits if requested
348 if (!empty($opt["max-time"])) {//moodlefix
349 $http->connect_timeout
= $opt["max-time"];
350 $http->max_time
= $opt["max-time"];
353 if (!empty($opt["post"])) {//moodlefix
354 $res = $http->post($url,$opt["postdata"]);
355 } elseif (!empty($opt["method"])) {
356 $res = $http->custom($opt["method"],$url,$opt["postdata"]);
358 $res = $http->get($url);
362 $opt["errno"] = (!$res && $http->error
) ?
1 : 0;
363 if ($opt["errno"]) $opt["error"] = $http->error
;
365 // die if CURLOPT_FAILONERROR is set and the HTTP result code is greater than 300
366 if ($opt["fail_on_error"]) {
367 if ($http->result_code
>300) die;
370 if ($res === false) {//moodlefix
371 return false;//moodlefix
374 $opt["stats"] = $http->stats
;
378 foreach ($http->response_headers
as $k=>$v) {
379 $headers .= "$k: $v\r\n";
382 // if a file handle was provided for header output, extract the headers
383 // and write them to the handle
384 if (isset($opt["header_handle"])) {
385 fwrite($opt["header_handle"],$headers);
388 $output = ($opt["include_headers"] ?
$headers."\r\n" : "") . ($opt["include_body"] ?
$http->response
: "");
390 // if a file handle was provided for output, write the output to it
391 if (isset($opt["output_handle"])) {
392 fwrite($opt["output_handle"],$output);
394 // if the caller requested that the response be returned, return it
395 } elseif ($opt["return_transfer"]) {
398 // otherwise, just echo the output to stdout
405 function curl_close($ch) {
406 $opt = &$GLOBALS["_CURLNAT_OPT"][$ch];
408 if ($opt["settings"]) {
409 $settings = &$opt["settings"];
410 // if the user used CURLOPT_INFILE to specify a file to upload, remove the
411 // temporary file created for the CURL binary
412 if ($settings["upload-file"]["value"] && file_exists($settings["upload-file"]["value"])) unlink($settings["upload-file"]["value"]);
415 unset($GLOBALS["_CURLNAT_OPT"][$ch]);
418 function curl_errno($ch) {
419 return (int) $GLOBALS["_CURLNAT_OPT"][$ch]["errno"];
422 function curl_error($ch) {
423 return $GLOBALS["_CURLNAT_OPT"][$ch]["error"];
426 function curl_getinfo($ch,$opt=NULL) {
428 $curlinfo_tags = array(
429 CURLINFO_EFFECTIVE_URL
=>"url",
430 CURLINFO_CONTENT_TYPE
=>"content_type",
431 CURLINFO_HTTP_CODE
=>"http_code",
432 CURLINFO_HEADER_SIZE
=>"header_size",
433 CURLINFO_REQUEST_SIZE
=>"request_size",
434 CURLINFO_FILETIME
=>"filetime",
435 CURLINFO_SSL_VERIFYRESULT
=>"ssl_verify_result",
436 CURLINFO_REDIRECT_COUNT
=>"redirect_count",
437 CURLINFO_TOTAL_TIME
=>"total_time",
438 CURLINFO_NAMELOOKUP_TIME
=>"namelookup_time",
439 CURLINFO_CONNECT_TIME
=>"connect_time",
440 CURLINFO_PRETRANSFER_TIME
=>"pretransfer_time",
441 CURLINFO_SIZE_UPLOAD
=>"size_upload",
442 CURLINFO_SIZE_DOWNLOAD
=>"size_download",
443 CURLINFO_SPEED_DOWNLOAD
=>"speed_download",
444 CURLINFO_SPEED_UPLOAD
=>"speed_upload",
445 CURLINFO_CONTENT_LENGTH_DOWNLOAD
=>"download_content_length",
446 CURLINFO_CONTENT_LENGTH_UPLOAD
=>"upload_content_length",
447 CURLINFO_STARTTRANSFER_TIME
=>"starttransfer_time",
448 CURLINFO_REDIRECT_TIME
=>"redirect_time"
451 $key = $curlinfo_tags[$opt];
452 return $GLOBALS["_CURLNAT_OPT"][$ch]["stats"][$key];
454 return $GLOBALS["_CURLNAT_OPT"][$ch]["stats"];
458 function curl_version() {
459 return "libcurlemu/".CURLNAT_VERSION
."-nat";