├── README.md ├── app ├── controllers │ ├── Controller.php │ └── MainController.php ├── models │ └── Messages.php └── views │ └── template.htm ├── composer.json ├── config.ini ├── index.php ├── routes.ini └── vendor ├── autoload.php ├── bcosca └── fatfree │ ├── .htaccess │ ├── composer.json │ ├── config.ini │ ├── index.php │ ├── lib │ ├── CHANGELOG │ ├── COPYING │ ├── audit.php │ ├── auth.php │ ├── base.php │ ├── basket.php │ ├── bcrypt.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 │ │ └── staticmap.php │ │ ├── openid.php │ │ └── pingback.php │ ├── readme.md │ └── ui │ ├── css │ ├── base.css │ └── theme.css │ ├── images │ ├── bitcoin.png │ ├── logo.png │ ├── paypal.png │ └── twitter.png │ ├── layout.htm │ ├── userref.htm │ └── welcome.htm └── composer ├── ClassLoader.php ├── autoload_classmap.php ├── autoload_files.php ├── autoload_namespaces.php ├── autoload_psr4.php ├── autoload_real.php └── installed.json /README.md: -------------------------------------------------------------------------------- 1 | # Fat-Free-PHP-MVC-Sample-Project 2 | 3 | This a sample project to kick-start an MVC web application based on the Fat-Free PHP Framework. 4 | 5 | The project is a result of a tutorial series that you can follow on http://takacsmark.com. 6 | 7 | The sample project works with a MySQL database. After cloning the repository update database configuration info in the config.ini file. 8 | 9 | You can run the project from the project directory by issuing the command "php -S localhost:8088 -t .". 10 | 11 | If you prefer to use your own web server, please make sure that it is configured to support f3 routing as described on http://fatfreeframework.com/routing-engine. 12 | -------------------------------------------------------------------------------- /app/controllers/Controller.php: -------------------------------------------------------------------------------- 1 | f3=$f3; 20 | 21 | $db=new DB\SQL( 22 | $f3->get('devdb'), 23 | $f3->get('devdbusername'), 24 | $f3->get('devdbpassword'), 25 | array( \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION ) 26 | ); 27 | 28 | $this->db=$db; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /app/controllers/MainController.php: -------------------------------------------------------------------------------- 1 | db); 8 | $message->key = 'Second message'; 9 | $message->message = 'This is the second message inserted from code'; 10 | $message->save(); 11 | 12 | $messages = new Messages($this->db); 13 | $msg = $messages->all()[0]; 14 | 15 | $this->f3->set('msg',$msg); 16 | $template=new Template; 17 | echo $template->render('template.htm'); 18 | 19 | } 20 | } -------------------------------------------------------------------------------- /app/models/Messages.php: -------------------------------------------------------------------------------- 1 | load(); 11 | return $this->query; 12 | } 13 | 14 | public function getById($id) { 15 | $this->load(array('id=?',$id)); 16 | return $this->query; 17 | } 18 | 19 | public function add() { 20 | $this->copyFrom('POST'); 21 | $this->save(); 22 | } 23 | 24 | public function edit($id) { 25 | $this->load(array('id=?',$id)); 26 | $this->copyFrom('POST'); 27 | $this->update(); 28 | } 29 | 30 | public function delete($id) { 31 | $this->load(array('id=?',$id)); 32 | $this->erase(); 33 | } 34 | } -------------------------------------------------------------------------------- /app/views/template.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Tutorial page 5 | 6 | 7 |

{{ @msg.message }}

