- upgraded FatFreeFramework 3.6.1 -> 3.6.2

This commit is contained in:
Mark Friedrich
2018-01-06 19:51:16 +01:00
parent 6fdb1ed91b
commit ac417fb19f
26 changed files with 842 additions and 580 deletions

View File

@@ -108,7 +108,7 @@ class Audit extends Prefab {
**/
function isdesktop($agent=NULL) {
if (!isset($agent))
$agent=Base::instance()->get('AGENT');
$agent=Base::instance()->AGENT;
return (bool)preg_match('/('.self::UA_Desktop.')/i',$agent) &&
!$this->ismobile($agent);
}
@@ -120,7 +120,7 @@ class Audit extends Prefab {
**/
function ismobile($agent=NULL) {
if (!isset($agent))
$agent=Base::instance()->get('AGENT');
$agent=Base::instance()->AGENT;
return (bool)preg_match('/('.self::UA_Mobile.')/i',$agent);
}
@@ -131,7 +131,7 @@ class Audit extends Prefab {
**/
function isbot($agent=NULL) {
if (!isset($agent))
$agent=Base::instance()->get('AGENT');
$agent=Base::instance()->AGENT;
return (bool)preg_match('/('.self::UA_Bot.')/i',$agent);
}

View File

@@ -115,18 +115,27 @@ class Auth {
* @param $pw string
**/
protected function _ldap($id,$pw) {
$dc=@ldap_connect($this->args['dc']);
$port=(int)($this->args['port']?:389);
$filter=$this->args['filter']=$this->args['filter']?:"uid=".$id;
$this->args['attr']=$this->args['attr']?:["uid"];
array_walk($this->args['attr'],
function($attr)use(&$filter,$id) {
$filter=str_ireplace($attr."=*",$attr."=".$id,$filter);});
$dc=@ldap_connect($this->args['dc'],$port);
if ($dc &&
ldap_set_option($dc,LDAP_OPT_PROTOCOL_VERSION,3) &&
ldap_set_option($dc,LDAP_OPT_REFERRALS,0) &&
ldap_bind($dc,$this->args['rdn'],$this->args['pw']) &&
($result=ldap_search($dc,$this->args['base_dn'],
'uid='.$id)) &&
$filter,$this->args['attr'])) &&
ldap_count_entries($dc,$result) &&
($info=ldap_get_entries($dc,$result)) &&
$info['count']==1 &&
@ldap_bind($dc,$info[0]['dn'],$pw) &&
@ldap_close($dc)) {
return $info[0]['uid'][0]==$id;
return in_array($id,(array_map(function($value){return $value[0];},
array_intersect_key($info[0],
array_flip($this->args['attr'])))),TRUE);
}
user_error(self::E_LDAP,E_USER_ERROR);
}
@@ -160,12 +169,12 @@ class Auth {
stream_set_blocking($socket,TRUE);
$dialog();
$fw=Base::instance();
$dialog('EHLO '.$fw->get('HOST'));
$dialog('EHLO '.$fw->HOST);
if (strtolower($this->args['scheme'])=='tls') {
$dialog('STARTTLS');
stream_socket_enable_crypto(
$socket,TRUE,STREAM_CRYPTO_METHOD_TLS_CLIENT);
$dialog('EHLO '.$fw->get('HOST'));
$dialog('EHLO '.$fw->HOST);
}
// Authenticate
$dialog('AUTH LOGIN');
@@ -196,7 +205,7 @@ class Auth {
**/
function basic($func=NULL) {
$fw=Base::instance();
$realm=$fw->get('REALM');
$realm=$fw->REALM;
$hdr=NULL;
if (isset($_SERVER['HTTP_AUTHORIZATION']))
$hdr=$_SERVER['HTTP_AUTHORIZATION'];

File diff suppressed because it is too large Load Diff

View File

@@ -193,7 +193,7 @@ class Basket extends Magic {
**/
function copyfrom($var) {
if (is_string($var))
$var=\Base::instance()->get($var);
$var=\Base::instance()->$var;
foreach ($var as $key=>$val)
$this->set($key,$val);
}

View File

@@ -143,24 +143,26 @@ abstract class Cursor extends \Magic implements \IteratorAggregate {
* @param $filter string|array
* @param $options array
* @param $ttl int
* @param $bounce bool
**/
function paginate(
$pos=0,$size=10,$filter=NULL,array $options=NULL,$ttl=0) {
$pos=0,$size=10,$filter=NULL,array $options=NULL,$ttl=0,$bounce=TRUE) {
$total=$this->count($filter,$options,$ttl);
$count=ceil($total/$size);
$pos=max(0,min($pos,$count-1));
if ($bounce)
$pos=max(0,min($pos,$count-1));
return [
'subset'=>$this->find($filter,
'subset'=>($bounce || $pos<$count)?$this->find($filter,
array_merge(
$options?:[],
['limit'=>$size,'offset'=>$pos*$size]
),
$ttl
),
):[],
'total'=>$total,
'limit'=>$size,
'count'=>$count,
'pos'=>$pos<$count?$pos:0
'pos'=>$bounce?($pos<$count?$pos:0):$pos
];
}

View File

@@ -80,7 +80,7 @@ class Jig {
$fw=\Base::instance();
switch ($this->format) {
case self::FORMAT_JSON:
$out=json_encode($data,@constant('JSON_PRETTY_PRINT'));
$out=json_encode($data,JSON_PRETTY_PRINT);
break;
case self::FORMAT_Serialized:
$out=$fw->serialize($data);

View File

@@ -120,21 +120,20 @@ class Mapper extends \DB\Cursor {
* @param $str string
**/
function token($str) {
$self=$this;
$str=preg_replace_callback(
'/(?<!\w)@(\w(?:[\w\.\[\]])*)/',
function($token) use($self) {
function($token) {
// Convert from JS dot notation to PHP array notation
return '$'.preg_replace_callback(
'/(\.\w+)|\[((?:[^\[\]]*|(?R))*)\]/',
function($expr) use($self) {
function($expr) {
$fw=\Base::instance();
return
'['.
($expr[1]?
$fw->stringify(substr($expr[1],1)):
(preg_match('/^\w+/',
$mix=$self->token($expr[2]))?
$mix=$this->token($expr[2]))?
$fw->stringify($mix):
$mix)).
']';
@@ -168,7 +167,7 @@ class Mapper extends \DB\Cursor {
$db=$this->db;
$now=microtime(TRUE);
$data=[];
if (!$fw->get('CACHE') || !$ttl || !($cached=$cache->exists(
if (!$fw->CACHE || !$ttl || !($cached=$cache->exists(
$hash=$fw->hash($this->db->dir().
$fw->stringify([$filter,$options])).'.jig',$data)) ||
$cached[0]+$ttl<microtime(TRUE)) {
@@ -259,7 +258,7 @@ class Mapper extends \DB\Cursor {
}
$data=array_slice($data,
$options['offset'],$options['limit']?:NULL,TRUE);
if ($fw->get('CACHE') && $ttl)
if ($fw->CACHE && $ttl)
// Save to cache backend
$cache->set($hash,$data,$ttl);
}
@@ -367,15 +366,16 @@ class Mapper extends \DB\Cursor {
* Delete current record
* @return bool
* @param $filter array
* @param $quick bool
**/
function erase($filter=NULL) {
function erase($filter=NULL,$quick=FALSE) {
$db=$this->db;
$now=microtime(TRUE);
$data=&$db->read($this->file);
$pkey=['_id'=>$this->id];
if ($filter) {
foreach ($this->find($filter,NULL,FALSE) as $mapper)
if (!$mapper->erase())
if (!$mapper->erase(null,$quick))
return FALSE;
return TRUE;
}
@@ -385,7 +385,7 @@ class Mapper extends \DB\Cursor {
}
else
return FALSE;
if (isset($this->trigger['beforeerase']) &&
if (!$quick && isset($this->trigger['beforeerase']) &&
\Base::instance()->call($this->trigger['beforeerase'],
[$this,$pkey])===FALSE)
return FALSE;
@@ -404,7 +404,7 @@ class Mapper extends \DB\Cursor {
$db->jot('('.sprintf('%.1f',1e3*(microtime(TRUE)-$now)).'ms) '.
$this->file.' [erase] '.
($filter?preg_replace($keys,$vals,$filter[0],1):''));
if (isset($this->trigger['aftererase']))
if (!$quick && isset($this->trigger['aftererase']))
\Base::instance()->call($this->trigger['aftererase'],
[$this,$pkey]);
return TRUE;
@@ -428,7 +428,7 @@ class Mapper extends \DB\Cursor {
**/
function copyfrom($var,$func=NULL) {
if (is_string($var))
$var=\Base::instance()->get($var);
$var=\Base::instance()->$var;
if ($func)
$var=call_user_func($func,$var);
foreach ($var as $key=>$val)

View File

@@ -70,10 +70,11 @@ class Session extends Mapper {
$fw=\Base::instance();
if (!isset($this->onsuspect) ||
$fw->call($this->onsuspect,[$this,$id])===FALSE) {
//NB: `session_destroy` can't be called at that stage (`session_start` not completed)
// NB: `session_destroy` can't be called at that stage;
// `session_start` not completed
$this->destroy($id);
$this->close();
$fw->clear('COOKIE.'.session_name());
unset($fw->{'COOKIE.'.session_name()});
$fw->error(403);
}
}
@@ -178,12 +179,12 @@ class Session extends Mapper {
);
register_shutdown_function('session_commit');
$fw=\Base::instance();
$headers=$fw->get('HEADERS');
$this->_csrf=$fw->get('SEED').'.'.$fw->hash(mt_rand());
$headers=$fw->HEADERS;
$this->_csrf=$fw->SEED.'.'.$fw->hash(mt_rand());
if ($key)
$fw->set($key,$this->_csrf);
$fw->$key=$this->_csrf;
$this->_agent=isset($headers['User-Agent'])?$headers['User-Agent']:'';
$this->_ip=$fw->get('IP');
$this->_ip=$fw->IP;
}
}

View File

@@ -146,7 +146,7 @@ class Mapper extends \DB\Cursor {
]
);
$tmp=$this->db->selectcollection(
$fw->get('HOST').'.'.$fw->get('BASE').'.'.
$fw->HOST.'.'.$fw->BASE.'.'.
uniqid(NULL,TRUE).'.tmp'
);
$tmp->batchinsert($grp['retval'],['w'=>1]);
@@ -179,7 +179,7 @@ class Mapper extends \DB\Cursor {
}
if ($options['group'])
$tmp->drop();
if ($fw->get('CACHE') && $ttl)
if ($fw->CACHE && $ttl)
// Save to cache backend
$cache->set($hash,$result,$ttl);
}
@@ -222,7 +222,7 @@ class Mapper extends \DB\Cursor {
[$filter])).'.mongo',$result)) || !$ttl ||
$cached[0]+$ttl<microtime(TRUE)) {
$result=$this->collection->count($filter?:[]);
if ($fw->get('CACHE') && $ttl)
if ($fw->CACHE && $ttl)
// Save to cache backend
$cache->set($hash,$result,$ttl);
}
@@ -292,10 +292,17 @@ class Mapper extends \DB\Cursor {
/**
* Delete current record
* @return bool
* @param $quick bool
* @param $filter array
**/
function erase($filter=NULL) {
function erase($filter=NULL,$quick=TRUE) {
if ($filter) {
if (!$quick) {
foreach ($this->find($filter) as $mapper)
if (!$mapper->erase())
return FALSE;
return TRUE;
}
return $this->legacy?
$this->collection->remove($filter):
$this->collection->deletemany($filter);
@@ -332,7 +339,7 @@ class Mapper extends \DB\Cursor {
**/
function copyfrom($var,$func=NULL) {
if (is_string($var))
$var=\Base::instance()->get($var);
$var=\Base::instance()->$var;
if ($func)
$var=call_user_func($func,$var);
foreach ($var as $key=>$val)

View File

@@ -70,10 +70,11 @@ class Session extends Mapper {
$fw=\Base::instance();
if (!isset($this->onsuspect) ||
$fw->call($this->onsuspect,[$this,$id])===FALSE) {
//NB: `session_destroy` can't be called at that stage (`session_start` not completed)
// NB: `session_destroy` can't be called at that stage;
// `session_start` not completed
$this->destroy($id);
$this->close();
$fw->clear('COOKIE.'.session_name());
unset($fw->{'COOKIE.'.session_name()});
$fw->error(403);
}
}
@@ -178,12 +179,12 @@ class Session extends Mapper {
);
register_shutdown_function('session_commit');
$fw=\Base::instance();
$headers=$fw->get('HEADERS');
$this->_csrf=$fw->get('SEED').'.'.$fw->hash(mt_rand());
$headers=$fw->HEADERS;
$this->_csrf=$fw->SEED.'.'.$fw->hash(mt_rand());
if ($key)
$fw->set($key,$this->_csrf);
$fw->$key=$this->_csrf;
$this->_agent=isset($headers['User-Agent'])?$headers['User-Agent']:'';
$this->_ip=$fw->get('IP');
$this->_ip=$fw->IP;
}
}

View File

@@ -124,7 +124,7 @@ class SQL {
$val=str_replace(',','.',$val);
return $val;
case \PDO::PARAM_NULL:
return (unset)$val;
return NULL;
case \PDO::PARAM_INT:
return (int)$val;
case \PDO::PARAM_BOOL:
@@ -185,7 +185,7 @@ class SQL {
continue;
$now=microtime(TRUE);
$keys=$vals=[];
if ($fw->get('CACHE') && $ttl && ($cached=$cache->exists(
if ($fw->CACHE && $ttl && ($cached=$cache->exists(
$hash=$fw->hash($this->dsn.$cmd.
$fw->stringify($arg)).($tag?'.'.$tag:'').'.sql',$result)) &&
$cached[0]+$ttl>microtime(TRUE)) {
@@ -220,13 +220,15 @@ class SQL {
'/';
}
if ($log)
$this->log.=($stamp?(date('r').' '):'').'('.
sprintf('%.1f',1e3*(microtime(TRUE)-$now)).'ms) '.
$this->log.=($stamp?(date('r').' '):'').' (-0ms) '.
preg_replace($keys,$vals,
str_replace('?',chr(0).'?',$cmd),1).PHP_EOL;
$query->execute();
$error=$query->errorinfo();
if ($error[0]!=\PDO::ERR_NONE) {
if ($log)
$this->log=str_replace('(-0ms)',
'('.sprintf('%.1f',1e3*(microtime(TRUE)-$now)).'ms)',
$this->log);
if (($error=$query->errorinfo()) && $error[0]!=\PDO::ERR_NONE) {
// Statement-level error occurred
if ($this->trans)
$this->rollback();
@@ -246,7 +248,7 @@ class SQL {
$result[$pos][trim($key,'\'"[]`')]=$val;
}
$this->rows=count($result);
if ($fw->get('CACHE') && $ttl)
if ($fw->CACHE && $ttl)
// Save to cache backend
$cache->set($hash,$result,$ttl);
}
@@ -255,15 +257,13 @@ class SQL {
$query->closecursor();
unset($query);
}
else {
$error=$this->errorinfo();
if ($error[0]!=\PDO::ERR_NONE) {
// PDO-level error occurred
if ($this->trans)
$this->rollback();
user_error('PDO: '.$error[2],E_USER_ERROR);
}
elseif (($error=$this->errorinfo()) && $error[0]!=\PDO::ERR_NONE) {
// PDO-level error occurred
if ($this->trans)
$this->rollback();
user_error('PDO: '.$error[2],E_USER_ERROR);
}
}
if ($this->trans && $auto)
$this->commit();
@@ -280,8 +280,8 @@ class SQL {
/**
* Return SQL profiler results (or disable logging)
* @param $flag bool
* @return string
* @param $flag bool
**/
function log($flag=TRUE) {
if ($flag)
@@ -289,6 +289,20 @@ class SQL {
$this->log=FALSE;
}
/**
* Return TRUE if table exists
* @return bool
* @param $table string
**/
function exists($table) {
$mode=$this->pdo->getAttribute(\PDO::ATTR_ERRMODE);
$this->pdo->setAttribute(\PDO::ATTR_ERRMODE,\PDO::ERRMODE_SILENT);
$out=$this->pdo->
query('SELECT 1 FROM '.$this->quotekey($table).' LIMIT 1');
$this->pdo->setAttribute(\PDO::ATTR_ERRMODE,$mode);
return is_object($out);
}
/**
* Retrieve schema of SQL table
* @return array|FALSE
@@ -297,43 +311,50 @@ class SQL {
* @param $ttl int|array
**/
function schema($table,$fields=NULL,$ttl=0) {
$fw=\Base::instance();
$cache=\Cache::instance();
if ($fw->CACHE && $ttl &&
($cached=$cache->exists(
$hash=$fw->hash($this->dsn.$table).'.schema',$result)) &&
$cached[0]+$ttl>microtime(TRUE))
return $result;
if (strpos($table,'.'))
list($schema,$table)=explode('.',$table);
// Supported engines
$cmd=[
'sqlite2?'=>[
'PRAGMA table_info("'.$table.'")',
'PRAGMA table_info(`'.$table.'`)',
'name','type','dflt_value','notnull',0,'pk',TRUE],
'mysql'=>[
'SHOW columns FROM `'.$this->dbname.'`.`'.$table.'`',
'Field','Type','Default','Null','YES','Key','PRI'],
'mssql|sqlsrv|sybase|dblib|pgsql|odbc'=>[
'SELECT '.
'c.column_name AS field,'.
'c.data_type AS type,'.
'c.column_default AS defval,'.
'c.is_nullable AS nullable,'.
't.constraint_type AS pkey '.
'FROM information_schema.columns AS c '.
'C.COLUMN_NAME AS field,'.
'C.DATA_TYPE AS type,'.
'C.COLUMN_DEFAULT AS defval,'.
'C.IS_NULLABLE AS nullable,'.
'T.CONSTRAINT_TYPE AS pkey '.
'FROM INFORMATION_SCHEMA.COLUMNS AS C '.
'LEFT OUTER JOIN '.
'information_schema.key_column_usage AS k '.
'INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS K '.
'ON '.
'c.table_name=k.table_name AND '.
'c.column_name=k.column_name AND '.
'c.table_schema=k.table_schema '.
'C.TABLE_NAME=K.TABLE_NAME AND '.
'C.COLUMN_NAME=K.COLUMN_NAME AND '.
'C.TABLE_SCHEMA=K.TABLE_SCHEMA '.
($this->dbname?
('AND c.table_catalog=k.table_catalog '):'').
('AND C.TABLE_CATALOG=K.TABLE_CATALOG '):'').
'LEFT OUTER JOIN '.
'information_schema.table_constraints AS t ON '.
'k.table_name=t.table_name AND '.
'k.constraint_name=t.constraint_name AND '.
'k.table_schema=t.table_schema '.
'INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS T ON '.
'K.TABLE_NAME=T.TABLE_NAME AND '.
'K.CONSTRAINT_NAME=T.CONSTRAINT_NAME AND '.
'K.TABLE_SCHEMA=T.TABLE_SCHEMA '.
($this->dbname?
('AND k.table_catalog=t.table_catalog '):'').
('AND K.TABLE_CATALOG=T.TABLE_CATALOG '):'').
'WHERE '.
'c.table_name='.$this->quote($table).
'C.TABLE_NAME='.$this->quote($table).
($this->dbname?
(' AND c.table_catalog='.
(' AND C.TABLE_CATALOG='.
$this->quote($this->dbname)):''),
'field','type','defval','nullable','YES','pkey','PRIMARY KEY'],
'oci'=>[
@@ -354,32 +375,34 @@ class SQL {
];
if (is_string($fields))
$fields=\Base::instance()->split($fields);
$conv=[
'int\b|integer'=>\PDO::PARAM_INT,
'bool'=>\PDO::PARAM_BOOL,
'blob|bytea|image|binary'=>\PDO::PARAM_LOB,
'float|real|double|decimal|numeric'=>self::PARAM_FLOAT,
'.+'=>\PDO::PARAM_STR
];
foreach ($cmd as $key=>$val)
if (preg_match('/'.$key.'/',$this->engine)) {
$rows=[];
foreach ($this->exec($val[0],NULL,$ttl) as $row) {
if (!$fields || in_array($row[$val[1]],$fields))
foreach ($this->exec($val[0],NULL) as $row)
if (!$fields || in_array($row[$val[1]],$fields)) {
foreach ($conv as $regex=>$type)
if (preg_match('/'.$regex.'/i',$row[$val[2]]))
break;
$rows[$row[$val[1]]]=[
'type'=>$row[$val[2]],
'pdo_type'=>
preg_match('/int\b|integer/i',$row[$val[2]])?
\PDO::PARAM_INT:
(preg_match('/bool/i',$row[$val[2]])?
\PDO::PARAM_BOOL:
(preg_match(
'/blob|bytea|image|binary/i',
$row[$val[2]])?\PDO::PARAM_LOB:
(preg_match(
'/float|decimal|real|numeric|double/i',
$row[$val[2]])?self::PARAM_FLOAT:
\PDO::PARAM_STR))),
'pdo_type'=>$type,
'default'=>is_string($row[$val[3]])?
preg_replace('/^\s*([\'"])(.*)\1\s*/','\2',
$row[$val[3]]):$row[$val[3]],
'nullable'=>$row[$val[4]]==$val[5],
'pkey'=>$row[$val[6]]==$val[7]
];
}
}
if ($fw->CACHE && $ttl)
// Save to cache backend
$cache->set($hash,$rows,$ttl);
return $rows;
}
user_error(sprintf(self::E_PKey,$table),E_USER_ERROR);
@@ -448,8 +471,8 @@ class SQL {
**/
function quotekey($key, $split=TRUE) {
$delims=[
'mysql'=>'``',
'sqlite2?|pgsql|oci'=>'""',
'sqlite2?|mysql'=>'``',
'pgsql|oci'=>'""',
'mssql|sqlsrv|odbc|sybase|dblib'=>'[]'
];
$use='';
@@ -492,7 +515,7 @@ class SQL {
$options=[];
if (isset($parts[0]) && strstr($parts[0],':',TRUE)=='mysql')
$options+=[\PDO::MYSQL_ATTR_INIT_COMMAND=>'SET NAMES '.
strtolower(str_replace('-','',$fw->get('ENCODING'))).';'];
strtolower(str_replace('-','',$fw->ENCODING)).';'];
$this->pdo=new \PDO($dsn,$user,$pw,$options);
$this->engine=$this->pdo->getattribute(\PDO::ATTR_DRIVER_NAME);
}

View File

@@ -39,7 +39,9 @@ class Mapper extends \DB\Cursor {
//! Defined fields
$fields,
//! Adhoc fields
$adhoc=[];
$adhoc=[],
//! Dynamic properties
$props=[];
/**
* Return database type
@@ -57,15 +59,6 @@ class Mapper extends \DB\Cursor {
return $this->source;
}
/**
* Return TRUE if field is defined
* @return bool
* @param $key string
**/
function exists($key) {
return array_key_exists($key,$this->fields+$this->adhoc);
}
/**
* Return TRUE if any/specified field value has changed
* @return bool
@@ -80,6 +73,15 @@ class Mapper extends \DB\Cursor {
return FALSE;
}
/**
* Return TRUE if field is defined
* @return bool
* @param $key string
**/
function exists($key) {
return array_key_exists($key,$this->fields+$this->adhoc);
}
/**
* Assign value to field
* @return scalar
@@ -95,12 +97,14 @@ class Mapper extends \DB\Cursor {
$this->fields[$key]['changed']=TRUE;
return $this->fields[$key]['value']=$val;
}
// adjust result on existing expressions
// Adjust result on existing expressions
if (isset($this->adhoc[$key]))
$this->adhoc[$key]['value']=$val;
else
elseif (is_string($val))
// Parenthesize expression in case it's a subquery
$this->adhoc[$key]=['expr'=>'('.$val.')','value'=>NULL];
else
$this->props[$key]=$val;
return $val;
}
@@ -116,6 +120,8 @@ class Mapper extends \DB\Cursor {
return $this->fields[$key]['value'];
elseif (array_key_exists($key,$this->adhoc))
return $this->adhoc[$key]['value'];
elseif (array_key_exists($key,$this->props))
return $this->props[$key];
user_error(sprintf(self::E_Field,$key),E_USER_ERROR);
}
@@ -127,26 +133,22 @@ class Mapper extends \DB\Cursor {
function clear($key) {
if (array_key_exists($key,$this->adhoc))
unset($this->adhoc[$key]);
else
unset($this->props[$key]);
}
/**
* Get PHP type equivalent of PDO constant
* @return string
* @param $pdo string
* Invoke dynamic method
* @return mixed
* @param $func string
* @param $args array
**/
function type($pdo) {
switch ($pdo) {
case \PDO::PARAM_NULL:
return 'unset';
case \PDO::PARAM_INT:
return 'int';
case \PDO::PARAM_BOOL:
return 'bool';
case \PDO::PARAM_STR:
return 'string';
case \DB\SQL::PARAM_FLOAT:
return 'float';
}
function __call($func,$args) {
return call_user_func_array(
(array_key_exists($func,$this->props)?
$this->props[$func]:
$this->$func),$args
);
}
/**
@@ -192,14 +194,13 @@ class Mapper extends \DB\Cursor {
}
/**
* Build query string and execute
* @return static[]
* Build query string and arguments
* @return array
* @param $fields string
* @param $filter string|array
* @param $options array
* @param $ttl int|array
**/
function select($fields,$filter=NULL,array $options=NULL,$ttl=0) {
function stringify($fields,$filter=NULL,array $options=NULL) {
if (!$options)
$options=[];
$options+=[
@@ -224,7 +225,7 @@ class Mapper extends \DB\Cursor {
$sql.=' GROUP BY '.implode(',',array_map(
function($str) use($db) {
return preg_replace_callback(
'/\b(\w+)\h*(HAVING.+|$)/i',
'/\b(\w+[._\-\w]*)\h*(HAVING.+|$)/i',
function($parts) use($db) {
return $db->quotekey($parts[1]).
(isset($parts[2])?(' '.$parts[2]):'');
@@ -235,47 +236,63 @@ class Mapper extends \DB\Cursor {
explode(',',$options['group'])));
}
if ($options['order']) {
$sql.=' ORDER BY '.implode(',',array_map(
$order=' ORDER BY '.implode(',',array_map(
function($str) use($db) {
return preg_match('/^(\w+)(?:\h+(ASC|DESC))?\h*(?:,|$)/i',
return preg_match('/^\h*(\w+[._\-\w]*)(?:\h+((?:ASC|DESC)[\w\h]*))?\h*$/i',
$str,$parts)?
($db->quotekey($parts[1]).
(isset($parts[2])?(' '.$parts[2]):'')):$str;
},
explode(',',$options['order'])));
}
// SQL Server fixes
if (preg_match('/mssql|sqlsrv|odbc/', $this->engine) &&
($options['limit'] || $options['offset'])) {
$pkeys=[];
foreach ($this->fields as $key=>$field)
if ($field['pkey'])
$pkeys[]=$key;
// order by pkey when no ordering option was given
if (!$options['order'])
foreach ($this->fields as $key=>$field)
if ($field['pkey']) {
$order=' ORDER BY '.$db->quotekey($key);
break;
}
$ofs=$options['offset']?(int)$options['offset']:0;
$lmt=$options['limit']?(int)$options['limit']:0;
if (strncmp($db->version(),'11',2)>=0) {
// SQL Server 2012
if (!$options['order'])
$sql.=' ORDER BY '.$db->quotekey($pkeys[0]);
$sql.=' OFFSET '.$ofs.' ROWS';
// SQL Server >= 2012
$sql.=$order.' OFFSET '.$ofs.' ROWS';
if ($lmt)
$sql.=' FETCH NEXT '.$lmt.' ROWS ONLY';
}
else {
// SQL Server 2008
$sql=str_replace('SELECT',
$sql=preg_replace('/SELECT/',
'SELECT '.
($lmt>0?'TOP '.($ofs+$lmt):'').' ROW_NUMBER() '.
'OVER (ORDER BY '.
$db->quotekey($pkeys[0]).') AS rnum,',$sql);
'OVER ('.$order.') AS rnum,',$sql.$order,1);
$sql='SELECT * FROM ('.$sql.') x WHERE rnum > '.($ofs);
}
}
else {
if (isset($order))
$sql.=$order;
if ($options['limit'])
$sql.=' LIMIT '.(int)$options['limit'];
if ($options['offset'])
$sql.=' OFFSET '.(int)$options['offset'];
}
return [$sql,$args];
}
/**
* Build query string and execute
* @return object
* @param $fields string
* @param $filter string|array
* @param $options array
* @param $ttl int|array
**/
function select($fields,$filter=NULL,array $options=NULL,$ttl=0) {
list($sql,$args)=$this->stringify($fields,$filter,$options);
$result=$this->db->exec($sql,$args,$ttl);
$out=[];
foreach ($result as &$row) {
@@ -285,8 +302,6 @@ class Mapper extends \DB\Cursor {
$val=$this->db->value(
$this->fields[$field]['pdo_type'],$val);
}
elseif (array_key_exists($field,$this->adhoc))
$this->adhoc[$field]['value']=$val;
unset($val);
}
$out[]=$this->factory($row);
@@ -329,14 +344,17 @@ class Mapper extends \DB\Cursor {
* @param $ttl int|array
**/
function count($filter=NULL,array $options=NULL,$ttl=0) {
$expr='COUNT(*)';
$field='rows';
$this->adhoc[$field]=['expr'=>$expr,'value'=>NULL];
$result=$this->select($expr.' AS '.$this->db->quotekey($field),
$filter,$options,$ttl);
$out=$result[0]->adhoc[$field]['value'];
unset($this->adhoc[$field]);
return $out;
$adhoc='';
foreach ($this->adhoc as $key=>$field)
$adhoc.=','.$field['expr'].' AS '.$this->db->quotekey($key);
$fields='*'.$adhoc;
if (preg_match('/mssql|dblib|sqlsrv/',$this->engine))
$fields='TOP 100 PERCENT '.$fields;
list($sql,$args)=$this->stringify($fields,$filter,$options);
$sql='SELECT COUNT(*) AS '.$this->db->quotekey('_rows').' '.
'FROM ('.$sql.') AS '.$this->db->quotekey('_temp');
$result=$this->db->exec($sql,$args,$ttl);
return (int)$result[0]['_rows'];
}
/**
@@ -404,28 +422,27 @@ class Mapper extends \DB\Cursor {
$actr++;
$ckeys[]=$key;
}
$field['changed']=FALSE;
unset($field);
}
if ($fields) {
$this->db->exec(
$add='';
if ($this->engine=='pgsql') {
$names=array_keys($pkeys);
$aik=end($names);
$add=' RETURNING '.$this->db->quotekey($aik);
}
$lID=$this->db->exec(
(preg_match('/mssql|dblib|sqlsrv/',$this->engine) &&
array_intersect(array_keys($pkeys),$ckeys)?
'SET IDENTITY_INSERT '.$this->table.' ON;':'').
'INSERT INTO '.$this->table.' ('.$fields.') '.
'VALUES ('.$values.')',$args
'VALUES ('.$values.')'.$add,$args
);
$seq=NULL;
if ($this->engine=='pgsql') {
$names=array_keys($pkeys);
$aik=end($names);
if ($this->fields[$aik]['pdo_type']==\PDO::PARAM_INT)
$seq=$this->source.'_'.$aik.'_seq';
}
if ($this->engine!='oci' && !($this->engine=='pgsql' && !$seq))
$this->_id=$this->db->lastinsertid($seq);
if ($this->engine=='pgsql' && $lID)
$this->_id=$lID[0][$aik];
elseif ($this->engine!='oci')
$this->_id=$this->db->lastinsertid();
// Reload to obtain default and auto-increment field values
if ($inc || $filter)
if ($reload=($inc || $filter))
$this->load($inc?
[$inc.'=?',$this->db->value(
$this->fields[$inc]['pdo_type'],$this->_id)]:
@@ -433,6 +450,13 @@ class Mapper extends \DB\Cursor {
if (isset($this->trigger['afterinsert']))
\Base::instance()->call($this->trigger['afterinsert'],
[$this,$pkeys]);
// reset changed flag after calling afterinsert
if (!$reload)
foreach ($this->fields as $key=>&$field) {
$field['changed']=FALSE;
$field['initial']=$field['value'];
unset($field);
}
}
return $this;
}
@@ -484,10 +508,17 @@ class Mapper extends \DB\Cursor {
/**
* Delete current record
* @return int
* @param $quick bool
* @param $filter string|array
**/
function erase($filter=NULL) {
function erase($filter=NULL,$quick=TRUE) {
if (isset($filter)) {
if (!$quick) {
$out=0;
foreach ($this->find($filter) as $mapper)
$out+=$mapper->erase();
return $out;
}
$args=[];
if (is_array($filter)) {
$args=isset($filter[1]) && is_array($filter[1])?
@@ -497,7 +528,8 @@ class Mapper extends \DB\Cursor {
list($filter)=$filter;
}
return $this->db->
exec('DELETE FROM '.$this->table.($filter?' WHERE '.$filter:'').';',$args);
exec('DELETE FROM '.$this->table.
($filter?' WHERE '.$filter:'').';',$args);
}
$args=[];
$ctr=0;
@@ -561,7 +593,7 @@ class Mapper extends \DB\Cursor {
**/
function copyfrom($var,$func=NULL) {
if (is_string($var))
$var=\Base::instance()->get($var);
$var=\Base::instance()->$var;
if ($func)
$var=call_user_func($func,$var);
foreach ($var as $key=>$val)

View File

@@ -73,7 +73,7 @@ class Session extends Mapper {
//NB: `session_destroy` can't be called at that stage (`session_start` not completed)
$this->destroy($id);
$this->close();
$fw->clear('COOKIE.'.session_name());
unset($fw->{'COOKIE.'.session_name()});
$fw->error(403);
}
}
@@ -170,8 +170,9 @@ class Session extends Mapper {
if ($force) {
$eol="\n";
$tab="\t";
$sqlsrv=preg_match('/mssql|sqlsrv|sybase/',$db->driver());
$db->exec(
(preg_match('/mssql|sqlsrv|sybase/',$db->driver())?
($sqlsrv?
('IF NOT EXISTS (SELECT * FROM sysobjects WHERE '.
'name='.$db->quote($table).' AND xtype=\'U\') '.
'CREATE TABLE dbo.'):
@@ -179,12 +180,14 @@ class Session extends Mapper {
((($name=$db->name())&&$db->driver()!='pgsql')?
($db->quotekey($name,FALSE).'.'):''))).
$db->quotekey($table,FALSE).' ('.$eol.
($sqlsrv?$tab.$db->quotekey('id').' INT IDENTITY,'.$eol:'').
$tab.$db->quotekey('session_id').' VARCHAR(255),'.$eol.
$tab.$db->quotekey('data').' TEXT,'.$eol.
$tab.$db->quotekey('ip').' VARCHAR(45),'.$eol.
$tab.$db->quotekey('agent').' VARCHAR(300),'.$eol.
$tab.$db->quotekey('stamp').' INTEGER,'.$eol.
$tab.'PRIMARY KEY ('.$db->quotekey('session_id').')'.$eol.
$tab.'PRIMARY KEY ('.$db->quotekey($sqlsrv?'id':'session_id').')'.$eol.
($sqlsrv?',CONSTRAINT [UK_session_id] UNIQUE(session_id)':'').
');'
);
}
@@ -200,12 +203,15 @@ class Session extends Mapper {
);
register_shutdown_function('session_commit');
$fw=\Base::instance();
$headers=$fw->get('HEADERS');
$this->_csrf=$fw->get('SEED').'.'.$fw->hash(mt_rand());
$headers=$fw->HEADERS;
$this->_csrf=$fw->SEED.'.'.$fw->hash(mt_rand());
if ($key)
$fw->set($key,$this->_csrf);
$fw->$key=$this->_csrf;
$this->_agent=isset($headers['User-Agent'])?$headers['User-Agent']:'';
$this->_ip=$fw->get('IP');
if (strlen($this->_agent) > 300) {
$this->_agent = substr($this->_agent, 0, 300);
}
$this->_ip=$fw->IP;
}
}

View File

@@ -409,7 +409,7 @@ class Image {
return FALSE;
}
$fw=Base::instance();
foreach ($fw->split($path?:$fw->get('UI').';./') as $dir)
foreach ($fw->split($path?:$fw->UI.';./') as $dir)
if (is_file($path=$dir.$font)) {
$seed=strtoupper(substr(
$ssl?bin2hex(openssl_random_pseudo_bytes($len)):uniqid(),
@@ -448,7 +448,7 @@ class Image {
}
imagesavealpha($this->data,TRUE);
if ($key)
$fw->set($key,$seed);
$fw->$key=$seed;
return $this->save();
}
user_error(self::E_Font,E_USER_ERROR);
@@ -480,7 +480,7 @@ class Image {
$format=$args?array_shift($args):'png';
if (PHP_SAPI!='cli') {
header('Content-Type: image/'.$format);
header('X-Powered-By: '.Base::instance()->get('PACKAGE'));
header('X-Powered-By: '.Base::instance()->PACKAGE);
}
call_user_func_array(
'image'.$format,
@@ -518,10 +518,10 @@ class Image {
function save() {
$fw=Base::instance();
if ($this->flag) {
if (!is_dir($dir=$fw->get('TEMP')))
if (!is_dir($dir=$fw->TEMP))
mkdir($dir,Base::MODE,TRUE);
$this->count++;
$fw->write($dir.'/'.$fw->get('SEED').'.'.
$fw->write($dir.'/'.$fw->SEED.'.'.
$fw->hash($this->file).'-'.$this->count.'.png',
$this->dump());
}
@@ -535,8 +535,8 @@ class Image {
**/
function restore($state=1) {
$fw=Base::instance();
if ($this->flag && is_file($file=($path=$fw->get('TEMP').
$fw->get('SEED').'.'.$fw->hash($this->file).'-').$state.'.png')) {
if ($this->flag && is_file($file=($path=$fw->TEMP.
$fw->SEED.'.'.$fw->hash($this->file).'-').$state.'.png')) {
if (is_resource($this->data))
imagedestroy($this->data);
$this->data=imagecreatefromstring($fw->read($file));
@@ -589,7 +589,7 @@ class Image {
// Create image from file
$this->file=$file;
if (!isset($path))
$path=$fw->get('UI').';./';
$path=$fw->UI.';./';
foreach ($fw->split($path,FALSE) as $dir)
if (is_file($dir.$file))
return $this->load($fw->read($dir.$file));
@@ -605,7 +605,7 @@ class Image {
if (is_resource($this->data)) {
imagedestroy($this->data);
$fw=Base::instance();
$path=$fw->get('TEMP').$fw->get('SEED').'.'.$fw->hash($this->file);
$path=$fw->TEMP.$fw->SEED.'.'.$fw->hash($this->file);
if ($glob=@glob($path.'*.png',GLOB_NOSORT))
foreach ($glob as $match)
if (preg_match('/-(\d+)\.png/',$match))

View File

@@ -59,7 +59,7 @@ class Log {
**/
function __construct($file) {
$fw=Base::instance();
if (!is_dir($dir=$fw->get('LOGS')))
if (!is_dir($dir=$fw->LOGS))
mkdir($dir,Base::MODE,TRUE);
$this->file=$dir.$file;
}

View File

@@ -64,7 +64,7 @@ class Markdown extends Prefab {
protected function _fence($hint,$str) {
$str=$this->snip($str);
$fw=Base::instance();
if ($fw->get('HIGHLIGHT')) {
if ($fw->HIGHLIGHT) {
switch (strtolower($hint)) {
case 'php':
$str=$fw->highlight($str);
@@ -288,20 +288,19 @@ class Markdown extends Prefab {
if (strlen($str)) {
if (preg_match('/^(.+?\n)([>#].+)$/s',$str,$parts))
return $this->_p($parts[1]).$this->build($parts[2]);
$self=$this;
$str=preg_replace_callback(
'/([^<>\[]+)?(<[\?%].+?[\?%]>|<.+?>|\[.+?\]\s*\(.+?\))|'.
'(.+)/s',
function($expr) use($self) {
function($expr) {
$tmp='';
if (isset($expr[4]))
$tmp.=$self->esc($expr[4]);
$tmp.=$this->esc($expr[4]);
else {
if (isset($expr[1]))
$tmp.=$self->esc($expr[1]);
$tmp.=$this->esc($expr[1]);
$tmp.=$expr[2];
if (isset($expr[3]))
$tmp.=$self->esc($expr[3]);
$tmp.=$this->esc($expr[3]);
}
return $tmp;
},
@@ -347,17 +346,16 @@ class Markdown extends Prefab {
* @param $str string
**/
protected function _img($str) {
$self=$this;
return preg_replace_callback(
'/!(?:\[(.+?)\])?\h*\(<?(.*?)>?(?:\h*"(.*?)"\h*)?\)/',
function($expr) use($self) {
function($expr) {
return '<img src="'.$expr[2].'"'.
(empty($expr[1])?
'':
(' alt="'.$self->esc($expr[1]).'"')).
(' alt="'.$this->esc($expr[1]).'"')).
(empty($expr[3])?
'':
(' title="'.$self->esc($expr[3]).'"')).' />';
(' title="'.$this->esc($expr[3]).'"')).' />';
},
$str
);
@@ -369,15 +367,14 @@ class Markdown extends Prefab {
* @param $str string
**/
protected function _a($str) {
$self=$this;
return preg_replace_callback(
'/(?<!\\\\)\[(.+?)(?!\\\\)\]\h*\(<?(.*?)>?(?:\h*"(.*?)"\h*)?\)/',
function($expr) use($self) {
return '<a href="'.$self->esc($expr[2]).'"'.
function($expr) {
return '<a href="'.$this->esc($expr[2]).'"'.
(empty($expr[3])?
'':
(' title="'.$self->esc($expr[3]).'"')).
'>'.$self->scan($expr[1]).'</a>';
(' title="'.$this->esc($expr[3]).'"')).
'>'.$this->scan($expr[1]).'</a>';
},
$str
);
@@ -389,12 +386,11 @@ class Markdown extends Prefab {
* @param $str string
**/
protected function _auto($str) {
$self=$this;
return preg_replace_callback(
'/`.*?<(.+?)>.*?`|<(.+?)>/',
function($expr) use($self) {
function($expr) {
if (empty($expr[1]) && parse_url($expr[2],PHP_URL_SCHEME)) {
$expr[2]=$self->esc($expr[2]);
$expr[2]=$this->esc($expr[2]);
return '<a href="'.$expr[2].'">'.$expr[2].'</a>';
}
return $expr[0];
@@ -409,12 +405,11 @@ class Markdown extends Prefab {
* @param $str string
**/
protected function _code($str) {
$self=$this;
return preg_replace_callback(
'/`` (.+?) ``|(?<!\\\\)`(.+?)(?!\\\\)`/',
function($expr) use($self) {
function($expr) {
return '<code>'.
$self->esc(empty($expr[1])?$expr[2]:$expr[1]).'</code>';
$this->esc(empty($expr[1])?$expr[2]:$expr[1]).'</code>';
},
$str
);
@@ -436,7 +431,7 @@ class Markdown extends Prefab {
foreach ($this->special as $key=>$val)
$str=preg_replace('/'.preg_quote($key,'/').'/i',$val,$str);
return htmlspecialchars($str,ENT_COMPAT,
Base::instance()->get('ENCODING'),FALSE);
Base::instance()->ENCODING,FALSE);
}
/**
@@ -488,7 +483,6 @@ class Markdown extends Prefab {
'p'=>'/^(.+?(?:\n{2,}|\n*$))/s'
];
}
$self=$this;
// Treat lines with nothing but whitespaces as empty lines
$str=preg_replace('/\n\h+(?=\n)/',"\n",$str);
// Initialize block parser
@@ -509,16 +503,16 @@ class Markdown extends Prefab {
'/(?<!\\\\)\[('.$ref.')(?!\\\\)\]\s*\[\]|'.
'(!?)(?:\[([^\[\]]+)\]\s*)?'.
'(?<!\\\\)\[('.$ref.')(?!\\\\)\]/',
function($expr) use($match,$self) {
function($expr) use($match) {
return (empty($expr[2]))?
// Anchor
('<a href="'.$self->esc($match[2]).'"'.
('<a href="'.$this->esc($match[2]).'"'.
(empty($match[3])?
'':
(' title="'.
$self->esc($match[3]).'"')).'>'.
$this->esc($match[3]).'"')).'>'.
// Link
$self->scan(
$this->scan(
empty($expr[3])?
(empty($expr[1])?
$expr[4]:
@@ -530,11 +524,11 @@ class Markdown extends Prefab {
(empty($expr[2])?
'':
(' alt="'.
$self->esc($expr[3]).'"')).
$this->esc($expr[3]).'"')).
(empty($match[3])?
'':
(' title="'.
$self->esc($match[3]).'"')).
$this->esc($match[3]).'"')).
' />');
},
$tmp=$dst

View File

@@ -72,7 +72,7 @@ class Session {
//NB: `session_destroy` can't be called at that stage (`session_start` not completed)
$this->destroy($id);
$this->close();
$fw->clear('COOKIE.'.session_name());
unset($fw->{'COOKIE.'.session_name()});
$fw->error(403);
}
}
@@ -87,7 +87,7 @@ class Session {
**/
function write($id,$data) {
$fw=Base::instance();
$jar=$fw->get('JAR');
$jar=$fw->JAR;
$this->_cache->set($id.'.@',
[
'data'=>$data,
@@ -95,7 +95,7 @@ class Session {
'agent'=>$this->_agent,
'stamp'=>time()
],
$jar['expire']?($jar['expire']-time()):0
$jar['expire']
);
return TRUE;
}
@@ -181,12 +181,12 @@ class Session {
);
register_shutdown_function('session_commit');
$fw=\Base::instance();
$headers=$fw->get('HEADERS');
$this->_csrf=$fw->get('SEED').'.'.$fw->hash(mt_rand());
$headers=$fw->HEADERS;
$this->_csrf=$fw->SEED.'.'.$fw->hash(mt_rand());
if ($key)
$fw->set($key,$this->_csrf);
$fw->$key=$this->_csrf;
$this->_agent=isset($headers['User-Agent'])?$headers['User-Agent']:'';
$this->_ip=$fw->get('IP');
$this->_ip=$fw->IP;
}
}

View File

@@ -171,7 +171,7 @@ class SMTP extends Magic {
if (!is_file($file))
user_error(sprintf(self::E_Attach,$file),E_USER_ERROR);
if ($alias)
$file=[$alias=>$file];
$file=[$alias,$file];
$this->attachments[]=['filename'=>$file,'cid'=>$cid];
}
@@ -206,14 +206,15 @@ class SMTP extends Magic {
// Get server's initial response
$this->dialog(NULL,TRUE,$mock);
// Announce presence
$reply=$this->dialog('EHLO '.$fw->get('HOST'),$log,$mock);
$reply=$this->dialog('EHLO '.$fw->HOST,$log,$mock);
if (strtolower($this->scheme)=='tls') {
$this->dialog('STARTTLS',$log,$mock);
if (!$mock)
stream_socket_enable_crypto(
$socket,TRUE,STREAM_CRYPTO_METHOD_TLS_CLIENT);
$reply=$this->dialog('EHLO '.$fw->get('HOST'),$log,$mock);
$reply=$this->dialog('EHLO '.$fw->HOST,$log,$mock);
}
$message=wordwrap($message,998);
if (preg_match('/8BITMIME/',$reply))
$headers['Content-Transfer-Encoding']='8bit';
else {
@@ -243,14 +244,8 @@ class SMTP extends Magic {
if (empty($headers[$id]))
user_error(sprintf(self::E_Header,$id),E_USER_ERROR);
$eol="\r\n";
$str='';
// Stringify headers
foreach ($headers as $key=>&$val) {
if (!in_array($key,$reqd) &&
(!$this->attachments ||
$key!='Content-Type' &&
$key!='Content-Transfer-Encoding'))
$str.=$key.': '.$val.$eol;
if (in_array($key,['From','To','Cc','Bcc'])) {
$email='';
preg_match_all('/(?:".+?" )?(?:<.+?>|[^ ,]+)/',
@@ -290,11 +285,11 @@ class SMTP extends Magic {
$out.='--'.$hash.$eol;
$out.='Content-Type: '.$type.$eol;
$out.='Content-Transfer-Encoding: '.$enc.$eol;
$out.=$str.$eol;
$out.=$eol;
$out.=$message.$eol;
foreach ($this->attachments as $attachment) {
if (is_array($attachment['filename']))
list($alias,$file)=each($attachment['filename']);
list($alias,$file)=$attachment['filename'];
else
$alias=basename($file=$attachment['filename']);
$out.='--'.$hash.$eol;
@@ -338,20 +333,21 @@ class SMTP extends Magic {
* @param $scheme string
* @param $user string
* @param $pw string
* @param $ctx resource
**/
function __construct(
$host='localhost',$port=25,$scheme=NULL,$user=NULL,$pw=NULL,$ctx=NULL) {
$this->headers=[
'MIME-Version'=>'1.0',
'Content-Type'=>'text/plain; '.
'charset='.Base::instance()->get('ENCODING')
'charset='.Base::instance()->ENCODING
];
$this->host=(strtolower($this->scheme=strtolower($scheme))=='ssl'?
'ssl':'tcp').'://'.$host;
$this->host=strtolower((($this->scheme=strtolower($scheme))=='ssl'?
'ssl':'tcp').'://'.$host);
$this->port=$port;
$this->user=$user;
$this->pw=$pw;
$this->context=$ctx;
$this->context=stream_context_create($ctx);
}
}

View File

@@ -65,8 +65,8 @@ class Template extends Preview {
return '\''.$pair[1].'\'=>'.
(preg_match('/^\'.*\'$/',$pair[2]) ||
preg_match('/\$/',$pair[2])?
$pair[2]:
\Base::instance()->stringify($pair[2]));
$pair[2]:Base::instance()->stringify(
Base::instance()->cast($pair[2])));
},$pairs)).']+get_defined_vars()'):
'get_defined_vars()';
$ttl=isset($attrib['ttl'])?(int)$attrib['ttl']:0;
@@ -77,7 +77,7 @@ class Template extends Preview {
(preg_match('/^\{\{(.+?)\}\}$/',$attrib['href'])?
$this->token($attrib['href']):
Base::instance()->stringify($attrib['href'])).','.
'$this->mime,'.$hive.','.$ttl.'); ?>');
'NULL,'.$hive.','.$ttl.'); ?>');
}
/**
@@ -252,7 +252,7 @@ class Template extends Preview {
/**
* Call custom tag handler
* @return string|FALSE
* @param $func callback
* @param $func string
* @param $args array
**/
function __call($func,array $args) {
@@ -265,10 +265,11 @@ class Template extends Preview {
/**
* Parse string for template directives and tokens
* @return string|array
* @return array
* @param $text string
**/
function parse($text) {
$text=parent::parse($text);
// Build tree structure
for ($ptr=0,$w=5,$len=strlen($text),$tree=[],$tmp='';$ptr<$len;)
if (preg_match('/^(.{0,'.$w.'}?)<(\/?)(?:F3:)?'.
@@ -276,21 +277,23 @@ class Template extends Preview {
'(?:\h*=\h*(?:"(?:.*?)"|\'(?:.*?)\'))?|'.
'\h*\{\{.+?\}\})*)\h*(\/?)>/is',
substr($text,$ptr),$match)) {
if (strlen($tmp)||$match[1])
if (strlen($tmp) || $match[1])
$tree[]=$tmp.$match[1];
// Element node
if ($match[2]) {
// Find matching start tag
$stack=[];
for($i=count($tree)-1;$i>=0;$i--) {
$item = $tree[$i];
if (is_array($item) && array_key_exists($match[3],$item)
&& !isset($item[$match[3]][0])) {
$item=$tree[$i];
if (is_array($item) &&
array_key_exists($match[3],$item) &&
!isset($item[$match[3]][0])) {
// Start tag found
$tree[$i][$match[3]]+=array_reverse($stack);
$tree=array_slice($tree,0,$i+1);
break;
} else $stack[]=$item;
}
else $stack[]=$item;
}
}
else {

View File

@@ -191,7 +191,7 @@ class UTF extends Prefab {
':,'=>'\u1f60f', // think
':/'=>'\u1f623', // skeptic
'8O'=>'\u1f632', // oops
]+Base::instance()->get('EMOJI');
]+Base::instance()->EMOJI;
return $this->translate(str_replace(array_keys($map),
array_values($map),$str));
}

View File

@@ -138,7 +138,7 @@ class Web extends Prefab {
'filename="'.($name!==NULL?$name:basename($file)).'"');
header('Accept-Ranges: bytes');
header('Content-Length: '.$size);
header('X-Powered-By: '.Base::instance()->get('PACKAGE'));
header('X-Powered-By: '.Base::instance()->PACKAGE);
}
if (!$kbps && $flush) {
while (ob_get_level())
@@ -179,13 +179,13 @@ class Web extends Prefab {
**/
function receive($func=NULL,$overwrite=FALSE,$slug=TRUE) {
$fw=Base::instance();
$dir=$fw->get('UPLOADS');
$dir=$fw->UPLOADS;
if (!is_dir($dir))
mkdir($dir,Base::MODE,TRUE);
if ($fw->get('VERB')=='PUT') {
$tmp=$fw->get('TEMP').$fw->get('SEED').'.'.$fw->hash(uniqid());
if (!$fw->get('RAW'))
$fw->write($tmp,$fw->get('BODY'));
if ($fw->VERB=='PUT') {
$tmp=$fw->TEMP.$fw->SEED.'.'.$fw->hash(uniqid());
if (!$fw->RAW)
$fw->write($tmp,$fw->BODY);
else {
$src=@fopen('php://input','r');
$dst=@fopen($tmp,'w');
@@ -198,7 +198,7 @@ class Web extends Prefab {
fclose($dst);
fclose($src);
}
$base=basename($fw->get('URI'));
$base=basename($fw->URI);
$file=[
'name'=>$dir.
($slug && preg_match('/(.+?)(\.\w+)?$/',$base,$parts)?
@@ -305,6 +305,7 @@ class Web extends Prefab {
$body=ob_get_clean();
if (!$err &&
$options['follow_location'] &&
preg_grep('/HTTP\/1\.\d 3\d{2}/',$headers) &&
preg_match('/^Location: (.+)$/m',implode(PHP_EOL,$headers),$loc)) {
$options['max_redirects']--;
if($loc[1][0] == '/') {
@@ -424,6 +425,7 @@ class Web extends Prefab {
break;
}
if ($options['follow_location'] &&
preg_grep('/HTTP\/1\.\d 3\d{2}/',$headers) &&
preg_match('/Location: (.+?)'.preg_quote($eol).'/',
$html[0],$loc)) {
$options['max_redirects']--;
@@ -489,9 +491,9 @@ class Web extends Prefab {
$parts=parse_url($url);
if (empty($parts['scheme'])) {
// Local URL
$url=$fw->get('SCHEME').'://'.
$fw->get('HOST').
($url[0]!='/'?($fw->get('BASE').'/'):'').$url;
$url=$fw->SCHEME.'://'.$fw->HOST.
(in_array($fw->PORT,[80,443])?'':(':'.$fw->PORT)).
($url[0]!='/'?($fw->BASE.'/'):'').$url;
$parts=parse_url($url);
}
elseif (!preg_match('/https?/',$parts['scheme']))
@@ -544,7 +546,7 @@ class Web extends Prefab {
'ignore_errors'=>FALSE
];
$eol="\r\n";
if ($fw->get('CACHE') &&
if ($fw->CACHE &&
preg_match('/GET|HEAD/',$options['method'])) {
$cache=Cache::instance();
if ($cache->exists(
@@ -591,13 +593,13 @@ class Web extends Prefab {
$cache=Cache::instance();
$dst='';
if (!isset($path))
$path=$fw->get('UI').';./';
$path=$fw->UI.';./';
foreach ($fw->split($path,FALSE) as $dir)
foreach ($files as $file)
if (is_file($save=$fw->fixslashes($dir.$file)) &&
is_bool(strpos($save,'../')) &&
preg_match('/\.(css|js)$/i',$file)) {
if ($fw->get('CACHE') &&
if ($fw->CACHE &&
($cached=$cache->exists(
$hash=$fw->hash($save).'.'.$ext[0],$data)) &&
$cached[0]>filemtime($save))
@@ -692,7 +694,9 @@ class Web extends Prefab {
preg_match('/[\w'.($ext[0]=='css'?
'#\.%+\-*()\[\]':'\$').']{2}|'.
'[+\-]{2}/',
substr($data,-1).$src[$ptr+1]))
substr($data,-1).$src[$ptr+1]) ||
($ext[0]=='css' && $ptr+2<strlen($src) &&
preg_match('/:\w/',substr($src,$ptr+1,2))))
$data.=' ';
$ptr++;
continue;
@@ -700,13 +704,15 @@ class Web extends Prefab {
$data.=$src[$ptr];
$ptr++;
}
if ($fw->get('CACHE'))
if ($ext[0]=='css')
$data=str_replace(';}','}',$data);
if ($fw->CACHE)
$cache->set($hash,$data);
$dst.=$data;
}
}
if (PHP_SAPI!='cli' && $header)
header('Content-Type: '.$mime.'; charset='.$fw->get('ENCODING'));
header('Content-Type: '.$mime.'; charset='.$fw->ENCODING);
return $dst;
}
@@ -773,6 +779,63 @@ class Web extends Prefab {
return $info['timed_out']?FALSE:trim($response);
}
/**
* Return preset diacritics translation table
* @return array
**/
function diacritics() {
return [
'Ǎ'=>'A','А'=>'A','Ā'=>'A','Ă'=>'A','Ą'=>'A','Å'=>'A',
'Ǻ'=>'A','Ä'=>'Ae','Á'=>'A','À'=>'A','Ã'=>'A','Â'=>'A',
'Æ'=>'AE','Ǽ'=>'AE','Б'=>'B','Ç'=>'C','Ć'=>'C','Ĉ'=>'C',
'Č'=>'C','Ċ'=>'C','Ц'=>'C','Ч'=>'Ch','Ð'=>'Dj','Đ'=>'Dj',
'Ď'=>'Dj','Д'=>'Dj','É'=>'E','Ę'=>'E','Ё'=>'E','Ė'=>'E',
'Ê'=>'E','Ě'=>'E','Ē'=>'E','È'=>'E','Е'=>'E','Э'=>'E',
'Ë'=>'E','Ĕ'=>'E','Ф'=>'F','Г'=>'G','Ģ'=>'G','Ġ'=>'G',
'Ĝ'=>'G','Ğ'=>'G','Х'=>'H','Ĥ'=>'H','Ħ'=>'H','Ï'=>'I',
'Ĭ'=>'I','İ'=>'I','Į'=>'I','Ī'=>'I','Í'=>'I','Ì'=>'I',
'И'=>'I','Ǐ'=>'I','Ĩ'=>'I','Î'=>'I','IJ'=>'IJ','Ĵ'=>'J',
'Й'=>'J','Я'=>'Ja','Ю'=>'Ju','К'=>'K','Ķ'=>'K','Ĺ'=>'L',
'Л'=>'L','Ł'=>'L','Ŀ'=>'L','Ļ'=>'L','Ľ'=>'L','М'=>'M',
'Н'=>'N','Ń'=>'N','Ñ'=>'N','Ņ'=>'N','Ň'=>'N','Ō'=>'O',
'О'=>'O','Ǿ'=>'O','Ǒ'=>'O','Ơ'=>'O','Ŏ'=>'O','Ő'=>'O',
'Ø'=>'O','Ö'=>'Oe','Õ'=>'O','Ó'=>'O','Ò'=>'O','Ô'=>'O',
'Œ'=>'OE','П'=>'P','Ŗ'=>'R','Р'=>'R','Ř'=>'R','Ŕ'=>'R',
'Ŝ'=>'S','Ş'=>'S','Š'=>'S','Ș'=>'S','Ś'=>'S','С'=>'S',
'Ш'=>'Sh','Щ'=>'Shch','Ť'=>'T','Ŧ'=>'T','Ţ'=>'T','Ț'=>'T',
'Т'=>'T','Ů'=>'U','Ű'=>'U','Ŭ'=>'U','Ũ'=>'U','Ų'=>'U',
'Ū'=>'U','Ǜ'=>'U','Ǚ'=>'U','Ù'=>'U','Ú'=>'U','Ü'=>'Ue',
'Ǘ'=>'U','Ǖ'=>'U','У'=>'U','Ư'=>'U','Ǔ'=>'U','Û'=>'U',
'В'=>'V','Ŵ'=>'W','Ы'=>'Y','Ŷ'=>'Y','Ý'=>'Y','Ÿ'=>'Y',
'Ź'=>'Z','З'=>'Z','Ż'=>'Z','Ž'=>'Z','Ж'=>'Zh','á'=>'a',
'ă'=>'a','â'=>'a','à'=>'a','ā'=>'a','ǻ'=>'a','å'=>'a',
'ä'=>'ae','ą'=>'a','ǎ'=>'a','ã'=>'a','а'=>'a','ª'=>'a',
'æ'=>'ae','ǽ'=>'ae','б'=>'b','č'=>'c','ç'=>'c','ц'=>'c',
'ċ'=>'c','ĉ'=>'c','ć'=>'c','ч'=>'ch','ð'=>'dj','ď'=>'dj',
'д'=>'dj','đ'=>'dj','э'=>'e','é'=>'e','ё'=>'e','ë'=>'e',
'ê'=>'e','е'=>'e','ĕ'=>'e','è'=>'e','ę'=>'e','ě'=>'e',
'ė'=>'e','ē'=>'e','ƒ'=>'f','ф'=>'f','ġ'=>'g','ĝ'=>'g',
'ğ'=>'g','г'=>'g','ģ'=>'g','х'=>'h','ĥ'=>'h','ħ'=>'h',
'ǐ'=>'i','ĭ'=>'i','и'=>'i','ī'=>'i','ĩ'=>'i','į'=>'i',
'ı'=>'i','ì'=>'i','î'=>'i','í'=>'i','ï'=>'i','ij'=>'ij',
'ĵ'=>'j','й'=>'j','я'=>'ja','ю'=>'ju','ķ'=>'k','к'=>'k',
'ľ'=>'l','ł'=>'l','ŀ'=>'l','ĺ'=>'l','ļ'=>'l','л'=>'l',
'м'=>'m','ņ'=>'n','ñ'=>'n','ń'=>'n','н'=>'n','ň'=>'n',
'ʼn'=>'n','ó'=>'o','ò'=>'o','ǒ'=>'o','ő'=>'o','о'=>'o',
'ō'=>'o','º'=>'o','ơ'=>'o','ŏ'=>'o','ô'=>'o','ö'=>'oe',
'õ'=>'o','ø'=>'o','ǿ'=>'o','œ'=>'oe','п'=>'p','р'=>'r',
'ř'=>'r','ŕ'=>'r','ŗ'=>'r','ſ'=>'s','ŝ'=>'s','ș'=>'s',
'š'=>'s','ś'=>'s','с'=>'s','ş'=>'s','ш'=>'sh','щ'=>'shch',
'ß'=>'ss','ţ'=>'t','т'=>'t','ŧ'=>'t','ť'=>'t','ț'=>'t',
'у'=>'u','ǘ'=>'u','ŭ'=>'u','û'=>'u','ú'=>'u','ų'=>'u',
'ù'=>'u','ű'=>'u','ů'=>'u','ư'=>'u','ū'=>'u','ǚ'=>'u',
'ǜ'=>'u','ǔ'=>'u','ǖ'=>'u','ũ'=>'u','ü'=>'ue','в'=>'v',
'ŵ'=>'w','ы'=>'y','ÿ'=>'y','ý'=>'y','ŷ'=>'y','ź'=>'z',
'ž'=>'z','з'=>'z','ż'=>'z','ж'=>'zh','ь'=>'','ъ'=>'',
'\''=>'',
];
}
/**
* Return a URL/filesystem-friendly version of string
* @return string
@@ -780,56 +843,7 @@ class Web extends Prefab {
**/
function slug($text) {
return trim(strtolower(preg_replace('/([^\pL\pN])+/u','-',
trim(strtr(str_replace('\'','',$text),
[
'Ǎ'=>'A','А'=>'A','Ā'=>'A','Ă'=>'A','Ą'=>'A','Å'=>'A',
'Ǻ'=>'A','Ä'=>'Ae','Á'=>'A','À'=>'A','Ã'=>'A','Â'=>'A',
'Æ'=>'AE','Ǽ'=>'AE','Б'=>'B','Ç'=>'C','Ć'=>'C','Ĉ'=>'C',
'Č'=>'C','Ċ'=>'C','Ц'=>'C','Ч'=>'Ch','Ð'=>'Dj','Đ'=>'Dj',
'Ď'=>'Dj','Д'=>'Dj','É'=>'E','Ę'=>'E','Ё'=>'E','Ė'=>'E',
'Ê'=>'E','Ě'=>'E','Ē'=>'E','È'=>'E','Е'=>'E','Э'=>'E',
'Ë'=>'E','Ĕ'=>'E','Ф'=>'F','Г'=>'G','Ģ'=>'G','Ġ'=>'G',
'Ĝ'=>'G','Ğ'=>'G','Х'=>'H','Ĥ'=>'H','Ħ'=>'H','Ï'=>'I',
'Ĭ'=>'I','İ'=>'I','Į'=>'I','Ī'=>'I','Í'=>'I','Ì'=>'I',
'И'=>'I','Ǐ'=>'I','Ĩ'=>'I','Î'=>'I','IJ'=>'IJ','Ĵ'=>'J',
'Й'=>'J','Я'=>'Ja','Ю'=>'Ju','К'=>'K','Ķ'=>'K','Ĺ'=>'L',
'Л'=>'L','Ł'=>'L','Ŀ'=>'L','Ļ'=>'L','Ľ'=>'L','М'=>'M',
'Н'=>'N','Ń'=>'N','Ñ'=>'N','Ņ'=>'N','Ň'=>'N','Ō'=>'O',
'О'=>'O','Ǿ'=>'O','Ǒ'=>'O','Ơ'=>'O','Ŏ'=>'O','Ő'=>'O',
'Ø'=>'O','Ö'=>'Oe','Õ'=>'O','Ó'=>'O','Ò'=>'O','Ô'=>'O',
'Œ'=>'OE','П'=>'P','Ŗ'=>'R','Р'=>'R','Ř'=>'R','Ŕ'=>'R',
'Ŝ'=>'S','Ş'=>'S','Š'=>'S','Ș'=>'S','Ś'=>'S','С'=>'S',
'Ш'=>'Sh','Щ'=>'Shch','Ť'=>'T','Ŧ'=>'T','Ţ'=>'T','Ț'=>'T',
'Т'=>'T','Ů'=>'U','Ű'=>'U','Ŭ'=>'U','Ũ'=>'U','Ų'=>'U',
'Ū'=>'U','Ǜ'=>'U','Ǚ'=>'U','Ù'=>'U','Ú'=>'U','Ü'=>'Ue',
'Ǘ'=>'U','Ǖ'=>'U','У'=>'U','Ư'=>'U','Ǔ'=>'U','Û'=>'U',
'В'=>'V','Ŵ'=>'W','Ы'=>'Y','Ŷ'=>'Y','Ý'=>'Y','Ÿ'=>'Y',
'Ź'=>'Z','З'=>'Z','Ż'=>'Z','Ž'=>'Z','Ж'=>'Zh','á'=>'a',
'ă'=>'a','â'=>'a','à'=>'a','ā'=>'a','ǻ'=>'a','å'=>'a',
'ä'=>'ae','ą'=>'a','ǎ'=>'a','ã'=>'a','а'=>'a','ª'=>'a',
'æ'=>'ae','ǽ'=>'ae','б'=>'b','č'=>'c','ç'=>'c','ц'=>'c',
'ċ'=>'c','ĉ'=>'c','ć'=>'c','ч'=>'ch','ð'=>'dj','ď'=>'dj',
'д'=>'dj','đ'=>'dj','э'=>'e','é'=>'e','ё'=>'e','ë'=>'e',
'ê'=>'e','е'=>'e','ĕ'=>'e','è'=>'e','ę'=>'e','ě'=>'e',
'ė'=>'e','ē'=>'e','ƒ'=>'f','ф'=>'f','ġ'=>'g','ĝ'=>'g',
'ğ'=>'g','г'=>'g','ģ'=>'g','х'=>'h','ĥ'=>'h','ħ'=>'h',
'ǐ'=>'i','ĭ'=>'i','и'=>'i','ī'=>'i','ĩ'=>'i','į'=>'i',
'ı'=>'i','ì'=>'i','î'=>'i','í'=>'i','ï'=>'i','ij'=>'ij',
'ĵ'=>'j','й'=>'j','я'=>'ja','ю'=>'ju','ķ'=>'k','к'=>'k',
'ľ'=>'l','ł'=>'l','ŀ'=>'l','ĺ'=>'l','ļ'=>'l','л'=>'l',
'м'=>'m','ņ'=>'n','ñ'=>'n','ń'=>'n','н'=>'n','ň'=>'n',
'ʼn'=>'n','ó'=>'o','ò'=>'o','ǒ'=>'o','ő'=>'o','о'=>'o',
'ō'=>'o','º'=>'o','ơ'=>'o','ŏ'=>'o','ô'=>'o','ö'=>'oe',
'õ'=>'o','ø'=>'o','ǿ'=>'o','œ'=>'oe','п'=>'p','р'=>'r',
'ř'=>'r','ŕ'=>'r','ŗ'=>'r','ſ'=>'s','ŝ'=>'s','ș'=>'s',
'š'=>'s','ś'=>'s','с'=>'s','ş'=>'s','ш'=>'sh','щ'=>'shch',
'ß'=>'ss','ţ'=>'t','т'=>'t','ŧ'=>'t','ť'=>'t','ț'=>'t',
'у'=>'u','ǘ'=>'u','ŭ'=>'u','û'=>'u','ú'=>'u','ų'=>'u',
'ù'=>'u','ű'=>'u','ů'=>'u','ư'=>'u','ū'=>'u','ǚ'=>'u',
'ǜ'=>'u','ǔ'=>'u','ǖ'=>'u','ũ'=>'u','ü'=>'ue','в'=>'v',
'ŵ'=>'w','ы'=>'y','ÿ'=>'y','ý'=>'y','ŷ'=>'y','ź'=>'z',
'ž'=>'z','з'=>'z','ż'=>'z','ж'=>'zh','ь'=>'','ъ'=>''
]+Base::instance()->get('DIACRITICS'))))),'-');
trim(strtr($text,Base::instance()->DIACRITICS+$this->diacritics())))),'-');
}
/**
@@ -881,9 +895,9 @@ if (!function_exists('gzdecode')) {
**/
function gzdecode($str) {
$fw=Base::instance();
if (!is_dir($tmp=$fw->get('TEMP')))
if (!is_dir($tmp=$fw->TEMP))
mkdir($tmp,Base::MODE,TRUE);
file_put_contents($file=$tmp.'/'.$fw->get('SEED').'.'.
file_put_contents($file=$tmp.'/'.$fw->SEED.'.'.
$fw->hash(uniqid(NULL,TRUE)).'.gz',$str,LOCK_EX);
ob_start();
readgzfile($file);

View File

@@ -55,7 +55,7 @@ class Geo extends \Prefab {
$fw=\Base::instance();
$web=\Web::instance();
if (!$ip)
$ip=$fw->get('IP');
$ip=$fw->IP;
$public=filter_var($ip,FILTER_VALIDATE_IP,
FILTER_FLAG_IPV4|FILTER_FLAG_IPV6|
FILTER_FLAG_NO_RES_RANGE|FILTER_FLAG_NO_PRIV_RANGE);

View File

@@ -0,0 +1,58 @@
<?php
/*
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).
This is free software: you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or later.
Fat-Free Framework is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License along
with Fat-Free Framework. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Web\Google;
//! Google ReCAPTCHA v2 plug-in
class Recaptcha {
const
//! API URL
URL_Recaptcha='https://www.google.com/recaptcha/api/siteverify';
/**
* Verify reCAPTCHA response
* @param string $secret
* @param string $response
* @return bool
**/
static function verify($secret,$response=NULL) {
$fw=\Base::instance();
if (!isset($response))
$response=$fw->{'POST.g-recaptcha-response'};
if (!$response)
return FALSE;
$web=\Web::instance();
$out=$web->request(self::URL_Recaptcha,[
'method'=>'POST',
'content'=>http_build_query([
'secret'=>$secret,
'response'=>$response,
'remoteip'=>$fw->IP
]),
]);
return isset($out['body']) &&
($json=json_decode($out['body'],TRUE)) &&
isset($json['success']) && $json['success'];
}
}

View File

@@ -63,7 +63,7 @@ class OAuth2 extends \Magic {
);
$response=$web->request($uri,$options);
if ($response['error'])
user_error($response['error']);
user_error($response['error'],E_USER_ERROR);
return $response['body'] &&
preg_grep('/HTTP\/1\.\d 200/',$response['headers'])?
json_decode($response['body'],TRUE):

View File

@@ -143,9 +143,9 @@ class OpenID extends \Magic {
**/
function auth($proxy=NULL,$attr=[],array $reqd=NULL) {
$fw=\Base::instance();
$root=$fw->get('SCHEME').'://'.$fw->get('HOST');
$root=$fw->SCHEME.'://'.$fw->HOST;
if (empty($this->args['trust_root']))
$this->args['trust_root']=$root.$fw->get('BASE').'/';
$this->args['trust_root']=$root.$fw->BASE.'/';
if (empty($this->args['return_to']))
$this->args['return_to']=$root.$_SERVER['REQUEST_URI'];
$this->args['mode']='checkid_setup';

View File

@@ -66,9 +66,9 @@ class Pingback extends \Prefab {
$web=\Web::instance();
$parts=parse_url($source);
if (empty($parts['scheme']) || empty($parts['host']) ||
$parts['host']==$fw->get('HOST')) {
$parts['host']==$fw->HOST) {
$req=$web->request($source);
$doc=new \DOMDocument('1.0',$fw->get('ENCODING'));
$doc=new \DOMDocument('1.0',$fw->ENCODING);
$doc->stricterrorchecking=FALSE;
$doc->recover=TRUE;
if (@$doc->loadhtml($req['body'])) {
@@ -85,7 +85,7 @@ class Pingback extends \Prefab {
'content'=>xmlrpc_encode_request(
'pingback.ping',
[$source,$permalink],
['encoding'=>$fw->get('ENCODING')]
['encoding'=>$fw->ENCODING]
)
]
);
@@ -110,29 +110,29 @@ class Pingback extends \Prefab {
function listen($func,$path=NULL) {
$fw=\Base::instance();
if (PHP_SAPI!='cli') {
header('X-Powered-By: '.$fw->get('PACKAGE'));
header('X-Powered-By: '.$fw->PACKAGE);
header('Content-Type: application/xml; '.
'charset='.$charset=$fw->get('ENCODING'));
'charset='.$charset=$fw->ENCODING);
}
if (!$path)
$path=$fw->get('BASE');
$path=$fw->BASE;
$web=\Web::instance();
$args=xmlrpc_decode_request($fw->get('BODY'),$method,$charset);
$args=xmlrpc_decode_request($fw->BODY,$method,$charset);
$options=['encoding'=>$charset];
if ($method=='pingback.ping' && isset($args[0],$args[1])) {
list($source,$permalink)=$args;
$doc=new \DOMDocument('1.0',$fw->get('ENCODING'));
$doc=new \DOMDocument('1.0',$fw->ENCODING);
// Check local page if pingback-enabled
$parts=parse_url($permalink);
if ((empty($parts['scheme']) ||
$parts['host']==$fw->get('HOST')) &&
$parts['host']==$fw->HOST) &&
preg_match('/^'.preg_quote($path,'/').'/'.
($fw->get('CASELESS')?'i':''),$parts['path']) &&
($fw->CASELESS?'i':''),$parts['path']) &&
$this->enabled($permalink)) {
// Check source
$parts=parse_url($source);
if ((empty($parts['scheme']) ||
$parts['host']==$fw->get('HOST')) &&
$parts['host']==$fw->HOST) &&
($req=$web->request($source)) &&
$doc->loadhtml($req['body'])) {
$links=$doc->getelementsbytagname('a');