1
0
Fork 0
mirror of https://github.com/24eme/signaturepdf synced 2026-03-14 13:55:44 +01:00

Updated fatfree to version 3.9.0 to be compatible with php 8.4

This commit is contained in:
Vincent LAURENT 2025-01-16 00:03:34 +01:00
commit 252b843148
25 changed files with 457 additions and 179 deletions

View file

@ -1,6 +1,51 @@
CHANGELOG
3.9.0 (29.12.2024)
---
* feat [#377], DB\SQL: check TABLE_SCHEMA in fields introspection query
* feat [#379]: Added `REROUTE_TRAILING_SLASH` to optionally disable rerouting
* feat [#380], Audit: Adding new mac address validation
* fix [#372], Audit: `isprivate()`, `FILTER_FLAG_NO_PRIV_RANGE` usage
* fix [#378]: websocket handlers call
* fix: php 8.4 session handler compatibility
* fix: various php 8.4 warnings
* fix [#382]: PHP 8.4 `E_STRICT` deprecation fix
* fix [#371]: trim string based routes handler
* fix [bcosca/fatfree#1285]: multi-line template tags
* fix [#375]: PHP 8.4 Fixes for implicit nullability deprecation
* fix [#374]: http_build_query usage deprecation fix
* fix [#369]: unify key string replacement for cache getter/setter
3.8.2 (24.07.2023)
---
* feat, Base->format: optimize international date formatting for php8.1+
* fix, Base->format: keep php7 compatibility in date formatter [#360](https://github.com/f3-factory/fatfree-core/issues/360)
* fix, Markdown: unicode chars not captured correctly for headline slugs [#363](https://github.com/f3-factory/fatfree-core/issues/363)
* fix, Preview->resolve: PHP8+ error, undefined variable $hash [#359](https://github.com/f3-factory/fatfree-core/issues/359)
* fix, Base->clean: PHP8+ error, strip_tags with null value usage
3.8.1 (05.11.2022)
---
* fix: CORS preflight request fails to find route for ajax-only definitions [bcosca/fatfree#1242](https://github.com/bcosca/fatfree/issues/1242)
* fix: add realpath to captcha font filepath, [#314](https://github.com/bcosca/fatfree-core/issues/314)
* fix: case-insensitive custom tag matching [#353](https://github.com/bcosca/fatfree-core/issues/353)
* fix: php8 error suppression on invalid locale constant access [bcosca/fatfree#1259](https://github.com/bcosca/fatfree/issues/1259)
* fix: iteration over inaccessible object properties, fixes [#350](https://github.com/bcosca/fatfree-core/issues/350)
* feat: let jig handle utf8 issues more gracefully [#352](https://github.com/bcosca/fatfree-core/issues/352)
* fix: BC issue for pre php74
* fix: ensure template->parse does render zero text-node, [#354](https://github.com/bcosca/fatfree-core/issues/354)
* fix: DB\SQL\Mapper: allow to pass an empty array as $filter, fixes [bcosca/fatfree#1257](https://github.com/bcosca/fatfree/issues/1257)
* fix: adhoc null fields in Twig are executed as callable, [#310](https://github.com/bcosca/fatfree-core/issues/310)
* fix: ensure merged default PARAMS are properly encoded when building alias, [#345](https://github.com/bcosca/fatfree-core/issues/345)
* fix: Added CORS defaults that are not initialized
* fix: SQL cache schema for $fields
* fix: adhoc field with null value php81 issue, [#339](https://github.com/bcosca/fatfree-core/issues/339)
* fix: check against correct identity flags when using IDENTITY_INSERT for sql server
* added missing file location in error handler [bcosca/fatfree#1255](https://github.com/bcosca/fatfree/issues/1255)
* Web->request, add option to adjust accept-encoding in curl engine [#355](https://github.com/bcosca/fatfree-core/issues/355)
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)
@ -13,6 +58,7 @@ CHANGELOG
* 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)
* added SMTP dialog error handling, [#317](https://github.com/bcosca/fatfree-core/issues/317)
* Fix: Check active transaction before rollback/commit (PHP8 issue)
@ -28,6 +74,7 @@ CHANGELOG
* Fixed a couple PHPDOC issues
3.7.2 (28 May 2020)
---
* CHANGED, View->sandbox: disable escaping when rendering as text/plain, [bcosca/fatfree#654](https://github.com/bcosca/fatfree/issues/654)
* update HTTP protocol checks, [bcosca/fatfree#1190](https://github.com/bcosca/fatfree/issues/1190)
* Base->clear: close vulnerability on variable compilation, [bcosca/fatfree#1191](https://github.com/bcosca/fatfree/issues/1191)
@ -43,12 +90,14 @@ CHANGELOG
* only use money_format up until php7.4, [bcosca/fatfree#1174](https://github.com/bcosca/fatfree/issues/1174)
3.7.1 (30. December 2019)
---
* Base->build: Add support for brace-enclosed route tokens
* Base->reroute, fix duplicate fragment issue on non-alias routes
* DB\SQL\Mapper: fix empty check for pkey when reloading after insert
* Web->minify: fix minification with multiple files, [bcosca/fatfree#1152](https://github.com/bcosca/fatfree/issues/1152), [#bcosca/fatfree#1169](https://github.com/bcosca/fatfree/issues/1169)
3.7.0 (26. November 2019)
---
* NEW: Matrix, added select and walk methods for array processing and validation tools
* NEW: Added configurable file locking via LOCK var
* NEW: json support for dictionary files
@ -84,6 +133,7 @@ CHANGELOG
* fix PHPdoc and variable inspection, [bcosca/fatfree#865](https://github.com/bcosca/fatfree/issues/865), [bcosca/fatfree#1128](https://github.com/bcosca/fatfree/issues/1128)
3.6.5 (24 December 2018)
---
* NEW: Log, added timestamp to each line
* NEW: Auth, added support for custom compare method, [#116](https://github.com/bcosca/fatfree-core/issues/116)
* NEW: cache tag support for mongo & jig mapper, ref [#166](https://github.com/bcosca/fatfree-core/issues/116)
@ -127,6 +177,7 @@ CHANGELOG
* Expose Mapper->factory() method
3.6.4 (19 April 2018)
---
* NEW: Added Dependency Injection support with CONTAINER variable [#221](https://github.com/bcosca/fatfree-core/issues/221)
* NEW: configurable LOGGABLE error codes [#1091](https://github.com/bcosca/fatfree/issues/1091#issuecomment-364674701)
* NEW: JAR.lifetime option, [#178](https://github.com/bcosca/fatfree-core/issues/178)
@ -152,6 +203,7 @@ CHANGELOG
* Fixed expiration time when updating an existing cookie
3.6.3 (31 December 2017)
---
* PHP7 fix: remove deprecated (unset) cast
* Web->request: restricted follow_location to 3XX responses only
* CLI mode: refactored arguments parsing
@ -184,6 +236,7 @@ CHANGELOG
* fix View->render using potentially wrong cache entry
3.6.2 (26 June 2017)
---
* Return a status code > 0 when dying on error [#220](https://github.com/bcosca/fatfree-core/issues/220)
* fix SMTP line width [#215](https://github.com/bcosca/fatfree-core/issues/215)
* Allow using a custom field for ldap user id checking [#217](https://github.com/bcosca/fatfree-core/issues/217)
@ -211,6 +264,7 @@ CHANGELOG
* Optimize template conversion to PHP file
3.6.1 (2 April 2017)
---
* NEW: Recaptcha plugin [#194](https://github.com/bcosca/fatfree-core/pull/194)
* NEW: MB variable for detecting multibyte support
* NEW: DB\SQL: Cache parsed schema for the TTL duration
@ -267,6 +321,7 @@ CHANGELOG
* Bug fix: base stripped twice in router (#176)
3.6.0 (19 November 2016)
---
* NEW: [cli] request type
* NEW: console-friendly CLI mode
* NEW: lexicon caching
@ -375,6 +430,7 @@ CHANGELOG
* Bug fix: Trailing slash redirection on UTF-8 paths (#121)
3.5.1 (31 December 2015)
---
* NEW: ttl attribute in <include> template tag
* NEW: allow anonymous function for template filter
* NEW: format modifier for international and custom currency symbol
@ -422,6 +478,7 @@ CHANGELOG
* Bug fix: Web->send() Single quotes around filename not interpreted correctly by some browsers
3.5.0 (2 June 2015)
---
* NEW: until() method for long polling
* NEW: abort() to disconnect HTTP client (and continue execution)
* NEW: SQL Mapper->required() returns TRUE if field is not nullable
@ -490,6 +547,7 @@ CHANGELOG
* Bug fix: ONERROR does not receive PARAMS on fatal error
3.4.0 (1 January 2015)
---
* NEW: [redirects] section
* NEW: Custom config sections
* NEW: User-defined AUTOLOAD function
@ -552,6 +610,7 @@ CHANGELOG
* Bug fix: Undefined pkey (#607)
3.3.0 (8 August 2014)
---
* NEW: Attribute in <include> tag to extend hive
* NEW: Image overlay with transparency and alignment control
* NEW: Allow redirection of specified route patterns to a URL
@ -583,6 +642,7 @@ CHANGELOG
* Quick reference: add RAW variable
3.2.2 (19 March 2014)
---
* NEW: Locales set automatically (Feature request #522)
* NEW: Mapper dbtype()
* NEW: before- and after- triggers for all mappers
@ -623,6 +683,7 @@ CHANGELOG
* Bug fix: BASE is incorrect on Windows
3.2.1 (7 January 2014)
---
* NEW: EMOJI variable, UTF->translate(), UTF->emojify(), and UTF->strrev()
* Allow empty strings in config()
* Add support for turning off php://input buffering via RAW
@ -649,6 +710,7 @@ CHANGELOG
* Bug fix: stringify() recursion
3.2.0 (18 December 2013)
---
* NEW: Automatic CSRF protection (with IP and User-Agent checks) for
sessions mapped to SQL-, Jig-, Mongo- and Cache-based backends
* NEW: Named routes
@ -718,6 +780,7 @@ CHANGELOG
* Bug fix: Loose comparison in stringify()
3.1.2 (5 November 2013)
---
* Abandon .chm help format; Package API documentation in plain HTML;
(Launch lib/api/index.html in your browser)
* Deprecate BAIL in favor of HALT (default: TRUE)
@ -738,6 +801,7 @@ CHANGELOG
* Bug fix: Unknown bcrypt constant
3.1.1 (13 October 2013)
---
* NEW: Support OpenID attribute exchange
* NEW: BAIL variable enables/disables continuance of execution on non-fatal
errors
@ -765,6 +829,7 @@ CHANGELOG
* Bug fix: Calculation of elapsed time
3.1.0 (20 August 2013)
---
* NEW: Web->filler() returns a chunk of text from the standard
Lorem Ipsum passage
* Change in behavior: Drop support for JSON serialization
@ -793,6 +858,7 @@ CHANGELOG
equivalent
3.0.9 (12 June 2013)
---
* NEW: Web->whois()
* NEW: Template <switch> <case> tags
* Improve CACHE consistency
@ -814,6 +880,7 @@ CHANGELOG
* Bug fix: Country code constants
3.0.8 (17 May 2013)
---
* NEW: Bcrypt lightweight hashing library\
* Return total number of records in superset in Cursor->paginate()
* ONERROR short-circuit (Enhancement #334)
@ -824,6 +891,7 @@ CHANGELOG
* Bug fix: Unsupported operand types (Issue #324)
3.0.7 (2 May 2013)
---
* NEW: route() now allows an array of routing patterns as first argument;
support array as first argument of map()
* NEW: entropy() for calculating password strength (NIST 800-63)
@ -847,6 +915,7 @@ CHANGELOG
* Bug fix: Incorrect regex in SMTP
3.0.6 (31 Mar 2013)
---
* NEW: Image->crop()
* Modify documentation blocks for PHPDoc interoperability
* Allow user to control whether Base->rerouet() uses a permanent or
@ -874,6 +943,7 @@ CHANGELOG
* Bug fix: Base->scrub() ignores pass-thru * argument (Issue #274)
3.0.5 (16 Feb 2013)
---
* NEW: Markdown class with PHP, HTML, and .ini syntax highlighting support
* NEW: Options for caching of select() and find() results
* NEW: Web->acceptable()
@ -897,6 +967,7 @@ CHANGELOG
* Bug fix: weather() fails when server is unreachable
3.0.4 (29 Jan 2013)
---
* NEW: Support for ICU/CLDR pluralization
* NEW: User-defined FALLBACK language
* NEW: minify() now recognizes CSS @import directives
@ -934,6 +1005,7 @@ CHANGELOG
* Bug fix: language() return value
3.0.3 (29 Dec 2013)
---
* NEW: [ajax] and [sync] routing pattern modifiers
* NEW: Basket class (session-based pseudo-mapper, shopping cart, etc.)
* NEW: Test->message() method
@ -965,6 +1037,7 @@ CHANGELOG
* Bug fix: URL-decoding
3.0.2 (23 Dec 2013)
---
* NEW: Syntax-highlighted stack traces via Base->highlight(); boolean
HIGHLIGHT global variable can be used to enable/disable this feature
* NEW: Template engine <ignore> tag
@ -995,4 +1068,5 @@ CHANGELOG
* Use file_get_contents() in methods that don't involve high concurrency
3.0.1 (14 Dec 2013)
---
* Major rewrite of much of the framework's core features

View file

@ -77,8 +77,8 @@ class Audit extends Prefab {
* @param $addr string
**/
function isprivate($addr) {
return !(bool)filter_var($addr,FILTER_VALIDATE_IP,
FILTER_FLAG_IPV4|FILTER_FLAG_IPV6|FILTER_FLAG_NO_PRIV_RANGE);
return (bool)filter_var($addr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6)
&& !(bool)filter_var($addr, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE);
}
/**
@ -189,4 +189,14 @@ class Audit extends Prefab {
'/[A-Z].*?[0-9[:punct:]]|[0-9[:punct:]].*?[A-Z]/',$str));
}
/**
* Return TRUE if string is a valid MAC address including EUI-64 format
* @return bool
* @param $addr string
**/
function mac($addr) {
return (bool)filter_var($addr,FILTER_VALIDATE_MAC)
|| preg_match('/^([0-9a-f]{2}:){3}ff:fe(:[0-9a-f]{2}){3}$/i', $addr);
}
}

View file

@ -247,7 +247,7 @@ class Auth {
* @param $args array
* @param $func callback
**/
function __construct($storage,array $args=NULL,$func=NULL) {
function __construct($storage,?array $args=NULL,$func=NULL) {
if (is_object($storage) && is_a($storage,'DB\Cursor')) {
$this->storage=$storage->dbtype();
$this->mapper=$storage;

View file

@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2019 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2023 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).
@ -38,14 +38,88 @@ abstract class Prefab {
}
}
/**
* @property string ALIAS
* @property array ALIASES
* @property string|array AUTOLOAD
* @property bool|string CACHE
* @property bool CASELESS
* @property callable|\Prefab|\Psr\Container\ContainerInterface CONTAINER
* @property array COOKIE
* @property array GET
* @property array POST
* @property array REQUEST
* @property array SESSION
* @property array FILES
* @property array SERVER
* @property array ENV
* @property array CORS
* @property int DEBUG
* @property array DIACRITICS
* @property string DNSBL
* @property array EMOJI
* @property string ENCODING
* @property bool ESCAPE
* @property string EXEMPT
* @property object EXCEPTION
* @property string FALLBACK
* @property array FORMATS
* @property string FRAGMENT
* @property bool HALT
* @property bool HIGHLIGHT
* @property array JAR
* @property string LANGUAGE
* @property string LOCALES
* @property string|array LOGGABLE
* @property string LOGS
* @property mixed ONERROR
* @property mixed ONREROUTE
* @property string|null PACKAGE
* @property array PARAMS
* @property string PLUGINS
* @property string PREFIX
* @property string PREMAP
* @property bool QUIET
* @property bool RAW
* @property array ROUTES
* @property string SEED
* @property string SERIALIZER
* @property string TEMP
* @property float TIME
* @property bool REROUTE_TRAILING_SLASH
* @property string TZ
* @property string UI
* @property callback UNLOAD
* @property string UPLOADS
* @property string URI
* @property string VERB
* @property string VERSION
* @property string|null XFRAME
* @property-read string AGENT
* @property-read bool AJAX
* @property-read string BASE
* @property-read string BODY
* @property-read bool CLI
* @property-read array ERROR
* @property-read array HEADERS
* @property-read string HOST
* @property-read string IP
* @property-read string PATH
* @property-read string PATTERN
* @property-read int PORT
* @property-read string QUERY
* @property-read string REALM
* @property-read string RESPONSE
* @property-read string ROOT
* @property-read string SCHEME
*/
//! Base structure
final class Base extends Prefab implements ArrayAccess {
//@{ Framework details
const
PACKAGE='Fat-Free Framework',
VERSION='3.8.1-Dev';
VERSION='3.9.0-Release';
//@}
//@{ HTTP status codes (RFC 2616)
@ -166,13 +240,17 @@ final class Base extends Prefab implements ArrayAccess {
* Replace tokenized URL with available token values
* @return string
* @param $url array|string
* @param $addParams boolean merge default PARAMS from hive into args
* @param $args array
**/
function build($url,$args=[]) {
$args+=$this->hive['PARAMS'];
function build($url, $args=[], $addParams=TRUE) {
if ($addParams)
$args+=$this->recursive($this->hive['PARAMS'], function($val) {
return implode('/', array_map('urlencode', explode('/', $val)));
});
if (is_array($url))
foreach ($url as &$var) {
$var=$this->build($var,$args);
$var=$this->build($var,$args, false);
unset($var);
}
else {
@ -722,7 +800,7 @@ final class Base extends Prefab implements ArrayAccess {
* @param $arg mixed
* @param $stack array
**/
function stringify($arg,array $stack=NULL) {
function stringify($arg,?array $stack=NULL) {
if ($stack) {
foreach ($stack as $node)
if ($arg===$node)
@ -879,11 +957,15 @@ final class Base extends Prefab implements ArrayAccess {
$ref=new ReflectionClass($arg);
if ($ref->iscloneable()) {
$arg=clone($arg);
$cast=is_a($arg,'IteratorAggregate')?
$cast=($it=is_a($arg,'IteratorAggregate'))?
iterator_to_array($arg):get_object_vars($arg);
foreach ($cast as $key=>$val)
foreach ($cast as $key=>$val) {
// skip inaccessible properties #350
if (!$it && !isset($arg->$key))
continue;
$arg->$key=$this->recursive(
$val,$func,array_merge($stack,[$arg]));
}
}
return $arg;
case 'array':
@ -907,7 +989,7 @@ final class Base extends Prefab implements ArrayAccess {
return $this->recursive($arg,
function($val) use($tags) {
if ($tags!='*')
$val=trim(strip_tags($val,
$val=trim(strip_tags($val??'',
'<'.implode('><',$this->split($tags)).'>'));
return trim(preg_replace(
'/[\x00-\x08\x0B\x0C\x0E-\x1F]/','',$val));
@ -1055,11 +1137,13 @@ final class Base extends Prefab implements ArrayAccess {
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);
$dateType=(empty($mod) || $mod=='short') ? IntlDateFormatter::SHORT :
($mod=='full' ? IntlDateFormatter::FULL : IntlDateFormatter::LONG);
$pattern = $dateType === IntlDateFormatter::SHORT
? (($ptn=IntlDatePatternGenerator::create($lang[0]))
? $ptn->getBestPattern('yyyyMMdd') : null) : null;
$formatter = new IntlDateFormatter($lang[0],$dateType,
IntlDateFormatter::NONE, null,null, $pattern);
return $formatter->format($args[$pos]);
} else {
if (empty($mod) || $mod=='short')
@ -1133,10 +1217,12 @@ final class Base extends Prefab implements ArrayAccess {
foreach (preg_grep('/^(?!tr)/i',$this->languages) as $locale) {
if ($windows) {
$parts=explode('-',$locale);
$locale=@constant('ISO::LC_'.$parts[0]);
if (!defined('ISO::LC_'.$parts[0]))
continue;
$locale=constant('ISO::LC_'.$parts[0]);
if (isset($parts[1]) &&
$country=@constant('ISO::CC_'.strtolower($parts[1])))
$locale.='-'.$country;
defined($cc='ISO::CC_'.strtolower($parts[1])))
$locale.='-'.constant($cc);
}
$locale=str_replace('-','_',$locale);
$locales[]=$locale.'.'.ini_get('default_charset');
@ -1304,7 +1390,7 @@ final class Base extends Prefab implements ArrayAccess {
* @param $trace array|NULL
* @param $format bool
**/
function trace(array $trace=NULL,$format=TRUE) {
function trace(?array $trace=NULL,$format=TRUE) {
if (!$trace) {
$trace=debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
$frame=$trace[0];
@ -1352,7 +1438,7 @@ final class Base extends Prefab implements ArrayAccess {
* @param $trace array
* @param $level int
**/
function error($code,$text='',array $trace=NULL,$level=0) {
function error($code,$text='',?array $trace=NULL,$level=0) {
$prior=$this->hive['ERROR'];
$header=$this->status($code);
$req=$this->hive['VERB'].' '.$this->hive['PATH'];
@ -1431,7 +1517,7 @@ final class Base extends Prefab implements ArrayAccess {
* @param $body string
**/
function mock($pattern,
array $args=NULL,array $headers=NULL,$body=NULL) {
?array $args=NULL,?array $headers=NULL,$body=NULL) {
if (!$args)
$args=[];
$types=['sync','ajax','cli'];
@ -1524,7 +1610,7 @@ final class Base extends Prefab implements ArrayAccess {
if (!preg_match('/'.self::VERBS.'/',$verb))
$this->error(501,$verb.' '.$this->hive['URI']);
$this->hive['ROUTES'][$parts[3]][$type][strtoupper($verb)]=
[$handler,$ttl,$kbps,$alias];
[is_string($handler) ? trim($handler) : $handler,$ttl,$kbps,$alias];
}
}
@ -1710,12 +1796,14 @@ final class Base extends Prefab implements ArrayAccess {
$route=NULL;
$ptr=$this->hive['CLI']?self::REQ_CLI:$this->hive['AJAX']+1;
if (isset($routes[$ptr][$this->hive['VERB']]) ||
($preflight && isset($routes[$ptr])) ||
isset($routes[$ptr=0]))
$route=$routes[$ptr];
if (!$route)
continue;
if (isset($route[$this->hive['VERB']]) && !$preflight) {
if ($this->hive['VERB']=='GET' &&
if ($this->hive['REROUTE_TRAILING_SLASH']===TRUE &&
$this->hive['VERB']=='GET' &&
preg_match('/.+\/$/',$this->hive['PATH']))
$this->reroute(substr($this->hive['PATH'],0,-1).
($this->hive['QUERY']?('?'.$this->hive['QUERY']):''));
@ -2068,7 +2156,7 @@ final class Base extends Prefab implements ArrayAccess {
array_merge([$match['lval']],
str_getcsv($cmd[1]=='config'?
$this->cast($match['rval']):
$match['rval']))
$match['rval'],",",'"', "\\"))
);
}
else {
@ -2091,7 +2179,7 @@ final class Base extends Prefab implements ArrayAccess {
// Mark quoted strings with 0x00 whitespace
str_getcsv(preg_replace(
'/(?<!\\\\)(")(.*?)\1/',
"\\1\x00\\2\\1",trim($rval)))
"\\1\x00\\2\\1",trim($rval)),",",'"', "\\")
);
preg_match('/^(?<section>[^:]+)(?:\:(?<func>.+))?/',
$sec,$parts);
@ -2358,7 +2446,11 @@ final class Base extends Prefab implements ArrayAccess {
@ini_set('magic_quotes_gpc',0);
@ini_set('register_globals',0);
// Intercept errors/exceptions; PHP5.3-compatible
$check=error_reporting((E_ALL|E_STRICT)&~(E_NOTICE|E_USER_NOTICE));
if (PHP_VERSION_ID >= 80400) {
$check = error_reporting((E_ALL) & ~(E_NOTICE | E_USER_NOTICE));
} else {
$check = error_reporting((E_ALL | E_STRICT) & ~(E_NOTICE | E_USER_NOTICE));
}
set_exception_handler(
function($obj) {
/** @var Exception $obj */
@ -2371,8 +2463,11 @@ final class Base extends Prefab implements ArrayAccess {
);
set_error_handler(
function($level,$text,$file,$line) {
if ($level & error_reporting())
$this->error(500,$text,NULL,$level);
if ($level & error_reporting()) {
$trace=$this->trace(null, false);
array_unshift($trace,['file'=>$file,'line'=>$line]);
$this->error(500,$text,$trace,$level);
}
}
);
if (!isset($_SERVER['SERVER_NAME']) || $_SERVER['SERVER_NAME']==='')
@ -2483,13 +2578,7 @@ final class Base extends Prefab implements ArrayAccess {
'CACHE'=>FALSE,
'CASELESS'=>TRUE,
'CLI'=>$cli,
'CORS'=>[
'headers'=>'',
'origin'=>FALSE,
'credentials'=>FALSE,
'expose'=>FALSE,
'ttl'=>0
],
'CORS'=>[],
'DEBUG'=>0,
'DIACRITICS'=>[],
'DNSBL'=>'',
@ -2520,6 +2609,7 @@ final class Base extends Prefab implements ArrayAccess {
'PACKAGE'=>self::PACKAGE,
'PARAMS'=>[],
'PATH'=>$path,
'REROUTE_TRAILING_SLASH'=>TRUE,
'PATTERN'=>NULL,
'PLUGINS'=>$this->fixslashes(__DIR__).'/',
'PORT'=>$port,
@ -2548,6 +2638,13 @@ final class Base extends Prefab implements ArrayAccess {
'VERSION'=>self::VERSION,
'XFRAME'=>'SAMEORIGIN'
];
$this->hive['CORS']+=[
'headers'=>'',
'origin'=>FALSE,
'credentials'=>FALSE,
'expose'=>FALSE,
'ttl'=>0
];
if (!headers_sent() && session_status()!=PHP_SESSION_ACTIVE) {
unset($jar['expire']);
session_cache_limiter('');
@ -2631,7 +2728,8 @@ class Cache extends Prefab {
$raw=xcache_get($ndx);
break;
case 'folder':
$raw=$fw->read($parts[1].$ndx);
$raw=$fw->read($parts[1]
.str_replace(['/','\\'],'',$ndx));
break;
}
if (!empty($raw)) {
@ -2911,7 +3009,7 @@ class View extends Prefab {
* @param $hive array
* @param $mime string
**/
protected function sandbox(array $hive=NULL,$mime=NULL) {
protected function sandbox(?array $hive=NULL,$mime=NULL) {
$fw=$this->fw;
$implicit=FALSE;
if (is_null($hive)) {
@ -2948,7 +3046,7 @@ class View extends Prefab {
* @param $hive array
* @param $ttl int
**/
function render($file,$mime='text/html',array $hive=NULL,$ttl=0) {
function render($file,$mime='text/html',?array $hive=NULL,$ttl=0) {
$fw=$this->fw;
$cache=Cache::instance();
foreach ($fw->split($fw->UI) as $dir) {
@ -3095,7 +3193,8 @@ class Preview extends View {
* @param $persist bool
* @param $escape bool
**/
function resolve($node,array $hive=NULL,$ttl=0,$persist=FALSE,$escape=NULL) {
function resolve($node,?array $hive=NULL,$ttl=0,$persist=FALSE,$escape=NULL) {
$hash=null;
$fw=$this->fw;
$cache=Cache::instance();
if ($escape!==NULL) {
@ -3156,7 +3255,7 @@ class Preview extends View {
* @param $hive array
* @param $ttl int
**/
function render($file,$mime='text/html',array $hive=NULL,$ttl=0) {
function render($file,$mime='text/html',?array $hive=NULL,$ttl=0) {
$fw=$this->fw;
$cache=Cache::instance();
if (!is_dir($tmp=$fw->TEMP))

View file

@ -399,8 +399,8 @@ class Agent {
if (is_bool($server->write($this->socket,$buf)))
return FALSE;
if (!in_array($op,[WS::Pong,WS::Close]) &&
isset($this->server->events['send']) &&
is_callable($func=$this->server->events['send']))
isset($this->server->events()['send']) &&
is_callable($func=$this->server->events()['send']))
$func($this,$op,$data);
return $data;
}
@ -446,8 +446,8 @@ class Agent {
case WS::Text:
$data=trim($data);
case WS::Binary:
if (isset($this->server->events['receive']) &&
is_callable($func=$this->server->events['receive']))
if (isset($this->server->events()['receive']) &&
is_callable($func=$this->server->events()['receive']))
$func($this,$op,$data);
break;
}
@ -459,8 +459,8 @@ class Agent {
* Destroy object
**/
function __destruct() {
if (isset($this->server->events['disconnect']) &&
is_callable($func=$this->server->events['disconnect']))
if (isset($this->server->events()['disconnect']) &&
is_callable($func=$this->server->events()['disconnect']))
$func($this);
}
@ -479,8 +479,8 @@ class Agent {
$this->uri=$uri;
$this->headers=$hdrs;
if (isset($server->events['connect']) &&
is_callable($func=$server->events['connect']))
if (isset($server->events()['connect']) &&
is_callable($func=$server->events()['connect']))
$func($this);
}

View file

@ -4,7 +4,7 @@
"homepage": "http://fatfreeframework.com/",
"license": "GPL-3.0",
"require": {
"php": ">=5.4"
"php": ">=7.2"
},
"autoload": {
"classmap": ["."]

View file

@ -64,7 +64,7 @@ abstract class Cursor extends \Magic implements \IteratorAggregate {
* @param $options array
* @param $ttl int
**/
abstract function find($filter=NULL,array $options=NULL,$ttl=0);
abstract function find($filter=NULL,?array $options=NULL,$ttl=0);
/**
* Count records that match criteria
@ -73,7 +73,7 @@ abstract class Cursor extends \Magic implements \IteratorAggregate {
* @param $options array
* @param $ttl int
**/
abstract function count($filter=NULL,array $options=NULL,$ttl=0);
abstract function count($filter=NULL,?array $options=NULL,$ttl=0);
/**
* Insert new record
@ -126,7 +126,7 @@ abstract class Cursor extends \Magic implements \IteratorAggregate {
* @param $options array
* @param $ttl int
**/
function findone($filter=NULL,array $options=NULL,$ttl=0) {
function findone($filter=NULL,?array $options=NULL,$ttl=0) {
if (!$options)
$options=[];
// Override limit
@ -147,7 +147,7 @@ abstract class Cursor extends \Magic implements \IteratorAggregate {
* @param $bounce bool
**/
function paginate(
$pos=0,$size=10,$filter=NULL,array $options=NULL,$ttl=0,$bounce=TRUE) {
$pos=0,$size=10,$filter=NULL,?array $options=NULL,$ttl=0,$bounce=TRUE) {
$total=$this->count($filter,$options,$ttl);
$count=(int)ceil($total/$size);
if ($bounce)
@ -169,12 +169,12 @@ abstract class Cursor extends \Magic implements \IteratorAggregate {
/**
* Map to first record that matches criteria
* @return array|FALSE
* @return \DB\SQL\Mapper|FALSE
* @param $filter string|array
* @param $options array
* @param $ttl int
**/
function load($filter=NULL,array $options=NULL,$ttl=0) {
function load($filter=NULL,?array $options=NULL,$ttl=0) {
$this->reset();
return ($this->query=$this->find($filter,$options,$ttl)) &&
$this->skip(0)?$this->query[$this->ptr]:FALSE;

View file

@ -78,13 +78,16 @@ class Jig {
* @param $file string
* @param $data array
**/
function write($file,array $data=NULL) {
function write($file,?array $data=NULL) {
if (!$this->dir || $this->lazy)
return count($this->data[$file]=$data);
$fw=\Base::instance();
switch ($this->format) {
case self::FORMAT_JSON:
$out=json_encode($data,JSON_PRETTY_PRINT);
if(version_compare(PHP_VERSION, '7.2.0') >= 0)
$out=json_encode($data,JSON_PRETTY_PRINT | JSON_INVALID_UTF8_IGNORE);
else
$out=json_encode($data,JSON_PRETTY_PRINT | JSON_PARTIAL_OUTPUT_ON_ERROR);
break;
case self::FORMAT_Serialized:
$out=$fw->serialize($data);

View file

@ -156,7 +156,7 @@ class Mapper extends \DB\Cursor {
* @param $ttl int|array
* @param $log bool
**/
function find($filter=NULL,array $options=NULL,$ttl=0,$log=TRUE) {
function find($filter=NULL,?array $options=NULL,$ttl=0,$log=TRUE) {
if (!$options)
$options=[];
$options+=[
@ -352,7 +352,7 @@ class Mapper extends \DB\Cursor {
* @param $options array
* @param $ttl int|array
**/
function count($filter=NULL,array $options=NULL,$ttl=0) {
function count($filter=NULL,?array $options=NULL,$ttl=0) {
$now=microtime(TRUE);
$out=count($this->find($filter,$options,$ttl,FALSE));
$this->db->jot('('.sprintf('%.1f',1e3*(microtime(TRUE)-$now)).'ms) '.

View file

@ -22,6 +22,9 @@
namespace DB\Jig;
use ReturnTypeWillChange;
use SessionAdapter;
//! Jig-managed session handler
class Session extends Mapper {
@ -43,15 +46,17 @@ class Session extends Mapper {
* @param $path string
* @param $name string
**/
function open($path,$name) {
return TRUE;
}
function open(string $path, string $name): bool
{
return TRUE;
}
/**
* Close session
* @return TRUE
**/
function close() {
function close(): bool
{
$this->reset();
$this->sid=NULL;
return TRUE;
@ -59,10 +64,12 @@ class Session extends Mapper {
/**
* Return session data in serialized format
* @return string
* @return string|false
* @param $id string
**/
function read($id) {
#[ReturnTypeWillChange]
function read($id)
{
$this->load(['@session_id=?',$this->sid=$id]);
if ($this->dry())
return '';
@ -87,7 +94,8 @@ class Session extends Mapper {
* @param $id string
* @param $data string
**/
function write($id,$data) {
function write(string $id, string $data): bool
{
$this->set('session_id',$id);
$this->set('data',$data);
$this->set('ip',$this->_ip);
@ -102,19 +110,19 @@ class Session extends Mapper {
* @return TRUE
* @param $id string
**/
function destroy($id) {
function destroy($id): bool
{
$this->erase(['@session_id=?',$id]);
return TRUE;
}
/**
* Garbage collector
* @return TRUE
* @param $max int
**/
function cleanup($max) {
$this->erase(['@stamp+?<?',$max,time()]);
return TRUE;
#[ReturnTypeWillChange]
function gc(int $max_lifetime): int
{
return (int) $this->erase(['@stamp+?<?',$max_lifetime,time()]);
}
/**
@ -169,14 +177,19 @@ class Session extends Mapper {
function __construct(\DB\Jig $db,$file='sessions',$onsuspect=NULL,$key=NULL) {
parent::__construct($db,$file);
$this->onsuspect=$onsuspect;
session_set_save_handler(
[$this,'open'],
[$this,'close'],
[$this,'read'],
[$this,'write'],
[$this,'destroy'],
[$this,'cleanup']
);
if (version_compare(PHP_VERSION, '8.4.0')>=0) {
// TODO: remove this when php7 support is dropped
session_set_save_handler(new SessionAdapter($this));
} else {
session_set_save_handler(
[$this,'open'],
[$this,'close'],
[$this,'read'],
[$this,'write'],
[$this,'destroy'],
[$this,'gc']
);
}
register_shutdown_function('session_commit');
$fw=\Base::instance();
$headers=$fw->HEADERS;

View file

@ -130,7 +130,7 @@ class Mongo {
* @param $dbname string
* @param $options array
**/
function __construct($dsn,$dbname,array $options=NULL) {
function __construct($dsn,$dbname,?array $options=NULL) {
$this->uuid=\Base::instance()->hash($this->dsn=$dsn);
if ($this->legacy=class_exists('\MongoClient')) {
$this->db=new \MongoDB(new \MongoClient($dsn,$options?:[]),$dbname);

View file

@ -121,7 +121,7 @@ class Mapper extends \DB\Cursor {
* @param $options array
* @param $ttl int|array
**/
function select($fields=NULL,$filter=NULL,array $options=NULL,$ttl=0) {
function select($fields=NULL,$filter=NULL,?array $options=NULL,$ttl=0) {
if (!$options)
$options=[];
$options+=[
@ -199,7 +199,7 @@ class Mapper extends \DB\Cursor {
* @param $options array
* @param $ttl int|array
**/
function find($filter=NULL,array $options=NULL,$ttl=0) {
function find($filter=NULL,?array $options=NULL,$ttl=0) {
if (!$options)
$options=[];
$options+=[
@ -218,7 +218,7 @@ class Mapper extends \DB\Cursor {
* @param $options array
* @param $ttl int|array
**/
function count($filter=NULL,array $options=NULL,$ttl=0) {
function count($filter=NULL,?array $options=NULL,$ttl=0) {
$fw=\Base::instance();
$cache=\Cache::instance();
$tag='';

View file

@ -22,6 +22,9 @@
namespace DB\Mongo;
use ReturnTypeWillChange;
use SessionAdapter;
//! MongoDB-managed session handler
class Session extends Mapper {
@ -43,7 +46,8 @@ class Session extends Mapper {
* @param $path string
* @param $name string
**/
function open($path,$name) {
function open(string $path, string $name): bool
{
return TRUE;
}
@ -51,7 +55,8 @@ class Session extends Mapper {
* Close session
* @return TRUE
**/
function close() {
function close(): bool
{
$this->reset();
$this->sid=NULL;
return TRUE;
@ -62,7 +67,9 @@ class Session extends Mapper {
* @return string
* @param $id string
**/
function read($id) {
#[ReturnTypeWillChange]
function read(string $id)
{
$this->load(['session_id'=>$this->sid=$id]);
if ($this->dry())
return '';
@ -87,7 +94,8 @@ class Session extends Mapper {
* @param $id string
* @param $data string
**/
function write($id,$data) {
function write(string $id, string $data): bool
{
$this->set('session_id',$id);
$this->set('data',$data);
$this->set('ip',$this->_ip);
@ -102,19 +110,19 @@ class Session extends Mapper {
* @return TRUE
* @param $id string
**/
function destroy($id) {
function destroy($id): bool
{
$this->erase(['session_id'=>$id]);
return TRUE;
}
/**
* Garbage collector
* @return TRUE
* @param $max int
**/
function cleanup($max) {
$this->erase(['$where'=>'this.stamp+'.$max.'<'.time()]);
return TRUE;
#[ReturnTypeWillChange]
function gc(int $max_lifetime): int
{
return (int) $this->erase(['$where'=>'this.stamp+'.$max_lifetime.'<'.time()]);
}
/**
@ -169,14 +177,19 @@ class Session extends Mapper {
function __construct(\DB\Mongo $db,$table='sessions',$onsuspect=NULL,$key=NULL) {
parent::__construct($db,$table);
$this->onsuspect=$onsuspect;
session_set_save_handler(
[$this,'open'],
[$this,'close'],
[$this,'read'],
[$this,'write'],
[$this,'destroy'],
[$this,'cleanup']
);
if (version_compare(PHP_VERSION, '8.4.0')>=0) {
// TODO: remove this when php7 support is dropped
session_set_save_handler(new SessionAdapter($this));
} else {
session_set_save_handler(
[$this,'open'],
[$this,'close'],
[$this,'read'],
[$this,'write'],
[$this,'destroy'],
[$this,'gc']
);
}
register_shutdown_function('session_commit');
$fw=\Base::instance();
$headers=$fw->HEADERS;

View file

@ -124,8 +124,8 @@ class SQL {
function value($type,$val) {
switch ($type) {
case self::PARAM_FLOAT:
if (!is_string($val))
$val=str_replace(',','.',$val);
if (!is_string($val) && $val !== NULL)
$val=str_replace(',','.',(string) $val);
return $val;
case \PDO::PARAM_NULL:
return NULL;
@ -319,7 +319,7 @@ class SQL {
$cache=\Cache::instance();
if ($fw->CACHE && $ttl &&
($cached=$cache->exists(
$hash=$fw->hash($this->dsn.$table).'.schema',$result)) &&
$hash=$fw->hash($this->dsn.$table.(is_array($fields) ? implode(',',$fields) : $fields)).'.schema',$result)) &&
$cached[0]+$ttl>microtime(TRUE))
return $result;
if (strpos($table,'.'))
@ -375,6 +375,7 @@ class SQL {
('AND K.TABLE_CATALOG=T.TABLE_CATALOG '):'').
'WHERE '.
'C.TABLE_NAME='.$this->quote($table).
(empty($schema) ? '' : ' AND C.TABLE_SCHEMA='.$this->quote($schema)).
($this->dbname?
(' AND C.TABLE_CATALOG='.
$this->quote($this->dbname)):''),
@ -535,7 +536,7 @@ class SQL {
* @param $pw string
* @param $options array
**/
function __construct($dsn,$user=NULL,$pw=NULL,array $options=NULL) {
function __construct($dsn,$user=NULL,$pw=NULL,?array $options=NULL) {
$fw=\Base::instance();
$this->uuid=$fw->hash($this->dsn=$dsn);
if (preg_match('/^.+?(?:dbname|database)=(.+?)(?=;|$)/is',$dsn,$parts))

View file

@ -149,13 +149,11 @@ class Mapper extends \DB\Cursor {
* @return mixed
* @param $func string
* @param $args array
* @deprecated (this is only used for custom dynamic properties that are callables
**/
function __call($func,$args) {
return call_user_func_array(
(array_key_exists($func,$this->props)?
$this->props[$func]:
$this->$func),$args
);
$callable = (array_key_exists($func,$this->props) ? $this->props[$func] : $this->$func);
return $callable ? call_user_func_array($callable,$args) : null;
}
/**
@ -207,7 +205,7 @@ class Mapper extends \DB\Cursor {
* @param $filter string|array
* @param $options array
**/
function stringify($fields,$filter=NULL,array $options=NULL) {
function stringify($fields,$filter=NULL,?array $options=NULL) {
if (!$options)
$options=[];
$options+=[
@ -222,7 +220,7 @@ class Mapper extends \DB\Cursor {
if (isset($this->as))
$sql.=' AS '.$this->db->quotekey($this->as);
$args=[];
if (is_array($filter)) {
if (is_array($filter) && !empty($filter)) {
$args=isset($filter[1]) && is_array($filter[1])?
$filter[1]:
array_slice($filter,1,NULL,TRUE);
@ -305,7 +303,7 @@ class Mapper extends \DB\Cursor {
* @param $options array
* @param $ttl int|array
**/
function select($fields,$filter=NULL,array $options=NULL,$ttl=0) {
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=[];
@ -331,7 +329,7 @@ class Mapper extends \DB\Cursor {
* @param $options array
* @param $ttl int|array
**/
function find($filter=NULL,array $options=NULL,$ttl=0) {
function find($filter=NULL,?array $options=NULL,$ttl=0) {
if (!$options)
$options=[];
$options+=[
@ -357,7 +355,7 @@ class Mapper extends \DB\Cursor {
* @param $options array
* @param $ttl int|array
**/
function count($filter=NULL,array $options=NULL,$ttl=0) {
function count($filter=NULL,?array $options=NULL,$ttl=0) {
$adhoc=[];
// with grouping involved, we need to wrap the actualy query and count the results
if ($subquery_mode=($options && !empty($options['group']))) {

View file

@ -22,6 +22,9 @@
namespace DB\SQL;
use ReturnTypeWillChange;
use SessionAdapter;
//! SQL-managed session handler
class Session extends Mapper {
@ -43,7 +46,8 @@ class Session extends Mapper {
* @param $path string
* @param $name string
**/
function open($path,$name) {
function open(string $path, string $name): bool
{
return TRUE;
}
@ -51,7 +55,8 @@ class Session extends Mapper {
* Close session
* @return TRUE
**/
function close() {
function close(): bool
{
$this->reset();
$this->sid=NULL;
return TRUE;
@ -59,10 +64,12 @@ class Session extends Mapper {
/**
* Return session data in serialized format
* @return string
* @return string|false
* @param $id string
**/
function read($id) {
#[ReturnTypeWillChange]
function read(string $id)
{
$this->load(['session_id=?',$this->sid=$id]);
if ($this->dry())
return '';
@ -86,7 +93,8 @@ class Session extends Mapper {
* @param $id string
* @param $data string
**/
function write($id,$data) {
function write(string $id, string $data): bool
{
$this->set('session_id',$id);
$this->set('data',$data);
$this->set('ip',$this->_ip);
@ -101,19 +109,19 @@ class Session extends Mapper {
* @return TRUE
* @param $id string
**/
function destroy($id) {
function destroy($id): bool
{
$this->erase(['session_id=?',$id]);
return TRUE;
}
/**
* Garbage collector
* @return TRUE
* @param $max int
**/
function cleanup($max) {
$this->erase(['stamp+?<?',$max,time()]);
return TRUE;
#[ReturnTypeWillChange]
function gc(int $max_lifetime): int
{
return (int) $this->erase(['stamp+?<?',$max_lifetime,time()]);
}
/**
@ -194,14 +202,19 @@ class Session extends Mapper {
}
parent::__construct($db,$table);
$this->onsuspect=$onsuspect;
session_set_save_handler(
[$this,'open'],
[$this,'close'],
[$this,'read'],
[$this,'write'],
[$this,'destroy'],
[$this,'cleanup']
);
if (version_compare(PHP_VERSION, '8.4.0')>=0) {
// TODO: remove this when php7 support is dropped
session_set_save_handler(new SessionAdapter($this));
} else {
session_set_save_handler(
[$this,'open'],
[$this,'close'],
[$this,'read'],
[$this,'write'],
[$this,'destroy'],
[$this,'gc']
);
}
register_shutdown_function('session_commit');
$fw=\Base::instance();
$headers=$fw->HEADERS;

View file

@ -414,7 +414,7 @@ class Image {
}
$fw=Base::instance();
foreach ($fw->split($path?:$fw->UI.';./') as $dir)
if (is_file($path=$dir.$font)) {
if (is_file($path=realpath($dir.$font))) {
$seed=strtoupper(substr(
$ssl?bin2hex(openssl_random_pseudo_bytes($len)):uniqid(),
-$len));

View file

@ -467,8 +467,8 @@ class Markdown extends Prefab {
'fence'=>'/^`{3}\h*(\w+)?.*?[^\n]*\n+(.+?)`{3}[^\n]*'.
'(?:\n+|$)/s',
'hr'=>'/^\h*[*_\-](?:\h?[\*_\-]){2,}\h*(?:\n+|$)/',
'atx'=>'/^\h*(#{1,6})\h?(.+?)\h*(?:#.*)?(?:\n+|$)/',
'setext'=>'/^\h*(.+?)\h*\n([=\-])+\h*(?:\n+|$)/',
'atx'=>'/^\h*(#{1,6})\h?(.+?)\h*(?:#.*)?(?:\n+|$)/u',
'setext'=>'/^\h*(.+?)\h*\n([=\-])+\h*(?:\n+|$)/u',
'li'=>'/^(?:(?:[*+\-]|\d+\.)\h.+?(?:\n+|$)'.
'(?:(?: {4}|\t)+.+?(?:\n+|$))*)+/s',
'raw'=>'/^((?:<!--.+?-->|'.

View file

@ -45,7 +45,8 @@ class Session extends Magic {
* @param $path string
* @param $name string
**/
function open($path,$name) {
function open(string $path, string $name): bool
{
return TRUE;
}
@ -53,7 +54,8 @@ class Session extends Magic {
* Close session
* @return TRUE
**/
function close() {
function close(): bool
{
$this->sid=NULL;
$this->_data=[];
return TRUE;
@ -61,10 +63,12 @@ class Session extends Magic {
/**
* Return session data in serialized format
* @return string
* @return false|string
* @param $id string
**/
function read($id) {
#[ReturnTypeWillChange]
function read(string $id)
{
$this->sid=$id;
if (!$data=$this->_cache->get($id.'.@'))
return '';
@ -85,11 +89,9 @@ class Session extends Magic {
/**
* Write session data
* @return TRUE
* @param $id string
* @param $data string
**/
function write($id,$data) {
*/
function write(string $id, string $data): bool
{
$fw=Base::instance();
$jar=$fw->JAR;
$this->_cache->set($id.'.@',
@ -106,21 +108,20 @@ class Session extends Magic {
/**
* Destroy session
* @return TRUE
* @param $id string
**/
function destroy($id) {
*/
function destroy(string $id): bool
{
$this->_cache->clear($id.'.@');
return TRUE;
}
/**
* Garbage collector
* @return TRUE
* @param $max int
**/
function cleanup($max) {
$this->_cache->reset('.@',$max);
#[ReturnTypeWillChange]
function gc(int $max_lifetime)
{
$this->_cache->reset('.@',$max_lifetime);
return TRUE;
}
@ -175,14 +176,19 @@ class Session extends Magic {
function __construct($onsuspect=NULL,$key=NULL,$cache=null) {
$this->onsuspect=$onsuspect;
$this->_cache=$cache?:Cache::instance();
session_set_save_handler(
[$this,'open'],
[$this,'close'],
[$this,'read'],
[$this,'write'],
[$this,'destroy'],
[$this,'cleanup']
);
if (version_compare(PHP_VERSION, '8.4.0')>=0) {
// TODO: remove this when php7 support is dropped
session_set_save_handler(new SessionAdapter($this));
} else {
session_set_save_handler(
[$this,'open'],
[$this,'close'],
[$this,'read'],
[$this,'write'],
[$this,'destroy'],
[$this,'gc']
);
}
register_shutdown_function('session_commit');
$fw=\Base::instance();
$headers=$fw->HEADERS;

46
vendor/fatfree/sessionadapter.php vendored Normal file
View file

@ -0,0 +1,46 @@
<?php
/**
* To be removed once the legacy session handlers are reworked when php 7 support is dropped
*/
class SessionAdapter implements \SessionHandlerInterface
{
protected $_handler;
public function __construct($handler)
{
$this->_handler = $handler;
}
public function close(): bool
{
return $this->_handler->close();
}
public function destroy(string $id): bool
{
return $this->_handler->destroy($id);
}
#[ReturnTypeWillChange]
public function gc(int $max_lifetime): int
{
return $this->_handler->gc($max_lifetime);
}
public function open(string $path, string $name): bool
{
return $this->_handler->open($path, $name);
}
#[ReturnTypeWillChange]
public function read(string $id): string
{
return $this->_handler->read($id);
}
public function write(string $id, string $data): bool
{
return $this->_handler->write($id, $data);
}
}

View file

@ -275,9 +275,9 @@ class Template extends Preview {
if (preg_match('/^(.{0,'.$w.'}?)<(\/?)(?:F3:)?'.
'('.$this->tags.')\b((?:\s+[\w.:@!\-]+'.
'(?:\h*=\h*(?:"(?:.*?)"|\'(?:.*?)\'))?|'.
'\h*\{\{.+?\}\})*)\h*(\/?)>/is',
'\h*\{\{.+?\}\})*)\s*(\/?)>/is',
substr($text,$ptr),$match)) {
if (strlen($tmp) || $match[1])
if (strlen($tmp) || isset($match[1]))
$tree[]=$tmp.$match[1];
// Element node
if ($match[2]) {
@ -286,10 +286,10 @@ class Template extends Preview {
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])) {
array_key_exists($k=strtolower($match[3]),$item) &&
!isset($item[$k][0])) {
// Start tag found
$tree[$i][$match[3]]+=array_reverse($stack);
$tree[$i][$k]+=array_reverse($stack);
$tree=array_slice($tree,0,$i+1);
break;
}
@ -298,7 +298,7 @@ class Template extends Preview {
}
else {
// Start tag
$node=&$tree[][$match[3]];
$node=&$tree[][strtolower($match[3])];
$node=[];
if ($match[4]) {
// Process attributes

View file

@ -359,7 +359,8 @@ class Web extends Prefab {
curl_setopt($curl,CURLOPT_POSTFIELDS,$options['content']);
if (isset($options['proxy']))
curl_setopt($curl,CURLOPT_PROXY,$options['proxy']);
curl_setopt($curl,CURLOPT_ENCODING,'gzip,deflate');
curl_setopt($curl,CURLOPT_ENCODING,isset($options['encoding'])
? $options['encoding'] : 'gzip,deflate');
$timeout=isset($options['timeout'])?
$options['timeout']:
ini_get('default_socket_timeout');
@ -591,7 +592,7 @@ class Web extends Prefab {
* @param $url string
* @param $options array
**/
function request($url,array $options=NULL) {
function request($url,?array $options=NULL) {
$fw=Base::instance();
$parts=parse_url($url);
if (empty($parts['scheme'])) {
@ -617,7 +618,8 @@ class Web extends Prefab {
}
$this->subst($options['header'],
[
'Accept-Encoding: gzip,deflate',
'Accept-Encoding: '.(isset($options['encoding'])?
$options['encoding']:'gzip,deflate'),
'User-Agent: '.(isset($options['user_agent'])?
$options['user_agent']:
'Mozilla/5.0 (compatible; '.php_uname('s').')'),

View file

@ -39,7 +39,7 @@ class OAuth2 extends \Magic {
**/
function uri($endpoint,$query=TRUE) {
return $endpoint.($query?('?'.
http_build_query($this->args,null,'&',$this->enc_type)):'');
http_build_query($this->args,'','&',$this->enc_type)):'');
}
/**
@ -53,7 +53,7 @@ class OAuth2 extends \Magic {
$web=\Web::instance();
$options=[
'method'=>$method,
'content'=>http_build_query($this->args,null,'&',$this->enc_type),
'content'=>http_build_query($this->args,'','&',$this->enc_type),
'header'=>['Accept: application/json']
];
if ($token)

View file

@ -141,7 +141,7 @@ class OpenID extends \Magic {
* @param $attr array
* @param $reqd string|array
**/
function auth($proxy=NULL,$attr=[],array $reqd=NULL) {
function auth($proxy=NULL,$attr=[],?array $reqd=NULL) {
$fw=\Base::instance();
$root=$fw->SCHEME.'://'.$fw->HOST;
if (empty($this->args['trust_root']))

View file

@ -69,7 +69,7 @@ class Pingback extends \Prefab {
$parts['host']==$fw->HOST) {
$req=$web->request($source);
$doc=new \DOMDocument('1.0',$fw->ENCODING);
$doc->stricterrorchecking=FALSE;
$doc->strictErrorChecking=FALSE;
$doc->recover=TRUE;
if (@$doc->loadhtml($req['body'])) {
// Parse anchor tags