8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "takacsmark/fatfreetutorial1", 3 | "authors": [ 4 | { 5 | "name": "Mark Takacs", 6 | "email": "takacs.mark@gmail.com" 7 | } 8 | ], 9 | "require": { 10 | "bcosca/fatfree": "3.5.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /config.ini: -------------------------------------------------------------------------------- 1 | [globals] 2 | 3 | DEBUG=3 4 | UI=app/views/ 5 | AUTOLOAD=app/controllers/|app/models/ 6 | 7 | devdb = "mysql:host=127.0.0.1;port=3306;dbname=f3MVC" 8 | devdbusername = "f3MVCadmin" 9 | devdbpassword = "f3MVCadmin" 10 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | config('config.ini'); 8 | $f3->config('routes.ini'); 9 | 10 | $f3->run(); 11 | -------------------------------------------------------------------------------- /routes.ini: -------------------------------------------------------------------------------- 1 | [routes] 2 | 3 | ;base routes 4 | GET /=MainController->render 5 | 6 | -------------------------------------------------------------------------------- /vendor/autoload.php: -------------------------------------------------------------------------------- 1 | =5.3.6" 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 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/config.ini: -------------------------------------------------------------------------------- 1 | [globals] 2 | 3 | DEBUG=3 4 | UI=ui/ 5 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/index.php: -------------------------------------------------------------------------------- 1 | set('DEBUG',1); 7 | if ((float)PCRE_VERSION<7.9) 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 | ), 22 | 'Cache'=> 23 | array( 24 | 'apc', 25 | 'memcache', 26 | 'wincache', 27 | 'xcache' 28 | ), 29 | 'DB\SQL'=> 30 | array( 31 | 'pdo', 32 | 'pdo_dblib', 33 | 'pdo_mssql', 34 | 'pdo_mysql', 35 | 'pdo_odbc', 36 | 'pdo_pgsql', 37 | 'pdo_sqlite', 38 | 'pdo_sqlsrv' 39 | ), 40 | 'DB\Jig'=> 41 | array('json'), 42 | 'DB\Mongo'=> 43 | array( 44 | 'json', 45 | 'mongo' 46 | ), 47 | 'Auth'=> 48 | array('ldap','pdo'), 49 | 'Bcrypt'=> 50 | array( 51 | 'mcrypt', 52 | 'openssl' 53 | ), 54 | 'Image'=> 55 | array('gd'), 56 | 'Lexicon'=> 57 | array('iconv'), 58 | 'SMTP'=> 59 | array('openssl'), 60 | 'Web'=> 61 | array('curl','openssl','simplexml'), 62 | 'Web\Geo'=> 63 | array('geoip','json'), 64 | 'Web\OpenID'=> 65 | array('json','simplexml'), 66 | 'Web\Pingback'=> 67 | array('dom','xmlrpc') 68 | ); 69 | $f3->set('classes',$classes); 70 | $f3->set('content','welcome.htm'); 71 | echo View::instance()->render('layout.htm'); 72 | } 73 | ); 74 | 75 | $f3->route('GET /userref', 76 | function($f3) { 77 | $f3->set('content','userref.htm'); 78 | echo View::instance()->render('layout.htm'); 79 | } 80 | ); 81 | 82 | $f3->run(); 83 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/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=array(); 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()->get('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()->get('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()->get('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}$/',$id)) 170 | return 'MasterCard'; 171 | if (preg_match('/^4[0-9]{12}(?:[0-9]{3})?$/',$id)) 172 | return 'Visa'; 173 | } 174 | return FALSE; 175 | } 176 | 177 | /** 178 | * Return entropy estimate of a password (NIST 800-63) 179 | * @return int|float 180 | * @param $str string 181 | **/ 182 | function entropy($str) { 183 | $len=strlen($str); 184 | return 4*min($len,1)+($len>1?(2*(min($len,8)-1)):0)+ 185 | ($len>8?(1.5*(min($len,20)-8)):0)+($len>20?($len-20):0)+ 186 | 6*(bool)(preg_match( 187 | '/[A-Z].*?[0-9[:punct:]]|[0-9[:punct:]].*?[A-Z]/',$str)); 188 | } 189 | 190 | } 191 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/lib/auth.php: -------------------------------------------------------------------------------- 1 | . 20 | 21 | */ 22 | 23 | 24 | //! Authorization/authentication plug-in 25 | class Auth { 26 | 27 | //@{ Error messages 28 | const 29 | E_LDAP='LDAP connection failure', 30 | E_SMTP='SMTP connection failure'; 31 | //@} 32 | 33 | protected 34 | //! Auth storage 35 | $storage, 36 | //! Mapper object 37 | $mapper, 38 | //! Storage options 39 | $args; 40 | 41 | /** 42 | * Jig storage handler 43 | * @return bool 44 | * @param $id string 45 | * @param $pw string 46 | * @param $realm string 47 | **/ 48 | protected function _jig($id,$pw,$realm) { 49 | return (bool) 50 | call_user_func_array( 51 | array($this->mapper,'load'), 52 | array( 53 | array_merge( 54 | array( 55 | '@'.$this->args['id'].'==? AND '. 56 | '@'.$this->args['pw'].'==?'. 57 | (isset($this->args['realm'])? 58 | (' AND @'.$this->args['realm'].'==?'):''), 59 | $id,$pw 60 | ), 61 | (isset($this->args['realm'])?array($realm):array()) 62 | ) 63 | ) 64 | ); 65 | } 66 | 67 | /** 68 | * MongoDB storage handler 69 | * @return bool 70 | * @param $id string 71 | * @param $pw string 72 | * @param $realm string 73 | **/ 74 | protected function _mongo($id,$pw,$realm) { 75 | return (bool) 76 | $this->mapper->load( 77 | array( 78 | $this->args['id']=>$id, 79 | $this->args['pw']=>$pw 80 | )+ 81 | (isset($this->args['realm'])? 82 | array($this->args['realm']=>$realm):array()) 83 | ); 84 | } 85 | 86 | /** 87 | * SQL storage handler 88 | * @return bool 89 | * @param $id string 90 | * @param $pw string 91 | * @param $realm string 92 | **/ 93 | protected function _sql($id,$pw,$realm) { 94 | return (bool) 95 | call_user_func_array( 96 | array($this->mapper,'load'), 97 | array( 98 | array_merge( 99 | array( 100 | $this->args['id'].'=? AND '. 101 | $this->args['pw'].'=?'. 102 | (isset($this->args['realm'])? 103 | (' AND '.$this->args['realm'].'=?'):''), 104 | $id,$pw 105 | ), 106 | (isset($this->args['realm'])?array($realm):array()) 107 | ) 108 | ) 109 | ); 110 | } 111 | 112 | /** 113 | * LDAP storage handler 114 | * @return bool 115 | * @param $id string 116 | * @param $pw string 117 | **/ 118 | protected function _ldap($id,$pw) { 119 | $dc=@ldap_connect($this->args['dc']); 120 | if ($dc && 121 | ldap_set_option($dc,LDAP_OPT_PROTOCOL_VERSION,3) && 122 | ldap_set_option($dc,LDAP_OPT_REFERRALS,0) && 123 | ldap_bind($dc,$this->args['rdn'],$this->args['pw']) && 124 | ($result=ldap_search($dc,$this->args['base_dn'], 125 | 'uid='.$id)) && 126 | ldap_count_entries($dc,$result) && 127 | ($info=ldap_get_entries($dc,$result)) && 128 | @ldap_bind($dc,$info[0]['dn'],$pw) && 129 | @ldap_close($dc)) { 130 | return $info[0]['uid'][0]==$id; 131 | } 132 | user_error(self::E_LDAP,E_USER_ERROR); 133 | } 134 | 135 | /** 136 | * SMTP storage handler 137 | * @return bool 138 | * @param $id string 139 | * @param $pw string 140 | **/ 141 | protected function _smtp($id,$pw) { 142 | $socket=@fsockopen( 143 | (strtolower($this->args['scheme'])=='ssl'? 144 | 'ssl://':'').$this->args['host'], 145 | $this->args['port']); 146 | $dialog=function($cmd=NULL) use($socket) { 147 | if (!is_null($cmd)) 148 | fputs($socket,$cmd."\r\n"); 149 | $reply=''; 150 | while (!feof($socket) && 151 | ($info=stream_get_meta_data($socket)) && 152 | !$info['timed_out'] && $str=fgets($socket,4096)) { 153 | $reply.=$str; 154 | if (preg_match('/(?:^|\n)\d{3} .+\r\n/s', 155 | $reply)) 156 | break; 157 | } 158 | return $reply; 159 | }; 160 | if ($socket) { 161 | stream_set_blocking($socket,TRUE); 162 | $dialog(); 163 | $fw=Base::instance(); 164 | $dialog('EHLO '.$fw->get('HOST')); 165 | if (strtolower($this->args['scheme'])=='tls') { 166 | $dialog('STARTTLS'); 167 | stream_socket_enable_crypto( 168 | $socket,TRUE,STREAM_CRYPTO_METHOD_TLS_CLIENT); 169 | $dialog('EHLO '.$fw->get('HOST')); 170 | } 171 | // Authenticate 172 | $dialog('AUTH LOGIN'); 173 | $dialog(base64_encode($id)); 174 | $reply=$dialog(base64_encode($pw)); 175 | $dialog('QUIT'); 176 | fclose($socket); 177 | return (bool)preg_match('/^235 /',$reply); 178 | } 179 | user_error(self::E_SMTP,E_USER_ERROR); 180 | } 181 | 182 | /** 183 | * Login auth mechanism 184 | * @return bool 185 | * @param $id string 186 | * @param $pw string 187 | * @param $realm string 188 | **/ 189 | function login($id,$pw,$realm=NULL) { 190 | return $this->{'_'.$this->storage}($id,$pw,$realm); 191 | } 192 | 193 | /** 194 | * HTTP basic auth mechanism 195 | * @return bool 196 | * @param $func callback 197 | **/ 198 | function basic($func=NULL) { 199 | $fw=Base::instance(); 200 | $realm=$fw->get('REALM'); 201 | $hdr=NULL; 202 | if (isset($_SERVER['HTTP_AUTHORIZATION'])) 203 | $hdr=$_SERVER['HTTP_AUTHORIZATION']; 204 | elseif (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) 205 | $hdr=$_SERVER['REDIRECT_HTTP_AUTHORIZATION']; 206 | if (!empty($hdr)) 207 | list($_SERVER['PHP_AUTH_USER'],$_SERVER['PHP_AUTH_PW'])= 208 | explode(':',base64_decode(substr($hdr,6))); 209 | if (isset($_SERVER['PHP_AUTH_USER'],$_SERVER['PHP_AUTH_PW']) && 210 | $this->login( 211 | $_SERVER['PHP_AUTH_USER'], 212 | $func? 213 | $fw->call($func,$_SERVER['PHP_AUTH_PW']): 214 | $_SERVER['PHP_AUTH_PW'], 215 | $realm 216 | )) 217 | return TRUE; 218 | if (PHP_SAPI!='cli') 219 | header('WWW-Authenticate: Basic realm="'.$realm.'"'); 220 | $fw->status(401); 221 | return FALSE; 222 | } 223 | 224 | /** 225 | * Instantiate class 226 | * @return object 227 | * @param $storage string|object 228 | * @param $args array 229 | **/ 230 | function __construct($storage,array $args=NULL) { 231 | if (is_object($storage) && is_a($storage,'DB\Cursor')) { 232 | $this->storage=$storage->dbtype(); 233 | $this->mapper=$storage; 234 | unset($ref); 235 | } 236 | else 237 | $this->storage=$storage; 238 | $this->args=$args; 239 | } 240 | 241 | } 242 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/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=array(); 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=array(); 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 | $obj=clone($this); 95 | $obj->id=$id; 96 | $obj->item=$item; 97 | $out[]=$obj; 98 | } 99 | } 100 | return $out; 101 | } 102 | 103 | /** 104 | * Return first item that matches key/value pair 105 | * @return object|FALSE 106 | * @param $key string 107 | * @param $val mixed 108 | **/ 109 | function findone($key,$val) { 110 | return ($data=$this->find($key,$val))?$data[0]:FALSE; 111 | } 112 | 113 | /** 114 | * Map current item to matching key/value pair 115 | * @return array 116 | * @param $key string 117 | * @param $val mixed 118 | **/ 119 | function load($key,$val) { 120 | if ($found=$this->find($key,$val)) { 121 | $this->id=$found[0]->id; 122 | return $this->item=$found[0]->item; 123 | } 124 | $this->reset(); 125 | return array(); 126 | } 127 | 128 | /** 129 | * Return TRUE if current item is empty/undefined 130 | * @return bool 131 | **/ 132 | function dry() { 133 | return !$this->item; 134 | } 135 | 136 | /** 137 | * Return number of items in basket 138 | * @return int 139 | **/ 140 | function count() { 141 | return isset($_SESSION[$this->key])?count($_SESSION[$this->key]):0; 142 | } 143 | 144 | /** 145 | * Save current item 146 | * @return array 147 | **/ 148 | function save() { 149 | if (!$this->id) 150 | $this->id=uniqid(NULL,TRUE); 151 | $_SESSION[$this->key][$this->id]=$this->item; 152 | return $this->item; 153 | } 154 | 155 | /** 156 | * Erase item matching key/value pair 157 | * @return bool 158 | * @param $key string 159 | * @param $val mixed 160 | **/ 161 | function erase($key,$val) { 162 | $found=$this->find($key,$val); 163 | if ($found && $id=$found[0]->id) { 164 | unset($_SESSION[$this->key][$id]); 165 | if ($id==$this->id) 166 | $this->reset(); 167 | return TRUE; 168 | } 169 | return FALSE; 170 | } 171 | 172 | /** 173 | * Reset cursor 174 | * @return NULL 175 | **/ 176 | function reset() { 177 | $this->id=NULL; 178 | $this->item=array(); 179 | } 180 | 181 | /** 182 | * Empty basket 183 | * @return NULL 184 | **/ 185 | function drop() { 186 | unset($_SESSION[$this->key]); 187 | } 188 | 189 | /** 190 | * Hydrate item using hive array variable 191 | * @return NULL 192 | * @param $var array|string 193 | **/ 194 | function copyfrom($var) { 195 | if (is_string($var)) 196 | $var=\Base::instance()->get($var); 197 | foreach ($var as $key=>$val) 198 | $this->item[$key]=$val; 199 | } 200 | 201 | /** 202 | * Populate hive array variable with item contents 203 | * @return NULL 204 | * @param $key string 205 | **/ 206 | function copyto($key) { 207 | $var=&\Base::instance()->ref($key); 208 | foreach ($this->item as $key=>$field) 209 | $var[$key]=$field; 210 | } 211 | 212 | /** 213 | * Check out basket contents 214 | * @return array 215 | **/ 216 | function checkout() { 217 | if (isset($_SESSION[$this->key])) { 218 | $out=$_SESSION[$this->key]; 219 | unset($_SESSION[$this->key]); 220 | return $out; 221 | } 222 | return array(); 223 | } 224 | 225 | /** 226 | * Instantiate class 227 | * @return void 228 | * @param $key string 229 | **/ 230 | function __construct($key='basket') { 231 | $this->key=$key; 232 | @session_start(); 233 | Base::instance()->sync('SESSION'); 234 | $this->reset(); 235 | } 236 | 237 | } 238 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/lib/bcrypt.php: -------------------------------------------------------------------------------- 1 | . 20 | 21 | */ 22 | 23 | //! Lightweight password hashing library 24 | class Bcrypt extends Prefab { 25 | 26 | //@{ Error messages 27 | const 28 | E_CostArg='Invalid cost parameter', 29 | E_SaltArg='Salt must be at least 22 alphanumeric characters'; 30 | //@} 31 | 32 | //! Default cost 33 | const 34 | COST=10; 35 | 36 | /** 37 | * Generate bcrypt hash of string 38 | * @return string|FALSE 39 | * @param $pw string 40 | * @param $salt string 41 | * @param $cost int 42 | **/ 43 | function hash($pw,$salt=NULL,$cost=self::COST) { 44 | if ($cost<4 || $cost>31) 45 | user_error(self::E_CostArg,E_USER_ERROR); 46 | $len=22; 47 | if ($salt) { 48 | if (!preg_match('/^[[:alnum:]\.\/]{'.$len.',}$/',$salt)) 49 | user_error(self::E_SaltArg,E_USER_ERROR); 50 | } 51 | else { 52 | $raw=16; 53 | $iv=''; 54 | if (extension_loaded('mcrypt')) 55 | $iv=mcrypt_create_iv($raw,MCRYPT_DEV_URANDOM); 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 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/lib/code.css: -------------------------------------------------------------------------------- 1 | code{word-wrap:break-word;color:black}.comment,.doc_comment,.ml_comment{color:dimgray;font-style:italic}.variable{color:blueviolet}.const,.constant_encapsed_string,.class_c,.dir,.file,.func_c,.halt_compiler,.line,.method_c,.lnumber,.dnumber{color:crimson}.string,.and_equal,.boolean_and,.boolean_or,.concat_equal,.dec,.div_equal,.inc,.is_equal,.is_greater_or_equal,.is_identical,.is_not_equal,.is_not_identical,.is_smaller_or_equal,.logical_and,.logical_or,.logical_xor,.minus_equal,.mod_equal,.mul_equal,.ns_c,.ns_separator,.or_equal,.plus_equal,.sl,.sl_equal,.sr,.sr_equal,.xor_equal,.start_heredoc,.end_heredoc,.object_operator,.paamayim_nekudotayim{color:black}.abstract,.array,.array_cast,.as,.break,.case,.catch,.class,.clone,.continue,.declare,.default,.do,.echo,.else,.elseif,.empty.enddeclare,.endfor,.endforach,.endif,.endswitch,.endwhile,.eval,.exit,.extends,.final,.for,.foreach,.function,.global,.goto,.if,.implements,.include,.include_once,.instanceof,.interface,.isset,.list,.namespace,.new,.print,.private,.public,.protected,.require,.require_once,.return,.static,.switch,.throw,.try,.unset,.use,.var,.while{color:royalblue}.open_tag,.open_tag_with_echo,.close_tag{color:orange}.ini_section{color:black}.ini_key{color:royalblue}.ini_value{color:crimson}.xml_tag{color:dodgerblue}.xml_attr{color:blueviolet}.xml_data{color:red}.section{color:black}.directive{color:blue}.data{color:dimgray} 2 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/lib/db/cursor.php: -------------------------------------------------------------------------------- 1 | . 20 | 21 | */ 22 | 23 | namespace DB; 24 | 25 | //! Simple cursor implementation 26 | abstract class Cursor extends \Magic implements \IteratorAggregate { 27 | 28 | //@{ Error messages 29 | const 30 | E_Field='Undefined field %s'; 31 | //@} 32 | 33 | protected 34 | //! Query results 35 | $query=array(), 36 | //! Current position 37 | $ptr=0, 38 | //! Event listeners 39 | $trigger=array(); 40 | 41 | /** 42 | * Return database type 43 | * @return string 44 | **/ 45 | abstract function dbtype(); 46 | 47 | /** 48 | * Return field names 49 | * @return array 50 | **/ 51 | abstract function fields(); 52 | 53 | /** 54 | * Return fields of mapper object as an associative array 55 | * @return array 56 | * @param $obj object 57 | **/ 58 | abstract function cast($obj=NULL); 59 | 60 | /** 61 | * Return records (array of mapper objects) that match criteria 62 | * @return array 63 | * @param $filter string|array 64 | * @param $options array 65 | * @param $ttl int 66 | **/ 67 | abstract function find($filter=NULL,array $options=NULL,$ttl=0); 68 | 69 | /** 70 | * Count records that match criteria 71 | * @return int 72 | * @param $filter array 73 | * @param $ttl int 74 | **/ 75 | abstract function count($filter=NULL,$ttl=0); 76 | 77 | /** 78 | * Insert new record 79 | * @return array 80 | **/ 81 | abstract function insert(); 82 | 83 | /** 84 | * Update current record 85 | * @return array 86 | **/ 87 | abstract function update(); 88 | 89 | /** 90 | * Hydrate mapper object using hive array variable 91 | * @return NULL 92 | * @param $var array|string 93 | * @param $func callback 94 | **/ 95 | abstract function copyfrom($var,$func=NULL); 96 | 97 | /** 98 | * Populate hive array variable with mapper fields 99 | * @return NULL 100 | * @param $key string 101 | **/ 102 | abstract function copyto($key); 103 | 104 | /** 105 | * Get cursor's equivalent external iterator 106 | * Causes a fatal error in PHP 5.3.5if uncommented 107 | * return ArrayIterator 108 | **/ 109 | abstract function getiterator(); 110 | 111 | 112 | /** 113 | * Return TRUE if current cursor position is not mapped to any record 114 | * @return bool 115 | **/ 116 | function dry() { 117 | return empty($this->query[$this->ptr]); 118 | } 119 | 120 | /** 121 | * Return first record (mapper object) that matches criteria 122 | * @return \DB\Cursor|FALSE 123 | * @param $filter string|array 124 | * @param $options array 125 | * @param $ttl int 126 | **/ 127 | function findone($filter=NULL,array $options=NULL,$ttl=0) { 128 | if (!$options) 129 | $options=array(); 130 | // Override limit 131 | $options['limit']=1; 132 | return ($data=$this->find($filter,$options,$ttl))?$data[0]:FALSE; 133 | } 134 | 135 | /** 136 | * Return array containing subset of records matching criteria, 137 | * total number of records in superset, specified limit, number of 138 | * subsets available, and actual subset position 139 | * @return array 140 | * @param $pos int 141 | * @param $size int 142 | * @param $filter string|array 143 | * @param $options array 144 | * @param $ttl int 145 | **/ 146 | function paginate( 147 | $pos=0,$size=10,$filter=NULL,array $options=NULL,$ttl=0) { 148 | $total=$this->count($filter,$ttl); 149 | $count=ceil($total/$size); 150 | $pos=max(0,min($pos,$count-1)); 151 | return array( 152 | 'subset'=>$this->find($filter, 153 | array_merge( 154 | $options?:array(), 155 | array('limit'=>$size,'offset'=>$pos*$size) 156 | ), 157 | $ttl 158 | ), 159 | 'total'=>$total, 160 | 'limit'=>$size, 161 | 'count'=>$count, 162 | 'pos'=>$pos<$count?$pos:0 163 | ); 164 | } 165 | 166 | /** 167 | * Map to first record that matches criteria 168 | * @return array|FALSE 169 | * @param $filter string|array 170 | * @param $options array 171 | * @param $ttl int 172 | **/ 173 | function load($filter=NULL,array $options=NULL,$ttl=0) { 174 | return ($this->query=$this->find($filter,$options,$ttl)) && 175 | $this->skip(0)?$this->query[$this->ptr=0]:FALSE; 176 | } 177 | 178 | /** 179 | * Return the count of records loaded 180 | * @return int 181 | **/ 182 | function loaded() { 183 | return count($this->query); 184 | } 185 | 186 | /** 187 | * Map to first record in cursor 188 | * @return mixed 189 | **/ 190 | function first() { 191 | return $this->skip(-$this->ptr); 192 | } 193 | 194 | /** 195 | * Map to last record in cursor 196 | * @return mixed 197 | **/ 198 | function last() { 199 | return $this->skip(($ofs=count($this->query)-$this->ptr)?$ofs-1:0); 200 | } 201 | 202 | /** 203 | * Map to nth record relative to current cursor position 204 | * @return mixed 205 | * @param $ofs int 206 | **/ 207 | function skip($ofs=1) { 208 | $this->ptr+=$ofs; 209 | return $this->ptr>-1 && $this->ptrquery)? 210 | $this->query[$this->ptr]:FALSE; 211 | } 212 | 213 | /** 214 | * Map next record 215 | * @return mixed 216 | **/ 217 | function next() { 218 | return $this->skip(); 219 | } 220 | 221 | /** 222 | * Map previous record 223 | * @return mixed 224 | **/ 225 | function prev() { 226 | return $this->skip(-1); 227 | } 228 | 229 | /** 230 | * Return whether current iterator position is valid. 231 | */ 232 | function valid() { 233 | return !$this->dry(); 234 | } 235 | 236 | /** 237 | * Save mapped record 238 | * @return mixed 239 | **/ 240 | function save() { 241 | return $this->query?$this->update():$this->insert(); 242 | } 243 | 244 | /** 245 | * Delete current record 246 | * @return int|bool 247 | **/ 248 | function erase() { 249 | $this->query=array_slice($this->query,0,$this->ptr,TRUE)+ 250 | array_slice($this->query,$this->ptr,NULL,TRUE); 251 | $this->skip(0); 252 | } 253 | 254 | /** 255 | * Define onload trigger 256 | * @return callback 257 | * @param $func callback 258 | **/ 259 | function onload($func) { 260 | return $this->trigger['load']=$func; 261 | } 262 | 263 | /** 264 | * Define beforeinsert trigger 265 | * @return callback 266 | * @param $func callback 267 | **/ 268 | function beforeinsert($func) { 269 | return $this->trigger['beforeinsert']=$func; 270 | } 271 | 272 | /** 273 | * Define afterinsert trigger 274 | * @return callback 275 | * @param $func callback 276 | **/ 277 | function afterinsert($func) { 278 | return $this->trigger['afterinsert']=$func; 279 | } 280 | 281 | /** 282 | * Define oninsert trigger 283 | * @return callback 284 | * @param $func callback 285 | **/ 286 | function oninsert($func) { 287 | return $this->afterinsert($func); 288 | } 289 | 290 | /** 291 | * Define beforeupdate trigger 292 | * @return callback 293 | * @param $func callback 294 | **/ 295 | function beforeupdate($func) { 296 | return $this->trigger['beforeupdate']=$func; 297 | } 298 | 299 | /** 300 | * Define afterupdate trigger 301 | * @return callback 302 | * @param $func callback 303 | **/ 304 | function afterupdate($func) { 305 | return $this->trigger['afterupdate']=$func; 306 | } 307 | 308 | /** 309 | * Define onupdate trigger 310 | * @return callback 311 | * @param $func callback 312 | **/ 313 | function onupdate($func) { 314 | return $this->afterupdate($func); 315 | } 316 | 317 | /** 318 | * Define beforesave trigger 319 | * @return callback 320 | * @param $func callback 321 | **/ 322 | function beforesave($func) { 323 | $this->trigger['beforeinsert']=$func; 324 | $this->trigger['beforeupdate']=$func; 325 | return $func; 326 | } 327 | 328 | /** 329 | * Define aftersave trigger 330 | * @return callback 331 | * @param $func callback 332 | **/ 333 | function aftersave($func) { 334 | $this->trigger['afterinsert']=$func; 335 | $this->trigger['afterupdate']=$func; 336 | return $func; 337 | } 338 | 339 | /** 340 | * Define onsave trigger 341 | * @return callback 342 | * @param $func callback 343 | **/ 344 | function onsave($func) { 345 | return $this->aftersave($func); 346 | } 347 | 348 | /** 349 | * Define beforeerase trigger 350 | * @return callback 351 | * @param $func callback 352 | **/ 353 | function beforeerase($func) { 354 | return $this->trigger['beforeerase']=$func; 355 | } 356 | 357 | /** 358 | * Define aftererase trigger 359 | * @return callback 360 | * @param $func callback 361 | **/ 362 | function aftererase($func) { 363 | return $this->trigger['aftererase']=$func; 364 | } 365 | 366 | /** 367 | * Define onerase trigger 368 | * @return callback 369 | * @param $func callback 370 | **/ 371 | function onerase($func) { 372 | return $this->aftererase($func); 373 | } 374 | 375 | /** 376 | * Reset cursor 377 | * @return NULL 378 | **/ 379 | function reset() { 380 | $this->query=array(); 381 | $this->ptr=0; 382 | } 383 | 384 | } 385 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/lib/db/jig.php: -------------------------------------------------------------------------------- 1 | . 20 | 21 | */ 22 | 23 | namespace DB; 24 | 25 | //! In-memory/flat-file DB wrapper 26 | class Jig { 27 | 28 | //@{ Storage formats 29 | const 30 | FORMAT_JSON=0, 31 | FORMAT_Serialized=1; 32 | //@} 33 | 34 | protected 35 | //! UUID 36 | $uuid, 37 | //! Storage location 38 | $dir, 39 | //! Current storage format 40 | $format, 41 | //! Jig log 42 | $log, 43 | //! Memory-held data 44 | $data; 45 | 46 | /** 47 | * Read data from memory/file 48 | * @return array 49 | * @param $file string 50 | **/ 51 | function &read($file) { 52 | if (!$this->dir || !is_file($dst=$this->dir.$file)) { 53 | if (!isset($this->data[$file])) 54 | $this->data[$file]=array(); 55 | return $this->data[$file]; 56 | } 57 | $fw=\Base::instance(); 58 | $raw=$fw->read($dst); 59 | switch ($this->format) { 60 | case self::FORMAT_JSON: 61 | $data=json_decode($raw,TRUE); 62 | break; 63 | case self::FORMAT_Serialized: 64 | $data=$fw->unserialize($raw); 65 | break; 66 | } 67 | $this->data[$file] = $data; 68 | return $this->data[$file]; 69 | } 70 | 71 | /** 72 | * Write data to memory/file 73 | * @return int 74 | * @param $file string 75 | * @param $data array 76 | **/ 77 | function write($file,array $data=NULL) { 78 | if (!$this->dir) 79 | return count($this->data[$file]=$data); 80 | $fw=\Base::instance(); 81 | switch ($this->format) { 82 | case self::FORMAT_JSON: 83 | $out=json_encode($data,@constant('JSON_PRETTY_PRINT')); 84 | break; 85 | case self::FORMAT_Serialized: 86 | $out=$fw->serialize($data); 87 | break; 88 | } 89 | return $fw->write($this->dir.'/'.$file,$out); 90 | } 91 | 92 | /** 93 | * Return directory 94 | * @return string 95 | **/ 96 | function dir() { 97 | return $this->dir; 98 | } 99 | 100 | /** 101 | * Return UUID 102 | * @return string 103 | **/ 104 | function uuid() { 105 | return $this->uuid; 106 | } 107 | 108 | /** 109 | * Return profiler results 110 | * @return string 111 | **/ 112 | function log() { 113 | return $this->log; 114 | } 115 | 116 | /** 117 | * Jot down log entry 118 | * @return NULL 119 | * @param $frame string 120 | **/ 121 | function jot($frame) { 122 | if ($frame) 123 | $this->log.=date('r').' '.$frame.PHP_EOL; 124 | } 125 | 126 | /** 127 | * Clean storage 128 | * @return NULL 129 | **/ 130 | function drop() { 131 | if (!$this->dir) 132 | $this->data=array(); 133 | elseif ($glob=@glob($this->dir.'/*',GLOB_NOSORT)) 134 | foreach ($glob as $file) 135 | @unlink($file); 136 | } 137 | 138 | /** 139 | * Instantiate class 140 | * @param $dir string 141 | * @param $format int 142 | **/ 143 | function __construct($dir=NULL,$format=self::FORMAT_JSON) { 144 | if ($dir && !is_dir($dir)) 145 | mkdir($dir,\Base::MODE,TRUE); 146 | $this->uuid=\Base::instance()->hash($this->dir=$dir); 147 | $this->format=$format; 148 | } 149 | 150 | } 151 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/lib/db/jig/mapper.php: -------------------------------------------------------------------------------- 1 | . 20 | 21 | */ 22 | 23 | namespace DB\Jig; 24 | 25 | //! Flat-file DB mapper 26 | class Mapper extends \DB\Cursor { 27 | 28 | protected 29 | //! Flat-file DB wrapper 30 | $db, 31 | //! Data file 32 | $file, 33 | //! Document identifier 34 | $id, 35 | //! Document contents 36 | $document=array(); 37 | 38 | /** 39 | * Return database type 40 | * @return string 41 | **/ 42 | function dbtype() { 43 | return 'Jig'; 44 | } 45 | 46 | /** 47 | * Return TRUE if field is defined 48 | * @return bool 49 | * @param $key string 50 | **/ 51 | function exists($key) { 52 | return array_key_exists($key,$this->document); 53 | } 54 | 55 | /** 56 | * Assign value to field 57 | * @return scalar|FALSE 58 | * @param $key string 59 | * @param $val scalar 60 | **/ 61 | function set($key,$val) { 62 | return ($key=='_id')?FALSE:($this->document[$key]=$val); 63 | } 64 | 65 | /** 66 | * Retrieve value of field 67 | * @return scalar|FALSE 68 | * @param $key string 69 | **/ 70 | function &get($key) { 71 | if ($key=='_id') 72 | return $this->id; 73 | if (array_key_exists($key,$this->document)) 74 | return $this->document[$key]; 75 | user_error(sprintf(self::E_Field,$key),E_USER_ERROR); 76 | } 77 | 78 | /** 79 | * Delete field 80 | * @return NULL 81 | * @param $key string 82 | **/ 83 | function clear($key) { 84 | if ($key!='_id') 85 | unset($this->document[$key]); 86 | } 87 | 88 | /** 89 | * Convert array to mapper object 90 | * @return object 91 | * @param $id string 92 | * @param $row array 93 | **/ 94 | protected function factory($id,$row) { 95 | $mapper=clone($this); 96 | $mapper->reset(); 97 | $mapper->id=$id; 98 | foreach ($row as $field=>$val) 99 | $mapper->document[$field]=$val; 100 | $mapper->query=array(clone($mapper)); 101 | if (isset($mapper->trigger['load'])) 102 | \Base::instance()->call($mapper->trigger['load'],$mapper); 103 | return $mapper; 104 | } 105 | 106 | /** 107 | * Return fields of mapper object as an associative array 108 | * @return array 109 | * @param $obj object 110 | **/ 111 | function cast($obj=NULL) { 112 | if (!$obj) 113 | $obj=$this; 114 | return $obj->document+array('_id'=>$this->id); 115 | } 116 | 117 | /** 118 | * Convert tokens in string expression to variable names 119 | * @return string 120 | * @param $str string 121 | **/ 122 | function token($str) { 123 | $self=$this; 124 | $str=preg_replace_callback( 125 | '/(?stringify(substr($expr[1],1)): 136 | (preg_match('/^\w+/', 137 | $mix=$self->token($expr[2]))? 138 | $fw->stringify($mix): 139 | $mix)). 140 | ']'; 141 | }, 142 | $token[1] 143 | ); 144 | }, 145 | $str 146 | ); 147 | return trim($str); 148 | } 149 | 150 | /** 151 | * Return records that match criteria 152 | * @return \DB\JIG\Mapper[]|FALSE 153 | * @param $filter array 154 | * @param $options array 155 | * @param $ttl int 156 | * @param $log bool 157 | **/ 158 | function find($filter=NULL,array $options=NULL,$ttl=0,$log=TRUE) { 159 | if (!$options) 160 | $options=array(); 161 | $options+=array( 162 | 'order'=>NULL, 163 | 'limit'=>0, 164 | 'offset'=>0 165 | ); 166 | $fw=\Base::instance(); 167 | $cache=\Cache::instance(); 168 | $db=$this->db; 169 | $now=microtime(TRUE); 170 | $data=array(); 171 | if (!$fw->get('CACHE') || !$ttl || !($cached=$cache->exists( 172 | $hash=$fw->hash($this->db->dir(). 173 | $fw->stringify(array($filter,$options))).'.jig',$data)) || 174 | $cached[0]+$ttlread($this->file); 176 | if (is_null($data)) 177 | return FALSE; 178 | foreach ($data as $id=>&$doc) { 179 | $doc['_id']=$id; 180 | unset($doc); 181 | } 182 | if ($filter) { 183 | if (!is_array($filter)) 184 | return FALSE; 185 | // Normalize equality operator 186 | $expr=preg_replace('/(?<=[^<>!=])=(?!=)/','==',$filter[0]); 187 | // Prepare query arguments 188 | $args=isset($filter[1]) && is_array($filter[1])? 189 | $filter[1]: 190 | array_slice($filter,1,NULL,TRUE); 191 | $args=is_array($args)?$args:array(1=>$args); 192 | $keys=$vals=array(); 193 | $tokens=array_slice( 194 | token_get_all('token($expr)),1); 195 | $data=array_filter($data, 196 | function($_row) use($fw,$args,$tokens) { 197 | $_expr=''; 198 | $ctr=0; 199 | $named=FALSE; 200 | foreach ($tokens as $token) { 201 | if (is_string($token)) 202 | if ($token=='?') { 203 | // Positional 204 | $ctr++; 205 | $key=$ctr; 206 | } 207 | else { 208 | if ($token==':') 209 | $named=TRUE; 210 | else 211 | $_expr.=$token; 212 | continue; 213 | } 214 | elseif ($named && 215 | token_name($token[0])=='T_STRING') { 216 | $key=':'.$token[1]; 217 | $named=FALSE; 218 | } 219 | else { 220 | $_expr.=$token[1]; 221 | continue; 222 | } 223 | $_expr.=$fw->stringify( 224 | is_string($args[$key])? 225 | addcslashes($args[$key],'\''): 226 | $args[$key]); 227 | } 228 | // Avoid conflict with user code 229 | unset($fw,$tokens,$args,$ctr,$token,$key,$named); 230 | extract($_row); 231 | // Evaluate pseudo-SQL expression 232 | return eval('return '.$_expr.';'); 233 | } 234 | ); 235 | } 236 | if (isset($options['order'])) { 237 | $cols=$fw->split($options['order']); 238 | uasort( 239 | $data, 240 | function($val1,$val2) use($cols) { 241 | foreach ($cols as $col) { 242 | $parts=explode(' ',$col,2); 243 | $order=empty($parts[1])? 244 | SORT_ASC: 245 | constant($parts[1]); 246 | $col=$parts[0]; 247 | if (!array_key_exists($col,$val1)) 248 | $val1[$col]=NULL; 249 | if (!array_key_exists($col,$val2)) 250 | $val2[$col]=NULL; 251 | list($v1,$v2)=array($val1[$col],$val2[$col]); 252 | if ($out=strnatcmp($v1,$v2)* 253 | (($order==SORT_ASC)*2-1)) 254 | return $out; 255 | } 256 | return 0; 257 | } 258 | ); 259 | } 260 | $data=array_slice($data, 261 | $options['offset'],$options['limit']?:NULL,TRUE); 262 | if ($fw->get('CACHE') && $ttl) 263 | // Save to cache backend 264 | $cache->set($hash,$data,$ttl); 265 | } 266 | $out=array(); 267 | foreach ($data as $id=>&$doc) { 268 | unset($doc['_id']); 269 | $out[]=$this->factory($id,$doc); 270 | unset($doc); 271 | } 272 | if ($log && isset($args)) { 273 | if ($filter) 274 | foreach ($args as $key=>$val) { 275 | $vals[]=$fw->stringify(is_array($val)?$val[0]:$val); 276 | $keys[]='/'.(is_numeric($key)?'\?':preg_quote($key)).'/'; 277 | } 278 | $db->jot('('.sprintf('%.1f',1e3*(microtime(TRUE)-$now)).'ms) '. 279 | $this->file.' [find] '. 280 | ($filter?preg_replace($keys,$vals,$filter[0],1):'')); 281 | } 282 | return $out; 283 | } 284 | 285 | /** 286 | * Count records that match criteria 287 | * @return int 288 | * @param $filter array 289 | * @param $ttl int 290 | **/ 291 | function count($filter=NULL,$ttl=0) { 292 | $now=microtime(TRUE); 293 | $out=count($this->find($filter,NULL,$ttl,FALSE)); 294 | $this->db->jot('('.sprintf('%.1f',1e3*(microtime(TRUE)-$now)).'ms) '. 295 | $this->file.' [count] '.($filter?json_encode($filter):'')); 296 | return $out; 297 | } 298 | 299 | /** 300 | * Return record at specified offset using criteria of previous 301 | * load() call and make it active 302 | * @return array 303 | * @param $ofs int 304 | **/ 305 | function skip($ofs=1) { 306 | $this->document=($out=parent::skip($ofs))?$out->document:array(); 307 | $this->id=$out?$out->id:NULL; 308 | if ($this->document && isset($this->trigger['load'])) 309 | \Base::instance()->call($this->trigger['load'],$this); 310 | return $out; 311 | } 312 | 313 | /** 314 | * Insert new record 315 | * @return array 316 | **/ 317 | function insert() { 318 | if ($this->id) 319 | return $this->update(); 320 | $db=$this->db; 321 | $now=microtime(TRUE); 322 | while (($id=uniqid(NULL,TRUE)) && 323 | ($data=&$db->read($this->file)) && isset($data[$id]) && 324 | !connection_aborted()) 325 | usleep(mt_rand(0,100)); 326 | $this->id=$id; 327 | $pkey=array('_id'=>$this->id); 328 | if (isset($this->trigger['beforeinsert']) && 329 | \Base::instance()->call($this->trigger['beforeinsert'], 330 | array($this,$pkey))===FALSE) 331 | return $this->document; 332 | $data[$id]=$this->document; 333 | $db->write($this->file,$data); 334 | $db->jot('('.sprintf('%.1f',1e3*(microtime(TRUE)-$now)).'ms) '. 335 | $this->file.' [insert] '.json_encode($this->document)); 336 | if (isset($this->trigger['afterinsert'])) 337 | \Base::instance()->call($this->trigger['afterinsert'], 338 | array($this,$pkey)); 339 | $this->load(array('@_id=?',$this->id)); 340 | return $this->document; 341 | } 342 | 343 | /** 344 | * Update current record 345 | * @return array 346 | **/ 347 | function update() { 348 | $db=$this->db; 349 | $now=microtime(TRUE); 350 | $data=&$db->read($this->file); 351 | if (isset($this->trigger['beforeupdate']) && 352 | \Base::instance()->call($this->trigger['beforeupdate'], 353 | array($this,array('_id'=>$this->id)))===FALSE) 354 | return $this->document; 355 | $data[$this->id]=$this->document; 356 | $db->write($this->file,$data); 357 | $db->jot('('.sprintf('%.1f',1e3*(microtime(TRUE)-$now)).'ms) '. 358 | $this->file.' [update] '.json_encode($this->document)); 359 | if (isset($this->trigger['afterupdate'])) 360 | \Base::instance()->call($this->trigger['afterupdate'], 361 | array($this,array('_id'=>$this->id))); 362 | return $this->document; 363 | } 364 | 365 | /** 366 | * Delete current record 367 | * @return bool 368 | * @param $filter array 369 | **/ 370 | function erase($filter=NULL) { 371 | $db=$this->db; 372 | $now=microtime(TRUE); 373 | $data=&$db->read($this->file); 374 | $pkey=array('_id'=>$this->id); 375 | if ($filter) { 376 | foreach ($this->find($filter,NULL,FALSE) as $mapper) 377 | if (!$mapper->erase()) 378 | return FALSE; 379 | return TRUE; 380 | } 381 | elseif (isset($this->id)) { 382 | unset($data[$this->id]); 383 | parent::erase(); 384 | } 385 | else 386 | return FALSE; 387 | if (isset($this->trigger['beforeerase']) && 388 | \Base::instance()->call($this->trigger['beforeerase'], 389 | array($this,$pkey))===FALSE) 390 | return FALSE; 391 | $db->write($this->file,$data); 392 | if ($filter) { 393 | $args=isset($filter[1]) && is_array($filter[1])? 394 | $filter[1]: 395 | array_slice($filter,1,NULL,TRUE); 396 | $args=is_array($args)?$args:array(1=>$args); 397 | foreach ($args as $key=>$val) { 398 | $vals[]=\Base::instance()-> 399 | stringify(is_array($val)?$val[0]:$val); 400 | $keys[]='/'.(is_numeric($key)?'\?':preg_quote($key)).'/'; 401 | } 402 | } 403 | $db->jot('('.sprintf('%.1f',1e3*(microtime(TRUE)-$now)).'ms) '. 404 | $this->file.' [erase] '. 405 | ($filter?preg_replace($keys,$vals,$filter[0],1):'')); 406 | if (isset($this->trigger['aftererase'])) 407 | \Base::instance()->call($this->trigger['aftererase'], 408 | array($this,$pkey)); 409 | return TRUE; 410 | } 411 | 412 | /** 413 | * Reset cursor 414 | * @return NULL 415 | **/ 416 | function reset() { 417 | $this->id=NULL; 418 | $this->document=array(); 419 | parent::reset(); 420 | } 421 | 422 | /** 423 | * Hydrate mapper object using hive array variable 424 | * @return NULL 425 | * @param $var array|string 426 | * @param $func callback 427 | **/ 428 | function copyfrom($var,$func=NULL) { 429 | if (is_string($var)) 430 | $var=\Base::instance()->get($var); 431 | if ($func) 432 | $var=call_user_func($func,$var); 433 | foreach ($var as $key=>$val) 434 | $this->document[$key]=$val; 435 | } 436 | 437 | /** 438 | * Populate hive array variable with mapper fields 439 | * @return NULL 440 | * @param $key string 441 | **/ 442 | function copyto($key) { 443 | $var=&\Base::instance()->ref($key); 444 | foreach ($this->document as $key=>$field) 445 | $var[$key]=$field; 446 | } 447 | 448 | /** 449 | * Return field names 450 | * @return array 451 | **/ 452 | function fields() { 453 | return array_keys($this->document); 454 | } 455 | 456 | /** 457 | * Retrieve external iterator for fields 458 | * @return object 459 | **/ 460 | function getiterator() { 461 | return new \ArrayIterator($this->cast()); 462 | } 463 | 464 | /** 465 | * Instantiate class 466 | * @return void 467 | * @param $db object 468 | * @param $file string 469 | **/ 470 | function __construct(\DB\Jig $db,$file) { 471 | $this->db=$db; 472 | $this->file=$file; 473 | $this->reset(); 474 | } 475 | 476 | } 477 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/lib/db/jig/session.php: -------------------------------------------------------------------------------- 1 | . 20 | 21 | */ 22 | 23 | namespace DB\Jig; 24 | 25 | //! Jig-managed session handler 26 | class Session extends Mapper { 27 | 28 | protected 29 | //! Session ID 30 | $sid; 31 | 32 | /** 33 | * Open session 34 | * @return TRUE 35 | * @param $path string 36 | * @param $name string 37 | **/ 38 | function open($path,$name) { 39 | return TRUE; 40 | } 41 | 42 | /** 43 | * Close session 44 | * @return TRUE 45 | **/ 46 | function close() { 47 | return TRUE; 48 | } 49 | 50 | /** 51 | * Return session data in serialized format 52 | * @return string|FALSE 53 | * @param $id string 54 | **/ 55 | function read($id) { 56 | if ($id!=$this->sid) 57 | $this->load(array('@session_id=?',$this->sid=$id)); 58 | return $this->dry()?FALSE:$this->get('data'); 59 | } 60 | 61 | /** 62 | * Write session data 63 | * @return TRUE 64 | * @param $id string 65 | * @param $data string 66 | **/ 67 | function write($id,$data) { 68 | $fw=\Base::instance(); 69 | $sent=headers_sent(); 70 | $headers=$fw->get('HEADERS'); 71 | if ($id!=$this->sid) 72 | $this->load(array('@session_id=?',$this->sid=$id)); 73 | $csrf=$fw->hash($fw->get('ROOT').$fw->get('BASE')).'.'. 74 | $fw->hash(mt_rand()); 75 | $this->set('session_id',$id); 76 | $this->set('data',$data); 77 | $this->set('csrf',$sent?$this->csrf():$csrf); 78 | $this->set('ip',$fw->get('IP')); 79 | $this->set('agent', 80 | isset($headers['User-Agent'])?$headers['User-Agent']:''); 81 | $this->set('stamp',time()); 82 | $this->save(); 83 | return TRUE; 84 | } 85 | 86 | /** 87 | * Destroy session 88 | * @return TRUE 89 | * @param $id string 90 | **/ 91 | function destroy($id) { 92 | $this->erase(array('@session_id=?',$id)); 93 | setcookie(session_name(),'',strtotime('-1 year')); 94 | unset($_COOKIE[session_name()]); 95 | header_remove('Set-Cookie'); 96 | return TRUE; 97 | } 98 | 99 | /** 100 | * Garbage collector 101 | * @return TRUE 102 | * @param $max int 103 | **/ 104 | function cleanup($max) { 105 | $this->erase(array('@stamp+?dry()?FALSE:$this->get('csrf'); 115 | } 116 | 117 | /** 118 | * Return IP address 119 | * @return string|FALSE 120 | **/ 121 | function ip() { 122 | return $this->dry()?FALSE:$this->get('ip'); 123 | } 124 | 125 | /** 126 | * Return Unix timestamp 127 | * @return string|FALSE 128 | **/ 129 | function stamp() { 130 | return $this->dry()?FALSE:$this->get('stamp'); 131 | } 132 | 133 | /** 134 | * Return HTTP user agent 135 | * @return string|FALSE 136 | **/ 137 | function agent() { 138 | return $this->dry()?FALSE:$this->get('agent'); 139 | } 140 | 141 | /** 142 | * Instantiate class 143 | * @param $db object 144 | * @param $file string 145 | * @param $onsuspect callback 146 | **/ 147 | function __construct(\DB\Jig $db,$file='sessions',$onsuspect=NULL) { 148 | parent::__construct($db,$file); 149 | session_set_save_handler( 150 | array($this,'open'), 151 | array($this,'close'), 152 | array($this,'read'), 153 | array($this,'write'), 154 | array($this,'destroy'), 155 | array($this,'cleanup') 156 | ); 157 | register_shutdown_function('session_commit'); 158 | @session_start(); 159 | $fw=\Base::instance(); 160 | $headers=$fw->get('HEADERS'); 161 | if (($ip=$this->ip()) && $ip!=$fw->get('IP') || 162 | ($agent=$this->agent()) && 163 | (!isset($headers['User-Agent']) || 164 | $agent!=$headers['User-Agent'])) { 165 | if (isset($onsuspect)) 166 | $fw->call($onsuspect,array($this)); 167 | else { 168 | session_destroy(); 169 | $fw->error(403); 170 | } 171 | } 172 | $csrf=$fw->hash($fw->get('ROOT').$fw->get('BASE')).'.'. 173 | $fw->hash(mt_rand()); 174 | if ($this->load(array('@session_id=?',$this->sid=session_id()))) { 175 | $this->set('csrf',$csrf); 176 | $this->save(); 177 | } 178 | } 179 | 180 | } 181 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/lib/db/mongo.php: -------------------------------------------------------------------------------- 1 | . 20 | 21 | */ 22 | 23 | namespace DB; 24 | 25 | //! MongoDB wrapper 26 | class Mongo { 27 | 28 | //@{ 29 | const 30 | E_Profiler='MongoDB profiler is disabled'; 31 | //@} 32 | 33 | protected 34 | //! UUID 35 | $uuid, 36 | //! Data source name 37 | $dsn, 38 | //! MongoDB object 39 | $db, 40 | //! MongoDB log 41 | $log; 42 | 43 | /** 44 | * Return data source name 45 | * @return string 46 | **/ 47 | function dsn() { 48 | return $this->dsn; 49 | } 50 | 51 | /** 52 | * Return UUID 53 | * @return string 54 | **/ 55 | function uuid() { 56 | return $this->uuid; 57 | } 58 | 59 | /** 60 | * Return MongoDB profiler results 61 | * @return string 62 | **/ 63 | function log() { 64 | $cursor=$this->selectcollection('system.profile')->find(); 65 | foreach (iterator_to_array($cursor) as $frame) 66 | if (!preg_match('/\.system\..+$/',$frame['ns'])) 67 | $this->log.=date('r',$frame['ts']->sec).' ('. 68 | sprintf('%.1f',$frame['millis']).'ms) '. 69 | $frame['ns'].' ['.$frame['op'].'] '. 70 | (empty($frame['query'])? 71 | '':json_encode($frame['query'])). 72 | (empty($frame['command'])? 73 | '':json_encode($frame['command'])). 74 | PHP_EOL; 75 | return $this->log; 76 | } 77 | 78 | /** 79 | * Intercept native call to re-enable profiler 80 | * @return int 81 | **/ 82 | function drop() { 83 | $out=$this->db->drop(); 84 | $this->setprofilinglevel(2); 85 | return $out; 86 | } 87 | 88 | /** 89 | * Redirect call to MongoDB object 90 | * @return mixed 91 | * @param $func string 92 | * @param $args array 93 | **/ 94 | function __call($func,array $args) { 95 | return call_user_func_array(array($this->db,$func),$args); 96 | } 97 | 98 | /** 99 | * Instantiate class 100 | * @param $dsn string 101 | * @param $dbname string 102 | * @param $options array 103 | **/ 104 | function __construct($dsn,$dbname,array $options=NULL) { 105 | $this->uuid=\Base::instance()->hash($this->dsn=$dsn); 106 | $class=class_exists('\MongoClient')?'\MongoClient':'\Mongo'; 107 | $this->db=new \MongoDB(new $class($dsn,$options?:array()),$dbname); 108 | $this->setprofilinglevel(2); 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/lib/db/mongo/mapper.php: -------------------------------------------------------------------------------- 1 | . 20 | 21 | */ 22 | 23 | namespace DB\Mongo; 24 | 25 | //! MongoDB mapper 26 | class Mapper extends \DB\Cursor { 27 | 28 | protected 29 | //! MongoDB wrapper 30 | $db, 31 | //! Mongo collection 32 | $collection, 33 | //! Mongo document 34 | $document=array(), 35 | //! Mongo cursor 36 | $cursor; 37 | 38 | /** 39 | * Return database type 40 | * @return string 41 | **/ 42 | function dbtype() { 43 | return 'Mongo'; 44 | } 45 | 46 | /** 47 | * Return TRUE if field is defined 48 | * @return bool 49 | * @param $key string 50 | **/ 51 | function exists($key) { 52 | return array_key_exists($key,$this->document); 53 | } 54 | 55 | /** 56 | * Assign value to field 57 | * @return scalar|FALSE 58 | * @param $key string 59 | * @param $val scalar 60 | **/ 61 | function set($key,$val) { 62 | return $this->document[$key]=$val; 63 | } 64 | 65 | /** 66 | * Retrieve value of field 67 | * @return scalar|FALSE 68 | * @param $key string 69 | **/ 70 | function &get($key) { 71 | if ($this->exists($key)) 72 | return $this->document[$key]; 73 | user_error(sprintf(self::E_Field,$key),E_USER_ERROR); 74 | } 75 | 76 | /** 77 | * Delete field 78 | * @return NULL 79 | * @param $key string 80 | **/ 81 | function clear($key) { 82 | unset($this->document[$key]); 83 | } 84 | 85 | /** 86 | * Convert array to mapper object 87 | * @return \DB\Mongo\Mapper 88 | * @param $row array 89 | **/ 90 | protected function factory($row) { 91 | $mapper=clone($this); 92 | $mapper->reset(); 93 | foreach ($row as $key=>$val) 94 | $mapper->document[$key]=$val; 95 | $mapper->query=array(clone($mapper)); 96 | if (isset($mapper->trigger['load'])) 97 | \Base::instance()->call($mapper->trigger['load'],$mapper); 98 | return $mapper; 99 | } 100 | 101 | /** 102 | * Return fields of mapper object as an associative array 103 | * @return array 104 | * @param $obj object 105 | **/ 106 | function cast($obj=NULL) { 107 | if (!$obj) 108 | $obj=$this; 109 | return $obj->document; 110 | } 111 | 112 | /** 113 | * Build query and execute 114 | * @return \DB\Mongo\Mapper[] 115 | * @param $fields string 116 | * @param $filter array 117 | * @param $options array 118 | * @param $ttl int 119 | **/ 120 | function select($fields=NULL,$filter=NULL,array $options=NULL,$ttl=0) { 121 | if (!$options) 122 | $options=array(); 123 | $options+=array( 124 | 'group'=>NULL, 125 | 'order'=>NULL, 126 | 'limit'=>0, 127 | 'offset'=>0 128 | ); 129 | $fw=\Base::instance(); 130 | $cache=\Cache::instance(); 131 | if (!($cached=$cache->exists($hash=$fw->hash($this->db->dsn(). 132 | $fw->stringify(array($fields,$filter,$options))).'.mongo', 133 | $result)) || !$ttl || $cached[0]+$ttlcollection->group( 136 | $options['group']['keys'], 137 | $options['group']['initial'], 138 | $options['group']['reduce'], 139 | array( 140 | 'condition'=>$filter, 141 | 'finalize'=>$options['group']['finalize'] 142 | ) 143 | ); 144 | $tmp=$this->db->selectcollection( 145 | $fw->get('HOST').'.'.$fw->get('BASE').'.'. 146 | uniqid(NULL,TRUE).'.tmp' 147 | ); 148 | $tmp->batchinsert($grp['retval'],array('w'=>1)); 149 | $filter=array(); 150 | $collection=$tmp; 151 | } 152 | else { 153 | $filter=$filter?:array(); 154 | $collection=$this->collection; 155 | } 156 | $this->cursor=$collection->find($filter,$fields?:array()); 157 | if ($options['order']) 158 | $this->cursor=$this->cursor->sort($options['order']); 159 | if ($options['limit']) 160 | $this->cursor=$this->cursor->limit($options['limit']); 161 | if ($options['offset']) 162 | $this->cursor=$this->cursor->skip($options['offset']); 163 | $result=array(); 164 | while ($this->cursor->hasnext()) 165 | $result[]=$this->cursor->getnext(); 166 | if ($options['group']) 167 | $tmp->drop(); 168 | if ($fw->get('CACHE') && $ttl) 169 | // Save to cache backend 170 | $cache->set($hash,$result,$ttl); 171 | } 172 | $out=array(); 173 | foreach ($result as $doc) 174 | $out[]=$this->factory($doc); 175 | return $out; 176 | } 177 | 178 | /** 179 | * Return records that match criteria 180 | * @return \DB\Mongo\Mapper[] 181 | * @param $filter array 182 | * @param $options array 183 | * @param $ttl int 184 | **/ 185 | function find($filter=NULL,array $options=NULL,$ttl=0) { 186 | if (!$options) 187 | $options=array(); 188 | $options+=array( 189 | 'group'=>NULL, 190 | 'order'=>NULL, 191 | 'limit'=>0, 192 | 'offset'=>0 193 | ); 194 | return $this->select(NULL,$filter,$options,$ttl); 195 | } 196 | 197 | /** 198 | * Count records that match criteria 199 | * @return int 200 | * @param $filter array 201 | * @param $ttl int 202 | **/ 203 | function count($filter=NULL,$ttl=0) { 204 | $fw=\Base::instance(); 205 | $cache=\Cache::instance(); 206 | if (!($cached=$cache->exists($hash=$fw->hash($fw->stringify( 207 | array($filter))).'.mongo',$result)) || !$ttl || 208 | $cached[0]+$ttlcollection->count($filter?:array()); 210 | if ($fw->get('CACHE') && $ttl) 211 | // Save to cache backend 212 | $cache->set($hash,$result,$ttl); 213 | } 214 | return $result; 215 | } 216 | 217 | /** 218 | * Return record at specified offset using criteria of previous 219 | * load() call and make it active 220 | * @return array 221 | * @param $ofs int 222 | **/ 223 | function skip($ofs=1) { 224 | $this->document=($out=parent::skip($ofs))?$out->document:array(); 225 | if ($this->document && isset($this->trigger['load'])) 226 | \Base::instance()->call($this->trigger['load'],$this); 227 | return $out; 228 | } 229 | 230 | /** 231 | * Insert new record 232 | * @return array 233 | **/ 234 | function insert() { 235 | if (isset($this->document['_id'])) 236 | return $this->update(); 237 | if (isset($this->trigger['beforeinsert']) && 238 | \Base::instance()->call($this->trigger['beforeinsert'], 239 | array($this,array('_id'=>$this->document['_id'])))===FALSE) 240 | return $this->document; 241 | $this->collection->insert($this->document); 242 | $pkey=array('_id'=>$this->document['_id']); 243 | if (isset($this->trigger['afterinsert'])) 244 | \Base::instance()->call($this->trigger['afterinsert'], 245 | array($this,$pkey)); 246 | $this->load($pkey); 247 | return $this->document; 248 | } 249 | 250 | /** 251 | * Update current record 252 | * @return array 253 | **/ 254 | function update() { 255 | $pkey=array('_id'=>$this->document['_id']); 256 | if (isset($this->trigger['beforeupdate']) && 257 | \Base::instance()->call($this->trigger['beforeupdate'], 258 | array($this,$pkey))===FALSE) 259 | return $this->document; 260 | $this->collection->update( 261 | $pkey,$this->document,array('upsert'=>TRUE)); 262 | if (isset($this->trigger['afterupdate'])) 263 | \Base::instance()->call($this->trigger['afterupdate'], 264 | array($this,$pkey)); 265 | return $this->document; 266 | } 267 | 268 | /** 269 | * Delete current record 270 | * @return bool 271 | * @param $filter array 272 | **/ 273 | function erase($filter=NULL) { 274 | if ($filter) 275 | return $this->collection->remove($filter); 276 | $pkey=array('_id'=>$this->document['_id']); 277 | if (isset($this->trigger['beforeerase']) && 278 | \Base::instance()->call($this->trigger['beforeerase'], 279 | array($this,$pkey))===FALSE) 280 | return FALSE; 281 | $result=$this->collection-> 282 | remove(array('_id'=>$this->document['_id'])); 283 | parent::erase(); 284 | if (isset($this->trigger['aftererase'])) 285 | \Base::instance()->call($this->trigger['aftererase'], 286 | array($this,$pkey)); 287 | return $result; 288 | } 289 | 290 | /** 291 | * Reset cursor 292 | * @return NULL 293 | **/ 294 | function reset() { 295 | $this->document=array(); 296 | parent::reset(); 297 | } 298 | 299 | /** 300 | * Hydrate mapper object using hive array variable 301 | * @return NULL 302 | * @param $var array|string 303 | * @param $func callback 304 | **/ 305 | function copyfrom($var,$func=NULL) { 306 | if (is_string($var)) 307 | $var=\Base::instance()->get($var); 308 | if ($func) 309 | $var=call_user_func($func,$var); 310 | foreach ($var as $key=>$val) 311 | $this->document[$key]=$val; 312 | } 313 | 314 | /** 315 | * Populate hive array variable with mapper fields 316 | * @return NULL 317 | * @param $key string 318 | **/ 319 | function copyto($key) { 320 | $var=&\Base::instance()->ref($key); 321 | foreach ($this->document as $key=>$field) 322 | $var[$key]=$field; 323 | } 324 | 325 | /** 326 | * Return field names 327 | * @return array 328 | **/ 329 | function fields() { 330 | return array_keys($this->document); 331 | } 332 | 333 | /** 334 | * Return the cursor from last query 335 | * @return object|NULL 336 | **/ 337 | function cursor() { 338 | return $this->cursor; 339 | } 340 | 341 | /** 342 | * Retrieve external iterator for fields 343 | * @return object 344 | **/ 345 | function getiterator() { 346 | return new \ArrayIterator($this->cast()); 347 | } 348 | 349 | /** 350 | * Instantiate class 351 | * @return void 352 | * @param $db object 353 | * @param $collection string 354 | **/ 355 | function __construct(\DB\Mongo $db,$collection) { 356 | $this->db=$db; 357 | $this->collection=$db->selectcollection($collection); 358 | $this->reset(); 359 | } 360 | 361 | } 362 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/lib/db/mongo/session.php: -------------------------------------------------------------------------------- 1 | . 20 | 21 | */ 22 | 23 | namespace DB\Mongo; 24 | 25 | //! MongoDB-managed session handler 26 | class Session extends Mapper { 27 | 28 | protected 29 | //! Session ID 30 | $sid; 31 | 32 | /** 33 | * Open session 34 | * @return TRUE 35 | * @param $path string 36 | * @param $name string 37 | **/ 38 | function open($path,$name) { 39 | return TRUE; 40 | } 41 | 42 | /** 43 | * Close session 44 | * @return TRUE 45 | **/ 46 | function close() { 47 | return TRUE; 48 | } 49 | 50 | /** 51 | * Return session data in serialized format 52 | * @return string|FALSE 53 | * @param $id string 54 | **/ 55 | function read($id) { 56 | if ($id!=$this->sid) 57 | $this->load(array('session_id'=>$this->sid=$id)); 58 | return $this->dry()?FALSE:$this->get('data'); 59 | } 60 | 61 | /** 62 | * Write session data 63 | * @return TRUE 64 | * @param $id string 65 | * @param $data string 66 | **/ 67 | function write($id,$data) { 68 | $fw=\Base::instance(); 69 | $sent=headers_sent(); 70 | $headers=$fw->get('HEADERS'); 71 | if ($id!=$this->sid) 72 | $this->load(array('session_id'=>$this->sid=$id)); 73 | $csrf=$fw->hash($fw->get('ROOT').$fw->get('BASE')).'.'. 74 | $fw->hash(mt_rand()); 75 | $this->set('session_id',$id); 76 | $this->set('data',$data); 77 | $this->set('csrf',$sent?$this->csrf():$csrf); 78 | $this->set('ip',$fw->get('IP')); 79 | $this->set('agent', 80 | isset($headers['User-Agent'])?$headers['User-Agent']:''); 81 | $this->set('stamp',time()); 82 | $this->save(); 83 | return TRUE; 84 | } 85 | 86 | /** 87 | * Destroy session 88 | * @return TRUE 89 | * @param $id string 90 | **/ 91 | function destroy($id) { 92 | $this->erase(array('session_id'=>$id)); 93 | setcookie(session_name(),'',strtotime('-1 year')); 94 | unset($_COOKIE[session_name()]); 95 | header_remove('Set-Cookie'); 96 | return TRUE; 97 | } 98 | 99 | /** 100 | * Garbage collector 101 | * @return TRUE 102 | * @param $max int 103 | **/ 104 | function cleanup($max) { 105 | $this->erase(array('$where'=>'this.stamp+'.$max.'<'.time())); 106 | return TRUE; 107 | } 108 | 109 | /** 110 | * Return anti-CSRF token 111 | * @return string|FALSE 112 | **/ 113 | function csrf() { 114 | return $this->dry()?FALSE:$this->get('csrf'); 115 | } 116 | 117 | /** 118 | * Return IP address 119 | * @return string|FALSE 120 | **/ 121 | function ip() { 122 | return $this->dry()?FALSE:$this->get('ip'); 123 | } 124 | 125 | /** 126 | * Return Unix timestamp 127 | * @return string|FALSE 128 | **/ 129 | function stamp() { 130 | return $this->dry()?FALSE:$this->get('stamp'); 131 | } 132 | 133 | /** 134 | * Return HTTP user agent 135 | * @return string|FALSE 136 | **/ 137 | function agent() { 138 | return $this->dry()?FALSE:$this->get('agent'); 139 | } 140 | 141 | /** 142 | * Instantiate class 143 | * @param $db object 144 | * @param $table string 145 | * @param $onsuspect callback 146 | **/ 147 | function __construct(\DB\Mongo $db,$table='sessions',$onsuspect=NULL) { 148 | parent::__construct($db,$table); 149 | session_set_save_handler( 150 | array($this,'open'), 151 | array($this,'close'), 152 | array($this,'read'), 153 | array($this,'write'), 154 | array($this,'destroy'), 155 | array($this,'cleanup') 156 | ); 157 | register_shutdown_function('session_commit'); 158 | @session_start(); 159 | $fw=\Base::instance(); 160 | $headers=$fw->get('HEADERS'); 161 | if (($ip=$this->ip()) && $ip!=$fw->get('IP') || 162 | ($agent=$this->agent()) && 163 | (!isset($headers['User-Agent']) || 164 | $agent!=$headers['User-Agent'])) { 165 | if (isset($onsuspect)) 166 | $fw->call($onsuspect,array($this)); 167 | else { 168 | session_destroy(); 169 | $fw->error(403); 170 | } 171 | } 172 | $csrf=$fw->hash($fw->get('ROOT').$fw->get('BASE')).'.'. 173 | $fw->hash(mt_rand()); 174 | if ($this->load(array('session_id'=>$this->sid=session_id()))) { 175 | $this->set('csrf',$csrf); 176 | $this->save(); 177 | } 178 | } 179 | 180 | } 181 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/lib/db/sql.php: -------------------------------------------------------------------------------- 1 | . 20 | 21 | */ 22 | 23 | namespace DB; 24 | 25 | //! PDO wrapper 26 | class SQL { 27 | 28 | //@{ Error messages 29 | const 30 | E_PKey='Table %s does not have a primary key'; 31 | //@} 32 | 33 | protected 34 | //! UUID 35 | $uuid, 36 | //! Raw PDO 37 | $pdo, 38 | //! Data source name 39 | $dsn, 40 | //! Database engine 41 | $engine, 42 | //! Database name 43 | $dbname, 44 | //! Transaction flag 45 | $trans=FALSE, 46 | //! Number of rows affected by query 47 | $rows=0, 48 | //! SQL log 49 | $log; 50 | 51 | /** 52 | * Begin SQL transaction 53 | * @return bool 54 | **/ 55 | function begin() { 56 | $out=$this->pdo->begintransaction(); 57 | $this->trans=TRUE; 58 | return $out; 59 | } 60 | 61 | /** 62 | * Rollback SQL transaction 63 | * @return bool 64 | **/ 65 | function rollback() { 66 | $out=$this->pdo->rollback(); 67 | $this->trans=FALSE; 68 | return $out; 69 | } 70 | 71 | /** 72 | * Commit SQL transaction 73 | * @return bool 74 | **/ 75 | function commit() { 76 | $out=$this->pdo->commit(); 77 | $this->trans=FALSE; 78 | return $out; 79 | } 80 | 81 | /** 82 | * Map data type of argument to a PDO constant 83 | * @return int 84 | * @param $val scalar 85 | **/ 86 | function type($val) { 87 | switch (gettype($val)) { 88 | case 'NULL': 89 | return \PDO::PARAM_NULL; 90 | case 'boolean': 91 | return \PDO::PARAM_BOOL; 92 | case 'integer': 93 | return \PDO::PARAM_INT; 94 | default: 95 | return \PDO::PARAM_STR; 96 | } 97 | } 98 | 99 | /** 100 | * Cast value to PHP type 101 | * @return scalar 102 | * @param $type string 103 | * @param $val scalar 104 | **/ 105 | function value($type,$val) { 106 | switch ($type) { 107 | case \PDO::PARAM_NULL: 108 | return (unset)$val; 109 | case \PDO::PARAM_INT: 110 | return (int)$val; 111 | case \PDO::PARAM_BOOL: 112 | return (bool)$val; 113 | case \PDO::PARAM_STR: 114 | return (string)$val; 115 | } 116 | } 117 | 118 | /** 119 | * Execute SQL statement(s) 120 | * @return array|int|FALSE 121 | * @param $cmds string|array 122 | * @param $args string|array 123 | * @param $ttl int 124 | * @param $log bool 125 | **/ 126 | function exec($cmds,$args=NULL,$ttl=0,$log=TRUE) { 127 | $auto=FALSE; 128 | if (is_null($args)) 129 | $args=array(); 130 | elseif (is_scalar($args)) 131 | $args=array(1=>$args); 132 | if (is_array($cmds)) { 133 | if (count($args)<($count=count($cmds))) 134 | // Apply arguments to SQL commands 135 | $args=array_fill(0,$count,$args); 136 | if (!$this->trans) { 137 | $this->begin(); 138 | $auto=TRUE; 139 | } 140 | } 141 | else { 142 | $count=1; 143 | $cmds=array($cmds); 144 | $args=array($args); 145 | } 146 | $fw=\Base::instance(); 147 | $cache=\Cache::instance(); 148 | $result=FALSE; 149 | for ($i=0;$i<$count;$i++) { 150 | $cmd=$cmds[$i]; 151 | $arg=$args[$i]; 152 | if (!preg_replace('/(^\s+|[\s;]+$)/','',$cmd)) 153 | continue; 154 | $now=microtime(TRUE); 155 | $keys=$vals=array(); 156 | if ($fw->get('CACHE') && $ttl && ($cached=$cache->exists( 157 | $hash=$fw->hash($this->dsn.$cmd. 158 | $fw->stringify($arg)).'.sql',$result)) && 159 | $cached[0]+$ttl>microtime(TRUE)) { 160 | foreach ($arg as $key=>$val) { 161 | $vals[]=$fw->stringify(is_array($val)?$val[0]:$val); 162 | $keys[]='/'.preg_quote(is_numeric($key)?chr(0).'?':$key). 163 | '/'; 164 | } 165 | if ($log) 166 | $this->log.=date('r').' ('. 167 | sprintf('%.1f',1e3*(microtime(TRUE)-$now)).'ms) '. 168 | '[CACHED] '. 169 | preg_replace($keys,$vals, 170 | str_replace('?',chr(0).'?',$cmd),1).PHP_EOL; 171 | } 172 | elseif (is_object($query=$this->pdo->prepare($cmd))) { 173 | foreach ($arg as $key=>$val) { 174 | if (is_array($val)) { 175 | // User-specified data type 176 | $query->bindvalue($key,$val[0],$val[1]); 177 | $vals[]=$fw->stringify($this->value($val[1],$val[0])); 178 | } 179 | else { 180 | // Convert to PDO data type 181 | $query->bindvalue($key,$val, 182 | $type=$this->type($val)); 183 | $vals[]=$fw->stringify($this->value($type,$val)); 184 | } 185 | $keys[]='/'.preg_quote(is_numeric($key)?chr(0).'?':$key). 186 | '/'; 187 | } 188 | if ($log) 189 | $this->log.=date('r').' ('. 190 | sprintf('%.1f',1e3*(microtime(TRUE)-$now)).'ms) '. 191 | preg_replace($keys,$vals, 192 | str_replace('?',chr(0).'?',$cmd),1).PHP_EOL; 193 | $query->execute(); 194 | $error=$query->errorinfo(); 195 | if ($error[0]!=\PDO::ERR_NONE) { 196 | // Statement-level error occurred 197 | if ($this->trans) 198 | $this->rollback(); 199 | user_error('PDOStatement: '.$error[2],E_USER_ERROR); 200 | } 201 | if (preg_match('/^\s*'. 202 | '(?:EXPLAIN|SELECT|PRAGMA|SHOW|RETURNING)\b/is',$cmd) || 203 | (preg_match('/^\s*(?:CALL|EXEC)\b/is',$cmd) && 204 | $query->columnCount())) { 205 | $result=$query->fetchall(\PDO::FETCH_ASSOC); 206 | // Work around SQLite quote bug 207 | if (preg_match('/sqlite2?/',$this->engine)) 208 | foreach ($result as $pos=>$rec) { 209 | unset($result[$pos]); 210 | $result[$pos]=array(); 211 | foreach ($rec as $key=>$val) 212 | $result[$pos][trim($key,'\'"[]`')]=$val; 213 | } 214 | $this->rows=count($result); 215 | if ($fw->get('CACHE') && $ttl) 216 | // Save to cache backend 217 | $cache->set($hash,$result,$ttl); 218 | } 219 | else 220 | $this->rows=$result=$query->rowcount(); 221 | $query->closecursor(); 222 | unset($query); 223 | } 224 | else { 225 | $error=$this->errorinfo(); 226 | if ($error[0]!=\PDO::ERR_NONE) { 227 | // PDO-level error occurred 228 | if ($this->trans) 229 | $this->rollback(); 230 | user_error('PDO: '.$error[2],E_USER_ERROR); 231 | } 232 | } 233 | } 234 | if ($this->trans && $auto) 235 | $this->commit(); 236 | return $result; 237 | } 238 | 239 | /** 240 | * Return number of rows affected by last query 241 | * @return int 242 | **/ 243 | function count() { 244 | return $this->rows; 245 | } 246 | 247 | /** 248 | * Return SQL profiler results 249 | * @return string 250 | **/ 251 | function log() { 252 | return $this->log; 253 | } 254 | 255 | /** 256 | * Retrieve schema of SQL table 257 | * @return array|FALSE 258 | * @param $table string 259 | * @param $fields array|string 260 | * @param $ttl int 261 | **/ 262 | function schema($table,$fields=NULL,$ttl=0) { 263 | if (strpos($table,'.')) 264 | list($schema,$table)=explode('.',$table); 265 | // Supported engines 266 | $cmd=array( 267 | 'sqlite2?'=>array( 268 | 'PRAGMA table_info("'.$table.'");', 269 | 'name','type','dflt_value','notnull',0,'pk',TRUE), 270 | 'mysql'=>array( 271 | 'SHOW columns FROM `'.$this->dbname.'`.`'.$table.'`;', 272 | 'Field','Type','Default','Null','YES','Key','PRI'), 273 | 'mssql|sqlsrv|sybase|dblib|pgsql|odbc'=>array( 274 | 'SELECT '. 275 | 'c.column_name AS field,'. 276 | 'c.data_type AS type,'. 277 | 'c.column_default AS defval,'. 278 | 'c.is_nullable AS nullable,'. 279 | 't.constraint_type AS pkey '. 280 | 'FROM information_schema.columns AS c '. 281 | 'LEFT OUTER JOIN '. 282 | 'information_schema.key_column_usage AS k '. 283 | 'ON '. 284 | 'c.table_name=k.table_name AND '. 285 | 'c.column_name=k.column_name AND '. 286 | 'c.table_schema=k.table_schema '. 287 | ($this->dbname? 288 | ('AND c.table_catalog=k.table_catalog '):''). 289 | 'LEFT OUTER JOIN '. 290 | 'information_schema.table_constraints AS t ON '. 291 | 'k.table_name=t.table_name AND '. 292 | 'k.constraint_name=t.constraint_name AND '. 293 | 'k.table_schema=t.table_schema '. 294 | ($this->dbname? 295 | ('AND k.table_catalog=t.table_catalog '):''). 296 | 'WHERE '. 297 | 'c.table_name='.$this->quote($table). 298 | ($this->dbname? 299 | (' AND c.table_catalog='. 300 | $this->quote($this->dbname)):''). 301 | ';', 302 | 'field','type','defval','nullable','YES','pkey','PRIMARY KEY'), 303 | 'oci'=>array( 304 | 'SELECT c.column_name AS field, '. 305 | 'c.data_type AS type, '. 306 | 'c.data_default AS defval, '. 307 | 'c.nullable AS nullable, '. 308 | '(SELECT t.constraint_type '. 309 | 'FROM all_cons_columns acc '. 310 | 'LEFT OUTER JOIN all_constraints t '. 311 | 'ON acc.constraint_name=t.constraint_name '. 312 | 'WHERE acc.table_name='.$this->quote($table).' '. 313 | 'AND acc.column_name=c.column_name '. 314 | 'AND constraint_type='.$this->quote('P').') AS pkey '. 315 | 'FROM all_tab_cols c '. 316 | 'WHERE c.table_name='.$this->quote($table), 317 | 'FIELD','TYPE','DEFVAL','NULLABLE','Y','PKEY','P') 318 | ); 319 | if (is_string($fields)) 320 | $fields=\Base::instance()->split($fields); 321 | foreach ($cmd as $key=>$val) 322 | if (preg_match('/'.$key.'/',$this->engine)) { 323 | // Improve InnoDB performance on MySQL with 324 | // SET GLOBAL innodb_stats_on_metadata=0; 325 | // This requires SUPER privilege! 326 | $rows=array(); 327 | foreach ($this->exec($val[0],NULL,$ttl) as $row) { 328 | if (!$fields || in_array($row[$val[1]],$fields)) 329 | $rows[$row[$val[1]]]=array( 330 | 'type'=>$row[$val[2]], 331 | 'pdo_type'=> 332 | preg_match('/int\b|integer/i',$row[$val[2]])? 333 | \PDO::PARAM_INT: 334 | (preg_match('/bool/i',$row[$val[2]])? 335 | \PDO::PARAM_BOOL: 336 | \PDO::PARAM_STR), 337 | 'default'=>is_string($row[$val[3]])? 338 | preg_replace('/^\s*([\'"])(.*)\1\s*/','\2', 339 | $row[$val[3]]):$row[$val[3]], 340 | 'nullable'=>$row[$val[4]]==$val[5], 341 | 'pkey'=>$row[$val[6]]==$val[7] 342 | ); 343 | } 344 | return $rows; 345 | } 346 | user_error(sprintf(self::E_PKey,$table),E_USER_ERROR); 347 | return FALSE; 348 | } 349 | 350 | /** 351 | * Quote string 352 | * @return string 353 | * @param $val mixed 354 | * @param $type int 355 | **/ 356 | function quote($val,$type=\PDO::PARAM_STR) { 357 | return $this->engine=='odbc'? 358 | (is_string($val)? 359 | \Base::instance()->stringify(str_replace('\'','\'\'',$val)): 360 | $val): 361 | $this->pdo->quote($val,$type); 362 | } 363 | 364 | /** 365 | * Return UUID 366 | * @return string 367 | **/ 368 | function uuid() { 369 | return $this->uuid; 370 | } 371 | 372 | /** 373 | * Return parent object 374 | * @return \PDO 375 | **/ 376 | function pdo() { 377 | return $this->pdo; 378 | } 379 | 380 | /** 381 | * Return database engine 382 | * @return string 383 | **/ 384 | function driver() { 385 | return $this->engine; 386 | } 387 | 388 | /** 389 | * Return server version 390 | * @return string 391 | **/ 392 | function version() { 393 | return $this->pdo->getattribute(\PDO::ATTR_SERVER_VERSION); 394 | } 395 | 396 | /** 397 | * Return database name 398 | * @return string 399 | **/ 400 | function name() { 401 | return $this->dbname; 402 | } 403 | 404 | /** 405 | * Return quoted identifier name 406 | * @return string 407 | * @param $key 408 | **/ 409 | function quotekey($key) { 410 | $delims=array( 411 | 'mysql'=>'``', 412 | 'sqlite2?|pgsql|oci'=>'""', 413 | 'mssql|sqlsrv|odbc|sybase|dblib'=>'[]' 414 | ); 415 | $use=''; 416 | foreach ($delims as $engine=>$delim) 417 | if (preg_match('/'.$engine.'/',$this->engine)) { 418 | $use=$delim; 419 | break; 420 | } 421 | return $use[0].implode($use[1].'.'.$use[0],explode('.',$key)).$use[1]; 422 | } 423 | 424 | /** 425 | * Redirect call to MongoDB object 426 | * @return mixed 427 | * @param $func string 428 | * @param $args array 429 | **/ 430 | function __call($func,array $args) { 431 | return call_user_func_array(array($this->pdo,$func),$args); 432 | } 433 | 434 | /** 435 | * Instantiate class 436 | * @param $dsn string 437 | * @param $user string 438 | * @param $pw string 439 | * @param $options array 440 | **/ 441 | function __construct($dsn,$user=NULL,$pw=NULL,array $options=NULL) { 442 | $fw=\Base::instance(); 443 | $this->uuid=$fw->hash($this->dsn=$dsn); 444 | if (preg_match('/^.+?(?:dbname|database)=(.+?)(?=;|$)/is',$dsn,$parts)) 445 | $this->dbname=$parts[1]; 446 | if (!$options) 447 | $options=array(); 448 | if (isset($parts[0]) && strstr($parts[0],':',TRUE)=='mysql') 449 | $options+=array(\PDO::MYSQL_ATTR_INIT_COMMAND=>'SET NAMES '. 450 | strtolower(str_replace('-','',$fw->get('ENCODING'))).';'); 451 | $this->pdo=new \PDO($dsn,$user,$pw,$options); 452 | $this->engine=$this->pdo->getattribute(\PDO::ATTR_DRIVER_NAME); 453 | } 454 | 455 | } 456 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/lib/db/sql/session.php: -------------------------------------------------------------------------------- 1 | . 20 | 21 | */ 22 | 23 | namespace DB\SQL; 24 | 25 | //! SQL-managed session handler 26 | class Session extends Mapper { 27 | 28 | protected 29 | //! Session ID 30 | $sid; 31 | 32 | /** 33 | * Open session 34 | * @return TRUE 35 | * @param $path string 36 | * @param $name string 37 | **/ 38 | function open($path,$name) { 39 | return TRUE; 40 | } 41 | 42 | /** 43 | * Close session 44 | * @return TRUE 45 | **/ 46 | function close() { 47 | return TRUE; 48 | } 49 | 50 | /** 51 | * Return session data in serialized format 52 | * @return string|FALSE 53 | * @param $id string 54 | **/ 55 | function read($id) { 56 | if ($id!=$this->sid) 57 | $this->load(array('session_id=?',$this->sid=$id)); 58 | return $this->dry()?FALSE:$this->get('data'); 59 | } 60 | 61 | /** 62 | * Write session data 63 | * @return TRUE 64 | * @param $id string 65 | * @param $data string 66 | **/ 67 | function write($id,$data) { 68 | $fw=\Base::instance(); 69 | $sent=headers_sent(); 70 | $headers=$fw->get('HEADERS'); 71 | if ($id!=$this->sid) 72 | $this->load(array('session_id=?',$this->sid=$id)); 73 | $csrf=$fw->hash($fw->get('ROOT').$fw->get('BASE')).'.'. 74 | $fw->hash(mt_rand()); 75 | $this->set('session_id',$id); 76 | $this->set('data',$data); 77 | $this->set('csrf',$sent?$this->csrf():$csrf); 78 | $this->set('ip',$fw->get('IP')); 79 | $this->set('agent', 80 | isset($headers['User-Agent'])?$headers['User-Agent']:''); 81 | $this->set('stamp',time()); 82 | $this->save(); 83 | return TRUE; 84 | } 85 | 86 | /** 87 | * Destroy session 88 | * @return TRUE 89 | * @param $id string 90 | **/ 91 | function destroy($id) { 92 | $this->erase(array('session_id=?',$id)); 93 | setcookie(session_name(),'',strtotime('-1 year')); 94 | unset($_COOKIE[session_name()]); 95 | header_remove('Set-Cookie'); 96 | return TRUE; 97 | } 98 | 99 | /** 100 | * Garbage collector 101 | * @return TRUE 102 | * @param $max int 103 | **/ 104 | function cleanup($max) { 105 | $this->erase(array('stamp+?dry()?FALSE:$this->get('csrf'); 115 | } 116 | 117 | /** 118 | * Return IP address 119 | * @return string|FALSE 120 | **/ 121 | function ip() { 122 | return $this->dry()?FALSE:$this->get('ip'); 123 | } 124 | 125 | /** 126 | * Return Unix timestamp 127 | * @return string|FALSE 128 | **/ 129 | function stamp() { 130 | return $this->dry()?FALSE:$this->get('stamp'); 131 | } 132 | 133 | /** 134 | * Return HTTP user agent 135 | * @return string|FALSE 136 | **/ 137 | function agent() { 138 | return $this->dry()?FALSE:$this->get('agent'); 139 | } 140 | 141 | /** 142 | * Instantiate class 143 | * @param $db object 144 | * @param $table string 145 | * @param $force bool 146 | * @param $onsuspect callback 147 | **/ 148 | function __construct(\DB\SQL $db,$table='sessions',$force=TRUE,$onsuspect=NULL) { 149 | if ($force) { 150 | $eol="\n"; 151 | $tab="\t"; 152 | $db->exec( 153 | (preg_match('/mssql|sqlsrv|sybase/',$db->driver())? 154 | ('IF NOT EXISTS (SELECT * FROM sysobjects WHERE '. 155 | 'name='.$db->quote($table).' AND xtype=\'U\') '. 156 | 'CREATE TABLE dbo.'): 157 | ('CREATE TABLE IF NOT EXISTS '. 158 | ((($name=$db->name())&&$db->driver()!='pgsql')? 159 | ($name.'.'):''))). 160 | $table.' ('.$eol. 161 | $tab.$db->quotekey('session_id').' VARCHAR(40),'.$eol. 162 | $tab.$db->quotekey('data').' TEXT,'.$eol. 163 | $tab.$db->quotekey('csrf').' TEXT,'.$eol. 164 | $tab.$db->quotekey('ip').' VARCHAR(40),'.$eol. 165 | $tab.$db->quotekey('agent').' VARCHAR(255),'.$eol. 166 | $tab.$db->quotekey('stamp').' INTEGER,'.$eol. 167 | $tab.'PRIMARY KEY ('.$db->quotekey('session_id').')'.$eol. 168 | ');' 169 | ); 170 | } 171 | parent::__construct($db,$table); 172 | session_set_save_handler( 173 | array($this,'open'), 174 | array($this,'close'), 175 | array($this,'read'), 176 | array($this,'write'), 177 | array($this,'destroy'), 178 | array($this,'cleanup') 179 | ); 180 | register_shutdown_function('session_commit'); 181 | @session_start(); 182 | $fw=\Base::instance(); 183 | $headers=$fw->get('HEADERS'); 184 | if (($ip=$this->ip()) && $ip!=$fw->get('IP') || 185 | ($agent=$this->agent()) && 186 | (!isset($headers['User-Agent']) || 187 | $agent!=$headers['User-Agent'])) { 188 | if (isset($onsuspect)) 189 | $fw->call($onsuspect,array($this)); 190 | else { 191 | session_destroy(); 192 | $fw->error(403); 193 | } 194 | } 195 | $csrf=$fw->hash($fw->get('ROOT').$fw->get('BASE')).'.'. 196 | $fw->hash(mt_rand()); 197 | if ($this->load(array('session_id=?',$this->sid=session_id()))) { 198 | $this->set('csrf',$csrf); 199 | $this->save(); 200 | } 201 | } 202 | 203 | } 204 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/lib/f3.php: -------------------------------------------------------------------------------- 1 | . 20 | 21 | */ 22 | 23 | //! Legacy mode enabler 24 | class F3 { 25 | 26 | static 27 | //! Framework instance 28 | $fw; 29 | 30 | /** 31 | * Forward function calls to framework 32 | * @return mixed 33 | * @param $func callback 34 | * @param $args array 35 | **/ 36 | static function __callstatic($func,array $args) { 37 | if (!self::$fw) 38 | self::$fw=Base::instance(); 39 | return call_user_func_array(array(self::$fw,$func),$args); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/lib/image.php: -------------------------------------------------------------------------------- 1 | . 20 | 21 | */ 22 | 23 | //! Image manipulation tools 24 | class Image { 25 | 26 | //@{ Messages 27 | const 28 | E_Color='Invalid color specified: %s', 29 | E_File='File not found', 30 | E_Font='CAPTCHA font not found', 31 | E_Length='Invalid CAPTCHA length: %s'; 32 | //@} 33 | 34 | //@{ Positional cues 35 | const 36 | POS_Left=1, 37 | POS_Center=2, 38 | POS_Right=4, 39 | POS_Top=8, 40 | POS_Middle=16, 41 | POS_Bottom=32; 42 | //@} 43 | 44 | protected 45 | //! Source filename 46 | $file, 47 | //! Image resource 48 | $data, 49 | //! Enable/disable history 50 | $flag=FALSE, 51 | //! Filter count 52 | $count=0; 53 | 54 | /** 55 | * Convert RGB hex triad to array 56 | * @return array|FALSE 57 | * @param $color int 58 | **/ 59 | function rgb($color) { 60 | $hex=str_pad($hex=dechex($color),$color<4096?3:6,'0',STR_PAD_LEFT); 61 | if (($len=strlen($hex))>6) 62 | user_error(sprintf(self::E_Color,'0x'.$hex),E_USER_ERROR); 63 | $color=str_split($hex,$len/3); 64 | foreach ($color as &$hue) { 65 | $hue=hexdec(str_repeat($hue,6/$len)); 66 | unset($hue); 67 | } 68 | return $color; 69 | } 70 | 71 | /** 72 | * Invert image 73 | * @return object 74 | **/ 75 | function invert() { 76 | imagefilter($this->data,IMG_FILTER_NEGATE); 77 | return $this->save(); 78 | } 79 | 80 | /** 81 | * Adjust brightness (range:-255 to 255) 82 | * @return object 83 | * @param $level int 84 | **/ 85 | function brightness($level) { 86 | imagefilter($this->data,IMG_FILTER_BRIGHTNESS,$level); 87 | return $this->save(); 88 | } 89 | 90 | /** 91 | * Adjust contrast (range:-100 to 100) 92 | * @return object 93 | * @param $level int 94 | **/ 95 | function contrast($level) { 96 | imagefilter($this->data,IMG_FILTER_CONTRAST,$level); 97 | return $this->save(); 98 | } 99 | 100 | /** 101 | * Convert to grayscale 102 | * @return object 103 | **/ 104 | function grayscale() { 105 | imagefilter($this->data,IMG_FILTER_GRAYSCALE); 106 | return $this->save(); 107 | } 108 | 109 | /** 110 | * Adjust smoothness 111 | * @return object 112 | * @param $level int 113 | **/ 114 | function smooth($level) { 115 | imagefilter($this->data,IMG_FILTER_SMOOTH,$level); 116 | return $this->save(); 117 | } 118 | 119 | /** 120 | * Emboss the image 121 | * @return object 122 | **/ 123 | function emboss() { 124 | imagefilter($this->data,IMG_FILTER_EMBOSS); 125 | return $this->save(); 126 | } 127 | 128 | /** 129 | * Apply sepia effect 130 | * @return object 131 | **/ 132 | function sepia() { 133 | imagefilter($this->data,IMG_FILTER_GRAYSCALE); 134 | imagefilter($this->data,IMG_FILTER_COLORIZE,90,60,45); 135 | return $this->save(); 136 | } 137 | 138 | /** 139 | * Pixelate the image 140 | * @return object 141 | * @param $size int 142 | **/ 143 | function pixelate($size) { 144 | imagefilter($this->data,IMG_FILTER_PIXELATE,$size,TRUE); 145 | return $this->save(); 146 | } 147 | 148 | /** 149 | * Blur the image using Gaussian filter 150 | * @return object 151 | * @param $selective bool 152 | **/ 153 | function blur($selective=FALSE) { 154 | imagefilter($this->data, 155 | $selective?IMG_FILTER_SELECTIVE_BLUR:IMG_FILTER_GAUSSIAN_BLUR); 156 | return $this->save(); 157 | } 158 | 159 | /** 160 | * Apply sketch effect 161 | * @return object 162 | **/ 163 | function sketch() { 164 | imagefilter($this->data,IMG_FILTER_MEAN_REMOVAL); 165 | return $this->save(); 166 | } 167 | 168 | /** 169 | * Flip on horizontal axis 170 | * @return object 171 | **/ 172 | function hflip() { 173 | $tmp=imagecreatetruecolor( 174 | $width=$this->width(),$height=$this->height()); 175 | imagesavealpha($tmp,TRUE); 176 | imagefill($tmp,0,0,IMG_COLOR_TRANSPARENT); 177 | imagecopyresampled($tmp,$this->data, 178 | 0,0,$width-1,0,$width,$height,-$width,$height); 179 | imagedestroy($this->data); 180 | $this->data=$tmp; 181 | return $this->save(); 182 | } 183 | 184 | /** 185 | * Flip on vertical axis 186 | * @return object 187 | **/ 188 | function vflip() { 189 | $tmp=imagecreatetruecolor( 190 | $width=$this->width(),$height=$this->height()); 191 | imagesavealpha($tmp,TRUE); 192 | imagefill($tmp,0,0,IMG_COLOR_TRANSPARENT); 193 | imagecopyresampled($tmp,$this->data, 194 | 0,0,0,$height-1,$width,$height,$width,-$height); 195 | imagedestroy($this->data); 196 | $this->data=$tmp; 197 | return $this->save(); 198 | } 199 | 200 | /** 201 | * Crop the image 202 | * @return object 203 | * @param $x1 int 204 | * @param $y1 int 205 | * @param $x2 int 206 | * @param $y2 int 207 | **/ 208 | function crop($x1,$y1,$x2,$y2) { 209 | $tmp=imagecreatetruecolor($width=$x2-$x1+1,$height=$y2-$y1+1); 210 | imagesavealpha($tmp,TRUE); 211 | imagefill($tmp,0,0,IMG_COLOR_TRANSPARENT); 212 | imagecopyresampled($tmp,$this->data, 213 | 0,0,$x1,$y1,$width,$height,$width,$height); 214 | imagedestroy($this->data); 215 | $this->data=$tmp; 216 | return $this->save(); 217 | } 218 | 219 | /** 220 | * Resize image (Maintain aspect ratio); Crop relative to center 221 | * if flag is enabled; Enlargement allowed if flag is enabled 222 | * @return object 223 | * @param $width int 224 | * @param $height int 225 | * @param $crop bool 226 | * @param $enlarge bool 227 | **/ 228 | function resize($width,$height,$crop=TRUE,$enlarge=TRUE) { 229 | // Adjust dimensions; retain aspect ratio 230 | $ratio=($origw=imagesx($this->data))/($origh=imagesy($this->data)); 231 | if (!$crop) { 232 | if ($width/$ratio<=$height) 233 | $height=$width/$ratio; 234 | else 235 | $width=$height*$ratio; 236 | } 237 | if (!$enlarge) { 238 | $width=min($origw,$width); 239 | $height=min($origh,$height); 240 | } 241 | // Create blank image 242 | $tmp=imagecreatetruecolor($width,$height); 243 | imagesavealpha($tmp,TRUE); 244 | imagefill($tmp,0,0,IMG_COLOR_TRANSPARENT); 245 | // Resize 246 | if ($crop) { 247 | if ($width/$ratio<=$height) { 248 | $cropw=$origh*$width/$height; 249 | imagecopyresampled($tmp,$this->data, 250 | 0,0,($origw-$cropw)/2,0,$width,$height,$cropw,$origh); 251 | } 252 | else { 253 | $croph=$origw*$height/$width; 254 | imagecopyresampled($tmp,$this->data, 255 | 0,0,0,($origh-$croph)/2,$width,$height,$origw,$croph); 256 | } 257 | } 258 | else 259 | imagecopyresampled($tmp,$this->data, 260 | 0,0,0,0,$width,$height,$origw,$origh); 261 | imagedestroy($this->data); 262 | $this->data=$tmp; 263 | return $this->save(); 264 | } 265 | 266 | /** 267 | * Rotate image 268 | * @return object 269 | * @param $angle int 270 | **/ 271 | function rotate($angle) { 272 | $this->data=imagerotate($this->data,$angle, 273 | imagecolorallocatealpha($this->data,0,0,0,127)); 274 | imagesavealpha($this->data,TRUE); 275 | return $this->save(); 276 | } 277 | 278 | /** 279 | * Apply an image overlay 280 | * @return object 281 | * @param $img object 282 | * @param $align int|array 283 | * @param $alpha int 284 | **/ 285 | function overlay(Image $img,$align=NULL,$alpha=100) { 286 | if (is_null($align)) 287 | $align=self::POS_Right|self::POS_Bottom; 288 | if (is_array($align)) { 289 | list($posx,$posy)=$align; 290 | $align = 0; 291 | } 292 | $ovr=imagecreatefromstring($img->dump()); 293 | imagesavealpha($ovr,TRUE); 294 | $imgw=$this->width(); 295 | $imgh=$this->height(); 296 | $ovrw=imagesx($ovr); 297 | $ovrh=imagesy($ovr); 298 | if ($align & self::POS_Left) 299 | $posx=0; 300 | if ($align & self::POS_Center) 301 | $posx=($imgw-$ovrw)/2; 302 | if ($align & self::POS_Right) 303 | $posx=$imgw-$ovrw; 304 | if ($align & self::POS_Top) 305 | $posy=0; 306 | if ($align & self::POS_Middle) 307 | $posy=($imgh-$ovrh)/2; 308 | if ($align & self::POS_Bottom) 309 | $posy=$imgh-$ovrh; 310 | if (empty($posx)) 311 | $posx=0; 312 | if (empty($posy)) 313 | $posy=0; 314 | if ($alpha==100) 315 | imagecopy($this->data,$ovr,$posx,$posy,0,0,$ovrw,$ovrh); 316 | else { 317 | $cut=imagecreatetruecolor($ovrw,$ovrh); 318 | imagecopy($cut,$this->data,0,0,$posx,$posy,$ovrw,$ovrh); 319 | imagecopy($cut,$ovr,0,0,0,0,$ovrw,$ovrh); 320 | imagecopymerge($this->data, 321 | $cut,$posx,$posy,0,0,$ovrw,$ovrh,$alpha); 322 | } 323 | return $this->save(); 324 | } 325 | 326 | /** 327 | * Generate identicon 328 | * @return object 329 | * @param $str string 330 | * @param $size int 331 | * @param $blocks int 332 | **/ 333 | function identicon($str,$size=64,$blocks=4) { 334 | $sprites=array( 335 | array(.5,1,1,0,1,1), 336 | array(.5,0,1,0,.5,1,0,1), 337 | array(.5,0,1,0,1,1,.5,1,1,.5), 338 | array(0,.5,.5,0,1,.5,.5,1,.5,.5), 339 | array(0,.5,1,0,1,1,0,1,1,.5), 340 | array(1,0,1,1,.5,1,1,.5,.5,.5), 341 | array(0,0,1,0,1,.5,0,0,.5,1,0,1), 342 | array(0,0,.5,0,1,.5,.5,1,0,1,.5,.5), 343 | array(.5,0,.5,.5,1,.5,1,1,.5,1,.5,.5,0,.5), 344 | array(0,0,1,0,.5,.5,1,.5,.5,1,.5,.5,0,1), 345 | array(0,.5,.5,1,1,.5,.5,0,1,0,1,1,0,1), 346 | array(.5,0,1,0,1,1,.5,1,1,.75,.5,.5,1,.25), 347 | array(0,.5,.5,0,.5,.5,1,0,1,.5,.5,1,.5,.5,0,1), 348 | array(0,0,1,0,1,1,0,1,1,.5,.5,.25,.5,.75,0,.5,.5,.25), 349 | array(0,.5,.5,.5,.5,0,1,0,.5,.5,1,.5,.5,1,.5,.5,0,1), 350 | array(0,0,1,0,.5,.5,.5,0,0,.5,1,.5,.5,1,.5,.5,0,1) 351 | ); 352 | $hash=sha1($str); 353 | $this->data=imagecreatetruecolor($size,$size); 354 | list($r,$g,$b)=$this->rgb(hexdec(substr($hash,-3))); 355 | $fg=imagecolorallocate($this->data,$r,$g,$b); 356 | imagefill($this->data,0,0,IMG_COLOR_TRANSPARENT); 357 | $ctr=count($sprites); 358 | $dim=$blocks*floor($size/$blocks)*2/$blocks; 359 | for ($j=0,$y=ceil($blocks/2);$j<$y;$j++) 360 | for ($i=$j,$x=$blocks-1-$j;$i<$x;$i++) { 361 | $sprite=imagecreatetruecolor($dim,$dim); 362 | imagefill($sprite,0,0,IMG_COLOR_TRANSPARENT); 363 | if ($block=$sprites[ 364 | hexdec($hash[($j*$blocks+$i)*2])%$ctr]) { 365 | for ($k=0,$pts=count($block);$k<$pts;$k++) 366 | $block[$k]*=$dim; 367 | imagefilledpolygon($sprite,$block,$pts/2,$fg); 368 | } 369 | $sprite=imagerotate($sprite, 370 | 90*(hexdec($hash[($j*$blocks+$i)*2+1])%4), 371 | imagecolorallocatealpha($sprite,0,0,0,127)); 372 | for ($k=0;$k<4;$k++) { 373 | imagecopyresampled($this->data,$sprite, 374 | $i*$dim/2,$j*$dim/2,0,0,$dim/2,$dim/2,$dim,$dim); 375 | $this->data=imagerotate($this->data,90, 376 | imagecolorallocatealpha($this->data,0,0,0,127)); 377 | } 378 | imagedestroy($sprite); 379 | } 380 | imagesavealpha($this->data,TRUE); 381 | return $this->save(); 382 | } 383 | 384 | /** 385 | * Generate CAPTCHA image 386 | * @return object|FALSE 387 | * @param $font string 388 | * @param $size int 389 | * @param $len int 390 | * @param $key string 391 | * @param $path string 392 | * @param $fg int 393 | * @param $bg int 394 | **/ 395 | function captcha($font,$size=24,$len=5, 396 | $key=NULL,$path='',$fg=0xFFFFFF,$bg=0x000000) { 397 | if ((!$ssl=extension_loaded('openssl')) && ($len<4 || $len>13)) { 398 | user_error(sprintf(self::E_Length,$len),E_USER_ERROR); 399 | return FALSE; 400 | } 401 | $fw=Base::instance(); 402 | foreach ($fw->split($path?:$fw->get('UI').';./') as $dir) 403 | if (is_file($path=$dir.$font)) { 404 | $seed=strtoupper(substr( 405 | $ssl?bin2hex(openssl_random_pseudo_bytes($len)):uniqid(), 406 | -$len)); 407 | $block=$size*3; 408 | $tmp=array(); 409 | for ($i=0,$width=0,$height=0;$i<$len;$i++) { 410 | // Process at 2x magnification 411 | $box=imagettfbbox($size*2,0,$path,$seed[$i]); 412 | $w=$box[2]-$box[0]; 413 | $h=$box[1]-$box[5]; 414 | $char=imagecreatetruecolor($block,$block); 415 | imagefill($char,0,0,$bg); 416 | imagettftext($char,$size*2,0, 417 | ($block-$w)/2,$block-($block-$h)/2, 418 | $fg,$path,$seed[$i]); 419 | $char=imagerotate($char,mt_rand(-30,30), 420 | imagecolorallocatealpha($char,0,0,0,127)); 421 | // Reduce to normal size 422 | $tmp[$i]=imagecreatetruecolor( 423 | ($w=imagesx($char))/2,($h=imagesy($char))/2); 424 | imagefill($tmp[$i],0,0,IMG_COLOR_TRANSPARENT); 425 | imagecopyresampled($tmp[$i], 426 | $char,0,0,0,0,$w/2,$h/2,$w,$h); 427 | imagedestroy($char); 428 | $width+=$i+1<$len?$block/2:$w/2; 429 | $height=max($height,$h/2); 430 | } 431 | $this->data=imagecreatetruecolor($width,$height); 432 | imagefill($this->data,0,0,IMG_COLOR_TRANSPARENT); 433 | for ($i=0;$i<$len;$i++) { 434 | imagecopy($this->data,$tmp[$i], 435 | $i*$block/2,($height-imagesy($tmp[$i]))/2,0,0, 436 | imagesx($tmp[$i]),imagesy($tmp[$i])); 437 | imagedestroy($tmp[$i]); 438 | } 439 | imagesavealpha($this->data,TRUE); 440 | if ($key) 441 | $fw->set($key,$seed); 442 | return $this->save(); 443 | } 444 | user_error(self::E_Font,E_USER_ERROR); 445 | return FALSE; 446 | } 447 | 448 | /** 449 | * Return image width 450 | * @return int 451 | **/ 452 | function width() { 453 | return imagesx($this->data); 454 | } 455 | 456 | /** 457 | * Return image height 458 | * @return int 459 | **/ 460 | function height() { 461 | return imagesy($this->data); 462 | } 463 | 464 | /** 465 | * Send image to HTTP client 466 | * @return NULL 467 | **/ 468 | function render() { 469 | $args=func_get_args(); 470 | $format=$args?array_shift($args):'png'; 471 | if (PHP_SAPI!='cli') { 472 | header('Content-Type: image/'.$format); 473 | header('X-Powered-By: '.Base::instance()->get('PACKAGE')); 474 | } 475 | call_user_func_array('image'.$format, 476 | array_merge(array($this->data),$args)); 477 | } 478 | 479 | /** 480 | * Return image as a string 481 | * @return string 482 | **/ 483 | function dump() { 484 | $args=func_get_args(); 485 | $format=$args?array_shift($args):'png'; 486 | ob_start(); 487 | call_user_func_array('image'.$format, 488 | array_merge(array($this->data),$args)); 489 | return ob_get_clean(); 490 | } 491 | 492 | /** 493 | * Save current state 494 | * @return object 495 | **/ 496 | function save() { 497 | $fw=Base::instance(); 498 | if ($this->flag) { 499 | if (!is_dir($dir=$fw->get('TEMP'))) 500 | mkdir($dir,Base::MODE,TRUE); 501 | $this->count++; 502 | $fw->write($dir.'/'. 503 | $fw->hash($fw->get('ROOT').$fw->get('BASE')).'.'. 504 | $fw->hash($this->file).'-'.$this->count.'.png', 505 | $this->dump()); 506 | } 507 | return $this; 508 | } 509 | 510 | /** 511 | * Revert to specified state 512 | * @return object 513 | * @param $state int 514 | **/ 515 | function restore($state=1) { 516 | $fw=Base::instance(); 517 | if ($this->flag && is_file($file=($path=$fw->get('TEMP'). 518 | $fw->hash($fw->get('ROOT').$fw->get('BASE')).'.'. 519 | $fw->hash($this->file).'-').$state.'.png')) { 520 | if (is_resource($this->data)) 521 | imagedestroy($this->data); 522 | $this->data=imagecreatefromstring($fw->read($file)); 523 | imagesavealpha($this->data,TRUE); 524 | foreach (glob($path.'*.png',GLOB_NOSORT) as $match) 525 | if (preg_match('/-(\d+)\.png/',$match,$parts) && 526 | $parts[1]>$state) 527 | @unlink($match); 528 | $this->count=$state; 529 | } 530 | return $this; 531 | } 532 | 533 | /** 534 | * Undo most recently applied filter 535 | * @return object 536 | **/ 537 | function undo() { 538 | if ($this->flag) { 539 | if ($this->count) 540 | $this->count--; 541 | return $this->restore($this->count); 542 | } 543 | return $this; 544 | } 545 | 546 | /** 547 | * Load string 548 | * @return object 549 | * @param $str string 550 | **/ 551 | function load($str) { 552 | $this->data=imagecreatefromstring($str); 553 | imagesavealpha($this->data,TRUE); 554 | $this->save(); 555 | return $this; 556 | } 557 | 558 | /** 559 | * Instantiate image 560 | * @param $file string 561 | * @param $flag bool 562 | * @param $path string 563 | **/ 564 | function __construct($file=NULL,$flag=FALSE,$path=NULL) { 565 | $this->flag=$flag; 566 | if ($file) { 567 | $fw=Base::instance(); 568 | // Create image from file 569 | $this->file=$file; 570 | if (!isset($path)) 571 | $path=$fw->get('UI').';./'; 572 | foreach ($fw->split($path,FALSE) as $dir) 573 | if (is_file($dir.$file)) 574 | return $this->load($fw->read($dir.$file)); 575 | user_error(self::E_File,E_USER_ERROR); 576 | } 577 | } 578 | 579 | /** 580 | * Wrap-up 581 | * @return NULL 582 | **/ 583 | function __destruct() { 584 | if (is_resource($this->data)) { 585 | imagedestroy($this->data); 586 | $fw=Base::instance(); 587 | $path=$fw->get('TEMP'). 588 | $fw->hash($fw->get('ROOT').$fw->get('BASE')).'.'. 589 | $fw->hash($this->file); 590 | if ($glob=@glob($path.'*.png',GLOB_NOSORT)) 591 | foreach ($glob as $match) 592 | if (preg_match('/-(\d+)\.png/',$match)) 593 | @unlink($match); 594 | } 595 | } 596 | 597 | } 598 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/lib/log.php: -------------------------------------------------------------------------------- 1 | . 20 | 21 | */ 22 | 23 | //! Custom logger 24 | class Log { 25 | 26 | protected 27 | //! File name 28 | $file; 29 | 30 | /** 31 | * Write specified text to log file 32 | * @return string 33 | * @param $text string 34 | * @param $format string 35 | **/ 36 | function write($text,$format='r') { 37 | $fw=Base::instance(); 38 | $fw->write( 39 | $this->file, 40 | date($format). 41 | (isset($_SERVER['REMOTE_ADDR'])? 42 | (' ['.$_SERVER['REMOTE_ADDR'].']'):'').' '. 43 | trim($text).PHP_EOL, 44 | TRUE 45 | ); 46 | } 47 | 48 | /** 49 | * Erase log 50 | * @return NULL 51 | **/ 52 | function erase() { 53 | @unlink($this->file); 54 | } 55 | 56 | /** 57 | * Instantiate class 58 | * @param $file string 59 | **/ 60 | function __construct($file) { 61 | $fw=Base::instance(); 62 | if (!is_dir($dir=$fw->get('LOGS'))) 63 | mkdir($dir,Base::MODE,TRUE); 64 | $this->file=$dir.$file; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/lib/magic.php: -------------------------------------------------------------------------------- 1 | . 20 | 21 | */ 22 | 23 | //! PHP magic wrapper 24 | abstract class Magic implements ArrayAccess { 25 | 26 | /** 27 | * Return TRUE if key is not empty 28 | * @return bool 29 | * @param $key string 30 | **/ 31 | abstract function exists($key); 32 | 33 | /** 34 | * Bind value to key 35 | * @return mixed 36 | * @param $key string 37 | * @param $val mixed 38 | **/ 39 | abstract function set($key,$val); 40 | 41 | /** 42 | * Retrieve contents of key 43 | * @return mixed 44 | * @param $key string 45 | **/ 46 | abstract function &get($key); 47 | 48 | /** 49 | * Unset key 50 | * @return NULL 51 | * @param $key string 52 | **/ 53 | abstract function clear($key); 54 | 55 | /** 56 | * Convenience method for checking property value 57 | * @return mixed 58 | * @param $key string 59 | **/ 60 | function offsetexists($key) { 61 | return Base::instance()->visible($this,$key)? 62 | isset($this->$key):$this->exists($key); 63 | } 64 | 65 | /** 66 | * Convenience method for assigning property value 67 | * @return mixed 68 | * @param $key string 69 | * @param $val scalar 70 | **/ 71 | function offsetset($key,$val) { 72 | return Base::instance()->visible($this,$key)? 73 | ($this->key=$val):$this->set($key,$val); 74 | } 75 | 76 | /** 77 | * Convenience method for retrieving property value 78 | * @return mixed 79 | * @param $key string 80 | **/ 81 | function &offsetget($key) { 82 | if (Base::instance()->visible($this,$key)) 83 | $val=&$this->$key; 84 | else 85 | $val=&$this->get($key); 86 | return $val; 87 | } 88 | 89 | /** 90 | * Convenience method for removing property value 91 | * @return NULL 92 | * @param $key string 93 | **/ 94 | function offsetunset($key) { 95 | if (Base::instance()->visible($this,$key)) 96 | unset($this->$key); 97 | else 98 | $this->clear($key); 99 | } 100 | 101 | /** 102 | * Alias for offsetexists() 103 | * @return mixed 104 | * @param $key string 105 | **/ 106 | function __isset($key) { 107 | return $this->offsetexists($key); 108 | } 109 | 110 | /** 111 | * Alias for offsetset() 112 | * @return mixed 113 | * @param $key string 114 | * @param $val scalar 115 | **/ 116 | function __set($key,$val) { 117 | return $this->offsetset($key,$val); 118 | } 119 | 120 | /** 121 | * Alias for offsetget() 122 | * @return mixed 123 | * @param $key string 124 | **/ 125 | function &__get($key) { 126 | $val=&$this->offsetget($key); 127 | return $val; 128 | } 129 | 130 | /** 131 | * Alias for offsetunset() 132 | * @return NULL 133 | * @param $key string 134 | **/ 135 | function __unset($key) { 136 | $this->offsetunset($key); 137 | } 138 | 139 | } 140 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/lib/markdown.php: -------------------------------------------------------------------------------- 1 | . 20 | 21 | */ 22 | 23 | //! Markdown-to-HTML converter 24 | class Markdown extends Prefab { 25 | 26 | protected 27 | //! Parsing rules 28 | $blocks, 29 | //! Special characters 30 | $special; 31 | 32 | /** 33 | * Process blockquote 34 | * @return string 35 | * @param $str string 36 | **/ 37 | protected function _blockquote($str) { 38 | $str=preg_replace('/(?<=^|\n)\h?>\h?(.*?(?:\n+|$))/','\1',$str); 39 | return strlen($str)? 40 | ('
'.$this->build($str).'
'."\n\n"):''; 41 | } 42 | 43 | /** 44 | * Process whitespace-prefixed code block 45 | * @return string 46 | * @param $str string 47 | **/ 48 | protected function _pre($str) { 49 | $str=preg_replace('/(?<=^|\n)(?: {4}|\t)(.+?(?:\n+|$))/','\1', 50 | $this->esc($str)); 51 | return strlen($str)? 52 | ('
'.
 53 | 				$this->esc($this->snip($str)).
 54 | 			'
