--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+\f
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
--- /dev/null
+CURL Extension Emulation Library
+Version 1.0.3
+Copyright 2004-2005, Steve Blinch
+http://code.blitzaffe.com
+============================================================================
+
+DESCRIPTION
+
+Provides a pure-PHP implementation of the PHP CURL extension, for use on
+systems which do not already have the CURL extension installed. It emulates
+all of the curl_* functions normally provided by the CURL extension itself.
+
+This will automatically detect and use the best CURL implementation available
+on your server. It will attempt the following, in order:
+
+1) Check for the existence of the "real" CURL PHP Extension. If it is
+loaded, the library will do nothing (and it will not interfere with the
+"real" extension).
+2) Check for the existence of the CURL console binary (usually located in
+/usr/bin/curl). If found, the library will emulate the CURL PHP
+extension (including all curl_* functions) and use the console binary
+to execute all requests.
+3) If neither the "real" CURL PHP Extension nor the CURL console binary
+are available, the library will emulate the CURL PHP extension (including
+all curl_* functions) using a native, pure-PHP HTTP client implementation.
+This implementation is somewhat limited, but it provides support for most
+of the common CURL options. HTTPS (SSL) support is available in this
+mode under PHP 4.3.0 if the OpenSSL Extension is loaded.
+
+Thus, by including this library in your project, you can rely on having some
+level of CURL support regardless of the configuration of the server on which
+it is being used.
+
+
+USAGE
+
+Simply copy all of the libcurlemu files into your project directory, then:
+
+require_once("libcurlemu.inc.php");
+
+After this, you can use all of the curl_* functions documented in the PHP
+Manual.
+
+
+EXAMPLE
+
+// CURL Extension Emulation Library Example
+//
+// Usage should be straightforward; you simply use this script exactly as you
+// would normally use the PHP CURL extension functions.
+
+// first, include libcurlemu.inc.php
+require_once('libcurlemu.inc.php');
+
+// at this point, libcurlemu has detected the best available CURL solution
+// (either the CURL extension, if available, or the CURL commandline binary,
+// if available, or as a last resort, HTTPRetriever, our native-PHP HTTP
+// client implementation) and has implemented the curl_* functions if
+// necessary, so you can use CURL normally and safely assume that all CURL
+// functions are available.
+
+// the rest of this example code is copied straight from the PHP manual's
+// reference for the curl_init() function, and will work fine with libcurlemu
+
+// create a new CURL resource
+$ch = curl_init();
+
+// set URL and other appropriate options
+curl_setopt($ch, CURLOPT_URL, "http://www.example.com/");
+curl_setopt($ch, CURLOPT_HEADER, false);
+
+// grab URL and pass it to the browser
+curl_exec($ch);
+
+// close CURL resource, and free up system resources
+curl_close($ch);
+
+
+LICENSE
+
+This script is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This script is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+details.
+
+You should have received a copy of the GNU General Public License along
+with this script; if not, write to the Free Software Foundation, Inc.,
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
--- /dev/null
+<?php
+/* HTTP Retriever
+ * Version v1.1.9
+ * Copyright 2004-2006, Steve Blinch
+ * http://code.blitzaffe.com
+ * ============================================================================
+ *
+ * DESCRIPTION
+ *
+ * Provides a pure-PHP implementation of an HTTP v1.1 client, including support
+ * for chunked transfer encoding and user agent spoofing. Both GET and POST
+ * requests are supported.
+ *
+ * This can be used in place of something like CURL or WGET for HTTP requests.
+ * Native SSL (HTTPS) requests are also supported if the OpenSSL extension is
+ * installed under PHP v4.3.0 or greater.
+ *
+ * If native SSL support is not available, the class will also check for the
+ * CURL extension; if it's installed, it will transparently be used for SSL
+ * (HTTPS) requests.
+ *
+ * If neither native SSL support nor the CURL extension are available, and
+ * libcurlemu (a CURL emulation library available from our web site) is found,
+ * the class will also check for the CURL console binary (usually in
+ * /usr/bin/curl); if it's installed, it will transparently be used for SSL
+ * requests.
+ *
+ * In short, if it's possible to make an HTTP/HTTPS request from your server,
+ * this class can most likely do it.
+ *
+ *
+ * HISTORY
+ *
+ * 1.1.9 (11-Oct-2006)
+ * - Added set_transfer_display() and default_transfer_callback()
+ * methods for transfer progress tracking
+ * - Suppressed possible "fatal protocol error" when remote SSL server
+ * closes the connection early
+ * - Added get_content_type() method
+ * - make_query_string() now handles arrays
+ *
+ * 1.1.8 (19-Jun-2006)
+ * - Added set_progress_display() and default_progress_callback()
+ * methods for debug output
+ * - Added support for relative URLs in HTTP redirects
+ * - Added cookie support (sending and receiving)
+ * - Numerous bug fixes
+ *
+ * 1.1.7 (18-Apr-2006)
+ * - Added support for automatically following HTTP redirects
+ * - Added ::get_error() method to get any available error message (be
+ * it an HTTP result error or an internal/connection error)
+ * - Added ::cache_hit variable to determine whether the page was cached
+ *
+ * 1.1.6 (04-Mar-2006)
+ * - Added stream_timeout class variable.
+ * - Added progress_callback class variable.
+ * - Added support for braindead servers that ignore Connection: close
+ *
+ *
+ * EXAMPLE
+ *
+ * // HTTPRetriever usage example
+ * require_once("class_HTTPRetriever.php");
+ * $http = &new HTTPRetriever();
+ *
+ *
+ * // Example GET request:
+ * // ----------------------------------------------------------------------------
+ * $keyword = "blitzaffe code"; // search Google for this keyword
+ * if (!$http->get("http://www.google.com/search?hl=en&q=%22".urlencode($keyword)."%22&btnG=Search&meta=")) {
+ * echo "HTTP request error: #{$http->result_code}: {$http->result_text}";
+ * return false;
+ * }
+ * echo "HTTP response headers:<br><pre>";
+ * var_dump($http->response_headers);
+ * echo "</pre><br>";
+ *
+ * echo "Page content:<br><pre>";
+ * echo $http->response;
+ * echo "</pre>";
+ * // ----------------------------------------------------------------------------
+ *
+ *
+ * // Example POST request:
+ * // ----------------------------------------------------------------------------
+ * $keyword = "blitzaffe code"; // search Google for this keyword
+ * $values = array(
+ * "hl"=>"en",
+ * "q"=>"%22".urlencode($keyword)."%22",
+ * "btnG"=>"Search",
+ * "meta"=>""
+ * );
+ * // Note: This example is just to demonstrate the POST equivalent of the GET
+ * // example above; running this script will return a 501 Not Implemented, as
+ * // Google does not support POST requests.
+ * if (!$http->post("http://www.google.com/search",$http->make_query_string($values))) {
+ * echo "HTTP request error: #{$http->result_code}: {$http->result_text}";
+ * return false;
+ * }
+ * echo "HTTP response headers:<br><pre>";
+ * var_dump($http->response_headers);
+ * echo "</pre><br>";
+ *
+ * echo "Page content:<br><pre>";
+ * echo $http->response;
+ * echo "</pre>";
+ * // ----------------------------------------------------------------------------
+ *
+ *
+ * LICENSE
+ *
+ * This script is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This script is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this script; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+// define user agent ID's
+define("UA_EXPLORER",0);
+define("UA_MOZILLA",1);
+define("UA_FIREFOX",2);
+define("UA_OPERA",3);
+
+// define progress message severity levels
+define('HRP_DEBUG',0);
+define('HRP_INFO',1);
+define('HRP_ERROR',2);
+
+if (!defined("CURL_PATH")) define("CURL_PATH","/usr/bin/curl");
+
+// if the CURL extension is not loaded, but the CURL Emulation Library is found, try
+// to load it
+if (!extension_loaded("curl") && !defined('HTTPR_NO_REDECLARE_CURL') ) {
+ foreach (array(dirname(__FILE__)."/",dirname(__FILE__)."/libcurlemu/") as $k=>$libcurlemupath) {
+ $libcurlemuinc = $libcurlemupath.'libcurlexternal.inc.php';
+ if (is_readable($libcurlemuinc)) require_once($libcurlemuinc);
+ }
+}
+
+class HTTPRetriever {
+
+ // Constructor
+ function HTTPRetriever() {
+ // default HTTP headers to send with all requests
+ $this->headers = array(
+ "Referer"=>"",
+ "User-Agent"=>"HTTPRetriever/1.0",
+ "Connection"=>"close"
+ );
+
+ // HTTP version (has no effect if using CURL)
+ $this->version = "1.1";
+
+ // Normally, CURL is only used for HTTPS requests; setting this to
+ // TRUE will force CURL for HTTP requests as well. Not recommended.
+ $this->force_curl = false;
+
+ // If you don't want to use CURL at all, set this to TRUE.
+ $this->disable_curl = false;
+
+ // If HTTPS request return an error message about SSL certificates in
+ // $this->error and you don't care about security, set this to TRUE
+ $this->insecure_ssl = false;
+
+ // Set the maximum time to wait for a connection
+ $this->connect_timeout = 15;
+
+ // Set the maximum time to allow a transfer to run, or 0 to disable.
+ $this->max_time = 0;
+
+ // Set the maximum time for a socket read/write operation, or 0 to disable.
+ $this->stream_timeout = 0;
+
+ // If you're making an HTTPS request to a host whose SSL certificate
+ // doesn't match its domain name, AND YOU FULLY UNDERSTAND THE
+ // SECURITY IMPLICATIONS OF IGNORING THIS PROBLEM, set this to TRUE.
+ $this->ignore_ssl_hostname = false;
+
+ // If TRUE, the get() and post() methods will close the connection
+ // and return immediately after receiving the HTTP result code
+ $this->result_close = false;
+
+ // If set to a positive integer value, retrieved pages will be cached
+ // for this number of seconds. Any subsequent calls within the cache
+ // period will return the cached page, without contacting the remote
+ // server.
+ $this->caching = false;
+
+ // If $this->caching is enabled, this specifies the folder under which
+ // cached pages are saved.
+ $this->cache_path = '/tmp/';
+
+ // Set these to perform basic HTTP authentication
+ $this->auth_username = '';
+ $this->auth_password = '';
+
+ // Optionally set this to a valid callback method to have HTTPRetriever
+ // provide progress messages. Your callback must accept 2 parameters:
+ // an integer representing the severity (0=debug, 1=information, 2=error),
+ // and a string representing the progress message
+ $this->progress_callback = null;
+
+ // Optionally set this to a valid callback method to have HTTPRetriever
+ // provide bytes-transferred messages. Your callbcak must accept 2
+ // parameters: an integer representing the number of bytes transferred,
+ // and an integer representing the total number of bytes expected (or
+ // -1 if unknown).
+ $this->transfer_callback = null;
+
+ // Set this to TRUE if you HTTPRetriever to transparently follow HTTP
+ // redirects (code 301, 302, 303, and 307). Optionally set this to a
+ // numeric value to limit the maximum number of redirects to the specified
+ // value. (Redirection loops are detected automatically.)
+ // Note that non-GET/HEAD requests will NOT be redirected except on code
+ // 303, as per HTTP standards.
+ $this->follow_redirects = false;
+ }
+
+ // Send an HTTP GET request to $url; if $ipaddress is specified, the
+ // connection will be made to the selected IP instead of resolving the
+ // hostname in $url.
+ //
+ // If $cookies is set, it should be an array in one of two formats.
+ //
+ // Either: $cookies[ 'cookiename' ] = array (
+ // '/path/'=>array(
+ // 'expires'=>time(),
+ // 'domain'=>'yourdomain.com',
+ // 'value'=>'cookievalue'
+ // )
+ // );
+ //
+ // Or, a more simplified format:
+ // $cookies[ 'cookiename' ] = 'value';
+ //
+ // The former format will automatically check to make sure that the path, domain,
+ // and expiration values match the HTTP request, and will only send the cookie if
+ // they do match. The latter will force the cookie to be set for the HTTP request
+ // unconditionally.
+ //
+ function get($url,$ipaddress = false,$cookies = false) {
+ $this->method = "GET";
+ $this->post_data = "";
+ $this->connect_ip = $ipaddress;
+ return $this->_execute_request($url,$cookies);
+ }
+
+ // Send an HTTP POST request to $url containing the POST data $data. See ::get()
+ // for a description of the remaining arguments.
+ function post($url,$data="",$ipaddress = false,$cookies = false) {
+ $this->method = "POST";
+ $this->post_data = $data;
+ $this->connect_ip = $ipaddress;
+ return $this->_execute_request($url,$cookies);
+ }
+
+ // Send an HTTP HEAD request to $url. See ::get() for a description of the arguments.
+ function head($url,$ipaddress = false,$cookies = false) {
+ $this->method = "HEAD";
+ $this->post_data = "";
+ $this->connect_ip = $ipaddress;
+ return $this->_execute_request($url,$cookies);
+ }
+
+ // send an alternate (non-GET/POST) HTTP request to $url
+ function custom($method,$url,$data="",$ipaddress = false,$cookies = false) {
+ $this->method = $method;
+ $this->post_data = $data;
+ $this->connect_ip = $ipaddress;
+ return $this->_execute_request($url,$cookies);
+ }
+
+ function array_to_query($arrayname,$arraycontents) {
+ $output = "";
+ foreach ($arraycontents as $key=>$value) {
+ if (is_array($value)) {
+ $output .= $this->array_to_query(sprintf('%s[%s]',$arrayname,urlencode($key)),$value);
+ } else {
+ $output .= sprintf('%s[%s]=%s&',$arrayname,urlencode($key),urlencode($value));
+ }
+ }
+ return $output;
+ }
+
+ // builds a query string from the associative array array $data;
+ // returns a string that can be passed to $this->post()
+ function make_query_string($data) {
+ $output = "";
+ if (is_array($data)) {
+ foreach ($data as $name=>$value) {
+ if (is_array($value)) {
+ $output .= $this->array_to_query(urlencode($name),$value);
+ } elseif (is_scalar($value)) {
+ $output .= urlencode($name)."=".urlencode($value)."&";
+ } else {
+ $output .= urlencode($name)."=".urlencode(serialize($value)).'&';
+ }
+ }
+ }
+ return substr($output,0,strlen($output)-1);
+ }
+
+
+ // this is pretty limited... but really, if you're going to spoof you UA, you'll probably
+ // want to use a Windows OS for the spoof anyway
+ //
+ // if you want to set the user agent to a custom string, just assign your string to
+ // $this->headers["User-Agent"] directly
+ function set_user_agent($agenttype,$agentversion,$windowsversion) {
+ $useragents = array(
+ "Mozilla/4.0 (compatible; MSIE %agent%; Windows NT %os%)", // IE
+ "Mozilla/5.0 (Windows; U; Windows NT %os%; en-US; rv:%agent%) Gecko/20040514", // Moz
+ "Mozilla/5.0 (Windows; U; Windows NT %os%; en-US; rv:1.7) Gecko/20040803 Firefox/%agent%", // FFox
+ "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT %os%) Opera %agent% [en]", // Opera
+ );
+ $agent = $useragents[$agenttype];
+ $this->headers["User-Agent"] = str_replace(array("%agent%","%os%"),array($agentversion,$windowsversion),$agent);
+ }
+
+ // this isn't presently used as it's now handled inline by the request parser
+ function remove_chunkiness() {
+ $remaining = $this->response;
+ $this->response = "";
+
+ while ($remaining) {
+ $hexlen = strpos($remaining,"\r");
+ $chunksize = substr($remaining,0,$hexlen);
+ $argstart = strpos($chunksize,';');
+ if ($argstart!==false) $chunksize = substr($chunksize,0,$argstart);
+ $chunksize = (int) @hexdec($chunksize);
+
+ $this->response .= substr($remaining,$hexlen+2,$chunksize);
+ $remaining = substr($remaining,$hexlen+2+$chunksize+2);
+
+ if (!$chunksize) {
+ // either we're done, or something's borked... exit
+ $this->response .= $remaining;
+ return;
+ }
+ }
+ }
+
+ // (internal) store a page in the cache
+ function _cache_store($token) {
+ $values = array(
+ "stats"=>$this->stats,
+ "result_code"=>$this->result_code,
+ "result_text"=>$this->result_text,
+ "version"=>$this->version,
+ "response"=>$this->response,
+ "response_headers"=>$this->response_headers,
+ "response_cookies"=>$this->response_cookies,
+ "raw_response"=>$this->raw_response,
+ );
+ $values = serialize($values);
+
+ $filename = $this->cache_path.$token.'.tmp';
+
+ $fp = @fopen($filename,"w");
+ if (!$fp) {
+ $this->progress(HRP_DEBUG,"Unable to create cache file");
+ return false;
+ }
+ fwrite($fp,$values);
+ fclose($fp);
+
+ $this->progress(HRP_DEBUG,"HTTP response stored to cache");
+ }
+
+ // (internal) fetch a page from the cache
+ function _cache_fetch($token) {
+ $this->cache_hit = false;
+ $this->progress(HRP_DEBUG,"Checking for cached page value");
+
+ $filename = $this->cache_path.$token.'.tmp';
+ if (!file_exists($filename)) {
+ $this->progress(HRP_DEBUG,"Page not available in cache");
+ return false;
+ }
+
+ if (time()-filemtime($filename)>$this->caching) {
+ $this->progress(HRP_DEBUG,"Page in cache is expired");
+ @unlink($filename);
+ return false;
+ }
+
+ if ($values = file_get_contents($filename)) {
+ $values = unserialize($values);
+ if (!$values) {
+ $this->progress(HRP_DEBUG,"Invalid cache contents");
+ return false;
+ }
+
+ $this->stats = $values["stats"];
+ $this->result_code = $values["result_code"];
+ $this->result_text = $values["result_text"];
+ $this->version = $values["version"];
+ $this->response = $values["response"];
+ $this->response_headers = $values["response_headers"];
+ $this->response_cookies = $values["response_cookies"];
+ $this->raw_response = $values["raw_response"];
+
+ $this->progress(HRP_DEBUG,"Page loaded from cache");
+ $this->cache_hit = true;
+ return true;
+ } else {
+ $this->progress(HRP_DEBUG,"Error reading cache file");
+ return false;
+ }
+ }
+
+ function parent_path($path) {
+ if (substr($path,0,1)=='/') $path = substr($path,1);
+ if (substr($path,-1)=='/') $path = substr($path,0,strlen($path)-1);
+ $path = explode('/',$path);
+ array_pop($path);
+ return count($path) ? ('/' . implode('/',$path)) : '';
+ }
+
+ // $cookies should be an array in one of two formats.
+ //
+ // Either: $cookies[ 'cookiename' ] = array (
+ // '/path/'=>array(
+ // 'expires'=>time(),
+ // 'domain'=>'yourdomain.com',
+ // 'value'=>'cookievalue'
+ // )
+ // );
+ //
+ // Or, a more simplified format:
+ // $cookies[ 'cookiename' ] = 'value';
+ //
+ // The former format will automatically check to make sure that the path, domain,
+ // and expiration values match the HTTP request, and will only send the cookie if
+ // they do match. The latter will force the cookie to be set for the HTTP request
+ // unconditionally.
+ //
+ function response_to_request_cookies($cookies,$urlinfo) {
+
+ // check for simplified cookie format (name=value)
+ $cookiekeys = array_keys($cookies);
+ if (!count($cookiekeys)) return;
+
+ $testkey = array_pop($cookiekeys);
+ if (!is_array($cookies[ $testkey ])) {
+ foreach ($cookies as $k=>$v) $this->request_cookies[$k] = $v;
+ return;
+ }
+
+ // must not be simplified format, so parse as complex format:
+ foreach ($cookies as $name=>$paths) {
+ foreach ($paths as $path=>$values) {
+ // make sure the cookie isn't expired
+ if ( isset($values['expires']) && ($values['expires']<time()) ) continue;
+
+ $cookiehost = $values['domain'];
+ $requesthost = $urlinfo['host'];
+ // make sure the cookie is valid for this host
+ $domain_match = (
+ ($requesthost==$cookiehost) ||
+ (substr($requesthost,-(strlen($cookiehost)+1))=='.'.$cookiehost)
+ );
+
+ // make sure the cookie is valid for this path
+ $cookiepath = $path; if (substr($cookiepath,-1)!='/') $cookiepath .= '/';
+ $requestpath = $urlinfo['path']; if (substr($requestpath,-1)!='/') $requestpath .= '/';
+ if (substr($requestpath,0,strlen($cookiepath))!=$cookiepath) continue;
+
+ $this->request_cookies[$name] = $values['value'];
+ }
+ }
+ }
+
+ // Execute the request for a particular URL, and transparently follow
+ // HTTP redirects if enabled. If $cookies is specified, it is assumed
+ // to be an array received from $this->response_cookies and will be
+ // processed to determine which cookies are valid for this host/URL.
+ function _execute_request($url,$cookies = false) {
+ // valid codes for which we transparently follow a redirect
+ $redirect_codes = array(301,302,303,307);
+ // valid methods for which we transparently follow a redirect
+ $redirect_methods = array('GET','HEAD');
+
+ $request_result = false;
+
+ $this->followed_redirect = false;
+ $this->response_cookies = array();
+
+ $previous_redirects = array();
+ do {
+ // send the request
+ $request_result = $this->_send_request($url,$cookies);
+ $lasturl = $url;
+ $url = false;
+
+ // see if a redirect code was received
+ if ($this->follow_redirects && in_array($this->result_code,$redirect_codes)) {
+
+ // only redirect on a code 303 or if the method was GET/HEAD
+ if ( ($this->result_code==303) || in_array($this->method,$redirect_methods) ) {
+
+ // parse the information from the OLD URL so that we can handle
+ // relative links
+ $oldurlinfo = parse_url($lasturl);
+
+ $url = $this->response_headers['Location'];
+
+ // parse the information in the new URL, and fill in any blanks
+ // using values from the old URL
+ $urlinfo = parse_url($url);
+ foreach ($oldurlinfo as $k=>$v) {
+ if (!$urlinfo[$k]) $urlinfo[$k] = $v;
+ }
+
+ // create an absolute path
+ if (substr($urlinfo['path'],0,1)!='/') {
+ $baseurl = $oldurlinfo['path'];
+ if (substr($baseurl,-1)!='/') $baseurl = $this->parent_path($url) . '/';
+ $urlinfo['path'] = $baseurl . $urlinfo['path'];
+ }
+
+ // rebuild the URL
+ $url = $this->rebuild_url($urlinfo);
+
+ $this->progress(HRP_INFO,'Redirected to '.$url);
+ }
+ }
+
+ if ( $url && strlen($url) ) {
+
+ if (isset($previous_redirects[$url])) {
+ $this->error = "Infinite redirection loop";
+ $request_result = false;
+ break;
+ }
+ if ( is_numeric($this->follow_redirects) && (count($previous_redirects)>$this->follow_redirects) ) {
+ $this->error = "Exceeded redirection limit";
+ $request_result = false;
+ break;
+ }
+
+ $previous_redirects[$url] = true;
+ }
+
+ } while ($url && strlen($url));
+
+ // clear headers that shouldn't persist across multiple requests
+ $per_request_headers = array('Host','Content-Length');
+ foreach ($per_request_headers as $k=>$v) unset($this->headers[$v]);
+
+ if (count($previous_redirects)>1) $this->followed_redirect = array_keys($previous_redirects);
+
+ return $request_result;
+ }
+
+ // private - sends an HTTP request to $url
+ function _send_request($url,$cookies = false) {
+ $this->progress(HRP_INFO,"Initiating {$this->method} request for $url");
+ if ($this->caching) {
+ $cachetoken = md5($url.'|'.$this->post_data);
+ if ($this->_cache_fetch($cachetoken)) return true;
+ }
+
+ $time_request_start = $this->getmicrotime();
+
+ $urldata = parse_url($url);
+ $http_host = $urldata['host'] . (isset($urldata['port']) ? ':'.$urldata['port'] : '');
+
+ if (!isset($urldata["port"]) || !$urldata["port"]) $urldata["port"] = ($urldata["scheme"]=="https") ? 443 : 80;
+ if (!isset($urldata["path"]) || !$urldata["path"]) $urldata["path"] = '/';
+
+ if (!empty($urldata['user'])) $this->auth_username = $urldata['user'];
+ if (!empty($urldata['pass'])) $this->auth_password = $urldata['pass'];
+
+ //echo "Sending HTTP/{$this->version} {$this->method} request for ".$urldata["host"].":".$urldata["port"]." page ".$urldata["path"]."<br>";
+
+ if ($this->version>"1.0") $this->headers["Host"] = $http_host;
+ if ($this->method=="POST") {
+ $this->headers["Content-Length"] = strlen($this->post_data);
+ if (!isset($this->headers["Content-Type"])) $this->headers["Content-Type"] = "application/x-www-form-urlencoded";
+ }
+
+ if ( !empty($this->auth_username) || !empty($this->auth_password) ) {
+ $this->headers['Authorization'] = 'Basic '.base64_encode($this->auth_username.':'.$this->auth_password);
+ } else {
+ unset($this->headers['Authorization']);
+ }
+
+ if (is_array($cookies)) {
+ $this->response_to_request_cookies($cookies,$urldata);
+ }
+
+ if (($this->method=="GET") && (!empty($urldata["query"]))) $urldata["path"] .= "?".$urldata["query"];
+ $request = $this->method." ".$urldata["path"]." HTTP/".$this->version."\r\n";
+ $request .= $this->build_headers();
+ $request .= $this->post_data;
+
+ $this->response = "";
+
+ // Native SSL support requires the OpenSSL extension, and was introduced in PHP 4.3.0
+ $php_ssl_support = extension_loaded("openssl") && version_compare(phpversion(),"4.3.0")>=0;
+
+ // if this is a plain HTTP request, or if it's an HTTPS request and OpenSSL support is available,
+ // natively perform the HTTP request
+ if ( ( ($urldata["scheme"]=="http") || ($php_ssl_support && ($urldata["scheme"]=="https")) ) && (!$this->force_curl) ) {
+ $curl_mode = false;
+
+ $hostname = $this->connect_ip ? $this->connect_ip : $urldata['host'];
+ if ($urldata["scheme"]=="https") $hostname = 'ssl://'.$hostname;
+
+ $time_connect_start = $this->getmicrotime();
+
+ $this->progress(HRP_INFO,'Opening socket connection to '.$hostname.' port '.$urldata['port']);
+
+ $this->expected_bytes = -1;
+ $this->received_bytes = 0;
+
+ $fp = @fsockopen ($hostname,$urldata["port"],$errno,$errstr,$this->connect_timeout);
+ $time_connected = $this->getmicrotime();
+ $connect_time = $time_connected - $time_connect_start;
+ if ($fp) {
+ if ($this->stream_timeout) stream_set_timeout($fp,$this->stream_timeout);
+ $this->progress(HRP_INFO,"Connected; sending request");
+
+ $this->progress(HRP_DEBUG,$request);
+ fputs ($fp, $request);
+ $this->raw_request = $request;
+
+ if ($this->stream_timeout) {
+ $meta = socket_get_status($fp);
+ if ($meta['timed_out']) {
+ $this->error = "Exceeded socket write timeout of ".$this->stream_timeout." seconds";
+ $this->progress(HRP_ERROR,$this->error);
+ return false;
+ }
+ }
+
+ $this->progress(HRP_INFO,"Request sent; awaiting reply");
+
+ $headers_received = false;
+ $data_length = false;
+ $chunked = false;
+ $iterations = 0;
+ while (!feof($fp)) {
+
+ if ($data_length>0) {
+ $line = fread($fp,$data_length);
+ $data_length -= strlen($line);
+ } else {
+ $line = @fgets($fp,10240);
+ if ($chunked) {
+ $line = trim($line);
+ if (!strlen($line)) continue;
+
+ list($data_length,) = explode(';',$line);
+ $data_length = (int) hexdec(trim($data_length));
+
+ if ($data_length==0) {
+ $this->progress(HRP_DEBUG,"Done");
+ // end of chunked data
+ break;
+ }
+ $this->progress(HRP_DEBUG,"Chunk length $data_length (0x$line)");
+ continue;
+ }
+ }
+
+ $this->response .= $line;
+
+ $iterations++;
+ if ($headers_received) {
+ if ($time_connected>0) {
+ $time_firstdata = $this->getmicrotime();
+ $process_time = $time_firstdata - $time_connected;
+ $time_connected = 0;
+ }
+ $this->received_bytes += strlen($line);
+ if ($iterations % 20 == 0) {
+ $this->update_transfer_counters();
+ }
+ }
+
+
+ // some dumbass webservers don't respect Connection: close and just
+ // leave the connection open, so we have to be diligent about
+ // calculating the content length so we can disconnect at the end of
+ // the response
+ if ( (!$headers_received) && (trim($line)=="") ) {
+ $headers_received = true;
+
+ if (preg_match('/^Content-Length: ([0-9]+)/im',$this->response,$matches)) {
+ $data_length = (int) $matches[1];
+ $this->progress(HRP_DEBUG,"Content length is $data_length");
+ $this->expected_bytes = $data_length;
+ $this->update_transfer_counters();
+ }
+ if (preg_match("/^Transfer-Encoding: chunked/im",$this->response,$matches)) {
+ $chunked = true;
+ $this->progress(HRP_DEBUG,"Chunked transfer encoding requested");
+ }
+
+ if (preg_match_all("/^Set-Cookie: ((.*?)\=(.*?)(?:;\s*(.*))?)$/im",$this->response,$cookielist,PREG_SET_ORDER)) {
+ // get the path for which cookies will be valid if no path is specified
+ $cookiepath = preg_replace('/\/{2,}/','',$urldata['path']);
+ if (substr($cookiepath,-1)!='/') {
+ $cookiepath = explode('/',$cookiepath);
+ array_pop($cookiepath);
+ $cookiepath = implode('/',$cookiepath) . '/';
+ }
+ // process each cookie
+ foreach ($cookielist as $k=>$cookiedata) {
+ list(,$rawcookie,$name,$value,$attributedata) = $cookiedata;
+ $attributedata = explode(';',trim($attributedata));
+ $attributes = array();
+
+ $cookie = array(
+ 'value'=>$value,
+ 'raw'=>trim($rawcookie),
+ );
+ foreach ($attributedata as $k=>$attribute) {
+ list($attrname,$attrvalue) = explode('=',trim($attribute));
+ $cookie[$attrname] = $attrvalue;
+ }
+
+ if (!isset($cookie['domain']) || !$cookie['domain']) $cookie['domain'] = $urldata['host'];
+ if (!isset($cookie['path']) || !$cookie['path']) $cookie['path'] = $cookiepath;
+ if (isset($cookie['expires']) && $cookie['expires']) $cookie['expires'] = strtotime($cookie['expires']);
+
+ if (!$this->validate_response_cookie($cookie,$urldata['host'])) continue;
+
+ // do not store expired cookies; if one exists, unset it
+ if ( isset($cookie['expires']) && ($cookie['expires']<time()) ) {
+ unset($this->response_cookies[ $name ][ $cookie['path'] ]);
+ return false;
+ }
+
+ $this->response_cookies[ $name ][ $cookie['path'] ] = $cookie;
+ }
+ }
+ }
+
+ //$this->progress(HRP_INFO,"Next [$line]");
+ if ($this->stream_timeout) {
+ $meta = socket_get_status($fp);
+ if ($meta['timed_out']) {
+ $this->error = "Exceeded socket read timeout of ".$this->stream_timeout." seconds";
+ $this->progress(HRP_ERROR,$this->error);
+ return false;
+ }
+ }
+
+ // check time limits if requested
+ if ($this->max_time>0) {
+ if ($this->getmicrotime() - $time_request_start > $this->max_time) {
+ $this->error = "Exceeded maximum transfer time of ".$this->max_time." seconds";
+ $this->progress(HRP_ERROR,$this->error);
+ return false;
+ break;
+ }
+ }
+ if ($this->result_close) {
+ if (preg_match_all("/HTTP\/([0-9\.]+) ([0-9]+) (.*?)[\r\n]/",$this->response,$matches)) {
+ $resultcodes = $matches[2];
+ foreach ($resultcodes as $k=>$code) {
+ if ($code!=100) {
+ $this->progress(HRP_INFO,'HTTP result code received; closing connection');
+
+ $this->result_code = $code;
+ $this->result_text = $matches[3][$k];
+ fclose($fp);
+
+ return ($this->result_code==200);
+ }
+ }
+ }
+ }
+ }
+ @fclose ($fp);
+
+ $this->update_transfer_counters();
+
+ if (is_array($this->response_cookies)) {
+ // make sure paths are sorted in the order in which they should be applied
+ // when setting response cookies
+ foreach ($this->response_cookies as $name=>$paths) {
+ ksort($this->response_cookies[$name]);
+ }
+ }
+ $this->progress(HRP_INFO,'Request complete');
+ } else {
+ $this->error = strtoupper($urldata["scheme"])." connection to ".$hostname." port ".$urldata["port"]." failed";
+ $this->progress(HRP_ERROR,$this->error);
+ return false;
+ }
+
+ // perform an HTTP/HTTPS request using CURL
+ } elseif ( !$this->disable_curl && ( ($urldata["scheme"]=="https") || ($this->force_curl) ) ) {
+ $this->progress(HRP_INFO,'Passing HTTP request for $url to CURL');
+ $curl_mode = true;
+ if (!$this->_curl_request($url)) return false;
+
+ // unknown protocol
+ } else {
+ $this->error = "Unsupported protocol: ".$urldata["scheme"];
+ $this->progress(HRP_ERROR,$this->error);
+ return false;
+ }
+
+ $this->raw_response = $this->response;
+
+ $totallength = strlen($this->response);
+
+ do {
+ $headerlength = strpos($this->response,"\r\n\r\n");
+
+ $response_headers = explode("\r\n",substr($this->response,0,$headerlength));
+ $http_status = trim(array_shift($response_headers));
+ foreach ($response_headers as $line) {
+ list($k,$v) = explode(":",$line,2);
+ $this->response_headers[trim($k)] = trim($v);
+ }
+ $this->response = substr($this->response,$headerlength+4);
+
+ /* // Handled in-transfer now
+ if (($this->response_headers['Transfer-Encoding']=="chunked") && (!$curl_mode)) {
+ $this->remove_chunkiness();
+ }
+ */
+
+ if (!preg_match("/^HTTP\/([0-9\.]+) ([0-9]+) (.*?)$/",$http_status,$matches)) {
+ $matches = array("",$this->version,0,"HTTP request error");
+ }
+ list (,$response_version,$this->result_code,$this->result_text) = $matches;
+
+ // skip HTTP result code 100 (Continue) responses
+ } while (($this->result_code==100) && ($headerlength));
+
+ // record some statistics, roughly compatible with CURL's curl_getinfo()
+ if (!$curl_mode) {
+ $total_time = $this->getmicrotime() - $time_request_start;
+ $transfer_time = $total_time - $connect_time;
+ $this->stats = array(
+ "total_time"=>$total_time,
+ "connect_time"=>$connect_time, // time between connection request and connection established
+ "process_time"=>$process_time, // time between HTTP request and first data (non-headers) received
+ "url"=>$url,
+ "content_type"=>$this->response_headers["Content-Type"],
+ "http_code"=>$this->result_code,
+ "header_size"=>$headerlength,
+ "request_size"=>$totallength,
+ "filetime"=>strtotime($this->response_headers["Date"]),
+ "pretransfer_time"=>$connect_time,
+ "size_download"=>$totallength,
+ "speed_download"=>$transfer_time > 0 ? round($totallength / $transfer_time) : 0,
+ "download_content_length"=>$totallength,
+ "upload_content_length"=>0,
+ "starttransfer_time"=>$connect_time,
+ );
+ }
+
+
+ $ok = ($this->result_code==200);
+ if ($ok && $this->caching) $this->_cache_store($cachetoken);
+
+ return $ok;
+ }
+
+ function validate_response_cookie($cookie,$actual_hostname) {
+ // make sure the cookie can't be set for a TLD, eg: '.com'
+ $cookiehost = $cookie['domain'];
+ $p = strrpos($cookiehost,'.');
+ if ($p===false) return false;
+
+ $tld = strtolower(substr($cookiehost,$p+1));
+ $special_domains = array("com", "edu", "net", "org", "gov", "mil", "int");
+ $periods_required = in_array($tld,$special_domains) ? 1 : 2;
+
+ $periods = substr_count($cookiehost,'.');
+ if ($periods<$periods_required) return false;
+
+ if (substr($actual_hostname,0,1)!='.') $actual_hostname = '.'.$actual_hostname;
+ if (substr($cookiehost,0,1)!='.') $cookiehost = '.'.$cookiehost;
+ $domain_match = (
+ ($actual_hostname==$cookiehost) ||
+ (substr($actual_hostname,-strlen($cookiehost))==$cookiehost)
+ );
+
+ return $domain_match;
+
+ }
+
+ function build_headers() {
+ $headers = "";
+ foreach ($this->headers as $name=>$value) {
+ $value = trim($value);
+ if (empty($value)) continue;
+ $headers .= "{$name}: {$value}\r\n";
+ }
+
+ if (isset($this->request_cookies) && is_array($this->request_cookies)) {
+ $cookielist = array();
+ foreach ($this->request_cookies as $name=>$value) {
+ $cookielist[] = "{$name}={$value}";
+ }
+ if (count($cookielist)) $headers .= "Cookie: ".implode('; ',$cookielist)."\r\n";
+ }
+
+
+ $headers .= "\r\n";
+
+ return $headers;
+ }
+
+ // opposite of parse_url()
+ function rebuild_url($urlinfo) {
+ $url = $urlinfo['scheme'].'://';
+
+ if ($urlinfo['user'] || $urlinfo['pass']) {
+ $url .= $urlinfo['user'];
+ if ($urlinfo['pass']) {
+ if ($urlinfo['user']) $url .= ':';
+ $url .= $urlinfo['pass'];
+ }
+ $url .= '@';
+ }
+
+ $url .= $urlinfo['host'];
+ if ($urlinfo['port']) $url .= ':'.$urlinfo['port'];
+
+ $url .= $urlinfo['path'];
+
+ if ($urlinfo['query']) $url .= '?'.$urlinfo['query'];
+ if ($urlinfo['fragment']) $url .= '#'.$urlinfo['fragment'];
+
+ return $url;
+ }
+
+ function _replace_hostname(&$url,$new_hostname) {
+ $parts = parse_url($url);
+ $old_hostname = $parts['host'];
+
+ $parts['host'] = $new_hostname;
+
+ $url = $this->rebuild_url($parts);
+
+ return $old_hostname;
+ }
+
+ function _curl_request($url) {
+ $this->error = false;
+
+ // if a direct connection IP address was specified, replace the hostname
+ // in the URL with the IP address, and set the Host: header to the
+ // original hostname
+ if ($this->connect_ip) {
+ $old_hostname = $this->_replace_hostname($url,$this->connect_ip);
+ $this->headers["Host"] = $old_hostname;
+ }
+
+
+ unset($this->headers["Content-Length"]);
+ $headers = explode("\n",$this->build_headers());
+
+ $ch = curl_init();
+ curl_setopt($ch,CURLOPT_URL, $url);
+ curl_setopt($ch,CURLOPT_USERAGENT, $this->headers["User-Agent"]);
+ curl_setopt($ch,CURLOPT_HEADER, 1);
+ curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1);
+// curl_setopt($ch,CURLOPT_FOLLOWLOCATION, 1); // native method doesn't support this yet, so it's disabled for consistency
+ curl_setopt($ch,CURLOPT_TIMEOUT, 10);
+ curl_setopt($ch,CURLOPT_HTTPHEADER, $headers);
+
+ if ($this->method=="POST") {
+ curl_setopt($ch,CURLOPT_POST,1);
+ curl_setopt($ch,CURLOPT_POSTFIELDS,$this->post_data);
+ }
+ if ($this->insecure_ssl) {
+ curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,0);
+ }
+ if ($this->ignore_ssl_hostname) {
+ curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,1);
+ }
+
+ $this->response = curl_exec ($ch);
+ if (curl_errno($ch)!=0) {
+ $this->error = "CURL error #".curl_errno($ch).": ".curl_error($ch);
+ }
+
+ $this->stats = curl_getinfo($ch);
+ curl_close($ch);
+
+ return ($this->error === false);
+ }
+
+ function progress($level,$msg) {
+ if (is_callable($this->progress_callback)) call_user_func($this->progress_callback,$level,$msg);
+ }
+
+ // Gets any available HTTPRetriever error message (including both internal
+ // errors and HTTP errors)
+ function get_error() {
+ return $this->error ? $this->error : 'HTTP ' . $this->result_code.': '.$this->result_text;
+ }
+
+ function get_content_type() {
+ if (!$ctype = $this->response_headers['Content-Type']) {
+ $ctype = $this->response_headers['Content-type'];
+ }
+ list($ctype,) = explode(';',$ctype);
+
+ return strtolower($ctype);
+ }
+
+ function update_transfer_counters() {
+ if (is_callable($this->transfer_callback)) call_user_func($this->transfer_callback,$this->received_bytes,$this->expected_bytes);
+ }
+
+ function set_transfer_display($enabled = true) {
+ if ($enabled) {
+ $this->transfer_callback = array(&$this,'default_transfer_callback');
+ } else {
+ unset($this->transfer_callback);
+ }
+ }
+
+ function set_progress_display($enabled = true) {
+ if ($enabled) {
+ $this->progress_callback = array(&$this,'default_progress_callback');
+ } else {
+ unset($this->progress_callback);
+ }
+ }
+
+ function default_progress_callback($severity,$message) {
+ $severities = array(
+ HRP_DEBUG=>'debug',
+ HRP_INFO=>'info',
+ HRP_ERROR=>'error',
+ );
+
+ echo date('Y-m-d H:i:sa').' ['.$severities[$severity].'] '.$message."\n";
+ flush();
+ }
+
+ function default_transfer_callback($transferred,$expected) {
+ $msg = "Transferred " . round($transferred/1024,1);
+ if ($expected>=0) $msg .= "/" . round($expected/1024,1);
+ $msg .= "KB";
+ if ($expected>0) $msg .= " (".round($transferred*100/$expected,1)."%)";
+ echo date('Y-m-d H:i:sa')." $msg\n";
+ flush();
+ }
+
+ function getmicrotime() {
+ list($usec, $sec) = explode(" ",microtime());
+ return ((float)$usec + (float)$sec);
+ }
+}
+?>
\ No newline at end of file
--- /dev/null
+<?php
+/* CURL Extension Emulation Library
+ * Version 1.0.3
+ * Copyright 2004-2005, Steve Blinch
+ * http://code.blitzaffe.com
+ * ============================================================================
+ *
+ * DESCRIPTION
+ *
+ * Provides a pure-PHP implementation of the PHP CURL extension, for use on
+ * systems which do not already have the CURL extension installed. It emulates
+ * all of the curl_* functions normally provided by the CURL extension itself.
+ *
+ * This will automatically detect and use the best CURL implementation available
+ * on your server. It will attempt the following, in order:
+ *
+ * 1) Check for the existence of the "real" CURL PHP Extension. If it is
+ * loaded, the library will do nothing (and it will not interfere with the
+ * "real" extension).
+ * 2) Check for the existence of the CURL console binary (usually located in
+ * /usr/bin/curl). If found, the library will emulate the CURL PHP
+ * extension (including all curl_* functions) and use the console binary
+ * to execute all requests.
+ * 3) If neither the "real" CURL PHP Extension nor the CURL console binary
+ * are available, the library will emulate the CURL PHP extension (including
+ * all curl_* functions) using a native, pure-PHP HTTP client implementation.
+ * This implementation is somewhat limited, but it provides support for most
+ * of the common CURL options. HTTPS (SSL) support is available in this
+ * mode under PHP 4.3.0 if the OpenSSL Extension is loaded.
+ *
+ * Thus, by including this library in your project, you can rely on having some
+ * level of CURL support regardless of the configuration of the server on which
+ * it is being used.
+ *
+ *
+ * USAGE
+ *
+ * Simply copy all of the libcurlemu files into your project directory, then:
+ *
+ * require_once("libcurlemu.inc.php");
+ *
+ * After this, you can use all of the curl_* functions documented in the PHP
+ * Manual.
+ *
+ *
+ * EXAMPLE
+ *
+ * // CURL Extension Emulation Library Example
+ * //
+ * // Usage should be straightforward; you simply use this script exactly as you
+ * // would normally use the PHP CURL extension functions.
+ *
+ * // first, include libcurlemu.inc.php
+ * require_once('libcurlemu.inc.php');
+ *
+ * // at this point, libcurlemu has detected the best available CURL solution
+ * // (either the CURL extension, if available, or the CURL commandline binary,
+ * // if available, or as a last resort, HTTPRetriever, our native-PHP HTTP
+ * // client implementation) and has implemented the curl_* functions if
+ * // necessary, so you can use CURL normally and safely assume that all CURL
+ * // functions are available.
+ *
+ * // the rest of this example code is copied straight from the PHP manual's
+ * // reference for the curl_init() function, and will work fine with libcurlemu
+ *
+ * // create a new CURL resource
+ * $ch = curl_init();
+ *
+ * // set URL and other appropriate options
+ * curl_setopt($ch, CURLOPT_URL, "http://www.example.com/");
+ * curl_setopt($ch, CURLOPT_HEADER, false);
+ *
+ * // grab URL and pass it to the browser
+ * curl_exec($ch);
+ *
+ * // close CURL resource, and free up system resources
+ * curl_close($ch);
+ *
+ *
+ * LICENSE
+ *
+ * This script is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This script is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this script; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+if (!extension_loaded('curl') && !function_exists('curl_init')) {
+ define('CURLEXT_MISSING_ABORT',true);
+ require_once(dirname(__FILE__)."/libcurlexternal.inc.php");
+
+ if (!function_exists('curl_init')) {
+ require_once(dirname(__FILE__)."/class_HTTPRetriever.php");
+ require_once(dirname(__FILE__)."/libcurlnative.inc.php");
+ }
+}
+?>
\ No newline at end of file
--- /dev/null
+<?php
+/* CURL Extension Emulation Library (Console Binary)
+ * Copyright 2004-2005, Steve Blinch
+ * http://code.blitzaffe.com
+ * ============================================================================
+ *
+ * DESCRIPTION
+ *
+ * Provides a pure-PHP implementation of the PHP CURL extension, for use on
+ * systems which do not already have the CURL extension installed. It emulates
+ * all of the curl_* functions normally provided by the CURL extension itself
+ * by wrapping the CURL console binary.
+ *
+ * This library will automatically detect whether or not the "real" CURL
+ * extension is installed, and if so, it will not interfere. Thus, it can be
+ * used to ensure that, one way or another, the CURL functions are available
+ * for use.
+ *
+ * This library is actually a wrapper for the CURL console application (usually
+ * found in /usr/bin/curl), so you must have the CURL binary installed in order
+ * to use this script.
+ *
+ *
+ * USAGE
+ *
+ * Please see the PHP documentation under the "CURL, Client URL Library
+ * Functions" section for information about using this library. Almost all of
+ * the documentation and examples in the PHP manual should work with this
+ * library.
+ *
+ *
+ * LICENSE
+ *
+ * This script is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This script is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this script; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+// if the real CURL PHP extension is installed, exit without doing anything
+if (!extension_loaded("curl")) {
+
+// if the CURL path was not defined by the calling script, define it
+if (!defined("CURL_PATH")) define("CURL_PATH","/usr/bin/curl");
+
+// if the CURL binary was not found, do one of the following:
+// - if CURLEXT_MISSING_ABORT was defined, then exit without implementing the CURL functions
+// - if CURLEXT_MISSING_IGNORE was defined, then implement the CURL functions anyway (even
+// though they won't work without the CURL binary installed)
+// - otherwise, raise a fatal error and halt the script
+if (!is_executable(CURL_PATH)) {
+
+ if (defined("CURLEXT_MISSING_ABORT") && CURLEXT_MISSING_ABORT) {
+ return;
+ } elseif (defined("CURLEXT_MISSING_IGNORE") && CURLEXT_MISSING_IGNORE) {
+ // proceed and implement the CURL functions anyway, even though they won't work
+ } else {
+ trigger_error("CURL extension is not loaded, and the commandline version of CURL was not found at ".CURL_PATH,E_USER_ERROR);
+ }
+}
+
+define("CURLEXT_VERSION","1.0.0");
+
+define('CURLOPT_NOTHING',0);
+define('CURLOPT_FILE',10001);
+define('CURLOPT_URL',10002);
+define('CURLOPT_PORT',3);
+define('CURLOPT_PROXY',10004);
+define('CURLOPT_USERPWD',10005);
+define('CURLOPT_PROXYUSERPWD',10006);
+define('CURLOPT_RANGE',10007);
+define('CURLOPT_INFILE',10009);
+define('CURLOPT_ERRORBUFFER',10010);
+define('CURLOPT_WRITEFUNCTION',20011);
+define('CURLOPT_READFUNCTION',20012);
+define('CURLOPT_TIMEOUT',13);
+define('CURLOPT_INFILESIZE',14);
+define('CURLOPT_POSTFIELDS',10015);
+define('CURLOPT_REFERER',10016);
+define('CURLOPT_FTPPORT',10017);
+define('CURLOPT_USERAGENT',10018);
+define('CURLOPT_LOW_SPEED_LIMIT',19);
+define('CURLOPT_LOW_SPEED_TIME',20);
+define('CURLOPT_RESUME_FROM',21);
+define('CURLOPT_COOKIE',10022);
+define('CURLOPT_HTTPHEADER',10023);
+define('CURLOPT_HTTPPOST',10024);
+define('CURLOPT_SSLCERT',10025);
+define('CURLOPT_SSLCERTPASSWD',10026);
+define('CURLOPT_SSLKEYPASSWD',10026);
+define('CURLOPT_CRLF',27);
+define('CURLOPT_QUOTE',10028);
+define('CURLOPT_WRITEHEADER',10029);
+define('CURLOPT_COOKIEFILE',10031);
+define('CURLOPT_SSLVERSION',32);
+define('CURLOPT_TIMECONDITION',33);
+define('CURLOPT_TIMEVALUE',34);
+define('CURLOPT_HTTPREQUEST',10035);
+define('CURLOPT_CUSTOMREQUEST',10036);
+define('CURLOPT_STDERR',10037);
+define('CURLOPT_POSTQUOTE',10039);
+define('CURLOPT_WRITEINFO',10040);
+define('CURLOPT_VERBOSE',41);
+define('CURLOPT_HEADER',42);
+define('CURLOPT_NOPROGRESS',43);
+define('CURLOPT_NOBODY',44);
+define('CURLOPT_FAILONERROR',45);
+define('CURLOPT_UPLOAD',46);
+define('CURLOPT_POST',47);
+define('CURLOPT_FTPLISTONLY',48);
+define('CURLOPT_FTPAPPEND',50);
+define('CURLOPT_NETRC',51);
+define('CURLOPT_FOLLOWLOCATION',52);
+define('CURLOPT_FTPASCII',53);
+define('CURLOPT_TRANSFERTEXT',53);
+define('CURLOPT_PUT',54);
+define('CURLOPT_MUTE',55);
+define('CURLOPT_PROGRESSFUNCTION',20056);
+define('CURLOPT_PROGRESSDATA',10057);
+define('CURLOPT_AUTOREFERER',58);
+define('CURLOPT_PROXYPORT',59);
+define('CURLOPT_POSTFIELDSIZE',60);
+define('CURLOPT_HTTPPROXYTUNNEL',61);
+define('CURLOPT_INTERFACE',10062);
+define('CURLOPT_KRB4LEVEL',10063);
+define('CURLOPT_SSL_VERIFYPEER',64);
+define('CURLOPT_CAINFO',10065);
+define('CURLOPT_PASSWDFUNCTION',20066);
+define('CURLOPT_PASSWDDATA',10067);
+define('CURLOPT_MAXREDIRS',68);
+define('CURLOPT_FILETIME',10069);
+define('CURLOPT_TELNETOPTIONS',10070);
+define('CURLOPT_MAXCONNECTS',71);
+define('CURLOPT_CLOSEPOLICY',72);
+define('CURLOPT_CLOSEFUNCTION',20073);
+define('CURLOPT_FRESH_CONNECT',74);
+define('CURLOPT_FORBID_REUSE',75);
+define('CURLOPT_RANDOM_FILE',10076);
+define('CURLOPT_EGDSOCKET',10077);
+define('CURLOPT_CONNECTTIMEOUT',78);
+define('CURLOPT_HEADERFUNCTION',20079);
+define('CURLOPT_HTTPGET',80);
+define('CURLOPT_SSL_VERIFYHOST',81);
+define('CURLOPT_COOKIEJAR',10082);
+define('CURLOPT_SSL_CIPHER_LIST',10083);
+define('CURLOPT_HTTP_VERSION',84);
+define('CURLOPT_FTP_USE_EPSV',85);
+define('CURLOPT_SSLCERTTYPE',10086);
+define('CURLOPT_SSLKEY',10087);
+define('CURLOPT_SSLKEYTYPE',10088);
+define('CURLOPT_SSLENGINE',10089);
+define('CURLOPT_SSLENGINE_DEFAULT',90);
+define('CURLOPT_DNS_USE_GLOBAL_CACHE',91);
+define('CURLOPT_DNS_CACHE_TIMEOUT',92);
+define('CURLOPT_PREQUOTE',10093);
+
+define('CURLINFO_EFFECTIVE_URL',1);
+define('CURLINFO_HTTP_CODE',2);
+define('CURLINFO_FILETIME',14);
+define('CURLINFO_TOTAL_TIME',3);
+define('CURLINFO_NAMELOOKUP_TIME',4);
+define('CURLINFO_CONNECT_TIME',5);
+define('CURLINFO_PRETRANSFER_TIME',6);
+define('CURLINFO_STARTTRANSFER_TIME',17);
+define('CURLINFO_REDIRECT_TIME',19);
+define('CURLINFO_REDIRECT_COUNT',20);
+define('CURLINFO_SIZE_UPLOAD',7);
+define('CURLINFO_SIZE_DOWNLOAD',8);
+define('CURLINFO_SPEED_DOWNLOAD',9);
+define('CURLINFO_SPEED_UPLOAD',10);
+define('CURLINFO_HEADER_SIZE',11);
+define('CURLINFO_REQUEST_SIZE',12);
+define('CURLINFO_SSL_VERIFYRESULT',13);
+define('CURLINFO_CONTENT_LENGTH_DOWNLOAD',15);
+define('CURLINFO_CONTENT_LENGTH_UPLOAD',16);
+define('CURLINFO_CONTENT_TYPE',18);
+
+
+define("TIMECOND_ISUNMODSINCE",1);
+define("TIMECOND_IFMODSINCE",2);
+
+
+function _curlopt_name($curlopt) {
+ foreach (get_defined_constants() as $k=>$v) {
+ if ( (substr($k,0,8)=="CURLOPT_") && ($v==$curlopt)) return $k;
+ }
+ return false;
+}
+
+// Initialize a CURL emulation session
+function curl_init($url=false) {
+ $i = $GLOBALS["_CURLEXT_OPT"]["index"]++;
+ $GLOBALS["_CURLEXT_OPT"][$i] = array("url"=>$url);
+
+ return $i;
+}
+
+// Set an option for a CURL emulation transfer
+function curl_setopt($ch,$option,$value) {
+
+ $opt = &$GLOBALS["_CURLEXT_OPT"][$ch];
+ if (!$opt["args"]) $opt["args"] = array();
+ $args = &$opt["args"];
+ if (!$opt["settings"]) $opt["settings"] = array();
+ $settings = &$opt["settings"];
+
+ switch($option) {
+ case CURLOPT_URL:
+ $opt["url"] = $value;
+ break;
+ case CURLOPT_VERBOSE:
+ $opt["verbose"] = $value>0;
+ break;
+ case CURLOPT_USERPWD:
+ if ($value==="") $value = false;
+ $settings["user"] = $value;
+ break;
+ case CURLOPT_PROXYUSERPWD:
+ if ($value==="") $value = false;
+ $settings["proxy-user"] = $value;
+ break;
+ case CURLOPT_COOKIE:
+ if ($value==="") $value = false;
+ if ( is_bool($value) || (strpos($value,"=")!==false) ) $settings["cookie"] = $value;
+ break;
+ case CURLOPT_COOKIEFILE:
+ if ($value==="") $value = false;
+ $settings["cookie"] = $value;
+ break;
+ case CURLOPT_COOKIEJAR:
+ if ($value==="") $value = false;
+ $settings["cookie-jar"] = $value;
+ break;
+ case CURLOPT_CUSTOMREQUEST:
+ if ($value==="") $value = false;
+ $settings["request"] = $value;
+ break;
+ case CURLOPT_PROXY:
+ if ($value==="") $value = false;
+ $settings["proxy"] = $value;
+ break;
+ case CURLOPT_INTERFACE:
+ if ($value==="") $value = false;
+ $settings["interface"] = $value;
+ break;
+ case CURLOPT_KRB4LEVEL:
+ if ($value==="") $value = false;
+ $settings["krb4"] = $value;
+ break;
+ case CURLOPT_SSLCERT:
+ $pass = "";
+ if (is_string($settings["cert"])) {
+ list(,$pass) = explode(":",$settings["cert"]);
+ if (strlen($pass)) $pass = ":$pass";
+ }
+ $settings["cert"] = $value.$pass;
+ break;
+ case CURLOPT_SSLCERTPASSWD:
+ $filename = "";
+ if (is_string($settings["cert"])) {
+ list($filename,) = explode(":",$settings["cert"]);
+ }
+ $settings["cert"] = $filename.":".$value;
+ break;
+ case CURLOPT_RANGE:
+ if ($value==="") $value = false;
+ $settings["range"] = $value;
+ break;
+ case CURLOPT_REFERER:
+ if ($value==="") $value = false;
+ $settings["referer"] = $value;
+ break;
+ case CURLOPT_NOBODY:
+ $settings["head"] = $value>0;
+ break;
+ case CURLOPT_FAILONERROR:
+ $opt["fail_on_error"] = $value>0;
+ break;
+ case CURLOPT_USERAGENT:
+ $settings["user-agent"] = $value;
+ break;
+ case CURLOPT_HEADER:
+ $settings["include"] = $value>0;
+ break;
+ case CURLOPT_RETURNTRANSFER:
+ $opt["return_transfer"] = $value>0;
+ break;
+ case CURLOPT_TIMEOUT:
+ $settings["max-time"] = (int) $value;
+ break;
+ case CURLOPT_HTTPHEADER:
+ reset($value);
+ foreach ($value as $k=>$header) $args[] = "header=".$header;
+ break;
+ case CURLOPT_POST:
+ $settings["data"]["enabled"] = $value>0;
+ break;
+ case CURLOPT_POSTFIELDS:
+ if ($value==="") $value = false;
+ $settings["data"]["value"] = $value;
+ break;
+ case CURLOPT_SSL_VERIFYPEER:
+ $settings["insecure"] = ($value==0);
+ break;
+ case CURLOPT_SSL_VERIFYHOST:
+ // not supported by the commandline client
+ break;
+ case CURLOPT_FOLLOWLOCATION:
+ $settings["location"] = $value>0;
+ break;
+ case CURLOPT_PUT:
+ $settings["upload-file"]["enabled"] = $value>0;
+ break;
+ case CURLOPT_INFILE:
+ if ($value==="") $value = false;
+
+ if (is_resource($value)) {
+
+ // Ugh, this is a terrible hack. The CURL extension accepts a file handle, but
+ // the CURL binary obviously wants a filename. Since you can't derive a filename
+ // from a file handle, we have to make a copy of the file from the file handle,
+ // then pass the temporary filename to the CURL binary.
+
+ $tmpfilename = tempnam("/tmp","cif");
+ $fp = @fopen($tmpfilename,"w");
+ if (!$fp) {
+ trigger_error("CURL emulation library could not create a temporary file for CURLOPT_INFILE; upload aborted",E_USER_WARNING);
+ } else {
+ while (!feof($value)) {
+ $contents = fread($value,8192);
+ fwrite($fp,$contents);
+ }
+ fclose($fp);
+ // if a temporary file was previously created, unlink it
+ if ($settings["upload-file"]["value"] && file_exists($settings["upload-file"]["value"])) unlink($settings["upload-file"]["value"]);
+
+ // set the new upload-file filename
+ $settings["upload-file"]["value"] = $tmpfilename;
+ }
+ } else {
+ trigger_error("CURLOPT_INFILE must specify a valid file resource",E_USER_WARNING);
+ }
+
+ break;
+ case CURLOPT_MUTE:
+ // we're already mute, no?
+ break;
+ case CURLOPT_LOW_SPEED_LIMIT:
+ $settings["speed-limit"] = (int) $value;
+ break;
+ case CURLOPT_LOW_SPEED_TIME:
+ $settings["speed-time"] = (int) $value;
+ break;
+ case CURLOPT_RESUME_FROM:
+ $settings["continue-at"] = (int) $value;
+ break;
+ case CURLOPT_CAINFO:
+ if ($value==="") $value = false;
+ $settings["cacert"] = $value;
+ break;
+ case CURLOPT_SSLVERSION:
+ $value = (int) $value;
+ switch($value) {
+ case 2:
+ case 3:
+ unset($settings["sslv2"]);
+ unset($settings["sslv3"]);
+ $settings["sslv".$value] = true;
+ break;
+ }
+ break;
+ case CURLOPT_TIMECONDITION:
+ // untested - I'm lazy :)
+ if (!isset($settings["time-cond"]["enabled"])) $settings["time-cond"]["enabled"] = false;
+ if (!$settings["time-cond"]["value"]) $settings["time-cond"]["value"] = 1;
+
+ $settings["time-cond"]["value"] = abs($settings["time-cond"]["value"]);
+ if ($value==TIMECOND_ISUNMODSINCE) {
+ $settings["time-cond"]["value"] *= -1;
+ }
+
+ break;
+ case CURLOPT_TIMEVALUE:
+ // untested - I'm lazy :)
+ if ($settings["time-cond"]["value"]) {
+ $sign = $settings["time-cond"]["value"] / abs($settings["time-cond"]["value"]);
+ } else {
+ $sign = 1;
+ }
+ $settings["time-cond"]["value"] = (int) $value * $sign;
+ break;
+ case CURLOPT_FILE:
+ if (is_resource($value)) {
+ $opt["output_handle"] = $value;
+ } else {
+ trigger_error("CURLOPT_FILE must specify a valid file resource",E_USER_WARNING);
+ }
+ break;
+ case CURLOPT_WRITEHEADER:
+ if (is_resource($value)) {
+ $opt["header_handle"] = $value;
+ } else {
+ trigger_error("CURLOPT_WRITEHEADER must specify a valid file resource",E_USER_WARNING);
+ }
+ break;
+ case CURLOPT_STDERR:
+ // not implemented for now - not really relevant
+ break;
+ // FTP stuff not implemented
+ case CURLOPT_QUOTE:
+ case CURLOPT_POSTQUOTE:
+ case CURLOPT_UPLOAD:
+ case CURLOPT_FTPLISTONLY:
+ case CURLOPT_FTPAPPEND:
+ case CURLOPT_FTPPORT:
+ // Other stuff not implemented
+ case CURLOPT_NETRC:
+ default:
+ trigger_error("CURL emulation does not implement CURL option "._curlopt_name($option),E_USER_WARNING);
+ break;
+ }
+}
+
+// Perform a CURL emulation session
+function curl_exec($ch) {
+ $opt = &$GLOBALS["_CURLEXT_OPT"][$ch];
+ $url = $opt["url"];
+ $verbose = $opt["verbose"];
+
+ // ask commandline CURL to return its statistics at the end of its output
+ $opt["settings"]["write-out"] = "%{http_code}|%{time_total}|%{time_namelookup}|%{time_connect}|%{time_pretransfer}|%{time_starttransfer}|%{size_download}|%{size_upload}|%{size_header}|%{size_request}|%{speed_download}|%{speed_upload}|||||||%{content_type}|%{url_effective}";
+ $writeout_order = array(
+ CURLINFO_HTTP_CODE,
+ CURLINFO_TOTAL_TIME,
+ CURLINFO_NAMELOOKUP_TIME,
+ CURLINFO_CONNECT_TIME,
+ CURLINFO_PRETRANSFER_TIME,
+ CURLINFO_STARTTRANSFER_TIME,
+ CURLINFO_SIZE_DOWNLOAD,
+ CURLINFO_SIZE_UPLOAD,
+ CURLINFO_HEADER_SIZE,
+ CURLINFO_REQUEST_SIZE,
+ CURLINFO_SPEED_DOWNLOAD,
+ CURLINFO_SPEED_UPLOAD,
+
+ // the following 5 items are not provided by commandline CURL, and thus are left empty
+ CURLINFO_FILETIME,
+ CURLINFO_REDIRECT_TIME,
+ CURLINFO_SSL_VERIFYRESULT,
+ CURLINFO_CONTENT_LENGTH_DOWNLOAD,
+ CURLINFO_CONTENT_LENGTH_UPLOAD,
+ CURLINFO_REDIRECT_COUNT,
+
+ CURLINFO_CONTENT_TYPE,
+ CURLINFO_EFFECTIVE_URL,
+ );
+
+ // if the CURLOPT_NOBODY option was specified (to remove the body from the output),
+ // but an output file handle was set, we need to tell CURL to return the body so
+ // that we can write it to the output handle and strip it from the output
+ if ($opt["settings"]["head"] && $opt["output_handle"]) {
+ unset($opt["settings"]["head"]);
+ $strip_body = true;
+ }
+ // if the CURLOPT_HEADER option was NOT specified, but a header file handle was
+ // specified, we again need to tell CURL to return the headers so we can write
+ // them, then strip them from the output
+ if (!isset($opt["settings"]["include"]) && isset($opt["header_handle"])) {
+ $opt["settings"]["include"] = true;
+ $strip_headers = true;
+ }
+
+ // build the CURL argument list
+ $arguments = "";
+ foreach ($opt["args"] as $k=>$arg) {
+ list($argname,$argval) = explode('=',$arg,2);
+ $arguments .= "--$argname ".escapeshellarg($argval)." ";
+ }
+ foreach ($opt["settings"] as $argname=>$argval) {
+ if (is_array($argval)) {
+ if (isset($argval["enabled"]) && !$argval["enabled"]) continue;
+ $argval = $argval["value"];
+ }
+ if ($argval===false) continue;
+ if (is_bool($argval)) $argval = "";
+ $arguments .= "--$argname ".escapeshellarg($argval)." ";
+ }
+
+ // build the CURL commandline and execute it
+ $cmd = CURL_PATH." ".$arguments." ".escapeshellarg($url);
+
+ if ($verbose) echo "libcurlemu: Executing: $cmd\n";
+ exec($cmd,$output,$ret);
+
+ if ($verbose) {
+ echo "libcurlemu: Result: ";
+ var_dump($output);
+ echo "libcurlemu: Exit code: $ret\n";
+ }
+
+ // check for errors
+ $opt["errno"] = $ret;
+ if ($ret) $opt["error"] = "CURL error #$ret";
+
+ // die if CURLOPT_FAILONERROR is set and the HTTP result code is greater than 300
+ if ($opt["fail_on_error"]) {
+ if (preg_match("/^HTTP\/1.[0-9]+ ([0-9]{3}) /",$output[0],$matches)) {
+ $resultcode = (int) $matches[1];
+ if ($resultcode>300) die;
+ } else {
+ die; // couldn't get result code!
+ }
+ }
+
+ // pull the statistics out from the output
+ $stats = explode('|',array_pop($output));
+ foreach ($writeout_order as $k=>$item) {
+ $opt["stats"][$item] = $stats[$k];
+ }
+
+ // build the response string
+ $output = implode("\r\n",$output);
+
+
+ // find the header end position if needed
+ if ($strip_headers || $strip_body || isset($opt["header_handle"])) {
+ $headerpos = strpos($output,"\r\n\r\n");
+ }
+
+ // if a file handle was provided for header output, extract the headers
+ // and write them to the handle
+ if (isset($opt["header_handle"])) {
+ $headers = substr($output,0,$headerpos);
+ fwrite($opt["header_handle"],$headers);
+ }
+
+ // if the caller did not request headers in the output, strip them
+ if ($strip_headers) {
+ $output = substr($output,$headerpos+4);
+ }
+
+ // if the caller did not request the response body in the output, strip it
+ if ($strip_body) {
+ if ($strip_headers) {
+ $body = $output;
+ $output = "";
+ } else {
+ $body = substr($output,$headerpos+4);
+ $output = substr($output,0,$headerpos);
+ }
+ }
+
+ // if a file handle was provided for output, write the output to it
+ if (isset($opt["output_handle"])) {
+ fwrite($opt["output_handle"],$output);
+
+ // if the caller requested that the response be returned, return it
+ } elseif ($opt["return_transfer"]) {
+ return $output;
+
+ // otherwise, just echo the output to stdout
+ } else {
+ echo $output;
+ }
+ return true;
+}
+
+function curl_close($ch) {
+ $opt = &$GLOBALS["_CURLEXT_OPT"][$ch];
+
+ if ($opt["settings"]) {
+ $settings = &$opt["settings"];
+ // if the user used CURLOPT_INFILE to specify a file to upload, remove the
+ // temporary file created for the CURL binary
+ if ($settings["upload-file"]["value"] && file_exists($settings["upload-file"]["value"])) unlink($settings["upload-file"]["value"]);
+ }
+
+ unset($GLOBALS["_CURLEXT_OPT"][$ch]);
+}
+
+function curl_errno($ch) {
+ return (int) $GLOBALS["_CURLEXT_OPT"][$ch]["errno"];
+}
+
+function curl_error($ch) {
+ return $GLOBALS["_CURLEXT_OPT"][$ch]["error"];
+}
+
+function curl_getinfo($ch,$opt=NULL) {
+ if ($opt) {
+ return $GLOBALS["_CURLEXT_OPT"][$ch]["stats"][$opt];
+ } else {
+ $curlinfo_tags = array(
+ "url"=>CURLINFO_EFFECTIVE_URL,
+ "content_type"=>CURLINFO_CONTENT_TYPE,
+ "http_code"=>CURLINFO_HTTP_CODE,
+ "header_size"=>CURLINFO_HEADER_SIZE,
+ "request_size"=>CURLINFO_REQUEST_SIZE,
+ "filetime"=>CURLINFO_FILETIME,
+ "ssl_verify_result"=>CURLINFO_SSL_VERIFYRESULT,
+ "redirect_count"=>CURLINFO_REDIRECT_COUNT,
+ "total_time"=>CURLINFO_TOTAL_TIME,
+ "namelookup_time"=>CURLINFO_NAMELOOKUP_TIME,
+ "connect_time"=>CURLINFO_CONNECT_TIME,
+ "pretransfer_time"=>CURLINFO_PRETRANSFER_TIME,
+ "size_upload"=>CURLINFO_SIZE_UPLOAD,
+ "size_download"=>CURLINFO_SIZE_DOWNLOAD,
+ "speed_download"=>CURLINFO_SPEED_DOWNLOAD,
+ "speed_upload"=>CURLINFO_SPEED_UPLOAD,
+ "download_content_length"=>CURLINFO_CONTENT_LENGTH_DOWNLOAD,
+ "upload_content_length"=>CURLINFO_CONTENT_LENGTH_UPLOAD,
+ "starttransfer_time"=>CURLINFO_STARTTRANSFER_TIME,
+ "redirect_time"=>CURLINFO_REDIRECT_TIME
+ );
+ $res = array();
+ foreach ($curlinfo_tags as $tag=>$opt) {
+ $res[$tag] = $GLOBALS["_CURLEXT_OPT"][$ch]["stats"][$opt];
+ }
+ return $res;
+ }
+}
+
+function curl_version() {
+ return "libcurlemu/".CURLEXT_VERSION."-ext";
+}
+
+}
+?>
\ No newline at end of file
--- /dev/null
+<?php
+/* CURL Extension Emulation Library (Native PHP)
+ * Copyright 2004-2005, Steve Blinch
+ * http://code.blitzaffe.com
+ * ============================================================================
+ *
+ * DESCRIPTION
+ *
+ * Provides a pure-PHP implementation of the PHP CURL extension, for use on
+ * systems which do not already have the CURL extension installed. It emulates
+ * all of the curl_* functions normally provided by the CURL extension itself,
+ * and uses an internal, native-PHP HTTP library to make requests.
+ *
+ * This library will automatically detect whether or not the "real" CURL
+ * extension is installed, and if so, it will not interfere. Thus, it can be
+ * used to ensure that, one way or another, the CURL functions are available
+ * for use.
+ *
+ * Note that this is only a *rough* emulation of CURL; it is not exact, and
+ * many of CURL's options are not implemented. For a more precise emulation of
+ * CURL, you may want to try our other libcurlexternal library which is based on
+ * the CURL console binary (and is virtually identical to the CURL extension).
+ *
+ *
+ * USAGE
+ *
+ * Please see the PHP documentation under the "CURL, Client URL Library
+ * Functions" section for information about using this library. Almost all of
+ * the documentation and examples in the PHP manual should work with this
+ * library.
+ *
+ *
+ * LICENSE
+ *
+ * This script is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This script is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this script; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+// if the real CURL PHP extension is installed, exit without doing anything;
+// if libcurlemu is installed and providing a wrapper for the CURL binary,
+// exit without doing anything
+if (!extension_loaded("curl") && !function_exists("curl_init")) {
+
+
+// if the CURL binary was not found, do one of the following:
+// - if CURLNAT_MISSING_ABORT was defined, then exit without
+// implementing the CURL functions
+// - otherwise, raise a fatal error and halt the script
+if (!class_exists("HTTPRetriever")) {
+ if (is_readable(dirname(__FILE__)."/class_HTTPRetriever.php")) {
+ define("HTTPR_NO_REDECLARE_CURL",true);
+ require_once(dirname(__FILE__)."/class_HTTPRetriever.php");
+ } else {
+ if (defined("CURLNAT_MISSING_ABORT") && CURLNAT_MISSING_ABORT) {
+ return;
+ } else {
+ trigger_error("CURL extension is not loaded, libcurlemu is not loaded, and the HTTPRetriever class is unavailable",E_USER_ERROR);
+ }
+ }
+}
+
+define("CURLNAT_VERSION","1.0.0");
+
+define('CURLOPT_NOTHING',0);
+define('CURLOPT_FILE',10001);
+define('CURLOPT_URL',10002);
+define('CURLOPT_PORT',3);
+define('CURLOPT_PROXY',10004);
+define('CURLOPT_USERPWD',10005);
+define('CURLOPT_PROXYUSERPWD',10006);
+define('CURLOPT_RANGE',10007);
+define('CURLOPT_INFILE',10009);
+define('CURLOPT_ERRORBUFFER',10010);
+define('CURLOPT_WRITEFUNCTION',20011);
+define('CURLOPT_READFUNCTION',20012);
+define('CURLOPT_TIMEOUT',13);
+define('CURLOPT_INFILESIZE',14);
+define('CURLOPT_POSTFIELDS',10015);
+define('CURLOPT_REFERER',10016);
+define('CURLOPT_FTPPORT',10017);
+define('CURLOPT_USERAGENT',10018);
+define('CURLOPT_LOW_SPEED_LIMIT',19);
+define('CURLOPT_LOW_SPEED_TIME',20);
+define('CURLOPT_RESUME_FROM',21);
+define('CURLOPT_COOKIE',10022);
+define('CURLOPT_HTTPHEADER',10023);
+define('CURLOPT_HTTPPOST',10024);
+define('CURLOPT_SSLCERT',10025);
+define('CURLOPT_SSLCERTPASSWD',10026);
+define('CURLOPT_SSLKEYPASSWD',10026);
+define('CURLOPT_CRLF',27);
+define('CURLOPT_QUOTE',10028);
+define('CURLOPT_WRITEHEADER',10029);
+define('CURLOPT_COOKIEFILE',10031);
+define('CURLOPT_SSLVERSION',32);
+define('CURLOPT_TIMECONDITION',33);
+define('CURLOPT_TIMEVALUE',34);
+define('CURLOPT_HTTPREQUEST',10035);
+define('CURLOPT_CUSTOMREQUEST',10036);
+define('CURLOPT_STDERR',10037);
+define('CURLOPT_POSTQUOTE',10039);
+define('CURLOPT_WRITEINFO',10040);
+define('CURLOPT_VERBOSE',41);
+define('CURLOPT_HEADER',42);
+define('CURLOPT_NOPROGRESS',43);
+define('CURLOPT_NOBODY',44);
+define('CURLOPT_FAILONERROR',45);
+define('CURLOPT_UPLOAD',46);
+define('CURLOPT_POST',47);
+define('CURLOPT_FTPLISTONLY',48);
+define('CURLOPT_FTPAPPEND',50);
+define('CURLOPT_NETRC',51);
+define('CURLOPT_FOLLOWLOCATION',52);
+define('CURLOPT_FTPASCII',53);
+define('CURLOPT_TRANSFERTEXT',53);
+define('CURLOPT_PUT',54);
+define('CURLOPT_MUTE',55);
+define('CURLOPT_PROGRESSFUNCTION',20056);
+define('CURLOPT_PROGRESSDATA',10057);
+define('CURLOPT_AUTOREFERER',58);
+define('CURLOPT_PROXYPORT',59);
+define('CURLOPT_POSTFIELDSIZE',60);
+define('CURLOPT_HTTPPROXYTUNNEL',61);
+define('CURLOPT_INTERFACE',10062);
+define('CURLOPT_KRB4LEVEL',10063);
+define('CURLOPT_SSL_VERIFYPEER',64);
+define('CURLOPT_CAINFO',10065);
+define('CURLOPT_PASSWDFUNCTION',20066);
+define('CURLOPT_PASSWDDATA',10067);
+define('CURLOPT_MAXREDIRS',68);
+define('CURLOPT_FILETIME',10069);
+define('CURLOPT_TELNETOPTIONS',10070);
+define('CURLOPT_MAXCONNECTS',71);
+define('CURLOPT_CLOSEPOLICY',72);
+define('CURLOPT_CLOSEFUNCTION',20073);
+define('CURLOPT_FRESH_CONNECT',74);
+define('CURLOPT_FORBID_REUSE',75);
+define('CURLOPT_RANDOM_FILE',10076);
+define('CURLOPT_EGDSOCKET',10077);
+define('CURLOPT_CONNECTTIMEOUT',78);
+define('CURLOPT_HEADERFUNCTION',20079);
+define('CURLOPT_HTTPGET',80);
+define('CURLOPT_SSL_VERIFYHOST',81);
+define('CURLOPT_COOKIEJAR',10082);
+define('CURLOPT_SSL_CIPHER_LIST',10083);
+define('CURLOPT_HTTP_VERSION',84);
+define('CURLOPT_FTP_USE_EPSV',85);
+define('CURLOPT_SSLCERTTYPE',10086);
+define('CURLOPT_SSLKEY',10087);
+define('CURLOPT_SSLKEYTYPE',10088);
+define('CURLOPT_SSLENGINE',10089);
+define('CURLOPT_SSLENGINE_DEFAULT',90);
+define('CURLOPT_DNS_USE_GLOBAL_CACHE',91);
+define('CURLOPT_DNS_CACHE_TIMEOUT',92);
+define('CURLOPT_PREQUOTE',10093);
+
+define('CURLINFO_EFFECTIVE_URL',1);
+define('CURLINFO_HTTP_CODE',2);
+define('CURLINFO_FILETIME',14);
+define('CURLINFO_TOTAL_TIME',3);
+define('CURLINFO_NAMELOOKUP_TIME',4);
+define('CURLINFO_CONNECT_TIME',5);
+define('CURLINFO_PRETRANSFER_TIME',6);
+define('CURLINFO_STARTTRANSFER_TIME',17);
+define('CURLINFO_REDIRECT_TIME',19);
+define('CURLINFO_REDIRECT_COUNT',20);
+define('CURLINFO_SIZE_UPLOAD',7);
+define('CURLINFO_SIZE_DOWNLOAD',8);
+define('CURLINFO_SPEED_DOWNLOAD',9);
+define('CURLINFO_SPEED_UPLOAD',10);
+define('CURLINFO_HEADER_SIZE',11);
+define('CURLINFO_REQUEST_SIZE',12);
+define('CURLINFO_SSL_VERIFYRESULT',13);
+define('CURLINFO_CONTENT_LENGTH_DOWNLOAD',15);
+define('CURLINFO_CONTENT_LENGTH_UPLOAD',16);
+define('CURLINFO_CONTENT_TYPE',18);
+
+
+define("TIMECOND_ISUNMODSINCE",1);
+define("TIMECOND_IFMODSINCE",2);
+
+
+function _curlopt_name($curlopt) {
+ foreach (get_defined_constants() as $k=>$v) {
+ if ( (substr($k,0,8)=="CURLOPT_") && ($v==$curlopt)) return $k;
+ }
+ return false;
+}
+
+// Initialize a CURL emulation session
+function curl_init() {
+ $i = $GLOBALS["_CURLNAT_OPT"]["index"]++;
+ $GLOBALS["_CURLNAT_OPT"][$i] = array();
+ $GLOBALS["_CURLNAT_OPT"][$i]["http"] = &new HTTPRetriever();
+ $GLOBALS["_CURLNAT_OPT"][$i]["include_body"] = true;
+ return $i;
+}
+
+// Set an option for a CURL emulation transfer
+function curl_setopt($ch,$option,$value) {
+
+ $opt = &$GLOBALS["_CURLNAT_OPT"][$ch];
+ if (!$opt["args"]) $opt["args"] = array();
+ $args = &$opt["args"];
+ if (!$opt["settings"]) $opt["settings"] = array();
+ $settings = &$opt["settings"];
+ $http = &$opt["http"];
+
+ switch($option) {
+ case CURLOPT_URL:
+ $opt["url"] = $value;
+ break;
+ case CURLOPT_CUSTOMREQUEST:
+ $opt["method"] = $value;
+ break;
+ case CURLOPT_REFERER:
+ $http->headers["Referer"] = $value;
+ break;
+ case CURLOPT_NOBODY:
+ $opt["include_body"] = $value==0;
+ break;
+ case CURLOPT_FAILONERROR:
+ $opt["fail_on_error"] = $value>0;
+ break;
+ case CURLOPT_USERAGENT:
+ $http->headers["User-Agent"] = $value;
+ break;
+ case CURLOPT_HEADER:
+ $opt["include_headers"] = $value>0;
+ break;
+ case CURLOPT_RETURNTRANSFER:
+ $opt["return_transfer"] = $value>0;
+ break;
+ case CURLOPT_TIMEOUT:
+ $opt["max-time"] = (int) $value;
+ break;
+ case CURLOPT_HTTPHEADER:
+ reset($value);
+ foreach ($value as $k=>$header) {
+ list($headername,$headervalue) = explode(":",$header);
+ $http->headers[$headername] = ltrim($headervalue);
+ }
+ break;
+ case CURLOPT_POST:
+ $opt["post"] = $value>0;
+ break;
+ case CURLOPT_POSTFIELDS:
+ $opt["postdata"] = $value;
+ break;
+ case CURLOPT_MUTE:
+ // we're already mute, no?
+ break;
+ case CURLOPT_FILE:
+ if (is_resource($value)) {
+ $opt["output_handle"] = $value;
+ } else {
+ trigger_error("CURLOPT_FILE must specify a valid file resource",E_USER_WARNING);
+ }
+ break;
+ case CURLOPT_WRITEHEADER:
+ if (is_resource($value)) {
+ $opt["header_handle"] = $value;
+ } else {
+ trigger_error("CURLOPT_WRITEHEADER must specify a valid file resource",E_USER_WARNING);
+ }
+ break;
+ case CURLOPT_STDERR:
+ // not implemented for now - not really relevant
+ break;
+
+ case CURLOPT_SSL_VERIFYPEER:
+ case CURLOPT_SSL_VERIFYHOST:
+ // these are automatically disabled using ssl:// anyway
+ break;
+
+ case CURLOPT_USERPWD:
+ list($curl_user,$curl_pass) = explode(':',$value,2);
+ $http->auth_username = $curl_user;
+ $http->auth_password = $curl_pass;
+ break;
+
+ // Important stuff not implemented (as it's not yet supported by HTTPRetriever)
+ case CURLOPT_PUT:
+ case CURLOPT_INFILE:
+ case CURLOPT_FOLLOWLOCATION:
+ case CURLOPT_PROXYUSERPWD:
+ case CURLOPT_COOKIE:
+ case CURLOPT_COOKIEFILE:
+ case CURLOPT_PROXY:
+ case CURLOPT_RANGE:
+ case CURLOPT_RESUME_FROM:
+
+ // Things that cannot (reasonably) be implemented here
+ case CURLOPT_LOW_SPEED_LIMIT:
+ case CURLOPT_LOW_SPEED_TIME:
+ case CURLOPT_KRB4LEVEL:
+ case CURLOPT_SSLCERT:
+ case CURLOPT_SSLCERTPASSWD:
+ case CURLOPT_SSLVERSION:
+ case CURLOPT_INTERFACE:
+ case CURLOPT_CAINFO:
+ case CURLOPT_TIMECONDITION:
+ case CURLOPT_TIMEVALUE:
+
+ // FTP stuff not implemented
+ case CURLOPT_QUOTE:
+ case CURLOPT_POSTQUOTE:
+ case CURLOPT_UPLOAD:
+ case CURLOPT_FTPLISTONLY:
+ case CURLOPT_FTPAPPEND:
+ case CURLOPT_FTPPORT:
+
+ // Other stuff not implemented
+ case CURLOPT_VERBOSE:
+ case CURLOPT_NETRC:
+ default:
+ trigger_error("CURL emulation does not implement CURL option "._curlopt_name($option),E_USER_WARNING);
+ break;
+ }
+}
+
+// Perform a CURL emulation session
+function curl_exec($ch) {
+ $opt = &$GLOBALS["_CURLNAT_OPT"][$ch];
+ $url = $opt["url"];
+
+ $http = &$opt["http"];
+ $http->disable_curl = true; // avoid problems with recursion, since we *ARE* CURL
+
+ // set time limits if requested
+ if ($opt["max-time"]) {
+ $http->connect_timeout = $opt["max-time"];
+ $http->max_time = $opt["max-time"];
+ }
+
+ if ($opt["post"]) {
+ $res = $http->post($url,$opt["postdata"]);
+ } elseif ($opt["method"]) {
+ $res = $http->custom($opt["method"],$url,$opt["postdata"]);
+ } else {
+ $res = $http->get($url);
+ }
+
+ // check for errors
+ $opt["errno"] = (!$res && $http->error) ? 1 : 0;
+ if ($opt["errno"]) $opt["error"] = $http->error;
+
+ // die if CURLOPT_FAILONERROR is set and the HTTP result code is greater than 300
+ if ($opt["fail_on_error"]) {
+ if ($http->result_code>300) die;
+ }
+
+ $opt["stats"] = $http->stats;
+
+
+ $headers = "";
+ foreach ($http->response_headers as $k=>$v) {
+ $headers .= "$k: $v\r\n";
+ }
+
+ // if a file handle was provided for header output, extract the headers
+ // and write them to the handle
+ if (isset($opt["header_handle"])) {
+ fwrite($opt["header_handle"],$headers);
+ }
+
+ $output = ($opt["include_headers"] ? $headers."\r\n" : "") . ($opt["include_body"] ? $http->response : "");
+
+ // if a file handle was provided for output, write the output to it
+ if (isset($opt["output_handle"])) {
+ fwrite($opt["output_handle"],$output);
+
+ // if the caller requested that the response be returned, return it
+ } elseif ($opt["return_transfer"]) {
+ return $output;
+
+ // otherwise, just echo the output to stdout
+ } else {
+ echo $output;
+ }
+ return true;
+}
+
+function curl_close($ch) {
+ $opt = &$GLOBALS["_CURLNAT_OPT"][$ch];
+
+ if ($opt["settings"]) {
+ $settings = &$opt["settings"];
+ // if the user used CURLOPT_INFILE to specify a file to upload, remove the
+ // temporary file created for the CURL binary
+ if ($settings["upload-file"]["value"] && file_exists($settings["upload-file"]["value"])) unlink($settings["upload-file"]["value"]);
+ }
+
+ unset($GLOBALS["_CURLNAT_OPT"][$ch]);
+}
+
+function curl_errno($ch) {
+ return (int) $GLOBALS["_CURLNAT_OPT"][$ch]["errno"];
+}
+
+function curl_error($ch) {
+ return $GLOBALS["_CURLNAT_OPT"][$ch]["error"];
+}
+
+function curl_getinfo($ch,$opt=NULL) {
+ if ($opt) {
+ $curlinfo_tags = array(
+ CURLINFO_EFFECTIVE_URL=>"url",
+ CURLINFO_CONTENT_TYPE=>"content_type",
+ CURLINFO_HTTP_CODE=>"http_code",
+ CURLINFO_HEADER_SIZE=>"header_size",
+ CURLINFO_REQUEST_SIZE=>"request_size",
+ CURLINFO_FILETIME=>"filetime",
+ CURLINFO_SSL_VERIFYRESULT=>"ssl_verify_result",
+ CURLINFO_REDIRECT_COUNT=>"redirect_count",
+ CURLINFO_TOTAL_TIME=>"total_time",
+ CURLINFO_NAMELOOKUP_TIME=>"namelookup_time",
+ CURLINFO_CONNECT_TIME=>"connect_time",
+ CURLINFO_PRETRANSFER_TIME=>"pretransfer_time",
+ CURLINFO_SIZE_UPLOAD=>"size_upload",
+ CURLINFO_SIZE_DOWNLOAD=>"size_download",
+ CURLINFO_SPEED_DOWNLOAD=>"speed_download",
+ CURLINFO_SPEED_UPLOAD=>"speed_upload",
+ CURLINFO_CONTENT_LENGTH_DOWNLOAD=>"download_content_length",
+ CURLINFO_CONTENT_LENGTH_UPLOAD=>"upload_content_length",
+ CURLINFO_STARTTRANSFER_TIME=>"starttransfer_time",
+ CURLINFO_REDIRECT_TIME=>"redirect_time"
+ );
+
+ $key = $curlinfo_tags[$opt];
+ return $GLOBALS["_CURLNAT_OPT"][$ch]["stats"][$key];
+ } else {
+ return $GLOBALS["_CURLNAT_OPT"][$ch]["stats"];
+ }
+}
+
+function curl_version() {
+ return "libcurlemu/".CURLNAT_VERSION."-nat";
+}
+
+}
+?>
\ No newline at end of file
--- /dev/null
+Description of libcurlemu v1.0.3 import into Moodle
+
+Changes:
+ * example.php - removed
+ * original HTTPRetriever v1.1.5 replaced by standalone package v1.1.9
+
+$Id$
\ No newline at end of file