diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/base.php | 34 | ||||
-rw-r--r-- | lib/l10n/et_EE.php | 3 | ||||
-rw-r--r-- | lib/private/app.php | 31 | ||||
-rw-r--r-- | lib/private/appframework/core/api.php | 7 | ||||
-rw-r--r-- | lib/private/connector/sabre/file.php | 13 | ||||
-rw-r--r-- | lib/private/eventsource.php | 93 | ||||
-rw-r--r-- | lib/private/files.php | 2 | ||||
-rw-r--r-- | lib/private/files/cache/changepropagator.php | 8 | ||||
-rw-r--r-- | lib/private/files/cache/homecache.php | 3 | ||||
-rw-r--r-- | lib/private/files/cache/updater.php | 214 | ||||
-rw-r--r-- | lib/private/files/view.php | 65 | ||||
-rw-r--r-- | lib/private/helper.php | 12 | ||||
-rw-r--r-- | lib/private/preview/office-cl.php | 2 | ||||
-rw-r--r-- | lib/private/preview/office.php | 2 | ||||
-rw-r--r-- | lib/private/server.php | 9 | ||||
-rw-r--r-- | lib/private/share/constants.php | 2 | ||||
-rw-r--r-- | lib/private/share/share.php | 5 | ||||
-rw-r--r-- | lib/private/template/functions.php | 18 | ||||
-rwxr-xr-x | lib/private/util.php | 16 | ||||
-rw-r--r-- | lib/public/ieventsource.php | 34 | ||||
-rw-r--r-- | lib/public/iservercontainer.php | 7 |
21 files changed, 311 insertions, 269 deletions
diff --git a/lib/base.php b/lib/base.php index 18331dd86aa..5d52db68cb7 100644 --- a/lib/base.php +++ b/lib/base.php @@ -554,7 +554,9 @@ class OC { OC_Group::useBackend(new OC_Group_Database()); //setup extra user backends - OC_User::setupBackends(); + if (!self::checkUpgrade(false)) { + OC_User::setupBackends(); + } self::registerCacheHooks(); self::registerFilesystemHooks(); @@ -583,6 +585,21 @@ class OC { ); return; } + + $host = OC_Request::insecureServerHost(); + // if the host passed in headers isn't trusted + if (!OC::$CLI + // overwritehost is always trusted + && OC_Request::getOverwriteHost() === null + && !OC_Request::isTrustedDomain($host) + ) { + header('HTTP/1.1 400 Bad Request'); + header('Status: 400 Bad Request'); + $tmpl = new OCP\Template('core', 'untrustedDomain', 'guest'); + $tmpl->assign('domain', $_SERVER['SERVER_NAME']); + $tmpl->printPage(); + return; + } } private static function registerLocalAddressBook() { @@ -683,21 +700,6 @@ class OC { exit(); } - $host = OC_Request::insecureServerHost(); - // if the host passed in headers isn't trusted - if (!OC::$CLI - // overwritehost is always trusted - && OC_Request::getOverwriteHost() === null - && !OC_Request::isTrustedDomain($host) - ) { - header('HTTP/1.1 400 Bad Request'); - header('Status: 400 Bad Request'); - $tmpl = new OCP\Template('core', 'untrustedDomain', 'guest'); - $tmpl->assign('domain', $_SERVER['SERVER_NAME']); - $tmpl->printPage(); - return; - } - $request = OC_Request::getPathInfo(); if (substr($request, -3) !== '.js') { // we need these files during the upgrade self::checkMaintenanceMode(); diff --git a/lib/l10n/et_EE.php b/lib/l10n/et_EE.php index 365c2e1f96a..9209d9bb6b3 100644 --- a/lib/l10n/et_EE.php +++ b/lib/l10n/et_EE.php @@ -5,6 +5,7 @@ $TRANSLATIONS = array( "See %s" => "Vaata %s", "This can usually be fixed by %sgiving the webserver write access to the config directory%s." => "Tavaliselt saab selle lahendada %s andes veebiserverile seadete kataloogile \"config\" kirjutusõigused %s", "Sample configuration detected" => "Tuvastati näidisseaded", +"It has been detected that the sample configuration has been copied. This can break your installation and is unsupported. Please read the documentation before performing changes on config.php" => "Tuvastati, et kopeeriti näidisseaded. See võib lõhkuda sinu saidi ja see pole toetatud. Palun loe enne faili config.php muutmist dokumentatsiooni", "Help" => "Abiinfo", "Personal" => "Isiklik", "Settings" => "Seaded", @@ -65,6 +66,7 @@ $TRANSLATIONS = array( "Share type %s is not valid for %s" => "Jagamise tüüp %s ei ole õige %s jaoks", "Setting permissions for %s failed, because the permissions exceed permissions granted to %s" => "Lubade seadistus %s jaoks ebaõnnestus, kuna antud õigused ületavad %s jaoks määratud õigusi", "Setting permissions for %s failed, because the item was not found" => "Lubade seadistus %s jaoks ebaõnnestus, kuna üksust ei leitud", +"Cannot set expiration date. Shares cannot expire later than %s after they have been shared" => "Aegumise kuupäeva ei saa määrata. Jagamised ei saa aeguda hiljem kui %s peale jagamist.", "Cannot set expiration date. Expiration date is in the past" => "Aegumiskuupäeva ei saa määrata. Aegumise kuupäev on minevikus", "Sharing backend %s must implement the interface OCP\\Share_Backend" => "Jagamise tagarakend %s peab kasutusele võtma OCP\\Share_Backend liidese", "Sharing backend %s not found" => "Jagamise tagarakendit %s ei leitud", @@ -97,6 +99,7 @@ $TRANSLATIONS = array( "Cannot create \"data\" directory (%s)" => "Ei suuda luua \"data\" kataloogi (%s)", "This can usually be fixed by <a href=\"%s\" target=\"_blank\">giving the webserver write access to the root directory</a>." => "Tavaliselt saab selle lahendada <a href=\"%s\" target=\"_blank\">andes veebiserverile juur-kataloogile kirjutusõigused</a>.", "Setting locale to %s failed" => "Lokaadi %s määramine ebaõnnestus.", +"Please install one of these locales on your system and restart your webserver." => "Palun paigalda mõni neist lokaatides oma süsteemi ning taaskäivita veebiserver.", "Please ask your server administrator to install the module." => "Palu oma serveri haldajal moodul paigadalda.", "PHP module %s not installed." => "PHP moodulit %s pole paigaldatud.", "PHP %s or higher is required." => "PHP %s või uuem on nõutav.", diff --git a/lib/private/app.php b/lib/private/app.php index d10d352b432..3eed9e3c443 100644 --- a/lib/private/app.php +++ b/lib/private/app.php @@ -172,17 +172,29 @@ class OC_App { */ protected static $enabledAppsCache = array(); - public static function getEnabledApps($forceRefresh = false) { + /** + * Returns apps enabled for the current user. + * + * @param bool $forceRefresh whether to refresh the cache + * @param bool $all whether to return apps for all users, not only the + * currently logged in one + */ + public static function getEnabledApps($forceRefresh = false, $all = false) { if (!OC_Config::getValue('installed', false)) { return array(); } - if (!$forceRefresh && !empty(self::$enabledAppsCache)) { + // in incognito mode or when logged out, $user will be false, + // which is also the case during an upgrade + $user = null; + if (!$all) { + $user = \OC_User::getUser(); + } + if (is_string($user) && !$forceRefresh && !empty(self::$enabledAppsCache)) { return self::$enabledAppsCache; } $apps = array(); $appConfig = \OC::$server->getAppConfig(); $appStatus = $appConfig->getValues(false, 'enabled'); - $user = \OC_User::getUser(); foreach ($appStatus as $app => $enabled) { if ($app === 'files') { continue; @@ -192,11 +204,16 @@ class OC_App { } else if ($enabled !== 'no') { $groups = json_decode($enabled); if (is_array($groups)) { - foreach ($groups as $group) { - if (\OC_Group::inGroup($user, $group)) { - $apps[] = $app; - break; + if (is_string($user)) { + foreach ($groups as $group) { + if (\OC_Group::inGroup($user, $group)) { + $apps[] = $app; + break; + } } + } else { + // global, consider app as enabled + $apps[] = $app; } } } diff --git a/lib/private/appframework/core/api.php b/lib/private/appframework/core/api.php index ba6b9f95cb2..279f4bf97f7 100644 --- a/lib/private/appframework/core/api.php +++ b/lib/private/appframework/core/api.php @@ -110,12 +110,11 @@ class API implements IApi{ /** - * used to return and open a new eventsource - * @return \OC_EventSource a new open EventSource class + * used to return and open a new event source + * @return \OCP\IEventSource a new open EventSource class */ public function openEventSource(){ - # TODO: use public api - return new \OC_EventSource(); + return \OC::$server->createEventSource(); } /** diff --git a/lib/private/connector/sabre/file.php b/lib/private/connector/sabre/file.php index 44c86e69719..5333583e78d 100644 --- a/lib/private/connector/sabre/file.php +++ b/lib/private/connector/sabre/file.php @@ -102,13 +102,16 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements \Sabre\ throw new OC_Connector_Sabre_Exception_FileLocked($e->getMessage(), $e->getCode(), $e); } + // if content length is sent by client: // double check if the file was fully received // compare expected and actual size - $expected = $_SERVER['CONTENT_LENGTH']; - $actual = $this->fileView->filesize($partFilePath); - if ($actual != $expected) { - $this->fileView->unlink($partFilePath); - throw new \Sabre\DAV\Exception\BadRequest('expected filesize ' . $expected . ' got ' . $actual); + if (isset($_SERVER['CONTENT_LENGTH'])) { + $expected = $_SERVER['CONTENT_LENGTH']; + $actual = $this->fileView->filesize($partFilePath); + if ($actual != $expected) { + $this->fileView->unlink($partFilePath); + throw new \Sabre\DAV\Exception\BadRequest('expected filesize ' . $expected . ' got ' . $actual); + } } // rename to correct path diff --git a/lib/private/eventsource.php b/lib/private/eventsource.php index 192c1446b5a..53947f3a2f2 100644 --- a/lib/private/eventsource.php +++ b/lib/private/eventsource.php @@ -1,25 +1,10 @@ <?php - /** -* ownCloud -* -* @author Robin Appelman -* @copyright 2012 Robin Appelman icewind1991@gmail.com -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE -* License as published by the Free Software Foundation; either -* version 3 of the License, or any later version. -* -* This library is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU AFFERO GENERAL PUBLIC LICENSE for more details. -* -* You should have received a copy of the GNU Affero General Public -* License along with this library. If not, see <http://www.gnu.org/licenses/>. -* -*/ + * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ /** * wrapper for server side events (http://en.wikipedia.org/wiki/Server-sent_events) @@ -27,51 +12,73 @@ * * use server side events with caution, to many open requests can hang the server */ -class OC_EventSource{ +class OC_EventSource implements \OCP\IEventSource { + /** + * @var bool + */ private $fallback; - private $fallBackId=0; - public function __construct() { + /** + * @var int + */ + private $fallBackId = 0; + + /** + * @var bool + */ + private $started = false; + + protected function init() { + if ($this->started) { + return; + } + $this->started = true; + + // prevent php output buffering, caching and nginx buffering OC_Util::obEnd(); header('Cache-Control: no-cache'); header('X-Accel-Buffering: no'); - $this->fallback=isset($_GET['fallback']) and $_GET['fallback']=='true'; - if($this->fallback) { - $this->fallBackId=$_GET['fallback_id']; + $this->fallback = isset($_GET['fallback']) and $_GET['fallback'] == 'true'; + if ($this->fallback) { + $this->fallBackId = (int)$_GET['fallback_id']; header("Content-Type: text/html"); - echo str_repeat('<span></span>'.PHP_EOL, 10); //dummy data to keep IE happy - }else{ + echo str_repeat('<span></span>' . PHP_EOL, 10); //dummy data to keep IE happy + } else { header("Content-Type: text/event-stream"); } - if( !OC_Util::isCallRegistered()) { + if (!OC_Util::isCallRegistered()) { $this->send('error', 'Possible CSRF attack. Connection will be closed.'); $this->close(); exit(); } flush(); - } /** * send a message to the client + * * @param string $type * @param mixed $data * + * @throws \BadMethodCallException * if only one parameter is given, a typeless message will be send with that parameter as data */ - public function send($type, $data=null) { - if(is_null($data)) { - $data=$type; - $type=null; + public function send($type, $data = null) { + if ($data and !preg_match('/^[A-Za-z0-9_]+$/', $type)) { + throw new BadMethodCallException('Type needs to be alphanumeric ('. $type .')'); + } + $this->init(); + if (is_null($data)) { + $data = $type; + $type = null; } - if($this->fallback) { - $fallBackId = OC_Util::sanitizeHTML($this->fallBackId); - $response='<script type="text/javascript">window.parent.OC.EventSource.fallBackCallBack(' - .$fallBackId.',"' . $type . '",' . OCP\JSON::encode($data) . ')</script>' . PHP_EOL; + if ($this->fallback) { + $response = '<script type="text/javascript">window.parent.OC.EventSource.fallBackCallBack(' + . $this->fallBackId . ',"' . $type . '",' . OCP\JSON::encode($data) . ')</script>' . PHP_EOL; echo $response; - }else{ - if($type) { - echo 'event: ' . $type.PHP_EOL; + } else { + if ($type) { + echo 'event: ' . $type . PHP_EOL; } echo 'data: ' . OCP\JSON::encode($data) . PHP_EOL; } @@ -80,9 +87,9 @@ class OC_EventSource{ } /** - * close the connection of the even source + * close the connection of the event source */ public function close() { - $this->send('__internal__', 'close');//server side closing can be an issue, let the client do it + $this->send('__internal__', 'close'); //server side closing can be an issue, let the client do it } } diff --git a/lib/private/files.php b/lib/private/files.php index 739dae64180..06fc2dc9109 100644 --- a/lib/private/files.php +++ b/lib/private/files.php @@ -49,7 +49,7 @@ class OC_Files { header('Content-Type: application/zip'); } else { $filesize = \OC\Files\Filesystem::filesize($filename); - header('Content-Type: '.\OC\Files\Filesystem::getMimeType($filename)); + header('Content-Type: '.\OC_Helper::getSecureMimeType(\OC\Files\Filesystem::getMimeType($filename))); if ($filesize > -1) { header("Content-Length: ".$filesize); } diff --git a/lib/private/files/cache/changepropagator.php b/lib/private/files/cache/changepropagator.php index 30f2e675e2e..2967c8f6259 100644 --- a/lib/private/files/cache/changepropagator.php +++ b/lib/private/files/cache/changepropagator.php @@ -57,9 +57,11 @@ class ChangePropagator { */ list($storage, $internalPath) = $this->view->resolvePath($parent); - $cache = $storage->getCache(); - $id = $cache->getId($internalPath); - $cache->update($id, array('mtime' => $time, 'etag' => $storage->getETag($internalPath))); + if ($storage) { + $cache = $storage->getCache(); + $id = $cache->getId($internalPath); + $cache->update($id, array('mtime' => $time, 'etag' => $storage->getETag($internalPath))); + } } } diff --git a/lib/private/files/cache/homecache.php b/lib/private/files/cache/homecache.php index 06ae62015a5..2b3967c8807 100644 --- a/lib/private/files/cache/homecache.php +++ b/lib/private/files/cache/homecache.php @@ -39,6 +39,9 @@ class HomeCache extends Cache { $totalSize = 0 + $sum; $unencryptedSize = 0 + $unencryptedSum; $entry['size'] += 0; + if (!isset($entry['unencrypted_size'])) { + $entry['unencrypted_size'] = 0; + } $entry['unencrypted_size'] += 0; if ($entry['size'] !== $totalSize) { $this->update($id, array('size' => $totalSize)); diff --git a/lib/private/files/cache/updater.php b/lib/private/files/cache/updater.php index 0e5e07c587d..c303ff24b1f 100644 --- a/lib/private/files/cache/updater.php +++ b/lib/private/files/cache/updater.php @@ -1,6 +1,6 @@ <?php /** - * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com> + * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com> * This file is licensed under the Affero General Public License version 3 or * later. * See the COPYING-README file. @@ -9,165 +9,116 @@ namespace OC\Files\Cache; /** - * listen to filesystem hooks and change the cache accordingly + * Update the cache and propagate changes */ class Updater { + /** + * @var \OC\Files\View + */ + protected $view; /** - * resolve a path to a storage and internal path - * - * @param string $path the relative path - * @return array an array consisting of the storage and the internal path + * @var \OC\Files\Cache\ChangePropagator */ - static public function resolvePath($path) { - $view = \OC\Files\Filesystem::getView(); - return $view->resolvePath($path); + protected $propagator; + + /** + * @param \OC\Files\View $view + */ + public function __construct($view) { + $this->view = $view; + $this->propagator = new ChangePropagator($view); } /** - * perform a write update + * Update the cache for $path * - * @param string $path the relative path of the file + * @param string $path + * @param int $time */ - static public function writeUpdate($path) { + public function update($path, $time = null) { /** * @var \OC\Files\Storage\Storage $storage * @var string $internalPath */ - list($storage, $internalPath) = self::resolvePath($path); + list($storage, $internalPath) = $this->view->resolvePath($path); if ($storage) { + $this->propagator->addChange($path); $cache = $storage->getCache($internalPath); $scanner = $storage->getScanner($internalPath); $data = $scanner->scan($internalPath, Scanner::SCAN_SHALLOW); + $this->correctParentStorageMtime($storage, $internalPath); $cache->correctFolderSize($internalPath, $data); - self::correctFolder($path, $storage->filemtime($internalPath)); - self::correctParentStorageMtime($storage, $internalPath); + $this->propagator->propagateChanges($time); } } /** - * perform a delete update + * Remove $path from the cache * - * @param string $path the relative path of the file + * @param string $path */ - static public function deleteUpdate($path) { + public function remove($path) { /** * @var \OC\Files\Storage\Storage $storage * @var string $internalPath */ - list($storage, $internalPath) = self::resolvePath($path); + list($storage, $internalPath) = $this->view->resolvePath($path); if ($storage) { $parent = dirname($internalPath); if ($parent === '.') { $parent = ''; } + $this->propagator->addChange($path); $cache = $storage->getCache($internalPath); $cache->remove($internalPath); $cache->correctFolderSize($parent); - self::correctFolder($path, time()); - self::correctParentStorageMtime($storage, $internalPath); + $this->correctParentStorageMtime($storage, $internalPath); + $this->propagator->propagateChanges(); } } /** - * preform a rename update - * - * @param string $from the relative path of the source file - * @param string $to the relative path of the target file + * @param string $source + * @param string $target */ - static public function renameUpdate($from, $to) { + public function rename($source, $target) { /** - * @var \OC\Files\Storage\Storage $storageFrom - * @var \OC\Files\Storage\Storage $storageTo - * @var string $internalFrom - * @var string $internalTo + * @var \OC\Files\Storage\Storage $sourceStorage + * @var \OC\Files\Storage\Storage $targetStorage + * @var string $sourceInternalPath + * @var string $targetInternalPath */ - list($storageFrom, $internalFrom) = self::resolvePath($from); + list($sourceStorage, $sourceInternalPath) = $this->view->resolvePath($source); // if it's a moved mountpoint we dont need to do anything - if ($internalFrom === '') { + if ($sourceInternalPath === '') { return; } - list($storageTo, $internalTo) = self::resolvePath($to); - if ($storageFrom && $storageTo) { - if ($storageFrom === $storageTo) { - $cache = $storageFrom->getCache($internalFrom); - $cache->move($internalFrom, $internalTo); - if (pathinfo($internalFrom, PATHINFO_EXTENSION) !== pathinfo($internalTo, PATHINFO_EXTENSION)) { - // redetect mime type change - $mimeType = $storageTo->getMimeType($internalTo); - $fileId = $storageTo->getCache()->getId($internalTo); - $storageTo->getCache()->update($fileId, array('mimetype' => $mimeType)); + list($targetStorage, $targetInternalPath) = $this->view->resolvePath($target); + + if ($sourceStorage && $targetStorage) { + if ($sourceStorage === $targetStorage) { + $cache = $sourceStorage->getCache($sourceInternalPath); + $cache->move($sourceInternalPath, $targetInternalPath); + + if (pathinfo($sourceInternalPath, PATHINFO_EXTENSION) !== pathinfo($targetInternalPath, PATHINFO_EXTENSION)) { + // handle mime type change + $mimeType = $sourceStorage->getMimeType($targetInternalPath); + $fileId = $cache->getId($targetInternalPath); + $cache->update($fileId, array('mimetype' => $mimeType)); } - $cache->correctFolderSize($internalFrom); - $cache->correctFolderSize($internalTo); - self::correctFolder($from, time()); - self::correctFolder($to, time()); - self::correctParentStorageMtime($storageFrom, $internalFrom); - self::correctParentStorageMtime($storageTo, $internalTo); - } else { - self::deleteUpdate($from); - self::writeUpdate($to); - } - } - } - /** - * get file owner and path - * @param string $filename - * @return string[] with the owner's uid and the owner's path - */ - private static function getUidAndFilename($filename) { - - $uid = \OC\Files\Filesystem::getOwner($filename); - \OC\Files\Filesystem::initMountPoints($uid); - - $filename = (strpos($filename, '/') !== 0) ? '/' . $filename : $filename; - if ($uid != \OCP\User::getUser()) { - $info = \OC\Files\Filesystem::getFileInfo($filename); - if (!$info) { - return array($uid, '/files' . $filename); - } - $ownerView = new \OC\Files\View('/' . $uid . '/files'); - $filename = $ownerView->getPath($info['fileid']); - } - return array($uid, '/files' . $filename); - } - - /** - * Update the mtime and ETag of all parent folders - * - * @param string $path - * @param string $time - */ - static public function correctFolder($path, $time) { - if ($path !== '' && $path !== '/' && $path !== '\\') { - list($owner, $realPath) = self::getUidAndFilename(dirname($path)); - - /** - * @var \OC\Files\Storage\Storage $storage - * @var string $internalPath - */ - $view = new \OC\Files\View('/' . $owner); - - list($storage, $internalPath) = $view->resolvePath($realPath); - $cache = $storage->getCache(); - $id = $cache->getId($internalPath); - - while ($id !== -1) { - $cache->update($id, array('mtime' => $time, 'etag' => $storage->getETag($internalPath))); - if ($realPath !== '') { - $realPath = dirname($realPath); - if ($realPath === DIRECTORY_SEPARATOR) { - $realPath = ""; - } - // check storage for parent in case we change the storage in this step - list($storage, $internalPath) = $view->resolvePath($realPath); - $cache = $storage->getCache(); - $id = $cache->getId($internalPath); - } else { - $id = -1; - } + $cache->correctFolderSize($sourceInternalPath); + $cache->correctFolderSize($targetInternalPath); + $this->correctParentStorageMtime($sourceStorage, $sourceInternalPath); + $this->correctParentStorageMtime($targetStorage, $targetInternalPath); + $this->propagator->addChange($source); + $this->propagator->addChange($target); + } else { + $this->remove($source); + $this->update($target); } + $this->propagator->propagateChanges(); } } @@ -177,52 +128,17 @@ class Updater { * @param \OC\Files\Storage\Storage $storage * @param string $internalPath */ - static private function correctParentStorageMtime($storage, $internalPath) { + private function correctParentStorageMtime($storage, $internalPath) { $cache = $storage->getCache(); $parentId = $cache->getParentId($internalPath); $parent = dirname($internalPath); - - if ($parent === '.' || $parent === '/' || $parent === '\\') { - $parent = ''; - } - if ($parentId != -1) { $cache->update($parentId, array('storage_mtime' => $storage->filemtime($parent))); } } - /** - * @param array $params - */ - static public function writeHook($params) { - self::writeUpdate($params['path']); - } - - /** - * @param array $params - */ - static public function touchHook($params) { - $path = $params['path']; - list($storage, $internalPath) = self::resolvePath($path); - $cache = $storage->getCache(); - $id = $cache->getId($internalPath); - if ($id !== -1) { - $cache->update($id, array('etag' => $storage->getETag($internalPath))); - } - self::writeUpdate($path); - } - - /** - * @param array $params - */ - static public function renameHook($params) { - self::renameUpdate($params['oldpath'], $params['newpath']); - } - - /** - * @param array $params - */ - static public function deleteHook($params) { - self::deleteUpdate($params['path']); + public function __destruct() { + // propagate any leftover changes + $this->propagator->propagateChanges(); } } diff --git a/lib/private/files/view.php b/lib/private/files/view.php index d310a0fa4e1..95f3e9a2c7f 100644 --- a/lib/private/files/view.php +++ b/lib/private/files/view.php @@ -31,8 +31,14 @@ use OC\Files\Mount\MoveableMount; class View { private $fakeRoot = ''; + /** + * @var \OC\Files\Cache\Updater + */ + protected $updater; + public function __construct($root = '') { $this->fakeRoot = $root; + $this->updater = new Updater($this); } public function getAbsolutePath($path = '/') { @@ -168,10 +174,10 @@ class View { * @param string $path relative to data/ * @return boolean */ - protected function removeMount($mount, $path){ + protected function removeMount($mount, $path) { if ($mount instanceof MoveableMount) { // cut of /user/files to get the relative path to data/user/files - $pathParts= explode('/', $path, 4); + $pathParts = explode('/', $path, 4); $relPath = '/' . $pathParts[3]; \OC_Hook::emit( Filesystem::CLASSNAME, "umount", @@ -194,7 +200,7 @@ class View { } public function rmdir($path) { - $absolutePath= $this->getAbsolutePath($path); + $absolutePath = $this->getAbsolutePath($path); $mount = Filesystem::getMountManager()->find($absolutePath); if ($mount->getInternalPath($absolutePath) === '') { return $this->removeMount($mount, $path); @@ -304,7 +310,16 @@ class View { $hooks[] = 'write'; } $result = $this->basicOperation('touch', $path, $hooks, $mtime); - if (!$result) { //if native touch fails, we emulate it by changing the mtime in the cache + if (!$result) { + // If create file fails because of permissions on external storage like SMB folders, + // check file exists and return false if not. + if(!$this->file_exists($path)){ + return false; + } + if (is_null($mtime)) { + $mtime = time(); + } + //if native touch fails, we emulate it by changing the mtime in the cache $this->putFileInfo($path, array('mtime' => $mtime)); } return true; @@ -368,10 +383,8 @@ class View { list ($count, $result) = \OC_Helper::streamCopy($data, $target); fclose($target); fclose($data); + $this->updater->update($path); if ($this->shouldEmitHooks($path) && $result !== false) { - Updater::writeHook(array( - 'path' => $this->getHookPath($path) - )); $this->emit_file_hooks_post($exists, $path); } \OC_FileProxy::runPostProxies('file_put_contents', $absolutePath, $count); @@ -396,7 +409,7 @@ class View { $postFix = (substr($path, -1, 1) === '/') ? '/' : ''; $absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path)); $mount = Filesystem::getMountManager()->find($absolutePath . $postFix); - if ($mount->getInternalPath($absolutePath) === '') { + if ($mount and $mount->getInternalPath($absolutePath) === '') { return $this->removeMount($mount, $absolutePath); } return $this->basicOperation('unlink', $path, array('delete')); @@ -489,15 +502,14 @@ class View { } } } - if ($this->shouldEmitHooks() && (Cache\Scanner::isPartialFile($path1) && !Cache\Scanner::isPartialFile($path2)) && $result !== false) { + if ((Cache\Scanner::isPartialFile($path1) && !Cache\Scanner::isPartialFile($path2)) && $result !== false) { // if it was a rename from a part file to a regular file it was a write and not a rename operation - Updater::writeHook(array('path' => $this->getHookPath($path2))); - $this->emit_file_hooks_post($exists, $path2); + $this->updater->update($path2); + if ($this->shouldEmitHooks()) { + $this->emit_file_hooks_post($exists, $path2); + } } elseif ($this->shouldEmitHooks() && $result !== false) { - Updater::renameHook(array( - 'oldpath' => $this->getHookPath($path1), - 'newpath' => $this->getHookPath($path2) - )); + $this->updater->rename($path1, $path2); \OC_Hook::emit( Filesystem::CLASSNAME, Filesystem::signal_post_rename, @@ -576,6 +588,7 @@ class View { fclose($target); } } + $this->updater->update($path2); if ($this->shouldEmitHooks() && $result !== false) { \OC_Hook::emit( Filesystem::CLASSNAME, @@ -754,7 +767,19 @@ class View { } else { $result = $storage->$operation($internalPath); } + $result = \OC_FileProxy::runPostProxies($operation, $this->getAbsolutePath($path), $result); + + if (in_array('delete', $hooks)) { + $this->updater->remove($path); + } + if (in_array('write', $hooks)) { + $this->updater->update($path); + } + if (in_array('touch', $hooks)) { + $this->updater->update($path, $extraParam); + } + if ($this->shouldEmitHooks($path) && $result !== false) { if ($operation != 'fopen') { //no post hooks for fopen, the file stream is still open $this->runHooks($hooks, $path, true); @@ -808,16 +833,6 @@ class View { $run = true; if ($this->shouldEmitHooks($path)) { foreach ($hooks as $hook) { - // manually triger updater hooks to ensure they are called first - if ($post) { - if ($hook == 'write') { - Updater::writeHook(array('path' => $path)); - } elseif ($hook == 'touch') { - Updater::touchHook(array('path' => $path)); - } else if ($hook == 'delete') { - Updater::deleteHook(array('path' => $path)); - } - } if ($hook != 'read') { \OC_Hook::emit( Filesystem::CLASSNAME, diff --git a/lib/private/helper.php b/lib/private/helper.php index 7c1edd1b058..f696b5a8900 100644 --- a/lib/private/helper.php +++ b/lib/private/helper.php @@ -129,12 +129,12 @@ class OC_Helper { * Returns a absolute url to the given service. */ public static function linkToPublic($service, $add_slash = false) { - return OC::$server->getURLGenerator()->getAbsoluteURL( - self::linkTo( - '', 'public.php') . '?service=' . $service - . (($add_slash && $service[strlen($service) - 1] != '/') ? '/' : '' - ) - ); + if ($service === 'files') { + $url = OC::$server->getURLGenerator()->getAbsoluteURL('/s'); + } else { + $url = OC::$server->getURLGenerator()->getAbsoluteURL(self::linkTo('', 'public.php').'?service='.$service); + } + return $url . (($add_slash && $service[strlen($service) - 1] != '/') ? '/' : ''); } /** diff --git a/lib/private/preview/office-cl.php b/lib/private/preview/office-cl.php index 81e0cf4b6ae..42d2cbf34fc 100644 --- a/lib/private/preview/office-cl.php +++ b/lib/private/preview/office-cl.php @@ -29,7 +29,7 @@ if (!\OC_Util::runningOnWindows()) { $tmpDir = get_temp_dir(); - $defaultParameters = ' -env:UserInstallation=file://' . escapeshellarg($tmpDir) . ' --headless --nologo --nofirststartwizard --invisible --norestore -convert-to pdf -outdir '; + $defaultParameters = ' -env:UserInstallation=file://' . escapeshellarg($tmpDir . '/owncloud-' . \OC_Util::getInstanceId().'/') . ' --headless --nologo --nofirststartwizard --invisible --norestore -convert-to pdf -outdir '; $clParameters = \OCP\Config::getSystemValue('preview_office_cl_parameters', $defaultParameters); $exec = $this->cmd . $clParameters . escapeshellarg($tmpDir) . ' ' . escapeshellarg($absPath); diff --git a/lib/private/preview/office.php b/lib/private/preview/office.php index 16e395cb1a8..b47cbc6e08f 100644 --- a/lib/private/preview/office.php +++ b/lib/private/preview/office.php @@ -17,7 +17,7 @@ if (extension_loaded('imagick')) { if (!\OC_Util::runningOnWindows()) { $whichLibreOffice = ($isShellExecEnabled ? shell_exec('command -v libreoffice') : ''); $isLibreOfficeAvailable = !empty($whichLibreOffice); - $whichOpenOffice = ($isShellExecEnabled ? shell_exec('command -v libreoffice') : ''); + $whichOpenOffice = ($isShellExecEnabled ? shell_exec('command -v openoffice') : ''); $isOpenOfficeAvailable = !empty($whichOpenOffice); //let's see if there is libreoffice or openoffice on this machine if($isShellExecEnabled && ($isLibreOfficeAvailable || $isOpenOfficeAvailable || is_string(\OC_Config::getValue('preview_libreoffice_path', null)))) { diff --git a/lib/private/server.php b/lib/private/server.php index 71a098f9074..912d5c4f635 100644 --- a/lib/private/server.php +++ b/lib/private/server.php @@ -518,4 +518,13 @@ class Server extends SimpleContainer implements IServerContainer { } return new CertificateManager($user); } + + /** + * Create a new event source + * + * @return \OCP\IEventSource + */ + function createEventSource() { + return new \OC_EventSource(); + } } diff --git a/lib/private/share/constants.php b/lib/private/share/constants.php index 4c398c43c2d..798327cc154 100644 --- a/lib/private/share/constants.php +++ b/lib/private/share/constants.php @@ -34,7 +34,7 @@ class Constants { const FORMAT_STATUSES = -2; const FORMAT_SOURCES = -3; // ToDo Check if it is still in use otherwise remove it - const TOKEN_LENGTH = 32; // see db_structure.xml + const TOKEN_LENGTH = 15; // old (oc7) length is 32, keep token length in db at least that for compatibility protected static $shareTypeUserAndGroups = -1; protected static $shareTypeGroupUserUnique = 2; diff --git a/lib/private/share/share.php b/lib/private/share/share.php index e2e9b94125e..8441e6a94c4 100644 --- a/lib/private/share/share.php +++ b/lib/private/share/share.php @@ -640,7 +640,10 @@ class Share extends \OC\Share\Constants { if (isset($oldToken)) { $token = $oldToken; } else { - $token = \OC_Util::generateRandomBytes(self::TOKEN_LENGTH); + $token = \OC::$server->getSecureRandom()->getMediumStrengthGenerator()->generate(self::TOKEN_LENGTH, + \OCP\Security\ISecureRandom::CHAR_LOWER.\OCP\Security\ISecureRandom::CHAR_UPPER. + \OCP\Security\ISecureRandom::CHAR_DIGITS + ); } $result = self::put($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions, null, $token, $itemSourceName, $expirationDate); diff --git a/lib/private/template/functions.php b/lib/private/template/functions.php index 3cbf0d9748f..09db011e748 100644 --- a/lib/private/template/functions.php +++ b/lib/private/template/functions.php @@ -24,6 +24,24 @@ function print_unescaped($string) { } /** + * Shortcut for adding scripts to a page + * @param string $app the appname + * @param string $file the filename + */ +function script($app, $file) { + OC_Util::addScript($app, $file); +} + +/** + * Shortcut for adding styles to a page + * @param string $app the appname + * @param string $file the filename + */ +function style($app, $file) { + OC_Util::addStyle($app, $file); +} + +/** * make OC_Helper::linkTo available as a simple function * @param string $app app * @param string $file file diff --git a/lib/private/util.php b/lib/private/util.php index 2a0f9197e3c..6f45e00215d 100755 --- a/lib/private/util.php +++ b/lib/private/util.php @@ -1461,9 +1461,11 @@ class OC_Util { } /** - * Check whether the instance needs to preform an upgrade + * Check whether the instance needs to perform an upgrade, + * either when the core version is higher or any app requires + * an upgrade. * - * @return bool + * @return bool whether the core or any app needs an upgrade */ public static function needUpgrade() { if (OC_Config::getValue('installed', false)) { @@ -1473,14 +1475,16 @@ class OC_Util { return true; } - // also check for upgrades for apps - $apps = \OC_App::getEnabledApps(); + // also check for upgrades for apps (independently from the user) + $apps = \OC_App::getEnabledApps(false, true); + $shouldUpgrade = false; foreach ($apps as $app) { if (\OC_App::shouldUpgrade($app)) { - return true; + $shouldUpgrade = true; + break; } } - return false; + return $shouldUpgrade; } else { return false; } diff --git a/lib/public/ieventsource.php b/lib/public/ieventsource.php new file mode 100644 index 00000000000..eb7853c5e90 --- /dev/null +++ b/lib/public/ieventsource.php @@ -0,0 +1,34 @@ +<?php +/** + * Copyright (c) 2014 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OCP; + +/** + * wrapper for server side events (http://en.wikipedia.org/wiki/Server-sent_events) + * includes a fallback for older browsers and IE + * + * use server side events with caution, to many open requests can hang the server + * + * The event source will initialize the connection to the client when the first data is sent + */ +interface IEventSource { + /** + * send a message to the client + * + * @param string $type + * @param mixed $data + * + * if only one parameter is given, a typeless message will be send with that parameter as data + */ + public function send($type, $data = null); + + /** + * close the connection of the event source + */ + public function close(); +} diff --git a/lib/public/iservercontainer.php b/lib/public/iservercontainer.php index 60b0b497c54..1abf0d9938d 100644 --- a/lib/public/iservercontainer.php +++ b/lib/public/iservercontainer.php @@ -235,4 +235,11 @@ interface IServerContainer { * @return \OCP\ICertificateManager */ function getCertificateManager($user = null); + + /** + * Create a new event source + * + * @return \OCP\IEventSource + */ + function createEventSource(); } |