'."\n\n"): 55 | ''; 56 | } 57 | 58 | /** 59 | * Process fenced code block 60 | * @return string 61 | * @param $hint string 62 | * @param $str string 63 | **/ 64 | protected function _fence($hint,$str) { 65 | $str=$this->snip($str); 66 | $fw=Base::instance(); 67 | if ($fw->get('HIGHLIGHT')) { 68 | switch (strtolower($hint)) { 69 | case 'php': 70 | $str=$fw->highlight($str); 71 | break; 72 | case 'apache': 73 | preg_match_all('/(?<=^|\n)(\h*)'. 74 | '(?:(<\/?)(\w+)((?:\h+[^>]+)*)(>)|'. 75 | '(?:(\w+)(\h.+?)))(\h*(?:\n+|$))/', 76 | $str,$matches,PREG_SET_ORDER); 77 | $out=''; 78 | foreach ($matches as $match) 79 | $out.=$match[1]. 80 | ($match[3]? 81 | (''. 82 | $this->esc($match[2]).$match[3]. 83 | ''. 84 | ($match[4]? 85 | (''. 86 | $this->esc($match[4]). 87 | ''): 88 | ''). 89 | ''. 90 | $this->esc($match[5]). 91 | ''): 92 | (''. 93 | $match[6]. 94 | ''. 95 | ''. 96 | $this->esc($match[7]). 97 | '')). 98 | $match[8]; 99 | $str=''.$out.''; 100 | break; 101 | case 'html': 102 | preg_match_all( 103 | '/(?:(?:<(\/?)(\w+)'. 104 | '((?:\h+(?:\w+\h*=\h*)?".+?"|[^>]+)*|'. 105 | '\h+.+?)(\h*\/?)>)|(.+?))/s', 106 | $str,$matches,PREG_SET_ORDER 107 | ); 108 | $out=''; 109 | foreach ($matches as $match) { 110 | if ($match[2]) { 111 | $out.='<'. 112 | $match[1].$match[2].''; 113 | if ($match[3]) { 114 | preg_match_all( 115 | '/(?:\h+(?:(?:(\w+)\h*=\h*)?'. 116 | '(".+?")|(.+)))/', 117 | $match[3],$parts,PREG_SET_ORDER 118 | ); 119 | foreach ($parts as $part) 120 | $out.=' '. 121 | (empty($part[3])? 122 | ((empty($part[1])? 123 | '': 124 | (''. 125 | $part[1].'=')). 126 | ''. 127 | $part[2].''): 128 | (''. 129 | $part[3].'')); 130 | } 131 | $out.=''. 132 | $match[4].'>'; 133 | } 134 | else 135 | $out.=$this->esc($match[5]); 136 | } 137 | $str=''.$out.''; 138 | break; 139 | case 'ini': 140 | preg_match_all( 141 | '/(?<=^|\n)(?:'. 142 | '(;[^\n]*)|(?:<\?php.+?\?>?)|'. 143 | '(?:\[(.+?)\])|'. 144 | '(.+?)\h*=\h*'. 145 | '((?:\\\\\h*\r?\n|.+?)*)'. 146 | ')((?:\r?\n)+|$)/', 147 | $str,$matches,PREG_SET_ORDER 148 | ); 149 | $out=''; 150 | foreach ($matches as $match) { 151 | if ($match[1]) 152 | $out.=''.$match[1]. 153 | ''; 154 | elseif ($match[2]) 155 | $out.='['.$match[2].']'. 156 | ''; 157 | elseif ($match[3]) 158 | $out.=''.$match[3]. 159 | '='. 160 | ($match[4]? 161 | (''. 162 | $match[4].''):''); 163 | else 164 | $out.=$match[0]; 165 | if (isset($match[5])) 166 | $out.=$match[5]; 167 | } 168 | $str=''.$out.''; 169 | break; 170 | default: 171 | $str=''.$this->esc($str).''; 172 | break; 173 | } 174 | } 175 | else 176 | $str=''.$this->esc($str).''; 177 | return '
'.$str.'
'."\n\n"; 178 | } 179 | 180 | /** 181 | * Process horizontal rule 182 | * @return string 183 | **/ 184 | protected function _hr() { 185 | return '
'."\n\n"; 186 | } 187 | 188 | /** 189 | * Process atx-style heading 190 | * @return string 191 | * @param $type string 192 | * @param $str string 193 | **/ 194 | protected function _atx($type,$str) { 195 | $level=strlen($type); 196 | return ''. 197 | $this->scan($str).''."\n\n"; 198 | } 199 | 200 | /** 201 | * Process setext-style heading 202 | * @return string 203 | * @param $str string 204 | * @param $type string 205 | **/ 206 | protected function _setext($str,$type) { 207 | $level=strpos('=-',$type)+1; 208 | return ''. 209 | $this->scan($str).''."\n\n"; 210 | } 211 | 212 | /** 213 | * Process ordered/unordered list 214 | * @return string 215 | * @param $str string 216 | **/ 217 | protected function _li($str) { 218 | // Initialize list parser 219 | $len=strlen($str); 220 | $ptr=0; 221 | $dst=''; 222 | $first=TRUE; 223 | $tight=TRUE; 224 | $type='ul'; 225 | // Main loop 226 | while ($ptr<$len) { 227 | if (preg_match('/^\h*[*-](?:\h?[*-]){2,}(?:\n+|$)/', 228 | substr($str,$ptr),$match)) { 229 | $ptr+=strlen($match[0]); 230 | // Embedded horizontal rule 231 | return (strlen($dst)? 232 | ('<'.$type.'>'."\n".$dst.''."\n\n"):''). 233 | '
'."\n\n".$this->build(substr($str,$ptr)); 234 | } 235 | elseif (preg_match('/(?<=^|\n)([*+-]|\d+\.)\h'. 236 | '(.+?(?:\n+|$))((?:(?: {4}|\t)+.+?(?:\n+|$))*)/s', 237 | substr($str,$ptr),$match)) { 238 | $match[3]=preg_replace('/(?<=^|\n)(?: {4}|\t)/','',$match[3]); 239 | $found=FALSE; 240 | foreach (array_slice($this->blocks,0,-1) as $regex) 241 | if (preg_match($regex,$match[3])) { 242 | $found=TRUE; 243 | break; 244 | } 245 | // List 246 | if ($first) { 247 | // First pass 248 | if (is_numeric($match[1])) 249 | $type='ol'; 250 | if (preg_match('/\n{2,}$/',$match[2]. 251 | ($found?'':$match[3]))) 252 | // Loose structure; Use paragraphs 253 | $tight=FALSE; 254 | $first=FALSE; 255 | } 256 | // Strip leading whitespaces 257 | $ptr+=strlen($match[0]); 258 | $tmp=$this->snip($match[2].$match[3]); 259 | if ($tight) { 260 | if ($found) 261 | $tmp=$match[2].$this->build($this->snip($match[3])); 262 | } 263 | else 264 | $tmp=$this->build($tmp); 265 | $dst.='
  • '.$this->scan(trim($tmp)).'
  • '."\n"; 266 | } 267 | } 268 | return strlen($dst)? 269 | ('<'.$type.'>'."\n".$dst.''."\n\n"):''; 270 | } 271 | 272 | /** 273 | * Ignore raw HTML 274 | * @return string 275 | * @param $str string 276 | **/ 277 | protected function _raw($str) { 278 | return $str; 279 | } 280 | 281 | /** 282 | * Process paragraph 283 | * @return string 284 | * @param $str string 285 | **/ 286 | protected function _p($str) { 287 | $str=trim($str); 288 | if (strlen($str)) { 289 | if (preg_match('/^(.+?\n)([>#].+)$/s',$str,$parts)) 290 | return $this->_p($parts[1]).$this->build($parts[2]); 291 | $self=$this; 292 | $str=preg_replace_callback( 293 | '/([^<>\[]+)?(<[\?%].+?[\?%]>|<.+?>|\[.+?\]\s*\(.+?\))|'. 294 | '(.+)/s', 295 | function($expr) use($self) { 296 | $tmp=''; 297 | if (isset($expr[4])) 298 | $tmp.=$self->esc($expr[4]); 299 | else { 300 | if (isset($expr[1])) 301 | $tmp.=$self->esc($expr[1]); 302 | $tmp.=$expr[2]; 303 | if (isset($expr[3])) 304 | $tmp.=$self->esc($expr[3]); 305 | } 306 | return $tmp; 307 | }, 308 | $str 309 | ); 310 | return '

    '.$this->scan($str).'

    '."\n\n"; 311 | } 312 | return ''; 313 | } 314 | 315 | /** 316 | * Process strong/em/strikethrough spans 317 | * @return string 318 | * @param $str string 319 | **/ 320 | protected function _text($str) { 321 | $tmp=''; 322 | while ($str!=$tmp) 323 | $str=preg_replace_callback( 324 | '/(?'.$expr[2].''; 329 | case 2: 330 | return ''.$expr[2].''; 331 | case 3: 332 | return ''.$expr[2].''; 333 | } 334 | }, 335 | preg_replace( 336 | '/(?\1', 338 | $tmp=$str 339 | ) 340 | ); 341 | return $str; 342 | } 343 | 344 | /** 345 | * Process image span 346 | * @return string 347 | * @param $str string 348 | **/ 349 | protected function _img($str) { 350 | $self=$this; 351 | return preg_replace_callback( 352 | '/!(?:\[(.+?)\])?\h*\(?(?:\h*"(.*?)"\h*)?\)/', 353 | function($expr) use($self) { 354 | return ''.$self->esc($expr[1]).''; 361 | }, 362 | $str 363 | ); 364 | } 365 | 366 | /** 367 | * Process anchor span 368 | * @return string 369 | * @param $str string 370 | **/ 371 | protected function _a($str) { 372 | $self=$this; 373 | return preg_replace_callback( 374 | '/(??(?:\h*"(.*?)"\h*)?\)/', 375 | function($expr) use($self) { 376 | return ''.$self->scan($expr[1]).''; 381 | }, 382 | $str 383 | ); 384 | } 385 | 386 | /** 387 | * Auto-convert links 388 | * @return string 389 | * @param $str string 390 | **/ 391 | protected function _auto($str) { 392 | $self=$this; 393 | return preg_replace_callback( 394 | '/`.*?<(.+?)>.*?`|<(.+?)>/', 395 | function($expr) use($self) { 396 | if (empty($expr[1]) && parse_url($expr[2],PHP_URL_SCHEME)) { 397 | $expr[2]=$self->esc($expr[2]); 398 | return ''.$expr[2].''; 399 | } 400 | return $expr[0]; 401 | }, 402 | $str 403 | ); 404 | } 405 | 406 | /** 407 | * Process code span 408 | * @return string 409 | * @param $str string 410 | **/ 411 | protected function _code($str) { 412 | $self=$this; 413 | return preg_replace_callback( 414 | '/`` (.+?) ``|(?'. 417 | $self->esc(empty($expr[1])?$expr[2]:$expr[1]).''; 418 | }, 419 | $str 420 | ); 421 | } 422 | 423 | /** 424 | * Convert characters to HTML entities 425 | * @return string 426 | * @param $str string 427 | **/ 428 | function esc($str) { 429 | if (!$this->special) 430 | $this->special=array( 431 | '...'=>'…', 432 | '(tm)'=>'™', 433 | '(r)'=>'®', 434 | '(c)'=>'©' 435 | ); 436 | foreach ($this->special as $key=>$val) 437 | $str=preg_replace('/'.preg_quote($key,'/').'/i',$val,$str); 438 | return htmlspecialchars($str,ENT_COMPAT, 439 | Base::instance()->get('ENCODING'),FALSE); 440 | } 441 | 442 | /** 443 | * Reduce multiple line feeds 444 | * @return string 445 | * @param $str string 446 | **/ 447 | protected function snip($str) { 448 | return preg_replace('/(?:(?<=\n)\n+)|\n+$/',"\n",$str); 449 | } 450 | 451 | /** 452 | * Scan line for convertible spans 453 | * @return string 454 | * @param $str string 455 | **/ 456 | function scan($str) { 457 | $inline=array('img','a','text','auto','code'); 458 | foreach ($inline as $func) 459 | $str=$this->{'_'.$func}($str); 460 | return $str; 461 | } 462 | 463 | /** 464 | * Assemble blocks 465 | * @return string 466 | * @param $str string 467 | **/ 468 | protected function build($str) { 469 | if (!$this->blocks) { 470 | // Regexes for capturing entire blocks 471 | $this->blocks=array( 472 | 'blockquote'=>'/^(?:\h?>\h?.*?(?:\n+|$))+/', 473 | 'pre'=>'/^(?:(?: {4}|\t).+?(?:\n+|$))+/', 474 | 'fence'=>'/^`{3}\h*(\w+)?.*?[^\n]*\n+(.+?)`{3}[^\n]*'. 475 | '(?:\n+|$)/s', 476 | 'hr'=>'/^\h*[*_-](?:\h?[\*_-]){2,}\h*(?:\n+|$)/', 477 | 'atx'=>'/^\h*(#{1,6})\h?(.+?)\h*(?:#.*)?(?:\n+|$)/', 478 | 'setext'=>'/^\h*(.+?)\h*\n([=-])+\h*(?:\n+|$)/', 479 | 'li'=>'/^(?:(?:[*+-]|\d+\.)\h.+?(?:\n+|$)'. 480 | '(?:(?: {4}|\t)+.+?(?:\n+|$))*)+/s', 481 | 'raw'=>'/^((?:|'. 482 | '<(address|article|aside|audio|blockquote|canvas|dd|'. 483 | 'div|dl|fieldset|figcaption|figure|footer|form|h\d|'. 484 | 'header|hgroup|hr|noscript|object|ol|output|p|pre|'. 485 | 'section|table|tfoot|ul|video).*?'. 486 | '(?:\/>|>(?:(?>[^><]+)|(?R))*<\/\2>))'. 487 | '\h*(?:\n{2,}|\n*$)|<[\?%].+?[\?%]>\h*(?:\n?$|\n*))/s', 488 | 'p'=>'/^(.+?(?:\n{2,}|\n*$))/s' 489 | ); 490 | } 491 | $self=$this; 492 | // Treat lines with nothing but whitespaces as empty lines 493 | $str=preg_replace('/\n\h+(?=\n)/',"\n",$str); 494 | // Initialize block parser 495 | $len=strlen($str); 496 | $ptr=0; 497 | $dst=''; 498 | // Main loop 499 | while ($ptr<$len) { 500 | if (preg_match('/^ {0,3}\[([^\[\]]+)\]:\s*?\s*'. 501 | '(?:"([^\n]*)")?(?:\n+|$)/s',substr($str,$ptr),$match)) { 502 | // Reference-style link; Backtrack 503 | $ptr+=strlen($match[0]); 504 | $tmp=''; 505 | // Catch line breaks in title attribute 506 | $ref=preg_replace('/\h/','\s',preg_quote($match[1],'/')); 507 | while ($dst!=$tmp) { 508 | $dst=preg_replace_callback( 509 | '/(?esc($match[2]).'"'. 516 | (empty($match[3])? 517 | '': 518 | (' title="'. 519 | $self->esc($match[3]).'"')).'>'. 520 | // Link 521 | $self->scan( 522 | empty($expr[3])? 523 | (empty($expr[1])? 524 | $expr[4]: 525 | $expr[1]): 526 | $expr[3] 527 | ).''): 528 | // Image 529 | (''.
533 | 										$self->esc($expr[3]).''); 539 | }, 540 | $tmp=$dst 541 | ); 542 | } 543 | } 544 | else 545 | foreach ($this->blocks as $func=>$regex) 546 | if (preg_match($regex,substr($str,$ptr),$match)) { 547 | $ptr+=strlen($match[0]); 548 | $dst.=call_user_func_array( 549 | array($this,'_'.$func), 550 | count($match)>1?array_slice($match,1):$match 551 | ); 552 | break; 553 | } 554 | } 555 | return $dst; 556 | } 557 | 558 | /** 559 | * Render HTML equivalent of markdown 560 | * @return string 561 | * @param $txt string 562 | **/ 563 | function convert($txt) { 564 | $txt=preg_replace_callback( 565 | '/(.+?<\/code>|'. 566 | '<[^>\n]+>|\([^\n\)]+\)|"[^"\n]+")|'. 567 | '\\\\(.)/s', 568 | function($expr) { 569 | // Process escaped characters 570 | return empty($expr[1])?$expr[2]:$expr[1]; 571 | }, 572 | $this->build(preg_replace('/\r\n|\r/',"\n",$txt)) 573 | ); 574 | return $this->snip($txt); 575 | } 576 | 577 | } 578 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/lib/matrix.php: -------------------------------------------------------------------------------- 1 | . 20 | 21 | */ 22 | 23 | //! Generic array utilities 24 | class Matrix extends Prefab { 25 | 26 | /** 27 | * Retrieve values from a specified column of a multi-dimensional 28 | * array variable 29 | * @return array 30 | * @param $var array 31 | * @param $col mixed 32 | **/ 33 | function pick(array $var,$col) { 34 | return array_map( 35 | function($row) use($col) { 36 | return $row[$col]; 37 | }, 38 | $var 39 | ); 40 | } 41 | 42 | /** 43 | * Rotate a two-dimensional array variable 44 | * @return NULL 45 | * @param $var array 46 | **/ 47 | function transpose(array &$var) { 48 | $out=array(); 49 | foreach ($var as $keyx=>$cols) 50 | foreach ($cols as $keyy=>$valy) 51 | $out[$keyy][$keyx]=$valy; 52 | $var=$out; 53 | } 54 | 55 | /** 56 | * Sort a multi-dimensional array variable on a specified column 57 | * @return bool 58 | * @param $var array 59 | * @param $col mixed 60 | * @param $order int 61 | **/ 62 | function sort(array &$var,$col,$order=SORT_ASC) { 63 | uasort( 64 | $var, 65 | function($val1,$val2) use($col,$order) { 66 | list($v1,$v2)=array($val1[$col],$val2[$col]); 67 | $out=is_numeric($v1) && is_numeric($v2)? 68 | Base::instance()->sign($v1-$v2):strcmp($v1,$v2); 69 | if ($order==SORT_DESC) 70 | $out=-$out; 71 | return $out; 72 | } 73 | ); 74 | $var=array_values($var); 75 | } 76 | 77 | /** 78 | * Change the key of a two-dimensional array element 79 | * @return NULL 80 | * @param $var array 81 | * @param $old string 82 | * @param $new string 83 | **/ 84 | function changekey(array &$var,$old,$new) { 85 | $keys=array_keys($var); 86 | $vals=array_values($var); 87 | $keys[array_search($old,$keys)]=$new; 88 | $var=array_combine($keys,$vals); 89 | } 90 | 91 | /** 92 | * Return month calendar of specified date, with optional setting for 93 | * first day of week (0 for Sunday) 94 | * @return array 95 | * @param $date string 96 | * @param $first int 97 | **/ 98 | function calendar($date='now',$first=0) { 99 | $parts=getdate(strtotime($date)); 100 | $days=cal_days_in_month(CAL_GREGORIAN,$parts['mon'],$parts['year']); 101 | $ref=date('w',strtotime(date('Y-m',$parts[0]).'-01'))+(7-$first)%7; 102 | $out=array(); 103 | for ($i=0;$i<$days;$i++) 104 | $out[floor(($ref+$i)/7)][($ref+$i)%7]=$i+1; 105 | return $out; 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/lib/session.php: -------------------------------------------------------------------------------- 1 | . 20 | 21 | */ 22 | 23 | //! Cache-based session handler 24 | class Session { 25 | 26 | protected 27 | //! Session ID 28 | $sid; 29 | 30 | /** 31 | * Open session 32 | * @return TRUE 33 | * @param $path string 34 | * @param $name string 35 | **/ 36 | function open($path,$name) { 37 | return TRUE; 38 | } 39 | 40 | /** 41 | * Close session 42 | * @return TRUE 43 | **/ 44 | function close() { 45 | return TRUE; 46 | } 47 | 48 | /** 49 | * Return session data in serialized format 50 | * @return string|FALSE 51 | * @param $id string 52 | **/ 53 | function read($id) { 54 | if ($id!=$this->sid) 55 | $this->sid=$id; 56 | return Cache::instance()->exists($id.'.@',$data)?$data['data']:FALSE; 57 | } 58 | 59 | /** 60 | * Write session data 61 | * @return TRUE 62 | * @param $id string 63 | * @param $data string 64 | **/ 65 | function write($id,$data) { 66 | $fw=Base::instance(); 67 | $sent=headers_sent(); 68 | $headers=$fw->get('HEADERS'); 69 | $csrf=$fw->hash($fw->get('ROOT').$fw->get('BASE')).'.'. 70 | $fw->hash(mt_rand()); 71 | $jar=$fw->get('JAR'); 72 | if ($id!=$this->sid) 73 | $this->sid=$id; 74 | Cache::instance()->set($id.'.@', 75 | array( 76 | 'data'=>$data, 77 | 'csrf'=>$sent?$this->csrf():$csrf, 78 | 'ip'=>$fw->get('IP'), 79 | 'agent'=>isset($headers['User-Agent'])? 80 | $headers['User-Agent']:'', 81 | 'stamp'=>time() 82 | ), 83 | $jar['expire']?($jar['expire']-time()):0 84 | ); 85 | return TRUE; 86 | } 87 | 88 | /** 89 | * Destroy session 90 | * @return TRUE 91 | * @param $id string 92 | **/ 93 | function destroy($id) { 94 | Cache::instance()->clear($id.'.@'); 95 | setcookie(session_name(),'',strtotime('-1 year')); 96 | unset($_COOKIE[session_name()]); 97 | header_remove('Set-Cookie'); 98 | return TRUE; 99 | } 100 | 101 | /** 102 | * Garbage collector 103 | * @return TRUE 104 | * @param $max int 105 | **/ 106 | function cleanup($max) { 107 | Cache::instance()->reset('.@',$max); 108 | return TRUE; 109 | } 110 | 111 | /** 112 | * Return anti-CSRF token 113 | * @return string|FALSE 114 | **/ 115 | function csrf() { 116 | return Cache::instance()-> 117 | exists(($this->sid?:session_id()).'.@',$data)? 118 | $data['csrf']:FALSE; 119 | } 120 | 121 | /** 122 | * Return IP address 123 | * @return string|FALSE 124 | **/ 125 | function ip() { 126 | return Cache::instance()-> 127 | exists(($this->sid?:session_id()).'.@',$data)? 128 | $data['ip']:FALSE; 129 | } 130 | 131 | /** 132 | * Return Unix timestamp 133 | * @return string|FALSE 134 | **/ 135 | function stamp() { 136 | return Cache::instance()-> 137 | exists(($this->sid?:session_id()).'.@',$data)? 138 | $data['stamp']:FALSE; 139 | } 140 | 141 | /** 142 | * Return HTTP user agent 143 | * @return string|FALSE 144 | **/ 145 | function agent() { 146 | return Cache::instance()-> 147 | exists(($this->sid?:session_id()).'.@',$data)? 148 | $data['agent']:FALSE; 149 | } 150 | 151 | /** 152 | * Instantiate class 153 | * @param $onsuspect callback 154 | **/ 155 | function __construct($onsuspect=NULL) { 156 | session_set_save_handler( 157 | array($this,'open'), 158 | array($this,'close'), 159 | array($this,'read'), 160 | array($this,'write'), 161 | array($this,'destroy'), 162 | array($this,'cleanup') 163 | ); 164 | register_shutdown_function('session_commit'); 165 | @session_start(); 166 | $fw=\Base::instance(); 167 | $headers=$fw->get('HEADERS'); 168 | if (($ip=$this->ip()) && $ip!=$fw->get('IP') || 169 | ($agent=$this->agent()) && 170 | (!isset($headers['User-Agent']) || 171 | $agent!=$headers['User-Agent'])) { 172 | if (isset($onsuspect)) 173 | $fw->call($onsuspect,array($this)); 174 | else { 175 | session_destroy(); 176 | $fw->error(403); 177 | } 178 | } 179 | $csrf=$fw->hash($fw->get('ROOT').$fw->get('BASE')).'.'. 180 | $fw->hash(mt_rand()); 181 | $jar=$fw->get('JAR'); 182 | if (Cache::instance()->exists(($this->sid=session_id()).'.@',$data)) { 183 | $data['csrf']=$csrf; 184 | Cache::instance()->set($this->sid.'.@', 185 | $data, 186 | $jar['expire']?($jar['expire']-time()):0 187 | ); 188 | } 189 | } 190 | 191 | } 192 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/lib/smtp.php: -------------------------------------------------------------------------------- 1 | . 20 | 21 | */ 22 | 23 | //! SMTP plug-in 24 | class SMTP extends Magic { 25 | 26 | //@{ Locale-specific error/exception messages 27 | const 28 | E_Header='%s: header is required', 29 | E_Blank='Message must not be blank', 30 | E_Attach='Attachment %s not found'; 31 | //@} 32 | 33 | protected 34 | //! Message properties 35 | $headers, 36 | //! E-mail attachments 37 | $attachments, 38 | //! SMTP host 39 | $host, 40 | //! SMTP port 41 | $port, 42 | //! TLS/SSL 43 | $scheme, 44 | //! User ID 45 | $user, 46 | //! Password 47 | $pw, 48 | //! TCP/IP socket 49 | $socket, 50 | //! Server-client conversation 51 | $log; 52 | 53 | /** 54 | * Fix header 55 | * @return string 56 | * @param $key string 57 | **/ 58 | protected function fixheader($key) { 59 | return str_replace(' ','-', 60 | ucwords(preg_replace('/[_-]/',' ',strtolower($key)))); 61 | } 62 | 63 | /** 64 | * Return TRUE if header exists 65 | * @return bool 66 | * @param $key 67 | **/ 68 | function exists($key) { 69 | $key=$this->fixheader($key); 70 | return isset($this->headers[$key]); 71 | } 72 | 73 | /** 74 | * Bind value to e-mail header 75 | * @return string 76 | * @param $key string 77 | * @param $val string 78 | **/ 79 | function set($key,$val) { 80 | $key=$this->fixheader($key); 81 | return $this->headers[$key]=$val; 82 | } 83 | 84 | /** 85 | * Return value of e-mail header 86 | * @return string|NULL 87 | * @param $key string 88 | **/ 89 | function &get($key) { 90 | $key=$this->fixheader($key); 91 | if (isset($this->headers[$key])) 92 | $val=&$this->headers[$key]; 93 | else 94 | $val=NULL; 95 | return $val; 96 | } 97 | 98 | /** 99 | * Remove header 100 | * @return NULL 101 | * @param $key string 102 | **/ 103 | function clear($key) { 104 | $key=$this->fixheader($key); 105 | unset($this->headers[$key]); 106 | } 107 | 108 | /** 109 | * Return client-server conversation history 110 | * @return string 111 | **/ 112 | function log() { 113 | return str_replace("\n",PHP_EOL,$this->log); 114 | } 115 | 116 | /** 117 | * Send SMTP command and record server response 118 | * @return string 119 | * @param $cmd string 120 | * @param $log bool 121 | **/ 122 | protected function dialog($cmd=NULL,$log=TRUE) { 123 | $socket=&$this->socket; 124 | if (!is_null($cmd)) 125 | fputs($socket,$cmd."\r\n"); 126 | $reply=''; 127 | while (!feof($socket) && ($info=stream_get_meta_data($socket)) && 128 | !$info['timed_out'] && $str=fgets($socket,4096)) { 129 | $reply.=$str; 130 | if (preg_match('/(?:^|\n)\d{3} .+?\r\n/s',$reply)) 131 | break; 132 | } 133 | if ($log) { 134 | $this->log.=$cmd."\n"; 135 | $this->log.=str_replace("\r",'',$reply); 136 | } 137 | return $reply; 138 | } 139 | 140 | /** 141 | * Add e-mail attachment 142 | * @return NULL 143 | * @param $file string 144 | * @param $alias string 145 | * @param $cid string 146 | **/ 147 | function attach($file,$alias=NULL,$cid=NULL) { 148 | if (!is_file($file)) 149 | user_error(sprintf(self::E_Attach,$file),E_USER_ERROR); 150 | if (is_string($alias)) 151 | $file=array($alias=>$file); 152 | $this->attachments[]=array('filename'=>$file,'cid'=>$cid); 153 | } 154 | 155 | /** 156 | * Transmit message 157 | * @return bool 158 | * @param $message string 159 | * @param $log bool 160 | **/ 161 | function send($message,$log=TRUE) { 162 | if ($this->scheme=='ssl' && !extension_loaded('openssl')) 163 | return FALSE; 164 | // Message should not be blank 165 | if (!$message) 166 | user_error(self::E_Blank,E_USER_ERROR); 167 | $fw=Base::instance(); 168 | // Retrieve headers 169 | $headers=$this->headers; 170 | // Connect to the server 171 | $socket=&$this->socket; 172 | $socket=@fsockopen($this->host,$this->port); 173 | if (!$socket) 174 | return FALSE; 175 | stream_set_blocking($socket,TRUE); 176 | // Get server's initial response 177 | $this->dialog(NULL,FALSE); 178 | // Announce presence 179 | $reply=$this->dialog('EHLO '.$fw->get('HOST'),$log); 180 | if (strtolower($this->scheme)=='tls') { 181 | $this->dialog('STARTTLS',$log); 182 | stream_socket_enable_crypto( 183 | $socket,TRUE,STREAM_CRYPTO_METHOD_TLS_CLIENT); 184 | $reply=$this->dialog('EHLO '.$fw->get('HOST'),$log); 185 | if (preg_match('/8BITMIME/',$reply)) 186 | $headers['Content-Transfer-Encoding']='8bit'; 187 | else { 188 | $headers['Content-Transfer-Encoding']='quoted-printable'; 189 | $message=quoted_printable_encode($message); 190 | } 191 | } 192 | if ($this->user && $this->pw && preg_match('/AUTH/',$reply)) { 193 | // Authenticate 194 | $this->dialog('AUTH LOGIN',$log); 195 | $this->dialog(base64_encode($this->user),$log); 196 | $this->dialog(base64_encode($this->pw),$log); 197 | } 198 | // Required headers 199 | $reqd=array('From','To','Subject'); 200 | foreach ($reqd as $id) 201 | if (empty($headers[$id])) 202 | user_error(sprintf(self::E_Header,$id),E_USER_ERROR); 203 | $eol="\r\n"; 204 | $str=''; 205 | // Stringify headers 206 | foreach ($headers as $key=>&$val) { 207 | if (!in_array($key,$reqd)) { 208 | $str.=$key.': '.$val.$eol; 209 | } 210 | if (in_array($key,array('From','To','Cc','Bcc')) && 211 | !preg_match('/[<>]/',$val)) 212 | $val='<'.$val.'>'; 213 | unset($val); 214 | } 215 | // Start message dialog 216 | $this->dialog('MAIL FROM: '.strstr($headers['From'],'<'),$log); 217 | foreach ($fw->split($headers['To']. 218 | (isset($headers['Cc'])?(';'.$headers['Cc']):''). 219 | (isset($headers['Bcc'])?(';'.$headers['Bcc']):'')) as $dst) 220 | $this->dialog('RCPT TO: '.strstr($dst,'<'),$log); 221 | $this->dialog('DATA',$log); 222 | if ($this->attachments) { 223 | // Replace Content-Type 224 | $hash=uniqid(NULL,TRUE); 225 | $type=$headers['Content-Type']; 226 | $headers['Content-Type']='multipart/mixed; '. 227 | 'boundary="'.$hash.'"'; 228 | // Send mail headers 229 | $out=''; 230 | foreach ($headers as $key=>$val) 231 | if ($key!='Bcc') 232 | $out.=$key.': '.$val.$eol; 233 | $out.=$eol; 234 | $out.='This is a multi-part message in MIME format'.$eol; 235 | $out.=$eol; 236 | $out.='--'.$hash.$eol; 237 | $out.='Content-Type: '.$type.$eol; 238 | $out.=$eol; 239 | $out.=$message.$eol; 240 | foreach ($this->attachments as $attachment) { 241 | if (is_array($attachment['filename'])) { 242 | list($alias,$file)=each($attachment); 243 | $filename=$alias; 244 | $attachment['filename']=$file; 245 | } 246 | else 247 | $filename=basename($attachment); 248 | $out.='--'.$hash.$eol; 249 | $out.='Content-Type: application/octet-stream'.$eol; 250 | $out.='Content-Transfer-Encoding: base64'.$eol; 251 | if ($attachment['cid']) 252 | $out.='Content-ID: '.$attachment['cid'].$eol; 253 | $out.='Content-Disposition: attachment; '. 254 | 'filename="'.$filename.'"'.$eol; 255 | $out.=$eol; 256 | $out.=chunk_split( 257 | base64_encode(file_get_contents($attachment))).$eol; 258 | } 259 | $out.=$eol; 260 | $out.='--'.$hash.'--'.$eol; 261 | $out.='.'; 262 | $this->dialog($out,FALSE); 263 | } 264 | else { 265 | // Send mail headers 266 | $out=''; 267 | foreach ($headers as $key=>$val) 268 | if ($key!='Bcc') 269 | $out.=$key.': '.$val.$eol; 270 | $out.=$eol; 271 | $out.=$message.$eol; 272 | $out.='.'; 273 | // Send message 274 | $this->dialog($out); 275 | } 276 | $this->dialog('QUIT',$log); 277 | if ($socket) 278 | fclose($socket); 279 | return TRUE; 280 | } 281 | 282 | /** 283 | * Instantiate class 284 | * @param $host string 285 | * @param $port int 286 | * @param $scheme string 287 | * @param $user string 288 | * @param $pw string 289 | **/ 290 | function __construct($host,$port,$scheme,$user,$pw) { 291 | $this->headers=array( 292 | 'MIME-Version'=>'1.0', 293 | 'Content-Type'=>'text/plain; '. 294 | 'charset='.Base::instance()->get('ENCODING') 295 | ); 296 | $this->host=$host; 297 | if (strtolower($this->scheme=strtolower($scheme))=='ssl') 298 | $this->host='ssl://'.$host; 299 | $this->port=$port; 300 | $this->user=$user; 301 | $this->pw=$pw; 302 | } 303 | 304 | } 305 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/lib/template.php: -------------------------------------------------------------------------------- 1 | . 20 | 21 | */ 22 | 23 | //! XML-style template engine 24 | class Template extends Preview { 25 | 26 | //@{ Error messages 27 | const 28 | E_Method='Call to undefined method %s()'; 29 | //@} 30 | 31 | protected 32 | //! Template tags 33 | $tags, 34 | //! Custom tag handlers 35 | $custom=array(); 36 | 37 | /** 38 | * Template -set- tag handler 39 | * @return string 40 | * @param $node array 41 | **/ 42 | protected function _set(array $node) { 43 | $out=''; 44 | foreach ($node['@attrib'] as $key=>$val) 45 | $out.='$'.$key.'='. 46 | (preg_match('/\{\{(.+?)\}\}/',$val)? 47 | $this->token($val): 48 | Base::instance()->stringify($val)).'; '; 49 | return ''; 50 | } 51 | 52 | /** 53 | * Template -include- tag handler 54 | * @return string 55 | * @param $node array 56 | **/ 57 | protected function _include(array $node) { 58 | $attrib=$node['@attrib']; 59 | $hive=isset($attrib['with']) && 60 | ($attrib['with']=$this->token($attrib['with'])) && 61 | preg_match_all('/(\w+)\h*=\h*(.+?)(?=,|$)/', 62 | $attrib['with'],$pairs,PREG_SET_ORDER)? 63 | 'array('.implode(',', 64 | array_map(function($pair) { 65 | return '\''.$pair[1].'\'=>'. 66 | (preg_match('/^\'.*\'$/',$pair[2]) || 67 | preg_match('/\$/',$pair[2])? 68 | $pair[2]: 69 | \Base::instance()->stringify($pair[2])); 70 | },$pairs)).')+get_defined_vars()': 71 | 'get_defined_vars()'; 72 | return 73 | 'token($attrib['if']).') '):''). 75 | ('echo $this->render('. 76 | (preg_match('/^\{\{(.+?)\}\}$/',$attrib['href'])? 77 | $this->token($attrib['href']): 78 | Base::instance()->stringify($attrib['href'])).','. 79 | '$this->mime,'.$hive.'); ?>'); 80 | } 81 | 82 | /** 83 | * Template -exclude- tag handler 84 | * @return string 85 | **/ 86 | protected function _exclude() { 87 | return ''; 88 | } 89 | 90 | /** 91 | * Template -ignore- tag handler 92 | * @return string 93 | * @param $node array 94 | **/ 95 | protected function _ignore(array $node) { 96 | return $node[0]; 97 | } 98 | 99 | /** 100 | * Template -loop- tag handler 101 | * @return string 102 | * @param $node array 103 | **/ 104 | protected function _loop(array $node) { 105 | $attrib=$node['@attrib']; 106 | unset($node['@attrib']); 107 | return 108 | 'token($attrib['from']).';'. 110 | $this->token($attrib['to']).';'. 111 | $this->token($attrib['step']).'): ?>'. 112 | $this->build($node). 113 | ''; 114 | } 115 | 116 | /** 117 | * Template -repeat- tag handler 118 | * @return string 119 | * @param $node array 120 | **/ 121 | protected function _repeat(array $node) { 122 | $attrib=$node['@attrib']; 123 | unset($node['@attrib']); 124 | return 125 | 'token($attrib['counter'])).'=0; '):''). 128 | 'foreach (('. 129 | $this->token($attrib['group']).'?:array()) as '. 130 | (isset($attrib['key'])? 131 | ($this->token($attrib['key']).'=>'):''). 132 | $this->token($attrib['value']).'):'. 133 | (isset($ctr)?(' '.$ctr.'++;'):'').' ?>'. 134 | $this->build($node). 135 | ''; 136 | } 137 | 138 | /** 139 | * Template -check- tag handler 140 | * @return string 141 | * @param $node array 142 | **/ 143 | protected function _check(array $node) { 144 | $attrib=$node['@attrib']; 145 | unset($node['@attrib']); 146 | // Grab and blocks 147 | foreach ($node as $pos=>$block) 148 | if (isset($block['true'])) 149 | $true=array($pos,$block); 150 | elseif (isset($block['false'])) 151 | $false=array($pos,$block); 152 | if (isset($true,$false) && $true[0]>$false[0]) 153 | // Reverse and blocks 154 | list($node[$true[0]],$node[$false[0]])=array($false[1],$true[1]); 155 | return 156 | 'token($attrib['if']).'): ?>'. 157 | $this->build($node). 158 | ''; 159 | } 160 | 161 | /** 162 | * Template -true- tag handler 163 | * @return string 164 | * @param $node array 165 | **/ 166 | protected function _true(array $node) { 167 | return $this->build($node); 168 | } 169 | 170 | /** 171 | * Template -false- tag handler 172 | * @return string 173 | * @param $node array 174 | **/ 175 | protected function _false(array $node) { 176 | return ''.$this->build($node); 177 | } 178 | 179 | /** 180 | * Template -switch- tag handler 181 | * @return string 182 | * @param $node array 183 | **/ 184 | protected function _switch(array $node) { 185 | $attrib=$node['@attrib']; 186 | unset($node['@attrib']); 187 | foreach ($node as $pos=>$block) 188 | if (is_string($block) && !preg_replace('/\s+/','',$block)) 189 | unset($node[$pos]); 190 | return 191 | 'token($attrib['expr']).'): ?>'. 192 | $this->build($node). 193 | ''; 194 | } 195 | 196 | /** 197 | * Template -case- tag handler 198 | * @return string 199 | * @param $node array 200 | **/ 201 | protected function _case(array $node) { 202 | $attrib=$node['@attrib']; 203 | unset($node['@attrib']); 204 | return 205 | 'token($attrib['value']): 207 | Base::instance()->stringify($attrib['value'])).': ?>'. 208 | $this->build($node). 209 | 'token($attrib['break']).') ':''). 211 | 'break; ?>'; 212 | } 213 | 214 | /** 215 | * Template -default- tag handler 216 | * @return string 217 | * @param $node array 218 | **/ 219 | protected function _default(array $node) { 220 | return 221 | ''. 222 | $this->build($node). 223 | ''; 224 | } 225 | 226 | /** 227 | * Assemble markup 228 | * @return string 229 | * @param $node array|string 230 | **/ 231 | protected function build($node) { 232 | if (is_string($node)) 233 | return parent::build($node); 234 | $out=''; 235 | foreach ($node as $key=>$val) 236 | $out.=is_int($key)?$this->build($val):$this->{'_'.$key}($val); 237 | return $out; 238 | } 239 | 240 | /** 241 | * Extend template with custom tag 242 | * @return NULL 243 | * @param $tag string 244 | * @param $func callback 245 | **/ 246 | function extend($tag,$func) { 247 | $this->tags.='|'.$tag; 248 | $this->custom['_'.$tag]=$func; 249 | } 250 | 251 | /** 252 | * Call custom tag handler 253 | * @return string|FALSE 254 | * @param $func callback 255 | * @param $args array 256 | **/ 257 | function __call($func,array $args) { 258 | if ($func[0]=='_') 259 | return call_user_func_array($this->custom[$func],$args); 260 | if (method_exists($this,$func)) 261 | return call_user_func_array(array($this,$func),$args); 262 | user_error(sprintf(self::E_Method,$func),E_USER_ERROR); 263 | } 264 | 265 | /** 266 | * Parse string for template directives and tokens 267 | * @return string|array 268 | * @param $text string 269 | **/ 270 | function parse($text) { 271 | // Build tree structure 272 | for ($ptr=0,$len=strlen($text),$tree=array(),$node=&$tree, 273 | $stack=array(),$depth=0,$tmp='';$ptr<$len;) 274 | if (preg_match('/^<(\/?)(?:F3:)?'. 275 | '('.$this->tags.')\b((?:\h+[\w-]+'. 276 | '(?:\h*=\h*(?:"(?:.+?)"|\'(?:.+?)\'))?|'. 277 | '\h*\{\{.+?\}\})*)\h*(\/?)>/is', 278 | substr($text,$ptr),$match)) { 279 | if (strlen($tmp)) 280 | $node[]=$tmp; 281 | // Element node 282 | if ($match[1]) { 283 | // Find matching start tag 284 | $save=$depth; 285 | $found=FALSE; 286 | while ($depth>0) { 287 | $depth--; 288 | foreach ($stack[$depth] as $item) 289 | if (is_array($item) && isset($item[$match[2]])) { 290 | // Start tag found 291 | $found=TRUE; 292 | break 2; 293 | } 294 | } 295 | if (!$found) 296 | // Unbalanced tag 297 | $depth=$save; 298 | $node=&$stack[$depth]; 299 | } 300 | else { 301 | // Start tag 302 | $stack[$depth]=&$node; 303 | $node=&$node[][$match[2]]; 304 | if ($match[3]) { 305 | // Process attributes 306 | preg_match_all( 307 | '/(?:\b([\w-]+)\h*'. 308 | '(?:=\h*(?:"(.*?)"|\'(.*?)\'))?|'. 309 | '(\{\{.+?\}\}))/s', 310 | $match[3],$attr,PREG_SET_ORDER); 311 | foreach ($attr as $kv) 312 | if (isset($kv[4])) 313 | $node['@attrib'][]=$kv[4]; 314 | else 315 | $node['@attrib'][$kv[1]]= 316 | (isset($kv[2]) && $kv[2]!==''? 317 | $kv[2]: 318 | (isset($kv[3]) && $kv[3]!==''? 319 | $kv[3]:NULL)); 320 | } 321 | if ($match[4]) 322 | // Empty tag 323 | $node=&$stack[$depth]; 324 | else 325 | $depth++; 326 | } 327 | $tmp=''; 328 | $ptr+=strlen($match[0]); 329 | } 330 | else { 331 | // Text node 332 | $tmp.=substr($text,$ptr,1); 333 | $ptr++; 334 | } 335 | if (strlen($tmp)) 336 | // Append trailing text 337 | $node[]=$tmp; 338 | // Break references 339 | unset($node); 340 | unset($stack); 341 | return $tree; 342 | } 343 | 344 | /** 345 | * Class constructor 346 | * return object 347 | **/ 348 | function __construct() { 349 | $ref=new ReflectionClass(__CLASS__); 350 | $this->tags=''; 351 | foreach ($ref->getmethods() as $method) 352 | if (preg_match('/^_(?=[[:alpha:]])/',$method->name)) 353 | $this->tags.=(strlen($this->tags)?'|':''). 354 | substr($method->name,1); 355 | } 356 | 357 | } 358 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/lib/test.php: -------------------------------------------------------------------------------- 1 | . 20 | 21 | */ 22 | 23 | //! Unit test kit 24 | class Test { 25 | 26 | //@{ Reporting level 27 | const 28 | FLAG_False=0, 29 | FLAG_True=1, 30 | FLAG_Both=2; 31 | //@} 32 | 33 | protected 34 | //! Test results 35 | $data=array(), 36 | //! Success indicator 37 | $passed=TRUE; 38 | 39 | /** 40 | * Return test results 41 | * @return array 42 | **/ 43 | function results() { 44 | return $this->data; 45 | } 46 | 47 | /** 48 | * Return FALSE if at least one test case fails 49 | * @return bool 50 | **/ 51 | function passed() { 52 | return $this->passed; 53 | } 54 | 55 | /** 56 | * Evaluate condition and save test result 57 | * @return object 58 | * @param $cond bool 59 | * @param $text string 60 | **/ 61 | function expect($cond,$text=NULL) { 62 | $out=(bool)$cond; 63 | if ($this->level==$out || $this->level==self::FLAG_Both) { 64 | $data=array('status'=>$out,'text'=>$text,'source'=>NULL); 65 | foreach (debug_backtrace() as $frame) 66 | if (isset($frame['file'])) { 67 | $data['source']=Base::instance()-> 68 | fixslashes($frame['file']).':'.$frame['line']; 69 | break; 70 | } 71 | $this->data[]=$data; 72 | } 73 | if (!$out && $this->passed) 74 | $this->passed=FALSE; 75 | return $this; 76 | } 77 | 78 | /** 79 | * Append message to test results 80 | * @return NULL 81 | * @param $text string 82 | **/ 83 | function message($text) { 84 | $this->expect(TRUE,$text); 85 | } 86 | 87 | /** 88 | * Class constructor 89 | * @return NULL 90 | * @param $level int 91 | **/ 92 | function __construct($level=self::FLAG_Both) { 93 | $this->level=$level; 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/lib/utf.php: -------------------------------------------------------------------------------- 1 | . 20 | 21 | */ 22 | 23 | //! Unicode string manager 24 | class UTF extends Prefab { 25 | 26 | /** 27 | * Get string length 28 | * @return int 29 | * @param $str string 30 | **/ 31 | function strlen($str) { 32 | preg_match_all('/./us',$str,$parts); 33 | return count($parts[0]); 34 | } 35 | 36 | /** 37 | * Reverse a string 38 | * @return string 39 | * @param $str string 40 | **/ 41 | function strrev($str) { 42 | preg_match_all('/./us',$str,$parts); 43 | return implode('',array_reverse($parts[0])); 44 | } 45 | 46 | /** 47 | * Find position of first occurrence of a string (case-insensitive) 48 | * @return int|FALSE 49 | * @param $stack string 50 | * @param $needle string 51 | * @param $ofs int 52 | **/ 53 | function stripos($stack,$needle,$ofs=0) { 54 | return $this->strpos($stack,$needle,$ofs,TRUE); 55 | } 56 | 57 | /** 58 | * Find position of first occurrence of a string 59 | * @return int|FALSE 60 | * @param $stack string 61 | * @param $needle string 62 | * @param $ofs int 63 | * @param $case bool 64 | **/ 65 | function strpos($stack,$needle,$ofs=0,$case=FALSE) { 66 | return preg_match('/^(.{'.$ofs.'}.*?)'. 67 | preg_quote($needle,'/').'/us'.($case?'i':''),$stack,$match)? 68 | $this->strlen($match[1]):FALSE; 69 | } 70 | 71 | /** 72 | * Returns part of haystack string from the first occurrence of 73 | * needle to the end of haystack (case-insensitive) 74 | * @return string|FALSE 75 | * @param $stack string 76 | * @param $needle string 77 | * @param $before bool 78 | **/ 79 | function stristr($stack,$needle,$before=FALSE) { 80 | return $this->strstr($stack,$needle,$before,TRUE); 81 | } 82 | 83 | /** 84 | * Returns part of haystack string from the first occurrence of 85 | * needle to the end of haystack 86 | * @return string|FALSE 87 | * @param $stack string 88 | * @param $needle string 89 | * @param $before bool 90 | * @param $case bool 91 | **/ 92 | function strstr($stack,$needle,$before=FALSE,$case=FALSE) { 93 | if (!$needle) 94 | return FALSE; 95 | preg_match('/^(.*?)'.preg_quote($needle,'/').'/us'.($case?'i':''), 96 | $stack,$match); 97 | return isset($match[1])? 98 | ($before? 99 | $match[1]: 100 | $this->substr($stack,$this->strlen($match[1]))): 101 | FALSE; 102 | } 103 | 104 | /** 105 | * Return part of a string 106 | * @return string|FALSE 107 | * @param $str string 108 | * @param $start int 109 | * @param $len int 110 | **/ 111 | function substr($str,$start,$len=0) { 112 | if ($start<0) 113 | $start=$this->strlen($str)+$start; 114 | if (!$len) 115 | $len=$this->strlen($str)-$start; 116 | return preg_match('/^.{'.$start.'}(.{0,'.$len.'})/us',$str,$match)? 117 | $match[1]:FALSE; 118 | } 119 | 120 | /** 121 | * Count the number of substring occurrences 122 | * @return int 123 | * @param $stack string 124 | * @param $needle string 125 | **/ 126 | function substr_count($stack,$needle) { 127 | preg_match_all('/'.preg_quote($needle,'/').'/us',$stack, 128 | $matches,PREG_SET_ORDER); 129 | return count($matches); 130 | } 131 | 132 | /** 133 | * Strip whitespaces from the beginning of a string 134 | * @return string 135 | * @param $str string 136 | **/ 137 | function ltrim($str) { 138 | return preg_replace('/^[\pZ\pC]+/u','',$str); 139 | } 140 | 141 | /** 142 | * Strip whitespaces from the end of a string 143 | * @return string 144 | * @param $str string 145 | **/ 146 | function rtrim($str) { 147 | return preg_replace('/[\pZ\pC]+$/u','',$str); 148 | } 149 | 150 | /** 151 | * Strip whitespaces from the beginning and end of a string 152 | * @return string 153 | * @param $str string 154 | **/ 155 | function trim($str) { 156 | return preg_replace('/^[\pZ\pC]+|[\pZ\pC]+$/u','',$str); 157 | } 158 | 159 | /** 160 | * Return UTF-8 byte order mark 161 | * @return string 162 | **/ 163 | function bom() { 164 | return chr(0xef).chr(0xbb).chr(0xbf); 165 | } 166 | 167 | /** 168 | * Convert code points to Unicode symbols 169 | * @return string 170 | * @param $str string 171 | **/ 172 | function translate($str) { 173 | return html_entity_decode( 174 | preg_replace('/\\\\u([[:xdigit:]]+)/i','&#x\1;',$str)); 175 | } 176 | 177 | /** 178 | * Translate emoji tokens to Unicode font-supported symbols 179 | * @return string 180 | * @param $str string 181 | **/ 182 | function emojify($str) { 183 | $map=array( 184 | ':('=>'\u2639', // frown 185 | ':)'=>'\u263a', // smile 186 | '<3'=>'\u2665', // heart 187 | ':D'=>'\u1f603', // grin 188 | 'XD'=>'\u1f606', // laugh 189 | ';)'=>'\u1f609', // wink 190 | ':P'=>'\u1f60b', // tongue 191 | ':,'=>'\u1f60f', // think 192 | ':/'=>'\u1f623', // skeptic 193 | '8O'=>'\u1f632', // oops 194 | )+Base::instance()->get('EMOJI'); 195 | return $this->translate(str_replace(array_keys($map), 196 | array_values($map),$str)); 197 | } 198 | 199 | } 200 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/lib/web/geo.php: -------------------------------------------------------------------------------- 1 | . 20 | 21 | */ 22 | 23 | namespace Web; 24 | 25 | //! Geo plug-in 26 | class Geo extends \Prefab { 27 | 28 | /** 29 | * Return information about specified Unix time zone 30 | * @return array 31 | * @param $zone string 32 | **/ 33 | function tzinfo($zone) { 34 | $ref=new \DateTimeZone($zone); 35 | $loc=$ref->getLocation(); 36 | $trn=$ref->getTransitions($now=time(),$now); 37 | $out=array( 38 | 'offset'=>$ref-> 39 | getOffset(new \DateTime('now',new \DateTimeZone('GMT')))/3600, 40 | 'country'=>$loc['country_code'], 41 | 'latitude'=>$loc['latitude'], 42 | 'longitude'=>$loc['longitude'], 43 | 'dst'=>$trn[0]['isdst'] 44 | ); 45 | unset($ref); 46 | return $out; 47 | } 48 | 49 | /** 50 | * Return geolocation data based on specified/auto-detected IP address 51 | * @return array|FALSE 52 | * @param $ip string 53 | **/ 54 | function location($ip=NULL) { 55 | $fw=\Base::instance(); 56 | $web=\Web::instance(); 57 | if (!$ip) 58 | $ip=$fw->get('IP'); 59 | $public=filter_var($ip,FILTER_VALIDATE_IP, 60 | FILTER_FLAG_IPV4|FILTER_FLAG_IPV6| 61 | FILTER_FLAG_NO_RES_RANGE|FILTER_FLAG_NO_PRIV_RANGE); 62 | if (function_exists('geoip_db_avail') && 63 | geoip_db_avail(GEOIP_CITY_EDITION_REV1) && 64 | $out=@geoip_record_by_name($ip)) { 65 | $out['request']=$ip; 66 | $out['region_code']=$out['region']; 67 | $out['region_name']=geoip_region_name_by_code( 68 | $out['country_code'],$out['region']); 69 | unset($out['country_code3'],$out['region'],$out['postal_code']); 70 | return $out; 71 | } 72 | if (($req=$web->request('http://www.geoplugin.net/json.gp'. 73 | ($public?('?ip='.$ip):''))) && 74 | $data=json_decode($req['body'],TRUE)) { 75 | $out=array(); 76 | foreach ($data as $key=>$val) 77 | if (!strpos($key,'currency') && $key!=='geoplugin_status' 78 | && $key!=='geoplugin_region') 79 | $out[$fw->snakecase(substr($key, 10))]=$val; 80 | return $out; 81 | } 82 | return FALSE; 83 | } 84 | 85 | /** 86 | * Return weather data based on specified latitude/longitude 87 | * @return array|FALSE 88 | * @param $latitude float 89 | * @param $longitude float 90 | **/ 91 | function weather($latitude,$longitude) { 92 | $fw=\Base::instance(); 93 | $web=\Web::instance(); 94 | $query=array( 95 | 'lat'=>$latitude, 96 | 'lon'=>$longitude 97 | ); 98 | $req=$web->request( 99 | 'http://api.openweathermap.org/data/2.5/weather?'. 100 | http_build_query($query)); 101 | return ($req=$web->request( 102 | 'http://api.openweathermap.org/data/2.5/weather?'. 103 | http_build_query($query)))? 104 | json_decode($req['body'],TRUE): 105 | FALSE; 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/lib/web/google/staticmap.php: -------------------------------------------------------------------------------- 1 | . 20 | 21 | */ 22 | 23 | namespace Web\Google; 24 | 25 | //! Google Static Maps API v2 plug-in 26 | class StaticMap { 27 | 28 | const 29 | //! API URL 30 | URL_Static='http://maps.googleapis.com/maps/api/staticmap'; 31 | 32 | protected 33 | //! Query arguments 34 | $query=array(); 35 | 36 | /** 37 | * Specify API key-value pair via magic call 38 | * @return object 39 | * @param $func string 40 | * @param $args array 41 | **/ 42 | function __call($func,array $args) { 43 | $this->query[]=array($func,$args[0]); 44 | return $this; 45 | } 46 | 47 | /** 48 | * Generate map 49 | * @return string 50 | **/ 51 | function dump() { 52 | $fw=\Base::instance(); 53 | $web=\Web::instance(); 54 | $out=''; 55 | return ($req=$web->request( 56 | self::URL_Static.'?'.array_reduce( 57 | $this->query, 58 | function($out,$item) { 59 | return ($out.=($out?'&':''). 60 | urlencode($item[0]).'='.urlencode($item[1])); 61 | } 62 | ))) && $req['body']?$req['body']:FALSE; 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/lib/web/openid.php: -------------------------------------------------------------------------------- 1 | . 20 | 21 | */ 22 | 23 | namespace Web; 24 | 25 | //! OpenID consumer 26 | class OpenID extends \Magic { 27 | 28 | protected 29 | //! OpenID provider endpoint URL 30 | $url, 31 | //! HTTP request parameters 32 | $args=array(); 33 | 34 | /** 35 | * Determine OpenID provider 36 | * @return string|FALSE 37 | * @param $proxy string 38 | **/ 39 | protected function discover($proxy) { 40 | // Normalize 41 | if (!preg_match('/https?:\/\//i',$this->args['identity'])) 42 | $this->args['identity']='http://'.$this->args['identity']; 43 | $url=parse_url($this->args['identity']); 44 | // Remove fragment; reconnect parts 45 | $this->args['identity']=$url['scheme'].'://'. 46 | (isset($url['user'])? 47 | ($url['user']. 48 | (isset($url['pass'])?(':'.$url['pass']):'').'@'):''). 49 | strtolower($url['host']).(isset($url['path'])?$url['path']:'/'). 50 | (isset($url['query'])?('?'.$url['query']):''); 51 | // HTML-based discovery of OpenID provider 52 | $req=\Web::instance()-> 53 | request($this->args['identity'],array('proxy'=>$proxy)); 54 | if (!$req) 55 | return FALSE; 56 | $type=array_values(preg_grep('/Content-Type:/',$req['headers'])); 57 | if ($type && 58 | preg_match('/application\/xrds\+xml|text\/xml/',$type[0]) && 59 | ($sxml=simplexml_load_string($req['body'])) && 60 | ($xrds=json_decode(json_encode($sxml),TRUE)) && 61 | isset($xrds['XRD'])) { 62 | // XRDS document 63 | $svc=$xrds['XRD']['Service']; 64 | if (isset($svc[0])) 65 | $svc=$svc[0]; 66 | if (preg_grep('/http:\/\/specs\.openid\.net\/auth\/2.0\/'. 67 | '(?:server|signon)/',$svc['Type'])) { 68 | $this->args['provider']=$svc['URI']; 69 | if (isset($svc['LocalID'])) 70 | $this->args['localidentity']=$svc['LocalID']; 71 | elseif (isset($svc['CanonicalID'])) 72 | $this->args['localidentity']=$svc['CanonicalID']; 73 | } 74 | $this->args['server']=$svc['URI']; 75 | if (isset($svc['Delegate'])) 76 | $this->args['delegate']=$svc['Delegate']; 77 | } 78 | else { 79 | $len=strlen($req['body']); 80 | $ptr=0; 81 | // Parse document 82 | while ($ptr<$len) 83 | if (preg_match( 84 | '/^/is', 86 | substr($req['body'],$ptr),$parts)) { 87 | if ($parts[1] && 88 | // Process attributes 89 | preg_match_all('/\b(rel|href)\h*=\h*'. 90 | '(?:"(.+?)"|\'(.+?)\')/s',$parts[1],$attr, 91 | PREG_SET_ORDER)) { 92 | $node=array(); 93 | foreach ($attr as $kv) 94 | $node[$kv[1]]=isset($kv[2])?$kv[2]:$kv[3]; 95 | if (isset($node['rel']) && 96 | preg_match('/openid2?\.(\w+)/', 97 | $node['rel'],$var) && 98 | isset($node['href'])) 99 | $this->args[$var[1]]=$node['href']; 100 | 101 | } 102 | $ptr+=strlen($parts[0]); 103 | } 104 | else 105 | $ptr++; 106 | } 107 | // Get OpenID provider's endpoint URL 108 | if (isset($this->args['provider'])) { 109 | // OpenID 2.0 110 | $this->args['ns']='http://specs.openid.net/auth/2.0'; 111 | if (isset($this->args['localidentity'])) 112 | $this->args['identity']=$this->args['localidentity']; 113 | if (isset($this->args['trust_root'])) 114 | $this->args['realm']=$this->args['trust_root']; 115 | } 116 | elseif (isset($this->args['server'])) { 117 | // OpenID 1.1 118 | $this->args['ns']='http://openid.net/signon/1.1'; 119 | if (isset($this->args['delegate'])) 120 | $this->args['identity']=$this->args['delegate']; 121 | } 122 | if (isset($this->args['provider'])) { 123 | // OpenID 2.0 124 | if (empty($this->args['claimed_id'])) 125 | $this->args['claimed_id']=$this->args['identity']; 126 | return $this->args['provider']; 127 | } 128 | elseif (isset($this->args['server'])) 129 | // OpenID 1.1 130 | return $this->args['server']; 131 | else 132 | return FALSE; 133 | } 134 | 135 | /** 136 | * Initiate OpenID authentication sequence; Return FALSE on failure 137 | * or redirect to OpenID provider URL 138 | * @return bool 139 | * @param $proxy string 140 | * @param $attr array 141 | * @param $reqd string|array 142 | **/ 143 | function auth($proxy=NULL,$attr=array(),array $reqd=NULL) { 144 | $fw=\Base::instance(); 145 | $root=$fw->get('SCHEME').'://'.$fw->get('HOST'); 146 | if (empty($this->args['trust_root'])) 147 | $this->args['trust_root']=$root.$fw->get('BASE').'/'; 148 | if (empty($this->args['return_to'])) 149 | $this->args['return_to']=$root.$_SERVER['REQUEST_URI']; 150 | $this->args['mode']='checkid_setup'; 151 | if ($this->url=$this->discover($proxy)) { 152 | if ($attr) { 153 | $this->args['ns.ax']='http://openid.net/srv/ax/1.0'; 154 | $this->args['ax.mode']='fetch_request'; 155 | foreach ($attr as $key=>$val) 156 | $this->args['ax.type.'.$key]=$val; 157 | $this->args['ax.required']=is_string($reqd)? 158 | $reqd:implode(',',$reqd); 159 | } 160 | $var=array(); 161 | foreach ($this->args as $key=>$val) 162 | $var['openid.'.$key]=$val; 163 | $fw->reroute($this->url.'?'.http_build_query($var)); 164 | } 165 | return FALSE; 166 | } 167 | 168 | /** 169 | * Return TRUE if OpenID verification was successful 170 | * @return bool 171 | * @param $proxy string 172 | **/ 173 | function verified($proxy=NULL) { 174 | preg_match_all('/(?<=^|&)openid\.([^=]+)=([^&]+)/', 175 | $_SERVER['QUERY_STRING'],$matches,PREG_SET_ORDER); 176 | foreach ($matches as $match) 177 | $this->args[$match[1]]=urldecode($match[2]); 178 | if (isset($this->args['mode']) && 179 | $this->args['mode']!='error' && 180 | $this->url=$this->discover($proxy)) { 181 | $this->args['mode']='check_authentication'; 182 | $var=array(); 183 | foreach ($this->args as $key=>$val) 184 | $var['openid.'.$key]=$val; 185 | $req=\Web::instance()->request( 186 | $this->url, 187 | array( 188 | 'method'=>'POST', 189 | 'content'=>http_build_query($var), 190 | 'proxy'=>$proxy 191 | ) 192 | ); 193 | return (bool)preg_match('/is_valid:true/i',$req['body']); 194 | } 195 | return FALSE; 196 | } 197 | 198 | /** 199 | * Return OpenID response fields 200 | * @return array 201 | **/ 202 | function response() { 203 | return $this->args; 204 | } 205 | 206 | /** 207 | * Return TRUE if OpenID request parameter exists 208 | * @return bool 209 | * @param $key string 210 | **/ 211 | function exists($key) { 212 | return isset($this->args[$key]); 213 | } 214 | 215 | /** 216 | * Bind value to OpenID request parameter 217 | * @return string 218 | * @param $key string 219 | * @param $val string 220 | **/ 221 | function set($key,$val) { 222 | return $this->args[$key]=$val; 223 | } 224 | 225 | /** 226 | * Return value of OpenID request parameter 227 | * @return mixed 228 | * @param $key string 229 | **/ 230 | function &get($key) { 231 | if (isset($this->args[$key])) 232 | $val=&$this->args[$key]; 233 | else 234 | $val=NULL; 235 | return $val; 236 | } 237 | 238 | /** 239 | * Remove OpenID request parameter 240 | * @return NULL 241 | * @param $key 242 | **/ 243 | function clear($key) { 244 | unset($this->args[$key]); 245 | } 246 | 247 | } 248 | 249 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/lib/web/pingback.php: -------------------------------------------------------------------------------- 1 | . 20 | 21 | */ 22 | 23 | namespace Web; 24 | 25 | //! Pingback 1.0 protocol (client and server) implementation 26 | class Pingback extends \Prefab { 27 | 28 | protected 29 | //! Transaction history 30 | $log; 31 | 32 | /** 33 | * Return TRUE if URL points to a pingback-enabled resource 34 | * @return bool 35 | * @param $url 36 | **/ 37 | protected function enabled($url) { 38 | $web=\Web::instance(); 39 | $req=$web->request($url); 40 | $found=FALSE; 41 | if ($req && $req['body']) { 42 | // Look for pingback header 43 | foreach ($req['headers'] as $header) 44 | if (preg_match('/^X-Pingback:\h*(.+)/',$header,$href)) { 45 | $found=$href[1]; 46 | break; 47 | } 48 | if (!$found && 49 | // Scan page for pingback link tag 50 | preg_match('//i',$req['body'],$parts) && 51 | preg_match('/rel\h*=\h*"pingback"/i',$parts[1]) && 52 | preg_match('/href\h*=\h*"\h*(.+?)\h*"/i',$parts[1],$href)) 53 | $found=$href[1]; 54 | } 55 | return $found; 56 | } 57 | 58 | /** 59 | * Load local page contents, parse HTML anchor tags, find permalinks, 60 | * and send XML-RPC calls to corresponding pingback servers 61 | * @return NULL 62 | * @param $source string 63 | **/ 64 | function inspect($source) { 65 | $fw=\Base::instance(); 66 | $web=\Web::instance(); 67 | $parts=parse_url($source); 68 | if (empty($parts['scheme']) || empty($parts['host']) || 69 | $parts['host']==$fw->get('HOST')) { 70 | $req=$web->request($source); 71 | $doc=new \DOMDocument('1.0',$fw->get('ENCODING')); 72 | $doc->stricterrorchecking=FALSE; 73 | $doc->recover=TRUE; 74 | if ($req && @$doc->loadhtml($req['body'])) { 75 | // Parse anchor tags 76 | $links=$doc->getelementsbytagname('a'); 77 | foreach ($links as $link) { 78 | $permalink=$link->getattribute('href'); 79 | // Find pingback-enabled resources 80 | if ($permalink && $found=$this->enabled($permalink)) { 81 | $req=$web->request($found, 82 | array( 83 | 'method'=>'POST', 84 | 'header'=>'Content-Type: application/xml', 85 | 'content'=>xmlrpc_encode_request( 86 | 'pingback.ping', 87 | array($source,$permalink), 88 | array('encoding'=>$fw->get('ENCODING')) 89 | ) 90 | ) 91 | ); 92 | if ($req && $req['body']) 93 | $this->log.=date('r').' '. 94 | $permalink.' [permalink:'.$found.']'.PHP_EOL. 95 | $req['body'].PHP_EOL; 96 | } 97 | } 98 | } 99 | unset($doc); 100 | } 101 | } 102 | 103 | /** 104 | * Receive ping, check if local page is pingback-enabled, verify 105 | * source contents, and return XML-RPC response 106 | * @return string 107 | * @param $func callback 108 | * @param $path string 109 | **/ 110 | function listen($func,$path=NULL) { 111 | $fw=\Base::instance(); 112 | if (PHP_SAPI!='cli') { 113 | header('X-Powered-By: '.$fw->get('PACKAGE')); 114 | header('Content-Type: application/xml; '. 115 | 'charset='.$charset=$fw->get('ENCODING')); 116 | } 117 | if (!$path) 118 | $path=$fw->get('BASE'); 119 | $web=\Web::instance(); 120 | $args=xmlrpc_decode_request($fw->get('BODY'),$method,$charset); 121 | $options=array('encoding'=>$charset); 122 | if ($method=='pingback.ping' && isset($args[0],$args[1])) { 123 | list($source,$permalink)=$args; 124 | $doc=new \DOMDocument('1.0',$fw->get('ENCODING')); 125 | // Check local page if pingback-enabled 126 | $parts=parse_url($permalink); 127 | if ((empty($parts['scheme']) || 128 | $parts['host']==$fw->get('HOST')) && 129 | preg_match('/^'.preg_quote($path,'/').'/'. 130 | ($fw->get('CASELESS')?'i':''),$parts['path']) && 131 | $this->enabled($permalink)) { 132 | // Check source 133 | $parts=parse_url($source); 134 | if ((empty($parts['scheme']) || 135 | $parts['host']==$fw->get('HOST')) && 136 | ($req=$web->request($source)) && 137 | $doc->loadhtml($req['body'])) { 138 | $links=$doc->getelementsbytagname('a'); 139 | foreach ($links as $link) { 140 | if ($link->getattribute('href')==$permalink) { 141 | call_user_func_array($func, 142 | array($source,$req['body'])); 143 | // Success 144 | die(xmlrpc_encode_request(NULL,$source,$options)); 145 | } 146 | } 147 | // No link to local page 148 | die(xmlrpc_encode_request(NULL,0x11,$options)); 149 | } 150 | // Source failure 151 | die(xmlrpc_encode_request(NULL,0x10,$options)); 152 | } 153 | // Doesn't exist (or not pingback-enabled) 154 | die(xmlrpc_encode_request(NULL,0x21,$options)); 155 | } 156 | // Access denied 157 | die(xmlrpc_encode_request(NULL,0x31,$options)); 158 | } 159 | 160 | /** 161 | * Return transaction history 162 | * @return string 163 | **/ 164 | function log() { 165 | return $this->log; 166 | } 167 | 168 | /** 169 | * Instantiate class 170 | * @return object 171 | **/ 172 | function __construct() { 173 | // Suppress errors caused by invalid HTML structures 174 | libxml_use_internal_errors(TRUE); 175 | } 176 | 177 | } 178 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/ui/css/base.css: -------------------------------------------------------------------------------- 1 | /* Reset */ 2 | html,body,div,span,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,abbr,address,cite,code,del,dfn,em,img,ins,kbd,q,samp,small,strong,sub,sup,var,b,i,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,figcaption,figure,footer,header,hgroup,dir,menu,nav,section,summary,time,mark,audio,video{margin:0;padding:0;border:0;outline:0;font-size:100%;vertical-align:baseline;background:transparent}body{line-height:1}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}nav ul{list-style:none}ol{list-style:decimal}ul{list-style:disc}ul ul{list-style:circle}blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:none}a{margin:0;padding:0;font-size:100%;vertical-align:baseline;background:transparent}ins{text-decoration:underline}mark{background:none}del{text-decoration:line-through}abbr[title],dfn[title]{border-bottom:1px dotted;cursor:help}table{border-collapse:collapse;border-spacing:0}hr{display:block;height:1px;border:0;border-top:1px solid #ccc;margin:1em 0;padding:0}input,select,a img{vertical-align:middle} 3 | /* Typography */ 4 | *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;max-width:100%}html{height:100%;font-size:100%;font-family:serif;overflow-y:scroll;-webkit-text-size-adjust:100%}body{margin:0;min-height:100%;overflow:hidden}body,pre,label,input,button,select,textarea{font:normal 100%/1.25 serif;vertical-align:top}a{display:inline-block}p,ul,ol{margin:1.25em 0}h1{font-size:2em;line-height:1.25em;margin:0.625em 0}h2{font-size:1.5em;line-height:1.6667em;margin:0.8333em 0}h3{font-size:1.25em;line-height:1em;margin:1em 0}h4{font-size:1em;line-height:1.25em;margin:1.25em 0}h5{font-size:0.8125em;line-height:1.5385em;margin:1.5385em 0}h6{font-size:0.6875em;line-height:1.8182em;margin:1.8182em 0}blockquote{margin:0 3em}caption{font-weight:bold}ul,ol,dir,menu,dd{margin-left:3em}ul,dir,menu{list-style:disc}ol{list-style:decimal}sub,sup{font-size:75%;line-height:0;vertical-align:baseline;position:relative}sub{top:0.5em}sup{top:-0.5em}label{display:inline-block}input[type="text"],input[type="password"],input[type="file"]{padding:1px;border:1px solid #999;margin:-4px 0 0 0}select,textarea{padding:0;border:1px solid #999;margin:-4px 0 0 0}fieldset{padding:0.625em;border:1px solid #ccc;margin-bottom:0.625em}input[type="radio"],input[type="checkbox"]{height:1em;vertical-align:top;margin:0.125em}div,table{overflow:hidden} 5 | /* Fluid Fonts */ 6 | @media screen and (max-width:960px){body{font-size:0.81255em}} -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/ui/css/theme.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family:Ubuntu,sans-serif; 3 | font-size:1.2em; 4 | } 5 | 6 | h1 { 7 | color:#faa; 8 | } 9 | 10 | h2 { 11 | color:#e88; 12 | } 13 | 14 | h3 { 15 | color:#b66; 16 | } 17 | 18 | h4 { 19 | color:#944; 20 | } 21 | 22 | h5 { 23 | color:#722; 24 | } 25 | 26 | h6 { 27 | color:#500; 28 | } 29 | 30 | small { 31 | font-size:0.75em 32 | } 33 | 34 | a { 35 | text-decoration:none; 36 | color:#66f; 37 | } 38 | 39 | a:hover { 40 | color:#666; 41 | } 42 | 43 | img { 44 | max-width:100% 45 | } 46 | 47 | table { 48 | font-size:.8em; 49 | color:#666 !important; 50 | background:#eee; 51 | width:100%; 52 | border-radius:.5em; 53 | } 54 | 55 | table code { 56 | background:transparent; 57 | padding:0 58 | } 59 | 60 | tr { 61 | border-bottom:1px solid #fff; 62 | } 63 | 64 | tr:last-child { 65 | border-bottom:none; 66 | } 67 | 68 | th,td { 69 | font-size:1em; 70 | line-height:1.25em; 71 | margin:0; 72 | padding:1em; 73 | white-space:nowrap; 74 | } 75 | 76 | th { 77 | font-weight:bold; 78 | text-align:left; 79 | text-transform:uppercase; 80 | color:#fff; 81 | background:#999; 82 | } 83 | 84 | th a { 85 | color:#fff; 86 | } 87 | 88 | th:first-child, 89 | td:first-child { 90 | width:50%; 91 | } 92 | 93 | pre { 94 | background:#efefef; 95 | padding:0.75em; 96 | border-radius:0.75em; 97 | } 98 | 99 | ul,p { 100 | color:#666; 101 | line-height:1.5em; 102 | } 103 | 104 | p code,ul code { 105 | padding:.25em .75em; 106 | border-radius:.75em; 107 | white-space:nowrap 108 | } 109 | 110 | blockquote pre,blockquote code { 111 | color:#666; 112 | background:#fff; 113 | } 114 | 115 | code { 116 | background:#eee; 117 | } 118 | 119 | .center { 120 | text-align:center; 121 | } 122 | 123 | .right { 124 | text-align:right; 125 | } 126 | 127 | .content { 128 | padding:0 20px; 129 | max-width:768px; 130 | margin:0 auto; 131 | } 132 | 133 | .header { 134 | background:#eee; 135 | } 136 | 137 | .header img { 138 | width:90%; 139 | max-width:768px; 140 | padding:0 5%; 141 | } 142 | 143 | .footer { 144 | font-size:0.9em; 145 | background:#333; 146 | } 147 | 148 | .footer p { 149 | color:#eee; 150 | padding:20px; 151 | max-width:768px; 152 | margin:0 auto; 153 | } 154 | 155 | .footer .stats { 156 | font-size:.9em; 157 | } 158 | 159 | @media screen and (max-width:48em) { 160 | 161 | body { 162 | font-size:1em; 163 | } 164 | 165 | } 166 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/ui/images/bitcoin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/takacsmark/Fat-Free-PHP-MVC-Sample-Project/650949c374ce90fc4542e2e76b84a529b2357206/vendor/bcosca/fatfree/ui/images/bitcoin.png -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/ui/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/takacsmark/Fat-Free-PHP-MVC-Sample-Project/650949c374ce90fc4542e2e76b84a529b2357206/vendor/bcosca/fatfree/ui/images/logo.png -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/ui/images/paypal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/takacsmark/Fat-Free-PHP-MVC-Sample-Project/650949c374ce90fc4542e2e76b84a529b2357206/vendor/bcosca/fatfree/ui/images/paypal.png -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/ui/images/twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/takacsmark/Fat-Free-PHP-MVC-Sample-Project/650949c374ce90fc4542e2e76b84a529b2357206/vendor/bcosca/fatfree/ui/images/twitter.png -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/ui/layout.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Powered by <?php echo $PACKAGE; ?> 6 | 7 | 8 | 9 | 10 | 11 | 12 | render(Base::instance()->get('content')); ?> 13 | 14 | 15 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/ui/userref.htm: -------------------------------------------------------------------------------- 1 |
    2 | 3 | convert(Base::instance()->read('readme.md')); ?> 4 |
    5 | -------------------------------------------------------------------------------- /vendor/bcosca/fatfree/ui/welcome.htm: -------------------------------------------------------------------------------- 1 |
    2 |

    3 |
    4 |
    5 |

    Version

    6 |

    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 |
      8 |
    • Application and code libraries
    • 9 |
    • HTML templates
    • 10 |
    • Graphics and media files
    • 11 |
    • Javascript and CSS files
    • 12 |
    • Database (if you plan to use an embedded DB like SQLite)
    • 13 |
    • Configuration files
    • 14 |
    • Uploads/Downloads
    • 15 |
    16 |

    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.

    17 |

    F3 can autoload OOP classes for you. Just add the path to the AUTOLOAD variable.

    18 |

    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!

    19 |

    PHP Dependencies

    20 |

    Some framework features in this version will not be available if PHP is not configured with the modules needed by your application.

    21 | 22 | 23 | 24 | 25 | 26 | $modules): ?> 27 | 28 | 29 | 34 | 35 | 36 |
    Class/Plug-inPHP Module
    30 | 31 | onclick="return false">
    32 | 33 |
    37 |
      38 |
    • The Base class requires all listed PHP modules enabled to function properly.
    • 39 |
    • The Cache class will use any available module in the list. If none can be found, it will use the filesystem as fallback.
    • 40 |
    • The DB\SQL class requires the pdo module and a PDO driver relevant to your application.
    • 41 |
    • The Bcrypt class will use the mcrypt or openssl module for entropy generation. Otherwise, it employs a custom random function.
    • 42 |
    • The 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.
    • 43 |
    • The geoip module listed in the Web\Geo class is optional; the class will use an alternative Web service for geo-location.
    • 44 |
    • Other framework classes in the list need all its listed modules enabled.
    • 45 |
    46 |

    Need Help?

    47 |

    If you have any questions regarding the framework, technical support is available at https://groups.google.com/forum/?fromgroups#!forum/f3-framework

    48 |

    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.

    49 |

    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.

    50 |

    Take a close look at the Fat-Free API Documentation for in-depth information about the framework.

    51 |

    Fair Licensing

    52 |

    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 |

    Support F3

    55 |

    F3 is community-driven software. Support the development of the Fat-Free Framework. Your contributions help keep this project alive.

    56 |

    57 |
    58 | 63 | -------------------------------------------------------------------------------- /vendor/composer/ClassLoader.php: -------------------------------------------------------------------------------- 1 | 7 | * Jordi Boggiano 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | 13 | namespace Composer\Autoload; 14 | 15 | /** 16 | * ClassLoader implements a PSR-0 class loader 17 | * 18 | * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md 19 | * 20 | * $loader = new \Composer\Autoload\ClassLoader(); 21 | * 22 | * // register classes with namespaces 23 | * $loader->add('Symfony\Component', __DIR__.'/component'); 24 | * $loader->add('Symfony', __DIR__.'/framework'); 25 | * 26 | * // activate the autoloader 27 | * $loader->register(); 28 | * 29 | * // to enable searching the include path (eg. for PEAR packages) 30 | * $loader->setUseIncludePath(true); 31 | * 32 | * In this example, if you try to use a class in the Symfony\Component 33 | * namespace or one of its children (Symfony\Component\Console for instance), 34 | * the autoloader will first look for the class under the component/ 35 | * directory, and it will then fallback to the framework/ directory if not 36 | * found before giving up. 37 | * 38 | * This class is loosely based on the Symfony UniversalClassLoader. 39 | * 40 | * @author Fabien Potencier 41 | * @author Jordi Boggiano 42 | */ 43 | class ClassLoader 44 | { 45 | // PSR-4 46 | private $prefixLengthsPsr4 = array(); 47 | private $prefixDirsPsr4 = array(); 48 | private $fallbackDirsPsr4 = array(); 49 | 50 | // PSR-0 51 | private $prefixesPsr0 = array(); 52 | private $fallbackDirsPsr0 = array(); 53 | 54 | private $useIncludePath = false; 55 | private $classMap = array(); 56 | 57 | private $classMapAuthoritative = false; 58 | 59 | public function getPrefixes() 60 | { 61 | if (!empty($this->prefixesPsr0)) { 62 | return call_user_func_array('array_merge', $this->prefixesPsr0); 63 | } 64 | 65 | return array(); 66 | } 67 | 68 | public function getPrefixesPsr4() 69 | { 70 | return $this->prefixDirsPsr4; 71 | } 72 | 73 | public function getFallbackDirs() 74 | { 75 | return $this->fallbackDirsPsr0; 76 | } 77 | 78 | public function getFallbackDirsPsr4() 79 | { 80 | return $this->fallbackDirsPsr4; 81 | } 82 | 83 | public function getClassMap() 84 | { 85 | return $this->classMap; 86 | } 87 | 88 | /** 89 | * @param array $classMap Class to filename map 90 | */ 91 | public function addClassMap(array $classMap) 92 | { 93 | if ($this->classMap) { 94 | $this->classMap = array_merge($this->classMap, $classMap); 95 | } else { 96 | $this->classMap = $classMap; 97 | } 98 | } 99 | 100 | /** 101 | * Registers a set of PSR-0 directories for a given prefix, either 102 | * appending or prepending to the ones previously set for this prefix. 103 | * 104 | * @param string $prefix The prefix 105 | * @param array|string $paths The PSR-0 root directories 106 | * @param bool $prepend Whether to prepend the directories 107 | */ 108 | public function add($prefix, $paths, $prepend = false) 109 | { 110 | if (!$prefix) { 111 | if ($prepend) { 112 | $this->fallbackDirsPsr0 = array_merge( 113 | (array) $paths, 114 | $this->fallbackDirsPsr0 115 | ); 116 | } else { 117 | $this->fallbackDirsPsr0 = array_merge( 118 | $this->fallbackDirsPsr0, 119 | (array) $paths 120 | ); 121 | } 122 | 123 | return; 124 | } 125 | 126 | $first = $prefix[0]; 127 | if (!isset($this->prefixesPsr0[$first][$prefix])) { 128 | $this->prefixesPsr0[$first][$prefix] = (array) $paths; 129 | 130 | return; 131 | } 132 | if ($prepend) { 133 | $this->prefixesPsr0[$first][$prefix] = array_merge( 134 | (array) $paths, 135 | $this->prefixesPsr0[$first][$prefix] 136 | ); 137 | } else { 138 | $this->prefixesPsr0[$first][$prefix] = array_merge( 139 | $this->prefixesPsr0[$first][$prefix], 140 | (array) $paths 141 | ); 142 | } 143 | } 144 | 145 | /** 146 | * Registers a set of PSR-4 directories for a given namespace, either 147 | * appending or prepending to the ones previously set for this namespace. 148 | * 149 | * @param string $prefix The prefix/namespace, with trailing '\\' 150 | * @param array|string $paths The PSR-0 base directories 151 | * @param bool $prepend Whether to prepend the directories 152 | * 153 | * @throws \InvalidArgumentException 154 | */ 155 | public function addPsr4($prefix, $paths, $prepend = false) 156 | { 157 | if (!$prefix) { 158 | // Register directories for the root namespace. 159 | if ($prepend) { 160 | $this->fallbackDirsPsr4 = array_merge( 161 | (array) $paths, 162 | $this->fallbackDirsPsr4 163 | ); 164 | } else { 165 | $this->fallbackDirsPsr4 = array_merge( 166 | $this->fallbackDirsPsr4, 167 | (array) $paths 168 | ); 169 | } 170 | } elseif (!isset($this->prefixDirsPsr4[$prefix])) { 171 | // Register directories for a new namespace. 172 | $length = strlen($prefix); 173 | if ('\\' !== $prefix[$length - 1]) { 174 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); 175 | } 176 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 177 | $this->prefixDirsPsr4[$prefix] = (array) $paths; 178 | } elseif ($prepend) { 179 | // Prepend directories for an already registered namespace. 180 | $this->prefixDirsPsr4[$prefix] = array_merge( 181 | (array) $paths, 182 | $this->prefixDirsPsr4[$prefix] 183 | ); 184 | } else { 185 | // Append directories for an already registered namespace. 186 | $this->prefixDirsPsr4[$prefix] = array_merge( 187 | $this->prefixDirsPsr4[$prefix], 188 | (array) $paths 189 | ); 190 | } 191 | } 192 | 193 | /** 194 | * Registers a set of PSR-0 directories for a given prefix, 195 | * replacing any others previously set for this prefix. 196 | * 197 | * @param string $prefix The prefix 198 | * @param array|string $paths The PSR-0 base directories 199 | */ 200 | public function set($prefix, $paths) 201 | { 202 | if (!$prefix) { 203 | $this->fallbackDirsPsr0 = (array) $paths; 204 | } else { 205 | $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; 206 | } 207 | } 208 | 209 | /** 210 | * Registers a set of PSR-4 directories for a given namespace, 211 | * replacing any others previously set for this namespace. 212 | * 213 | * @param string $prefix The prefix/namespace, with trailing '\\' 214 | * @param array|string $paths The PSR-4 base directories 215 | * 216 | * @throws \InvalidArgumentException 217 | */ 218 | public function setPsr4($prefix, $paths) 219 | { 220 | if (!$prefix) { 221 | $this->fallbackDirsPsr4 = (array) $paths; 222 | } else { 223 | $length = strlen($prefix); 224 | if ('\\' !== $prefix[$length - 1]) { 225 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); 226 | } 227 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 228 | $this->prefixDirsPsr4[$prefix] = (array) $paths; 229 | } 230 | } 231 | 232 | /** 233 | * Turns on searching the include path for class files. 234 | * 235 | * @param bool $useIncludePath 236 | */ 237 | public function setUseIncludePath($useIncludePath) 238 | { 239 | $this->useIncludePath = $useIncludePath; 240 | } 241 | 242 | /** 243 | * Can be used to check if the autoloader uses the include path to check 244 | * for classes. 245 | * 246 | * @return bool 247 | */ 248 | public function getUseIncludePath() 249 | { 250 | return $this->useIncludePath; 251 | } 252 | 253 | /** 254 | * Turns off searching the prefix and fallback directories for classes 255 | * that have not been registered with the class map. 256 | * 257 | * @param bool $classMapAuthoritative 258 | */ 259 | public function setClassMapAuthoritative($classMapAuthoritative) 260 | { 261 | $this->classMapAuthoritative = $classMapAuthoritative; 262 | } 263 | 264 | /** 265 | * Should class lookup fail if not found in the current class map? 266 | * 267 | * @return bool 268 | */ 269 | public function isClassMapAuthoritative() 270 | { 271 | return $this->classMapAuthoritative; 272 | } 273 | 274 | /** 275 | * Registers this instance as an autoloader. 276 | * 277 | * @param bool $prepend Whether to prepend the autoloader or not 278 | */ 279 | public function register($prepend = false) 280 | { 281 | spl_autoload_register(array($this, 'loadClass'), true, $prepend); 282 | } 283 | 284 | /** 285 | * Unregisters this instance as an autoloader. 286 | */ 287 | public function unregister() 288 | { 289 | spl_autoload_unregister(array($this, 'loadClass')); 290 | } 291 | 292 | /** 293 | * Loads the given class or interface. 294 | * 295 | * @param string $class The name of the class 296 | * @return bool|null True if loaded, null otherwise 297 | */ 298 | public function loadClass($class) 299 | { 300 | if ($file = $this->findFile($class)) { 301 | includeFile($file); 302 | 303 | return true; 304 | } 305 | } 306 | 307 | /** 308 | * Finds the path to the file where the class is defined. 309 | * 310 | * @param string $class The name of the class 311 | * 312 | * @return string|false The path if found, false otherwise 313 | */ 314 | public function findFile($class) 315 | { 316 | // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731 317 | if ('\\' == $class[0]) { 318 | $class = substr($class, 1); 319 | } 320 | 321 | // class map lookup 322 | if (isset($this->classMap[$class])) { 323 | return $this->classMap[$class]; 324 | } 325 | if ($this->classMapAuthoritative) { 326 | return false; 327 | } 328 | 329 | $file = $this->findFileWithExtension($class, '.php'); 330 | 331 | // Search for Hack files if we are running on HHVM 332 | if ($file === null && defined('HHVM_VERSION')) { 333 | $file = $this->findFileWithExtension($class, '.hh'); 334 | } 335 | 336 | if ($file === null) { 337 | // Remember that this class does not exist. 338 | return $this->classMap[$class] = false; 339 | } 340 | 341 | return $file; 342 | } 343 | 344 | private function findFileWithExtension($class, $ext) 345 | { 346 | // PSR-4 lookup 347 | $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; 348 | 349 | $first = $class[0]; 350 | if (isset($this->prefixLengthsPsr4[$first])) { 351 | foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { 352 | if (0 === strpos($class, $prefix)) { 353 | foreach ($this->prefixDirsPsr4[$prefix] as $dir) { 354 | if (is_file($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { 355 | return $file; 356 | } 357 | } 358 | } 359 | } 360 | } 361 | 362 | // PSR-4 fallback dirs 363 | foreach ($this->fallbackDirsPsr4 as $dir) { 364 | if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { 365 | return $file; 366 | } 367 | } 368 | 369 | // PSR-0 lookup 370 | if (false !== $pos = strrpos($class, '\\')) { 371 | // namespaced class name 372 | $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) 373 | . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); 374 | } else { 375 | // PEAR-like class name 376 | $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; 377 | } 378 | 379 | if (isset($this->prefixesPsr0[$first])) { 380 | foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { 381 | if (0 === strpos($class, $prefix)) { 382 | foreach ($dirs as $dir) { 383 | if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { 384 | return $file; 385 | } 386 | } 387 | } 388 | } 389 | } 390 | 391 | // PSR-0 fallback dirs 392 | foreach ($this->fallbackDirsPsr0 as $dir) { 393 | if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { 394 | return $file; 395 | } 396 | } 397 | 398 | // PSR-0 include paths. 399 | if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { 400 | return $file; 401 | } 402 | } 403 | } 404 | 405 | /** 406 | * Scope isolated include. 407 | * 408 | * Prevents access to $this/self from included files. 409 | */ 410 | function includeFile($file) 411 | { 412 | include $file; 413 | } 414 | -------------------------------------------------------------------------------- /vendor/composer/autoload_classmap.php: -------------------------------------------------------------------------------- 1 | $path) { 28 | $loader->set($namespace, $path); 29 | } 30 | 31 | $map = require __DIR__ . '/autoload_psr4.php'; 32 | foreach ($map as $namespace => $path) { 33 | $loader->setPsr4($namespace, $path); 34 | } 35 | 36 | $classMap = require __DIR__ . '/autoload_classmap.php'; 37 | if ($classMap) { 38 | $loader->addClassMap($classMap); 39 | } 40 | 41 | $loader->register(true); 42 | 43 | $includeFiles = require __DIR__ . '/autoload_files.php'; 44 | foreach ($includeFiles as $file) { 45 | composerRequire0384b0918b581c48636378ad44a7766a($file); 46 | } 47 | 48 | return $loader; 49 | } 50 | } 51 | 52 | function composerRequire0384b0918b581c48636378ad44a7766a($file) 53 | { 54 | require $file; 55 | } 56 | -------------------------------------------------------------------------------- /vendor/composer/installed.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "bcosca/fatfree", 4 | "version": "3.5.0", 5 | "version_normalized": "3.5.0.0", 6 | "source": { 7 | "type": "git", 8 | "url": "https://github.com/bcosca/fatfree.git", 9 | "reference": "9cc485be8db3b2b9d7c1f098db24afd05e5259da" 10 | }, 11 | "dist": { 12 | "type": "zip", 13 | "url": "https://api.github.com/repos/bcosca/fatfree/zipball/9cc485be8db3b2b9d7c1f098db24afd05e5259da", 14 | "reference": "9cc485be8db3b2b9d7c1f098db24afd05e5259da", 15 | "shasum": "" 16 | }, 17 | "require": { 18 | "php": ">=5.3.6" 19 | }, 20 | "time": "2015-06-02 21:34:13", 21 | "type": "library", 22 | "installation-source": "dist", 23 | "autoload": { 24 | "files": [ 25 | "lib/base.php" 26 | ] 27 | }, 28 | "notification-url": "https://packagist.org/downloads/", 29 | "license": [ 30 | "GPL-3.0" 31 | ], 32 | "description": "A powerful yet easy-to-use PHP micro-framework designed to help you build dynamic and robust Web applications - fast!", 33 | "homepage": "http://fatfreeframework.com/" 34 | } 35 | ] 36 | --------------------------------------------------------------------------------