diff options
Diffstat (limited to 'lib/private')
30 files changed, 626 insertions, 48 deletions
diff --git a/lib/private/activitymanager.php b/lib/private/activitymanager.php new file mode 100755 index 00000000000..7e7e2257874 --- /dev/null +++ b/lib/private/activitymanager.php @@ -0,0 +1,69 @@ +<?php +/** + * Copyright (c) 2013 Thomas Müller thomas.mueller@tmit.eu + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + * + */ +namespace OC; + + +use OCP\Activity\IConsumer; +use OCP\Activity\IManager; + +class ActivityManager implements IManager { + + private $consumers = array(); + + /** + * @param $app + * @param $subject + * @param $subjectParams + * @param $message + * @param $messageParams + * @param $file + * @param $link + * @param $affectedUser + * @param $type + * @param $priority + * @return mixed + */ + function publishActivity($app, $subject, $subjectParams, $message, $messageParams, $file, $link, $affectedUser, $type, $priority) { + foreach($this->consumers as $consumer) { + $c = $consumer(); + if ($c instanceof IConsumer) { + try { + $c->receive( + $app, + $subject, + $subjectParams, + $message, + $messageParams, + $file, + $link, + $affectedUser, + $type, + $priority); + } catch (\Exception $ex) { + // TODO: log the excepetion + } + } + + } + } + + /** + * In order to improve lazy loading a closure can be registered which will be called in case + * activity consumers are actually requested + * + * $callable has to return an instance of OCA\Activity\IConsumer + * + * @param string $key + * @param \Closure $callable + */ + function registerConsumer(\Closure $callable) { + array_push($this->consumers, $callable); + } + +} diff --git a/lib/private/api.php b/lib/private/api.php index 31f3f968d9b..26091657b31 100644 --- a/lib/private/api.php +++ b/lib/private/api.php @@ -46,6 +46,7 @@ class OC_API { * api actions */ protected static $actions = array(); + private static $logoutRequired = false; /** * registers an api call @@ -115,7 +116,9 @@ class OC_API { $formats = array('json', 'xml'); $format = !empty($_GET['format']) && in_array($_GET['format'], $formats) ? $_GET['format'] : 'xml'; - OC_User::logout(); + if (self::$logoutRequired) { + OC_User::logout(); + } self::respond($response, $format); } @@ -235,10 +238,23 @@ class OC_API { * http basic auth * @return string|false (username, or false on failure) */ - private static function loginUser(){ + private static function loginUser(){ + // basic auth $authUser = isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : ''; $authPw = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : ''; - return OC_User::login($authUser, $authPw) ? $authUser : false; + $return = OC_User::login($authUser, $authPw); + if ($return === true) { + self::$logoutRequired = true; + return $authUser; + } + + // reuse existing login + $loggedIn = OC_User::isLoggedIn(); + if ($loggedIn === true) { + return OC_User::getUser(); + } + + return false; } /** diff --git a/lib/private/app.php b/lib/private/app.php index 6f45b6e6dd7..eca40a81cc1 100644 --- a/lib/private/app.php +++ b/lib/private/app.php @@ -249,6 +249,7 @@ class OC_App{ if(isset($appdata['id'])) { OC_Appconfig::setValue( $app, 'ocsid', $appdata['id'] ); } + \OC_Hook::emit('OC_App', 'post_enable', array('app' => $app)); } }else{ throw new \Exception($l->t("No app name specified")); diff --git a/lib/private/appconfig.php b/lib/private/appconfig.php index e615d838173..4f170e054e9 100644 --- a/lib/private/appconfig.php +++ b/lib/private/appconfig.php @@ -134,6 +134,12 @@ class OC_Appconfig{ .' WHERE `appid` = ? AND `configkey` = ?' ); $query->execute( array( $value, $app, $key )); } + // TODO where should this be documented? + \OC_Hook::emit('OC_Appconfig', 'post_set_value', array( + 'app' => $app, + 'key' => $key, + 'value' => $value + )); } /** diff --git a/lib/private/appframework/dependencyinjection/dicontainer.php b/lib/private/appframework/dependencyinjection/dicontainer.php index 81910df6990..e2ea974e104 100644 --- a/lib/private/appframework/dependencyinjection/dicontainer.php +++ b/lib/private/appframework/dependencyinjection/dicontainer.php @@ -24,7 +24,7 @@ namespace OC\AppFramework\DependencyInjection; -use OC\AppFramework\Http\Http; +use OC\AppFramework\Http; use OC\AppFramework\Http\Request; use OC\AppFramework\Http\Dispatcher; use OC\AppFramework\Core\API; @@ -88,8 +88,9 @@ class DIContainer extends SimpleContainer implements IAppContainer{ /** * Middleware */ - $this['SecurityMiddleware'] = $this->share(function($c){ - return new SecurityMiddleware($this, $c['Request']); + $app = $this; + $this['SecurityMiddleware'] = $this->share(function($c) use ($app){ + return new SecurityMiddleware($app, $c['Request']); }); $middleWares = $this->middleWares; diff --git a/lib/private/appframework/http/http.php b/lib/private/appframework/http.php index e00dc9cdc4a..41fc0db6b38 100644 --- a/lib/private/appframework/http/http.php +++ b/lib/private/appframework/http.php @@ -22,10 +22,11 @@ */ -namespace OC\AppFramework\Http; +namespace OC\AppFramework; +use OCP\AppFramework\Http as BaseHttp; -class Http extends \OCP\AppFramework\Http\Http{ +class Http extends BaseHttp { private $server; private $protocolVersion; diff --git a/lib/private/appframework/http/dispatcher.php b/lib/private/appframework/http/dispatcher.php index 51283fd64e7..a2afb53f0fa 100644 --- a/lib/private/appframework/http/dispatcher.php +++ b/lib/private/appframework/http/dispatcher.php @@ -25,6 +25,7 @@ namespace OC\AppFramework\Http; use \OC\AppFramework\Middleware\MiddlewareDispatcher; +use \OC\AppFramework\Http; use OCP\AppFramework\Controller; diff --git a/lib/private/appframework/http/redirectresponse.php b/lib/private/appframework/http/redirectresponse.php index 688447f1618..c4e21059480 100644 --- a/lib/private/appframework/http/redirectresponse.php +++ b/lib/private/appframework/http/redirectresponse.php @@ -24,7 +24,8 @@ namespace OC\AppFramework\Http; -use OCP\AppFramework\Http\Response; +use OCP\AppFramework\Http\Response, + OCP\AppFramework\Http; /** diff --git a/lib/private/appframework/middleware/security/securitymiddleware.php b/lib/private/appframework/middleware/security/securitymiddleware.php index f103a40ee7f..c3143754823 100644 --- a/lib/private/appframework/middleware/security/securitymiddleware.php +++ b/lib/private/appframework/middleware/security/securitymiddleware.php @@ -24,7 +24,7 @@ namespace OC\AppFramework\Middleware\Security; -use OC\AppFramework\Http\Http; +use OC\AppFramework\Http; use OC\AppFramework\Http\RedirectResponse; use OC\AppFramework\Utility\MethodAnnotationReader; use OCP\AppFramework\Middleware; diff --git a/lib/private/config.php b/lib/private/config.php index 72423137fa3..caf7b1d7066 100644 --- a/lib/private/config.php +++ b/lib/private/config.php @@ -172,7 +172,7 @@ class Config { $result = @file_put_contents($this->configFilename, $content); if (!$result) { $defaults = new \OC_Defaults; - $url = $defaults->getDocBaseUrl() . '/server/5.0/admin_manual/installation/installation_source.html#set-the-directory-permissions'; + $url = \OC_Helper::linkToDocs('admin-dir-permissions'); throw new HintException( "Can't write into config directory!", 'This can usually be fixed by ' diff --git a/lib/private/connector/sabre/file.php b/lib/private/connector/sabre/file.php index 3402946a136..6ace8d14484 100644 --- a/lib/private/connector/sabre/file.php +++ b/lib/private/connector/sabre/file.php @@ -148,6 +148,9 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D } \OC\Files\Filesystem::unlink($this->path); + // remove properties + $this->removeProperties(); + } /** diff --git a/lib/private/connector/sabre/node.php b/lib/private/connector/sabre/node.php index c38e9f86375..3c2ad60f1dd 100644 --- a/lib/private/connector/sabre/node.php +++ b/lib/private/connector/sabre/node.php @@ -191,6 +191,17 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr } /** + * removes all properties for this node and user + */ + public function removeProperties() { + $query = OC_DB::prepare( 'DELETE FROM `*PREFIX*properties`' + .' WHERE `userid` = ? AND `propertypath` = ?' ); + $query->execute( array( OC_User::getUser(), $this->path)); + + $this->setPropertyCache(null); + } + + /** * @brief Returns a list of properties for this nodes.; * @param array $properties * @return array diff --git a/lib/private/connector/sabre/objecttree.php b/lib/private/connector/sabre/objecttree.php index df8902f66e2..cd3f081f7cc 100644 --- a/lib/private/connector/sabre/objecttree.php +++ b/lib/private/connector/sabre/objecttree.php @@ -97,6 +97,11 @@ class ObjectTree extends \Sabre_DAV_ObjectTree { throw new \Sabre_DAV_Exception_Forbidden(''); } + // update properties + $query = \OC_DB::prepare( 'UPDATE `*PREFIX*properties` SET `propertypath` = ?' + .' WHERE `userid` = ? AND `propertypath` = ?' ); + $query->execute( array( $destinationPath, \OC_User::getUser(), $sourcePath )); + $this->markDirty($sourceDir); $this->markDirty($destinationDir); diff --git a/lib/private/connector/sabre/server.php b/lib/private/connector/sabre/server.php new file mode 100644 index 00000000000..41e8885917a --- /dev/null +++ b/lib/private/connector/sabre/server.php @@ -0,0 +1,235 @@ +<?php +/** + * ownCloud / SabreDAV + * + * @author Markus Goetz + * + * @copyright Copyright (C) 2007-2013 Rooftop Solutions. All rights reserved. + * @author Evert Pot (http://www.rooftopsolutions.nl/) + * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License + */ + +/** + * Class OC_Connector_Sabre_Server + * + * This class reimplements some methods from @see Sabre_DAV_Server. + * + * Basically we add handling of depth: infinity. + * + * The right way to handle this would have been to submit a patch to the upstream project + * and grab the corresponding version one merged. + * + * Due to time constrains and the limitations where we don't want to upgrade 3rdparty code in + * this stage of the release cycle we did choose this approach. + * + * For ownCloud 7 we will upgrade SabreDAV and submit the patch - if needed. + * + * @see Sabre_DAV_Server + */ +class OC_Connector_Sabre_Server extends Sabre_DAV_Server { + + /** + * @see Sabre_DAV_Server + */ + protected function httpPropfind($uri) { + + // $xml = new Sabre_DAV_XMLReader(file_get_contents('php://input')); + $requestedProperties = $this->parsePropFindRequest($this->httpRequest->getBody(true)); + + $depth = $this->getHTTPDepth(1); + // The only two options for the depth of a propfind is 0 or 1 + // if ($depth!=0) $depth = 1; + + $newProperties = $this->getPropertiesForPath($uri,$requestedProperties,$depth); + + // This is a multi-status response + $this->httpResponse->sendStatus(207); + $this->httpResponse->setHeader('Content-Type','application/xml; charset=utf-8'); + $this->httpResponse->setHeader('Vary','Brief,Prefer'); + + // Normally this header is only needed for OPTIONS responses, however.. + // iCal seems to also depend on these being set for PROPFIND. Since + // this is not harmful, we'll add it. + $features = array('1','3', 'extended-mkcol'); + foreach($this->plugins as $plugin) { + $features = array_merge($features,$plugin->getFeatures()); + } + + $this->httpResponse->setHeader('DAV',implode(', ',$features)); + + $prefer = $this->getHTTPPrefer(); + $minimal = $prefer['return-minimal']; + + $data = $this->generateMultiStatus($newProperties, $minimal); + $this->httpResponse->sendBody($data); + + } + + /** + * Small helper to support PROPFIND with DEPTH_INFINITY. + */ + private function addPathNodesRecursively(&$nodes, $path) { + foreach($this->tree->getChildren($path) as $childNode) { + $nodes[$path . '/' . $childNode->getName()] = $childNode; + if ($childNode instanceof Sabre_DAV_ICollection) + $this->addPathNodesRecursively($nodes, $path . '/' . $childNode->getName()); + } + } + + public function getPropertiesForPath($path, $propertyNames = array(), $depth = 0) { + + // if ($depth!=0) $depth = 1; + + $path = rtrim($path,'/'); + + $returnPropertyList = array(); + + $parentNode = $this->tree->getNodeForPath($path); + $nodes = array( + $path => $parentNode + ); + if ($depth==1 && $parentNode instanceof Sabre_DAV_ICollection) { + foreach($this->tree->getChildren($path) as $childNode) + $nodes[$path . '/' . $childNode->getName()] = $childNode; + } else if ($depth == self::DEPTH_INFINITY && $parentNode instanceof Sabre_DAV_ICollection) { + $this->addPathNodesRecursively($nodes, $path); + } + + // If the propertyNames array is empty, it means all properties are requested. + // We shouldn't actually return everything we know though, and only return a + // sensible list. + $allProperties = count($propertyNames)==0; + + foreach($nodes as $myPath=>$node) { + + $currentPropertyNames = $propertyNames; + + $newProperties = array( + '200' => array(), + '404' => array(), + ); + + if ($allProperties) { + // Default list of propertyNames, when all properties were requested. + $currentPropertyNames = array( + '{DAV:}getlastmodified', + '{DAV:}getcontentlength', + '{DAV:}resourcetype', + '{DAV:}quota-used-bytes', + '{DAV:}quota-available-bytes', + '{DAV:}getetag', + '{DAV:}getcontenttype', + ); + } + + // If the resourceType was not part of the list, we manually add it + // and mark it for removal. We need to know the resourcetype in order + // to make certain decisions about the entry. + // WebDAV dictates we should add a / and the end of href's for collections + $removeRT = false; + if (!in_array('{DAV:}resourcetype',$currentPropertyNames)) { + $currentPropertyNames[] = '{DAV:}resourcetype'; + $removeRT = true; + } + + $result = $this->broadcastEvent('beforeGetProperties',array($myPath, $node, &$currentPropertyNames, &$newProperties)); + // If this method explicitly returned false, we must ignore this + // node as it is inaccessible. + if ($result===false) continue; + + if (count($currentPropertyNames) > 0) { + + if ($node instanceof Sabre_DAV_IProperties) { + $nodeProperties = $node->getProperties($currentPropertyNames); + + // The getProperties method may give us too much, + // properties, in case the implementor was lazy. + // + // So as we loop through this list, we will only take the + // properties that were actually requested and discard the + // rest. + foreach($currentPropertyNames as $k=>$currentPropertyName) { + if (isset($nodeProperties[$currentPropertyName])) { + unset($currentPropertyNames[$k]); + $newProperties[200][$currentPropertyName] = $nodeProperties[$currentPropertyName]; + } + } + + } + + } + + foreach($currentPropertyNames as $prop) { + + if (isset($newProperties[200][$prop])) continue; + + switch($prop) { + case '{DAV:}getlastmodified' : if ($node->getLastModified()) $newProperties[200][$prop] = new Sabre_DAV_Property_GetLastModified($node->getLastModified()); break; + case '{DAV:}getcontentlength' : + if ($node instanceof Sabre_DAV_IFile) { + $size = $node->getSize(); + if (!is_null($size)) { + $newProperties[200][$prop] = (int)$node->getSize(); + } + } + break; + case '{DAV:}quota-used-bytes' : + if ($node instanceof Sabre_DAV_IQuota) { + $quotaInfo = $node->getQuotaInfo(); + $newProperties[200][$prop] = $quotaInfo[0]; + } + break; + case '{DAV:}quota-available-bytes' : + if ($node instanceof Sabre_DAV_IQuota) { + $quotaInfo = $node->getQuotaInfo(); + $newProperties[200][$prop] = $quotaInfo[1]; + } + break; + case '{DAV:}getetag' : if ($node instanceof Sabre_DAV_IFile && $etag = $node->getETag()) $newProperties[200][$prop] = $etag; break; + case '{DAV:}getcontenttype' : if ($node instanceof Sabre_DAV_IFile && $ct = $node->getContentType()) $newProperties[200][$prop] = $ct; break; + case '{DAV:}supported-report-set' : + $reports = array(); + foreach($this->plugins as $plugin) { + $reports = array_merge($reports, $plugin->getSupportedReportSet($myPath)); + } + $newProperties[200][$prop] = new Sabre_DAV_Property_SupportedReportSet($reports); + break; + case '{DAV:}resourcetype' : + $newProperties[200]['{DAV:}resourcetype'] = new Sabre_DAV_Property_ResourceType(); + foreach($this->resourceTypeMapping as $className => $resourceType) { + if ($node instanceof $className) $newProperties[200]['{DAV:}resourcetype']->add($resourceType); + } + break; + + } + + // If we were unable to find the property, we will list it as 404. + if (!$allProperties && !isset($newProperties[200][$prop])) $newProperties[404][$prop] = null; + + } + + $this->broadcastEvent('afterGetProperties',array(trim($myPath,'/'),&$newProperties, $node)); + + $newProperties['href'] = trim($myPath,'/'); + + // Its is a WebDAV recommendation to add a trailing slash to collectionnames. + // Apple's iCal also requires a trailing slash for principals (rfc 3744), though this is non-standard. + if ($myPath!='' && isset($newProperties[200]['{DAV:}resourcetype'])) { + $rt = $newProperties[200]['{DAV:}resourcetype']; + if ($rt->is('{DAV:}collection') || $rt->is('{DAV:}principal')) { + $newProperties['href'] .='/'; + } + } + + // If the resourcetype property was manually added to the requested property list, + // we will remove it again. + if ($removeRT) unset($newProperties[200]['{DAV:}resourcetype']); + + $returnPropertyList[] = $newProperties; + + } + + return $returnPropertyList; + + } +} diff --git a/lib/private/davclient.php b/lib/private/davclient.php new file mode 100644 index 00000000000..28f48f3b921 --- /dev/null +++ b/lib/private/davclient.php @@ -0,0 +1,46 @@ +<?php +/** + * ownCloud + * + * @author Vincent Petry + * @copyright 2013 Vincent Petry <pvince81@owncloud.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/>. + * + */ + +/** + * This class extends the SabreDAV client with additional functionality + * like request timeout. + */ + +class OC_DAVClient extends \Sabre_DAV_Client { + + protected $requestTimeout; + + /** + * @brief Sets the request timeout or 0 to disable timeout. + * @param int timeout in seconds or 0 to disable + */ + public function setRequestTimeout($timeout) { + $this->requestTimeout = (int)$timeout; + } + + protected function curlRequest($url, $settings) { + if ($this->requestTimeout > 0) { + $settings[CURLOPT_TIMEOUT] = $this->requestTimeout; + } + return parent::curlRequest($url, $settings); + } +} diff --git a/lib/private/db/connection.php b/lib/private/db/connection.php index 2d3193a148a..2581969dbd0 100644 --- a/lib/private/db/connection.php +++ b/lib/private/db/connection.php @@ -12,7 +12,7 @@ use Doctrine\DBAL\Configuration; use Doctrine\DBAL\Cache\QueryCacheProfile; use Doctrine\Common\EventManager; -class Connection extends \Doctrine\DBAL\Connection implements \OCP\IDBConnection { +class Connection extends \Doctrine\DBAL\Connection { /** * @var string $tablePrefix */ diff --git a/lib/private/db/connectionwrapper.php b/lib/private/db/connectionwrapper.php new file mode 100644 index 00000000000..93d4fb57f74 --- /dev/null +++ b/lib/private/db/connectionwrapper.php @@ -0,0 +1,99 @@ +<?php +/** + * Copyright (c) 2013 Thomas Müller <deepdiver@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\DB; + + +class ConnectionWrapper implements \OCP\IDBConnection { + + private $connection; + + public function __construct(Connection $conn) { + $this->connection = $conn; + } + + /** + * Used to the owncloud database access away + * @param string $sql the sql query with ? placeholder for params + * @param int $limit the maximum number of rows + * @param int $offset from which row we want to start + * @return \Doctrine\DBAL\Driver\Statement The prepared statement. + */ + public function prepare($sql, $limit = null, $offset = null) + { + return $this->connection->prepare($sql, $limit, $offset); + } + + /** + * Used to get the id of the just inserted element + * @param string $tableName the name of the table where we inserted the item + * @return int the id of the inserted element + */ + public function lastInsertId($table = null) + { + return $this->connection->lastInsertId($table); + } + + /** + * Insert a row if a matching row doesn't exists. + * @param string The table name (will replace *PREFIX*) to perform the replace on. + * @param array + * + * The input array if in the form: + * + * array ( 'id' => array ( 'value' => 6, + * 'key' => true + * ), + * 'name' => array ('value' => 'Stoyan'), + * 'family' => array ('value' => 'Stefanov'), + * 'birth_date' => array ('value' => '1975-06-20') + * ); + * @return bool + * + */ + public function insertIfNotExist($table, $input) + { + return $this->connection->insertIfNotExist($table, $input); + } + + /** + * Start a transaction + * @return bool TRUE on success or FALSE on failure + */ + public function beginTransaction() + { + return $this->connection->beginTransaction(); + } + + /** + * Commit the database changes done during a transaction that is in progress + * @return bool TRUE on success or FALSE on failure + */ + public function commit() + { + return $this->connection->commit(); + } + + /** + * Rollback the database changes done during a transaction that is in progress + * @return bool TRUE on success or FALSE on failure + */ + public function rollBack() + { + return $this->connection->rollBack(); + } + + /** + * Gets the error code and message as a string for logging + * @return string + */ + public function getError() + { + return $this->connection->getError(); + } +} diff --git a/lib/private/db/mdb2schemamanager.php b/lib/private/db/mdb2schemamanager.php index fc13e881bff..416e2f55426 100644 --- a/lib/private/db/mdb2schemamanager.php +++ b/lib/private/db/mdb2schemamanager.php @@ -61,6 +61,7 @@ class MDB2SchemaManager { $toSchema = $schemaReader->loadSchemaFromFile($file); // remove tables we don't know about + /** @var $table \Doctrine\DBAL\Schema\Table */ foreach($fromSchema->getTables() as $table) { if (!$toSchema->hasTable($table->getName())) { $fromSchema->dropTable($table->getName()); @@ -77,11 +78,10 @@ class MDB2SchemaManager { $schemaDiff = $comparator->compare($fromSchema, $toSchema); $platform = $this->conn->getDatabasePlatform(); - $tables = $schemaDiff->newTables + $schemaDiff->changedTables + $schemaDiff->removedTables; - foreach($tables as $tableDiff) { + foreach($schemaDiff->changedTables as $tableDiff) { $tableDiff->name = $platform->quoteIdentifier($tableDiff->name); } - + if ($generateSql) { return $this->generateChangeScript($schemaDiff); } @@ -110,6 +110,7 @@ class MDB2SchemaManager { $schemaReader = new MDB2SchemaReader(\OC_Config::getObject(), $this->conn->getDatabasePlatform()); $fromSchema = $schemaReader->loadSchemaFromFile($file); $toSchema = clone $fromSchema; + /** @var $table \Doctrine\DBAL\Schema\Table */ foreach($toSchema->getTables() as $table) { $toSchema->dropTable($table->getName()); } diff --git a/lib/private/files/cache/cache.php b/lib/private/files/cache/cache.php index 364a50d377c..fc2d965d7f9 100644 --- a/lib/private/files/cache/cache.php +++ b/lib/private/files/cache/cache.php @@ -69,9 +69,15 @@ class Cache { } if (!isset(self::$mimetypeIds[$mime])) { - $result = \OC_DB::executeAudited('INSERT INTO `*PREFIX*mimetypes`(`mimetype`) VALUES(?)', array($mime)); - self::$mimetypeIds[$mime] = \OC_DB::insertid('*PREFIX*mimetypes'); - self::$mimetypes[self::$mimetypeIds[$mime]] = $mime; + try{ + $result = \OC_DB::executeAudited('INSERT INTO `*PREFIX*mimetypes`(`mimetype`) VALUES(?)', array($mime)); + self::$mimetypeIds[$mime] = \OC_DB::insertid('*PREFIX*mimetypes'); + self::$mimetypes[self::$mimetypeIds[$mime]] = $mime; + } + catch (\Doctrine\DBAL\DBALException $e){ + \OC_Log::write('core', 'Exception during mimetype insertion: ' . $e->getmessage(), \OC_Log::DEBUG); + return -1; + } } return self::$mimetypeIds[$mime]; @@ -84,8 +90,8 @@ class Cache { return isset(self::$mimetypes[$id]) ? self::$mimetypes[$id] : null; } - - protected function loadMimetypes(){ + + public function loadMimetypes(){ $result = \OC_DB::executeAudited('SELECT `id`, `mimetype` FROM `*PREFIX*mimetypes`', array()); if ($result) { while ($row = $result->fetchRow()) { diff --git a/lib/private/files/cache/scanner.php b/lib/private/files/cache/scanner.php index 96f84609cf2..f63abf2d4fc 100644 --- a/lib/private/files/cache/scanner.php +++ b/lib/private/files/cache/scanner.php @@ -190,24 +190,34 @@ class Scanner extends BasicEmitter { } $newChildren = array(); if ($this->storage->is_dir($path) && ($dh = $this->storage->opendir($path))) { + $exceptionOccurred = false; \OC_DB::beginTransaction(); if (is_resource($dh)) { while (($file = readdir($dh)) !== false) { $child = ($path) ? $path . '/' . $file : $file; if (!Filesystem::isIgnoredDir($file)) { $newChildren[] = $file; - $data = $this->scanFile($child, $reuse, true); - if ($data) { - if ($data['size'] === -1) { - if ($recursive === self::SCAN_RECURSIVE) { - $childQueue[] = $child; - } else { - $size = -1; + try { + $data = $this->scanFile($child, $reuse, true); + if ($data) { + if ($data['size'] === -1) { + if ($recursive === self::SCAN_RECURSIVE) { + $childQueue[] = $child; + } else { + $size = -1; + } + } else if ($size !== -1) { + $size += $data['size']; } - } else if ($size !== -1) { - $size += $data['size']; } } + catch (\Doctrine\DBAL\DBALException $ex){ + // might happen if inserting duplicate while a scanning + // process is running in parallel + // log and ignore + \OC_Log::write('core', 'Exception while scanning file "' . $child . '": ' . $ex->getMessage(), \OC_Log::DEBUG); + $exceptionOccurred = true; + } } } } @@ -217,6 +227,14 @@ class Scanner extends BasicEmitter { $this->cache->remove($child); } \OC_DB::commit(); + if ($exceptionOccurred){ + // It might happen that the parallel scan process has already + // inserted mimetypes but those weren't available yet inside the transaction + // To make sure to have the updated mime types in such cases, + // we reload them here + $this->cache->loadMimetypes(); + } + foreach ($childQueue as $child) { $childSize = $this->scanChildren($child, self::SCAN_RECURSIVE, $reuse); if ($childSize === -1) { diff --git a/lib/private/group.php b/lib/private/group.php index 9144ef683b6..444788c97f1 100644 --- a/lib/private/group.php +++ b/lib/private/group.php @@ -268,7 +268,7 @@ class OC_Group { $users = $group->searchDisplayName($search, $limit, $offset); $displayNames = array(); foreach ($users as $user) { - $displayNames[] = $user->getDisplayName(); + $displayNames[$user->getUID()] = $user->getDisplayName(); } return $displayNames; } else { diff --git a/lib/private/helper.php b/lib/private/helper.php index e9b129db0ca..fca08adca8b 100644 --- a/lib/private/helper.php +++ b/lib/private/helper.php @@ -59,6 +59,15 @@ class OC_Helper { } /** + * @param $key + * @return string url to the online documentation + */ + public static function linkToDocs($key) { + $theme = new OC_Defaults(); + return $theme->getDocBaseUrl() . '/server/5.0/go.php?to=' . $key; + } + + /** * @brief Creates an absolute url * @param string $app app * @param string $file file diff --git a/lib/private/log/owncloud.php b/lib/private/log/owncloud.php index a408e3830d6..15cace88f41 100644 --- a/lib/private/log/owncloud.php +++ b/lib/private/log/owncloud.php @@ -35,7 +35,17 @@ class OC_Log_Owncloud { public static function init() { $defaultLogFile = OC_Config::getValue("datadirectory", OC::$SERVERROOT.'/data').'/owncloud.log'; self::$logFile = OC_Config::getValue("logfile", $defaultLogFile); - if (!file_exists(self::$logFile)) { + + /* + * Fall back to default log file if specified logfile does not exist + * and can not be created. Error suppression is required in order to + * not end up in the error handler which will try to log the error. + * A better solution (compared to error suppression) would be checking + * !is_writable(dirname(self::$logFile)) before touch(), but + * is_writable() on directories used to be pretty unreliable on Windows + * for at least some time. + */ + if (!file_exists(self::$logFile) && !@touch(self::$logFile)) { self::$logFile = $defaultLogFile; } } @@ -61,6 +71,7 @@ class OC_Log_Owncloud { $entry=array('app'=>$app, 'message'=>$message, 'level'=>$level, 'time'=> $time->format($format)); $entry = json_encode($entry); $handle = @fopen(self::$logFile, 'a'); + @chmod(self::$logFile, 0640); if ($handle) { fwrite($handle, $entry."\n"); fclose($handle); diff --git a/lib/private/ocs/cloud.php b/lib/private/ocs/cloud.php index 2dd99319057..cbbf3b626f5 100644 --- a/lib/private/ocs/cloud.php +++ b/lib/private/ocs/cloud.php @@ -64,8 +64,7 @@ class OC_OCS_Cloud { // Check if they are viewing information on themselves if($parameters['userid'] === OC_User::getUser()) { // Self lookup - $quota = array(); - $storage = OC_Helper::getStorageInfo(); + $storage = OC_Helper::getStorageInfo('/'); $quota = array( 'free' => $storage['free'], 'used' => $storage['used'], @@ -79,6 +78,16 @@ class OC_OCS_Cloud { } } + public static function getCurrentUser() { + $email=OC_Preferences::getValue(OC_User::getUser(), 'settings', 'email', ''); + $data = array( + 'id' => OC_User::getUser(), + 'display-name' => OC_User::getDisplayName(), + 'email' => $email, + ); + return new OC_OCS_Result($data); + } + public static function getUserPublickey($parameters) { if(OC_User::userExists($parameters['user'])) { diff --git a/lib/private/preview/movies.php b/lib/private/preview/movies.php index dc50d160346..4d85e23c63c 100644 --- a/lib/private/preview/movies.php +++ b/lib/private/preview/movies.php @@ -11,7 +11,7 @@ namespace OC\Preview; // movie preview is currently not supported on Windows if (!\OC_Util::runningOnWindows()) { $isShellExecEnabled = !in_array('shell_exec', explode(', ', ini_get('disable_functions'))); - $whichAVCONV = shell_exec('which avconv'); + $whichAVCONV = ($isShellExecEnabled ? shell_exec('which avconv') : ''); $isAVCONVAvailable = !empty($whichAVCONV); if($isShellExecEnabled && $isAVCONVAvailable) { diff --git a/lib/private/preview/office.php b/lib/private/preview/office.php index 673b16edc19..318ab51f851 100644 --- a/lib/private/preview/office.php +++ b/lib/private/preview/office.php @@ -9,11 +9,11 @@ if (extension_loaded('imagick')) { $isShellExecEnabled = !in_array('shell_exec', explode(', ', ini_get('disable_functions'))); - // movie preview is currently not supported on Windows + // LibreOffice preview is currently not supported on Windows if (!\OC_Util::runningOnWindows()) { - $whichLibreOffice = shell_exec('which libreoffice'); + $whichLibreOffice = ($isShellExecEnabled ? shell_exec('which libreoffice') : ''); $isLibreOfficeAvailable = !empty($whichLibreOffice); - $whichOpenOffice = shell_exec('which libreoffice'); + $whichOpenOffice = ($isShellExecEnabled ? shell_exec('which libreoffice') : ''); $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 e55f59f6a1c..65899f3007e 100644 --- a/lib/private/server.php +++ b/lib/private/server.php @@ -5,6 +5,7 @@ namespace OC; use OC\AppFramework\Http\Request; use OC\AppFramework\Utility\SimpleContainer; use OC\Cache\UserCache; +use OC\DB\ConnectionWrapper; use OC\Files\Node\Root; use OC\Files\View; use OCP\IServerContainer; @@ -127,6 +128,9 @@ class Server extends SimpleContainer implements IServerContainer { $this->registerService('UserCache', function($c) { return new UserCache(); }); + $this->registerService('ActivityManager', function($c) { + return new ActivityManager(); + }); } /** @@ -286,7 +290,15 @@ class Server extends SimpleContainer implements IServerContainer { * @return \OCP\IDBConnection */ function getDatabaseConnection() { - return \OC_DB::getConnection(); + return new ConnectionWrapper(\OC_DB::getConnection()); } + /** + * Returns the activity manager + * + * @return \OCP\Activity\IManager + */ + function getActivityManager() { + return $this->query('ActivityManager'); + } } diff --git a/lib/private/setup.php b/lib/private/setup.php index 6bf3c88370f..3cc1d29c6a4 100644 --- a/lib/private/setup.php +++ b/lib/private/setup.php @@ -183,7 +183,7 @@ class OC_Setup { $error = $l->t('Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken.'); $hint = $l->t('Please double check the <a href=\'%s\'>installation guides</a>.', - 'http://doc.owncloud.org/server/5.0/admin_manual/installation.html'); + link_to_docs('admin-install')); OC_Template::printErrorPage($error, $hint); exit(); diff --git a/lib/private/template/functions.php b/lib/private/template/functions.php index 0aa2b27b96b..ce42633b364 100644 --- a/lib/private/template/functions.php +++ b/lib/private/template/functions.php @@ -36,6 +36,14 @@ function link_to( $app, $file, $args = array() ) { } /** + * @param $key + * @return string url to the online documentation + */ +function link_to_docs($key) { + return OC_Helper::linkToDocs($key); +} + +/** * @brief make OC_Helper::imagePath available as a simple function * @param string $app app * @param string $image image diff --git a/lib/private/util.php b/lib/private/util.php index 6c0a8d7bab5..f63884c0f32 100755 --- a/lib/private/util.php +++ b/lib/private/util.php @@ -303,16 +303,16 @@ class OC_Util { //common hint for all file permissions error messages $permissionsHint = 'Permissions can usually be fixed by ' - .'<a href="' . $defaults->getDocBaseUrl() . '/server/5.0/admin_manual/installation/installation_source.html' - .'#set-the-directory-permissions" target="_blank">giving the webserver write access to the root directory</a>.'; + .'<a href="' . OC_Helper::linkToDocs('admin-dir_permissions') + .'" target="_blank">giving the webserver write access to the root directory</a>.'; // Check if config folder is writable. if(!is_writable(OC::$SERVERROOT."/config/") or !is_readable(OC::$SERVERROOT."/config/")) { $errors[] = array( 'error' => "Can't write into config directory", 'hint' => 'This can usually be fixed by ' - .'<a href="' . $defaults->getDocBaseUrl() . '/server/5.0/admin_manual/installation/installation_source.html' - .'#set-the-directory-permissions" target="_blank">giving the webserver write access to the config directory</a>.' + .'<a href="' . OC_Helper::linkToDocs('admin-dir_permissions') + .'" target="_blank">giving the webserver write access to the config directory</a>.' ); } @@ -324,8 +324,8 @@ class OC_Util { $errors[] = array( 'error' => "Can't write into apps directory", 'hint' => 'This can usually be fixed by ' - .'<a href="' . $defaults->getDocBaseUrl() . '/server/5.0/admin_manual/installation/installation_source.html' - .'#set-the-directory-permissions" target="_blank">giving the webserver write access to the apps directory</a> ' + .'<a href="' . OC_Helper::linkToDocs('admin-dir_permissions') + .'" target="_blank">giving the webserver write access to the apps directory</a> ' .'or disabling the appstore in the config file.' ); } @@ -340,8 +340,8 @@ class OC_Util { $errors[] = array( 'error' => "Can't create data directory (".$CONFIG_DATADIRECTORY.")", 'hint' => 'This can usually be fixed by ' - .'<a href="' . $defaults->getDocBaseUrl() . '/server/5.0/admin_manual/installation/installation_source.html' - .'#set-the-directory-permissions" target="_blank">giving the webserver write access to the root directory</a>.' + .'<a href="' . OC_Helper::linkToDocs('admin-dir_permissions') + .'" target="_blank">giving the webserver write access to the root directory</a>.' ); } } else if(!is_writable($CONFIG_DATADIRECTORY) or !is_readable($CONFIG_DATADIRECTORY)) { @@ -754,6 +754,10 @@ class OC_Util { * file in the data directory and trying to access via http */ public static function isHtAccessWorking() { + if (!\OC_Config::getValue("check_for_working_htaccess", true)) { + return true; + } + // testdata $fileName = '/htaccesstest.txt'; $testContent = 'testcontent'; @@ -802,11 +806,16 @@ class OC_Util { if (!function_exists('curl_init')) { return true; } + if (!\OC_Config::getValue("check_for_working_webdav", true)) { + return true; + } $settings = array( 'baseUri' => OC_Helper::linkToRemote('webdav'), ); - $client = new \Sabre_DAV_Client($settings); + $client = new \OC_DAVClient($settings); + + $client->setRequestTimeout(10); // for this self test we don't care if the ssl certificate is self signed and the peer cannot be verified. $client->setVerifyPeer(false); |