1
0
mirror of https://github.com/24eme/signaturepdf.git synced 2023-08-25 09:33:08 +02:00

Fatfree 3.8.0 with php 8 compatibility

This commit is contained in:
Vincent LAURENT 2022-03-26 23:36:32 +01:00
parent 253cc31d73
commit 2c8c9a7f8e
19 changed files with 191 additions and 65 deletions

View File

@ -1,6 +1,18 @@
CHANGELOG CHANGELOG
3.7.3 3.8.0 (15 Feb 2022)
* Feat: allow access to previous session data in cache-based session handler
* Feat: pass session information to onSuspect Session handler
* Fix: PHP 8.1 compatibility fixes [#332](https://github.com/bcosca/fatfree-core/issues/332) [#333](https://github.com/bcosca/fatfree-core/issues/333)
* Fix: check for critical schemes in url validation
* Fix: plural format syntax with empty param, [#325](https://github.com/bcosca/fatfree-core/issues/325)
* Fix: DB mapper not able to fetch field scheme in sqlite views
* Fix: capitalization of array key X-Http-Method-Override in headers [#327](https://github.com/bcosca/fatfree-core/issues/327)
* Fix SMTP: allow RFC2047 encoded words in From/To/Cc/Bcc headers
* Fix: use correct ternary value, [#323](https://github.com/bcosca/fatfree-core/issues/323)
* Fix: trace not present in error handler when in CLI mode and !DEBUG, [#323](https://github.com/bcosca/fatfree-core/issues/323)
3.7.3 (13 Dec 2020)
* NEW: added auto_increment detection, [bcosca/fatfree#1192](https://github.com/bcosca/fatfree/issues/1192), [bcosca/fatfree#1093](https://github.com/bcosca/fatfree/issues/1093), [bcosca/fatfree#1175](https://github.com/bcosca/fatfree/issues/1175), [#290](https://github.com/bcosca/fatfree-core/issues/290) * NEW: added auto_increment detection, [bcosca/fatfree#1192](https://github.com/bcosca/fatfree/issues/1192), [bcosca/fatfree#1093](https://github.com/bcosca/fatfree/issues/1093), [bcosca/fatfree#1175](https://github.com/bcosca/fatfree/issues/1175), [#290](https://github.com/bcosca/fatfree-core/issues/290)
* added SMTP dialog error handling, [#317](https://github.com/bcosca/fatfree-core/issues/317) * added SMTP dialog error handling, [#317](https://github.com/bcosca/fatfree-core/issues/317)
* Fix: Check active transaction before rollback/commit (PHP8 issue) * Fix: Check active transaction before rollback/commit (PHP8 issue)

0
vendor/fatfree/lib/COPYING vendored Executable file → Normal file
View File

29
vendor/fatfree/lib/README.md vendored Normal file
View File

@ -0,0 +1,29 @@
# fatfree-core
Fat-Free Framework core library
### Usage:
First make sure to add a proper url rewrite configuration to your server, see https://fatfreeframework.com/3.6/routing-engine#DynamicWebSites
**without composer:**
```php
$f3 = require('lib/base.php');
```
**with composer:**
```
composer require bcosca/fatfree-core
```
```php
require("vendor/autoload.php");
$f3 = \Base::instance();
```
---
For the main repository (demo package), see https://github.com/bcosca/fatfree
For the test bench and unit tests, see https://github.com/f3-factory/fatfree-dev
For the user guide, see https://fatfreeframework.com/user-guide
For the documentation, see https://fatfreeframework.com/api-reference

View File

@ -36,7 +36,8 @@ class Audit extends Prefab {
* @param $str string * @param $str string
**/ **/
function url($str) { function url($str) {
return is_string(filter_var($str,FILTER_VALIDATE_URL)); return is_string(filter_var($str,FILTER_VALIDATE_URL))
&& !preg_match('/^(javascript|php):\/\/.*$/i', $str);
} }
/** /**

View File

@ -45,7 +45,7 @@ final class Base extends Prefab implements ArrayAccess {
//@{ Framework details //@{ Framework details
const const
PACKAGE='Fat-Free Framework', PACKAGE='Fat-Free Framework',
VERSION='3.7.3-Release'; VERSION='3.8.1-Dev';
//@} //@}
//@{ HTTP status codes (RFC 2616) //@{ HTTP status codes (RFC 2616)
@ -159,7 +159,7 @@ final class Base extends Prefab implements ArrayAccess {
**/ **/
private function cut($key) { private function cut($key) {
return preg_split('/\[\h*[\'"]?(.+?)[\'"]?\h*\]|(->)|\./', return preg_split('/\[\h*[\'"]?(.+?)[\'"]?\h*\]|(->)|\./',
$key,NULL,PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE); $key,-1,PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE);
} }
/** /**
@ -221,11 +221,11 @@ final class Base extends Prefab implements ArrayAccess {
* @return mixed * @return mixed
*/ */
function cast($val) { function cast($val) {
if (preg_match('/^(?:0x[0-9a-f]+|0[0-7]+|0b[01]+)$/i',$val)) if ($val && preg_match('/^(?:0x[0-9a-f]+|0[0-7]+|0b[01]+)$/i',$val))
return intval($val,0); return intval($val,0);
if (is_numeric($val)) if (is_numeric($val))
return $val+0; return $val+0;
$val=trim($val); $val=trim($val?:'');
if (preg_match('/^\w+$/i',$val) && defined($val)) if (preg_match('/^\w+$/i',$val) && defined($val))
return constant($val); return constant($val);
return $val; return $val;
@ -389,18 +389,18 @@ final class Base extends Prefab implements ArrayAccess {
if (version_compare(PHP_VERSION, '7.3.0') >= 0) { if (version_compare(PHP_VERSION, '7.3.0') >= 0) {
unset($jar['expire']); unset($jar['expire']);
if (isset($_COOKIE[$parts[1]])) if (isset($_COOKIE[$parts[1]]))
setcookie($parts[1],NULL,['expires'=>0]+$jar); setcookie($parts[1],'',['expires'=>0]+$jar);
if ($ttl) if ($ttl)
$jar['expires']=$time+$ttl; $jar['expires']=$time+$ttl;
setcookie($parts[1],$val,$jar); setcookie($parts[1],$val?:'',$jar);
} else { } else {
unset($jar['samesite']); unset($jar['samesite']);
if (isset($_COOKIE[$parts[1]])) if (isset($_COOKIE[$parts[1]]))
call_user_func_array('setcookie', call_user_func_array('setcookie',
array_merge([$parts[1],NULL],['expire'=>0]+$jar)); array_merge([$parts[1],''],['expire'=>0]+$jar));
if ($ttl) if ($ttl)
$jar['expire']=$time+$ttl; $jar['expire']=$time+$ttl;
call_user_func_array('setcookie',[$parts[1],$val]+$jar); call_user_func_array('setcookie',[$parts[1],$val?:'']+$jar);
} }
$_COOKIE[$parts[1]]=$val; $_COOKIE[$parts[1]]=$val;
return $val; return $val;
@ -501,11 +501,11 @@ final class Base extends Prefab implements ArrayAccess {
if (version_compare(PHP_VERSION, '7.3.0') >= 0) { if (version_compare(PHP_VERSION, '7.3.0') >= 0) {
$jar['expires']=$jar['expire']; $jar['expires']=$jar['expire'];
unset($jar['expire']); unset($jar['expire']);
setcookie($parts[1],NULL,$jar); setcookie($parts[1],'',$jar);
} else { } else {
unset($jar['samesite']); unset($jar['samesite']);
call_user_func_array('setcookie', call_user_func_array('setcookie',
array_merge([$parts[1],NULL],$jar)); array_merge([$parts[1],''],$jar));
} }
unset($_COOKIE[$parts[1]]); unset($_COOKIE[$parts[1]]);
} }
@ -713,7 +713,7 @@ final class Base extends Prefab implements ArrayAccess {
**/ **/
function split($str,$noempty=TRUE) { function split($str,$noempty=TRUE) {
return array_map('trim', return array_map('trim',
preg_split('/[,;|]/',$str,0,$noempty?PREG_SPLIT_NO_EMPTY:0)); preg_split('/[,;|]/',$str?:'',0,$noempty?PREG_SPLIT_NO_EMPTY:0));
} }
/** /**
@ -829,7 +829,7 @@ final class Base extends Prefab implements ArrayAccess {
**/ **/
function hash($str) { function hash($str) {
return str_pad(base_convert( return str_pad(base_convert(
substr(sha1($str),-16),16,36),11,'0',STR_PAD_LEFT); substr(sha1($str?:''),-16),16,36),11,'0',STR_PAD_LEFT);
} }
/** /**
@ -968,10 +968,11 @@ final class Base extends Prefab implements ArrayAccess {
isset($prop)?$prop:null isset($prop)?$prop:null
] ]
); );
$php81=version_compare(PHP_VERSION, '8.1.0')>=0;
switch ($type) { switch ($type) {
case 'plural': case 'plural':
preg_match_all('/(?<tag>\w+)'. preg_match_all('/(?<tag>\w+)'.
'(?:\s*\{\s*(?<data>.+?)\s*\})/', '(?:\s*\{\s*(?<data>.*?)\s*\})/',
$mod,$matches,PREG_SET_ORDER); $mod,$matches,PREG_SET_ORDER);
$ord=['zero','one','two']; $ord=['zero','one','two'];
foreach ($matches as $match) { foreach ($matches as $match) {
@ -1051,6 +1052,16 @@ final class Base extends Prefab implements ArrayAccess {
($frac?strlen($frac)-2:0), ($frac?strlen($frac)-2:0),
$decimal_point,$thousands_sep); $decimal_point,$thousands_sep);
case 'date': case 'date':
if ($php81) {
$lang = $this->split($this->LANGUAGE);
// requires intl extension
$formatter = new IntlDateFormatter($lang[0],
(empty($mod) || $mod=='short')
? IntlDateFormatter::SHORT :
($mod=='full' ? IntlDateFormatter::LONG : IntlDateFormatter::MEDIUM),
IntlDateFormatter::NONE);
return $formatter->format($args[$pos]);
} else {
if (empty($mod) || $mod=='short') if (empty($mod) || $mod=='short')
$prop='%x'; $prop='%x';
elseif ($mod=='full') elseif ($mod=='full')
@ -1058,12 +1069,25 @@ final class Base extends Prefab implements ArrayAccess {
elseif ($mod!='custom') elseif ($mod!='custom')
$prop='%d %B %Y'; $prop='%d %B %Y';
return strftime($prop,$args[$pos]); return strftime($prop,$args[$pos]);
}
case 'time': case 'time':
if ($php81) {
$lang = $this->split($this->LANGUAGE);
// requires intl extension
$formatter = new IntlDateFormatter($lang[0],
IntlDateFormatter::NONE,
(empty($mod) || $mod=='short')
? IntlDateFormatter::SHORT :
($mod=='full' ? IntlDateFormatter::LONG : IntlDateFormatter::MEDIUM),
IntlTimeZone::createTimeZone($this->hive['TZ']));
return $formatter->format($args[$pos]);
} else {
if (empty($mod) || $mod=='short') if (empty($mod) || $mod=='short')
$prop='%X'; $prop='%X';
elseif ($mod!='custom') elseif ($mod!='custom')
$prop='%r'; $prop='%r';
return strftime($prop,$args[$pos]); return strftime($prop,$args[$pos]);
}
default: default:
return $expr[0]; return $expr[0];
} }
@ -1089,7 +1113,7 @@ final class Base extends Prefab implements ArrayAccess {
* @param $code string * @param $code string
**/ **/
function language($code) { function language($code) {
$code=preg_replace('/\h+|;q=[0-9.]+/','',$code); $code=preg_replace('/\h+|;q=[0-9.]+/','',$code?:'');
$code.=($code?',':'').$this->fallback; $code.=($code?',':'').$this->fallback;
$this->languages=[]; $this->languages=[];
foreach (array_reverse(explode(',',$code)) as $lang) foreach (array_reverse(explode(',',$code)) as $lang)
@ -1225,7 +1249,7 @@ final class Base extends Prefab implements ArrayAccess {
$time=microtime(TRUE); $time=microtime(TRUE);
header_remove('Pragma'); header_remove('Pragma');
header('Cache-Control: max-age='.$secs); header('Cache-Control: max-age='.$secs);
header('Expires: '.gmdate('r',$time+$secs)); header('Expires: '.gmdate('r',round($time+$secs)));
header('Last-Modified: '.gmdate('r')); header('Last-Modified: '.gmdate('r'));
} }
else { else {
@ -1342,7 +1366,7 @@ final class Base extends Prefab implements ArrayAccess {
$loggable=$this->split($loggable); $loggable=$this->split($loggable);
foreach ($loggable as $status) foreach ($loggable as $status)
if ($status=='*' || if ($status=='*' ||
preg_match('/^'.preg_replace('/\D/','\d',$status).'$/',$code)) { preg_match('/^'.preg_replace('/\D/','\d',$status).'$/',(string) $code)) {
error_log($text); error_log($text);
foreach (explode("\n",$trace) as $nexus) foreach (explode("\n",$trace) as $nexus)
if ($nexus) if ($nexus)
@ -1376,7 +1400,7 @@ final class Base extends Prefab implements ArrayAccess {
if ($this->hive['CLI']) if ($this->hive['CLI'])
echo PHP_EOL.'==================================='.PHP_EOL. echo PHP_EOL.'==================================='.PHP_EOL.
'ERROR '.$error['code'].' - '.$error['status'].PHP_EOL. 'ERROR '.$error['code'].' - '.$error['status'].PHP_EOL.
$error['text'].PHP_EOL.PHP_EOL.$error['trace']; $error['text'].PHP_EOL.PHP_EOL.(isset($error['trace']) ? $error['trace'] : '');
else else
echo $this->hive['AJAX']? echo $this->hive['AJAX']?
json_encode($error): json_encode($error):
@ -1424,7 +1448,7 @@ final class Base extends Prefab implements ArrayAccess {
if (empty($parts[4])) if (empty($parts[4]))
user_error(sprintf(self::E_Pattern,$pattern),E_USER_ERROR); user_error(sprintf(self::E_Pattern,$pattern),E_USER_ERROR);
$url=parse_url($parts[4]); $url=parse_url($parts[4]);
parse_str(@$url['query'],$GLOBALS['_GET']); parse_str(isset($url['query'])?$url['query']:'',$GLOBALS['_GET']);
if (preg_match('/GET|HEAD/',$verb)) if (preg_match('/GET|HEAD/',$verb))
$GLOBALS['_GET']=array_merge($GLOBALS['_GET'],$args); $GLOBALS['_GET']=array_merge($GLOBALS['_GET'],$args);
$GLOBALS['_POST']=$verb=='POST'?$args:[]; $GLOBALS['_POST']=$verb=='POST'?$args:[];
@ -1775,7 +1799,7 @@ final class Base extends Prefab implements ArrayAccess {
++$ctr; ++$ctr;
if ($ctr/$kbps>($elapsed=microtime(TRUE)-$now) && if ($ctr/$kbps>($elapsed=microtime(TRUE)-$now) &&
!connection_aborted()) !connection_aborted())
usleep(1e6*($ctr/$kbps-$elapsed)); usleep(round(1e6*($ctr/$kbps-$elapsed)));
echo $part; echo $part;
} }
} }
@ -2234,6 +2258,7 @@ final class Base extends Prefab implements ArrayAccess {
* @return mixed * @return mixed
* @param $key string * @param $key string
**/ **/
#[\ReturnTypeWillChange]
function offsetexists($key) { function offsetexists($key) {
return $this->exists($key); return $this->exists($key);
} }
@ -2244,6 +2269,7 @@ final class Base extends Prefab implements ArrayAccess {
* @param $key string * @param $key string
* @param $val mixed * @param $val mixed
**/ **/
#[\ReturnTypeWillChange]
function offsetset($key,$val) { function offsetset($key,$val) {
return $this->set($key,$val); return $this->set($key,$val);
} }
@ -2253,6 +2279,7 @@ final class Base extends Prefab implements ArrayAccess {
* @return mixed * @return mixed
* @param $key string * @param $key string
**/ **/
#[\ReturnTypeWillChange]
function &offsetget($key) { function &offsetget($key) {
$val=&$this->ref($key); $val=&$this->ref($key);
return $val; return $val;
@ -2262,6 +2289,7 @@ final class Base extends Prefab implements ArrayAccess {
* Convenience method for removing hive key * Convenience method for removing hive key
* @param $key string * @param $key string
**/ **/
#[\ReturnTypeWillChange]
function offsetunset($key) { function offsetunset($key) {
$this->clear($key); $this->clear($key);
} }
@ -2378,7 +2406,7 @@ final class Base extends Prefab implements ArrayAccess {
$req.='?'.$query; $req.='?'.$query;
} }
$_SERVER['REQUEST_URI']=$req; $_SERVER['REQUEST_URI']=$req;
parse_str($query,$GLOBALS['_GET']); parse_str($query?:'',$GLOBALS['_GET']);
} }
elseif (function_exists('getallheaders')) { elseif (function_exists('getallheaders')) {
foreach (getallheaders() as $key=>$val) { foreach (getallheaders() as $key=>$val) {
@ -2400,8 +2428,8 @@ final class Base extends Prefab implements ArrayAccess {
$headers[strtr(ucwords(strtolower(strtr( $headers[strtr(ucwords(strtolower(strtr(
substr($key,5),'_',' '))),' ','-')]=&$_SERVER[$key]; substr($key,5),'_',' '))),' ','-')]=&$_SERVER[$key];
} }
if (isset($headers['X-HTTP-Method-Override'])) if (isset($headers['X-Http-Method-Override']))
$_SERVER['REQUEST_METHOD']=$headers['X-HTTP-Method-Override']; $_SERVER['REQUEST_METHOD']=$headers['X-Http-Method-Override'];
elseif ($_SERVER['REQUEST_METHOD']=='POST' && isset($_POST['_method'])) elseif ($_SERVER['REQUEST_METHOD']=='POST' && isset($_POST['_method']))
$_SERVER['REQUEST_METHOD']=strtoupper($_POST['_method']); $_SERVER['REQUEST_METHOD']=strtoupper($_POST['_method']);
$scheme=isset($_SERVER['HTTPS']) && $_SERVER['HTTPS']=='on' || $scheme=isset($_SERVER['HTTPS']) && $_SERVER['HTTPS']=='on' ||
@ -2533,9 +2561,11 @@ final class Base extends Prefab implements ArrayAccess {
if (PHP_SAPI=='cli-server' && if (PHP_SAPI=='cli-server' &&
preg_match('/^'.preg_quote($base,'/').'$/',$this->hive['URI'])) preg_match('/^'.preg_quote($base,'/').'$/',$this->hive['URI']))
$this->reroute('/'); $this->reroute('/');
if (ini_get('auto_globals_jit')) if (ini_get('auto_globals_jit')) {
// Override setting // Override setting
$GLOBALS+=['_ENV'=>$_ENV,'_REQUEST'=>$_REQUEST]; $GLOBALS['_ENV']=$_ENV;
$GLOBALS['_REQUEST']=$_REQUEST;
}
// Sync PHP globals with corresponding hive keys // Sync PHP globals with corresponding hive keys
$this->init=$this->hive; $this->init=$this->hive;
foreach (explode('|',self::GLOBALS) as $global) { foreach (explode('|',self::GLOBALS) as $global) {
@ -2699,7 +2729,7 @@ class Cache extends Prefab {
if (!$this->dsn) if (!$this->dsn)
return TRUE; return TRUE;
$regex='/'.preg_quote($this->prefix.'.','/').'.*'. $regex='/'.preg_quote($this->prefix.'.','/').'.*'.
preg_quote($suffix,'/').'/'; preg_quote($suffix?:'','/').'/';
$parts=explode('=',$this->dsn,2); $parts=explode('=',$this->dsn,2);
switch ($parts[0]) { switch ($parts[0]) {
case 'apc': case 'apc':

View File

@ -148,7 +148,7 @@ class Basket extends Magic {
**/ **/
function save() { function save() {
if (!$this->id) if (!$this->id)
$this->id=uniqid(NULL,TRUE); $this->id=uniqid('',TRUE);
$_SESSION[$this->key][$this->id]=$this->item; $_SESSION[$this->key][$this->id]=$this->item;
return $this->item; return $this->item;
} }

0
vendor/fatfree/lib/code.css vendored Executable file → Normal file
View File

12
vendor/fatfree/lib/composer.json vendored Normal file
View File

@ -0,0 +1,12 @@
{
"name": "bcosca/fatfree-core",
"description": "A powerful yet easy-to-use PHP micro-framework designed to help you build dynamic and robust Web applications - fast!",
"homepage": "http://fatfreeframework.com/",
"license": "GPL-3.0",
"require": {
"php": ">=5.4"
},
"autoload": {
"classmap": ["."]
}
}

View File

@ -107,6 +107,7 @@ abstract class Cursor extends \Magic implements \IteratorAggregate {
* Causes a fatal error in PHP 5.3.5 if uncommented * Causes a fatal error in PHP 5.3.5 if uncommented
* return ArrayIterator * return ArrayIterator
**/ **/
#[\ReturnTypeWillChange]
abstract function getiterator(); abstract function getiterator();

View File

@ -325,7 +325,7 @@ class Mapper extends \DB\Cursor {
if (!array_key_exists($col,$val2)) if (!array_key_exists($col,$val2))
$val2[$col]=NULL; $val2[$col]=NULL;
list($v1,$v2)=[$val1[$col],$val2[$col]]; list($v1,$v2)=[$val1[$col],$val2[$col]];
if ($out=strnatcmp($v1,$v2)* if ($out=strnatcmp($v1?:'',$v2?:'')*
(($order==SORT_ASC)*2-1)) (($order==SORT_ASC)*2-1))
return $out; return $out;
} }
@ -383,7 +383,7 @@ class Mapper extends \DB\Cursor {
return $this->update(); return $this->update();
$db=$this->db; $db=$this->db;
$now=microtime(TRUE); $now=microtime(TRUE);
while (($id=uniqid(NULL,TRUE)) && while (($id=uniqid('',TRUE)) &&
($data=&$db->read($this->file)) && isset($data[$id]) && ($data=&$db->read($this->file)) && isset($data[$id]) &&
!connection_aborted()) !connection_aborted())
usleep(mt_rand(0,100)); usleep(mt_rand(0,100));

View File

@ -150,7 +150,7 @@ class Mapper extends \DB\Cursor {
); );
$tmp=$this->db->selectcollection( $tmp=$this->db->selectcollection(
$fw->HOST.'.'.$fw->BASE.'.'. $fw->HOST.'.'.$fw->BASE.'.'.
uniqid(NULL,TRUE).'.tmp' uniqid('',TRUE).'.tmp'
); );
$tmp->batchinsert($grp['retval'],['w'=>1]); $tmp->batchinsert($grp['retval'],['w'=>1]);
$filter=[]; $filter=[];

View File

@ -339,7 +339,7 @@ class SQL {
$cmd=[ $cmd=[
'sqlite2?'=>[ 'sqlite2?'=>[
'SELECT * FROM pragma_table_info('.$this->quote($table).') JOIN ('. 'SELECT * FROM pragma_table_info('.$this->quote($table).') JOIN ('.
'SELECT sql FROM sqlite_master WHERE type=\'table\' AND '. 'SELECT sql FROM sqlite_master WHERE (type=\'table\' OR type=\'view\') AND '.
'name='.$this->quote($table).')', 'name='.$this->quote($table).')',
'name','type','dflt_value','notnull',0,'pk',TRUE,'sql', 'name','type','dflt_value','notnull',0,'pk',TRUE,'sql',
'/\W(%s)\W+[^,]+?AUTOINCREMENT\W/i'], '/\W(%s)\W+[^,]+?AUTOINCREMENT\W/i'],

View File

@ -427,6 +427,7 @@ class Mapper extends \DB\Cursor {
$values=''; $values='';
$filter=''; $filter='';
$pkeys=[]; $pkeys=[];
$aikeys=[];
$nkeys=[]; $nkeys=[];
$ckeys=[]; $ckeys=[];
$inc=NULL; $inc=NULL;
@ -449,6 +450,9 @@ class Mapper extends \DB\Cursor {
unset($field); unset($field);
} }
foreach ($this->fields as $key=>&$field) { foreach ($this->fields as $key=>&$field) {
if ($field['auto_inc']) {
$aikeys[] = $key;
}
if ($field['pkey']) { if ($field['pkey']) {
$field['previous']=$field['value']; $field['previous']=$field['value'];
if (!$inc && empty($field['value']) && if (!$inc && empty($field['value']) &&
@ -478,7 +482,7 @@ class Mapper extends \DB\Cursor {
} }
$lID=$this->db->exec( $lID=$this->db->exec(
(preg_match('/mssql|dblib|sqlsrv/',$this->engine) && (preg_match('/mssql|dblib|sqlsrv/',$this->engine) &&
array_intersect(array_keys($pkeys),$ckeys)? array_intersect(array_keys($aikeys),$ckeys)?
'SET IDENTITY_INSERT '.$this->table.' ON;':''). 'SET IDENTITY_INSERT '.$this->table.' ON;':'').
'INSERT INTO '.$this->table.' ('.$fields.') '. 'INSERT INTO '.$this->table.' ('.$fields.') '.
'VALUES ('.$values.')'.$add,$args 'VALUES ('.$values.')'.$add,$args

View File

@ -258,12 +258,12 @@ class Image {
if ($width/$ratio<=$height) { if ($width/$ratio<=$height) {
$cropw=round($origh*$width/$height); $cropw=round($origh*$width/$height);
imagecopyresampled($tmp,$this->data, imagecopyresampled($tmp,$this->data,
0,0,($origw-$cropw)/2,0,$width,$height,$cropw,$origh); 0,0,round(($origw-$cropw)/2),0,$width,$height,$cropw,$origh);
} }
else { else {
$croph=round($origw*$height/$width); $croph=round($origw*$height/$width);
imagecopyresampled($tmp,$this->data, imagecopyresampled($tmp,$this->data,
0,0,0,($origh-$croph)/2,$width,$height,$origw,$croph); 0,0,0,round(($origh-$croph)/2),$width,$height,$origw,$croph);
} }
} }
else else
@ -309,13 +309,13 @@ class Image {
if ($align & self::POS_Left) if ($align & self::POS_Left)
$posx=0; $posx=0;
if ($align & self::POS_Center) if ($align & self::POS_Center)
$posx=($imgw-$ovrw)/2; $posx=round(($imgw-$ovrw)/2);
if ($align & self::POS_Right) if ($align & self::POS_Right)
$posx=$imgw-$ovrw; $posx=$imgw-$ovrw;
if ($align & self::POS_Top) if ($align & self::POS_Top)
$posy=0; $posy=0;
if ($align & self::POS_Middle) if ($align & self::POS_Middle)
$posy=($imgh-$ovrh)/2; $posy=round(($imgh-$ovrh)/2);
if ($align & self::POS_Bottom) if ($align & self::POS_Bottom)
$posy=$imgh-$ovrh; $posy=$imgh-$ovrh;
if (empty($posx)) if (empty($posx))
@ -374,10 +374,14 @@ class Image {
$block=$sprites[hexdec($hash[($j*$blocks+$i)*2])%$ctr]; $block=$sprites[hexdec($hash[($j*$blocks+$i)*2])%$ctr];
for ($k=0,$pts=count($block);$k<$pts;++$k) for ($k=0,$pts=count($block);$k<$pts;++$k)
$block[$k]*=$dim; $block[$k]*=$dim;
if (version_compare(PHP_VERSION, '8.1.0') >= 0) {
imagefilledpolygon($sprite,$block,$fg);
} else {
imagefilledpolygon($sprite,$block,$pts/2,$fg); imagefilledpolygon($sprite,$block,$pts/2,$fg);
}
for ($k=0;$k<4;++$k) { for ($k=0;$k<4;++$k) {
imagecopyresampled($this->data,$sprite, imagecopyresampled($this->data,$sprite,
$i*$dim/2,$j*$dim/2,0,0,$dim/2,$dim/2,$dim,$dim); round($i*$dim/2),round($j*$dim/2),0,0,round($dim/2),round($dim/2),$dim,$dim);
$this->data=imagerotate($this->data,90, $this->data=imagerotate($this->data,90,
imagecolorallocatealpha($this->data,0,0,0,127)); imagecolorallocatealpha($this->data,0,0,0,127));
} }
@ -424,25 +428,25 @@ class Image {
$char=imagecreatetruecolor($block,$block); $char=imagecreatetruecolor($block,$block);
imagefill($char,0,0,$bg); imagefill($char,0,0,$bg);
imagettftext($char,$size*2,0, imagettftext($char,$size*2,0,
($block-$w)/2,$block-($block-$h)/2, round(($block-$w)/2),round($block-($block-$h)/2),
$fg,$path,$seed[$i]); $fg,$path,$seed[$i]);
$char=imagerotate($char,mt_rand(-30,30), $char=imagerotate($char,mt_rand(-30,30),
imagecolorallocatealpha($char,0,0,0,127)); imagecolorallocatealpha($char,0,0,0,127));
// Reduce to normal size // Reduce to normal size
$tmp[$i]=imagecreatetruecolor( $tmp[$i]=imagecreatetruecolor(
($w=imagesx($char))/2,($h=imagesy($char))/2); round(($w=imagesx($char))/2),round(($h=imagesy($char))/2));
imagefill($tmp[$i],0,0,IMG_COLOR_TRANSPARENT); imagefill($tmp[$i],0,0,IMG_COLOR_TRANSPARENT);
imagecopyresampled($tmp[$i], imagecopyresampled($tmp[$i],
$char,0,0,0,0,$w/2,$h/2,$w,$h); $char,0,0,0,0,round($w/2),round($h/2),$w,$h);
imagedestroy($char); imagedestroy($char);
$width+=$i+1<$len?$block/2:$w/2; $width+=$i+1<$len?$block/2:$w/2;
$height=max($height,$h/2); $height=max($height,$h/2);
} }
$this->data=imagecreatetruecolor($width,$height); $this->data=imagecreatetruecolor(round($width),round($height));
imagefill($this->data,0,0,IMG_COLOR_TRANSPARENT); imagefill($this->data,0,0,IMG_COLOR_TRANSPARENT);
for ($i=0;$i<$len;++$i) { for ($i=0;$i<$len;++$i) {
imagecopy($this->data,$tmp[$i], imagecopy($this->data,$tmp[$i],
$i*$block/2,($height-imagesy($tmp[$i]))/2,0,0, round($i*$block/2),round(($height-imagesy($tmp[$i]))/2),0,0,
imagesx($tmp[$i]),imagesy($tmp[$i])); imagesx($tmp[$i]),imagesy($tmp[$i]));
imagedestroy($tmp[$i]); imagedestroy($tmp[$i]);
} }

View File

@ -57,6 +57,7 @@ abstract class Magic implements ArrayAccess {
* @return mixed * @return mixed
* @param $key string * @param $key string
**/ **/
#[\ReturnTypeWillChange]
function offsetexists($key) { function offsetexists($key) {
return Base::instance()->visible($this,$key)? return Base::instance()->visible($this,$key)?
isset($this->$key): isset($this->$key):
@ -69,6 +70,7 @@ abstract class Magic implements ArrayAccess {
* @param $key string * @param $key string
* @param $val mixed * @param $val mixed
**/ **/
#[\ReturnTypeWillChange]
function offsetset($key,$val) { function offsetset($key,$val) {
return Base::instance()->visible($this,$key)? return Base::instance()->visible($this,$key)?
($this->$key=$val):$this->set($key,$val); ($this->$key=$val):$this->set($key,$val);
@ -79,6 +81,7 @@ abstract class Magic implements ArrayAccess {
* @return mixed * @return mixed
* @param $key string * @param $key string
**/ **/
#[\ReturnTypeWillChange]
function &offsetget($key) { function &offsetget($key) {
if (Base::instance()->visible($this,$key)) if (Base::instance()->visible($this,$key))
$val=&$this->$key; $val=&$this->$key;
@ -92,6 +95,7 @@ abstract class Magic implements ArrayAccess {
* @return NULL * @return NULL
* @param $key string * @param $key string
**/ **/
#[\ReturnTypeWillChange]
function offsetunset($key) { function offsetunset($key) {
if (Base::instance()->visible($this,$key)) if (Base::instance()->visible($this,$key))
unset($this->$key); unset($this->$key);

View File

@ -21,7 +21,7 @@
*/ */
//! Cache-based session handler //! Cache-based session handler
class Session { class Session extends Magic {
protected protected
//! Session ID //! Session ID
@ -35,7 +35,9 @@ class Session {
//! Suspect callback //! Suspect callback
$onsuspect, $onsuspect,
//! Cache instance //! Cache instance
$_cache; $_cache,
//! Session meta data
$_data=[];
/** /**
* Open session * Open session
@ -53,6 +55,7 @@ class Session {
**/ **/
function close() { function close() {
$this->sid=NULL; $this->sid=NULL;
$this->_data=[];
return TRUE; return TRUE;
} }
@ -65,6 +68,7 @@ class Session {
$this->sid=$id; $this->sid=$id;
if (!$data=$this->_cache->get($id.'.@')) if (!$data=$this->_cache->get($id.'.@'))
return ''; return '';
$this->_data = $data;
if ($data['ip']!=$this->_ip || $data['agent']!=$this->_agent) { if ($data['ip']!=$this->_ip || $data['agent']!=$this->_agent) {
$fw=Base::instance(); $fw=Base::instance();
if (!isset($this->onsuspect) || if (!isset($this->onsuspect) ||
@ -193,4 +197,29 @@ class Session {
$this->_ip=$fw->IP; $this->_ip=$fw->IP;
} }
/**
* check latest meta data existence
* @param string $key
* @return bool
*/
function exists($key) {
return isset($this->_data[$key]);
}
/**
* get meta data from latest session
* @param string $key
* @return mixed
*/
function &get($key) {
return $this->_data[$key];
}
function set($key,$val) {
trigger_error('Unable to set data on previous session');
}
function clear($key) {
trigger_error('Unable to clear data on previous session');
}
} }

View File

@ -256,7 +256,7 @@ class SMTP extends Magic {
foreach ($headers as $key=>&$val) { foreach ($headers as $key=>&$val) {
if (in_array($key,['From','To','Cc','Bcc'])) { if (in_array($key,['From','To','Cc','Bcc'])) {
$email=''; $email='';
preg_match_all('/(?:".+?" )?(?:<.+?>|[^ ,]+)/', preg_match_all('/(?:".+?" |=\?.+?\?= )?(?:<.+?>|[^ ,]+)/',
$val,$matches,PREG_SET_ORDER); $val,$matches,PREG_SET_ORDER);
foreach ($matches as $raw) foreach ($matches as $raw)
$email.=($email?', ':''). $email.=($email?', ':'').
@ -283,7 +283,7 @@ class SMTP extends Magic {
unset($headers['Content-Type']); unset($headers['Content-Type']);
$enc=$headers['Content-Transfer-Encoding']; $enc=$headers['Content-Transfer-Encoding'];
unset($headers['Content-Transfer-Encoding']); unset($headers['Content-Transfer-Encoding']);
$hash=uniqid(NULL,TRUE); $hash=uniqid('',TRUE);
// Send mail headers // Send mail headers
$out='Content-Type: multipart/mixed; boundary="'.$hash.'"'.$eol; $out='Content-Type: multipart/mixed; boundary="'.$hash.'"'.$eol;
foreach ($headers as $key=>$val) foreach ($headers as $key=>$val)
@ -352,7 +352,7 @@ class SMTP extends Magic {
'Content-Type'=>'text/plain; '. 'Content-Type'=>'text/plain; '.
'charset='.Base::instance()->ENCODING 'charset='.Base::instance()->ENCODING
]; ];
$this->host=strtolower((($this->scheme=strtolower($scheme))=='ssl'? $this->host=strtolower((($this->scheme=strtolower($scheme?:''))=='ssl'?
'ssl':'tcp').'://'.$host); 'ssl':'tcp').'://'.$host);
$this->port=$port; $this->port=$port;
$this->user=$user; $this->user=$user;

View File

@ -43,7 +43,7 @@ class Template extends Preview {
$out=''; $out='';
foreach ($node['@attrib'] as $key=>$val) foreach ($node['@attrib'] as $key=>$val)
$out.='$'.$key.'='. $out.='$'.$key.'='.
(preg_match('/\{\{(.+?)\}\}/',$val)? (preg_match('/\{\{(.+?)\}\}/',$val?:'')?
$this->token($val): $this->token($val):
Base::instance()->stringify($val)).'; '; Base::instance()->stringify($val)).'; ';
return '<?php '.$out.'?>'; return '<?php '.$out.'?>';

View File

@ -232,7 +232,7 @@ class Web extends Prefab {
// Throttle output // Throttle output
++$ctr; ++$ctr;
if ($ctr/$kbps>$elapsed=microtime(TRUE)-$start) if ($ctr/$kbps>$elapsed=microtime(TRUE)-$start)
usleep(1e6*($ctr/$kbps-$elapsed)); usleep(round(1e6*($ctr/$kbps-$elapsed)));
} }
// Send 1KiB and reset timer // Send 1KiB and reset timer
echo fread($handle,1024); echo fread($handle,1024);
@ -1006,7 +1006,7 @@ if (!function_exists('gzdecode')) {
if (!is_dir($tmp=$fw->TEMP)) if (!is_dir($tmp=$fw->TEMP))
mkdir($tmp,Base::MODE,TRUE); mkdir($tmp,Base::MODE,TRUE);
file_put_contents($file=$tmp.'/'.$fw->SEED.'.'. file_put_contents($file=$tmp.'/'.$fw->SEED.'.'.
$fw->hash(uniqid(NULL,TRUE)).'.gz',$str,LOCK_EX); $fw->hash(uniqid('',TRUE)).'.gz',$str,LOCK_EX);
ob_start(); ob_start();
readgzfile($file); readgzfile($file);
$out=ob_get_clean(); $out=ob_get_clean();