diff options
author | Bart Visscher <bartv@thisnet.nl> | 2014-01-31 16:43:12 +0100 |
---|---|---|
committer | Bart Visscher <bartv@thisnet.nl> | 2014-01-31 16:43:12 +0100 |
commit | bca725dc32e159d756f023d428816b8f9821b732 (patch) | |
tree | c3e1910e952728433c2572cea96fa8024c79d1d5 /lib | |
parent | 09d2ba017e603fe6ac237da7830d86d74b2da61c (diff) | |
parent | 271088a7a23ffcdb2082b6dfc5b6f50833612a0f (diff) | |
download | nextcloud-server-bca725dc32e159d756f023d428816b8f9821b732.tar.gz nextcloud-server-bca725dc32e159d756f023d428816b8f9821b732.zip |
Merge branch 'master' into setup
Conflicts:
core/setup.php
Diffstat (limited to 'lib')
280 files changed, 6752 insertions, 3205 deletions
diff --git a/lib/autoloader.php b/lib/autoloader.php index b5b58918372..3451f799e18 100644 --- a/lib/autoloader.php +++ b/lib/autoloader.php @@ -16,6 +16,12 @@ class Autoloader { private $classPaths = array(); /** + * Optional low-latency memory cache for class to path mapping. + * @var \OC\Memcache\Cache + */ + protected $memoryCache; + + /** * Add a custom prefix to the autoloader * * @param string $prefix @@ -112,44 +118,39 @@ class Autoloader { * @param string $class * @return bool */ - protected $memoryCache = null; - protected $constructingMemoryCache = true; // hack to prevent recursion public function load($class) { - // Does this PHP have an in-memory cache? We cache the paths there - if ($this->constructingMemoryCache && !$this->memoryCache) { - $this->constructingMemoryCache = false; - try { - $this->memoryCache = \OC\Memcache\Factory::createLowLatency('Autoloader'); - } catch(\Exception $ex) { - // no caching then - fine with me - } - } + $pathsToRequire = null; if ($this->memoryCache) { $pathsToRequire = $this->memoryCache->get($class); - if (is_array($pathsToRequire)) { - foreach ($pathsToRequire as $path) { - require_once $path; - } - return false; - } } - // Use the normal class loading path - $paths = $this->findClass($class); - if (is_array($paths)) { + if (!is_array($pathsToRequire)) { + // No cache or cache miss $pathsToRequire = array(); - foreach ($paths as $path) { - if ($fullPath = stream_resolve_include_path($path)) { - require_once $fullPath; + foreach ($this->findClass($class) as $path) { + $fullPath = stream_resolve_include_path($path); + if ($fullPath) { $pathsToRequire[] = $fullPath; } } - // Save in our memory cache if ($this->memoryCache) { $this->memoryCache->set($class, $pathsToRequire, 60); // cache 60 sec } } + + foreach ($pathsToRequire as $fullPath) { + require_once $fullPath; + } + return false; } + + /** + * @brief Sets the optional low-latency cache for class to path mapping. + * @param \OC\Memcache\Cache $memoryCache Instance of memory cache. + */ + public function setMemoryCache(\OC\Memcache\Cache $memoryCache = null) { + $this->memoryCache = $memoryCache; + } } diff --git a/lib/base.php b/lib/base.php index 1246aee8110..0a890942c3b 100644 --- a/lib/base.php +++ b/lib/base.php @@ -57,6 +57,9 @@ class OC { * web path in 'url' */ public static $APPSROOTS = array(); + + public static $configDir; + /* * requested app */ @@ -69,8 +72,9 @@ class OC { * check if owncloud runs in cli mode */ public static $CLI = false; - /* - * OC router + + /** + * @var OC_Router */ protected static $router = null; @@ -99,6 +103,13 @@ class OC { get_include_path() ); + if(defined('PHPUNIT_RUN') and PHPUNIT_RUN and is_dir(OC::$SERVERROOT . '/tests/config/')) { + self::$configDir = OC::$SERVERROOT . '/tests/config/'; + } else { + self::$configDir = OC::$SERVERROOT . '/config/'; + } + OC_Config::$object = new \OC\Config(self::$configDir); + OC::$SUBURI = str_replace("\\", "/", substr(realpath($_SERVER["SCRIPT_FILENAME"]), strlen(OC::$SERVERROOT))); $scriptName = OC_Request::scriptName(); if (substr($scriptName, -1) == '/') { @@ -130,8 +141,8 @@ class OC { OC::$THIRDPARTYROOT = rtrim(dirname(OC::$SERVERROOT), '/'); } else { throw new Exception('3rdparty directory not found! Please put the ownCloud 3rdparty' - .' folder in the ownCloud folder or the folder above.' - .' You can also configure the location in the config.php file.'); + . ' folder in the ownCloud folder or the folder above.' + . ' You can also configure the location in the config.php file.'); } // search the apps folder $config_paths = OC_Config::getValue('apps_paths', array()); @@ -155,7 +166,7 @@ class OC { if (empty(OC::$APPSROOTS)) { throw new Exception('apps directory not found! Please put the ownCloud apps folder in the ownCloud folder' - .' or the folder above. You can also configure the location in the config.php file.'); + . ' or the folder above. You can also configure the location in the config.php file.'); } $paths = array(); foreach (OC::$APPSROOTS as $path) { @@ -174,14 +185,23 @@ class OC { } public static function checkConfig() { - if (file_exists(OC::$SERVERROOT . "/config/config.php") - and !is_writable(OC::$SERVERROOT . "/config/config.php")) { + if (file_exists(self::$configDir . "/config.php") + and !is_writable(self::$configDir . "/config.php") + ) { $defaults = new OC_Defaults(); - OC_Template::printErrorPage( - "Can't write into config directory!", - '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>.' - ); + if (self::$CLI) { + echo "Can't write into config directory!\n"; + echo "This can usually be fixed by giving the webserver write access to the config directory\n"; + echo "\n"; + echo "See " . \OC_Helper::linkToDocs('admin-dir_permissions') . "\n"; + exit; + } else { + OC_Template::printErrorPage( + "Can't write into config directory!", + 'This can usually be fixed by ' + . '<a href="' . \OC_Helper::linkToDocs('admin-dir_permissions') . '" target="_blank">giving the webserver write access to the config directory</a>.' + ); + } } } @@ -223,41 +243,73 @@ class OC { header('Retry-After: 120'); // render error page - OC_Template::printErrorPage('ownCloud is in maintenance mode'); + $tmpl = new OC_Template('', 'update.user', 'guest'); + $tmpl->printPage(); + die(); } } - public static function checkUpgrade($showTemplate = true) { + public static function checkSingleUserMode() { + $user = OC_User::getUserSession()->getUser(); + $group = OC_Group::getManager()->get('admin'); + if ($user && OC_Config::getValue('singleuser', false) && !$group->inGroup($user)) { + // send http status 503 + header('HTTP/1.1 503 Service Temporarily Unavailable'); + header('Status: 503 Service Temporarily Unavailable'); + header('Retry-After: 120'); + + // render error page + $tmpl = new OC_Template('', 'singleuser.user', 'guest'); + $tmpl->printPage(); + die(); + } + } + + /** + * check if the instance needs to preform an upgrade + * + * @return bool + */ + public static function needUpgrade() { if (OC_Config::getValue('installed', false)) { $installedVersion = OC_Config::getValue('version', '0.0.0'); $currentVersion = implode('.', OC_Util::getVersion()); - if (version_compare($currentVersion, $installedVersion, '>')) { - if ($showTemplate && !OC_Config::getValue('maintenance', false)) { - OC_Config::setValue('theme', ''); - $minimizerCSS = new OC_Minimizer_CSS(); - $minimizerCSS->clearCache(); - $minimizerJS = new OC_Minimizer_JS(); - $minimizerJS->clearCache(); - OC_Util::addscript('update'); - $tmpl = new OC_Template('', 'update', 'guest'); - $tmpl->assign('version', OC_Util::getVersionString()); - $tmpl->printPage(); - exit(); - } else { - return true; - } - } + return version_compare($currentVersion, $installedVersion, '>'); + } else { return false; } } + public static function checkUpgrade($showTemplate = true) { + if (self::needUpgrade()) { + if ($showTemplate && !OC_Config::getValue('maintenance', false)) { + OC_Config::setValue('theme', ''); + $minimizerCSS = new OC_Minimizer_CSS(); + $minimizerCSS->clearCache(); + $minimizerJS = new OC_Minimizer_JS(); + $minimizerJS->clearCache(); + OC_Util::addScript('config'); // needed for web root + OC_Util::addScript('update'); + $tmpl = new OC_Template('', 'update.admin', 'guest'); + $tmpl->assign('version', OC_Util::getVersionString()); + $tmpl->printPage(); + exit(); + } else { + return true; + } + } + return false; + } + public static function initTemplateEngine() { // Add the stuff we need always + // TODO: read from core/js/core.json OC_Util::addScript("jquery-1.10.0.min"); OC_Util::addScript("jquery-migrate-1.2.1.min"); OC_Util::addScript("jquery-ui-1.10.0.custom"); OC_Util::addScript("jquery-showpassword"); OC_Util::addScript("jquery.infieldlabel"); + OC_Util::addScript("jquery.placeholder"); OC_Util::addScript("jquery-tipsy"); OC_Util::addScript("compatibility"); OC_Util::addScript("jquery.ocdialog"); @@ -280,6 +332,7 @@ class OC { } OC_Util::addStyle("styles"); + OC_Util::addStyle("icons"); OC_Util::addStyle("apps"); OC_Util::addStyle("fixes"); OC_Util::addStyle("multiselect"); @@ -304,15 +357,9 @@ class OC { self::$session = new \OC\Session\Internal(OC_Util::getInstanceId()); // if session cant be started break with http 500 error } catch (Exception $e) { - OC_Log::write('core', 'Session could not be initialized', - OC_Log::ERROR); - - header('HTTP/1.1 500 Internal Server Error'); - OC_Util::addStyle("styles"); - $error = 'Session could not be initialized. Please contact your '; - $error .= 'system administrator'; - - OC_Template::printErrorPage($error); + //show the user a detailed error page + OC_Response::setStatus(OC_Response::STATUS_INTERNAL_SERVER_ERROR); + OC_Template::printExceptionErrorPage($e); } $sessionLifeTime = self::getSessionLifeTime(); @@ -344,6 +391,9 @@ class OC { return OC_Config::getValue('session_lifetime', 60 * 60 * 24); } + /** + * @return OC_Router + */ public static function getRouter() { if (!isset(OC::$router)) { OC::$router = new OC_Router(); @@ -372,8 +422,6 @@ class OC { self::$loader->registerPrefix('Doctrine\\DBAL', 'doctrine/dbal/lib'); self::$loader->registerPrefix('Symfony\\Component\\Routing', 'symfony/routing'); self::$loader->registerPrefix('Symfony\\Component\\Console', 'symfony/console'); - self::$loader->registerPrefix('Sabre\\VObject', '3rdparty'); - self::$loader->registerPrefix('Sabre_', '3rdparty'); self::$loader->registerPrefix('Patchwork', '3rdparty'); spl_autoload_register(array(self::$loader, 'load')); @@ -431,8 +479,22 @@ class OC { } self::initPaths(); + if (OC_Config::getValue('instanceid', false)) { + // \OC\Memcache\Cache has a hidden dependency on + // OC_Util::getInstanceId() for namespacing. See #5409. + try { + self::$loader->setMemoryCache(\OC\Memcache\Factory::createLowLatency('Autoloader')); + } catch (\Exception $ex) { + } + } OC_Util::isSetLocaleWorking(); + // setup 3rdparty autoloader + $vendorAutoLoad = OC::$THIRDPARTYROOT . '/3rdparty/autoload.php'; + if (file_exists($vendorAutoLoad)) { + require_once $vendorAutoLoad; + } + // set debug mode if an xdebug session is active if (!defined('DEBUG') || !DEBUG) { if (isset($_COOKIE['XDEBUG_SESSION'])) { @@ -471,7 +533,14 @@ class OC { $errors = OC_Util::checkServer(); if (count($errors) > 0) { - OC_Template::printGuestPage('', 'error', array('errors' => $errors)); + if (self::$CLI) { + foreach ($errors as $error) { + echo $error['error'] . "\n"; + echo $error['hint'] . "\n\n"; + } + } else { + OC_Template::printGuestPage('', 'error', array('errors' => $errors)); + } exit; } @@ -487,8 +556,13 @@ class OC { OC_User::useBackend(new OC_User_Database()); OC_Group::useBackend(new OC_Group_Database()); - if (isset($_SERVER['PHP_AUTH_USER']) && self::$session->exists('user_id') - && $_SERVER['PHP_AUTH_USER'] != self::$session->get('user_id')) { + if (isset($_SERVER['PHP_AUTH_USER']) && self::$session->exists('loginname') + && $_SERVER['PHP_AUTH_USER'] !== self::$session->get('loginname')) { + $sessionUser = self::$session->get('loginname'); + $serverUser = $_SERVER['PHP_AUTH_USER']; + OC_Log::write('core', + "Session loginname ($sessionUser) doesn't match SERVER[PHP_AUTH_USER] ($serverUser).", + OC_Log::WARN); OC_User::logout(); } @@ -496,7 +570,7 @@ class OC { // This includes plugins for users and filesystems as well global $RUNTIME_NOAPPS; global $RUNTIME_APPTYPES; - if (!$RUNTIME_NOAPPS) { + if (!$RUNTIME_NOAPPS && !self::checkUpgrade(false)) { if ($RUNTIME_APPTYPES) { OC_App::loadApps($RUNTIME_APPTYPES); } else { @@ -545,12 +619,6 @@ class OC { } } - // write error into log if locale can't be set - if (OC_Util::isSetLocaleWorking() == false) { - OC_Log::write('core', - 'setting locale to en_US.UTF-8/en_US.UTF8 failed. Support is probably not installed on your system', - OC_Log::ERROR); - } if (OC_Config::getValue('installed', false) && !self::checkUpgrade(false)) { if (OC_Appconfig::getValue('core', 'backgroundjobs_mode', 'ajax') == 'ajax') { OC_Util::addScript('backgroundjobs'); @@ -562,13 +630,9 @@ class OC { * register hooks for the cache */ public static function registerCacheHooks() { - if (OC_Config::getValue('installed', false)) { //don't try to do this before we are properly setup - // register cache cleanup jobs - try { //if this is executed before the upgrade to the new backgroundjob system is completed it will throw an exception - \OCP\BackgroundJob::registerJob('OC\Cache\FileGlobalGC'); - } catch (Exception $e) { + if (OC_Config::getValue('installed', false) && !self::needUpgrade()) { //don't try to do this before we are properly setup + \OCP\BackgroundJob::registerJob('OC\Cache\FileGlobalGC'); - } // NOTE: This will be replaced to use OCP $userSession = \OC_User::getUserSession(); $userSession->listen('postLogin', '\OC\Cache\File', 'loginListener'); @@ -579,14 +643,9 @@ class OC { * register hooks for the cache */ public static function registerLogRotate() { - if (OC_Config::getValue('installed', false) && OC_Config::getValue('log_rotate_size', false)) { + if (OC_Config::getValue('installed', false) && OC_Config::getValue('log_rotate_size', false) && !self::needUpgrade()) { //don't try to do this before we are properly setup - // register cache cleanup jobs - try { //if this is executed before the upgrade to the new backgroundjob system is completed it will throw an exception - \OCP\BackgroundJob::registerJob('OC\Log\Rotate', OC_Config::getValue("datadirectory", OC::$SERVERROOT.'/data').'/owncloud.log'); - } catch (Exception $e) { - - } + \OCP\BackgroundJob::registerJob('OC\Log\Rotate', OC_Config::getValue("datadirectory", OC::$SERVERROOT . '/data') . '/owncloud.log'); } } @@ -605,13 +664,15 @@ class OC { public static function registerPreviewHooks() { OC_Hook::connect('OC_Filesystem', 'post_write', 'OC\Preview', 'post_write'); OC_Hook::connect('OC_Filesystem', 'delete', 'OC\Preview', 'post_delete'); + OC_Hook::connect('\OCP\Versions', 'delete', 'OC\Preview', 'post_delete'); + OC_Hook::connect('\OCP\Trashbin', 'delete', 'OC\Preview', 'post_delete'); } /** * register hooks for sharing */ public static function registerShareHooks() { - if(\OC_Config::getValue('installed')) { + if (\OC_Config::getValue('installed')) { OC_Hook::connect('OC_User', 'post_deleteUser', 'OCP\Share', 'post_deleteUser'); OC_Hook::connect('OC_User', 'post_addToGroup', 'OCP\Share', 'post_addToGroup'); OC_Hook::connect('OC_User', 'post_removeFromGroup', 'OCP\Share', 'post_removeFromGroup'); @@ -635,7 +696,7 @@ class OC { } $request = OC_Request::getPathInfo(); - if(substr($request, -3) !== '.js') {// we need these files during the upgrade + if (substr($request, -3) !== '.js') { // we need these files during the upgrade self::checkMaintenanceMode(); self::checkUpgrade(); } @@ -643,11 +704,12 @@ class OC { // Test it the user is already authenticated using Apaches AuthType Basic... very usable in combination with LDAP OC::tryBasicAuthLogin(); - if (!self::$CLI) { + if (!self::$CLI and (!isset($_GET["logout"]) or ($_GET["logout"] !== 'true'))) { try { if (!OC_Config::getValue('maintenance', false)) { OC_App::loadApps(); } + self::checkSingleUserMode(); OC::getRouter()->match(OC_Request::getRawPathInfo()); return; } catch (Symfony\Component\Routing\Exception\ResourceNotFoundException $e) { @@ -680,7 +742,11 @@ class OC { } // Handle WebDAV if ($_SERVER['REQUEST_METHOD'] == 'PROPFIND') { - header('location: ' . OC_Helper::linkToRemote('webdav')); + // not allowed any more to prevent people + // mounting this root directly. + // Users need to mount remote.php/webdav instead. + header('HTTP/1.1 405 Method Not Allowed'); + header('Status: 405 Method Not Allowed'); return; } @@ -744,12 +810,23 @@ class OC { protected static function handleLogin() { OC_App::loadApps(array('prelogin')); $error = array(); - // remember was checked after last login - if (OC::tryRememberLogin()) { + + // auth possible via apache module? + if (OC::tryApacheAuth()) { + $error[] = 'apacheauthfailed'; + } // remember was checked after last login + elseif (OC::tryRememberLogin()) { $error[] = 'invalidcookie'; - // Someone wants to log in : - } elseif (OC::tryFormLogin()) { + } // logon via web form + elseif (OC::tryFormLogin()) { $error[] = 'invalidpassword'; + if ( OC_Config::getValue('log_authfailip', false) ) { + OC_Log::write('core', 'Login failed: user \''.$_POST["user"].'\' , wrong password, IP:'.$_SERVER['REMOTE_ADDR'], + OC_Log::WARN); + } else { + OC_Log::write('core', 'Login failed: user \''.$_POST["user"].'\' , wrong password, IP:set log_authfailip=true in conf', + OC_Log::WARN); + } } OC_Util::displayLoginPage(array_unique($error)); @@ -766,6 +843,20 @@ class OC { } } + protected static function tryApacheAuth() { + $return = OC_User::handleApacheAuth(); + + // if return is true we are logged in -> redirect to the default page + if ($return === true) { + $_REQUEST['redirect_url'] = \OC_Request::requestUri(); + OC_Util::redirectToDefaultPage(); + exit; + } + + // in case $return is null apache based auth is not enabled + return is_null($return) ? false : true; + } + protected static function tryRememberLogin() { if (!isset($_COOKIE["oc_remember_login"]) || !isset($_COOKIE["oc_token"]) diff --git a/lib/private/l10n/ach.php b/lib/l10n/ach.php index 406ff5f5a26..406ff5f5a26 100644 --- a/lib/private/l10n/ach.php +++ b/lib/l10n/ach.php diff --git a/lib/private/l10n/de_AT.php b/lib/l10n/ady.php index 15f78e0bce6..15f78e0bce6 100644 --- a/lib/private/l10n/de_AT.php +++ b/lib/l10n/ady.php diff --git a/lib/private/l10n/es_MX.php b/lib/l10n/af.php index 15f78e0bce6..15f78e0bce6 100644 --- a/lib/private/l10n/es_MX.php +++ b/lib/l10n/af.php diff --git a/lib/private/l10n/af_ZA.php b/lib/l10n/af_ZA.php index d6bf5771e8d..d6bf5771e8d 100644 --- a/lib/private/l10n/af_ZA.php +++ b/lib/l10n/af_ZA.php diff --git a/lib/l10n/ak.php b/lib/l10n/ak.php new file mode 100644 index 00000000000..4124ad0d880 --- /dev/null +++ b/lib/l10n/ak.php @@ -0,0 +1,8 @@ +<?php +$TRANSLATIONS = array( +"_%n minute ago_::_%n minutes ago_" => array("",""), +"_%n hour ago_::_%n hours ago_" => array("",""), +"_%n day go_::_%n days ago_" => array("",""), +"_%n month ago_::_%n months ago_" => array("","") +); +$PLURAL_FORMS = "nplurals=2; plural=n > 1;"; diff --git a/lib/private/l10n/ar.php b/lib/l10n/ar.php index f626dcdfda6..6870c549940 100644 --- a/lib/private/l10n/ar.php +++ b/lib/l10n/ar.php @@ -35,6 +35,7 @@ $TRANSLATIONS = array( "Set an admin password." => "اعداد كلمة مرور للمدير", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "اعدادات خادمك غير صحيحة بشكل تسمح لك بمزامنة ملفاتك وذلك بسبب أن واجهة WebDAV تبدو معطلة", "Please double check the <a href='%s'>installation guides</a>." => "الرجاء التحقق من <a href='%s'>دليل التنصيب</a>.", +"Could not find category \"%s\"" => "تعذر العثور على المجلد \"%s\"", "seconds ago" => "منذ ثواني", "_%n minute ago_::_%n minutes ago_" => array("","","","","",""), "_%n hour ago_::_%n hours ago_" => array("","","","","",""), @@ -44,7 +45,6 @@ $TRANSLATIONS = array( "last month" => "الشهر الماضي", "_%n month ago_::_%n months ago_" => array("","","","","",""), "last year" => "السنةالماضية", -"years ago" => "سنة مضت", -"Could not find category \"%s\"" => "تعذر العثور على المجلد \"%s\"" +"years ago" => "سنة مضت" ); $PLURAL_FORMS = "nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;"; diff --git a/lib/private/l10n/km.php b/lib/l10n/az.php index e7b09649a24..e7b09649a24 100644 --- a/lib/private/l10n/km.php +++ b/lib/l10n/az.php diff --git a/lib/private/l10n/be.php b/lib/l10n/be.php index 1570411eb86..b1cf270aba2 100644 --- a/lib/private/l10n/be.php +++ b/lib/l10n/be.php @@ -1,8 +1,15 @@ <?php $TRANSLATIONS = array( +"Settings" => "Налады", +"seconds ago" => "Секунд таму", "_%n minute ago_::_%n minutes ago_" => array("","","",""), "_%n hour ago_::_%n hours ago_" => array("","","",""), +"today" => "Сёння", +"yesterday" => "Ўчора", "_%n day go_::_%n days ago_" => array("","","",""), -"_%n month ago_::_%n months ago_" => array("","","","") +"last month" => "У мінулым месяцы", +"_%n month ago_::_%n months ago_" => array("","","",""), +"last year" => "У мінулым годзе", +"years ago" => "Гадоў таму" ); $PLURAL_FORMS = "nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"; diff --git a/lib/private/l10n/bg_BG.php b/lib/l10n/bg_BG.php index b6cc949eb8a..c9de3d64d89 100644 --- a/lib/private/l10n/bg_BG.php +++ b/lib/l10n/bg_BG.php @@ -36,6 +36,7 @@ $TRANSLATIONS = array( "Set an admin password." => "Въведете парола за администратор.", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Вашият web сървър все още не е удачно настроен да позволява синхронизация на файлове, защото WebDAV интерфейсът изглежда не работи.", "Please double check the <a href='%s'>installation guides</a>." => "Моля направете повторна справка с <a href='%s'>ръководството за инсталиране</a>.", +"Could not find category \"%s\"" => "Невъзможно откриване на категорията \"%s\"", "seconds ago" => "преди секунди", "_%n minute ago_::_%n minutes ago_" => array("",""), "_%n hour ago_::_%n hours ago_" => array("",""), @@ -45,7 +46,6 @@ $TRANSLATIONS = array( "last month" => "последният месец", "_%n month ago_::_%n months ago_" => array("",""), "last year" => "последната година", -"years ago" => "последните години", -"Could not find category \"%s\"" => "Невъзможно откриване на категорията \"%s\"" +"years ago" => "последните години" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/private/l10n/bn_BD.php b/lib/l10n/bn_BD.php index a42435a2a47..a42435a2a47 100644 --- a/lib/private/l10n/bn_BD.php +++ b/lib/l10n/bn_BD.php diff --git a/lib/private/l10n/bs.php b/lib/l10n/bs.php index 3cb98906e62..3cb98906e62 100644 --- a/lib/private/l10n/bs.php +++ b/lib/l10n/bs.php diff --git a/lib/private/l10n/ca.php b/lib/l10n/ca.php index a8769224705..4755392d271 100644 --- a/lib/private/l10n/ca.php +++ b/lib/l10n/ca.php @@ -8,7 +8,6 @@ $TRANSLATIONS = array( "Users" => "Usuaris", "Admin" => "Administració", "Failed to upgrade \"%s\"." => "Ha fallat l'actualització \"%s\".", -"Custom profile pictures don't work with encryption yet" => "Les imatges de perfil personals encara no funcionen amb encriptació", "Unknown filetype" => "Tipus de fitxer desconegut", "Invalid image" => "Imatge no vàlida", "web services under your control" => "controleu els vostres serveis web", @@ -17,7 +16,7 @@ $TRANSLATIONS = array( "Files need to be downloaded one by one." => "Els fitxers s'han de baixar d'un en un.", "Back to Files" => "Torna a Fitxers", "Selected files too large to generate zip file." => "Els fitxers seleccionats son massa grans per generar un fitxer zip.", -"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Baixeu els fitxers en trossos petits, de forma separada, o pregunteu a l'administrador.", +"Please download the files separately in smaller chunks or kindly ask your administrator." => "Baixeu els fitxers separadament en petits trossos o pregunteu a l'administrador.", "No source specified when installing app" => "No heu especificat la font en instal·lar l'aplicació", "No href specified when installing app from http" => "No heu especificat href en instal·lar l'aplicació des de http", "No path specified when installing app from local file" => "No heu seleccionat el camí en instal·lar una aplicació des d'un fitxer local", @@ -56,6 +55,7 @@ $TRANSLATIONS = array( "Set an admin password." => "Establiu una contrasenya per l'administrador.", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "El servidor web no està configurat correctament per permetre la sincronització de fitxers perquè la interfície WebDAV sembla no funcionar correctament.", "Please double check the <a href='%s'>installation guides</a>." => "Comproveu les <a href='%s'>guies d'instal·lació</a>.", +"Could not find category \"%s\"" => "No s'ha trobat la categoria \"%s\"", "seconds ago" => "segons enrere", "_%n minute ago_::_%n minutes ago_" => array("fa %n minut","fa %n minuts"), "_%n hour ago_::_%n hours ago_" => array("fa %n hora","fa %n hores"), @@ -65,8 +65,6 @@ $TRANSLATIONS = array( "last month" => "el mes passat", "_%n month ago_::_%n months ago_" => array("fa %n mes","fa %n mesos"), "last year" => "l'any passat", -"years ago" => "anys enrere", -"Caused by:" => "Provocat per:", -"Could not find category \"%s\"" => "No s'ha trobat la categoria \"%s\"" +"years ago" => "anys enrere" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/private/l10n/cs_CZ.php b/lib/l10n/cs_CZ.php index ed31ae79529..df3a47b5ae3 100644 --- a/lib/private/l10n/cs_CZ.php +++ b/lib/l10n/cs_CZ.php @@ -8,7 +8,6 @@ $TRANSLATIONS = array( "Users" => "Uživatelé", "Admin" => "Administrace", "Failed to upgrade \"%s\"." => "Selhala aktualizace verze \"%s\".", -"Custom profile pictures don't work with encryption yet" => "Vlastní profilové obrázky zatím nefungují v kombinaci se šifrováním", "Unknown filetype" => "Neznámý typ souboru", "Invalid image" => "Chybný obrázek", "web services under your control" => "webové služby pod Vaší kontrolou", @@ -17,7 +16,7 @@ $TRANSLATIONS = array( "Files need to be downloaded one by one." => "Soubory musí být stahovány jednotlivě.", "Back to Files" => "Zpět k souborům", "Selected files too large to generate zip file." => "Vybrané soubory jsou příliš velké pro vytvoření ZIP souboru.", -"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Stáhněte soubory po menších částech, samostatně, nebo se obraťte na správce.", +"Please download the files separately in smaller chunks or kindly ask your administrator." => "Prosím stáhněte soubory odděleně po menších množstvích nebo požádejte vašeho správce.", "No source specified when installing app" => "Nebyl zadán zdroj při instalaci aplikace", "No href specified when installing app from http" => "Nebyl zadán odkaz pro instalaci aplikace z HTTP", "No path specified when installing app from local file" => "Nebyla zadána cesta pro instalaci aplikace z místního souboru", @@ -56,6 +55,7 @@ $TRANSLATIONS = array( "Set an admin password." => "Zadejte heslo správce.", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Váš webový server není správně nastaven pro umožnění synchronizace, rozhraní WebDAV se zdá být rozbité.", "Please double check the <a href='%s'>installation guides</a>." => "Zkonzultujte, prosím, <a href='%s'>průvodce instalací</a>.", +"Could not find category \"%s\"" => "Nelze nalézt kategorii \"%s\"", "seconds ago" => "před pár sekundami", "_%n minute ago_::_%n minutes ago_" => array("před %n minutou","před %n minutami","před %n minutami"), "_%n hour ago_::_%n hours ago_" => array("před %n hodinou","před %n hodinami","před %n hodinami"), @@ -65,8 +65,6 @@ $TRANSLATIONS = array( "last month" => "minulý měsíc", "_%n month ago_::_%n months ago_" => array("před %n měsícem","před %n měsíci","před %n měsíci"), "last year" => "minulý rok", -"years ago" => "před lety", -"Caused by:" => "Příčina:", -"Could not find category \"%s\"" => "Nelze nalézt kategorii \"%s\"" +"years ago" => "před lety" ); $PLURAL_FORMS = "nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;"; diff --git a/lib/private/l10n/cy_GB.php b/lib/l10n/cy_GB.php index 6973b51878f..0a52f5df776 100644 --- a/lib/private/l10n/cy_GB.php +++ b/lib/l10n/cy_GB.php @@ -35,6 +35,7 @@ $TRANSLATIONS = array( "Set an admin password." => "Gosod cyfrinair y gweinyddwr.", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Nid yw eich gweinydd wedi'i gyflunio eto i ganiatáu cydweddu ffeiliau oherwydd bod y rhyngwyneb WebDAV wedi torri.", "Please double check the <a href='%s'>installation guides</a>." => "Gwiriwch y <a href='%s'>canllawiau gosod</a> eto.", +"Could not find category \"%s\"" => "Methu canfod categori \"%s\"", "seconds ago" => "eiliad yn ôl", "_%n minute ago_::_%n minutes ago_" => array("","","",""), "_%n hour ago_::_%n hours ago_" => array("","","",""), @@ -44,7 +45,6 @@ $TRANSLATIONS = array( "last month" => "mis diwethaf", "_%n month ago_::_%n months ago_" => array("","","",""), "last year" => "y llynedd", -"years ago" => "blwyddyn yn ôl", -"Could not find category \"%s\"" => "Methu canfod categori \"%s\"" +"years ago" => "blwyddyn yn ôl" ); $PLURAL_FORMS = "nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3;"; diff --git a/lib/private/l10n/da.php b/lib/l10n/da.php index 05a43f42ed9..65eb7466b6a 100644 --- a/lib/private/l10n/da.php +++ b/lib/l10n/da.php @@ -8,7 +8,6 @@ $TRANSLATIONS = array( "Users" => "Brugere", "Admin" => "Admin", "Failed to upgrade \"%s\"." => "Upgradering af \"%s\" fejlede", -"Custom profile pictures don't work with encryption yet" => "Personligt profilbillede virker endnu ikke sammen med kryptering", "Unknown filetype" => "Ukendt filtype", "Invalid image" => "Ugyldigt billede", "web services under your control" => "Webtjenester under din kontrol", @@ -17,7 +16,7 @@ $TRANSLATIONS = array( "Files need to be downloaded one by one." => "Filer skal downloades en for en.", "Back to Files" => "Tilbage til Filer", "Selected files too large to generate zip file." => "De markerede filer er for store til at generere en ZIP-fil.", -"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Download filerne i små bider, seperat, eller kontakt venligst din administrator.", +"Please download the files separately in smaller chunks or kindly ask your administrator." => "Hent venligst filerne hver for sig i mindre dele eller spørg din administrator.", "No source specified when installing app" => "Ingen kilde angivet under installation af app", "No href specified when installing app from http" => "Ingen href angivet under installation af app via http", "No path specified when installing app from local file" => "Ingen sti angivet under installation af app fra lokal fil", @@ -56,6 +55,7 @@ $TRANSLATIONS = array( "Set an admin password." => "Angiv et admin kodeord.", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Din webserver er endnu ikke sat op til at tillade fil synkronisering fordi WebDAV grænsefladen virker ødelagt.", "Please double check the <a href='%s'>installation guides</a>." => "Dobbelttjek venligst <a href='%s'>installations vejledningerne</a>.", +"Could not find category \"%s\"" => "Kunne ikke finde kategorien \"%s\"", "seconds ago" => "sekunder siden", "_%n minute ago_::_%n minutes ago_" => array("%n minut siden","%n minutter siden"), "_%n hour ago_::_%n hours ago_" => array("%n time siden","%n timer siden"), @@ -65,8 +65,6 @@ $TRANSLATIONS = array( "last month" => "sidste måned", "_%n month ago_::_%n months ago_" => array("%n måned siden","%n måneder siden"), "last year" => "sidste år", -"years ago" => "år siden", -"Caused by:" => "Forårsaget af:", -"Could not find category \"%s\"" => "Kunne ikke finde kategorien \"%s\"" +"years ago" => "år siden" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/private/l10n/de.php b/lib/l10n/de.php index 87e7a67b47b..b1045892fb1 100644 --- a/lib/private/l10n/de.php +++ b/lib/l10n/de.php @@ -8,7 +8,6 @@ $TRANSLATIONS = array( "Users" => "Benutzer", "Admin" => "Administration", "Failed to upgrade \"%s\"." => "Konnte \"%s\" nicht aktualisieren.", -"Custom profile pictures don't work with encryption yet" => "Individuelle Profilbilder werden noch nicht von der Verschlüsselung unterstützt", "Unknown filetype" => "Unbekannter Dateityp", "Invalid image" => "Ungültiges Bild", "web services under your control" => "Web-Services unter Deiner Kontrolle", @@ -17,19 +16,19 @@ $TRANSLATIONS = array( "Files need to be downloaded one by one." => "Die Dateien müssen einzeln heruntergeladen werden.", "Back to Files" => "Zurück zu \"Dateien\"", "Selected files too large to generate zip file." => "Die gewählten Dateien sind zu groß, um eine ZIP-Datei zu erstellen.", -"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Lade die Dateien in kleineren, separaten, Stücken herunter oder bitte deinen Administrator.", +"Please download the files separately in smaller chunks or kindly ask your administrator." => "Bitte lade die Dateien einzeln in kleineren Teilen herunter oder bitte Deinen Administrator.", "No source specified when installing app" => "Für die Installation der Applikation wurde keine Quelle angegeben", -"No href specified when installing app from http" => "Der Link (href) wurde nicht angegeben um die Applikation per http zu installieren", +"No href specified when installing app from http" => "Für die Installation der Applikation über http wurde keine Quelle (href) angegeben", "No path specified when installing app from local file" => "Bei der Installation der Applikation aus einer lokalen Datei wurde kein Pfad angegeben", "Archives of type %s are not supported" => "Archive vom Typ %s werden nicht unterstützt", "Failed to open archive when installing app" => "Das Archiv konnte bei der Installation der Applikation nicht geöffnet werden", "App does not provide an info.xml file" => "Die Applikation enthält keine info,xml Datei", -"App can't be installed because of not allowed code in the App" => "Die Applikation kann auf Grund von unerlaubten Code nicht installiert werden", +"App can't be installed because of not allowed code in the App" => "Die Applikation kann auf Grund von unerlaubtem Code nicht installiert werden", "App can't be installed because it is not compatible with this version of ownCloud" => "Die Anwendung konnte nicht installiert werden, weil Sie nicht mit dieser Version von ownCloud kompatibel ist.", -"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "Die Applikation konnte nicht installiert werden, da diese das <shipped>true</shipped> Tag beinhaltet und dieses, bei nicht mitausgelieferten Applikationen, nicht erlaubt ist ist", +"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "Die Applikation konnte nicht installiert werden, da diese das <shipped>true</shipped> Tag beinhaltet und dieses, bei nicht mitausgelieferten Applikationen, nicht erlaubt ist", "App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "Die Applikation konnte nicht installiert werden, da die Version in der info.xml nicht die gleiche Version wie im App-Store ist", "App directory already exists" => "Das Applikationsverzeichnis existiert bereits", -"Can't create app folder. Please fix permissions. %s" => "Es kann kein Applikationsordner erstellt werden. Bitte passen sie die Berechtigungen an. %s", +"Can't create app folder. Please fix permissions. %s" => "Es kann kein Applikationsordner erstellt werden. Bitte passe die Berechtigungen an. %s", "Application is not enabled" => "Die Anwendung ist nicht aktiviert", "Authentication error" => "Fehler bei der Anmeldung", "Token expired. Please reload page." => "Token abgelaufen. Bitte lade die Seite neu.", @@ -56,17 +55,16 @@ $TRANSLATIONS = array( "Set an admin password." => "Setze Administrator Passwort", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Dein Web-Server ist noch nicht für Datei-Synchronisation bereit, weil die WebDAV-Schnittstelle vermutlich defekt ist.", "Please double check the <a href='%s'>installation guides</a>." => "Bitte prüfe die <a href='%s'>Installationsanleitungen</a>.", +"Could not find category \"%s\"" => "Die Kategorie \"%s\" konnte nicht gefunden werden.", "seconds ago" => "Gerade eben", -"_%n minute ago_::_%n minutes ago_" => array("","Vor %n Minuten"), -"_%n hour ago_::_%n hours ago_" => array("","Vor %n Stunden"), +"_%n minute ago_::_%n minutes ago_" => array("Vor %n Minute","Vor %n Minuten"), +"_%n hour ago_::_%n hours ago_" => array("Vor %n Stunde","Vor %n Stunden"), "today" => "Heute", "yesterday" => "Gestern", -"_%n day go_::_%n days ago_" => array("","Vor %n Tagen"), +"_%n day go_::_%n days ago_" => array("Vor %n Tag","Vor %n Tagen"), "last month" => "Letzten Monat", -"_%n month ago_::_%n months ago_" => array("","Vor %n Monaten"), +"_%n month ago_::_%n months ago_" => array("Vor %n Monat","Vor %n Monaten"), "last year" => "Letztes Jahr", -"years ago" => "Vor Jahren", -"Caused by:" => "Verursacht durch:", -"Could not find category \"%s\"" => "Die Kategorie \"%s\" konnte nicht gefunden werden." +"years ago" => "Vor Jahren" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/private/l10n/hy.php b/lib/l10n/de_AT.php index 15f78e0bce6..15f78e0bce6 100644 --- a/lib/private/l10n/hy.php +++ b/lib/l10n/de_AT.php diff --git a/lib/private/l10n/de_CH.php b/lib/l10n/de_CH.php index 33f3446a693..7325aad931e 100644 --- a/lib/private/l10n/de_CH.php +++ b/lib/l10n/de_CH.php @@ -14,7 +14,6 @@ $TRANSLATIONS = array( "Files need to be downloaded one by one." => "Die Dateien müssen einzeln heruntergeladen werden.", "Back to Files" => "Zurück zu \"Dateien\"", "Selected files too large to generate zip file." => "Die gewählten Dateien sind zu gross, um eine ZIP-Datei zu erstellen.", -"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Laden Sie die Dateien in kleineren, separaten, Stücken herunter oder bitten Sie Ihren Administrator.", "App can't be installed because of not allowed code in the App" => "Anwendung kann wegen nicht erlaubten Codes nicht installiert werden", "App directory already exists" => "Anwendungsverzeichnis existiert bereits", "Application is not enabled" => "Die Anwendung ist nicht aktiviert", @@ -43,6 +42,7 @@ $TRANSLATIONS = array( "Set an admin password." => "Setze Administrator Passwort", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Ihr Web-Server ist noch nicht für eine Datei-Synchronisation konfiguriert, weil die WebDAV-Schnittstelle vermutlich defekt ist.", "Please double check the <a href='%s'>installation guides</a>." => "Bitte prüfen Sie die <a href='%s'>Installationsanleitungen</a>.", +"Could not find category \"%s\"" => "Die Kategorie «%s» konnte nicht gefunden werden.", "seconds ago" => "Gerade eben", "_%n minute ago_::_%n minutes ago_" => array("","Vor %n Minuten"), "_%n hour ago_::_%n hours ago_" => array("","Vor %n Stunden"), @@ -52,8 +52,6 @@ $TRANSLATIONS = array( "last month" => "Letzten Monat", "_%n month ago_::_%n months ago_" => array("","Vor %n Monaten"), "last year" => "Letztes Jahr", -"years ago" => "Vor Jahren", -"Caused by:" => "Verursacht durch:", -"Could not find category \"%s\"" => "Die Kategorie «%s» konnte nicht gefunden werden." +"years ago" => "Vor Jahren" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/private/l10n/de_DE.php b/lib/l10n/de_DE.php index 09be0eea22d..1a1c9783f42 100644 --- a/lib/private/l10n/de_DE.php +++ b/lib/l10n/de_DE.php @@ -8,7 +8,6 @@ $TRANSLATIONS = array( "Users" => "Benutzer", "Admin" => "Administrator", "Failed to upgrade \"%s\"." => "Konnte \"%s\" nicht aktualisieren.", -"Custom profile pictures don't work with encryption yet" => "Individuelle Profilbilder werden noch nicht von der Verschlüsselung unterstützt", "Unknown filetype" => "Unbekannter Dateityp", "Invalid image" => "Ungültiges Bild", "web services under your control" => "Web-Services unter Ihrer Kontrolle", @@ -17,7 +16,7 @@ $TRANSLATIONS = array( "Files need to be downloaded one by one." => "Die Dateien müssen einzeln heruntergeladen werden.", "Back to Files" => "Zurück zu \"Dateien\"", "Selected files too large to generate zip file." => "Die gewählten Dateien sind zu groß, um eine ZIP-Datei zu erstellen.", -"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Laden Sie die Dateien in kleineren, separaten, Stücken herunter oder bitten Sie Ihren Administrator.", +"Please download the files separately in smaller chunks or kindly ask your administrator." => "Bitte laden Sie die Dateien einzeln in kleineren Teilen herunter oder bitten Sie Ihren Administrator.", "No source specified when installing app" => "Für die Installation der Applikation wurde keine Quelle angegeben", "No href specified when installing app from http" => "Der Link (href) wurde nicht angegeben um die Applikation per http zu installieren", "No path specified when installing app from local file" => "Bei der Installation der Applikation aus einer lokalen Datei wurde kein Pfad angegeben", @@ -56,6 +55,7 @@ $TRANSLATIONS = array( "Set an admin password." => "Setze Administrator Passwort", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Ihr Web-Server ist noch nicht für eine Datei-Synchronisation konfiguriert, weil die WebDAV-Schnittstelle vermutlich defekt ist.", "Please double check the <a href='%s'>installation guides</a>." => "Bitte prüfen Sie die <a href='%s'>Installationsanleitungen</a>.", +"Could not find category \"%s\"" => "Die Kategorie \"%s\" konnte nicht gefunden werden.", "seconds ago" => "Gerade eben", "_%n minute ago_::_%n minutes ago_" => array("Vor %n Minute","Vor %n Minuten"), "_%n hour ago_::_%n hours ago_" => array("Vor %n Stunde","Vor %n Stunden"), @@ -65,8 +65,6 @@ $TRANSLATIONS = array( "last month" => "Letzten Monat", "_%n month ago_::_%n months ago_" => array("Vor %n Monat","Vor %n Monaten"), "last year" => "Letztes Jahr", -"years ago" => "Vor Jahren", -"Caused by:" => "Verursacht durch:", -"Could not find category \"%s\"" => "Die Kategorie \"%s\" konnte nicht gefunden werden." +"years ago" => "Vor Jahren" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/private/l10n/el.php b/lib/l10n/el.php index dcbf82d4a4b..7f7797bbc7a 100644 --- a/lib/private/l10n/el.php +++ b/lib/l10n/el.php @@ -1,18 +1,33 @@ <?php $TRANSLATIONS = array( +"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "Η εφαρμογή \"%s\" δεν μπορεί να εγκατασταθεί επειδή δεν είναι συμβατή με αυτή την έκδοση του ownCloud.", +"No app name specified" => "Δεν προδιορίστηκε όνομα εφαρμογής", "Help" => "Βοήθεια", "Personal" => "Προσωπικά", "Settings" => "Ρυθμίσεις", "Users" => "Χρήστες", "Admin" => "Διαχειριστής", "Failed to upgrade \"%s\"." => "Αποτυχία αναβάθμισης του \"%s\".", +"Unknown filetype" => "Άγνωστος τύπος αρχείου", +"Invalid image" => "Μη έγκυρη εικόνα", "web services under your control" => "υπηρεσίες δικτύου υπό τον έλεγχό σας", "cannot open \"%s\"" => "αδυναμία ανοίγματος \"%s\"", "ZIP download is turned off." => "Η λήψη ZIP απενεργοποιήθηκε.", "Files need to be downloaded one by one." => "Τα αρχεία πρέπει να ληφθούν ένα-ένα.", "Back to Files" => "Πίσω στα Αρχεία", "Selected files too large to generate zip file." => "Τα επιλεγμένα αρχεία είναι μεγάλα ώστε να δημιουργηθεί αρχείο zip.", -"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Λήψη των αρχείων σε μικρότερα κομμάτια, χωριστά ή ρωτήστε τον διαχειριστή σας.", +"Please download the files separately in smaller chunks or kindly ask your administrator." => "Παρακαλώ κάντε λήψη των αρχείων σε μικρότερα κομμάτια ή ζητήστε το από το διαχειριστή σας.", +"No source specified when installing app" => "Δεν προσδιορίστηκε πηγή κατά την εγκατάσταση της εφαρμογής", +"No href specified when installing app from http" => "Δεν προσδιορίστηκε href κατά την εγκατάσταση της εφαρμογής μέσω http ", +"No path specified when installing app from local file" => "Δεν προσδιορίστηκε μονοπάτι κατά την εγκατάσταση εφαρμογής από τοπικό αρχείο", +"Archives of type %s are not supported" => "Συλλογές αρχείων τύπου %s δεν υποστηρίζονται", +"Failed to open archive when installing app" => "Αποτυχία ανοίγματος συλλογής αρχείων κατά την εγκατάσταση εφαρμογής", +"App does not provide an info.xml file" => "Η εφαρμογή δεν παρέχει αρχείο info.xml", +"App can't be installed because of not allowed code in the App" => "Η εφαρμογή δεν μπορεί να εγκατασταθεί λόγω μη-επιτρεπόμενου κώδικα μέσα στην Εφαρμογή", +"App can't be installed because it is not compatible with this version of ownCloud" => "Η εφαρμογή δεν μπορεί να εγκατασταθεί επειδή δεν είναι συμβατή με αυτή την έκδοση ownCloud", +"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "Η εφαρμογή δεν μπορεί να εγκατασταθεί επειδή η έκδοση στο info.xml/version δεν είναι η ίδια με την έκδοση που αναφέρεται στο κατάστημα εφαρμογών", +"App directory already exists" => "Ο κατάλογος εφαρμογών υπάρχει ήδη", +"Can't create app folder. Please fix permissions. %s" => "Δεν είναι δυνατόν να δημιουργηθεί ο φάκελος εφαρμογής. Παρακαλώ διορθώστε τις άδειες πρόσβασης. %s", "Application is not enabled" => "Δεν ενεργοποιήθηκε η εφαρμογή", "Authentication error" => "Σφάλμα πιστοποίησης", "Token expired. Please reload page." => "Το αναγνωριστικό έληξε. Παρακαλώ φορτώστε ξανά την σελίδα.", @@ -39,17 +54,16 @@ $TRANSLATIONS = array( "Set an admin password." => "Εισάγετε συνθηματικό διαχειριστή.", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Ο διακομιστής σας δεν έχει ρυθμιστεί κατάλληλα ώστε να επιτρέπει τον συγχρονισμό αρχείων γιατί η διεπαφή WebDAV πιθανόν να είναι κατεστραμμένη.", "Please double check the <a href='%s'>installation guides</a>." => "Ελέγξτε ξανά τις <a href='%s'>οδηγίες εγκατάστασης</a>.", +"Could not find category \"%s\"" => "Αδυναμία εύρεσης κατηγορίας \"%s\"", "seconds ago" => "δευτερόλεπτα πριν", -"_%n minute ago_::_%n minutes ago_" => array("",""), -"_%n hour ago_::_%n hours ago_" => array("",""), +"_%n minute ago_::_%n minutes ago_" => array("","%n λεπτά πριν"), +"_%n hour ago_::_%n hours ago_" => array("","%n ώρες πριν"), "today" => "σήμερα", "yesterday" => "χτες", -"_%n day go_::_%n days ago_" => array("",""), +"_%n day go_::_%n days ago_" => array("","%n ημέρες πριν"), "last month" => "τελευταίο μήνα", -"_%n month ago_::_%n months ago_" => array("",""), +"_%n month ago_::_%n months ago_" => array("","%n μήνες πριν"), "last year" => "τελευταίο χρόνο", -"years ago" => "χρόνια πριν", -"Caused by:" => "Προκλήθηκε από:", -"Could not find category \"%s\"" => "Αδυναμία εύρεσης κατηγορίας \"%s\"" +"years ago" => "χρόνια πριν" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/private/l10n/en@pirate.php b/lib/l10n/en@pirate.php index a8175b1400f..a8175b1400f 100644 --- a/lib/private/l10n/en@pirate.php +++ b/lib/l10n/en@pirate.php diff --git a/lib/private/l10n/en_GB.php b/lib/l10n/en_GB.php index d02f553eda8..e2e8ee2e541 100644 --- a/lib/private/l10n/en_GB.php +++ b/lib/l10n/en_GB.php @@ -8,7 +8,6 @@ $TRANSLATIONS = array( "Users" => "Users", "Admin" => "Admin", "Failed to upgrade \"%s\"." => "Failed to upgrade \"%s\".", -"Custom profile pictures don't work with encryption yet" => "Custom profile pictures don't work with encryption yet", "Unknown filetype" => "Unknown filetype", "Invalid image" => "Invalid image", "web services under your control" => "web services under your control", @@ -17,7 +16,7 @@ $TRANSLATIONS = array( "Files need to be downloaded one by one." => "Files need to be downloaded one by one.", "Back to Files" => "Back to Files", "Selected files too large to generate zip file." => "Selected files too large to generate zip file.", -"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Download the files in smaller chunks, seperately or kindly ask your administrator.", +"Please download the files separately in smaller chunks or kindly ask your administrator." => "Please download the files separately in smaller chunks or kindly ask your administrator.", "No source specified when installing app" => "No source specified when installing app", "No href specified when installing app from http" => "No href specified when installing app from http", "No path specified when installing app from local file" => "No path specified when installing app from local file", @@ -56,6 +55,7 @@ $TRANSLATIONS = array( "Set an admin password." => "Set an admin password.", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Your web server is not yet properly setup to allow files synchronisation because the WebDAV interface seems to be broken.", "Please double check the <a href='%s'>installation guides</a>." => "Please double check the <a href='%s'>installation guides</a>.", +"Could not find category \"%s\"" => "Could not find category \"%s\"", "seconds ago" => "seconds ago", "_%n minute ago_::_%n minutes ago_" => array("%n minute ago","%n minutes ago"), "_%n hour ago_::_%n hours ago_" => array("%n hour ago","%n hours ago"), @@ -65,8 +65,6 @@ $TRANSLATIONS = array( "last month" => "last month", "_%n month ago_::_%n months ago_" => array("%n month ago","%n months ago"), "last year" => "last year", -"years ago" => "years ago", -"Caused by:" => "Caused by:", -"Could not find category \"%s\"" => "Could not find category \"%s\"" +"years ago" => "years ago" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/private/l10n/eo.php b/lib/l10n/eo.php index 5311dd6eb15..53d1ec1854d 100644 --- a/lib/private/l10n/eo.php +++ b/lib/l10n/eo.php @@ -33,6 +33,7 @@ $TRANSLATIONS = array( "Set an admin password." => "Starigi administran pasvorton.", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Via TTT-servilo ankoraŭ ne ĝuste agordiĝis por permesi sinkronigi dosierojn ĉar la WebDAV-interfaco ŝajnas rompita.", "Please double check the <a href='%s'>installation guides</a>." => "Bonvolu duoble kontroli la <a href='%s'>gvidilon por instalo</a>.", +"Could not find category \"%s\"" => "Ne troviĝis kategorio “%s”", "seconds ago" => "sekundoj antaŭe", "_%n minute ago_::_%n minutes ago_" => array("",""), "_%n hour ago_::_%n hours ago_" => array("",""), @@ -42,7 +43,6 @@ $TRANSLATIONS = array( "last month" => "lastamonate", "_%n month ago_::_%n months ago_" => array("",""), "last year" => "lastajare", -"years ago" => "jaroj antaŭe", -"Could not find category \"%s\"" => "Ne troviĝis kategorio “%s”" +"years ago" => "jaroj antaŭe" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/private/l10n/es.php b/lib/l10n/es.php index 047d5d955bb..f231cd2bb6e 100644 --- a/lib/private/l10n/es.php +++ b/lib/l10n/es.php @@ -8,13 +8,15 @@ $TRANSLATIONS = array( "Users" => "Usuarios", "Admin" => "Administración", "Failed to upgrade \"%s\"." => "Falló la actualización \"%s\".", +"Unknown filetype" => "Tipo de archivo desconocido", +"Invalid image" => "Imagen inválida", "web services under your control" => "Servicios web bajo su control", "cannot open \"%s\"" => "No se puede abrir \"%s\"", "ZIP download is turned off." => "La descarga en ZIP está desactivada.", "Files need to be downloaded one by one." => "Los archivos deben ser descargados uno por uno.", "Back to Files" => "Volver a Archivos", "Selected files too large to generate zip file." => "Los archivos seleccionados son demasiado grandes para generar el archivo zip.", -"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Descargue los archivos en trozos más pequeños, por separado o solicítelos amablemente su administrador.", +"Please download the files separately in smaller chunks or kindly ask your administrator." => "Descargue los archivos en trozos más pequeños, por separado o solicítelos amablemente a su administrador.", "No source specified when installing app" => "No se ha especificado origen cuando se ha instalado la aplicación", "No href specified when installing app from http" => "No href especificado cuando se ha instalado la aplicación", "No path specified when installing app from local file" => "Sin path especificado cuando se ha instalado la aplicación desde el fichero local", @@ -53,6 +55,7 @@ $TRANSLATIONS = array( "Set an admin password." => "Configurar la contraseña del administrador.", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Su servidor web aún no está configurado adecuadamente para permitir sincronización de archivos ya que la interfaz WebDAV parece no estar funcionando.", "Please double check the <a href='%s'>installation guides</a>." => "Por favor, vuelva a comprobar las <a href='%s'>guías de instalación</a>.", +"Could not find category \"%s\"" => "No puede encontrar la categoria \"%s\"", "seconds ago" => "hace segundos", "_%n minute ago_::_%n minutes ago_" => array("Hace %n minuto","Hace %n minutos"), "_%n hour ago_::_%n hours ago_" => array("Hace %n hora","Hace %n horas"), @@ -62,8 +65,6 @@ $TRANSLATIONS = array( "last month" => "mes pasado", "_%n month ago_::_%n months ago_" => array("Hace %n mes","Hace %n meses"), "last year" => "año pasado", -"years ago" => "hace años", -"Caused by:" => "Causado por:", -"Could not find category \"%s\"" => "No puede encontrar la categoria \"%s\"" +"years ago" => "hace años" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/private/l10n/es_AR.php b/lib/l10n/es_AR.php index f637eb403ed..bc5fcd7e012 100644 --- a/lib/private/l10n/es_AR.php +++ b/lib/l10n/es_AR.php @@ -8,13 +8,14 @@ $TRANSLATIONS = array( "Users" => "Usuarios", "Admin" => "Administración", "Failed to upgrade \"%s\"." => "No se pudo actualizar \"%s\".", +"Unknown filetype" => "Tipo de archivo desconocido", +"Invalid image" => "Imagen inválida", "web services under your control" => "servicios web sobre los que tenés control", "cannot open \"%s\"" => "no se puede abrir \"%s\"", "ZIP download is turned off." => "La descarga en ZIP está desactivada.", "Files need to be downloaded one by one." => "Los archivos deben ser descargados de a uno.", "Back to Files" => "Volver a Archivos", "Selected files too large to generate zip file." => "Los archivos seleccionados son demasiado grandes para generar el archivo zip.", -"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Descargá los archivos en partes más chicas, de forma separada, o pedíselos al administrador", "No source specified when installing app" => "No se especificó el origen al instalar la app", "No href specified when installing app from http" => "No se especificó href al instalar la app", "No path specified when installing app from local file" => "No se especificó PATH al instalar la app desde el archivo local", @@ -53,6 +54,7 @@ $TRANSLATIONS = array( "Set an admin password." => "Configurar una contraseña de administrador.", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Tu servidor web no está configurado todavía para permitir sincronización de archivos porque la interfaz WebDAV parece no funcionar.", "Please double check the <a href='%s'>installation guides</a>." => "Por favor, comprobá nuevamente la <a href='%s'>guía de instalación</a>.", +"Could not find category \"%s\"" => "No fue posible encontrar la categoría \"%s\"", "seconds ago" => "segundos atrás", "_%n minute ago_::_%n minutes ago_" => array("Hace %n minuto","Hace %n minutos"), "_%n hour ago_::_%n hours ago_" => array("Hace %n hora","Hace %n horas"), @@ -62,8 +64,6 @@ $TRANSLATIONS = array( "last month" => "el mes pasado", "_%n month ago_::_%n months ago_" => array("Hace %n mes","Hace %n meses"), "last year" => "el año pasado", -"years ago" => "años atrás", -"Caused by:" => "Provocado por:", -"Could not find category \"%s\"" => "No fue posible encontrar la categoría \"%s\"" +"years ago" => "años atrás" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/l10n/es_CL.php b/lib/l10n/es_CL.php new file mode 100644 index 00000000000..46158b0ccc7 --- /dev/null +++ b/lib/l10n/es_CL.php @@ -0,0 +1,10 @@ +<?php +$TRANSLATIONS = array( +"Settings" => "Configuración", +"Files" => "Archivos", +"_%n minute ago_::_%n minutes ago_" => array("",""), +"_%n hour ago_::_%n hours ago_" => array("",""), +"_%n day go_::_%n days ago_" => array("",""), +"_%n month ago_::_%n months ago_" => array("","") +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/l10n/es_MX.php b/lib/l10n/es_MX.php new file mode 100644 index 00000000000..7454d4966d8 --- /dev/null +++ b/lib/l10n/es_MX.php @@ -0,0 +1,70 @@ +<?php +$TRANSLATIONS = array( +"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "La aplicación \"%s\" no puede ser instalada porque no es compatible con esta versión de ownCloud", +"No app name specified" => "No se ha especificado nombre de la aplicación", +"Help" => "Ayuda", +"Personal" => "Personal", +"Settings" => "Ajustes", +"Users" => "Usuarios", +"Admin" => "Administración", +"Failed to upgrade \"%s\"." => "Falló la actualización \"%s\".", +"Unknown filetype" => "Tipo de archivo desconocido", +"Invalid image" => "Imagen inválida", +"web services under your control" => "Servicios web bajo su control", +"cannot open \"%s\"" => "No se puede abrir \"%s\"", +"ZIP download is turned off." => "La descarga en ZIP está desactivada.", +"Files need to be downloaded one by one." => "Los archivos deben ser descargados uno por uno.", +"Back to Files" => "Volver a Archivos", +"Selected files too large to generate zip file." => "Los archivos seleccionados son demasiado grandes para generar el archivo zip.", +"Please download the files separately in smaller chunks or kindly ask your administrator." => "Descargue los archivos en trozos más pequeños, por separado o solicítelos amablemente a su administrador.", +"No source specified when installing app" => "No se ha especificado origen cuando se ha instalado la aplicación", +"No href specified when installing app from http" => "No href especificado cuando se ha instalado la aplicación", +"No path specified when installing app from local file" => "Sin path especificado cuando se ha instalado la aplicación desde el archivo local", +"Archives of type %s are not supported" => "Archivos de tipo %s no son soportados", +"Failed to open archive when installing app" => "Fallo de abrir archivo mientras se instala la aplicación", +"App does not provide an info.xml file" => "La aplicación no suministra un archivo info.xml", +"App can't be installed because of not allowed code in the App" => "La aplicación no puede ser instalada por tener código no autorizado en la aplicación", +"App can't be installed because it is not compatible with this version of ownCloud" => "La aplicación no se puede instalar porque no es compatible con esta versión de ownCloud", +"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "La aplicación no se puede instalar porque contiene la etiqueta\n<shipped>\ntrue\n</shipped>\nque no está permitida para aplicaciones no distribuidas", +"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "La aplicación no puede ser instalada por que la versión en info.xml/version no es la misma que la establecida en la app store", +"App directory already exists" => "El directorio de la aplicación ya existe", +"Can't create app folder. Please fix permissions. %s" => "No se puede crear la carpeta de la aplicación. Corrija los permisos. %s", +"Application is not enabled" => "La aplicación no está habilitada", +"Authentication error" => "Error de autenticación", +"Token expired. Please reload page." => "Token expirado. Por favor, recarga la página.", +"Files" => "Archivos", +"Text" => "Texto", +"Images" => "Imágenes", +"%s enter the database username." => "%s ingresar el usuario de la base de datos.", +"%s enter the database name." => "%s ingresar el nombre de la base de datos", +"%s you may not use dots in the database name" => "%s puede utilizar puntos en el nombre de la base de datos", +"MS SQL username and/or password not valid: %s" => "Usuario y/o contraseña de MS SQL no válidos: %s", +"You need to enter either an existing account or the administrator." => "Tiene que ingresar una cuenta existente o la del administrador.", +"MySQL username and/or password not valid" => "Usuario y/o contraseña de MySQL no válidos", +"DB Error: \"%s\"" => "Error BD: \"%s\"", +"Offending command was: \"%s\"" => "Comando infractor: \"%s\"", +"MySQL user '%s'@'localhost' exists already." => "Usuario MySQL '%s'@'localhost' ya existe.", +"Drop this user from MySQL" => "Eliminar este usuario de MySQL", +"MySQL user '%s'@'%%' already exists" => "Usuario MySQL '%s'@'%%' ya existe", +"Drop this user from MySQL." => "Eliminar este usuario de MySQL.", +"Oracle connection could not be established" => "No se pudo establecer la conexión a Oracle", +"Oracle username and/or password not valid" => "Usuario y/o contraseña de Oracle no válidos", +"Offending command was: \"%s\", name: %s, password: %s" => "Comando infractor: \"%s\", nombre: %s, contraseña: %s", +"PostgreSQL username and/or password not valid" => "Usuario y/o contraseña de PostgreSQL no válidos", +"Set an admin username." => "Configurar un nombre de usuario del administrador", +"Set an admin password." => "Configurar la contraseña del administrador.", +"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Su servidor web aún no está configurado adecuadamente para permitir sincronización de archivos ya que la interfaz WebDAV parece no estar funcionando.", +"Please double check the <a href='%s'>installation guides</a>." => "Por favor, vuelva a comprobar las <a href='%s'>guías de instalación</a>.", +"Could not find category \"%s\"" => "No puede encontrar la categoria \"%s\"", +"seconds ago" => "hace segundos", +"_%n minute ago_::_%n minutes ago_" => array("Hace %n minuto","Hace %n minutos"), +"_%n hour ago_::_%n hours ago_" => array("Hace %n hora","Hace %n horas"), +"today" => "hoy", +"yesterday" => "ayer", +"_%n day go_::_%n days ago_" => array("Hace %n día","Hace %n días"), +"last month" => "mes pasado", +"_%n month ago_::_%n months ago_" => array("Hace %n mes","Hace %n meses"), +"last year" => "año pasado", +"years ago" => "hace años" +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/private/l10n/et_EE.php b/lib/l10n/et_EE.php index 85dfaeb52d5..96fceaa04ed 100644 --- a/lib/private/l10n/et_EE.php +++ b/lib/l10n/et_EE.php @@ -8,7 +8,6 @@ $TRANSLATIONS = array( "Users" => "Kasutajad", "Admin" => "Admin", "Failed to upgrade \"%s\"." => "Ebaõnnestunud uuendus \"%s\".", -"Custom profile pictures don't work with encryption yet" => "Kohandatud profiili pildid ei toimi veel koos krüpteeringuga", "Unknown filetype" => "Tundmatu failitüüp", "Invalid image" => "Vigane pilt", "web services under your control" => "veebitenused sinu kontrolli all", @@ -17,7 +16,7 @@ $TRANSLATIONS = array( "Files need to be downloaded one by one." => "Failid tuleb alla laadida ükshaaval.", "Back to Files" => "Tagasi failide juurde", "Selected files too large to generate zip file." => "Valitud failid on ZIP-faili loomiseks liiga suured.", -"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Laadi failid alla eraldi väiksemate osadena või küsi nõu oma süsteemiadminstraatorilt.", +"Please download the files separately in smaller chunks or kindly ask your administrator." => "Palun laadi failid alla eraldi väiksemate osadena või palu abi oma süsteemihaldurilt.", "No source specified when installing app" => "Ühegi lähteallikat pole rakendi paigalduseks määratletud", "No href specified when installing app from http" => "Ühtegi aadressi pole määratletud rakendi paigalduseks veebist", "No path specified when installing app from local file" => "Ühtegi teed pole määratletud paigaldamaks rakendit kohalikust failist", @@ -56,6 +55,7 @@ $TRANSLATIONS = array( "Set an admin password." => "Määra admini parool.", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Veebiserveri ei ole veel korralikult seadistatud võimaldamaks failide sünkroniseerimist, kuna WebDAV liides näib olevat mittetoimiv.", "Please double check the <a href='%s'>installation guides</a>." => "Palun tutvu veelkord <a href='%s'>paigalduse juhenditega</a>.", +"Could not find category \"%s\"" => "Ei leia kategooriat \"%s\"", "seconds ago" => "sekundit tagasi", "_%n minute ago_::_%n minutes ago_" => array("","%n minutit tagasi"), "_%n hour ago_::_%n hours ago_" => array("","%n tundi tagasi"), @@ -65,8 +65,6 @@ $TRANSLATIONS = array( "last month" => "viimasel kuul", "_%n month ago_::_%n months ago_" => array("","%n kuud tagasi"), "last year" => "viimasel aastal", -"years ago" => "aastat tagasi", -"Caused by:" => "Põhjustaja:", -"Could not find category \"%s\"" => "Ei leia kategooriat \"%s\"" +"years ago" => "aastat tagasi" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/private/l10n/eu.php b/lib/l10n/eu.php index 413819f4f94..e3f18fca47a 100644 --- a/lib/private/l10n/eu.php +++ b/lib/l10n/eu.php @@ -1,18 +1,34 @@ <?php $TRANSLATIONS = array( +"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "\"%s\" Aplikazioa ezin da instalatu ownCloud bertsio honekin bateragarria ez delako", +"No app name specified" => "Ez da aplikazioaren izena zehaztu", "Help" => "Laguntza", "Personal" => "Pertsonala", "Settings" => "Ezarpenak", "Users" => "Erabiltzaileak", "Admin" => "Admin", "Failed to upgrade \"%s\"." => "Ezin izan da \"%s\" eguneratu.", +"Unknown filetype" => "Fitxategi mota ezezaguna", +"Invalid image" => "Baliogabeko irudia", "web services under your control" => "web zerbitzuak zure kontrolpean", "cannot open \"%s\"" => "ezin da \"%s\" ireki", "ZIP download is turned off." => "ZIP deskarga ez dago gaituta.", "Files need to be downloaded one by one." => "Fitxategiak banan-banan deskargatu behar dira.", "Back to Files" => "Itzuli fitxategietara", "Selected files too large to generate zip file." => "Hautatuko fitxategiak oso handiak dira zip fitxategia sortzeko.", -"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Deskargatu fitzategiak zati txikiagoetan, banan-banan edo eskatu mesedez zure administradoreari", +"Please download the files separately in smaller chunks or kindly ask your administrator." => "Mesedez deskargatu fitzategiak zati txikiagoetan, banan-banan edo eskatu mesedez zure administradoreari.", +"No source specified when installing app" => "Ez da jatorririk zehaztu aplikazioa instalatzerakoan", +"No href specified when installing app from http" => "Ez da href parametrorik zehaztu http bidez aplikazioa instalatzerakoan", +"No path specified when installing app from local file" => "Ez da kokalekurik zehaztu fitxategi lokal moduan aplikazioa instalatzerakoan", +"Archives of type %s are not supported" => "%s motako fitxategiak ez dira onartzen", +"Failed to open archive when installing app" => "Fitxategia irekitzeak huts egin du aplikazioa instalatzerakoan", +"App does not provide an info.xml file" => "Aplikazioak ez du info.xml fitxategia", +"App can't be installed because of not allowed code in the App" => "Aplikazioa ezin da instalatu bertan duen baimendu gabeko kodea dela eta", +"App can't be installed because it is not compatible with this version of ownCloud" => "Aplikazioa ezin da instalatu ownCloud bertsio honekin bateragarria ez delako", +"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "Aplikazioa ezin da instalatu <shipped>true</shipped> etiketa duelako eta etiketa hau ez da onartzen banaketan ez datozen aplikazioetan", +"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "Aplikazioa ezin da instalatu info.xml/version bertsioa ez delako \"app store\"an jartzen duenaren berdina", +"App directory already exists" => "Aplikazioaren karpeta dagoeneko existitzen da", +"Can't create app folder. Please fix permissions. %s" => "Ezin izan da aplikazioaren karpeta sortu. Mesdez konpondu baimenak. %s", "Application is not enabled" => "Aplikazioa ez dago gaituta", "Authentication error" => "Autentifikazio errorea", "Token expired. Please reload page." => "Tokena iraungitu da. Mesedez birkargatu orria.", @@ -39,6 +55,7 @@ $TRANSLATIONS = array( "Set an admin password." => "Ezarri administraziorako pasahitza.", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Zure web zerbitzaria ez dago oraindik ongi konfiguratuta fitxategien sinkronizazioa egiteko, WebDAV interfazea ongi ez dagoela dirudi.", "Please double check the <a href='%s'>installation guides</a>." => "Mesedez begiratu <a href='%s'>instalazio gidak</a>.", +"Could not find category \"%s\"" => "Ezin da \"%s\" kategoria aurkitu", "seconds ago" => "segundu", "_%n minute ago_::_%n minutes ago_" => array("orain dela minutu %n","orain dela %n minutu"), "_%n hour ago_::_%n hours ago_" => array("orain dela ordu %n","orain dela %n ordu"), @@ -48,8 +65,6 @@ $TRANSLATIONS = array( "last month" => "joan den hilabetean", "_%n month ago_::_%n months ago_" => array("orain dela hilabete %n","orain dela %n hilabete"), "last year" => "joan den urtean", -"years ago" => "urte", -"Caused by:" => "Honek eraginda:", -"Could not find category \"%s\"" => "Ezin da \"%s\" kategoria aurkitu" +"years ago" => "urte" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/private/l10n/fa.php b/lib/l10n/fa.php index e9cb695bade..788b3703966 100644 --- a/lib/private/l10n/fa.php +++ b/lib/l10n/fa.php @@ -36,6 +36,7 @@ $TRANSLATIONS = array( "Set an admin password." => "یک رمزعبور برای مدیر تنظیم نمایید.", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "احتمالاً وب سرور شما طوری تنظیم نشده است که اجازه ی همگام سازی فایلها را بدهد زیرا به نظر میرسد رابط WebDAV از کار افتاده است.", "Please double check the <a href='%s'>installation guides</a>." => "لطفاً دوباره <a href='%s'>راهنمای نصب</a>را بررسی کنید.", +"Could not find category \"%s\"" => "دسته بندی %s یافت نشد", "seconds ago" => "ثانیهها پیش", "_%n minute ago_::_%n minutes ago_" => array(""), "_%n hour ago_::_%n hours ago_" => array(""), @@ -45,7 +46,6 @@ $TRANSLATIONS = array( "last month" => "ماه قبل", "_%n month ago_::_%n months ago_" => array(""), "last year" => "سال قبل", -"years ago" => "سالهای قبل", -"Could not find category \"%s\"" => "دسته بندی %s یافت نشد" +"years ago" => "سالهای قبل" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/lib/private/l10n/fi.php b/lib/l10n/fi.php index ac1f80a8f73..ac1f80a8f73 100644 --- a/lib/private/l10n/fi.php +++ b/lib/l10n/fi.php diff --git a/lib/private/l10n/fi_FI.php b/lib/l10n/fi_FI.php index 1d2bdab749c..573704da44c 100644 --- a/lib/private/l10n/fi_FI.php +++ b/lib/l10n/fi_FI.php @@ -8,7 +8,6 @@ $TRANSLATIONS = array( "Users" => "Käyttäjät", "Admin" => "Ylläpitäjä", "Failed to upgrade \"%s\"." => "Kohteen \"%s\" päivitys epäonnistui.", -"Custom profile pictures don't work with encryption yet" => "Omavalintaiset profiilikuvat eivät toimi salauksen kanssa vielä", "Unknown filetype" => "Tuntematon tiedostotyyppi", "Invalid image" => "Virheellinen kuva", "web services under your control" => "verkkopalvelut hallinnassasi", @@ -17,8 +16,10 @@ $TRANSLATIONS = array( "Back to Files" => "Takaisin tiedostoihin", "Selected files too large to generate zip file." => "Valitut tiedostot ovat liian suurikokoisia mahtuakseen zip-tiedostoon.", "No source specified when installing app" => "Lähdettä ei määritelty sovellusta asennettaessa", +"No href specified when installing app from http" => "Href-määritettä ei asetettu asennettaessa sovellusta http:n yli", "No path specified when installing app from local file" => "Polkua ei määritelty sovellusta asennettaessa paikallisesta tiedostosta", "Archives of type %s are not supported" => "Tyypin %s arkistot eivät ole tuettuja", +"Failed to open archive when installing app" => "Pakettitiedoston avaaminen epäonnistui sovellusta asennettaessa", "App does not provide an info.xml file" => "Sovellus ei sisällä info.xml-tiedostoa", "App can't be installed because of not allowed code in the App" => "Sovellusta ei voi asentaa, koska sovellus sisältää kiellettyä koodia", "App can't be installed because it is not compatible with this version of ownCloud" => "Sovellusta ei voi asentaa, koska se ei ole yhteensopiva käytössä olevan ownCloud-version kanssa", @@ -46,6 +47,7 @@ $TRANSLATIONS = array( "Set an admin username." => "Aseta ylläpitäjän käyttäjätunnus.", "Set an admin password." => "Aseta ylläpitäjän salasana.", "Please double check the <a href='%s'>installation guides</a>." => "Lue tarkasti <a href='%s'>asennusohjeet</a>.", +"Could not find category \"%s\"" => "Luokkaa \"%s\" ei löytynyt", "seconds ago" => "sekuntia sitten", "_%n minute ago_::_%n minutes ago_" => array("%n minuutti sitten","%n minuuttia sitten"), "_%n hour ago_::_%n hours ago_" => array("%n tunti sitten","%n tuntia sitten"), @@ -55,8 +57,6 @@ $TRANSLATIONS = array( "last month" => "viime kuussa", "_%n month ago_::_%n months ago_" => array("%n kuukausi sitten","%n kuukautta sitten"), "last year" => "viime vuonna", -"years ago" => "vuotta sitten", -"Caused by:" => "Aiheuttaja:", -"Could not find category \"%s\"" => "Luokkaa \"%s\" ei löytynyt" +"years ago" => "vuotta sitten" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/private/l10n/fr.php b/lib/l10n/fr.php index ab3d618849e..75a4f277271 100644 --- a/lib/private/l10n/fr.php +++ b/lib/l10n/fr.php @@ -8,7 +8,6 @@ $TRANSLATIONS = array( "Users" => "Utilisateurs", "Admin" => "Administration", "Failed to upgrade \"%s\"." => "Echec de la mise à niveau \"%s\".", -"Custom profile pictures don't work with encryption yet" => "Les images de profil personnalisées ne fonctionnent pas encore avec le système de chiffrement.", "Unknown filetype" => "Type de fichier inconnu", "Invalid image" => "Image invalide", "web services under your control" => "services web sous votre contrôle", @@ -17,7 +16,7 @@ $TRANSLATIONS = array( "Files need to be downloaded one by one." => "Les fichiers nécessitent d'être téléchargés un par un.", "Back to Files" => "Retour aux Fichiers", "Selected files too large to generate zip file." => "Les fichiers sélectionnés sont trop volumineux pour être compressés.", -"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Télécharger les fichiers en parties plus petites, séparément ou demander avec bienveillance à votre administrateur.", +"Please download the files separately in smaller chunks or kindly ask your administrator." => "Merci de télécharger les fichiers séparément en parties plus petites, ou demandez aimablement à votre administrateur.", "No source specified when installing app" => "Aucune source spécifiée pour installer l'application", "No href specified when installing app from http" => "Aucun href spécifié pour installer l'application par http", "No path specified when installing app from local file" => "Aucun chemin spécifié pour installer l'application depuis un fichier local", @@ -56,6 +55,7 @@ $TRANSLATIONS = array( "Set an admin password." => "Spécifiez un mot de passe administrateur.", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Votre serveur web, n'est pas correctement configuré pour permettre la synchronisation des fichiers, car l'interface WebDav ne fonctionne pas comme il faut.", "Please double check the <a href='%s'>installation guides</a>." => "Veuillez vous référer au <a href='%s'>guide d'installation</a>.", +"Could not find category \"%s\"" => "Impossible de trouver la catégorie \"%s\"", "seconds ago" => "il y a quelques secondes", "_%n minute ago_::_%n minutes ago_" => array("","il y a %n minutes"), "_%n hour ago_::_%n hours ago_" => array("","Il y a %n heures"), @@ -65,8 +65,6 @@ $TRANSLATIONS = array( "last month" => "le mois dernier", "_%n month ago_::_%n months ago_" => array("","Il y a %n mois"), "last year" => "l'année dernière", -"years ago" => "il y a plusieurs années", -"Caused by:" => "Causé par :", -"Could not find category \"%s\"" => "Impossible de trouver la catégorie \"%s\"" +"years ago" => "il y a plusieurs années" ); $PLURAL_FORMS = "nplurals=2; plural=(n > 1);"; diff --git a/lib/l10n/fr_CA.php b/lib/l10n/fr_CA.php new file mode 100644 index 00000000000..406ff5f5a26 --- /dev/null +++ b/lib/l10n/fr_CA.php @@ -0,0 +1,8 @@ +<?php +$TRANSLATIONS = array( +"_%n minute ago_::_%n minutes ago_" => array("",""), +"_%n hour ago_::_%n hours ago_" => array("",""), +"_%n day go_::_%n days ago_" => array("",""), +"_%n month ago_::_%n months ago_" => array("","") +); +$PLURAL_FORMS = "nplurals=2; plural=(n > 1);"; diff --git a/lib/private/l10n/gl.php b/lib/l10n/gl.php index 406272d690f..81a62021556 100644 --- a/lib/private/l10n/gl.php +++ b/lib/l10n/gl.php @@ -8,7 +8,6 @@ $TRANSLATIONS = array( "Users" => "Usuarios", "Admin" => "Administración", "Failed to upgrade \"%s\"." => "Non foi posíbel anovar «%s».", -"Custom profile pictures don't work with encryption yet" => "As imaxes personalizadas de perfil aínda non funcionan co cifrado", "Unknown filetype" => "Tipo de ficheiro descoñecido", "Invalid image" => "Imaxe incorrecta", "web services under your control" => "servizos web baixo o seu control", @@ -17,7 +16,7 @@ $TRANSLATIONS = array( "Files need to be downloaded one by one." => "Os ficheiros necesitan seren descargados dun en un.", "Back to Files" => "Volver aos ficheiros", "Selected files too large to generate zip file." => "Os ficheiros seleccionados son demasiado grandes como para xerar un ficheiro zip.", -"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Descargue os ficheiros en cachos máis pequenos e por separado, ou pídallos amabelmente ao seu administrador.", +"Please download the files separately in smaller chunks or kindly ask your administrator." => "Descargue os ficheiros en fragmentos máis pequenos e por separado, ou pídallos amabelmente ao seu administrador.", "No source specified when installing app" => "Non foi especificada ningunha orixe ao instalar aplicativos", "No href specified when installing app from http" => "Non foi especificada ningunha href ao instalar aplicativos", "No path specified when installing app from local file" => "Non foi especificada ningunha ruta ao instalar aplicativos desde un ficheiro local", @@ -56,6 +55,7 @@ $TRANSLATIONS = array( "Set an admin password." => "Estabeleza un contrasinal de administrador", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "O seu servidor web non está aínda configurado adecuadamente para permitir a sincronización de ficheiros xa que semella que a interface WebDAV non está a funcionar.", "Please double check the <a href='%s'>installation guides</a>." => "Volva comprobar as <a href='%s'>guías de instalación</a>", +"Could not find category \"%s\"" => "Non foi posíbel atopar a categoría «%s»", "seconds ago" => "segundos atrás", "_%n minute ago_::_%n minutes ago_" => array("hai %n minuto","hai %n minutos"), "_%n hour ago_::_%n hours ago_" => array("hai %n hora","hai %n horas"), @@ -65,8 +65,6 @@ $TRANSLATIONS = array( "last month" => "último mes", "_%n month ago_::_%n months ago_" => array("hai %n mes","hai %n meses"), "last year" => "último ano", -"years ago" => "anos atrás", -"Caused by:" => "Causado por:", -"Could not find category \"%s\"" => "Non foi posíbel atopar a categoría «%s»" +"years ago" => "anos atrás" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/private/l10n/he.php b/lib/l10n/he.php index ced6244ee91..5bbfffe9ae9 100644 --- a/lib/private/l10n/he.php +++ b/lib/l10n/he.php @@ -18,6 +18,7 @@ $TRANSLATIONS = array( "Images" => "תמונות", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "שרת האינטרנט שלך אינו מוגדר לצורכי סנכרון קבצים עדיין כיוון שמנשק ה־WebDAV כנראה אינו תקין.", "Please double check the <a href='%s'>installation guides</a>." => "נא לעיין שוב ב<a href='%s'>מדריכי ההתקנה</a>.", +"Could not find category \"%s\"" => "לא ניתן למצוא את הקטגוריה „%s“", "seconds ago" => "שניות", "_%n minute ago_::_%n minutes ago_" => array("","לפני %n דקות"), "_%n hour ago_::_%n hours ago_" => array("","לפני %n שעות"), @@ -27,7 +28,6 @@ $TRANSLATIONS = array( "last month" => "חודש שעבר", "_%n month ago_::_%n months ago_" => array("","לפני %n חודשים"), "last year" => "שנה שעברה", -"years ago" => "שנים", -"Could not find category \"%s\"" => "לא ניתן למצוא את הקטגוריה „%s“" +"years ago" => "שנים" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/private/l10n/hi.php b/lib/l10n/hi.php index 039dfa4465d..039dfa4465d 100644 --- a/lib/private/l10n/hi.php +++ b/lib/l10n/hi.php diff --git a/lib/private/l10n/hr.php b/lib/l10n/hr.php index d217f924099..d217f924099 100644 --- a/lib/private/l10n/hr.php +++ b/lib/l10n/hr.php diff --git a/lib/private/l10n/hu_HU.php b/lib/l10n/hu_HU.php index e944291caee..efaf2a2fd48 100644 --- a/lib/private/l10n/hu_HU.php +++ b/lib/l10n/hu_HU.php @@ -1,5 +1,6 @@ <?php $TRANSLATIONS = array( +"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "A(z) \"%s\" alkalmazást nem lehet telepíteni, mert nem kompatibilis az ownCloud telepített verziójával.", "No app name specified" => "Nincs az alkalmazás név megadva.", "Help" => "Súgó", "Personal" => "Személyes", @@ -15,9 +16,17 @@ $TRANSLATIONS = array( "Files need to be downloaded one by one." => "A fájlokat egyenként kell letölteni.", "Back to Files" => "Vissza a Fájlokhoz", "Selected files too large to generate zip file." => "A kiválasztott fájlok túl nagyok a zip tömörítéshez.", -"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Tölts le a fileokat kisebb chunkokban, kölün vagy kérj segitséget a rendszergazdádtól.", +"Please download the files separately in smaller chunks or kindly ask your administrator." => "A file-t kisebb részekben töltsd le vagy beszélj az adminisztrátorral a megoldás érdekében.", +"No source specified when installing app" => "Az alkalmazás telepítéséhez nincs forrás megadva", +"No href specified when installing app from http" => "Az alkalmazás http-n keresztül történő telepítéséhez nincs href hivetkozás megadva", +"No path specified when installing app from local file" => "Az alkalmazás helyi telepítéséhez nincs útvonal (mappa) megadva", +"Archives of type %s are not supported" => "A(z) %s típusú tömörített állomány nem támogatott", +"Failed to open archive when installing app" => "Nem sikerült megnyitni a tömörített állományt a telepítés során", "App does not provide an info.xml file" => "Az alkalmazás nem szolgáltatott info.xml file-t", +"App can't be installed because of not allowed code in the App" => "Az alkalmazást nem lehet telepíteni, mert abban nem engedélyezett programkód szerepel", "App can't be installed because it is not compatible with this version of ownCloud" => "Az alalmazás nem telepíthető, mert nem kompatibilis az ownClod ezzel a verziójával.", +"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "Az alkalmazást nem lehet telepíteni, mert tartalmazza a \n<shipped>\ntrue\n</shipped>\ncímkét, ami a nem szállított alkalmazások esetén nem engedélyezett", +"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "Az alkalmazást nem lehet telepíteni, mert az info.xml/version-ben megadott verzió nem egyezik az alkalmazás-áruházban feltüntetett verzióval.", "App directory already exists" => "Az alkalmazás mappája már létezik", "Can't create app folder. Please fix permissions. %s" => "Nem lehetett létrehozni az alkalmzás mappáját. Kérlek ellenőrizd a jogosultásgokat. %s", "Application is not enabled" => "Az alkalmazás nincs engedélyezve", @@ -48,15 +57,14 @@ $TRANSLATIONS = array( "Please double check the <a href='%s'>installation guides</a>." => "Kérjük tüzetesen tanulmányozza át a <a href='%s'>telepítési útmutatót</a>.", "Could not find category \"%s\"" => "Ez a kategória nem található: \"%s\"", "seconds ago" => "pár másodperce", -"_%n minute ago_::_%n minutes ago_" => array("",""), -"_%n hour ago_::_%n hours ago_" => array("",""), +"_%n minute ago_::_%n minutes ago_" => array("","%n perccel ezelőtt"), +"_%n hour ago_::_%n hours ago_" => array("%n órával ezelőtt","%n órával ezelőtt"), "today" => "ma", "yesterday" => "tegnap", -"_%n day go_::_%n days ago_" => array("",""), +"_%n day go_::_%n days ago_" => array("%n nappal ezelőtt","%n nappal ezelőtt"), "last month" => "múlt hónapban", -"_%n month ago_::_%n months ago_" => array("",""), +"_%n month ago_::_%n months ago_" => array("%n hónappal ezelőtt","%n hónappal ezelőtt"), "last year" => "tavaly", -"years ago" => "több éve", -"Caused by:" => "Okozta:" +"years ago" => "több éve" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/private/l10n/ml_IN.php b/lib/l10n/hy.php index 15f78e0bce6..15f78e0bce6 100644 --- a/lib/private/l10n/ml_IN.php +++ b/lib/l10n/hy.php diff --git a/lib/private/l10n/ia.php b/lib/l10n/ia.php index 34f43bc424a..34f43bc424a 100644 --- a/lib/private/l10n/ia.php +++ b/lib/l10n/ia.php diff --git a/lib/l10n/id.php b/lib/l10n/id.php new file mode 100644 index 00000000000..27d7843104b --- /dev/null +++ b/lib/l10n/id.php @@ -0,0 +1,70 @@ +<?php +$TRANSLATIONS = array( +"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "Apl \"%s\" tidak dapat diinstal karena tidak kompatibel dengan versi ownCloud.", +"No app name specified" => "Tidak ada nama apl yang ditentukan", +"Help" => "Bantuan", +"Personal" => "Pribadi", +"Settings" => "Pengaturan", +"Users" => "Pengguna", +"Admin" => "Admin", +"Failed to upgrade \"%s\"." => "Gagal memperbarui \"%s\".", +"Unknown filetype" => "Tipe berkas tak dikenal", +"Invalid image" => "Gambar tidak sah", +"web services under your control" => "layanan web dalam kendali anda", +"cannot open \"%s\"" => "tidak dapat membuka \"%s\"", +"ZIP download is turned off." => "Pengunduhan ZIP dimatikan.", +"Files need to be downloaded one by one." => "Berkas harus diunduh satu persatu.", +"Back to Files" => "Kembali ke Berkas", +"Selected files too large to generate zip file." => "Berkas yang dipilih terlalu besar untuk dibuat berkas zip-nya.", +"Please download the files separately in smaller chunks or kindly ask your administrator." => "Silahkan unduh berkas secara terpisah dalam bentuk potongan kecil atau meminta ke administrator anda.", +"No source specified when installing app" => "Tidak ada sumber yang ditentukan saat menginstal apl", +"No href specified when installing app from http" => "Href tidak ditentukan saat menginstal apl dari http", +"No path specified when installing app from local file" => "Lokasi tidak ditentukan saat menginstal apl dari berkas lokal", +"Archives of type %s are not supported" => "Arsip dengan tipe %s tidak didukung", +"Failed to open archive when installing app" => "Gagal membuka arsip saat menginstal apl", +"App does not provide an info.xml file" => "Apl tidak menyediakan berkas info.xml", +"App can't be installed because of not allowed code in the App" => "Apl tidak dapat diinstal karena terdapat kode yang tidak diizinkan didalam Apl", +"App can't be installed because it is not compatible with this version of ownCloud" => "Apl tidak dapat diinstal karena tidak kompatibel dengan versi ownCloud", +"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "Apl tidak dapat diinstal karena mengandung tag <shipped>true</shipped> yang tidak diizinkan untuk apl yang bukan bawaan.", +"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "Apl tidak dapat diinstal karena versi di info.xml/versi tidak sama dengan versi yang dilansir dari toko apl", +"App directory already exists" => "Direktori Apl sudah ada", +"Can't create app folder. Please fix permissions. %s" => "Tidak dapat membuat folder apl. Silakan perbaiki perizinan. %s", +"Application is not enabled" => "Aplikasi tidak diaktifkan", +"Authentication error" => "Galat saat otentikasi", +"Token expired. Please reload page." => "Token sudah kedaluwarsa. Silakan muat ulang halaman.", +"Files" => "Berkas", +"Text" => "Teks", +"Images" => "Gambar", +"%s enter the database username." => "%s masukkan nama pengguna basis data.", +"%s enter the database name." => "%s masukkan nama basis data.", +"%s you may not use dots in the database name" => "%s anda tidak boleh menggunakan karakter titik pada nama basis data", +"MS SQL username and/or password not valid: %s" => "Nama pengguna dan/atau sandi MySQL tidak sah: %s", +"You need to enter either an existing account or the administrator." => "Anda harus memasukkan akun yang sudah ada atau administrator.", +"MySQL username and/or password not valid" => "Nama pengguna dan/atau sandi MySQL tidak sah", +"DB Error: \"%s\"" => "Galat Basis Data: \"%s\"", +"Offending command was: \"%s\"" => "Perintah yang bermasalah: \"%s\"", +"MySQL user '%s'@'localhost' exists already." => "Pengguna MySQL '%s'@'localhost' sudah ada.", +"Drop this user from MySQL" => "Hapus pengguna ini dari MySQL", +"MySQL user '%s'@'%%' already exists" => "Pengguna MySQL '%s'@'%%' sudah ada.", +"Drop this user from MySQL." => "Hapus pengguna ini dari MySQL.", +"Oracle connection could not be established" => "Koneksi Oracle tidak dapat dibuat", +"Oracle username and/or password not valid" => "Nama pengguna dan/atau sandi Oracle tidak sah", +"Offending command was: \"%s\", name: %s, password: %s" => "Perintah yang bermasalah: \"%s\", nama pengguna: %s, sandi: %s", +"PostgreSQL username and/or password not valid" => "Nama pengguna dan/atau sandi PostgreSQL tidak valid", +"Set an admin username." => "Atur nama pengguna admin.", +"Set an admin password." => "Atur sandi admin.", +"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Web server Anda belum dikonfigurasikan dengan baik untuk mengizinkan sinkronisasi berkas karena tampaknya antarmuka WebDAV rusak.", +"Please double check the <a href='%s'>installation guides</a>." => "Silakan periksa ulang <a href='%s'>panduan instalasi</a>.", +"Could not find category \"%s\"" => "Tidak menemukan kategori \"%s\"", +"seconds ago" => "beberapa detik yang lalu", +"_%n minute ago_::_%n minutes ago_" => array("%n menit yang lalu"), +"_%n hour ago_::_%n hours ago_" => array("%n jam yang lalu"), +"today" => "hari ini", +"yesterday" => "kemarin", +"_%n day go_::_%n days ago_" => array("%n hari yang lalu"), +"last month" => "bulan kemarin", +"_%n month ago_::_%n months ago_" => array("%n bulan yang lalu"), +"last year" => "tahun kemarin", +"years ago" => "beberapa tahun lalu" +); +$PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/lib/private/l10n/is.php b/lib/l10n/is.php index 7512d278fb8..032289fd304 100644 --- a/lib/private/l10n/is.php +++ b/lib/l10n/is.php @@ -16,6 +16,7 @@ $TRANSLATIONS = array( "Files" => "Skrár", "Text" => "Texti", "Images" => "Myndir", +"Could not find category \"%s\"" => "Fann ekki flokkinn \"%s\"", "seconds ago" => "sek.", "_%n minute ago_::_%n minutes ago_" => array("",""), "_%n hour ago_::_%n hours ago_" => array("",""), @@ -25,7 +26,6 @@ $TRANSLATIONS = array( "last month" => "síðasta mánuði", "_%n month ago_::_%n months ago_" => array("",""), "last year" => "síðasta ári", -"years ago" => "einhverjum árum", -"Could not find category \"%s\"" => "Fann ekki flokkinn \"%s\"" +"years ago" => "einhverjum árum" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/private/l10n/it.php b/lib/l10n/it.php index b00789bc86f..cd2073bfd0a 100644 --- a/lib/private/l10n/it.php +++ b/lib/l10n/it.php @@ -8,7 +8,6 @@ $TRANSLATIONS = array( "Users" => "Utenti", "Admin" => "Admin", "Failed to upgrade \"%s\"." => "Aggiornamento non riuscito \"%s\".", -"Custom profile pictures don't work with encryption yet" => "Le immagini personalizzate del profilo non funzionano ancora con la cifratura", "Unknown filetype" => "Tipo di file sconosciuto", "Invalid image" => "Immagine non valida", "web services under your control" => "servizi web nelle tue mani", @@ -17,7 +16,7 @@ $TRANSLATIONS = array( "Files need to be downloaded one by one." => "I file devono essere scaricati uno alla volta.", "Back to Files" => "Torna ai file", "Selected files too large to generate zip file." => "I file selezionati sono troppo grandi per generare un file zip.", -"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Scarica i file in blocchi più piccoli, separatamente o chiedi al tuo amministratore.", +"Please download the files separately in smaller chunks or kindly ask your administrator." => "Scarica i file separatamente in blocchi più piccoli o chiedi al tuo amministratore.", "No source specified when installing app" => "Nessuna fonte specificata durante l'installazione dell'applicazione", "No href specified when installing app from http" => "Nessun href specificato durante l'installazione dell'applicazione da http", "No path specified when installing app from local file" => "Nessun percorso specificato durante l'installazione dell'applicazione da file locale", @@ -56,6 +55,7 @@ $TRANSLATIONS = array( "Set an admin password." => "Imposta una password di amministrazione.", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Il tuo server web non è configurato correttamente per consentire la sincronizzazione dei file poiché l'interfaccia WebDAV sembra essere danneggiata.", "Please double check the <a href='%s'>installation guides</a>." => "Leggi attentamente le <a href='%s'>guide d'installazione</a>.", +"Could not find category \"%s\"" => "Impossibile trovare la categoria \"%s\"", "seconds ago" => "secondi fa", "_%n minute ago_::_%n minutes ago_" => array("%n minuto fa","%n minuti fa"), "_%n hour ago_::_%n hours ago_" => array("%n ora fa","%n ore fa"), @@ -65,8 +65,6 @@ $TRANSLATIONS = array( "last month" => "mese scorso", "_%n month ago_::_%n months ago_" => array("%n mese fa","%n mesi fa"), "last year" => "anno scorso", -"years ago" => "anni fa", -"Caused by:" => "Causato da:", -"Could not find category \"%s\"" => "Impossibile trovare la categoria \"%s\"" +"years ago" => "anni fa" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/private/l10n/ja_JP.php b/lib/l10n/ja_JP.php index b9e6a0e6924..9c5c0ba4763 100644 --- a/lib/private/l10n/ja_JP.php +++ b/lib/l10n/ja_JP.php @@ -8,7 +8,6 @@ $TRANSLATIONS = array( "Users" => "ユーザ", "Admin" => "管理", "Failed to upgrade \"%s\"." => "\"%s\" へのアップグレードに失敗しました。", -"Custom profile pictures don't work with encryption yet" => "暗号無しでは利用不可なカスタムプロフィール画像", "Unknown filetype" => "不明なファイルタイプ", "Invalid image" => "無効な画像", "web services under your control" => "管理下のウェブサービス", @@ -17,7 +16,7 @@ $TRANSLATIONS = array( "Files need to be downloaded one by one." => "ファイルは1つずつダウンロードする必要があります。", "Back to Files" => "ファイルに戻る", "Selected files too large to generate zip file." => "選択したファイルはZIPファイルの生成には大きすぎます。", -"Download the files in smaller chunks, seperately or kindly ask your administrator." => "ファイルは、小さいファイルに分割されてダウンロードされます。もしくは、管理者にお尋ねください。", +"Please download the files separately in smaller chunks or kindly ask your administrator." => "少しずつに分けてファイルをダウンロードするか、管理者に問い合わせてください。", "No source specified when installing app" => "アプリインストール時のソースが未指定", "No href specified when installing app from http" => "アプリインストール時のhttpの URL が未指定", "No path specified when installing app from local file" => "アプリインストール時のローカルファイルのパスが未指定", @@ -56,17 +55,16 @@ $TRANSLATIONS = array( "Set an admin password." => "管理者のパスワードを設定。", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "WebDAVインタフェースが動作していないと考えられるため、あなたのWEBサーバはまだファイルの同期を許可するように適切な設定がされていません。", "Please double check the <a href='%s'>installation guides</a>." => "<a href='%s'>インストールガイド</a>をよく確認してください。", +"Could not find category \"%s\"" => "カテゴリ \"%s\" が見つかりませんでした", "seconds ago" => "数秒前", "_%n minute ago_::_%n minutes ago_" => array("%n 分前"), -"_%n hour ago_::_%n hours ago_" => array("%n 時間後"), +"_%n hour ago_::_%n hours ago_" => array("%n 時間前"), "today" => "今日", "yesterday" => "昨日", -"_%n day go_::_%n days ago_" => array("%n 日後"), +"_%n day go_::_%n days ago_" => array("%n 日前"), "last month" => "一月前", -"_%n month ago_::_%n months ago_" => array("%n カ月後"), +"_%n month ago_::_%n months ago_" => array("%n ヶ月前"), "last year" => "一年前", -"years ago" => "年前", -"Caused by:" => "原因は以下:", -"Could not find category \"%s\"" => "カテゴリ \"%s\" が見つかりませんでした" +"years ago" => "年前" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/lib/private/l10n/ka.php b/lib/l10n/ka.php index 04fefe8bdf1..04fefe8bdf1 100644 --- a/lib/private/l10n/ka.php +++ b/lib/l10n/ka.php diff --git a/lib/private/l10n/ka_GE.php b/lib/l10n/ka_GE.php index 8fbe34e6786..0cf6ab333e8 100644 --- a/lib/private/l10n/ka_GE.php +++ b/lib/l10n/ka_GE.php @@ -35,6 +35,7 @@ $TRANSLATIONS = array( "Set an admin password." => "დააყენეთ ადმინისტრატორის პაროლი.", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "თქვენი web სერვერი არ არის კონფიგურირებული ფაილ სინქრონიზაციისთვის, რადგან WebDAV ინტერფეისი შეიძლება იყოს გატეხილი.", "Please double check the <a href='%s'>installation guides</a>." => "გთხოვთ გადაათვალიეროთ <a href='%s'>ინსტალაციის გზამკვლევი</a>.", +"Could not find category \"%s\"" => "\"%s\" კატეგორიის მოძებნა ვერ მოხერხდა", "seconds ago" => "წამის წინ", "_%n minute ago_::_%n minutes ago_" => array(""), "_%n hour ago_::_%n hours ago_" => array(""), @@ -44,7 +45,6 @@ $TRANSLATIONS = array( "last month" => "გასულ თვეში", "_%n month ago_::_%n months ago_" => array(""), "last year" => "ბოლო წელს", -"years ago" => "წლის წინ", -"Could not find category \"%s\"" => "\"%s\" კატეგორიის მოძებნა ვერ მოხერხდა" +"years ago" => "წლის წინ" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/lib/private/l10n/kn.php b/lib/l10n/km.php index e7b09649a24..e7b09649a24 100644 --- a/lib/private/l10n/kn.php +++ b/lib/l10n/km.php diff --git a/lib/private/l10n/nqo.php b/lib/l10n/kn.php index e7b09649a24..e7b09649a24 100644 --- a/lib/private/l10n/nqo.php +++ b/lib/l10n/kn.php diff --git a/lib/private/l10n/ko.php b/lib/l10n/ko.php index 3ef39fefa60..b33ad01546f 100644 --- a/lib/private/l10n/ko.php +++ b/lib/l10n/ko.php @@ -8,52 +8,51 @@ $TRANSLATIONS = array( "Users" => "사용자", "Admin" => "관리자", "Failed to upgrade \"%s\"." => "\"%s\" 업그레이드에 실패했습니다.", -"Custom profile pictures don't work with encryption yet" => "개개인의 프로필 사진은 아직은 암호화 되지 않습니다", -"Unknown filetype" => "알수없는 파일형식", +"Unknown filetype" => "알 수 없는 파일 형식", "Invalid image" => "잘못된 그림", "web services under your control" => "내가 관리하는 웹 서비스", "cannot open \"%s\"" => "\"%s\"을(를) 열 수 없습니다.", -"ZIP download is turned off." => "ZIP 다운로드가 비활성화되었습니다.", +"ZIP download is turned off." => "ZIP 다운로드가 비활성화 되었습니다.", "Files need to be downloaded one by one." => "파일을 개별적으로 다운로드해야 합니다.", "Back to Files" => "파일로 돌아가기", "Selected files too large to generate zip file." => "선택한 파일들은 ZIP 파일을 생성하기에 너무 큽니다.", -"Download the files in smaller chunks, seperately or kindly ask your administrator." => "작은 조각들 안에 들어있는 파일들을 받고자 하신다면, 나누어서 받으시거나 혹은 시스템 관리자에게 정중하게 물어보십시오", +"Please download the files separately in smaller chunks or kindly ask your administrator." => "작은 조각들 안에 들어있는 파일들을 받고자 하신다면, 나누어서 받으시거나 혹은 시스템 관리자에게 정중하게 물어보십시오", "No source specified when installing app" => "앱을 설치할 때 소스가 지정되지 않았습니다.", -"No href specified when installing app from http" => "http에서 앱을 설치할 대 href가 지정되지 않았습니다.", +"No href specified when installing app from http" => "http에서 앱을 설치할 때 href가 지정되지 않았습니다.", "No path specified when installing app from local file" => "로컬 파일에서 앱을 설치할 때 경로가 지정되지 않았습니다.", "Archives of type %s are not supported" => "%s 타입 아카이브는 지원되지 않습니다.", "Failed to open archive when installing app" => "앱을 설치할 때 아카이브를 열지 못했습니다.", "App does not provide an info.xml file" => "앱에서 info.xml 파일이 제공되지 않았습니다.", -"App can't be installed because of not allowed code in the App" => "앱에 허용되지 않는 코드가 있어서 앱을 설치할 수 없습니다. ", +"App can't be installed because of not allowed code in the App" => "앱에 허용되지 않는 코드가 있어서 앱을 설치할 수 없습니다.", "App can't be installed because it is not compatible with this version of ownCloud" => "현재 ownCloud 버전과 호환되지 않기 때문에 앱을 설치할 수 없습니다.", -"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "출하되지 않은 앱에 허용되지 않는 <shipped>true</shipped> 태그를 포함하고 있기 때문에 앱을 설치할 수 없습니다.", -"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "info.xml/version에 포함된 버전과 앱 스토어에 보고된 버전이 같지 않아서 앱을 설치할 수 없습니다. ", -"App directory already exists" => "앱 디렉토리가 이미 존재합니다. ", -"Can't create app folder. Please fix permissions. %s" => "앱 폴더를 만들 수 없습니다. 권한을 수정하십시오. %s ", +"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "출시되지 않은 앱에 허용되지 않는 <shipped>true</shipped> 태그를 포함하고 있기 때문에 앱을 설치할 수 없습니다.", +"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "info.xml/version에 포함된 버전과 앱 스토어에 보고된 버전이 같지 않아서 앱을 설치할 수 없습니다.", +"App directory already exists" => "앱 디렉터리가 이미 존재합니다.", +"Can't create app folder. Please fix permissions. %s" => "앱 폴더를 만들 수 없습니다. 권한을 수정하십시오. %s", "Application is not enabled" => "앱이 활성화되지 않았습니다", "Authentication error" => "인증 오류", "Token expired. Please reload page." => "토큰이 만료되었습니다. 페이지를 새로 고치십시오.", "Files" => "파일", "Text" => "텍스트", "Images" => "그림", -"%s enter the database username." => "데이터베이스 사용자 명을 %s 에 입력해주십시오", -"%s enter the database name." => "데이터베이스 명을 %s 에 입력해주십시오", -"%s you may not use dots in the database name" => "%s 에 적으신 데이터베이스 이름에는 점을 사용할수 없습니다", +"%s enter the database username." => "%s 데이터베이스 사용자 이름을 입력해 주십시오.", +"%s enter the database name." => "%s 데이터베이스 이름을 입력하십시오.", +"%s you may not use dots in the database name" => "%s 데이터베이스 이름에는 마침표를 사용할 수 없습니다", "MS SQL username and/or password not valid: %s" => "MS SQL 사용자 이름이나 암호가 잘못되었습니다: %s", "You need to enter either an existing account or the administrator." => "기존 계정이나 administrator(관리자)를 입력해야 합니다.", "MySQL username and/or password not valid" => "MySQL 사용자 이름이나 암호가 잘못되었습니다.", "DB Error: \"%s\"" => "DB 오류: \"%s\"", "Offending command was: \"%s\"" => "잘못된 명령: \"%s\"", "MySQL user '%s'@'localhost' exists already." => "MySQL 사용자 '%s'@'localhost'이(가) 이미 존재합니다.", -"Drop this user from MySQL" => "이 사용자를 MySQL에서 뺍니다.", -"MySQL user '%s'@'%%' already exists" => "MySQL 사용자 '%s'@'%%'이(가) 이미 존재합니다. ", -"Drop this user from MySQL." => "이 사용자를 MySQL에서 뺍니다.", +"Drop this user from MySQL" => "이 사용자를 MySQL에서 삭제하십시오", +"MySQL user '%s'@'%%' already exists" => "MySQL 사용자 '%s'@'%%'이(가) 이미 존재합니다.", +"Drop this user from MySQL." => "이 사용자를 MySQL에서 삭제하십시오.", "Oracle connection could not be established" => "Oracle 연결을 수립할 수 없습니다.", "Oracle username and/or password not valid" => "Oracle 사용자 이름이나 암호가 잘못되었습니다.", "Offending command was: \"%s\", name: %s, password: %s" => "잘못된 명령: \"%s\", 이름: %s, 암호: %s", -"PostgreSQL username and/or password not valid" => "PostgreSQL의 사용자 명 혹은 비밀번호가 잘못되었습니다", -"Set an admin username." => "관리자 이름 설정", -"Set an admin password." => "관리자 비밀번호 설정", +"PostgreSQL username and/or password not valid" => "PostgreSQL의 사용자 이름 또는 암호가 잘못되었습니다", +"Set an admin username." => "관리자의 사용자 이름을 설정합니다.", +"Set an admin password." => "관리자의 암호를 설정합니다.", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "WebDAV 인터페이스가 제대로 작동하지 않습니다. 웹 서버에서 파일 동기화를 사용할 수 있도록 설정이 제대로 되지 않은 것 같습니다.", "Please double check the <a href='%s'>installation guides</a>." => "<a href='%s'>설치 가이드</a>를 다시 한 번 확인하십시오.", "Could not find category \"%s\"" => "분류 \"%s\"을(를) 찾을 수 없습니다.", @@ -66,7 +65,6 @@ $TRANSLATIONS = array( "last month" => "지난 달", "_%n month ago_::_%n months ago_" => array("%n달 전 "), "last year" => "작년", -"years ago" => "년 전", -"Caused by:" => "원인: " +"years ago" => "년 전" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/lib/private/l10n/ku_IQ.php b/lib/l10n/ku_IQ.php index c99f9dd2a12..c99f9dd2a12 100644 --- a/lib/private/l10n/ku_IQ.php +++ b/lib/l10n/ku_IQ.php diff --git a/lib/private/l10n/lb.php b/lib/l10n/lb.php index c25f5b55bd5..629d5b11c30 100644 --- a/lib/private/l10n/lb.php +++ b/lib/l10n/lb.php @@ -5,12 +5,14 @@ $TRANSLATIONS = array( "Settings" => "Astellungen", "Users" => "Benotzer", "Admin" => "Admin", +"Unknown filetype" => "Onbekannten Fichier Typ", +"Invalid image" => "Ongülteg d'Bild", "web services under your control" => "Web-Servicer ënnert denger Kontroll", "Authentication error" => "Authentifikatioun's Fehler", "Files" => "Dateien", "Text" => "SMS", "seconds ago" => "Sekonnen hir", -"_%n minute ago_::_%n minutes ago_" => array("",""), +"_%n minute ago_::_%n minutes ago_" => array("","%n Minutten hir"), "_%n hour ago_::_%n hours ago_" => array("",""), "today" => "haut", "yesterday" => "gëschter", diff --git a/lib/private/l10n/lt_LT.php b/lib/l10n/lt_LT.php index db8d96c1018..25957702d2d 100644 --- a/lib/private/l10n/lt_LT.php +++ b/lib/l10n/lt_LT.php @@ -8,7 +8,6 @@ $TRANSLATIONS = array( "Users" => "Vartotojai", "Admin" => "Administravimas", "Failed to upgrade \"%s\"." => "Nepavyko pakelti „%s“ versijos.", -"Custom profile pictures don't work with encryption yet" => "Saviti profilio paveiksliukai dar neveikia su šifravimu", "Unknown filetype" => "Nežinomas failo tipas", "Invalid image" => "Netinkamas paveikslėlis", "web services under your control" => "jūsų valdomos web paslaugos", @@ -17,7 +16,7 @@ $TRANSLATIONS = array( "Files need to be downloaded one by one." => "Failai turi būti parsiunčiami vienas po kito.", "Back to Files" => "Atgal į Failus", "Selected files too large to generate zip file." => "Pasirinkti failai per dideli archyvavimui į ZIP.", -"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Atsisiųskite failus mažesnėmis dalimis atskirai, arba mandagiai prašykite savo administratoriaus.", +"Please download the files separately in smaller chunks or kindly ask your administrator." => "Prašome atsisiųsti failus mažesnėmis dalimis atskirai, arba mandagiai prašykite savo administratoriaus.", "No source specified when installing app" => "Nenurodytas šaltinis diegiant programą", "No href specified when installing app from http" => "Nenurodytas href diegiant programą iš http", "No path specified when installing app from local file" => "Nenurodytas kelias diegiant programą iš vietinio failo", @@ -56,6 +55,7 @@ $TRANSLATIONS = array( "Set an admin password." => "Nustatyti administratoriaus slaptažodį.", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Jūsų serveris nėra tvarkingai nustatytas leisti failų sinchronizaciją, nes WebDAV sąsaja panašu, kad yra sugadinta.", "Please double check the <a href='%s'>installation guides</a>." => "Prašome pažiūrėkite dar kartą <a href='%s'>diegimo instrukcijas</a>.", +"Could not find category \"%s\"" => "Nepavyko rasti kategorijos „%s“", "seconds ago" => "prieš sekundę", "_%n minute ago_::_%n minutes ago_" => array("prieš %n min.","Prieš % minutes","Prieš %n minučių"), "_%n hour ago_::_%n hours ago_" => array("Prieš %n valandą","Prieš %n valandas","Prieš %n valandų"), @@ -65,8 +65,6 @@ $TRANSLATIONS = array( "last month" => "praeitą mėnesį", "_%n month ago_::_%n months ago_" => array("Prieš %n mėnesį","Prieš %n mėnesius","Prieš %n mėnesių"), "last year" => "praeitais metais", -"years ago" => "prieš metus", -"Caused by:" => "Iššaukė:", -"Could not find category \"%s\"" => "Nepavyko rasti kategorijos „%s“" +"years ago" => "prieš metus" ); $PLURAL_FORMS = "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);"; diff --git a/lib/private/l10n/lv.php b/lib/l10n/lv.php index 4090a36edcc..8ecee5bdae8 100644 --- a/lib/private/l10n/lv.php +++ b/lib/l10n/lv.php @@ -12,7 +12,6 @@ $TRANSLATIONS = array( "Files need to be downloaded one by one." => "Datnes var lejupielādēt tikai katru atsevišķi.", "Back to Files" => "Atpakaļ pie datnēm", "Selected files too large to generate zip file." => "Izvēlētās datnes ir pārāk lielas, lai izveidotu zip datni.", -"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Lejupielādējiet savus failus mazākās daļās, atsevišķi vai palūdziet tos administratoram.", "Application is not enabled" => "Lietotne nav aktivēta", "Authentication error" => "Autentifikācijas kļūda", "Token expired. Please reload page." => "Pilnvarai ir beidzies termiņš. Lūdzu, pārlādējiet lapu.", @@ -39,6 +38,7 @@ $TRANSLATIONS = array( "Set an admin password." => "Iestatiet administratora paroli.", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Jūsu serveris vēl nav pareizi iestatīts, lai ļautu sinhronizēt datnes, jo izskatās, ka WebDAV saskarne ir salauzta.", "Please double check the <a href='%s'>installation guides</a>." => "Lūdzu, vēlreiz pārbaudiet <a href='%s'>instalēšanas palīdzību</a>.", +"Could not find category \"%s\"" => "Nevarēja atrast kategoriju “%s”", "seconds ago" => "sekundes atpakaļ", "_%n minute ago_::_%n minutes ago_" => array("","","Pirms %n minūtēm"), "_%n hour ago_::_%n hours ago_" => array("","","Pirms %n stundām"), @@ -48,8 +48,6 @@ $TRANSLATIONS = array( "last month" => "pagājušajā mēnesī", "_%n month ago_::_%n months ago_" => array("","","Pirms %n mēnešiem"), "last year" => "gājušajā gadā", -"years ago" => "gadus atpakaļ", -"Caused by:" => "Cēlonis:", -"Could not find category \"%s\"" => "Nevarēja atrast kategoriju “%s”" +"years ago" => "gadus atpakaļ" ); $PLURAL_FORMS = "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);"; diff --git a/lib/private/l10n/mk.php b/lib/l10n/mk.php index 69d4a1cb694..deaf1bc8d05 100644 --- a/lib/private/l10n/mk.php +++ b/lib/l10n/mk.php @@ -5,6 +5,8 @@ $TRANSLATIONS = array( "Settings" => "Подесувања", "Users" => "Корисници", "Admin" => "Админ", +"Unknown filetype" => "Непознат тип на датотека", +"Invalid image" => "Невалидна фотографија", "web services under your control" => "веб сервиси под Ваша контрола", "ZIP download is turned off." => "Преземање во ZIP е исклучено", "Files need to be downloaded one by one." => "Датотеките треба да се симнат една по една.", @@ -16,6 +18,7 @@ $TRANSLATIONS = array( "Files" => "Датотеки", "Text" => "Текст", "Images" => "Слики", +"Could not find category \"%s\"" => "Не можам да најдам категорија „%s“", "seconds ago" => "пред секунди", "_%n minute ago_::_%n minutes ago_" => array("",""), "_%n hour ago_::_%n hours ago_" => array("",""), @@ -25,7 +28,6 @@ $TRANSLATIONS = array( "last month" => "минатиот месец", "_%n month ago_::_%n months ago_" => array("",""), "last year" => "минатата година", -"years ago" => "пред години", -"Could not find category \"%s\"" => "Не можам да најдам категорија „%s“" +"years ago" => "пред години" ); $PLURAL_FORMS = "nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;"; diff --git a/lib/private/l10n/ne.php b/lib/l10n/ml_IN.php index 15f78e0bce6..15f78e0bce6 100644 --- a/lib/private/l10n/ne.php +++ b/lib/l10n/ml_IN.php diff --git a/lib/private/l10n/ms_MY.php b/lib/l10n/ms_MY.php index 17ef07f83dd..17ef07f83dd 100644 --- a/lib/private/l10n/ms_MY.php +++ b/lib/l10n/ms_MY.php diff --git a/lib/private/l10n/my_MM.php b/lib/l10n/my_MM.php index 5f4b6ddc820..7fdf0d0285d 100644 --- a/lib/private/l10n/my_MM.php +++ b/lib/l10n/my_MM.php @@ -12,6 +12,7 @@ $TRANSLATIONS = array( "Files" => "ဖိုင်များ", "Text" => "စာသား", "Images" => "ပုံရိပ်များ", +"Could not find category \"%s\"" => "\"%s\"ခေါင်းစဉ်ကို ရှာမတွေ့ပါ", "seconds ago" => "စက္ကန့်အနည်းငယ်က", "_%n minute ago_::_%n minutes ago_" => array(""), "_%n hour ago_::_%n hours ago_" => array(""), @@ -21,7 +22,6 @@ $TRANSLATIONS = array( "last month" => "ပြီးခဲ့သောလ", "_%n month ago_::_%n months ago_" => array(""), "last year" => "မနှစ်က", -"years ago" => "နှစ် အရင်က", -"Could not find category \"%s\"" => "\"%s\"ခေါင်းစဉ်ကို ရှာမတွေ့ပါ" +"years ago" => "နှစ် အရင်က" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/lib/private/l10n/nb_NO.php b/lib/l10n/nb_NO.php index 8e7d095d369..5da36f9be37 100644 --- a/lib/private/l10n/nb_NO.php +++ b/lib/l10n/nb_NO.php @@ -5,6 +5,8 @@ $TRANSLATIONS = array( "Settings" => "Innstillinger", "Users" => "Brukere", "Admin" => "Admin", +"Unknown filetype" => "Ukjent filtype", +"Invalid image" => "Ugyldig bilde", "web services under your control" => "web tjenester du kontrollerer", "ZIP download is turned off." => "ZIP-nedlasting av avslått", "Files need to be downloaded one by one." => "Filene må lastes ned en om gangen", @@ -18,16 +20,16 @@ $TRANSLATIONS = array( "Images" => "Bilder", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Din nettservev er ikke konfigurert korrekt for filsynkronisering. WebDAV ser ut til å ikke funkere.", "Please double check the <a href='%s'>installation guides</a>." => "Vennligst dobbelsjekk <a href='%s'>installasjonsguiden</a>.", +"Could not find category \"%s\"" => "Kunne ikke finne kategori \"%s\"", "seconds ago" => "sekunder siden", -"_%n minute ago_::_%n minutes ago_" => array("",""), -"_%n hour ago_::_%n hours ago_" => array("",""), +"_%n minute ago_::_%n minutes ago_" => array("","%n minutter siden"), +"_%n hour ago_::_%n hours ago_" => array("","%n timer siden"), "today" => "i dag", "yesterday" => "i går", -"_%n day go_::_%n days ago_" => array("",""), +"_%n day go_::_%n days ago_" => array("","%n dager siden"), "last month" => "forrige måned", -"_%n month ago_::_%n months ago_" => array("",""), +"_%n month ago_::_%n months ago_" => array("","%n dager siden"), "last year" => "forrige år", -"years ago" => "år siden", -"Could not find category \"%s\"" => "Kunne ikke finne kategori \"%s\"" +"years ago" => "år siden" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/private/l10n/sw_KE.php b/lib/l10n/nds.php index 15f78e0bce6..15f78e0bce6 100644 --- a/lib/private/l10n/sw_KE.php +++ b/lib/l10n/nds.php diff --git a/lib/l10n/ne.php b/lib/l10n/ne.php new file mode 100644 index 00000000000..15f78e0bce6 --- /dev/null +++ b/lib/l10n/ne.php @@ -0,0 +1,8 @@ +<?php +$TRANSLATIONS = array( +"_%n minute ago_::_%n minutes ago_" => array("",""), +"_%n hour ago_::_%n hours ago_" => array("",""), +"_%n day go_::_%n days ago_" => array("",""), +"_%n month ago_::_%n months ago_" => array("","") +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/private/l10n/nl.php b/lib/l10n/nl.php index 20374f1f0f8..2f6205fcf1c 100644 --- a/lib/private/l10n/nl.php +++ b/lib/l10n/nl.php @@ -8,7 +8,6 @@ $TRANSLATIONS = array( "Users" => "Gebruikers", "Admin" => "Beheerder", "Failed to upgrade \"%s\"." => "Upgrade \"%s\" mislukt.", -"Custom profile pictures don't work with encryption yet" => "Maatwerk profielafbeelding werkt nog niet met versleuteling", "Unknown filetype" => "Onbekend bestandsformaat", "Invalid image" => "Ongeldige afbeelding", "web services under your control" => "Webdiensten in eigen beheer", @@ -17,7 +16,7 @@ $TRANSLATIONS = array( "Files need to be downloaded one by one." => "Bestanden moeten één voor één worden gedownload.", "Back to Files" => "Terug naar bestanden", "Selected files too large to generate zip file." => "De geselecteerde bestanden zijn te groot om een zip bestand te maken.", -"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Download de bestanden in kleinere brokken, appart of vraag uw administrator.", +"Please download the files separately in smaller chunks or kindly ask your administrator." => "Download de bestanden afzonderlijk in kleinere porties of vraag het uw beheerder,", "No source specified when installing app" => "Geen bron opgegeven bij installatie van de app", "No href specified when installing app from http" => "Geen href opgegeven bij installeren van de app vanaf http", "No path specified when installing app from local file" => "Geen pad opgegeven bij installeren van de app vanaf een lokaal bestand", @@ -56,6 +55,7 @@ $TRANSLATIONS = array( "Set an admin password." => "Stel een beheerderswachtwoord in.", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Uw webserver is nog niet goed ingesteld voor bestandssynchronisatie omdat de WebDAV interface verbroken lijkt.", "Please double check the <a href='%s'>installation guides</a>." => "Controleer de <a href='%s'>installatiehandleiding</a> goed.", +"Could not find category \"%s\"" => "Kon categorie \"%s\" niet vinden", "seconds ago" => "seconden geleden", "_%n minute ago_::_%n minutes ago_" => array("%n minuut geleden","%n minuten geleden"), "_%n hour ago_::_%n hours ago_" => array("%n uur geleden","%n uur geleden"), @@ -65,8 +65,6 @@ $TRANSLATIONS = array( "last month" => "vorige maand", "_%n month ago_::_%n months ago_" => array("%n maand geleden","%n maanden geleden"), "last year" => "vorig jaar", -"years ago" => "jaar geleden", -"Caused by:" => "Gekomen door:", -"Could not find category \"%s\"" => "Kon categorie \"%s\" niet vinden" +"years ago" => "jaar geleden" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/private/l10n/nn_NO.php b/lib/l10n/nn_NO.php index e8bf8dfdef4..e8bf8dfdef4 100644 --- a/lib/private/l10n/nn_NO.php +++ b/lib/l10n/nn_NO.php diff --git a/lib/l10n/nqo.php b/lib/l10n/nqo.php new file mode 100644 index 00000000000..e7b09649a24 --- /dev/null +++ b/lib/l10n/nqo.php @@ -0,0 +1,8 @@ +<?php +$TRANSLATIONS = array( +"_%n minute ago_::_%n minutes ago_" => array(""), +"_%n hour ago_::_%n hours ago_" => array(""), +"_%n day go_::_%n days ago_" => array(""), +"_%n month ago_::_%n months ago_" => array("") +); +$PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/lib/private/l10n/oc.php b/lib/l10n/oc.php index 40a527cc76c..40a527cc76c 100644 --- a/lib/private/l10n/oc.php +++ b/lib/l10n/oc.php diff --git a/lib/private/l10n/pa.php b/lib/l10n/pa.php index 069fea6e710..069fea6e710 100644 --- a/lib/private/l10n/pa.php +++ b/lib/l10n/pa.php diff --git a/lib/private/l10n/pl.php b/lib/l10n/pl.php index 270559b4e50..fe3e876916a 100644 --- a/lib/private/l10n/pl.php +++ b/lib/l10n/pl.php @@ -8,7 +8,6 @@ $TRANSLATIONS = array( "Users" => "Użytkownicy", "Admin" => "Administrator", "Failed to upgrade \"%s\"." => "Błąd przy aktualizacji \"%s\".", -"Custom profile pictures don't work with encryption yet" => "Domyślny profil zdjęć nie działa z szyfrowaniem jeszcze", "Unknown filetype" => "Nieznany typ pliku", "Invalid image" => "Błędne zdjęcie", "web services under your control" => "Kontrolowane serwisy", @@ -17,7 +16,7 @@ $TRANSLATIONS = array( "Files need to be downloaded one by one." => "Pliki muszą zostać pobrane pojedynczo.", "Back to Files" => "Wróć do plików", "Selected files too large to generate zip file." => "Wybrane pliki są zbyt duże, aby wygenerować plik zip.", -"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Pobierz pliki w mniejszy kawałkach, oddzielnie lub poproś administratora o zwiększenie limitu.", +"Please download the files separately in smaller chunks or kindly ask your administrator." => "Proszę ściągać pliki osobno w mniejszych paczkach lub poprosić administratora.", "No source specified when installing app" => "Nie określono źródła podczas instalacji aplikacji", "No href specified when installing app from http" => "Nie określono linku skąd aplikacja ma być zainstalowana", "No path specified when installing app from local file" => "Nie określono lokalnego pliku z którego miała być instalowana aplikacja", @@ -66,7 +65,6 @@ $TRANSLATIONS = array( "last month" => "w zeszłym miesiącu", "_%n month ago_::_%n months ago_" => array("%n miesiąc temu","%n miesięcy temu","%n miesięcy temu"), "last year" => "w zeszłym roku", -"years ago" => "lat temu", -"Caused by:" => "Spowodowane przez:" +"years ago" => "lat temu" ); $PLURAL_FORMS = "nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"; diff --git a/lib/private/l10n/pl_PL.php b/lib/l10n/pl_PL.php index 5494e3dab25..5494e3dab25 100644 --- a/lib/private/l10n/pl_PL.php +++ b/lib/l10n/pl_PL.php diff --git a/lib/private/l10n/pt_BR.php b/lib/l10n/pt_BR.php index 7a580799701..cc20fb3cb02 100644 --- a/lib/private/l10n/pt_BR.php +++ b/lib/l10n/pt_BR.php @@ -8,7 +8,6 @@ $TRANSLATIONS = array( "Users" => "Usuários", "Admin" => "Admin", "Failed to upgrade \"%s\"." => "Falha na atualização de \"%s\".", -"Custom profile pictures don't work with encryption yet" => "Fotos de perfil personalizados ainda não funcionam com criptografia", "Unknown filetype" => "Tipo de arquivo desconhecido", "Invalid image" => "Imagem inválida", "web services under your control" => "serviços web sob seu controle", @@ -17,7 +16,7 @@ $TRANSLATIONS = array( "Files need to be downloaded one by one." => "Arquivos precisam ser baixados um de cada vez.", "Back to Files" => "Voltar para Arquivos", "Selected files too large to generate zip file." => "Arquivos selecionados são muito grandes para gerar arquivo zip.", -"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Baixe os arquivos em pedaços menores, separadamente ou solicite educadamente ao seu administrador.", +"Please download the files separately in smaller chunks or kindly ask your administrator." => "Por favor baixe os arquivos separadamente em pedaços ou educadamente pergunte ao seu administrador.", "No source specified when installing app" => "Nenhuma fonte foi especificada enquanto instalava o aplicativo", "No href specified when installing app from http" => "Nenhuma href foi especificada enquanto instalava o aplicativo de httml", "No path specified when installing app from local file" => "Nenhum caminho foi especificado enquanto instalava o aplicativo do arquivo local", @@ -56,6 +55,7 @@ $TRANSLATIONS = array( "Set an admin password." => "Defina uma senha de administrador.", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Seu servidor web não está configurado corretamente para permitir sincronização de arquivos porque a interface WebDAV parece estar quebrada.", "Please double check the <a href='%s'>installation guides</a>." => "Por favor, confira os <a href='%s'>guias de instalação</a>.", +"Could not find category \"%s\"" => "Impossível localizar categoria \"%s\"", "seconds ago" => "segundos atrás", "_%n minute ago_::_%n minutes ago_" => array("","ha %n minutos"), "_%n hour ago_::_%n hours ago_" => array("","ha %n horas"), @@ -65,8 +65,6 @@ $TRANSLATIONS = array( "last month" => "último mês", "_%n month ago_::_%n months ago_" => array("","ha %n meses"), "last year" => "último ano", -"years ago" => "anos atrás", -"Caused by:" => "Causados por:", -"Could not find category \"%s\"" => "Impossível localizar categoria \"%s\"" +"years ago" => "anos atrás" ); $PLURAL_FORMS = "nplurals=2; plural=(n > 1);"; diff --git a/lib/private/l10n/pt_PT.php b/lib/l10n/pt_PT.php index 6e2bcba7b10..bd9165ebb1a 100644 --- a/lib/private/l10n/pt_PT.php +++ b/lib/l10n/pt_PT.php @@ -1,5 +1,7 @@ <?php $TRANSLATIONS = array( +"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "A aplicação \"%s\" não pode ser instaladas por não ser compatível com esta versão da ownCloud.", +"No app name specified" => "O nome da aplicação não foi especificado", "Help" => "Ajuda", "Personal" => "Pessoal", "Settings" => "Configurações", @@ -14,7 +16,19 @@ $TRANSLATIONS = array( "Files need to be downloaded one by one." => "Os ficheiros precisam de ser descarregados um por um.", "Back to Files" => "Voltar a Ficheiros", "Selected files too large to generate zip file." => "Os ficheiros seleccionados são grandes demais para gerar um ficheiro zip.", -"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Descarregue os ficheiros em partes menores, separados ou peça gentilmente ao seu administrador.", +"Please download the files separately in smaller chunks or kindly ask your administrator." => "Por favor descarregue os ficheiros divididos em partes mais pequenas ou peça ajuda ao seu administrador.", +"No source specified when installing app" => "Não foi especificada uma fonte de instalação desta aplicação", +"No href specified when installing app from http" => "Não foi especificada uma href http para instalar esta aplicação", +"No path specified when installing app from local file" => "Não foi especificado o caminho de instalação desta aplicação", +"Archives of type %s are not supported" => "Arquivos do tipo %s não são suportados", +"Failed to open archive when installing app" => "Ocorreu um erro ao abrir o ficheiro de instalação desta aplicação", +"App does not provide an info.xml file" => "A aplicação não disponibiliza um ficheiro info.xml", +"App can't be installed because of not allowed code in the App" => "A aplicação não pode ser instalado devido a código não permitido dentro da aplicação", +"App can't be installed because it is not compatible with this version of ownCloud" => "A aplicação não pode ser instalada por não ser compatível com esta versão do ownCloud", +"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "Esta aplicação não pode ser instalada por que contém o tag <shipped>true</shipped> que só é permitido para aplicações nativas", +"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "Esta aplicação não pode ser instalada porque a versão no info.xml/version não coincide com a reportada na loja de aplicações", +"App directory already exists" => "A directoria da aplicação já existe", +"Can't create app folder. Please fix permissions. %s" => "Não foi possível criar a pasta da aplicação. Por favor verifique as permissões. %s", "Application is not enabled" => "A aplicação não está activada", "Authentication error" => "Erro na autenticação", "Token expired. Please reload page." => "O token expirou. Por favor recarregue a página.", @@ -41,6 +55,7 @@ $TRANSLATIONS = array( "Set an admin password." => "Definiar uma password de administrador", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "O seu servidor web não está configurado correctamente para autorizar sincronização de ficheiros, pois o interface WebDAV parece estar com problemas.", "Please double check the <a href='%s'>installation guides</a>." => "Por favor verifique <a href='%s'>installation guides</a>.", +"Could not find category \"%s\"" => "Não foi encontrado a categoria \"%s\"", "seconds ago" => "Minutos atrás", "_%n minute ago_::_%n minutes ago_" => array("","%n minutos atrás"), "_%n hour ago_::_%n hours ago_" => array("","%n horas atrás"), @@ -50,8 +65,6 @@ $TRANSLATIONS = array( "last month" => "ultímo mês", "_%n month ago_::_%n months ago_" => array("","%n meses atrás"), "last year" => "ano passado", -"years ago" => "anos atrás", -"Caused by:" => "Causado por:", -"Could not find category \"%s\"" => "Não foi encontrado a categoria \"%s\"" +"years ago" => "anos atrás" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/private/l10n/ro.php b/lib/l10n/ro.php index 76dafcd03e0..94ff7a4326a 100644 --- a/lib/private/l10n/ro.php +++ b/lib/l10n/ro.php @@ -20,6 +20,7 @@ $TRANSLATIONS = array( "Images" => "Imagini", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Serverul de web nu este încă setat corespunzător pentru a permite sincronizarea fișierelor deoarece interfața WebDAV pare a fi întreruptă.", "Please double check the <a href='%s'>installation guides</a>." => "Vă rugăm să verificați <a href='%s'>ghiduri de instalare</a>.", +"Could not find category \"%s\"" => "Cloud nu a gasit categoria \"%s\"", "seconds ago" => "secunde în urmă", "_%n minute ago_::_%n minutes ago_" => array("","","acum %n minute"), "_%n hour ago_::_%n hours ago_" => array("","","acum %n ore"), @@ -29,7 +30,6 @@ $TRANSLATIONS = array( "last month" => "ultima lună", "_%n month ago_::_%n months ago_" => array("","",""), "last year" => "ultimul an", -"years ago" => "ani în urmă", -"Could not find category \"%s\"" => "Cloud nu a gasit categoria \"%s\"" +"years ago" => "ani în urmă" ); $PLURAL_FORMS = "nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));"; diff --git a/lib/private/l10n/ru.php b/lib/l10n/ru.php index 501065f8b5f..34d1730aaf2 100644 --- a/lib/private/l10n/ru.php +++ b/lib/l10n/ru.php @@ -8,7 +8,6 @@ $TRANSLATIONS = array( "Users" => "Пользователи", "Admin" => "Admin", "Failed to upgrade \"%s\"." => "Не смог обновить \"%s\".", -"Custom profile pictures don't work with encryption yet" => "Пользовательские картинки профиля ещё не поддерживают шифрование", "Unknown filetype" => "Неизвестный тип файла", "Invalid image" => "Изображение повреждено", "web services under your control" => "веб-сервисы под вашим управлением", @@ -17,7 +16,7 @@ $TRANSLATIONS = array( "Files need to be downloaded one by one." => "Файлы должны быть загружены по одному.", "Back to Files" => "Назад к файлам", "Selected files too large to generate zip file." => "Выбранные файлы слишком велики, чтобы создать zip файл.", -"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Загрузите файл маленьшими порциями, раздельно или вежливо попросите Вашего администратора.", +"Please download the files separately in smaller chunks or kindly ask your administrator." => "Загрузите файлы раздельно маленькими частями или вежливо попросите вашего администратора.", "No source specified when installing app" => "Не указан источник при установке приложения", "No href specified when installing app from http" => "Не указан атрибут href при установке приложения через http", "No path specified when installing app from local file" => "Не указан путь при установке приложения из локального файла", @@ -56,6 +55,7 @@ $TRANSLATIONS = array( "Set an admin password." => "становит пароль для admin.", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Ваш веб сервер до сих пор не настроен правильно для возможности синхронизации файлов, похоже что проблема в неисправности интерфейса WebDAV.", "Please double check the <a href='%s'>installation guides</a>." => "Пожалуйста, дважды просмотрите <a href='%s'>инструкции по установке</a>.", +"Could not find category \"%s\"" => "Категория \"%s\" не найдена", "seconds ago" => "несколько секунд назад", "_%n minute ago_::_%n minutes ago_" => array("%n минута назад","%n минуты назад","%n минут назад"), "_%n hour ago_::_%n hours ago_" => array("%n час назад","%n часа назад","%n часов назад"), @@ -65,8 +65,6 @@ $TRANSLATIONS = array( "last month" => "в прошлом месяце", "_%n month ago_::_%n months ago_" => array("%n месяц назад","%n месяца назад","%n месяцев назад"), "last year" => "в прошлом году", -"years ago" => "несколько лет назад", -"Caused by:" => "Вызвано:", -"Could not find category \"%s\"" => "Категория \"%s\" не найдена" +"years ago" => "несколько лет назад" ); $PLURAL_FORMS = "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"; diff --git a/lib/private/l10n/si_LK.php b/lib/l10n/si_LK.php index d10804cae69..d10804cae69 100644 --- a/lib/private/l10n/si_LK.php +++ b/lib/l10n/si_LK.php diff --git a/lib/private/l10n/sk.php b/lib/l10n/sk.php index 54812b15a6f..5cfafe6ca0c 100644 --- a/lib/private/l10n/sk.php +++ b/lib/l10n/sk.php @@ -1,5 +1,7 @@ <?php $TRANSLATIONS = array( +"Personal" => "Osobné", +"Settings" => "Nastavenia", "_%n minute ago_::_%n minutes ago_" => array("","",""), "_%n hour ago_::_%n hours ago_" => array("","",""), "_%n day go_::_%n days ago_" => array("","",""), diff --git a/lib/private/l10n/sk_SK.php b/lib/l10n/sk_SK.php index 13487b039d6..59c45e2b0bc 100644 --- a/lib/private/l10n/sk_SK.php +++ b/lib/l10n/sk_SK.php @@ -1,6 +1,6 @@ <?php $TRANSLATIONS = array( -"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "Aplikácia \"%s\" nemôže byť nainštalovaná kvôli nekompatibilite z danou verziou ownCloudu.", +"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "Aplikácia \"%s\" nemôže byť nainštalovaná kvôli nekompatibilite z touto verziou ownCloudu.", "No app name specified" => "Nešpecifikované meno aplikácie", "Help" => "Pomoc", "Personal" => "Osobné", @@ -8,24 +8,26 @@ $TRANSLATIONS = array( "Users" => "Používatelia", "Admin" => "Administrátor", "Failed to upgrade \"%s\"." => "Zlyhala aktualizácia \"%s\".", +"Unknown filetype" => "Neznámy typ súboru", +"Invalid image" => "Chybný obrázok", "web services under your control" => "webové služby pod Vašou kontrolou", "cannot open \"%s\"" => "nemožno otvoriť \"%s\"", "ZIP download is turned off." => "Sťahovanie súborov ZIP je vypnuté.", "Files need to be downloaded one by one." => "Súbory musia byť nahrávané jeden za druhým.", "Back to Files" => "Späť na súbory", "Selected files too large to generate zip file." => "Zvolené súbory sú príliš veľké na vygenerovanie zip súboru.", -"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Stiahnite súbory po menších častiach, samostatne, alebo sa obráťte na správcu.", +"Please download the files separately in smaller chunks or kindly ask your administrator." => "Prosím, stiahnite si súbory samostatne v menších blokoch alebo sa obráťte na správcu.", "No source specified when installing app" => "Nešpecifikovaný zdroj pri inštalácii aplikácie", "No href specified when installing app from http" => "Nešpecifikovaný atribút \"href\" pri inštalácii aplikácie pomocou protokolu \"http\"", "No path specified when installing app from local file" => "Nešpecifikovaná cesta pri inštalácii aplikácie z lokálneho súboru", -"Archives of type %s are not supported" => "Typ archívu %s nie je podporovaný", +"Archives of type %s are not supported" => "Tento typ archívu %s nie je podporovaný", "Failed to open archive when installing app" => "Zlyhanie pri otváraní archívu počas inštalácie aplikácie", "App does not provide an info.xml file" => "Aplikácia neposkytuje súbor info.xml", -"App can't be installed because of not allowed code in the App" => "Aplikácia nemôže byť inštalovaná pre nepovolený kód v aplikácii", -"App can't be installed because it is not compatible with this version of ownCloud" => "Aplikácia nemôže byť inštalovaná pre nekompatibilitu z danou verziou ownCloudu", -"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "Aplikácia nemôže byť inštalovaná pretože obsahuje <shipped>pravý</shipped> štítok, ktorý nie je povolený pre zaslané \"shipped\" aplikácie", -"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "Aplikácia nemôže byť inštalovaná pretože verzia v info.xml/version nezodpovedá verzii špecifikovanej v aplikačnom obchode", -"App directory already exists" => "Aplikačný adresár už existuje", +"App can't be installed because of not allowed code in the App" => "Aplikácia nemôže byť nainštalovaná pre nepovolený kód v aplikácii", +"App can't be installed because it is not compatible with this version of ownCloud" => "Aplikácia nemôže byť nainštalovaná pre nekompatibilitu z touto verziou ownCloudu", +"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "Aplikácia nemôže byť nainštalovaná pretože obsahuje <shipped>pravý</shipped> štítok, ktorý nie je povolený pre zaslané \"shipped\" aplikácie", +"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "Aplikácia nemôže byť nainštalovaná pretože verzia v info.xml/version nezodpovedá verzii špecifikovanej v obchode s aplikáciami", +"App directory already exists" => "Aplikačný priečinok už existuje", "Can't create app folder. Please fix permissions. %s" => "Nemožno vytvoriť aplikačný priečinok. Prosím upravte povolenia. %s", "Application is not enabled" => "Aplikácia nie je zapnutá", "Authentication error" => "Chyba autentifikácie", @@ -33,7 +35,7 @@ $TRANSLATIONS = array( "Files" => "Súbory", "Text" => "Text", "Images" => "Obrázky", -"%s enter the database username." => "Zadajte používateľské meno %s databázy..", +"%s enter the database username." => "Zadajte používateľské meno %s databázy.", "%s enter the database name." => "Zadajte názov databázy pre %s databázy.", "%s you may not use dots in the database name" => "V názve databázy %s nemôžete používať bodky", "MS SQL username and/or password not valid: %s" => "Používateľské meno, alebo heslo MS SQL nie je platné: %s", @@ -53,17 +55,16 @@ $TRANSLATIONS = array( "Set an admin password." => "Zadajte heslo administrátora.", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Váš webový server nie je správne nastavený na synchronizáciu, pretože rozhranie WebDAV je poškodené.", "Please double check the <a href='%s'>installation guides</a>." => "Prosím skontrolujte <a href='%s'>inštalačnú príručku</a>.", +"Could not find category \"%s\"" => "Nemožno nájsť danú kategóriu \"%s\"", "seconds ago" => "pred sekundami", -"_%n minute ago_::_%n minutes ago_" => array("","","pred %n minútami"), -"_%n hour ago_::_%n hours ago_" => array("","","pred %n hodinami"), +"_%n minute ago_::_%n minutes ago_" => array("pred %n minútou","pred %n minútami","pred %n minútami"), +"_%n hour ago_::_%n hours ago_" => array("pred %n hodinou","pred %n hodinami","pred %n hodinami"), "today" => "dnes", "yesterday" => "včera", -"_%n day go_::_%n days ago_" => array("","","pred %n dňami"), +"_%n day go_::_%n days ago_" => array("pred %n dňom","pred %n dňami","pred %n dňami"), "last month" => "minulý mesiac", -"_%n month ago_::_%n months ago_" => array("","","pred %n mesiacmi"), +"_%n month ago_::_%n months ago_" => array("pred %n mesiacom","pred %n mesiacmi","pred %n mesiacmi"), "last year" => "minulý rok", -"years ago" => "pred rokmi", -"Caused by:" => "Príčina:", -"Could not find category \"%s\"" => "Nemožno nájsť danú kategóriu \"%s\"" +"years ago" => "pred rokmi" ); $PLURAL_FORMS = "nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;"; diff --git a/lib/l10n/sl.php b/lib/l10n/sl.php new file mode 100644 index 00000000000..3cc8dd130c8 --- /dev/null +++ b/lib/l10n/sl.php @@ -0,0 +1,70 @@ +<?php +$TRANSLATIONS = array( +"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "Programa \"%s\" ni mogoče namestiti, ker ni skladen s trenutno nameščeno različico oblaka ownCloud.", +"No app name specified" => "Ni podanega imena programa", +"Help" => "Pomoč", +"Personal" => "Osebno", +"Settings" => "Nastavitve", +"Users" => "Uporabniki", +"Admin" => "Skrbništvo", +"Failed to upgrade \"%s\"." => "Posodabljanje \"%s\" je spodletelo.", +"Unknown filetype" => "Neznana vrsta datoteke", +"Invalid image" => "Neveljavna slika", +"web services under your control" => "spletne storitve pod vašim nadzorom", +"cannot open \"%s\"" => "ni mogoče odpreti \"%s\"", +"ZIP download is turned off." => "Prejemanje datotek v paketu ZIP je onemogočeno.", +"Files need to be downloaded one by one." => "Datoteke je mogoče prejeti le posamično.", +"Back to Files" => "Nazaj na datoteke", +"Selected files too large to generate zip file." => "Izbrane datoteke so prevelike za ustvarjanje datoteke arhiva zip.", +"Please download the files separately in smaller chunks or kindly ask your administrator." => "Datoteke je treba prejeti ločeno v manjših paketih, ali pa je treba za pomoč prositi skrbnika.", +"No source specified when installing app" => "Ni podanega vira med nameščenjem programa", +"No href specified when installing app from http" => "Ni podanega podatka naslova HREF med nameščenjem programa preko protokola HTTP.", +"No path specified when installing app from local file" => "Ni podane poti med nameščenjem programa iz krajevne datoteke", +"Archives of type %s are not supported" => "Arhivi vrste %s niso podprti", +"Failed to open archive when installing app" => "Odpiranje arhiva je med nameščanjem spodletelo", +"App does not provide an info.xml file" => "Program je brez datoteke info.xml", +"App can't be installed because of not allowed code in the App" => "Programa ni mogoče namestiti zaradi nedovoljene programske kode.", +"App can't be installed because it is not compatible with this version of ownCloud" => "Programa ni mogoče namestiti, ker ni skladen z trenutno nameščeno različico oblaka ownCloud.", +"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "Programa ni mogoče namestiti, ker vsebuje oznako <shipped>potrditve</shipped>, ki pa ni dovoljena za javne programe.", +"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "Program ni mogoče namestiti zaradi neustrezne različice datoteke info.xml. Ta ni enaka različici programa.", +"App directory already exists" => "Programska mapa že obstaja", +"Can't create app folder. Please fix permissions. %s" => "Programske mape ni mogoče ustvariti. Ni ustreznih dovoljenj. %s", +"Application is not enabled" => "Program ni omogočen", +"Authentication error" => "Napaka overjanja", +"Token expired. Please reload page." => "Žeton je potekel. Stran je treba ponovno naložiti.", +"Files" => "Datoteke", +"Text" => "Besedilo", +"Images" => "Slike", +"%s enter the database username." => "%s - vnos uporabniškega imena podatkovne zbirke.", +"%s enter the database name." => "%s - vnos imena podatkovne zbirke.", +"%s you may not use dots in the database name" => "%s - v imenu podatkovne zbirke ni dovoljeno uporabljati pik.", +"MS SQL username and/or password not valid: %s" => "Uporabniško ime ali geslo MS SQL ni veljavno: %s", +"You need to enter either an existing account or the administrator." => "Prijaviti se je treba v obstoječi ali pa skrbniški račun.", +"MySQL username and/or password not valid" => "Uporabniško ime ali geslo MySQL ni veljavno", +"DB Error: \"%s\"" => "Napaka podatkovne zbirke: \"%s\"", +"Offending command was: \"%s\"" => "Napačni ukaz je: \"%s\"", +"MySQL user '%s'@'localhost' exists already." => "Uporabnik MySQL '%s'@'localhost' že obstaja.", +"Drop this user from MySQL" => "Odstrani uporabnika iz podatkovne zbirke MySQL", +"MySQL user '%s'@'%%' already exists" => "Uporabnik MySQL '%s'@'%%' že obstaja.", +"Drop this user from MySQL." => "Odstrani uporabnika iz podatkovne zbirke MySQL", +"Oracle connection could not be established" => "Povezave s sistemom Oracle ni mogoče vzpostaviti.", +"Oracle username and/or password not valid" => "Uporabniško ime ali geslo Oracle ni veljavno", +"Offending command was: \"%s\", name: %s, password: %s" => "Napačni ukaz je: \"%s\", ime: %s, geslo: %s", +"PostgreSQL username and/or password not valid" => "Uporabniško ime ali geslo PostgreSQL ni veljavno", +"Set an admin username." => "Nastavi uporabniško ime skrbnika.", +"Set an admin password." => "Nastavi geslo skrbnika.", +"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Spletni stražnik še ni ustrezno nastavljen in ne omogoča usklajevanja, saj je nastavitev WebDAV okvarjena.", +"Please double check the <a href='%s'>installation guides</a>." => "Preverite <a href='%s'>navodila namestitve</a>.", +"Could not find category \"%s\"" => "Kategorije \"%s\" ni mogoče najti.", +"seconds ago" => "pred nekaj sekundami", +"_%n minute ago_::_%n minutes ago_" => array("pred %n minuto","pred %n minutama","pred %n minutami","pred %n minutami"), +"_%n hour ago_::_%n hours ago_" => array("pred %n uro","pred %n urama","pred %n urami","pred %n urami"), +"today" => "danes", +"yesterday" => "včeraj", +"_%n day go_::_%n days ago_" => array("pred %n dnevom","pred %n dnevoma","pred %n dnevi","pred %n dnevi"), +"last month" => "zadnji mesec", +"_%n month ago_::_%n months ago_" => array("pred %n mesecem","pred %n mesecema","pred %n meseci","pred %n meseci"), +"last year" => "lansko leto", +"years ago" => "let nazaj" +); +$PLURAL_FORMS = "nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);"; diff --git a/lib/private/l10n/sq.php b/lib/l10n/sq.php index edaa1df2b86..b36aa4ceefc 100644 --- a/lib/private/l10n/sq.php +++ b/lib/l10n/sq.php @@ -35,6 +35,7 @@ $TRANSLATIONS = array( "Set an admin password." => "Cakto kodin e administratorit.", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Serveri web i juaji nuk është konfiguruar akoma për të lejuar sinkronizimin e skedarëve sepse ndërfaqja WebDAV mund të jetë e dëmtuar.", "Please double check the <a href='%s'>installation guides</a>." => "Ju lutemi kontrolloni mirë <a href='%s'>shoqëruesin e instalimit</a>.", +"Could not find category \"%s\"" => "Kategoria \"%s\" nuk u gjet", "seconds ago" => "sekonda më parë", "_%n minute ago_::_%n minutes ago_" => array("","%n minuta më parë"), "_%n hour ago_::_%n hours ago_" => array("","%n orë më parë"), @@ -44,7 +45,6 @@ $TRANSLATIONS = array( "last month" => "muajin e shkuar", "_%n month ago_::_%n months ago_" => array("","%n muaj më parë"), "last year" => "vitin e shkuar", -"years ago" => "vite më parë", -"Could not find category \"%s\"" => "Kategoria \"%s\" nuk u gjet" +"years ago" => "vite më parë" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/private/l10n/sr.php b/lib/l10n/sr.php index 9441d0578fc..47a84803683 100644 --- a/lib/private/l10n/sr.php +++ b/lib/l10n/sr.php @@ -18,6 +18,7 @@ $TRANSLATIONS = array( "Images" => "Слике", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Ваш веб сервер тренутно не подржава синхронизацију датотека јер се чини да је WebDAV сучеље неисправно.", "Please double check the <a href='%s'>installation guides</a>." => "Погледајте <a href='%s'>водиче за инсталацију</a>.", +"Could not find category \"%s\"" => "Не могу да пронађем категорију „%s“.", "seconds ago" => "пре неколико секунди", "_%n minute ago_::_%n minutes ago_" => array("","",""), "_%n hour ago_::_%n hours ago_" => array("","",""), @@ -27,7 +28,6 @@ $TRANSLATIONS = array( "last month" => "прошлог месеца", "_%n month ago_::_%n months ago_" => array("","",""), "last year" => "прошле године", -"years ago" => "година раније", -"Could not find category \"%s\"" => "Не могу да пронађем категорију „%s“." +"years ago" => "година раније" ); $PLURAL_FORMS = "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"; diff --git a/lib/private/l10n/sr@latin.php b/lib/l10n/sr@latin.php index d8fa9289221..d8fa9289221 100644 --- a/lib/private/l10n/sr@latin.php +++ b/lib/l10n/sr@latin.php diff --git a/lib/private/l10n/sv.php b/lib/l10n/sv.php index e7c3420a85b..ffffe5956f1 100644 --- a/lib/private/l10n/sv.php +++ b/lib/l10n/sv.php @@ -8,13 +8,15 @@ $TRANSLATIONS = array( "Users" => "Användare", "Admin" => "Admin", "Failed to upgrade \"%s\"." => "Misslyckades med att uppgradera \"%s\".", +"Unknown filetype" => "Okänd filtyp", +"Invalid image" => "Ogiltig bild", "web services under your control" => "webbtjänster under din kontroll", "cannot open \"%s\"" => "Kan inte öppna \"%s\"", "ZIP download is turned off." => "Nerladdning av ZIP är avstängd.", "Files need to be downloaded one by one." => "Filer laddas ner en åt gången.", "Back to Files" => "Tillbaka till Filer", "Selected files too large to generate zip file." => "Valda filer är för stora för att skapa zip-fil.", -"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Ladda ner filerna i mindre bitar, separat eller fråga din administratör.", +"Please download the files separately in smaller chunks or kindly ask your administrator." => "Ladda ner filerna i mindre bitar, separat eller fråga din administratör.", "No source specified when installing app" => "Ingen källa angiven vid installation av app ", "No href specified when installing app from http" => "Ingen href angiven vid installation av app från http", "No path specified when installing app from local file" => "Ingen sökväg angiven vid installation av app från lokal fil", @@ -53,6 +55,7 @@ $TRANSLATIONS = array( "Set an admin password." => "Ange ett administratörslösenord.", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Din webbserver är inte korrekt konfigurerad för att tillåta filsynkronisering eftersom WebDAV inte verkar fungera.", "Please double check the <a href='%s'>installation guides</a>." => "Var god kontrollera <a href='%s'>installationsguiden</a>.", +"Could not find category \"%s\"" => "Kunde inte hitta kategorin \"%s\"", "seconds ago" => "sekunder sedan", "_%n minute ago_::_%n minutes ago_" => array("%n minut sedan","%n minuter sedan"), "_%n hour ago_::_%n hours ago_" => array("%n timme sedan","%n timmar sedan"), @@ -62,8 +65,6 @@ $TRANSLATIONS = array( "last month" => "förra månaden", "_%n month ago_::_%n months ago_" => array("%n månad sedan","%n månader sedan"), "last year" => "förra året", -"years ago" => "år sedan", -"Caused by:" => "Orsakad av:", -"Could not find category \"%s\"" => "Kunde inte hitta kategorin \"%s\"" +"years ago" => "år sedan" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/l10n/sw_KE.php b/lib/l10n/sw_KE.php new file mode 100644 index 00000000000..15f78e0bce6 --- /dev/null +++ b/lib/l10n/sw_KE.php @@ -0,0 +1,8 @@ +<?php +$TRANSLATIONS = array( +"_%n minute ago_::_%n minutes ago_" => array("",""), +"_%n hour ago_::_%n hours ago_" => array("",""), +"_%n day go_::_%n days ago_" => array("",""), +"_%n month ago_::_%n months ago_" => array("","") +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/private/l10n/ta_LK.php b/lib/l10n/ta_LK.php index e70e65845be..f761ccab0e2 100644 --- a/lib/private/l10n/ta_LK.php +++ b/lib/l10n/ta_LK.php @@ -16,6 +16,7 @@ $TRANSLATIONS = array( "Files" => "கோப்புகள்", "Text" => "உரை", "Images" => "படங்கள்", +"Could not find category \"%s\"" => "பிரிவு \"%s\" ஐ கண்டுப்பிடிக்க முடியவில்லை", "seconds ago" => "செக்கன்களுக்கு முன்", "_%n minute ago_::_%n minutes ago_" => array("",""), "_%n hour ago_::_%n hours ago_" => array("",""), @@ -25,7 +26,6 @@ $TRANSLATIONS = array( "last month" => "கடந்த மாதம்", "_%n month ago_::_%n months ago_" => array("",""), "last year" => "கடந்த வருடம்", -"years ago" => "வருடங்களுக்கு முன்", -"Could not find category \"%s\"" => "பிரிவு \"%s\" ஐ கண்டுப்பிடிக்க முடியவில்லை" +"years ago" => "வருடங்களுக்கு முன்" ); $PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/private/l10n/te.php b/lib/l10n/te.php index 524ea0c6024..524ea0c6024 100644 --- a/lib/private/l10n/te.php +++ b/lib/l10n/te.php diff --git a/lib/private/l10n/th_TH.php b/lib/l10n/th_TH.php index 3344d0bb18e..173d0f2856b 100644 --- a/lib/private/l10n/th_TH.php +++ b/lib/l10n/th_TH.php @@ -16,6 +16,7 @@ $TRANSLATIONS = array( "Files" => "ไฟล์", "Text" => "ข้อความ", "Images" => "รูปภาพ", +"Could not find category \"%s\"" => "ไม่พบหมวดหมู่ \"%s\"", "seconds ago" => "วินาที ก่อนหน้านี้", "_%n minute ago_::_%n minutes ago_" => array(""), "_%n hour ago_::_%n hours ago_" => array(""), @@ -25,7 +26,6 @@ $TRANSLATIONS = array( "last month" => "เดือนที่แล้ว", "_%n month ago_::_%n months ago_" => array(""), "last year" => "ปีที่แล้ว", -"years ago" => "ปี ที่ผ่านมา", -"Could not find category \"%s\"" => "ไม่พบหมวดหมู่ \"%s\"" +"years ago" => "ปี ที่ผ่านมา" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/lib/private/l10n/tr.php b/lib/l10n/tr.php index b63c37c7240..7d25836f7d8 100644 --- a/lib/private/l10n/tr.php +++ b/lib/l10n/tr.php @@ -1,6 +1,6 @@ <?php $TRANSLATIONS = array( -"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "Owncloud yazılımının bu sürümü ile uyumlu olmadığı için \"%s\" uygulaması kurulamaz.", +"App \"%s\" can't be installed because it is not compatible with this version of ownCloud." => "ownCloud yazılımının bu sürümü ile uyumlu olmadığı için \"%s\" uygulaması kurulamaz.", "No app name specified" => "Uygulama adı belirtimedli", "Help" => "Yardım", "Personal" => "Kişisel", @@ -8,33 +8,35 @@ $TRANSLATIONS = array( "Users" => "Kullanıcılar", "Admin" => "Yönetici", "Failed to upgrade \"%s\"." => "\"%s\" yükseltme başarısız oldu.", -"web services under your control" => "Bilgileriniz güvenli ve şifreli", +"Unknown filetype" => "Bilinmeyen dosya türü", +"Invalid image" => "Geçersiz resim", +"web services under your control" => "kontrolünüzün altındaki web hizmetleri", "cannot open \"%s\"" => "\"%s\" açılamıyor", -"ZIP download is turned off." => "ZIP indirmeleri kapatılmıştır.", +"ZIP download is turned off." => "ZIP indirmeleri kapatıldı.", "Files need to be downloaded one by one." => "Dosyaların birer birer indirilmesi gerekmektedir.", "Back to Files" => "Dosyalara dön", -"Selected files too large to generate zip file." => "Seçilen dosyalar bir zip dosyası oluşturmak için fazla büyüktür.", -"Download the files in smaller chunks, seperately or kindly ask your administrator." => "Dosyaları ayrı ayrı, küçük parçalar halinde indirin ya da yöneticinizden yardım isteyin. ", +"Selected files too large to generate zip file." => "Seçilen dosyalar bir zip dosyası oluşturmak için fazla büyük.", +"Please download the files separately in smaller chunks or kindly ask your administrator." => "Dosyaları ayrı ayrı, küçük parçalar halinde indirin veya yöneticinizden yardım isteyin. ", "No source specified when installing app" => "Uygulama kurulurken bir kaynak belirtilmedi", -"No href specified when installing app from http" => "Uygulama kuruluyorken http'de href belirtilmedi.", -"No path specified when installing app from local file" => "Uygulama yerel dosyadan kuruluyorken dosya yolu belirtilmedi", -"Archives of type %s are not supported" => "%s arşiv tipi desteklenmiyor", +"No href specified when installing app from http" => "Uygulama kuruluyorken http'de href belirtilmedi", +"No path specified when installing app from local file" => "Uygulama yerel dosyadan kurulurken dosya yolu belirtilmedi", +"Archives of type %s are not supported" => "%s arşiv türü desteklenmiyor", "Failed to open archive when installing app" => "Uygulama kuruluyorken arşiv dosyası açılamadı", "App does not provide an info.xml file" => "Uygulama info.xml dosyası sağlamıyor", -"App can't be installed because of not allowed code in the App" => "Uygulamada izin verilmeyeden kodlar olduğu için kurulamıyor.", -"App can't be installed because it is not compatible with this version of ownCloud" => "Owncloud versiyonunuz ile uyumsuz olduğu için uygulama kurulamıyor.", -"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "Uygulama kurulamıyor. Çünkü \"non shipped\" uygulamalar için <shipped>true</shipped> tag içermektedir.", -"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "Uygulama kurulamıyor çünkü info.xml/version ile uygulama marketde belirtilen sürüm aynı değil.", -"App directory already exists" => "App dizini zaten mevcut", -"Can't create app folder. Please fix permissions. %s" => "app dizini oluşturulamıyor. Lütfen izinleri düzeltin. %s", +"App can't be installed because of not allowed code in the App" => "Uygulama, izin verilmeyen kodlar barındırdığından kurulamıyor.", +"App can't be installed because it is not compatible with this version of ownCloud" => "ownCloud sürümünüz ile uyumsuz olduğu için uygulama kurulamıyor.", +"App can't be installed because it contains the <shipped>true</shipped> tag which is not allowed for non shipped apps" => "Uygulama kurulamıyor. Çünkü \"birlikte gelmeyen\" uygulamalar için <shipped>true</shipped> etiketi içeriyor", +"App can't be installed because the version in info.xml/version is not the same as the version reported from the app store" => "Uygulama kurulamıyor çünkü info.xml/version ile uygulama markette belirtilen sürüm aynı değil", +"App directory already exists" => "Uygulama dizini zaten mevcut", +"Can't create app folder. Please fix permissions. %s" => "Uygulama dizini oluşturulamıyor. Lütfen izinleri düzeltin. %s", "Application is not enabled" => "Uygulama etkinleştirilmedi", "Authentication error" => "Kimlik doğrulama hatası", "Token expired. Please reload page." => "Jetonun süresi geçti. Lütfen sayfayı yenileyin.", "Files" => "Dosyalar", "Text" => "Metin", "Images" => "Resimler", -"%s enter the database username." => "%s veritabanı kullanıcı adını gir.", -"%s enter the database name." => "%s veritabanı adını gir.", +"%s enter the database username." => "%s veritabanı kullanıcı adını girin.", +"%s enter the database name." => "%s veritabanı adını girin.", "%s you may not use dots in the database name" => "%s veritabanı adında nokta kullanamayabilirsiniz", "MS SQL username and/or password not valid: %s" => "MS SQL kullanıcı adı ve/veya parolası geçersiz: %s", "You need to enter either an existing account or the administrator." => "Bir konto veya kullanici birlemek ihtiyacin. ", @@ -44,7 +46,7 @@ $TRANSLATIONS = array( "MySQL user '%s'@'localhost' exists already." => "MySQL kullanici '%s @local host zatan var. ", "Drop this user from MySQL" => "Bu kullanici MySQLden list disari koymak. ", "MySQL user '%s'@'%%' already exists" => "MySQL kullanici '%s @ % % zaten var (zaten yazili)", -"Drop this user from MySQL." => "Bu kulanıcıyı MySQL veritabanından kaldır", +"Drop this user from MySQL." => "Bu kullanıcıyı MySQL veritabanından kaldır", "Oracle connection could not be established" => "Oracle bağlantısı kurulamadı", "Oracle username and/or password not valid" => "Adi klullanici ve/veya parola Oracle mantikli değildir. ", "Offending command was: \"%s\", name: %s, password: %s" => "Hatalı komut: \"%s\", ad: %s, parola: %s", @@ -53,6 +55,7 @@ $TRANSLATIONS = array( "Set an admin password." => "Parola yonetici birlemek. ", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Web sunucunuz dosya transferi için düzgün bir şekilde yapılandırılmamış. WevDAV arabirimini sorunlu gözüküyor.", "Please double check the <a href='%s'>installation guides</a>." => "Lütfen <a href='%s'>kurulum kılavuzlarını</a> iki kez kontrol edin.", +"Could not find category \"%s\"" => "\"%s\" kategorisi bulunamadı", "seconds ago" => "saniye önce", "_%n minute ago_::_%n minutes ago_" => array("","%n dakika önce"), "_%n hour ago_::_%n hours ago_" => array("","%n saat önce"), @@ -62,8 +65,6 @@ $TRANSLATIONS = array( "last month" => "geçen ay", "_%n month ago_::_%n months ago_" => array("","%n ay önce"), "last year" => "geçen yıl", -"years ago" => "yıl önce", -"Caused by:" => "Neden olan:", -"Could not find category \"%s\"" => "\"%s\" kategorisi bulunamadı" +"years ago" => "yıl önce" ); $PLURAL_FORMS = "nplurals=2; plural=(n > 1);"; diff --git a/lib/l10n/tzm.php b/lib/l10n/tzm.php new file mode 100644 index 00000000000..3120c509265 --- /dev/null +++ b/lib/l10n/tzm.php @@ -0,0 +1,8 @@ +<?php +$TRANSLATIONS = array( +"_%n minute ago_::_%n minutes ago_" => array("",""), +"_%n hour ago_::_%n hours ago_" => array("",""), +"_%n day go_::_%n days ago_" => array("",""), +"_%n month ago_::_%n months ago_" => array("","") +); +$PLURAL_FORMS = "nplurals=2; plural=(n == 0 || n == 1 || (n > 10 && n < 100) ? 0 : 1;"; diff --git a/lib/private/l10n/ug.php b/lib/l10n/ug.php index e2cf38ecc8c..e2cf38ecc8c 100644 --- a/lib/private/l10n/ug.php +++ b/lib/l10n/ug.php diff --git a/lib/private/l10n/uk.php b/lib/l10n/uk.php index c1513c5bb79..32e010f1d40 100644 --- a/lib/private/l10n/uk.php +++ b/lib/l10n/uk.php @@ -5,6 +5,8 @@ $TRANSLATIONS = array( "Settings" => "Налаштування", "Users" => "Користувачі", "Admin" => "Адмін", +"Unknown filetype" => "Невідомий тип файлу", +"Invalid image" => "Невірне зображення", "web services under your control" => "підконтрольні Вам веб-сервіси", "ZIP download is turned off." => "ZIP завантаження вимкнено.", "Files need to be downloaded one by one." => "Файли повинні бути завантаженні послідовно.", @@ -35,16 +37,16 @@ $TRANSLATIONS = array( "Set an admin password." => "Встановіть пароль адміністратора.", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Ваш Web-сервер ще не налаштований належним чином для того, щоб дозволити синхронізацію файлів, через те що інтерфейс WebDAV, здається, зламаний.", "Please double check the <a href='%s'>installation guides</a>." => "Будь ласка, перевірте <a href='%s'>інструкції по встановленню</a>.", +"Could not find category \"%s\"" => "Не вдалося знайти категорію \"%s\"", "seconds ago" => "секунди тому", -"_%n minute ago_::_%n minutes ago_" => array("","",""), -"_%n hour ago_::_%n hours ago_" => array("","",""), +"_%n minute ago_::_%n minutes ago_" => array("","","%n хвилин тому"), +"_%n hour ago_::_%n hours ago_" => array("","","%n годин тому"), "today" => "сьогодні", "yesterday" => "вчора", -"_%n day go_::_%n days ago_" => array("","",""), +"_%n day go_::_%n days ago_" => array("","","%n днів тому"), "last month" => "минулого місяця", -"_%n month ago_::_%n months ago_" => array("","",""), +"_%n month ago_::_%n months ago_" => array("","","%n місяців тому"), "last year" => "минулого року", -"years ago" => "роки тому", -"Could not find category \"%s\"" => "Не вдалося знайти категорію \"%s\"" +"years ago" => "роки тому" ); $PLURAL_FORMS = "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);"; diff --git a/lib/l10n/ur.php b/lib/l10n/ur.php new file mode 100644 index 00000000000..15f78e0bce6 --- /dev/null +++ b/lib/l10n/ur.php @@ -0,0 +1,8 @@ +<?php +$TRANSLATIONS = array( +"_%n minute ago_::_%n minutes ago_" => array("",""), +"_%n hour ago_::_%n hours ago_" => array("",""), +"_%n day go_::_%n days ago_" => array("",""), +"_%n month ago_::_%n months ago_" => array("","") +); +$PLURAL_FORMS = "nplurals=2; plural=(n != 1);"; diff --git a/lib/private/l10n/ur_PK.php b/lib/l10n/ur_PK.php index 7dc967ccd93..7dc967ccd93 100644 --- a/lib/private/l10n/ur_PK.php +++ b/lib/l10n/ur_PK.php diff --git a/lib/l10n/uz.php b/lib/l10n/uz.php new file mode 100644 index 00000000000..e7b09649a24 --- /dev/null +++ b/lib/l10n/uz.php @@ -0,0 +1,8 @@ +<?php +$TRANSLATIONS = array( +"_%n minute ago_::_%n minutes ago_" => array(""), +"_%n hour ago_::_%n hours ago_" => array(""), +"_%n day go_::_%n days ago_" => array(""), +"_%n month ago_::_%n months ago_" => array("") +); +$PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/lib/private/l10n/vi.php b/lib/l10n/vi.php index dc0045c35ca..5840283110e 100644 --- a/lib/private/l10n/vi.php +++ b/lib/l10n/vi.php @@ -16,6 +16,7 @@ $TRANSLATIONS = array( "Files" => "Tập tin", "Text" => "Văn bản", "Images" => "Hình ảnh", +"Could not find category \"%s\"" => "không thể tìm thấy mục \"%s\"", "seconds ago" => "vài giây trước", "_%n minute ago_::_%n minutes ago_" => array(""), "_%n hour ago_::_%n hours ago_" => array(""), @@ -25,7 +26,6 @@ $TRANSLATIONS = array( "last month" => "tháng trước", "_%n month ago_::_%n months ago_" => array(""), "last year" => "năm trước", -"years ago" => "năm trước", -"Could not find category \"%s\"" => "không thể tìm thấy mục \"%s\"" +"years ago" => "năm trước" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/lib/private/l10n/zh_CN.php b/lib/l10n/zh_CN.php index 2c34356ea10..ae9243cf412 100644 --- a/lib/private/l10n/zh_CN.php +++ b/lib/l10n/zh_CN.php @@ -5,6 +5,8 @@ $TRANSLATIONS = array( "Settings" => "设置", "Users" => "用户", "Admin" => "管理", +"Unknown filetype" => "未知的文件类型", +"Invalid image" => "无效的图像", "web services under your control" => "您控制的web服务", "ZIP download is turned off." => "ZIP 下载已经关闭", "Files need to be downloaded one by one." => "需要逐一下载文件", @@ -37,6 +39,7 @@ $TRANSLATIONS = array( "Set an admin password." => "请设置一个管理员密码。", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "您的Web服务器尚未正确设置以允许文件同步, 因为WebDAV的接口似乎已损坏.", "Please double check the <a href='%s'>installation guides</a>." => "请认真检查<a href='%s'>安装指南</a>.", +"Could not find category \"%s\"" => "无法找到分类 \"%s\"", "seconds ago" => "秒前", "_%n minute ago_::_%n minutes ago_" => array("%n 分钟前"), "_%n hour ago_::_%n hours ago_" => array("%n 小时前"), @@ -46,7 +49,6 @@ $TRANSLATIONS = array( "last month" => "上月", "_%n month ago_::_%n months ago_" => array("%n 月前"), "last year" => "去年", -"years ago" => "年前", -"Could not find category \"%s\"" => "无法找到分类 \"%s\"" +"years ago" => "年前" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/lib/private/l10n/zh_HK.php b/lib/l10n/zh_HK.php index ca3e6d504e7..ca3e6d504e7 100644 --- a/lib/private/l10n/zh_HK.php +++ b/lib/l10n/zh_HK.php diff --git a/lib/private/l10n/zh_TW.php b/lib/l10n/zh_TW.php index 210c766aa59..35719c8b17e 100644 --- a/lib/private/l10n/zh_TW.php +++ b/lib/l10n/zh_TW.php @@ -8,13 +8,14 @@ $TRANSLATIONS = array( "Users" => "使用者", "Admin" => "管理", "Failed to upgrade \"%s\"." => "升級失敗:%s", +"Unknown filetype" => "未知的檔案類型", +"Invalid image" => "無效的圖片", "web services under your control" => "由您控制的網路服務", "cannot open \"%s\"" => "無法開啓 %s", "ZIP download is turned off." => "ZIP 下載已關閉。", "Files need to be downloaded one by one." => "檔案需要逐一下載。", "Back to Files" => "回到檔案列表", "Selected files too large to generate zip file." => "選擇的檔案太大以致於無法產生壓縮檔。", -"Download the files in smaller chunks, seperately or kindly ask your administrator." => "以小分割下載您的檔案,請詢問您的系統管理員。", "No source specified when installing app" => "沒有指定應用程式安裝來源", "No href specified when installing app from http" => "從 http 安裝應用程式,找不到 href 屬性", "No path specified when installing app from local file" => "從本地檔案安裝應用程式時沒有指定路徑", @@ -53,6 +54,7 @@ $TRANSLATIONS = array( "Set an admin password." => "設定管理員密碼。", "Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "您的網頁伺服器尚未被正確設定來進行檔案同步,因為您的 WebDAV 界面似乎無法使用。", "Please double check the <a href='%s'>installation guides</a>." => "請參考<a href='%s'>安裝指南</a>。", +"Could not find category \"%s\"" => "找不到分類:\"%s\"", "seconds ago" => "幾秒前", "_%n minute ago_::_%n minutes ago_" => array("%n 分鐘前"), "_%n hour ago_::_%n hours ago_" => array("%n 小時前"), @@ -62,8 +64,6 @@ $TRANSLATIONS = array( "last month" => "上個月", "_%n month ago_::_%n months ago_" => array("%n 個月前"), "last year" => "去年", -"years ago" => "幾年前", -"Caused by:" => "原因:", -"Could not find category \"%s\"" => "找不到分類:\"%s\"" +"years ago" => "幾年前" ); $PLURAL_FORMS = "nplurals=1; plural=0;"; 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/allconfig.php b/lib/private/allconfig.php index 72aabf60793..a4aa69d43fb 100644 --- a/lib/private/allconfig.php +++ b/lib/private/allconfig.php @@ -4,7 +4,7 @@ * This file is licensed under the Affero General Public License version 3 or * later. * See the COPYING-README file. - * + * */ namespace OC; @@ -15,6 +15,7 @@ namespace OC; class AllConfig implements \OCP\IConfig { /** * Sets a new system wide value + * * @param string $key the key of the value, under which will be saved * @param string $value the value that should be stored * @todo need a use case for this @@ -25,16 +26,19 @@ class AllConfig implements \OCP\IConfig { /** * Looks up a system wide defined value + * * @param string $key the key of the value, under which it was saved + * @param string $default the default value to be returned if the value isn't set * @return string the saved value */ - public function getSystemValue($key) { - return \OCP\Config::getSystemValue($key, ''); + public function getSystemValue($key, $default = '') { + return \OCP\Config::getSystemValue($key, $default); } /** * Writes a new app wide value + * * @param string $appName the appName that we want to store the value under * @param string $key the key of the value, under which will be saved * @param string $value the value that should be stored @@ -45,17 +49,20 @@ class AllConfig implements \OCP\IConfig { /** * Looks up an app wide defined value + * * @param string $appName the appName that we stored the value under * @param string $key the key of the value, under which it was saved + * @param string $default the default value to be returned if the value isn't set * @return string the saved value */ - public function getAppValue($appName, $key) { - return \OCP\Config::getAppValue($appName, $key, ''); + public function getAppValue($appName, $key, $default = '') { + return \OCP\Config::getAppValue($appName, $key, $default); } /** * Set a user defined value + * * @param string $userId the userId of the user that we want to store the value under * @param string $appName the appName that we want to store the value under * @param string $key the key under which the value is being stored @@ -67,11 +74,14 @@ class AllConfig implements \OCP\IConfig { /** * Shortcut for getting a user defined value + * * @param string $userId the userId of the user that we want to store the value under * @param string $appName the appName that we stored the value under * @param string $key the key under which the value is being stored + * @param string $default the default value to be returned if the value isn't set + * @return string */ - public function getUserValue($userId, $appName, $key){ - return \OCP\Config::getUserValue($userId, $appName, $key); + public function getUserValue($userId, $appName, $key, $default = '') { + return \OCP\Config::getUserValue($userId, $appName, $key, $default); } } diff --git a/lib/private/api.php b/lib/private/api.php index 31f3f968d9b..c713368125c 100644 --- a/lib/private/api.php +++ b/lib/private/api.php @@ -33,7 +33,7 @@ class OC_API { const USER_AUTH = 1; const SUBADMIN_AUTH = 2; const ADMIN_AUTH = 3; - + /** * API Response Codes */ @@ -41,12 +41,13 @@ class OC_API { const RESPOND_SERVER_ERROR = 996; const RESPOND_NOT_FOUND = 998; const RESPOND_UNKNOWN_ERROR = 999; - + /** * api actions */ protected static $actions = array(); - + private static $logoutRequired = false; + /** * registers an api call * @param string $method the http method @@ -57,7 +58,7 @@ class OC_API { * @param array $defaults * @param array $requirements */ - public static function register($method, $url, $action, $app, + public static function register($method, $url, $action, $app, $authLevel = OC_API::USER_AUTH, $defaults = array(), $requirements = array()) { @@ -74,7 +75,7 @@ class OC_API { } self::$actions[$name][] = array('app' => $app, 'action' => $action, 'authlevel' => $authLevel); } - + /** * handles an api call * @param array $parameters @@ -95,6 +96,7 @@ class OC_API { $responses[] = array( 'app' => $action['app'], 'response' => new OC_OCS_Result(null, OC_API::RESPOND_UNAUTHORISED, 'Unauthorised'), + 'shipped' => OC_App::isShipped($action['app']), ); continue; } @@ -102,6 +104,7 @@ class OC_API { $responses[] = array( 'app' => $action['app'], 'response' => new OC_OCS_Result(null, OC_API::RESPOND_NOT_FOUND, 'Api method not found'), + 'shipped' => OC_App::isShipped($action['app']), ); continue; } @@ -109,22 +112,25 @@ class OC_API { $responses[] = array( 'app' => $action['app'], 'response' => call_user_func($action['action'], $parameters), + 'shipped' => OC_App::isShipped($action['app']), ); } $response = self::mergeResponses($responses); $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); } - + /** * merge the returned result objects into one response * @param array $responses */ - private static function mergeResponses($responses) { + public static function mergeResponses($responses) { $response = array(); // Sort into shipped and thirdparty $shipped = array( @@ -137,53 +143,81 @@ class OC_API { ); foreach($responses as $response) { - if(OC_App::isShipped($response['app']) || ($response['app'] === 'core')) { + if($response['shipped'] || ($response['app'] === 'core')) { if($response['response']->succeeded()) { - $shipped['succeeded'][$response['app']] = $response['response']; + $shipped['succeeded'][$response['app']] = $response; } else { - $shipped['failed'][$response['app']] = $response['response']; + $shipped['failed'][$response['app']] = $response; } } else { if($response['response']->succeeded()) { - $thirdparty['succeeded'][$response['app']] = $response['response']; + $thirdparty['succeeded'][$response['app']] = $response; } else { - $thirdparty['failed'][$response['app']] = $response['response']; + $thirdparty['failed'][$response['app']] = $response; } } } // Remove any error responses if there is one shipped response that succeeded - if(!empty($shipped['succeeded'])) { - $responses = array_merge($shipped['succeeded'], $thirdparty['succeeded']); - } else if(!empty($shipped['failed'])) { + if(!empty($shipped['failed'])) { // Which shipped response do we use if they all failed? // They may have failed for different reasons (different status codes) // Which reponse code should we return? // Maybe any that are not OC_API::RESPOND_SERVER_ERROR - $response = reset($shipped['failed']); + // Merge failed responses if more than one + $data = array(); + foreach($shipped['failed'] as $failure) { + $data = array_merge_recursive($data, $failure['response']->getData()); + } + $picked = reset($shipped['failed']); + $code = $picked['response']->getStatusCode(); + $meta = $picked['response']->getMeta(); + $response = new OC_OCS_Result($data, $code, $meta['message']); return $response; + } elseif(!empty($shipped['succeeded'])) { + $responses = array_merge($shipped['succeeded'], $thirdparty['succeeded']); } elseif(!empty($thirdparty['failed'])) { - // Return the third party failure result - $response = reset($thirdparty['failed']); + // Merge failed responses if more than one + $data = array(); + foreach($thirdparty['failed'] as $failure) { + $data = array_merge_recursive($data, $failure['response']->getData()); + } + $picked = reset($thirdparty['failed']); + $code = $picked['response']->getStatusCode(); + $meta = $picked['response']->getMeta(); + $response = new OC_OCS_Result($data, $code, $meta['message']); return $response; } else { - $responses = array_merge($shipped['succeeded'], $thirdparty['succeeded']); + $responses = $thirdparty['succeeded']; } // Merge the successful responses - $meta = array(); $data = array(); foreach($responses as $app => $response) { - if(OC_App::isShipped($app)) { - $data = array_merge_recursive($response->getData(), $data); + if($response['shipped']) { + $data = array_merge_recursive($response['response']->getData(), $data); } else { - $data = array_merge_recursive($data, $response->getData()); + $data = array_merge_recursive($data, $response['response']->getData()); + } + $codes[] = array('code' => $response['response']->getStatusCode(), + 'meta' => $response['response']->getMeta()); + } + + // Use any non 100 status codes + $statusCode = 100; + $statusMessage = null; + foreach($codes as $code) { + if($code['code'] != 100) { + $statusCode = $code['code']; + $statusMessage = $code['meta']['message']; + break; } } - $result = new OC_OCS_Result($data, 100); + + $result = new OC_OCS_Result($data, $statusCode, $statusMessage); return $result; } - + /** * authenticate the api call * @param array $action the action details as supplied to OC_API::register() @@ -229,18 +263,40 @@ class OC_API { return false; break; } - } - + } + /** * 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; + + // initialize the user's filesystem + \OC_Util::setUpFS(\OC_User::getUser()); + + return $authUser; + } + + // reuse existing login + $loggedIn = OC_User::isLoggedIn(); + $ocsApiRequest = isset($_SERVER['HTTP_OCS_APIREQUEST']) ? $_SERVER['HTTP_OCS_APIREQUEST'] === 'true' : false; + if ($loggedIn === true && $ocsApiRequest) { + + // initialize the user's filesystem + \OC_Util::setUpFS(\OC_User::getUser()); + + return OC_User::getUser(); + } + + return false; } - + /** * respond to a call * @param OC_OCS_Result $result @@ -289,5 +345,5 @@ class OC_API { } } } - + } diff --git a/lib/private/app.php b/lib/private/app.php index 0ab1ee57f63..0c60557914a 100644 --- a/lib/private/app.php +++ b/lib/private/app.php @@ -165,17 +165,23 @@ class OC_App{ /** * get all enabled apps */ - public static function getEnabledApps() { + private static $enabledAppsCache = array(); + public static function getEnabledApps($forceRefresh = false) { if(!OC_Config::getValue('installed', false)) { return array(); } + if(!$forceRefresh && !empty(self::$enabledAppsCache)) { + return self::$enabledAppsCache; + } $apps=array('files'); $sql = 'SELECT `appid` FROM `*PREFIX*appconfig`' - .' WHERE `configkey` = \'enabled\' AND `configvalue`=\'yes\''; + . ' WHERE `configkey` = \'enabled\' AND `configvalue`=\'yes\'' + . ' ORDER BY `appid`'; if (OC_Config::getValue( 'dbtype', 'sqlite' ) === 'oci') { //FIXME oracle hack: need to explicitly cast CLOB to CHAR for comparison $sql = 'SELECT `appid` FROM `*PREFIX*appconfig`' - .' WHERE `configkey` = \'enabled\' AND to_char(`configvalue`)=\'yes\''; + . ' WHERE `configkey` = \'enabled\' AND to_char(`configvalue`)=\'yes\'' + . ' ORDER BY `appid`'; } $query = OC_DB::prepare( $sql ); $result=$query->execute(); @@ -187,6 +193,7 @@ class OC_App{ $apps[]=$row['appid']; } } + self::$enabledAppsCache = $apps; return $apps; } @@ -198,11 +205,11 @@ class OC_App{ * This function checks whether or not an app is enabled. */ public static function isEnabled( $app ) { - if( 'files'==$app or ('yes' == OC_Appconfig::getValue( $app, 'enabled' ))) { + if('files' == $app) { return true; } - - return false; + $enabledApps = self::getEnabledApps(); + return in_array($app, $enabledApps); } /** @@ -214,6 +221,7 @@ class OC_App{ * This function set an app as enabled in appconfig. */ public static function enable( $app ) { + self::$enabledAppsCache = array(); // flush if(!OC_Installer::isInstalled($app)) { // check if app is a shipped app or not. OCS apps have an integer as id, shipped apps use a string if(!is_numeric($app)) { @@ -243,6 +251,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")); @@ -257,6 +266,7 @@ class OC_App{ * This function set an app as disabled in appconfig. */ public static function disable( $app ) { + self::$enabledAppsCache = array(); // flush // check if app is a shipped app or not. if not delete \OC_Hook::emit('OC_App', 'pre_disable', array('app' => $app)); OC_Appconfig::setValue( $app, 'enabled', 'no' ); @@ -545,6 +555,10 @@ class OC_App{ }elseif($child->getName()=='description') { $xml=(string)$child->asXML(); $data[$child->getName()]=substr($xml, 13, -14);//script <description> tags + }elseif($child->getName()=='documentation') { + foreach($child as $subchild) { + $data["documentation"][$subchild->getName()] = (string)$subchild; + } }else{ $data[$child->getName()]=(string)$child; } @@ -745,10 +759,43 @@ class OC_App{ } else { $combinedApps = $appList; } + // bring the apps into the right order with a custom sort funtion + usort( $combinedApps, '\OC_App::customSort' ); + return $combinedApps; } /** + * @brief: Internal custom sort funtion to bring the app into the right order. Should only be called by listAllApps + * @return array + */ + private static function customSort($a, $b) { + + // prio 1: active + if ($a['active'] != $b['active']) { + return $b['active'] - $a['active']; + } + + // prio 2: shipped + $ashipped = (array_key_exists('shipped', $a) && $a['shipped'] === 'true') ? 1 : 0; + $bshipped = (array_key_exists('shipped', $b) && $b['shipped'] === 'true') ? 1 : 0; + if ($ashipped !== $bshipped) { + return ($bshipped - $ashipped); + } + + // prio 3: recommended + if ($a['internalclass'] != $b['internalclass']) { + $atemp = ($a['internalclass'] == 'recommendedapp' ? 1 : 0); + $btemp = ($b['internalclass'] == 'recommendedapp' ? 1 : 0); + return ($btemp - $atemp); + } + + // prio 4: alphabetical + return strcasecmp($a['name'], $b['name']); + + } + + /** * @brief: get a list of all apps on apps.owncloud.com * @return array, multi-dimensional array of apps. * Keys: id, name, type, typename, personid, license, detailpage, preview, changed, description diff --git a/lib/private/appconfig.php b/lib/private/appconfig.php index e615d838173..da0b2ff8604 100644 --- a/lib/private/appconfig.php +++ b/lib/private/appconfig.php @@ -37,7 +37,12 @@ * This class provides an easy way for apps to store config values in the * database. */ -class OC_Appconfig{ +class OC_Appconfig { + + private static $cache = array(); + + private static $appsLoaded = array(); + /** * @brief Get all apps using the config * @return array with app ids @@ -47,11 +52,11 @@ class OC_Appconfig{ */ public static function getApps() { // No magic in here! - $query = OC_DB::prepare( 'SELECT DISTINCT `appid` FROM `*PREFIX*appconfig`' ); + $query = OC_DB::prepare('SELECT DISTINCT `appid` FROM `*PREFIX*appconfig` ORDER BY `appid`'); $result = $query->execute(); $apps = array(); - while( $row = $result->fetchRow()) { + while ($row = $result->fetchRow()) { $apps[] = $row["appid"]; } @@ -66,19 +71,35 @@ class OC_Appconfig{ * This function gets all keys of an app. Please note that the values are * not returned. */ - public static function getKeys( $app ) { + public static function getKeys($app) { // No magic in here as well - $query = OC_DB::prepare( 'SELECT `configkey` FROM `*PREFIX*appconfig` WHERE `appid` = ?' ); - $result = $query->execute( array( $app )); + $query = OC_DB::prepare('SELECT `configkey` FROM `*PREFIX*appconfig` WHERE `appid` = ?'); + $result = $query->execute(array($app)); $keys = array(); - while( $row = $result->fetchRow()) { + while ($row = $result->fetchRow()) { $keys[] = $row["configkey"]; } return $keys; } + private static function getAppValues($app) { + if (!isset(self::$cache[$app])) { + self::$cache[$app] = array(); + } + if (array_search($app, self::$appsLoaded) === false) { + $query = OC_DB::prepare('SELECT `configvalue`, `configkey` FROM `*PREFIX*appconfig`' + . ' WHERE `appid` = ?'); + $result = $query->execute(array($app)); + while ($row = $result->fetchRow()) { + self::$cache[$app][$row['configkey']] = $row['configvalue']; + } + self::$appsLoaded[] = $app; + } + return self::$cache[$app]; + } + /** * @brief Gets the config value * @param string $app app @@ -89,15 +110,18 @@ class OC_Appconfig{ * This function gets a value from the appconfig table. If the key does * not exist the default value will be returned */ - public static function getValue( $app, $key, $default = null ) { - // At least some magic in here :-) - $query = OC_DB::prepare( 'SELECT `configvalue` FROM `*PREFIX*appconfig`' - .' WHERE `appid` = ? AND `configkey` = ?' ); - $result = $query->execute( array( $app, $key )); - $row = $result->fetchRow(); - if($row) { - return $row["configvalue"]; - }else{ + public static function getValue($app, $key, $default = null) { + if (!isset(self::$cache[$app])) { + self::$cache[$app] = array(); + } + if (isset(self::$cache[$app][$key])) { + return self::$cache[$app][$key]; + } + $values = self::getAppValues($app); + if (isset($values[$key])) { + return $values[$key]; + } else { + self::$cache[$app][$key] = $default; return $default; } } @@ -109,8 +133,11 @@ class OC_Appconfig{ * @return bool */ public static function hasKey($app, $key) { - $exists = self::getKeys( $app ); - return in_array( $key, $exists ); + if (isset(self::$cache[$app]) and isset(self::$cache[$app][$key])) { + return true; + } + $exists = self::getKeys($app); + return in_array($key, $exists); } /** @@ -122,18 +149,27 @@ class OC_Appconfig{ * * Sets a value. If the key did not exist before it will be created. */ - public static function setValue( $app, $key, $value ) { + public static function setValue($app, $key, $value) { // Does the key exist? yes: update. No: insert - if(! self::hasKey($app, $key)) { - $query = OC_DB::prepare( 'INSERT INTO `*PREFIX*appconfig` ( `appid`, `configkey`, `configvalue` )' - .' VALUES( ?, ?, ? )' ); - $query->execute( array( $app, $key, $value )); + if (!self::hasKey($app, $key)) { + $query = OC_DB::prepare('INSERT INTO `*PREFIX*appconfig` ( `appid`, `configkey`, `configvalue` )' + . ' VALUES( ?, ?, ? )'); + $query->execute(array($app, $key, $value)); + } else { + $query = OC_DB::prepare('UPDATE `*PREFIX*appconfig` SET `configvalue` = ?' + . ' WHERE `appid` = ? AND `configkey` = ?'); + $query->execute(array($value, $app, $key)); } - else{ - $query = OC_DB::prepare( 'UPDATE `*PREFIX*appconfig` SET `configvalue` = ?' - .' 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 + )); + if (!isset(self::$cache[$app])) { + self::$cache[$app] = array(); } + self::$cache[$app][$key] = $value; } /** @@ -144,10 +180,13 @@ class OC_Appconfig{ * * Deletes a key. */ - public static function deleteKey( $app, $key ) { + public static function deleteKey($app, $key) { // Boring! - $query = OC_DB::prepare( 'DELETE FROM `*PREFIX*appconfig` WHERE `appid` = ? AND `configkey` = ?' ); - $query->execute( array( $app, $key )); + $query = OC_DB::prepare('DELETE FROM `*PREFIX*appconfig` WHERE `appid` = ? AND `configkey` = ?'); + $query->execute(array($app, $key)); + if (isset(self::$cache[$app]) and isset(self::$cache[$app][$key])) { + unset(self::$cache[$app][$key]); + } return true; } @@ -159,44 +198,46 @@ class OC_Appconfig{ * * Removes all keys in appconfig belonging to the app. */ - public static function deleteApp( $app ) { + public static function deleteApp($app) { // Nothing special - $query = OC_DB::prepare( 'DELETE FROM `*PREFIX*appconfig` WHERE `appid` = ?' ); - $query->execute( array( $app )); + $query = OC_DB::prepare('DELETE FROM `*PREFIX*appconfig` WHERE `appid` = ?'); + $query->execute(array($app)); + self::$cache[$app] = array(); return true; } /** * get multiply values, either the app or key can be used as wildcard by setting it to false + * * @param app * @param key * @return array */ public static function getValues($app, $key) { - if($app!==false and $key!==false) { + if ($app !== false and $key !== false) { return false; } - $fields='`configvalue`'; - $where='WHERE'; - $params=array(); - if($app!==false) { - $fields.=', `configkey`'; - $where.=' `appid` = ?'; - $params[]=$app; - $key='configkey'; - }else{ - $fields.=', `appid`'; - $where.=' `configkey` = ?'; - $params[]=$key; - $key='appid'; + $fields = '`configvalue`'; + $where = 'WHERE'; + $params = array(); + if ($app !== false) { + $fields .= ', `configkey`'; + $where .= ' `appid` = ?'; + $params[] = $app; + $key = 'configkey'; + } else { + $fields .= ', `appid`'; + $where .= ' `configkey` = ?'; + $params[] = $key; + $key = 'appid'; } - $queryString='SELECT '.$fields.' FROM `*PREFIX*appconfig` '.$where; - $query=OC_DB::prepare($queryString); - $result=$query->execute($params); - $values=array(); - while($row=$result->fetchRow()) { - $values[$row[$key]]=$row['configvalue']; + $queryString = 'SELECT ' . $fields . ' FROM `*PREFIX*appconfig` ' . $where; + $query = OC_DB::prepare($queryString); + $result = $query->execute($params); + $values = array(); + while ($row = $result->fetchRow()) { + $values[$row[$key]] = $row['configvalue']; } return $values; } diff --git a/lib/private/appframework/app.php b/lib/private/appframework/app.php index 7ff55bb809d..b835188661a 100644 --- a/lib/private/appframework/app.php +++ b/lib/private/appframework/app.php @@ -42,12 +42,13 @@ class App { * @param string $controllerName the name of the controller under which it is * stored in the DI container * @param string $methodName the method that you want to call - * @param array $urlParams an array with variables extracted from the routes * @param DIContainer $container an instance of a pimple container. + * @param array $urlParams list of URL parameters (optional) */ - public static function main($controllerName, $methodName, array $urlParams, - IAppContainer $container) { - $container['urlParams'] = $urlParams; + public static function main($controllerName, $methodName, DIContainer $container, array $urlParams = null) { + if (!is_null($urlParams)) { + $container['urlParams'] = $urlParams; + } $controller = $container[$controllerName]; // initialize the dispatcher and run all the middleware before the controller diff --git a/lib/private/appframework/core/api.php b/lib/private/appframework/core/api.php index 39522ee3dd5..e7269373bb0 100644 --- a/lib/private/appframework/core/api.php +++ b/lib/private/appframework/core/api.php @@ -100,89 +100,6 @@ class API implements IApi{ /** - * Returns the translation object - * @return \OC_L10N the translation object - */ - public function getTrans(){ - # TODO: use public api - return \OC_L10N::get($this->appName); - } - - - /** - * Returns the URL for a route - * @param string $routeName the name of the route - * @param array $arguments an array with arguments which will be filled into the url - * @return string the url - */ - public function linkToRoute($routeName, $arguments=array()){ - return \OCP\Util::linkToRoute($routeName, $arguments); - } - - - /** - * Returns an URL for an image or file - * @param string $file the name of the file - * @param string $appName the name of the app, defaults to the current one - */ - public function linkTo($file, $appName=null){ - if($appName === null){ - $appName = $this->appName; - } - return \OCP\Util::linkTo($appName, $file); - } - - - /** - * Returns the link to an image, like link to but only with prepending img/ - * @param string $file the name of the file - * @param string $appName the name of the app, defaults to the current one - */ - public function imagePath($file, $appName=null){ - if($appName === null){ - $appName = $this->appName; - } - return \OCP\Util::imagePath($appName, $file); - } - - - /** - * Makes an URL absolute - * @param string $url the url - * @return string the absolute url - */ - public function getAbsoluteURL($url){ - # TODO: use public api - return \OC_Helper::makeURLAbsolute($url); - } - - - /** - * links to a file - * @param string $file the name of the file - * @param string $appName the name of the app, defaults to the current one - * @deprecated replaced with linkToRoute() - * @return string the url - */ - public function linkToAbsolute($file, $appName=null){ - if($appName === null){ - $appName = $this->appName; - } - return \OCP\Util::linkToAbsolute($appName, $file); - } - - - /** - * Checks if the CSRF check was correct - * @return bool true if CSRF check passed - */ - public function passesCSRFCheck(){ - # TODO: use public api - return \OC_Util::isCallRegistered(); - } - - - /** * Checks if an app is enabled * @param string $appName the name of an app * @return bool true if app is enabled @@ -193,44 +110,6 @@ class API implements IApi{ /** - * Writes a function into the error log - * @param string $msg the error message to be logged - * @param int $level the error level - */ - public function log($msg, $level=null){ - switch($level){ - case 'debug': - $level = \OCP\Util::DEBUG; - break; - case 'info': - $level = \OCP\Util::INFO; - break; - case 'warn': - $level = \OCP\Util::WARN; - break; - case 'fatal': - $level = \OCP\Util::FATAL; - break; - default: - $level = \OCP\Util::ERROR; - break; - } - \OCP\Util::writeLog($this->appName, $msg, $level); - } - - - /** - * turns an owncloud path into a path on the filesystem - * @param string path the path to the file on the oc filesystem - * @return string the filepath in the filesystem - */ - public function getLocalFilePath($path){ - # TODO: use public api - return \OC_Filesystem::getLocalFile($path); - } - - - /** * used to return and open a new eventsource * @return \OC_EventSource a new open EventSource class */ @@ -275,15 +154,6 @@ class API implements IApi{ } } - /** - * Gets the content of an URL by using CURL or a fallback if it is not - * installed - * @param string $url the url that should be fetched - * @return string the content of the webpage - */ - public function getUrlContent($url) { - return \OC_Util::getUrlContent($url); - } /** * Register a backgroundjob task @@ -295,25 +165,6 @@ class API implements IApi{ \OCP\Backgroundjob::addRegularTask($className, $methodName); } - /** - * Returns a template - * @param string $templateName the name of the template - * @param string $renderAs how it should be rendered - * @param string $appName the name of the app - * @return \OCP\Template a new template - */ - public function getTemplate($templateName, $renderAs='user', $appName=null){ - if($appName === null){ - $appName = $this->appName; - } - - if($renderAs === 'blank'){ - return new \OCP\Template($appName, $templateName); - } else { - return new \OCP\Template($appName, $templateName, $renderAs); - } - } - /** * Tells ownCloud to include a template in the admin overview @@ -330,19 +181,4 @@ class API implements IApi{ } - /** - * get the filesystem info - * - * @param string $path - * @return array with the following keys: - * - size - * - mtime - * - mimetype - * - encrypted - * - versioned - */ - public function getFileInfo($path) { - return \OC\Files\Filesystem::getFileInfo($path); - } - } diff --git a/lib/private/appframework/dependencyinjection/dicontainer.php b/lib/private/appframework/dependencyinjection/dicontainer.php index 3755d45fa09..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; @@ -35,6 +35,7 @@ use OC\AppFramework\Utility\TimeFactory; use OCP\AppFramework\IApi; use OCP\AppFramework\IAppContainer; use OCP\AppFramework\IMiddleWare; +use OCP\AppFramework\Middleware; use OCP\IServerContainer; @@ -49,9 +50,10 @@ class DIContainer extends SimpleContainer implements IAppContainer{ * Put your class dependencies in here * @param string $appName the name of the app */ - public function __construct($appName){ + public function __construct($appName, $urlParams = array()){ $this['AppName'] = $appName; + $this['urlParams'] = $urlParams; $this->registerParameter('ServerContainer', \OC::$server); @@ -66,6 +68,7 @@ class DIContainer extends SimpleContainer implements IAppContainer{ /** @var $c SimpleContainer */ /** @var $server IServerContainer */ $server = $c->query('ServerContainer'); + $server->registerParameter('urlParams', $c['urlParams']); return $server->getRequest(); }); @@ -85,15 +88,17 @@ class DIContainer extends SimpleContainer implements IAppContainer{ /** * Middleware */ - $this['SecurityMiddleware'] = $this->share(function($c){ - return new SecurityMiddleware($c['API'], $c['Request']); + $app = $this; + $this['SecurityMiddleware'] = $this->share(function($c) use ($app){ + return new SecurityMiddleware($app, $c['Request']); }); - $this['MiddlewareDispatcher'] = $this->share(function($c){ + $middleWares = $this->middleWares; + $this['MiddlewareDispatcher'] = $this->share(function($c) use ($middleWares) { $dispatcher = new MiddlewareDispatcher(); $dispatcher->registerMiddleware($c['SecurityMiddleware']); - foreach($this->middleWares as $middleWare) { + foreach($middleWares as $middleWare) { $dispatcher->registerMiddleware($middleWare); } @@ -129,10 +134,10 @@ class DIContainer extends SimpleContainer implements IAppContainer{ } /** - * @param IMiddleWare $middleWare + * @param Middleware $middleWare * @return boolean */ - function registerMiddleWare(IMiddleWare $middleWare) { + function registerMiddleWare(Middleware $middleWare) { array_push($this->middleWares, $middleWare); } @@ -143,4 +148,49 @@ class DIContainer extends SimpleContainer implements IAppContainer{ function getAppName() { return $this->query('AppName'); } + + /** + * @return boolean + */ + function isLoggedIn() { + return \OC_User::isLoggedIn(); + } + + /** + * @return boolean + */ + function isAdminUser() { + $uid = $this->getUserId(); + return \OC_User::isAdminUser($uid); + } + + private function getUserId() { + return \OC::$session->get('user_id'); + } + + /** + * @param $message + * @param $level + * @return mixed + */ + function log($message, $level) { + switch($level){ + case 'debug': + $level = \OCP\Util::DEBUG; + break; + case 'info': + $level = \OCP\Util::INFO; + break; + case 'warn': + $level = \OCP\Util::WARN; + break; + case 'fatal': + $level = \OCP\Util::FATAL; + break; + default: + $level = \OCP\Util::ERROR; + break; + } + \OCP\Util::writeLog($this->getAppName(), $message, $level); + } } 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 ea57a6860cc..a2afb53f0fa 100644 --- a/lib/private/appframework/http/dispatcher.php +++ b/lib/private/appframework/http/dispatcher.php @@ -24,8 +24,9 @@ namespace OC\AppFramework\Http; -use \OC\AppFramework\Controller\Controller; 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/http/request.php b/lib/private/appframework/http/request.php index 34605acdfea..3e1f4ff87ed 100644 --- a/lib/private/appframework/http/request.php +++ b/lib/private/appframework/http/request.php @@ -31,6 +31,8 @@ use OCP\IRequest; class Request implements \ArrayAccess, \Countable, IRequest { + protected $inputStream; + protected $content; protected $items = array(); protected $allowedKeys = array( 'get', @@ -40,35 +42,48 @@ class Request implements \ArrayAccess, \Countable, IRequest { 'env', 'cookies', 'urlParams', - 'params', 'parameters', - 'method' + 'method', + 'requesttoken', ); /** * @param array $vars An associative array with the following optional values: - * @param array 'params' the parsed json array * @param array 'urlParams' the parameters which were matched from the URL * @param array 'get' the $_GET array - * @param array 'post' the $_POST array + * @param array|string 'post' the $_POST array or JSON string * @param array 'files' the $_FILES array * @param array 'server' the $_SERVER array * @param array 'env' the $_ENV array - * @param array 'session' the $_SESSION array * @param array 'cookies' the $_COOKIE array * @param string 'method' the request method (GET, POST etc) + * @param string|false 'requesttoken' the requesttoken or false when not available * @see http://www.php.net/manual/en/reserved.variables.php */ public function __construct(array $vars=array()) { foreach($this->allowedKeys as $name) { - $this->items[$name] = isset($vars[$name]) + $this->items[$name] = isset($vars[$name]) ? $vars[$name] : array(); } + if (defined('PHPUNIT_RUN') && PHPUNIT_RUN + && in_array('fakeinput', stream_get_wrappers())) { + $this->inputStream = 'fakeinput://data'; + } else { + $this->inputStream = 'php://input'; + } + + // Only 'application/x-www-form-urlencoded' requests are automatically + // transformed by PHP, 'application/json' must be decoded manually. + if ($this->method === 'POST' + && strpos($this->getHeader('Content-Type'), 'application/json') !== false + ) { + $this->items['params'] = $this->items['post'] = json_decode(file_get_contents($this->inputStream), true); + } + $this->items['parameters'] = array_merge( - $this->items['params'], $this->items['get'], $this->items['post'], $this->items['urlParams'] @@ -141,17 +156,22 @@ class Request implements \ArrayAccess, \Countable, IRequest { * $request->myvar; or $request->{'myvar'}; or $request->{$myvar} * Looks in the combined GET, POST and urlParams array. * - * if($request->method !== 'POST') { - * throw new Exception('This function can only be invoked using POST'); - * } + * If you access e.g. ->post but the current HTTP request method + * is GET a \LogicException will be thrown. * * @param string $name The key to look for. + * @throws \LogicException * @return mixed|null */ public function __get($name) { switch($name) { + case 'put': + case 'patch': case 'get': case 'post': + if($this->method !== strtoupper($name)) { + throw new \LogicException(sprintf('%s cannot be accessed in a %s request.', $name, $this->method)); + } case 'files': case 'server': case 'env': @@ -159,9 +179,13 @@ class Request implements \ArrayAccess, \Countable, IRequest { case 'parameters': case 'params': case 'urlParams': - return isset($this->items[$name]) - ? $this->items[$name] - : null; + if(in_array($name, array('put', 'patch'))) { + return $this->getContent($name); + } else { + return isset($this->items[$name]) + ? $this->items[$name] + : null; + } break; case 'method': return $this->items['method']; @@ -280,28 +304,86 @@ class Request implements \ArrayAccess, \Countable, IRequest { /** * Returns the request body content. * - * @param Boolean $asResource If true, a resource will be returned + * If the HTTP request method is PUT and the body + * not application/x-www-form-urlencoded or application/json a stream + * resource is returned, otherwise an array. * - * @return string|resource The request body content or a resource to read the body stream. + * @return array|string|resource The request body content or a resource to read the body stream. * * @throws \LogicException */ - function getContent($asResource = false) { - return null; -// if (false === $this->content || (true === $asResource && null !== $this->content)) { -// throw new \LogicException('getContent() can only be called once when using the resource return type.'); -// } -// -// if (true === $asResource) { -// $this->content = false; -// -// return fopen('php://input', 'rb'); -// } -// -// if (null === $this->content) { -// $this->content = file_get_contents('php://input'); -// } -// -// return $this->content; + protected function getContent() { + if ($this->content === false && $this->method === 'PUT') { + throw new \LogicException( + '"put" can only be accessed once if not ' + . 'application/x-www-form-urlencoded or application/json.' + ); + } + + // If the content can't be parsed into an array then return a stream resource. + if ($this->method === 'PUT' + && strpos($this->getHeader('Content-Type'), 'application/x-www-form-urlencoded') === false + && strpos($this->getHeader('Content-Type'), 'application/json') === false + ) { + $this->content = false; + return fopen($this->inputStream, 'rb'); + } + + if (is_null($this->content)) { + $this->content = file_get_contents($this->inputStream); + + /* + * Normal jquery ajax requests are sent as application/x-www-form-urlencoded + * and in $_GET and $_POST PHP transformes the data into an array. + * The first condition mimics this. + * The second condition allows for sending raw application/json data while + * still getting the result as an array. + * + */ + if (strpos($this->getHeader('Content-Type'), 'application/x-www-form-urlencoded') !== false) { + parse_str($this->content, $content); + if(is_array($content)) { + $this->content = $content; + } + } elseif (strpos($this->getHeader('Content-Type'), 'application/json') !== false) { + $content = json_decode($this->content, true); + if(is_array($content)) { + $this->content = $content; + } + } + } + + return $this->content; } -} + + /** + * Checks if the CSRF check was correct + * @return bool true if CSRF check passed + * @see OC_Util::$callLifespan + * @see OC_Util::callRegister() + */ + public function passesCSRFCheck() { + if($this->items['requesttoken'] === false) { + return false; + } + + if (isset($this->items['get']['requesttoken'])) { + $token = $this->items['get']['requesttoken']; + } elseif (isset($this->items['post']['requesttoken'])) { + $token = $this->items['post']['requesttoken']; + } elseif (isset($this->items['server']['HTTP_REQUESTTOKEN'])) { + $token = $this->items['server']['HTTP_REQUESTTOKEN']; + } else { + //no token found. + return false; + } + + // Check if the token is valid + if($token !== $this->items['requesttoken']) { + // Not valid + return false; + } else { + // Valid token + return true; + } + }} diff --git a/lib/private/appframework/middleware/middlewaredispatcher.php b/lib/private/appframework/middleware/middlewaredispatcher.php index 70ab108e6b8..681140c2242 100644 --- a/lib/private/appframework/middleware/middlewaredispatcher.php +++ b/lib/private/appframework/middleware/middlewaredispatcher.php @@ -24,9 +24,9 @@ namespace OC\AppFramework\Middleware; -use OC\AppFramework\Controller\Controller; +use OCP\AppFramework\Controller; use OCP\AppFramework\Http\Response; - +use OCP\AppFramework\MiddleWare; /** * This class is used to store and run all the middleware in correct order diff --git a/lib/private/appframework/middleware/security/securitymiddleware.php b/lib/private/appframework/middleware/security/securitymiddleware.php index 4f1447e1afb..c3143754823 100644 --- a/lib/private/appframework/middleware/security/securitymiddleware.php +++ b/lib/private/appframework/middleware/security/securitymiddleware.php @@ -24,15 +24,14 @@ namespace OC\AppFramework\Middleware\Security; -use OC\AppFramework\Controller\Controller; -use OC\AppFramework\Http\Http; -use OC\AppFramework\Http\Request; +use OC\AppFramework\Http; use OC\AppFramework\Http\RedirectResponse; use OC\AppFramework\Utility\MethodAnnotationReader; -use OC\AppFramework\Middleware\Middleware; -use OC\AppFramework\Core\API; +use OCP\AppFramework\Middleware; use OCP\AppFramework\Http\Response; use OCP\AppFramework\Http\JSONResponse; +use OCP\AppFramework\IAppContainer; +use OCP\IRequest; /** @@ -43,18 +42,22 @@ use OCP\AppFramework\Http\JSONResponse; */ class SecurityMiddleware extends Middleware { - private $api; + /** + * @var \OCP\AppFramework\IAppContainer + */ + private $app; /** - * @var \OC\AppFramework\Http\Request + * @var \OCP\IRequest */ private $request; /** - * @param API $api an instance of the api + * @param IAppContainer $app + * @param IRequest $request */ - public function __construct(API $api, Request $request){ - $this->api = $api; + public function __construct(IAppContainer $app, IRequest $request){ + $this->app = $app; $this->request = $request; } @@ -74,24 +77,24 @@ class SecurityMiddleware extends Middleware { // this will set the current navigation entry of the app, use this only // for normal HTML requests and not for AJAX requests - $this->api->activateNavigationEntry(); + $this->app->getServer()->getNavigationManager()->setActiveEntry($this->app->getAppName()); // security checks $isPublicPage = $annotationReader->hasAnnotation('PublicPage'); if(!$isPublicPage) { - if(!$this->api->isLoggedIn()) { + if(!$this->app->isLoggedIn()) { throw new SecurityException('Current user is not logged in', Http::STATUS_UNAUTHORIZED); } if(!$annotationReader->hasAnnotation('NoAdminRequired')) { - if(!$this->api->isAdminUser($this->api->getUserId())) { + if(!$this->app->isAdminUser()) { throw new SecurityException('Logged in user must be an admin', Http::STATUS_FORBIDDEN); } } } if(!$annotationReader->hasAnnotation('NoCSRFRequired')) { - if(!$this->api->passesCSRFCheck()) { + if(!$this->request->passesCSRFCheck()) { throw new SecurityException('CSRF check failed', Http::STATUS_PRECONDITION_FAILED); } } @@ -118,12 +121,13 @@ class SecurityMiddleware extends Middleware { array('message' => $exception->getMessage()), $exception->getCode() ); - $this->api->log($exception->getMessage(), 'debug'); + $this->app->log($exception->getMessage(), 'debug'); } else { - $url = $this->api->linkToAbsolute('index.php', ''); // TODO: replace with link to route + // TODO: replace with link to route + $url = $this->app->getServer()->getURLGenerator()->getAbsoluteURL('index.php'); $response = new RedirectResponse($url); - $this->api->log($exception->getMessage(), 'debug'); + $this->app->log($exception->getMessage(), 'debug'); } return $response; diff --git a/lib/private/appframework/routing/routeactionhandler.php b/lib/private/appframework/routing/routeactionhandler.php index 7fb56f14eab..2b9dc38dc43 100644 --- a/lib/private/appframework/routing/routeactionhandler.php +++ b/lib/private/appframework/routing/routeactionhandler.php @@ -37,6 +37,6 @@ class RouteActionHandler { } public function __invoke($params) { - App::main($this->controllerName, $this->actionName, $params, $this->container); + App::main($this->controllerName, $this->actionName, $this->container, $params); } } diff --git a/lib/private/appframework/utility/simplecontainer.php b/lib/private/appframework/utility/simplecontainer.php index 7e4db63bde5..e631e657756 100644 --- a/lib/private/appframework/utility/simplecontainer.php +++ b/lib/private/appframework/utility/simplecontainer.php @@ -3,7 +3,7 @@ namespace OC\AppFramework\Utility; // register 3rdparty autoloaders -require_once __DIR__ . '/../../../../3rdparty/Pimple/Pimple.php'; +require_once 'Pimple/Pimple.php'; /** * Class SimpleContainer diff --git a/lib/private/apphelper.php b/lib/private/apphelper.php new file mode 100644 index 00000000000..bd02f3aabfa --- /dev/null +++ b/lib/private/apphelper.php @@ -0,0 +1,25 @@ +<?php +/** + * Copyright (c) 2013 Bart Visscher <bartv@thisnet.nl> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + * + */ + +namespace OC; + +/** + * TODO: Description + */ +class AppHelper implements \OCP\IHelper { + /** + * Gets the content of an URL by using CURL or a fallback if it is not + * installed + * @param string $url the url that should be fetched + * @return string the content of the webpage + */ + public function getUrlContent($url) { + return \OC_Util::getUrlContent($url); + } +} diff --git a/lib/private/avatar.php b/lib/private/avatar.php index f20980c364b..e97f55eecaf 100644 --- a/lib/private/avatar.php +++ b/lib/private/avatar.php @@ -10,7 +10,7 @@ * This class gets and sets users avatars. */ -class OC_Avatar { +class OC_Avatar implements \OCP\IAvatar { private $view; @@ -24,7 +24,7 @@ class OC_Avatar { /** * @brief get the users avatar - * @param $size integer size in px of the avatar, defaults to 64 + * @param $size integer size in px of the avatar, avatars are square, defaults to 64 * @return boolean|\OC_Image containing the avatar or false if there's no image */ public function get ($size = 64) { @@ -44,21 +44,23 @@ class OC_Avatar { /** * @brief sets the users avatar - * @param $data mixed imagedata or path to set a new avatar + * @param $data mixed OC_Image, imagedata or path to set a new avatar * @throws Exception if the provided file is not a jpg or png image * @throws Exception if the provided image is not valid * @throws \OC\NotSquareException if the image is not square * @return void */ public function set ($data) { - if (\OC_App::isEnabled('files_encryption')) { - $l = \OC_L10N::get('lib'); - throw new \Exception($l->t("Custom profile pictures don't work with encryption yet")); + if($data instanceOf OC_Image) { + $img = $data; + $data = $img->data(); + } else { + $img = new OC_Image($data); } - - $img = new OC_Image($data); $type = substr($img->mimeType(), -3); - if ($type === 'peg') { $type = 'jpg'; } + if ($type === 'peg') { + $type = 'jpg'; + } if ($type !== 'jpg' && $type !== 'png') { $l = \OC_L10N::get('lib'); throw new \Exception($l->t("Unknown filetype")); diff --git a/lib/private/avatarmanager.php b/lib/private/avatarmanager.php new file mode 100644 index 00000000000..3ca46868ea6 --- /dev/null +++ b/lib/private/avatarmanager.php @@ -0,0 +1,26 @@ +<?php +/** + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC; + +use OCP\IAvatarManager; + +/* + * This class implements methods to access Avatar functionality + */ +class AvatarManager implements IAvatarManager { + + /** + * @brief return a user specific instance of \OCP\IAvatar + * @see \OCP\IAvatar + * @param $user string the ownCloud user id + * @return \OCP\IAvatar + */ + function getAvatar($user) { + return new \OC_Avatar($user); + } +} diff --git a/lib/private/backgroundjob/job.php b/lib/private/backgroundjob/job.php index 49fbffbd684..92bd0f8fdbd 100644 --- a/lib/private/backgroundjob/job.php +++ b/lib/private/backgroundjob/job.php @@ -9,16 +9,35 @@ namespace OC\BackgroundJob; abstract class Job { + /** + * @var int $id + */ protected $id; + + /** + * @var int $lastRun + */ protected $lastRun; + + /** + * @var mixed $argument + */ protected $argument; /** * @param JobList $jobList + * @param \OC\Log $logger */ - public function execute($jobList) { + public function execute($jobList, $logger = null) { $jobList->setLastRun($this); - $this->run($this->argument); + try { + $this->run($this->argument); + } catch (\Exception $e) { + if ($logger) { + $logger->error('Error while running background job: ' . $e->getMessage()); + } + $jobList->remove($this, $this->argument); + } } abstract protected function run($argument); diff --git a/lib/private/backgroundjob/joblist.php b/lib/private/backgroundjob/joblist.php index cc803dd9b5f..99743a70c77 100644 --- a/lib/private/backgroundjob/joblist.php +++ b/lib/private/backgroundjob/joblist.php @@ -138,7 +138,7 @@ class JobList { $job = new $class(); $job->setId($row['id']); $job->setLastRun($row['last_run']); - $job->setArgument(json_decode($row['argument'])); + $job->setArgument(json_decode($row['argument'], true)); return $job; } diff --git a/lib/private/backgroundjob/queuedjob.php b/lib/private/backgroundjob/queuedjob.php index 1714182820d..799eac47848 100644 --- a/lib/private/backgroundjob/queuedjob.php +++ b/lib/private/backgroundjob/queuedjob.php @@ -20,9 +20,10 @@ abstract class QueuedJob extends Job { * run the job, then remove it from the joblist * * @param JobList $jobList + * @param \OC\Log $logger */ - public function execute($jobList) { + public function execute($jobList, $logger = null) { $jobList->remove($this); - $this->run($this->argument); + parent::execute($jobList, $logger); } } diff --git a/lib/private/backgroundjob/timedjob.php b/lib/private/backgroundjob/timedjob.php index ae9f33505ab..09e05f1d846 100644 --- a/lib/private/backgroundjob/timedjob.php +++ b/lib/private/backgroundjob/timedjob.php @@ -31,11 +31,11 @@ abstract class TimedJob extends Job { * run the job if * * @param JobList $jobList + * @param \OC\Log $logger */ - public function execute($jobList) { + public function execute($jobList, $logger = null) { if ((time() - $this->lastRun) > $this->interval) { - $jobList->setLastRun($this); - $this->run($this->argument); + parent::execute($jobList, $logger); } } } diff --git a/lib/private/cache/file.php b/lib/private/cache/file.php index 2ab914d17b8..b0738d2a92b 100644 --- a/lib/private/cache/file.php +++ b/lib/private/cache/file.php @@ -41,6 +41,24 @@ class File { return $result; } + /** + * Returns the size of the stored/cached data + * + * @param $key + * @return int + */ + public function size($key) { + $result = 0; + $proxyStatus = \OC_FileProxy::$enabled; + \OC_FileProxy::$enabled = false; + if ($this->hasKey($key)) { + $storage = $this->getStorage(); + $result = $storage->filesize($key); + } + \OC_FileProxy::$enabled = $proxyStatus; + return $result; + } + public function set($key, $value, $ttl=0) { $storage = $this->getStorage(); $result = false; diff --git a/lib/private/config.php b/lib/private/config.php index e773e6e2eb0..8a9d5ca6158 100644 --- a/lib/private/config.php +++ b/lib/private/config.php @@ -50,7 +50,7 @@ class Config { protected $debugMode; /** - * @param $configDir path to the config dir, needs to end with '/' + * @param string $configDir path to the config dir, needs to end with '/' */ public function __construct($configDir) { $this->configDir = $configDir; @@ -160,7 +160,6 @@ class Config { */ private function writeData() { // Create a php file ... - $defaults = new \OC_Defaults; $content = "<?php\n"; if ($this->debugMode) { $content .= "define('DEBUG',true);\n"; @@ -172,7 +171,8 @@ class Config { // Write the file $result = @file_put_contents($this->configFilename, $content); if (!$result) { - $url = $defaults->getDocBaseUrl() . '/server/5.0/admin_manual/installation/installation_source.html#set-the-directory-permissions'; + $defaults = new \OC_Defaults; + $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/aborteduploaddetectionplugin.php b/lib/private/connector/sabre/aborteduploaddetectionplugin.php index 15dca3a6809..10cca647e8d 100644 --- a/lib/private/connector/sabre/aborteduploaddetectionplugin.php +++ b/lib/private/connector/sabre/aborteduploaddetectionplugin.php @@ -53,6 +53,12 @@ class OC_Connector_Sabre_AbortedUploadDetectionPlugin extends Sabre_DAV_ServerPl */ public function verifyContentLength($filePath, Sabre_DAV_INode $node = null) { + // we should only react on PUT which is used for upload + // e.g. with LOCK this will not work, but LOCK uses createFile() as well + if ($this->server->httpRequest->getMethod() !== 'PUT' ) { + return; + } + // ownCloud chunked upload will be handled in its own plugin $chunkHeader = $this->server->httpRequest->getHeader('OC-Chunked'); if ($chunkHeader) { diff --git a/lib/private/connector/sabre/auth.php b/lib/private/connector/sabre/auth.php index bf3a49593cb..0c84fa6b757 100644 --- a/lib/private/connector/sabre/auth.php +++ b/lib/private/connector/sabre/auth.php @@ -72,7 +72,8 @@ class OC_Connector_Sabre_Auth extends Sabre_DAV_Auth_Backend_AbstractBasic { * @return bool */ public function authenticate(Sabre_DAV_Server $server, $realm) { - if (OC_User::isLoggedIn()) { + + if (OC_User::handleApacheAuth() || OC_User::isLoggedIn()) { $user = OC_User::getUser(); OC_Util::setupFS($user); $this->currentUser = $user; diff --git a/lib/private/connector/sabre/directory.php b/lib/private/connector/sabre/directory.php index 382bdf06df1..02d1a9f4ba2 100644 --- a/lib/private/connector/sabre/directory.php +++ b/lib/private/connector/sabre/directory.php @@ -50,51 +50,31 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa */ public function createFile($name, $data = null) { - if (!\OC\Files\Filesystem::isCreatable($this->path)) { + if ($name === 'Shared' && empty($this->path)) { throw new \Sabre_DAV_Exception_Forbidden(); } + // for chunked upload also updating a existing file is a "createFile" + // because we create all the chunks before reasamble them to the existing file. if (isset($_SERVER['HTTP_OC_CHUNKED'])) { - $info = OC_FileChunking::decodeName($name); - if (empty($info)) { - throw new Sabre_DAV_Exception_NotImplemented(); - } - $chunk_handler = new OC_FileChunking($info); - $chunk_handler->store($info['index'], $data); - if ($chunk_handler->isComplete()) { - $newPath = $this->path . '/' . $info['name']; - $chunk_handler->file_assemble($newPath); - return OC_Connector_Sabre_Node::getETagPropertyForPath($newPath); - } - } else { - $newPath = $this->path . '/' . $name; - - // mark file as partial while uploading (ignored by the scanner) - $partpath = $newPath . '.part'; - \OC\Files\Filesystem::file_put_contents($partpath, $data); - - // rename to correct path - $renameOkay = \OC\Files\Filesystem::rename($partpath, $newPath); - $fileExists = \OC\Files\Filesystem::file_exists($newPath); - if ($renameOkay === false || $fileExists === false) { - \OC_Log::write('webdav', '\OC\Files\Filesystem::rename() failed', \OC_Log::ERROR); - \OC\Files\Filesystem::unlink($partpath); - throw new Sabre_DAV_Exception(); + // exit if we can't create a new file and we don't updatable existing file + $info = OC_FileChunking::decodeName($name); + if (!\OC\Files\Filesystem::isCreatable($this->path) && + !\OC\Files\Filesystem::isUpdatable($this->path . '/' . $info['name'])) { + throw new \Sabre_DAV_Exception_Forbidden(); } - // allow sync clients to send the mtime along in a header - $mtime = OC_Request::hasModificationTime(); - if ($mtime !== false) { - if(\OC\Files\Filesystem::touch($newPath, $mtime)) { - header('X-OC-MTime: accepted'); - } + } else { + // For non-chunked upload it is enough to check if we can create a new file + if (!\OC\Files\Filesystem::isCreatable($this->path)) { + throw new \Sabre_DAV_Exception_Forbidden(); } - - return OC_Connector_Sabre_Node::getETagPropertyForPath($newPath); } - return null; + $path = $this->path . '/' . $name; + $node = new OC_Connector_Sabre_File($path); + return $node->put($data); } /** @@ -106,6 +86,10 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa */ public function createDirectory($name) { + if ($name === 'Shared' && empty($this->path)) { + throw new \Sabre_DAV_Exception_Forbidden(); + } + if (!\OC\Files\Filesystem::isCreatable($this->path)) { throw new \Sabre_DAV_Exception_Forbidden(); } @@ -211,13 +195,16 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa */ public function delete() { - if (!\OC\Files\Filesystem::isDeletable($this->path)) { + if ($this->path === 'Shared') { throw new \Sabre_DAV_Exception_Forbidden(); } - if ($this->path != "/Shared") { - \OC\Files\Filesystem::rmdir($this->path); + + if (!\OC\Files\Filesystem::isDeletable($this->path)) { + throw new \Sabre_DAV_Exception_Forbidden(); } + \OC\Files\Filesystem::rmdir($this->path); + } /** @@ -243,14 +230,14 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa * If the array is empty, all properties should be returned * * @param array $properties - * @return void + * @return array */ public function getProperties($properties) { $props = parent::getProperties($properties); if (in_array(self::GETETAG_PROPERTYNAME, $properties) && !isset($props[self::GETETAG_PROPERTYNAME])) { - $props[self::GETETAG_PROPERTYNAME] - = OC_Connector_Sabre_Node::getETagPropertyForPath($this->path); + $props[self::GETETAG_PROPERTYNAME] = $this->getETagPropertyForPath($this->path); } return $props; } + } diff --git a/lib/private/connector/sabre/exception/entitytoolarge.php b/lib/private/connector/sabre/exception/entitytoolarge.php new file mode 100644 index 00000000000..2bda51f2f3e --- /dev/null +++ b/lib/private/connector/sabre/exception/entitytoolarge.php @@ -0,0 +1,22 @@ +<?php + +/** + * Entity Too Large + * + * This exception is thrown whenever a user tries to upload a file which exceeds hard limitations + * + */ +class OC_Connector_Sabre_Exception_EntityTooLarge extends Sabre_DAV_Exception { + + /** + * Returns the HTTP status code for this exception + * + * @return int + */ + public function getHTTPCode() { + + return 413; + + } + +} diff --git a/lib/private/connector/sabre/exception/unsupportedmediatype.php b/lib/private/connector/sabre/exception/unsupportedmediatype.php new file mode 100644 index 00000000000..95d6a8cc651 --- /dev/null +++ b/lib/private/connector/sabre/exception/unsupportedmediatype.php @@ -0,0 +1,22 @@ +<?php + +/** + * Unsupported Media Type + * + * This exception is thrown whenever a user tries to upload a file which holds content which is not allowed + * + */ +class OC_Connector_Sabre_Exception_UnsupportedMediaType extends Sabre_DAV_Exception { + + /** + * Returns the HTTP status code for this exception + * + * @return int + */ + public function getHTTPCode() { + + return 415; + + } + +} diff --git a/lib/private/connector/sabre/exceptionloggerplugin.php b/lib/private/connector/sabre/exceptionloggerplugin.php new file mode 100644 index 00000000000..8e77afaf207 --- /dev/null +++ b/lib/private/connector/sabre/exceptionloggerplugin.php @@ -0,0 +1,50 @@ +<?php + +/** + * ownCloud + * + * @author Vincent Petry + * @copyright 2014 Vincent Petry <pvince81@owncloud.com> + * + * @license AGPL3 + */ + +class OC_Connector_Sabre_ExceptionLoggerPlugin extends Sabre_DAV_ServerPlugin +{ + private $appName; + + /** + * @param string $loggerAppName app name to use when logging + */ + public function __construct($loggerAppName = 'webdav') { + $this->appName = $loggerAppName; + } + + /** + * This initializes the plugin. + * + * This function is called by Sabre_DAV_Server, after + * addPlugin is called. + * + * This method should set up the required event subscriptions. + * + * @param Sabre_DAV_Server $server + * @return void + */ + public function initialize(Sabre_DAV_Server $server) { + + $server->subscribeEvent('exception', array($this, 'logException'), 10); + } + + /** + * Log exception + * + * @internal param Exception $e exception + */ + public function logException($e) { + $exceptionClass = get_class($e); + if ($exceptionClass !== 'Sabre_DAV_Exception_NotAuthenticated') { + \OCP\Util::logException($this->appName, $e); + } + } +} diff --git a/lib/private/connector/sabre/file.php b/lib/private/connector/sabre/file.php index 433b1148552..ed27cef440d 100644 --- a/lib/private/connector/sabre/file.php +++ b/lib/private/connector/sabre/file.php @@ -28,7 +28,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D * * The data argument is a readable stream resource. * - * After a succesful put operation, you may choose to return an ETag. The + * After a successful put operation, you may choose to return an ETag. The * etag must always be surrounded by double-quotes. These quotes must * appear in the actual string you're returning. * @@ -46,7 +46,10 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D */ public function put($data) { - if (!\OC\Files\Filesystem::isUpdatable($this->path)) { + $fs = $this->getFS(); + + if ($fs->file_exists($this->path) && + !$fs->isUpdatable($this->path)) { throw new \Sabre_DAV_Exception_Forbidden(); } @@ -54,44 +57,66 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D if (\OC_Util::encryptedFiles()) { throw new \Sabre_DAV_Exception_ServiceUnavailable(); } - + + // chunked handling + if (isset($_SERVER['HTTP_OC_CHUNKED'])) { + return $this->createFileChunked($data); + } + // mark file as partial while uploading (ignored by the scanner) - $partpath = $this->path . '.part'; + $partpath = $this->path . '.ocTransferId' . rand() . '.part'; - \OC\Files\Filesystem::file_put_contents($partpath, $data); + // if file is located in /Shared we write the part file to the users + // root folder because we can't create new files in /shared + // we extend the name with a random number to avoid overwriting a existing file + if (dirname($partpath) === 'Shared') { + $partpath = pathinfo($partpath, PATHINFO_FILENAME) . rand() . '.part'; + } - //detect aborted upload - if (isset ($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT') { - if (isset($_SERVER['CONTENT_LENGTH'])) { - $expected = $_SERVER['CONTENT_LENGTH']; - $actual = \OC\Files\Filesystem::filesize($partpath); - if ($actual != $expected) { - \OC\Files\Filesystem::unlink($partpath); - throw new Sabre_DAV_Exception_BadRequest( - 'expected filesize ' . $expected . ' got ' . $actual); - } + try { + $putOkay = $fs->file_put_contents($partpath, $data); + if ($putOkay === false) { + \OC_Log::write('webdav', '\OC\Files\Filesystem::file_put_contents() failed', \OC_Log::ERROR); + $fs->unlink($partpath); + // because we have no clue about the cause we can only throw back a 500/Internal Server Error + throw new Sabre_DAV_Exception('Could not write file contents'); } + } catch (\OCP\Files\NotPermittedException $e) { + // a more general case - due to whatever reason the content could not be written + throw new Sabre_DAV_Exception_Forbidden($e->getMessage()); + + } catch (\OCP\Files\EntityTooLargeException $e) { + // the file is too big to be stored + throw new OC_Connector_Sabre_Exception_EntityTooLarge($e->getMessage()); + + } catch (\OCP\Files\InvalidContentException $e) { + // the file content is not permitted + throw new OC_Connector_Sabre_Exception_UnsupportedMediaType($e->getMessage()); + + } catch (\OCP\Files\InvalidPathException $e) { + // the path for the file was not valid + // TODO: find proper http status code for this case + throw new Sabre_DAV_Exception_Forbidden($e->getMessage()); } // rename to correct path - $renameOkay = \OC\Files\Filesystem::rename($partpath, $this->path); - $fileExists = \OC\Files\Filesystem::file_exists($this->path); + $renameOkay = $fs->rename($partpath, $this->path); + $fileExists = $fs->file_exists($this->path); if ($renameOkay === false || $fileExists === false) { \OC_Log::write('webdav', '\OC\Files\Filesystem::rename() failed', \OC_Log::ERROR); - \OC\Files\Filesystem::unlink($partpath); - throw new Sabre_DAV_Exception(); + $fs->unlink($partpath); + throw new Sabre_DAV_Exception('Could not rename part file to final file'); } - - //allow sync clients to send the mtime along in a header + // allow sync clients to send the mtime along in a header $mtime = OC_Request::hasModificationTime(); if ($mtime !== false) { - if (\OC\Files\Filesystem::touch($this->path, $mtime)) { + if($fs->touch($this->path, $mtime)) { header('X-OC-MTime: accepted'); } } - return OC_Connector_Sabre_Node::getETagPropertyForPath($this->path); + return $this->getETagPropertyForPath($this->path); } /** @@ -101,7 +126,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D */ public function get() { - //throw execption if encryption is disabled but files are still encrypted + //throw exception if encryption is disabled but files are still encrypted if (\OC_Util::encryptedFiles()) { throw new \Sabre_DAV_Exception_ServiceUnavailable(); } else { @@ -118,11 +143,18 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D */ public function delete() { + if ($this->path === 'Shared') { + throw new \Sabre_DAV_Exception_Forbidden(); + } + if (!\OC\Files\Filesystem::isDeletable($this->path)) { throw new \Sabre_DAV_Exception_Forbidden(); } \OC\Files\Filesystem::unlink($this->path); + // remove properties + $this->removeProperties(); + } /** @@ -144,7 +176,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D * * An ETag is a unique identifier representing the current version of the * file. If the file changes, the ETag MUST change. The ETag is an - * arbritrary string, but MUST be surrounded by double-quotes. + * arbitrary string, but MUST be surrounded by double-quotes. * * Return null if the ETag can not effectively be determined * @@ -173,4 +205,62 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D return \OC\Files\Filesystem::getMimeType($this->path); } + + private function createFileChunked($data) + { + list($path, $name) = \Sabre_DAV_URLUtil::splitPath($this->path); + + $info = OC_FileChunking::decodeName($name); + if (empty($info)) { + throw new Sabre_DAV_Exception_NotImplemented(); + } + $chunk_handler = new OC_FileChunking($info); + $bytesWritten = $chunk_handler->store($info['index'], $data); + + //detect aborted upload + if (isset ($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT' ) { + if (isset($_SERVER['CONTENT_LENGTH'])) { + $expected = $_SERVER['CONTENT_LENGTH']; + if ($bytesWritten != $expected) { + $chunk_handler->remove($info['index']); + throw new Sabre_DAV_Exception_BadRequest( + 'expected filesize ' . $expected . ' got ' . $bytesWritten); + } + } + } + + if ($chunk_handler->isComplete()) { + + // we first assembly the target file as a part file + $partFile = $path . '/' . $info['name'] . '.ocTransferId' . $info['transferid'] . '.part'; + $chunk_handler->file_assemble($partFile); + + // here is the final atomic rename + $fs = $this->getFS(); + $targetPath = $path . '/' . $info['name']; + $renameOkay = $fs->rename($partFile, $targetPath); + $fileExists = $fs->file_exists($targetPath); + if ($renameOkay === false || $fileExists === false) { + \OC_Log::write('webdav', '\OC\Files\Filesystem::rename() failed', \OC_Log::ERROR); + // only delete if an error occurred and the target file was already created + if ($fileExists) { + $fs->unlink($targetPath); + } + throw new Sabre_DAV_Exception('Could not rename part file assembled from chunks'); + } + + // allow sync clients to send the mtime along in a header + $mtime = OC_Request::hasModificationTime(); + if ($mtime !== false) { + if($fs->touch($targetPath, $mtime)) { + header('X-OC-MTime: accepted'); + } + } + + return OC_Connector_Sabre_Node::getETagPropertyForPath($targetPath); + } + + return null; + } + } diff --git a/lib/private/connector/sabre/filesplugin.php b/lib/private/connector/sabre/filesplugin.php new file mode 100644 index 00000000000..65231040fb5 --- /dev/null +++ b/lib/private/connector/sabre/filesplugin.php @@ -0,0 +1,103 @@ +<?php + +/** + * ownCloud + * + * @author Thomas Müller + * @copyright 2013 Thomas Müller <thomas.mueller@tmit.eu> + * + * @license AGPL3 + */ + +class OC_Connector_Sabre_FilesPlugin extends Sabre_DAV_ServerPlugin +{ + + // namespace + const NS_OWNCLOUD = 'http://owncloud.org/ns'; + + /** + * Reference to main server object + * + * @var Sabre_DAV_Server + */ + private $server; + + /** + * This initializes the plugin. + * + * This function is called by Sabre_DAV_Server, after + * addPlugin is called. + * + * This method should set up the required event subscriptions. + * + * @param Sabre_DAV_Server $server + * @return void + */ + public function initialize(Sabre_DAV_Server $server) { + + $server->xmlNamespaces[self::NS_OWNCLOUD] = 'oc'; + $server->protectedProperties[] = '{' . self::NS_OWNCLOUD . '}id'; + + $this->server = $server; + $this->server->subscribeEvent('beforeGetProperties', array($this, 'beforeGetProperties')); + $this->server->subscribeEvent('afterCreateFile', array($this, 'sendFileIdHeader')); + $this->server->subscribeEvent('afterWriteContent', array($this, 'sendFileIdHeader')); + } + + /** + * Adds all ownCloud-specific properties + * + * @param string $path + * @param Sabre_DAV_INode $node + * @param array $requestedProperties + * @param array $returnedProperties + * @return void + */ + public function beforeGetProperties($path, Sabre_DAV_INode $node, array &$requestedProperties, array &$returnedProperties) { + + if ($node instanceof OC_Connector_Sabre_Node) { + + $fileid_propertyname = '{' . self::NS_OWNCLOUD . '}id'; + if (array_search($fileid_propertyname, $requestedProperties)) { + unset($requestedProperties[array_search($fileid_propertyname, $requestedProperties)]); + } + + /** @var $node OC_Connector_Sabre_Node */ + $fileId = $node->getFileId(); + if (!is_null($fileId)) { + $returnedProperties[200][$fileid_propertyname] = $fileId; + } + + } + + } + + /** + * @param $filePath + * @param Sabre_DAV_INode $node + * @throws Sabre_DAV_Exception_BadRequest + */ + public function sendFileIdHeader($filePath, Sabre_DAV_INode $node = null) { + // chunked upload handling + if (isset($_SERVER['HTTP_OC_CHUNKED'])) { + list($path, $name) = \Sabre_DAV_URLUtil::splitPath($filePath); + $info = OC_FileChunking::decodeName($name); + if (!empty($info)) { + $filePath = $path . '/' . $info['name']; + } + } + + // we get the node for the given $filePath here because in case of afterCreateFile $node is the parent folder + if (!$this->server->tree->nodeExists($filePath)) { + return; + } + $node = $this->server->tree->getNodeForPath($filePath); + if ($node instanceof OC_Connector_Sabre_Node) { + $fileId = $node->getFileId(); + if (!is_null($fileId)) { + $this->server->httpResponse->setHeader('OC-FileId', $fileId); + } + } + } + +} diff --git a/lib/private/connector/sabre/node.php b/lib/private/connector/sabre/node.php index 29b7f9e53a5..993aa73faeb 100644 --- a/lib/private/connector/sabre/node.php +++ b/lib/private/connector/sabre/node.php @@ -33,11 +33,19 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr public static $ETagFunction = null; /** + * is kept public to allow overwrite for unit testing + * + * @var \OC\Files\View + */ + public $fileView; + + /** * The path to the current node * * @var string */ protected $path; + /** * node fileinfo cache * @var array @@ -140,12 +148,6 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr * Even if the modification time is set to a custom value the access time is set to now. */ public function touch($mtime) { - - // touch is only allowed if the update privilege is granted - if (!\OC\Files\Filesystem::isUpdatable($this->path)) { - throw new \Sabre_DAV_Exception_Forbidden(); - } - \OC\Files\Filesystem::touch($this->path, $mtime); } @@ -190,6 +192,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 @@ -199,6 +212,7 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr * properties should be returned */ public function getProperties($properties) { + if (is_null($this->property_cache)) { $sql = 'SELECT * FROM `*PREFIX*properties` WHERE `userid` = ? AND `propertypath` = ?'; $result = OC_DB::executeAudited( $sql, array( OC_User::getUser(), $this->path ) ); @@ -207,7 +221,14 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr while( $row = $result->fetchRow()) { $this->property_cache[$row['propertyname']] = $row['propertyvalue']; } - $this->property_cache[self::GETETAG_PROPERTYNAME] = $this->getETagPropertyForPath($this->path); + + // Don't call the static getETagPropertyForPath, its result is not cached + $this->getFileinfoCache(); + if ($this->fileinfo_cache['etag']) { + $this->property_cache[self::GETETAG_PROPERTYNAME] = '"'.$this->fileinfo_cache['etag'].'"'; + } else { + $this->property_cache[self::GETETAG_PROPERTYNAME] = null; + } } // if the array was empty, we need to return everything @@ -217,8 +238,11 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr $props = array(); foreach($properties as $property) { - if (isset($this->property_cache[$property])) $props[$property] = $this->property_cache[$property]; + if (isset($this->property_cache[$property])) { + $props[$property] = $this->property_cache[$property]; + } } + return $props; } @@ -227,12 +251,34 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr * @param string $path Path of the file * @return string|null Returns null if the ETag can not effectively be determined */ - static public function getETagPropertyForPath($path) { - $data = \OC\Files\Filesystem::getFileInfo($path); + protected function getETagPropertyForPath($path) { + $data = $this->getFS()->getFileInfo($path); if (isset($data['etag'])) { return '"'.$data['etag'].'"'; } return null; } + protected function getFS() { + if (is_null($this->fileView)) { + $this->fileView = \OC\Files\Filesystem::getView(); + } + return $this->fileView; + } + + /** + * @return mixed + */ + public function getFileId() + { + $this->getFileinfoCache(); + + if (isset($this->fileinfo_cache['fileid'])) { + $instanceId = OC_Util::getInstanceId(); + $id = sprintf('%08d', $this->fileinfo_cache['fileid']); + return $id . $instanceId; + } + + return null; + } } diff --git a/lib/private/connector/sabre/objecttree.php b/lib/private/connector/sabre/objecttree.php index 80c3840b99d..cd3f081f7cc 100644 --- a/lib/private/connector/sabre/objecttree.php +++ b/lib/private/connector/sabre/objecttree.php @@ -87,6 +87,9 @@ class ObjectTree extends \Sabre_DAV_ObjectTree { if (!$fs->isUpdatable($destinationDir)) { throw new \Sabre_DAV_Exception_Forbidden(); } + if (!$fs->isDeletable($sourcePath)) { + throw new \Sabre_DAV_Exception_Forbidden(); + } } $renameOkay = $fs->rename($sourcePath, $destinationPath); @@ -94,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.php b/lib/private/db.php index 1e5d12649df..562065259fa 100644 --- a/lib/private/db.php +++ b/lib/private/db.php @@ -101,6 +101,9 @@ class OC_DB { ); $connectionParams['adapter'] = '\OC\DB\Adapter'; $connectionParams['wrapperClass'] = 'OC\DB\Connection'; + // Send "SET NAMES utf8". Only required on PHP 5.3 below 5.3.6. + // See http://stackoverflow.com/questions/4361459/php-pdo-charset-set-names#4361485 + $eventManager->addEventSubscriber(new \Doctrine\DBAL\Event\Listeners\MysqlSessionInit); break; case 'pgsql': $connectionParams = array( diff --git a/lib/private/db/adaptersqlsrv.php b/lib/private/db/adaptersqlsrv.php index d0a67af28a7..a6bc0e21052 100644 --- a/lib/private/db/adaptersqlsrv.php +++ b/lib/private/db/adaptersqlsrv.php @@ -10,13 +10,6 @@ namespace OC\DB; class AdapterSQLSrv extends Adapter { - public function lastInsertId($table) { - if($table !== null) { - $table = $this->conn->replaceTablePrefix( $table ); - } - return $this->conn->lastInsertId($table); - } - public function fixupStatement($statement) { $statement = preg_replace( "/\`(.*?)`/", "[$1]", $statement ); $statement = str_ireplace( 'NOW()', 'CURRENT_TIMESTAMP', $statement ); 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 8e76f46c78f..6378c769055 100644 --- a/lib/private/db/mdb2schemamanager.php +++ b/lib/private/db/mdb2schemamanager.php @@ -19,6 +19,8 @@ class MDB2SchemaManager { */ public function __construct($conn) { $this->conn = $conn; + $this->conn->close(); + $this->conn->connect(); } /** @@ -53,7 +55,7 @@ class MDB2SchemaManager { * @param string $file file to read structure from * @return bool */ - public function updateDbFromStructure($file) { + public function updateDbFromStructure($file, $generateSql = false) { $sm = $this->conn->getSchemaManager(); $fromSchema = $sm->createSchema(); @@ -61,6 +63,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,10 +80,13 @@ 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); + } return $this->executeSchemaChange($schemaDiff); } @@ -106,6 +112,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()); } @@ -147,4 +154,20 @@ class MDB2SchemaManager { $this->conn->commit(); return true; } + + /** + * @param \Doctrine\DBAL\Schema\Schema $schema + * @return string + */ + public function generateChangeScript($schema) { + + $script = ''; + $sqls = $schema->toSql($this->conn->getDatabasePlatform()); + foreach($sqls as $sql) { + $script .= $sql . ';'; + $script .= PHP_EOL; + } + + return $script; + } } diff --git a/lib/private/db/mdb2schemareader.php b/lib/private/db/mdb2schemareader.php index b7128a2f176..b1fd2454cb0 100644 --- a/lib/private/db/mdb2schemareader.php +++ b/lib/private/db/mdb2schemareader.php @@ -150,6 +150,9 @@ class MDB2SchemaReader { case 'timestamp': $type = 'datetime'; break; + case 'numeric': + $type = 'decimal'; + break; } break; case 'length': @@ -180,20 +183,28 @@ class MDB2SchemaReader { $primary = $this->asBool($child); $options['primary'] = $primary; break; + case 'precision': + $precision = (string)$child; + $options['precision'] = $precision; + break; + case 'scale': + $scale = (string)$child; + $options['scale'] = $scale; + break; default: throw new \DomainException('Unknown element: ' . $child->getName()); } } if (isset($name) && isset($type)) { - if (empty($options['default'])) { + if (isset($options['default']) && empty($options['default'])) { if (empty($options['notnull']) || !$options['notnull']) { unset($options['default']); $options['notnull'] = false; } else { $options['default'] = ''; } - if ($type == 'integer') { + if ($type == 'integer' || $type == 'decimal') { $options['default'] = 0; } elseif ($type == 'boolean') { $options['default'] = false; diff --git a/lib/private/db/statementwrapper.php b/lib/private/db/statementwrapper.php index b8da1afc0e5..5e89261d936 100644 --- a/lib/private/db/statementwrapper.php +++ b/lib/private/db/statementwrapper.php @@ -30,25 +30,6 @@ class OC_DB_StatementWrapper { } /** - * provide numRows - */ - public function numRows() { - $type = OC_Config::getValue( "dbtype", "sqlite" ); - if ($type == 'oci') { - // OCI doesn't have a queryString, just do a rowCount for now - return $this->statement->rowCount(); - } - $regex = '/^SELECT\s+(?:ALL\s+|DISTINCT\s+)?(?:.*?)\s+FROM\s+(.*)$/i'; - $queryString = $this->statement->getWrappedStatement()->queryString; - if (preg_match($regex, $queryString, $output) > 0) { - $query = OC_DB::prepare("SELECT COUNT(*) FROM {$output[1]}"); - return $query->execute($this->lastArguments)->fetchColumn(); - }else{ - return $this->statement->rowCount(); - } - } - - /** * make execute return the result instead of a bool */ public function execute($input=array()) { diff --git a/lib/private/defaults.php b/lib/private/defaults.php index 10813a3e8d8..cec9a65c7f3 100644 --- a/lib/private/defaults.php +++ b/lib/private/defaults.php @@ -1,18 +1,17 @@ <?php -/** - * Default strings and values which differ between the enterprise and the - * community edition. Use the get methods to always get the right strings. - */ - - if (file_exists(OC::$SERVERROOT . '/themes/' . OC_Util::getTheme() . '/defaults.php')) { require_once 'themes/' . OC_Util::getTheme() . '/defaults.php'; } +/** + * Default strings and values which differ between the enterprise and the + * community edition. Use the get methods to always get the right strings. + */ class OC_Defaults { private $theme; + private $l; private $defaultEntity; private $defaultName; @@ -24,7 +23,7 @@ class OC_Defaults { private $defaultLogoClaim; function __construct() { - $l = OC_L10N::get('core'); + $this->l = OC_L10N::get('core'); $this->defaultEntity = "ownCloud"; /* e.g. company name, used for footers and copyright notices */ $this->defaultName = "ownCloud"; /* short name, used when referring to the software */ @@ -32,7 +31,7 @@ class OC_Defaults { $this->defaultBaseUrl = "http://owncloud.org"; $this->defaultSyncClientUrl = " http://owncloud.org/sync-clients/"; $this->defaultDocBaseUrl = "http://doc.owncloud.org"; - $this->defaultSlogan = $l->t("web services under your control"); + $this->defaultSlogan = $this->l->t("web services under your control"); $this->defaultLogoClaim = ""; if (class_exists("OC_Theme")) { @@ -47,6 +46,10 @@ class OC_Defaults { return false; } + /** + * Returns the base URL + * @return string URL + */ public function getBaseUrl() { if ($this->themeExist('getBaseUrl')) { return $this->theme->getBaseUrl(); @@ -55,6 +58,10 @@ class OC_Defaults { } } + /** + * Returns the URL where the sync clients are listed + * @return string URL + */ public function getSyncClientUrl() { if ($this->themeExist('getSyncClientUrl')) { return $this->theme->getSyncClientUrl(); @@ -63,6 +70,10 @@ class OC_Defaults { } } + /** + * Returns the documentation URL + * @return string URL + */ public function getDocBaseUrl() { if ($this->themeExist('getDocBaseUrl')) { return $this->theme->getDocBaseUrl(); @@ -71,6 +82,10 @@ class OC_Defaults { } } + /** + * Returns the title + * @return string title + */ public function getTitle() { if ($this->themeExist('getTitle')) { return $this->theme->getTitle(); @@ -79,6 +94,10 @@ class OC_Defaults { } } + /** + * Returns the short name of the software + * @return string title + */ public function getName() { if ($this->themeExist('getName')) { return $this->theme->getName(); @@ -87,6 +106,10 @@ class OC_Defaults { } } + /** + * Returns entity (e.g. company name) - used for footer, copyright + * @return string entity name + */ public function getEntity() { if ($this->themeExist('getEntity')) { return $this->theme->getEntity(); @@ -95,6 +118,10 @@ class OC_Defaults { } } + /** + * Returns slogan + * @return string slogan + */ public function getSlogan() { if ($this->themeExist('getSlogan')) { return $this->theme->getSlogan(); @@ -103,6 +130,10 @@ class OC_Defaults { } } + /** + * Returns logo claim + * @return string logo claim + */ public function getLogoClaim() { if ($this->themeExist('getLogoClaim')) { return $this->theme->getLogoClaim(); @@ -111,6 +142,10 @@ class OC_Defaults { } } + /** + * Returns short version of the footer + * @return string short footer + */ public function getShortFooter() { if ($this->themeExist('getShortFooter')) { $footer = $this->theme->getShortFooter(); @@ -122,6 +157,10 @@ class OC_Defaults { return $footer; } + /** + * Returns long version of the footer + * @return string long footer + */ public function getLongFooter() { if ($this->themeExist('getLongFooter')) { $footer = $this->theme->getLongFooter(); diff --git a/lib/private/eventsource.php b/lib/private/eventsource.php index a83084d9251..4df0bc2e7cd 100644 --- a/lib/private/eventsource.php +++ b/lib/private/eventsource.php @@ -64,13 +64,13 @@ class OC_EventSource{ } if($this->fallback) { $response='<script type="text/javascript">window.parent.OC.EventSource.fallBackCallBack(' - .$this->fallBackId.',"'.$type.'",'.json_encode($data).')</script>'.PHP_EOL; + .$this->fallBackId.',"' . $type . '",' . OCP\JSON::encode($data) . ')</script>' . PHP_EOL; echo $response; }else{ if($type) { - echo 'event: '.$type.PHP_EOL; + echo 'event: ' . $type.PHP_EOL; } - echo 'data: '.json_encode($data).PHP_EOL; + echo 'data: ' . OCP\JSON::encode($data) . PHP_EOL; } echo PHP_EOL; flush(); diff --git a/lib/private/filechunking.php b/lib/private/filechunking.php index 313a6ee87d2..aa4f73c7c05 100644 --- a/lib/private/filechunking.php +++ b/lib/private/filechunking.php @@ -34,10 +34,19 @@ class OC_FileChunking { return $this->cache; } + /** + * Stores the given $data under the given $key - the number of stored bytes is returned + * + * @param $index + * @param $data + * @return int + */ public function store($index, $data) { $cache = $this->getCache(); $name = $this->getPrefix().$index; $cache->set($name, $data); + + return $cache->size($name); } public function isComplete() { @@ -58,12 +67,34 @@ class OC_FileChunking { $count = 0; for($i=0; $i < $this->info['chunkcount']; $i++) { $chunk = $cache->get($prefix.$i); - $cache->remove($prefix.$i); $count += fwrite($f, $chunk); } + + $this->cleanup(); return $count; } + /** + * Removes all chunks which belong to this transmission + */ + public function cleanup() { + $cache = $this->getCache(); + $prefix = $this->getPrefix(); + for($i=0; $i < $this->info['chunkcount']; $i++) { + $cache->remove($prefix.$i); + } + } + + /** + * Removes one specific chunk + * @param $index + */ + public function remove($index) { + $cache = $this->getCache(); + $prefix = $this->getPrefix(); + $cache->remove($prefix.$index); + } + public function signature_split($orgfile, $input) { $info = unpack('n', fread($input, 2)); $blocksize = $info[1]; diff --git a/lib/private/fileproxy.php b/lib/private/fileproxy.php index 52ec79b4bdb..2997aaf81b6 100644 --- a/lib/private/fileproxy.php +++ b/lib/private/fileproxy.php @@ -67,7 +67,11 @@ class OC_FileProxy{ self::$proxies[]=$proxy; } - public static function getProxies($operation) { + public static function getProxies($operation = null) { + if ($operation === null) { + // return all + return self::$proxies; + } $proxies=array(); foreach(self::$proxies as $proxy) { if(method_exists($proxy, $operation)) { diff --git a/lib/private/files.php b/lib/private/files.php index c705d2adb1a..8ce632013cf 100644 --- a/lib/private/files.php +++ b/lib/private/files.php @@ -28,8 +28,8 @@ class OC_Files { static $tmpFiles = array(); - static public function getFileInfo($path){ - return \OC\Files\Filesystem::getFileInfo($path); + static public function getFileInfo($path, $includeMountPoints = true){ + return \OC\Files\Filesystem::getFileInfo($path, $includeMountPoints); } static public function getDirectoryContent($path){ @@ -83,7 +83,7 @@ class OC_Files { if ($basename) { $name = $basename . '.zip'; } else { - $name = 'owncloud.zip'; + $name = 'download.zip'; } set_time_limit($executionTime); @@ -109,15 +109,13 @@ class OC_Files { $zip = false; $filename = $dir . '/' . $files; $name = $files; + if ($xsendfile && OC_App::isEnabled('files_encryption')) { + $xsendfile = false; + } } OC_Util::obEnd(); if ($zip or \OC\Files\Filesystem::isReadable($filename)) { - if ( preg_match( "/MSIE/", $_SERVER["HTTP_USER_AGENT"] ) ) { - header( 'Content-Disposition: attachment; filename="' . rawurlencode($name) . '"' ); - } else { - header( 'Content-Disposition: attachment; filename*=UTF-8\'\'' . rawurlencode($name) - . '; filename="' . rawurlencode($name) . '"' ); - } + OC_Response::setContentDispositionHeader($name, 'attachment'); header('Content-Transfer-Encoding: binary'); OC_Response::disableCaching(); if ($zip) { @@ -131,9 +129,11 @@ class OC_Files { if ($filesize > -1) { header("Content-Length: ".$filesize); } - list($storage) = \OC\Files\Filesystem::resolvePath($filename); - if ($storage instanceof \OC\Files\Storage\Local) { - self::addSendfileHeader(\OC\Files\Filesystem::getLocalFile($filename)); + if ($xsendfile) { + list($storage) = \OC\Files\Filesystem::resolvePath(\OC\Files\Filesystem::getView()->getAbsolutePath($filename)); + if ($storage instanceof \OC\Files\Storage\Local) { + self::addSendfileHeader(\OC\Files\Filesystem::getLocalFile($filename)); + } } } } elseif ($zip or !\OC\Files\Filesystem::file_exists($filename)) { @@ -251,7 +251,7 @@ class OC_Files { header("HTTP/1.0 409 Conflict"); OC_Template::printErrorPage( $l->t('Selected files too large to generate zip file.'), - $l->t('Download the files in smaller chunks, seperately or kindly ask your administrator.') + $l->t('Please download the files separately in smaller chunks or kindly ask your administrator.') .'<br/><a href="javascript:history.back()">' . $l->t('Back to Files') . '</a>' ); diff --git a/lib/private/files/cache/cache.php b/lib/private/files/cache/cache.php index e69733727af..1e7936ca26d 100644 --- a/lib/private/files/cache/cache.php +++ b/lib/private/files/cache/cache.php @@ -34,8 +34,8 @@ class Cache { */ private $storageCache; - private $mimetypeIds = array(); - private $mimetypes = array(); + private static $mimetypeIds = array(); + private static $mimetypes = array(); /** * @param \OC\Files\Storage\Storage|string $storage @@ -64,30 +64,45 @@ class Cache { * @return int */ public function getMimetypeId($mime) { - if (!isset($this->mimetypeIds[$mime])) { - $result = \OC_DB::executeAudited('SELECT `id` FROM `*PREFIX*mimetypes` WHERE `mimetype` = ?', array($mime)); - if ($row = $result->fetchRow()) { - $this->mimetypeIds[$mime] = $row['id']; - } else { + if (empty($mime)) { + // Can not insert empty string into Oracle NOT NULL column. + $mime = 'application/octet-stream'; + } + if (empty(self::$mimetypeIds)) { + $this->loadMimetypes(); + } + + if (!isset(self::$mimetypeIds[$mime])) { + try{ $result = \OC_DB::executeAudited('INSERT INTO `*PREFIX*mimetypes`(`mimetype`) VALUES(?)', array($mime)); - $this->mimetypeIds[$mime] = \OC_DB::insertid('*PREFIX*mimetypes'); + self::$mimetypeIds[$mime] = \OC_DB::insertid('*PREFIX*mimetypes'); + self::$mimetypes[self::$mimetypeIds[$mime]] = $mime; } - $this->mimetypes[$this->mimetypeIds[$mime]] = $mime; - } - return $this->mimetypeIds[$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]; } public function getMimetype($id) { - if (!isset($this->mimetypes[$id])) { - $sql = 'SELECT `mimetype` FROM `*PREFIX*mimetypes` WHERE `id` = ?'; - $result = \OC_DB::executeAudited($sql, array($id)); - if ($row = $result->fetchRow()) { - $this->mimetypes[$id] = $row['mimetype']; - } else { - return null; - } + if (empty(self::$mimetypes)) { + $this->loadMimetypes(); } - return $this->mimetypes[$id]; + + return isset(self::$mimetypes[$id]) ? self::$mimetypes[$id] : null; + } + + public function loadMimetypes(){ + $result = \OC_DB::executeAudited('SELECT `id`, `mimetype` FROM `*PREFIX*mimetypes`', array()); + if ($result) { + while ($row = $result->fetchRow()) { + self::$mimetypeIds[$row['mimetype']] = $row['id']; + self::$mimetypes[$row['id']] = $row['mimetype']; + } + } } /** @@ -129,6 +144,7 @@ class Cache { $data['fileid'] = (int)$data['fileid']; $data['size'] = (int)$data['size']; $data['mtime'] = (int)$data['mtime']; + $data['storage_mtime'] = (int)$data['storage_mtime']; $data['encrypted'] = (bool)$data['encrypted']; $data['unencrypted_size'] = (int)$data['unencrypted_size']; $data['storage'] = $this->storageId; @@ -162,6 +178,10 @@ class Cache { if ($file['storage_mtime'] == 0) { $file['storage_mtime'] = $file['mtime']; } + if ($file['encrypted'] or ($file['unencrypted_size'] > 0 and $file['mimetype'] === 'httpd/unix-directory')) { + $file['encrypted_size'] = $file['size']; + $file['size'] = $file['unencrypted_size']; + } } return $files; } else { @@ -491,22 +511,34 @@ class Cache { $entry = $this->get($path); if ($entry && $entry['mimetype'] === 'httpd/unix-directory') { $id = $entry['fileid']; - $sql = 'SELECT SUM(`size`), MIN(`size`) FROM `*PREFIX*filecache` '. + $sql = 'SELECT SUM(`size`) AS f1, MIN(`size`) AS f2, ' . + 'SUM(`unencrypted_size`) AS f3 ' . + 'FROM `*PREFIX*filecache` ' . 'WHERE `parent` = ? AND `storage` = ?'; $result = \OC_DB::executeAudited($sql, array($id, $this->getNumericStorageId())); if ($row = $result->fetchRow()) { - list($sum, $min) = array_values($row); + list($sum, $min, $unencryptedSum) = array_values($row); $sum = (int)$sum; $min = (int)$min; + $unencryptedSum = (int)$unencryptedSum; if ($min === -1) { $totalSize = $min; } else { $totalSize = $sum; } + $update = array(); if ($entry['size'] !== $totalSize) { - $this->update($id, array('size' => $totalSize)); + $update['size'] = $totalSize; + } + if ($entry['unencrypted_size'] !== $unencryptedSum) { + $update['unencrypted_size'] = $unencryptedSum; + } + if (count($update) > 0) { + $this->update($id, $update); + } + if ($totalSize !== -1 and $unencryptedSum > 0) { + $totalSize = $unencryptedSum; } - } } return $totalSize; diff --git a/lib/private/files/cache/homecache.php b/lib/private/files/cache/homecache.php new file mode 100644 index 00000000000..71bb944da71 --- /dev/null +++ b/lib/private/files/cache/homecache.php @@ -0,0 +1,53 @@ +<?php +/** + * Copyright (c) 2012 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 OC\Files\Cache; + +class HomeCache extends Cache { + /** + * get the size of a folder and set it in the cache + * + * @param string $path + * @return int + */ + public function calculateFolderSize($path) { + if ($path !== '/' and $path !== '' and $path !== 'files') { + return parent::calculateFolderSize($path); + } + + $totalSize = 0; + $entry = $this->get($path); + if ($entry && $entry['mimetype'] === 'httpd/unix-directory') { + $id = $entry['fileid']; + $sql = 'SELECT SUM(`size`) FROM `*PREFIX*filecache` ' . + 'WHERE `parent` = ? AND `storage` = ? AND `size` >= 0'; + $result = \OC_DB::executeAudited($sql, array($id, $this->getNumericStorageId())); + if ($row = $result->fetchRow()) { + list($sum) = array_values($row); + $totalSize = (int)$sum; + if ($entry['size'] !== $totalSize) { + $this->update($id, array('size' => $totalSize)); + } + } + } + return $totalSize; + } + + public function get($path) { + $data = parent::get($path); + if ($path === '' or $path === '/') { + // only the size of the "files" dir counts + $filesData = parent::get('files'); + + if (isset($filesData['size'])) { + $data['size'] = $filesData['size']; + } + } + return $data; + } +} diff --git a/lib/private/files/cache/scanner.php b/lib/private/files/cache/scanner.php index 96f84609cf2..92a4c01841b 100644 --- a/lib/private/files/cache/scanner.php +++ b/lib/private/files/cache/scanner.php @@ -17,6 +17,8 @@ use OC\Hooks\BasicEmitter; * Hooks available in scope \OC\Files\Cache\Scanner: * - scanFile(string $path, string $storageId) * - scanFolder(string $path, string $storageId) + * - postScanFile(string $path, string $storageId) + * - postScanFolder(string $path, string $storageId) * * @package OC\Files\Cache */ @@ -62,8 +64,12 @@ class Scanner extends BasicEmitter { * @return array with metadata of the file */ public function getData($path) { + if (!$this->storage->isReadable($path)) { + //cant read, nothing we can do + \OCP\Util::writeLog('OC\Files\Cache\Scanner', "!!! Path '$path' is not readable !!!", \OCP\Util::DEBUG); + return null; + } $data = array(); - if (!$this->storage->isReadable($path)) return null; //cant read, nothing we can do $data['mimetype'] = $this->storage->getMimeType($path); $data['mtime'] = $this->storage->filemtime($path); if ($data['mimetype'] == 'httpd/unix-directory') { @@ -104,7 +110,9 @@ class Scanner extends BasicEmitter { $newData = $data; $cacheData = $this->cache->get($file); if ($cacheData) { - $this->permissionsCache->remove($cacheData['fileid']); + if (isset($cacheData['fileid'])) { + $this->permissionsCache->remove($cacheData['fileid']); + } if ($reuseExisting) { // prevent empty etag $etag = $cacheData['etag']; @@ -114,7 +122,7 @@ class Scanner extends BasicEmitter { $propagateETagChange = true; } // only reuse data if the file hasn't explicitly changed - if (isset($data['mtime']) && isset($cacheData['mtime']) && $data['mtime'] === $cacheData['mtime']) { + if (isset($data['storage_mtime']) && isset($cacheData['storage_mtime']) && $data['storage_mtime'] === $cacheData['storage_mtime']) { if (($reuseExisting & self::REUSE_SIZE) && ($data['size'] === -1)) { $data['size'] = $cacheData['size']; } @@ -136,11 +144,20 @@ class Scanner extends BasicEmitter { } } // Only update metadata that has changed - $newData = array_diff($data, $cacheData); + $newData = array_diff_assoc($data, $cacheData); + if (isset($newData['etag'])) { + $cacheDataString = print_r($cacheData, true); + $dataString = print_r($data, true); + \OCP\Util::writeLog('OC\Files\Cache\Scanner', + "!!! No reuse of etag for '$file' !!! \ncache: $cacheDataString \ndata: $dataString", + \OCP\Util::DEBUG); + } } } if (!empty($newData)) { $this->cache->put($file, $newData); + $this->emit('\OC\Files\Cache\Scanner', 'postScanFile', array($file, $this->storageId)); + \OC_Hook::emit('\OC\Files\Cache\Scanner', 'post_scan_file', array('path' => $file, 'storage' => $this->storageId)); } } else { $this->cache->remove($file); @@ -190,24 +207,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 +244,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) { @@ -227,6 +262,7 @@ class Scanner extends BasicEmitter { } $this->cache->put($path, array('size' => $size)); } + $this->emit('\OC\Files\Cache\Scanner', 'postScanFolder', array($path, $this->storageId)); return $size; } @@ -250,7 +286,7 @@ class Scanner extends BasicEmitter { public function backgroundScan() { $lastPath = null; while (($path = $this->cache->getIncomplete()) !== false && $path !== $lastPath) { - $this->scan($path); + $this->scan($path, self::SCAN_RECURSIVE, self::REUSE_ETAG); $this->cache->correctFolderSize($path); $lastPath = $path; } diff --git a/lib/private/files/cache/storage.php b/lib/private/files/cache/storage.php index 8a9e47ca36d..5657cf06e12 100644 --- a/lib/private/files/cache/storage.php +++ b/lib/private/files/cache/storage.php @@ -48,7 +48,7 @@ class Storage { } public static function getStorageId($numericId) { - + $sql = 'SELECT `id` FROM `*PREFIX*storages` WHERE `numeric_id` = ?'; $result = \OC_DB::executeAudited($sql, array($numericId)); if ($row = $result->fetchRow()) { @@ -57,4 +57,17 @@ class Storage { return null; } } + + public static function exists($storageId) { + if (strlen($storageId) > 64) { + $storageId = md5($storageId); + } + $sql = 'SELECT `numeric_id` FROM `*PREFIX*storages` WHERE `id` = ?'; + $result = \OC_DB::executeAudited($sql, array($storageId)); + if ($row = $result->fetchRow()) { + return true; + } else { + return false; + } + } } diff --git a/lib/private/files/cache/updater.php b/lib/private/files/cache/updater.php index 1f30173a8f8..73bc30e538f 100644 --- a/lib/private/files/cache/updater.php +++ b/lib/private/files/cache/updater.php @@ -7,6 +7,7 @@ */ namespace OC\Files\Cache; + use OCP\Util; /** @@ -42,6 +43,7 @@ class Updater { $scanner->scan($internalPath, Scanner::SCAN_SHALLOW); $cache->correctFolderSize($internalPath); self::correctFolder($path, $storage->filemtime($internalPath)); + self::correctParentStorageMtime($storage, $internalPath); } } @@ -57,10 +59,15 @@ class Updater { */ list($storage, $internalPath) = self::resolvePath($path); if ($storage) { + $parent = dirname($internalPath); + if ($parent === '.') { + $parent = ''; + } $cache = $storage->getCache($internalPath); $cache->remove($internalPath); - $cache->correctFolderSize($internalPath); + $cache->correctFolderSize($parent); self::correctFolder($path, time()); + self::correctParentStorageMtime($storage, $internalPath); } } @@ -83,10 +90,18 @@ class Updater { 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)); + } $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); @@ -95,6 +110,24 @@ class Updater { } /** + * @brief get file owner and path + * @param string $filename + * @return array with the oweners uid and the owners path + */ + private static function getUidAndFilename($filename) { + + $uid = \OC\Files\Filesystem::getOwner($filename); + \OC\Files\Filesystem::initMountPoints($uid); + + if ($uid != \OCP\User::getUser()) { + $info = \OC\Files\Filesystem::getFileInfo($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 @@ -102,29 +135,53 @@ class Updater { */ static public function correctFolder($path, $time) { if ($path !== '' && $path !== '/') { - $parent = dirname($path); - if ($parent === '.' || $parent === '\\') { - $parent = ''; - } + + list($owner, $realPath) = self::getUidAndFilename(dirname($path)); + /** * @var \OC\Files\Storage\Storage $storage * @var string $internalPath */ - list($storage, $internalPath) = self::resolvePath($parent); - if ($storage) { - $cache = $storage->getCache(); - $id = $cache->getId($internalPath); - if ($id !== -1) { - $cache->update($id, array('mtime' => $time, 'etag' => $storage->getETag($internalPath))); - self::correctFolder($parent, $time); + $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 { - Util::writeLog('core', 'Path not in cache: '.$internalPath, Util::ERROR); + $id = -1; } } } } /** + * update the storage_mtime of the parent + * + * @param \OC\Files\Storage\Storage $storage + * @param string $internalPath + */ + static private function correctParentStorageMtime($storage, $internalPath) { + $cache = $storage->getCache(); + $parentId = $cache->getParentId($internalPath); + $parent = dirname($internalPath); + if ($parentId != -1) { + $cache->update($parentId, array('storage_mtime' => $storage->filemtime($parent))); + } + } + + /** * @param array $params */ static public function writeHook($params) { diff --git a/lib/private/files/cache/upgrade.php b/lib/private/files/cache/upgrade.php index cfb9a117311..e3a46896cbf 100644 --- a/lib/private/files/cache/upgrade.php +++ b/lib/private/files/cache/upgrade.php @@ -192,7 +192,15 @@ class Upgrade { */ static function needUpgrade($user) { $cacheVersion = (int)\OCP\Config::getUserValue($user, 'files', 'cache_version', 4); - return $cacheVersion < 5; + if ($cacheVersion < 5) { + $legacy = new \OC\Files\Cache\Legacy($user); + if ($legacy->hasItems()) { + return true; + } + self::upgradeDone($user); + } + + return false; } /** diff --git a/lib/private/files/cache/watcher.php b/lib/private/files/cache/watcher.php index 8bfd4602f3a..251ecbe7071 100644 --- a/lib/private/files/cache/watcher.php +++ b/lib/private/files/cache/watcher.php @@ -15,17 +15,17 @@ class Watcher { /** * @var \OC\Files\Storage\Storage $storage */ - private $storage; + protected $storage; /** * @var Cache $cache */ - private $cache; + protected $cache; /** * @var Scanner $scanner; */ - private $scanner; + protected $scanner; /** * @param \OC\Files\Storage\Storage $storage @@ -40,6 +40,7 @@ class Watcher { * check $path for updates * * @param string $path + * @return boolean | array true if path was updated, otherwise the cached data is returned */ public function checkUpdate($path) { $cachedEntry = $this->cache->get($path); @@ -53,7 +54,9 @@ class Watcher { $this->cleanFolder($path); } $this->cache->correctFolderSize($path); + return true; } + return $cachedEntry; } /** diff --git a/lib/private/files/filesystem.php b/lib/private/files/filesystem.php index 10ec5c41d11..a83e9aa86d2 100644 --- a/lib/private/files/filesystem.php +++ b/lib/private/files/filesystem.php @@ -305,7 +305,21 @@ class Filesystem { $parser = new \OC\ArrayParser(); $root = \OC_User::getHome($user); - self::mount('\OC\Files\Storage\Local', array('datadir' => $root), $user); + + $userObject = \OC_User::getManager()->get($user); + + if (!is_null($userObject)) { + // check for legacy home id (<= 5.0.12) + if (\OC\Files\Cache\Storage::exists('local::' . $root . '/')) { + self::mount('\OC\Files\Storage\Home', array('user' => $userObject, 'legacy' => true), $user); + } + else { + self::mount('\OC\Files\Storage\Home', array('user' => $userObject), $user); + } + } + else { + self::mount('\OC\Files\Storage\Local', array('datadir' => $root), $user); + } $datadir = \OC_Config::getValue("datadirectory", \OC::$SERVERROOT . "/data"); //move config file to it's new position @@ -675,18 +689,32 @@ class Filesystem { } //no windows style slashes $path = str_replace('\\', '/', $path); + //add leading slash if ($path[0] !== '/') { $path = '/' . $path; } - //remove duplicate slashes - while (strpos($path, '//') !== false) { - $path = str_replace('//', '/', $path); + + // remove '/./' + // ugly, but str_replace() can't replace them all in one go + // as the replacement itself is part of the search string + // which will only be found during the next iteration + while (strpos($path, '/./') !== false) { + $path = str_replace('/./', '/', $path); } + // remove sequences of slashes + $path = preg_replace('#/{2,}#', '/', $path); + //remove trailing slash if ($stripTrailingSlash and strlen($path) > 1 and substr($path, -1, 1) === '/') { $path = substr($path, 0, -1); } + + // remove trailing '/.' + if (substr($path, -2) == '/.') { + $path = substr($path, 0, -2); + } + //normalize unicode if possible $path = \OC_Util::normalizeUnicode($path); @@ -697,6 +725,8 @@ class Filesystem { * get the filesystem info * * @param string $path + * @param boolean $includeMountPoints whether to add mountpoint sizes, + * defaults to true * @return array * * returns an associative array with the following keys: @@ -706,8 +736,8 @@ class Filesystem { * - encrypted * - versioned */ - public static function getFileInfo($path) { - return self::$defaultInstance->getFileInfo($path); + public static function getFileInfo($path, $includeMountPoints = true) { + return self::$defaultInstance->getFileInfo($path, $includeMountPoints); } /** diff --git a/lib/private/files/storage/common.php b/lib/private/files/storage/common.php index a5b79f0e967..678bf419023 100644 --- a/lib/private/files/storage/common.php +++ b/lib/private/files/storage/common.php @@ -21,11 +21,11 @@ namespace OC\Files\Storage; */ abstract class Common implements \OC\Files\Storage\Storage { - private $cache; - private $scanner; - private $permissioncache; - private $watcher; - private $storageCache; + protected $cache; + protected $scanner; + protected $permissioncache; + protected $watcher; + protected $storageCache; public function __construct($parameters) { } @@ -51,6 +51,19 @@ abstract class Common implements \OC\Files\Storage\Storage { } } + public function isReadable($path) { + // at least check whether it exists + // subclasses might want to implement this more thoroughly + return $this->file_exists($path); + } + + public function isUpdatable($path) { + // at least check whether it exists + // subclasses might want to implement this more thoroughly + // a non-existing file/folder isn't updatable + return $this->file_exists($path); + } + public function isCreatable($path) { if ($this->is_dir($path) && $this->isUpdatable($path)) { return true; @@ -142,7 +155,7 @@ abstract class Common implements \OC\Files\Storage\Storage { return false; } else { $directoryHandle = $this->opendir($directory); - if(is_resource($directoryHandle)) { + if (is_resource($directoryHandle)) { while (($contents = readdir($directoryHandle)) !== false) { if (!\OC\Files\Filesystem::isIgnoredDir($contents)) { $path = $directory . '/' . $contents; @@ -165,27 +178,13 @@ abstract class Common implements \OC\Files\Storage\Storage { } public function getMimeType($path) { - if (!$this->file_exists($path)) { - return false; - } if ($this->is_dir($path)) { return 'httpd/unix-directory'; - } - $source = $this->fopen($path, 'r'); - if (!$source) { - return false; - } - $head = fread($source, 8192); //8kb should suffice to determine a mimetype - if ($pos = strrpos($path, '.')) { - $extension = substr($path, $pos); + } elseif ($this->file_exists($path)) { + return \OC_Helper::getFileNameMimeType($path); } else { - $extension = ''; + return false; } - $tmpFile = \OC_Helper::tmpFile($extension); - file_put_contents($tmpFile, $head); - $mime = \OC_Helper::getMimeType($tmpFile); - unlink($tmpFile); - return $mime; } public function hash($type, $path, $raw = false) { @@ -227,7 +226,7 @@ abstract class Common implements \OC\Files\Storage\Storage { private function addLocalFolder($path, $target) { $dh = $this->opendir($path); - if(is_resource($dh)) { + if (is_resource($dh)) { while (($file = readdir($dh)) !== false) { if ($file !== '.' and $file !== '..') { if ($this->is_dir($path . '/' . $file)) { @@ -298,7 +297,7 @@ abstract class Common implements \OC\Files\Storage\Storage { return $this->watcher; } - public function getStorageCache(){ + public function getStorageCache() { if (!isset($this->storageCache)) { $this->storageCache = new \OC\Files\Cache\Storage($this); } diff --git a/lib/private/files/storage/commontest.php b/lib/private/files/storage/commontest.php index c3f1eb31955..2394b14a82f 100644 --- a/lib/private/files/storage/commontest.php +++ b/lib/private/files/storage/commontest.php @@ -54,7 +54,7 @@ class CommonTest extends \OC\Files\Storage\Common{ return $this->storage->stat($path); } public function filetype($path) { - return $this->storage->filetype($path); + return @$this->storage->filetype($path); } public function isReadable($path) { return $this->storage->isReadable($path); diff --git a/lib/private/files/storage/home.php b/lib/private/files/storage/home.php new file mode 100644 index 00000000000..1c2a682f197 --- /dev/null +++ b/lib/private/files/storage/home.php @@ -0,0 +1,66 @@ +<?php +/** + * Copyright (c) 2012 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 OC\Files\Storage; + +/** + * Specialized version of Local storage for home directory usage + */ +class Home extends Local { + /** + * @var string + */ + protected $id; + + /** + * @var \OC\User\User $user + */ + protected $user; + + /** + * @brief Construct a Home storage instance + * @param array $arguments array with "user" containing the + * storage owner and "legacy" containing "true" if the storage is + * a legacy storage with "local::" URL instead of the new "home::" one. + */ + public function __construct($arguments) { + $this->user = $arguments['user']; + $datadir = $this->user->getHome(); + if (isset($arguments['legacy']) && $arguments['legacy']) { + // legacy home id (<= 5.0.12) + $this->id = 'local::' . $datadir . '/'; + } + else { + $this->id = 'home::' . $this->user->getUID(); + } + + parent::__construct(array('datadir' => $datadir)); + } + + public function getId() { + return $this->id; + } + + /** + * @return \OC\Files\Cache\HomeCache + */ + public function getCache($path = '') { + if (!isset($this->cache)) { + $this->cache = new \OC\Files\Cache\HomeCache($this); + } + return $this->cache; + } + + /** + * @brief Returns the owner of this home storage + * @return \OC\User\User owner of this home storage + */ + public function getUser() { + return $this->user; + } +} diff --git a/lib/private/files/storage/local.php b/lib/private/files/storage/local.php index 5209fabc30a..db3c6bfca3a 100644 --- a/lib/private/files/storage/local.php +++ b/lib/private/files/storage/local.php @@ -203,14 +203,6 @@ if (\OC_Util::runningOnWindows()) { return $return; } - public function getMimeType($path) { - if ($this->isReadable($path)) { - return \OC_Helper::getMimeType($this->datadir . $path); - } else { - return false; - } - } - private function delTree($dir) { $dirRelative = $dir; $dir = $this->datadir . $dir; @@ -264,7 +256,7 @@ if (\OC_Util::runningOnWindows()) { public function free_space($path) { $space = @disk_free_space($this->datadir . $path); - if ($space === false) { + if ($space === false || is_null($space)) { return \OC\Files\SPACE_UNKNOWN; } return $space; diff --git a/lib/private/files/storage/mappedlocal.php b/lib/private/files/storage/mappedlocal.php index ba5ac4191c5..6c37d445867 100644 --- a/lib/private/files/storage/mappedlocal.php +++ b/lib/private/files/storage/mappedlocal.php @@ -210,14 +210,6 @@ class MappedLocal extends \OC\Files\Storage\Common{ return $return; } - public function getMimeType($path) { - if($this->isReadable($path)) { - return \OC_Helper::getMimeType($this->buildPath($path)); - }else{ - return false; - } - } - private function delTree($dir, $isLogicPath=true) { $dirRelative=$dir; if ($isLogicPath) { diff --git a/lib/private/files/storage/storage.php b/lib/private/files/storage/storage.php index b673bb9a32d..5be90f24756 100644 --- a/lib/private/files/storage/storage.php +++ b/lib/private/files/storage/storage.php @@ -14,278 +14,6 @@ namespace OC\Files\Storage; * All paths passed to the storage are relative to the storage and should NOT have a leading slash. */ interface Storage extends \OCP\Files\Storage { - /** - * $parameters is a free form array with the configuration options needed to construct the storage - * - * @param array $parameters - */ - public function __construct($parameters); - - /** - * Get the identifier for the storage, - * the returned id should be the same for every storage object that is created with the same parameters - * and two storage objects with the same id should refer to two storages that display the same files. - * - * @return string - */ - public function getId(); - - /** - * see http://php.net/manual/en/function.mkdir.php - * - * @param string $path - * @return bool - */ - public function mkdir($path); - - /** - * see http://php.net/manual/en/function.rmdir.php - * - * @param string $path - * @return bool - */ - public function rmdir($path); - - /** - * see http://php.net/manual/en/function.opendir.php - * - * @param string $path - * @return resource - */ - public function opendir($path); - - /** - * see http://php.net/manual/en/function.is_dir.php - * - * @param string $path - * @return bool - */ - public function is_dir($path); - - /** - * see http://php.net/manual/en/function.is_file.php - * - * @param string $path - * @return bool - */ - public function is_file($path); - - /** - * see http://php.net/manual/en/function.stat.php - * only the following keys are required in the result: size and mtime - * - * @param string $path - * @return array - */ - public function stat($path); - - /** - * see http://php.net/manual/en/function.filetype.php - * - * @param string $path - * @return bool - */ - public function filetype($path); - - /** - * see http://php.net/manual/en/function.filesize.php - * The result for filesize when called on a folder is required to be 0 - * - * @param string $path - * @return int - */ - public function filesize($path); - - /** - * check if a file can be created in $path - * - * @param string $path - * @return bool - */ - public function isCreatable($path); - - /** - * check if a file can be read - * - * @param string $path - * @return bool - */ - public function isReadable($path); - - /** - * check if a file can be written to - * - * @param string $path - * @return bool - */ - public function isUpdatable($path); - - /** - * check if a file can be deleted - * - * @param string $path - * @return bool - */ - public function isDeletable($path); - - /** - * check if a file can be shared - * - * @param string $path - * @return bool - */ - public function isSharable($path); - - /** - * get the full permissions of a path. - * Should return a combination of the PERMISSION_ constants defined in lib/public/constants.php - * - * @param string $path - * @return int - */ - public function getPermissions($path); - - /** - * see http://php.net/manual/en/function.file_exists.php - * - * @param string $path - * @return bool - */ - public function file_exists($path); - - /** - * see http://php.net/manual/en/function.filemtime.php - * - * @param string $path - * @return int - */ - public function filemtime($path); - - /** - * see http://php.net/manual/en/function.file_get_contents.php - * - * @param string $path - * @return string - */ - public function file_get_contents($path); - - /** - * see http://php.net/manual/en/function.file_put_contents.php - * - * @param string $path - * @param string $data - * @return bool - */ - public function file_put_contents($path, $data); - - /** - * see http://php.net/manual/en/function.unlink.php - * - * @param string $path - * @return bool - */ - public function unlink($path); - - /** - * see http://php.net/manual/en/function.rename.php - * - * @param string $path1 - * @param string $path2 - * @return bool - */ - public function rename($path1, $path2); - - /** - * see http://php.net/manual/en/function.copy.php - * - * @param string $path1 - * @param string $path2 - * @return bool - */ - public function copy($path1, $path2); - - /** - * see http://php.net/manual/en/function.fopen.php - * - * @param string $path - * @param string $mode - * @return resource - */ - public function fopen($path, $mode); - - /** - * get the mimetype for a file or folder - * The mimetype for a folder is required to be "httpd/unix-directory" - * - * @param string $path - * @return string - */ - public function getMimeType($path); - - /** - * see http://php.net/manual/en/function.hash.php - * - * @param string $type - * @param string $path - * @param bool $raw - * @return string - */ - public function hash($type, $path, $raw = false); - - /** - * see http://php.net/manual/en/function.free_space.php - * - * @param string $path - * @return int - */ - public function free_space($path); - - /** - * search for occurrences of $query in file names - * - * @param string $query - * @return array - */ - public function search($query); - - /** - * see http://php.net/manual/en/function.touch.php - * If the backend does not support the operation, false should be returned - * - * @param string $path - * @param int $mtime - * @return bool - */ - public function touch($path, $mtime = null); - - /** - * get the path to a local version of the file. - * The local version of the file can be temporary and doesn't have to be persistent across requests - * - * @param string $path - * @return string - */ - public function getLocalFile($path); - - /** - * get the path to a local version of the folder. - * The local version of the folder can be temporary and doesn't have to be persistent across requests - * - * @param string $path - * @return string - */ - public function getLocalFolder($path); - /** - * check if a file or folder has been updated since $time - * - * @param string $path - * @param int $time - * @return bool - * - * hasUpdated for folders should return at least true if a file inside the folder is add, removed or renamed. - * returning true for other changes in the folder is optional - */ - public function hasUpdated($path, $time); /** * get a cache instance for the storage @@ -333,11 +61,4 @@ interface Storage extends \OCP\Files\Storage { */ public function getStorageCache(); - /** - * get the ETag for a file or folder - * - * @param string $path - * @return string - */ - public function getETag($path); } diff --git a/lib/private/files/storage/wrapper/quota.php b/lib/private/files/storage/wrapper/quota.php index e2da8cf2e05..a430e3e4617 100644 --- a/lib/private/files/storage/wrapper/quota.php +++ b/lib/private/files/storage/wrapper/quota.php @@ -95,7 +95,7 @@ class Quota extends Wrapper { public function fopen($path, $mode) { $source = $this->storage->fopen($path, $mode); $free = $this->free_space(''); - if ($free >= 0) { + if ($source && $free >= 0 && $mode !== 'r' && $mode !== 'rb') { return \OC\Files\Stream\Quota::wrap($source, $free); } else { return $source; diff --git a/lib/private/files/storage/wrapper/wrapper.php b/lib/private/files/storage/wrapper/wrapper.php index 0336c27efa1..f9adda80314 100644 --- a/lib/private/files/storage/wrapper/wrapper.php +++ b/lib/private/files/storage/wrapper/wrapper.php @@ -424,4 +424,12 @@ class Wrapper implements \OC\Files\Storage\Storage { public function getETag($path) { return $this->storage->getETag($path); } + + /** + * Returns true + * @return true + */ + public function test() { + return $this->storage->test(); + } } diff --git a/lib/private/files/stream/quota.php b/lib/private/files/stream/quota.php index 53d8a03d30f..60e60da8e67 100644 --- a/lib/private/files/stream/quota.php +++ b/lib/private/files/stream/quota.php @@ -66,12 +66,24 @@ class Quota { } public function stream_seek($offset, $whence = SEEK_SET) { - if ($whence === SEEK_SET) { + if ($whence === SEEK_END){ + // go to the end to find out last position's offset + $oldOffset = $this->stream_tell(); + if (fseek($this->source, 0, $whence) !== 0){ + return false; + } + $whence = SEEK_SET; + $offset = $this->stream_tell() + $offset; + $this->limit += $oldOffset - $offset; + } + else if ($whence === SEEK_SET) { $this->limit += $this->stream_tell() - $offset; } else { $this->limit -= $offset; } - fseek($this->source, $offset, $whence); + // this wrapper needs to return "true" for success. + // the fseek call itself returns 0 on succeess + return !fseek($this->source, $offset, $whence); } public function stream_tell() { diff --git a/lib/private/files/type/detection.php b/lib/private/files/type/detection.php index 242a81cb5a4..d7cc9ebbf4e 100644 --- a/lib/private/files/type/detection.php +++ b/lib/private/files/type/detection.php @@ -61,8 +61,6 @@ class Detection { * @return string */ public function detect($path) { - $isWrapped = (strpos($path, '://') !== false) and (substr($path, 0, 7) === 'file://'); - if (@is_dir($path)) { // directories are easy return "httpd/unix-directory"; @@ -76,9 +74,11 @@ class Detection { $info = @strtolower(finfo_file($finfo, $path)); if ($info) { $mimeType = substr($info, 0, strpos($info, ';')); + return empty($mimeType) ? 'application/octet-stream' : $mimeType; } finfo_close($finfo); } + $isWrapped = (strpos($path, '://') !== false) and (substr($path, 0, 7) === 'file://'); if (!$isWrapped and $mimeType === 'application/octet-stream' && function_exists("mime_content_type")) { // use mime magic extension if available $mimeType = mime_content_type($path); @@ -94,6 +94,10 @@ class Detection { //trim the newline $mimeType = trim($reply); + if (empty($mimeType)) { + $mimeType = 'application/octet-stream'; + } + } return $mimeType; } diff --git a/lib/private/files/view.php b/lib/private/files/view.php index aa08a5f7cc9..d97544b865e 100644 --- a/lib/private/files/view.php +++ b/lib/private/files/view.php @@ -110,7 +110,9 @@ class View { * @return array consisting of the storage and the internal path */ public function resolvePath($path) { - return Filesystem::resolvePath($this->getAbsolutePath($path)); + $a = $this->getAbsolutePath($path); + $p = Filesystem::normalizePath($a); + return Filesystem::resolvePath($p); } /** @@ -157,7 +159,11 @@ class View { } public function rmdir($path) { - return $this->basicOperation('rmdir', $path, array('delete')); + if ($this->is_dir($path)) { + return $this->basicOperation('rmdir', $path, array('delete')); + } else { + return false; + } } public function opendir($path) { @@ -324,11 +330,25 @@ class View { return false; } } else { - return $this->basicOperation('file_put_contents', $path, array('create', 'write'), $data); + $hooks = ($this->file_exists($path)) ? array('write') : array('create', 'write'); + return $this->basicOperation('file_put_contents', $path, $hooks, $data); } } public function unlink($path) { + if ($path === '' || $path === '/') { + // do not allow deleting the root + return false; + } + $postFix = (substr($path, -1, 1) === '/') ? '/' : ''; + $absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path)); + list($storage, $internalPath) = Filesystem::resolvePath($absolutePath . $postFix); + if (!$internalPath || $internalPath === '' || $internalPath === '/') { + // do not allow deleting the storage's root / the mount point + // because for some storages it might delete the whole contents + // but isn't supposed to work that way + return false; + } return $this->basicOperation('unlink', $path, array('delete')); } @@ -709,7 +729,10 @@ class View { return false; } $defaultRoot = Filesystem::getRoot(); - return (strlen($this->fakeRoot) >= strlen($defaultRoot)) && (substr($this->fakeRoot, 0, strlen($defaultRoot)) === $defaultRoot); + if ($this->fakeRoot === $defaultRoot) { + return true; + } + return (strlen($this->fakeRoot) > strlen($defaultRoot)) && (substr($this->fakeRoot, 0, strlen($defaultRoot) + 1) === $defaultRoot . '/'); } private function runHooks($hooks, $path, $post = false) { @@ -756,6 +779,8 @@ class View { * get the filesystem info * * @param string $path + * @param boolean $includeMountPoints whether to add mountpoint sizes, + * defaults to true * @return array * * returns an associative array with the following keys: @@ -765,7 +790,7 @@ class View { * - encrypted * - versioned */ - public function getFileInfo($path) { + public function getFileInfo($path, $includeMountPoints = true) { $data = array(); if (!Filesystem::isValidPath($path)) { return $data; @@ -776,6 +801,7 @@ class View { * @var string $internalPath */ list($storage, $internalPath) = Filesystem::resolvePath($path); + $data = null; if ($storage) { $cache = $storage->getCache($internalPath); $permissionsCache = $storage->getPermissionsCache($internalPath); @@ -786,13 +812,15 @@ class View { $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW); } else { $watcher = $storage->getWatcher($internalPath); - $watcher->checkUpdate($internalPath); + $data = $watcher->checkUpdate($internalPath); } - $data = $cache->get($internalPath); + if (!is_array($data)) { + $data = $cache->get($internalPath); + } if ($data and $data['fileid']) { - if ($data['mimetype'] === 'httpd/unix-directory') { + if ($includeMountPoints and $data['mimetype'] === 'httpd/unix-directory') { //add the sizes of other mountpoints to the folder $mountPoints = Filesystem::getMountPoints($path); foreach ($mountPoints as $mountPoint) { @@ -898,7 +926,8 @@ class View { $permissions = $subStorage->getPermissions($rootEntry['path']); $subPermissionsCache->set($rootEntry['fileid'], $user, $permissions); } - $rootEntry['permissions'] = $permissions; + // do not allow renaming/deleting the mount point + $rootEntry['permissions'] = $permissions & (\OCP\PERMISSION_ALL - (\OCP\PERMISSION_UPDATE | \OCP\PERMISSION_DELETE)); //remove any existing entry with the same name foreach ($files as $i => $file) { diff --git a/lib/private/group.php b/lib/private/group.php index ba93dc129a1..444788c97f1 100644 --- a/lib/private/group.php +++ b/lib/private/group.php @@ -265,10 +265,10 @@ class OC_Group { public static function displayNamesInGroup($gid, $search = '', $limit = -1, $offset = 0) { $group = self::getManager()->get($gid); if ($group) { - $users = $group->searchDisplayName($search . $limit, $offset); + $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/group/group.php b/lib/private/group/group.php index bcd2419b309..8d2aa87a788 100644 --- a/lib/private/group/group.php +++ b/lib/private/group/group.php @@ -18,7 +18,12 @@ class Group { /** * @var \OC\User\User[] $users */ - private $users; + private $users = array(); + + /** + * @var bool $usersLoaded + */ + private $usersLoaded; /** * @var \OC_Group_Backend[] | \OC_Group_Database[] $backend @@ -26,7 +31,7 @@ class Group { private $backends; /** - * @var \OC\Hooks\PublicEmitter $emitter; + * @var \OC\Hooks\PublicEmitter $emitter */ private $emitter; @@ -58,7 +63,7 @@ class Group { * @return \OC\User\User[] */ public function getUsers() { - if ($this->users) { + if ($this->usersLoaded) { return $this->users; } @@ -74,6 +79,7 @@ class Group { } $this->users = $this->getVerifiedUsers($userIds); + $this->usersLoaded = true; return $this->users; } @@ -84,8 +90,12 @@ class Group { * @return bool */ public function inGroup($user) { + if (isset($this->users[$user->getUID()])) { + return true; + } foreach ($this->backends as $backend) { if ($backend->inGroup($user->getUID(), $this->gid)) { + $this->users[$user->getUID()] = $user; return true; } } @@ -185,6 +195,7 @@ class Group { * @return \OC\User\User[] */ public function searchDisplayName($search, $limit = null, $offset = null) { + $users = array(); foreach ($this->backends as $backend) { if ($backend->implementsActions(OC_GROUP_BACKEND_GET_DISPLAYNAME)) { $userIds = array_keys($backend->displayNamesInGroup($this->gid, $search, $limit, $offset)); @@ -229,17 +240,17 @@ class Group { /** * @brief returns all the Users from an array that really exists - * @param $userIds an array containing user IDs - * @return an Array with the userId as Key and \OC\User\User as value + * @param string[] $userIds an array containing user IDs + * @return \OC\User\User[] an Array with the userId as Key and \OC\User\User as value */ private function getVerifiedUsers($userIds) { - if(!is_array($userIds)) { + if (!is_array($userIds)) { return array(); } $users = array(); foreach ($userIds as $userId) { $user = $this->userManager->get($userId); - if(!is_null($user)) { + if (!is_null($user)) { $users[$userId] = $user; } } diff --git a/lib/private/helper.php b/lib/private/helper.php index 66e7acb407a..58bee9c6300 100644 --- a/lib/private/helper.php +++ b/lib/private/helper.php @@ -41,8 +41,7 @@ class OC_Helper { * Returns a url to the given app and file. */ public static function linkToRoute($route, $parameters = array()) { - $urlLinkTo = OC::getRouter()->generate($route, $parameters); - return $urlLinkTo; + return OC::$server->getURLGenerator()->linkToRoute($route, $parameters); } /** @@ -56,32 +55,16 @@ class OC_Helper { * Returns a url to the given app and file. */ public static function linkTo( $app, $file, $args = array() ) { - if( $app != '' ) { - $app_path = OC_App::getAppPath($app); - // Check if the app is in the app folder - if ($app_path && file_exists($app_path . '/' . $file)) { - if (substr($file, -3) == 'php' || substr($file, -3) == 'css') { - $urlLinkTo = OC::$WEBROOT . '/index.php/apps/' . $app; - $urlLinkTo .= ($file != 'index.php') ? '/' . $file : ''; - } else { - $urlLinkTo = OC_App::getAppWebPath($app) . '/' . $file; - } - } else { - $urlLinkTo = OC::$WEBROOT . '/' . $app . '/' . $file; - } - } else { - if (file_exists(OC::$SERVERROOT . '/core/' . $file)) { - $urlLinkTo = OC::$WEBROOT . '/core/' . $file; - } else { - $urlLinkTo = OC::$WEBROOT . '/' . $file; - } - } - - if ($args && $query = http_build_query($args, '', '&')) { - $urlLinkTo .= '?' . $query; - } + return OC::$server->getURLGenerator()->linkTo($app, $file, $args); + } - return $urlLinkTo; + /** + * @param $key + * @return string url to the online documentation + */ + public static function linkToDocs($key) { + $theme = new OC_Defaults(); + return $theme->getDocBaseUrl() . '/server/6.0/go.php?to=' . $key; } /** @@ -107,7 +90,7 @@ class OC_Helper { * Returns a absolute url to the given app and file. */ public static function makeURLAbsolute($url) { - return OC_Request::serverProtocol() . '://' . OC_Request::serverHost() . $url; + return OC::$server->getURLGenerator()->getAbsoluteURL($url); } /** @@ -156,25 +139,7 @@ class OC_Helper { * Returns the path to the image. */ public static function imagePath($app, $image) { - // Read the selected theme from the config file - $theme = OC_Util::getTheme(); - - // Check if the app is in the app folder - if (file_exists(OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$image")) { - return OC::$WEBROOT . "/themes/$theme/apps/$app/img/$image"; - } elseif (file_exists(OC_App::getAppPath($app) . "/img/$image")) { - return OC_App::getAppWebPath($app) . "/img/$image"; - } elseif (!empty($app) and file_exists(OC::$SERVERROOT . "/themes/$theme/$app/img/$image")) { - return OC::$WEBROOT . "/themes/$theme/$app/img/$image"; - } elseif (!empty($app) and file_exists(OC::$SERVERROOT . "/$app/img/$image")) { - return OC::$WEBROOT . "/$app/img/$image"; - } elseif (file_exists(OC::$SERVERROOT . "/themes/$theme/core/img/$image")) { - return OC::$WEBROOT . "/themes/$theme/core/img/$image"; - } elseif (file_exists(OC::$SERVERROOT . "/core/img/$image")) { - return OC::$WEBROOT . "/core/img/$image"; - } else { - throw new RuntimeException('image not found: image:' . $image . ' webroot:' . OC::$WEBROOT . ' serverroot:' . OC::$SERVERROOT); - } + return OC::$server->getURLGenerator()->imagePath($app, $image); } /** @@ -196,6 +161,7 @@ class OC_Helper { 'application/vnd.oasis.opendocument.text-template' => 'x-office/document', 'application/vnd.oasis.opendocument.text-web' => 'x-office/document', 'application/vnd.oasis.opendocument.text-master' => 'x-office/document', + 'application/mspowerpoint' => 'x-office/presentation', 'application/vnd.ms-powerpoint' => 'x-office/presentation', 'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'x-office/presentation', 'application/vnd.openxmlformats-officedocument.presentationml.template' => 'x-office/presentation', @@ -206,6 +172,7 @@ class OC_Helper { 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12' => 'x-office/presentation', 'application/vnd.oasis.opendocument.presentation' => 'x-office/presentation', 'application/vnd.oasis.opendocument.presentation-template' => 'x-office/presentation', + 'application/msexcel' => 'x-office/spreadsheet', 'application/vnd.ms-excel' => 'x-office/spreadsheet', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'x-office/spreadsheet', 'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => 'x-office/spreadsheet', @@ -215,6 +182,7 @@ class OC_Helper { 'application/vnd.ms-excel.sheet.binary.macroEnabled.12' => 'x-office/spreadsheet', 'application/vnd.oasis.opendocument.spreadsheet' => 'x-office/spreadsheet', 'application/vnd.oasis.opendocument.spreadsheet-template' => 'x-office/spreadsheet', + 'application/msaccess' => 'database', ); if (isset($alias[$mimetype])) { @@ -266,11 +234,11 @@ class OC_Helper { * Returns the path to the preview of the file. */ public static function previewIcon($path) { - return self::linkToRoute( 'core_ajax_preview', array('x' => 36, 'y' => 36, 'file' => urlencode($path) )); + return self::linkToRoute( 'core_ajax_preview', array('x' => 36, 'y' => 36, 'file' => $path )); } public static function publicPreviewIcon( $path, $token ) { - return self::linkToRoute( 'core_ajax_public_preview', array('x' => 36, 'y' => 36, 'file' => urlencode($path), 't' => $token)); + return self::linkToRoute( 'core_ajax_public_preview', array('x' => 36, 'y' => 36, 'file' => $path, 't' => $token)); } /** @@ -287,7 +255,7 @@ class OC_Helper { if ($bytes < 1024) { return "$bytes B"; } - $bytes = round($bytes / 1024, 1); + $bytes = round($bytes / 1024, 0); if ($bytes < 1024) { return "$bytes kB"; } @@ -553,11 +521,11 @@ class OC_Helper { * * @param resource $source * @param resource $target - * @return int the number of bytes copied + * @return array the number of bytes copied and result */ public static function streamCopy($source, $target) { if (!$source or !$target) { - return false; + return array(0, false); } $result = true; $count = 0; @@ -893,11 +861,13 @@ class OC_Helper { if (!function_exists($function_name)) { return false; } - $disabled = explode(', ', ini_get('disable_functions')); + $disabled = explode(',', ini_get('disable_functions')); + $disabled = array_map('trim', $disabled); if (in_array($function_name, $disabled)) { return false; } - $disabled = explode(', ', ini_get('suhosin.executor.func.blacklist')); + $disabled = explode(',', ini_get('suhosin.executor.func.blacklist')); + $disabled = array_map('trim', $disabled); if (in_array($function_name, $disabled)) { return false; } @@ -911,7 +881,8 @@ class OC_Helper { * @return array */ public static function getStorageInfo($path) { - $rootInfo = \OC\Files\Filesystem::getFileInfo($path); + // return storage info without adding mount points + $rootInfo = \OC\Files\Filesystem::getFileInfo($path, false); $used = $rootInfo['size']; if ($used < 0) { $used = 0; diff --git a/lib/private/hook.php b/lib/private/hook.php index 8516cf0dcff..b63b442c31b 100644 --- a/lib/private/hook.php +++ b/lib/private/hook.php @@ -97,4 +97,12 @@ class OC_Hook{ self::$registered=array(); } } + + /** + * DO NOT USE! + * For unit tests ONLY! + */ + static public function getHooks() { + return self::$registered; + } } diff --git a/lib/private/installer.php b/lib/private/installer.php index e082c7eeee9..835b6b4c01a 100644 --- a/lib/private/installer.php +++ b/lib/private/installer.php @@ -147,7 +147,14 @@ class OC_Installer{ } // check if the ocs version is the same as the version in info.xml/version - if(!isset($info['version']) or ($info['version']<>$data['appdata']['version'])) { + $versionFile= $extractDir.'/appinfo/version'; + if(is_file($versionFile)) { + $version = trim(file_get_contents($versionFile)); + }else{ + $version = trim($info['version']); + } + + if($version<>trim($data['appdata']['version'])) { OC_Helper::rmdirr($extractDir); throw new \Exception($l->t("App can't be installed because the version in info.xml/version is not the same as the version reported from the app store")); } @@ -181,7 +188,11 @@ class OC_Installer{ //install the database if(is_file($basedir.'/appinfo/database.xml')) { - OC_DB::createDbFromStructure($basedir.'/appinfo/database.xml'); + if (OC_Appconfig::getValue($info['id'], 'installed_version') === null) { + OC_DB::createDbFromStructure($basedir.'/appinfo/database.xml'); + } else { + OC_DB::updateDbFromStructure($basedir.'/appinfo/database.xml'); + } } //run appinfo/install.php @@ -259,7 +270,7 @@ class OC_Installer{ /** * @brief Check if an update for the app is available * @param $name name of the application - * @returns empty string is no update available or the version number of the update + * @return boolean false or the version number of the update * * The function will check if an update for a version is available */ @@ -275,11 +286,11 @@ class OC_Installer{ return($ocsversion); }else{ - return(''); + return false; } }else{ - return(''); + return false; } } @@ -396,6 +407,9 @@ class OC_Installer{ include OC_App::getAppPath($app)."/appinfo/install.php"; } $info=OC_App::getAppInfo($app); + if (is_null($info)) { + return false; + } OC_Appconfig::setValue($app, 'installed_version', OC_App::getAppVersion($app)); //set remote/public handelers @@ -449,8 +463,7 @@ class OC_Installer{ ); // is the code checker enabled? - if(OC_Config::getValue('appcodechecker', false)) { - + if(OC_Config::getValue('appcodechecker', true)) { // check if grep is installed $grep = exec('which grep'); if($grep=='') { diff --git a/lib/private/json.php b/lib/private/json.php index 6ba0b13806b..5c5d7e3a3da 100644 --- a/lib/private/json.php +++ b/lib/private/json.php @@ -65,6 +65,20 @@ class OC_JSON{ } /** + * Check is a given user exists - send json error msg if not + * @param string $user + */ + public static function checkUserExists($user) { + if (!OCP\User::userExists($user)) { + $l = OC_L10N::get('lib'); + OCP\JSON::error(array('data' => array('message' => $l->t('Unknown user')))); + exit; + } + } + + + + /** * Check if the user is a subadmin, send json error msg if not */ public static function checkSubAdminUser() { @@ -109,7 +123,16 @@ class OC_JSON{ if($setContentType) { self::setContentTypeHeader(); } - array_walk_recursive($data, array('OC_JSON', 'to_string')); - echo json_encode($data); + echo self::encode($data); + } + + /** + * Encode JSON + */ + public static function encode($data) { + if (is_array($data)) { + array_walk_recursive($data, array('OC_JSON', 'to_string')); + } + return json_encode($data); } } diff --git a/lib/private/l10n.php b/lib/private/l10n.php index f93443b886a..98665c84c55 100644 --- a/lib/private/l10n.php +++ b/lib/private/l10n.php @@ -25,12 +25,7 @@ /** * This class is for i18n and l10n */ -class OC_L10N { - /** - * cached instances - */ - protected static $instances=array(); - +class OC_L10N implements \OCP\IL10N { /** * cache */ @@ -83,13 +78,10 @@ class OC_L10N { * @return OC_L10N */ public static function get($app, $lang=null) { - if(is_null($lang)) { - if(!isset(self::$instances[$app])) { - self::$instances[$app]=new OC_L10N($app); - } - return self::$instances[$app]; - }else{ - return new OC_L10N($app, $lang); + if (is_null($lang)) { + return OC::$server->getL10N($app); + } else { + return new \OC_L10N($app, $lang); } } @@ -270,7 +262,7 @@ class OC_L10N { */ public function n($text_singular, $text_plural, $count, $parameters = array()) { $this->init(); - $identifier = "_${text_singular}__${text_plural}_"; + $identifier = "_${text_singular}_::_${text_plural}_"; if( array_key_exists($identifier, $this->translations)) { return new OC_L10N_String( $this, $identifier, $parameters, $count ); } @@ -427,7 +419,7 @@ class OC_L10N { /** * @brief find the best language * @param $app Array or string, details below - * @returns language + * @returns string language * * If $app is an array, ownCloud assumes that these are the available * languages. Otherwise ownCloud tries to find the files in the l10n @@ -446,8 +438,7 @@ class OC_L10N { if(is_array($app)) { $available = $app; $lang_exists = array_search($lang, $available) !== false; - } - else { + } else { $lang_exists = self::languageExists($app, $lang); } if($lang_exists) { @@ -455,35 +446,40 @@ class OC_L10N { } } - $default_language = OC_Config::getValue('default_language', false); + $default_language = OC_Config::getValue('default_language', false); - if($default_language !== false) { - return $default_language; - } + if($default_language !== false) { + return $default_language; + } if(isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { - $accepted_languages = preg_split('/,\s*/', strtolower($_SERVER['HTTP_ACCEPT_LANGUAGE'])); if(is_array($app)) { $available = $app; - } - else{ + } else { $available = self::findAvailableLanguages($app); } - foreach($accepted_languages as $i) { - $temp = explode(';', $i); - $temp[0] = str_replace('-', '_', $temp[0]); - if( ($key = array_search($temp[0], $available)) !== false) { - if (is_null($app)) { - self::$language = $available[$key]; + + // E.g. make sure that 'de' is before 'de_DE'. + sort($available); + + $preferences = preg_split('/,\s*/', strtolower($_SERVER['HTTP_ACCEPT_LANGUAGE'])); + foreach($preferences as $preference) { + list($preferred_language) = explode(';', $preference); + $preferred_language = str_replace('-', '_', $preferred_language); + foreach($available as $available_language) { + if ($preferred_language === strtolower($available_language)) { + if (is_null($app)) { + self::$language = $available_language; + } + return $available_language; } - return $available[$key]; } - foreach($available as $l) { - if ( $temp[0] == substr($l, 0, 2) ) { + foreach($available as $available_language) { + if (substr($preferred_language, 0, 2) === $available_language) { if (is_null($app)) { - self::$language = $l; + self::$language = $available_language; } - return $l; + return $available_language; } } } diff --git a/lib/private/l10n/factory.php b/lib/private/l10n/factory.php new file mode 100644 index 00000000000..8c65f368171 --- /dev/null +++ b/lib/private/l10n/factory.php @@ -0,0 +1,34 @@ +<?php +/** + * Copyright (c) 2013 Bart Visscher <bartv@thisnet.nl> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + * + */ + +namespace OC\L10N; + +/** + * TODO: Description + */ +class Factory { + /** + * cached instances + */ + protected $instances = array(); + + /** + * get an L10N instance + * @param $app string + * @param $lang string|null + * @return \OC_L10N + */ + public function get($app) { + if (!isset($this->instances[$app])) { + $this->instances[$app] = new \OC_L10N($app); + } + return $this->instances[$app]; + } + +} diff --git a/lib/private/l10n/id.php b/lib/private/l10n/id.php deleted file mode 100644 index 080faddb321..00000000000 --- a/lib/private/l10n/id.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php -$TRANSLATIONS = array( -"Help" => "Bantuan", -"Personal" => "Pribadi", -"Settings" => "Setelan", -"Users" => "Pengguna", -"Admin" => "Admin", -"web services under your control" => "layanan web dalam kontrol Anda", -"ZIP download is turned off." => "Pengunduhan ZIP dimatikan.", -"Files need to be downloaded one by one." => "Berkas harus diunduh satu persatu.", -"Back to Files" => "Kembali ke Daftar Berkas", -"Selected files too large to generate zip file." => "Berkas yang dipilih terlalu besar untuk dibuat berkas zip-nya.", -"Application is not enabled" => "Aplikasi tidak diaktifkan", -"Authentication error" => "Galat saat autentikasi", -"Token expired. Please reload page." => "Token kedaluwarsa. Silakan muat ulang halaman.", -"Files" => "Berkas", -"Text" => "Teks", -"Images" => "Gambar", -"%s enter the database username." => "%s masukkan nama pengguna basis data.", -"%s enter the database name." => "%s masukkan nama basis data.", -"%s you may not use dots in the database name" => "%sAnda tidak boleh menggunakan karakter titik pada nama basis data", -"MS SQL username and/or password not valid: %s" => "Nama pengguna dan/atau sandi MySQL tidak valid: %s", -"You need to enter either an existing account or the administrator." => "Anda harus memasukkan akun yang sudah ada atau administrator.", -"MySQL username and/or password not valid" => "Nama pengguna dan/atau sandi MySQL tidak valid", -"DB Error: \"%s\"" => "Galat Basis Data: \"%s\"", -"Offending command was: \"%s\"" => "Perintah yang bermasalah: \"%s\"", -"MySQL user '%s'@'localhost' exists already." => "Pengguna MySQL '%s'@'localhost' sudah ada.", -"Drop this user from MySQL" => "Hapus pengguna ini dari MySQL", -"MySQL user '%s'@'%%' already exists" => "Pengguna MySQL '%s'@'%%' sudah ada.", -"Drop this user from MySQL." => "Hapus pengguna ini dari MySQL.", -"Oracle username and/or password not valid" => "Nama pengguna dan/atau sandi Oracle tidak valid", -"Offending command was: \"%s\", name: %s, password: %s" => "Perintah yang bermasalah: \"%s\", nama pengguna: %s, sandi: %s", -"PostgreSQL username and/or password not valid" => "Nama pengguna dan/atau sandi PostgreSQL tidak valid", -"Set an admin username." => "Setel nama pengguna admin.", -"Set an admin password." => "Setel sandi admin.", -"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Web server Anda belum dikonfigurasikan dengan baik untuk mengizinkan sinkronisasi berkas karena tampaknya antarmuka WebDAV rusak.", -"Please double check the <a href='%s'>installation guides</a>." => "Silakan periksa ulang <a href='%s'>panduan instalasi</a>.", -"seconds ago" => "beberapa detik yang lalu", -"_%n minute ago_::_%n minutes ago_" => array(""), -"_%n hour ago_::_%n hours ago_" => array(""), -"today" => "hari ini", -"yesterday" => "kemarin", -"_%n day go_::_%n days ago_" => array(""), -"last month" => "bulan kemarin", -"_%n month ago_::_%n months ago_" => array(""), -"last year" => "tahun kemarin", -"years ago" => "beberapa tahun lalu", -"Could not find category \"%s\"" => "Tidak dapat menemukan kategori \"%s\"" -); -$PLURAL_FORMS = "nplurals=1; plural=0;"; diff --git a/lib/private/l10n/sl.php b/lib/private/l10n/sl.php deleted file mode 100644 index 5722191aedf..00000000000 --- a/lib/private/l10n/sl.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php -$TRANSLATIONS = array( -"Help" => "Pomoč", -"Personal" => "Osebno", -"Settings" => "Nastavitve", -"Users" => "Uporabniki", -"Admin" => "Skrbništvo", -"web services under your control" => "spletne storitve pod vašim nadzorom", -"ZIP download is turned off." => "Prejemanje datotek v paketu ZIP je onemogočeno.", -"Files need to be downloaded one by one." => "Datoteke je mogoče prejeti le posamično.", -"Back to Files" => "Nazaj na datoteke", -"Selected files too large to generate zip file." => "Izbrane datoteke so prevelike za ustvarjanje datoteke arhiva zip.", -"Application is not enabled" => "Program ni omogočen", -"Authentication error" => "Napaka pri overjanju", -"Token expired. Please reload page." => "Žeton je potekel. Stran je treba ponovno naložiti.", -"Files" => "Datoteke", -"Text" => "Besedilo", -"Images" => "Slike", -"%s enter the database username." => "%s - vnos uporabniškega imena podatkovne zbirke.", -"%s enter the database name." => "%s - vnos imena podatkovne zbirke.", -"%s you may not use dots in the database name" => "%s - v imenu podatkovne zbirke ni dovoljeno uporabljati pik.", -"MS SQL username and/or password not valid: %s" => "Uporabniško ime ali geslo MS SQL ni veljavno: %s", -"You need to enter either an existing account or the administrator." => "Prijaviti se je treba v obstoječi ali pa skrbniški račun.", -"MySQL username and/or password not valid" => "Uporabniško ime ali geslo MySQL ni veljavno", -"DB Error: \"%s\"" => "Napaka podatkovne zbirke: \"%s\"", -"Offending command was: \"%s\"" => "Napačni ukaz je: \"%s\"", -"MySQL user '%s'@'localhost' exists already." => "Uporabnik MySQL '%s'@'localhost' že obstaja.", -"Drop this user from MySQL" => "Odstrani uporabnika s podatkovne zbirke MySQL", -"MySQL user '%s'@'%%' already exists" => "Uporabnik MySQL '%s'@'%%' že obstaja.", -"Drop this user from MySQL." => "Odstrani uporabnika s podatkovne zbirke MySQL", -"Oracle connection could not be established" => "Povezava z bazo Oracle ni uspela.", -"Oracle username and/or password not valid" => "Uporabniško ime ali geslo Oracle ni veljavno", -"Offending command was: \"%s\", name: %s, password: %s" => "Napačni ukaz je: \"%s\", ime: %s, geslo: %s", -"PostgreSQL username and/or password not valid" => "Uporabniško ime ali geslo PostgreSQL ni veljavno", -"Set an admin username." => "Nastavi uporabniško ime skrbnika.", -"Set an admin password." => "Nastavi geslo skrbnika.", -"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Spletni stražnik še ni ustrezno nastavljen in ne omogoča usklajevanja, saj je nastavitev WebDAV okvarjena.", -"Please double check the <a href='%s'>installation guides</a>." => "Preverite <a href='%s'>navodila namestitve</a>.", -"seconds ago" => "pred nekaj sekundami", -"_%n minute ago_::_%n minutes ago_" => array("","","",""), -"_%n hour ago_::_%n hours ago_" => array("","","",""), -"today" => "danes", -"yesterday" => "včeraj", -"_%n day go_::_%n days ago_" => array("","","",""), -"last month" => "zadnji mesec", -"_%n month ago_::_%n months ago_" => array("","","",""), -"last year" => "lansko leto", -"years ago" => "let nazaj", -"Could not find category \"%s\"" => "Kategorije \"%s\" ni mogoče najti." -); -$PLURAL_FORMS = "nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);"; diff --git a/lib/private/legacy/cache/fileglobalgc.php b/lib/private/legacy/cache/fileglobalgc.php new file mode 100644 index 00000000000..385f6406673 --- /dev/null +++ b/lib/private/legacy/cache/fileglobalgc.php @@ -0,0 +1,4 @@ +<?php + +class OC_Cache_FileGlobalGC extends OC\Cache\FileGlobalGC{ +} diff --git a/lib/private/legacy/config.php b/lib/private/legacy/config.php index 7e498013737..ab67c8d3020 100644 --- a/lib/private/legacy/config.php +++ b/lib/private/legacy/config.php @@ -38,7 +38,6 @@ * This class is responsible for reading and writing config.php, the very basic * configuration file of ownCloud. */ -OC_Config::$object = new \OC\Config(OC::$SERVERROOT.'/config/'); class OC_Config { /** @@ -83,11 +82,7 @@ class OC_Config { * */ public static function setValue($key, $value) { - try { - self::$object->setValue($key, $value); - } catch (\OC\HintException $e) { - \OC_Template::printErrorPage($e->getMessage(), $e->getHint()); - } + self::$object->setValue($key, $value); } /** @@ -98,10 +93,6 @@ class OC_Config { * */ public static function deleteKey($key) { - try { - self::$object->deleteKey($key); - } catch (\OC\HintException $e) { - \OC_Template::printErrorPage($e->getMessage(), $e->getHint()); - } + self::$object->deleteKey($key); } } diff --git a/lib/private/log/owncloud.php b/lib/private/log/owncloud.php index d16b9537a16..4c86d0e45e0 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; } } @@ -51,12 +61,25 @@ class OC_Log_Owncloud { if($level>=$minLevel) { // default to ISO8601 $format = OC_Config::getValue('logdateformat', 'c'); - $time = date($format, time()); - $entry=array('app'=>$app, 'message'=>$message, 'level'=>$level, 'time'=> $time); + $logtimezone=OC_Config::getValue( "logtimezone", 'UTC' ); + try { + $timezone = new DateTimeZone($logtimezone); + } catch (Exception $e) { + $timezone = new DateTimeZone('UTC'); + } + $time = new DateTime(null, $timezone); + // remove username/passswords from URLs before writing the to the log file + $message = preg_replace('/\/\/(.*):(.*)@/', '//xxx:xxx@', $message); + $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, json_encode($entry)."\n"); + fwrite($handle, $entry."\n"); fclose($handle); + } else { + // Fall back to error_log + error_log($entry); } } } diff --git a/lib/private/memcache/apc.php b/lib/private/memcache/apc.php index 575ee4427db..e995cbc526e 100644 --- a/lib/private/memcache/apc.php +++ b/lib/private/memcache/apc.php @@ -50,6 +50,8 @@ class APC extends Cache { static public function isAvailable() { if (!extension_loaded('apc')) { return false; + } elseif (!ini_get('apc.enabled')) { + return false; } elseif (!ini_get('apc.enable_cli') && \OC::$CLI) { return false; } else { diff --git a/lib/private/memcache/apcu.php b/lib/private/memcache/apcu.php index ccc1aa6e562..dac0f5f208a 100644 --- a/lib/private/memcache/apcu.php +++ b/lib/private/memcache/apcu.php @@ -12,7 +12,7 @@ class APCu extends APC { public function clear($prefix = '') { $ns = $this->getNamespace() . $prefix; $ns = preg_quote($ns, '/'); - $iter = new \APCIterator('/^'.$ns.'/'); + $iter = new \APCIterator('user', '/^'.$ns.'/'); return apc_delete($iter); } diff --git a/lib/private/memcache/xcache.php b/lib/private/memcache/xcache.php index 33de30562f9..1337a7ad612 100644 --- a/lib/private/memcache/xcache.php +++ b/lib/private/memcache/xcache.php @@ -8,9 +8,13 @@ namespace OC\Memcache; +/** + * See http://xcache.lighttpd.net/wiki/XcacheApi for provided constants and + * functions etc. + */ class XCache extends Cache { /** - * entries in XCache gets namespaced to prevent collisions between owncloud instances and users + * entries in XCache gets namespaced to prevent collisions between ownCloud instances and users */ protected function getNameSpace() { return $this->prefix; @@ -37,24 +41,32 @@ class XCache extends Cache { } public function clear($prefix='') { - xcache_unset_by_prefix($this->getNamespace().$prefix); + if (function_exists('xcache_unset_by_prefix')) { + return xcache_unset_by_prefix($this->getNamespace().$prefix); + } else { + // Since we can not clear by prefix, we just clear the whole cache. + xcache_clear_cache(\XC_TYPE_VAR, 0); + } return true; } static public function isAvailable(){ if (!extension_loaded('xcache')) { return false; - } elseif (\OC::$CLI) { + } + if (\OC::$CLI) { return false; - }else{ - return true; } - } -} - -if(!function_exists('xcache_unset_by_prefix')) { - function xcache_unset_by_prefix($prefix) { - // Since we can't clear targetted cache, we'll clear all. :( - xcache_clear_cache(\XC_TYPE_VAR, 0); + if (!function_exists('xcache_unset_by_prefix') && ini_get('xcache.admin.enable_auth')) { + // We do not want to use XCache if we can not clear it without + // using the administration function xcache_clear_cache() + // AND administration functions are password-protected. + return false; + } + $var_size = (int) ini_get('xcache.var_size'); + if (!$var_size) { + return false; + } + return true; } } diff --git a/lib/private/mimetypes.list.php b/lib/private/mimetypes.list.php index 8ab8ac81bd8..40fb1d2d97d 100644 --- a/lib/private/mimetypes.list.php +++ b/lib/private/mimetypes.list.php @@ -21,87 +21,91 @@ */ /** - * list of mimetypes by extension + * Array mapping file extensions to mimetypes (in alphabetical order). */ - return array( + 'accdb'=>'application/msaccess', + 'ai' => 'application/illustrator', + 'avi'=>'video/x-msvideo', + 'bash' => 'text/x-shellscript', + 'blend'=>'application/x-blender', + 'cc' => 'text/x-c', + 'cdr' => 'application/coreldraw', + 'cpp' => 'text/x-c++src', 'css'=>'text/css', + 'c' => 'text/x-c', + 'c++' => 'text/x-c++src', + 'doc'=>'application/msword', + 'docx'=>'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'dot'=>'application/msword', + 'dotx'=>'application/vnd.openxmlformats-officedocument.wordprocessingml.template', + 'dv'=>'video/dv', + 'epub' => 'application/epub+zip', + 'exe'=>'application/x-ms-dos-executable', 'flac'=>'audio/flac', 'gif'=>'image/gif', - 'gzip'=>'application/x-gzip', 'gz'=>'application/x-gzip', + 'gzip'=>'application/x-gzip', 'html'=>'text/html', 'htm'=>'text/html', - 'ics'=>'text/calendar', 'ical'=>'text/calendar', + 'ics'=>'text/calendar', + 'impress' => 'text/impress', 'jpeg'=>'image/jpeg', 'jpg'=>'image/jpeg', 'js'=>'application/javascript', + 'keynote'=>'application/x-iwork-keynote-sffkey', + 'kra'=>'application/x-krita', + 'm2t'=>'video/mp2t', + 'm4v'=>'video/mp4', + 'markdown' => 'text/markdown', + 'mdown' => 'text/markdown', + 'md' => 'text/markdown', + 'mdb'=>'application/msaccess', + 'mdwn' => 'text/markdown', + 'mobi' => 'application/x-mobipocket-ebook', + 'mov'=>'video/quicktime', + 'mp3'=>'audio/mpeg', + 'mp4'=>'video/mp4', + 'mpeg'=>'video/mpeg', + 'mpg'=>'video/mpeg', + 'msi'=>'application/x-msi', + 'numbers'=>'application/x-iwork-numbers-sffnumbers', + 'odg'=>'application/vnd.oasis.opendocument.graphics', + 'odp'=>'application/vnd.oasis.opendocument.presentation', + 'ods'=>'application/vnd.oasis.opendocument.spreadsheet', + 'odt'=>'application/vnd.oasis.opendocument.text', 'oga'=>'audio/ogg', 'ogg'=>'audio/ogg', 'ogv'=>'video/ogg', + 'pages'=>'application/x-iwork-pages-sffpages', 'pdf'=>'application/pdf', + 'php'=>'application/x-php', + 'pl'=>'application/x-pearl', 'png'=>'image/png', + 'ppt'=>'application/mspowerpoint', + 'pptx'=>'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'psd'=>'application/x-photoshop', + 'py'=>'text/x-script.python', + 'reveal' => 'text/reveal', + 'sgf' => 'application/sgf', + 'sh-lib' => 'text/x-shellscript', + 'sh' => 'text/x-shellscript', 'svg'=>'image/svg+xml', 'tar'=>'application/x-tar', - 'tgz'=>'application/x-compressed', 'tar.gz'=>'application/x-compressed', - 'tif'=>'image/tiff', + 'tgz'=>'application/x-compressed', 'tiff'=>'image/tiff', + 'tif'=>'image/tiff', 'txt'=>'text/plain', - 'zip'=>'application/zip', + 'vcard' => 'text/vcard', + 'vcf' => 'text/vcard', 'wav'=>'audio/wav', - 'odt'=>'application/vnd.oasis.opendocument.text', - 'ods'=>'application/vnd.oasis.opendocument.spreadsheet', - 'odg'=>'application/vnd.oasis.opendocument.graphics', - 'odp'=>'application/vnd.oasis.opendocument.presentation', - 'pages'=>'application/x-iwork-pages-sffpages', - 'numbers'=>'application/x-iwork-numbers-sffnumbers', - 'keynote'=>'application/x-iwork-keynote-sffkey', - 'kra'=>'application/x-krita', - 'mp3'=>'audio/mpeg', - 'doc'=>'application/msword', - 'docx'=>'application/msword', - 'xls'=>'application/msexcel', - 'xlsx'=>'application/msexcel', - 'php'=>'application/x-php', - 'exe'=>'application/x-ms-dos-executable', - 'pl'=>'application/x-pearl', - 'py'=>'application/x-python', - 'blend'=>'application/x-blender', - 'xcf'=>'application/x-gimp', - 'psd'=>'application/x-photoshop', - 'xml'=>'application/xml', - 'avi'=>'video/x-msvideo', - 'dv'=>'video/dv', - 'm2t'=>'video/mp2t', - 'mp4'=>'video/mp4', - 'm4v'=>'video/mp4', - 'mpg'=>'video/mpeg', - 'mpeg'=>'video/mpeg', - 'mov'=>'video/quicktime', 'webm'=>'video/webm', 'wmv'=>'video/x-ms-asf', - 'py'=>'text/x-script.phyton', - 'vcf' => 'text/vcard', - 'vcard' => 'text/vcard', - 'doc'=>'application/msword', - 'docx'=>'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'xcf'=>'application/x-gimp', 'xls'=>'application/msexcel', 'xlsx'=>'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', - 'ppt'=>'application/mspowerpoint', - 'pptx'=>'application/vnd.openxmlformats-officedocument.presentationml.presentation', - 'sgf' => 'application/sgf', - 'cdr' => 'application/coreldraw', - 'impress' => 'text/impress', - 'ai' => 'application/illustrator', - 'epub' => 'application/epub+zip', - 'mobi' => 'application/x-mobipocket-ebook', - 'exe' => 'application', - 'msi' => 'application', - 'md' => 'text/markdown', - 'markdown' => 'text/markdown', - 'mdown' => 'text/markdown', - 'mdwn' => 'text/markdown', - 'reveal' => 'text/reveal' + 'xml'=>'application/xml', + 'zip'=>'application/zip', ); diff --git a/lib/private/ocs.php b/lib/private/ocs.php index 93e8931ce2e..e067196cf11 100644 --- a/lib/private/ocs.php +++ b/lib/private/ocs.php @@ -228,36 +228,4 @@ class OC_OCS { } } } - - /** - * get private data - * @param string $user - * @param string $app - * @param string $key - * @param bool $like use LIKE instead of = when comparing keys - * @return array - */ - public static function getData($user, $app="", $key="") { - if($app) { - $apps=array($app); - }else{ - $apps=OC_Preferences::getApps($user); - } - if($key) { - $keys=array($key); - }else{ - foreach($apps as $app) { - $keys=OC_Preferences::getKeys($user, $app); - } - } - $result=array(); - foreach($apps as $app) { - foreach($keys as $key) { - $value=OC_Preferences::getValue($user, $app, $key); - $result[]=array('app'=>$app, 'key'=>$key, 'value'=>$value); - } - } - return $result; - } - } 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/ocs/privatedata.php b/lib/private/ocs/privatedata.php index 4dfd0a6e66e..932413711b8 100644 --- a/lib/private/ocs/privatedata.php +++ b/lib/private/ocs/privatedata.php @@ -22,45 +22,87 @@ * */ + class OC_OCS_Privatedata { + /** + * read keys + * test: curl http://login:passwd@oc/core/ocs/v1.php/privatedata/getattribute/testy/123 + * test: curl http://login:passwd@oc/core/ocs/v1.php/privatedata/getattribute/testy + * @param array $parameters The OCS parameter + * @return \OC_OCS_Result + */ public static function get($parameters) { - OC_Util::checkLoggedIn(); $user = OC_User::getUser(); $app = addslashes(strip_tags($parameters['app'])); - $key = addslashes(strip_tags($parameters['key'])); - $result = OC_OCS::getData($user, $app, $key); + $key = isset($parameters['key']) ? addslashes(strip_tags($parameters['key'])) : null; + + if(empty($key)) { + $query = \OCP\DB::prepare('SELECT `key`, `app`, `value` FROM `*PREFIX*privatedata` WHERE `user` = ? AND `app` = ? '); + $result = $query->execute(array($user, $app)); + } else { + $query = \OCP\DB::prepare('SELECT `key`, `app`, `value` FROM `*PREFIX*privatedata` WHERE `user` = ? AND `app` = ? AND `key` = ? '); + $result = $query->execute(array($user, $app, $key)); + } + $xml = array(); - foreach($result as $i=>$log) { - $xml[$i]['key']=$log['key']; - $xml[$i]['app']=$log['app']; - $xml[$i]['value']=$log['value']; + while ($row = $result->fetchRow()) { + $data=array(); + $data['key']=$row['key']; + $data['app']=$row['app']; + $data['value']=$row['value']; + $xml[] = $data; } + return new OC_OCS_Result($xml); - //TODO: replace 'privatedata' with 'attribute' once a new libattice has been released that works with it } + /** + * set a key + * test: curl http://login:passwd@oc/core/ocs/v1.php/privatedata/setattribute/testy/123 --data "value=foobar" + * @param array $parameters The OCS parameter + * @return \OC_OCS_Result + */ public static function set($parameters) { - OC_Util::checkLoggedIn(); $user = OC_User::getUser(); $app = addslashes(strip_tags($parameters['app'])); $key = addslashes(strip_tags($parameters['key'])); $value = OC_OCS::readData('post', 'value', 'text'); - if(OC_Preferences::setValue($user, $app, $key, $value)) { - return new OC_OCS_Result(null, 100); + + // update in DB + $query = \OCP\DB::prepare('UPDATE `*PREFIX*privatedata` SET `value` = ? WHERE `user` = ? AND `app` = ? AND `key` = ?'); + $numRows = $query->execute(array($value, $user, $app, $key)); + + if ($numRows === false || $numRows === 0) { + // store in DB + $query = \OCP\DB::prepare('INSERT INTO `*PREFIX*privatedata` (`user`, `app`, `key`, `value`)' . ' VALUES(?, ?, ?, ?)'); + $query->execute(array($user, $app, $key, $value)); } + + return new OC_OCS_Result(null, 100); } + /** + * delete a key + * test: curl http://login:passwd@oc/core/ocs/v1.php/privatedata/deleteattribute/testy/123 --data "post=1" + * @param array $parameters The OCS parameter + * @return \OC_OCS_Result + */ public static function delete($parameters) { - OC_Util::checkLoggedIn(); $user = OC_User::getUser(); + if (!isset($parameters['app']) or !isset($parameters['key'])) { + //key and app are NOT optional here + return new OC_OCS_Result(null, 101); + } + $app = addslashes(strip_tags($parameters['app'])); $key = addslashes(strip_tags($parameters['key'])); - if($key==="" or $app==="") { - return new OC_OCS_Result(null, 101); //key and app are NOT optional here - } - if(OC_Preferences::deleteKey($user, $app, $key)) { - return new OC_OCS_Result(null, 100); - } + + // delete in DB + $query = \OCP\DB::prepare('DELETE FROM `*PREFIX*privatedata` WHERE `user` = ? AND `app` = ? AND `key` = ? '); + $query->execute(array($user, $app, $key )); + + return new OC_OCS_Result(null, 100); } } + diff --git a/lib/private/preview.php b/lib/private/preview.php index 266f7795f12..ff93f438f73 100755 --- a/lib/private/preview.php +++ b/lib/private/preview.php @@ -9,7 +9,7 @@ * Thumbnails: * structure of filename: * /data/user/thumbnails/pathhash/x-y.png - * + * */ namespace OC; @@ -40,6 +40,7 @@ class Preview { private $maxX; private $maxY; private $scalingup; + private $mimetype; //preview images object /** @@ -59,11 +60,18 @@ class Preview { * @param int $maxX The maximum X size of the thumbnail. It can be smaller depending on the shape of the image * @param int $maxY The maximum Y size of the thumbnail. It can be smaller depending on the shape of the image * @param bool $scalingUp Disable/Enable upscaling of previews - * @return mixed (bool / string) + * @return mixed (bool / string) * false if thumbnail does not exist * path to thumbnail if thumbnail exists */ public function __construct($user='', $root='/', $file='', $maxX=1, $maxY=1, $scalingUp=true) { + //init fileviews + if($user === ''){ + $user = \OC_User::getUser(); + } + $this->fileView = new \OC\Files\View('/' . $user . '/' . $root); + $this->userView = new \OC\Files\View('/' . $user); + //set config $this->configMaxX = \OC_Config::getValue('preview_max_x', null); $this->configMaxY = \OC_Config::getValue('preview_max_y', null); @@ -75,13 +83,6 @@ class Preview { $this->setMaxY($maxY); $this->setScalingUp($scalingUp); - //init fileviews - if($user === ''){ - $user = \OC_User::getUser(); - } - $this->fileView = new \OC\Files\View('/' . $user . '/' . $root); - $this->userView = new \OC\Files\View('/' . $user); - $this->preview = null; //check if there are preview backends @@ -166,10 +167,21 @@ class Preview { */ public function setFile($file) { $this->file = $file; + if ($file !== '') { + $this->mimetype = $this->fileView->getMimeType($this->file); + } return $this; } /** + * @brief set mimetype explicitely + * @param string $mimetype + */ + public function setMimetype($mimetype) { + $this->mimetype = $mimetype; + } + + /** * @brief set the the max width of the preview * @param int $maxX * @return $this @@ -265,7 +277,7 @@ class Preview { $fileInfo = $this->fileView->getFileInfo($file); $fileId = $fileInfo['fileid']; - + $previewPath = $this->getThumbnailsFolder() . '/' . $fileId . '/'; $this->userView->deleteAll($previewPath); $this->userView->rmdir($previewPath); @@ -274,7 +286,7 @@ class Preview { /** * @brief check if thumbnail or bigger version of thumbnail of file is cached - * @return mixed (bool / string) + * @return mixed (bool / string) * false if thumbnail does not exist * path to thumbnail if thumbnail exists */ @@ -386,11 +398,10 @@ class Preview { } if(is_null($this->preview)) { - $mimetype = $this->fileView->getMimeType($file); $preview = null; foreach(self::$providers as $supportedMimetype => $provider) { - if(!preg_match($supportedMimetype, $mimetype)) { + if(!preg_match($supportedMimetype, $this->mimetype)) { continue; } @@ -516,7 +527,7 @@ class Preview { $cropY = 0; $image->crop($cropX, $cropY, $x, $y); - + $this->preview = $image; return; } @@ -598,7 +609,7 @@ class Preview { public static function post_write($args) { self::post_delete($args); } - + public static function post_delete($args) { $path = $args['path']; if(substr($path, 0, 1) === '/') { diff --git a/lib/private/preview/image.php b/lib/private/preview/image.php index 9aec967282d..84343df2608 100644 --- a/lib/private/preview/image.php +++ b/lib/private/preview/image.php @@ -21,11 +21,11 @@ class Image extends Provider { return false; } + $image = new \OC_Image(); //check if file is encrypted if($fileInfo['encrypted'] === true) { - $image = new \OC_Image(stream_get_contents($fileview->fopen($path, 'r'))); + $image->loadFromData(stream_get_contents($fileview->fopen($path, 'r'))); }else{ - $image = new \OC_Image(); $image->loadFromFile($fileview->getLocalFile($path)); } diff --git a/lib/private/preview/movies.php b/lib/private/preview/movies.php index c318137ff0e..71cd3bae057 100644 --- a/lib/private/preview/movies.php +++ b/lib/private/preview/movies.php @@ -8,40 +8,83 @@ */ namespace OC\Preview; -$isShellExecEnabled = !in_array('shell_exec', explode(', ', ini_get('disable_functions'))); -$whichAVCONV = shell_exec('which avconv'); -$isAVCONVAvailable = !empty($whichAVCONV); - -if($isShellExecEnabled && $isAVCONVAvailable) { +function findBinaryPath($program) { + exec('which ' . escapeshellarg($program) . ' 2> /dev/null', $output, $returnCode); + if ($returnCode === 0 && count($output) > 0) { + return escapeshellcmd($output[0]); + } + return null; +} - class Movie extends Provider { +// movie preview is currently not supported on Windows +if (!\OC_Util::runningOnWindows()) { + $isExecEnabled = \OC_Helper::is_function_enabled('exec'); + $ffmpegBinary = null; + $avconvBinary = null; - public function getMimeType() { - return '/video\/.*/'; + if ($isExecEnabled) { + $avconvBinary = findBinaryPath('avconv'); + if (!$avconvBinary) { + $ffmpegBinary = findBinaryPath('ffmpeg'); } + } + + if($isExecEnabled && ( $avconvBinary || $ffmpegBinary )) { - public function getThumbnail($path, $maxX, $maxY, $scalingup, $fileview) { - $absPath = \OC_Helper::tmpFile(); - $tmpPath = \OC_Helper::tmpFile(); + class Movie extends Provider { + public static $avconvBinary; + public static $ffmpegBinary; - $handle = $fileview->fopen($path, 'rb'); + public function getMimeType() { + return '/video\/.*/'; + } - $firstmb = stream_get_contents($handle, 1048576); //1024 * 1024 = 1048576 - file_put_contents($absPath, $firstmb); + public function getThumbnail($path, $maxX, $maxY, $scalingup, $fileview) { + // TODO: use proc_open() and stream the source file ? + $absPath = \OC_Helper::tmpFile(); + $tmpPath = \OC_Helper::tmpFile(); - //$cmd = 'ffmpeg -y -i ' . escapeshellarg($absPath) . ' -f mjpeg -vframes 1 -ss 1 -s ' . escapeshellarg($maxX) . 'x' . escapeshellarg($maxY) . ' ' . $tmpPath; - $cmd = 'avconv -an -y -ss 1 -i ' . escapeshellarg($absPath) . ' -f mjpeg -vframes 1 ' . escapeshellarg($tmpPath); - - shell_exec($cmd); + $handle = $fileview->fopen($path, 'rb'); - $image = new \OC_Image($tmpPath); + // we better use 5MB (1024 * 1024 * 5 = 5242880) instead of 1MB. + // in some cases 1MB was no enough to generate thumbnail + $firstmb = stream_get_contents($handle, 5242880); + file_put_contents($absPath, $firstmb); - unlink($absPath); - unlink($tmpPath); + if (self::$avconvBinary) { + $cmd = self::$avconvBinary . ' -an -y -ss 5'. + ' -i ' . escapeshellarg($absPath) . + ' -f mjpeg -vframes 1 -vsync 1 ' . escapeshellarg($tmpPath) . + ' > /dev/null 2>&1'; + } + else { + $cmd = self::$ffmpegBinary . ' -y -ss 5' . + ' -i ' . escapeshellarg($absPath) . + ' -f mjpeg -vframes 1' . + ' -s ' . escapeshellarg($maxX) . 'x' . escapeshellarg($maxY) . + ' ' . escapeshellarg($tmpPath) . + ' > /dev/null 2>&1'; + } - return $image->valid() ? $image : false; + exec($cmd, $output, $returnCode); + + unlink($absPath); + + if ($returnCode === 0) { + $image = new \OC_Image(); + $image->loadFromFile($tmpPath); + unlink($tmpPath); + return $image->valid() ? $image : false; + } + return false; + } } + + // a bit hacky but didn't want to use subclasses + Movie::$avconvBinary = $avconvBinary; + Movie::$ffmpegBinary = $ffmpegBinary; + + \OC\Preview::registerProvider('OC\Preview\Movie'); } +} - \OC\Preview::registerProvider('OC\Preview\Movie'); -}
\ No newline at end of file diff --git a/lib/private/preview/mp3.php b/lib/private/preview/mp3.php index 1eed566315c..3fc0ab0490c 100644 --- a/lib/private/preview/mp3.php +++ b/lib/private/preview/mp3.php @@ -25,7 +25,8 @@ class MP3 extends Provider { if(isset($tags['id3v2']['APIC'][0]['data'])) { $picture = @$tags['id3v2']['APIC'][0]['data']; unlink($tmpPath); - $image = new \OC_Image($picture); + $image = new \OC_Image(); + $image->loadFromData($picture); return $image->valid() ? $image : $this->getNoCoverThumbnail(); } @@ -39,7 +40,8 @@ class MP3 extends Provider { return false; } - $image = new \OC_Image($icon); + $image = new \OC_Image(); + $image->loadFromFile($icon); return $image->valid() ? $image : false; } diff --git a/lib/private/preview/office-cl.php b/lib/private/preview/office-cl.php index 112909d6523..b11fed13ba1 100644 --- a/lib/private/preview/office-cl.php +++ b/lib/private/preview/office-cl.php @@ -7,128 +7,133 @@ */ namespace OC\Preview; -//we need imagick to convert -class Office extends Provider { +// office preview is currently not supported on Windows +if (!\OC_Util::runningOnWindows()) { - private $cmd; + //we need imagick to convert + class Office extends Provider { - public function getMimeType() { - return null; - } + private $cmd; - public function getThumbnail($path, $maxX, $maxY, $scalingup, $fileview) { - $this->initCmd(); - if(is_null($this->cmd)) { - return false; + public function getMimeType() { + return null; } - $absPath = $fileview->toTmpFile($path); + public function getThumbnail($path, $maxX, $maxY, $scalingup, $fileview) { + $this->initCmd(); + if(is_null($this->cmd)) { + return false; + } + + $absPath = $fileview->toTmpFile($path); + + $tmpDir = get_temp_dir(); - $tmpDir = get_temp_dir(); + $defaultParameters = ' --headless --nologo --nofirststartwizard --invisible --norestore -convert-to pdf -outdir '; + $clParameters = \OCP\Config::getSystemValue('preview_office_cl_parameters', $defaultParameters); - $defaultParameters = ' --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); + $export = 'export HOME=/' . $tmpDir; - $exec = $this->cmd . $clParameters . escapeshellarg($tmpDir) . ' ' . escapeshellarg($absPath); - $export = 'export HOME=/' . $tmpDir; + shell_exec($export . "\n" . $exec); - shell_exec($export . "\n" . $exec); + //create imagick object from pdf + try{ + $pdf = new \imagick($absPath . '.pdf' . '[0]'); + $pdf->setImageFormat('jpg'); + } catch (\Exception $e) { + unlink($absPath); + unlink($absPath . '.pdf'); + \OC_Log::write('core', $e->getmessage(), \OC_Log::ERROR); + return false; + } + + $image = new \OC_Image(); + $image->loadFromData($pdf); - //create imagick object from pdf - try{ - $pdf = new \imagick($absPath . '.pdf' . '[0]'); - $pdf->setImageFormat('jpg'); - } catch (\Exception $e) { unlink($absPath); unlink($absPath . '.pdf'); - \OC_Log::write('core', $e->getmessage(), \OC_Log::ERROR); - return false; + + return $image->valid() ? $image : false; } - $image = new \OC_Image($pdf); + private function initCmd() { + $cmd = ''; - unlink($absPath); - unlink($absPath . '.pdf'); + if(is_string(\OC_Config::getValue('preview_libreoffice_path', null))) { + $cmd = \OC_Config::getValue('preview_libreoffice_path', null); + } - return $image->valid() ? $image : false; - } + $whichLibreOffice = shell_exec('which libreoffice'); + if($cmd === '' && !empty($whichLibreOffice)) { + $cmd = 'libreoffice'; + } - private function initCmd() { - $cmd = ''; + $whichOpenOffice = shell_exec('which openoffice'); + if($cmd === '' && !empty($whichOpenOffice)) { + $cmd = 'openoffice'; + } - if(is_string(\OC_Config::getValue('preview_libreoffice_path', null))) { - $cmd = \OC_Config::getValue('preview_libreoffice_path', null); - } + if($cmd === '') { + $cmd = null; + } - $whichLibreOffice = shell_exec('which libreoffice'); - if($cmd === '' && !empty($whichLibreOffice)) { - $cmd = 'libreoffice'; + $this->cmd = $cmd; } + } - $whichOpenOffice = shell_exec('which openoffice'); - if($cmd === '' && !empty($whichOpenOffice)) { - $cmd = 'openoffice'; - } + //.doc, .dot + class MSOfficeDoc extends Office { - if($cmd === '') { - $cmd = null; + public function getMimeType() { + return '/application\/msword/'; } - $this->cmd = $cmd; - } -} - -//.doc, .dot -class MSOfficeDoc extends Office { - - public function getMimeType() { - return '/application\/msword/'; } -} + \OC\Preview::registerProvider('OC\Preview\MSOfficeDoc'); -\OC\Preview::registerProvider('OC\Preview\MSOfficeDoc'); + //.docm, .dotm, .xls(m), .xlt(m), .xla(m), .ppt(m), .pot(m), .pps(m), .ppa(m) + class MSOffice2003 extends Office { -//.docm, .dotm, .xls(m), .xlt(m), .xla(m), .ppt(m), .pot(m), .pps(m), .ppa(m) -class MSOffice2003 extends Office { + public function getMimeType() { + return '/application\/vnd.ms-.*/'; + } - public function getMimeType() { - return '/application\/vnd.ms-.*/'; } -} + \OC\Preview::registerProvider('OC\Preview\MSOffice2003'); -\OC\Preview::registerProvider('OC\Preview\MSOffice2003'); + //.docx, .dotx, .xlsx, .xltx, .pptx, .potx, .ppsx + class MSOffice2007 extends Office { -//.docx, .dotx, .xlsx, .xltx, .pptx, .potx, .ppsx -class MSOffice2007 extends Office { + public function getMimeType() { + return '/application\/vnd.openxmlformats-officedocument.*/'; + } - public function getMimeType() { - return '/application\/vnd.openxmlformats-officedocument.*/'; } -} + \OC\Preview::registerProvider('OC\Preview\MSOffice2007'); -\OC\Preview::registerProvider('OC\Preview\MSOffice2007'); + //.odt, .ott, .oth, .odm, .odg, .otg, .odp, .otp, .ods, .ots, .odc, .odf, .odb, .odi, .oxt + class OpenDocument extends Office { -//.odt, .ott, .oth, .odm, .odg, .otg, .odp, .otp, .ods, .ots, .odc, .odf, .odb, .odi, .oxt -class OpenDocument extends Office { + public function getMimeType() { + return '/application\/vnd.oasis.opendocument.*/'; + } - public function getMimeType() { - return '/application\/vnd.oasis.opendocument.*/'; } -} + \OC\Preview::registerProvider('OC\Preview\OpenDocument'); -\OC\Preview::registerProvider('OC\Preview\OpenDocument'); + //.sxw, .stw, .sxc, .stc, .sxd, .std, .sxi, .sti, .sxg, .sxm + class StarOffice extends Office { -//.sxw, .stw, .sxc, .stc, .sxd, .std, .sxi, .sti, .sxg, .sxm -class StarOffice extends Office { + public function getMimeType() { + return '/application\/vnd.sun.xml.*/'; + } - public function getMimeType() { - return '/application\/vnd.sun.xml.*/'; } + \OC\Preview::registerProvider('OC\Preview\StarOffice'); } - -\OC\Preview::registerProvider('OC\Preview\StarOffice');
\ No newline at end of file diff --git a/lib/private/preview/office-fallback.php b/lib/private/preview/office-fallback.php index e69ab0ab8cb..f184b3149d5 100644 --- a/lib/private/preview/office-fallback.php +++ b/lib/private/preview/office-fallback.php @@ -80,7 +80,8 @@ class MSOfficeExcel extends Provider { unlink($absPath); unlink($tmpPath); - $image = new \OC_Image($pdf); + $image = new \OC_Image(); + $image->loadFromData($pdf); return $image->valid() ? $image : false; } diff --git a/lib/private/preview/office.php b/lib/private/preview/office.php index 5287bbd6ac1..7a4826c76ec 100644 --- a/lib/private/preview/office.php +++ b/lib/private/preview/office.php @@ -7,16 +7,23 @@ */ //both, libreoffice backend and php fallback, need imagick if (extension_loaded('imagick')) { - $isShellExecEnabled = !in_array('shell_exec', explode(', ', ini_get('disable_functions'))); - $whichLibreOffice = shell_exec('which libreoffice'); - $isLibreOfficeAvailable = !empty($whichLibreOffice); - $whichOpenOffice = 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)))) { - require_once('office-cl.php'); - }else{ + $isShellExecEnabled = \OC_Helper::is_function_enabled('shell_exec'); + + // LibreOffice preview is currently not supported on Windows + if (!\OC_Util::runningOnWindows()) { + $whichLibreOffice = ($isShellExecEnabled ? shell_exec('which libreoffice') : ''); + $isLibreOfficeAvailable = !empty($whichLibreOffice); + $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)))) { + require_once('office-cl.php'); + }else{ + //in case there isn't, use our fallback + require_once('office-fallback.php'); + } + } else { //in case there isn't, use our fallback require_once('office-fallback.php'); } -}
\ No newline at end of file +} diff --git a/lib/private/preview/provider.php b/lib/private/preview/provider.php index e4a730bafc8..65d09705f40 100644 --- a/lib/private/preview/provider.php +++ b/lib/private/preview/provider.php @@ -11,9 +11,15 @@ abstract class Provider { abstract public function getMimeType(); /** - * search for $query - * @param string $query - * @return + * get thumbnail for file at path $path + * @param string $path Path of file + * @param int $maxX The maximum X size of the thumbnail. It can be smaller depending on the shape of the image + * @param int $maxY The maximum Y size of the thumbnail. It can be smaller depending on the shape of the image + * @param bool $scalingUp Disable/Enable upscaling of previews + * @param object $fileview fileview object of user folder + * @return mixed + * false if no preview was generated + * OC_Image object of the preview */ abstract public function getThumbnail($path, $maxX, $maxY, $scalingup, $fileview); } diff --git a/lib/private/preview/txt.php b/lib/private/preview/txt.php index 77e728eb364..c9aa20968d8 100644 --- a/lib/private/preview/txt.php +++ b/lib/private/preview/txt.php @@ -9,20 +9,19 @@ namespace OC\Preview; class TXT extends Provider { - private static $blacklist = array( - 'text/calendar', - 'text/vcard', - ); - public function getMimeType() { - return '/text\/.*/'; + return '/text\/plain/'; } + /** + * @param string $path + * @param int $maxX + * @param int $maxY + * @param boolean $scalingup + * @param \OC\Files\View $fileview + * @return bool|\OC_Image + */ public function getThumbnail($path, $maxX, $maxY, $scalingup, $fileview) { - $mimetype = $fileview->getMimeType($path); - if(in_array($mimetype, self::$blacklist)) { - return false; - } $content = $fileview->fopen($path, 'r'); $content = stream_get_contents($content); @@ -62,22 +61,12 @@ class TXT extends Provider { \OC\Preview::registerProvider('OC\Preview\TXT'); -class PHP extends TXT { - - public function getMimeType() { - return '/application\/x-php/'; - } - -} - -\OC\Preview::registerProvider('OC\Preview\PHP'); - -class JavaScript extends TXT { +class MarkDown extends TXT { public function getMimeType() { - return '/application\/javascript/'; + return '/text\/(x-)?markdown/'; } } -\OC\Preview::registerProvider('OC\Preview\JavaScript');
\ No newline at end of file +\OC\Preview::registerProvider('OC\Preview\MarkDown'); diff --git a/lib/private/preview/unknown.php b/lib/private/preview/unknown.php index 9e6cd68d401..4747f9e25ed 100644 --- a/lib/private/preview/unknown.php +++ b/lib/private/preview/unknown.php @@ -20,8 +20,30 @@ class Unknown extends Provider { $path = \OC_Helper::mimetypeIcon($mimetype); $path = \OC::$SERVERROOT . substr($path, strlen(\OC::$WEBROOT)); - return new \OC_Image($path); + $svgPath = substr_replace($path, 'svg', -3); + + if (extension_loaded('imagick') && file_exists($svgPath)) { + + // http://www.php.net/manual/de/imagick.setresolution.php#85284 + $svg = new \Imagick(); + $svg->readImage($svgPath); + $res = $svg->getImageResolution(); + $x_ratio = $res['x'] / $svg->getImageWidth(); + $y_ratio = $res['y'] / $svg->getImageHeight(); + $svg->removeImage(); + $svg->setResolution($maxX * $x_ratio, $maxY * $y_ratio); + $svg->setBackgroundColor(new \ImagickPixel('transparent')); + $svg->readImage($svgPath); + $svg->setImageFormat('png32'); + + $image = new \OC_Image(); + $image->loadFromData($svg); + } else { + $image = new \OC_Image($path); + } + + return $image; } } -\OC\Preview::registerProvider('OC\Preview\Unknown');
\ No newline at end of file +\OC\Preview::registerProvider('OC\Preview\Unknown'); diff --git a/lib/private/repair.php b/lib/private/repair.php new file mode 100644 index 00000000000..e9de3baa7ce --- /dev/null +++ b/lib/private/repair.php @@ -0,0 +1,21 @@ +<?php +/** + * Copyright (c) 2013 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 OC; + +use OC\Hooks\BasicEmitter; + +class Repair extends BasicEmitter { + /** + * run a series of repair steps for common problems + * progress can be reported by emitting \OC\Repair::step events + */ + public function run() { + $this->emit('\OC\Repair', 'step', array('No repair steps configured at the moment')); + } +} diff --git a/lib/private/request.php b/lib/private/request.php index df33217f95d..d9d5ae08e28 100755 --- a/lib/private/request.php +++ b/lib/private/request.php @@ -7,8 +7,14 @@ */ class OC_Request { + + const USER_AGENT_IE = '/MSIE/'; + // Android Chrome user agent: https://developers.google.com/chrome/mobile/docs/user-agent + const USER_AGENT_ANDROID_MOBILE_CHROME = '#Android.*Chrome/[.0-9]*#'; + /** * @brief Check overwrite condition + * @param string $type * @returns bool */ private static function isOverwriteCondition($type = '') { @@ -99,7 +105,7 @@ class OC_Request { public static function scriptName() { $name = $_SERVER['SCRIPT_NAME']; if (OC_Config::getValue('overwritewebroot', '') !== '' and self::isOverwriteCondition()) { - $serverroot = str_replace("\\", '/', substr(__DIR__, 0, -4)); + $serverroot = str_replace("\\", '/', substr(__DIR__, 0, -strlen('lib/private/'))); $suburi = str_replace("\\", "/", substr(realpath($_SERVER["SCRIPT_FILENAME"]), strlen($serverroot))); $name = OC_Config::getValue('overwritewebroot', '') . $suburi; } @@ -135,12 +141,40 @@ class OC_Request { * @returns string Path info or false when not found */ public static function getRawPathInfo() { - $path_info = substr($_SERVER['REQUEST_URI'], strlen($_SERVER['SCRIPT_NAME'])); + $requestUri = $_SERVER['REQUEST_URI']; + // remove too many leading slashes - can be caused by reverse proxy configuration + if (strpos($requestUri, '/') === 0) { + $requestUri = '/' . ltrim($requestUri, '/'); + } + // Remove the query string from REQUEST_URI - if ($pos = strpos($path_info, '?')) { - $path_info = substr($path_info, 0, $pos); + if ($pos = strpos($requestUri, '?')) { + $requestUri = substr($requestUri, 0, $pos); + } + + $scriptName = $_SERVER['SCRIPT_NAME']; + $path_info = $requestUri; + + // strip off the script name's dir and file name + list($path, $name) = \Sabre_DAV_URLUtil::splitPath($scriptName); + if (!empty($path)) { + if( $path === $path_info || strpos($path_info, $path.'/') === 0) { + $path_info = substr($path_info, strlen($path)); + } else { + throw new Exception("The requested uri($requestUri) cannot be processed by the script '$scriptName')"); + } + } + if (strpos($path_info, '/'.$name) === 0) { + $path_info = substr($path_info, strlen($name) + 1); + } + if (strpos($path_info, $name) === 0) { + $path_info = substr($path_info, strlen($name)); + } + if($path_info === '/'){ + return ''; + } else { + return $path_info; } - return $path_info; } /** @@ -181,4 +215,22 @@ class OC_Request { return false; } } + + /** + * Checks whether the user agent matches a given regex + * @param string|array $agent agent name or array of agent names + * @return boolean true if at least one of the given agent matches, + * false otherwise + */ + static public function isUserAgent($agent) { + if (!is_array($agent)) { + $agent = array($agent); + } + foreach ($agent as $regex) { + if (preg_match($regex, $_SERVER['HTTP_USER_AGENT'])) { + return true; + } + } + return false; + } } diff --git a/lib/private/response.php b/lib/private/response.php index 674176d078b..04746437347 100644 --- a/lib/private/response.php +++ b/lib/private/response.php @@ -148,6 +148,20 @@ class OC_Response { } /** + * Sets the content disposition header (with possible workarounds) + * @param string $filename file name + * @param string $type disposition type, either 'attachment' or 'inline' + */ + static public function setContentDispositionHeader( $filename, $type = 'attachment' ) { + if (OC_Request::isUserAgent(array(OC_Request::USER_AGENT_IE, OC_Request::USER_AGENT_ANDROID_MOBILE_CHROME))) { + header( 'Content-Disposition: ' . rawurlencode($type) . '; filename="' . rawurlencode( $filename ) . '"' ); + } else { + header( 'Content-Disposition: ' . rawurlencode($type) . '; filename*=UTF-8\'\'' . rawurlencode( $filename ) + . '; filename="' . rawurlencode( $filename ) . '"' ); + } + } + + /** * @brief Send file as response, checking and setting caching headers * @param $filepath of file to send */ diff --git a/lib/private/route.php b/lib/private/route.php index 5901717c094..fb7da456b62 100644 --- a/lib/private/route.php +++ b/lib/private/route.php @@ -52,6 +52,14 @@ class OC_Route extends Route { } /** + * Specify PATCH as the method to use with this route + */ + public function patch() { + $this->method('PATCH'); + return $this; + } + + /** * Defaults to use for this route * * @param array $defaults The defaults diff --git a/lib/private/router.php b/lib/private/router.php index dbaca9e0d5d..19c1e4473ec 100644 --- a/lib/private/router.php +++ b/lib/private/router.php @@ -67,7 +67,8 @@ class OC_Router { $this->useCollection($app); require_once $file; $collection = $this->getCollection($app); - $this->root->addCollection($collection, '/apps/'.$app); + $collection->addPrefix('/apps/'.$app); + $this->root->addCollection($collection); } $this->useCollection('root'); require_once 'settings/routes.php'; @@ -76,7 +77,8 @@ class OC_Router { // include ocs routes require_once 'ocs/routes.php'; $collection = $this->getCollection('ocs'); - $this->root->addCollection($collection, '/ocs'); + $collection->addPrefix('/ocs'); + $this->root->addCollection($collection); } protected function getCollection($name) { diff --git a/lib/private/server.php b/lib/private/server.php index cabb15324ec..2cbd37a97d7 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; @@ -22,12 +23,16 @@ class Server extends SimpleContainer implements IServerContainer { return new ContactsManager(); }); $this->registerService('Request', function($c) { - $params = array(); + if (isset($c['urlParams'])) { + $urlParams = $c['urlParams']; + } else { + $urlParams = array(); + } - // we json decode the body only in case of content type json - if (isset($_SERVER['CONTENT_TYPE']) && stripos($_SERVER['CONTENT_TYPE'],'json') !== false ) { - $params = json_decode(file_get_contents('php://input'), true); - $params = is_array($params) ? $params: array(); + if (\OC::$session->exists('requesttoken')) { + $requesttoken = \OC::$session->get('requesttoken'); + } else { + $requesttoken = false; } return new Request( @@ -41,8 +46,8 @@ class Server extends SimpleContainer implements IServerContainer { 'method' => (isset($_SERVER) && isset($_SERVER['REQUEST_METHOD'])) ? $_SERVER['REQUEST_METHOD'] : null, - 'params' => $params, - 'urlParams' => $c['urlParams'] + 'urlParams' => $urlParams, + 'requesttoken' => $requesttoken, ) ); }); @@ -64,10 +69,18 @@ class Server extends SimpleContainer implements IServerContainer { return new Root($manager, $view, $user); }); $this->registerService('UserManager', function($c) { - return new \OC\User\Manager(); + /** + * @var SimpleContainer $c + * @var \OC\AllConfig $config + */ + $config = $c->query('AllConfig'); + return new \OC\User\Manager($config); }); $this->registerService('UserSession', function($c) { - /** @var $c SimpleContainer */ + /** + * @var SimpleContainer $c + * @var \OC\User\Manager $manager + */ $manager = $c->query('UserManager'); $userSession = new \OC\User\Session($manager, \OC::$session); $userSession->listen('\OC\User', 'preCreateUser', function ($uid, $password) { @@ -111,9 +124,26 @@ class Server extends SimpleContainer implements IServerContainer { $this->registerService('AllConfig', function($c) { return new \OC\AllConfig(); }); + $this->registerService('L10NFactory', function($c) { + return new \OC\L10N\Factory(); + }); + $this->registerService('URLGenerator', function($c) { + /** @var $c SimpleContainer */ + $config = $c->query('AllConfig'); + return new \OC\URLGenerator($config); + }); + $this->registerService('AppHelper', function($c) { + return new \OC\AppHelper(); + }); $this->registerService('UserCache', function($c) { return new UserCache(); }); + $this->registerService('ActivityManager', function($c) { + return new ActivityManager(); + }); + $this->registerService('AvatarManager', function($c) { + return new AvatarManager(); + }); } /** @@ -154,6 +184,15 @@ class Server extends SimpleContainer implements IServerContainer { } /** + * Returns the avatar manager, used for avatar functionality + * + * @return \OCP\IAvatarManager + */ + function getAvatarManager() { + return $this->query('AvatarManager'); + } + + /** * Returns the root folder of ownCloud's data directory * * @return \OCP\Files\Folder @@ -220,13 +259,36 @@ class Server extends SimpleContainer implements IServerContainer { } /** - * @return \OC\Config + * @return \OCP\IConfig */ function getConfig() { return $this->query('AllConfig'); } /** + * get an L10N instance + * @param $app string appid + * @return \OC_L10N + */ + function getL10N($app) { + return $this->query('L10NFactory')->get($app); + } + + /** + * @return \OC\URLGenerator + */ + function getURLGenerator() { + return $this->query('URLGenerator'); + } + + /** + * @return \OC\Helper + */ + function getHelper() { + return $this->query('AppHelper'); + } + + /** * Returns an ICache instance * * @return \OCP\ICache @@ -250,6 +312,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/session/internal.php b/lib/private/session/internal.php index 60aecccc8aa..a7c9e2fdefd 100644 --- a/lib/private/session/internal.php +++ b/lib/private/session/internal.php @@ -26,10 +26,21 @@ class Internal extends Memory { } public function __destruct() { - $_SESSION = $this->data; + $_SESSION = array_merge($_SESSION, $this->data); session_write_close(); } + /** + * @param string $key + */ + public function remove($key) { + // also remove it from $_SESSION to prevent re-setting the old value during the merge + if (isset($_SESSION[$key])) { + unset($_SESSION[$key]); + } + parent::remove($key); + } + public function clear() { session_unset(); @session_regenerate_id(true); diff --git a/lib/private/session/memory.php b/lib/private/session/memory.php index c148ff4b9b9..134cee582ed 100644 --- a/lib/private/session/memory.php +++ b/lib/private/session/memory.php @@ -11,7 +11,7 @@ namespace OC\Session; /** * Class Internal * - * store session data in an in-memory array, not persistance + * store session data in an in-memory array, not persistent * * @package OC\Session */ diff --git a/lib/private/session/session.php b/lib/private/session/session.php index c55001eccac..fe160faa267 100644 --- a/lib/private/session/session.php +++ b/lib/private/session/session.php @@ -8,7 +8,10 @@ namespace OC\Session; -abstract class Session implements \ArrayAccess, \OCP\ISession { +use OCP\ISession; + +abstract class Session implements \ArrayAccess, ISession { + /** * $name serves as a namespace for the session keys * @@ -17,36 +20,6 @@ abstract class Session implements \ArrayAccess, \OCP\ISession { abstract public function __construct($name); /** - * @param string $key - * @param mixed $value - */ - abstract public function set($key, $value); - - /** - * @param string $key - * @return mixed should return null if $key does not exist - */ - abstract public function get($key); - - /** - * @param string $key - * @return bool - */ - abstract public function exists($key); - - /** - * should not throw any errors if $key does not exist - * - * @param string $key - */ - abstract public function remove($key); - - /** - * removes all entries within the cache namespace - */ - abstract public function clear(); - - /** * @param mixed $offset * @return bool */ diff --git a/lib/private/setup.php b/lib/private/setup.php index 6bf3c88370f..5232398d1d7 100644 --- a/lib/private/setup.php +++ b/lib/private/setup.php @@ -159,14 +159,28 @@ class OC_Setup { $content.= "</IfModule>\n"; $content.= "AddDefaultCharset utf-8\n"; $content.= "Options -Indexes\n"; + $content.= "<IfModule pagespeed_module>\n"; + $content.= "ModPagespeed Off\n"; + $content.= "</IfModule>\n"; @file_put_contents(OC::$SERVERROOT.'/.htaccess', $content); //supress errors in case we don't have permissions for it self::protectDataDirectory(); } public static function protectDataDirectory() { - $content = "deny from all\n"; - $content.= "IndexIgnore *"; + //Require all denied + $now = date('Y-m-d H:i:s'); + $content = "# Generated by ownCloud on $now\n"; + $content.= "# line below if for Apache 2.4\n"; + $content.= "<ifModule mod_authz_core>\n"; + $content.= "Require all denied\n"; + $content.= "</ifModule>\n\n"; + $content.= "# line below if for Apache 2.2\n"; + $content.= "<ifModule !mod_authz_core>\n"; + $content.= "deny from all\n"; + $content.= "</ifModule>\n\n"; + $content.= "# section for Apache 2.2 and 2.4\n"; + $content.= "IndexIgnore *\n"; file_put_contents(OC_Config::getValue('datadirectory', OC::$SERVERROOT.'/data').'/.htaccess', $content); file_put_contents(OC_Config::getValue('datadirectory', OC::$SERVERROOT.'/data').'/index.html', ''); } @@ -183,7 +197,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'); + \OC_Helper::linkToDocs('admin-install')); OC_Template::printErrorPage($error, $hint); exit(); diff --git a/lib/private/setup/abstractdatabase.php b/lib/private/setup/abstractdatabase.php index 0beada7bd29..84625a217ee 100644 --- a/lib/private/setup/abstractdatabase.php +++ b/lib/private/setup/abstractdatabase.php @@ -3,6 +3,10 @@ namespace OC\Setup; abstract class AbstractDatabase { + + /** + * @var \OC_L10N + */ protected $trans; protected $dbDefinitionFile; protected $dbuser; diff --git a/lib/private/setup/oci.php b/lib/private/setup/oci.php index 326d7a00531..24863b9e38a 100644 --- a/lib/private/setup/oci.php +++ b/lib/private/setup/oci.php @@ -29,10 +29,10 @@ class OCI extends AbstractDatabase { \OC_Log::write('setup oracle', 'connect string: ' . $easy_connect_string, \OC_Log::DEBUG); $connection = @oci_connect($this->dbuser, $this->dbpassword, $easy_connect_string); if(!$connection) { - $e = oci_error(); - if (is_array ($e) && isset ($e['message'])) { + $errorMessage = $this->getLastError(); + if ($errorMessage) { throw new \DatabaseSetupException($this->trans->t('Oracle connection could not be established'), - $e['message'].' Check environment: ORACLE_HOME='.getenv('ORACLE_HOME') + $errorMessage.' Check environment: ORACLE_HOME='.getenv('ORACLE_HOME') .' ORACLE_SID='.getenv('ORACLE_SID') .' LD_LIBRARY_PATH='.getenv('LD_LIBRARY_PATH') .' NLS_LANG='.getenv('NLS_LANG') @@ -51,7 +51,7 @@ class OCI extends AbstractDatabase { ." WHERE user_role_privs.granted_role = role_sys_privs.role AND privilege = 'CREATE ROLE'"; $stmt = oci_parse($connection, $query); if (!$stmt) { - $entry = $this->trans->t('DB Error: "%s"', array(oci_last_error($connection))) . '<br />'; + $entry = $this->trans->t('DB Error: "%s"', array($this->getLastError($connection))) . '<br />'; $entry .= $this->trans->t('Offending command was: "%s"', array($query)) . '<br />'; \OC_Log::write('setup.oci', $entry, \OC_Log::WARN); } @@ -68,25 +68,25 @@ class OCI extends AbstractDatabase { $this->dbpassword=\OC_Util::generateRandomBytes(30); //oracle passwords are treated as identifiers: - // must start with aphanumeric char + // must start with alphanumeric char // needs to be shortened to 30 bytes, as the two " needed to escape the identifier count towards the identifier length. $this->dbpassword=substr($this->dbpassword, 0, 30); $this->createDBUser($connection); - \OC_Config::setValue('dbuser', $this->dbusername); - \OC_Config::setValue('dbname', $this->dbusername); + \OC_Config::setValue('dbuser', $this->dbuser); + \OC_Config::setValue('dbname', $this->dbuser); \OC_Config::setValue('dbpassword', $this->dbpassword); - //create the database not neccessary, oracle implies user = schema - //$this->createDatabase($this->dbname, $this->dbusername, $connection); + //create the database not necessary, oracle implies user = schema + //$this->createDatabase($this->dbname, $this->dbuser, $connection); } else { \OC_Config::setValue('dbuser', $this->dbuser); \OC_Config::setValue('dbname', $this->dbname); \OC_Config::setValue('dbpassword', $this->dbpassword); - //create the database not neccessary, oracle implies user = schema + //create the database not necessary, oracle implies user = schema //$this->createDatabase($this->dbname, $this->dbuser, $connection); } @@ -115,10 +115,10 @@ class OCI extends AbstractDatabase { } $query = "SELECT count(*) FROM user_tables WHERE table_name = :un"; $stmt = oci_parse($connection, $query); - $un = $this->dbtableprefix.'users'; + $un = $this->tableprefix.'users'; oci_bind_by_name($stmt, ':un', $un); if (!$stmt) { - $entry = $this->trans->t('DB Error: "%s"', array(oci_error($connection))) . '<br />'; + $entry = $this->trans->t('DB Error: "%s"', array($this->getLastError($connection))) . '<br />'; $entry .= $this->trans->t('Offending command was: "%s"', array($query)) . '<br />'; \OC_Log::write('setup.oci', $entry, \OC_Log::WARN); } @@ -133,25 +133,22 @@ class OCI extends AbstractDatabase { } /** - * - * @param String $name - * @param String $password * @param resource $connection */ private function createDBUser($connection) { $name = $this->dbuser; - $password = $this->password; + $password = $this->dbpassword; $query = "SELECT * FROM all_users WHERE USERNAME = :un"; $stmt = oci_parse($connection, $query); if (!$stmt) { - $entry = $this->trans->t('DB Error: "%s"', array(oci_error($connection))) . '<br />'; + $entry = $this->trans->t('DB Error: "%s"', array($this->getLastError($connection))) . '<br />'; $entry .= $this->trans->t('Offending command was: "%s"', array($query)) . '<br />'; \OC_Log::write('setup.oci', $entry, \OC_Log::WARN); } oci_bind_by_name($stmt, ':un', $name); $result = oci_execute($stmt); if(!$result) { - $entry = $this->trans->t('DB Error: "%s"', array(oci_error($connection))) . '<br />'; + $entry = $this->trans->t('DB Error: "%s"', array($this->getLastError($connection))) . '<br />'; $entry .= $this->trans->t('Offending command was: "%s"', array($query)) . '<br />'; \OC_Log::write('setup.oci', $entry, \OC_Log::WARN); } @@ -162,14 +159,14 @@ class OCI extends AbstractDatabase { $query = 'CREATE USER '.$name.' IDENTIFIED BY "'.$password.'" DEFAULT TABLESPACE '.$this->dbtablespace; $stmt = oci_parse($connection, $query); if (!$stmt) { - $entry = $this->trans->t('DB Error: "%s"', array(oci_error($connection))) . '<br />'; + $entry = $this->trans->t('DB Error: "%s"', array($this->getLastError($connection))) . '<br />'; $entry .= $this->trans->t('Offending command was: "%s"', array($query)) . '<br />'; \OC_Log::write('setup.oci', $entry, \OC_Log::WARN); } //oci_bind_by_name($stmt, ':un', $name); $result = oci_execute($stmt); if(!$result) { - $entry = $this->trans->t('DB Error: "%s"', array(oci_error($connection))) . '<br />'; + $entry = $this->trans->t('DB Error: "%s"', array($this->getLastError($connection))) . '<br />'; $entry .= $this->trans->t('Offending command was: "%s", name: %s, password: %s', array($query, $name, $password)) . '<br />'; \OC_Log::write('setup.oci', $entry, \OC_Log::WARN); @@ -178,7 +175,7 @@ class OCI extends AbstractDatabase { $query = "ALTER USER :un IDENTIFIED BY :pw"; $stmt = oci_parse($connection, $query); if (!$stmt) { - $entry = $this->trans->t('DB Error: "%s"', array(oci_error($connection))) . '<br />'; + $entry = $this->trans->t('DB Error: "%s"', array($this->getLastError($connection))) . '<br />'; $entry .= $this->trans->t('Offending command was: "%s"', array($query)) . '<br />'; \OC_Log::write('setup.oci', $entry, \OC_Log::WARN); } @@ -186,7 +183,7 @@ class OCI extends AbstractDatabase { oci_bind_by_name($stmt, ':pw', $password); $result = oci_execute($stmt); if(!$result) { - $entry = $this->trans->t('DB Error: "%s"', array(oci_error($connection))) . '<br />'; + $entry = $this->trans->t('DB Error: "%s"', array($this->getLastError($connection))) . '<br />'; $entry .= $this->trans->t('Offending command was: "%s"', array($query)) . '<br />'; \OC_Log::write('setup.oci', $entry, \OC_Log::WARN); } @@ -195,16 +192,34 @@ class OCI extends AbstractDatabase { $query = 'GRANT CREATE SESSION, CREATE TABLE, CREATE SEQUENCE, CREATE TRIGGER, UNLIMITED TABLESPACE TO '.$name; $stmt = oci_parse($connection, $query); if (!$stmt) { - $entry = $this->trans->t('DB Error: "%s"', array(oci_error($connection))) . '<br />'; + $entry = $this->trans->t('DB Error: "%s"', array($this->getLastError($connection))) . '<br />'; $entry .= $this->trans->t('Offending command was: "%s"', array($query)) . '<br />'; \OC_Log::write('setup.oci', $entry, \OC_Log::WARN); } $result = oci_execute($stmt); if(!$result) { - $entry = $this->trans->t('DB Error: "%s"', array(oci_error($connection))) . '<br />'; + $entry = $this->trans->t('DB Error: "%s"', array($this->getLastError($connection))) . '<br />'; $entry .= $this->trans->t('Offending command was: "%s", name: %s, password: %s', array($query, $name, $password)) . '<br />'; \OC_Log::write('setup.oci', $entry, \OC_Log::WARN); } } + + /** + * @param resource $connection + * @return string + */ + protected function getLastError($connection = null) { + if ($connection) { + $error = oci_error($connection); + } else { + $error = oci_error(); + } + foreach (array('message', 'code') as $key) { + if (isset($error[$key])) { + return $error[$key]; + } + } + return ''; + } } diff --git a/lib/private/tags.php b/lib/private/tags.php index 9fdb35a7d6e..fe7de1073a0 100644 --- a/lib/private/tags.php +++ b/lib/private/tags.php @@ -480,7 +480,7 @@ class Tags implements \OCP\ITags { return $this->getIdsForTag(self::TAG_FAVORITE); } catch(\Exception $e) { \OCP\Util::writeLog('core', __METHOD__.', exception: ' . $e->getMessage(), - \OCP\Util::ERROR); + \OCP\Util::DEBUG); return array(); } } diff --git a/lib/private/template.php b/lib/private/template.php index 9b2c1211e61..b2c3a20f281 100644 --- a/lib/private/template.php +++ b/lib/private/template.php @@ -292,9 +292,8 @@ class OC_Template extends \OC\Template\Base { if (!empty($hint)) { $hint = '<pre>'.$hint.'</pre>'; } - $l = OC_L10N::get('lib'); while (method_exists($exception, 'previous') && $exception = $exception->previous()) { - $error_msg .= '<br/>'.$l->t('Caused by:').' '; + $error_msg .= '<br/>Caused by:' . ' '; if ($exception->getCode()) { $error_msg .= '['.$exception->getCode().'] '; } diff --git a/lib/private/template/functions.php b/lib/private/template/functions.php index 501f8081bff..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 @@ -85,22 +93,51 @@ function human_file_size( $bytes ) { return OC_Helper::humanFileSize( $bytes ); } -function relative_modified_date($timestamp) { +/** + * @brief Strips the timestamp of its time value + * @param int $timestamp UNIX timestamp to strip + * @return $timestamp without time value + */ +function strip_time($timestamp){ + $date = new \DateTime("@{$timestamp}"); + $date->setTime(0, 0, 0); + return intval($date->format('U')); +} + +/** + * @brief Formats timestamp relatively to the current time using + * a human-friendly format like "x minutes ago" or "yesterday" + * @param int $timestamp timestamp to format + * @param int $fromTime timestamp to compare from, defaults to current time + * @param bool $dateOnly whether to strip time information + * @return formatted timestamp + */ +function relative_modified_date($timestamp, $fromTime = null, $dateOnly = false) { $l=OC_L10N::get('lib'); - $timediff = time() - $timestamp; + if (!isset($fromTime) || $fromTime === null){ + $fromTime = time(); + } + if ($dateOnly){ + $fromTime = strip_time($fromTime); + $timestamp = strip_time($timestamp); + } + $timediff = $fromTime - $timestamp; $diffminutes = round($timediff/60); $diffhours = round($diffminutes/60); $diffdays = round($diffhours/24); $diffmonths = round($diffdays/31); - if($timediff < 60) { return $l->t('seconds ago'); } - else if($timediff < 3600) { return $l->n('%n minute ago', '%n minutes ago', $diffminutes); } - else if($timediff < 86400) { return $l->n('%n hour ago', '%n hours ago', $diffhours); } - else if((date('G')-$diffhours) > 0) { return $l->t('today'); } - else if((date('G')-$diffhours) > -24) { return $l->t('yesterday'); } + if(!$dateOnly && $timediff < 60) { return $l->t('seconds ago'); } + else if(!$dateOnly && $timediff < 3600) { return $l->n('%n minute ago', '%n minutes ago', $diffminutes); } + else if(!$dateOnly && $timediff < 86400) { return $l->n('%n hour ago', '%n hours ago', $diffhours); } + else if((date('G', $fromTime)-$diffhours) >= 0) { return $l->t('today'); } + else if((date('G', $fromTime)-$diffhours) >= -24) { return $l->t('yesterday'); } + // 86400 * 31 days = 2678400 else if($timediff < 2678400) { return $l->n('%n day go', '%n days ago', $diffdays); } + // 86400 * 60 days = 518400 else if($timediff < 5184000) { return $l->t('last month'); } - else if((date('n')-$diffmonths) > 0) { return $l->n('%n month ago', '%n months ago', $diffmonths); } + else if((date('n', $fromTime)-$diffmonths) > 0) { return $l->n('%n month ago', '%n months ago', $diffmonths); } + // 86400 * 365.25 days * 2 = 63113852 else if($timediff < 63113852) { return $l->t('last year'); } else { return $l->t('years ago'); } } diff --git a/lib/private/templatelayout.php b/lib/private/templatelayout.php index 625f3424a04..d5cd5039753 100644 --- a/lib/private/templatelayout.php +++ b/lib/private/templatelayout.php @@ -46,6 +46,7 @@ class OC_TemplateLayout extends OC_Template { $user_displayname = OC_User::getDisplayName(); $this->assign( 'user_displayname', $user_displayname ); $this->assign( 'user_uid', OC_User::getUser() ); + $this->assign( 'appsmanagement_active', strpos(OC_Request::requestUri(), OC_Helper::linkToRoute('settings_apps')) === 0 ); $this->assign('enableAvatars', \OC_Config::getValue('enable_avatars', true)); } else if ($renderas == 'guest' || $renderas == 'error') { parent::__construct('core', 'layout.guest'); diff --git a/lib/private/updater.php b/lib/private/updater.php index 9827d8a8c12..764a0f14120 100644 --- a/lib/private/updater.php +++ b/lib/private/updater.php @@ -37,7 +37,7 @@ class Updater extends BasicEmitter { /** * Check if a new version is available - * @param string $updateUrl the url to check, i.e. 'http://apps.owncloud.com/updater.php' + * @param string $updaterUrl the url to check, i.e. 'http://apps.owncloud.com/updater.php' * @return array | bool */ public function check($updaterUrl) { @@ -58,6 +58,7 @@ class Updater extends BasicEmitter { $version['updated'] = \OC_Appconfig::getValue('core', 'lastupdatedat'); $version['updatechannel'] = \OC_Util::getChannel(); $version['edition'] = \OC_Util::getEditionString(); + $version['build'] = \OC_Util::getBuild(); $versionString = implode('x', $version); //fetch xml data from updater @@ -115,6 +116,10 @@ class Updater extends BasicEmitter { \OC_App::checkAppsRequirements(); // load all apps to also upgrade enabled apps \OC_App::loadApps(); + + $repair = new Repair(); + $repair->run(); + \OC_Config::setValue('maintenance', false); $this->emit('\OC\Updater', 'maintenanceEnd'); } diff --git a/lib/private/urlgenerator.php b/lib/private/urlgenerator.php new file mode 100644 index 00000000000..4e3c1109000 --- /dev/null +++ b/lib/private/urlgenerator.php @@ -0,0 +1,152 @@ +<?php +/** + * Copyright (c) 2013 Bart Visscher <bartv@thisnet.nl> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + * + */ + +namespace OC; +use OCP\IURLGenerator; +use RuntimeException; + +/** + * Class to generate URLs + */ +class URLGenerator implements IURLGenerator { + + /** + * @var \OCP\IConfig + */ + private $config; + + /** + * @param \OCP\IConfig $config + */ + public function __construct($config) { + $this->config = $config; + } + + /** + * @brief Creates an url using a defined route + * @param $route + * @param array $parameters + * @return + * @internal param array $args with param=>value, will be appended to the returned url + * @returns string the url + * + * Returns a url to the given app and file. + */ + public function linkToRoute($route, $parameters = array()) { + $urlLinkTo = \OC::getRouter()->generate($route, $parameters); + return $urlLinkTo; + } + + /** + * @brief Creates an url + * @param string $app app + * @param string $file file + * @param array $args array with param=>value, will be appended to the returned url + * The value of $args will be urlencoded + * @return string the url + * + * Returns a url to the given app and file. + */ + public function linkTo( $app, $file, $args = array() ) { + $frontControllerActive=($this->config->getSystemValue('front_controller_active', 'false') == 'true'); + + if( $app != '' ) { + $app_path = \OC_App::getAppPath($app); + // Check if the app is in the app folder + if ($app_path && file_exists($app_path . '/' . $file)) { + if (substr($file, -3) == 'php' || substr($file, -3) == 'css') { + + $urlLinkTo = \OC::$WEBROOT . '/index.php/apps/' . $app; + if ($frontControllerActive) { + $urlLinkTo = \OC::$WEBROOT . '/apps/' . $app; + } + $urlLinkTo .= ($file != 'index.php') ? '/' . $file : ''; + } else { + $urlLinkTo = \OC_App::getAppWebPath($app) . '/' . $file; + } + } else { + $urlLinkTo = \OC::$WEBROOT . '/' . $app . '/' . $file; + } + } else { + if (file_exists(\OC::$SERVERROOT . '/core/' . $file)) { + $urlLinkTo = \OC::$WEBROOT . '/core/' . $file; + } else { + if ($frontControllerActive && $file === 'index.php') { + $urlLinkTo = \OC::$WEBROOT; + } else { + $urlLinkTo = \OC::$WEBROOT . '/' . $file; + } + } + } + + if ($args && $query = http_build_query($args, '', '&')) { + $urlLinkTo .= '?' . $query; + } + + return $urlLinkTo; + } + + /** + * @brief Creates path to an image + * @param string $app app + * @param string $image image name + * @return string the url + * + * Returns the path to the image. + */ + public function imagePath($app, $image) { + // Read the selected theme from the config file + $theme = \OC_Util::getTheme(); + + //if a theme has a png but not an svg always use the png + $basename = substr(basename($image),0,-4); + + // Check if the app is in the app folder + if (file_exists(\OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$image")) { + return \OC::$WEBROOT . "/themes/$theme/apps/$app/img/$image"; + } elseif (!file_exists(\OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$basename.svg") + && file_exists(\OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$basename.png")) { + return \OC::$WEBROOT . "/themes/$theme/apps/$app/img/$basename.png"; + } elseif (file_exists(\OC_App::getAppPath($app) . "/img/$image")) { + return \OC_App::getAppWebPath($app) . "/img/$image"; + } elseif (!file_exists(\OC_App::getAppPath($app) . "/img/$basename.svg") + && file_exists(\OC_App::getAppPath($app) . "/img/$basename.png")) { + return \OC_App::getAppPath($app) . "/img/$basename.png"; + } elseif (!empty($app) and file_exists(\OC::$SERVERROOT . "/themes/$theme/$app/img/$image")) { + return \OC::$WEBROOT . "/themes/$theme/$app/img/$image"; + } elseif (!empty($app) and (!file_exists(\OC::$SERVERROOT . "/themes/$theme/$app/img/$basename.svg") + && file_exists(\OC::$SERVERROOT . "/themes/$theme/$app/img/$basename.png"))) { + return \OC::$WEBROOT . "/themes/$theme/$app/img/$basename.png"; + } elseif (!empty($app) and file_exists(\OC::$SERVERROOT . "/$app/img/$image")) { + return \OC::$WEBROOT . "/$app/img/$image"; + } elseif (!empty($app) and (!file_exists(\OC::$SERVERROOT . "/$app/img/$basename.svg") + && file_exists(\OC::$SERVERROOT . "/$app/img/$basename.png"))) { + return \OC::$WEBROOT . "/$app/img/$basename.png"; + } elseif (file_exists(\OC::$SERVERROOT . "/themes/$theme/core/img/$image")) { + return \OC::$WEBROOT . "/themes/$theme/core/img/$image"; + } elseif (!file_exists(\OC::$SERVERROOT . "/themes/$theme/core/img/$basename.svg") + && file_exists(\OC::$SERVERROOT . "/themes/$theme/core/img/$basename.png")) { + return \OC::$WEBROOT . "/themes/$theme/core/img/$basename.png"; + } elseif (file_exists(\OC::$SERVERROOT . "/core/img/$image")) { + return \OC::$WEBROOT . "/core/img/$image"; + } else { + throw new RuntimeException('image not found: image:' . $image . ' webroot:' . \OC::$WEBROOT . ' serverroot:' . \OC::$SERVERROOT); + } + } + + + /** + * Makes an URL absolute + * @param string $url the url in the owncloud host + * @return string the absolute version of the url + */ + public function getAbsoluteURL($url) { + return \OC_Request::serverProtocol() . '://' . \OC_Request::serverHost() . $url; + } +} diff --git a/lib/private/user.php b/lib/private/user.php index 15e807088b4..98ebebbe5c1 100644 --- a/lib/private/user.php +++ b/lib/private/user.php @@ -54,6 +54,9 @@ class OC_User { private static $_setupedBackends = array(); + // bool, stores if a user want to access a resource anonymously, e.g if he opens a public link + private static $incognitoMode = false; + /** * @brief registers backend * @param string $backend name of the backend @@ -187,17 +190,28 @@ class OC_User { public static function deleteUser($uid) { $user = self::getManager()->get($uid); if ($user) { - $user->delete(); + $result = $user->delete(); + + // if delete was successful we clean-up the rest + if ($result) { + + // We have to delete the user from all groups + foreach (OC_Group::getUserGroups($uid) as $i) { + OC_Group::removeFromGroup($uid, $i); + } + // Delete the user's keys in preferences + OC_Preferences::deleteUser($uid); - // We have to delete the user from all groups - foreach (OC_Group::getUserGroups($uid) as $i) { - OC_Group::removeFromGroup($uid, $i); + // Delete user files in /data/ + OC_Helper::rmdirr(\OC_User::getHome($uid)); + + // Remove it from the Cache + self::getManager()->delete($uid); } - // Delete the user's keys in preferences - OC_Preferences::deleteUser($uid); - // Delete user files in /data/ - OC_Helper::rmdirr(OC_Config::getValue('datadirectory', OC::$SERVERROOT . '/data') . '/' . $uid . '/'); + return true; + } else { + return false; } } @@ -214,6 +228,57 @@ class OC_User { } /** + * @brief Try to login a user, assuming authentication + * has already happened (e.g. via Single Sign On). + * + * Log in a user and regenerate a new session. + * + * @param \OCP\Authentication\IApacheBackend $backend + * @return bool + */ + public static function loginWithApache(\OCP\Authentication\IApacheBackend $backend) { + + $uid = $backend->getCurrentUserId(); + $run = true; + OC_Hook::emit( "OC_User", "pre_login", array( "run" => &$run, "uid" => $uid )); + + if($uid) { + session_regenerate_id(true); + self::setUserId($uid); + self::setDisplayName($uid); + self::getUserSession()->setLoginName($uid); + + OC_Hook::emit( "OC_User", "post_login", array( "uid" => $uid, 'password'=>'' )); + return true; + } + return false; + } + + /** + * @brief Verify with Apache whether user is authenticated. + * + * @return boolean|null + * true: authenticated + * false: not authenticated + * null: not handled / no backend available + */ + public static function handleApacheAuth() { + $backend = self::findFirstActiveUsedBackend(); + if ($backend) { + OC_App::loadApps(); + + //setup extra user backends + self::setupBackends(); + self::unsetMagicInCookie(); + + return self::loginWithApache($backend); + } + + return null; + } + + + /** * @brief Sets user id for session and triggers emit */ public static function setUserId($uid) { @@ -251,7 +316,7 @@ class OC_User { * Checks if the user is logged in */ public static function isLoggedIn() { - if (\OC::$session->get('user_id')) { + if (\OC::$session->get('user_id') && self::$incognitoMode === false) { OC_App::loadApps(array('authentication')); self::setupBackends(); return self::userExists(\OC::$session->get('user_id')); @@ -260,12 +325,37 @@ class OC_User { } /** + * @brief set incognito mode, e.g. if a user wants to open a public link + * @param bool $status + */ + public static function setIncognitoMode($status) { + self::$incognitoMode = $status; + + } + + /** + * Supplies an attribute to the logout hyperlink. The default behaviour + * is to return an href with '?logout=true' appended. However, it can + * supply any attribute(s) which are valid for <a>. + * + * @return string with one or more HTML attributes. + */ + public static function getLogoutAttribute() { + $backend = self::findFirstActiveUsedBackend(); + if ($backend) { + return $backend->getLogoutAttribute(); + } + + return 'href="' . link_to('', 'index.php') . '?logout=true"'; + } + + /** * @brief Check if the user is an admin user * @param string $uid uid of the admin * @return bool */ public static function isAdminUser($uid) { - if (OC_Group::inGroup($uid, 'admin')) { + if (OC_Group::inGroup($uid, 'admin') && self::$incognitoMode === false) { return true; } return false; @@ -278,7 +368,7 @@ class OC_User { */ public static function getUser() { $uid = OC::$session ? OC::$session->get('user_id') : null; - if (!is_null($uid)) { + if (!is_null($uid) && self::$incognitoMode === false) { return $uid; } else { return false; @@ -337,6 +427,22 @@ class OC_User { } /** + * @brief Check whether user can change his avatar + * @param string $uid The username + * @return bool + * + * Check whether a specified user can change his avatar + */ + public static function canUserChangeAvatar($uid) { + $user = self::getManager()->get($uid); + if ($user) { + return $user->canChangeAvatar(); + } else { + return false; + } + } + + /** * @brief Check whether user can change his password * @param string $uid The username * @return bool @@ -497,4 +603,20 @@ class OC_User { public static function unsetMagicInCookie() { self::getUserSession()->unsetMagicInCookie(); } + + /** + * @brief Returns the first active backend from self::$_usedBackends. + * @return null if no backend active, otherwise OCP\Authentication\IApacheBackend + */ + private static function findFirstActiveUsedBackend() { + foreach (self::$_usedBackends as $backend) { + if ($backend instanceof OCP\Authentication\IApacheBackend) { + if ($backend->isSessionActive()) { + return $backend; + } + } + } + + return null; + } } diff --git a/lib/private/user/backend.php b/lib/private/user/backend.php index e9be08e429c..f4e5618e04a 100644 --- a/lib/private/user/backend.php +++ b/lib/private/user/backend.php @@ -31,13 +31,15 @@ define('OC_USER_BACKEND_NOT_IMPLEMENTED', -501); /** * actions that user backends can define */ -define('OC_USER_BACKEND_CREATE_USER', 0x000001); -define('OC_USER_BACKEND_SET_PASSWORD', 0x000010); -define('OC_USER_BACKEND_CHECK_PASSWORD', 0x000100); -define('OC_USER_BACKEND_GET_HOME', 0x001000); -define('OC_USER_BACKEND_GET_DISPLAYNAME', 0x010000); -define('OC_USER_BACKEND_SET_DISPLAYNAME', 0x100000); - +define('OC_USER_BACKEND_CREATE_USER', 0x00000001); +define('OC_USER_BACKEND_SET_PASSWORD', 0x00000010); +define('OC_USER_BACKEND_CHECK_PASSWORD', 0x00000100); +define('OC_USER_BACKEND_GET_HOME', 0x00001000); +define('OC_USER_BACKEND_GET_DISPLAYNAME', 0x00010000); +define('OC_USER_BACKEND_SET_DISPLAYNAME', 0x00100000); +define('OC_USER_BACKEND_PROVIDE_AVATAR', 0x01000000); +define('OC_USER_BACKEND_COUNT_USERS', 0x10000000); +//more actions cannot be defined without breaking 32bit platforms! /** * Abstract base class for user management. Provides methods for querying backend @@ -54,6 +56,8 @@ abstract class OC_User_Backend implements OC_User_Interface { OC_USER_BACKEND_GET_HOME => 'getHome', OC_USER_BACKEND_GET_DISPLAYNAME => 'getDisplayName', OC_USER_BACKEND_SET_DISPLAYNAME => 'setDisplayName', + OC_USER_BACKEND_PROVIDE_AVATAR => 'canChangeAvatar', + OC_USER_BACKEND_COUNT_USERS => 'countUsers', ); /** diff --git a/lib/private/user/database.php b/lib/private/user/database.php index 9f00a022d9f..1a63755b980 100644 --- a/lib/private/user/database.php +++ b/lib/private/user/database.php @@ -42,13 +42,13 @@ class OC_User_Database extends OC_User_Backend { /** * @var PasswordHash */ - static private $hasher=null; + static private $hasher = null; private function getHasher() { - if(!self::$hasher) { + if (!self::$hasher) { //we don't want to use DES based crypt(), since it doesn't return a hash with a recognisable prefix - $forcePortable=(CRYPT_BLOWFISH!=1); - self::$hasher=new PasswordHash(8, $forcePortable); + $forcePortable = (CRYPT_BLOWFISH != 1); + self::$hasher = new PasswordHash(8, $forcePortable); } return self::$hasher; @@ -63,14 +63,14 @@ class OC_User_Database extends OC_User_Backend { * Creates a new user. Basic checking of username is done in OC_User * itself, not in its subclasses. */ - public function createUser( $uid, $password ) { - if( $this->userExists($uid) ) { + public function createUser($uid, $password) { + if ($this->userExists($uid)) { return false; - }else{ - $hasher=$this->getHasher(); - $hash = $hasher->HashPassword($password.OC_Config::getValue('passwordsalt', '')); - $query = OC_DB::prepare( 'INSERT INTO `*PREFIX*users` ( `uid`, `password` ) VALUES( ?, ? )' ); - $result = $query->execute( array( $uid, $hash)); + } else { + $hasher = $this->getHasher(); + $hash = $hasher->HashPassword($password . OC_Config::getValue('passwordsalt', '')); + $query = OC_DB::prepare('INSERT INTO `*PREFIX*users` ( `uid`, `password` ) VALUES( ?, ? )'); + $result = $query->execute(array($uid, $hash)); return $result ? true : false; } @@ -83,10 +83,10 @@ class OC_User_Database extends OC_User_Backend { * * Deletes a user */ - public function deleteUser( $uid ) { + public function deleteUser($uid) { // Delete user-group-relation - $query = OC_DB::prepare( 'DELETE FROM `*PREFIX*users` WHERE `uid` = ?' ); - $query->execute( array( $uid )); + $query = OC_DB::prepare('DELETE FROM `*PREFIX*users` WHERE `uid` = ?'); + $query->execute(array($uid)); return true; } @@ -98,15 +98,15 @@ class OC_User_Database extends OC_User_Backend { * * Change the password of a user */ - public function setPassword( $uid, $password ) { - if( $this->userExists($uid) ) { - $hasher=$this->getHasher(); - $hash = $hasher->HashPassword($password.OC_Config::getValue('passwordsalt', '')); - $query = OC_DB::prepare( 'UPDATE `*PREFIX*users` SET `password` = ? WHERE `uid` = ?' ); - $query->execute( array( $hash, $uid )); + public function setPassword($uid, $password) { + if ($this->userExists($uid)) { + $hasher = $this->getHasher(); + $hash = $hasher->HashPassword($password . OC_Config::getValue('passwordsalt', '')); + $query = OC_DB::prepare('UPDATE `*PREFIX*users` SET `password` = ? WHERE `uid` = ?'); + $query->execute(array($hash, $uid)); return true; - }else{ + } else { return false; } } @@ -119,12 +119,12 @@ class OC_User_Database extends OC_User_Backend { * * Change the display name of a user */ - public function setDisplayName( $uid, $displayName ) { - if( $this->userExists($uid) ) { - $query = OC_DB::prepare( 'UPDATE `*PREFIX*users` SET `displayname` = ? WHERE `uid` = ?' ); - $query->execute( array( $displayName, $uid )); + public function setDisplayName($uid, $displayName) { + if ($this->userExists($uid)) { + $query = OC_DB::prepare('UPDATE `*PREFIX*users` SET `displayname` = ? WHERE LOWER(`uid`) = ?'); + $query->execute(array($displayName, $uid)); return true; - }else{ + } else { return false; } } @@ -132,18 +132,16 @@ class OC_User_Database extends OC_User_Backend { /** * @brief get display name of the user * @param $uid user ID of the user - * @return display name + * @return string display name */ public function getDisplayName($uid) { - if( $this->userExists($uid) ) { - $query = OC_DB::prepare( 'SELECT `displayname` FROM `*PREFIX*users` WHERE `uid` = ?' ); - $result = $query->execute( array( $uid ))->fetchAll(); - $displayName = trim($result[0]['displayname'], ' '); - if ( !empty($displayName) ) { - return $displayName; - } else { - return $uid; - } + $query = OC_DB::prepare('SELECT `displayname` FROM `*PREFIX*users` WHERE `uid` = ?'); + $result = $query->execute(array($uid))->fetchAll(); + $displayName = trim($result[0]['displayname'], ' '); + if (!empty($displayName)) { + return $displayName; + } else { + return $uid; } } @@ -156,25 +154,14 @@ class OC_User_Database extends OC_User_Backend { public function getDisplayNames($search = '', $limit = null, $offset = null) { $displayNames = array(); $query = OC_DB::prepare('SELECT `uid`, `displayname` FROM `*PREFIX*users`' - .' WHERE LOWER(`displayname`) LIKE LOWER(?)', $limit, $offset); - $result = $query->execute(array($search.'%')); + . ' WHERE LOWER(`displayname`) LIKE LOWER(?) OR ' + . 'LOWER(`uid`) LIKE LOWER(?)', $limit, $offset); + $result = $query->execute(array($search . '%', $search . '%')); $users = array(); while ($row = $result->fetchRow()) { $displayNames[$row['uid']] = $row['displayname']; } - // let's see if we can also find some users who don't have a display name yet - $query = OC_DB::prepare('SELECT `uid`, `displayname` FROM `*PREFIX*users`' - .' WHERE LOWER(`uid`) LIKE LOWER(?)', $limit, $offset); - $result = $query->execute(array($search.'%')); - while ($row = $result->fetchRow()) { - $displayName = trim($row['displayname'], ' '); - if ( empty($displayName) ) { - $displayNames[$row['uid']] = $row['uid']; - } - } - - return $displayNames; } @@ -187,30 +174,30 @@ class OC_User_Database extends OC_User_Backend { * Check if the password is correct without logging in the user * returns the user id or false */ - public function checkPassword( $uid, $password ) { - $query = OC_DB::prepare( 'SELECT `uid`, `password` FROM `*PREFIX*users` WHERE LOWER(`uid`) = LOWER(?)' ); - $result = $query->execute( array( $uid)); + public function checkPassword($uid, $password) { + $query = OC_DB::prepare('SELECT `uid`, `password` FROM `*PREFIX*users` WHERE LOWER(`uid`) = LOWER(?)'); + $result = $query->execute(array($uid)); - $row=$result->fetchRow(); - if($row) { - $storedHash=$row['password']; - if ($storedHash[0]=='$') {//the new phpass based hashing - $hasher=$this->getHasher(); - if($hasher->CheckPassword($password.OC_Config::getValue('passwordsalt', ''), $storedHash)) { + $row = $result->fetchRow(); + if ($row) { + $storedHash = $row['password']; + if ($storedHash[0] == '$') { //the new phpass based hashing + $hasher = $this->getHasher(); + if ($hasher->CheckPassword($password . OC_Config::getValue('passwordsalt', ''), $storedHash)) { return $row['uid']; - }else{ + } else { return false; } - }else{//old sha1 based hashing - if(sha1($password)==$storedHash) { + } else { //old sha1 based hashing + if (sha1($password) == $storedHash) { //upgrade to new hashing $this->setPassword($row['uid'], $password); return $row['uid']; - }else{ + } else { return false; } } - }else{ + } else { return false; } } @@ -223,7 +210,7 @@ class OC_User_Database extends OC_User_Backend { */ public function getUsers($search = '', $limit = null, $offset = null) { $query = OC_DB::prepare('SELECT `uid` FROM `*PREFIX*users` WHERE LOWER(`uid`) LIKE LOWER(?)', $limit, $offset); - $result = $query->execute(array($search.'%')); + $result = $query->execute(array($search . '%')); $users = array(); while ($row = $result->fetchRow()) { $users[] = $row['uid']; @@ -237,8 +224,8 @@ class OC_User_Database extends OC_User_Backend { * @return boolean */ public function userExists($uid) { - $query = OC_DB::prepare( 'SELECT COUNT(*) FROM `*PREFIX*users` WHERE LOWER(`uid`) = LOWER(?)' ); - $result = $query->execute( array( $uid )); + $query = OC_DB::prepare('SELECT COUNT(*) FROM `*PREFIX*users` WHERE LOWER(`uid`) = LOWER(?)'); + $result = $query->execute(array($uid)); if (OC_DB::isError($result)) { OC_Log::write('core', OC_DB::getErrorMessage($result), OC_Log::ERROR); return false; @@ -247,14 +234,14 @@ class OC_User_Database extends OC_User_Backend { } /** - * @brief get the user's home directory - * @param string $uid the username - * @return boolean - */ + * @brief get the user's home directory + * @param string $uid the username + * @return boolean + */ public function getHome($uid) { - if($this->userExists($uid)) { - return OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" ) . '/' . $uid; - }else{ + if ($this->userExists($uid)) { + return OC_Config::getValue("datadirectory", OC::$SERVERROOT . "/data") . '/' . $uid; + } else { return false; } } @@ -266,4 +253,19 @@ class OC_User_Database extends OC_User_Backend { return true; } + /** + * counts the users in the database + * + * @return int | bool + */ + public function countUsers() { + $query = OC_DB::prepare('SELECT COUNT(*) FROM `*PREFIX*users`'); + $result = $query->execute(); + if (OC_DB::isError($result)) { + OC_Log::write('core', OC_DB::getErrorMessage($result), OC_Log::ERROR); + return false; + } + return $result->fetchOne(); + } + } diff --git a/lib/private/user/dummy.php b/lib/private/user/dummy.php index b5b7a6c3c7a..fc15a630cf3 100644 --- a/lib/private/user/dummy.php +++ b/lib/private/user/dummy.php @@ -88,8 +88,8 @@ class OC_User_Dummy extends OC_User_Backend { * returns the user id or false */ public function checkPassword($uid, $password) { - if (isset($this->users[$uid])) { - return ($this->users[$uid] == $password); + if (isset($this->users[$uid]) && $this->users[$uid] === $password) { + return $uid; } else { return false; } @@ -123,4 +123,13 @@ class OC_User_Dummy extends OC_User_Backend { public function hasUserListings() { return true; } + + /** + * counts the users in the database + * + * @return int | bool + */ + public function countUsers() { + return 0; + } } diff --git a/lib/private/user/manager.php b/lib/private/user/manager.php index 13286bc28a4..90970ef9963 100644 --- a/lib/private/user/manager.php +++ b/lib/private/user/manager.php @@ -35,7 +35,16 @@ class Manager extends PublicEmitter { */ private $cachedUsers = array(); - public function __construct() { + /** + * @var \OC\AllConfig $config + */ + private $config; + + /** + * @param \OC\AllConfig $config + */ + public function __construct($config = null) { + $this->config = $config; $cachedUsers = $this->cachedUsers; $this->listen('\OC\User', 'postDelete', function ($user) use (&$cachedUsers) { $i = array_search($user, $cachedUsers); @@ -103,7 +112,7 @@ class Manager extends PublicEmitter { if (isset($this->cachedUsers[$uid])) { return $this->cachedUsers[$uid]; } - $this->cachedUsers[$uid] = new User($uid, $backend, $this); + $this->cachedUsers[$uid] = new User($uid, $backend, $this, $this->config); return $this->cachedUsers[$uid]; } @@ -119,6 +128,20 @@ class Manager extends PublicEmitter { } /** + * remove deleted user from cache + * + * @param string $uid + * @return bool + */ + public function delete($uid) { + if (isset($this->cachedUsers[$uid])) { + unset($this->cachedUsers[$uid]); + return true; + } + return false; + } + + /** * Check if the password is valid for the user * * @param $loginname @@ -127,7 +150,7 @@ class Manager extends PublicEmitter { */ public function checkPassword($loginname, $password) { foreach ($this->backends as $backend) { - if($backend->implementsActions(\OC_USER_BACKEND_CHECK_PASSWORD)) { + if ($backend->implementsActions(\OC_USER_BACKEND_CHECK_PASSWORD)) { $uid = $backend->checkPassword($loginname, $password); if ($uid !== false) { return $this->getUserObject($uid, $backend); @@ -220,7 +243,7 @@ class Manager extends PublicEmitter { // Allowed are: "a-z", "A-Z", "0-9" and "_.@-" if (preg_match('/[^a-zA-Z0-9 _\.@\-]/', $uid)) { throw new \Exception('Only the following characters are allowed in a username:' - . ' "a-z", "A-Z", "0-9", and "_.@-"'); + . ' "a-z", "A-Z", "0-9", and "_.@-"'); } // No empty username if (trim($uid) == '') { @@ -247,4 +270,26 @@ class Manager extends PublicEmitter { } return false; } + + /** + * returns how many users per backend exist (if supported by backend) + * + * @return array with backend class as key and count number as value + */ + public function countUsers() { + $userCountStatistics = array(); + foreach ($this->backends as $backend) { + if ($backend->implementsActions(\OC_USER_BACKEND_COUNT_USERS)) { + $backendusers = $backend->countUsers(); + if($backendusers !== false) { + if(isset($userCountStatistics[get_class($backend)])) { + $userCountStatistics[get_class($backend)] += $backendusers; + } else { + $userCountStatistics[get_class($backend)] = $backendusers; + } + } + } + } + return $userCountStatistics; + } } diff --git a/lib/private/user/session.php b/lib/private/user/session.php index 525c65ab8a1..1e299416fb3 100644 --- a/lib/private/user/session.php +++ b/lib/private/user/session.php @@ -113,6 +113,38 @@ class Session implements Emitter, \OCP\IUserSession { } /** + * set the login name + * + * @param string $loginName for the logged in user + */ + public function setLoginName($loginName) { + if (is_null($loginName)) { + $this->session->remove('loginname'); + } else { + $this->session->set('loginname', $loginName); + } + } + + /** + * get the login name of the current user + * + * @return string + */ + public function getLoginName() { + if ($this->activeUser) { + return $this->session->get('loginname'); + } else { + $uid = $this->session->get('user_id'); + if ($uid) { + $this->activeUser = $this->manager->get($uid); + return $this->session->get('loginname'); + } else { + return null; + } + } + } + + /** * try to login with the provided credentials * * @param string $uid @@ -126,6 +158,7 @@ class Session implements Emitter, \OCP\IUserSession { if (!is_null($user)) { if ($user->isEnabled()) { $this->setUser($user); + $this->setLoginName($uid); $this->manager->emit('\OC\User', 'postLogin', array($user, $password)); return true; } else { @@ -143,6 +176,7 @@ class Session implements Emitter, \OCP\IUserSession { public function logout() { $this->manager->emit('\OC\User', 'logout'); $this->setUser(null); + $this->setLoginName(null); $this->unsetMagicInCookie(); } @@ -170,5 +204,10 @@ class Session implements Emitter, \OCP\IUserSession { setcookie('oc_username', '', time()-3600, \OC::$WEBROOT); setcookie('oc_token', '', time()-3600, \OC::$WEBROOT); setcookie('oc_remember_login', '', time()-3600, \OC::$WEBROOT); + // old cookies might be stored under /webroot/ instead of /webroot + // and Firefox doesn't like it! + setcookie('oc_username', '', time()-3600, \OC::$WEBROOT . '/'); + setcookie('oc_token', '', time()-3600, \OC::$WEBROOT . '/'); + setcookie('oc_remember_login', '', time()-3600, \OC::$WEBROOT . '/'); } } diff --git a/lib/private/user/user.php b/lib/private/user/user.php index e5f842944f1..ef5364cbf7b 100644 --- a/lib/private/user/user.php +++ b/lib/private/user/user.php @@ -38,11 +38,22 @@ class User { private $emitter; /** + * @var string $home + */ + private $home; + + /** + * @var \OC\AllConfig $config + */ + private $config; + + /** * @param string $uid * @param \OC_User_Backend $backend - * @param Emitter $emitter + * @param \OC\Hooks\Emitter $emitter + * @param \OC\AllConfig $config */ - public function __construct($uid, $backend, $emitter = null) { + public function __construct($uid, $backend, $emitter = null, $config = null) { $this->uid = $uid; if ($backend and $backend->implementsActions(OC_USER_BACKEND_GET_DISPLAYNAME)) { $this->displayName = $backend->getDisplayName($uid); @@ -51,8 +62,13 @@ class User { } $this->backend = $backend; $this->emitter = $emitter; - $enabled = \OC_Preferences::getValue($uid, 'core', 'enabled', 'true'); //TODO: DI for OC_Preferences - $this->enabled = ($enabled === 'true'); + $this->config = $config; + if ($this->config) { + $enabled = $this->config->getUserValue($uid, 'core', 'enabled', 'true'); + $this->enabled = ($enabled === 'true'); + } else { + $this->enabled = true; + } } /** @@ -133,10 +149,28 @@ class User { * @return string */ public function getHome() { - if ($this->backend->implementsActions(\OC_USER_BACKEND_GET_HOME) and $home = $this->backend->getHome($this->uid)) { - return $home; + if (!$this->home) { + if ($this->backend->implementsActions(\OC_USER_BACKEND_GET_HOME) and $home = $this->backend->getHome($this->uid)) { + $this->home = $home; + } elseif ($this->config) { + $this->home = $this->config->getSystemValue('datadirectory') . '/' . $this->uid; + } else { + $this->home = \OC::$SERVERROOT . '/data/' . $this->uid; + } + } + return $this->home; + } + + /** + * check if the backend allows the user to change his avatar on Personal page + * + * @return bool + */ + public function canChangeAvatar() { + if ($this->backend->implementsActions(\OC_USER_BACKEND_PROVIDE_AVATAR)) { + return $this->backend->canChangeAvatar($this->uid); } - return \OC_Config::getValue("datadirectory", \OC::$SERVERROOT . "/data") . '/' . $this->uid; //TODO switch to Config object once implemented + return true; } /** @@ -154,7 +188,11 @@ class User { * @return bool */ public function canChangeDisplayName() { - return $this->backend->implementsActions(\OC_USER_BACKEND_SET_DISPLAYNAME); + if ($this->config and $this->config->getSystemValue('allow_user_to_change_display_name') === false) { + return false; + } else { + return $this->backend->implementsActions(\OC_USER_BACKEND_SET_DISPLAYNAME); + } } /** @@ -173,7 +211,9 @@ class User { */ public function setEnabled($enabled) { $this->enabled = $enabled; - $enabled = ($enabled) ? 'true' : 'false'; - \OC_Preferences::setValue($this->uid, 'core', 'enabled', $enabled); + if ($this->config) { + $enabled = ($enabled) ? 'true' : 'false'; + $this->config->setUserValue($this->uid, 'core', 'enabled', $enabled); + } } } diff --git a/lib/private/util.php b/lib/private/util.php index 43d1d393da7..0585749d615 100755 --- a/lib/private/util.php +++ b/lib/private/util.php @@ -51,23 +51,33 @@ class OC_Util { self::$rootMounted = true; } + if ($user != '' && !OCP\User::userExists($user)) { + return false; + } + //if we aren't logged in, there is no use to set up the filesystem if( $user != "" ) { - $quota = self::getUserQuota($user); - if ($quota !== \OC\Files\SPACE_UNLIMITED) { - \OC\Files\Filesystem::addStorageWrapper(function($mountPoint, $storage) use ($quota, $user) { - if ($mountPoint === '/' . $user . '/'){ + \OC\Files\Filesystem::addStorageWrapper(function($mountPoint, $storage){ + // set up quota for home storages, even for other users + // which can happen when using sharing + + if ($storage instanceof \OC\Files\Storage\Home) { + $user = $storage->getUser()->getUID(); + $quota = OC_Util::getUserQuota($user); + if ($quota !== \OC\Files\SPACE_UNLIMITED) { return new \OC\Files\Storage\Wrapper\Quota(array('storage' => $storage, 'quota' => $quota)); - } else { - return $storage; } - }); - } + } + + return $storage; + }); + $userDir = '/'.$user.'/files'; $userRoot = OC_User::getHome($user); $userDirectory = $userRoot . '/files'; if( !is_dir( $userDirectory )) { mkdir( $userDirectory, 0755, true ); + OC_Util::copySkeleton($userDirectory); } //jail the user into his "home" directory \OC\Files\Filesystem::init($user, $userDir); @@ -93,6 +103,35 @@ class OC_Util { } /** + * @brief copies the user skeleton files into the fresh user home files + * @param string $userDirectory + */ + public static function copySkeleton($userDirectory) { + OC_Util::copyr(\OC::$SERVERROOT.'/core/skeleton' , $userDirectory); + } + + /** + * @brief copies a directory recursively + * @param string $source + * @param string $target + * @return void + */ + public static function copyr($source,$target) { + $dir = opendir($source); + @mkdir($target); + while(false !== ( $file = readdir($dir)) ) { + if ( !\OC\Files\Filesystem::isIgnoredDir($file) ) { + if ( is_dir($source . '/' . $file) ) { + OC_Util::copyr($source . '/' . $file , $target . '/' . $file); + } else { + copy($source . '/' . $file,$target . '/' . $file); + } + } + } + closedir($dir); + } + + /** * @return void */ public static function tearDownFS() { @@ -138,7 +177,7 @@ class OC_Util { OC_Util::loadVersion(); return \OC::$server->getSession()->get('OC_Channel'); } - + /** * @description get the build number of the current installed of ownCloud. * @return string @@ -152,9 +191,12 @@ class OC_Util { * @description load the version.php into the session as cache */ private static function loadVersion() { - if(!\OC::$server->getSession()->exists('OC_Version')) { + $timestamp = filemtime(OC::$SERVERROOT.'/version.php'); + if(!\OC::$server->getSession()->exists('OC_Version') or OC::$server->getSession()->get('OC_Version_Timestamp') != $timestamp) { require 'version.php'; $session = \OC::$server->getSession(); + /** @var $timestamp int */ + $session->set('OC_Version_Timestamp', $timestamp); /** @var $OC_Version string */ $session->set('OC_Version', $OC_Version); /** @var $OC_VersionString string */ @@ -270,16 +312,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/")) { + if(!is_writable(OC::$configDir) or !is_readable(OC::$configDir)) { $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>.' ); } @@ -291,8 +333,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.' ); } @@ -307,8 +349,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)) { @@ -320,6 +362,13 @@ class OC_Util { $errors = array_merge($errors, self::checkDataDirectoryPermissions($CONFIG_DATADIRECTORY)); } + if(!OC_Util::isSetLocaleWorking()) { + $errors[] = array( + 'error' => 'Setting locale to en_US.UTF-8/fr_FR.UTF-8/es_ES.UTF-8/de_DE.UTF-8/ru_RU.UTF-8/pt_BR.UTF-8/it_IT.UTF-8/ja_JP.UTF-8/zh_CN.UTF-8 failed', + 'hint' => 'Please install one of theses locales on your system and restart your webserver.' + ); + } + $moduleHint = "Please ask your server administrator to install the module."; // check if all required php modules are present if(!class_exists('ZipArchive')) { @@ -392,11 +441,11 @@ class OC_Util { ); $webServerRestart = true; } - if(floatval(phpversion()) < 5.3) { + if(version_compare(phpversion(), '5.3.3', '<')) { $errors[] = array( - 'error'=>'PHP 5.3 is required.', - 'hint'=>'Please ask your server administrator to update PHP to version 5.3 or higher.' - .' PHP 5.2 is no longer supported by ownCloud and the PHP community.' + 'error'=>'PHP 5.3.3 or higher is required.', + 'hint'=>'Please ask your server administrator to update PHP to the latest version.' + .' Your PHP version is no longer supported by ownCloud and the PHP community.' ); $webServerRestart = true; } @@ -535,7 +584,7 @@ class OC_Util { // Check if we are a user if( !OC_User::isLoggedIn()) { header( 'Location: '.OC_Helper::linkToAbsolute( '', 'index.php', - array('redirectUrl' => OC_Request::requestUri()) + array('redirect_url' => OC_Request::requestUri()) )); exit(); } @@ -546,6 +595,7 @@ class OC_Util { * @return void */ public static function checkAdminUser() { + OC_Util::checkLoggedIn(); if( !OC_User::isAdminUser(OC_User::getUser())) { header( 'Location: '.OC_Helper::linkToAbsolute( '', 'index.php' )); exit(); @@ -578,6 +628,7 @@ class OC_Util { * @return array $groups where the current user is subadmin */ public static function checkSubAdminUser() { + OC_Util::checkLoggedIn(); if(!OC_SubAdmin::isSubAdmin(OC_User::getUser())) { header( 'Location: '.OC_Helper::linkToAbsolute( '', 'index.php' )); exit(); @@ -665,29 +716,7 @@ class OC_Util { * @see OC_Util::callRegister() */ public static function isCallRegistered() { - if(!\OC::$session->exists('requesttoken')) { - return false; - } - - if(isset($_GET['requesttoken'])) { - $token = $_GET['requesttoken']; - } elseif(isset($_POST['requesttoken'])) { - $token = $_POST['requesttoken']; - } elseif(isset($_SERVER['HTTP_REQUESTTOKEN'])) { - $token = $_SERVER['HTTP_REQUESTTOKEN']; - } else { - //no token found. - return false; - } - - // Check if the token is valid - if($token !== \OC::$session->get('requesttoken')) { - // Not valid - return false; - } else { - // Valid token - return true; - } + return \OC::$server->getRequest()->passesCSRFCheck(); } /** @@ -743,6 +772,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'; @@ -795,11 +828,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); @@ -829,8 +867,8 @@ class OC_Util { return true; } - $result = setlocale(LC_ALL, 'en_US.UTF-8', 'en_US.UTF8'); - if($result == false) { + \Patchwork\Utf8\Bootup::initLocale(); + if ('' === basename('§')) { return false; } return true; @@ -845,6 +883,14 @@ class OC_Util { } /** + * @brief Check if a PHP version older then 5.3.8 is installed. + * @return bool + */ + public static function isPHPoutdated() { + return version_compare(phpversion(), '5.3.8', '<'); + } + + /** * @brief Check if the ownCloud server can connect to the internet * @return bool */ @@ -854,6 +900,11 @@ class OC_Util { return false; } + // in case the connection is via proxy return true to avoid connecting to owncloud.org + if(OC_Config::getValue('proxy', '') != '') { + return true; + } + // try to connect to owncloud.org to see if http connections to the internet are possible. $connected = @fsockopen("www.owncloud.org", 80); if ($connected) { @@ -956,9 +1007,9 @@ class OC_Util { * @param string $url Url to get content * @return string of the response or false on error * This function get the content of a page via curl, if curl is enabled. - * If not, file_get_element is used. + * If not, file_get_contents is used. */ - public static function getUrlContent($url){ + public static function getUrlContent($url) { if (function_exists('curl_init')) { $curl = curl_init(); @@ -1047,7 +1098,11 @@ class OC_Util { } // XCache if (function_exists('xcache_clear_cache')) { - xcache_clear_cache(XC_TYPE_VAR, 0); + if (ini_get('xcache.admin.enable_auth')) { + OC_Log::write('core', 'XCache opcode cache will not be cleared because "xcache.admin.enable_auth" is enabled.', \OC_Log::WARN); + } else { + xcache_clear_cache(XC_TYPE_PHP, 0); + } } // Opcache (PHP >= 5.5) if (function_exists('opcache_reset')) { @@ -1081,4 +1136,17 @@ class OC_Util { $t = explode('/', $file); return array_pop($t); } + + /** + * A human readable string is generated based on version, channel and build number + * @return string + */ + public static function getHumanVersion() { + $version = OC_Util::getVersionString().' ('.OC_Util::getChannel().')'; + $build = OC_Util::getBuild(); + if(!empty($build) and OC_Util::getChannel() === 'daily') { + $version .= ' Build:' . $build; + } + return $version; + } } diff --git a/lib/public/activity/iconsumer.php b/lib/public/activity/iconsumer.php new file mode 100644 index 00000000000..9afacf4e745 --- /dev/null +++ b/lib/public/activity/iconsumer.php @@ -0,0 +1,48 @@ +<?php +/** + * ownCloud + * + * @author Thomas Müller + * @copyright 2013 Thomas Müller deepdiver@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/>. + * + */ + +/** + * Public interface of ownCloud for apps to use. + * Activity/IConsumer interface + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes +namespace OCP\Activity; + +interface IConsumer { + /** + * @param $app + * @param $subject + * @param $subjectParams + * @param $message + * @param $messageParams + * @param $file + * @param $link + * @param $affectedUser + * @param $type + * @param $priority + * @return mixed + */ + function receive($app, $subject, $subjectParams, $message, $messageParams, $file, $link, $affectedUser, $type, $priority ); +} + diff --git a/lib/public/activity/imanager.php b/lib/public/activity/imanager.php new file mode 100644 index 00000000000..086e430d677 --- /dev/null +++ b/lib/public/activity/imanager.php @@ -0,0 +1,59 @@ +<?php +/** + * ownCloud + * + * @author Thomas Müller + * @copyright 2013 Thomas Müller deepdiver@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/>. + * + */ + +/** + * Public interface of ownCloud for apps to use. + * Activity/IManager interface + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes +namespace OCP\Activity; + +interface IManager { + + /** + * @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); + + /** + * 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 \Closure $callable + */ + function registerConsumer(\Closure $callable); + +} diff --git a/lib/public/api.php b/lib/public/api.php index d94b68e908a..f53188d2721 100644 --- a/lib/public/api.php +++ b/lib/public/api.php @@ -1,25 +1,33 @@ <?php /** -* ownCloud -* -* @author Tom Needham -* @copyright 2012 Tom Needham tom@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/>. -* -*/ + * ownCloud + * + * @author Tom Needham + * @copyright 2012 Tom Needham tom@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/>. + * + */ + +/** + * Public interface of ownCloud for apps to use. + * API Class + * + */ +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes namespace OCP; /** diff --git a/lib/public/app.php b/lib/public/app.php index 0a5721b334e..e0b5682242b 100644 --- a/lib/public/app.php +++ b/lib/public/app.php @@ -1,28 +1,28 @@ <?php /** -* ownCloud -* -* @author Frank Karlitschek -* @copyright 2012 Frank Karlitschek frank@owncloud.org -* -* 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/>. -* -*/ + * ownCloud + * + * @author Frank Karlitschek + * @copyright 2012 Frank Karlitschek frank@owncloud.org + * + * 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/>. + * + */ /** * Public interface of ownCloud for apps to use. - * App Class. + * App Class * */ @@ -35,14 +35,12 @@ namespace OCP; */ class App { /** - * @brief Makes ownCloud aware of this app - * @brief This call is deprecated and not necessary to use. - * @param $data array with all information - * @returns boolean + * Makes ownCloud aware of this app + * @param array with all information + * @return boolean * - * @deprecated this method is deprecated - * Do not call it anymore - * It'll remain in our public API for compatibility reasons + * @deprecated This method is deprecated. Do not call it anymore. + * It'll remain in our public API for compatibility reasons. * */ public static function register( $data ) { @@ -50,9 +48,9 @@ class App { } /** - * @brief adds an entry to the navigation - * @param $data array containing the data - * @returns boolean + * Adds an entry to the navigation + * @param array containing the data + * @return boolean * * This function adds a new entry to the navigation visible to users. $data * is an associative array. @@ -71,9 +69,9 @@ class App { } /** - * @brief marks a navigation entry as active - * @param $id string id of the entry - * @returns boolean + * Marks a navigation entry as active + * @param string id of the entry + * @return boolean * * This function sets a navigation entry as active and removes the 'active' * property from all other entries. The templates can use this for @@ -84,7 +82,7 @@ class App { } /** - * @brief Register a Configuration Screen that should appear in the personal settings section. + * Register a Configuration Screen that should appear in the personal settings section. * @param $app string appid * @param $page string page to be included */ @@ -93,7 +91,7 @@ class App { } /** - * @brief Register a Configuration Screen that should appear in the Admin section. + * Register a Configuration Screen that should appear in the Admin section. * @param $app string appid * @param $page string page to be included */ @@ -102,19 +100,19 @@ class App { } /** - * @brief Read app metadata from the info.xml file + * Read app metadata from the info.xml file * @param string $app id of the app or the path of the info.xml file * @param boolean $path (optional) - * @returns array + * @return array */ public static function getAppInfo( $app, $path=false ) { return \OC_App::getAppInfo( $app, $path); } /** - * @brief checks whether or not an app is enabled - * @param $app app - * @returns boolean + * checks whether or not an app is enabled + * @param string + * @return boolean * * This function checks whether or not an app is enabled. */ @@ -123,17 +121,17 @@ class App { } /** - * @brief Check if the app is enabled, redirects to home if not - * @param $app app + * Check if the app is enabled, redirects to home if not + * @param string */ public static function checkAppEnabled( $app ) { \OC_Util::checkAppEnabled( $app ); } /** - * @brief Get the last version of the app, either from appinfo/version or from appinfo/info.xml - * @param $app app - * @returns boolean + * Get the last version of the app, either from appinfo/version or from appinfo/info.xml + * @param string + * @return boolean */ public static function getAppVersion( $app ) { return \OC_App::getAppVersion( $app ); diff --git a/lib/public/appframework/app.php b/lib/public/appframework/app.php index d97c5c81848..90150245c41 100644 --- a/lib/public/appframework/app.php +++ b/lib/public/appframework/app.php @@ -20,7 +20,13 @@ * */ +/** + * Public interface of ownCloud for apps to use. + * AppFramework/App class + */ + namespace OCP\AppFramework; +use OC\AppFramework\routing\RouteConfig; /** @@ -31,8 +37,11 @@ namespace OCP\AppFramework; * to be registered using IContainer::registerService */ class App { - public function __construct($appName) { - $this->container = new \OC\AppFramework\DependencyInjection\DIContainer($appName); + /** + * @param array $urlParams an array with variables extracted from the routes + */ + public function __construct($appName, $urlParams = array()) { + $this->container = new \OC\AppFramework\DependencyInjection\DIContainer($appName, $urlParams); } private $container; @@ -45,13 +54,35 @@ class App { } /** + * This function is to be called to create single routes and restful routes based on the given $routes array. + * + * Example code in routes.php of tasks app (it will register two restful resources): + * $routes = array( + * 'resources' => array( + * 'lists' => array('url' => '/tasklists'), + * 'tasks' => array('url' => '/tasklists/{listId}/tasks') + * ) + * ); + * + * $a = new TasksApp(); + * $a->registerRoutes($this, $routes); + * + * @param \OC_Router $router + * @param array $routes + */ + public function registerRoutes($router, $routes) { + $routeConfig = new RouteConfig($this->container, $router, $routes); + $routeConfig->register(); + } + + /** * This function is called by the routing component to fire up the frameworks dispatch mechanism. * * Example code in routes.php of the task app: * $this->create('tasks_index', '/')->get()->action( * function($params){ - * $app = new TaskApp(); - * $app->dispatch('PageController', 'index', $params); + * $app = new TaskApp($params); + * $app->dispatch('PageController', 'index'); * } * ); * @@ -59,8 +90,8 @@ class App { * Example for for TaskApp implementation: * class TaskApp extends \OCP\AppFramework\App { * - * public function __construct(){ - * parent::__construct('tasks'); + * public function __construct($params){ + * parent::__construct('tasks', $params); * * $this->getContainer()->registerService('PageController', function(IAppContainer $c){ * $a = $c->query('API'); @@ -73,9 +104,8 @@ class App { * @param string $controllerName the name of the controller under which it is * stored in the DI container * @param string $methodName the method that you want to call - * @param array $urlParams an array with variables extracted from the routes */ - public function dispatch($controllerName, $methodName, array $urlParams) { - \OC\AppFramework\App::main($controllerName, $methodName, $urlParams, $this->container); + public function dispatch($controllerName, $methodName) { + \OC\AppFramework\App::main($controllerName, $methodName, $this->container); } } diff --git a/lib/private/appframework/controller/controller.php b/lib/public/appframework/controller.php index 0ea0a38cc09..dc8da967871 100644 --- a/lib/private/appframework/controller/controller.php +++ b/lib/public/appframework/controller.php @@ -1,5 +1,4 @@ <?php - /** * ownCloud - App Framework * @@ -21,12 +20,16 @@ * */ +/** + * Public interface of ownCloud for apps to use. + * AppFramework\Controller class + */ -namespace OC\AppFramework\Controller; +namespace OCP\AppFramework; -use OC\AppFramework\Http\Request; -use OC\AppFramework\Core\API; use OCP\AppFramework\Http\TemplateResponse; +use OCP\AppFramework\IAppContainer; +use OCP\IRequest; /** @@ -35,18 +38,24 @@ use OCP\AppFramework\Http\TemplateResponse; abstract class Controller { /** - * @var API instance of the api layer + * app container for dependency injection + * @var \OCP\AppFramework\IAppContainer */ - protected $api; + protected $app; + /** + * current request + * @var \OCP\IRequest + */ protected $request; /** - * @param API $api an api wrapper instance - * @param Request $request an instance of the request + * constructor of the controller + * @param IAppContainer $app interface to the app + * @param IRequest $request an instance of the request */ - public function __construct(API $api, Request $request){ - $this->api = $api; + public function __construct(IAppContainer $app, IRequest $request){ + $this->app = $app; $this->request = $request; } @@ -127,7 +136,7 @@ abstract class Controller { */ public function render($templateName, array $params=array(), $renderAs='user', array $headers=array()){ - $response = new TemplateResponse($this->api, $templateName); + $response = new TemplateResponse($this->app->getAppName(), $templateName); $response->setParams($params); $response->renderAs($renderAs); diff --git a/lib/public/appframework/http/http.php b/lib/public/appframework/http.php index 9eafe782726..60f314202cc 100644 --- a/lib/public/appframework/http/http.php +++ b/lib/public/appframework/http.php @@ -1,5 +1,4 @@ <?php - /** * ownCloud - App Framework * @@ -21,10 +20,16 @@ * */ +/** + * Public interface of ownCloud for apps to use. + * AppFramework\HTTP class + */ -namespace OCP\AppFramework\Http; - +namespace OCP\AppFramework; +/** + * Base class which contains constants for HTTP status codes + */ class Http { const STATUS_CONTINUE = 100; diff --git a/lib/public/appframework/http/jsonresponse.php b/lib/public/appframework/http/jsonresponse.php index 085fdbed2f9..b54b23a34e6 100644 --- a/lib/public/appframework/http/jsonresponse.php +++ b/lib/public/appframework/http/jsonresponse.php @@ -1,5 +1,4 @@ <?php - /** * ownCloud - App Framework * @@ -21,19 +20,29 @@ * */ +/** + * Public interface of ownCloud for apps to use. + * AppFramework\HTTP\JSONResponse class + */ namespace OCP\AppFramework\Http; +use OCP\AppFramework\Http; /** * A renderer for JSON calls */ class JSONResponse extends Response { + /** + * response data + * @var array|object + */ protected $data; /** + * constructor of JSONResponse * @param array|object $data the object or array that should be transformed * @param int $statusCode the Http status code, defaults to 200 */ @@ -55,7 +64,7 @@ class JSONResponse extends Response { /** * Sets values in the data json array - * @param array|object $params an array or object which will be transformed + * @param array|object $data an array or object which will be transformed * to JSON */ public function setData($data){ diff --git a/lib/public/appframework/http/response.php b/lib/public/appframework/http/response.php index 64477258948..0f5a18ca4fe 100644 --- a/lib/public/appframework/http/response.php +++ b/lib/public/appframework/http/response.php @@ -1,5 +1,4 @@ <?php - /** * ownCloud - App Framework * @@ -21,17 +20,25 @@ * */ +/** + * Public interface of ownCloud for apps to use. + * AppFramework\HTTP\Response class + */ namespace OCP\AppFramework\Http; +use OCP\AppFramework\Http; /** - * Base class for responses. Also used to just send headers + * Base class for responses. Also used to just send headers. + * + * It handles headers, HTTP status code, last modified and ETag. */ class Response { /** - * @var array default headers + * Headers - defaults to ['Cache-Control' => 'no-cache, must-revalidate'] + * @var array */ private $headers = array( 'Cache-Control' => 'no-cache, must-revalidate' @@ -39,18 +46,21 @@ class Response { /** + * HTTP status code - defaults to STATUS OK * @var string */ private $status = Http::STATUS_OK; /** + * Last modified date * @var \DateTime */ private $lastModified; /** + * ETag * @var string */ private $ETag; @@ -64,7 +74,7 @@ class Response { public function cacheFor($cacheSeconds) { if($cacheSeconds > 0) { - $this->addHeader('Cache-Control', 'max-age=' . $cacheSeconds . + $this->addHeader('Cache-Control', 'max-age=' . $cacheSeconds . ', must-revalidate'); } else { $this->addHeader('Cache-Control', 'no-cache, must-revalidate'); @@ -94,16 +104,16 @@ class Response { */ public function getHeaders() { $mergeWith = array(); - + if($this->lastModified) { - $mergeWith['Last-Modified'] = + $mergeWith['Last-Modified'] = $this->lastModified->format(\DateTime::RFC2822); } if($this->ETag) { $mergeWith['ETag'] = '"' . $this->ETag . '"'; } - + return array_merge($mergeWith, $this->headers); } @@ -135,6 +145,7 @@ class Response { /** + * Get the ETag * @return string the etag */ public function getETag() { @@ -143,6 +154,7 @@ class Response { /** + * Get "last modified" date * @return string RFC2822 formatted last modified date */ public function getLastModified() { @@ -151,6 +163,7 @@ class Response { /** + * Set the ETag * @param string $ETag */ public function setETag($ETag) { @@ -159,6 +172,7 @@ class Response { /** + * Set "last modified" date * @param \DateTime $lastModified */ public function setLastModified($lastModified) { diff --git a/lib/public/appframework/http/templateresponse.php b/lib/public/appframework/http/templateresponse.php index 97678c96cba..2200a38beca 100644 --- a/lib/public/appframework/http/templateresponse.php +++ b/lib/public/appframework/http/templateresponse.php @@ -1,5 +1,4 @@ <?php - /** * ownCloud - App Framework * @@ -21,33 +20,51 @@ * */ +/** + * Public interface of ownCloud for apps to use. + * AppFramework\HTTP\TemplateResponse class + */ namespace OCP\AppFramework\Http; -use OC\AppFramework\Core\API; - /** * Response for a normal template */ class TemplateResponse extends Response { + /** + * name of the template + * @var string + */ protected $templateName; + + /** + * parameters + * @var array + */ protected $params; - protected $api; + + /** + * rendering type (admin, user, blank) + * @var string + */ protected $renderAs; + + /** + * app name + * @var string + */ protected $appName; /** - * @param API $api an API instance + * constructor of TemplateResponse + * @param string $appName the name of the app to load the template from * @param string $templateName the name of the template - * @param string $appName optional if you want to include a template from - * a different app */ - public function __construct(API $api, $templateName, $appName=null) { + public function __construct($appName, $templateName) { $this->templateName = $templateName; $this->appName = $appName; - $this->api = $api; $this->params = array(); $this->renderAs = 'user'; } @@ -108,13 +125,7 @@ class TemplateResponse extends Response { */ public function render(){ - if($this->appName !== null){ - $appName = $this->appName; - } else { - $appName = $this->api->getAppName(); - } - - $template = $this->api->getTemplate($this->templateName, $this->renderAs, $appName); + $template = new \OCP\Template($this->appName, $this->templateName, $this->renderAs); foreach($this->params as $key => $value){ $template->assign($key, $value); diff --git a/lib/public/appframework/iapi.php b/lib/public/appframework/iapi.php index fa6af5f5965..963e870f79b 100644 --- a/lib/public/appframework/iapi.php +++ b/lib/public/appframework/iapi.php @@ -1,5 +1,4 @@ <?php - /** * ownCloud - App Framework * @@ -21,6 +20,10 @@ * */ +/** + * Public interface of ownCloud for apps to use. + * AppFramework/IApi interface + */ namespace OCP\AppFramework; @@ -67,59 +70,6 @@ interface IApi { */ function add3rdPartyStyle($name); - /** - * Returns the translation object - * @return \OC_L10N the translation object - * - * FIXME: returns private object / should be retrieved from teh ServerContainer - */ - function getTrans(); - - - /** - * Returns the URL for a route - * @param string $routeName the name of the route - * @param array $arguments an array with arguments which will be filled into the url - * @return string the url - */ - function linkToRoute($routeName, $arguments=array()); - - - /** - * Returns an URL for an image or file - * @param string $file the name of the file - * @param string $appName the name of the app, defaults to the current one - */ - function linkTo($file, $appName=null); - - - /** - * Returns the link to an image, like link to but only with prepending img/ - * @param string $file the name of the file - * @param string $appName the name of the app, defaults to the current one - */ - function imagePath($file, $appName = null); - - - /** - * Makes an URL absolute - * @param string $url the url - * @return string the absolute url - * - * FIXME: function should live in Request / Response - */ - function getAbsoluteURL($url); - - - /** - * links to a file - * @param string $file the name of the file - * @param string $appName the name of the app, defaults to the current one - * @deprecated replaced with linkToRoute() - * @return string the url - */ - function linkToAbsolute($file, $appName = null); - /** * Checks if an app is enabled @@ -128,24 +78,4 @@ interface IApi { */ public function isAppEnabled($appName); - - /** - * Writes a function into the error log - * @param string $msg the error message to be logged - * @param int $level the error level - * - * FIXME: add logger instance to ServerContainer - */ - function log($msg, $level = null); - - - /** - * Returns a template - * @param string $templateName the name of the template - * @param string $renderAs how it should be rendered - * @param string $appName the name of the app - * @return \OCP\Template a new template - */ - function getTemplate($templateName, $renderAs='user', $appName=null); - } diff --git a/lib/public/appframework/iappcontainer.php b/lib/public/appframework/iappcontainer.php index 7d3b4b3bac7..7e6ec6016b7 100644 --- a/lib/public/appframework/iappcontainer.php +++ b/lib/public/appframework/iappcontainer.php @@ -50,8 +50,26 @@ interface IAppContainer extends IContainer{ function getServer(); /** - * @param IMiddleWare $middleWare + * @param Middleware $middleWare * @return boolean */ - function registerMiddleWare(IMiddleWare $middleWare); + function registerMiddleWare(Middleware $middleWare); + + /** + * @return boolean + */ + function isLoggedIn(); + + /** + * @return boolean + */ + function isAdminUser(); + + /** + * @param $message + * @param $level + * @return mixed + */ + function log($message, $level); + } diff --git a/lib/public/appframework/imiddleware.php b/lib/public/appframework/imiddleware.php deleted file mode 100644 index 1e76d3bbe49..00000000000 --- a/lib/public/appframework/imiddleware.php +++ /dev/null @@ -1,88 +0,0 @@ -<?php - -/** - * ownCloud - App Framework - * - * @author Bernhard Posselt - * @copyright 2012 Bernhard Posselt nukeawhale@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/>. - * - */ - - -namespace OCP\AppFramework; -use OCP\AppFramework\Http\Response; - - -/** - * Middleware is used to provide hooks before or after controller methods and - * deal with possible exceptions raised in the controller methods. - * They're modeled after Django's middleware system: - * https://docs.djangoproject.com/en/dev/topics/http/middleware/ - */ -interface IMiddleWare { - - - /** - * This is being run in normal order before the controller is being - * called which allows several modifications and checks - * - * @param Controller $controller the controller that is being called - * @param string $methodName the name of the method that will be called on - * the controller - */ - function beforeController($controller, $methodName); - - - /** - * This is being run when either the beforeController method or the - * controller method itself is throwing an exception. The middleware is - * asked in reverse order to handle the exception and to return a response. - * If the response is null, it is assumed that the exception could not be - * handled and the error will be thrown again - * - * @param Controller $controller the controller that is being called - * @param string $methodName the name of the method that will be called on - * the controller - * @param \Exception $exception the thrown exception - * @throws \Exception the passed in exception if it cant handle it - * @return Response a Response object in case that the exception was handled - */ - function afterException($controller, $methodName, \Exception $exception); - - /** - * This is being run after a successful controller method call and allows - * the manipulation of a Response object. The middleware is run in reverse order - * - * @param Controller $controller the controller that is being called - * @param string $methodName the name of the method that will be called on - * the controller - * @param Response $response the generated response from the controller - * @return Response a Response object - */ - function afterController($controller, $methodName, Response $response); - - /** - * This is being run after the response object has been rendered and - * allows the manipulation of the output. The middleware is run in reverse order - * - * @param Controller $controller the controller that is being called - * @param string $methodName the name of the method that will be called on - * the controller - * @param string $output the generated output from a response - * @return string the output that should be printed - */ - function beforeOutput($controller, $methodName, $output); -} diff --git a/lib/private/appframework/middleware/middleware.php b/lib/public/appframework/middleware.php index b12c03c3eb8..24f31939935 100644 --- a/lib/private/appframework/middleware/middleware.php +++ b/lib/public/appframework/middleware.php @@ -1,5 +1,4 @@ <?php - /** * ownCloud - App Framework * @@ -21,9 +20,14 @@ * */ +/** + * Public interface of ownCloud for apps to use. + * AppFramework\Middleware class + */ -namespace OC\AppFramework\Middleware; +namespace OCP\AppFramework; +use OCP\AppFramework\Controller; use OCP\AppFramework\Http\Response; diff --git a/lib/public/authentication/iapachebackend.php b/lib/public/authentication/iapachebackend.php new file mode 100644 index 00000000000..3979a14302e --- /dev/null +++ b/lib/public/authentication/iapachebackend.php @@ -0,0 +1,55 @@ +<?php +/** + * ownCloud - Apache backend + * + * @author Karl Beecher + * @copyright 2013 Karl Beecher - karl@endocode.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/>. + * + */ + +/** + * Public interface of ownCloud for apps to use. + * Authentication/IApacheBackend interface + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes +namespace OCP\Authentication; + +interface IApacheBackend { + + /** + * In case the user has been authenticated by Apache true is returned. + * + * @return boolean whether Apache reports a user as currently logged in. + */ + public function isSessionActive(); + + /** + * Creates an attribute which is added to the logout hyperlink. It can + * supply any attribute(s) which are valid for <a>. + * + * @return string with one or more HTML attributes. + */ + public function getLogoutAttribute(); + + /** + * Return the id of the current user + * @return string + */ + public function getCurrentUserId(); + +} diff --git a/lib/public/backgroundjob.php b/lib/public/backgroundjob.php index cc076a3a845..a7f54491dfa 100644 --- a/lib/public/backgroundjob.php +++ b/lib/public/backgroundjob.php @@ -44,7 +44,8 @@ use \OC\BackgroundJob\JobList; */ class BackgroundJob { /** - * @brief get the execution type of background jobs + * get the execution type of background jobs + * * @return string * * This method returns the type how background jobs are executed. If the user @@ -55,7 +56,8 @@ class BackgroundJob { } /** - * @brief sets the background jobs execution type + * sets the background jobs execution type + * * @param string $type execution type * @return boolean * @@ -77,19 +79,21 @@ class BackgroundJob { /** * @deprecated - * @brief creates a regular task + * creates a regular task * @param string $klass class name * @param string $method method name * @return true */ public static function addRegularTask($klass, $method) { - self::registerJob('OC\BackgroundJob\Legacy\RegularJob', array($klass, $method)); - return true; + if (!\OC::needUpgrade()) { + self::registerJob('OC\BackgroundJob\Legacy\RegularJob', array($klass, $method)); + return true; + } } /** * @deprecated - * @brief gets all regular tasks + * gets all regular tasks * @return associative array * * key is string "$klass-$method", value is array( $klass, $method ) @@ -109,7 +113,7 @@ class BackgroundJob { /** * @deprecated - * @brief Gets one queued task + * Gets one queued task * @param int $id ID of the task * @return associative array */ @@ -120,7 +124,7 @@ class BackgroundJob { /** * @deprecated - * @brief Gets all queued tasks + * Gets all queued tasks * @return array with associative arrays */ public static function allQueuedTasks() { @@ -139,7 +143,7 @@ class BackgroundJob { /** * @deprecated - * @brief Gets all queued tasks of a specific app + * Gets all queued tasks of a specific app * @param string $app app name * @return array with associative arrays */ @@ -161,7 +165,7 @@ class BackgroundJob { /** * @deprecated - * @brief queues a task + * queues a task * @param string $app app name * @param string $class class name * @param string $method method name @@ -175,7 +179,7 @@ class BackgroundJob { /** * @deprecated - * @brief deletes a queued task + * deletes a queued task * @param int $id id of task * @return bool * diff --git a/lib/public/config.php b/lib/public/config.php index 73476d7551d..d9355a0605f 100644 --- a/lib/public/config.php +++ b/lib/public/config.php @@ -1,24 +1,24 @@ <?php /** -* ownCloud -* -* @author Frank Karlitschek -* @copyright 2012 Frank Karlitschek frank@owncloud.org -* -* 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/>. -* -*/ + * ownCloud + * + * @author Frank Karlitschek + * @copyright 2012 Frank Karlitschek frank@owncloud.org + * + * 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/>. + * + */ /** * Public interface of ownCloud for apps to use. @@ -27,7 +27,7 @@ */ /** - * @brief use OCP namespace for all classes that are considered public. + * Use OCP namespace for all classes that are considered public. * * Classes that use this namespace are for use by apps, and not for use by internal * OC classes @@ -40,7 +40,7 @@ namespace OCP; */ class Config { /** - * @brief Gets a value from config.php + * Gets a value from config.php * @param string $key key * @param string $default = null default value * @return string the value or $default @@ -53,7 +53,7 @@ class Config { } /** - * @brief Sets a value + * Sets a value * @param string $key key * @param string $value value * @return bool @@ -71,7 +71,7 @@ class Config { } /** - * @brief Gets the config value + * Gets the config value * @param string $app app * @param string $key key * @param string $default = null, default value if the key does not exist @@ -85,7 +85,7 @@ class Config { } /** - * @brief sets a value in the appconfig + * Sets a value in the appconfig * @param string $app app * @param string $key key * @param string $value value @@ -103,7 +103,7 @@ class Config { } /** - * @brief Gets the preference + * Gets the preference * @param string $user user * @param string $app app * @param string $key key @@ -118,12 +118,12 @@ class Config { } /** - * @brief sets a value in the preferences + * Sets a value in the preferences * @param string $user user * @param string $app app * @param string $key key * @param string $value value - * @returns bool + * @return bool * * Adds a value to the preferences. If the key did not exist before, it * will be added automagically. diff --git a/lib/public/contacts/imanager.php b/lib/public/contacts/imanager.php index 3bfbca7be50..973d48be5ec 100644 --- a/lib/public/contacts/imanager.php +++ b/lib/public/contacts/imanager.php @@ -119,11 +119,15 @@ namespace OCP\Contacts { function isEnabled(); /** + * Registers an address book + * * @param \OCP\IAddressBook $address_book */ function registerAddressBook(\OCP\IAddressBook $address_book); /** + * Unregisters an address book + * * @param \OCP\IAddressBook $address_book */ function unregisterAddressBook(\OCP\IAddressBook $address_book); diff --git a/lib/public/db.php b/lib/public/db.php index 9512cca2d19..4a19d78d444 100644 --- a/lib/public/db.php +++ b/lib/public/db.php @@ -1,24 +1,24 @@ <?php /** -* ownCloud -* -* @author Frank Karlitschek -* @copyright 2012 Frank Karlitschek frank@owncloud.org -* -* 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/>. -* -*/ + * ownCloud + * + * @author Frank Karlitschek + * @copyright 2012 Frank Karlitschek frank@owncloud.org + * + * 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/>. + * + */ /** * Public interface of ownCloud for apps to use. @@ -35,18 +35,20 @@ namespace OCP; */ class DB { /** - * @brief Prepare a SQL query + * Prepare a SQL query * @param string $query Query string - * @return \MDB2_Statement_Common prepared SQL query + * @param int $limit Limit of the SQL statement + * @param int $offset Offset of the SQL statement + * @return \Doctrine\DBAL\Statement prepared SQL query * - * SQL query via MDB2 prepare(), needs to be execute()'d! + * SQL query via Doctrine prepare(), needs to be execute()'d! */ static public function prepare( $query, $limit=null, $offset=null ) { return(\OC_DB::prepare($query, $limit, $offset)); } /** - * @brief Insert a row if a matching row doesn't exists. + * Insert a row if a matching row doesn't exists. * @param $table string The table name (will replace *PREFIX*) to perform the replace on. * @param $input array * @@ -67,11 +69,11 @@ class DB { } /** - * @brief gets last value of autoincrement + * Gets last value of autoincrement * @param $table string The optional table name (will replace *PREFIX*) and add sequence suffix * @return int * - * MDB2 lastInsertID() + * \Doctrine\DBAL\Connection lastInsertID() * * Call this method right after the insert command or other functions may * cause trouble! @@ -81,21 +83,21 @@ class DB { } /** - * @brief Start a transaction + * Start a transaction */ public static function beginTransaction() { - return(\OC_DB::beginTransaction()); + \OC_DB::beginTransaction(); } /** - * @brief Commit the database changes done during a transaction that is in progress + * Commit the database changes done during a transaction that is in progress */ public static function commit() { - return(\OC_DB::commit()); + \OC_DB::commit(); } /** - * @brief check if a result is an error, works with MDB2 and PDOException + * Check if a result is an error, works with Doctrine * @param mixed $result * @return bool */ diff --git a/lib/public/defaults.php b/lib/public/defaults.php index 147f23e341f..34b68903ee8 100644 --- a/lib/public/defaults.php +++ b/lib/public/defaults.php @@ -1,41 +1,56 @@ <?php /** -* ownCloud -* -* @author Björn Schießle -* @copyright 2013 Björn Schießle schiessle@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/>. -* -*/ + * ownCloud + * + * @author Björn Schießle + * @copyright 2013 Björn Schießle schiessle@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/>. + * + */ + +/** + * Public interface of ownCloud for apps to use. + * Defaults Class + * + */ +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes namespace OCP; -/* +/** * public api to access default strings and urls for your templates */ - class Defaults { + /** + * \OC_Defaults instance to retrieve the defaults + * @return string + */ private $defaults; + /** + * creates a \OC_Defaults instance which is used in all methods to retrieve the + * actual defaults + */ function __construct() { $this->defaults = new \OC_Defaults(); } /** - * @breif get base URL for the organisation behind your ownCloud instance + * get base URL for the organisation behind your ownCloud instance * @return string */ public function getBaseUrl() { @@ -43,7 +58,7 @@ class Defaults { } /** - * @breif link to the desktop sync client + * link to the desktop sync client * @return string */ public function getSyncClientUrl() { @@ -51,7 +66,7 @@ class Defaults { } /** - * @breif base URL to the documentation of your ownCloud instance + * base URL to the documentation of your ownCloud instance * @return string */ public function getDocBaseUrl() { @@ -59,7 +74,7 @@ class Defaults { } /** - * @breif name of your ownCloud instance + * name of your ownCloud instance * @return string */ public function getName() { @@ -67,7 +82,7 @@ class Defaults { } /** - * @breif Entity behind your onwCloud instance + * Entity behind your onwCloud instance * @return string */ public function getEntity() { @@ -75,7 +90,7 @@ class Defaults { } /** - * @breif ownCloud slogan + * ownCloud slogan * @return string */ public function getSlogan() { @@ -83,7 +98,7 @@ class Defaults { } /** - * @breif logo claim + * logo claim * @return string */ public function getLogoClaim() { @@ -91,7 +106,7 @@ class Defaults { } /** - * @breif footer, short version + * footer, short version * @return string */ public function getShortFooter() { @@ -99,7 +114,7 @@ class Defaults { } /** - * @breif footer, long version + * footer, long version * @return string */ public function getLongFooter() { diff --git a/lib/public/files.php b/lib/public/files.php index 852b041eefb..d36d74fdf77 100644 --- a/lib/public/files.php +++ b/lib/public/files.php @@ -1,24 +1,24 @@ <?php /** -* ownCloud -* -* @author Frank Karlitschek -* @copyright 2012 Frank Karlitschek frank@owncloud.org -* -* 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/>. -* -*/ + * ownCloud + * + * @author Frank Karlitschek + * @copyright 2012 Frank Karlitschek frank@owncloud.org + * + * 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/>. + * + */ /** * Public interface of ownCloud for apps to use. @@ -36,9 +36,8 @@ namespace OCP; */ class Files { /** - * @brief Recusive deletion of folders - * @param string $dir path to the folder - * + * Recusive deletion of folders + * @param string path to the folder * @return bool */ static function rmdirr( $dir ) { @@ -46,7 +45,7 @@ class Files { } /** - * get the mimetype form a local file + * Get the mimetype form a local file * @param string path * @return string * does NOT work for ownClouds filesystem, use OC_FileSystem::getMimeType instead @@ -56,17 +55,16 @@ class Files { } /** - * search for files by mimetype - * - * @param string $query + * Search for files by mimetype + * @param string mimetype * @return array */ - static public function searchByMime($mimetype) { + static public function searchByMime( $mimetype ) { return(\OC\Files\Filesystem::searchByMime( $mimetype )); } /** - * copy the contents of one stream to another + * Copy the contents of one stream to another * @param resource source * @param resource target * @return int the number of bytes copied @@ -77,7 +75,7 @@ class Files { } /** - * create a temporary file with an unique filename + * Create a temporary file with an unique filename * @param string postfix * @return string * @@ -88,7 +86,7 @@ class Files { } /** - * create a temporary folder with an unique filename + * Create a temporary folder with an unique filename * @return string * * temporary files are automatically cleaned up after the script is finished @@ -99,9 +97,8 @@ class Files { /** * Adds a suffix to the name in case the file exists - * - * @param $path - * @param $filename + * @param string path + * @param string filename * @return string */ public static function buildNotExistingFileName( $path, $filename ) { @@ -109,8 +106,9 @@ class Files { } /** + * Gets the Storage for an app - creates the needed folder if they are not + * existant * @param string appid - * @param $app app * @return \OC\Files\View */ public static function getStorage( $app ) { diff --git a/lib/public/files/alreadyexistsexception.php b/lib/public/files/alreadyexistsexception.php index 32947c7a5c3..7bea947aef0 100644 --- a/lib/public/files/alreadyexistsexception.php +++ b/lib/public/files/alreadyexistsexception.php @@ -1,11 +1,35 @@ <?php /** - * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com> - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. + * ownCloud + * + * @author Robin Appelman + * @copyright 2013 Robin Appelman icewind@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/>. + * */ +/** + * Public interface of ownCloud for apps to use. + * Files/AlreadyExistsException class + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes namespace OCP\Files; +/** + * Exception for already existing files/folders + */ class AlreadyExistsException extends \Exception {} diff --git a/lib/public/files/entitytoolargeexception.php b/lib/public/files/entitytoolargeexception.php new file mode 100644 index 00000000000..eaa68a548b9 --- /dev/null +++ b/lib/public/files/entitytoolargeexception.php @@ -0,0 +1,35 @@ +<?php +/** + * ownCloud + * + * @author Thomas Müller + * @copyright 2013 Thomas Müller deepdiver@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/>. + * + */ + +/** + * Public interface of ownCloud for apps to use. + * Files/EntityTooLargeException class + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes +namespace OCP\Files; + +/** + * Exception for too large entity + */ +class EntityTooLargeException extends \Exception {} diff --git a/lib/public/files/file.php b/lib/public/files/file.php index 916b2edd6c4..c6cda59f9b0 100644 --- a/lib/public/files/file.php +++ b/lib/public/files/file.php @@ -1,11 +1,32 @@ <?php /** - * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com> - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. + * ownCloud + * + * @author Robin Appelman + * @copyright 2013 Robin Appelman icewind@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/>. + * */ +/** + * Public interface of ownCloud for apps to use. + * Files/File interface + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes namespace OCP\Files; interface File extends Node { diff --git a/lib/public/files/folder.php b/lib/public/files/folder.php index da7f20fd366..7fec1c529a5 100644 --- a/lib/public/files/folder.php +++ b/lib/public/files/folder.php @@ -1,11 +1,32 @@ <?php /** - * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com> - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. + * ownCloud + * + * @author Robin Appelman + * @copyright 2013 Robin Appelman icewind@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/>. + * */ +/** + * Public interface of ownCloud for apps to use. + * Files/Folder interface + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes namespace OCP\Files; interface Folder extends Node { diff --git a/lib/public/files/invalidcontentexception.php b/lib/public/files/invalidcontentexception.php new file mode 100644 index 00000000000..3dfe7378c4d --- /dev/null +++ b/lib/public/files/invalidcontentexception.php @@ -0,0 +1,35 @@ +<?php +/** + * ownCloud + * + * @author Thomas Müller + * @copyright 2013 Thomas Müller deepdiver@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/>. + * + */ + +/** + * Public interface of ownCloud for apps to use. + * Files/InvalidContentException class + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes +namespace OCP\Files; + +/** + * Exception for invalid content + */ +class InvalidContentException extends \Exception {} diff --git a/lib/public/files/invalidpathexception.php b/lib/public/files/invalidpathexception.php new file mode 100644 index 00000000000..8ecfa7d89ad --- /dev/null +++ b/lib/public/files/invalidpathexception.php @@ -0,0 +1,35 @@ +<?php +/** + * ownCloud + * + * @author Thomas Müller + * @copyright 2013 Thomas Müller deepdiver@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/>. + * + */ + +/** + * Public interface of ownCloud for apps to use. + * Files/InvalidPathException class + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes +namespace OCP\Files; + +/** + * Exception for invalid path + */ +class InvalidPathException extends \Exception {} diff --git a/lib/public/files/node.php b/lib/public/files/node.php index b3ddf6de621..972b1cfa492 100644 --- a/lib/public/files/node.php +++ b/lib/public/files/node.php @@ -1,11 +1,32 @@ <?php /** - * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com> - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. + * ownCloud + * + * @author Robin Appelman + * @copyright 2013 Robin Appelman icewind@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/>. + * */ +/** + * Public interface of ownCloud for apps to use. + * Files/Node interface + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes namespace OCP\Files; interface Node { diff --git a/lib/public/files/notenoughspaceexception.php b/lib/public/files/notenoughspaceexception.php index e51806666ad..17f91b31bfc 100644 --- a/lib/public/files/notenoughspaceexception.php +++ b/lib/public/files/notenoughspaceexception.php @@ -1,11 +1,35 @@ <?php /** - * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com> - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. + * ownCloud + * + * @author Robin Appelman + * @copyright 2013 Robin Appelman icewind@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/>. + * */ +/** + * Public interface of ownCloud for apps to use. + * Files/NotEnoughSpaceException class + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes namespace OCP\Files; +/** + * Exception for not enough space + */ class NotEnoughSpaceException extends \Exception {} diff --git a/lib/public/files/notfoundexception.php b/lib/public/files/notfoundexception.php index 1ff426a40c6..cb35199220b 100644 --- a/lib/public/files/notfoundexception.php +++ b/lib/public/files/notfoundexception.php @@ -1,11 +1,35 @@ <?php /** - * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com> - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. + * ownCloud + * + * @author Robin Appelman + * @copyright 2013 Robin Appelman icewind@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/>. + * */ +/** + * Public interface of ownCloud for apps to use. + * Files/NotFoundException class + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes namespace OCP\Files; +/** + * Exception for not found entity + */ class NotFoundException extends \Exception {} diff --git a/lib/public/files/notpermittedexception.php b/lib/public/files/notpermittedexception.php index 0509de7e829..e37bd6fad3c 100644 --- a/lib/public/files/notpermittedexception.php +++ b/lib/public/files/notpermittedexception.php @@ -1,11 +1,35 @@ <?php /** - * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com> - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. + * ownCloud + * + * @author Robin Appelman + * @copyright 2013 Robin Appelman icewind@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/>. + * */ +/** + * Public interface of ownCloud for apps to use. + * Files/NotPermittedException class + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes namespace OCP\Files; +/** + * Exception for not permitted action + */ class NotPermittedException extends \Exception {} diff --git a/lib/public/files/storage.php b/lib/public/files/storage.php index f32f2073483..194b42a6481 100644 --- a/lib/public/files/storage.php +++ b/lib/public/files/storage.php @@ -1,11 +1,32 @@ <?php /** - * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com> - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. + * ownCloud + * + * @author Robin Appelman + * @copyright 2012 Robin Appelman icewind@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/>. + * + */ + +/** + * Public interface of ownCloud for apps to use. + * Files/Storage interface */ +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes namespace OCP\Files; /** diff --git a/lib/public/groupinterface.php b/lib/public/groupinterface.php index 5603faa8265..625e0b12a87 100644 --- a/lib/public/groupinterface.php +++ b/lib/public/groupinterface.php @@ -1,24 +1,24 @@ <?php /** -* ownCloud -* -* @author Arthur Schiwon -* @copyright 2012 Arthur Schiwon blizzz@owncloud.org -* -* 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/>. -* -*/ + * ownCloud + * + * @author Arthur Schiwon + * @copyright 2012 Arthur Schiwon blizzz@owncloud.org + * + * 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/>. + * + */ /** * Public interface of ownCloud for apps to use. @@ -26,6 +26,8 @@ * */ +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes namespace OCP; interface GroupInterface extends \OC_Group_Interface {} diff --git a/lib/public/iaddressbook.php b/lib/public/iaddressbook.php index 77e8750d9da..dcfe08012e6 100644 --- a/lib/public/iaddressbook.php +++ b/lib/public/iaddressbook.php @@ -20,6 +20,11 @@ * */ +/** + * Public interface of ownCloud for apps to use. + * IAddressBook interface + */ + // use OCP namespace for all classes that are considered public. // This means that they should be used by apps instead of the internal ownCloud classes namespace OCP { diff --git a/lib/public/iavatar.php b/lib/public/iavatar.php new file mode 100644 index 00000000000..2cbec0d45c3 --- /dev/null +++ b/lib/public/iavatar.php @@ -0,0 +1,38 @@ +<?php +/** + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OCP; + +/** + * This class provides avatar functionality + */ + +interface IAvatar { + + /** + * @brief get the users avatar + * @param $size integer size in px of the avatar, avatars are square, defaults to 64 + * @return boolean|\OC_Image containing the avatar or false if there's no image + */ + function get($size = 64); + + /** + * @brief sets the users avatar + * @param $data mixed imagedata or path to set a new avatar + * @throws Exception if the provided file is not a jpg or png image + * @throws Exception if the provided image is not valid + * @throws \OCP\NotSquareException if the image is not square + * @return void + */ + function set($data); + + /** + * @brief remove the users avatar + * @return void + */ + function remove(); +} diff --git a/lib/public/iavatarmanager.php b/lib/public/iavatarmanager.php new file mode 100644 index 00000000000..9b185ae0467 --- /dev/null +++ b/lib/public/iavatarmanager.php @@ -0,0 +1,23 @@ +<?php +/** + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OCP; + +/** + * This class provides avatar functionality + */ + +interface IAvatarManager { + + /** + * @brief return a user specific instance of \OCP\IAvatar + * @see \OCP\IAvatar + * @param $user string the ownCloud user id + * @return \OCP\IAvatar + */ + function getAvatar($user); +} diff --git a/lib/public/icache.php b/lib/public/icache.php index 436ee71b2b9..0da994eadb3 100644 --- a/lib/public/icache.php +++ b/lib/public/icache.php @@ -1,10 +1,33 @@ <?php /** - * Copyright (c) 2013 Thomas Tanghus (thomas@tanghus.net) - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. + * ownCloud + * + * @author Thomas Tanghus + * @copyright 2013 Thomas Tanghus thomas@tanghus.net + * + * 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/>. + * */ + +/** + * Public interface of ownCloud for apps to use. + * Cache interface + * + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes namespace OCP; /** @@ -14,7 +37,6 @@ interface ICache { /** * Get a value from the user cache - * * @param string $key * @return mixed */ @@ -22,7 +44,6 @@ interface ICache { /** * Set a value in the user cache - * * @param string $key * @param mixed $value * @param int $ttl Time To Live in seconds. Defaults to 60*60*24 @@ -32,7 +53,6 @@ interface ICache { /** * Check if a value is set in the user cache - * * @param string $key * @return bool */ @@ -40,14 +60,13 @@ interface ICache { /** * Remove an item from the user cache - * * @param string $key * @return bool */ public function remove($key); /** - * clear the user cache of all entries starting with a prefix + * Clear the user cache of all entries starting with a prefix * @param string $prefix (optional) * @return bool */ diff --git a/lib/public/iconfig.php b/lib/public/iconfig.php index 850bddf6935..1d0f8e0015c 100644 --- a/lib/public/iconfig.php +++ b/lib/public/iconfig.php @@ -1,12 +1,33 @@ <?php /** - * Copyright (c) 2013 Bart Visscher <bartv@thisnet.nl> - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. - * + * ownCloud + * + * @author Bart Visscher + * @copyright 2013 Bart Visscher bartv@thisnet.nl + * + * 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/>. + * */ +/** + * Public interface of ownCloud for apps to use. + * Config interface + * + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes namespace OCP; /** @@ -15,6 +36,7 @@ namespace OCP; interface IConfig { /** * Sets a new system wide value + * * @param string $key the key of the value, under which will be saved * @param string $value the value that should be stored * @todo need a use case for this @@ -23,14 +45,17 @@ interface IConfig { /** * Looks up a system wide defined value + * * @param string $key the key of the value, under which it was saved + * @param string $default the default value to be returned if the value isn't set * @return string the saved value */ - public function getSystemValue($key); + public function getSystemValue($key, $default = ''); /** * Writes a new app wide value + * * @param string $appName the appName that we want to store the value under * @param string $key the key of the value, under which will be saved * @param string $value the value that should be stored @@ -39,15 +64,18 @@ interface IConfig { /** * Looks up an app wide defined value + * * @param string $appName the appName that we stored the value under * @param string $key the key of the value, under which it was saved + * @param string $default the default value to be returned if the value isn't set * @return string the saved value */ - public function getAppValue($appName, $key); + public function getAppValue($appName, $key, $default = ''); /** * Set a user defined value + * * @param string $userId the userId of the user that we want to store the value under * @param string $appName the appName that we want to store the value under * @param string $key the key under which the value is being stored @@ -57,9 +85,11 @@ interface IConfig { /** * Shortcut for getting a user defined value + * * @param string $userId the userId of the user that we want to store the value under * @param string $appName the appName that we stored the value under * @param string $key the key under which the value is being stored + * @param string $default the default value to be returned if the value isn't set */ - public function getUserValue($userId, $appName, $key); + public function getUserValue($userId, $appName, $key, $default = ''); } diff --git a/lib/public/icontainer.php b/lib/public/icontainer.php index d43c1c90f11..eaffa5d5a06 100644 --- a/lib/public/icontainer.php +++ b/lib/public/icontainer.php @@ -20,6 +20,14 @@ * */ +/** + * Public interface of ownCloud for apps to use. + * Container interface + * + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes namespace OCP; /** @@ -56,7 +64,7 @@ interface IContainer { * In case the parameter is false the service will be recreated on every call. * * @param string $name - * @param callable $closure + * @param \Closure $closure * @param bool $shared * @return void */ diff --git a/lib/public/idbconnection.php b/lib/public/idbconnection.php index c741a0f061a..656b5e7e5b2 100644 --- a/lib/public/idbconnection.php +++ b/lib/public/idbconnection.php @@ -1,12 +1,33 @@ <?php /** - * Copyright (c) 2013 Bart Visscher <bartv@thisnet.nl> - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. - * + * ownCloud + * + * @author Bart Visscher + * @copyright 2013 Bart Visscher bartv@thisnet.nl + * + * 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/>. + * */ +/** + * Public interface of ownCloud for apps to use. + * DBConnection interface + * + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes namespace OCP; /** @@ -24,15 +45,15 @@ interface IDBConnection { /** * Used to get the id of the just inserted element - * @param string $tableName the name of the table where we inserted the item + * @param string $table the name of the table where we inserted the item * @return int the id of the inserted element */ public function lastInsertId($table = null); /** - * @brief Insert a row if a matching row doesn't exists. - * @param $table string The table name (will replace *PREFIX*) to perform the replace on. - * @param $input array + * 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: * @@ -49,25 +70,25 @@ interface IDBConnection { public function insertIfNotExist($table, $input); /** - * @brief Start a transaction + * Start a transaction * @return bool TRUE on success or FALSE on failure */ public function beginTransaction(); /** - * @brief Commit the database changes done during a transaction that is in progress + * Commit the database changes done during a transaction that is in progress * @return bool TRUE on success or FALSE on failure */ public function commit(); /** - * @brief Rollback the database changes done during a transaction that is in progress + * Rollback the database changes done during a transaction that is in progress * @return bool TRUE on success or FALSE on failure */ public function rollBack(); /** - * returns the error code and message as a string for logging + * Gets the error code and message as a string for logging * @return string */ public function getError(); diff --git a/lib/public/ihelper.php b/lib/public/ihelper.php new file mode 100644 index 00000000000..c0723b8edc7 --- /dev/null +++ b/lib/public/ihelper.php @@ -0,0 +1,44 @@ +<?php +/** + * ownCloud + * + * @author Bart Visscher + * @copyright 2013 Bart Visscher bartv@thisnet.nl + * + * 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/>. + * + */ + +/** + * Public interface of ownCloud for apps to use. + * Helper interface + * + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes +namespace OCP; + +/** + * Functions that don't have any specific interface to place + */ +interface IHelper { + /** + * Gets the content of an URL by using CURL or a fallback if it is not + * installed + * @param string $url the url that should be fetched + * @return string the content of the webpage + */ + public function getUrlContent($url); +} diff --git a/lib/public/il10n.php b/lib/public/il10n.php new file mode 100644 index 00000000000..817b299b0b7 --- /dev/null +++ b/lib/public/il10n.php @@ -0,0 +1,75 @@ +<?php +/** + * Copyright (c) 2013 Bart Visscher <bartv@thisnet.nl> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + * + */ + +/** + * Public interface of ownCloud for apps to use. + * L10n interface + * + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes +namespace OCP; + +/** + * TODO: Description + */ +interface IL10N { + /** + * Translating + * @param $text String The text we need a translation for + * @param array $parameters default:array() Parameters for sprintf + * @return \OC_L10N_String|string Translation or the same text + * + * Returns the translation. If no translation is found, $text will be + * returned. + */ + public function t($text, $parameters = array()); + + /** + * Translating + * @param $text_singular String the string to translate for exactly one object + * @param $text_plural String the string to translate for n objects + * @param $count Integer Number of objects + * @param array $parameters default:array() Parameters for sprintf + * @return \OC_L10N_String|string Translation or the same text + * + * Returns the translation. If no translation is found, $text will be + * returned. %n will be replaced with the number of objects. + * + * The correct plural is determined by the plural_forms-function + * provided by the po file. + * + */ + public function n($text_singular, $text_plural, $count, $parameters = array()); + + /** + * Localization + * @param $type Type of localization + * @param $params parameters for this localization + * @return String or false + * + * Returns the localized data. + * + * Implemented types: + * - date + * - Creates a date + * - l10n-field: date + * - params: timestamp (int/string) + * - datetime + * - Creates date and time + * - l10n-field: datetime + * - params: timestamp (int/string) + * - time + * - Creates a time + * - l10n-field: time + * - params: timestamp (int/string) + */ + public function l($type, $data); +} diff --git a/lib/public/image.php b/lib/public/image.php index c6dd9a113ab..a9e2bfa724e 100644 --- a/lib/public/image.php +++ b/lib/public/image.php @@ -1,25 +1,33 @@ <?php /** -* ownCloud -* -* @author Bart Visscher -* @copyright 2013 Bart Visscher <bartv@thisnet.nl> -* -* 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/>. -* -*/ + * ownCloud + * + * @author Bart Visscher + * @copyright 2013 Bart Visscher <bartv@thisnet.nl> + * + * 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/>. + * + */ + +/** + * Public interface of ownCloud for apps to use. + * Image class + * + */ +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes namespace OCP; /** diff --git a/lib/public/inavigationmanager.php b/lib/public/inavigationmanager.php index f89e790c1d0..73e85d03761 100644 --- a/lib/public/inavigationmanager.php +++ b/lib/public/inavigationmanager.php @@ -1,12 +1,33 @@ <?php /** - * Copyright (c) 2013 Bart Visscher <bartv@thisnet.nl> - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. - * + * ownCloud + * + * @author Bart Visscher + * @copyright 2013 Bart Visscher bartv@thisnet.nl + * + * 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/>. + * */ +/** + * Public interface of ownCloud for apps to use. + * Navigation manager interface + * + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes namespace OCP; /** diff --git a/lib/public/ipreview.php b/lib/public/ipreview.php index b01e7f5b539..f74472ad368 100644 --- a/lib/public/ipreview.php +++ b/lib/public/ipreview.php @@ -1,11 +1,36 @@ <?php + /** - * Copyright (c) 2013 Frank Karlitschek frank@owncloud.org - * Copyright (c) 2013 Georg Ehrke georg@ownCloud.com - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. + * ownCloud + * + * @author Frank Karlitschek + * @author Georg Ehrke + * @copyright 2013 Frank Karlitschek frank@owncloud.org + * @copyright 2013 Georg Ehrke georg@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/>. + * */ + +/** + * Public interface of ownCloud for apps to use. + * Preview interface + * + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes namespace OCP; /** @@ -15,7 +40,7 @@ interface IPreview { /** - * @brief return a preview of a file + * Return a preview of a file * @param string $file The path to the file where you want a thumbnail from * @param int $maxX The maximum X size of the thumbnail. It can be smaller depending on the shape of the image * @param int $maxY The maximum Y size of the thumbnail. It can be smaller depending on the shape of the image @@ -26,7 +51,7 @@ interface IPreview /** - * @brief returns true if the passed mime type is supported + * Returns true if the passed mime type is supported * @param string $mimeType * @return boolean */ diff --git a/lib/public/irequest.php b/lib/public/irequest.php index 9f335b06f2a..ca23e12b7f5 100644 --- a/lib/public/irequest.php +++ b/lib/public/irequest.php @@ -20,8 +20,38 @@ * */ +/** + * Public interface of ownCloud for apps to use. + * Request interface + * + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes namespace OCP; +/** + * This interface provides an immutable object with with accessors to + * request variables and headers. + * + * Access request variables by method and name. + * + * Examples: + * + * $request->post['myvar']; // Only look for POST variables + * $request->myvar; or $request->{'myvar'}; or $request->{$myvar} + * Looks in the combined GET, POST and urlParams array. + * + * If you access e.g. ->post but the current HTTP request method + * is GET a \LogicException will be thrown. + * + * NOTE: + * - When accessing ->put a stream resource is returned and the accessor + * will return false on subsequent access to ->put or ->patch. + * - When accessing ->patch and the Content-Type is either application/json + * or application/x-www-form-urlencoded (most cases) it will act like ->get + * and ->post and return an array. Otherwise the raw data will be returned. + */ interface IRequest { @@ -86,11 +116,8 @@ interface IRequest { /** - * Returns the request body content. - * - * @param Boolean $asResource If true, a resource will be returned - * @return string|resource The request body content or a resource to read the body stream. - * @throws \LogicException + * Checks if the CSRF check was correct + * @return bool true if CSRF check passed */ - function getContent($asResource = false); + public function passesCSRFCheck(); } diff --git a/lib/public/iservercontainer.php b/lib/public/iservercontainer.php index f4045faefef..b958d2d03f4 100644 --- a/lib/public/iservercontainer.php +++ b/lib/public/iservercontainer.php @@ -20,6 +20,14 @@ * */ +/** + * Public interface of ownCloud for apps to use. + * Server container interface + * + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes namespace OCP; @@ -92,16 +100,41 @@ interface IServerContainer { function getUserSession(); /** + * Returns the navigation manager + * * @return \OCP\INavigationManager */ function getNavigationManager(); /** + * Returns the config manager + * * @return \OCP\IConfig */ function getConfig(); /** + * get an L10N instance + * @param $app string appid + * @return \OCP\IL10N + */ + function getL10N($app); + + /** + * Returns the URL generator + * + * @return \OCP\IURLGenerator + */ + function getURLGenerator(); + + /** + * Returns the Helper + * + * @return \OCP\IHelper + */ + function getHelper(); + + /** * Returns an ICache instance * * @return \OCP\ICache @@ -116,10 +149,24 @@ interface IServerContainer { function getSession(); /** + * Returns the activity manager + * + * @return \OCP\Activity\IManager + */ + function getActivityManager(); + + /** * Returns the current session * * @return \OCP\IDBConnection */ function getDatabaseConnection(); + /** + * Returns an avatar manager, used for avatar functionality + * + * @return \OCP\IAvatarManager + */ + function getAvatarManager(); + } diff --git a/lib/public/isession.php b/lib/public/isession.php index 0a77b0c823b..20da712cda3 100644 --- a/lib/public/isession.php +++ b/lib/public/isession.php @@ -1,13 +1,35 @@ <?php /** - * Copyright (c) 2013 Thomas Tanghus (thomas@tanghus.net) + * ownCloud + * * @author Thomas Tanghus * @author Robin Appelman - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. + * @copyright 2013 Thomas Tanghus thomas@tanghus.net + * @copyright 2013 Robin Appelman icewind@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/>. + * + */ + +/** + * Public interface of ownCloud for apps to use. + * Session interface + * */ +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes namespace OCP; /** diff --git a/lib/public/itagmanager.php b/lib/public/itagmanager.php index 07e1d12fc0f..40487de42b4 100644 --- a/lib/public/itagmanager.php +++ b/lib/public/itagmanager.php @@ -1,24 +1,34 @@ <?php /** -* ownCloud -* -* @author Thomas Tanghus -* @copyright 2013 Thomas Tanghus <thomas@tanghus.net> -* -* 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/>. -* -*/ + * ownCloud + * + * @author Thomas Tanghus + * @copyright 2013 Thomas Tanghus <thomas@tanghus.net> + * + * 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/>. + * + */ + +/** + * Public interface of ownCloud for apps to use. + * Tag manager interface + * + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes +namespace OCP; /** * Factory class creating instances of \OCP\ITags @@ -30,9 +40,6 @@ * are entered in. If a user already has a tag 'family' for a type, and * tries to add a tag named 'Family' it will be silently ignored. */ - -namespace OCP; - interface ITagManager { /** diff --git a/lib/public/itags.php b/lib/public/itags.php index 5b1ebd189da..ea62fb38ecb 100644 --- a/lib/public/itags.php +++ b/lib/public/itags.php @@ -1,25 +1,33 @@ <?php /** -* ownCloud -* -* @author Thomas Tanghus -* @copyright 2013 Thomas Tanghus <thomas@tanghus.net> -* -* 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/>. -* -*/ + * ownCloud + * + * @author Thomas Tanghus + * @copyright 2013 Thomas Tanghus <thomas@tanghus.net> + * + * 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/>. + * + */ + +/** + * Public interface of ownCloud for apps to use. + * Tags interface + * + */ +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes namespace OCP; // FIXME: Where should I put this? Or should it be implemented as a Listener? diff --git a/lib/public/iurlgenerator.php b/lib/public/iurlgenerator.php new file mode 100644 index 00000000000..afdf1b6f299 --- /dev/null +++ b/lib/public/iurlgenerator.php @@ -0,0 +1,68 @@ +<?php +/** + * ownCloud + * + * @author Bart Visscher + * @copyright 2013 Bart Visscher bartv@thisnet.nl + * + * 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/>. + * + */ + +/** + * Public interface of ownCloud for apps to use. + * URL generator interface + * + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes +namespace OCP; + +/** + * Class to generate URLs + */ +interface IURLGenerator { + /** + * Returns the URL for a route + * @param string $routeName the name of the route + * @param array $arguments an array with arguments which will be filled into the url + * @return string the url + */ + public function linkToRoute($routeName, $arguments = array()); + + /** + * Returns an URL for an image or file + * @param string $appName the name of the app + * @param string $file the name of the file + * @return string the url + */ + public function linkTo($appName, $file); + + /** + * Returns the link to an image, like linkTo but only with prepending img/ + * @param string $appName the name of the app + * @param string $file the name of the file + * @return string the url + */ + public function imagePath($appName, $file); + + + /** + * Makes an URL absolute + * @param string $url the url in the owncloud host + * @return string the absolute version of the url + */ + public function getAbsoluteURL($url); +} diff --git a/lib/public/iusersession.php b/lib/public/iusersession.php index 5dc1ecf71e6..131b326ab90 100644 --- a/lib/public/iusersession.php +++ b/lib/public/iusersession.php @@ -1,12 +1,33 @@ <?php /** - * Copyright (c) 2013 Bart Visscher <bartv@thisnet.nl> - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. - * + * ownCloud + * + * @author Bart Visscher + * @copyright 2013 Bart Visscher bartv@thisnet.nl + * + * 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/>. + * */ +/** + * Public interface of ownCloud for apps to use. + * User session interface + * + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes namespace OCP; /** @@ -22,7 +43,7 @@ interface IUserSession { public function login($user, $password); /** - * @brief Logs the user out including all the session data + * Logs the user out including all the session data * Logout, destroys session */ public function logout(); diff --git a/lib/public/json.php b/lib/public/json.php index 2186dd8ee49..cd5d233ef90 100644 --- a/lib/public/json.php +++ b/lib/public/json.php @@ -1,24 +1,24 @@ <?php /** -* ownCloud -* -* @author Frank Karlitschek -* @copyright 2012 Frank Karlitschek frank@owncloud.org -* -* 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/>. -* -*/ + * ownCloud + * + * @author Frank Karlitschek + * @copyright 2012 Frank Karlitschek frank@owncloud.org + * + * 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/>. + * + */ /** * Public interface of ownCloud for apps to use. @@ -35,7 +35,7 @@ namespace OCP; */ class JSON { /** - * @brief Encode and print $data in JSON format + * Encode and print $data in JSON format * @param array $data The data to use * @param string $setContentType the optional content type * @return string json formatted string. @@ -123,7 +123,7 @@ class JSON { } /** - * @brief set Content-Type header to jsonrequest + * Set Content-Type header to jsonrequest * @param array $type The contwnt type header * @return string json formatted string. */ @@ -167,6 +167,22 @@ class JSON { * @return string json formatted string if not admin user. */ public static function checkAdminUser() { - return(\OC_JSON::checkAdminUser()); + \OC_JSON::checkAdminUser(); + } + + /** + * Encode JSON + * @param array $data + */ + public static function encode($data) { + return(\OC_JSON::encode($data)); + } + + /** + * Check is a given user exists - send json error msg if not + * @param string $user + */ + public static function checkUserExists($user) { + \OC_JSON::checkUserExists($user); } } diff --git a/lib/public/response.php b/lib/public/response.php index de0c3f25347..24d3c81d628 100644 --- a/lib/public/response.php +++ b/lib/public/response.php @@ -1,24 +1,24 @@ <?php /** -* ownCloud -* -* @author Frank Karlitschek -* @copyright 2012 Frank Karlitschek frank@owncloud.org -* -* 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/>. -* -*/ + * ownCloud + * + * @author Frank Karlitschek + * @copyright 2012 Frank Karlitschek frank@owncloud.org + * + * 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/>. + * + */ /** * Public interface of ownCloud for apps to use. @@ -35,64 +35,73 @@ namespace OCP; */ class Response { /** - * @brief Enable response caching by sending correct HTTP headers - * @param int $cache_time time to cache the response - * >0 cache time in seconds - * 0 and <0 enable default browser caching - * null cache indefinitly - */ + * Enable response caching by sending correct HTTP headers + * @param int $cache_time time to cache the response + * >0 cache time in seconds + * 0 and <0 enable default browser caching + * null cache indefinitly + */ static public function enableCaching( $cache_time = null ) { \OC_Response::enableCaching( $cache_time ); } /** - * Checks and set Last-Modified header, when the request matches sends a - * 'not modified' response - * @param string $lastModified time when the reponse was last modified - */ + * Checks and set Last-Modified header, when the request matches sends a + * 'not modified' response + * @param string $lastModified time when the reponse was last modified + */ static public function setLastModifiedHeader( $lastModified ) { \OC_Response::setLastModifiedHeader( $lastModified ); } /** - * @brief disable browser caching - * @see enableCaching with cache_time = 0 - */ + * Sets the content disposition header (with possible workarounds) + * @param string $filename file name + * @param string $type disposition type, either 'attachment' or 'inline' + */ + static public function setContentDispositionHeader( $filename, $type = 'attachment' ) { + \OC_Response::setContentDispositionHeader( $filename, $type ); + } + + /** + * Disable browser caching + * @see enableCaching with cache_time = 0 + */ static public function disableCaching() { \OC_Response::disableCaching(); } /** - * Checks and set ETag header, when the request matches sends a - * 'not modified' response - * @param string $etag token to use for modification check - */ + * Checks and set ETag header, when the request matches sends a + * 'not modified' response + * @param string $etag token to use for modification check + */ static public function setETagHeader( $etag ) { \OC_Response::setETagHeader( $etag ); } /** - * @brief Send file as response, checking and setting caching headers - * @param string $filepath of file to send - */ + * Send file as response, checking and setting caching headers + * @param string $filepath of file to send + */ static public function sendFile( $filepath ) { \OC_Response::sendFile( $filepath ); } /** - * @brief Set response expire time - * @param string|\DateTime $expires date-time when the response expires - * string for DateInterval from now - * DateTime object when to expire response - */ + * Set response expire time + * @param string|\DateTime $expires date-time when the response expires + * string for DateInterval from now + * DateTime object when to expire response + */ static public function setExpiresHeader( $expires ) { \OC_Response::setExpiresHeader( $expires ); } /** - * @brief Send redirect response - * @param string $location to redirect to - */ + * Send redirect response + * @param string $location to redirect to + */ static public function redirect( $location ) { \OC_Response::redirect( $location ); } diff --git a/lib/public/share.php b/lib/public/share.php index 6c5783f1179..f832d04a70f 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -1,32 +1,41 @@ <?php /** -* ownCloud -* -* @author Michael Gapczynski -* @copyright 2012 Michael Gapczynski mtgap@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/>. -*/ + * ownCloud + * + * @author Michael Gapczynski + * @copyright 2012 Michael Gapczynski mtgap@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/>. + */ + +/** + * Public interface of ownCloud for apps to use. + * Share Class + * + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes namespace OCP; /** -* This class provides the ability for apps to share their content between users. -* Apps must create a backend class that implements OCP\Share_Backend and register it with this class. -* -* It provides the following hooks: -* - post_shared -*/ + * This class provides the ability for apps to share their content between users. + * Apps must create a backend class that implements OCP\Share_Backend and register it with this class. + * + * It provides the following hooks: + * - post_shared + */ class Share { const SHARE_TYPE_USER = 0; @@ -37,19 +46,19 @@ class Share { const SHARE_TYPE_REMOTE = 6; /** CRUDS permissions (Create, Read, Update, Delete, Share) using a bitmask - * Construct permissions for share() and setPermissions with Or (|) e.g. - * Give user read and update permissions: PERMISSION_READ | PERMISSION_UPDATE - * - * Check if permission is granted with And (&) e.g. Check if delete is - * granted: if ($permissions & PERMISSION_DELETE) - * - * Remove permissions with And (&) and Not (~) e.g. Remove the update - * permission: $permissions &= ~PERMISSION_UPDATE - * - * Apps are required to handle permissions on their own, this class only - * stores and manages the permissions of shares - * @see lib/public/constants.php - */ + * Construct permissions for share() and setPermissions with Or (|) e.g. + * Give user read and update permissions: PERMISSION_READ | PERMISSION_UPDATE + * + * Check if permission is granted with And (&) e.g. Check if delete is + * granted: if ($permissions & PERMISSION_DELETE) + * + * Remove permissions with And (&) and Not (~) e.g. Remove the update + * permission: $permissions &= ~PERMISSION_UPDATE + * + * Apps are required to handle permissions on their own, this class only + * stores and manages the permissions of shares + * @see lib/public/constants.php + */ const FORMAT_NONE = -1; const FORMAT_STATUSES = -2; @@ -64,13 +73,13 @@ class Share { private static $isResharingAllowed; /** - * @brief Register a sharing backend class that implements OCP\Share_Backend for an item type - * @param string Item type - * @param string Backend class - * @param string (optional) Depends on item type - * @param array (optional) List of supported file extensions if this item type depends on files - * @return Returns true if backend is registered or false if error - */ + * Register a sharing backend class that implements OCP\Share_Backend for an item type + * @param string Item type + * @param string Backend class + * @param string (optional) Depends on item type + * @param array (optional) List of supported file extensions if this item type depends on files + * @return Returns true if backend is registered or false if error + */ public static function registerBackend($itemType, $class, $collectionOf = null, $supportedFileExtensions = null) { if (self::isEnabled()) { if (!isset(self::$backendTypes[$itemType])) { @@ -94,12 +103,11 @@ class Share { } /** - * @brief Check if the Share API is enabled - * @return Returns true if enabled or false - * - * The Share API is enabled by default if not configured - * - */ + * Check if the Share API is enabled + * @return Returns true if enabled or false + * + * The Share API is enabled by default if not configured + */ public static function isEnabled() { if (\OC_Appconfig::getValue('core', 'shareapi_enabled', 'yes') == 'yes') { return true; @@ -108,9 +116,10 @@ class Share { } /** - * @brief Prepare a path to be passed to DB as file_target - * @return string Prepared path - */ + * Prepare a path to be passed to DB as file_target + * @param string $path path + * @return string Prepared path + */ public static function prepFileTarget( $path ) { // Paths in DB are stored with leading slashes, so add one if necessary @@ -125,14 +134,14 @@ class Share { } /** - * @brief Find which users can access a shared item - * @param $path to the file - * @param $user owner of the file - * @param include owner to the list of users with access to the file - * @return array - * @note $path needs to be relative to user data dir, e.g. 'file.txt' - * not '/admin/data/file.txt' - */ + * Find which users can access a shared item + * @param $path to the file + * @param $user owner of the file + * @param include owner to the list of users with access to the file + * @return array + * @note $path needs to be relative to user data dir, e.g. 'file.txt' + * not '/admin/data/file.txt' + */ public static function getUsersSharingFile($path, $user, $includeOwner = false) { $shares = array(); @@ -155,13 +164,13 @@ class Share { while ($source !== -1) { - // Fetch all shares of this file path from DB + // Fetch all shares with another user $query = \OC_DB::prepare( 'SELECT `share_with` FROM `*PREFIX*share` WHERE - `item_source` = ? AND `share_type` = ?' + `item_source` = ? AND `share_type` = ? AND `item_type` IN (\'file\', \'folder\')' ); $result = $query->execute(array($source, self::SHARE_TYPE_USER)); @@ -180,7 +189,7 @@ class Share { FROM `*PREFIX*share` WHERE - `item_source` = ? AND `share_type` = ?' + `item_source` = ? AND `share_type` = ? AND `item_type` IN (\'file\', \'folder\')' ); $result = $query->execute(array($source, self::SHARE_TYPE_GROUP)); @@ -201,7 +210,7 @@ class Share { FROM `*PREFIX*share` WHERE - `item_source` = ? AND `share_type` = ?' + `item_source` = ? AND `share_type` = ? AND `item_type` IN (\'file\', \'folder\')' ); $result = $query->execute(array($source, self::SHARE_TYPE_LINK)); @@ -232,12 +241,14 @@ class Share { } /** - * @brief Get the items of item type shared with the current user - * @param string Item type - * @param int Format (optional) Format type must be defined by the backend - * @param int Number of items to return (optional) Returns all by default - * @return Return depends on format - */ + * Get the items of item type shared with the current user + * @param string Item type + * @param int Format (optional) Format type must be defined by the backend + * @param mixed Parameters (optional) + * @param int Number of items to return (optional) Returns all by default + * @param bool include collections (optional) + * @return Return depends on format + */ public static function getItemsSharedWith($itemType, $format = self::FORMAT_NONE, $parameters = null, $limit = -1, $includeCollections = false) { return self::getItems($itemType, null, self::$shareTypeUserAndGroups, \OC_User::getUser(), null, $format, @@ -245,12 +256,14 @@ class Share { } /** - * @brief Get the item of item type shared with the current user - * @param string Item type - * @param string Item target - * @param int Format (optional) Format type must be defined by the backend - * @return Return depends on format - */ + * Get the item of item type shared with the current user + * @param string $itemType + * @param string $itemTarget + * @param int $format (optional) Format type must be defined by the backend + * @param mixed Parameters (optional) + * @param bool include collections (optional) + * @return Return depends on format + */ public static function getItemSharedWith($itemType, $itemTarget, $format = self::FORMAT_NONE, $parameters = null, $includeCollections = false) { return self::getItems($itemType, $itemTarget, self::$shareTypeUserAndGroups, \OC_User::getUser(), null, $format, @@ -258,12 +271,63 @@ class Share { } /** - * @brief Get the item of item type shared with the current user by source - * @param string Item type - * @param string Item source - * @param int Format (optional) Format type must be defined by the backend - * @return Return depends on format - */ + * Get the item of item type shared with a given user by source + * @param string $itemType + * @param string $itemSource + * @param string $user User user to whom the item was shared + * @return array Return list of items with file_target, permissions and expiration + */ + public static function getItemSharedWithUser($itemType, $itemSource, $user) { + + $shares = array(); + + // first check if there is a db entry for the specific user + $query = \OC_DB::prepare( + 'SELECT `file_target`, `permissions`, `expiration` + FROM + `*PREFIX*share` + WHERE + `item_source` = ? AND `item_type` = ? AND `share_with` = ?' + ); + + $result = \OC_DB::executeAudited($query, array($itemSource, $itemType, $user)); + + while ($row = $result->fetchRow()) { + $shares[] = $row; + } + + //if didn't found a result than let's look for a group share. + if(empty($shares)) { + $groups = \OC_Group::getUserGroups($user); + + $query = \OC_DB::prepare( + 'SELECT `file_target`, `permissions`, `expiration` + FROM + `*PREFIX*share` + WHERE + `item_source` = ? AND `item_type` = ? AND `share_with` in (?)' + ); + + $result = \OC_DB::executeAudited($query, array($itemSource, $itemType, implode(',', $groups))); + + while ($row = $result->fetchRow()) { + $shares[] = $row; + } + } + + return $shares; + + } + + /** + * Get the item of item type shared with the current user by source + * @param string Item type + * @param string Item source + * @param int Format (optional) Format type must be defined by the backend + * @param mixed Parameters + * @param bool include collections + * @return Return depends on format + */ public static function getItemSharedWithBySource($itemType, $itemSource, $format = self::FORMAT_NONE, $parameters = null, $includeCollections = false) { return self::getItems($itemType, $itemSource, self::$shareTypeUserAndGroups, \OC_User::getUser(), null, $format, @@ -271,44 +335,46 @@ class Share { } /** - * @brief Get the item of item type shared by a link - * @param string Item type - * @param string Item source - * @param string Owner of link - * @return Item - */ + * Get the item of item type shared by a link + * @param string Item type + * @param string Item source + * @param string Owner of link + * @return Item + */ public static function getItemSharedWithByLink($itemType, $itemSource, $uidOwner) { return self::getItems($itemType, $itemSource, self::SHARE_TYPE_LINK, null, $uidOwner, self::FORMAT_NONE, null, 1); } /** - * @brief Get the item shared by a token - * @param string token - * @return Item + * Based on the given token the share information will be returned - password protected shares will be verified + * @param string $token + * @return array | bool false will be returned in case the token is unknown or unauthorized */ - public static function getShareByToken($token) { + public static function getShareByToken($token, $checkPasswordProtection = true) { $query = \OC_DB::prepare('SELECT * FROM `*PREFIX*share` WHERE `token` = ?', 1); $result = $query->execute(array($token)); if (\OC_DB::isError($result)) { \OC_Log::write('OCP\Share', \OC_DB::getErrorMessage($result) . ', token=' . $token, \OC_Log::ERROR); } $row = $result->fetchRow(); + if ($row === false) { + return false; + } + if (is_array($row) and self::expireItem($row)) { + return false; + } - if (!empty($row['expiration'])) { - $now = new \DateTime(); - $expirationDate = new \DateTime($row['expiration'], new \DateTimeZone('UTC')); - if ($now > $expirationDate) { - self::delete($row['id']); - return false; - } + // password protected shares need to be authenticated + if ($checkPasswordProtection && !\OCP\Share::checkPasswordProtectedShare($row)) { + return false; } return $row; } /** - * @brief resolves reshares down to the last real share + * resolves reshares down to the last real share * @param $linkItem * @return $fileOwner */ @@ -331,12 +397,14 @@ class Share { /** - * @brief Get the shared items of item type owned by the current user - * @param string Item type - * @param int Format (optional) Format type must be defined by the backend - * @param int Number of items to return (optional) Returns all by default - * @return Return depends on format - */ + * Get the shared items of item type owned by the current user + * @param string Item type + * @param int Format (optional) Format type must be defined by the backend + * @param mixed Parameters + * @param int Number of items to return (optional) Returns all by default + * @param bool include collections + * @return Return depends on format + */ public static function getItemsShared($itemType, $format = self::FORMAT_NONE, $parameters = null, $limit = -1, $includeCollections = false) { return self::getItems($itemType, null, null, null, \OC_User::getUser(), $format, @@ -344,12 +412,14 @@ class Share { } /** - * @brief Get the shared item of item type owned by the current user - * @param string Item type - * @param string Item source - * @param int Format (optional) Format type must be defined by the backend - * @return Return depends on format - */ + * Get the shared item of item type owned by the current user + * @param string Item type + * @param string Item source + * @param int Format (optional) Format type must be defined by the backend + * @param mixed Parameters + * @param bool include collections + * @return Return depends on format + */ public static function getItemShared($itemType, $itemSource, $format = self::FORMAT_NONE, $parameters = null, $includeCollections = false) { return self::getItems($itemType, $itemSource, null, null, \OC_User::getUser(), $format, @@ -357,16 +427,18 @@ class Share { } /** - * Get all users an item is shared with - * @param string Item type - * @param string Item source - * @param string Owner - * @param bool Include collections - * @return Return array of users - */ - public static function getUsersItemShared($itemType, $itemSource, $uidOwner, $includeCollections = false) { + * Get all users an item is shared with + * @param string Item type + * @param string Item source + * @param string Owner + * @param bool Include collections + * @praram bool check expire date + * @return Return array of users + */ + public static function getUsersItemShared($itemType, $itemSource, $uidOwner, $includeCollections = false, $checkExpireDate = true) { + $users = array(); - $items = self::getItems($itemType, $itemSource, null, null, $uidOwner, self::FORMAT_NONE, null, -1, $includeCollections); + $items = self::getItems($itemType, $itemSource, null, null, $uidOwner, self::FORMAT_NONE, null, -1, $includeCollections, false, $checkExpireDate); if ($items) { foreach ($items as $item) { if ((int)$item['share_type'] === self::SHARE_TYPE_USER) { @@ -380,33 +452,45 @@ class Share { } /** - * @brief Share an item with a user, group, or via private link - * @param string Item type - * @param string Item source - * @param int SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK - * @param string User or group the item is being shared with - * @param int CRUDS permissions - * @return bool|string Returns true on success or false on failure, Returns token on success for links - */ - public static function shareItem($itemType, $itemSource, $shareType, $shareWith, $permissions) { + * Share an item with a user, group, or via private link + * @param string $itemType + * @param string $itemSource + * @param int $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK + * @param string $shareWith User or group the item is being shared with + * @param int $permissions CRUDS + * @param null $itemSourceName + * @throws \Exception + * @internal param \OCP\Item $string type + * @internal param \OCP\Item $string source + * @internal param \OCP\SHARE_TYPE_USER $int , SHARE_TYPE_GROUP, or SHARE_TYPE_LINK + * @internal param \OCP\User $string or group the item is being shared with + * @internal param \OCP\CRUDS $int permissions + * @return bool|string Returns true on success or false on failure, Returns token on success for links + */ + public static function shareItem($itemType, $itemSource, $shareType, $shareWith, $permissions, $itemSourceName = null) { $uidOwner = \OC_User::getUser(); $sharingPolicy = \OC_Appconfig::getValue('core', 'shareapi_share_policy', 'global'); + + if (is_null($itemSourceName)) { + $itemSourceName = $itemSource; + } + // Verify share type and sharing conditions are met if ($shareType === self::SHARE_TYPE_USER) { if ($shareWith == $uidOwner) { - $message = 'Sharing '.$itemSource.' failed, because the user '.$shareWith.' is the item owner'; + $message = 'Sharing '.$itemSourceName.' failed, because the user '.$shareWith.' is the item owner'; \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR); throw new \Exception($message); } if (!\OC_User::userExists($shareWith)) { - $message = 'Sharing '.$itemSource.' failed, because the user '.$shareWith.' does not exist'; + $message = 'Sharing '.$itemSourceName.' failed, because the user '.$shareWith.' does not exist'; \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR); throw new \Exception($message); } if ($sharingPolicy == 'groups_only') { $inGroup = array_intersect(\OC_Group::getUserGroups($uidOwner), \OC_Group::getUserGroups($shareWith)); if (empty($inGroup)) { - $message = 'Sharing '.$itemSource.' failed, because the user ' + $message = 'Sharing '.$itemSourceName.' failed, because the user ' .$shareWith.' is not a member of any groups that '.$uidOwner.' is a member of'; \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR); throw new \Exception($message); @@ -419,19 +503,19 @@ class Share { // owner and is not a user share, this use case is for increasing // permissions for a specific user if ($checkExists['uid_owner'] != $uidOwner || $checkExists['share_type'] == $shareType) { - $message = 'Sharing '.$itemSource.' failed, because this item is already shared with '.$shareWith; + $message = 'Sharing '.$itemSourceName.' failed, because this item is already shared with '.$shareWith; \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR); throw new \Exception($message); } } } else if ($shareType === self::SHARE_TYPE_GROUP) { if (!\OC_Group::groupExists($shareWith)) { - $message = 'Sharing '.$itemSource.' failed, because the group '.$shareWith.' does not exist'; + $message = 'Sharing '.$itemSourceName.' failed, because the group '.$shareWith.' does not exist'; \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR); throw new \Exception($message); } if ($sharingPolicy == 'groups_only' && !\OC_Group::inGroup($uidOwner, $shareWith)) { - $message = 'Sharing '.$itemSource.' failed, because ' + $message = 'Sharing '.$itemSourceName.' failed, because ' .$uidOwner.' is not a member of the group '.$shareWith; \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR); throw new \Exception($message); @@ -444,7 +528,7 @@ class Share { // owner and is not a group share, this use case is for increasing // permissions for a specific user if ($checkExists['uid_owner'] != $uidOwner || $checkExists['share_type'] == $shareType) { - $message = 'Sharing '.$itemSource.' failed, because this item is already shared with '.$shareWith; + $message = 'Sharing '.$itemSourceName.' failed, because this item is already shared with '.$shareWith; \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR); throw new \Exception($message); } @@ -486,14 +570,14 @@ class Share { $token = \OC_Util::generateRandomBytes(self::TOKEN_LENGTH); } $result = self::put($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions, - null, $token); + null, $token, $itemSourceName); if ($result) { return $token; } else { return false; } } - $message = 'Sharing '.$itemSource.' failed, because sharing with links is not allowed'; + $message = 'Sharing '.$itemSourceName.' failed, because sharing with links is not allowed'; \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR); throw new \Exception($message); return false; @@ -552,79 +636,67 @@ class Share { // return false; // } else { // Put the item into the database - return self::put($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions); + return self::put($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions, null, null, $itemSourceName); // } } /** - * @brief Unshare an item from a user, group, or delete a private link - * @param string Item type - * @param string Item source - * @param int SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK - * @param string User or group the item is being shared with - * @return Returns true on success or false on failure - */ + * Unshare an item from a user, group, or delete a private link + * @param string Item type + * @param string Item source + * @param int SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK + * @param string User or group the item is being shared with + * @return Returns true on success or false on failure + */ public static function unshare($itemType, $itemSource, $shareType, $shareWith) { if ($item = self::getItems($itemType, $itemSource, $shareType, $shareWith, \OC_User::getUser(), self::FORMAT_NONE, null, 1)) { - // Pass all the vars we have for now, they may be useful - \OC_Hook::emit('OCP\Share', 'pre_unshare', array( - 'itemType' => $itemType, - 'itemSource' => $itemSource, - 'fileSource' => $item['file_source'], - 'shareType' => $shareType, - 'shareWith' => $shareWith, - 'itemParent' => $item['parent'], - )); - self::delete($item['id']); - \OC_Hook::emit('OCP\Share', 'post_unshare', array( - 'itemType' => $itemType, - 'itemSource' => $itemSource, - 'shareType' => $shareType, - 'shareWith' => $shareWith, - 'itemParent' => $item['parent'], - )); + self::unshareItem($item); return true; } return false; } /** - * @brief Unshare an item from all users, groups, and remove all links - * @param string Item type - * @param string Item source - * @return Returns true on success or false on failure - */ + * Unshare an item from all users, groups, and remove all links + * @param string Item type + * @param string Item source + * @return Returns true on success or false on failure + */ public static function unshareAll($itemType, $itemSource) { - if ($shares = self::getItemShared($itemType, $itemSource)) { + // Get all of the owners of shares of this item. + $query = \OC_DB::prepare( 'SELECT `uid_owner` from `*PREFIX*share` WHERE `item_type`=? AND `item_source`=?' ); + $result = $query->execute(array($itemType, $itemSource)); + $shares = array(); + // Add each owner's shares to the array of all shares for this item. + while ($row = $result->fetchRow()) { + $shares = array_merge($shares, self::getItems($itemType, $itemSource, null, null, $row['uid_owner'])); + } + if (!empty($shares)) { // Pass all the vars we have for now, they may be useful - \OC_Hook::emit('OCP\Share', 'pre_unshareAll', array( + $hookParams = array( 'itemType' => $itemType, 'itemSource' => $itemSource, - 'shares' => $shares - )); + 'shares' => $shares, + ); + \OC_Hook::emit('OCP\Share', 'pre_unshareAll', $hookParams); foreach ($shares as $share) { - self::delete($share['id']); + self::unshareItem($share); } - \OC_Hook::emit('OCP\Share', 'post_unshareAll', array( - 'itemType' => $itemType, - 'itemSource' => $itemSource, - 'shares' => $shares - )); + \OC_Hook::emit('OCP\Share', 'post_unshareAll', $hookParams); return true; } return false; } /** - * @brief Unshare an item shared with the current user - * @param string Item type - * @param string Item target - * @return Returns true on success or false on failure - * - * Unsharing from self is not allowed for items inside collections - * - */ + * Unshare an item shared with the current user + * @param string Item type + * @param string Item target + * @return Returns true on success or false on failure + * + * Unsharing from self is not allowed for items inside collections + */ public static function unshareFromSelf($itemType, $itemTarget) { if ($item = self::getItemSharedWith($itemType, $itemTarget)) { if ((int)$item['share_type'] === self::SHARE_TYPE_GROUP) { @@ -653,16 +725,37 @@ class Share { } return false; } + /** + * sent status if users got informed by mail about share + * @param string $itemType + * @param string $itemSource + * @param int $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK + * @param bool $status + */ + public static function setSendMailStatus($itemType, $itemSource, $shareType, $status) { + $status = $status ? 1 : 0; + + $query = \OC_DB::prepare( + 'UPDATE `*PREFIX*share` + SET `mail_send` = ? + WHERE `item_type` = ? AND `item_source` = ? AND `share_type` = ?'); + + $result = $query->execute(array($status, $itemType, $itemSource, $shareType)); + + if($result === false) { + \OC_Log::write('OCP\Share', 'Couldn\'t set send mail status', \OC_Log::ERROR); + } + } /** - * @brief Set the permissions of an item for a specific user or group - * @param string Item type - * @param string Item source - * @param int SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK - * @param string User or group the item is being shared with - * @param int CRUDS permissions - * @return Returns true on success or false on failure - */ + * Set the permissions of an item for a specific user or group + * @param string Item type + * @param string Item source + * @param int SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK + * @param string User or group the item is being shared with + * @param int CRUDS permissions + * @return Returns true on success or false on failure + */ public static function setPermissions($itemType, $itemSource, $shareType, $shareWith, $permissions) { if ($item = self::getItems($itemType, $itemSource, $shareType, $shareWith, \OC_User::getUser(), self::FORMAT_NONE, null, 1, false)) { @@ -738,6 +831,13 @@ class Share { throw new \Exception($message); } + /** + * Set expiration date for a share + * @param string $itemType + * @param string $itemSource + * @param string $date expiration date + * @return Share_Backend + */ public static function setExpirationDate($itemType, $itemSource, $date) { if ($items = self::getItems($itemType, $itemSource, null, null, \OC_User::getUser(), self::FORMAT_NONE, null, -1, false)) { @@ -746,11 +846,12 @@ class Share { $date = null; } else { $date = new \DateTime($date); - $date = date('Y-m-d H:i', $date->format('U') - $date->getOffset()); } $query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `expiration` = ? WHERE `id` = ?'); + $query->bindValue(1, $date, 'datetime'); foreach ($items as $item) { - $query->execute(array($date, $item['id'])); + $query->bindValue(2, (int) $item['id']); + $query->execute(); } return true; } @@ -759,10 +860,50 @@ class Share { } /** - * @brief Get the backend class for the specified item type - * @param string $itemType - * @return Share_Backend - */ + * Checks whether a share has expired, calls unshareItem() if yes. + * @param array $item Share data (usually database row) + * @return bool True if item was expired, false otherwise. + */ + protected static function expireItem(array $item) { + if (!empty($item['expiration'])) { + $now = new \DateTime(); + $expires = new \DateTime($item['expiration']); + if ($now > $expires) { + self::unshareItem($item); + return true; + } + } + return false; + } + + /** + * Unshares a share given a share data array + * @param array $item Share data (usually database row) + * @return null + */ + protected static function unshareItem(array $item) { + // Pass all the vars we have for now, they may be useful + $hookParams = array( + 'itemType' => $item['item_type'], + 'itemSource' => $item['item_source'], + 'shareType' => $item['share_type'], + 'shareWith' => $item['share_with'], + 'itemParent' => $item['parent'], + 'uidOwner' => $item['uid_owner'], + ); + + \OC_Hook::emit('OCP\Share', 'pre_unshare', $hookParams + array( + 'fileSource' => $item['file_source'], + )); + self::delete($item['id']); + \OC_Hook::emit('OCP\Share', 'post_unshare', $hookParams); + } + + /** + * Get the backend class for the specified item type + * @param string $itemType + * @return Share_Backend + */ public static function getBackend($itemType) { if (isset(self::$backends[$itemType])) { return self::$backends[$itemType]; @@ -788,12 +929,11 @@ class Share { } /** - * @brief Check if resharing is allowed - * @return Returns true if allowed or false - * - * Resharing is allowed by default if not configured - * - */ + * Check if resharing is allowed + * @return Returns true if allowed or false + * + * Resharing is allowed by default if not configured + */ private static function isResharingAllowed() { if (!isset(self::$isResharingAllowed)) { if (\OC_Appconfig::getValue('core', 'shareapi_allow_resharing', 'yes') == 'yes') { @@ -806,10 +946,10 @@ class Share { } /** - * @brief Get a list of collection item types for the specified item type - * @param string Item type - * @return array - */ + * Get a list of collection item types for the specified item type + * @param string Item type + * @return array + */ private static function getCollectionItemTypes($itemType) { $collectionTypes = array($itemType); foreach (self::$backendTypes as $type => $backend) { @@ -830,24 +970,26 @@ class Share { } /** - * @brief Get shared items from the database - * @param string Item type - * @param string Item source or target (optional) - * @param int SHARE_TYPE_USER, SHARE_TYPE_GROUP, SHARE_TYPE_LINK, $shareTypeUserAndGroups, or $shareTypeGroupUserUnique - * @param string User or group the item is being shared with - * @param string User that is the owner of shared items (optional) - * @param int Format to convert items to with formatItems() - * @param mixed Parameters to pass to formatItems() - * @param int Number of items to return, -1 to return all matches (optional) - * @param bool Include collection item types (optional) - * @return mixed - * - * See public functions getItem(s)... for parameter usage - * - */ + * Get shared items from the database + * @param string Item type + * @param string Item source or target (optional) + * @param int SHARE_TYPE_USER, SHARE_TYPE_GROUP, SHARE_TYPE_LINK, $shareTypeUserAndGroups, or $shareTypeGroupUserUnique + * @param string User or group the item is being shared with + * @param string User that is the owner of shared items (optional) + * @param int Format to convert items to with formatItems() + * @param mixed Parameters to pass to formatItems() + * @param int Number of items to return, -1 to return all matches (optional) + * @param bool Include collection item types (optional) + * @param bool TODO (optional) + * @prams bool check expire date + * @return mixed + * + * See public functions getItem(s)... for parameter usage + * + */ private static function getItems($itemType, $item = null, $shareType = null, $shareWith = null, $uidOwner = null, $format = self::FORMAT_NONE, $parameters = null, $limit = -1, - $includeCollections = false, $itemShareWithBySource = false) { + $includeCollections = false, $itemShareWithBySource = false, $checkExpireDate = true) { if (!self::isEnabled()) { if ($limit == 1 || (isset($uidOwner) && isset($item))) { return false; @@ -889,6 +1031,10 @@ class Share { $queryArgs = array($itemType); } } + if (\OC_Appconfig::getValue('core', 'shareapi_allow_links', 'yes') !== 'yes') { + $where .= ' AND `share_type` != ?'; + $queryArgs[] = self::SHARE_TYPE_LINK; + } if (isset($shareType)) { // Include all user and group items if ($shareType == self::$shareTypeUserAndGroups && isset($shareWith)) { @@ -982,20 +1128,20 @@ class Share { // TODO Optimize selects if ($format == self::FORMAT_STATUSES) { if ($itemType == 'file' || $itemType == 'folder') { - $select = '`*PREFIX*share`.`id`, `item_type`, `*PREFIX*share`.`parent`,' - .' `share_type`, `file_source`, `path`, `expiration`, `storage`'; + $select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `*PREFIX*share`.`parent`,' + .' `share_type`, `file_source`, `path`, `expiration`, `storage`, `share_with`, `mail_send`, `uid_owner`'; } else { - $select = '`id`, `item_type`, `item_source`, `parent`, `share_type`, `expiration`'; + $select = '`id`, `item_type`, `item_source`, `parent`, `share_type`, `share_with`, `expiration`, `mail_send`, `uid_owner`'; } } else { if (isset($uidOwner)) { if ($itemType == 'file' || $itemType == 'folder') { - $select = '`*PREFIX*share`.`id`, `item_type`, `*PREFIX*share`.`parent`,' + $select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `*PREFIX*share`.`parent`,' .' `share_type`, `share_with`, `file_source`, `path`, `permissions`, `stime`,' - .' `expiration`, `token`, `storage`'; + .' `expiration`, `token`, `storage`, `mail_send`, `uid_owner`'; } else { $select = '`id`, `item_type`, `item_source`, `parent`, `share_type`, `share_with`, `permissions`,' - .' `stime`, `file_source`, `expiration`, `token`'; + .' `stime`, `file_source`, `expiration`, `token`, `mail_send`, `uid_owner`'; } } else { if ($fileDependent) { @@ -1003,14 +1149,14 @@ class Share { && $format == \OC_Share_Backend_File::FORMAT_GET_FOLDER_CONTENTS || $format == \OC_Share_Backend_File::FORMAT_FILE_APP_ROOT ) { - $select = '`*PREFIX*share`.`id`, `item_type`, `*PREFIX*share`.`parent`, `uid_owner`, ' + $select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `*PREFIX*share`.`parent`, `uid_owner`, ' .'`share_type`, `share_with`, `file_source`, `path`, `file_target`, ' .'`permissions`, `expiration`, `storage`, `*PREFIX*filecache`.`parent` as `file_parent`, ' - .'`name`, `mtime`, `mimetype`, `mimepart`, `size`, `encrypted`, `etag`'; + .'`name`, `mtime`, `mimetype`, `mimepart`, `size`, `encrypted`, `etag`, `mail_send`'; } else { $select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `item_target`, `*PREFIX*share`.`parent`, `share_type`, `share_with`, `uid_owner`, - `file_source`, `path`, `file_target`, `permissions`, `stime`, `expiration`, `token`, `storage`'; + `file_source`, `path`, `file_target`, `permissions`, `stime`, `expiration`, `token`, `storage`, `mail_send`'; } } else { $select = '*'; @@ -1109,10 +1255,8 @@ class Share { } } } - if (isset($row['expiration'])) { - $time = new \DateTime(); - if ($row['expiration'] < date('Y-m-d H:i', $time->format('U') - $time->getOffset())) { - self::delete($row['id']); + if($checkExpireDate) { + if (self::expireItem($row)) { continue; } } @@ -1235,30 +1379,35 @@ class Share { } /** - * @brief Put shared item into the database - * @param string Item type - * @param string Item source - * @param int SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK - * @param string User or group the item is being shared with - * @param int CRUDS permissions - * @param bool|array Parent folder target (optional) - * @return bool Returns true on success or false on failure - */ + * Put shared item into the database + * @param string Item type + * @param string Item source + * @param int SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK + * @param string User or group the item is being shared with + * @param string User that is the owner of shared item + * @param int CRUDS permissions + * @param bool|array Parent folder target (optional) + * @param string token (optional) + * @param string name of the source item (optional) + * @return bool Returns true on success or false on failure + */ private static function put($itemType, $itemSource, $shareType, $shareWith, $uidOwner, - $permissions, $parentFolder = null, $token = null) { + $permissions, $parentFolder = null, $token = null, $itemSourceName = null) { $backend = self::getBackend($itemType); + // Check if this is a reshare if ($checkReshare = self::getItemSharedWithBySource($itemType, $itemSource, self::FORMAT_NONE, null, true)) { + // Check if attempting to share back to owner if ($checkReshare['uid_owner'] == $shareWith && $shareType == self::SHARE_TYPE_USER) { - $message = 'Sharing '.$itemSource.' failed, because the user '.$shareWith.' is the original sharer'; + $message = 'Sharing '.$itemSourceName.' failed, because the user '.$shareWith.' is the original sharer'; \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR); throw new \Exception($message); } // Check if share permissions is granted if (self::isResharingAllowed() && (int)$checkReshare['permissions'] & PERMISSION_SHARE) { if (~(int)$checkReshare['permissions'] & $permissions) { - $message = 'Sharing '.$itemSource + $message = 'Sharing '.$itemSourceName .' failed, because the permissions exceed permissions granted to '.$uidOwner; \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR); throw new \Exception($message); @@ -1272,7 +1421,7 @@ class Share { $filePath = $checkReshare['file_target']; } } else { - $message = 'Sharing '.$itemSource.' failed, because resharing is not allowed'; + $message = 'Sharing '.$itemSourceName.' failed, because resharing is not allowed'; \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR); throw new \Exception($message); } @@ -1400,6 +1549,7 @@ class Share { 'id' => $parent, 'token' => $token )); + if ($parentFolder === true) { // Return parent folders to preserve file target paths for potential children return $parentFolders; @@ -1471,15 +1621,16 @@ class Share { } /** - * @brief Generate a unique target for the item - * @param string Item type - * @param string Item source - * @param int SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK - * @param string User or group the item is being shared with - * @param string The suggested target originating from a reshare (optional) - * @param int The id of the parent group share (optional) - * @return string Item target - */ + * Generate a unique target for the item + * @param string Item type + * @param string Item source + * @param int SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK + * @param string User or group the item is being shared with + * @param string User that is the owner of shared item + * @param string The suggested target originating from a reshare (optional) + * @param int The id of the parent group share (optional) + * @return string Item target + */ private static function generateTarget($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $suggestedTarget = null, $groupParent = null) { $backend = self::getBackend($itemType); @@ -1587,11 +1738,11 @@ class Share { } /** - * @brief Delete all reshares of an item - * @param int Id of item to delete - * @param bool If true, exclude the parent from the delete (optional) - * @param string The user that the parent was shared with (optinal) - */ + * Delete all reshares of an item + * @param int Id of item to delete + * @param bool If true, exclude the parent from the delete (optional) + * @param string The user that the parent was shared with (optinal) + */ private static function delete($parent, $excludeParent = false, $uidOwner = null) { $ids = array($parent); $parents = array($parent); @@ -1647,9 +1798,25 @@ class Share { } /** - * Hook Listeners - */ + * Delete all shares with type SHARE_TYPE_LINK + */ + public static function removeAllLinkShares() { + // Delete any link shares + $query = \OC_DB::prepare('SELECT `id` FROM `*PREFIX*share` WHERE `share_type` = ?'); + $result = $query->execute(array(self::SHARE_TYPE_LINK)); + while ($item = $result->fetchRow()) { + self::delete($item['id']); + } + } + + /** + * Hook Listeners + */ + /** + * Function that is called after a user is deleted. Cleans up the shares of that user. + * @param array arguments + */ public static function post_deleteUser($arguments) { // Delete any items shared with the deleted user $query = \OC_DB::prepare('DELETE FROM `*PREFIX*share`' @@ -1663,6 +1830,11 @@ class Share { } } + /** + * Function that is called after a user is added to a group. + * TODO what does it do? + * @param array arguments + */ public static function post_addToGroup($arguments) { // Find the group shares and check if the user needs a unique target $query = \OC_DB::prepare('SELECT * FROM `*PREFIX*share` WHERE `share_type` = ? AND `share_with` = ?'); @@ -1693,6 +1865,10 @@ class Share { } } + /** + * Function that is called after a user is removed from a group. Shares are cleaned up. + * @param array arguments + */ public static function post_removeFromGroup($arguments) { // TODO Don't call if user deleted? $sql = 'SELECT `id`, `share_type` FROM `*PREFIX*share`' @@ -1709,6 +1885,10 @@ class Share { } } + /** + * Function that is called after a group is removed. Cleans up the shares to that group. + * @param array arguments + */ public static function post_deleteGroup($arguments) { $sql = 'SELECT `id` FROM `*PREFIX*share` WHERE `share_type` = ? AND `share_with` = ?'; $result = \OC_DB::executeAudited($sql, array(self::SHARE_TYPE_GROUP, $arguments['gid'])); @@ -1717,90 +1897,117 @@ class Share { } } + /** + * In case a password protected link is not yet authenticated this function will return false + * + * @param array $linkItem + * @return bool + */ + public static function checkPasswordProtectedShare(array $linkItem) { + if (!isset($linkItem['share_with'])) { + return true; + } + if (!isset($linkItem['share_type'])) { + return true; + } + if (!isset($linkItem['id'])) { + return true; + } + + if ($linkItem['share_type'] != \OCP\Share::SHARE_TYPE_LINK) { + return true; + } + + if ( \OC::$session->exists('public_link_authenticated') + && \OC::$session->get('public_link_authenticated') === $linkItem['id'] ) { + return true; + } + + return false; + } } /** -* Interface that apps must implement to share content. -*/ + * Interface that apps must implement to share content. + */ interface Share_Backend { /** - * @brief Get the source of the item to be stored in the database - * @param string Item source - * @param string Owner of the item - * @return mixed|array|false Source - * - * Return an array if the item is file dependent, the array needs two keys: 'item' and 'file' - * Return false if the item does not exist for the user - * - * The formatItems() function will translate the source returned back into the item - */ + * Get the source of the item to be stored in the database + * @param string Item source + * @param string Owner of the item + * @return mixed|array|false Source + * + * Return an array if the item is file dependent, the array needs two keys: 'item' and 'file' + * Return false if the item does not exist for the user + * + * The formatItems() function will translate the source returned back into the item + */ public function isValidSource($itemSource, $uidOwner); /** - * @brief Get a unique name of the item for the specified user - * @param string Item source - * @param string|false User the item is being shared with - * @param array|null List of similar item names already existing as shared items - * @return string Target name - * - * This function needs to verify that the user does not already have an item with this name. - * If it does generate a new name e.g. name_# - */ + * Get a unique name of the item for the specified user + * @param string Item source + * @param string|false User the item is being shared with + * @param array|null List of similar item names already existing as shared items + * @return string Target name + * + * This function needs to verify that the user does not already have an item with this name. + * If it does generate a new name e.g. name_# + */ public function generateTarget($itemSource, $shareWith, $exclude = null); /** - * @brief Converts the shared item sources back into the item in the specified format - * @param array Shared items - * @param int Format - * @return ? - * - * The items array is a 3-dimensional array with the item_source as the - * first key and the share id as the second key to an array with the share - * info. - * - * The key/value pairs included in the share info depend on the function originally called: - * If called by getItem(s)Shared: id, item_type, item, item_source, - * share_type, share_with, permissions, stime, file_source - * - * If called by getItem(s)SharedWith: id, item_type, item, item_source, - * item_target, share_type, share_with, permissions, stime, file_source, - * file_target - * - * This function allows the backend to control the output of shared items with custom formats. - * It is only called through calls to the public getItem(s)Shared(With) functions. - */ + * Converts the shared item sources back into the item in the specified format + * @param array Shared items + * @param int Format + * @return TODO + * + * The items array is a 3-dimensional array with the item_source as the + * first key and the share id as the second key to an array with the share + * info. + * + * The key/value pairs included in the share info depend on the function originally called: + * If called by getItem(s)Shared: id, item_type, item, item_source, + * share_type, share_with, permissions, stime, file_source + * + * If called by getItem(s)SharedWith: id, item_type, item, item_source, + * item_target, share_type, share_with, permissions, stime, file_source, + * file_target + * + * This function allows the backend to control the output of shared items with custom formats. + * It is only called through calls to the public getItem(s)Shared(With) functions. + */ public function formatItems($items, $format, $parameters = null); } /** -* Interface for share backends that share content that is dependent on files. -* Extends the Share_Backend interface. -*/ + * Interface for share backends that share content that is dependent on files. + * Extends the Share_Backend interface. + */ interface Share_Backend_File_Dependent extends Share_Backend { /** - * @brief Get the file path of the item - * @param - * @param - * @return - */ + * Get the file path of the item + * @param string Item source + * @param string User that is the owner of shared item + */ public function getFilePath($itemSource, $uidOwner); } /** -* Interface for collections of of items implemented by another share backend. -* Extends the Share_Backend interface. -*/ + * Interface for collections of of items implemented by another share backend. + * Extends the Share_Backend interface. + */ interface Share_Backend_Collection extends Share_Backend { /** - * @brief Get the sources of the children of the item - * @param string Item source - * @return array Returns an array of children each inside an array with the keys: source, target, and file_path if applicable - */ + * Get the sources of the children of the item + * @param string Item source + * @return array Returns an array of children each inside an array with the keys: source, target, and file_path if applicable + */ public function getChildren($itemSource); } diff --git a/lib/public/template.php b/lib/public/template.php index 3b1a4ed4906..320b7c6393f 100644 --- a/lib/public/template.php +++ b/lib/public/template.php @@ -1,24 +1,24 @@ <?php /** -* ownCloud -* -* @author Frank Karlitschek -* @copyright 2012 Frank Karlitschek frank@owncloud.org -* -* 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/>. -* -*/ + * ownCloud + * + * @author Frank Karlitschek + * @copyright 2012 Frank Karlitschek frank@owncloud.org + * + * 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/>. + * + */ /** * Public interface of ownCloud for apps to use. @@ -32,12 +32,12 @@ namespace OCP; /** - * @brief make OC_Helper::imagePath available as a simple function - * @param $app app - * @param $image image - * @returns link to the image + * Make OC_Helper::imagePath available as a simple function + * @param string app + * @param string image + * @return link to the image * - * For further information have a look at OC_Helper::imagePath + * @see OC_Helper::imagePath */ function image_path( $app, $image ) { return(\image_path( $app, $image )); @@ -45,40 +45,39 @@ function image_path( $app, $image ) { /** - * @brief make OC_Helper::mimetypeIcon available as a simple function - * Returns the path to the image of this file type. - * @param $mimetype mimetype - * @returns link to the image + * Make OC_Helper::mimetypeIcon available as a simple function + * @param string mimetype + * @return path to the image of this file type. */ function mimetype_icon( $mimetype ) { return(\mimetype_icon( $mimetype )); } /** - * @brief make preview_icon available as a simple function - * Returns the path to the preview of the image. - * @param $path path of file - * @returns link to the preview + * Make preview_icon available as a simple function + * @param string path of file + * @return path to the preview of the image */ function preview_icon( $path ) { return(\preview_icon( $path )); } /** - * @brief make publicpreview_icon available as a simple function + * Make publicpreview_icon available as a simple function * Returns the path to the preview of the image. - * @param $path path of file - * @returns link to the preview + * @param string path of file + * @param string token + * @return link to the preview */ function publicPreview_icon ( $path, $token ) { return(\publicPreview_icon( $path, $token )); } /** - * @brief make OC_Helper::humanFileSize available as a simple function - * Makes 2048 to 2 kB. - * @param $bytes size in bytes - * @returns size as string + * Make OC_Helper::humanFileSize available as a simple function + * Example: 2048 to 2 kB. + * @param int size in bytes + * @return size as string */ function human_file_size( $bytes ) { return(\human_file_size( $bytes )); @@ -86,20 +85,21 @@ function human_file_size( $bytes ) { /** - * @brief Return the relative date in relation to today. Returns something like "last hour" or "two month ago" - * @param $timestamp unix timestamp - * @returns human readable interpretation of the timestamp + * Return the relative date in relation to today. Returns something like "last hour" or "two month ago" + * @param int unix timestamp + * @param boolean date only + * @return human readable interpretation of the timestamp */ -function relative_modified_date($timestamp) { - return(\relative_modified_date($timestamp)); +function relative_modified_date( $timestamp, $dateOnly = false ) { + return(\relative_modified_date($timestamp, null, $dateOnly)); } /** - * @brief DEPRECATED Return a human readable outout for a file size. + * Return a human readable outout for a file size. * @deprecated human_file_size() instead - * @param $byte size of a file in byte - * @returns human readable interpretation of a file size + * @param integer size of a file in byte + * @return human readable interpretation of a file size */ function simple_file_size($bytes) { return(\human_file_size($bytes)); @@ -107,11 +107,11 @@ function simple_file_size($bytes) { /** - * @brief Generate html code for an options block. + * Generate html code for an options block. * @param $options the options * @param $selected which one is selected? - * @param $params the parameters - * @returns html options + * @param array the parameters + * @return html options */ function html_select_options($options, $selected, $params=array()) { return(\html_select_options($options, $selected, $params)); diff --git a/lib/public/user.php b/lib/public/user.php index 576a64d7048..acc0e3b737b 100644 --- a/lib/public/user.php +++ b/lib/public/user.php @@ -1,28 +1,28 @@ <?php /** -* ownCloud -* -* @author Frank Karlitschek -* @copyright 2012 Frank Karlitschek frank@owncloud.org -* -* 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/>. -* -*/ + * ownCloud + * + * @author Frank Karlitschek + * @copyright 2012 Frank Karlitschek frank@owncloud.org + * + * 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/>. + * + */ /** * Public interface of ownCloud for apps to use. - * User Class. + * User Class * */ @@ -36,7 +36,7 @@ namespace OCP; */ class User { /** - * @brief get the user id of the user currently logged in. + * Get the user id of the user currently logged in. * @return string uid or false */ public static function getUser() { @@ -44,45 +44,46 @@ class User { } /** - * @brief Get a list of all users - * @returns array with all uids - * - * Get a list of all users. + * Get a list of all users + * @param string search pattern + * @param int limit + * @param int offset + * @return array with all uids */ - public static function getUsers($search = '', $limit = null, $offset = null) { - return \OC_User::getUsers($search, $limit, $offset); + public static function getUsers( $search = '', $limit = null, $offset = null ) { + return \OC_User::getUsers( $search, $limit, $offset ); } /** - * @brief get the user display name of the user currently logged in. + * Get the user display name of the user currently logged in. + * @param string user id or null for current user * @return string display name */ - public static function getDisplayName($user=null) { - return \OC_User::getDisplayName($user); + public static function getDisplayName( $user = null ) { + return \OC_User::getDisplayName( $user ); } /** - * @brief Get a list of all display names - * @returns array with all display names (value) and the correspondig uids (key) - * * Get a list of all display names and user ids. + * @param string search pattern + * @param int limit + * @param int offset + * @return array with all display names (value) and the correspondig uids (key) */ - public static function getDisplayNames($search = '', $limit = null, $offset = null) { - return \OC_User::getDisplayNames($search, $limit, $offset); + public static function getDisplayNames( $search = '', $limit = null, $offset = null ) { + return \OC_User::getDisplayNames( $search, $limit, $offset ); } /** - * @brief Check if the user is logged in - * @returns true/false - * - * Checks if the user is logged in + * Check if the user is logged in + * @return boolean */ public static function isLoggedIn() { return \OC_User::isLoggedIn(); } /** - * @brief check if a user exists + * Check if a user exists * @param string $uid the username * @param string $excludingBackend (default none) * @return boolean @@ -91,7 +92,7 @@ class User { return \OC_User::userExists( $uid, $excludingBackend ); } /** - * @brief Loggs the user out including all the session data + * Logs the user out including all the session data * Logout, destroys session */ public static function logout() { @@ -99,10 +100,10 @@ class User { } /** - * @brief Check if the password is correct - * @param $uid The username - * @param $password The password - * @returns mixed username on success, false otherwise + * Check if the password is correct + * @param string The username + * @param string The password + * @return mixed username on success, false otherwise * * Check if the password is correct without logging in the user */ diff --git a/lib/public/userinterface.php b/lib/public/userinterface.php index 53d9faf7a5e..1f6c2f7292b 100644 --- a/lib/public/userinterface.php +++ b/lib/public/userinterface.php @@ -1,31 +1,33 @@ <?php /** -* ownCloud -* -* @author Arthur Schiwon -* @copyright 2012 Arthur Schiwon blizzz@owncloud.org -* -* 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/>. -* -*/ + * ownCloud + * + * @author Arthur Schiwon + * @copyright 2012 Arthur Schiwon blizzz@owncloud.org + * + * 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/>. + * + */ /** * Public interface of ownCloud for apps to use. - * User Class. + * User Interface * */ +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes namespace OCP; interface UserInterface extends \OC_User_Interface {} diff --git a/lib/public/util.php b/lib/public/util.php index b33f07b55e6..26c5a15cff2 100644 --- a/lib/public/util.php +++ b/lib/public/util.php @@ -1,24 +1,24 @@ <?php /** -* ownCloud -* -* @author Frank Karlitschek -* @copyright 2012 Frank Karlitschek frank@owncloud.org -* -* 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/>. -* -*/ + * ownCloud + * + * @author Frank Karlitschek + * @copyright 2012 Frank Karlitschek frank@owncloud.org + * + * 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/>. + * + */ /** * Public interface of ownCloud for apps to use. @@ -42,7 +42,7 @@ class Util { const FATAL=4; /** - * @brief get the current installed version of ownCloud + * get the current installed version of ownCloud * @return array */ public static function getVersion() { @@ -50,7 +50,7 @@ class Util { } /** - * @brief send an email + * send an email * @param string $toaddress * @param string $toname * @param string $subject @@ -58,6 +58,10 @@ class Util { * @param string $fromaddress * @param string $fromname * @param bool $html + * @param string $altbody + * @param string $ccaddress + * @param string $ccname + * @param string $bcc */ public static function sendMail( $toaddress, $toname, $subject, $mailtext, $fromaddress, $fromname, $html = 0, $altbody = '', $ccaddress = '', $ccname = '', $bcc = '') { @@ -67,7 +71,7 @@ class Util { } /** - * @brief write a message in the log + * write a message in the log * @param string $app * @param string $message * @param int $level @@ -78,8 +82,45 @@ class Util { } /** - * @brief get l10n object - * @param string $app + * write exception into the log. Include the stack trace + * if DEBUG mode is enabled + * @param string $app app name + * @param Exception $ex exception to log + */ + public static function logException( $app, \Exception $ex ) { + $class = get_class($ex); + if ($class !== 'Exception') { + $message = $class . ': '; + } + $message .= $ex->getMessage(); + if ($ex->getCode()) { + $message .= ' [' . $ex->getCode() . ']'; + } + \OCP\Util::writeLog($app, 'Exception: ' . $message, \OCP\Util::FATAL); + if (defined('DEBUG') and DEBUG) { + // also log stack trace + $stack = explode("\n", $ex->getTraceAsString()); + // first element is empty + array_shift($stack); + foreach ($stack as $s) { + \OCP\Util::writeLog($app, 'Exception: ' . $s, \OCP\Util::FATAL); + } + + // include cause + while (method_exists($ex, 'getPrevious') && $ex = $ex->getPrevious()) { + $message .= ' - Caused by:' . ' '; + $message .= $ex->getMessage(); + if ($ex->getCode()) { + $message .= '[' . $ex->getCode() . '] '; + } + \OCP\Util::writeLog($app, 'Exception: ' . $message, \OCP\Util::FATAL); + } + } + } + + /** + * get l10n object + * @param string $application * @return OC_L10N */ public static function getL10N( $application ) { @@ -87,24 +128,25 @@ class Util { } /** - * @brief add a css file - * @param string $url + * add a css file + * @param string $application + * @param string $file */ public static function addStyle( $application, $file = null ) { \OC_Util::addStyle( $application, $file ); } /** - * @brief add a javascript file + * add a javascript file * @param string $application - * @param string $file + * @param string $file */ public static function addScript( $application, $file = null ) { \OC_Util::addScript( $application, $file ); } /** - * @brief Add a custom element to the header + * Add a custom element to the header * @param string $tag tag name of the element * @param array $attributes array of attributes for the element * @param string $text the text content for the element @@ -114,7 +156,7 @@ class Util { } /** - * @brief formats a timestamp in the "right" way + * formats a timestamp in the "right" way * @param int $timestamp $timestamp * @param bool $dateOnly option to omit time from the result */ @@ -123,93 +165,78 @@ class Util { } /** - * @brief check if some encrypted files are stored + * check if some encrypted files are stored * @return bool */ public static function encryptedFiles() { return \OC_Util::encryptedFiles(); } - + /** - * @brief Creates an absolute url + * Creates an absolute url to the given app and file. * @param string $app app * @param string $file file * @param array $args array with param=>value, will be appended to the returned url * The value of $args will be urlencoded - * @returns string the url - * - * Returns a absolute url to the given app and file. + * @return string the url */ public static function linkToAbsolute( $app, $file, $args = array() ) { return(\OC_Helper::linkToAbsolute( $app, $file, $args )); } /** - * @brief Creates an absolute url for remote use + * Creates an absolute url for remote use. * @param string $service id - * @returns string the url - * - * Returns a absolute url to the given app and file. + * @return string the url */ public static function linkToRemote( $service ) { return(\OC_Helper::linkToRemote( $service )); } /** - * @brief Creates an absolute url for public use + * Creates an absolute url for public use * @param string $service id - * @returns string the url - * - * Returns a absolute url to the given app and file. + * @return string the url */ public static function linkToPublic($service) { return \OC_Helper::linkToPublic($service); } /** - * @brief Creates an url using a defined route + * Creates an url using a defined route * @param $route * @param array $parameters * @return * @internal param array $args with param=>value, will be appended to the returned url - * @returns the url - * - * Returns a url to the given app and file. + * @return the url */ public static function linkToRoute( $route, $parameters = array() ) { return \OC_Helper::linkToRoute($route, $parameters); } /** - * @brief Creates an url + * Creates an url to the given app and file * @param string $app app * @param string $file file * @param array $args array with param=>value, will be appended to the returned url * The value of $args will be urlencoded - * @returns string the url - * - * Returns a url to the given app and file. + * @return string the url */ public static function linkTo( $app, $file, $args = array() ) { return(\OC_Helper::linkTo( $app, $file, $args )); } /** - * @brief Returns the server host - * @returns string the server host - * - * Returns the server host, even if the website uses one or more - * reverse proxies + * Returns the server host, even if the website uses one or more reverse proxy + * @return string the server host */ public static function getServerHost() { return(\OC_Request::serverHost()); } /** - * @brief returns the server hostname - * @returns string the server hostname - * * Returns the server host name without an eventual port number + * @return string the server hostname */ public static function getServerHostName() { $host_name = self::getServerHost(); @@ -222,17 +249,22 @@ class Util { } /** - * @brief Returns the default email address + * Returns the default email address * @param string $user_part the user part of the address - * @returns string the default email address + * @return string the default email address * * Assembles a default email address (using the server hostname * and the given user part, and returns it * Example: when given lostpassword-noreply as $user_part param, * and is currently accessed via http(s)://example.com/, * it would return 'lostpassword-noreply@example.com' + * + * If the configuration value 'mail_from_address' is set in + * config.php, this value will override the $user_part that + * is passed to this function */ public static function getDefaultEmailAddress($user_part) { + $user_part = \OC_Config::getValue('mail_from_address', $user_part); $host_name = self::getServerHostName(); $host_name = \OC_Config::getValue('mail_domain', $host_name); $defaultEmailAddress = $user_part.'@'.$host_name; @@ -246,66 +278,54 @@ class Util { } /** - * @brief Returns the server protocol - * @returns string the server protocol - * * Returns the server protocol. It respects reverse proxy servers and load balancers + * @return string the server protocol */ public static function getServerProtocol() { return(\OC_Request::serverProtocol()); } /** - * @brief Returns the request uri - * @returns the request uri + * Returns the request uri, even if the website uses one or more reverse proxies * - * Returns the request uri, even if the website uses one or more - * reverse proxies + * @return the request uri */ public static function getRequestUri() { return(\OC_Request::requestUri()); } /** - * @brief Returns the script name - * @returns the script name + * Returns the script name, even if the website uses one or more reverse proxies * - * Returns the script name, even if the website uses one or more - * reverse proxies + * @return the script name */ public static function getScriptName() { return(\OC_Request::scriptName()); } /** - * @brief Creates path to an image + * Creates path to an image * @param string $app app * @param string $image image name - * @returns string the url - * - * Returns the path to the image. + * @return string the url */ public static function imagePath( $app, $image ) { return(\OC_Helper::imagePath( $app, $image )); } /** - * @brief Make a human file size + * Make a human file size (2048 to 2 kB) * @param int $bytes file size in bytes - * @returns string a human readable file size - * - * Makes 2048 to 2 kB. + * @return string a human readable file size */ public static function humanFileSize( $bytes ) { return(\OC_Helper::humanFileSize( $bytes )); } /** - * @brief Make a computer file size + * Make a computer file size (2 kB to 2048) * @param string $str file size in a fancy format - * @returns int a file size in bytes - * - * Makes 2kB to 2048. + * @return int a file size in bytes * * Inspired by: http://www.php.net/manual/en/function.filesize.php#92418 */ @@ -314,12 +334,12 @@ class Util { } /** - * @brief connects a function to a hook + * connects a function to a hook * @param string $signalclass class name of emitter * @param string $signalname name of signal * @param string $slotclass class name of slot * @param string $slotname name of slot - * @returns bool + * @return bool * * This function makes it very easy to connect to use hooks. * @@ -330,13 +350,11 @@ class Util { } /** - * @brief emitts a signal + * Emits a signal. To get data from the slot use references! * @param string $signalclass class name of emitter * @param string $signalname name of signal * @param string $params defautl: array() array with additional data - * @returns bool true if slots exists or false if not - * - * Emits a signal. To get data from the slot use references! + * @return bool true if slots exists or false if not * * TODO: write example */ @@ -361,7 +379,7 @@ class Util { } /** - * @brief Used to sanitize HTML + * Used to sanitize HTML * * This function is used to sanitize HTML and should be applied on any * string or array of strings before displaying it on a web page. @@ -372,78 +390,75 @@ class Util { public static function sanitizeHTML( $value ) { return(\OC_Util::sanitizeHTML($value)); } - + /** - * @brief Public function to encode url parameters + * Public function to encode url parameters * * This function is used to encode path to file before output. * Encoding is done according to RFC 3986 with one exception: - * Character '/' is preserved as is. + * Character '/' is preserved as is. * * @param string $component part of URI to encode - * @return string + * @return string */ public static function encodePath($component) { return(\OC_Util::encodePath($component)); } /** - * @brief Returns an array with all keys from input lowercased or uppercased. Numbered indices are left as is. - * - * @param array $input The array to work on - * @param int $case Either MB_CASE_UPPER or MB_CASE_LOWER (default) - * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8 - * @return array - * - * - */ + * Returns an array with all keys from input lowercased or uppercased. Numbered indices are left as is. + * + * @param array $input The array to work on + * @param int $case Either MB_CASE_UPPER or MB_CASE_LOWER (default) + * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8 + * @return array + */ public static function mb_array_change_key_case($input, $case = MB_CASE_LOWER, $encoding = 'UTF-8') { return(\OC_Helper::mb_array_change_key_case($input, $case, $encoding)); } /** - * @brief replaces a copy of string delimited by the start and (optionally) length parameters with the string given in replacement. - * - * @param string $input The input string. .Opposite to the PHP build-in function does not accept an array. - * @param string $replacement The replacement string. - * @param int $start If start is positive, the replacing will begin at the start'th offset into string. If start is negative, the replacing will begin at the start'th character from the end of string. - * @param int $length Length of the part to be replaced - * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8 - * @return string - * - */ + * replaces a copy of string delimited by the start and (optionally) length parameters with the string given in replacement. + * + * @param string $string The input string. Opposite to the PHP build-in function does not accept an array. + * @param string $replacement The replacement string. + * @param int $start If start is positive, the replacing will begin at the start'th offset into string. If start is negative, the replacing will begin at the start'th character from the end of string. + * @param int $length Length of the part to be replaced + * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8 + * @return string + */ public static function mb_substr_replace($string, $replacement, $start, $length = null, $encoding = 'UTF-8') { return(\OC_Helper::mb_substr_replace($string, $replacement, $start, $length, $encoding)); } /** - * @brief Replace all occurrences of the search string with the replacement string - * - * @param string $search The value being searched for, otherwise known as the needle. String. - * @param string $replace The replacement string. - * @param string $subject The string or array being searched and replaced on, otherwise known as the haystack. - * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8 - * @param int $count If passed, this will be set to the number of replacements performed. - * @return string - * - */ + * Replace all occurrences of the search string with the replacement string + * + * @param string $search The value being searched for, otherwise known as the needle. String. + * @param string $replace The replacement string. + * @param string $subject The string or array being searched and replaced on, otherwise known as the haystack. + * @param string $encoding The encoding parameter is the character encoding. Defaults to UTF-8 + * @param int $count If passed, this will be set to the number of replacements performed. + * @return string + */ public static function mb_str_replace($search, $replace, $subject, $encoding = 'UTF-8', &$count = null) { return(\OC_Helper::mb_str_replace($search, $replace, $subject, $encoding, $count)); } /** - * @brief performs a search in a nested array - * @param array $haystack the array to be searched - * @param string $needle the search string - * @param int $index optional, only search this key name - * @return mixed the key of the matching field, otherwise false - */ + * performs a search in a nested array + * + * @param array $haystack the array to be searched + * @param string $needle the search string + * @param int $index optional, only search this key name + * @return mixed the key of the matching field, otherwise false + */ public static function recursiveArraySearch($haystack, $needle, $index = null) { return(\OC_Helper::recursiveArraySearch($haystack, $needle, $index)); } /** - * @brief calculates the maximum upload size respecting system settings, free space and user quota + * calculates the maximum upload size respecting system settings, free space and user quota * * @param $dir the current folder where the user currently operates * @return number of bytes representing |