Error 404
153 |Resource not found.
154 |├── 404.html ├── LICENSE ├── README.md ├── app.js ├── backend.php ├── dark-fomantic-ui.js ├── echarts ├── echarts.chalk.js ├── echarts.macarons.js ├── echarts.purple-passion.js ├── echarts.vintage.js ├── echarts.walden.js ├── echarts.westeros.js └── echarts.wonderland.js ├── fatfree-master.zip ├── fatfree-master ├── .gitignore ├── .htaccess ├── composer.json ├── config.ini ├── index.php ├── lib │ ├── CHANGELOG.md │ ├── COPYING │ ├── audit.php │ ├── auth.php │ ├── base.php │ ├── basket.php │ ├── bcrypt.php │ ├── cli │ │ └── ws.php │ ├── code.css │ ├── db │ │ ├── cursor.php │ │ ├── jig.php │ │ ├── jig │ │ │ ├── mapper.php │ │ │ └── session.php │ │ ├── mongo.php │ │ ├── mongo │ │ │ ├── mapper.php │ │ │ └── session.php │ │ ├── sql.php │ │ └── sql │ │ │ ├── mapper.php │ │ │ └── session.php │ ├── f3.php │ ├── image.php │ ├── log.php │ ├── magic.php │ ├── markdown.php │ ├── matrix.php │ ├── session.php │ ├── smtp.php │ ├── template.php │ ├── test.php │ ├── utf.php │ ├── web.php │ └── web │ │ ├── geo.php │ │ ├── google │ │ ├── recaptcha.php │ │ └── staticmap.php │ │ ├── oauth2.php │ │ ├── openid.php │ │ └── pingback.php ├── readme.md └── ui │ ├── css │ ├── base.css │ └── theme.css │ ├── images │ ├── logo.png │ ├── paypal.png │ └── twitter.png │ ├── layout.htm │ ├── userref.htm │ └── welcome.htm ├── index.html ├── package-lock.json ├── package.json ├── parser.js ├── server.js ├── server.php ├── ui.css ├── ui.js └── ui.wrappers.js /404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 |Resource not found.
154 |' . PHP_EOL; 24 | print_r($f3); 25 | echo '' . PHP_EOL; 26 | } 27 | ); 28 | $f3->route('GET /info', 29 | function() { 30 | phpinfo(); 31 | } 32 | ); 33 | $f3->route('GET /queue', 34 | function() { 35 | echo '
' . PHP_EOL; 36 | echo 'Showing nmap process queue:' . PHP_EOL . PHP_EOL; 37 | passthru('ps -efH | grep -v grep | grep nmap'); 38 | echo '' . PHP_EOL; 39 | } 40 | ); 41 | $f3->route('GET /report', 42 | function($f3) { 43 | header('Content-Type: text/xml'); 44 | $report = $f3->read(sys_get_temp_dir() . '/report.xml'); 45 | echo $report; 46 | } 47 | ); 48 | $f3->route('GET /report/@format', 49 | function($f3, $params) { 50 | switch ($params['format']) { 51 | case 'html': 52 | echo '
' . PHP_EOL; 53 | echo 'Reading XML report: ' . sys_get_temp_dir() . '/report.xml' . PHP_EOL; 54 | passthru('file ' . sys_get_temp_dir() . '/report.xml'); 55 | echo PHP_EOL . htmlentities($f3->read(sys_get_temp_dir() . '/report.xml')); 56 | echo '' . PHP_EOL; 57 | break; 58 | 59 | case 'raw': 60 | echo 'Reading XML report: ' . sys_get_temp_dir() . '/report.xml' . PHP_EOL; 61 | passthru('file ' . sys_get_temp_dir() . '/report.xml'); 62 | echo PHP_EOL . $f3->read(sys_get_temp_dir() . '/report.xml') . PHP_EOL; 63 | break; 64 | 65 | default: 66 | echo 'Unsupported format.' . PHP_EOL; 67 | break; 68 | } 69 | } 70 | ); 71 | $f3->route('GET /help', 72 | function() { 73 | echo '
' . PHP_EOL; 74 | echo 'Running cmd: /usr/bin/nmap --help' . PHP_EOL . PHP_EOL; 75 | passthru('/usr/bin/nmap --help'); 76 | echo '' . PHP_EOL; 77 | } 78 | ); 79 | $f3->route('POST /scan/@target', 80 | function($f3, $params) { 81 | // passthru('sudo /usr/bin/nmap -A -sS -vv -Pn localhost -oX /tmp/report.xml 2>&1 &'); 82 | // passthru('sudo /usr/bin/nmap -A -sS -vv -Pn localhost -oX /tmp/report.xml 2>&1'); 83 | if (!empty($params['target'])) { 84 | passthru('sudo /usr/bin/nmap -A -sS -vv -Pn ' . escapeshellarg(base64_decode($params['target'])) . ' -oX /tmp/report.xml 2>&1'); 85 | } 86 | else { 87 | echo 'Host not defined.' . PHP_EOL; 88 | } 89 | } 90 | ); 91 | $f3->run(); -------------------------------------------------------------------------------- /dark-fomantic-ui.js: -------------------------------------------------------------------------------- 1 | /** 2 | * MIT License 3 | * 4 | * Copyright (c) 2020 Jonathan Barda 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | "use strict"; 26 | 27 | // Manual selection 28 | window.init = { 29 | theme: '' 30 | }; 31 | 32 | // Boot stuff when DOM is loaded 33 | $(function () { 34 | console.group('Dark Fomantic-UI'); 35 | console.log('DOM Loaded.'); 36 | 37 | // ui theme elements 38 | var $themeElements = [ 39 | { name: 'lists', target: $('.ui.list').not('.inverted') }, 40 | { name: 'dividers', target: $('.ui.divider').not('.inverted') }, 41 | { name: 'dividingHeaders', target: $('.ui.dividing.header').not('.inverted') }, 42 | { name: 'iconHeaders', target: $('.ui.icon.header').not('.inverted') }, 43 | { name: 'icons', target: $('.icon').not('.button').not('.inverted').not('.close') }, 44 | { name: 'headers', target: $('.ui.header').not('.inverted') }, 45 | { name: 'forms', target: $('.ui.form').not('.inverted') }, 46 | // { name: 'tooltippedIcons', target: $('.tooltipped.icon') }, 47 | { name: 'cardsContainer', target: $('.ui.cards').not('.inverted') }, 48 | { name: 'cards', target: $('.ui.card').not('.inverted') }, 49 | { name: 'labels', target: $('.ui.label').not('.inverted') }, 50 | { name: 'dropdowns', target: $('.ui.dropdown').not('.search').not('.multiple') }, 51 | { name: 'fixedMenu', target: $('.ui.top.fixed.menu').not('.inverted') }, 52 | { name: 'breadcrumb', target: $('.ui.breadcrumb').not('.inverted') }, 53 | { name: 'accordions', target: $('.ui.accordion').not('.styled').not('.inverted') }, 54 | { name: 'tables', target: $('.ui.table').not('.inverted') }, 55 | { name: 'modals', target: $('.ui.modal').not('.inverted') }, 56 | { name: 'segments', target: $('.ui.segment').not('.inverted') }, 57 | { name: 'placeholders', target: $('.ui.placeholder').not('.inverted') } 58 | ]; 59 | var $themeValue = $('#theme-value'); 60 | var $darkThemeButton = $('div.right.menu div#dark-theme'); 61 | var $lightThemeButton = $('div.right.menu div#light-theme'); 62 | 63 | // query light / dark theme selection 64 | if (window.matchMedia('(prefers-color-scheme)').media !== 'not all') { 65 | console.log('🎉 Dark mode is supported'); 66 | 67 | // detect dark mode 68 | var darkMatcher = window.matchMedia('(prefers-color-scheme: dark)'); 69 | 70 | // attach dark mode listener 71 | darkMatcher.addListener(onUpdate); 72 | 73 | // remove listener on window unload 74 | window.unload = function (event) { 75 | console.log('window unloaded.', event); 76 | console.log('removing listeners.'); 77 | 78 | darkMatcher.removeListener(onUpdate); 79 | } 80 | 81 | // set and display initial theme value 82 | $themeValue.text((darkMatcher.matches === true ? 'dark' : 'light') + ' (media-query)'); 83 | window.init.theme = (darkMatcher.matches === true ? 'dark' : 'light'); 84 | 85 | // try to restore existing user selection first 86 | if (storageAvailable('sessionStorage')) { 87 | // Great! We can use sessionStorage awesomeness 88 | restoreState(); 89 | } 90 | 91 | // apply detected theme anyway 92 | else { 93 | // Too bad, no sessionStorage for us 94 | console.warn('Storage [sessionStorage] no available. Applying detected theme.'); 95 | } 96 | 97 | // initial theme buttons state 98 | if (darkMatcher.matches === true || window.init.theme === 'dark') { 99 | $lightThemeButton.toggleClass('hide'); 100 | } 101 | else { 102 | $darkThemeButton.toggleClass('hide'); 103 | } 104 | 105 | // apply defined theme 106 | applyTheme(); 107 | } 108 | 109 | console.groupEnd(); 110 | 111 | // light / dark theme buttons 112 | $darkThemeButton.on('click', function (event) { 113 | console.group('Dark Fomantic-UI'); 114 | console.log('Theme selector clicked.', event); 115 | 116 | // inverted logic because of animated buttons 117 | window.init.theme = 'light'; 118 | 119 | // display active theme 120 | $themeValue.text(window.init.theme + ' (user-event)'); 121 | 122 | // delayed button change 123 | var toggleState = setTimeout(function(){ 124 | switchButtons(); 125 | clearTimeout(toggleState); 126 | }, 600); 127 | 128 | // refresh DOM elements 129 | // refresh(); 130 | 131 | // apply defined theme 132 | applyTheme(); 133 | 134 | console.groupEnd(); 135 | }); 136 | $lightThemeButton.on('click', function (event) { 137 | console.group('Dark Fomantic-UI'); 138 | console.log('Theme selector clicked.', event); 139 | 140 | // inverted logic because of animated buttons 141 | window.init.theme = 'dark'; 142 | 143 | // display active theme 144 | $themeValue.text(window.init.theme + ' (user-event)'); 145 | 146 | // delayed button change 147 | var toggleState = setTimeout(function(){ 148 | switchButtons(); 149 | clearTimeout(toggleState); 150 | }, 600); 151 | 152 | // refresh DOM elements 153 | // refresh(); 154 | 155 | // apply defined theme 156 | applyTheme(); 157 | 158 | console.groupEnd(); 159 | }); 160 | 161 | // light / dark theme event handler 162 | function onUpdate(event) { 163 | console.group('Dark Fomantic-UI'); 164 | console.log('Theme changed.', event); 165 | console.log('Previous theme value:', window.init.theme); 166 | 167 | // set and display gathered theme value 168 | window.init.theme = (event.matches === true ? 'dark' : 'light'); 169 | $themeValue.text(window.init.theme + ' (media-event)'); 170 | 171 | // toggle theme buttons 172 | switchButtons(); 173 | 174 | // apply gathered theme 175 | applyTheme(); 176 | 177 | console.groupEnd(); 178 | } 179 | 180 | // light / dark theme button toggler 181 | function switchButtons() { 182 | $darkThemeButton.toggleClass('hide'); 183 | $lightThemeButton.toggleClass('hide'); 184 | } 185 | 186 | // light / dark theme apply 187 | function applyTheme() { 188 | console.log('Theme applied.', (!event ? '(auto/session)' : event)); 189 | console.log('New theme value:', window.init.theme); 190 | console.log('Dark mode is ' + (window.init.theme === 'dark' ? '🌒 on' : '☀️ off') + '.'); 191 | console.log('Theme elements:'); 192 | console.table($themeElements); 193 | $($themeElements).each(function () { 194 | console.log('Styling element [' + $(this)[0].name + ']:', $(this)[0].target); 195 | }); 196 | 197 | switch (window.init.theme) { 198 | case 'dark': 199 | $($themeElements).each(function () { 200 | var $target = $(this)[0].target; 201 | 202 | // Apply dark theme 203 | $target.addClass('inverted'); 204 | 205 | // Remove uggly extra shadow 206 | if ($target.hasClass('floating')) { 207 | $target.removeClass('floating'); 208 | $target.addClass('floating-disabled'); 209 | } 210 | }); 211 | 212 | // Apply dark theme on tooltips 213 | $('.tooltipped').attr('data-variation', 'inverted'); 214 | break; 215 | 216 | case 'light': 217 | default: 218 | $($themeElements).each(function () { 219 | var $target = $(this)[0].target; 220 | 221 | // Remove dark theme 222 | $target.removeClass('inverted'); 223 | 224 | // Add nice floating shadow 225 | if ($target.hasClass('floating-disabled')) { 226 | $target.removeClass('floating-disabled'); 227 | $target.addClass('floating'); 228 | } 229 | }); 230 | 231 | // Remove dark theme on tooltips 232 | $('.tooltipped').attr('data-variation', ''); 233 | break; 234 | } 235 | 236 | // Save user selection 237 | saveState(window.init.theme); 238 | } 239 | 240 | // Detect dynamic elements 241 | function refresh() { 242 | $themeElements = null; 243 | $themeElements = [ 244 | { name: 'dividingHeaders', target: $('.ui.dividing.header') }, 245 | { name: 'iconHeaders', target: $('.ui.icon.header') }, 246 | { name: 'tooltippedIcons', target: $('.tooltipped.icon') }, 247 | { name: 'cardsContainer', target: $('.ui.cards') }, 248 | { name: 'cards', target: $('.ui.card') }, 249 | { name: 'dropdowns', target: $('.ui.dropdown') }, 250 | { name: 'fixedMenu', target: $('.ui.top.fixed.menu') }, 251 | { name: 'breadcrumb', target: $('.ui.breadcrumb') }, 252 | { name: 'accordions', target: $('.ui.accordion').not('.styled').not('.inverted') }, 253 | { name: 'tables', target: $('.ui.table') }, 254 | { name: 'segments', target: $('.ui.segment').not('.inverted') }, 255 | { name: 'placeholders', target: $('.ui.placeholder') } 256 | ]; 257 | } 258 | 259 | // Detect if the Web Storage API is available 260 | // Taken from: https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API 261 | function storageAvailable(type) { 262 | var storage; 263 | try { 264 | storage = window[type]; 265 | var x = '__storage_test__'; 266 | storage.setItem(x, x); 267 | storage.removeItem(x); 268 | return true; 269 | } 270 | catch(e) { 271 | return e instanceof DOMException && ( 272 | // everything except Firefox 273 | e.code === 22 || 274 | // Firefox 275 | e.code === 1014 || 276 | // test name field too, because code might not be present 277 | // everything except Firefox 278 | e.name === 'QuotaExceededError' || 279 | // Firefox 280 | e.name === 'NS_ERROR_DOM_QUOTA_REACHED') && 281 | // acknowledge QuotaExceededError only if there's something already stored 282 | (storage && storage.length !== 0); 283 | } 284 | } 285 | 286 | // Store user selection in sessionStorage 287 | function restoreState() { 288 | if (storageAvailable('sessionStorage')) { 289 | // Great! We can use sessionStorage awesomeness 290 | console.log('Restoring user selection from session storage.'); 291 | window.init.theme = sessionStorage.getItem('currentTheme'); 292 | 293 | // toggle theme buttons 294 | // switchButtons(); 295 | } 296 | else { 297 | // Too bad, no sessionStorage for us 298 | console.warn('Storage [sessionStorage] no available. Can\'t restore user selected theme.'); 299 | } 300 | } 301 | 302 | // Store user selection in sessionStorage 303 | function saveState(theme) { 304 | if (storageAvailable('sessionStorage')) { 305 | // Great! We can use sessionStorage awesomeness 306 | if (theme !== null) { 307 | console.log('Saving user selection to session storage.'); 308 | sessionStorage.setItem('currentTheme', theme); 309 | } 310 | } 311 | else { 312 | // Too bad, no sessionStorage for us 313 | console.warn('Storage [sessionStorage] no available. Can\'t store user selected theme.'); 314 | } 315 | } 316 | }); 317 | -------------------------------------------------------------------------------- /fatfree-master.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jiab77/nmap-webui/a6d70c16170c7e53a8cdfc247ffe6d0912e741a0/fatfree-master.zip -------------------------------------------------------------------------------- /fatfree-master/.gitignore: -------------------------------------------------------------------------------- 1 | /tmp/ 2 | /.idea/ 3 | -------------------------------------------------------------------------------- /fatfree-master/.htaccess: -------------------------------------------------------------------------------- 1 | # Enable rewrite engine and route requests to framework 2 | RewriteEngine On 3 | 4 | # Some servers require you to specify the `RewriteBase` directive 5 | # In such cases, it should be the path (relative to the document root) 6 | # containing this .htaccess file 7 | # 8 | # RewriteBase / 9 | 10 | RewriteRule ^(app|tmp)\/|\.ini$ - [R=404] 11 | 12 | RewriteCond %{REQUEST_FILENAME} !-l 13 | RewriteCond %{REQUEST_FILENAME} !-f 14 | RewriteCond %{REQUEST_FILENAME} !-d 15 | RewriteRule .* index.php [L,QSA] 16 | RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L] 17 | -------------------------------------------------------------------------------- /fatfree-master/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bcosca/fatfree", 3 | "description": "A powerful yet easy-to-use PHP micro-framework designed to help you build dynamic and robust Web applications - fast!", 4 | "homepage": "http://fatfreeframework.com/", 5 | "license": "GPL-3.0", 6 | "require": { 7 | "php": ">=5.4" 8 | }, 9 | "repositories": [ 10 | { 11 | "type": "vcs", 12 | "url": "https://github.com/bcosca/fatfree" 13 | } 14 | ], 15 | "autoload": { 16 | "files": ["lib/base.php"] 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /fatfree-master/config.ini: -------------------------------------------------------------------------------- 1 | [globals] 2 | 3 | DEBUG=3 4 | UI=ui/ 5 | -------------------------------------------------------------------------------- /fatfree-master/index.php: -------------------------------------------------------------------------------- 1 | set('DEBUG',1); 7 | if ((float)PCRE_VERSION<8.0) 8 | trigger_error('PCRE version is out of date'); 9 | 10 | // Load configuration 11 | $f3->config('config.ini'); 12 | 13 | $f3->route('GET /', 14 | function($f3) { 15 | $classes=array( 16 | 'Base'=> 17 | array( 18 | 'hash', 19 | 'json', 20 | 'session', 21 | 'mbstring' 22 | ), 23 | 'Cache'=> 24 | array( 25 | 'apc', 26 | 'apcu', 27 | 'memcache', 28 | 'memcached', 29 | 'redis', 30 | 'wincache', 31 | 'xcache' 32 | ), 33 | 'DB\SQL'=> 34 | array( 35 | 'pdo', 36 | 'pdo_dblib', 37 | 'pdo_mssql', 38 | 'pdo_mysql', 39 | 'pdo_odbc', 40 | 'pdo_pgsql', 41 | 'pdo_sqlite', 42 | 'pdo_sqlsrv' 43 | ), 44 | 'DB\Jig'=> 45 | array('json'), 46 | 'DB\Mongo'=> 47 | array( 48 | 'json', 49 | 'mongo' 50 | ), 51 | 'Auth'=> 52 | array('ldap','pdo'), 53 | 'Bcrypt'=> 54 | array( 55 | 'openssl' 56 | ), 57 | 'Image'=> 58 | array('gd'), 59 | 'Lexicon'=> 60 | array('iconv'), 61 | 'SMTP'=> 62 | array('openssl'), 63 | 'Web'=> 64 | array('curl','openssl','simplexml'), 65 | 'Web\Geo'=> 66 | array('geoip','json'), 67 | 'Web\OpenID'=> 68 | array('json','simplexml'), 69 | 'Web\OAuth2'=> 70 | array('json'), 71 | 'Web\Pingback'=> 72 | array('dom','xmlrpc'), 73 | 'CLI\WS'=> 74 | array('pcntl') 75 | ); 76 | $f3->set('classes',$classes); 77 | $f3->set('content','welcome.htm'); 78 | echo View::instance()->render('layout.htm'); 79 | } 80 | ); 81 | 82 | $f3->route('GET /userref', 83 | function($f3) { 84 | $f3->set('content','userref.htm'); 85 | echo View::instance()->render('layout.htm'); 86 | } 87 | ); 88 | 89 | $f3->run(); 90 | -------------------------------------------------------------------------------- /fatfree-master/lib/audit.php: -------------------------------------------------------------------------------- 1 | . 20 | 21 | */ 22 | 23 | //! Data validator 24 | class Audit extends Prefab { 25 | 26 | //@{ User agents 27 | const 28 | UA_Mobile='android|blackberry|phone|ipod|palm|windows\s+ce', 29 | UA_Desktop='bsd|linux|os\s+[x9]|solaris|windows', 30 | UA_Bot='bot|crawl|slurp|spider'; 31 | //@} 32 | 33 | /** 34 | * Return TRUE if string is a valid URL 35 | * @return bool 36 | * @param $str string 37 | **/ 38 | function url($str) { 39 | return is_string(filter_var($str,FILTER_VALIDATE_URL)); 40 | } 41 | 42 | /** 43 | * Return TRUE if string is a valid e-mail address; 44 | * Check DNS MX records if specified 45 | * @return bool 46 | * @param $str string 47 | * @param $mx boolean 48 | **/ 49 | function email($str,$mx=TRUE) { 50 | $hosts=[]; 51 | return is_string(filter_var($str,FILTER_VALIDATE_EMAIL)) && 52 | (!$mx || getmxrr(substr($str,strrpos($str,'@')+1),$hosts)); 53 | } 54 | 55 | /** 56 | * Return TRUE if string is a valid IPV4 address 57 | * @return bool 58 | * @param $addr string 59 | **/ 60 | function ipv4($addr) { 61 | return (bool)filter_var($addr,FILTER_VALIDATE_IP,FILTER_FLAG_IPV4); 62 | } 63 | 64 | /** 65 | * Return TRUE if string is a valid IPV6 address 66 | * @return bool 67 | * @param $addr string 68 | **/ 69 | function ipv6($addr) { 70 | return (bool)filter_var($addr,FILTER_VALIDATE_IP,FILTER_FLAG_IPV6); 71 | } 72 | 73 | /** 74 | * Return TRUE if IP address is within private range 75 | * @return bool 76 | * @param $addr string 77 | **/ 78 | function isprivate($addr) { 79 | return !(bool)filter_var($addr,FILTER_VALIDATE_IP, 80 | FILTER_FLAG_IPV4|FILTER_FLAG_IPV6|FILTER_FLAG_NO_PRIV_RANGE); 81 | } 82 | 83 | /** 84 | * Return TRUE if IP address is within reserved range 85 | * @return bool 86 | * @param $addr string 87 | **/ 88 | function isreserved($addr) { 89 | return !(bool)filter_var($addr,FILTER_VALIDATE_IP, 90 | FILTER_FLAG_IPV4|FILTER_FLAG_IPV6|FILTER_FLAG_NO_RES_RANGE); 91 | } 92 | 93 | /** 94 | * Return TRUE if IP address is neither private nor reserved 95 | * @return bool 96 | * @param $addr string 97 | **/ 98 | function ispublic($addr) { 99 | return (bool)filter_var($addr,FILTER_VALIDATE_IP, 100 | FILTER_FLAG_IPV4|FILTER_FLAG_IPV6| 101 | FILTER_FLAG_NO_PRIV_RANGE|FILTER_FLAG_NO_RES_RANGE); 102 | } 103 | 104 | /** 105 | * Return TRUE if user agent is a desktop browser 106 | * @return bool 107 | * @param $agent string 108 | **/ 109 | function isdesktop($agent=NULL) { 110 | if (!isset($agent)) 111 | $agent=Base::instance()->AGENT; 112 | return (bool)preg_match('/('.self::UA_Desktop.')/i',$agent) && 113 | !$this->ismobile($agent); 114 | } 115 | 116 | /** 117 | * Return TRUE if user agent is a mobile device 118 | * @return bool 119 | * @param $agent string 120 | **/ 121 | function ismobile($agent=NULL) { 122 | if (!isset($agent)) 123 | $agent=Base::instance()->AGENT; 124 | return (bool)preg_match('/('.self::UA_Mobile.')/i',$agent); 125 | } 126 | 127 | /** 128 | * Return TRUE if user agent is a Web bot 129 | * @return bool 130 | * @param $agent string 131 | **/ 132 | function isbot($agent=NULL) { 133 | if (!isset($agent)) 134 | $agent=Base::instance()->AGENT; 135 | return (bool)preg_match('/('.self::UA_Bot.')/i',$agent); 136 | } 137 | 138 | /** 139 | * Return TRUE if specified ID has a valid (Luhn) Mod-10 check digit 140 | * @return bool 141 | * @param $id string 142 | **/ 143 | function mod10($id) { 144 | if (!ctype_digit($id)) 145 | return FALSE; 146 | $id=strrev($id); 147 | $sum=0; 148 | for ($i=0,$l=strlen($id);$i<$l;$i++) 149 | $sum+=$id[$i]+$i%2*(($id[$i]>4)*-4+$id[$i]%5); 150 | return !($sum%10); 151 | } 152 | 153 | /** 154 | * Return credit card type if number is valid 155 | * @return string|FALSE 156 | * @param $id string 157 | **/ 158 | function card($id) { 159 | $id=preg_replace('/[^\d]/','',$id); 160 | if ($this->mod10($id)) { 161 | if (preg_match('/^3[47][0-9]{13}$/',$id)) 162 | return 'American Express'; 163 | if (preg_match('/^3(?:0[0-5]|[68][0-9])[0-9]{11}$/',$id)) 164 | return 'Diners Club'; 165 | if (preg_match('/^6(?:011|5[0-9][0-9])[0-9]{12}$/',$id)) 166 | return 'Discover'; 167 | if (preg_match('/^(?:2131|1800|35\d{3})\d{11}$/',$id)) 168 | return 'JCB'; 169 | if (preg_match('/^5[1-5][0-9]{14}$|'. 170 | '^(222[1-9]|2[3-6]\d{2}|27[0-1]\d|2720)\d{12}$/',$id)) 171 | return 'MasterCard'; 172 | if (preg_match('/^4[0-9]{12}(?:[0-9]{3})?$/',$id)) 173 | return 'Visa'; 174 | } 175 | return FALSE; 176 | } 177 | 178 | /** 179 | * Return entropy estimate of a password (NIST 800-63) 180 | * @return int|float 181 | * @param $str string 182 | **/ 183 | function entropy($str) { 184 | $len=strlen($str); 185 | return 4*min($len,1)+($len>1?(2*(min($len,8)-1)):0)+ 186 | ($len>8?(1.5*(min($len,20)-8)):0)+($len>20?($len-20):0)+ 187 | 6*(bool)(preg_match( 188 | '/[A-Z].*?[0-9[:punct:]]|[0-9[:punct:]].*?[A-Z]/',$str)); 189 | } 190 | 191 | } 192 | -------------------------------------------------------------------------------- /fatfree-master/lib/auth.php: -------------------------------------------------------------------------------- 1 | . 20 | 21 | */ 22 | 23 | //! Authorization/authentication plug-in 24 | class Auth { 25 | 26 | //@{ Error messages 27 | const 28 | E_LDAP='LDAP connection failure', 29 | E_SMTP='SMTP connection failure'; 30 | //@} 31 | 32 | protected 33 | //! Auth storage 34 | $storage, 35 | //! Mapper object 36 | $mapper, 37 | //! Storage options 38 | $args, 39 | //! Custom compare function 40 | $func; 41 | 42 | /** 43 | * Jig storage handler 44 | * @return bool 45 | * @param $id string 46 | * @param $pw string 47 | * @param $realm string 48 | **/ 49 | protected function _jig($id,$pw,$realm) { 50 | $success = (bool) 51 | call_user_func_array( 52 | [$this->mapper,'load'], 53 | [ 54 | array_merge( 55 | [ 56 | '@'.$this->args['id'].'==?'. 57 | ($this->func?'':' AND @'.$this->args['pw'].'==?'). 58 | (isset($this->args['realm'])? 59 | (' AND @'.$this->args['realm'].'==?'):''), 60 | $id 61 | ], 62 | ($this->func?[]:[$pw]), 63 | (isset($this->args['realm'])?[$realm]:[]) 64 | ) 65 | ] 66 | ); 67 | if ($success && $this->func) 68 | $success = call_user_func($this->func,$pw,$this->mapper->get($this->args['pw'])); 69 | return $success; 70 | } 71 | 72 | /** 73 | * MongoDB storage handler 74 | * @return bool 75 | * @param $id string 76 | * @param $pw string 77 | * @param $realm string 78 | **/ 79 | protected function _mongo($id,$pw,$realm) { 80 | $success = (bool) 81 | $this->mapper->load( 82 | [$this->args['id']=>$id]+ 83 | ($this->func?[]:[$this->args['pw']=>$pw])+ 84 | (isset($this->args['realm'])? 85 | [$this->args['realm']=>$realm]:[]) 86 | ); 87 | if ($success && $this->func) 88 | $success = call_user_func($this->func,$pw,$this->mapper->get($this->args['pw'])); 89 | return $success; 90 | } 91 | 92 | /** 93 | * SQL storage handler 94 | * @return bool 95 | * @param $id string 96 | * @param $pw string 97 | * @param $realm string 98 | **/ 99 | protected function _sql($id,$pw,$realm) { 100 | $success = (bool) 101 | call_user_func_array( 102 | [$this->mapper,'load'], 103 | [ 104 | array_merge( 105 | [ 106 | $this->args['id'].'=?'. 107 | ($this->func?'':' AND '.$this->args['pw'].'=?'). 108 | (isset($this->args['realm'])? 109 | (' AND '.$this->args['realm'].'=?'):''), 110 | $id 111 | ], 112 | ($this->func?[]:[$pw]), 113 | (isset($this->args['realm'])?[$realm]:[]) 114 | ) 115 | ] 116 | ); 117 | if ($success && $this->func) 118 | $success = call_user_func($this->func,$pw,$this->mapper->get($this->args['pw'])); 119 | return $success; 120 | } 121 | 122 | /** 123 | * LDAP storage handler 124 | * @return bool 125 | * @param $id string 126 | * @param $pw string 127 | **/ 128 | protected function _ldap($id,$pw) { 129 | $port=(int)($this->args['port']?:389); 130 | $filter=$this->args['filter']=$this->args['filter']?:"uid=".$id; 131 | $this->args['attr']=$this->args['attr']?:["uid"]; 132 | array_walk($this->args['attr'], 133 | function($attr)use(&$filter,$id) { 134 | $filter=str_ireplace($attr."=*",$attr."=".$id,$filter);}); 135 | $dc=@ldap_connect($this->args['dc'],$port); 136 | if ($dc && 137 | ldap_set_option($dc,LDAP_OPT_PROTOCOL_VERSION,3) && 138 | ldap_set_option($dc,LDAP_OPT_REFERRALS,0) && 139 | ldap_bind($dc,$this->args['rdn'],$this->args['pw']) && 140 | ($result=ldap_search($dc,$this->args['base_dn'], 141 | $filter,$this->args['attr'])) && 142 | ldap_count_entries($dc,$result) && 143 | ($info=ldap_get_entries($dc,$result)) && 144 | $info['count']==1 && 145 | @ldap_bind($dc,$info[0]['dn'],$pw) && 146 | @ldap_close($dc)) { 147 | return in_array($id,(array_map(function($value){return $value[0];}, 148 | array_intersect_key($info[0], 149 | array_flip($this->args['attr'])))),TRUE); 150 | } 151 | user_error(self::E_LDAP,E_USER_ERROR); 152 | } 153 | 154 | /** 155 | * SMTP storage handler 156 | * @return bool 157 | * @param $id string 158 | * @param $pw string 159 | **/ 160 | protected function _smtp($id,$pw) { 161 | $socket=@fsockopen( 162 | (strtolower($this->args['scheme'])=='ssl'? 163 | 'ssl://':'').$this->args['host'], 164 | $this->args['port']); 165 | $dialog=function($cmd=NULL) use($socket) { 166 | if (!is_null($cmd)) 167 | fputs($socket,$cmd."\r\n"); 168 | $reply=''; 169 | while (!feof($socket) && 170 | ($info=stream_get_meta_data($socket)) && 171 | !$info['timed_out'] && $str=fgets($socket,4096)) { 172 | $reply.=$str; 173 | if (preg_match('/(?:^|\n)\d{3} .+\r\n/s', 174 | $reply)) 175 | break; 176 | } 177 | return $reply; 178 | }; 179 | if ($socket) { 180 | stream_set_blocking($socket,TRUE); 181 | $dialog(); 182 | $fw=Base::instance(); 183 | $dialog('EHLO '.$fw->HOST); 184 | if (strtolower($this->args['scheme'])=='tls') { 185 | $dialog('STARTTLS'); 186 | stream_socket_enable_crypto( 187 | $socket,TRUE,STREAM_CRYPTO_METHOD_TLS_CLIENT); 188 | $dialog('EHLO '.$fw->HOST); 189 | } 190 | // Authenticate 191 | $dialog('AUTH LOGIN'); 192 | $dialog(base64_encode($id)); 193 | $reply=$dialog(base64_encode($pw)); 194 | $dialog('QUIT'); 195 | fclose($socket); 196 | return (bool)preg_match('/^235 /',$reply); 197 | } 198 | user_error(self::E_SMTP,E_USER_ERROR); 199 | } 200 | 201 | /** 202 | * Login auth mechanism 203 | * @return bool 204 | * @param $id string 205 | * @param $pw string 206 | * @param $realm string 207 | **/ 208 | function login($id,$pw,$realm=NULL) { 209 | return $this->{'_'.$this->storage}($id,$pw,$realm); 210 | } 211 | 212 | /** 213 | * HTTP basic auth mechanism 214 | * @return bool 215 | * @param $func callback 216 | **/ 217 | function basic($func=NULL) { 218 | $fw=Base::instance(); 219 | $realm=$fw->REALM; 220 | $hdr=NULL; 221 | if (isset($_SERVER['HTTP_AUTHORIZATION'])) 222 | $hdr=$_SERVER['HTTP_AUTHORIZATION']; 223 | elseif (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) 224 | $hdr=$_SERVER['REDIRECT_HTTP_AUTHORIZATION']; 225 | if (!empty($hdr)) 226 | list($_SERVER['PHP_AUTH_USER'],$_SERVER['PHP_AUTH_PW'])= 227 | explode(':',base64_decode(substr($hdr,6))); 228 | if (isset($_SERVER['PHP_AUTH_USER'],$_SERVER['PHP_AUTH_PW']) && 229 | $this->login( 230 | $_SERVER['PHP_AUTH_USER'], 231 | $func? 232 | $fw->call($func,$_SERVER['PHP_AUTH_PW']): 233 | $_SERVER['PHP_AUTH_PW'], 234 | $realm 235 | )) 236 | return TRUE; 237 | if (PHP_SAPI!='cli') 238 | header('WWW-Authenticate: Basic realm="'.$realm.'"'); 239 | $fw->status(401); 240 | return FALSE; 241 | } 242 | 243 | /** 244 | * Instantiate class 245 | * @return object 246 | * @param $storage string|object 247 | * @param $args array 248 | * @param $func callback 249 | **/ 250 | function __construct($storage,array $args=NULL,$func=NULL) { 251 | if (is_object($storage) && is_a($storage,'DB\Cursor')) { 252 | $this->storage=$storage->dbtype(); 253 | $this->mapper=$storage; 254 | unset($ref); 255 | } 256 | else 257 | $this->storage=$storage; 258 | $this->args=$args; 259 | $this->func=$func; 260 | } 261 | 262 | } 263 | -------------------------------------------------------------------------------- /fatfree-master/lib/basket.php: -------------------------------------------------------------------------------- 1 | . 20 | 21 | */ 22 | 23 | //! Session-based pseudo-mapper 24 | class Basket extends Magic { 25 | 26 | //@{ Error messages 27 | const 28 | E_Field='Undefined field %s'; 29 | //@} 30 | 31 | protected 32 | //! Session key 33 | $key, 34 | //! Current item identifier 35 | $id, 36 | //! Current item contents 37 | $item=[]; 38 | 39 | /** 40 | * Return TRUE if field is defined 41 | * @return bool 42 | * @param $key string 43 | **/ 44 | function exists($key) { 45 | return array_key_exists($key,$this->item); 46 | } 47 | 48 | /** 49 | * Assign value to field 50 | * @return scalar|FALSE 51 | * @param $key string 52 | * @param $val scalar 53 | **/ 54 | function set($key,$val) { 55 | return ($key=='_id')?FALSE:($this->item[$key]=$val); 56 | } 57 | 58 | /** 59 | * Retrieve value of field 60 | * @return scalar|FALSE 61 | * @param $key string 62 | **/ 63 | function &get($key) { 64 | if ($key=='_id') 65 | return $this->id; 66 | if (array_key_exists($key,$this->item)) 67 | return $this->item[$key]; 68 | user_error(sprintf(self::E_Field,$key),E_USER_ERROR); 69 | return FALSE; 70 | } 71 | 72 | /** 73 | * Delete field 74 | * @return NULL 75 | * @param $key string 76 | **/ 77 | function clear($key) { 78 | unset($this->item[$key]); 79 | } 80 | 81 | /** 82 | * Return items that match key/value pair; 83 | * If no key/value pair specified, return all items 84 | * @return array 85 | * @param $key string 86 | * @param $val mixed 87 | **/ 88 | function find($key=NULL,$val=NULL) { 89 | $out=[]; 90 | if (isset($_SESSION[$this->key])) { 91 | foreach ($_SESSION[$this->key] as $id=>$item) 92 | if (!isset($key) || 93 | array_key_exists($key,$item) && $item[$key]==$val || 94 | $key=='_id' && $id==$val) { 95 | $obj=clone($this); 96 | $obj->id=$id; 97 | $obj->item=$item; 98 | $out[]=$obj; 99 | } 100 | } 101 | return $out; 102 | } 103 | 104 | /** 105 | * Return first item that matches key/value pair 106 | * @return object|FALSE 107 | * @param $key string 108 | * @param $val mixed 109 | **/ 110 | function findone($key,$val) { 111 | return ($data=$this->find($key,$val))?$data[0]:FALSE; 112 | } 113 | 114 | /** 115 | * Map current item to matching key/value pair 116 | * @return array 117 | * @param $key string 118 | * @param $val mixed 119 | **/ 120 | function load($key,$val) { 121 | if ($found=$this->find($key,$val)) { 122 | $this->id=$found[0]->id; 123 | return $this->item=$found[0]->item; 124 | } 125 | $this->reset(); 126 | return []; 127 | } 128 | 129 | /** 130 | * Return TRUE if current item is empty/undefined 131 | * @return bool 132 | **/ 133 | function dry() { 134 | return !$this->item; 135 | } 136 | 137 | /** 138 | * Return number of items in basket 139 | * @return int 140 | **/ 141 | function count() { 142 | return isset($_SESSION[$this->key])?count($_SESSION[$this->key]):0; 143 | } 144 | 145 | /** 146 | * Save current item 147 | * @return array 148 | **/ 149 | function save() { 150 | if (!$this->id) 151 | $this->id=uniqid(NULL,TRUE); 152 | $_SESSION[$this->key][$this->id]=$this->item; 153 | return $this->item; 154 | } 155 | 156 | /** 157 | * Erase item matching key/value pair 158 | * @return bool 159 | * @param $key string 160 | * @param $val mixed 161 | **/ 162 | function erase($key,$val) { 163 | $found=$this->find($key,$val); 164 | if ($found && $id=$found[0]->id) { 165 | unset($_SESSION[$this->key][$id]); 166 | if ($id==$this->id) 167 | $this->reset(); 168 | return TRUE; 169 | } 170 | return FALSE; 171 | } 172 | 173 | /** 174 | * Reset cursor 175 | * @return NULL 176 | **/ 177 | function reset() { 178 | $this->id=NULL; 179 | $this->item=[]; 180 | } 181 | 182 | /** 183 | * Empty basket 184 | * @return NULL 185 | **/ 186 | function drop() { 187 | unset($_SESSION[$this->key]); 188 | } 189 | 190 | /** 191 | * Hydrate item using hive array variable 192 | * @return NULL 193 | * @param $var array|string 194 | **/ 195 | function copyfrom($var) { 196 | if (is_string($var)) 197 | $var=\Base::instance()->$var; 198 | foreach ($var as $key=>$val) 199 | $this->set($key,$val); 200 | } 201 | 202 | /** 203 | * Populate hive array variable with item contents 204 | * @return NULL 205 | * @param $key string 206 | **/ 207 | function copyto($key) { 208 | $var=&\Base::instance()->ref($key); 209 | foreach ($this->item as $key=>$field) 210 | $var[$key]=$field; 211 | } 212 | 213 | /** 214 | * Check out basket contents 215 | * @return array 216 | **/ 217 | function checkout() { 218 | if (isset($_SESSION[$this->key])) { 219 | $out=$_SESSION[$this->key]; 220 | unset($_SESSION[$this->key]); 221 | return $out; 222 | } 223 | return []; 224 | } 225 | 226 | /** 227 | * Instantiate class 228 | * @return void 229 | * @param $key string 230 | **/ 231 | function __construct($key='basket') { 232 | $this->key=$key; 233 | if (session_status()!=PHP_SESSION_ACTIVE) 234 | session_start(); 235 | Base::instance()->sync('SESSION'); 236 | $this->reset(); 237 | } 238 | 239 | } 240 | -------------------------------------------------------------------------------- /fatfree-master/lib/bcrypt.php: -------------------------------------------------------------------------------- 1 | . 19 | * 20 | **/ 21 | 22 | /** 23 | * Lightweight password hashing library (PHP 5.5+ only) 24 | * @deprecated Use http://php.net/manual/en/ref.password.php instead 25 | **/ 26 | class Bcrypt extends Prefab { 27 | 28 | //@{ Error messages 29 | const 30 | E_CostArg='Invalid cost parameter', 31 | E_SaltArg='Salt must be at least 22 alphanumeric characters'; 32 | //@} 33 | 34 | //! Default cost 35 | const 36 | COST=10; 37 | 38 | /** 39 | * Generate bcrypt hash of string 40 | * @return string|FALSE 41 | * @param $pw string 42 | * @param $salt string 43 | * @param $cost int 44 | **/ 45 | function hash($pw,$salt=NULL,$cost=self::COST) { 46 | if ($cost<4 || $cost>31) 47 | user_error(self::E_CostArg,E_USER_ERROR); 48 | $len=22; 49 | if ($salt) { 50 | if (!preg_match('/^[[:alnum:]\.\/]{'.$len.',}$/',$salt)) 51 | user_error(self::E_SaltArg,E_USER_ERROR); 52 | } 53 | else { 54 | $raw=16; 55 | $iv=''; 56 | if (!$iv && extension_loaded('openssl')) 57 | $iv=openssl_random_pseudo_bytes($raw); 58 | if (!$iv) 59 | for ($i=0;$i<$raw;$i++) 60 | $iv.=chr(mt_rand(0,255)); 61 | $salt=str_replace('+','.',base64_encode($iv)); 62 | } 63 | $salt=substr($salt,0,$len); 64 | $hash=crypt($pw,sprintf('$2y$%02d$',$cost).$salt); 65 | return strlen($hash)>13?$hash:FALSE; 66 | } 67 | 68 | /** 69 | * Check if password is still strong enough 70 | * @return bool 71 | * @param $hash string 72 | * @param $cost int 73 | **/ 74 | function needs_rehash($hash,$cost=self::COST) { 75 | list($pwcost)=sscanf($hash,"$2y$%d$"); 76 | return $pwcost<$cost; 77 | } 78 | 79 | /** 80 | * Verify password against hash using timing attack resistant approach 81 | * @return bool 82 | * @param $pw string 83 | * @param $hash string 84 | **/ 85 | function verify($pw,$hash) { 86 | $val=crypt($pw,$hash); 87 | $len=strlen($val); 88 | if ($len!=strlen($hash) || $len<14) 89 | return FALSE; 90 | $out=0; 91 | for ($i=0;$i<$len;$i++) 92 | $out|=(ord($val[$i])^ord($hash[$i])); 93 | return $out===0; 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /fatfree-master/lib/cli/ws.php: -------------------------------------------------------------------------------- 1 | . 20 | 21 | */ 22 | 23 | namespace CLI; 24 | 25 | //! RFC6455 WebSocket server 26 | class WS { 27 | 28 | const 29 | //! UUID magic string 30 | Magic='258EAFA5-E914-47DA-95CA-C5AB0DC85B11', 31 | //! Max packet size 32 | Packet=65536; 33 | 34 | //@{ Mask bits for first byte of header 35 | const 36 | Text=0x01, 37 | Binary=0x02, 38 | Close=0x08, 39 | Ping=0x09, 40 | Pong=0x0a, 41 | OpCode=0x0f, 42 | Finale=0x80; 43 | //@} 44 | 45 | //@{ Mask bits for second byte of header 46 | const 47 | Length=0x7f; 48 | //@} 49 | 50 | protected 51 | $addr, 52 | $ctx, 53 | $wait, 54 | $sockets, 55 | $protocol, 56 | $agents=[], 57 | $events=[]; 58 | 59 | /** 60 | * Allocate stream socket 61 | * @return NULL 62 | * @param $socket resource 63 | **/ 64 | function alloc($socket) { 65 | if (is_bool($buf=$this->read($socket))) 66 | return; 67 | // Get WebSocket headers 68 | $hdrs=[]; 69 | $EOL="\r\n"; 70 | $verb=NULL; 71 | $uri=NULL; 72 | foreach (explode($EOL,trim($buf)) as $line) 73 | if (preg_match('/^(\w+)\s(.+)\sHTTP\/[\d.]{1,3}$/', 74 | trim($line),$match)) { 75 | $verb=$match[1]; 76 | $uri=$match[2]; 77 | } 78 | else 79 | if (preg_match('/^(.+): (.+)/',trim($line),$match)) 80 | // Standardize header 81 | $hdrs[ 82 | strtr( 83 | ucwords( 84 | strtolower( 85 | strtr($match[1],'-',' ') 86 | ) 87 | ),' ','-' 88 | ) 89 | ]=$match[2]; 90 | else { 91 | $this->close($socket); 92 | return; 93 | } 94 | if (empty($hdrs['Upgrade']) && 95 | empty($hdrs['Sec-Websocket-Key'])) { 96 | // Not a WebSocket request 97 | if ($verb && $uri) 98 | $this->write( 99 | $socket, 100 | 'HTTP/1.1 400 Bad Request'.$EOL. 101 | 'Connection: close'.$EOL.$EOL 102 | ); 103 | $this->close($socket); 104 | return; 105 | } 106 | // Handshake 107 | $buf='HTTP/1.1 101 Switching Protocols'.$EOL. 108 | 'Upgrade: websocket'.$EOL. 109 | 'Connection: Upgrade'.$EOL; 110 | if (isset($hdrs['Sec-Websocket-Protocol'])) 111 | $buf.='Sec-WebSocket-Protocol: '. 112 | $hdrs['Sec-Websocket-Protocol'].$EOL; 113 | $buf.='Sec-WebSocket-Accept: '. 114 | base64_encode( 115 | sha1($hdrs['Sec-Websocket-Key'].WS::Magic,TRUE) 116 | ).$EOL.$EOL; 117 | if ($this->write($socket,$buf)) { 118 | // Connect agent to server 119 | $this->sockets[(int)$socket]=$socket; 120 | $this->agents[(int)$socket]= 121 | new Agent($this,$socket,$verb,$uri,$hdrs); 122 | } 123 | } 124 | 125 | /** 126 | * Close stream socket 127 | * @return NULL 128 | * @param $socket resource 129 | **/ 130 | function close($socket) { 131 | if (isset($this->agents[(int)$socket])) 132 | unset($this->sockets[(int)$socket],$this->agents[(int)$socket]); 133 | stream_socket_shutdown($socket,STREAM_SHUT_WR); 134 | @fclose($socket); 135 | } 136 | 137 | /** 138 | * Read from stream socket 139 | * @return string|FALSE 140 | * @param $socket resource 141 | * @param $len int 142 | **/ 143 | function read($socket,$len=0) { 144 | if (!$len) 145 | $len=WS::Packet; 146 | if (is_string($buf=@fread($socket,$len)) && 147 | strlen($buf) && strlen($buf)<$len) 148 | return $buf; 149 | if (isset($this->events['error']) && 150 | is_callable($func=$this->events['error'])) 151 | $func($this); 152 | $this->close($socket); 153 | return FALSE; 154 | } 155 | 156 | /** 157 | * Write to stream socket 158 | * @return int|FALSE 159 | * @param $socket resource 160 | * @param $buf string 161 | **/ 162 | function write($socket,$buf) { 163 | for ($i=0,$bytes=0;$i
The first thing you might want to do is visualize your directory structures. Fat-Free gives you total control over your Web site. Organize your folders in any way that pleases you (or your development team if you're part of a group). Decide where you want to store the following:
7 |For security reasons, consider relocating the lib/
folder to a path that's not Web-accessible. If you decide to move this folder, just change the line in index.php
containing require 'lib/base.php';
so it points to the new location. The lib/
folder also contains framework plug-ins that extend F3's capabilities. You can change the default location of all plug-ins by moving the files to your desired subdirectory. Then, it's just a matter of pointing the PLUGINS
global variable to the new location. You may delete the plug-ins that you don't need. You can reinstate them later as you find necessary.
F3 can autoload OOP classes for you. Just add the path to the AUTOLOAD
variable.
When you're ready to write your F3-enabled site, you can start editing the rest of the code contained in the index.php
file that displayed this Web page. Developing PHP applications will never be the same!
Some framework features in this version will not be available if PHP is not configured with the modules needed by your application.
21 |Class/Plug-in | 24 |PHP Module | 25 |
---|---|
29 | |
30 |
31 | onclick="return false"> 32 | 33 | |
34 |
Base
class requires all listed PHP modules enabled to function properly.Cache
class will use any available module in the list. If none can be found, it will use the filesystem as fallback.DB\SQL
class requires the pdo
module and a PDO driver relevant to your application.Bcrypt
class will use the mcrypt
or openssl
module for entropy generation. Otherwise, it employs a custom random function.Web
class will use the curl
module for HTTP requests to another server. If this is not detected, it will use other transports available, such as the HTTP stream wrapper or native sockets.geoip
module listed in the Web\Geo
class is optional; the class will use an alternative Web service for geo-location.If you have any questions regarding the framework, technical support is available at https://groups.google.com/forum/?fromgroups#!forum/f3-framework
You can also join our Slack Channel to get support
49 |Need live support? You can talk to the development team and the rest of the Fat-Free community via IRC. We're on the FreeNode (chat.freenode.net
) #fatfree
channel. If the channel appears quiet, the development team might just be busy with the next great release, or it's probably due to time zone differences. Just hang around.
The User Reference is designed to serve as a handbook and programming guide. However, the online documentation at https://github.com/bcosca/fatfree
provides the latest and most comprehensive information about the framework.
Fat-Free Framework is free software covered by the terms of the GNU Public License (GPL v3). You may not use the software, documentation, and samples except in compliance with the license. If the terms and conditions of this license are too restrictive for your use, alternative licensing is available for a very reasonable fee.
53 |If you feel that this software is one great weapon to have in your programming arsenal, it saves you a lot of time and money, use it for commercial gain or in your business organization, please consider making a donation to the project. A significant amount of time, effort, and money has been spent on this project. Your donations help keep this project alive and the development team motivated. Donors and sponsors get priority support commensurate to your contribution (24-hour response time on business days).
54 |F3 is community-driven software. Support the development of the Fat-Free Framework. Your contributions help keep this project alive.
56 | 57 |' . PHP_EOL; 24 | print_r($f3); 25 | echo '' . PHP_EOL; 26 | } 27 | ); 28 | $f3->route('GET /info', 29 | function() { 30 | phpinfo(); 31 | } 32 | ); 33 | $f3->run(); 34 | -------------------------------------------------------------------------------- /ui.css: -------------------------------------------------------------------------------- 1 | body { 2 | display: flex; 3 | min-height: 100vh; 4 | flex-direction: column; 5 | } 6 | 7 | body.pushable.extended { 8 | height: calc(100% + 500px); 9 | } 10 | 11 | /* body.pushable { 12 | background: #545454; 13 | } */ 14 | 15 | /* body.pushable body.pusher.dimmed { 16 | background: #545454; 17 | } */ 18 | 19 | .pusher { 20 | display: -webkit-box; 21 | display: -webkit-flex; 22 | display: -ms-flexbox; 23 | display: flex; 24 | -webkit-flex-direction: column; 25 | -ms-flex-direction: column; 26 | flex-direction: column; 27 | min-height: 100vh !important; 28 | height: 100%; 29 | overflow: visible !important; 30 | } 31 | 32 | main { 33 | /* flex: 1 0 auto; */ 34 | -webkit-box-flex: 1; 35 | -webkit-flex: 1 1 auto; 36 | -ms-flex: 1 1 auto; 37 | flex: 1 1 auto; 38 | } 39 | 40 | main .ui.cards { 41 | margin-top: 1em; 42 | } 43 | 44 | .hidden.menu { 45 | display: none; 46 | } 47 | 48 | .hide { 49 | display: none !important; 50 | } 51 | 52 | .scrolling-table { 53 | max-height: 500px; 54 | overflow-y: scroll; 55 | } 56 | .ui.table.sticky-headed thead tr:first-child > th { 57 | position: sticky !important; 58 | top: 0; 59 | z-index: 2; 60 | } 61 | .ui.table.sticky-headed > thead > tr:first-child > th:first-child { 62 | border-radius: unset; 63 | } 64 | .ui.table.sticky-headed > thead > tr:first-child > th:last-child{ 65 | border-radius: unset; 66 | } 67 | .ui.table.sticky-headed.inverted .darken { 68 | /* background-color: rgba(0, 0, 0, 0.65) !important; */ 69 | background-color: #333333 !important; 70 | } 71 | /* .ui.table.sticky-headed.inverted .darken:hover { 72 | background-color: rgba(0, 0, 0, 0.85) !important; 73 | } */ 74 | .ui.table.sticky-headed:not(.inverted) .darken { 75 | border-top: 1px solid rgba(34, 36, 38, 0.1); 76 | } 77 | 78 | .secondary.menu .header.large.screen.only { 79 | display: block; 80 | } 81 | 82 | .secondary.menu .header.mobile.only { 83 | display: none !important; 84 | } 85 | 86 | .secondary.menu .header.mobile.only { 87 | transform: translateX(-20px); 88 | } 89 | 90 | .footer.segment { 91 | padding: 5em 0em; 92 | } 93 | 94 | .secondary.menu .toc.item { 95 | display: none; 96 | } 97 | 98 | /* Smoothie Charts */ 99 | .charts { 100 | border-radius: 3px; 101 | /* width: 100%; */ 102 | } 103 | .charts.large.screen.only { 104 | display: block !important; 105 | } 106 | .charts.mobile.only { 107 | display: none !important; 108 | } 109 | div.smoothie-chart-tooltip { 110 | background: #444; 111 | padding: 1em; 112 | margin-top: 20px; 113 | font-family: consolas; 114 | color: white; 115 | font-size: 10px; 116 | pointer-events: none; 117 | z-index: 9999999; 118 | } 119 | 120 | /* It's slow down the whole UI... */ 121 | /* .ui.segment, .ui.menu, .ui.table { 122 | transition: background-color .8s, color .8s; 123 | } */ 124 | 125 | @media only screen and (max-width: 900px) { 126 | /* body.pushable { 127 | background: #FFFFFF; 128 | } */ 129 | /* body.pushable body.pusher.dimmed { 130 | background: #545454; 131 | } */ 132 | /* .ui.fixed.menu { 133 | display: none !important; 134 | } */ 135 | .secondary.menu .right.menu { 136 | display: none !important; 137 | } 138 | .secondary.menu .toc.item { 139 | display: block; 140 | } 141 | .secondary.menu .header.large.screen.only { 142 | display: none !important; 143 | } 144 | .secondary.menu .header.mobile.only { 145 | display: block !important; 146 | } 147 | 148 | .charts.large.screen.only { 149 | display: none !important; 150 | } 151 | .charts.mobile.only { 152 | display: block !important; 153 | } 154 | } 155 | @media only screen and (max-width: 700px) { 156 | /* body.pushable { 157 | background: #FFFFFF; 158 | } */ 159 | /* body.pushable body.pusher.dimmed { 160 | background: #545454; 161 | } */ 162 | /* .ui.fixed.menu { 163 | display: none !important; 164 | } */ 165 | .secondary.menu .right.menu { 166 | display: none !important; 167 | } 168 | .secondary.menu .toc.item { 169 | display: block; 170 | } 171 | .secondary.menu .header.large.screen.only { 172 | display: none !important; 173 | } 174 | .secondary.menu .header.mobile.only { 175 | display: block !important; 176 | } 177 | 178 | .charts.large.screen.only { 179 | display: none !important; 180 | } 181 | .charts.mobile.only { 182 | display: block !important; 183 | } 184 | } -------------------------------------------------------------------------------- /ui.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | // app ui - Boot stuff when DOM is loaded 4 | $(function () { 5 | console.group('UI'); 6 | console.log('DOM Loaded.'); 7 | console.log('Based on Fomantic-UI.'); 8 | console.log('Loaded modules:', (typeof $.site.settings !== undefined ? $.site.settings.modules : null)); 9 | console.log('Available hooks:', (typeof window.UI !== undefined ? window.UI : null)); 10 | console.groupEnd(); 11 | 12 | // Disabled links 13 | $('a[href="#!"]').on('click', function(event) { 14 | event.preventDefault(); 15 | }); 16 | 17 | // Fix top menu when passed 18 | $('.ui.large.secondary.inverted.menu').visibility({ 19 | once: false, 20 | onBottomPassed: function() { 21 | $('.fixed.menu').transition('fade in'); 22 | }, 23 | onBottomPassedReverse: function() { 24 | $('.fixed.menu').transition('fade out'); 25 | } 26 | }); 27 | 28 | // Create sidebar and attach to menu open 29 | $('.ui.sidebar') 30 | // .sidebar('setting', { transition: 'scale down', mobileTransition: 'scale down' }) 31 | .sidebar('setting', { transition: 'overlay', mobileTransition: 'overlay' }) 32 | .sidebar('attach events', '.toc.item'); 33 | 34 | // Dropdowns 35 | $('.ui.dropdown').dropdown({ 36 | on: 'hover' 37 | }); 38 | 39 | // Accordions 40 | $('.ui.accordion').accordion(); 41 | 42 | // Checkboxes 43 | $('.ui.checkbox').checkbox() 44 | 45 | // Dismissable messages 46 | $('.message .close').on('click', function() { 47 | $(this).closest('.message').transition('fade'); 48 | }); 49 | 50 | // Modals 51 | $('.ui.modal').modal(); 52 | 53 | // Tooltips 54 | $('.tooltipped').popup(); 55 | 56 | // Scrolling tables 57 | // TODO: Add throttling... 58 | $('.scrolling-table').on('scroll', function (event) { 59 | // console.log('User is scrolling the table content.', event); 60 | // console.info('Scroll position:', event.target.scrollTop); 61 | // console.info('This:', $(this)); 62 | // console.info('Table header:', $(this).find('.ui.table.sticky-headed thead tr:first-child > th')); 63 | 64 | // Store scroll position 65 | var pos = event.target.scrollTop; 66 | 67 | // Target next table with sticky headers 68 | var $tableHeaders = $(this).find('.ui.table.sticky-headed thead tr:first-child > th'); 69 | 70 | // Set a darker background color when user is scrolling table content 71 | if (pos !== 0) { 72 | if (!$tableHeaders.hasClass('darken')) { 73 | $tableHeaders.addClass('darken'); 74 | } 75 | } 76 | else { 77 | if ($tableHeaders.hasClass('darken')) { 78 | $tableHeaders.removeClass('darken'); 79 | } 80 | } 81 | }); 82 | }); 83 | --------------------------------------------------------------------------------