├── .gitignore ├── README.md ├── check.bat ├── install.bat ├── start_server.bat ├── stop_server.bat ├── support ├── base.php ├── check.php ├── createprocess.exe ├── download.php ├── install.php ├── my-medium.ini ├── php │ ├── libcrypto-1_1-x64.dll │ ├── libssl-1_1-x64.dll │ ├── php.exe │ ├── php.ini │ ├── php7ts.dll │ ├── php_openssl.dll │ └── vcruntime140.dll ├── support │ ├── cacert.pem │ ├── crc32_stream.php │ ├── deflate_stream.php │ ├── emulate_curl.php │ ├── http.php │ ├── simple_html_dom.php │ ├── utf_utils.php │ └── web_browser.php └── upgrade.php ├── upgrade.bat └── vc_redist └── vcruntime140.dll /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore staging and debugging files that take up absurd amounts of space. 2 | proc/ 3 | apache/ 4 | apache_mod_php/ 5 | maria_db/ 6 | php/ 7 | staging/ 8 | installed.dat 9 | !support/php/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Portable Apache + Maria DB + PHP for Windows 2 | ============================================ 3 | 4 | This project is for web developers who prefer manually editing configuration files and want "manual" but quick startup of Apache and Maria DB (no Windows services). No more hunting for ZIP files for each separate piece of software. 5 | 6 | If XAMPP and similar incarnations are not really your style (e.g. you prefer the command-line and think phpMyAdmin is for weaklings), then this project might be more up your alley. Note that the primary purpose of this project is to set up a quick-and-dirty local WAMP install that just works and is not intended for use on production servers. 7 | 8 | [![Donate](https://cubiclesoft.com/res/donate-shield.png)](https://cubiclesoft.com/donate/) [![Discord](https://img.shields.io/discord/777282089980526602?label=chat&logo=discord)](https://cubiclesoft.com/product-support/github/) 9 | 10 | Features 11 | -------- 12 | 13 | * Classic Apache + Maria DB + PHP combo in a portable format. 14 | * A flashback from the past: Batch files! install.bat, start_server.bat, and stop_server.bat to install, start, and stop the software respectively. 15 | * Installation is designed to just adapt paths to the current host. No registry mess, no Windows services, no problem. 16 | * Has a liberal open source license. MIT or LGPL, your choice. (Only applies to the new files that this project adds. Each product has its own separate license. See below.) 17 | * Designed for relatively painless integration into your Windows environment. 18 | * Sits on GitHub for all of that pull request and issue tracker goodness to easily submit changes and ideas respectively. 19 | 20 | Useful Information 21 | ------------------ 22 | 23 | Do the whole 'git clone' thing to obtain the latest release. Then run 'install.bat' to get the configuration files set up quickly. Note that you will need approximately 2GB free to successfully complete the installation. 24 | 25 | Run 'start_server.bat' to start the Apache web server and Maria DB database server. To stop both servers, run 'stop_server.bat'. 26 | 27 | To upgrade to the latest version, stop the servers with 'stop_server.bat', run 'git pull', and then run 'upgrade.bat'. 28 | 29 | To check for the latest version (and bugs in the scraper), run 'check.bat'. 30 | 31 | To only install or upgrade one or two of the packages, run 'install.bat' with one or more of these options: apache, maria_db, php 32 | 33 | For example: upgrade.bat php 34 | 35 | Troubleshooting 36 | --------------- 37 | 38 | Requires 'taskkill.exe' for 'stop_server.bat' to work properly. This is part of Windows XP and later. 39 | 40 | If the PHP module for Apache fails to load or if you want to always have `php.exe` be more conveniently available from the command-line, modifying the system or user PATH environment variable can solve both problems AND create new problems. On Windows 10, the PATH is inconveniently buried under: Control Panel -> System -> Advanced system settings -> Environment Variables... -> PATH. Note that adding paths to the system or user PATH are problematic for other applications that run on the same system, which can result in [DLL hell](https://en.wikipedia.org/wiki/DLL_Hell) and also slow down the overall system. But adding an item to the PATH can make it easier to run both Apache and `php.exe` from the command-line without having to duplicate a bunch of DLLs when using PECL. 41 | 42 | Installing PECL Extensions 43 | -------------------------- 44 | 45 | [PECL](https://pecl.php.net/) contains a number of powerful and popular extensions for PHP such as [Xdebug](https://pecl.php.net/package/xdebug), [ImageMagick](https://pecl.php.net/package/imagick), [Redis](https://pecl.php.net/package/redis), etc. Getting them to work on Windows can be challenging. The following is a general guide. 46 | 47 | Most PECL packages work on Linux hosts since Linux is the defacto server OS in the world and also PECL's native environment. When a PECL package supports Windows, a little Windows icon plus a "DLL" appears next to it. There are far fewer packages with Windows support. The PECL DLLs are precompiled versions for several versions of PHP. The PECL subsystem automatically builds binaries for Windows when support is declared for those PECL packages. Whether or not a downloaded compiled DLL actually works with PHP is a completely different issue. 48 | 49 | There are typically four flavors of DLL in PECL: NTS x64, TS x64, NTS x86, and TS x86. This project currently uses: 64-bit (x64) Thread-safe (TS) PHP. So the PECL DLLs you want are of the "TS x64" variety. 50 | 51 | From a command-line, run `php.exe -v`. That will provide the current working version and also verify x64 vs x86 PHP. 52 | 53 | Downloading the right DLL is only the start. The next step is to update the `php.ini` and verify that the DLL is set up correctly. Each extension is different. PECL extensions generally go into the `php/ext` subdirectory. There are two areas to update in `php.ini`: 54 | 55 | ``` 56 | extension_dir = "C:/path/to/php/ext" <-- If not already uncommented. 57 | 58 | ... 59 | 60 | extension=extname <-- In general, no .dll 61 | zend_extention=zendextname <-- Rare. Mostly just Xdebug and Zend opcache these days. 62 | ``` 63 | 64 | For some extensions, you will need additional downloads. In particular, ImageMagick requires many additional DLLs to function. The PECL extension only provides the necessary glue between the ImageMagick DLLs, PHP core, and PHP userland (i.e. your PHP-based application). In addition, you need to match x86/x64 DLLs with PHP. If you prefer portable software, which you probably do if you are using this project, then you'll need to find a portable flavor of the library that only includes the required DLLs and not an installer. 65 | 66 | Some extensions are Zend extensions (e.g. Xdebug) and require a `zend_extension` line instead of `extension` in `php.ini`. A number of PECL extensions also add `php.ini` options. 67 | 68 | From a command-line, run `php.exe -v` again. That will verify that PHP didn't have any problems loading the extension. If it does, a dialog box will appear indicating it failed to load and then you have a lot of work ahead of you to determine why it failed. These tools are your friend: 69 | 70 | * [Microsoft SysInternals Process Monitor](https://docs.microsoft.com/en-us/sysinternals/downloads/procmon) - Watching for `php.exe` processes and the DLLs they attempt to load and what paths they attempt to load them from. 71 | * [Dependencies](https://github.com/lucasg/Dependencies) - Tossing the PECL extension DLL in to see dependency trees and whether or not Windows will be able to load the DLL itself. 72 | 73 | The Windows EXE/DLL loader has [complex, broken rules](https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order) on how it loads DLLs into RAM. In general, third-party DLLs that the PECL extension depend on (e.g. ImageMagick DLLs) go into the same directory as the running executable OR somewhere on the system/user PATH. The rules for how the Windows loader works basically invite wrecking a pristine Windows installation. Knowing how the Windows loader works under the hood will make your life a LOT easier when working with PECL extensions. 74 | 75 | Sources 76 | ------- 77 | 78 | The Apache web server is under the Apache License, Version 2.0. (http://www.apache.org/licenses/LICENSE-2.0.html) 79 | 80 | http://www.apachelounge.com/download/win32/ 81 | 82 | The Maria DB database server is under the GPL. (https://mariadb.com/kb/en/mariadb-license/) 83 | 84 | https://downloads.mariadb.org/ 85 | 86 | The PHP scripting language is under the PHP License. (http://www.php.net/license/3_01.txt) 87 | 88 | http://windows.php.net/download/ 89 | -------------------------------------------------------------------------------- /check.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | cls 3 | 4 | rem Portable Apache, Maria DB, PHP. 5 | rem (C) 2016 CubicleSoft. All Rights Reserved. 6 | 7 | "support/php/php.exe" support/check.php %1 %2 %3 8 | -------------------------------------------------------------------------------- /install.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | cls 3 | 4 | rem Portable Apache, Maria DB, PHP. 5 | rem (C) 2016 CubicleSoft. All Rights Reserved. 6 | 7 | "support/php/php.exe" support/install.php %1 %2 %3 8 | -------------------------------------------------------------------------------- /start_server.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | cls 3 | 4 | rem Portable Apache, Maria DB, PHP. 5 | rem (C) 2013 CubicleSoft. All Rights Reserved. 6 | 7 | echo Starting Apache... 8 | support\createprocess.exe /f=DETACHED_PROCESS /dir="apache/bin" "apache/bin/httpd.exe" 9 | 10 | echo Starting Maria DB... 11 | support\createprocess.exe /f=DETACHED_PROCESS /dir="maria_db/bin" "maria_db/bin/mysqld.exe" 12 | -------------------------------------------------------------------------------- /stop_server.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | cls 3 | 4 | rem Portable Apache, Maria DB, PHP. 5 | rem (C) 2013 CubicleSoft. All Rights Reserved. 6 | 7 | echo Stopping Apache... 8 | taskkill /F /FI "IMAGENAME eq httpd.exe" 2>&1 9 | 10 | echo Stopping Maria DB... 11 | support\createprocess.exe /dir="maria_db/bin" "maria_db/bin/mysqladmin.exe" shutdown -u root 12 | -------------------------------------------------------------------------------- /support/base.php: -------------------------------------------------------------------------------- 1 | false, "error" => "Copying '" . $srcdir . "/" . $file . "' to '" . $destdir . "/" . $file . "' failed.", "errorcode" => "copy_failed"); 30 | } 31 | } 32 | } 33 | 34 | closedir($dir); 35 | } 36 | else 37 | { 38 | return array("success" => false, "error" => "Unable to open directory '" . $srcdir . "'.", "opendir_failed"); 39 | } 40 | 41 | return array("success" => true); 42 | } 43 | ?> -------------------------------------------------------------------------------- /support/check.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /support/createprocess.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cubiclesoft/portable-apache-maria-db-php-for-windows/ef848e4b29d109e32bf3ede49d4ae314f9236ad8/support/createprocess.exe -------------------------------------------------------------------------------- /support/download.php: -------------------------------------------------------------------------------- 1 | ($size + strlen($data)) % 1000000) echo "."; 60 | } 61 | 62 | return true; 63 | } 64 | 65 | function DownloadAndExtract($installkey, $url) 66 | { 67 | global $stagingpath, $web; 68 | 69 | echo "Downloading: " . $url . "\n"; 70 | echo "Please wait..."; 71 | 72 | $fp = fopen($stagingpath . $installkey . ".zip", "wb"); 73 | $web2 = clone $web; 74 | $options = array( 75 | "read_body_callback" => "DownloadAndExtract_Callback", 76 | "read_body_callback_opts" => $fp 77 | ); 78 | $result = $web2->Process($url, $options); 79 | fclose($fp); 80 | 81 | if (!$result["success"]) DownloadFailed("Error retrieving URL. " . $result["error"]); 82 | else if ($result["response"]["code"] != 200) DownloadFailed("Error retrieving URL. Server returned: " . $result["response"]["code"] . " " . $result["response"]["meaning"]); 83 | 84 | echo "\n"; 85 | echo "ZIP file downloaded successfully.\n"; 86 | echo "Extracting..."; 87 | 88 | $emptyfiles = array(); 89 | $num = 0; 90 | @mkdir($stagingpath . $installkey); 91 | $zip = zip_open($stagingpath . $installkey . ".zip"); 92 | if (!is_resource($zip)) DownloadFailed("The ZIP file '" . $stagingpath . $installkey . ".zip" . "' was unable to be opened for reading."); 93 | while (($zipentry = zip_read($zip)) !== false) 94 | { 95 | $name = str_replace("\\", "/", zip_entry_name($zipentry)); 96 | $name = str_replace("../", "/", $name); 97 | $name = str_replace("./", "/", $name); 98 | $name = preg_replace("/\/+/", "/", $name); 99 | 100 | $pos = strrpos($name, "/"); 101 | if ($pos !== false) 102 | { 103 | $dirname = substr($name, 0, $pos); 104 | @mkdir($stagingpath . $installkey . "/" . $dirname, 0777, true); 105 | if (trim(substr($name, $pos + 1)) == "") continue; 106 | } 107 | 108 | $size = zip_entry_filesize($zipentry); 109 | if ($size == 0) 110 | { 111 | $emptyfiles[] = $name; 112 | continue; 113 | } 114 | 115 | if (!zip_entry_open($zip, $zipentry, "rb")) DownloadFailed("Error opening the ZIP file entry '" . zip_entry_name($name) . "' for reading."); 116 | $fp = fopen($stagingpath . $installkey . "/" . $name, "wb"); 117 | while ($size > 1000000) 118 | { 119 | fwrite($fp, zip_entry_read($zipentry, 1000000)); 120 | $size -= 1000000; 121 | } 122 | if ($size > 0) fwrite($fp, zip_entry_read($zipentry, $size)); 123 | fclose($fp); 124 | zip_entry_close($zipentry); 125 | 126 | $num++; 127 | if ($num % 10 == 0) echo "."; 128 | } 129 | zip_close($zip); 130 | 131 | foreach ($emptyfiles as $name) @file_put_contents($stagingpath . $installkey . "/" . $name, ""); 132 | 133 | echo "\n"; 134 | } 135 | 136 | function FindExtractedFile($path, $filename) 137 | { 138 | if (substr($path, -1) == "/") $path = substr($path, 0, -1); 139 | 140 | if (file_exists($path . "/" . $filename)) return $path . "/" . $filename; 141 | 142 | $dir = opendir($path); 143 | if ($dir) 144 | { 145 | while (($file = readdir($dir)) !== false) 146 | { 147 | if ($file != "." && $file != "..") 148 | { 149 | if (is_dir($path . "/" . $file)) 150 | { 151 | $result = FindExtractedFile($path . "/" . $file, $filename); 152 | if ($result !== false) return $result; 153 | } 154 | } 155 | } 156 | 157 | closedir($dir); 158 | } 159 | 160 | return false; 161 | } 162 | 163 | function SaveInstalledData() 164 | { 165 | global $installed, $installpath; 166 | 167 | file_put_contents($installpath . "installed.dat", json_encode($installed)); 168 | } 169 | 170 | // Track the versions of stuff that is installed. 171 | if (!file_exists($installpath . "installed.dat")) $installed = array(); 172 | else 173 | { 174 | $installed = @json_decode(@file_get_contents($installpath . "installed.dat"), true); 175 | if ($installed === false) $installed = array(); 176 | } 177 | 178 | if (!is_dir($stagingpath)) mkdir($stagingpath); 179 | 180 | // Determine if the user is only interested in a specific download. 181 | $downloadopts = array(); 182 | for ($x = 1; $x < $argc; $x++) $downloadopts[strtolower($argv[$x])] = true; 183 | if ($argc == 1) $downloadopts["apache"] = true; 184 | if ($argc == 1) $downloadopts["maria_db"] = true; 185 | if ($argc == 1) $downloadopts["php"] = true; 186 | 187 | // Apache. 188 | if (isset($downloadopts["apache"])) 189 | { 190 | $url = "https://www.apachelounge.com/download/"; 191 | echo "Detecting latest version of Apache:\n"; 192 | echo " " . $url . "\n"; 193 | echo "Please wait...\n"; 194 | $web = new WebBrowser(); 195 | $result = $web->Process($url); 196 | 197 | if (!$result["success"]) DownloadFailed("Error retrieving URL. " . $result["error"]); 198 | else if ($result["response"]["code"] != 200) DownloadFailed("Error retrieving URL. Server returned: " . $result["response"]["code"] . " " . $result["response"]["meaning"]); 199 | 200 | $baseurl = $result["url"]; 201 | 202 | $found = false; 203 | $html->load($result["body"]); 204 | $rows = $html->find("a[href]"); 205 | foreach ($rows as $row) 206 | { 207 | if (preg_match('/\/VS17\/binaries\/httpd-(.+)-[Ww]in64-VS17.zip$/', $row->href, $matches)) 208 | { 209 | $matches[1] .= " (VS17)"; 210 | 211 | echo "Found: " . $row->href . "\n"; 212 | echo "Latest version: " . $matches[1] . "\n"; 213 | echo "Currently installed: " . (isset($installed["apache"]) ? $installed["apache"] : "Not installed") . "\n"; 214 | $found = true; 215 | 216 | if ((!defined("CHECK_ONLY") || !CHECK_ONLY) && (!isset($installed["apache"]) || $matches[1] != $installed["apache"] || isset($downloadopts["force"]))) 217 | { 218 | DownloadAndExtract("apache", HTTP::ConvertRelativeToAbsoluteURL($baseurl, $row->href)); 219 | 220 | $extractpath = dirname(FindExtractedFile($stagingpath, "ABOUT_APACHE.txt")) . "/"; 221 | copy($installpath . "vc_redist/vcruntime140.dll", $extractpath . "bin/vcruntime140.dll"); 222 | @rename($extractpath . "cgi-bin", $extractpath . "orig-cgi-bin"); 223 | @rename($extractpath . "conf", $extractpath . "orig-conf"); 224 | @rename($extractpath . "htdocs", $extractpath . "orig-htdocs"); 225 | @rename($extractpath . "logs", $extractpath . "orig-logs"); 226 | 227 | echo "Copying staging files to final location...\n"; 228 | $result2 = CopyDirectory($extractpath, $installpath . "apache"); 229 | if (!$result2["success"]) echo "ERROR: Unable to copy files from staging to the final location. Partial upgrade applied.\n" . $result2["error"] . "\n"; 230 | else 231 | { 232 | echo "Cleaning up...\n"; 233 | ResetStagingArea($stagingpath); 234 | 235 | $installed["apache"] = $matches[1]; 236 | SaveInstalledData(); 237 | 238 | echo "Apache binaries updated to " . $matches[1] . ".\n"; 239 | } 240 | } 241 | 242 | break; 243 | } 244 | } 245 | if (!$found) 246 | { 247 | echo "ERROR: Unable to find latest Apache verison. Probably a bug.\n"; 248 | echo "Currently installed: " . (isset($installed["apache"]) ? $installed["apache"] : "Not installed") . "\n"; 249 | } 250 | } 251 | 252 | // Maria DB. 253 | if (isset($downloadopts["maria_db"])) 254 | { 255 | $url = "https://downloads.mariadb.org/rest-api/mariadb/"; 256 | echo "\n"; 257 | echo "Detecting latest version of Maria DB:\n"; 258 | echo " " . $url . "\n"; 259 | echo "Please wait...\n"; 260 | $web = new WebBrowser(); 261 | $result = $web->Process($url); 262 | 263 | if (!$result["success"]) DownloadFailed("Error retrieving URL. " . $result["error"]); 264 | else if ($result["response"]["code"] != 200) DownloadFailed("Error retrieving URL. Server returned: " . $result["response"]["code"] . " " . $result["response"]["meaning"]); 265 | 266 | $data = json_decode($result["body"], true); 267 | if (!is_array($data) || !isset($data["major_releases"])) DownloadFailed("Response data from the MariaDB API was not JSON."); 268 | 269 | // Find the latest stable release. 270 | $releaseid = false; 271 | foreach ($data["major_releases"] as $release) 272 | { 273 | if ($release["release_status"] === "Stable") 274 | { 275 | $releaseid = $release["release_id"]; 276 | } 277 | } 278 | 279 | if ($releaseid === false) DownloadFailed("Response data from the MariaDB API does not contain a Stable release."); 280 | 281 | $url = "https://downloads.mariadb.org/rest-api/mariadb/" . $releaseid . "/"; 282 | 283 | echo "Detecting download:\n"; 284 | echo " " . $url . "\n"; 285 | echo "Please wait...\n"; 286 | $web = new WebBrowser(); 287 | $result = $web->Process($url); 288 | 289 | if (!$result["success"]) DownloadFailed("Error retrieving URL. " . $result["error"]); 290 | else if ($result["response"]["code"] != 200) DownloadFailed("Error retrieving URL. Server returned: " . $result["response"]["code"] . " " . $result["response"]["meaning"]); 291 | 292 | $data = json_decode($result["body"], true); 293 | if (!is_array($data) || !isset($data["releases"])) DownloadFailed("Response data from the MariaDB API was not JSON."); 294 | 295 | $found = false; 296 | foreach ($data["releases"] as $ver => $verinfo) 297 | { 298 | foreach ($verinfo["files"] as $fileinfo) 299 | { 300 | if ($fileinfo["file_name"] === "mariadb-" . $ver . "-winx64.zip") 301 | { 302 | echo "Found: " . $fileinfo["file_download_url"] . "\n"; 303 | echo "Latest version: " . $ver . "\n"; 304 | echo "Currently installed: " . (isset($installed["maria_db"]) ? $installed["maria_db"] : "Not installed") . "\n"; 305 | $found = true; 306 | 307 | if ((!defined("CHECK_ONLY") || !CHECK_ONLY) && (!isset($installed["maria_db"]) || $ver != $installed["maria_db"] || isset($downloadopts["force"]))) 308 | { 309 | DownloadAndExtract("maria_db", $fileinfo["file_download_url"]); 310 | 311 | $extractpath = dirname(FindExtractedFile($stagingpath, "COPYING")) . "/"; 312 | @rename($extractpath . "data", $extractpath . "orig-data"); 313 | 314 | echo "Copying staging files to final location...\n"; 315 | $result2 = CopyDirectory($extractpath, $installpath . "maria_db"); 316 | if (!$result2["success"]) echo "ERROR: Unable to copy files from staging to the final location. Partial upgrade applied.\n" . $result2["error"] . "\n"; 317 | else 318 | { 319 | echo "Cleaning up...\n"; 320 | ResetStagingArea($stagingpath); 321 | 322 | $installed["maria_db"] = $ver; 323 | SaveInstalledData(); 324 | 325 | echo "Maria DB binaries updated to " . $ver . ".\n"; 326 | } 327 | } 328 | 329 | break; 330 | } 331 | } 332 | 333 | break; 334 | } 335 | if (!$found) 336 | { 337 | echo "ERROR: Unable to find latest Maria DB verison. Probably a bug.\n"; 338 | echo "Currently installed: " . (isset($installed["maria_db"]) ? $installed["maria_db"] : "Not installed") . "\n"; 339 | } 340 | } 341 | 342 | // PHP. 343 | if (isset($downloadopts["php"])) 344 | { 345 | $url = "https://windows.php.net/download/"; 346 | echo "\n"; 347 | echo "Detecting latest version of PHP:\n"; 348 | echo " " . $url . "\n"; 349 | echo "Please wait...\n"; 350 | $web = new WebBrowser(); 351 | $result = $web->Process($url); 352 | 353 | if (!$result["success"]) DownloadFailed("Error retrieving URL. " . $result["error"]); 354 | else if ($result["response"]["code"] != 200) DownloadFailed("Error retrieving URL. Server returned: " . $result["response"]["code"] . " " . $result["response"]["meaning"]); 355 | 356 | $baseurl = $result["url"]; 357 | 358 | $found = false; 359 | $html->load($result["body"]); 360 | $rows = $html->find("a[href]"); 361 | foreach ($rows as $row) 362 | { 363 | if (preg_match('/^\/downloads\/releases\/php-(8\.1\.\d+)-Win32-vs16-x64.zip$/', $row->href, $matches)) 364 | { 365 | echo "Found: " . $row->href . "\n"; 366 | echo "Latest version: " . $matches[1] . "\n"; 367 | echo "Currently installed: " . (isset($installed["php"]) ? $installed["php"] : "Not installed") . "\n"; 368 | $found = true; 369 | 370 | if ((!defined("CHECK_ONLY") || !CHECK_ONLY) && (!isset($installed["php"]) || $matches[1] != $installed["php"] || isset($downloadopts["force"]))) 371 | { 372 | DownloadAndExtract("php", HTTP::ConvertRelativeToAbsoluteURL($baseurl, $row->href)); 373 | 374 | $extractpath = dirname(FindExtractedFile($stagingpath, "php.exe")) . "/"; 375 | copy($installpath . "vc_redist/vcruntime140.dll", $extractpath . "vcruntime140.dll"); 376 | 377 | echo "Copying staging files to final location...\n"; 378 | $result2 = CopyDirectory($extractpath, $installpath . "php"); 379 | if (!$result2["success"]) echo "ERROR: Unable to copy files from staging to the final location. Partial upgrade applied.\n" . $result2["error"] . "\n"; 380 | else 381 | { 382 | echo "Cleaning up...\n"; 383 | ResetStagingArea($stagingpath); 384 | 385 | $installed["php"] = $matches[1]; 386 | SaveInstalledData(); 387 | 388 | echo "PHP binaries updated to " . $matches[1] . ".\n\n"; 389 | } 390 | } 391 | 392 | break; 393 | } 394 | } 395 | if (!$found) 396 | { 397 | echo "ERROR: Unable to find latest PHP verison. Probably a bug.\n"; 398 | echo "Currently installed: " . (isset($installed["php"]) ? $installed["php"] : "Not installed") . "\n"; 399 | } 400 | } 401 | 402 | ResetStagingArea($stagingpath); 403 | rmdir($stagingpath); 404 | 405 | echo "Updating finished.\n\n"; 406 | ?> -------------------------------------------------------------------------------- /support/install.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /support/my-medium.ini: -------------------------------------------------------------------------------- 1 | # Example MariaDB config file for medium systems. 2 | # 3 | # This is for a system with little memory (32M - 64M) where MariaDB plays 4 | # an important part, or systems up to 128M where MariaDB is used together with 5 | # other programs (such as a web server) 6 | # 7 | # MariaDB programs look for option files in a set of 8 | # locations which depend on the deployment platform. 9 | # You can copy this option file to one of those 10 | # locations. For information about these locations, do: 11 | # 'my_print_defaults --help' and see what is printed under 12 | # Default options are read from the following files in the given order: 13 | # More information at: http://dev.mysql.com/doc/mysql/en/option-files.html 14 | # 15 | # In this file, you can use all long options that a program supports. 16 | # If you want to know which options a program supports, run the program 17 | # with the "--help" option. 18 | 19 | # The following options will be passed to all MariaDB clients 20 | [client] 21 | #password = your_password 22 | port = 3306 23 | socket = /tmp/mysql.sock 24 | 25 | # Here follows entries for some specific programs 26 | 27 | # The MariaDB server 28 | [mysqld] 29 | port = 3306 30 | socket = /tmp/mysql.sock 31 | skip-external-locking 32 | key_buffer_size = 16M 33 | max_allowed_packet = 1M 34 | table_open_cache = 64 35 | sort_buffer_size = 512K 36 | net_buffer_length = 8K 37 | read_buffer_size = 256K 38 | read_rnd_buffer_size = 512K 39 | myisam_sort_buffer_size = 8M 40 | 41 | # Point the following paths to different dedicated disks 42 | #tmpdir = /tmp/ 43 | 44 | # Don't listen on a TCP/IP port at all. This can be a security enhancement, 45 | # if all processes that need to connect to mysqld run on the same host. 46 | # All interaction with mysqld must be made via Unix sockets or named pipes. 47 | # Note that using this option without enabling named pipes on Windows 48 | # (via the "enable-named-pipe" option) will render mysqld useless! 49 | # 50 | #skip-networking 51 | 52 | # Replication Master Server (default) 53 | # binary logging is required for replication 54 | log-bin=mysql-bin 55 | 56 | # binary logging format - mixed recommended 57 | binlog_format=mixed 58 | 59 | # required unique id between 1 and 2^32 - 1 60 | # defaults to 1 if master-host is not set 61 | # but will not function as a master if omitted 62 | server-id = 1 63 | 64 | # Replication Slave (comment out master section to use this) 65 | # 66 | # To configure this host as a replication slave, you can choose between 67 | # two methods : 68 | # 69 | # 1) Use the CHANGE MASTER TO command (fully described in our manual) - 70 | # the syntax is: 71 | # 72 | # CHANGE MASTER TO MASTER_HOST=, MASTER_PORT=, 73 | # MASTER_USER=, MASTER_PASSWORD= ; 74 | # 75 | # where you replace , , by quoted strings and 76 | # by the master's port number (3306 by default). 77 | # 78 | # Example: 79 | # 80 | # CHANGE MASTER TO MASTER_HOST='125.564.12.1', MASTER_PORT=3306, 81 | # MASTER_USER='joe', MASTER_PASSWORD='secret'; 82 | # 83 | # OR 84 | # 85 | # 2) Set the variables below. However, in case you choose this method, then 86 | # start replication for the first time (even unsuccessfully, for example 87 | # if you mistyped the password in master-password and the slave fails to 88 | # connect), the slave will create a master.info file, and any later 89 | # change in this file to the variables' values below will be ignored and 90 | # overridden by the content of the master.info file, unless you shutdown 91 | # the slave server, delete master.info and restart the slaver server. 92 | # For that reason, you may want to leave the lines below untouched 93 | # (commented) and instead use CHANGE MASTER TO (see above) 94 | # 95 | # required unique id between 2 and 2^32 - 1 96 | # (and different from the master) 97 | # defaults to 2 if master-host is set 98 | # but will not function as a slave if omitted 99 | #server-id = 2 100 | # 101 | # The replication master for this slave - required 102 | #master-host = 103 | # 104 | # The username the slave will use for authentication when connecting 105 | # to the master - required 106 | #master-user = 107 | # 108 | # The password the slave will authenticate with when connecting to 109 | # the master - required 110 | #master-password = 111 | # 112 | # The port the master is listening on. 113 | # optional - defaults to 3306 114 | #master-port = 115 | # 116 | # binary logging - not required for slaves, but recommended 117 | #log-bin=mysql-bin 118 | 119 | # Uncomment the following if you are using InnoDB tables 120 | #innodb_data_home_dir = C:\\mysql\\data\\ 121 | #innodb_data_file_path = ibdata1:10M:autoextend 122 | #innodb_log_group_home_dir = C:\\mysql\\data\\ 123 | # You can set .._buffer_pool_size up to 50 - 80 % 124 | # of RAM but beware of setting memory usage too high 125 | #innodb_buffer_pool_size = 16M 126 | # Set .._log_file_size to 25 % of buffer pool size 127 | #innodb_log_file_size = 5M 128 | #innodb_log_buffer_size = 8M 129 | #innodb_flush_log_at_trx_commit = 1 130 | #innodb_lock_wait_timeout = 50 131 | 132 | [mysqldump] 133 | quick 134 | max_allowed_packet = 16M 135 | 136 | [mysql] 137 | no-auto-rehash 138 | # Remove the next comment character if you are not familiar with SQL 139 | #safe-updates 140 | 141 | [myisamchk] 142 | key_buffer_size = 20M 143 | sort_buffer_size = 20M 144 | read_buffer = 2M 145 | write_buffer = 2M 146 | 147 | [mysqlhotcopy] 148 | interactive-timeout 149 | -------------------------------------------------------------------------------- /support/php/libcrypto-1_1-x64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cubiclesoft/portable-apache-maria-db-php-for-windows/ef848e4b29d109e32bf3ede49d4ae314f9236ad8/support/php/libcrypto-1_1-x64.dll -------------------------------------------------------------------------------- /support/php/libssl-1_1-x64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cubiclesoft/portable-apache-maria-db-php-for-windows/ef848e4b29d109e32bf3ede49d4ae314f9236ad8/support/php/libssl-1_1-x64.dll -------------------------------------------------------------------------------- /support/php/php.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cubiclesoft/portable-apache-maria-db-php-for-windows/ef848e4b29d109e32bf3ede49d4ae314f9236ad8/support/php/php.exe -------------------------------------------------------------------------------- /support/php/php7ts.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cubiclesoft/portable-apache-maria-db-php-for-windows/ef848e4b29d109e32bf3ede49d4ae314f9236ad8/support/php/php7ts.dll -------------------------------------------------------------------------------- /support/php/php_openssl.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cubiclesoft/portable-apache-maria-db-php-for-windows/ef848e4b29d109e32bf3ede49d4ae314f9236ad8/support/php/php_openssl.dll -------------------------------------------------------------------------------- /support/php/vcruntime140.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cubiclesoft/portable-apache-maria-db-php-for-windows/ef848e4b29d109e32bf3ede49d4ae314f9236ad8/support/php/vcruntime140.dll -------------------------------------------------------------------------------- /support/support/crc32_stream.php: -------------------------------------------------------------------------------- 1 | 0x04C11DB7, "start" => 0xFFFFFFFF, "xor" => 0xFFFFFFFF, "refdata" => 1, "refcrc" => 1); 14 | 15 | public function __construct() 16 | { 17 | $this->open = false; 18 | } 19 | 20 | public function Init($options = false) 21 | { 22 | if ($options === false && function_exists("hash_init")) $this->hash = hash_init("crc32b"); 23 | else 24 | { 25 | if ($options === false) $options = self::$default; 26 | 27 | $this->hash = false; 28 | $this->crctable = array(); 29 | $poly = $this->LIM32($options["poly"]); 30 | for ($x = 0; $x < 256; $x++) 31 | { 32 | $c = $this->SHL32($x, 24); 33 | for ($y = 0; $y < 8; $y++) $c = $this->SHL32($c, 1) ^ ($c & 0x80000000 ? $poly : 0); 34 | $this->crctable[$x] = $c; 35 | } 36 | 37 | $this->datareflect = $options["refdata"]; 38 | $this->crcreflect = $options["refcrc"]; 39 | $this->firstcrc = $options["start"]; 40 | $this->currcrc = $options["start"]; 41 | $this->finalxor = $options["xor"]; 42 | } 43 | 44 | $this->open = true; 45 | } 46 | 47 | public function AddData($data) 48 | { 49 | if (!$this->open) return false; 50 | 51 | if ($this->hash !== false) hash_update($this->hash, $data); 52 | else 53 | { 54 | $y = strlen($data); 55 | 56 | for ($x = 0; $x < $y; $x++) 57 | { 58 | if ($this->datareflect) $this->currcrc = $this->SHL32($this->currcrc, 8) ^ $this->crctable[$this->SHR32($this->currcrc, 24) ^ self::$revlookup[ord($data[$x])]]; 59 | else $this->currcrc = $this->SHL32($this->currcrc, 8) ^ $this->crctable[$this->SHR32($this->currcrc, 24) ^ ord($data[$x])]; 60 | } 61 | } 62 | 63 | return true; 64 | } 65 | 66 | public function Finalize() 67 | { 68 | if (!$this->open) return false; 69 | 70 | if ($this->hash !== false) 71 | { 72 | $result = hexdec(hash_final($this->hash)); 73 | 74 | $this->hash = hash_init("crc32b"); 75 | } 76 | else 77 | { 78 | if ($this->crcreflect) 79 | { 80 | $tempcrc = $this->currcrc; 81 | $this->currcrc = self::$revlookup[$this->SHR32($tempcrc, 24)] | $this->SHL32(self::$revlookup[$this->SHR32($tempcrc, 16) & 0xFF], 8) | $this->SHL32(self::$revlookup[$this->SHR32($tempcrc, 8) & 0xFF], 16) | $this->SHL32(self::$revlookup[$this->LIM32($tempcrc & 0xFF)], 24); 82 | } 83 | $result = $this->currcrc ^ $this->finalxor; 84 | 85 | $this->currcrc = $this->firstcrc; 86 | } 87 | 88 | return $result; 89 | } 90 | 91 | // These functions are a hacky, but effective way of enforcing unsigned 32-bit integers onto a generic signed int. 92 | // Allow bitwise operations to work across platforms. Minimum integer size must be 32-bit. 93 | private function SHR32($num, $bits) 94 | { 95 | $num = (int)$num; 96 | if ($bits < 0) $bits = 0; 97 | 98 | if ($num < 0 && $bits) 99 | { 100 | $num = ($num >> 1) & 0x7FFFFFFF; 101 | $bits--; 102 | } 103 | 104 | return $this->LIM32($num >> $bits); 105 | } 106 | 107 | private function SHL32($num, $bits) 108 | { 109 | if ($bits < 0) $bits = 0; 110 | 111 | return $this->LIM32((int)$num << $bits); 112 | } 113 | 114 | private function LIM32($num) 115 | { 116 | return (int)((int)$num & 0xFFFFFFFF); 117 | } 118 | } 119 | ?> -------------------------------------------------------------------------------- /support/support/deflate_stream.php: -------------------------------------------------------------------------------- 1 | open = false; 13 | } 14 | 15 | public function __destruct() 16 | { 17 | $this->Finalize(); 18 | } 19 | 20 | public static function IsSupported() 21 | { 22 | if (!is_bool(self::$supported)) 23 | { 24 | self::$supported = function_exists("stream_filter_append") && function_exists("stream_filter_remove") && function_exists("gzcompress"); 25 | if (self::$supported) 26 | { 27 | $data = self::Compress("test"); 28 | if ($data === false || $data === "") self::$supported = false; 29 | else 30 | { 31 | $data = self::Uncompress($data); 32 | if ($data === false || $data !== "test") self::$supported = false; 33 | } 34 | } 35 | } 36 | 37 | return self::$supported; 38 | } 39 | 40 | public static function Compress($data, $compresslevel = -1, $options = array()) 41 | { 42 | $ds = new DeflateStream; 43 | if (!$ds->Init("wb", $compresslevel, $options)) return false; 44 | if (!$ds->Write($data)) return false; 45 | if (!$ds->Finalize()) return false; 46 | $data = $ds->Read(); 47 | 48 | return $data; 49 | } 50 | 51 | public static function Uncompress($data, $options = array("type" => "auto")) 52 | { 53 | $ds = new DeflateStream; 54 | if (!$ds->Init("rb", -1, $options)) return false; 55 | if (!$ds->Write($data)) return false; 56 | if (!$ds->Finalize()) return false; 57 | $data = $ds->Read(); 58 | 59 | return $data; 60 | } 61 | 62 | public function Init($mode, $compresslevel = -1, $options = array()) 63 | { 64 | if ($mode !== "rb" && $mode !== "wb") return false; 65 | if ($this->open) $this->Finalize(); 66 | 67 | $this->fp = fopen("php://memory", "w+b"); 68 | if ($this->fp === false) return false; 69 | $this->compress = ($mode == "wb"); 70 | if (!isset($options["type"])) $options["type"] = "rfc1951"; 71 | 72 | if ($options["type"] == "rfc1950") $options["type"] = "zlib"; 73 | else if ($options["type"] == "rfc1952") $options["type"] = "gzip"; 74 | 75 | if ($options["type"] != "zlib" && $options["type"] != "gzip" && ($this->compress || $options["type"] != "auto")) $options["type"] = "raw"; 76 | $this->options = $options; 77 | 78 | // Add the deflate filter. 79 | if ($this->compress) $this->filter = stream_filter_append($this->fp, "zlib.deflate", STREAM_FILTER_WRITE, $compresslevel); 80 | else $this->filter = stream_filter_append($this->fp, "zlib.inflate", STREAM_FILTER_READ); 81 | 82 | $this->open = true; 83 | $this->indata = ""; 84 | $this->outdata = ""; 85 | 86 | if ($this->compress) 87 | { 88 | if ($this->options["type"] == "zlib") 89 | { 90 | $this->outdata .= "\x78\x9C"; 91 | $this->options["a"] = 1; 92 | $this->options["b"] = 0; 93 | } 94 | else if ($this->options["type"] == "gzip") 95 | { 96 | if (!class_exists("CRC32Stream", false)) require_once str_replace("\\", "/", dirname(__FILE__)) . "/crc32_stream.php"; 97 | 98 | $this->options["crc32"] = new CRC32Stream(); 99 | $this->options["crc32"]->Init(); 100 | $this->options["bytes"] = 0; 101 | 102 | $this->outdata .= "\x1F\x8B\x08"; 103 | $flags = 0; 104 | if (isset($this->options["filename"])) $flags |= 0x08; 105 | if (isset($this->options["comment"])) $flags |= 0x10; 106 | $this->outdata .= chr($flags); 107 | $this->outdata .= "\x00\x00\x00\x00"; 108 | $this->outdata .= "\x00"; 109 | $this->outdata .= "\x03"; 110 | 111 | if (isset($this->options["filename"])) $this->outdata .= str_replace("\x00", " ", $this->options["filename"]) . "\x00"; 112 | if (isset($this->options["comment"])) $this->outdata .= str_replace("\x00", " ", $this->options["comment"]) . "\x00"; 113 | } 114 | } 115 | else 116 | { 117 | $this->options["header"] = false; 118 | } 119 | 120 | return true; 121 | } 122 | 123 | public function Read() 124 | { 125 | $result = $this->outdata; 126 | $this->outdata = ""; 127 | 128 | return $result; 129 | } 130 | 131 | public function Write($data) 132 | { 133 | if (!$this->open) return false; 134 | 135 | if ($this->compress) 136 | { 137 | if ($this->options["type"] == "zlib") 138 | { 139 | // Adler-32. 140 | $y = strlen($data); 141 | for ($x = 0; $x < $y; $x++) 142 | { 143 | $this->options["a"] = ($this->options["a"] + ord($data[$x])) % 65521; 144 | $this->options["b"] = ($this->options["b"] + $this->options["a"]) % 65521; 145 | } 146 | } 147 | else if ($this->options["type"] == "gzip") 148 | { 149 | $this->options["crc32"]->AddData($data); 150 | $this->options["bytes"] = $this->ADD32($this->options["bytes"], strlen($data)); 151 | } 152 | 153 | $this->indata .= $data; 154 | while (strlen($this->indata) >= 65536) 155 | { 156 | fwrite($this->fp, substr($this->indata, 0, 65536)); 157 | $this->indata = substr($this->indata, 65536); 158 | 159 | $this->ProcessOutput(); 160 | } 161 | } 162 | else 163 | { 164 | $this->indata .= $data; 165 | $this->ProcessInput(); 166 | } 167 | 168 | return true; 169 | } 170 | 171 | // Finalizes the stream. 172 | public function Finalize() 173 | { 174 | if (!$this->open) return false; 175 | 176 | if (!$this->compress) $this->ProcessInput(true); 177 | 178 | if (strlen($this->indata) > 0) 179 | { 180 | fwrite($this->fp, $this->indata); 181 | $this->indata = ""; 182 | } 183 | 184 | // Removing the filter pushes the last buffer into the stream. 185 | stream_filter_remove($this->filter); 186 | $this->filter = false; 187 | 188 | $this->ProcessOutput(); 189 | 190 | fclose($this->fp); 191 | 192 | if ($this->compress) 193 | { 194 | if ($this->options["type"] == "zlib") $this->outdata .= pack("N", $this->SHL32($this->options["b"], 16) | $this->options["a"]); 195 | else if ($this->options["type"] == "gzip") $this->outdata .= pack("V", $this->options["crc32"]->Finalize()) . pack("V", $this->options["bytes"]); 196 | } 197 | 198 | $this->open = false; 199 | 200 | return true; 201 | } 202 | 203 | private function ProcessOutput() 204 | { 205 | rewind($this->fp); 206 | 207 | // Hack! Because ftell() on a stream with a filter is still broken even under the latest PHP a mere 11 years later. 208 | // See: https://bugs.php.net/bug.php?id=49874 209 | ob_start(); 210 | fpassthru($this->fp); 211 | $this->outdata .= ob_get_contents(); 212 | ob_end_clean(); 213 | 214 | rewind($this->fp); 215 | ftruncate($this->fp, 0); 216 | } 217 | 218 | private function ProcessInput($final = false) 219 | { 220 | // Automatically determine the type of data based on the header signature. 221 | if ($this->options["type"] == "auto") 222 | { 223 | if (strlen($this->indata) >= 3) 224 | { 225 | $zlibtest = unpack("n", substr($this->indata, 0, 2)); 226 | 227 | if (substr($this->indata, 0, 3) === "\x1F\x8B\x08") $this->options["type"] = "gzip"; 228 | else if ((ord($this->indata[0]) & 0x0F) == 8 && ((ord($this->indata[0]) & 0xF0) >> 4) < 8 && $zlibtest[1] % 31 == 0) $this->options["type"] = "zlib"; 229 | else $this->options["type"] = "raw"; 230 | } 231 | else if ($final) $this->options["type"] = "raw"; 232 | } 233 | 234 | if ($this->options["type"] == "gzip") 235 | { 236 | if (!$this->options["header"]) 237 | { 238 | if (strlen($this->indata) >= 10) 239 | { 240 | $idcm = substr($this->indata, 0, 3); 241 | $flg = ord($this->indata[3]); 242 | 243 | if ($idcm !== "\x1F\x8B\x08") $this->options["type"] = "ignore"; 244 | else 245 | { 246 | // Calculate the number of bytes to skip. If flags are set, the size can be dynamic. 247 | $size = 10; 248 | $y = strlen($this->indata); 249 | 250 | // FLG.FEXTRA 251 | if ($size && ($flg & 0x04)) 252 | { 253 | if ($size + 2 >= $y) $size = 0; 254 | else 255 | { 256 | $xlen = unpack("v", substr($this->indata, $size, 2)); 257 | $size = ($size + 2 + $xlen <= $y ? $size + 2 + $xlen : 0); 258 | } 259 | } 260 | 261 | // FLG.FNAME 262 | if ($size && ($flg & 0x08)) 263 | { 264 | $pos = strpos($this->indata, "\x00", $size); 265 | $size = ($pos !== false ? $pos + 1 : 0); 266 | } 267 | 268 | // FLG.FCOMMENT 269 | if ($size && ($flg & 0x10)) 270 | { 271 | $pos = strpos($this->indata, "\x00", $size); 272 | $size = ($pos !== false ? $pos + 1 : 0); 273 | } 274 | 275 | // FLG.FHCRC 276 | if ($size && ($flg & 0x02)) $size = ($size + 2 <= $y ? $size + 2 : 0); 277 | 278 | if ($size) 279 | { 280 | $this->indata = substr($this->indata, $size); 281 | $this->options["header"] = true; 282 | } 283 | } 284 | } 285 | } 286 | 287 | if ($this->options["header"] && strlen($this->indata) > 8) 288 | { 289 | fwrite($this->fp, substr($this->indata, 0, -8)); 290 | $this->indata = substr($this->indata, -8); 291 | 292 | $this->ProcessOutput(); 293 | } 294 | 295 | if ($final) $this->indata = ""; 296 | } 297 | else if ($this->options["type"] == "zlib") 298 | { 299 | if (!$this->options["header"]) 300 | { 301 | if (strlen($this->indata) >= 2) 302 | { 303 | $cmf = ord($this->indata[0]); 304 | $flg = ord($this->indata[1]); 305 | $cm = $cmf & 0x0F; 306 | $cinfo = ($cmf & 0xF0) >> 4; 307 | 308 | // Compression method 'deflate' ($cm = 8), window size - 8 ($cinfo < 8), no preset dictionaries ($flg bit 5), checksum validates. 309 | if ($cm != 8 || $cinfo > 7 || ($flg & 0x20) || (($cmf << 8 | $flg) % 31) != 0) $this->options["type"] = "ignore"; 310 | else 311 | { 312 | $this->indata = substr($this->indata, 2); 313 | $this->options["header"] = true; 314 | } 315 | } 316 | } 317 | 318 | if ($this->options["header"] && strlen($this->indata) > 4) 319 | { 320 | fwrite($this->fp, substr($this->indata, 0, -4)); 321 | $this->indata = substr($this->indata, -4); 322 | 323 | $this->ProcessOutput(); 324 | } 325 | 326 | if ($final) $this->indata = ""; 327 | } 328 | 329 | if ($this->options["type"] == "raw") 330 | { 331 | fwrite($this->fp, $this->indata); 332 | $this->indata = ""; 333 | 334 | $this->ProcessOutput(); 335 | } 336 | 337 | // Only set when an unrecoverable header error has occurred for gzip or zlib. 338 | if ($this->options["type"] == "ignore") $this->indata = ""; 339 | } 340 | 341 | private function SHL32($num, $bits) 342 | { 343 | if ($bits < 0) $bits = 0; 344 | 345 | return $this->LIM32((int)$num << $bits); 346 | } 347 | 348 | private function LIM32($num) 349 | { 350 | return (int)((int)$num & 0xFFFFFFFF); 351 | } 352 | 353 | private function ADD32($num, $num2) 354 | { 355 | $num = (int)$num; 356 | $num2 = (int)$num2; 357 | $add = ((($num >> 30) & 0x03) + (($num2 >> 30) & 0x03)); 358 | $num = ((int)($num & 0x3FFFFFFF) + (int)($num2 & 0x3FFFFFFF)); 359 | if ($num & 0x40000000) $add++; 360 | $num = (int)(($num & 0x3FFFFFFF) | (($add & 0x03) << 30)); 361 | 362 | return $num; 363 | } 364 | } 365 | ?> -------------------------------------------------------------------------------- /support/support/emulate_curl.php: -------------------------------------------------------------------------------- 1 | "CURLE_OK", 17 | 1 => "CURLE_UNSUPPORTED_PROTOCOL", 18 | 2 => "CURLE_FAILED_INIT", 19 | 3 => "CURLE_URL_MALFORMAT", 20 | 4 => "CURLE_NOT_BUILT_IN", 21 | 5 => "CURLE_COULDNT_RESOLVE_PROXY", 22 | 6 => "CURLE_COULDNT_RESOLVE_HOST", 23 | 7 => "CURLE_COULDNT_CONNECT", 24 | 8 => "CURLE_FTP_WEIRD_SERVER_REPLY", 25 | 9 => "CURLE_REMOTE_ACCESS_DENIED", 26 | 10 => "CURLE_FTP_ACCEPT_FAILED", 27 | 11 => "CURLE_FTP_WEIRD_PASS_REPLY", 28 | 12 => "CURLE_FTP_ACCEPT_TIMEOUT", 29 | 13 => "CURLE_FTP_WEIRD_PASV_REPLY", 30 | 14 => "CURLE_FTP_WEIRD_227_FORMAT", 31 | 15 => "CURLE_FTP_CANT_GET_HOST", 32 | 17 => "CURLE_FTP_COULDNT_SET_TYPE", 33 | 18 => "CURLE_PARTIAL_FILE", 34 | 19 => "CURLE_FTP_COULDNT_RETR_FILE", 35 | 21 => "CURLE_QUOTE_ERROR", 36 | 22 => "CURLE_HTTP_RETURNED_ERROR", 37 | 23 => "CURLE_WRITE_ERROR", 38 | 25 => "CURLE_UPLOAD_FAILED", 39 | 26 => "CURLE_READ_ERROR", 40 | 27 => "CURLE_OUT_OF_MEMORY", 41 | 28 => "CURLE_OPERATION_TIMEDOUT", 42 | 30 => "CURLE_FTP_PORT_FAILED", 43 | 31 => "CURLE_FTP_COULDNT_USE_REST", 44 | 33 => "CURLE_RANGE_ERROR", 45 | 34 => "CURLE_HTTP_POST_ERROR", 46 | 35 => "CURLE_SSL_CONNECT_ERROR", 47 | 36 => "CURLE_BAD_DOWNLOAD_RESUME", 48 | 37 => "CURLE_FILE_COULDNT_READ_FILE", 49 | 38 => "CURLE_LDAP_CANNOT_BIND", 50 | 39 => "CURLE_LDAP_SEARCH_FAILED", 51 | 41 => "CURLE_FUNCTION_NOT_FOUND", 52 | 42 => "CURLE_ABORTED_BY_CALLBACK", 53 | 43 => "CURLE_BAD_FUNCTION_ARGUMENT", 54 | 45 => "CURLE_INTERFACE_FAILED", 55 | 47 => "CURLE_TOO_MANY_REDIRECTS", 56 | 48 => "CURLE_UNKNOWN_OPTION", 57 | 49 => "CURLE_TELNET_OPTION_SYNTAX", 58 | 51 => "CURLE_PEER_FAILED_VERIFICATION", 59 | 52 => "CURLE_GOT_NOTHING", 60 | 53 => "CURLE_SSL_ENGINE_NOTFOUND", 61 | 54 => "CURLE_SSL_ENGINE_SETFAILED", 62 | 55 => "CURLE_SEND_ERROR", 63 | 56 => "CURLE_RECV_ERROR", 64 | 58 => "CURLE_SSL_CERTPROBLEM", 65 | 59 => "CURLE_SSL_CIPHER", 66 | 60 => "CURLE_SSL_CACERT", 67 | 61 => "CURLE_BAD_CONTENT_ENCODING", 68 | 62 => "CURLE_LDAP_INVALID_URL", 69 | 63 => "CURLE_FILESIZE_EXCEEDED", 70 | 64 => "CURLE_USE_SSL_FAILED", 71 | 65 => "CURLE_SEND_FAIL_REWIND", 72 | 66 => "CURLE_SSL_ENGINE_INITFAILED", 73 | 67 => "CURLE_LOGIN_DENIED", 74 | 68 => "CURLE_TFTP_NOTFOUND", 75 | 69 => "CURLE_TFTP_PERM", 76 | 70 => "CURLE_REMOTE_DISK_FULL", 77 | 71 => "CURLE_TFTP_ILLEGAL", 78 | 72 => "CURLE_TFTP_UNKNOWNID", 79 | 73 => "CURLE_REMOTE_FILE_EXISTS", 80 | 74 => "CURLE_TFTP_NOSUCHUSER", 81 | 75 => "CURLE_CONV_FAILED", 82 | 76 => "CURLE_CONV_REQD", 83 | 77 => "CURLE_SSL_CACERT_BADFILE", 84 | 78 => "CURLE_REMOTE_FILE_NOT_FOUND", 85 | 79 => "CURLE_SSH", 86 | 80 => "CURLE_SSL_SHUTDOWN_FAILED", 87 | 81 => "CURLE_AGAIN", 88 | 82 => "CURLE_SSL_CRL_BADFILE", 89 | 83 => "CURLE_SSL_ISSUER_ERROR", 90 | 84 => "CURLE_FTP_PRET_FAILED", 91 | 85 => "CURLE_RTSP_CSEQ_ERROR", 92 | 86 => "CURLE_RTSP_SESSION_ERROR", 93 | 87 => "CURLE_FTP_BAD_FILE_LIST", 94 | 88 => "CURLE_CHUNK_FAILED", 95 | ); 96 | 97 | // Define constants in the same order as the official PHP cURL extension with the same integer values. 98 | // Additional defines exist in some locations because they will likely be defined in a future version of PHP. 99 | // DO NOT rely on these constants existing in the official PHP extension! 100 | 101 | // Constants for curl_setopt(). 102 | define("CURLOPT_IPRESOLVE", 113); 103 | define("CURL_IPRESOLVE_WHATEVER", 0); 104 | define("CURL_IPRESOLVE_V4", 1); 105 | define("CURL_IPRESOLVE_V6", 2); 106 | define("CURLOPT_DNS_USE_GLOBAL_CACHE", 91); // DEPRECATED, do not use! 107 | define("CURLOPT_DNS_CACHE_TIMEOUT", 92); 108 | define("CURLOPT_PORT", 3); 109 | define("CURLOPT_FILE", 10001); 110 | define("CURLOPT_READDATA", 10009); 111 | define("CURLOPT_INFILE", 10009); 112 | define("CURLOPT_INFILESIZE", 14); 113 | define("CURLOPT_URL", 10002); 114 | define("CURLOPT_PROXY", 10004); 115 | define("CURLOPT_VERBOSE", 41); 116 | define("CURLOPT_HEADER", 42); 117 | define("CURLOPT_HTTPHEADER", 10023); 118 | define("CURLOPT_NOPROGRESS", 43); 119 | define("CURLOPT_PROGRESSFUNCTION", 20056); 120 | define("CURLOPT_NOBODY", 44); 121 | define("CURLOPT_FAILONERROR", 45); 122 | define("CURLOPT_UPLOAD", 46); 123 | define("CURLOPT_POST", 47); 124 | define("CURLOPT_FTPLISTONLY", 48); 125 | define("CURLOPT_FTPAPPEND", 50); 126 | define("CURLOPT_NETRC", 51); 127 | define("CURLOPT_FOLLOWLOCATION", 52); 128 | define("CURLOPT_PUT", 54); 129 | define("CURLOPT_USERPWD", 10005); 130 | define("CURLOPT_PROXYUSERPWD", 10006); 131 | define("CURLOPT_RANGE", 10007); 132 | define("CURLOPT_TIMEOUT", 13); 133 | define("CURLOPT_TIMEOUT_MS", 155); 134 | define("CURLOPT_POSTFIELDS", 10015); 135 | define("CURLOPT_REFERER", 10016); 136 | define("CURLOPT_USERAGENT", 10018); 137 | define("CURLOPT_FTPPORT", 10017); 138 | define("CURLOPT_FTP_USE_EPSV", 85); 139 | define("CURLOPT_LOW_SPEED_LIMIT", 19); 140 | define("CURLOPT_LOW_SPEED_TIME", 20); 141 | define("CURLOPT_RESUME_FROM", 21); 142 | define("CURLOPT_COOKIE", 10022); 143 | define("CURLOPT_COOKIESESSION", 96); 144 | define("CURLOPT_AUTOREFERER", 58); 145 | define("CURLOPT_SSLCERT", 10025); 146 | define("CURLOPT_SSLCERTPASSWD", 10026); 147 | define("CURLOPT_WRITEHEADER", 10029); 148 | define("CURLOPT_SSL_VERIFYHOST", 81); 149 | define("CURLOPT_COOKIEFILE", 10031); 150 | define("CURLOPT_SSLVERSION", 32); 151 | define("CURLOPT_TIMECONDITION", 33); 152 | define("CURLOPT_TIMEVALUE", 34); 153 | define("CURLOPT_CUSTOMREQUEST", 10036); 154 | define("CURLOPT_STDERR", 10037); 155 | define("CURLOPT_TRANSFERTEXT", 53); 156 | define("CURLOPT_RETURNTRANSFER", 19913); 157 | define("CURLOPT_QUOTE", 10028); 158 | define("CURLOPT_POSTQUOTE", 10039); 159 | define("CURLOPT_INTERFACE", 10062); 160 | define("CURLOPT_KRB4LEVEL", 10063); 161 | define("CURLOPT_HTTPPROXYTUNNEL", 61); 162 | define("CURLOPT_FILETIME", 69); 163 | define("CURLOPT_WRITEFUNCTION", 20011); 164 | define("CURLOPT_READFUNCTION", 20012); 165 | define("CURLOPT_HEADERFUNCTION", 20079); 166 | define("CURLOPT_MAXREDIRS", 68); 167 | define("CURLOPT_MAXCONNECTS", 71); 168 | define("CURLOPT_CLOSEPOLICY", 72); 169 | define("CURLOPT_FRESH_CONNECT", 74); 170 | define("CURLOPT_FORBID_REUSE", 75); 171 | define("CURLOPT_RANDOM_FILE", 10076); 172 | define("CURLOPT_EGDSOCKET", 10077); 173 | define("CURLOPT_CONNECTTIMEOUT", 78); 174 | define("CURLOPT_CONNECTTIMEOUT_MS", 156); 175 | define("CURLOPT_SSL_VERIFYPEER", 64); 176 | define("CURLOPT_CAINFO", 10065); 177 | define("CURLOPT_CAPATH", 10097); 178 | define("CURLOPT_COOKIEJAR", 10082); 179 | define("CURLOPT_SSL_CIPHER_LIST", 10083); 180 | define("CURLOPT_BINARYTRANSFER", 19914); 181 | define("CURLOPT_NOSIGNAL", 99); 182 | define("CURLOPT_PROXYTYPE", 101); 183 | define("CURLOPT_BUFFERSIZE", 98); 184 | define("CURLOPT_HTTPGET", 80); 185 | define("CURLOPT_HTTP_VERSION", 84); 186 | define("CURLOPT_SSLKEY", 10087); 187 | define("CURLOPT_SSLKEYTYPE", 10088); 188 | define("CURLOPT_SSLKEYPASSWD", 10026); 189 | define("CURLOPT_SSLENGINE", 10089); 190 | define("CURLOPT_SSLENGINE_DEFAULT", 90); 191 | define("CURLOPT_SSLCERTTYPE", 10086); 192 | define("CURLOPT_CRLF", 27); 193 | define("CURLOPT_ENCODING", 10102); 194 | define("CURLOPT_PROXYPORT", 59); 195 | define("CURLOPT_UNRESTRICTED_AUTH", 105); 196 | define("CURLOPT_FTP_USE_EPRT", 106); 197 | define("CURLOPT_TCP_NODELAY", 121); 198 | define("CURLOPT_HTTP200ALIASES", 10104); 199 | define("CURL_TIMECOND_NONE", 0); 200 | define("CURL_TIMECOND_IFMODSINCE", 1); 201 | define("CURL_TIMECOND_IFUNMODSINCE", 2); 202 | define("CURL_TIMECOND_LASTMOD", 3); 203 | define("CURLOPT_MAX_RECV_SPEED_LARGE", 30146); 204 | define("CURLOPT_MAX_SEND_SPEED_LARGE", 30145); 205 | define("CURLOPT_HTTPAUTH", 107); 206 | define("CURLAUTH_NONE", 0); 207 | define("CURLAUTH_BASIC", 1); 208 | define("CURLAUTH_DIGEST", 2); 209 | define("CURLAUTH_GSSNEGOTIATE", 4); 210 | define("CURLAUTH_NTLM", 8); 211 | define("CURLAUTH_DIGEST_IE", 16); 212 | define("CURLAUTH_NTLM_WB", 32); 213 | define("CURLAUTH_ANY", -17); 214 | define("CURLAUTH_ANYSAFE", -18); 215 | define("CURLOPT_PROXYAUTH", 111); 216 | define("CURLOPT_FTP_CREATE_MISSING_DIRS", 110); 217 | define("CURLOPT_PRIVATE", 10103); 218 | 219 | // Constants effecting the way CURLOPT_CLOSEPOLICY works. 220 | define("CURLCLOSEPOLICY_LEAST_RECENTLY_USED", 2); 221 | define("CURLCLOSEPOLICY_LEAST_TRAFFIC", 3); 222 | define("CURLCLOSEPOLICY_SLOWEST", 4); 223 | define("CURLCLOSEPOLICY_CALLBACK", 5); 224 | define("CURLCLOSEPOLICY_OLDEST", 1); 225 | 226 | // Info constants. 227 | define("CURLINFO_EFFECTIVE_URL", 0x100000 + 1); 228 | define("CURLINFO_HTTP_CODE", 0x200000 + 2); 229 | define("CURLINFO_RESPONSE_CODE", 0x200000 + 2); 230 | define("CURLINFO_HEADER_SIZE", 0x200000 + 11); 231 | define("CURLINFO_REQUEST_SIZE", 0x200000 + 12); 232 | define("CURLINFO_TOTAL_TIME", 0x300000 + 3); 233 | define("CURLINFO_NAMELOOKUP_TIME", 0x300000 + 4); 234 | define("CURLINFO_CONNECT_TIME", 0x300000 + 5); 235 | define("CURLINFO_PRETRANSFER_TIME", 0x300000 + 6); 236 | define("CURLINFO_SIZE_UPLOAD", 0x300000 + 7); 237 | define("CURLINFO_SIZE_DOWNLOAD", 0x300000 + 8); 238 | define("CURLINFO_SPEED_DOWNLOAD", 0x300000 + 9); 239 | define("CURLINFO_SPEED_UPLOAD", 0x300000 + 10); 240 | define("CURLINFO_FILETIME", 0x200000 + 14); 241 | define("CURLINFO_SSL_VERIFYRESULT", 0x200000 + 14); 242 | define("CURLINFO_CONTENT_LENGTH_DOWNLOAD", 0x300000 + 15); 243 | define("CURLINFO_CONTENT_LENGTH_UPLOAD", 0x300000 + 16); 244 | define("CURLINFO_STARTTRANSFER_TIME", 0x300000 + 17); 245 | define("CURLINFO_CONTENT_TYPE", 0x100000 + 18); 246 | define("CURLINFO_REDIRECT_TIME", 0x300000 + 19); 247 | define("CURLINFO_REDIRECT_COUNT", 0x200000 + 20); 248 | define("CURLINFO_HEADER_OUT", 2); 249 | define("CURLINFO_PRIVATE", 0x100000 + 21); 250 | define("CURLINFO_CERTINFO", 0x400000 + 34); 251 | define("CURLINFO_REDIRECT_URL", 0x100000 + 31); 252 | 253 | // cURL compile-time constants (curl_version). 254 | define("CURL_VERSION_IPV6", 1); 255 | define("CURL_VERSION_KERBEROS4", 2); 256 | define("CURL_VERSION_SSL", 4); 257 | define("CURL_VERSION_LIBZ", 8); 258 | define("CURL_VERSION_NTLM", 16); 259 | define("CURL_VERSION_GSSNEGOTIATE", 32); 260 | define("CURL_VERSION_DEBUG", 64); 261 | define("CURL_VERSION_ASYNCHDNS", 128); 262 | define("CURL_VERSION_SPNEGO", 256); 263 | define("CURL_VERSION_LARGEFILE", 512); 264 | define("CURL_VERSION_IDN", 1024); 265 | define("CURL_VERSION_SSPI", 2048); 266 | define("CURL_VERSION_CONV", 4096); 267 | define("CURL_VERSION_CURLDEBUG", 8192); 268 | define("CURL_VERSION_TLSAUTH_SRP", 16384); 269 | define("CURL_VERSION_NTLM_WB", 32768); 270 | 271 | // Version constants. 272 | define("CURLVERSION_NOW", 3); 273 | 274 | // Error constants. 275 | foreach ($curl_error__map as $num => $name) 276 | { 277 | if (!defined($name)) define($name, $num); 278 | } 279 | 280 | // Dear PHP devs: Comment your code. Thanks. 281 | define("CURLPROXY_HTTP", 0); 282 | define("CURLPROXY_HTTP_1_0", 1); 283 | define("CURLPROXY_SOCKS4", 4); 284 | define("CURLPROXY_SOCKS5", 5); 285 | define("CURLPROXY_SOCKS4A", 6); 286 | define("CURLPROXY_SOCKS5_HOSTNAME", 7); 287 | 288 | define("CURL_NETRC_OPTIONAL", 1); 289 | define("CURL_NETRC_IGNORED", 0); 290 | define("CURL_NETRC_REQUIRED", 2); 291 | 292 | define("CURL_HTTP_VERSION_NONE", 0); 293 | define("CURL_HTTP_VERSION_1_0", 1); 294 | define("CURL_HTTP_VERSION_1_1", 2); 295 | 296 | define("CURLM_CALL_MULTI_PERFORM", -1); 297 | define("CURLM_OK", 0); 298 | define("CURLM_BAD_HANDLE", 1); 299 | define("CURLM_BAD_EASY_HANDLE", 2); 300 | define("CURLM_OUT_OF_MEMORY", 3); 301 | define("CURLM_INTERNAL_ERROR", 4); 302 | define("CURLM_BAD_SOCKET", 5); 303 | define("CURLM_UNKNOWN_OPTION", 6); 304 | 305 | define("CURLMSG_DONE", 1); 306 | 307 | define("CURLOPT_FTPSSLAUTH", 129); 308 | define("CURLFTPAUTH_DEFAULT", 0); 309 | define("CURLFTPAUTH_SSL", 1); 310 | define("CURLFTPAUTH_TLS", 2); 311 | define("CURLOPT_FTP_SSL", 119); 312 | define("CURLFTPSSL_NONE", 0); 313 | define("CURLFTPSSL_TRY", 1); 314 | define("CURLFTPSSL_CONTROL", 2); 315 | define("CURLFTPSSL_ALL", 3); 316 | define("CURLUSESSL_NONE", 0); 317 | define("CURLUSESSL_TRY", 1); 318 | define("CURLUSESSL_CONTROL", 2); 319 | define("CURLUSESSL_ALL", 3); 320 | 321 | define("CURLOPT_CERTINFO", 172); 322 | define("CURLOPT_POSTREDIR", 161); 323 | 324 | define("CURLSSH_AUTH_ANY", -1); 325 | define("CURLSSH_AUTH_NONE", 0); 326 | define("CURLSSH_AUTH_PUBLICKEY", 1); 327 | define("CURLSSH_AUTH_PASSWORD", 2); 328 | define("CURLSSH_AUTH_HOST", 4); 329 | define("CURLSSH_AUTH_KEYBOARD", 8); 330 | define("CURLSSH_AUTH_DEFAULT", -1); 331 | define("CURLOPT_SSH_AUTH_TYPES", 151); 332 | define("CURLOPT_KEYPASSWD", 10026); 333 | define("CURLOPT_SSH_PUBLIC_KEYFILE", 10152); 334 | define("CURLOPT_SSH_PRIVATE_KEYFILE", 10153); 335 | define("CURLOPT_SSH_HOST_PUBLIC_KEY_MD5", 10162); 336 | 337 | define("CURLOPT_REDIR_PROTOCOLS", 182); 338 | define("CURLOPT_PROTOCOLS", 181); 339 | define("CURLPROTO_HTTP", 1); 340 | define("CURLPROTO_HTTPS", 2); 341 | define("CURLPROTO_FTP", 4); 342 | define("CURLPROTO_FTPS", 8); 343 | define("CURLPROTO_SCP", 16); 344 | define("CURLPROTO_SFTP", 32); 345 | define("CURLPROTO_TELNET", 64); 346 | define("CURLPROTO_LDAP", 128); 347 | define("CURLPROTO_LDAPS", 256); 348 | define("CURLPROTO_DICT", 512); 349 | define("CURLPROTO_FILE", 1024); 350 | define("CURLPROTO_TFTP", 2048); 351 | define("CURLPROTO_ALL", -1); 352 | 353 | define("CURLOPT_FTP_FILEMETHOD", 138); 354 | define("CURLOPT_FTP_SKIP_PASV_IP", 137); 355 | 356 | define("CURLFTPMETHOD_DEFAULT", 0); 357 | define("CURLFTPMETHOD_MULTICWD", 1); 358 | define("CURLFTPMETHOD_NOCWD", 2); 359 | define("CURLFTPMETHOD_SINGLECWD", 3); 360 | 361 | // Emulation internal use ONLY. DO NOT USE! 362 | define("CURLOPT_DEBUGFUNCTION", 20094); 363 | define("CURLOPT_DEBUGDATA", 10095); 364 | 365 | // Internal functions used by the public emulation routines. 366 | $curl_init__map = array(); 367 | function get_curl_init_key($ch) 368 | { 369 | ob_start(); 370 | echo $ch; 371 | ob_end_clean(); 372 | 373 | return ob_get_contents(); 374 | } 375 | 376 | function get_check_curl_init_key($ch) 377 | { 378 | global $curl_init__map; 379 | 380 | $key = get_curl_init_key($ch); 381 | if (!isset($curl_init__map[$key])) throw new Exception(HTTP::HTTPTranslate("cURL Emulator: Unable to find key mapping for resource.")); 382 | 383 | return $key; 384 | } 385 | 386 | // Public emulation functions. 387 | function curl_version($age = CURLVERSION_NOW) 388 | { 389 | $curlversion = "7.25.0"; 390 | $curlvernum = explode(".", $curlversion); 391 | 392 | $result = array( 393 | "version_number" => (($curlvernum[0] << 16) | ($curlvernum[1] << 8) | $curlvernum[2]), 394 | "age" => $age, 395 | "features" => CURL_VERSION_IPV6 | (defined("OPENSSL_VERSION_TEXT") ? CURL_VERSION_SSL : 0) | CURL_VERSION_DEBUG | CURL_VERSION_CURLDEBUG | CURL_VERSION_LARGEFILE | CURL_VERSION_IDN | CURL_VERSION_CONV, 396 | "ssl_version_number" => 0, 397 | "version" => $curlversion, 398 | "host" => "i386-pc-win32", 399 | "ssl_version" => (defined("OPENSSL_VERSION_TEXT") ? implode("/", array_slice(explode(" ", OPENSSL_VERSION_TEXT), 0, 2)) : ""), 400 | "libz_version" => "", 401 | "protocols" => array("http", "https") 402 | ); 403 | 404 | return $result; 405 | } 406 | 407 | function curl_init($url = false) 408 | { 409 | global $curl_init__map; 410 | 411 | // Evil hack to create a "resource" so that is_resource() works. 412 | // get_resource_type() will reveal its true identity but only an idiot would ever call that function. 413 | $ch = fopen(__FILE__, "rb"); 414 | $key = get_curl_init_key($ch); 415 | $options = array( 416 | CURLOPT_NOPROGRESS => true, 417 | CURLOPT_VERBOSE => false, 418 | CURLOPT_DNS_USE_GLOBAL_CACHE => true, 419 | CURLOPT_DNS_CACHE_TIMEOUT => 120, 420 | CURLOPT_MAXREDIRS => 20, 421 | CURLOPT_URL => $url 422 | ); 423 | 424 | if (!class_exists("WebBrowser", false)) require_once str_replace("\\", "/", dirname(__FILE__)) . "/web_browser.php"; 425 | 426 | $curl_init__map[$key] = array("self" => $ch, "method" => "GET", "options" => $options, "browser" => new WebBrowser(), "errorno" => CURLE_OK, "errorinfo" => ""); 427 | 428 | return $ch; 429 | } 430 | 431 | function curl_errno($ch) 432 | { 433 | global $curl_init__map; 434 | 435 | $key = get_check_curl_init_key($ch); 436 | 437 | return $curl_init__map[$key]["errorno"]; 438 | } 439 | 440 | function curl_error($ch) 441 | { 442 | global $curl_init__map, $curl_error__map; 443 | 444 | $key = get_check_curl_init_key($ch); 445 | 446 | return ($curl_init__map[$key]["errorinfo"] == "" ? "" : $curl_error__map[$curl_init__map[$key]["errorno"]] . " - " . $curl_init__map[$key]["errorinfo"]); 447 | } 448 | 449 | function curl_copy_handle($ch) 450 | { 451 | global $curl_init__map; 452 | 453 | $key = get_check_curl_init_key($ch); 454 | 455 | $ch = fopen(__FILE__, "rb"); 456 | $key2 = get_curl_init_key($ch); 457 | $curl_init__map[$key2] = $curl_init__map[$key]; 458 | 459 | return $ch; 460 | } 461 | 462 | function curl_close($ch) 463 | { 464 | global $curl_init__map; 465 | 466 | $key = get_check_curl_init_key($ch); 467 | unset($curl_init__map[$key]); 468 | fclose($ch); 469 | } 470 | 471 | function curl_setopt($ch, $option, $value) 472 | { 473 | global $curl_init__map; 474 | 475 | $key = get_check_curl_init_key($ch); 476 | 477 | if ($option != CURLINFO_HEADER_OUT) 478 | { 479 | if ($value === null) unset($curl_init__map[$key]["options"][$option]); 480 | else 481 | { 482 | if ($option == CURLOPT_HTTPGET && $value) $curl_init__map[$key]["method"] = "GET"; 483 | else if ($option == CURLOPT_NOBODY && $value) $curl_init__map[$key]["method"] = "HEAD"; 484 | else if ($option == CURLOPT_POST && $value) $curl_init__map[$key]["method"] = "POST"; 485 | else if ($option == CURLOPT_PUT && $value) $curl_init__map[$key]["method"] = "PUT"; 486 | else if ($option == CURLOPT_CUSTOMREQUEST) $curl_init__map[$key]["method"] = $value; 487 | 488 | $curl_init__map[$key]["options"][$option] = $value; 489 | } 490 | } 491 | else if ((bool)$value) 492 | { 493 | $curl_init__map[$key]["options"]["__CURLINFO_HEADER_OUT"] = true; 494 | } 495 | else 496 | { 497 | unset($curl_init__map[$key]["options"]["__CURLINFO_HEADER_OUT"]); 498 | } 499 | 500 | $curl_init__map[$key]["errorno"] = CURLE_OK; 501 | $curl_init__map[$key]["errorinfo"] = ""; 502 | 503 | return true; 504 | } 505 | 506 | function curl_setopt_array($ch, $options) 507 | { 508 | foreach ($options as $option => $value) 509 | { 510 | if (!curl_setopt($ch, $option, $value)) return false; 511 | } 512 | 513 | return true; 514 | } 515 | 516 | function curl_exec($ch) 517 | { 518 | global $curl_init__map; 519 | 520 | $key = get_check_curl_init_key($ch); 521 | 522 | // Set allowed protocols. 523 | $allowedprotocols = array("http" => true, "https" => true); 524 | if (isset($curl_init__map[$key]["options"][CURLOPT_PROTOCOLS])) 525 | { 526 | $allowedprotocols["http"] = (bool)($curl_init__map[$key]["options"][CURLOPT_PROTOCOLS] & CURLPROTO_HTTP); 527 | $allowedprotocols["https"] = (bool)($curl_init__map[$key]["options"][CURLOPT_PROTOCOLS] & CURLPROTO_HTTPS); 528 | } 529 | $curl_init__map[$key]["browser"]->SetState(array("allowedprotocols" => $allowedprotocols)); 530 | 531 | // Set allowed redirect protocols. 532 | $allowedprotocols = array("http" => true, "https" => true); 533 | if (isset($curl_init__map[$key]["options"][CURLOPT_REDIR_PROTOCOLS])) 534 | { 535 | $allowedprotocols["http"] = (bool)($curl_init__map[$key]["options"][CURLOPT_REDIR_PROTOCOLS] & CURLPROTO_HTTP); 536 | $allowedprotocols["https"] = (bool)($curl_init__map[$key]["options"][CURLOPT_REDIR_PROTOCOLS] & CURLPROTO_HTTPS); 537 | } 538 | $curl_init__map[$key]["browser"]->SetState(array("allowedredirprotocols" => $allowedprotocols)); 539 | 540 | // Load cookies. Violates the PHP/cURL definition a lot. Whatever. 541 | if (isset($curl_init__map[$key]["options"][CURLOPT_COOKIEFILE]) && is_string($curl_init__map[$key]["options"][CURLOPT_COOKIEFILE]) && $curl_init__map[$key]["options"][CURLOPT_COOKIEFILE] != "") 542 | { 543 | $data = @unserialize(@file_get_contents($curl_init__map[$key]["options"][CURLOPT_COOKIEFILE])); 544 | if ($data !== false && is_array($data)) 545 | { 546 | // Load the WebBrowser() object with the cookies. 547 | $curl_init__map[$key]["browser"]->SetState(array("cookies" => $data)); 548 | } 549 | $curl_init__map[$key]["options"][CURLOPT_COOKIEFILE] = ""; 550 | } 551 | if (isset($curl_init__map[$key]["options"][CURLOPT_COOKIESESSION]) && $curl_init__map[$key]["options"][CURLOPT_COOKIESESSION]) $curl_init__map[$key]["browser"]->DeleteSessionCookies(); 552 | 553 | // Set the autoreferer setting. 554 | $curl_init__map[$key]["browser"]->SetState(array("autoreferer" => (isset($curl_init__map[$key]["options"][CURLOPT_AUTOREFERER]) && $curl_init__map[$key]["options"][CURLOPT_AUTOREFERER]))); 555 | 556 | // Set the Referer. 557 | if (isset($curl_init__map[$key]["options"][CURLOPT_REFERER]) && is_string($curl_init__map[$key]["options"][CURLOPT_REFERER])) 558 | { 559 | $curl_init__map[$key]["browser"]->SetState(array("referer" => $curl_init__map[$key]["options"][CURLOPT_REFERER])); 560 | } 561 | 562 | // Set the followlocation and maxfollow settings. 563 | $curl_init__map[$key]["browser"]->SetState(array("followlocation" => (isset($curl_init__map[$key]["options"][CURLOPT_FOLLOWLOCATION]) && $curl_init__map[$key]["options"][CURLOPT_FOLLOWLOCATION]))); 564 | $curl_init__map[$key]["browser"]->SetState(array("maxfollow" => (isset($curl_init__map[$key]["options"][CURLOPT_MAXREDIRS]) ? $curl_init__map[$key]["options"][CURLOPT_MAXREDIRS] : 20))); 565 | 566 | // Set up the options array. 567 | $options = array(); 568 | 569 | // Set connect and total timeout options. 570 | if (isset($curl_init__map[$key]["options"][CURLOPT_CONNECTTIMEOUT]) || isset($curl_init__map[$key]["options"][CURLOPT_CONNECTTIMEOUT_MS])) 571 | { 572 | $timeout = (isset($curl_init__map[$key]["options"][CURLOPT_CONNECTTIMEOUT]) ? $curl_init__map[$key]["options"][CURLOPT_CONNECTTIMEOUT] : 0) + ((isset($curl_init__map[$key]["options"][CURLOPT_CONNECTTIMEOUT_MS]) ? $curl_init__map[$key]["options"][CURLOPT_CONNECTTIMEOUT_MS] : 0) / 1000); 573 | if ($timeout > 0) 574 | { 575 | $options["connecttimeout"] = $timeout; 576 | $options["proxyconnecttimeout"] = $timeout; 577 | } 578 | } 579 | if (isset($curl_init__map[$key]["options"][CURLOPT_TIMEOUT]) || isset($curl_init__map[$key]["options"][CURLOPT_TIMEOUT_MS])) 580 | { 581 | $timeout = (isset($curl_init__map[$key]["options"][CURLOPT_TIMEOUT]) ? $curl_init__map[$key]["options"][CURLOPT_TIMEOUT] : 0) + ((isset($curl_init__map[$key]["options"][CURLOPT_TIMEOUT_MS]) ? $curl_init__map[$key]["options"][CURLOPT_TIMEOUT_MS] : 0) / 1000); 582 | if ($timeout > 0) 583 | { 584 | $options["connecttimeout"] = $timeout; 585 | $options["proxyconnecttimeout"] = $timeout; 586 | } 587 | } 588 | 589 | // Set proxy options. 590 | if (isset($curl_init__map[$key]["options"][CURLOPT_PROXY])) 591 | { 592 | if (isset($curl_init__map[$key]["options"][CURLOPT_PROXYTYPE]) && $curl_init__map[$key]["options"][CURLOPT_PROXYTYPE] != CURLPROXY_HTTP) 593 | { 594 | $curl_init__map[$key]["errorno"] = CURLE_UNSUPPORTED_PROTOCOL; 595 | $curl_init__map[$key]["errorinfo"] = HTTP::HTTPTranslate("CURLOPT_PROXYTYPE option is unsupported."); 596 | 597 | return false; 598 | } 599 | 600 | $proxyurl = $curl_init__map[$key]["options"][CURLOPT_PROXY]; 601 | $proxyport = (int)(isset($curl_init__map[$key]["options"][CURLOPT_PROXYPORT]) ? $curl_init__map[$key]["options"][CURLOPT_PROXYPORT] : false); 602 | if ($proxyport < 1 || $proxyport > 65535) $proxyport = false; 603 | if (strpos($proxyurl, "://") === false) $proxyurl = ($proxyport == 443 ? "https://" : "http://") . $proxyurl; 604 | 605 | $proxyurl = HTTP::ExtractURL($proxyurl); 606 | if ($proxyport !== false) $proxyurl["port"] = $proxyport; 607 | if (isset($curl_init__map[$key]["options"][CURLOPT_PROXYUSERPWD])) 608 | { 609 | $userpass = explode(":", $curl_init__map[$key]["options"][CURLOPT_PROXYUSERPWD]); 610 | if (count($userpass) == 2) 611 | { 612 | $proxyurl["loginusername"] = urldecode($userpass[0]); 613 | $proxyurl["loginpassword"] = urldecode($userpass[1]); 614 | } 615 | } 616 | $options["proxyurl"] = HTTP::CondenseURL($proxyurl); 617 | 618 | if (isset($curl_init__map[$key]["options"][CURLOPT_HTTPPROXYTUNNEL])) $options["proxyconnect"] = $curl_init__map[$key]["options"][CURLOPT_HTTPPROXYTUNNEL]; 619 | } 620 | 621 | // Set SSL options. 622 | $options["sslopts"] = array(); 623 | $options["sslopts"]["verify_peer"] = (isset($curl_init__map[$key]["options"][CURLOPT_SSL_VERIFYPEER]) ? $curl_init__map[$key]["options"][CURLOPT_SSL_VERIFYPEER] : true); 624 | if (isset($curl_init__map[$key]["options"][CURLOPT_CAINFO])) $options["sslopts"]["cafile"] = $curl_init__map[$key]["options"][CURLOPT_CAINFO]; 625 | if (isset($curl_init__map[$key]["options"][CURLOPT_CAPATH])) $options["sslopts"]["capath"] = $curl_init__map[$key]["options"][CURLOPT_CAPATH]; 626 | if (!isset($options["sslopts"]["cafile"]) && !isset($options["sslopts"]["capath"])) $options["sslopts"]["auto_cainfo"] = true; 627 | if (isset($curl_init__map[$key]["options"][CURLOPT_SSLCERT]) && isset($curl_init__map[$key]["options"][CURLOPT_SSLKEY])) 628 | { 629 | if ($curl_init__map[$key]["options"][CURLOPT_SSLCERT] !== $curl_init__map[$key]["options"][CURLOPT_SSLKEY]) 630 | { 631 | $curl_init__map[$key]["errorno"] = CURLE_SSL_CONNECT_ERROR; 632 | $curl_init__map[$key]["errorinfo"] = HTTP::HTTPTranslate("CURLOPT_SSLCERT and CURLOPT_SSLKEY must be identical."); 633 | 634 | return false; 635 | } 636 | $certpass = (isset($curl_init__map[$key]["options"][CURLOPT_SSLCERTPASSWD]) ? $curl_init__map[$key]["options"][CURLOPT_SSLCERTPASSWD] : false); 637 | $keypass = (isset($curl_init__map[$key]["options"][CURLOPT_SSLKEYPASSWD]) ? $curl_init__map[$key]["options"][CURLOPT_SSLKEYPASSWD] : false); 638 | if ($certpass !== $keypass) 639 | { 640 | $curl_init__map[$key]["errorno"] = CURLE_SSL_CONNECT_ERROR; 641 | $curl_init__map[$key]["errorinfo"] = HTTP::HTTPTranslate("CURLOPT_SSLCERTPASSWD and CURLOPT_SSLKEYPASSWD must be identical."); 642 | 643 | return false; 644 | } 645 | $certtype = strtoupper(isset($curl_init__map[$key]["options"][CURLOPT_SSLCERTTYPE]) ? $curl_init__map[$key]["options"][CURLOPT_SSLCERTTYPE] : "PEM"); 646 | $keytype = strtoupper(isset($curl_init__map[$key]["options"][CURLOPT_SSLKEYTYPE]) ? $curl_init__map[$key]["options"][CURLOPT_SSLKEYTYPE] : "PEM"); 647 | if ($certpass !== $keypass || $certtype !== "PEM") 648 | { 649 | $curl_init__map[$key]["errorno"] = CURLE_SSL_CONNECT_ERROR; 650 | $curl_init__map[$key]["errorinfo"] = HTTP::HTTPTranslate("CURLOPT_SSLCERTTYPE and CURLOPT_SSLKEYTYPE must be PEM format."); 651 | 652 | return false; 653 | } 654 | 655 | $options["sslopts"]["local_cert"] = $curl_init__map[$key]["options"][CURLOPT_SSLCERT]; 656 | if ($certpass !== false) $options["sslopts"]["passphrase"] = $certpass; 657 | } 658 | if (isset($curl_init__map[$key]["options"][CURLOPT_SSL_CIPHER_LIST])) $options["sslopts"]["ciphers"] = $curl_init__map[$key]["options"][CURLOPT_SSL_CIPHER_LIST]; 659 | $options["sslopts"]["auto_cn_match"] = true; 660 | $options["sslopts"]["auto_sni"] = true; 661 | $options["sslopts"]["capture_peer_cert"] = (isset($curl_init__map[$key]["options"][CURLOPT_CERTINFO]) ? $curl_init__map[$key]["options"][CURLOPT_CERTINFO] : false); 662 | 663 | // Set the method. 664 | if (isset($curl_init__map[$key]["options"][CURLOPT_UPLOAD]) && (bool)$curl_init__map[$key]["options"][CURLOPT_UPLOAD]) $options["method"] = "PUT"; 665 | else $options["method"] = $curl_init__map[$key]["method"]; 666 | 667 | // Set the HTTP version. 668 | if (isset($curl_init__map[$key]["options"][CURLOPT_HTTP_VERSION])) 669 | { 670 | if ($curl_init__map[$key]["options"][CURLOPT_HTTP_VERSION] == CURL_HTTP_VERSION_1_0) $options["httpver"] = "1.0"; 671 | else if ($curl_init__map[$key]["options"][CURLOPT_HTTP_VERSION] == CURL_HTTP_VERSION_1_1) $options["httpver"] = "1.1"; 672 | } 673 | 674 | // Set rate limits. 675 | if (isset($curl_init__map[$key]["options"][CURLOPT_MAX_RECV_SPEED_LARGE])) $options["recvratelimit"] = $curl_init__map[$key]["options"][CURLOPT_MAX_RECV_SPEED_LARGE]; 676 | if (isset($curl_init__map[$key]["options"][CURLOPT_MAX_SEND_SPEED_LARGE])) $options["sendratelimit"] = $curl_init__map[$key]["options"][CURLOPT_MAX_SEND_SPEED_LARGE]; 677 | 678 | // Set headers. 679 | $options["headers"] = array(); 680 | $options["headers"]["Accept"] = "*/*"; 681 | if (isset($curl_init__map[$key]["options"][CURLOPT_HTTPHEADER]) && is_array($curl_init__map[$key]["options"][CURLOPT_HTTPHEADER])) 682 | { 683 | foreach ($curl_init__map[$key]["options"][CURLOPT_HTTPHEADER] as $header) 684 | { 685 | $pos = strpos($header, ":"); 686 | if ($pos !== false) 687 | { 688 | $val = ltrim(substr($header, $pos + 1)); 689 | if ($val == "") unset($options["headers"][HTTP::HeaderNameCleanup(substr($header, 0, $pos))]); 690 | else $options["headers"][HTTP::HeaderNameCleanup(substr($header, 0, $pos))] = $val; 691 | } 692 | } 693 | } 694 | if (isset($curl_init__map[$key]["options"][CURLOPT_USERAGENT])) $options["headers"]["User-Agent"] = $curl_init__map[$key]["options"][CURLOPT_USERAGENT]; 695 | if (isset($curl_init__map[$key]["options"][CURLOPT_COOKIE])) $options["headers"]["Cookie"] = $curl_init__map[$key]["options"][CURLOPT_COOKIE]; 696 | if (isset($curl_init__map[$key]["options"][CURLOPT_RANGE])) $options["headers"]["Range"] = "bytes=" . $curl_init__map[$key]["options"][CURLOPT_RANGE]; 697 | if (isset($curl_init__map[$key]["options"][CURLOPT_RESUME_FROM])) $options["headers"]["Range"] = "bytes=" . $curl_init__map[$key]["options"][CURLOPT_RESUME_FROM] . "-"; 698 | if (isset($curl_init__map[$key]["options"][CURLOPT_TIMECONDITION]) && isset($curl_init__map[$key]["options"][CURLOPT_TIMEVALUE])) 699 | { 700 | if ($curl_init__map[$key]["options"][CURLOPT_TIMECONDITION] == CURL_TIMECOND_IFMODSINCE) $options["headers"]["If-Modified-Since"] = gmdate("D, d M Y H:i:s", $curl_init__map[$key]["options"][CURLOPT_TIMEVALUE]) . " GMT"; 701 | else if ($curl_init__map[$key]["options"][CURLOPT_TIMECONDITION] == CURL_TIMECOND_IFUNMODSINCE) $options["headers"]["If-Unmodified-Since"] = gmdate("D, d M Y H:i:s", $curl_init__map[$key]["options"][CURLOPT_TIMEVALUE]) . " GMT"; 702 | } 703 | 704 | // Set POST variables and files. 705 | if (isset($curl_init__map[$key]["options"][CURLOPT_POSTFIELDS])) 706 | { 707 | $postvars = $curl_init__map[$key]["options"][CURLOPT_POSTFIELDS]; 708 | if (is_string($postvars)) 709 | { 710 | $postvars2 = array(); 711 | $postvars = explode("&", $postvars); 712 | foreach ($postvars as $postvar) 713 | { 714 | $pos = strpos($postvar, "="); 715 | if ($pos === false) 716 | { 717 | $name = urldecode($postvar); 718 | $val = ""; 719 | } 720 | else 721 | { 722 | $name = urldecode(substr($postvar, 0, $pos)); 723 | $val = urldecode(substr($postvar, $pos + 1)); 724 | } 725 | 726 | if (!isset($postvars2[$name])) $postvars2[$name] = array(); 727 | $postvars2[$name][] = $val; 728 | } 729 | $postvars = $postvars2; 730 | unset($postvars2); 731 | } 732 | 733 | foreach ($postvars as $name => $vals) 734 | { 735 | if (is_string($vals) || is_numeric($vals)) $vals = array($vals); 736 | foreach ($vals as $num => $val) 737 | { 738 | // Move files to their own array. 739 | if (substr($val, 0, 1) == "@") 740 | { 741 | $pos = strrpos($val, ";type="); 742 | if ($pos === false) $mimetype = ""; 743 | else 744 | { 745 | $mimetype = substr($val, $pos + 6); 746 | $val = substr($val, 0, $pos); 747 | } 748 | 749 | $val = substr($val, 1); 750 | if (file_exists($val)) 751 | { 752 | if (!isset($options["files"])) $options["files"] = array(); 753 | $options["files"][] = array( 754 | "name" => $name, 755 | "filename" => HTTP::FilenameSafe(HTTP::ExtractFilename($val)), 756 | "type" => $mimetype, 757 | "datafile" => $val 758 | ); 759 | 760 | unset($vals[$num]); 761 | } 762 | } 763 | } 764 | 765 | if (!count($vals)) unset($postvars[$name]); 766 | else $postvars[$name] = $vals; 767 | } 768 | 769 | $options["postvars"] = $postvars; 770 | $options["method"] = "POST"; 771 | } 772 | 773 | // Process the URL. 774 | if (!isset($curl_init__map[$key]["options"][CURLOPT_URL]) || !is_string($curl_init__map[$key]["options"][CURLOPT_URL]) || $curl_init__map[$key]["options"][CURLOPT_URL] == "") 775 | { 776 | $curl_init__map[$key]["errorno"] = CURLE_URL_MALFORMAT; 777 | $curl_init__map[$key]["errorinfo"] = HTTP::HTTPTranslate("No CURLOPT_URL option specified."); 778 | 779 | return false; 780 | } 781 | $url = HTTP::ExtractURL($curl_init__map[$key]["options"][CURLOPT_URL]); 782 | if ($url["scheme"] == "") 783 | { 784 | $curl_init__map[$key]["errorno"] = CURLE_URL_MALFORMAT; 785 | $curl_init__map[$key]["errorinfo"] = HTTP::HTTPTranslate("CURLOPT_URL does not have a scheme."); 786 | 787 | return false; 788 | } 789 | if ($url["host"] == "") 790 | { 791 | $curl_init__map[$key]["errorno"] = CURLE_URL_MALFORMAT; 792 | $curl_init__map[$key]["errorinfo"] = HTTP::HTTPTranslate("CURLOPT_URL does not specify a valid host."); 793 | 794 | return false; 795 | } 796 | if (isset($curl_init__map[$key]["options"][CURLOPT_PORT]) && (int)$curl_init__map[$key]["options"][CURLOPT_PORT] > 0 && (int)$curl_init__map[$key]["options"][CURLOPT_PORT] < 65536) 797 | { 798 | $url["port"] = (int)$curl_init__map[$key]["options"][CURLOPT_PORT]; 799 | } 800 | if (isset($curl_init__map[$key]["options"][CURLOPT_USERPWD])) 801 | { 802 | $userpass = explode(":", $curl_init__map[$key]["options"][CURLOPT_USERPWD]); 803 | if (count($userpass) == 2) 804 | { 805 | $url["loginusername"] = urldecode($userpass[0]); 806 | $url["loginpassword"] = urldecode($userpass[1]); 807 | } 808 | } 809 | else if (isset($curl_init__map[$key]["options"][CURLOPT_NETRC]) && $curl_init__map[$key]["options"][CURLOPT_NETRC]) 810 | { 811 | $data = @file_get_contents("~/.netrc"); 812 | if ($data !== false) 813 | { 814 | $lines = explode("\n", $data); 815 | unset($data); 816 | $host = false; 817 | $user = false; 818 | $password = false; 819 | foreach ($lines as $line) 820 | { 821 | $line = trim($line); 822 | if (substr($line, 0, 8) == "machine ") $host = trim(substr($line, 8)); 823 | if (substr($line, 0, 6) == "login ") $user = trim(substr($line, 6)); 824 | if (substr($line, 0, 9) == "password ") $password = trim(substr($line, 9)); 825 | 826 | if ($host !== false && $user !== false && $password !== false) 827 | { 828 | if ($host === $url["host"] || (isset($options["headers"]["Host"]) && $host === $options["headers"]["Host"])) 829 | { 830 | $url["loginusername"] = $user; 831 | $url["loginpassword"] = $password; 832 | } 833 | 834 | $host = false; 835 | $user = false; 836 | $password = false; 837 | } 838 | } 839 | unset($lines); 840 | } 841 | } 842 | 843 | // Condense URL. 844 | $url = HTTP::CondenseURL($url); 845 | 846 | // Set up internal callbacks. 847 | $options["read_headers_callback"] = "internal_curl_read_headers_callback"; 848 | $options["read_headers_callback_opts"] = $key; 849 | 850 | if (!isset($curl_init__map[$key]["options"][CURLOPT_NOBODY]) || !$curl_init__map[$key]["options"][CURLOPT_NOBODY]) 851 | { 852 | $options["read_body_callback"] = "internal_curl_read_body_callback"; 853 | $options["read_body_callback_opts"] = $key; 854 | } 855 | 856 | if ($options["method"] != "GET" && $options["method"] != "POST") 857 | { 858 | $options["write_body_callback"] = "internal_curl_write_body_callback"; 859 | $options["write_body_callback_opts"] = $key; 860 | } 861 | 862 | $options["debug_callback"] = "internal_curl_debug_callback"; 863 | $options["debug_callback_opts"] = $key; 864 | 865 | // Remove weird callback results. 866 | unset($curl_init__map[$key]["rawproxyheaders"]); 867 | unset($curl_init__map[$key]["rawheaders"]); 868 | unset($curl_init__map[$key]["returnresponse"]); 869 | unset($curl_init__map[$key]["returnheader"]); 870 | unset($curl_init__map[$key]["returnbody"]); 871 | unset($curl_init__map[$key]["filetime"]); 872 | $curl_init__map[$key]["outputbody"] = false; 873 | 874 | // Process the request. 875 | $options["profile"] = ""; 876 | $result = $curl_init__map[$key]["browser"]->Process($url, $options); 877 | $curl_init__map[$key]["lastresult"] = $result; 878 | 879 | // Deal with cookies. 880 | if (!isset($curl_init__map[$key]["options"][CURLOPT_COOKIEFILE]) || !is_string($curl_init__map[$key]["options"][CURLOPT_COOKIEFILE])) 881 | { 882 | // Delete all cookies for another run later. 883 | $curl_init__map[$key]["browser"]->SetState(array("cookies" => array())); 884 | } 885 | else if (isset($curl_init__map[$key]["options"][CURLOPT_COOKIEJAR])) 886 | { 887 | // Write out cookies here. Another violation of how cURL does things. Another - whatever. 888 | $state = $curl_init__map[$key]["browser"]->GetState(); 889 | file_put_contents($curl_init__map[$key]["options"][CURLOPT_COOKIEJAR], serialize($state["cookies"])); 890 | } 891 | 892 | // Process the response. 893 | if (!$result["success"]) 894 | { 895 | if ($result["errorcode"] == "allowed_protocols") 896 | { 897 | $curl_init__map[$key]["errorno"] = CURLE_UNSUPPORTED_PROTOCOL; 898 | $curl_init__map[$key]["errorinfo"] = HTTP::HTTPTranslate("The cURL emulation layer does not support the protocol or was redirected to an unsupported protocol by the host. %s", $result["error"]); 899 | } 900 | else if ($result["errorcode"] == "allowed_redir_protocols") 901 | { 902 | $curl_init__map[$key]["errorno"] = CURLE_UNSUPPORTED_PROTOCOL; 903 | $curl_init__map[$key]["errorinfo"] = HTTP::HTTPTranslate("The cURL emulation layer was redirected to an unsupported protocol by the host. %s", $result["error"]); 904 | } 905 | else if ($result["errorcode"] == "retrievewebpage") 906 | { 907 | if ($result["info"]["errorcode"] == "timeout_exceeded") 908 | { 909 | $curl_init__map[$key]["errorno"] = CURLE_OPERATION_TIMEDOUT; 910 | $curl_init__map[$key]["errorinfo"] = HTTP::HTTPTranslate("The operation timed out. %s", $result["error"]); 911 | } 912 | else if ($result["info"]["errorcode"] == "get_response_line") 913 | { 914 | $curl_init__map[$key]["errorno"] = CURLE_READ_ERROR; 915 | $curl_init__map[$key]["errorinfo"] = HTTP::HTTPTranslate("Unable to get the response line. %s", $result["error"]); 916 | } 917 | else if ($result["info"]["errorcode"] == "read_header_callback") 918 | { 919 | $curl_init__map[$key]["errorno"] = CURLE_READ_ERROR; 920 | $curl_init__map[$key]["errorinfo"] = HTTP::HTTPTranslate("A read error occurred in the read header callback. %s", $result["error"]); 921 | } 922 | else if ($result["info"]["errorcode"] == "read_body_callback") 923 | { 924 | $curl_init__map[$key]["errorno"] = CURLE_READ_ERROR; 925 | $curl_init__map[$key]["errorinfo"] = HTTP::HTTPTranslate("A read error occurred in the read body callback. %s", $result["error"]); 926 | } 927 | else if ($result["info"]["errorcode"] == "function_check") 928 | { 929 | $curl_init__map[$key]["errorno"] = CURLE_FUNCTION_NOT_FOUND; 930 | $curl_init__map[$key]["errorinfo"] = HTTP::HTTPTranslate("A required function was not found. %s", $result["error"]); 931 | } 932 | else if ($result["info"]["errorcode"] == "protocol_check") 933 | { 934 | $curl_init__map[$key]["errorno"] = CURLE_UNSUPPORTED_PROTOCOL; 935 | $curl_init__map[$key]["errorinfo"] = HTTP::HTTPTranslate("The cURL emulation layer does not support the protocol or was redirected to an unsupported protocol by the host. %s", $result["error"]); 936 | } 937 | else if ($result["info"]["errorcode"] == "transport_not_installed") 938 | { 939 | $curl_init__map[$key]["errorno"] = CURLE_NOT_BUILT_IN; 940 | $curl_init__map[$key]["errorinfo"] = HTTP::HTTPTranslate("The cURL emulation layer attempted to use a required transport to connect to a host but failed. %s", $result["error"]); 941 | } 942 | else if ($result["info"]["errorcode"] == "proxy_transport_not_installed") 943 | { 944 | $curl_init__map[$key]["errorno"] = CURLE_NOT_BUILT_IN; 945 | $curl_init__map[$key]["errorinfo"] = HTTP::HTTPTranslate("The cURL emulation layer attempted to use a required transport to connect to a proxy but failed. %s", $result["error"]); 946 | } 947 | else if ($result["info"]["errorcode"] == "proxy_connect") 948 | { 949 | $curl_init__map[$key]["errorno"] = CURLE_COULDNT_CONNECT; 950 | $curl_init__map[$key]["errorinfo"] = HTTP::HTTPTranslate("Unable to connect to the proxy. %s", $result["error"]); 951 | } 952 | else if ($result["info"]["errorcode"] == "proxy_connect_tunnel") 953 | { 954 | $curl_init__map[$key]["errorno"] = CURLE_COULDNT_CONNECT; 955 | $curl_init__map[$key]["errorinfo"] = HTTP::HTTPTranslate("Unable to open a tunnel through the connected proxy. %s", $result["error"]); 956 | } 957 | else if ($result["info"]["errorcode"] == "connect_failed") 958 | { 959 | $curl_init__map[$key]["errorno"] = CURLE_COULDNT_CONNECT; 960 | $curl_init__map[$key]["errorinfo"] = HTTP::HTTPTranslate("Unable to connect to the host. %s", $result["error"]); 961 | } 962 | else if ($result["info"]["errorcode"] == "write_body_callback") 963 | { 964 | $curl_init__map[$key]["errorno"] = CURLE_WRITE_ERROR; 965 | $curl_init__map[$key]["errorinfo"] = HTTP::HTTPTranslate("A write error occurred in the write body callback. %s", $result["error"]); 966 | } 967 | else if ($result["info"]["errorcode"] == "file_open") 968 | { 969 | $curl_init__map[$key]["errorno"] = CURLE_FILE_COULDNT_READ_FILE; 970 | $curl_init__map[$key]["errorinfo"] = HTTP::HTTPTranslate("Unable to open file for upload. %s", $result["error"]); 971 | } 972 | else if ($result["info"]["errorcode"] == "file_read") 973 | { 974 | $curl_init__map[$key]["errorno"] = CURLE_READ_ERROR; 975 | $curl_init__map[$key]["errorinfo"] = HTTP::HTTPTranslate("A read error occurred while uploading a file. %s", $result["error"]); 976 | } 977 | else 978 | { 979 | $curl_init__map[$key]["errorno"] = CURLE_HTTP_RETURNED_ERROR; 980 | $curl_init__map[$key]["errorinfo"] = HTTP::HTTPTranslate("An error occurred. %s", $result["error"]); 981 | } 982 | } 983 | 984 | return false; 985 | } 986 | 987 | if (isset($curl_init__map[$key]["returnresponse"]) && $curl_init__map[$key]["returnresponse"]["code"] >= 400 && isset($curl_init__map[$key]["options"][CURLOPT_FAILONERROR]) && $curl_init__map[$key]["options"][CURLOPT_FAILONERROR]) 988 | { 989 | $curl_init__map[$key]["errorno"] = CURLE_HTTP_RETURNED_ERROR; 990 | $curl_init__map[$key]["errorinfo"] = HTTP::HTTPTranslate("A HTTP error occurred. %s", $curl_init__map[$key]["returnresponse"]["line"]); 991 | 992 | return false; 993 | } 994 | 995 | if (isset($curl_init__map[$key]["options"][CURLOPT_FOLLOWLOCATION]) && $curl_init__map[$key]["options"][CURLOPT_FOLLOWLOCATION] && isset($result["headers"]["Location"])) 996 | { 997 | $curl_init__map[$key]["errorno"] = CURLE_TOO_MANY_REDIRECTS; 998 | $curl_init__map[$key]["errorinfo"] = HTTP::HTTPTranslate("Too many redirects took place."); 999 | 1000 | return false; 1001 | } 1002 | 1003 | if (isset($curl_init__map[$key]["options"][CURLOPT_RETURNTRANSFER]) && $curl_init__map[$key]["options"][CURLOPT_RETURNTRANSFER]) 1004 | { 1005 | return (isset($curl_init__map[$key]["returnheader"]) ? $curl_init__map[$key]["returnheader"] . "\r\n" : "") . (isset($curl_init__map[$key]["returnbody"]) ? $curl_init__map[$key]["returnbody"] : ""); 1006 | } 1007 | 1008 | return true; 1009 | } 1010 | 1011 | // Internal functions used by curl_exec(). 1012 | function internal_curl_debug_callback($type, $data, $key) 1013 | { 1014 | global $curl_init__map; 1015 | 1016 | ob_start(); 1017 | 1018 | if ($type == "proxypeercert") 1019 | { 1020 | if (isset($curl_init__map[$key]["options"][CURLOPT_CERTINFO]) && $curl_init__map[$key]["options"][CURLOPT_CERTINFO]) 1021 | { 1022 | echo HTTP::HTTPTranslate("Proxy SSL Certificate:\n"); 1023 | var_dump($data); 1024 | echo "\n"; 1025 | } 1026 | } 1027 | else if ($type == "peercert") 1028 | { 1029 | if (isset($curl_init__map[$key]["options"][CURLOPT_CERTINFO]) && $curl_init__map[$key]["options"][CURLOPT_CERTINFO]) 1030 | { 1031 | echo HTTP::HTTPTranslate("Peer SSL Certificate:\n"); 1032 | var_dump($data); 1033 | echo "\n"; 1034 | } 1035 | } 1036 | else if ($type == "rawproxyheaders") 1037 | { 1038 | if (isset($curl_init__map[$key]["options"]["__CURLINFO_HEADER_OUT"]) && $curl_init__map[$key]["options"]["__CURLINFO_HEADER_OUT"]) 1039 | { 1040 | $curl_init__map[$key]["rawproxyheaders"] = $data; 1041 | 1042 | echo HTTP::HTTPTranslate("Raw Proxy Headers:\n"); 1043 | echo $data; 1044 | } 1045 | } 1046 | else if ($type == "rawheaders") 1047 | { 1048 | if (isset($curl_init__map[$key]["options"]["__CURLINFO_HEADER_OUT"]) && $curl_init__map[$key]["options"]["__CURLINFO_HEADER_OUT"]) 1049 | { 1050 | $curl_init__map[$key]["rawheaders"] = $data; 1051 | 1052 | echo HTTP::HTTPTranslate("Raw Headers:\n"); 1053 | echo $data; 1054 | } 1055 | } 1056 | else if ($type == "rawsend") 1057 | { 1058 | echo HTTP::HTTPTranslate("Sent:\n"); 1059 | echo $data; 1060 | } 1061 | else if ($type == "rawrecv") 1062 | { 1063 | echo HTTP::HTTPTranslate("Received:\n"); 1064 | echo $data; 1065 | echo "\n"; 1066 | } 1067 | 1068 | $output = ob_get_contents(); 1069 | ob_end_clean(); 1070 | 1071 | if ($output !== "" && isset($curl_init__map[$key]["options"][CURLOPT_VERBOSE]) && $curl_init__map[$key]["options"][CURLOPT_VERBOSE]) 1072 | { 1073 | if (isset($curl_init__map[$key]["options"][CURLOPT_STDERR]) && is_resource($curl_init__map[$key]["options"][CURLOPT_STDERR])) fwrite($curl_init__map[$key]["options"][CURLOPT_STDERR], $output); 1074 | else if (defined("STDERR")) fwrite(STDERR, $output); 1075 | else echo $output; 1076 | } 1077 | } 1078 | 1079 | function internal_curl_write_body_callback(&$body, &$bodysize, $key) 1080 | { 1081 | global $curl_init__map; 1082 | 1083 | if (!$bodysize) 1084 | { 1085 | if (!isset($curl_init__map[$key]["options"][CURLOPT_INFILESIZE])) return false; 1086 | $bodysize = $curl_init__map[$key]["options"][CURLOPT_INFILESIZE]; 1087 | } 1088 | else if (isset($curl_init__map[$key]["options"][CURLOPT_READFUNCTION])) 1089 | { 1090 | $bodysize2 = ($bodysize > 32768 ? 32768 : $bodysize); 1091 | $bodysize3 = $bodysize2; 1092 | $body = $curl_init__map[$key]["options"][CURLOPT_READFUNCTION]($curl_init__map[$key]["self"], $curl_init__map[$key]["options"][CURLOPT_INFILE], $bodysize2); 1093 | if ($bodysize3 < strlen($body)) 1094 | { 1095 | if (isset($curl_init__map[$key]["options"][CURLOPT_VERBOSE]) && $curl_init__map[$key]["options"][CURLOPT_VERBOSE]) 1096 | { 1097 | $output = HTTP::HTTPTranslate("An error occurred in the read function callback while reading the data to send/upload to the host."); 1098 | 1099 | if (isset($curl_init__map[$key]["options"][CURLOPT_STDERR]) && is_resource($curl_init__map[$key]["options"][CURLOPT_STDERR])) fwrite($curl_init__map[$key]["options"][CURLOPT_STDERR], $output); 1100 | else if (defined("STDERR")) fwrite(STDERR, $output); 1101 | else echo $output; 1102 | } 1103 | 1104 | return false; 1105 | } 1106 | } 1107 | else 1108 | { 1109 | if (!isset($curl_init__map[$key]["options"][CURLOPT_INFILE]) || !is_resource($curl_init__map[$key]["options"][CURLOPT_INFILE])) return false; 1110 | if ($bodysize > 32768) $body = fread($curl_init__map[$key]["options"][CURLOPT_INFILE], 32768); 1111 | else $body = fread($curl_init__map[$key]["options"][CURLOPT_INFILE], $bodysize); 1112 | if ($body === false) 1113 | { 1114 | if (isset($curl_init__map[$key]["options"][CURLOPT_VERBOSE]) && $curl_init__map[$key]["options"][CURLOPT_VERBOSE]) 1115 | { 1116 | $output = HTTP::HTTPTranslate("An error occurred while reading the data to send/upload to the host."); 1117 | 1118 | if (isset($curl_init__map[$key]["options"][CURLOPT_STDERR]) && is_resource($curl_init__map[$key]["options"][CURLOPT_STDERR])) fwrite($curl_init__map[$key]["options"][CURLOPT_STDERR], $output); 1119 | else if (defined("STDERR")) fwrite(STDERR, $output); 1120 | else echo $output; 1121 | } 1122 | 1123 | return false; 1124 | } 1125 | } 1126 | 1127 | return true; 1128 | } 1129 | 1130 | function internal_curl_read_headers_callback(&$response, &$headers, $key) 1131 | { 1132 | global $curl_init__map; 1133 | 1134 | if (isset($curl_init__map[$key]["returnresponse"])) $data = ""; 1135 | else 1136 | { 1137 | $data = $response["line"] . "\r\n"; 1138 | 1139 | $curl_init__map[$key]["returnresponse"] = $response; 1140 | } 1141 | 1142 | if ($response["code"] >= 400 && isset($curl_init__map[$key]["options"][CURLOPT_FAILONERROR]) && $curl_init__map[$key]["options"][CURLOPT_FAILONERROR]) return true; 1143 | 1144 | foreach ($headers as $name => $vals) 1145 | { 1146 | foreach ($vals as $val) $data .= $name . ": " . $val . "\r\n"; 1147 | } 1148 | 1149 | if (isset($curl_init__map[$key]["options"][CURLOPT_HEADER]) && $curl_init__map[$key]["options"][CURLOPT_HEADER]) 1150 | { 1151 | if (isset($curl_init__map[$key]["options"][CURLOPT_VERBOSE]) && $curl_init__map[$key]["options"][CURLOPT_VERBOSE]) 1152 | { 1153 | if (isset($curl_init__map[$key]["options"][CURLOPT_STDERR]) && is_resource($curl_init__map[$key]["options"][CURLOPT_STDERR])) fwrite($curl_init__map[$key]["options"][CURLOPT_STDERR], HTTP::HTTPTranslate("Header:\n") . $data); 1154 | else if (defined("STDERR")) fwrite(STDERR, HTTP::HTTPTranslate("Header:\n") . $data); 1155 | else echo HTTP::HTTPTranslate("Header:\n") . $data; 1156 | } 1157 | } 1158 | 1159 | if (!isset($headers["Location"]) || !isset($curl_init__map[$key]["options"][CURLOPT_FOLLOWLOCATION]) || !$curl_init__map[$key]["options"][CURLOPT_FOLLOWLOCATION]) 1160 | { 1161 | if (isset($curl_init__map[$key]["options"][CURLOPT_HEADER]) && $curl_init__map[$key]["options"][CURLOPT_HEADER]) 1162 | { 1163 | if (isset($curl_init__map[$key]["options"][CURLOPT_WRITEHEADER]) && is_resource($curl_init__map[$key]["options"][CURLOPT_WRITEHEADER])) 1164 | { 1165 | fwrite($curl_init__map[$key]["options"][CURLOPT_WRITEHEADER], $data); 1166 | } 1167 | else if (isset($curl_init__map[$key]["options"][CURLOPT_RETURNTRANSFER]) && $curl_init__map[$key]["options"][CURLOPT_RETURNTRANSFER]) 1168 | { 1169 | if (!isset($curl_init__map[$key]["returnheader"])) $curl_init__map[$key]["returnheader"] = $data; 1170 | else $curl_init__map[$key]["returnheader"] .= $data; 1171 | } 1172 | else if (!$curl_init__map[$key]["outputbody"]) 1173 | { 1174 | if (isset($curl_init__map[$key]["options"][CURLOPT_FILE]) && is_resource($curl_init__map[$key]["options"][CURLOPT_FILE])) fwrite($curl_init__map[$key]["options"][CURLOPT_FILE], $data); 1175 | else echo $data; 1176 | } 1177 | } 1178 | 1179 | if (isset($curl_init__map[$key]["options"][CURLOPT_HEADERFUNCTION]) && $curl_init__map[$key]["options"][CURLOPT_HEADERFUNCTION]) 1180 | { 1181 | $curl_init__map[$key]["options"][CURLOPT_HEADERFUNCTION]($curl_init__map[$key]["self"], $data); 1182 | } 1183 | } 1184 | 1185 | return true; 1186 | } 1187 | 1188 | function internal_curl_read_body_callback(&$response, $data, $key) 1189 | { 1190 | global $curl_init__map; 1191 | 1192 | if ($response["code"] >= 400 && isset($curl_init__map[$key]["options"][CURLOPT_FAILONERROR]) && $curl_init__map[$key]["options"][CURLOPT_FAILONERROR]) return true; 1193 | 1194 | if (!isset($headers["Location"]) || !isset($curl_init__map[$key]["options"][CURLOPT_FOLLOWLOCATION]) || !$curl_init__map[$key]["options"][CURLOPT_FOLLOWLOCATION]) 1195 | { 1196 | if (!isset($curl_init__map[$key]["returnbody"])) $curl_init__map[$key]["returnbody"] = ""; 1197 | 1198 | if (isset($curl_init__map[$key]["options"][CURLOPT_RETURNTRANSFER]) && $curl_init__map[$key]["options"][CURLOPT_RETURNTRANSFER]) $curl_init__map[$key]["returnbody"] .= $data; 1199 | else 1200 | { 1201 | if (isset($curl_init__map[$key]["options"][CURLOPT_FILE]) && is_resource($curl_init__map[$key]["options"][CURLOPT_FILE])) fwrite($curl_init__map[$key]["options"][CURLOPT_FILE], $data); 1202 | else echo $data; 1203 | 1204 | $curl_init__map[$key]["outputbody"] = true; 1205 | } 1206 | 1207 | if (isset($curl_init__map[$key]["options"][CURLOPT_VERBOSE]) && $curl_init__map[$key]["options"][CURLOPT_VERBOSE]) 1208 | { 1209 | if (isset($curl_init__map[$key]["options"][CURLOPT_STDERR]) && is_resource($curl_init__map[$key]["options"][CURLOPT_STDERR])) fwrite($curl_init__map[$key]["options"][CURLOPT_STDERR], HTTP::HTTPTranslate("Body:\n") . $data); 1210 | else if (defined("STDERR")) fwrite(STDERR, HTTP::HTTPTranslate("Body:\n") . $data); 1211 | else echo HTTP::HTTPTranslate("Body:\n") . $data; 1212 | } 1213 | 1214 | if (isset($curl_init__map[$key]["options"][CURLOPT_WRITEFUNCTION]) && $curl_init__map[$key]["options"][CURLOPT_WRITEFUNCTION]) 1215 | { 1216 | $datasize = strlen($data); 1217 | $size = $curl_init__map[$key]["options"][CURLOPT_WRITEFUNCTION]($curl_init__map[$key]["self"], $data); 1218 | if ($size != $datasize) 1219 | { 1220 | if (isset($curl_init__map[$key]["options"][CURLOPT_VERBOSE]) && $curl_init__map[$key]["options"][CURLOPT_VERBOSE]) 1221 | { 1222 | $output = HTTP::HTTPTranslate("An error occurred in the write function callback while writing the data received from the host."); 1223 | 1224 | if (isset($curl_init__map[$key]["options"][CURLOPT_STDERR]) && is_resource($curl_init__map[$key]["options"][CURLOPT_STDERR])) fwrite($curl_init__map[$key]["options"][CURLOPT_STDERR], $output); 1225 | else if (defined("STDERR")) fwrite(STDERR, $output); 1226 | else echo $output; 1227 | } 1228 | 1229 | return false; 1230 | } 1231 | } 1232 | } 1233 | 1234 | return true; 1235 | } 1236 | 1237 | function curl_getinfo($ch, $opt = 0) 1238 | { 1239 | global $curl_init__map; 1240 | 1241 | $key = get_check_curl_init_key($ch); 1242 | 1243 | if (!isset($curl_init__map[$key]["lastresult"])) return false; 1244 | 1245 | $result = array( 1246 | "url" => $curl_init__map[$key]["lastresult"]["url"], 1247 | "content_type" => (isset($curl_init__map[$key]["lastresult"]["headers"]) && isset($curl_init__map[$key]["lastresult"]["headers"]["Content-Type"]) ? $curl_init__map[$key]["lastresult"]["headers"]["Content-Type"][0] : null), 1248 | "http_code" => (isset($curl_init__map[$key]["lastresult"]["response"]) && isset($curl_init__map[$key]["lastresult"]["response"]["code"]) ? (int)$curl_init__map[$key]["lastresult"]["response"]["code"] : null), 1249 | "header_size" => (isset($curl_init__map[$key]["lastresult"]["rawrecvheadersize"]) ? $curl_init__map[$key]["lastresult"]["rawrecvheadersize"] : 0), 1250 | "request_size" => (isset($curl_init__map[$key]["lastresult"]["totalrawsendsize"]) ? $curl_init__map[$key]["lastresult"]["totalrawsendsize"] : 0), 1251 | "filetime" => (isset($curl_init__map[$key]["options"][CURLOPT_FILETIME]) && $curl_init__map[$key]["options"][CURLOPT_FILETIME] && isset($curl_init__map[$key]["lastresult"]["headers"]) && isset($curl_init__map[$key]["lastresult"]["headers"]["Last-Modified"]) ? HTTP::GetDateTimestamp($curl_init__map[$key]["lastresult"]["headers"]["Last-Modified"][0]) : -1), 1252 | "ssl_verify_result" => 0, 1253 | "redirect_count" => (isset($curl_init__map[$key]["lastresult"]["numredirects"]) ? $curl_init__map[$key]["lastresult"]["numredirects"] : 0), 1254 | "total_time" => (isset($curl_init__map[$key]["lastresult"]["startts"]) && isset($curl_init__map[$key]["lastresult"]["endts"]) ? $curl_init__map[$key]["lastresult"]["endts"] - $curl_init__map[$key]["lastresult"]["startts"] : 0), 1255 | "namelookup_time" => (isset($curl_init__map[$key]["lastresult"]["startts"]) && isset($curl_init__map[$key]["lastresult"]["connected"]) ? ($curl_init__map[$key]["lastresult"]["connected"] - $curl_init__map[$key]["lastresult"]["startts"]) / 2 : 0), 1256 | "connect_time" => (isset($curl_init__map[$key]["lastresult"]["startts"]) && isset($curl_init__map[$key]["lastresult"]["connected"]) ? ($curl_init__map[$key]["lastresult"]["connected"] - $curl_init__map[$key]["lastresult"]["startts"]) / 2 : 0), 1257 | "pretransfer_time" => (isset($curl_init__map[$key]["lastresult"]["connected"]) && isset($curl_init__map[$key]["lastresult"]["sendstart"]) ? $curl_init__map[$key]["lastresult"]["sendstart"] - $curl_init__map[$key]["lastresult"]["connected"] : 0), 1258 | "size_upload" => (isset($curl_init__map[$key]["lastresult"]["rawsendsize"]) && isset($curl_init__map[$key]["lastresult"]["rawsendheadersize"]) ? $curl_init__map[$key]["lastresult"]["rawsendsize"] - $curl_init__map[$key]["lastresult"]["rawsendheadersize"] : 0), 1259 | "size_download" => (isset($curl_init__map[$key]["lastresult"]["rawrecvsize"]) && isset($curl_init__map[$key]["lastresult"]["rawrecvheadersize"]) ? $curl_init__map[$key]["lastresult"]["rawrecvsize"] - $curl_init__map[$key]["lastresult"]["rawrecvheadersize"] : 0) 1260 | ); 1261 | 1262 | $result["speed_download"] = (isset($curl_init__map[$key]["lastresult"]["recvstart"]) && isset($curl_init__map[$key]["lastresult"]["endts"]) && $curl_init__map[$key]["lastresult"]["endts"] - $curl_init__map[$key]["lastresult"]["recvstart"] > 0 ? $result["size_download"] / ($curl_init__map[$key]["lastresult"]["endts"] - $curl_init__map[$key]["lastresult"]["recvstart"]) : 0); 1263 | $result["speed_upload"] = (isset($curl_init__map[$key]["lastresult"]["sendstart"]) && isset($curl_init__map[$key]["lastresult"]["recvstart"]) && $curl_init__map[$key]["lastresult"]["recvstart"] - $curl_init__map[$key]["lastresult"]["sendstart"] > 0 ? $result["size_upload"] / ($curl_init__map[$key]["lastresult"]["recvstart"] - $curl_init__map[$key]["lastresult"]["sendstart"]) : 0); 1264 | $result["download_content_length"] = (isset($curl_init__map[$key]["lastresult"]["headers"]) && isset($curl_init__map[$key]["lastresult"]["headers"]["Content-Length"]) ? $curl_init__map[$key]["lastresult"]["headers"]["Content-Length"][0] : -1); 1265 | $result["upload_content_length"] = $result["size_upload"]; 1266 | $result["starttransfer_time"] = (isset($curl_init__map[$key]["lastresult"]["startts"]) && isset($curl_init__map[$key]["lastresult"]["sendstart"]) ? $curl_init__map[$key]["lastresult"]["sendstart"] - $curl_init__map[$key]["lastresult"]["startts"] : 0); 1267 | $result["redirect_time"] = (isset($curl_init__map[$key]["lastresult"]["firstreqts"]) && isset($curl_init__map[$key]["lastresult"]["redirectts"]) ? $curl_init__map[$key]["lastresult"]["redirectts"] - $curl_init__map[$key]["lastresult"]["firstreqts"] : 0); 1268 | if (isset($curl_init__map[$key]["rawheaders"])) $result["request_header"] = $curl_init__map[$key]["rawheaders"]; 1269 | 1270 | if ($opt == 0) return $result; 1271 | 1272 | $tempmap = array( 1273 | CURLINFO_EFFECTIVE_URL => "url", 1274 | CURLINFO_HTTP_CODE => "http_code", 1275 | CURLINFO_FILETIME => "filetime", 1276 | CURLINFO_TOTAL_TIME => "total_time", 1277 | CURLINFO_NAMELOOKUP_TIME => "namelookup_time", 1278 | CURLINFO_CONNECT_TIME => "connect_time", 1279 | CURLINFO_PRETRANSFER_TIME => "pretransfer_time", 1280 | CURLINFO_STARTTRANSFER_TIME => "starttransfer_time", 1281 | CURLINFO_REDIRECT_TIME => "redirect_time", 1282 | CURLINFO_SIZE_UPLOAD => "size_upload", 1283 | CURLINFO_SIZE_DOWNLOAD => "size_download", 1284 | CURLINFO_SPEED_DOWNLOAD => "speed_download", 1285 | CURLINFO_SPEED_UPLOAD => "speed_upload", 1286 | CURLINFO_HEADER_SIZE => "header_size", 1287 | CURLINFO_HEADER_OUT => "request_header", 1288 | CURLINFO_REQUEST_SIZE => "request_size", 1289 | CURLINFO_SSL_VERIFYRESULT => "ssl_verify_result", 1290 | CURLINFO_CONTENT_LENGTH_DOWNLOAD => "download_content_length", 1291 | CURLINFO_CONTENT_LENGTH_UPLOAD => "upload_content_length", 1292 | CURLINFO_CONTENT_TYPE => "content_type", 1293 | ); 1294 | if (!isset($tempmap[$opt]) || !isset($result[$tempmap[$opt]])) return false; 1295 | 1296 | return $result[$tempmap[$opt]]; 1297 | } 1298 | 1299 | // These functions really just cheat and do requests in serial. Laziness at its finest! 1300 | $curl_multi_init__map = array(); 1301 | function get_curl_multi_init_key($mh) 1302 | { 1303 | ob_start(); 1304 | echo $mh; 1305 | ob_end_clean(); 1306 | 1307 | return ob_get_contents(); 1308 | } 1309 | 1310 | function get_check_curl_multi_init_key($ch) 1311 | { 1312 | global $curl_init__map; 1313 | 1314 | $key = get_curl_multi_init_key($ch); 1315 | if (!isset($curl_multi_init__map[$key])) throw new Exception(HTTP::HTTPTranslate("cURL Emulator: Unable to find key mapping for resource.")); 1316 | 1317 | return $key; 1318 | } 1319 | 1320 | function curl_multi_init() 1321 | { 1322 | global $curl_multi_init__map; 1323 | 1324 | // Another evil hack to create a "resource" so that is_resource() works. 1325 | $mh = fopen(__FILE__, "rb"); 1326 | $key = get_curl_multi_init_key($mh); 1327 | $curl_multi_init__map[$key] = array("self" => $mh, "handles" => array(), "messages" => array()); 1328 | 1329 | return $mh; 1330 | } 1331 | 1332 | function curl_multi_add_handle($mh, $ch) 1333 | { 1334 | global $curl_multi_init__map; 1335 | 1336 | $key = get_check_curl_multi_init_key($mh); 1337 | $key2 = get_check_curl_init_key($ch); 1338 | 1339 | $curl_multi_init__map[$key]["handles"][$key2] = $ch; 1340 | 1341 | return 0; 1342 | } 1343 | 1344 | function curl_multi_remove_handle($mh, $ch) 1345 | { 1346 | global $curl_multi_init__map; 1347 | 1348 | $key = get_check_curl_multi_init_key($mh); 1349 | $key2 = get_check_curl_init_key($ch); 1350 | 1351 | unset($curl_multi_init__map[$key]["handles"][$key2]); 1352 | 1353 | return 0; 1354 | } 1355 | 1356 | function curl_multi_close($mh) 1357 | { 1358 | global $curl_multi_init__map; 1359 | 1360 | $key = get_check_curl_multi_init_key($mh); 1361 | 1362 | unset($curl_multi_init__map[$key]); 1363 | } 1364 | 1365 | function curl_multi_getcontent($ch) 1366 | { 1367 | global $curl_init__map; 1368 | 1369 | $key = get_check_curl_init_key($ch); 1370 | 1371 | if (isset($curl_init__map[$key]["options"][CURLOPT_RETURNTRANSFER]) && $curl_init__map[$key]["options"][CURLOPT_RETURNTRANSFER]) 1372 | { 1373 | return (isset($curl_init__map[$key]["returnheader"]) ? $curl_init__map[$key]["returnheader"] . "\r\n" : "") . (isset($curl_init__map[$key]["returnbody"]) ? $curl_init__map[$key]["returnbody"] : ""); 1374 | } 1375 | } 1376 | 1377 | function curl_multi_exec($mh, &$still_running) 1378 | { 1379 | global $curl_multi_init__map; 1380 | 1381 | $key = get_check_curl_multi_init_key($mh); 1382 | 1383 | foreach ($curl_multi_init__map[$key]["handles"] as $key2 => $ch) 1384 | { 1385 | curl_exec($ch); 1386 | $curl_multi_init__map[$key]["messages"][] = array( 1387 | "msg" => CURLMSG_DONE, 1388 | "result" => curl_errno($ch), 1389 | "handle" => $ch 1390 | ); 1391 | unset($curl_multi_init__map[$key]["handles"][$key2]); 1392 | } 1393 | 1394 | $still_running = 0; 1395 | 1396 | return CURLM_OK; 1397 | } 1398 | 1399 | function curl_multi_select($mh, $timeout = 1.0) 1400 | { 1401 | global $curl_multi_init__map; 1402 | 1403 | $key = get_check_curl_multi_init_key($mh); 1404 | 1405 | if (!count($curl_multi_init__map[$key]["handles"])) return -1; 1406 | 1407 | return count($curl_multi_init__map[$key]["handles"]); 1408 | } 1409 | 1410 | function curl_multi_info_read($mh, &$msgs_in_queue = NULL) 1411 | { 1412 | global $curl_multi_init__map; 1413 | 1414 | $key = get_check_curl_multi_init_key($mh); 1415 | 1416 | $msgs_in_queue = count($curl_multi_init__map[$key]["messages"]); 1417 | if (!$msgs_in_queue) return false; 1418 | $msgs_in_queue--; 1419 | 1420 | return array_shift($curl_multi_init__map[$key]["messages"]); 1421 | } 1422 | } 1423 | ?> -------------------------------------------------------------------------------- /support/support/simple_html_dom.php: -------------------------------------------------------------------------------- 1 | 6 | Acknowledge: Jose Solorzano (https://sourceforge.net/projects/php-html/) 7 | Contributions by: 8 | Yousuke Kumakura (Attribute filters) 9 | Vadim Voituk (Negative indexes supports of "find" method) 10 | Antcs (Constructor with automatically load contents either text or file/url) 11 | Licensed under The MIT License 12 | Redistributions of files must retain the above copyright notice. 13 | *******************************************************************************/ 14 | 15 | define('HDOM_TYPE_ELEMENT', 1); 16 | define('HDOM_TYPE_COMMENT', 2); 17 | define('HDOM_TYPE_TEXT', 3); 18 | define('HDOM_TYPE_ENDTAG', 4); 19 | define('HDOM_TYPE_ROOT', 5); 20 | define('HDOM_TYPE_UNKNOWN', 6); 21 | define('HDOM_QUOTE_DOUBLE', 0); 22 | define('HDOM_QUOTE_SINGLE', 1); 23 | define('HDOM_QUOTE_NO', 3); 24 | define('HDOM_INFO_BEGIN', 0); 25 | define('HDOM_INFO_END', 1); 26 | define('HDOM_INFO_QUOTE', 2); 27 | define('HDOM_INFO_SPACE', 3); 28 | define('HDOM_INFO_TEXT', 4); 29 | define('HDOM_INFO_INNER', 5); 30 | define('HDOM_INFO_OUTER', 6); 31 | define('HDOM_INFO_ENDSPACE',7); 32 | 33 | // helper functions 34 | // ----------------------------------------------------------------------------- 35 | // get html dom form file 36 | function file_get_html() { 37 | $dom = new simple_html_dom; 38 | $args = func_get_args(); 39 | $dom->load(call_user_func_array('file_get_contents', $args), true); 40 | return $dom; 41 | } 42 | 43 | // get html dom form string 44 | function str_get_html($str, $lowercase=true) { 45 | $dom = new simple_html_dom; 46 | $dom->load($str, $lowercase); 47 | return $dom; 48 | } 49 | 50 | // dump html dom tree 51 | function dump_html_tree($node, $show_attr=true, $deep=0) { 52 | $lead = str_repeat(' ', $deep); 53 | echo $lead.$node->tag; 54 | if ($show_attr && count($node->attr)>0) { 55 | echo '('; 56 | foreach($node->attr as $k=>$v) 57 | echo "[$k]=>\"".$node->$k.'", '; 58 | echo ')'; 59 | } 60 | echo "\n"; 61 | 62 | foreach($node->nodes as $c) 63 | dump_html_tree($c, $show_attr, $deep+1); 64 | } 65 | 66 | // get dom form file (deprecated) 67 | function file_get_dom() { 68 | $dom = new simple_html_dom; 69 | $args = func_get_args(); 70 | $dom->load(call_user_func_array('file_get_contents', $args), true); 71 | return $dom; 72 | } 73 | 74 | // get dom form string (deprecated) 75 | function str_get_dom($str, $lowercase=true) { 76 | $dom = new simple_html_dom; 77 | $dom->load($str, $lowercase); 78 | return $dom; 79 | } 80 | 81 | // simple html dom node 82 | // ----------------------------------------------------------------------------- 83 | class simple_html_dom_node { 84 | public $nodetype = HDOM_TYPE_TEXT; 85 | public $tag = 'text'; 86 | public $attr = array(); 87 | public $children = array(); 88 | public $nodes = array(); 89 | public $parent = null; 90 | public $_ = array(); 91 | private $dom = null; 92 | 93 | function __construct($dom) { 94 | $this->dom = $dom; 95 | $dom->nodes[] = $this; 96 | } 97 | 98 | function __destruct() { 99 | $this->clear(); 100 | } 101 | 102 | function __toString() { 103 | return $this->outertext(); 104 | } 105 | 106 | // clean up memory due to php5 circular references memory leak... 107 | function clear() { 108 | $this->dom = null; 109 | $this->nodes = null; 110 | $this->parent = null; 111 | $this->children = null; 112 | } 113 | 114 | // dump node's tree 115 | function dump($show_attr=true) { 116 | dump_html_tree($this, $show_attr); 117 | } 118 | 119 | // returns the parent of node 120 | function parent() { 121 | return $this->parent; 122 | } 123 | 124 | // returns children of node 125 | function children($idx=-1) { 126 | if ($idx===-1) return $this->children; 127 | if (isset($this->children[$idx])) return $this->children[$idx]; 128 | return null; 129 | } 130 | 131 | // returns the first child of node 132 | function first_child() { 133 | if (count($this->children)>0) return $this->children[0]; 134 | return null; 135 | } 136 | 137 | // returns the last child of node 138 | function last_child() { 139 | if (($count=count($this->children))>0) return $this->children[$count-1]; 140 | return null; 141 | } 142 | 143 | // returns the next sibling of node 144 | function next_sibling() { 145 | if ($this->parent===null) return null; 146 | $idx = 0; 147 | $count = count($this->parent->children); 148 | while ($idx<$count && $this!==$this->parent->children[$idx]) 149 | ++$idx; 150 | if (++$idx>=$count) return null; 151 | return $this->parent->children[$idx]; 152 | } 153 | 154 | // returns the previous sibling of node 155 | function prev_sibling() { 156 | if ($this->parent===null) return null; 157 | $idx = 0; 158 | $count = count($this->parent->children); 159 | while ($idx<$count && $this!==$this->parent->children[$idx]) 160 | ++$idx; 161 | if (--$idx<0) return null; 162 | return $this->parent->children[$idx]; 163 | } 164 | 165 | // get dom node's inner html 166 | function innertext() { 167 | if (isset($this->_[HDOM_INFO_INNER])) return $this->_[HDOM_INFO_INNER]; 168 | if (isset($this->_[HDOM_INFO_TEXT])) return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); 169 | 170 | $ret = ''; 171 | foreach($this->nodes as $n) 172 | $ret .= $n->outertext(); 173 | return $ret; 174 | } 175 | 176 | // get dom node's outer text (with tag) 177 | function outertext() { 178 | if ($this->tag==='root') return $this->innertext(); 179 | 180 | // trigger callback 181 | if ($this->dom->callback!==null) 182 | call_user_func_array($this->dom->callback, array($this)); 183 | 184 | if (isset($this->_[HDOM_INFO_OUTER])) return $this->_[HDOM_INFO_OUTER]; 185 | if (isset($this->_[HDOM_INFO_TEXT])) return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); 186 | 187 | // render begin tag 188 | $ret = $this->dom->nodes[$this->_[HDOM_INFO_BEGIN]]->makeup(); 189 | 190 | // render inner text 191 | if (isset($this->_[HDOM_INFO_INNER])) 192 | $ret .= $this->_[HDOM_INFO_INNER]; 193 | else { 194 | foreach($this->nodes as $n) 195 | $ret .= $n->outertext(); 196 | } 197 | 198 | // render end tag 199 | if(isset($this->_[HDOM_INFO_END]) && $this->_[HDOM_INFO_END]!=0) 200 | $ret .= 'tag.'>'; 201 | return $ret; 202 | } 203 | 204 | // get dom node's plain text 205 | function text() { 206 | if (isset($this->_[HDOM_INFO_INNER])) return $this->_[HDOM_INFO_INNER]; 207 | switch ($this->nodetype) { 208 | case HDOM_TYPE_TEXT: return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); 209 | case HDOM_TYPE_COMMENT: return ''; 210 | case HDOM_TYPE_UNKNOWN: return ''; 211 | } 212 | if (strcasecmp($this->tag, 'script')===0) return ''; 213 | if (strcasecmp($this->tag, 'style')===0) return ''; 214 | 215 | $ret = ''; 216 | foreach($this->nodes as $n) 217 | $ret .= $n->text(); 218 | return $ret; 219 | } 220 | 221 | function xmltext() { 222 | $ret = $this->innertext(); 223 | $ret = str_ireplace('', '', $ret); 225 | return $ret; 226 | } 227 | 228 | // build node's text with tag 229 | function makeup() { 230 | // text, comment, unknown 231 | if (isset($this->_[HDOM_INFO_TEXT])) return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); 232 | 233 | $ret = '<'.$this->tag; 234 | $i = -1; 235 | 236 | foreach($this->attr as $key=>$val) { 237 | ++$i; 238 | 239 | // skip removed attribute 240 | if ($val===null || $val===false) 241 | continue; 242 | 243 | $ret .= $this->_[HDOM_INFO_SPACE][$i][0]; 244 | //no value attr: nowrap, checked selected... 245 | if ($val===true) 246 | $ret .= $key; 247 | else { 248 | switch($this->_[HDOM_INFO_QUOTE][$i]) { 249 | case HDOM_QUOTE_DOUBLE: $quote = '"'; break; 250 | case HDOM_QUOTE_SINGLE: $quote = '\''; break; 251 | default: $quote = ''; 252 | } 253 | $ret .= $key.$this->_[HDOM_INFO_SPACE][$i][1].'='.$this->_[HDOM_INFO_SPACE][$i][2].$quote.$val.$quote; 254 | } 255 | } 256 | $ret = $this->dom->restore_noise($ret); 257 | return $ret . $this->_[HDOM_INFO_ENDSPACE] . '>'; 258 | } 259 | 260 | // find elements by css selector 261 | function find($selector, $idx=null) { 262 | $selectors = $this->parse_selector($selector); 263 | if (($count=count($selectors))===0) return array(); 264 | $found_keys = array(); 265 | 266 | // find each selector 267 | for ($c=0; $c<$count; ++$c) { 268 | if (($levle=count($selectors[0]))===0) return array(); 269 | if (!isset($this->_[HDOM_INFO_BEGIN])) return array(); 270 | 271 | $head = array($this->_[HDOM_INFO_BEGIN]=>1); 272 | 273 | // handle descendant selectors, no recursive! 274 | for ($l=0; $l<$levle; ++$l) { 275 | $ret = array(); 276 | foreach($head as $k=>$v) { 277 | $n = ($k===-1) ? $this->dom->root : $this->dom->nodes[$k]; 278 | $n->seek($selectors[$c][$l], $ret); 279 | } 280 | $head = $ret; 281 | } 282 | 283 | foreach($head as $k=>$v) { 284 | if (!isset($found_keys[$k])) 285 | $found_keys[$k] = 1; 286 | } 287 | } 288 | 289 | // sort keys 290 | ksort($found_keys); 291 | 292 | $found = array(); 293 | foreach($found_keys as $k=>$v) 294 | $found[] = $this->dom->nodes[$k]; 295 | 296 | // return nth-element or array 297 | if (is_null($idx)) return $found; 298 | else if ($idx<0) $idx = count($found) + $idx; 299 | return (isset($found[$idx])) ? $found[$idx] : null; 300 | } 301 | 302 | // seek for given conditions 303 | protected function seek($selector, &$ret) { 304 | list($tag, $key, $val, $exp, $no_key) = $selector; 305 | 306 | // xpath index 307 | if ($tag && $key && is_numeric($key)) { 308 | $count = 0; 309 | foreach ($this->children as $c) { 310 | if ($tag==='*' || $tag===$c->tag) { 311 | if (++$count==$key) { 312 | $ret[$c->_[HDOM_INFO_BEGIN]] = 1; 313 | return; 314 | } 315 | } 316 | } 317 | return; 318 | } 319 | 320 | $end = (!empty($this->_[HDOM_INFO_END])) ? $this->_[HDOM_INFO_END] : 0; 321 | if ($end==0) { 322 | $parent = $this->parent; 323 | while (!isset($parent->_[HDOM_INFO_END]) && $parent!==null) { 324 | $end -= 1; 325 | $parent = $parent->parent; 326 | } 327 | $end += $parent->_[HDOM_INFO_END]; 328 | } 329 | 330 | for($i=$this->_[HDOM_INFO_BEGIN]+1; $i<$end; ++$i) { 331 | $node = $this->dom->nodes[$i]; 332 | $pass = true; 333 | 334 | if ($tag==='*' && !$key) { 335 | if (in_array($node, $this->children, true)) 336 | $ret[$i] = 1; 337 | continue; 338 | } 339 | 340 | // compare tag 341 | if ($tag && $tag!=$node->tag && $tag!=='*') {$pass=false;} 342 | // compare key 343 | if ($pass && $key) { 344 | if ($no_key) { 345 | if (isset($node->attr[$key])) $pass=false; 346 | } 347 | else if (!isset($node->attr[$key])) $pass=false; 348 | } 349 | // compare value 350 | if ($pass && $key && $val && $val!=='*') { 351 | $check = $this->match($exp, $val, $node->attr[$key]); 352 | // handle multiple class 353 | if (!$check && strcasecmp($key, 'class')===0) { 354 | foreach(explode(' ',$node->attr[$key]) as $k) { 355 | $check = $this->match($exp, $val, $k); 356 | if ($check) break; 357 | } 358 | } 359 | if (!$check) $pass = false; 360 | } 361 | if ($pass) $ret[$i] = 1; 362 | unset($node); 363 | } 364 | } 365 | 366 | protected function match($exp, $pattern, $value) { 367 | switch ($exp) { 368 | case '=': 369 | return ($value===$pattern); 370 | case '!=': 371 | return ($value!==$pattern); 372 | case '^=': 373 | return preg_match("/^".preg_quote($pattern,'/')."/", $value); 374 | case '$=': 375 | return preg_match("/".preg_quote($pattern,'/')."$/", $value); 376 | case '*=': 377 | if ($pattern[0]=='/') 378 | return preg_match($pattern, $value); 379 | return preg_match("/".$pattern."/i", $value); 380 | } 381 | return false; 382 | } 383 | 384 | protected function parse_selector($selector_string) { 385 | // pattern of CSS selectors, modified from mootools 386 | $pattern = "/([\w\-:\*]*)(?:\#([\w-]+)|\.([\w-]+))?(?:\[@?(!?[\w-]+)(?:([!*^$]?=)[\"']?(.*?)[\"']?)?\])?([\/, ]+)/is"; 387 | preg_match_all($pattern, trim($selector_string).' ', $matches, PREG_SET_ORDER); 388 | $selectors = array(); 389 | $result = array(); 390 | //print_r($matches); 391 | 392 | foreach ($matches as $m) { 393 | $m[0] = trim($m[0]); 394 | if ($m[0]==='' || $m[0]==='/' || $m[0]==='//') continue; 395 | // for borwser grnreated xpath 396 | if ($m[1]==='tbody') continue; 397 | 398 | list($tag, $key, $val, $exp, $no_key) = array($m[1], null, null, '=', false); 399 | if(!empty($m[2])) {$key='id'; $val=$m[2];} 400 | if(!empty($m[3])) {$key='class'; $val=$m[3];} 401 | if(!empty($m[4])) {$key=$m[4];} 402 | if(!empty($m[5])) {$exp=$m[5];} 403 | if(!empty($m[6])) {$val=$m[6];} 404 | 405 | // convert to lowercase 406 | if ($this->dom->lowercase) {$tag=strtolower((string)$tag); $key=strtolower((string)$key);} 407 | //elements that do NOT have the specified attribute 408 | if (isset($key[0]) && $key[0]==='!') {$key=substr($key, 1); $no_key=true;} 409 | 410 | $result[] = array($tag, $key, $val, $exp, $no_key); 411 | if (trim($m[7])===',') { 412 | $selectors[] = $result; 413 | $result = array(); 414 | } 415 | } 416 | if (count($result)>0) 417 | $selectors[] = $result; 418 | return $selectors; 419 | } 420 | 421 | function __get($name) { 422 | if (isset($this->attr[$name])) return $this->attr[$name]; 423 | switch($name) { 424 | case 'outertext': return $this->outertext(); 425 | case 'innertext': return $this->innertext(); 426 | case 'plaintext': return $this->text(); 427 | case 'xmltext': return $this->xmltext(); 428 | default: return array_key_exists($name, $this->attr); 429 | } 430 | } 431 | 432 | function __set($name, $value) { 433 | switch($name) { 434 | case 'outertext': return $this->_[HDOM_INFO_OUTER] = $value; 435 | case 'innertext': 436 | if (isset($this->_[HDOM_INFO_TEXT])) return $this->_[HDOM_INFO_TEXT] = $value; 437 | return $this->_[HDOM_INFO_INNER] = $value; 438 | } 439 | if (!isset($this->attr[$name])) { 440 | $this->_[HDOM_INFO_SPACE][] = array(' ', '', ''); 441 | $this->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_DOUBLE; 442 | } 443 | $this->attr[$name] = $value; 444 | } 445 | 446 | function __isset($name) { 447 | switch($name) { 448 | case 'outertext': return true; 449 | case 'innertext': return true; 450 | case 'plaintext': return true; 451 | } 452 | //no value attr: nowrap, checked selected... 453 | return (array_key_exists($name, $this->attr)) ? true : isset($this->attr[$name]); 454 | } 455 | 456 | function __unset($name) { 457 | if (isset($this->attr[$name])) 458 | unset($this->attr[$name]); 459 | } 460 | 461 | // camel naming conventions 462 | function getAllAttributes() {return $this->attr;} 463 | function getAttribute($name) {return $this->__get($name);} 464 | function setAttribute($name, $value) {$this->__set($name, $value);} 465 | function hasAttribute($name) {return $this->__isset($name);} 466 | function removeAttribute($name) {$this->__set($name, null);} 467 | function getElementById($id) {return $this->find("#$id", 0);} 468 | function getElementsById($id, $idx=null) {return $this->find("#$id", $idx);} 469 | function getElementByTagName($name) {return $this->find($name, 0);} 470 | function getElementsByTagName($name, $idx=null) {return $this->find($name, $idx);} 471 | function parentNode() {return $this->parent();} 472 | function childNodes($idx=-1) {return $this->children($idx);} 473 | function firstChild() {return $this->first_child();} 474 | function lastChild() {return $this->last_child();} 475 | function nextSibling() {return $this->next_sibling();} 476 | function previousSibling() {return $this->prev_sibling();} 477 | } 478 | 479 | // simple html dom parser 480 | // ----------------------------------------------------------------------------- 481 | class simple_html_dom { 482 | public $root = null; 483 | public $nodes = array(); 484 | public $callback = null; 485 | public $lowercase = false; 486 | protected $pos; 487 | protected $doc; 488 | protected $char; 489 | protected $size; 490 | protected $cursor; 491 | protected $parent; 492 | protected $noise = array(); 493 | protected $token_blank = " \t\r\n"; 494 | protected $token_equal = ' =/>'; 495 | protected $token_slash = " />\r\n\t"; 496 | protected $token_attr = ' >'; 497 | // use isset instead of in_array, performance boost about 30%... 498 | protected $self_closing_tags = array('img'=>1, 'br'=>1, 'input'=>1, 'meta'=>1, 'link'=>1, 'hr'=>1, 'base'=>1, 'embed'=>1, 'spacer'=>1); 499 | protected $block_tags = array('root'=>1, 'body'=>1, 'form'=>1, 'div'=>1, 'span'=>1, 'table'=>1); 500 | protected $optional_closing_tags = array( 501 | 'tr'=>array('tr'=>1, 'td'=>1, 'th'=>1), 502 | 'th'=>array('th'=>1), 503 | 'td'=>array('td'=>1), 504 | 'li'=>array('li'=>1), 505 | 'dt'=>array('dt'=>1, 'dd'=>1), 506 | 'dd'=>array('dd'=>1, 'dt'=>1), 507 | 'dl'=>array('dd'=>1, 'dt'=>1), 508 | 'p'=>array('p'=>1), 509 | 'nobr'=>array('nobr'=>1), 510 | ); 511 | 512 | function __construct($str=null) { 513 | if ($str) { 514 | if (preg_match("/^http:\/\//i",$str) || is_file($str)) 515 | $this->load_file($str); 516 | else 517 | $this->load($str); 518 | } 519 | } 520 | 521 | function __destruct() { 522 | $this->clear(); 523 | } 524 | 525 | // load html from string 526 | function load($str, $lowercase=true) { 527 | // prepare 528 | $this->prepare($str, $lowercase); 529 | // strip out comments 530 | $this->remove_noise("''is"); 531 | // strip out cdata 532 | $this->remove_noise("''is", true); 533 | // strip out