├── .github └── dependabot.yml ├── .gitignore ├── CloudFirewallWHMCS.rar ├── LICENSE ├── README.md ├── composer.json ├── examples.php ├── src └── CloudFirewall.php ├── vendor ├── autoload.php └── composer │ ├── ClassLoader.php │ ├── LICENSE │ ├── autoload_classmap.php │ ├── autoload_namespaces.php │ ├── autoload_psr4.php │ ├── autoload_real.php │ ├── autoload_static.php │ └── installed.json └── versions.json /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: composer 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "11:00" 8 | open-pull-requests-limit: 10 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | /CloudFirewallWHMCS.rar 3 | /versions.json -------------------------------------------------------------------------------- /CloudFirewallWHMCS.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xaronnn/CloudFirewall/0cfbfea803826bad0aaa377c4b0c53a644fb215c/CloudFirewallWHMCS.rar -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 CloudFirewall - Uğur PEKESEN 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CloudFirewall 2 | Protect your website against bots/spam/flood, sql/xss injection attacks as using Cloudflare service. 3 | 4 | ![GitHub stars](https://img.shields.io/github/stars/0x5841524f4e/CloudFirewall) 5 | ![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/0x5841524f4e0x5841524f4e/CloudFirewall) 6 | ![GitHub](https://img.shields.io/github/license/0x5841524f4e/CloudFirewall) 7 | ![GitHub top language](https://img.shields.io/github/languages/top/0x5841524f4e/CloudFirewall) 8 | ![CodeFactor Grade](https://img.shields.io/codefactor/grade/github/0x5841524f4e/CloudFirewall) 9 | ![GitHub issues](https://img.shields.io/github/issues/0x5841524f4e/CloudFirewall) 10 | 11 | 12 | # Installation 13 | 14 | `composer require xaron/cloud-firewall` 15 | 16 | # WHMCS Module 17 | 18 | `Download: https://github.com/0x5841524f4e/CloudFirewall/raw/master/CloudFirewallWHMCS.rar` 19 | 20 | `Export files to your main WHMCS directory.` 21 | 22 | # Examples 23 | 24 | ```php 25 | changeSecurityLevel('medium', 'zone_id (Not required if already set in constructor)'); 40 | 41 | /* 42 | Create access rule. 43 | Actions: [block, challenge, whitelist, js_challenge] 44 | */ 45 | $firewall->createAccessRule('31.13.37.31', 'challenge'); 46 | 47 | /* 48 | Enabling block SQL injection attacks and it will ban from Cloudflare. 49 | Parameters: sqlInjectionBlock(true if you want request ip ban from Cloudflare. default is true.) 50 | */ 51 | $firewall->sqlInjectionBlock(); 52 | 53 | /* 54 | Enabling block XSS injection attacks and it will ban from Cloudflare. 55 | Parameters: xssInjectionBlock(true if you want request ip ban from Cloudflare. default is true.) 56 | */ 57 | $firewall->xssInjectionBlock(); 58 | 59 | /* 60 | Enabling block cookie steal attacks. 61 | Parameters: cookieStealBlock(true if you want request ip ban from Cloudflare. default is false.) 62 | */ 63 | $firewall->cookieStealBlock(); 64 | 65 | /* 66 | Enabling anti flood. 67 | Parameters: antiFlood(requestPerSecond, badRequestChance, badRequestResetInXseconds, banFromCloudflare) 68 | */ 69 | $firewall->antiFlood(1, 3, 5, true); 70 | 71 | /* 72 | Get script execution time. 73 | Info: Please write at the bottom of the page. 74 | Usage: echo($firewall->benchmark()); 75 | */ 76 | $firewall->benchmark(); 77 | ``` 78 | 79 | # Requirements 80 | 81 | - [x] PHP >= 7.1.* 82 | - [x] cURL extension 83 | - [x] OpenSSL extension 84 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "xaron/cloud-firewall", 3 | "type": "library", 4 | "description": "Protect your website against bots/spam/flood as using Cloudflare service.", 5 | "keywords": ["php", "cloudflare", "ddos", "block", "firewall", "sql", "injection", "xss", "flood", "protection"], 6 | "homepage": "https://xaron.us", 7 | "license": "MIT", 8 | "authors": [ 9 | { 10 | "name": "Uğur PEKESEN", 11 | "email": "me@xaron.us", 12 | "homepage": "http://xaron.us", 13 | "role": "Developer" 14 | } 15 | ], 16 | "require": { 17 | "php": "^7.1" 18 | }, 19 | "autoload": { 20 | "psr-4": { 21 | "CF\\": "src" 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /examples.php: -------------------------------------------------------------------------------- 1 | changeSecurityLevel('medium', 'zone_id (Not required if already set in constructor)'); 16 | 17 | /* 18 | Create access rule. 19 | Actions: [block, challenge, whitelist, js_challenge] 20 | */ 21 | $firewall->createAccessRule('31.13.37.31', 'block'); 22 | 23 | 24 | /* 25 | Enabling block SQL injection attacks and it will ban from Cloudflare. 26 | Parameters: sqlInjectionBlock(true if you want request ip ban from Cloudflare. default is true.) 27 | */ 28 | $firewall->sqlInjectionBlock(); 29 | 30 | /* 31 | Enabling block XSS injection attacks and it will ban from Cloudflare. 32 | Parameters: xssInjectionBlock(true if you want request ip ban from Cloudflare. default is true.) 33 | */ 34 | $firewall->xssInjectionBlock(); 35 | 36 | /* 37 | Enabling block cookie steal attacks. 38 | Parameters: cookieStealBlock(true if you want request ip ban from Cloudflare. default is true.) 39 | */ 40 | $firewall->cookieStealBlock(); 41 | 42 | /* 43 | Enabling anti flood. 44 | Parameters: antiFlood(requestPerSecond, badRequestChance, badRequestResetInXseconds, banFromCloudflare) 45 | */ 46 | $firewall->antiFlood(1, 3, 5, true); 47 | 48 | /* 49 | Get script execution time. 50 | Info: Please write at the bottom of the page. 51 | Usage: echo($firewall->benchmark()); 52 | */ 53 | $firewall->benchmark(); 54 | ?> -------------------------------------------------------------------------------- /src/CloudFirewall.php: -------------------------------------------------------------------------------- 1 | 7 | * @version 1.0.2 8 | */ 9 | 10 | namespace CF; 11 | 12 | class CloudFirewall { 13 | 14 | private $email, $key, $zone, $curl, $debug; 15 | protected $version = '1.0.2'; 16 | 17 | /** 18 | * CloudFirewall constructor. 19 | * 20 | * @param string $email The your Cloudflare email address. 21 | * @param string $key The your Cloudflare API key. 22 | * @param string $zone The your Cloudflare zone. 23 | */ 24 | public function __construct(string $email, string $key, string $zone = null) { 25 | $this->email = $email; 26 | $this->key = $key; 27 | $this->zone = $zone; 28 | $this->benchmarkStart = self::benchmarkStart(); 29 | if(isset($_SESSION)) { 30 | $_SESSION['CloudFirewall-Client-IP'] = $this->getIP(); 31 | } else { 32 | session_start(); 33 | $_SESSION['CloudFirewall-Client-IP'] = $this->getIP(); 34 | } 35 | set_error_handler(function($errno, $errstr, $errfile, $errline) { 36 | self::abort(500, 'Error: '.$errstr.' - Error Code '.$errno.'

File: '.$errfile.' - Line '.$errline.''); 37 | }); 38 | set_exception_handler(function($exception) { 39 | self::abort(500, $exception->getMessage()); 40 | }); 41 | header("x-powered-by: CloudFirewall WAF"); 42 | header("x-cloudfirewall: v".$this->version); 43 | self::requirements(); 44 | } 45 | 46 | /** 47 | * Changes security level on your zone. 48 | * 49 | * @param string $value The security levels [essentially_off, low, medium, high, under_attack]. 50 | * @param string $zone The zone id. 51 | * @return mixed Bool False if request is not responded. JSON if request success. 52 | */ 53 | public function changeSecurityLevel(string $value = 'low', string $zone = null) { 54 | if(self::checkSecurityLevel($value)) { 55 | if($zone) { 56 | return $this->connect('https://api.cloudflare.com/client/v4/zones/'.$zone.'/settings/security_level', 'PATCH', array('value' => $value)); 57 | } else { 58 | return $this->connect('https://api.cloudflare.com/client/v4/zones/'.$this->zone.'/settings/security_level', 'PATCH', array('value' => $value)); 59 | } 60 | } else { 61 | return false; 62 | } 63 | } 64 | 65 | /** 66 | * Create rule to specified IP address with an action. 67 | * 68 | * @param string $value The IP(v4/v6) address. 69 | * @param string $action The action [block, challenge, whitelist, js_challenge]. 70 | * @return mixed Bool False if request is not responded. JSON if request success. 71 | */ 72 | public function createAccessRule(string $value, string $action) { 73 | if(self::checkIP($value) && self::checkAccessRule($action)) { 74 | return $this->connect('https://api.cloudflare.com/client/v4/user/firewall/access_rules/rules', 'POST', array('mode' => $action, 'configuration' => array('target' => (self::checkIPv4($value) ? 'ip' : ($this->checkIPv4($value) ? 'ip6' : null)), 'value' => $value), 'notes' => 'Created by CloudFirewall')); 75 | } else { 76 | return false; 77 | } 78 | } 79 | 80 | /** 81 | * Enabling block SQL injection attacks. 82 | * 83 | * @param bool $ban Default is true and it will ban from Cloudflare. 84 | * @return none. 85 | */ 86 | public function sqlInjectionBlock(bool $ban = true) { 87 | foreach ($_GET as $key => $value) { 88 | if (is_array($value)) { 89 | $flattened = self::arrayFlatten($value); 90 | foreach ($flattened as $sub_key => $sub_value) { 91 | $this->sqlCheck($sub_value, "_GET", $sub_key, $ban); 92 | } 93 | } else { 94 | $this->sqlCheck($value, "_GET", $key, $ban); 95 | } 96 | } 97 | foreach ($_POST as $key => $value) { 98 | if (is_array($value)) { 99 | $flattened = self::arrayFlatten($value); 100 | foreach ($flattened as $sub_key => $sub_value) { 101 | $this->sqlCheck($sub_value, "_POST", $sub_key, $ban); 102 | } 103 | } else { 104 | $this->sqlCheck($value, "_POST", $key, $ban); 105 | } 106 | } 107 | foreach ($_COOKIE as $key => $value) { 108 | if (is_array($value)) { 109 | $flattened = self::arrayFlatten($value); 110 | foreach ($flattened as $sub_key => $sub_value) { 111 | $this->sqlCheck($sub_value, "_COOKIE", $sub_key, $ban); 112 | } 113 | } else { 114 | $this->sqlCheck($value, "_COOKIE", $key, $ban); 115 | } 116 | } 117 | } 118 | 119 | /** 120 | * Enabling block XSS injection attacks. 121 | * 122 | * @param bool $ban Default is true and it will ban from Cloudflare. 123 | * @return none. 124 | */ 125 | public function xssInjectionBlock(bool $ban = true) { 126 | foreach ($_GET as $key => $value) { 127 | if (is_array($value)) { 128 | $flattened = self::arrayFlatten($value); 129 | foreach ($flattened as $sub_key => $sub_value) { 130 | $this->xssCheck($sub_value, "GET", $sub_key, $ban); 131 | $this->htmlCheck($sub_value, "GET", $sub_key, $ban); 132 | } 133 | } else { 134 | $this->xssCheck($value, "GET", $key, $ban); 135 | $this->htmlCheck($value, "GET", $key, $ban); 136 | } 137 | } 138 | foreach ($_POST as $key => $value) { 139 | if (is_array($value)) { 140 | $flattened = self::arrayFlatten($value); 141 | foreach ($flattened as $sub_key => $sub_value) { 142 | $this->xssCheck($sub_value, "POST", $sub_key, $ban); 143 | $this->htmlCheck($sub_value, "POST", $sub_key, $ban); 144 | } 145 | } else { 146 | $this->xssCheck($value, "POST", $key, $ban); 147 | $this->htmlCheck($value, "POST", $key, $ban); 148 | } 149 | } 150 | foreach ($_COOKIE as $key => $value) { 151 | if (is_array($value)) { 152 | $flattened = self::arrayFlatten($value); 153 | foreach ($flattened as $sub_key => $sub_value) { 154 | $this->xssCheck($sub_value, "COOKIE", $sub_key, $ban); 155 | $this->htmlCheck($sub_value, "COOKIE", $sub_key, $ban); 156 | } 157 | } else { 158 | $this->xssCheck($value, "COOKIE", $key, $ban); 159 | $this->htmlCheck($value, "COOKIE", $key, $ban); 160 | } 161 | } 162 | } 163 | 164 | /** 165 | * Enabling block steal cookie attacks. 166 | * 167 | * @param bool $ban Default is false and it will ban from Cloudflare. 168 | * @return none. 169 | */ 170 | public function cookieStealBlock(bool $ban = false) { 171 | if (isset($_SESSION)) { 172 | if (!isset($_SESSION['CloudFirewall-Client-IP'])) { 173 | $_SESSION['CloudFirewall-Client-IP'] = $this->getIP(); 174 | } else { 175 | if ($_SESSION['CloudFirewall-Client-IP'] != $this->getIP()) { 176 | if($ban) { 177 | $this->createAccessRule($this->getIP(), 'block'); 178 | } 179 | session_destroy(); 180 | self::abort(403, 'Cookie Stealing Detected'); 181 | } 182 | } 183 | } 184 | } 185 | 186 | public function antiFlood(int $requestPerSecond = 2, int $badRequestChance = 3, int $badRequestReset = 5, bool $ban = false) { 187 | if(isset($_SESSION)) { 188 | if(!isset($_SESSION['CloudFirewall-Client-LastRequestTime']) && !isset($_SESSION['CloudFirewall-Client-BadRequest'])) { 189 | $_SESSION['CloudFirewall-Client-LastRequestTime'] = time(); 190 | $_SESSION['CloudFirewall-Client-BadRequest'] = 0; 191 | } else { 192 | if(isset($_SESSION['CloudFirewall-Client-LastBadRequestTime'])) { 193 | if($_SESSION['CloudFirewall-Client-LastBadRequestTime']+$badRequestReset <= time()) { 194 | unset($_SESSION['CloudFirewall-Client-LastBadRequestTime']); 195 | $_SESSION['CloudFirewall-Client-BadRequest'] = 0; 196 | } 197 | } 198 | if($_SESSION['CloudFirewall-Client-BadRequest'] >= $badRequestChance) { 199 | if($ban) { 200 | $this->createAccessRule($this->getIP(), 'block'); 201 | } 202 | $_SESSION['CloudFirewall-Client-LastBadRequestTime'] = time()+$requestPerSecond; 203 | self::abort(403, 'Flood Detected'); 204 | } 205 | if($_SESSION['CloudFirewall-Client-LastRequestTime'] >= time()) { 206 | $_SESSION['CloudFirewall-Client-LastBadRequestTime'] = time()+$requestPerSecond; 207 | $_SESSION['CloudFirewall-Client-BadRequest'] = $_SESSION['CloudFirewall-Client-BadRequest']+1; 208 | } 209 | } 210 | $_SESSION['CloudFirewall-Client-LastRequestTime'] = time(); 211 | } 212 | } 213 | 214 | /** 215 | * Enable debug mode. 216 | * 217 | * @return none. 218 | */ 219 | public function debug(bool $debug = false) { 220 | $this->debug = $debug; 221 | } 222 | 223 | /** 224 | * Get script execution time in seconds. 225 | * 226 | * @return float Script executed in X seconds. 227 | */ 228 | public function benchmark() { 229 | return self::benchmarkEnd($this->benchmarkStart); 230 | } 231 | 232 | private static function abort(int $status, string $message = null) { 233 | $statusses = ['404', '403', '500', '777']; 234 | if(in_array($status, $statusses)) { 235 | header('HTTP/1.0 '.$status.' Forbidden'); 236 | die(' '.$status.' - CloudFirewall

'.$status.'

'.($message ? '

'.$message.'

' : '').'




Ray ID: '.md5($status.$message.time()).' - Powered by CloudFirewall
'); 237 | } else { 238 | return false; 239 | } 240 | } 241 | 242 | private function xssCheck(string $value, string $method, string $displayName, bool $ban) { 243 | $replace = array("<3" => ":heart:"); 244 | foreach ($replace as $key => $value_rep) { 245 | $value = str_replace($key, $value_rep, $value); 246 | } 247 | $badWords = self::getVulnTypeData('XSS'); 248 | foreach ($badWords as $badWord) { 249 | if (strpos(strtolower($value), strtolower($badWord)) !== false) { 250 | if($ban) { 251 | $this->createAccessRule($this->getIP(), 'block'); 252 | } 253 | self::abort(403, 'XSS Injection Detected'); 254 | } 255 | } 256 | } 257 | 258 | private function sqlCheck(string $value, string $method, string $displayName, bool $ban) { 259 | $replace = array("can't" => "can not", "don't" => "do not"); 260 | foreach ($replace as $key => $value_rep) { 261 | $value = str_replace($key, $value_rep, $value); 262 | } 263 | $badWords = self::getVulnTypeData('SQL'); 264 | foreach ($badWords as $badWord) { 265 | if (strpos(strtolower($value), strtolower($badWord)) !== false) { 266 | if($ban) { 267 | $this->createAccessRule($this->getIP(), 'block'); 268 | } 269 | self::abort(403, 'SQL Injection Detected'); 270 | } 271 | } 272 | } 273 | 274 | private function htmlCheck(string $value, string $method, string $displayName, bool $ban) { 275 | if (self::is_html(strtolower($value)) !== false) { 276 | if($ban) { 277 | $this->createAccessRule($this->getIP(), 'block'); 278 | } 279 | self::abort(403, 'XSS Injection Detected'); 280 | } 281 | } 282 | 283 | protected static function is_html(string $string) { 284 | return ($string != strip_tags($string) ? true : false); 285 | } 286 | 287 | protected function getIP() { 288 | return (isset($_SERVER['HTTP_CF_CONNECTING_IP']) ? $_SERVER['HTTP_CF_CONNECTING_IP'] : $_SERVER['REMOTE_ADDR']); 289 | } 290 | 291 | private static function arrayFlatten(array $array) { 292 | $flatten = array(); 293 | array_walk_recursive($array, function($value) use(&$flatten) { 294 | $flatten[] = $value; 295 | }); 296 | return $flatten; 297 | } 298 | 299 | protected static function getVulnTypeData(string $type) { 300 | if($type && in_array($type, array('SQL', 'XSS'))) { 301 | $vuln['SQL'] = array( 302 | "'", 303 | '´', 304 | 'SELECT FROM', 305 | 'SELECT * FROM', 306 | 'ONION', 307 | 'union', 308 | 'UNION', 309 | 'TRUNCATE TABLE', 310 | 'INSERT INTO', 311 | 'UDPATE users SET', 312 | 'WHERE username', 313 | 'DROP TABLE', 314 | '0x50', 315 | 'mid((select', 316 | 'union(((((((', 317 | 'concat(0x', 318 | 'concat(', 319 | 'OR boolean', 320 | 'or HAVING', 321 | "OR '1", 322 | '0x3c62723e3c62723e3c62723e', 323 | '0x3c696d67207372633d22', 324 | '+#1q%0AuNiOn all#qa%0A#%0AsEleCt', 325 | 'unhex(hex(Concat(', 326 | 'Table_schema,0x3e,', 327 | '0x00', 328 | '0x08', 329 | '0x09', 330 | '0x0a', 331 | '0x0d', 332 | '0x1a', 333 | '0x22', 334 | '0x25', 335 | '0x27', 336 | '0x5c', 337 | '0x5f' 338 | ); 339 | $vuln['XSS'] = array('', 341 | 'style=', 342 | '', 356 | 'prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 178 | $this->prefixDirsPsr4[$prefix] = (array) $paths; 179 | } elseif ($prepend) { 180 | // Prepend directories for an already registered namespace. 181 | $this->prefixDirsPsr4[$prefix] = array_merge( 182 | (array) $paths, 183 | $this->prefixDirsPsr4[$prefix] 184 | ); 185 | } else { 186 | // Append directories for an already registered namespace. 187 | $this->prefixDirsPsr4[$prefix] = array_merge( 188 | $this->prefixDirsPsr4[$prefix], 189 | (array) $paths 190 | ); 191 | } 192 | } 193 | 194 | /** 195 | * Registers a set of PSR-0 directories for a given prefix, 196 | * replacing any others previously set for this prefix. 197 | * 198 | * @param string $prefix The prefix 199 | * @param array|string $paths The PSR-0 base directories 200 | */ 201 | public function set($prefix, $paths) 202 | { 203 | if (!$prefix) { 204 | $this->fallbackDirsPsr0 = (array) $paths; 205 | } else { 206 | $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; 207 | } 208 | } 209 | 210 | /** 211 | * Registers a set of PSR-4 directories for a given namespace, 212 | * replacing any others previously set for this namespace. 213 | * 214 | * @param string $prefix The prefix/namespace, with trailing '\\' 215 | * @param array|string $paths The PSR-4 base directories 216 | * 217 | * @throws \InvalidArgumentException 218 | */ 219 | public function setPsr4($prefix, $paths) 220 | { 221 | if (!$prefix) { 222 | $this->fallbackDirsPsr4 = (array) $paths; 223 | } else { 224 | $length = strlen($prefix); 225 | if ('\\' !== $prefix[$length - 1]) { 226 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); 227 | } 228 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 229 | $this->prefixDirsPsr4[$prefix] = (array) $paths; 230 | } 231 | } 232 | 233 | /** 234 | * Turns on searching the include path for class files. 235 | * 236 | * @param bool $useIncludePath 237 | */ 238 | public function setUseIncludePath($useIncludePath) 239 | { 240 | $this->useIncludePath = $useIncludePath; 241 | } 242 | 243 | /** 244 | * Can be used to check if the autoloader uses the include path to check 245 | * for classes. 246 | * 247 | * @return bool 248 | */ 249 | public function getUseIncludePath() 250 | { 251 | return $this->useIncludePath; 252 | } 253 | 254 | /** 255 | * Turns off searching the prefix and fallback directories for classes 256 | * that have not been registered with the class map. 257 | * 258 | * @param bool $classMapAuthoritative 259 | */ 260 | public function setClassMapAuthoritative($classMapAuthoritative) 261 | { 262 | $this->classMapAuthoritative = $classMapAuthoritative; 263 | } 264 | 265 | /** 266 | * Should class lookup fail if not found in the current class map? 267 | * 268 | * @return bool 269 | */ 270 | public function isClassMapAuthoritative() 271 | { 272 | return $this->classMapAuthoritative; 273 | } 274 | 275 | /** 276 | * APCu prefix to use to cache found/not-found classes, if the extension is enabled. 277 | * 278 | * @param string|null $apcuPrefix 279 | */ 280 | public function setApcuPrefix($apcuPrefix) 281 | { 282 | $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; 283 | } 284 | 285 | /** 286 | * The APCu prefix in use, or null if APCu caching is not enabled. 287 | * 288 | * @return string|null 289 | */ 290 | public function getApcuPrefix() 291 | { 292 | return $this->apcuPrefix; 293 | } 294 | 295 | /** 296 | * Registers this instance as an autoloader. 297 | * 298 | * @param bool $prepend Whether to prepend the autoloader or not 299 | */ 300 | public function register($prepend = false) 301 | { 302 | spl_autoload_register(array($this, 'loadClass'), true, $prepend); 303 | } 304 | 305 | /** 306 | * Unregisters this instance as an autoloader. 307 | */ 308 | public function unregister() 309 | { 310 | spl_autoload_unregister(array($this, 'loadClass')); 311 | } 312 | 313 | /** 314 | * Loads the given class or interface. 315 | * 316 | * @param string $class The name of the class 317 | * @return bool|null True if loaded, null otherwise 318 | */ 319 | public function loadClass($class) 320 | { 321 | if ($file = $this->findFile($class)) { 322 | includeFile($file); 323 | 324 | return true; 325 | } 326 | } 327 | 328 | /** 329 | * Finds the path to the file where the class is defined. 330 | * 331 | * @param string $class The name of the class 332 | * 333 | * @return string|false The path if found, false otherwise 334 | */ 335 | public function findFile($class) 336 | { 337 | // class map lookup 338 | if (isset($this->classMap[$class])) { 339 | return $this->classMap[$class]; 340 | } 341 | if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { 342 | return false; 343 | } 344 | if (null !== $this->apcuPrefix) { 345 | $file = apcu_fetch($this->apcuPrefix.$class, $hit); 346 | if ($hit) { 347 | return $file; 348 | } 349 | } 350 | 351 | $file = $this->findFileWithExtension($class, '.php'); 352 | 353 | // Search for Hack files if we are running on HHVM 354 | if (false === $file && defined('HHVM_VERSION')) { 355 | $file = $this->findFileWithExtension($class, '.hh'); 356 | } 357 | 358 | if (null !== $this->apcuPrefix) { 359 | apcu_add($this->apcuPrefix.$class, $file); 360 | } 361 | 362 | if (false === $file) { 363 | // Remember that this class does not exist. 364 | $this->missingClasses[$class] = true; 365 | } 366 | 367 | return $file; 368 | } 369 | 370 | private function findFileWithExtension($class, $ext) 371 | { 372 | // PSR-4 lookup 373 | $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; 374 | 375 | $first = $class[0]; 376 | if (isset($this->prefixLengthsPsr4[$first])) { 377 | $subPath = $class; 378 | while (false !== $lastPos = strrpos($subPath, '\\')) { 379 | $subPath = substr($subPath, 0, $lastPos); 380 | $search = $subPath . '\\'; 381 | if (isset($this->prefixDirsPsr4[$search])) { 382 | $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); 383 | foreach ($this->prefixDirsPsr4[$search] as $dir) { 384 | if (file_exists($file = $dir . $pathEnd)) { 385 | return $file; 386 | } 387 | } 388 | } 389 | } 390 | } 391 | 392 | // PSR-4 fallback dirs 393 | foreach ($this->fallbackDirsPsr4 as $dir) { 394 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { 395 | return $file; 396 | } 397 | } 398 | 399 | // PSR-0 lookup 400 | if (false !== $pos = strrpos($class, '\\')) { 401 | // namespaced class name 402 | $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) 403 | . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); 404 | } else { 405 | // PEAR-like class name 406 | $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; 407 | } 408 | 409 | if (isset($this->prefixesPsr0[$first])) { 410 | foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { 411 | if (0 === strpos($class, $prefix)) { 412 | foreach ($dirs as $dir) { 413 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { 414 | return $file; 415 | } 416 | } 417 | } 418 | } 419 | } 420 | 421 | // PSR-0 fallback dirs 422 | foreach ($this->fallbackDirsPsr0 as $dir) { 423 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { 424 | return $file; 425 | } 426 | } 427 | 428 | // PSR-0 include paths. 429 | if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { 430 | return $file; 431 | } 432 | 433 | return false; 434 | } 435 | } 436 | 437 | /** 438 | * Scope isolated include. 439 | * 440 | * Prevents access to $this/self from included files. 441 | */ 442 | function includeFile($file) 443 | { 444 | include $file; 445 | } 446 | -------------------------------------------------------------------------------- /vendor/composer/LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Copyright (c) Nils Adermann, Jordi Boggiano 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is furnished 9 | to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | -------------------------------------------------------------------------------- /vendor/composer/autoload_classmap.php: -------------------------------------------------------------------------------- 1 | array($baseDir . '/src'), 10 | ); 11 | -------------------------------------------------------------------------------- /vendor/composer/autoload_real.php: -------------------------------------------------------------------------------- 1 | = 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); 30 | if ($useStaticLoader) { 31 | require_once __DIR__ . '/autoload_static.php'; 32 | 33 | call_user_func(\Composer\Autoload\ComposerStaticInit30386fd83e5ea28747521c9249214186::getInitializer($loader)); 34 | } else { 35 | $map = require __DIR__ . '/autoload_namespaces.php'; 36 | foreach ($map as $namespace => $path) { 37 | $loader->set($namespace, $path); 38 | } 39 | 40 | $map = require __DIR__ . '/autoload_psr4.php'; 41 | foreach ($map as $namespace => $path) { 42 | $loader->setPsr4($namespace, $path); 43 | } 44 | 45 | $classMap = require __DIR__ . '/autoload_classmap.php'; 46 | if ($classMap) { 47 | $loader->addClassMap($classMap); 48 | } 49 | } 50 | 51 | $loader->register(true); 52 | 53 | return $loader; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /vendor/composer/autoload_static.php: -------------------------------------------------------------------------------- 1 | 11 | array ( 12 | 'CF\\' => 3, 13 | ), 14 | ); 15 | 16 | public static $prefixDirsPsr4 = array ( 17 | 'CF\\' => 18 | array ( 19 | 0 => __DIR__ . '/../..' . '/src', 20 | ), 21 | ); 22 | 23 | public static function getInitializer(ClassLoader $loader) 24 | { 25 | return \Closure::bind(function () use ($loader) { 26 | $loader->prefixLengthsPsr4 = ComposerStaticInit30386fd83e5ea28747521c9249214186::$prefixLengthsPsr4; 27 | $loader->prefixDirsPsr4 = ComposerStaticInit30386fd83e5ea28747521c9249214186::$prefixDirsPsr4; 28 | 29 | }, null, ClassLoader::class); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /vendor/composer/installed.json: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /versions.json: -------------------------------------------------------------------------------- 1 | { 2 | "whmcs": "0.1.4.6", 3 | "wordpress": "0.1.4.6" 4 | } --------------------------------------------------------------------------------