diff --git a/apps/files/ajax/delete.php b/apps/files/ajax/delete.php index 99f4918838..f6aa4f0c90 100644 --- a/apps/files/ajax/delete.php +++ b/apps/files/ajax/delete.php @@ -1,10 +1,9 @@ close(); + // Get data $dir = stripslashes($_POST["dir"]); diff --git a/apps/files/ajax/download.php b/apps/files/ajax/download.php index 6a34cbe4ef..1f7e42e0d3 100644 --- a/apps/files/ajax/download.php +++ b/apps/files/ajax/download.php @@ -29,6 +29,7 @@ $RUNTIME_APPTYPES=array('filesystem'); // Check if we are a user OCP\User::checkLoggedIn(); +\OC::$session->close(); $files = $_GET["files"]; $dir = $_GET["dir"]; diff --git a/apps/files/ajax/getstoragestats.php b/apps/files/ajax/getstoragestats.php index dd7c7dc557..17415b6933 100644 --- a/apps/files/ajax/getstoragestats.php +++ b/apps/files/ajax/getstoragestats.php @@ -10,6 +10,7 @@ if (isset($_GET['dir'])) { } OCP\JSON::checkLoggedIn(); +\OC::$session->close(); // send back json OCP\JSON::success(array('data' => \OCA\Files\Helper::buildFileStorageStatistics($dir))); diff --git a/apps/files/ajax/list.php b/apps/files/ajax/list.php index c8286bc15c..667209599a 100644 --- a/apps/files/ajax/list.php +++ b/apps/files/ajax/list.php @@ -7,6 +7,7 @@ $RUNTIME_APPTYPES=array('filesystem'); OCP\JSON::checkLoggedIn(); +\OC::$session->close(); // Load the files $dir = isset( $_GET['dir'] ) ? $_GET['dir'] : ''; diff --git a/apps/files/ajax/mimeicon.php b/apps/files/ajax/mimeicon.php index dbb8b60112..6557ff941a 100644 --- a/apps/files/ajax/mimeicon.php +++ b/apps/files/ajax/mimeicon.php @@ -1,3 +1,4 @@ close(); print OC_Helper::mimetypeIcon($_GET['mime']); diff --git a/apps/files/ajax/move.php b/apps/files/ajax/move.php index 04a260265c..0a8dbc24a6 100644 --- a/apps/files/ajax/move.php +++ b/apps/files/ajax/move.php @@ -1,10 +1,8 @@ close(); // Get data $dir = stripslashes($_POST["dir"]); diff --git a/apps/files/ajax/newfile.php b/apps/files/ajax/newfile.php index 0187b20075..1234cf1139 100644 --- a/apps/files/ajax/newfile.php +++ b/apps/files/ajax/newfile.php @@ -7,7 +7,8 @@ if(!OC_User::isLoggedIn()) { exit; } -session_write_close(); +\OC::$session->close(); + // Get the params $dir = isset( $_REQUEST['dir'] ) ? '/'.trim($_REQUEST['dir'], '/\\') : ''; $filename = isset( $_REQUEST['filename'] ) ? trim($_REQUEST['filename'], '/\\') : ''; diff --git a/apps/files/ajax/newfolder.php b/apps/files/ajax/newfolder.php index b2b4fb27f7..032447460f 100644 --- a/apps/files/ajax/newfolder.php +++ b/apps/files/ajax/newfolder.php @@ -5,6 +5,7 @@ OCP\JSON::checkLoggedIn(); OCP\JSON::callCheck(); +\OC::$session->close(); // Get the params $dir = isset( $_POST['dir'] ) ? stripslashes($_POST['dir']) : ''; diff --git a/apps/files/ajax/rawlist.php b/apps/files/ajax/rawlist.php index 6433ddefd6..6c2569e2eb 100644 --- a/apps/files/ajax/rawlist.php +++ b/apps/files/ajax/rawlist.php @@ -4,6 +4,7 @@ $RUNTIME_APPTYPES = array('filesystem'); OCP\JSON::checkLoggedIn(); +\OC::$session->close(); // Load the files $dir = isset($_GET['dir']) ? $_GET['dir'] : ''; diff --git a/apps/files/ajax/rename.php b/apps/files/ajax/rename.php index 5b07c306af..fa3ddace63 100644 --- a/apps/files/ajax/rename.php +++ b/apps/files/ajax/rename.php @@ -23,6 +23,7 @@ OCP\JSON::checkLoggedIn(); OCP\JSON::callCheck(); +\OC::$session->close(); $files = new \OCA\Files\App( \OC\Files\Filesystem::getView(), diff --git a/apps/files/ajax/scan.php b/apps/files/ajax/scan.php index 5b32b6db9b..d5d8848380 100644 --- a/apps/files/ajax/scan.php +++ b/apps/files/ajax/scan.php @@ -1,6 +1,6 @@ close(); $force = (isset($_GET['force']) and ($_GET['force'] === 'true')); $dir = isset($_GET['dir']) ? $_GET['dir'] : ''; diff --git a/apps/files/ajax/upload.php b/apps/files/ajax/upload.php index 145f40c50d..37c600e91d 100644 --- a/apps/files/ajax/upload.php +++ b/apps/files/ajax/upload.php @@ -58,6 +58,7 @@ if (empty($_POST['dirToken'])) { OCP\JSON::callCheck(); +\OC::$session->close(); // get array with current storage stats (e.g. max file size) diff --git a/apps/files_encryption/lib/helper.php b/apps/files_encryption/lib/helper.php index ef3775875f..8cbbe8a45a 100755 --- a/apps/files_encryption/lib/helper.php +++ b/apps/files_encryption/lib/helper.php @@ -367,9 +367,14 @@ class Helper { $post = 0; if(count($_POST) > 0) { $post = 1; - } - header('Location: ' . $location . '?p=' . $post . '&errorCode=' . $errorCode); - exit(); + } + + if(defined('PHPUNIT_RUN') and PHPUNIT_RUN) { + throw new \Exception("Encryption error: $errorCode"); + } + + header('Location: ' . $location . '?p=' . $post . '&errorCode=' . $errorCode); + exit(); } /** diff --git a/cron.php b/cron.php index 44ca421328..a0447f97f1 100644 --- a/cron.php +++ b/cron.php @@ -48,7 +48,7 @@ try { require_once 'lib/base.php'; - session_write_close(); + \OC::$session->close(); $logger = \OC_Log::$object; diff --git a/lib/private/connector/sabre/auth.php b/lib/private/connector/sabre/auth.php index 0c84fa6b75..5577273df8 100644 --- a/lib/private/connector/sabre/auth.php +++ b/lib/private/connector/sabre/auth.php @@ -73,6 +73,20 @@ class OC_Connector_Sabre_Auth extends Sabre_DAV_Auth_Backend_AbstractBasic { */ public function authenticate(Sabre_DAV_Server $server, $realm) { + $result = $this->auth($server, $realm); + + // close the session - right after authentication there is not need to write to the session any more + \OC::$session->close(); + + return $result; + } + + /** + * @param Sabre_DAV_Server $server + * @param $realm + * @return bool + */ + private function auth(Sabre_DAV_Server $server, $realm) { if (OC_User::handleApacheAuth() || OC_User::isLoggedIn()) { $user = OC_User::getUser(); OC_Util::setupFS($user); @@ -81,5 +95,5 @@ class OC_Connector_Sabre_Auth extends Sabre_DAV_Auth_Backend_AbstractBasic { } return parent::authenticate($server, $realm); - } + } } diff --git a/lib/private/session/internal.php b/lib/private/session/internal.php index a7c9e2fdef..42ec9606dc 100644 --- a/lib/private/session/internal.php +++ b/lib/private/session/internal.php @@ -26,8 +26,7 @@ class Internal extends Memory { } public function __destruct() { - $_SESSION = array_merge($_SESSION, $this->data); - session_write_close(); + $this->close(); } /** @@ -47,4 +46,15 @@ class Internal extends Memory { @session_start(); $this->data = $_SESSION = array(); } + + public function close() { + $_SESSION = array_merge($_SESSION, $this->data); + session_write_close(); + + parent::close(); + } + + public function reopen() { + throw new \Exception('The session cannot be reopened - reopen() is ony to be used in unit testing.'); + } } diff --git a/lib/private/session/memory.php b/lib/private/session/memory.php index 1b9ac45257..1497c0f892 100644 --- a/lib/private/session/memory.php +++ b/lib/private/session/memory.php @@ -28,6 +28,7 @@ class Memory extends Session { * @param integer $value */ public function set($key, $value) { + $this->validateSession(); $this->data[$key] = $value; } @@ -54,10 +55,29 @@ class Memory extends Session { * @param string $key */ public function remove($key) { + $this->validateSession(); unset($this->data[$key]); } public function clear() { $this->data = array(); } + + /** + * Helper function for PHPUnit execution - don't use in non-test code + */ + public function reopen() { + $this->sessionClosed = false; + } + + /** + * In case the session has already been locked an exception will be thrown + * + * @throws \Exception + */ + private function validateSession() { + if ($this->sessionClosed) { + throw new \Exception('Session has been closed - no further changes to the session as allowed'); + } + } } diff --git a/lib/private/session/session.php b/lib/private/session/session.php index fe160faa26..6f6c804f38 100644 --- a/lib/private/session/session.php +++ b/lib/private/session/session.php @@ -12,6 +12,11 @@ use OCP\ISession; abstract class Session implements \ArrayAccess, ISession { + /** + * @var bool + */ + protected $sessionClosed = false; + /** * $name serves as a namespace for the session keys * @@ -49,4 +54,11 @@ abstract class Session implements \ArrayAccess, ISession { public function offsetUnset($offset) { $this->remove($offset); } + + /** + * Close the session and release the lock + */ + public function close() { + $this->sessionClosed = true; + } } diff --git a/lib/public/isession.php b/lib/public/isession.php index 20da712cda..dc5719625c 100644 --- a/lib/public/isession.php +++ b/lib/public/isession.php @@ -75,4 +75,9 @@ interface ISession { */ public function clear(); + /** + * Close the session and release the lock + */ + public function close(); + } diff --git a/tests/phpunit-autotest.xml b/tests/phpunit-autotest.xml index 1a2ab35491..872ff2c259 100644 --- a/tests/phpunit-autotest.xml +++ b/tests/phpunit-autotest.xml @@ -36,6 +36,7 @@ + detail diff --git a/tests/phpunit.xml.dist b/tests/phpunit.xml.dist index 71a4ff2762..21c63ea046 100644 --- a/tests/phpunit.xml.dist +++ b/tests/phpunit.xml.dist @@ -29,4 +29,7 @@ + + + diff --git a/tests/startsessionlistener.php b/tests/startsessionlistener.php new file mode 100644 index 0000000000..808a2a2226 --- /dev/null +++ b/tests/startsessionlistener.php @@ -0,0 +1,44 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +/** + * Starts a new session before each test execution + */ +class StartSessionListener implements PHPUnit_Framework_TestListener { + + public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) { + } + + public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) { + } + + public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) { + } + + public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) { + } + + public function startTest(PHPUnit_Framework_Test $test) { + } + + public function endTest(PHPUnit_Framework_Test $test, $time) { + // reopen the session - only allowed for memory session + if (\OC::$session instanceof \OC\Session\Memory) { + /** @var $session \OC\Session\Memory */ + $session = \OC::$session; + $session->reopen(); + } + } + + public function startTestSuite(PHPUnit_Framework_TestSuite $suite) { + } + + public function endTestSuite(PHPUnit_Framework_TestSuite $suite) { + } + +}