libcurlnative.inc.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. <?php
  2. /* CURL Extension Emulation Library (Native PHP)
  3. * Copyright 2004-2007, Steve Blinch
  4. * http://code.blitzaffe.com
  5. * ============================================================================
  6. *
  7. * DESCRIPTION
  8. *
  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.
  13. *
  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
  17. * for use.
  18. *
  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).
  23. *
  24. *
  25. * USAGE
  26. *
  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
  30. * library.
  31. *
  32. *
  33. * LICENSE
  34. *
  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
  38. * version.
  39. *
  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
  43. * details.
  44. *
  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
  48. */
  49. // if the real CURL PHP extension is installed, exit without doing anything;
  50. // if libcurlemu is installed and providing a wrapper for the CURL binary,
  51. // exit without doing anything
  52. if (!extension_loaded("curl") && !function_exists("curl_init")) {
  53. // if the CURL binary was not found, do one of the following:
  54. // - if CURLNAT_MISSING_ABORT was defined, then exit without
  55. // implementing the CURL functions
  56. // - otherwise, raise a fatal error and halt the script
  57. if (!class_exists("HTTPRetriever")) {
  58. if (is_readable(dirname(__FILE__)."/class_HTTPRetriever.php")) {
  59. define("HTTPR_NO_REDECLARE_CURL",true);
  60. require_once(dirname(__FILE__)."/class_HTTPRetriever.php");
  61. } else {
  62. if (defined("CURLNAT_MISSING_ABORT") && CURLNAT_MISSING_ABORT) {
  63. return;
  64. } else {
  65. trigger_error("CURL extension is not loaded, libcurlemu is not loaded, and the HTTPRetriever class is unavailable",E_USER_ERROR);
  66. }
  67. }
  68. }
  69. define("CURLNAT_VERSION","1.0.0");
  70. define('CURLOPT_NOTHING',0);
  71. define('CURLOPT_FILE',10001);
  72. define('CURLOPT_URL',10002);
  73. define('CURLOPT_PORT',3);
  74. define('CURLOPT_PROXY',10004);
  75. define('CURLOPT_USERPWD',10005);
  76. define('CURLOPT_PROXYUSERPWD',10006);
  77. define('CURLOPT_RANGE',10007);
  78. define('CURLOPT_INFILE',10009);
  79. define('CURLOPT_ERRORBUFFER',10010);
  80. define('CURLOPT_WRITEFUNCTION',20011);
  81. define('CURLOPT_READFUNCTION',20012);
  82. define('CURLOPT_TIMEOUT',13);
  83. define('CURLOPT_INFILESIZE',14);
  84. define('CURLOPT_POSTFIELDS',10015);
  85. define('CURLOPT_REFERER',10016);
  86. define('CURLOPT_FTPPORT',10017);
  87. define('CURLOPT_USERAGENT',10018);
  88. define('CURLOPT_LOW_SPEED_LIMIT',19);
  89. define('CURLOPT_LOW_SPEED_TIME',20);
  90. define('CURLOPT_RESUME_FROM',21);
  91. define('CURLOPT_COOKIE',10022);
  92. define('CURLOPT_HTTPHEADER',10023);
  93. define('CURLOPT_HTTPPOST',10024);
  94. define('CURLOPT_SSLCERT',10025);
  95. define('CURLOPT_SSLCERTPASSWD',10026);
  96. define('CURLOPT_SSLKEYPASSWD',10026);
  97. define('CURLOPT_CRLF',27);
  98. define('CURLOPT_QUOTE',10028);
  99. define('CURLOPT_WRITEHEADER',10029);
  100. define('CURLOPT_COOKIEFILE',10031);
  101. define('CURLOPT_SSLVERSION',32);
  102. define('CURLOPT_TIMECONDITION',33);
  103. define('CURLOPT_TIMEVALUE',34);
  104. define('CURLOPT_HTTPREQUEST',10035);
  105. define('CURLOPT_CUSTOMREQUEST',10036);
  106. define('CURLOPT_STDERR',10037);
  107. define('CURLOPT_POSTQUOTE',10039);
  108. define('CURLOPT_WRITEINFO',10040);
  109. define('CURLOPT_VERBOSE',41);
  110. define('CURLOPT_HEADER',42);
  111. define('CURLOPT_NOPROGRESS',43);
  112. define('CURLOPT_NOBODY',44);
  113. define('CURLOPT_FAILONERROR',45);
  114. define('CURLOPT_UPLOAD',46);
  115. define('CURLOPT_POST',47);
  116. define('CURLOPT_FTPLISTONLY',48);
  117. define('CURLOPT_FTPAPPEND',50);
  118. define('CURLOPT_NETRC',51);
  119. define('CURLOPT_FOLLOWLOCATION',52);
  120. define('CURLOPT_FTPASCII',53);
  121. define('CURLOPT_TRANSFERTEXT',53);
  122. define('CURLOPT_PUT',54);
  123. define('CURLOPT_MUTE',55);
  124. define('CURLOPT_PROGRESSFUNCTION',20056);
  125. define('CURLOPT_PROGRESSDATA',10057);
  126. define('CURLOPT_AUTOREFERER',58);
  127. define('CURLOPT_PROXYPORT',59);
  128. define('CURLOPT_POSTFIELDSIZE',60);
  129. define('CURLOPT_HTTPPROXYTUNNEL',61);
  130. define('CURLOPT_INTERFACE',10062);
  131. define('CURLOPT_KRB4LEVEL',10063);
  132. define('CURLOPT_SSL_VERIFYPEER',64);
  133. define('CURLOPT_CAINFO',10065);
  134. define('CURLOPT_PASSWDFUNCTION',20066);
  135. define('CURLOPT_PASSWDDATA',10067);
  136. define('CURLOPT_MAXREDIRS',68);
  137. define('CURLOPT_FILETIME',10069);
  138. define('CURLOPT_TELNETOPTIONS',10070);
  139. define('CURLOPT_MAXCONNECTS',71);
  140. define('CURLOPT_CLOSEPOLICY',72);
  141. define('CURLOPT_CLOSEFUNCTION',20073);
  142. define('CURLOPT_FRESH_CONNECT',74);
  143. define('CURLOPT_FORBID_REUSE',75);
  144. define('CURLOPT_RANDOM_FILE',10076);
  145. define('CURLOPT_EGDSOCKET',10077);
  146. define('CURLOPT_CONNECTTIMEOUT',78);
  147. define('CURLOPT_HEADERFUNCTION',20079);
  148. define('CURLOPT_HTTPGET',80);
  149. define('CURLOPT_SSL_VERIFYHOST',81);
  150. define('CURLOPT_COOKIEJAR',10082);
  151. define('CURLOPT_SSL_CIPHER_LIST',10083);
  152. define('CURLOPT_HTTP_VERSION',84);
  153. define('CURLOPT_FTP_USE_EPSV',85);
  154. define('CURLOPT_SSLCERTTYPE',10086);
  155. define('CURLOPT_SSLKEY',10087);
  156. define('CURLOPT_SSLKEYTYPE',10088);
  157. define('CURLOPT_SSLENGINE',10089);
  158. define('CURLOPT_SSLENGINE_DEFAULT',90);
  159. define('CURLOPT_DNS_USE_GLOBAL_CACHE',91);
  160. define('CURLOPT_DNS_CACHE_TIMEOUT',92);
  161. define('CURLOPT_PREQUOTE',10093);
  162. define('CURLINFO_EFFECTIVE_URL',1);
  163. define('CURLINFO_HTTP_CODE',2);
  164. define('CURLINFO_FILETIME',14);
  165. define('CURLINFO_TOTAL_TIME',3);
  166. define('CURLINFO_NAMELOOKUP_TIME',4);
  167. define('CURLINFO_CONNECT_TIME',5);
  168. define('CURLINFO_PRETRANSFER_TIME',6);
  169. define('CURLINFO_STARTTRANSFER_TIME',17);
  170. define('CURLINFO_REDIRECT_TIME',19);
  171. define('CURLINFO_REDIRECT_COUNT',20);
  172. define('CURLINFO_SIZE_UPLOAD',7);
  173. define('CURLINFO_SIZE_DOWNLOAD',8);
  174. define('CURLINFO_SPEED_DOWNLOAD',9);
  175. define('CURLINFO_SPEED_UPLOAD',10);
  176. define('CURLINFO_HEADER_SIZE',11);
  177. define('CURLINFO_REQUEST_SIZE',12);
  178. define('CURLINFO_SSL_VERIFYRESULT',13);
  179. define('CURLINFO_CONTENT_LENGTH_DOWNLOAD',15);
  180. define('CURLINFO_CONTENT_LENGTH_UPLOAD',16);
  181. define('CURLINFO_CONTENT_TYPE',18);
  182. define("TIMECOND_ISUNMODSINCE",1);
  183. define("TIMECOND_IFMODSINCE",2);
  184. function _curlopt_name($curlopt) {
  185. foreach (get_defined_constants() as $k=>$v) {
  186. if ( (substr($k,0,8)=="CURLOPT_") && ($v==$curlopt)) return $k;
  187. }
  188. return false;
  189. }
  190. // Initialize a CURL emulation session
  191. function curl_init() {
  192. $i = $GLOBALS["_CURLNAT_OPT"]["index"]++;
  193. $GLOBALS["_CURLNAT_OPT"][$i] = array();
  194. $GLOBALS["_CURLNAT_OPT"][$i]["http"] = &new HTTPRetriever();
  195. $GLOBALS["_CURLNAT_OPT"][$i]["include_body"] = true;
  196. return $i;
  197. }
  198. // Set an option for a CURL emulation transfer
  199. function curl_setopt($ch,$option,$value) {
  200. $opt = &$GLOBALS["_CURLNAT_OPT"][$ch];
  201. if (!$opt["args"]) $opt["args"] = array();
  202. $args = &$opt["args"];
  203. if (!$opt["settings"]) $opt["settings"] = array();
  204. $settings = &$opt["settings"];
  205. $http = &$opt["http"];
  206. switch($option) {
  207. case CURLOPT_URL:
  208. $opt["url"] = $value;
  209. break;
  210. case CURLOPT_CUSTOMREQUEST:
  211. $opt["method"] = $value;
  212. break;
  213. case CURLOPT_REFERER:
  214. $http->headers["Referer"] = $value;
  215. break;
  216. case CURLOPT_NOBODY:
  217. $opt["include_body"] = $value==0;
  218. break;
  219. case CURLOPT_FAILONERROR:
  220. $opt["fail_on_error"] = $value>0;
  221. break;
  222. case CURLOPT_USERAGENT:
  223. $http->headers["User-Agent"] = $value;
  224. break;
  225. case CURLOPT_HEADER:
  226. $opt["include_headers"] = $value>0;
  227. break;
  228. case CURLOPT_RETURNTRANSFER:
  229. $opt["return_transfer"] = $value>0;
  230. break;
  231. case CURLOPT_TIMEOUT:
  232. $opt["max-time"] = (int) $value;
  233. break;
  234. case CURLOPT_HTTPHEADER:
  235. reset($value);
  236. foreach ($value as $k=>$header) {
  237. list($headername,$headervalue) = explode(":",$header);
  238. $http->headers[$headername] = ltrim($headervalue);
  239. }
  240. break;
  241. case CURLOPT_POST:
  242. $opt["post"] = $value>0;
  243. break;
  244. case CURLOPT_POSTFIELDS:
  245. $opt["postdata"] = $value;
  246. break;
  247. case CURLOPT_MUTE:
  248. // we're already mute, no?
  249. break;
  250. case CURLOPT_FILE:
  251. if (is_resource($value)) {
  252. $opt["output_handle"] = $value;
  253. } else {
  254. trigger_error("CURLOPT_FILE must specify a valid file resource",E_USER_WARNING);
  255. }
  256. break;
  257. case CURLOPT_WRITEHEADER:
  258. if (is_resource($value)) {
  259. $opt["header_handle"] = $value;
  260. } else {
  261. trigger_error("CURLOPT_WRITEHEADER must specify a valid file resource",E_USER_WARNING);
  262. }
  263. break;
  264. case CURLOPT_STDERR:
  265. // not implemented for now - not really relevant
  266. break;
  267. case CURLOPT_SSL_VERIFYPEER:
  268. case CURLOPT_SSL_VERIFYHOST:
  269. // these are automatically disabled using ssl:// anyway
  270. break;
  271. case CURLOPT_USERPWD:
  272. list($curl_user,$curl_pass) = explode(':',$value,2);
  273. $http->auth_username = $curl_user;
  274. $http->auth_password = $curl_pass;
  275. break;
  276. // Important stuff not implemented (as it's not yet supported by HTTPRetriever)
  277. case CURLOPT_PUT:
  278. case CURLOPT_INFILE:
  279. case CURLOPT_FOLLOWLOCATION:
  280. case CURLOPT_PROXYUSERPWD:
  281. case CURLOPT_COOKIE:
  282. case CURLOPT_COOKIEFILE:
  283. case CURLOPT_PROXY:
  284. case CURLOPT_RANGE:
  285. case CURLOPT_RESUME_FROM:
  286. // Things that cannot (reasonably) be implemented here
  287. case CURLOPT_LOW_SPEED_LIMIT:
  288. case CURLOPT_LOW_SPEED_TIME:
  289. case CURLOPT_KRB4LEVEL:
  290. case CURLOPT_SSLCERT:
  291. case CURLOPT_SSLCERTPASSWD:
  292. case CURLOPT_SSLVERSION:
  293. case CURLOPT_INTERFACE:
  294. case CURLOPT_CAINFO:
  295. case CURLOPT_TIMECONDITION:
  296. case CURLOPT_TIMEVALUE:
  297. // FTP stuff not implemented
  298. case CURLOPT_QUOTE:
  299. case CURLOPT_POSTQUOTE:
  300. case CURLOPT_UPLOAD:
  301. case CURLOPT_FTPLISTONLY:
  302. case CURLOPT_FTPAPPEND:
  303. case CURLOPT_FTPPORT:
  304. // Other stuff not implemented
  305. case CURLOPT_VERBOSE:
  306. case CURLOPT_NETRC:
  307. default:
  308. trigger_error("CURL emulation does not implement CURL option "._curlopt_name($option),E_USER_WARNING);
  309. break;
  310. }
  311. }
  312. // Perform a CURL emulation session
  313. function curl_exec($ch) {
  314. $opt = &$GLOBALS["_CURLNAT_OPT"][$ch];
  315. $url = $opt["url"];
  316. $http = &$opt["http"];
  317. $http->disable_curl = true; // avoid problems with recursion, since we *ARE* CURL
  318. // set time limits if requested
  319. if ($opt["max-time"]) {
  320. $http->connect_timeout = $opt["max-time"];
  321. $http->max_time = $opt["max-time"];
  322. }
  323. if ($opt["post"]) {
  324. $res = $http->post($url,$opt["postdata"]);
  325. } elseif ($opt["method"]) {
  326. $res = $http->custom($opt["method"],$url,$opt["postdata"]);
  327. } else {
  328. $res = $http->get($url);
  329. }
  330. // check for errors
  331. $opt["errno"] = (!$res && $http->error) ? 1 : 0;
  332. if ($opt["errno"]) $opt["error"] = $http->error;
  333. // die if CURLOPT_FAILONERROR is set and the HTTP result code is greater than 300
  334. if ($opt["fail_on_error"]) {
  335. if ($http->result_code>300) die;
  336. }
  337. $opt["stats"] = $http->stats;
  338. $headers = "";
  339. foreach ($http->headers as $k => $v) {
  340. $headers .= "$k: $v\r\n";
  341. }
  342. // if a file handle was provided for header output, extract the headers
  343. // and write them to the handle
  344. if (isset($opt["header_handle"])) {
  345. fwrite($opt["header_handle"],$headers);
  346. }
  347. $output = ($opt["include_headers"] ? $headers."\r\n" : "") . ($opt["include_body"] ? $http->response : "");
  348. // if a file handle was provided for output, write the output to it
  349. if (isset($opt["output_handle"])) {
  350. fwrite($opt["output_handle"],$output);
  351. // if the caller requested that the response be returned, return it
  352. } elseif ($opt["return_transfer"]) {
  353. return $output;
  354. // otherwise, just echo the output to stdout
  355. } else {
  356. echo $output;
  357. }
  358. return true;
  359. }
  360. function curl_close($ch) {
  361. $opt = &$GLOBALS["_CURLNAT_OPT"][$ch];
  362. if ($opt["settings"]) {
  363. $settings = &$opt["settings"];
  364. // if the user used CURLOPT_INFILE to specify a file to upload, remove the
  365. // temporary file created for the CURL binary
  366. if ($settings["upload-file"]["value"] && file_exists($settings["upload-file"]["value"])) unlink($settings["upload-file"]["value"]);
  367. }
  368. unset($GLOBALS["_CURLNAT_OPT"][$ch]);
  369. }
  370. function curl_errno($ch) {
  371. return (int) $GLOBALS["_CURLNAT_OPT"][$ch]["errno"];
  372. }
  373. function curl_error($ch) {
  374. return $GLOBALS["_CURLNAT_OPT"][$ch]["error"];
  375. }
  376. function curl_getinfo($ch,$opt=NULL) {
  377. if ($opt) {
  378. $curlinfo_tags = array(
  379. CURLINFO_EFFECTIVE_URL=>"url",
  380. CURLINFO_CONTENT_TYPE=>"content_type",
  381. CURLINFO_HTTP_CODE=>"http_code",
  382. CURLINFO_HEADER_SIZE=>"header_size",
  383. CURLINFO_REQUEST_SIZE=>"request_size",
  384. CURLINFO_FILETIME=>"filetime",
  385. CURLINFO_SSL_VERIFYRESULT=>"ssl_verify_result",
  386. CURLINFO_REDIRECT_COUNT=>"redirect_count",
  387. CURLINFO_TOTAL_TIME=>"total_time",
  388. CURLINFO_NAMELOOKUP_TIME=>"namelookup_time",
  389. CURLINFO_CONNECT_TIME=>"connect_time",
  390. CURLINFO_PRETRANSFER_TIME=>"pretransfer_time",
  391. CURLINFO_SIZE_UPLOAD=>"size_upload",
  392. CURLINFO_SIZE_DOWNLOAD=>"size_download",
  393. CURLINFO_SPEED_DOWNLOAD=>"speed_download",
  394. CURLINFO_SPEED_UPLOAD=>"speed_upload",
  395. CURLINFO_CONTENT_LENGTH_DOWNLOAD=>"download_content_length",
  396. CURLINFO_CONTENT_LENGTH_UPLOAD=>"upload_content_length",
  397. CURLINFO_STARTTRANSFER_TIME=>"starttransfer_time",
  398. CURLINFO_REDIRECT_TIME=>"redirect_time"
  399. );
  400. $key = $curlinfo_tags[$opt];
  401. return $GLOBALS["_CURLNAT_OPT"][$ch]["stats"][$key];
  402. } else {
  403. return $GLOBALS["_CURLNAT_OPT"][$ch]["stats"];
  404. }
  405. }
  406. function curl_version() {
  407. return "libcurlemu/".CURLNAT_VERSION."-nat";
  408. }
  409. }
  410. ?>