diff --git a/php/elFinder.class.php b/php/elFinder.class.php
index 14f6e4ab7..72c3e6f73 100644
--- a/php/elFinder.class.php
+++ b/php/elFinder.class.php
@@ -39,9 +39,17 @@ class elFinder {
*/
public static $locale = '';
+ /**
+ * elFinder session wrapper object
+ *
+ * @var elFinderSessionInterface
+ */
+ protected $session;
+
/**
* elFinder global sessionCacheKey
*
+ * @deprecated
* @var string
*/
public static $sessionCacheKey = '';
@@ -49,6 +57,7 @@ class elFinder {
/**
* Is session closed
*
+ * @deprecated
* @var bool
*/
private static $sessionClosed = false;
@@ -72,6 +81,8 @@ class elFinder {
/**
* Session key of net mount volumes
+ *
+ * @deprecated
* @var string
*/
protected $netVolumesSessionKey = '';
@@ -289,8 +300,28 @@ class elFinder {
* @author Dmitry (dio) Levashov
**/
public function __construct($opts) {
+ if (! interface_exists('elFinderSessionAbstarct')) {
+ include_once dirname(__FILE__).'/elFinderSessionInterface.php';
+ }
+
+ // session handler
+ if (!empty($opts['session']) && $opts['session'] instanceof elFinderSessionInterface) {
+ $this->session = $opts['session'];
+ } else {
+ $sessionOpts = array(
+ 'base64encode' => !empty($opts['base64encodeSessionData']),
+ 'keys' => array(
+ 'default' => !empty($opts['sessionCacheKey']) ? $opts['sessionCacheKey'] : 'elFinderCaches',
+ 'netvolume' => !empty($opts['netVolumesSessionKey'])? $opts['netVolumesSessionKey'] : 'elFinderNetVolumes'
+ )
+ );
+ if (! class_exists('elFinderSession')) {
+ include_once dirname(__FILE__) . '/elFinderSession.php';
+ }
+ $this->session = new elFinderSession($sessionOpts);
+ }
// try session start | restart
- @session_start();
+ $this->session->start();
$sessionUseCmds = array();
if (isset($opts['sessionUseCmds']) && is_array($opts['sessionUseCmds'])) {
@@ -308,23 +339,22 @@ class elFinder {
$this->sessionUseCmds = array_flip($sessionUseCmds);
$this->timeout = (isset($opts['timeout']) ? $opts['timeout'] : 0);
$this->uploadTempPath = (isset($opts['uploadTempPath']) ? $opts['uploadTempPath'] : '');
- $this->netVolumesSessionKey = !empty($opts['netVolumesSessionKey'])? $opts['netVolumesSessionKey'] : 'elFinderNetVolumes';
$this->callbackWindowURL = (isset($opts['callbackWindowURL']) ? $opts['callbackWindowURL'] : '');
- self::$sessionCacheKey = !empty($opts['sessionCacheKey']) ? $opts['sessionCacheKey'] : 'elFinderCaches';
elFinder::$commonTempPath = (isset($opts['commonTempPath']) ? $opts['commonTempPath'] : './.tmp');
if (!is_writable(elFinder::$commonTempPath)) {
elFinder::$commonTempPath = '';
}
$this->maxArcFilesSize = isset($opts['maxArcFilesSize'])? intval($opts['maxArcFilesSize']) : 0;
+ // deprecated settings
+ $this->netVolumesSessionKey = !empty($opts['netVolumesSessionKey'])? $opts['netVolumesSessionKey'] : 'elFinderNetVolumes';
+ self::$sessionCacheKey = !empty($opts['sessionCacheKey']) ? $opts['sessionCacheKey'] : 'elFinderCaches';
+
// check session cache
$_optsMD5 = md5(json_encode($opts['roots']));
- if (! isset($_SESSION[self::$sessionCacheKey]) || $_SESSION[self::$sessionCacheKey]['_optsMD5'] !== $_optsMD5) {
- $_SESSION[self::$sessionCacheKey] = array(
- '_optsMD5' => $_optsMD5
- );
+ if ($this->session->get('_optsMD5') !== $_optsMD5) {
+ $this->session->set('_optsMD5', $_optsMD5);
}
- self::$base64encodeSessionData = !empty($opts['base64encodeSessionData']);
// setlocale and global locale regists to elFinder::locale
self::$locale = !empty($opts['locale']) ? $opts['locale'] : 'en_US.UTF-8';
@@ -385,6 +415,8 @@ class elFinder {
if ($this->maxArcFilesSize && (empty($o['maxArcFilesSize']) || $this->maxArcFilesSize < $o['maxArcFilesSize'])) {
$o['maxArcFilesSize'] = $this->maxArcFilesSize;
}
+ // pass session handler
+ $volume->setSession($this->session);
if ($volume->mount($o)) {
// unique volume id (ends on "_") - used as prefix to files hash
$id = $volume->id();
@@ -410,6 +442,15 @@ class elFinder {
$this->loaded = !empty($this->default);
}
+ /**
+ * Return elFinder session wrapper instance
+ *
+ * @return object elFinderSessionInterface
+ **/
+ public function getSession() {
+ return $this->session;
+ }
+
/**
* Return true if fm init correctly
*
@@ -527,17 +568,17 @@ class elFinder {
private function session_expires() {
- if (!isset($_SESSION[self::$sessionCacheKey . ':LAST_ACTIVITY'])) {
- $_SESSION[self::$sessionCacheKey . ':LAST_ACTIVITY'] = time();
+ if (! $last = $this->session->get(':LAST_ACTIVITY')) {
+ $this->session->set(':LAST_ACTIVITY', time());
return false;
}
- if ( ($this->timeout > 0) && (time() - $_SESSION[self::$sessionCacheKey . ':LAST_ACTIVITY'] > $this->timeout) ) {
+ if ( ($this->timeout > 0) && (time() - $last > $this->timeout) ) {
return true;
}
- $_SESSION[self::$sessionCacheKey . ':LAST_ACTIVITY'] = time();
- return false;
+ $this->session->set(':LAST_ACTIVITY', time());
+ return false;
}
/**
@@ -578,8 +619,9 @@ class elFinder {
}
// unlock session data for multiple access
- if ($this->sessionCloseEarlier && $args['sessionCloseEarlier'] && session_id()) {
- session_write_close();
+ if ($this->sessionCloseEarlier && $args['sessionCloseEarlier']) {
+ $this->session->close();
+ // deprecated property
elFinder::$sessionClosed = true;
}
@@ -682,10 +724,8 @@ class elFinder {
* @author Dmitry (dio) Levashov
*/
protected function getNetVolumes() {
- if (isset($_SESSION[$this->netVolumesSessionKey])) {
- if ($data = elFinder::sessionDataDecode($_SESSION[$this->netVolumesSessionKey], 'array')) {
- return $data;
- }
+ if ($data = $this->session->get('netvolume', array())) {
+ return $data;
}
return array();
}
@@ -698,10 +738,7 @@ class elFinder {
* @author Dmitry (dio) Levashov
*/
protected function saveNetVolumes($volumes) {
- // try session restart
- @session_start();
- $_SESSION[$this->netVolumesSessionKey] = elFinder::sessionDataEncode($volumes);
- elFinder::sessionWrite();
+ $this->session->set('netvolume', $volumes);
}
/**
@@ -765,9 +802,6 @@ class elFinder {
}
protected function netmount($args) {
- // try session restart
- @session_start();
-
$options = array();
$protocol = $args['protocol'];
@@ -814,6 +848,9 @@ class elFinder {
$volume = new $class();
+ // pass session handler
+ $volume->setSession($this->session);
+
if (method_exists($volume, 'netmountPrepare')) {
$options = $volume->netmountPrepare($options);
if (isset($options['exit'])) {
@@ -2647,6 +2684,7 @@ class elFinder {
/**
* serialize and base64_encode of session data (If needed)
*
+ * @deprecated
* @param mixed $var target variable
* @author Naoki Sawada
*/
@@ -2660,6 +2698,7 @@ class elFinder {
/**
* base64_decode and unserialize of session data (If needed)
*
+ * @deprecated
* @param mixed $var target variable
* @param bool $checkIs data type for check (array|string|object|int)
* @author Naoki Sawada
@@ -2697,12 +2736,11 @@ class elFinder {
/**
* Call session_write_close() if session is restarted
*
+ * @deprecated
* @return void
*/
public static function sessionWrite() {
- if (elFinder::$sessionClosed) {
- session_write_close();
- }
+ $this->session->close();
}
/**
diff --git a/php/elFinderConnector.class.php b/php/elFinderConnector.class.php
index 14b4da246..b30c41d83 100644
--- a/php/elFinderConnector.class.php
+++ b/php/elFinderConnector.class.php
@@ -184,7 +184,7 @@ class elFinderConnector {
}
// unlock session data for multiple access
- session_id() && session_write_close();
+ $this->elFinder->getSession()->close();
// client disconnect should abort
ignore_user_abort(false);
diff --git a/php/elFinderSession.php b/php/elFinderSession.php
new file mode 100644
index 000000000..63934dd3f
--- /dev/null
+++ b/php/elFinderSession.php
@@ -0,0 +1,199 @@
+ false,
+ 'keys' => array(
+ 'default' => 'elFinderCaches',
+ 'netvolume' => 'elFinderNetVolumes'
+ )
+ );
+
+ public function __construct($opts)
+ {
+ $this->opts = array_merge($this->opts, $opts);
+ $this->base64encode = !empty($this->opts['base64encode']);
+ $this->keys = $this->opts['keys'];
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function start()
+ {
+ @session_start();
+ $this->started = session_id()? true : false;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function close()
+ {
+ if ($this->started) {
+ session_write_close();
+ }
+ $this->started = false;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get($key, $empty = null)
+ {
+ $closed = false;
+ if (! $this->started) {
+ $closed = true;
+ $this->start();
+ }
+
+ $data = null;
+
+ if ($this->started) {
+ $session =& $this->getSessionRef($key);
+ $data = $session;
+ if ($data && $this->base64encode) {
+ $data = $this->decodeData($data);
+ }
+ }
+
+ $checkFn = null;
+ if (! is_null($empty)) {
+ if (is_string($empty)) {
+ $checkFn = 'is_string';
+ } elseif (is_array($empty)) {
+ $checkFn = 'is_array';
+ } elseif (is_object($empty)) {
+ $checkFn = 'is_object';
+ } elseif (is_float($empty)) {
+ $checkFn = 'is_float';
+ } elseif (is_int($empty)) {
+ $checkFn = 'is_int';
+ }
+ }
+
+ if (is_null($data) || ($checkFn && ! $checkFn($data))) {
+ $session = $data = $empty;
+ }
+
+ if ($closed) {
+ $this->close();
+ }
+
+ return $data;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function set($key, $data)
+ {
+ $closed = false;
+ if (! $this->started) {
+ $closed = true;
+ $this->start();
+ }
+ $session =& $this->getSessionRef($key);
+ if ($this->base64encode) {
+ $data = $this->encodeData($data);
+ }
+ $session = $data;
+
+ if ($closed) {
+ $this->close();
+ }
+
+ return $this;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function remove($key)
+ {
+ $session =& $this->getSessionRef($key);
+ unset($session);
+
+ return $this;
+ }
+
+ protected function & getSessionRef($key)
+ {
+ $session = null;
+ if ($this->started) {
+ list($cat, $name) = array_pad(explode('.', $key, 2), 2, null);
+ if (is_null($name)) {
+ if (! isset($this->keys[$cat])) {
+ $name = $cat;
+ $cat = 'default';
+ }
+ }
+ if (isset($this->keys[$cat])) {
+ $cat = $this->keys[$cat];
+ } else {
+ $name = $cat . '.' . $name;
+ $cat = $this->keys['default'];
+ }
+ if (is_null($name)) {
+ if (! isset($_SESSION[$cat])) {
+ $_SESSION[$cat] = null;
+ }
+ $session =& $_SESSION[$cat];
+ } else {
+ if (! isset($_SESSION[$cat]) || ! is_array($_SESSION[$cat])) {
+ $_SESSION[$cat] = array();
+ }
+ if (! isset($_SESSION[$cat][$name])) {
+ $_SESSION[$cat][$name] = null;
+ }
+ $session =& $_SESSION[$cat][$name];
+ }
+ }
+ return $session;
+ }
+
+ protected function encodeData($data)
+ {
+ if ($this->base64encode) {
+ $data = base64_encode(serialize($data));
+ }
+ return $data;
+ }
+
+ protected function decodeData($data)
+ {
+ if ($this->base64encode) {
+ if (is_string($data)) {
+ if (($data = base64_decode($data)) !== false) {
+ $data = @unserialize($data);
+ } else {
+ $data = null;
+ }
+ } else {
+ $data = null;
+ }
+ }
+ return $data;
+ }
+}
diff --git a/php/elFinderSessionInterface.php b/php/elFinderSessionInterface.php
new file mode 100644
index 000000000..936848c7a
--- /dev/null
+++ b/php/elFinderSessionInterface.php
@@ -0,0 +1,59 @@
+id]
+ * This volume session cache
*
* @var array
*/
protected $sessionCache;
+ /**
+ * elFinder session wrapper object
+ *
+ * @var elFinderSessionInterface
+ */
+ protected $session;
/**
* Search start time
@@ -658,14 +664,14 @@ abstract class elFinderVolumeDriver {
}
}
+ /**
+ * @deprecated
+ */
protected function sessionRestart() {
- $start = @session_start();
- if (!isset($_SESSION[elFinder::$sessionCacheKey])) {
- $_SESSION[elFinder::$sessionCacheKey] = array();
- }
- $this->sessionCache = &$_SESSION[elFinder::$sessionCacheKey][$this->id];
- return $start;
+ $this->sessionCache = $this->session->start()->get($this->id, array());
+ return true;
}
+
/*********************************************************************/
/* PUBLIC API */
/*********************************************************************/
@@ -689,7 +695,16 @@ abstract class elFinderVolumeDriver {
public function id() {
return $this->id;
}
-
+
+ /**
+ * Assign elFinder session wrapper object
+ *
+ * @param $session elFinderSessionInterface
+ */
+ public function setSession($session) {
+ $this->session = $session;
+ }
+
/**
* Return debug info for client
*
@@ -780,7 +795,14 @@ abstract class elFinderVolumeDriver {
**/
public function mount(array $opts) {
if (!isset($opts['path']) || $opts['path'] === '') {
- return $this->setError('Path undefined.');;
+ return $this->setError('Path undefined.');
+ }
+
+ if (! $this->session) {
+ return $this->setError('Session wrapper dose not set. Need to `$volume->setSession(elFinderSessionInterface);` before mount.');
+ }
+ if (! ($this->session instanceof elFinderSessionInterface)) {
+ return $this->setError('Session wrapper instance must be "elFinderSessionInterface".');
}
$this->options = array_merge($this->options, $opts);
@@ -799,10 +821,10 @@ abstract class elFinderVolumeDriver {
$argInit = !empty($this->ARGS['init']);
// session cache
- if ($argInit || ! isset($_SESSION[elFinder::$sessionCacheKey][$this->id])) {
- $_SESSION[elFinder::$sessionCacheKey][$this->id] = array();
+ if ($argInit) {
+ $this->session->set($this->id, array());
}
- $this->sessionCache = &$_SESSION[elFinder::$sessionCacheKey][$this->id];
+ $this->sessionCache = $this->session->get($this->id, array());
// default file attribute
$this->defaults = array(
@@ -3039,7 +3061,7 @@ abstract class elFinderVolumeDriver {
if (! $this->isMyReload()) {
// need $path as key for netmount/netunmount
if (isset($this->sessionCache['rootstat'][$rootKey])) {
- if ($ret = elFinder::sessionDataDecode($this->sessionCache['rootstat'][$rootKey], 'array')) {
+ if ($ret = $this->sessionCache['rootstat'][$rootKey]) {
return $ret;
}
}
@@ -3049,9 +3071,8 @@ abstract class elFinderVolumeDriver {
? $this->cache[$path]
: $this->updateCache($path, $this->convEncOut($this->_stat($this->convEncIn($path))));
if ($is_root) {
- $this->sessionRestart();
- $this->sessionCache['rootstat'][$rootKey] = elFinder::sessionDataEncode($ret);
- elFinder::sessionWrite();
+ $this->sessionCache['rootstat'][$rootKey] = $ret;
+ $this->session->set($this->id, $this->sessionCache);
}
return $ret;
}
@@ -3257,9 +3278,8 @@ abstract class elFinderVolumeDriver {
**/
protected function clearcache() {
$this->cache = $this->dirsCache = array();
- $this->sessionRestart();
unset($this->sessionCache['rootstat'][md5($this->root)]);
- elFinder::sessionWrite();
+ $this->session->set($this->id, $this->sessionCache);
}
/**
@@ -4673,6 +4693,7 @@ abstract class elFinderVolumeDriver {
}
$this->sessionCache[$sessionKey] = $arcs;
+ $this->session->set($this->id, $this->sessionCache);
return $arcs;
}
diff --git a/php/elFinderVolumeDropbox.class.php b/php/elFinderVolumeDropbox.class.php
index ae99a1eb0..1c7741bcf 100644
--- a/php/elFinderVolumeDropbox.class.php
+++ b/php/elFinderVolumeDropbox.class.php
@@ -164,10 +164,10 @@ class elFinderVolumeDropbox extends elFinderVolumeDriver {
if ($options['pass'] === 'init') {
$html = '';
- if (isset($_SESSION['elFinderDropboxTokens'])) {
+ if ($sessionToken = $this->session->get('DropboxTokens')) {
// token check
try {
- list(, $accessToken, $accessTokenSecret) = $_SESSION['elFinderDropboxTokens'];
+ list(, $accessToken, $accessTokenSecret) = $sessionToken;
$this->oauth->setToken($accessToken, $accessTokenSecret);
$this->dropbox = new Dropbox_API($this->oauth, $this->options['root']);
$this->dropbox->getAccountInfo();
@@ -176,7 +176,7 @@ class elFinderVolumeDropbox extends elFinderVolumeDriver {
';
$html = $script;
} catch (Dropbox_Exception $e) {
- unset($_SESSION['elFinderDropboxTokens']);
+ $this->session->remove('DropboxTokens');
}
}
if (! $html) {
@@ -202,7 +202,7 @@ class elFinderVolumeDropbox extends elFinderVolumeDriver {
return array('exit' => true, 'body' => '{msg:errAccess}');
}
- $_SESSION['elFinderDropboxAuthTokens'] = $tokens;
+ $this->session->set('DropboxAuthTokens', $tokens);
$html = '';
$html .= '