diff options
author | Tom Needham <tom@owncloud.com> | 2013-03-05 04:25:56 +0400 |
---|---|---|
committer | Tom Needham <tom@owncloud.com> | 2013-03-05 04:25:56 +0400 |
commit | 370f202251df2425ec49c78265859a804a88433f (patch) | |
tree | 75fa9d4d8694032dcb6e0987bc97ef379691e546 /lib | |
parent | f141f8b523f71351841f64ab1e4782b4535ca1b7 (diff) | |
parent | ef70978524ad0f00c3e5f03a489753547afee45a (diff) |
Rebase to current master
Diffstat (limited to 'lib')
105 files changed, 3506 insertions, 838 deletions
diff --git a/lib/api.php b/lib/api.php index 5f2e83c9ce9..8d6bbb7cc09 100644 --- a/lib/api.php +++ b/lib/api.php @@ -81,7 +81,7 @@ class OC_API { // Prepare the request variables if($_SERVER['REQUEST_METHOD'] == 'PUT') { parse_str(file_get_contents("php://input"), $parameters['_put']); - } else if($_SERVER['REQUEST_METHOD'] == 'DELETE'){ + } else if($_SERVER['REQUEST_METHOD'] == 'DELETE') { parse_str(file_get_contents("php://input"), $parameters['_delete']); } $name = $parameters['_route']; diff --git a/lib/app.php b/lib/app.php index 3a4e21e8cd1..55b4543ec9f 100644 --- a/lib/app.php +++ b/lib/app.php @@ -39,6 +39,15 @@ class OC_App{ static private $altLogin = array(); /** + * @brief clean the appid + * @param $app Appid that needs to be cleaned + * @return string + */ + public static function cleanAppId($app) { + return str_replace(array('\0', '/', '\\', '..'), '', $app); + } + + /** * @brief loads all apps * @param array $types * @return bool @@ -67,14 +76,14 @@ class OC_App{ && empty(OC_Util::$core_scripts) && empty(OC_Util::$core_styles)) { OC_Util::$core_scripts = OC_Util::$scripts; - OC_Util::$scripts = array(); - OC_Util::$core_styles = OC_Util::$styles; - OC_Util::$styles = array(); + OC_Util::$scripts = array(); + OC_Util::$core_styles = OC_Util::$styles; + OC_Util::$styles = array(); + } } - } // return - return true; -} + return true; + } /** * load a single app @@ -148,7 +157,7 @@ class OC_App{ */ public static function isShipped($appid){ $info = self::getAppInfo($appid); - if(isset($info['shipped']) && $info['shipped']=='true'){ + if(isset($info['shipped']) && $info['shipped']=='true') { return true; } else { return false; @@ -159,10 +168,12 @@ class OC_App{ * get all enabled apps */ public static function getEnabledApps() { - if(!OC_Config::getValue('installed', false)) + if(!OC_Config::getValue('installed', false)) { return array(); + } $apps=array('files'); - $query = OC_DB::prepare( 'SELECT `appid` FROM `*PREFIX*appconfig` WHERE `configkey` = \'enabled\' AND `configvalue`=\'yes\'' ); + $query = OC_DB::prepare( 'SELECT `appid` FROM `*PREFIX*appconfig`' + .' WHERE `configkey` = \'enabled\' AND `configvalue`=\'yes\'' ); $result=$query->execute(); while($row=$result->fetchRow()) { if(array_search($row['appid'], $apps)===false) { @@ -203,7 +214,8 @@ class OC_App{ $appdata=OC_OCSClient::getApplication($app); $download=OC_OCSClient::getApplicationDownload($app, 1); if(isset($download['downloadlink']) and $download['downloadlink']!='') { - $app=OC_Installer::installApp(array('source'=>'http', 'href'=>$download['downloadlink'],'appdata'=>$appdata)); + $info = array('source'=>'http', 'href'=>$download['downloadlink'], 'appdata'=>$appdata); + $app=OC_Installer::installApp($info); } } } @@ -211,8 +223,11 @@ class OC_App{ // check if the app is compatible with this version of ownCloud $info=OC_App::getAppInfo($app); $version=OC_Util::getVersion(); - if(!isset($info['require']) or ($version[0]>$info['require'])) { - OC_Log::write('core', 'App "'.$info['name'].'" can\'t be installed because it is not compatible with this version of ownCloud', OC_Log::ERROR); + if(!isset($info['require']) or !self::isAppVersionCompatible($version, $info['require'])) { + OC_Log::write('core', + 'App "'.$info['name'].'" can\'t be installed because it is' + .' not compatible with this version of ownCloud', + OC_Log::ERROR); return false; }else{ OC_Appconfig::setValue( $app, 'enabled', 'yes' ); @@ -238,7 +253,7 @@ class OC_App{ OC_Appconfig::setValue( $app, 'enabled', 'no' ); // check if app is a shipped app or not. if not delete - if(!OC_App::isShipped( $app )){ + if(!OC_App::isShipped( $app )) { OC_Installer::removeApp( $app ); } } @@ -286,6 +301,23 @@ class OC_App{ } /** + * @brief Get the navigation entries for the $app + * @param string $app app + * @return array of the $data added with addNavigationEntry + */ + public static function getAppNavigationEntries($app) { + if(is_file(self::getAppPath($app).'/appinfo/app.php')) { + $save = self::$navigation; + self::$navigation = array(); + require $app.'/appinfo/app.php'; + $app_entries = self::$navigation; + self::$navigation = $save; + return $app_entries; + } + return array(); + } + + /** * @brief gets the active Menu entry * @return string id or empty string * @@ -310,33 +342,70 @@ class OC_App{ // by default, settings only contain the help menu if(OC_Config::getValue('knowledgebaseenabled', true)==true) { $settings = array( - array( "id" => "help", "order" => 1000, "href" => OC_Helper::linkToRoute( "settings_help" ), "name" => $l->t("Help"), "icon" => OC_Helper::imagePath( "settings", "help.svg" )) - ); + array( + "id" => "help", + "order" => 1000, + "href" => OC_Helper::linkToRoute( "settings_help" ), + "name" => $l->t("Help"), + "icon" => OC_Helper::imagePath( "settings", "help.svg" ) + ) + ); } // if the user is logged-in if (OC_User::isLoggedIn()) { // personal menu - $settings[] = array( "id" => "personal", "order" => 1, "href" => OC_Helper::linkToRoute( "settings_personal" ), "name" => $l->t("Personal"), "icon" => OC_Helper::imagePath( "settings", "personal.svg" )); + $settings[] = array( + "id" => "personal", + "order" => 1, + "href" => OC_Helper::linkToRoute( "settings_personal" ), + "name" => $l->t("Personal"), + "icon" => OC_Helper::imagePath( "settings", "personal.svg" ) + ); // if there are some settings forms - if(!empty(self::$settingsForms)) + if(!empty(self::$settingsForms)) { // settings menu - $settings[]=array( "id" => "settings", "order" => 1000, "href" => OC_Helper::linkToRoute( "settings_settings" ), "name" => $l->t("Settings"), "icon" => OC_Helper::imagePath( "settings", "settings.svg" )); + $settings[]=array( + "id" => "settings", + "order" => 1000, + "href" => OC_Helper::linkToRoute( "settings_settings" ), + "name" => $l->t("Settings"), + "icon" => OC_Helper::imagePath( "settings", "settings.svg" ) + ); + } //SubAdmins are also allowed to access user management if(OC_SubAdmin::isSubAdmin(OC_User::getUser())) { // admin users menu - $settings[] = array( "id" => "core_users", "order" => 2, "href" => OC_Helper::linkToRoute( "settings_users" ), "name" => $l->t("Users"), "icon" => OC_Helper::imagePath( "settings", "users.svg" )); + $settings[] = array( + "id" => "core_users", + "order" => 2, + "href" => OC_Helper::linkToRoute( "settings_users" ), + "name" => $l->t("Users"), + "icon" => OC_Helper::imagePath( "settings", "users.svg" ) + ); } // if the user is an admin if(OC_User::isAdminUser(OC_User::getUser())) { // admin apps menu - $settings[] = array( "id" => "core_apps", "order" => 3, "href" => OC_Helper::linkToRoute( "settings_apps" ).'?installed', "name" => $l->t("Apps"), "icon" => OC_Helper::imagePath( "settings", "apps.svg" )); + $settings[] = array( + "id" => "core_apps", + "order" => 3, + "href" => OC_Helper::linkToRoute( "settings_apps" ).'?installed', + "name" => $l->t("Apps"), + "icon" => OC_Helper::imagePath( "settings", "apps.svg" ) + ); - $settings[]=array( "id" => "admin", "order" => 1000, "href" => OC_Helper::linkToRoute( "settings_admin" ), "name" => $l->t("Admin"), "icon" => OC_Helper::imagePath( "settings", "admin.svg" )); + $settings[]=array( + "id" => "admin", + "order" => 1000, + "href" => OC_Helper::linkToRoute( "settings_admin" ), + "name" => $l->t("Admin"), + "icon" => OC_Helper::imagePath( "settings", "admin.svg" ) + ); } } @@ -369,8 +438,9 @@ class OC_App{ } foreach(OC::$APPSROOTS as $dir) { - if(isset($dir['writable']) && $dir['writable']===true) + if(isset($dir['writable']) && $dir['writable']===true) { return $dir['path']; + } } OC_Log::write('core', 'No application directories are marked as writable.', OC_Log::ERROR); @@ -531,16 +601,16 @@ class OC_App{ $forms=array(); switch($type) { case 'settings': - $source=self::$settingsForms; - break; + $source=self::$settingsForms; + break; case 'admin': - $source=self::$adminForms; - break; + $source=self::$adminForms; + break; case 'personal': - $source=self::$personalForms; - break; + $source=self::$personalForms; + break; default: - return array(); + return array(); } foreach($source as $form) { $forms[]=include $form; @@ -615,7 +685,8 @@ class OC_App{ public static function listAllApps() { $installedApps = OC_App::getAllApps(); - //TODO which apps do we want to blacklist and how do we integrate blacklisting with the multi apps folder feature? + //TODO which apps do we want to blacklist and how do we integrate + // blacklisting with the multi apps folder feature? $blacklist = array('files');//we dont want to show configuration for these $appList = array(); @@ -645,7 +716,7 @@ class OC_App{ $info['update']=false; } else { $info['internal']=false; - $info['internallabel']='3rd Party App'; + $info['internallabel']='3rd Party'; $info['internalclass']='externalapp'; $info['update']=OC_Installer::isUpdateAvailable($app); } @@ -668,25 +739,26 @@ class OC_App{ // OR $app['ocs_id'] == $remote['ocs_id'] ) { unset( $remoteApps[$key]); + } } } + $combinedApps = array_merge( $appList, $remoteApps ); + } else { + $combinedApps = $appList; } - $combinedApps = array_merge( $appList, $remoteApps ); - } else { - $combinedApps = $appList; - } - return $combinedApps; -} + return $combinedApps; + } /** * @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 + * @return array, multi-dimensional array of apps. + * Keys: id, name, type, typename, personid, license, detailpage, preview, changed, description */ public static function getAppstoreApps( $filter = 'approved' ) { - $catagoryNames = OC_OCSClient::getCategories(); - if ( is_array( $catagoryNames ) ) { + $categoryNames = OC_OCSClient::getCategories(); + if ( is_array( $categoryNames ) ) { // Check that categories of apps were retrieved correctly - if ( ! $categories = array_keys( $catagoryNames ) ) { + if ( ! $categories = array_keys( $categoryNames ) ) { return false; } @@ -700,7 +772,7 @@ class OC_App{ $app1[$i]['ocs_id'] = $app['id']; $app1[$i]['internal'] = $app1[$i]['active'] = 0; $app1[$i]['update'] = false; - if($app['label']=='recommended'){ + if($app['label']=='recommended') { $app1[$i]['internallabel'] = 'Recommended'; $app1[$i]['internalclass'] = 'recommendedapp'; }else{ @@ -748,7 +820,9 @@ class OC_App{ $installedVersion = $versions[$app]; if (version_compare($currentVersion, $installedVersion, '>')) { $info = self::getAppInfo($app); - OC_Log::write($app, 'starting app upgrade from '.$installedVersion.' to '.$currentVersion, OC_Log::DEBUG); + OC_Log::write($app, + 'starting app upgrade from '.$installedVersion.' to '.$currentVersion, + OC_Log::DEBUG); try { OC_App::updateApp($app); OC_Hook::emit('update', 'success', 'Updated '.$info['name'].' app'); @@ -777,14 +851,49 @@ class OC_App{ foreach($apps as $app) { // check if the app is compatible with this version of ownCloud $info = OC_App::getAppInfo($app); - if(!isset($info['require']) or (($version[0].'.'.$version[1])>$info['require'])) { - OC_Log::write('core', 'App "'.$info['name'].'" ('.$app.') can\'t be used because it is not compatible with this version of ownCloud', OC_Log::ERROR); + if(!isset($info['require']) or !self::isAppVersionCompatible($version, $info['require'])) { + OC_Log::write('core', + 'App "'.$info['name'].'" ('.$app.') can\'t be used because it is' + .' not compatible with this version of ownCloud', + OC_Log::ERROR); OC_App::disable( $app ); OC_Hook::emit('update', 'success', 'Disabled '.$info['name'].' app because it is not compatible'); } } } + + /** + * Compares the app version with the owncloud version to see if the app + * requires a newer version than the currently active one + * @param array $owncloudVersions array with 3 entries: major minor bugfix + * @param string $appRequired the required version from the xml + * major.minor.bugfix + * @return boolean true if compatible, otherwise false + */ + public static function isAppVersionCompatible($owncloudVersions, $appRequired){ + $appVersions = explode('.', $appRequired); + + for($i=0; $i<count($appVersions); $i++){ + $appVersion = (int) $appVersions[$i]; + + if(isset($owncloudVersions[$i])){ + $owncloudVersion = $owncloudVersions[$i]; + } else { + $owncloudVersion = 0; + } + + if($owncloudVersion < $appVersion){ + return false; + } elseif ($owncloudVersion > $appVersion) { + return true; + } + } + + return true; + } + + /** * get the installed version of all apps */ @@ -794,7 +903,8 @@ class OC_App{ return $versions; // when function is used besides in checkUpgrade } $versions=array(); - $query = OC_DB::prepare( 'SELECT `appid`, `configvalue` FROM `*PREFIX*appconfig` WHERE `configkey` = \'installed_version\'' ); + $query = OC_DB::prepare( 'SELECT `appid`, `configvalue` FROM `*PREFIX*appconfig`' + .' WHERE `configkey` = \'installed_version\'' ); $result = $query->execute(); while($row = $result->fetchRow()) { $versions[$row['appid']]=$row['configvalue']; diff --git a/lib/appconfig.php b/lib/appconfig.php index 1f2d576af87..e615d838173 100644 --- a/lib/appconfig.php +++ b/lib/appconfig.php @@ -91,7 +91,8 @@ class OC_Appconfig{ */ 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` = ?' ); + $query = OC_DB::prepare( 'SELECT `configvalue` FROM `*PREFIX*appconfig`' + .' WHERE `appid` = ? AND `configkey` = ?' ); $result = $query->execute( array( $app, $key )); $row = $result->fetchRow(); if($row) { @@ -124,11 +125,13 @@ class OC_Appconfig{ 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 = 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 = OC_DB::prepare( 'UPDATE `*PREFIX*appconfig` SET `configvalue` = ?' + .' WHERE `appid` = ? AND `configkey` = ?' ); $query->execute( array( $value, $app, $key )); } } diff --git a/lib/arrayparser.php b/lib/arrayparser.php new file mode 100644 index 00000000000..3bb394a5163 --- /dev/null +++ b/lib/arrayparser.php @@ -0,0 +1,189 @@ +<?php + +/** + * @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/>. + * + */ + +namespace OC; + +class SyntaxException extends \Exception { +} + +class ArrayParser { + const TYPE_NUM = 1; + const TYPE_BOOL = 2; + const TYPE_STRING = 3; + const TYPE_ARRAY = 4; + + function parsePHP($string) { + $string = $this->stripPHPTags($string); + $string = $this->stripAssignAndReturn($string); + return $this->parse($string); + } + + function stripPHPTags($string) { + $string = trim($string); + if (substr($string, 0, 5) === '<?php') { + $string = substr($string, 5); + } + if (substr($string, -2) === '?>') { + $string = substr($string, 0, -2); + } + return $string; + } + + function stripAssignAndReturn($string) { + $string = trim($string); + if (substr($string, 0, 6) === 'return') { + $string = substr($string, 6); + } + if (substr($string, 0, 1) === '$') { + list(, $string) = explode('=', $string, 2); + } + return $string; + } + + function parse($string) { + $string = trim($string); + $string = trim($string, ';'); + switch ($this->getType($string)) { + case self::TYPE_NUM: + return $this->parseNum($string); + case self::TYPE_BOOL: + return $this->parseBool($string); + case self::TYPE_STRING: + return $this->parseString($string); + case self::TYPE_ARRAY: + return $this->parseArray($string); + } + return null; + } + + function getType($string) { + $string = strtolower($string); + $first = substr($string, 0, 1); + $last = substr($string, -1, 1); + $arrayFirst = substr($string, 0, 5); + if (($first === '"' or $first === "'") and ($last === '"' or $last === "'")) { + return self::TYPE_STRING; + } elseif ($string === 'false' or $string === 'true') { + return self::TYPE_BOOL; + } elseif ($arrayFirst === 'array' and $last === ')') { + return self::TYPE_ARRAY; + } else { + return self::TYPE_NUM; + } + } + + function parseString($string) { + return substr($string, 1, -1); + } + + function parseNum($string) { + return intval($string); + } + + function parseBool($string) { + $string = strtolower($string); + return $string === 'true'; + } + + function parseArray($string) { + $body = substr($string, 5); + $body = trim($body); + $body = substr($body, 1, -1); + $items = $this->splitArray($body); + $result = array(); + $lastKey = -1; + foreach ($items as $item) { + $item = trim($item); + if ($item) { + if (strpos($item, '=>')) { + list($key, $value) = explode('=>', $item, 2); + $key = $this->parse($key); + $value = $this->parse($value); + } else { + $key = ++$lastKey; + $value = $item; + } + + if (is_numeric($key)) { + $lastKey = $key; + } + $result[$key] = $value; + } + } + return $result; + } + + function splitArray($body) { + $inSingleQuote = false;//keep track if we are inside quotes + $inDoubleQuote = false; + $bracketDepth = 0;//keep track if we are inside brackets + $parts = array(); + $start = 0; + $escaped = false;//keep track if we are after an escape character + $skips = array();//keep track of the escape characters we need to remove from the result + if (substr($body, -1, 1) !== ',') { + $body .= ','; + } + for ($i = 0; $i < strlen($body); $i++) { + $char = substr($body, $i, 1); + if ($char === '\\') { + if ($escaped) { + array_unshift($skips, $i - 1); + } + $escaped = !$escaped; + } else { + if ($char === '"' and !$inSingleQuote) { + if ($escaped) { + array_unshift($skips, $i - 1); + } else { + $inDoubleQuote = !$inDoubleQuote; + } + } elseif ($char === "'" and !$inDoubleQuote) { + if ($escaped) { + array_unshift($skips, $i - 1); + } else { + $inSingleQuote = !$inSingleQuote; + } + } elseif (!$inDoubleQuote and !$inSingleQuote) { + if ($char === '(') { + $bracketDepth++; + } elseif ($char === ')') { + if ($bracketDepth <= 0) { + throw new SyntaxException; + } else { + $bracketDepth--; + } + } elseif ($bracketDepth === 0 and $char === ',') { + $part = substr($body, $start, $i - $start); + foreach ($skips as $skip) { + $part = substr($part, 0, $skip - $start) . substr($part, $skip - $start + 1); + } + $parts[] = $part; + $start = $i + 1; + $skips = array(); + } + } + $escaped = false; + } + } + return $parts; + } +} diff --git a/lib/backgroundjob/queuedtask.php b/lib/backgroundjob/queuedtask.php index 8264e1a0ae6..b2ce6f39ed8 100644 --- a/lib/backgroundjob/queuedtask.php +++ b/lib/backgroundjob/queuedtask.php @@ -82,7 +82,8 @@ class OC_BackgroundJob_QueuedTask{ * @return id of task */ public static function add( $app, $klass, $method, $parameters ) { - $stmt = OC_DB::prepare( 'INSERT INTO `*PREFIX*queuedtasks` (`app`, `klass`, `method`, `parameters`) VALUES(?,?,?,?)' ); + $stmt = OC_DB::prepare( 'INSERT INTO `*PREFIX*queuedtasks` (`app`, `klass`, `method`, `parameters`)' + .' VALUES(?,?,?,?)' ); $result = $stmt->execute(array($app, $klass, $method, $parameters )); return OC_DB::insertid(); diff --git a/lib/base.php b/lib/base.php index 5bfdb0b7c0a..bffae36261e 100644 --- a/lib/base.php +++ b/lib/base.php @@ -162,7 +162,9 @@ class OC { OC::$THIRDPARTYWEBROOT = rtrim(dirname(OC::$WEBROOT), '/'); OC::$THIRDPARTYROOT = rtrim(dirname(OC::$SERVERROOT), '/'); } else { - echo("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."); + echo('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.'); exit; } // search the apps folder @@ -178,11 +180,16 @@ class OC { } elseif (file_exists(OC::$SERVERROOT . '/apps')) { OC::$APPSROOTS[] = array('path' => OC::$SERVERROOT . '/apps', 'url' => '/apps', 'writable' => true); } elseif (file_exists(OC::$SERVERROOT . '/../apps')) { - OC::$APPSROOTS[] = array('path' => rtrim(dirname(OC::$SERVERROOT), '/') . '/apps', 'url' => '/apps', 'writable' => true); + OC::$APPSROOTS[] = array( + 'path' => rtrim(dirname(OC::$SERVERROOT), '/') . '/apps', + 'url' => '/apps', + 'writable' => true + ); } if (empty(OC::$APPSROOTS)) { - echo("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."); + echo('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.'); exit; } $paths = array(); @@ -202,9 +209,14 @@ 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(OC::$SERVERROOT . "/config/config.php") + and !is_writable(OC::$SERVERROOT . "/config/config.php")) { $tmpl = new OC_Template('', 'error', 'guest'); - $tmpl->assign('errors', array(1 => array('error' => "Can't write into config directory 'config'", 'hint' => "You can usually fix this by giving the webserver user write access to the config directory in owncloud"))); + $tmpl->assign('errors', array(1 => array( + 'error' => "Can't write into config directory 'config'", + 'hint' => 'You can usually fix this by giving the webserver user write access' + .' to the config directory in owncloud' + ))); $tmpl->printPage(); exit(); } @@ -231,6 +243,11 @@ class OC { header("Location: $url"); exit(); } + } else { + // Invalidate HSTS headers + if (OC_Request::serverProtocol() === 'https') { + header('Strict-Transport-Security: max-age=0'); + } } } @@ -257,7 +274,9 @@ class OC { if (version_compare($currentVersion, $installedVersion, '>')) { if ($showTemplate && !OC_Config::getValue('maintenance', false)) { OC_Config::setValue('maintenance', true); - OC_Log::write('core', 'starting upgrade from ' . $installedVersion . ' to ' . $currentVersion, OC_Log::DEBUG); + OC_Log::write('core', + 'starting upgrade from ' . $installedVersion . ' to ' . $currentVersion, + OC_Log::DEBUG); OC_Util::addscript('update'); $tmpl = new OC_Template('', 'update', 'guest'); $tmpl->assign('version', OC_Util::getVersionString()); @@ -278,6 +297,7 @@ class OC { OC_Util::addScript("jquery-showpassword"); OC_Util::addScript("jquery.infieldlabel"); OC_Util::addScript("jquery-tipsy"); + OC_Util::addScript("compatibility"); OC_Util::addScript("oc-dialogs"); OC_Util::addScript("js"); OC_Util::addScript("eventsource"); @@ -300,19 +320,33 @@ class OC { // set the session name to the instance id - which is unique session_name(OC_Util::getInstanceId()); - // (re)-initialize session - session_start(); + // if session cant be started break with http 500 error + if (session_start() === false){ + 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'; + + $tmpl = new OC_Template('', 'error', 'guest'); + $tmpl->assign('errors', array(1 => array('error' => $error))); + $tmpl->printPage(); + + exit(); + } // regenerate session id periodically to avoid session fixation if (!isset($_SESSION['SID_CREATED'])) { $_SESSION['SID_CREATED'] = time(); - } else if (time() - $_SESSION['SID_CREATED'] > 900) { + } else if (time() - $_SESSION['SID_CREATED'] > 60*60*12) { session_regenerate_id(true); $_SESSION['SID_CREATED'] = time(); } // session timeout - if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > 3600)) { + if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > 60*60*24)) { if (isset($_COOKIE[session_name()])) { setcookie(session_name(), '', time() - 42000, '/'); } @@ -346,7 +380,7 @@ class OC { public static function init() { // register autoloader spl_autoload_register(array('OC', 'autoload')); - setlocale(LC_ALL, 'en_US.UTF-8'); + OC_Util::issetlocaleworking(); // set some stuff //ob_start(); @@ -387,14 +421,16 @@ class OC { } //set http auth headers for apache+php-cgi work around - if (isset($_SERVER['HTTP_AUTHORIZATION']) && preg_match('/Basic\s+(.*)$/i', $_SERVER['HTTP_AUTHORIZATION'], $matches)) { + if (isset($_SERVER['HTTP_AUTHORIZATION']) + && preg_match('/Basic\s+(.*)$/i', $_SERVER['HTTP_AUTHORIZATION'], $matches)) { list($name, $password) = explode(':', base64_decode($matches[1]), 2); $_SERVER['PHP_AUTH_USER'] = strip_tags($name); $_SERVER['PHP_AUTH_PW'] = strip_tags($password); } //set http auth headers for apache+php-cgi work around if variable gets renamed by apache - if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION']) && preg_match('/Basic\s+(.*)$/i', $_SERVER['REDIRECT_HTTP_AUTHORIZATION'], $matches)) { + if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION']) + && preg_match('/Basic\s+(.*)$/i', $_SERVER['REDIRECT_HTTP_AUTHORIZATION'], $matches)) { list($name, $password) = explode(':', base64_decode($matches[1]), 2); $_SERVER['PHP_AUTH_USER'] = strip_tags($name); $_SERVER['PHP_AUTH_PW'] = strip_tags($password); @@ -402,12 +438,6 @@ class OC { self::initPaths(); - if (!defined('PHPUNIT_RUN')) { - register_shutdown_function(array('OC_Log', 'onShutdown')); - set_error_handler(array('OC_Log', 'onError')); - set_exception_handler(array('OC_Log', 'onException')); - } - // set debug mode if an xdebug session is active if (!defined('DEBUG') || !DEBUG) { if (isset($_COOKIE['XDEBUG_SESSION'])) { @@ -415,6 +445,12 @@ class OC { } } + if (!defined('PHPUNIT_RUN') and !(defined('DEBUG') and DEBUG)) { + register_shutdown_function(array('OC_Log', 'onShutdown')); + set_error_handler(array('OC_Log', 'onError')); + set_exception_handler(array('OC_Log', 'onException')); + } + // register the stream wrappers stream_wrapper_register('fakedir', 'OC\Files\Stream\Dir'); stream_wrapper_register('static', 'OC\Files\Stream\StaticStream'); @@ -441,7 +477,8 @@ class OC { OC_User::useBackend(new OC_User_Database()); OC_Group::useBackend(new OC_Group_Database()); - if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SESSION['user_id']) && $_SERVER['PHP_AUTH_USER'] != $_SESSION['user_id']) { + if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SESSION['user_id']) + && $_SERVER['PHP_AUTH_USER'] != $_SESSION['user_id']) { OC_User::logout(); } @@ -468,7 +505,7 @@ class OC { register_shutdown_function(array('OC_Helper', 'cleanTmp')); //parse the given parameters - self::$REQUESTEDAPP = (isset($_GET['app']) && trim($_GET['app']) != '' && !is_null($_GET['app']) ? str_replace(array('\0', '/', '\\', '..'), '', strip_tags($_GET['app'])) : OC_Config::getValue('defaultapp', 'files')); + self::$REQUESTEDAPP = (isset($_GET['app']) && trim($_GET['app']) != '' && !is_null($_GET['app']) ? OC_App::cleanAppId(strip_tags($_GET['app'])) : OC_Config::getValue('defaultapp', 'files')); if (substr_count(self::$REQUESTEDAPP, '?') != 0) { $app = substr(self::$REQUESTEDAPP, 0, strpos(self::$REQUESTEDAPP, '?')); $param = substr($_GET['app'], strpos($_GET['app'], '?') + 1); @@ -498,9 +535,11 @@ 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 failed. Support is probably not installed on your system', OC_Log::ERROR); + 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)) { + if (OC_Config::getValue('installed', false) && !self::checkUpgrade(false)) { if (OC_Appconfig::getValue('core', 'backgroundjobs_mode', 'ajax') == 'ajax') { OC_Util::addScript('backgroundjobs'); } @@ -548,15 +587,19 @@ class OC { require_once 'core/setup.php'; exit(); } + $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(); } if (!self::$CLI) { try { - OC::getRouter()->match(OC_Request::getPathInfo()); + if (!OC_Config::getValue('maintenance', false)) { + OC_App::loadApps(); + } + OC::getRouter()->match(OC_Request::getRawPathInfo()); return; } catch (Symfony\Component\Routing\Exception\ResourceNotFoundException $e) { //header('HTTP/1.0 404 Not Found'); diff --git a/lib/config.php b/lib/config.php index cbea9199320..0bd497b8e50 100644 --- a/lib/config.php +++ b/lib/config.php @@ -166,7 +166,8 @@ class OC_Config{ $tmpl = new OC_Template( '', 'error', 'guest' ); $tmpl->assign('errors', array(1=>array( 'error'=>"Can't write into config directory 'config'", - 'hint'=>"You can usually fix this by giving the webserver user write access to the config directory in owncloud"))); + 'hint'=>'You can usually fix this by giving the webserver user write access' + .' to the config directory in owncloud'))); $tmpl->printPage(); exit; } diff --git a/lib/connector/sabre/directory.php b/lib/connector/sabre/directory.php index b210602bbf4..953692f80a9 100644 --- a/lib/connector/sabre/directory.php +++ b/lib/connector/sabre/directory.php @@ -62,7 +62,36 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa } } else { $newPath = $this->path . '/' . $name; - \OC\Files\Filesystem::file_put_contents($newPath, $data); + + // mark file as partial while uploading (ignored by the scanner) + $partpath = $newPath . '.part'; + + \OC\Files\Filesystem::file_put_contents($partpath, $data); + + //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); + } + } + } + + // rename to correct path + \OC\Files\Filesystem::rename($partpath, $newPath); + + // 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'); + } + } + return OC_Connector_Sabre_Node::getETagPropertyForPath($newPath); } @@ -121,7 +150,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa $paths = array(); foreach($folder_content as $info) { $paths[] = $this->path.'/'.$info['name']; - $properties[$this->path.'/'.$info['name']][self::GETETAG_PROPERTYNAME] = $info['etag']; + $properties[$this->path.'/'.$info['name']][self::GETETAG_PROPERTYNAME] = '"' . $info['etag'] . '"'; } if(count($paths)>0) { // @@ -131,7 +160,8 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa $chunks = array_chunk($paths, 200, false); foreach ($chunks as $pack) { $placeholders = join(',', array_fill(0, count($pack), '?')); - $query = OC_DB::prepare( 'SELECT * FROM `*PREFIX*properties` WHERE `userid` = ?' . ' AND `propertypath` IN ('.$placeholders.')' ); + $query = OC_DB::prepare( 'SELECT * FROM `*PREFIX*properties`' + .' WHERE `userid` = ?' . ' AND `propertypath` IN ('.$placeholders.')' ); array_unshift($pack, OC_User::getUser()); // prepend userid $result = $query->execute( $pack ); while($row = $result->fetchRow()) { diff --git a/lib/connector/sabre/file.php b/lib/connector/sabre/file.php index 1c18a391742..91646312e90 100644 --- a/lib/connector/sabre/file.php +++ b/lib/connector/sabre/file.php @@ -45,7 +45,34 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D */ public function put($data) { - \OC\Files\Filesystem::file_put_contents($this->path,$data); + // mark file as partial while uploading (ignored by the scanner) + $partpath = $this->path . '.part'; + + \OC\Files\Filesystem::file_put_contents($partpath, $data); + + //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); + } + } + } + + // rename to correct path + \OC\Files\Filesystem::rename($partpath, $this->path); + + //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)) { + header('X-OC-MTime: accepted'); + } + } return OC_Connector_Sabre_Node::getETagPropertyForPath($this->path); } @@ -57,7 +84,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D */ public function get() { - return \OC\Files\Filesystem::fopen($this->path,'rb'); + return \OC\Files\Filesystem::fopen($this->path, 'rb'); } @@ -86,8 +113,9 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D /** * Returns the ETag for a file * - * 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. + * 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. * * Return null if the ETag can not effectively be determined * diff --git a/lib/connector/sabre/locks.php b/lib/connector/sabre/locks.php index a72d003bc72..e58e584fb41 100644 --- a/lib/connector/sabre/locks.php +++ b/lib/connector/sabre/locks.php @@ -44,7 +44,8 @@ class OC_Connector_Sabre_Locks extends Sabre_DAV_Locks_Backend_Abstract { // NOTE: SQLite requires time() to be inserted directly. That's ugly // but otherwise reading locks from SQLite Databases will return // nothing - $query = 'SELECT * FROM `*PREFIX*locks` WHERE `userid` = ? AND (`created` + `timeout`) > '.time().' AND (( `uri` = ?)'; + $query = 'SELECT * FROM `*PREFIX*locks`' + .' WHERE `userid` = ? AND (`created` + `timeout`) > '.time().' AND (( `uri` = ?)'; $params = array(OC_User::getUser(), $uri); // We need to check locks for every part in the uri. @@ -116,11 +117,33 @@ class OC_Connector_Sabre_Locks extends Sabre_DAV_Locks_Backend_Abstract { } if ($exists) { - $query = OC_DB::prepare( 'UPDATE `*PREFIX*locks` SET `owner` = ?, `timeout` = ?, `scope` = ?, `depth` = ?, `uri` = ?, `created` = ? WHERE `userid` = ? AND `token` = ?' ); - $result = $query->execute( array($lockInfo->owner,$lockInfo->timeout,$lockInfo->scope,$lockInfo->depth,$uri,$lockInfo->created,OC_User::getUser(),$lockInfo->token)); + $query = OC_DB::prepare( 'UPDATE `*PREFIX*locks`' + .' SET `owner` = ?, `timeout` = ?, `scope` = ?, `depth` = ?, `uri` = ?, `created` = ?' + .' WHERE `userid` = ? AND `token` = ?' ); + $result = $query->execute( array( + $lockInfo->owner, + $lockInfo->timeout, + $lockInfo->scope, + $lockInfo->depth, + $uri, + $lockInfo->created, + OC_User::getUser(), + $lockInfo->token) + ); } else { - $query = OC_DB::prepare( 'INSERT INTO `*PREFIX*locks` (`userid`,`owner`,`timeout`,`scope`,`depth`,`uri`,`created`,`token`) VALUES (?,?,?,?,?,?,?,?)' ); - $result = $query->execute( array(OC_User::getUser(),$lockInfo->owner,$lockInfo->timeout,$lockInfo->scope,$lockInfo->depth,$uri,$lockInfo->created,$lockInfo->token)); + $query = OC_DB::prepare( 'INSERT INTO `*PREFIX*locks`' + .' (`userid`,`owner`,`timeout`,`scope`,`depth`,`uri`,`created`,`token`)' + .' VALUES (?,?,?,?,?,?,?,?)' ); + $result = $query->execute( array( + OC_User::getUser(), + $lockInfo->owner, + $lockInfo->timeout, + $lockInfo->scope, + $lockInfo->depth, + $uri, + $lockInfo->created, + $lockInfo->token) + ); } return true; diff --git a/lib/connector/sabre/node.php b/lib/connector/sabre/node.php index 52995630211..360c3066d05 100644 --- a/lib/connector/sabre/node.php +++ b/lib/connector/sabre/node.php @@ -84,12 +84,13 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr $newPath = $parentPath . '/' . $newName; $oldPath = $this->path; - \OC\Files\Filesystem::rename($this->path,$newPath); + \OC\Files\Filesystem::rename($this->path, $newPath); $this->path = $newPath; - $query = OC_DB::prepare( 'UPDATE `*PREFIX*properties` SET `propertypath` = ? WHERE `userid` = ? AND `propertypath` = ?' ); - $query->execute( array( $newPath,OC_User::getUser(), $oldPath )); + $query = OC_DB::prepare( 'UPDATE `*PREFIX*properties` SET `propertypath` = ?' + .' WHERE `userid` = ? AND `propertypath` = ?' ); + $query->execute( array( $newPath, OC_User::getUser(), $oldPath )); } @@ -149,7 +150,8 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr // If it was null, we need to delete the property if (is_null($propertyValue)) { if(array_key_exists( $propertyName, $existing )) { - $query = OC_DB::prepare( 'DELETE FROM `*PREFIX*properties` WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?' ); + $query = OC_DB::prepare( 'DELETE FROM `*PREFIX*properties`' + .' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?' ); $query->execute( array( OC_User::getUser(), $this->path, $propertyName )); } } @@ -160,10 +162,12 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr $this->touch($propertyValue); } else { if(!array_key_exists( $propertyName, $existing )) { - $query = OC_DB::prepare( 'INSERT INTO `*PREFIX*properties` (`userid`,`propertypath`,`propertyname`,`propertyvalue`) VALUES(?,?,?,?)' ); + $query = OC_DB::prepare( 'INSERT INTO `*PREFIX*properties`' + .' (`userid`,`propertypath`,`propertyname`,`propertyvalue`) VALUES(?,?,?,?)' ); $query->execute( array( OC_User::getUser(), $this->path, $propertyName,$propertyValue )); } else { - $query = OC_DB::prepare( 'UPDATE `*PREFIX*properties` SET `propertyvalue` = ? WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?' ); + $query = OC_DB::prepare( 'UPDATE `*PREFIX*properties` SET `propertyvalue` = ?' + .' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?' ); $query->execute( array( $propertyValue,OC_User::getUser(), $this->path, $propertyName )); } } diff --git a/lib/connector/sabre/quotaplugin.php b/lib/connector/sabre/quotaplugin.php index ce9a968eb3c..c80a33d04b1 100644 --- a/lib/connector/sabre/quotaplugin.php +++ b/lib/connector/sabre/quotaplugin.php @@ -50,7 +50,8 @@ class OC_Connector_Sabre_QuotaPlugin extends Sabre_DAV_ServerPlugin { $uri='/'.$uri; } list($parentUri, $newName) = Sabre_DAV_URLUtil::splitPath($uri); - if ($length > \OC\Files\Filesystem::free_space($parentUri)) { + $freeSpace = \OC\Files\Filesystem::free_space($parentUri); + if ($freeSpace !== \OC\Files\FREE_SPACE_UNKNOWN && $length > $freeSpace) { throw new Sabre_DAV_Exception_InsufficientStorage(); } } diff --git a/lib/connector/sabre/request.php b/lib/connector/sabre/request.php index 97a27996bf3..d70c25c4e70 100644 --- a/lib/connector/sabre/request.php +++ b/lib/connector/sabre/request.php @@ -40,7 +40,7 @@ class OC_Connector_Sabre_Request extends Sabre_HTTP_Request { * @return string */ public function getRawServerValue($field) { - if($field == 'REQUEST_URI'){ + if($field == 'REQUEST_URI') { return $this->getUri(); } else{ diff --git a/lib/db.php b/lib/db.php index 51f7c7679d4..347deac8519 100644 --- a/lib/db.php +++ b/lib/db.php @@ -42,6 +42,7 @@ class OC_DB { const BACKEND_MDB2=1; static private $preparedQueries = array(); + static private $cachingEnabled = true; /** * @var MDB2_Driver_Common @@ -178,6 +179,13 @@ class OC_DB { $dsn = 'oci:dbname=//' . $host . '/' . $name; } break; + case 'mssql': + if ($port) { + $dsn='sqlsrv:Server='.$host.','.$port.';Database='.$name; + } else { + $dsn='sqlsrv:Server='.$host.';Database='.$name; + } + break; default: return false; } @@ -228,11 +236,12 @@ class OC_DB { // Prepare options array $options = array( - 'portability' => MDB2_PORTABILITY_ALL - MDB2_PORTABILITY_FIX_CASE, - 'log_line_break' => '<br>', - 'idxname_format' => '%s', - 'debug' => true, - 'quote_identifier' => true ); + 'portability' => MDB2_PORTABILITY_ALL - MDB2_PORTABILITY_FIX_CASE, + 'log_line_break' => '<br>', + 'idxname_format' => '%s', + 'debug' => true, + 'quote_identifier' => true + ); // Add the dsn according to the database type switch($type) { @@ -277,6 +286,15 @@ class OC_DB { $dsn['database'] = $user; } break; + case 'mssql': + $dsn = array( + 'phptype' => 'sqlsrv', + 'username' => $user, + 'password' => $pass, + 'hostspec' => $host, + 'database' => $name + ); + break; default: return false; } @@ -339,7 +357,7 @@ class OC_DB { } } } else { - if (isset(self::$preparedQueries[$query])) { + if (isset(self::$preparedQueries[$query]) and self::$cachingEnabled) { return self::$preparedQueries[$query]; } } @@ -365,8 +383,11 @@ class OC_DB { } $result=new PDOStatementWrapper($result); } - if (is_null($limit) || $limit == -1) { - self::$preparedQueries[$rawQuery] = $result; + if ((is_null($limit) || $limit == -1) and self::$cachingEnabled ) { + $type = OC_Config::getValue( "dbtype", "sqlite" ); + if( $type != 'sqlite' && $type != 'sqlite3' ) { + self::$preparedQueries[$rawQuery] = $result; + } } return $result; } @@ -388,6 +409,13 @@ class OC_DB { $query = self::prepare('SELECT lastval() AS id'); $row = $query->execute()->fetchRow(); return $row['id']; + } + if( $type == 'mssql' ) { + if($table !== null) { + $prefix = OC_Config::getValue( "dbtableprefix", "oc_" ); + $table = str_replace( '*PREFIX*', $prefix, $table ); + } + return self::$connection->lastInsertId($table); }else{ if($table !== null) { $prefix = OC_Config::getValue( "dbtableprefix", "oc_" ); @@ -474,7 +502,8 @@ class OC_DB { * http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions037.htm */ if( $CONFIG_DBTYPE == 'pgsql' ) { //mysql support it too but sqlite doesn't - $content = str_replace( '<default>0000-00-00 00:00:00</default>', '<default>CURRENT_TIMESTAMP</default>', $content ); + $content = str_replace( '<default>0000-00-00 00:00:00</default>', + '<default>CURRENT_TIMESTAMP</default>', $content ); } file_put_contents( $file2, $content ); @@ -495,11 +524,15 @@ class OC_DB { $definition['name']=OC_Config::getValue( "dbuser", $oldname ); } + // we should never drop a database + $definition['overwrite'] = false; + $ret=self::$schema->createDatabase( $definition ); // Die in case something went wrong if( $ret instanceof MDB2_Error ) { - OC_Template::printErrorPage( self::$MDB2->getDebugOutput().' '.$ret->getMessage() . ': ' . $ret->getUserInfo() ); + OC_Template::printErrorPage( self::$MDB2->getDebugOutput().' '.$ret->getMessage() . ': ' + . $ret->getUserInfo() ); } return true; @@ -541,7 +574,8 @@ class OC_DB { * http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions037.htm */ if( $CONFIG_DBTYPE == 'pgsql' ) { //mysql support it too but sqlite doesn't - $content = str_replace( '<default>0000-00-00 00:00:00</default>', '<default>CURRENT_TIMESTAMP</default>', $content ); + $content = str_replace( '<default>0000-00-00 00:00:00</default>', + '<default>CURRENT_TIMESTAMP</default>', $content ); } file_put_contents( $file2, $content ); $op = self::$schema->updateDatabase($file2, $previousSchema, array(), false); @@ -624,7 +658,7 @@ class OC_DB { } else { return true; } - } elseif( $type == 'pgsql' || $type == 'oci' || $type == 'mysql') { + } elseif( $type == 'pgsql' || $type == 'oci' || $type == 'mysql' || $type == 'mssql') { $query = 'INSERT INTO `' .$table . '` (' . implode(',', array_keys($input)) . ') SELECT \'' . implode('\',\'', array_values($input)) . '\' FROM ' . $table . ' WHERE '; @@ -679,11 +713,20 @@ class OC_DB { $query = str_ireplace( 'UNIX_TIMESTAMP()', 'strftime(\'%s\',\'now\')', $query ); }elseif( $type == 'pgsql' ) { $query = str_replace( '`', '"', $query ); - $query = str_ireplace( 'UNIX_TIMESTAMP()', 'cast(extract(epoch from current_timestamp) as integer)', $query ); + $query = str_ireplace( 'UNIX_TIMESTAMP()', 'cast(extract(epoch from current_timestamp) as integer)', + $query ); }elseif( $type == 'oci' ) { $query = str_replace( '`', '"', $query ); $query = str_ireplace( 'NOW()', 'CURRENT_TIMESTAMP', $query ); - } + }elseif( $type == 'mssql' ) { + $query = preg_replace( "/\`(.*?)`/", "[$1]", $query ); + $query = str_replace( 'NOW()', 'CURRENT_TIMESTAMP', $query ); + $query = str_replace( 'now()', 'CURRENT_TIMESTAMP', $query ); + $query = str_replace( 'LENGTH(', 'LEN(', $query ); + $query = str_replace( 'SUBSTR(', 'SUBSTRING(', $query ); + + $query = self::fixLimitClauseForMSSQL($query); + } // replace table name prefix $query = str_replace( '*PREFIX*', $prefix, $query ); @@ -691,6 +734,60 @@ class OC_DB { return $query; } + private static function fixLimitClauseForMSSQL($query) { + $limitLocation = stripos ($query, "LIMIT"); + + if ( $limitLocation === false ) { + return $query; + } + + // total == 0 means all results - not zero results + // + // First number is either total or offset, locate it by first space + // + $offset = substr ($query, $limitLocation + 5); + $offset = substr ($offset, 0, stripos ($offset, ' ')); + $offset = trim ($offset); + + // check for another parameter + if (stripos ($offset, ',') === false) { + // no more parameters + $offset = 0; + $total = intval ($offset); + } else { + // found another parameter + $offset = intval ($offset); + + $total = substr ($query, $limitLocation + 5); + $total = substr ($total, stripos ($total, ',')); + + $total = substr ($total, 0, stripos ($total, ' ')); + $total = intval ($total); + } + + $query = trim (substr ($query, 0, $limitLocation)); + + if ($offset == 0 && $total !== 0) { + if (strpos($query, "SELECT") === false) { + $query = "TOP {$total} " . $query; + } else { + $query = preg_replace('/SELECT(\s*DISTINCT)?/Dsi', 'SELECT$1 TOP '.$total, $query); + } + } else if ($offset > 0) { + $query = preg_replace('/SELECT(\s*DISTINCT)?/Dsi', 'SELECT$1 TOP(10000000) ', $query); + $query = 'SELECT * + FROM (SELECT sub2.*, ROW_NUMBER() OVER(ORDER BY sub2.line2) AS line3 + FROM (SELECT 1 AS line2, sub1.* FROM (' . $query . ') AS sub1) as sub2) AS sub3'; + + if ($total > 0) { + $query .= ' WHERE line3 BETWEEN ' . ($offset + 1) . ' AND ' . ($offset + $total); + } else { + $query .= ' WHERE line3 > ' . $offset; + } + } + return $query; + } + /** * @brief drop a table * @param string $tableName the table to drop @@ -822,6 +919,16 @@ class OC_DB { } return $msg; } + + /** + * @param bool $enabled + */ + static public function enableCaching($enabled) { + if (!$enabled) { + self::$preparedQueries = array(); + } + self::$cachingEnabled = $enabled; + } } /** @@ -842,19 +949,119 @@ class PDOStatementWrapper{ * make execute return the result instead of a bool */ public function execute($input=array()) { - $this->lastArguments=$input; - if(count($input)>0) { + $this->lastArguments = $input; + if (count($input) > 0) { + + if (!isset($type)) { + $type = OC_Config::getValue( "dbtype", "sqlite" ); + } + + if ($type == 'mssql') { + $input = $this->tryFixSubstringLastArgumentDataForMSSQL($input); + } + $result=$this->statement->execute($input); - }else{ + } else { $result=$this->statement->execute(); } - if($result) { + + if ($result) { return $this; - }else{ + } else { return false; } } + private function tryFixSubstringLastArgumentDataForMSSQL($input) { + $query = $this->statement->queryString; + $pos = stripos ($query, 'SUBSTRING'); + + if ( $pos === false) { + return; + } + + try { + $newQuery = ''; + + $cArg = 0; + + $inSubstring = false; + + // Create new query + for ($i = 0; $i < strlen ($query); $i++) { + if ($inSubstring == false) { + // Defines when we should start inserting values + if (substr ($query, $i, 9) == 'SUBSTRING') { + $inSubstring = true; + } + } else { + // Defines when we should stop inserting values + if (substr ($query, $i, 1) == ')') { + $inSubstring = false; + } + } + + if (substr ($query, $i, 1) == '?') { + // We found a question mark + if ($inSubstring) { + $newQuery .= $input[$cArg]; + + // + // Remove from input array + // + array_splice ($input, $cArg, 1); + } else { + $newQuery .= substr ($query, $i, 1); + $cArg++; + } + } else { + $newQuery .= substr ($query, $i, 1); + } + } + + // The global data we need + $name = OC_Config::getValue( "dbname", "owncloud" ); + $host = OC_Config::getValue( "dbhost", "" ); + $user = OC_Config::getValue( "dbuser", "" ); + $pass = OC_Config::getValue( "dbpassword", "" ); + if (strpos($host,':')) { + list($host, $port) = explode(':', $host, 2); + } else { + $port = false; + } + $opts = array(); + + if ($port) { + $dsn = 'sqlsrv:Server='.$host.','.$port.';Database='.$name; + } else { + $dsn = 'sqlsrv:Server='.$host.';Database='.$name; + } + + $PDO = new PDO($dsn, $user, $pass, $opts); + $PDO->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); + $PDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + $this->statement = $PDO->prepare($newQuery); + + $this->lastArguments = $input; + + return $input; + } catch (PDOException $e){ + $entry = 'PDO DB Error: "'.$e->getMessage().'"<br />'; + $entry .= 'Offending command was: '.$this->statement->queryString .'<br />'; + $entry .= 'Input parameters: ' .print_r($input, true).'<br />'; + $entry .= 'Stack trace: ' .$e->getTraceAsString().'<br />'; + OC_Log::write('core', $entry, OC_Log::FATAL); + OC_User::setUserId(null); + + // send http status 503 + header('HTTP/1.1 503 Service Temporarily Unavailable'); + header('Status: 503 Service Temporarily Unavailable'); + OC_Template::printErrorPage('Failed to connect to database'); + die ($entry); + } + } + /** * provide numRows */ diff --git a/lib/eventsource.php b/lib/eventsource.php index 1b8033943a1..63f19792529 100644 --- a/lib/eventsource.php +++ b/lib/eventsource.php @@ -62,7 +62,8 @@ class OC_EventSource{ $type=null; } if($this->fallback) { - $response='<script type="text/javascript">window.parent.OC.EventSource.fallBackCallBack('.$this->fallBackId.',"'.$type.'",'.json_encode($data).')</script>'.PHP_EOL; + $response='<script type="text/javascript">window.parent.OC.EventSource.fallBackCallBack(' + .$this->fallBackId.',"'.$type.'",'.json_encode($data).')</script>'.PHP_EOL; echo $response; }else{ if($type) { diff --git a/lib/filechunking.php b/lib/filechunking.php index d63a0d72c83..e6d69273a44 100644 --- a/lib/filechunking.php +++ b/lib/filechunking.php @@ -97,7 +97,8 @@ class OC_FileChunking { $absolutePath = \OC\Files\Filesystem::normalizePath(\OC\Files\Filesystem::getView()->getAbsolutePath($path)); $data = ''; // use file_put_contents as method because that best matches what this function does - if (OC_FileProxy::runPreProxies('file_put_contents', $absolutePath, $data) && \OC\Files\Filesystem::isValidPath($path)) { + if (OC_FileProxy::runPreProxies('file_put_contents', $absolutePath, $data) + && \OC\Files\Filesystem::isValidPath($path)) { $path = \OC\Files\Filesystem::getView()->getRelativePath($absolutePath); $exists = \OC\Files\Filesystem::file_exists($path); $run = true; diff --git a/lib/fileproxy/fileoperations.php b/lib/fileproxy/fileoperations.php index 47ccd8f8c26..b2ff2e7e5e9 100644 --- a/lib/fileproxy/fileoperations.php +++ b/lib/fileproxy/fileoperations.php @@ -28,7 +28,7 @@ class OC_FileProxy_FileOperations extends OC_FileProxy{ static $rootView; public function premkdir($path) { - if(!self::$rootView){ + if(!self::$rootView) { self::$rootView = new \OC\Files\View(''); } return !self::$rootView->file_exists($path); diff --git a/lib/fileproxy/quota.php b/lib/fileproxy/quota.php index 7e0f631c8fb..3dac3264fbe 100644 --- a/lib/fileproxy/quota.php +++ b/lib/fileproxy/quota.php @@ -62,21 +62,21 @@ class OC_FileProxy_Quota extends OC_FileProxy{ * @var string $internalPath */ list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($path); - $owner=$storage->getOwner($internalPath); + $owner = $storage->getOwner($internalPath); if (!$owner) { return -1; } - $totalSpace=$this->getQuota($owner); - if($totalSpace==-1) { + $totalSpace = $this->getQuota($owner); + if($totalSpace == -1) { return -1; } $view = new \OC\Files\View("/".$owner."/files"); - $rootInfo=$view->getFileInfo('/'); - $usedSpace=isset($rootInfo['size'])?$rootInfo['size']:0; - return $totalSpace-$usedSpace; + $rootInfo = $view->getFileInfo('/'); + $usedSpace = isset($rootInfo['size'])?$rootInfo['size']:0; + return $totalSpace - $usedSpace; } public function postFree_space($path, $space) { @@ -84,6 +84,9 @@ class OC_FileProxy_Quota extends OC_FileProxy{ if($free==-1) { return $space; } + if ($space < 0){ + return $free; + } return min($free, $space); } @@ -95,7 +98,7 @@ class OC_FileProxy_Quota extends OC_FileProxy{ } public function preCopy($path1, $path2) { - if(!self::$rootView){ + if(!self::$rootView) { self::$rootView = new \OC\Files\View(''); } return (self::$rootView->filesize($path1)<$this->getFreeSpace($path2) or $this->getFreeSpace($path2)==-1); diff --git a/lib/files.php b/lib/files.php index e3245653f99..b594b78c4b7 100644 --- a/lib/files.php +++ b/lib/files.php @@ -200,7 +200,8 @@ class OC_Files { $errors = array( array( 'error' => $l->t('ZIP download is turned off.'), - 'hint' => $l->t('Files need to be downloaded one by one.') . '<br/><a href="javascript:history.back()">' . $l->t('Back to Files') . '</a>', + 'hint' => $l->t('Files need to be downloaded one by one.') + . '<br/><a href="javascript:history.back()">' . $l->t('Back to Files') . '</a>', ) ); $tmpl->assign('errors', $errors); @@ -225,7 +226,9 @@ class OC_Files { $errors = array( array( 'error' => $l->t('Selected files too large to generate zip file.'), - 'hint' => 'Download the files in smaller chunks, seperately or kindly ask your administrator.<br/><a href="javascript:history.back()">' . $l->t('Back to Files') . '</a>', + 'hint' => 'Download the files in smaller chunks, seperately' + .' or kindly ask your administrator.<br/><a href="javascript:history.back()">' + . $l->t('Back to Files') . '</a>', ) ); $tmpl->assign('errors', $errors); @@ -287,7 +290,9 @@ class OC_Files { file_put_contents(OC::$SERVERROOT . '/.htaccess', $htaccess); return OC_Helper::computerFileSize($size); } else { - OC_Log::write('files', 'Can\'t write upload limit to ' . OC::$SERVERROOT . '/.htaccess. Please check the file permissions', OC_Log::WARN); + OC_Log::write('files', + 'Can\'t write upload limit to ' . OC::$SERVERROOT . '/.htaccess. Please check the file permissions', + OC_Log::WARN); } return false; } diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index dcb6e8fd39a..f288919df74 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -48,6 +48,9 @@ class Cache { } else { $this->storageId = $storage; } + if (strlen($this->storageId) > 64) { + $this->storageId = md5($this->storageId); + } $query = \OC_DB::prepare('SELECT `numeric_id` FROM `*PREFIX*storages` WHERE `id` = ?'); $result = $query->execute(array($this->storageId)); @@ -56,7 +59,7 @@ class Cache { } else { $query = \OC_DB::prepare('INSERT INTO `*PREFIX*storages`(`id`) VALUES(?)'); $query->execute(array($this->storageId)); - $this->numericId = \OC_DB::insertid('*PREFIX*filecache'); + $this->numericId = \OC_DB::insertid('*PREFIX*storages'); } } @@ -198,7 +201,8 @@ class Cache { $params[] = $this->numericId; $valuesPlaceholder = array_fill(0, count($queryParts), '?'); - $query = \OC_DB::prepare('INSERT INTO `*PREFIX*filecache`(' . implode(', ', $queryParts) . ') VALUES(' . implode(', ', $valuesPlaceholder) . ')'); + $query = \OC_DB::prepare('INSERT INTO `*PREFIX*filecache`(' . implode(', ', $queryParts) . ')' + . ' VALUES(' . implode(', ', $valuesPlaceholder) . ')'); $query->execute($params); return (int)\OC_DB::insertid('*PREFIX*filecache'); @@ -215,7 +219,8 @@ class Cache { list($queryParts, $params) = $this->buildParts($data); $params[] = $id; - $query = \OC_DB::prepare('UPDATE `*PREFIX*filecache` SET ' . implode(' = ?, ', $queryParts) . '=? WHERE fileid = ?'); + $query = \OC_DB::prepare('UPDATE `*PREFIX*filecache` SET ' . implode(' = ?, ', $queryParts) . '=?' + . ' WHERE fileid = ?'); $query->execute($params); } @@ -308,6 +313,9 @@ class Cache { } $query = \OC_DB::prepare('DELETE FROM `*PREFIX*filecache` WHERE `fileid` = ?'); $query->execute(array($entry['fileid'])); + + $permissionsCache = new Permissions($this->storageId); + $permissionsCache->remove($entry['fileid']); } /** @@ -332,7 +340,8 @@ class Cache { $query->execute(array($targetPath, md5($targetPath), $child['fileid'])); } - $query = \OC_DB::prepare('UPDATE `*PREFIX*filecache` SET `path` = ?, `path_hash` = ?, `parent` =? WHERE `fileid` = ?'); + $query = \OC_DB::prepare('UPDATE `*PREFIX*filecache` SET `path` = ?, `path_hash` = ?, `parent` =?' + . ' WHERE `fileid` = ?'); $query->execute(array($target, md5($target), $newParentId, $sourceId)); } @@ -492,9 +501,10 @@ class Cache { * @return string|bool the path of the folder or false when no folder matched */ public function getIncomplete() { - $query = \OC_DB::prepare('SELECT `path` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `size` = -1 ORDER BY `fileid` DESC LIMIT 1'); - $query->execute(array($this->numericId)); - if ($row = $query->fetchRow()) { + $query = \OC_DB::prepare('SELECT `path` FROM `*PREFIX*filecache`' + . ' WHERE `storage` = ? AND `size` = -1 ORDER BY `fileid` DESC LIMIT 1'); + $result = $query->execute(array($this->numericId)); + if ($row = $result->fetchRow()) { return $row['path']; } else { return false; diff --git a/lib/files/cache/legacy.php b/lib/files/cache/legacy.php index 33d4b8e7c9f..2b8689fcbda 100644 --- a/lib/files/cache/legacy.php +++ b/lib/files/cache/legacy.php @@ -51,6 +51,12 @@ class Legacy { $this->cacheHasItems = false; return false; } + + if ($result === false || property_exists($result, 'error_message_prefix')) { + $this->cacheHasItems = false; + return false; + } + $this->cacheHasItems = (bool)$result->fetchRow(); return $this->cacheHasItems; } diff --git a/lib/files/cache/permissions.php b/lib/files/cache/permissions.php index d0968337f02..a5c9c144054 100644 --- a/lib/files/cache/permissions.php +++ b/lib/files/cache/permissions.php @@ -17,10 +17,10 @@ class Permissions { /** * @param \OC\Files\Storage\Storage|string $storage */ - public function __construct($storage){ - if($storage instanceof \OC\Files\Storage\Storage){ + public function __construct($storage) { + if ($storage instanceof \OC\Files\Storage\Storage) { $this->storageId = $storage->getId(); - }else{ + } else { $this->storageId = $storage; } } @@ -51,9 +51,11 @@ class Permissions { */ public function set($fileId, $user, $permissions) { if (self::get($fileId, $user) !== -1) { - $query = \OC_DB::prepare('UPDATE `*PREFIX*permissions` SET `permissions` = ? WHERE `user` = ? AND `fileid` = ?'); + $query = \OC_DB::prepare('UPDATE `*PREFIX*permissions` SET `permissions` = ?' + . ' WHERE `user` = ? AND `fileid` = ?'); } else { - $query = \OC_DB::prepare('INSERT INTO `*PREFIX*permissions`(`permissions`, `user`, `fileid`) VALUES(?, ?,? )'); + $query = \OC_DB::prepare('INSERT INTO `*PREFIX*permissions`(`permissions`, `user`, `fileid`)' + . ' VALUES(?, ?,? )'); } $query->execute(array($permissions, $user, $fileId)); } @@ -73,7 +75,8 @@ class Permissions { $params[] = $user; $inPart = implode(', ', array_fill(0, count($fileIds), '?')); - $query = \OC_DB::prepare('SELECT `fileid`, `permissions` FROM `*PREFIX*permissions` WHERE `fileid` IN (' . $inPart . ') AND `user` = ?'); + $query = \OC_DB::prepare('SELECT `fileid`, `permissions` FROM `*PREFIX*permissions`' + . ' WHERE `fileid` IN (' . $inPart . ') AND `user` = ?'); $result = $query->execute($params); $filePermissions = array(); while ($row = $result->fetchRow()) { @@ -88,14 +91,19 @@ class Permissions { * @param int $fileId * @param string $user */ - public function remove($fileId, $user) { - $query = \OC_DB::prepare('DELETE FROM `*PREFIX*permissions` WHERE `fileid` = ? AND `user` = ?'); - $query->execute(array($fileId, $user)); + public function remove($fileId, $user = null) { + if (is_null($user)) { + $query = \OC_DB::prepare('DELETE FROM `*PREFIX*permissions` WHERE `fileid` = ?'); + $query->execute(array($fileId)); + } else { + $query = \OC_DB::prepare('DELETE FROM `*PREFIX*permissions` WHERE `fileid` = ? AND `user` = ?'); + $query->execute(array($fileId, $user)); + } } public function removeMultiple($fileIds, $user) { $query = \OC_DB::prepare('DELETE FROM `*PREFIX*permissions` WHERE `fileid` = ? AND `user` = ?'); - foreach($fileIds as $fileId){ + foreach ($fileIds as $fileId) { $query->execute(array($fileId, $user)); } } diff --git a/lib/files/cache/scanner.php b/lib/files/cache/scanner.php index 8d504af6163..88f208547f6 100644 --- a/lib/files/cache/scanner.php +++ b/lib/files/cache/scanner.php @@ -58,9 +58,10 @@ class Scanner { * scan a single file and store it in the cache * * @param string $file + * @param bool $checkExisting check existing folder sizes in the cache instead of always using -1 for folder size * @return array with metadata of the scanned file */ - public function scanFile($file) { + public function scanFile($file, $checkExisting = false) { \OC_Hook::emit('\OC\Files\Cache\Scanner', 'scan_file', array('path' => $file, 'storage' => $this->storageId)); $data = $this->getData($file); if ($data) { @@ -73,7 +74,15 @@ class Scanner { $this->scanFile($parent); } } - $id = $this->cache->put($file, $data); + if ($checkExisting and $cacheData = $this->cache->get($file)) { + if ($data['size'] === -1) { + $data['size'] = $cacheData['size']; + } + if ($data['mtime'] === $cacheData['mtime']) { + $data['etag'] = $cacheData['etag']; + } + } + $this->cache->put($file, $data); } return $data; } @@ -97,22 +106,20 @@ class Scanner { if ($this->storage->is_dir($path) && ($dh = $this->storage->opendir($path))) { \OC_DB::beginTransaction(); while ($file = readdir($dh)) { - if ($file !== '.' and $file !== '..') { + if (!$this->isIgnoredFile($file)) { $child = ($path) ? $path . '/' . $file : $file; - $data = $this->scanFile($child); + $data = $this->scanFile($child, $recursive === self::SCAN_SHALLOW); if ($data) { - if ($data['mimetype'] === 'httpd/unix-directory') { + if ($data['size'] === -1) { if ($recursive === self::SCAN_RECURSIVE) { $childQueue[] = $child; $data['size'] = 0; } else { - $data['size'] = -1; + $size = -1; } - } else { } - if ($data['size'] === -1) { - $size = -1; - } elseif ($size !== -1) { + + if ($size !== -1) { $size += $data['size']; } } @@ -135,10 +142,26 @@ class Scanner { } /** + * @brief check if the file should be ignored when scanning + * NOTE: files with a '.part' extension are ignored as well! + * prevents unfinished put requests to be scanned + * @param String $file + * @return boolean + */ + private function isIgnoredFile($file) { + if ($file === '.' || $file === '..' + || pathinfo($file, PATHINFO_EXTENSION) === 'part' + ) { + return true; + } + return false; + } + + /** * walk over any folders that are not fully scanned yet and scan them */ public function backgroundScan() { - while ($path = $this->cache->getIncomplete()) { + while (($path = $this->cache->getIncomplete()) !== false) { $this->scan($path); $this->cache->correctFolderSize($path); } diff --git a/lib/files/cache/upgrade.php b/lib/files/cache/upgrade.php index eb8c7297c3e..1fe4c584686 100644 --- a/lib/files/cache/upgrade.php +++ b/lib/files/cache/upgrade.php @@ -69,7 +69,8 @@ class Upgrade { ( `fileid`, `storage`, `path`, `path_hash`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted` ) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'); - $insertQuery->execute(array($data['id'], $data['storage'], $data['path'], $data['path_hash'], $data['parent'], $data['name'], + $insertQuery->execute(array($data['id'], $data['storage'], + $data['path'], $data['path_hash'], $data['parent'], $data['name'], $data['mimetype'], $data['mimepart'], $data['size'], $data['mtime'], $data['encrypted'])); } } diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php index 71bf3d8708d..0bbd7550d74 100644 --- a/lib/files/filesystem.php +++ b/lib/files/filesystem.php @@ -29,6 +29,8 @@ namespace OC\Files; +const FREE_SPACE_UNKNOWN = -2; + class Filesystem { public static $loaded = false; /** @@ -135,7 +137,9 @@ class Filesystem { /** * get the mountpoint of the storage object for a path - ( note: because a storage is not always mounted inside the fakeroot, the returned mountpoint is relative to the absolute root of the filesystem and doesn't take the chroot into account + * ( note: because a storage is not always mounted inside the fakeroot, the + * returned mountpoint is relative to the absolute root of the filesystem + * and doesn't take the chroot into account ) * * @param string $path * @return string @@ -190,14 +194,14 @@ class Filesystem { } } - static public function init($root) { + static public function init($user, $root) { if (self::$defaultInstance) { return false; } self::$defaultInstance = new View($root); //load custom mount config - self::initMountPoints(); + self::initMountPoints($user); self::$loaded = true; @@ -213,9 +217,18 @@ class Filesystem { if ($user == '') { $user = \OC_User::getUser(); } + $parser = new \OC\ArrayParser(); + + $root = \OC_User::getHome($user); + self::mount('\OC\Files\Storage\Local', array('datadir' => $root), $user); + // Load system mount points - if (is_file(\OC::$SERVERROOT . '/config/mount.php')) { - $mountConfig = include 'config/mount.php'; + if (is_file(\OC::$SERVERROOT . '/config/mount.php') or is_file(\OC::$SERVERROOT . '/config/mount.json')) { + if (is_file(\OC::$SERVERROOT . '/config/mount.json')) { + $mountConfig = json_decode(file_get_contents(\OC::$SERVERROOT . '/config/mount.json'), true); + } elseif (is_file(\OC::$SERVERROOT . '/config/mount.php')) { + $mountConfig = $parser->parsePHP(file_get_contents(\OC::$SERVERROOT . '/config/mount.php')); + } if (isset($mountConfig['global'])) { foreach ($mountConfig['global'] as $mountPoint => $options) { self::mount($options['class'], $options['options'], $mountPoint); @@ -249,10 +262,12 @@ class Filesystem { } } // Load personal mount points - $root = \OC_User::getHome($user); - self::mount('\OC\Files\Storage\Local', array('datadir' => $root), $user); - if (is_file($root . '/mount.php')) { - $mountConfig = include $root . '/mount.php'; + if (is_file($root . '/mount.php') or is_file($root . '/mount.json')) { + if (is_file($root . '/mount.json')) { + $mountConfig = json_decode(file_get_contents($root . '/mount.json'), true); + } elseif (is_file($root . '/mount.php')) { + $mountConfig = $parser->parsePHP(file_get_contents($root . '/mount.php')); + } if (isset($mountConfig['user'][$user])) { foreach ($mountConfig['user'][$user] as $mountPoint => $options) { self::mount($options['class'], $options['options'], $mountPoint); @@ -318,7 +333,8 @@ class Filesystem { /** * return the path to a local version of the file - * we need this because we can't know if a file is stored local or not from outside the filestorage and for some purposes a local file is needed + * we need this because we can't know if a file is stored local or not from + * outside the filestorage and for some purposes a local file is needed * * @param string $path * @return string @@ -374,21 +390,29 @@ class Filesystem { * @param array $data from hook */ static public function isBlacklisted($data) { - $blacklist = \OC_Config::getValue('blacklisted_files', array('.htaccess')); if (isset($data['path'])) { $path = $data['path']; } else if (isset($data['newpath'])) { $path = $data['newpath']; } if (isset($path)) { - $filename = strtolower(basename($path)); - if (in_array($filename, $blacklist)) { + if (self::isFileBlacklisted($path)) { $data['run'] = false; } } } /** + * @param string $filename + * @return bool + */ + static public function isFileBlacklisted($filename) { + $blacklist = \OC_Config::getValue('blacklisted_files', array('.htaccess')); + $filename = strtolower(basename($filename)); + return (in_array($filename, $blacklist)); + } + + /** * following functions are equivalent to their php builtin equivalents for arguments/return values. */ static public function mkdir($path) { @@ -610,11 +634,11 @@ class Filesystem { } /** - * Get the owner for a file or folder - * - * @param string $path - * @return string - */ + * Get the owner for a file or folder + * + * @param string $path + * @return string + */ public static function getOwner($path) { return self::$defaultInstance->getOwner($path); } diff --git a/lib/files/mapper.php b/lib/files/mapper.php new file mode 100644 index 00000000000..520fadbd8c6 --- /dev/null +++ b/lib/files/mapper.php @@ -0,0 +1,230 @@ +<?php + +namespace OC\Files; + +/** + * class Mapper is responsible to translate logical paths to physical paths and reverse + */ +class Mapper +{ + private $unchangedPhysicalRoot; + + public function __construct($rootDir) { + $this->unchangedPhysicalRoot = $rootDir; + } + + /** + * @param string $logicPath + * @param bool $create indicates if the generated physical name shall be stored in the database or not + * @return string the physical path + */ + public function logicToPhysical($logicPath, $create) { + $physicalPath = $this->resolveLogicPath($logicPath); + if ($physicalPath !== null) { + return $physicalPath; + } + + return $this->create($logicPath, $create); + } + + /** + * @param string $physicalPath + * @return string + */ + public function physicalToLogic($physicalPath) { + $logicPath = $this->resolvePhysicalPath($physicalPath); + if ($logicPath !== null) { + return $logicPath; + } + + $this->insert($physicalPath, $physicalPath); + return $physicalPath; + } + + /** + * @param string $path + * @param bool $isLogicPath indicates if $path is logical or physical + * @param $recursive + * @return void + */ + public function removePath($path, $isLogicPath, $recursive) { + if ($recursive) { + $path=$path.'%'; + } + + if ($isLogicPath) { + $query = \OC_DB::prepare('DELETE FROM `*PREFIX*file_map` WHERE `logic_path` LIKE ?'); + $query->execute(array($path)); + } else { + $query = \OC_DB::prepare('DELETE FROM `*PREFIX*file_map` WHERE `physic_path` LIKE ?'); + $query->execute(array($path)); + } + } + + /** + * @param $path1 + * @param $path2 + * @throws \Exception + */ + public function copy($path1, $path2) + { + $path1 = $this->stripLast($path1); + $path2 = $this->stripLast($path2); + $physicPath1 = $this->logicToPhysical($path1, true); + $physicPath2 = $this->logicToPhysical($path2, true); + + $query = \OC_DB::prepare('SELECT * FROM `*PREFIX*file_map` WHERE `logic_path` LIKE ?'); + $result = $query->execute(array($path1.'%')); + $updateQuery = \OC_DB::prepare('UPDATE `*PREFIX*file_map`' + .' SET `logic_path` = ?' + .' AND `physic_path` = ?' + .' WHERE `logic_path` = ?'); + while( $row = $result->fetchRow()) { + $currentLogic = $row['logic_path']; + $currentPhysic = $row['physic_path']; + $newLogic = $path2.$this->stripRootFolder($currentLogic, $path1); + $newPhysic = $physicPath2.$this->stripRootFolder($currentPhysic, $physicPath1); + if ($path1 !== $currentLogic) { + try { + $updateQuery->execute(array($newLogic, $newPhysic, $currentLogic)); + } catch (\Exception $e) { + error_log('Mapper::Copy failed '.$currentLogic.' -> '.$newLogic.'\n'.$e); + throw $e; + } + } + } + } + + /** + * @param $path + * @param $root + * @return bool|string + */ + public function stripRootFolder($path, $root) { + if (strpos($path, $root) !== 0) { + // throw exception ??? + return false; + } + if (strlen($path) > strlen($root)) { + return substr($path, strlen($root)); + } + + return ''; + } + + private function stripLast($path) { + if (substr($path, -1) == '/') { + $path = substr_replace($path, '', -1); + } + return $path; + } + + private function resolveLogicPath($logicPath) { + $logicPath = $this->stripLast($logicPath); + $query = \OC_DB::prepare('SELECT * FROM `*PREFIX*file_map` WHERE `logic_path_hash` = ?'); + $result = $query->execute(array(md5($logicPath))); + $result = $result->fetchRow(); + if ($result === false) { + return null; + } + + return $result['physic_path']; + } + + private function resolvePhysicalPath($physicalPath) { + $physicalPath = $this->stripLast($physicalPath); + $query = \OC_DB::prepare('SELECT * FROM `*PREFIX*file_map` WHERE `physic_path_hash` = ?'); + $result = $query->execute(array(md5($physicalPath))); + $result = $result->fetchRow(); + + return $result['logic_path']; + } + + private function create($logicPath, $store) { + $logicPath = $this->stripLast($logicPath); + $index = 0; + + // create the slugified path + $physicalPath = $this->slugifyPath($logicPath); + + // detect duplicates + while ($this->resolvePhysicalPath($physicalPath) !== null) { + $physicalPath = $this->slugifyPath($physicalPath, $index++); + } + + // insert the new path mapping if requested + if ($store) { + $this->insert($logicPath, $physicalPath); + } + + return $physicalPath; + } + + private function insert($logicPath, $physicalPath) { + $query = \OC_DB::prepare('INSERT INTO `*PREFIX*file_map`(`logic_path`, `physic_path`, `logic_path_hash`, `physic_path_hash`) VALUES(?, ?, ?, ?)'); + $query->execute(array($logicPath, $physicalPath, md5($logicPath), md5($physicalPath))); + } + + private function slugifyPath($path, $index=null) { + $path = $this->stripRootFolder($path, $this->unchangedPhysicalRoot); + + $pathElements = explode('/', $path); + $sluggedElements = array(); + + foreach ($pathElements as $pathElement) { + // remove empty elements + if (empty($pathElement)) { + continue; + } + + // TODO: remove file ext before slugify on last element + $sluggedElements[] = self::slugify($pathElement); + } + + // + // TODO: add the index before the file extension + // + if ($index !== null) { + $last= end($sluggedElements); + array_pop($sluggedElements); + array_push($sluggedElements, $last.'-'.$index); + } + + $sluggedPath = $this->unchangedPhysicalRoot.implode(DIRECTORY_SEPARATOR, $sluggedElements); + return $this->stripLast($sluggedPath); + } + + /** + * Modifies a string to remove all non ASCII characters and spaces. + * + * @param string $text + * @return string + */ + private function slugify($text) + { + // replace non letter or digits by - + $text = preg_replace('~[^\\pL\d]+~u', '-', $text); + + // trim + $text = trim($text, '-'); + + // transliterate + if (function_exists('iconv')) { + $text = iconv('utf-8', 'us-ascii//TRANSLIT', $text); + } + + // lowercase + $text = strtolower($text); + + // remove unwanted characters + $text = preg_replace('~[^-\w]+~', '', $text); + + if (empty($text)) + { + // TODO: we better generate a guid in this case + return 'n-a'; + } + + return $text; + } +} diff --git a/lib/files/mount.php b/lib/files/mount.php index 74ee483b1be..6e99d8eabb4 100644 --- a/lib/files/mount.php +++ b/lib/files/mount.php @@ -93,6 +93,9 @@ class Mount { $this->storage = $this->createStorage(); } $this->storageId = $this->storage->getId(); + if (strlen($this->storageId) > 64) { + $this->storageId = md5($this->storageId); + } } return $this->storageId; } @@ -177,6 +180,9 @@ class Mount { * @return \OC\Files\Storage\Storage[] */ public static function findById($id) { + if (strlen($id) > 64) { + $id = md5($id); + } $result = array(); foreach (self::$mounts as $mount) { if ($mount->getStorageId() === $id) { diff --git a/lib/files/storage/common.php b/lib/files/storage/common.php index 591803f0440..8aa227ec0b7 100644 --- a/lib/files/storage/common.php +++ b/lib/files/storage/common.php @@ -22,83 +22,104 @@ namespace OC\Files\Storage; abstract class Common implements \OC\Files\Storage\Storage { - public function __construct($parameters) {} + public function __construct($parameters) { + } + public function is_dir($path) { - return $this->filetype($path)=='dir'; + return $this->filetype($path) == 'dir'; } + public function is_file($path) { - return $this->filetype($path)=='file'; + return $this->filetype($path) == 'file'; } + public function filesize($path) { - if($this->is_dir($path)) { - return 0;//by definition - }else{ + if ($this->is_dir($path)) { + return 0; //by definition + } else { $stat = $this->stat($path); - return $stat['size']; + if (isset($stat['size'])) { + return $stat['size']; + } else { + return 0; + } } } + public function isCreatable($path) { if ($this->is_dir($path) && $this->isUpdatable($path)) { return true; } return false; } + public function isDeletable($path) { return $this->isUpdatable($path); } + public function isSharable($path) { return $this->isReadable($path); } - public function getPermissions($path){ + + public function getPermissions($path) { $permissions = 0; - if($this->isCreatable($path)){ + if ($this->isCreatable($path)) { $permissions |= \OCP\PERMISSION_CREATE; } - if($this->isReadable($path)){ + if ($this->isReadable($path)) { $permissions |= \OCP\PERMISSION_READ; } - if($this->isUpdatable($path)){ + if ($this->isUpdatable($path)) { $permissions |= \OCP\PERMISSION_UPDATE; } - if($this->isDeletable($path)){ + if ($this->isDeletable($path)) { $permissions |= \OCP\PERMISSION_DELETE; } - if($this->isSharable($path)){ + if ($this->isSharable($path)) { $permissions |= \OCP\PERMISSION_SHARE; } return $permissions; } + public function filemtime($path) { $stat = $this->stat($path); - return $stat['mtime']; + if (isset($stat['mtime'])) { + return $stat['mtime']; + } else { + return 0; + } } + public function file_get_contents($path) { $handle = $this->fopen($path, "r"); - if(!$handle) { + if (!$handle) { return false; } - $size=$this->filesize($path); - if($size==0) { + $size = $this->filesize($path); + if ($size == 0) { return ''; } return fread($handle, $size); } - public function file_put_contents($path,$data) { + + public function file_put_contents($path, $data) { $handle = $this->fopen($path, "w"); return fwrite($handle, $data); } - public function rename($path1,$path2) { - if($this->copy($path1,$path2)) { + + public function rename($path1, $path2) { + if ($this->copy($path1, $path2)) { return $this->unlink($path1); - }else{ + } else { return false; } } - public function copy($path1,$path2) { - $source=$this->fopen($path1,'r'); - $target=$this->fopen($path2,'w'); - $count=\OC_Helper::streamCopy($source,$target); - return $count>0; + + public function copy($path1, $path2) { + $source = $this->fopen($path1, 'r'); + $target = $this->fopen($path2, 'w'); + list($count, $result) = \OC_Helper::streamCopy($source, $target); + return $result; } /** @@ -110,117 +131,126 @@ abstract class Common implements \OC\Files\Storage\Storage { * @note By default the directory specified by $directory will be * deleted together with its contents. To avoid this set $empty to true */ - public function deleteAll( $directory, $empty = false ) { - $directory = trim($directory,'/'); + public function deleteAll($directory, $empty = false) { + $directory = trim($directory, '/'); - if ( !$this->file_exists( \OCP\USER::getUser() . '/' . $directory ) || !$this->is_dir( \OCP\USER::getUser() . '/' . $directory ) ) { + if (!$this->file_exists(\OCP\USER::getUser() . '/' . $directory) + || !$this->is_dir(\OCP\USER::getUser() . '/' . $directory) + ) { return false; - } elseif( !$this->isReadable( \OCP\USER::getUser() . '/' . $directory ) ) { + } elseif (!$this->isReadable(\OCP\USER::getUser() . '/' . $directory)) { return false; } else { - $directoryHandle = $this->opendir( \OCP\USER::getUser() . '/' . $directory ); - while ( $contents = readdir( $directoryHandle ) ) { - if ( $contents != '.' && $contents != '..') { + $directoryHandle = $this->opendir(\OCP\USER::getUser() . '/' . $directory); + while ($contents = readdir($directoryHandle)) { + if ($contents != '.' && $contents != '..') { $path = $directory . "/" . $contents; - if ( $this->is_dir( $path ) ) { - $this->deleteAll( $path ); + if ($this->is_dir($path)) { + $this->deleteAll($path); } else { - $this->unlink( \OCP\USER::getUser() .'/' . $path ); // TODO: make unlink use same system path as is_dir + $this->unlink(\OCP\USER::getUser() . '/' . $path); // TODO: make unlink use same system path as is_dir } } } //$this->closedir( $directoryHandle ); // TODO: implement closedir in OC_FSV - if ( $empty == false ) { - if ( !$this->rmdir( $directory ) ) { - return false; + if ($empty == false) { + if (!$this->rmdir($directory)) { + return false; } } return true; } } + public function getMimeType($path) { - if(!$this->file_exists($path)) { + if (!$this->file_exists($path)) { return false; } - if($this->is_dir($path)) { + if ($this->is_dir($path)) { return 'httpd/unix-directory'; } - $source=$this->fopen($path,'r'); - if(!$source) { + $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); - }else{ - $extension=''; + $head = fread($source, 8192); //8kb should suffice to determine a mimetype + if ($pos = strrpos($path, '.')) { + $extension = substr($path, $pos); + } else { + $extension = ''; } - $tmpFile=\OC_Helper::tmpFile($extension); - file_put_contents($tmpFile,$head); - $mime=\OC_Helper::getMimeType($tmpFile); + $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) { - $tmpFile=$this->getLocalFile($path); - $hash=hash($type,$tmpFile,$raw); + + public function hash($type, $path, $raw = false) { + $tmpFile = $this->getLocalFile($path); + $hash = hash($type, $tmpFile, $raw); unlink($tmpFile); return $hash; } + public function search($query) { return $this->searchInDir($query); } + public function getLocalFile($path) { return $this->toTmpFile($path); } - private function toTmpFile($path) {//no longer in the storage api, still useful here - $source=$this->fopen($path,'r'); - if(!$source) { + + private function toTmpFile($path) { //no longer in the storage api, still useful here + $source = $this->fopen($path, 'r'); + if (!$source) { return false; } - if($pos=strrpos($path,'.')) { - $extension=substr($path,$pos); - }else{ - $extension=''; + if ($pos = strrpos($path, '.')) { + $extension = substr($path, $pos); + } else { + $extension = ''; } - $tmpFile=\OC_Helper::tmpFile($extension); - $target=fopen($tmpFile,'w'); - \OC_Helper::streamCopy($source,$target); + $tmpFile = \OC_Helper::tmpFile($extension); + $target = fopen($tmpFile, 'w'); + \OC_Helper::streamCopy($source, $target); return $tmpFile; } + public function getLocalFolder($path) { - $baseDir=\OC_Helper::tmpFolder(); - $this->addLocalFolder($path,$baseDir); + $baseDir = \OC_Helper::tmpFolder(); + $this->addLocalFolder($path, $baseDir); return $baseDir; } - private function addLocalFolder($path,$target) { - if($dh=$this->opendir($path)) { - while($file=readdir($dh)) { - if($file!=='.' and $file!=='..') { - if($this->is_dir($path.'/'.$file)) { - mkdir($target.'/'.$file); - $this->addLocalFolder($path.'/'.$file,$target.'/'.$file); - }else{ - $tmp=$this->toTmpFile($path.'/'.$file); - rename($tmp,$target.'/'.$file); + + private function addLocalFolder($path, $target) { + if ($dh = $this->opendir($path)) { + while ($file = readdir($dh)) { + if ($file !== '.' and $file !== '..') { + if ($this->is_dir($path . '/' . $file)) { + mkdir($target . '/' . $file); + $this->addLocalFolder($path . '/' . $file, $target . '/' . $file); + } else { + $tmp = $this->toTmpFile($path . '/' . $file); + rename($tmp, $target . '/' . $file); } } } } } - protected function searchInDir($query,$dir='') { - $files=array(); - $dh=$this->opendir($dir); - if($dh) { - while($item=readdir($dh)) { + protected function searchInDir($query, $dir = '') { + $files = array(); + $dh = $this->opendir($dir); + if ($dh) { + while ($item = readdir($dh)) { if ($item == '.' || $item == '..') continue; - if(strstr(strtolower($item), strtolower($query))!==false) { - $files[]=$dir.'/'.$item; + if (strstr(strtolower($item), strtolower($query)) !== false) { + $files[] = $dir . '/' . $item; } - if($this->is_dir($dir.'/'.$item)) { - $files=array_merge($files,$this->searchInDir($query,$dir.'/'.$item)); + if ($this->is_dir($dir . '/' . $item)) { + $files = array_merge($files, $this->searchInDir($query, $dir . '/' . $item)); } } } @@ -229,32 +259,34 @@ abstract class Common implements \OC\Files\Storage\Storage { /** * check if a file or folder has been updated since $time + * * @param string $path * @param int $time * @return bool */ - public function hasUpdated($path,$time) { - return $this->filemtime($path)>$time; + public function hasUpdated($path, $time) { + return $this->filemtime($path) > $time; } - public function getCache($path=''){ + public function getCache($path = '') { return new \OC\Files\Cache\Cache($this); } - public function getScanner($path=''){ + public function getScanner($path = '') { return new \OC\Files\Cache\Scanner($this); } - public function getPermissionsCache($path=''){ + public function getPermissionsCache($path = '') { return new \OC\Files\Cache\Permissions($this); } - public function getWatcher($path=''){ + public function getWatcher($path = '') { return new \OC\Files\Cache\Watcher($this); } /** * get the owner of a path + * * @param string $path The path to get the owner * @return string uid or false */ @@ -268,13 +300,54 @@ abstract class Common implements \OC\Files\Storage\Storage { * @param string $path * @return string */ - public function getETag($path){ + public function getETag($path) { $ETagFunction = \OC_Connector_Sabre_Node::$ETagFunction; - if($ETagFunction) { + if ($ETagFunction) { $hash = call_user_func($ETagFunction, $path); return $hash; - }else{ + } else { return uniqid(); } } + + /** + * clean a path, i.e. remove all redundant '.' and '..' + * making sure that it can't point to higher than '/' + * + * @param $path The path to clean + * @return string cleaned path + */ + public function cleanPath($path) { + if (strlen($path) == 0 or $path[0] != '/') { + $path = '/' . $path; + } + + $output = array(); + foreach (explode('/', $path) as $chunk) { + if ($chunk == '..') { + array_pop($output); + } else if ($chunk == '.') { + } else { + $output[] = $chunk; + } + } + return implode('/', $output); + } + + public function test() { + if ($this->stat('')) { + return true; + } + return false; + } + + /** + * get the free space in the storage + * + * @param $path + * return int + */ + public function free_space($path) { + return \OC\Files\FREE_SPACE_UNKNOWN; + } } diff --git a/lib/files/storage/local.php b/lib/files/storage/local.php index a5db4ba9194..da6597c8057 100644 --- a/lib/files/storage/local.php +++ b/lib/files/storage/local.php @@ -8,6 +8,12 @@ namespace OC\Files\Storage; +if (\OC_Util::runningOnWindows()) { + class Local extends MappedLocal { + + } +} else { + /** * for local filestore, we only have to map the paths */ @@ -19,6 +25,8 @@ class Local extends \OC\Files\Storage\Common{ $this->datadir.='/'; } } + public function __destruct() { + } public function getId(){ return 'local::'.$this->datadir; } @@ -32,7 +40,7 @@ class Local extends \OC\Files\Storage\Common{ return opendir($this->datadir.$path); } public function is_dir($path) { - if(substr($path,-1)=='/') { + if(substr($path, -1)=='/') { $path=substr($path, 0, -1); } return is_dir($this->datadir.$path); @@ -109,11 +117,11 @@ class Local extends \OC\Files\Storage\Common{ } public function rename($path1, $path2) { if (!$this->isUpdatable($path1)) { - \OC_Log::write('core','unable to rename, file is not writable : '.$path1,\OC_Log::ERROR); + \OC_Log::write('core', 'unable to rename, file is not writable : '.$path1, \OC_Log::ERROR); return false; } if(! $this->file_exists($path1)) { - \OC_Log::write('core','unable to rename, file does not exists : '.$path1,\OC_Log::ERROR); + \OC_Log::write('core', 'unable to rename, file does not exists : '.$path1, \OC_Log::ERROR); return false; } @@ -197,7 +205,9 @@ class Local extends \OC\Files\Storage\Common{ return (float)exec('stat -c %s ' . escapeshellarg($fullPath)); } } else { - \OC_Log::write('core', 'Unable to determine file size of "'.$fullPath.'". Unknown OS: '.$name, \OC_Log::ERROR); + \OC_Log::write('core', + 'Unable to determine file size of "'.$fullPath.'". Unknown OS: '.$name, + \OC_Log::ERROR); } return 0; @@ -245,3 +255,4 @@ class Local extends \OC\Files\Storage\Common{ return $this->filemtime($path)>$time; } } +} diff --git a/lib/files/storage/mappedlocal.php b/lib/files/storage/mappedlocal.php new file mode 100644 index 00000000000..434c10bcbf7 --- /dev/null +++ b/lib/files/storage/mappedlocal.php @@ -0,0 +1,340 @@ +<?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; + +/** + * for local filestore, we only have to map the paths + */ +class MappedLocal extends \OC\Files\Storage\Common{ + protected $datadir; + private $mapper; + + public function __construct($arguments) { + $this->datadir=$arguments['datadir']; + if(substr($this->datadir, -1)!=='/') { + $this->datadir.='/'; + } + + $this->mapper= new \OC\Files\Mapper($this->datadir); + } + public function __destruct() { + if (defined('PHPUNIT_RUN')) { + $this->mapper->removePath($this->datadir, true, true); + } + } + public function getId(){ + return 'local::'.$this->datadir; + } + public function mkdir($path) { + return @mkdir($this->buildPath($path)); + } + public function rmdir($path) { + if ($result = @rmdir($this->buildPath($path))) { + $this->cleanMapper($path); + } + return $result; + } + public function opendir($path) { + $files = array('.', '..'); + $physicalPath= $this->buildPath($path); + + $logicalPath = $this->mapper->physicalToLogic($physicalPath); + $dh = opendir($physicalPath); + while ($file = readdir($dh)) { + if ($file === '.' or $file === '..') { + continue; + } + + $logicalFilePath = $this->mapper->physicalToLogic($physicalPath.DIRECTORY_SEPARATOR.$file); + + $file= $this->mapper->stripRootFolder($logicalFilePath, $logicalPath); + $file = $this->stripLeading($file); + $files[]= $file; + } + + \OC\Files\Stream\Dir::register('local-win32'.$path, $files); + return opendir('fakedir://local-win32'.$path); + } + public function is_dir($path) { + if(substr($path, -1)=='/') { + $path=substr($path, 0, -1); + } + return is_dir($this->buildPath($path)); + } + public function is_file($path) { + return is_file($this->buildPath($path)); + } + public function stat($path) { + $fullPath = $this->buildPath($path); + $statResult = stat($fullPath); + + if ($statResult['size'] < 0) { + $size = self::getFileSizeFromOS($fullPath); + $statResult['size'] = $size; + $statResult[7] = $size; + } + return $statResult; + } + public function filetype($path) { + $filetype=filetype($this->buildPath($path)); + if($filetype=='link') { + $filetype=filetype(realpath($this->buildPath($path))); + } + return $filetype; + } + public function filesize($path) { + if($this->is_dir($path)) { + return 0; + }else{ + $fullPath = $this->buildPath($path); + $fileSize = filesize($fullPath); + if ($fileSize < 0) { + return self::getFileSizeFromOS($fullPath); + } + + return $fileSize; + } + } + public function isReadable($path) { + return is_readable($this->buildPath($path)); + } + public function isUpdatable($path) { + return is_writable($this->buildPath($path)); + } + public function file_exists($path) { + return file_exists($this->buildPath($path)); + } + public function filemtime($path) { + return filemtime($this->buildPath($path)); + } + public function touch($path, $mtime=null) { + // sets the modification time of the file to the given value. + // If mtime is nil the current time is set. + // note that the access time of the file always changes to the current time. + if(!is_null($mtime)) { + $result=touch( $this->buildPath($path), $mtime ); + }else{ + $result=touch( $this->buildPath($path)); + } + if( $result ) { + clearstatcache( true, $this->buildPath($path) ); + } + + return $result; + } + public function file_get_contents($path) { + return file_get_contents($this->buildPath($path)); + } + public function file_put_contents($path, $data) {//trigger_error("$path = ".var_export($path, 1)); + return file_put_contents($this->buildPath($path), $data); + } + public function unlink($path) { + return $this->delTree($path); + } + public function rename($path1, $path2) { + if (!$this->isUpdatable($path1)) { + \OC_Log::write('core', 'unable to rename, file is not writable : '.$path1, \OC_Log::ERROR); + return false; + } + if(! $this->file_exists($path1)) { + \OC_Log::write('core', 'unable to rename, file does not exists : '.$path1, \OC_Log::ERROR); + return false; + } + + $physicPath1 = $this->buildPath($path1); + $physicPath2 = $this->buildPath($path2); + if($return=rename($physicPath1, $physicPath2)) { + // mapper needs to create copies or all children + $this->copyMapping($path1, $path2); + $this->cleanMapper($physicPath1, false, true); + } + return $return; + } + public function copy($path1, $path2) { + if($this->is_dir($path2)) { + if(!$this->file_exists($path2)) { + $this->mkdir($path2); + } + $source=substr($path1, strrpos($path1, '/')+1); + $path2.=$source; + } + if($return=copy($this->buildPath($path1), $this->buildPath($path2))) { + // mapper needs to create copies or all children + $this->copyMapping($path1, $path2); + } + return $return; + } + public function fopen($path, $mode) { + if($return=fopen($this->buildPath($path), $mode)) { + switch($mode) { + case 'r': + break; + case 'r+': + case 'w+': + case 'x+': + case 'a+': + break; + case 'w': + case 'x': + case 'a': + break; + } + } + 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) { + $dir=$this->buildPath($dir); + } + if (!file_exists($dir)) { + return true; + } + if (!is_dir($dir) || is_link($dir)) { + if($return=unlink($dir)) { + $this->cleanMapper($dir, false); + return $return; + } + } + foreach (scandir($dir) as $item) { + if ($item == '.' || $item == '..') { + continue; + } + if(is_file($dir.'/'.$item)) { + if(unlink($dir.'/'.$item)) { + $this->cleanMapper($dir.'/'.$item, false); + } + }elseif(is_dir($dir.'/'.$item)) { + if (!$this->delTree($dir. "/" . $item, false)) { + return false; + }; + } + } + if($return=rmdir($dir)) { + $this->cleanMapper($dir, false); + } + return $return; + } + + private static function getFileSizeFromOS($fullPath) { + $name = strtolower(php_uname('s')); + // Windows OS: we use COM to access the filesystem + if (strpos($name, 'win') !== false) { + if (class_exists('COM')) { + $fsobj = new \COM("Scripting.FileSystemObject"); + $f = $fsobj->GetFile($fullPath); + return $f->Size; + } + } else if (strpos($name, 'bsd') !== false) { + if (\OC_Helper::is_function_enabled('exec')) { + return (float)exec('stat -f %z ' . escapeshellarg($fullPath)); + } + } else if (strpos($name, 'linux') !== false) { + if (\OC_Helper::is_function_enabled('exec')) { + return (float)exec('stat -c %s ' . escapeshellarg($fullPath)); + } + } else { + \OC_Log::write('core', + 'Unable to determine file size of "'.$fullPath.'". Unknown OS: '.$name, + \OC_Log::ERROR); + } + + return 0; + } + + public function hash($path, $type, $raw=false) { + return hash_file($type, $this->buildPath($path), $raw); + } + + public function free_space($path) { + return @disk_free_space($this->buildPath($path)); + } + + public function search($query) { + return $this->searchInDir($query); + } + public function getLocalFile($path) { + return $this->buildPath($path); + } + public function getLocalFolder($path) { + return $this->buildPath($path); + } + + protected function searchInDir($query, $dir='') { + $files=array(); + $physicalDir = $this->buildPath($dir); + foreach (scandir($physicalDir) as $item) { + if ($item == '.' || $item == '..') + continue; + $physicalItem = $this->mapper->physicalToLogic($physicalDir.DIRECTORY_SEPARATOR.$item); + $item = substr($physicalItem, strlen($physicalDir)+1); + + if(strstr(strtolower($item), strtolower($query)) !== false) { + $files[]=$dir.'/'.$item; + } + if(is_dir($physicalItem)) { + $files=array_merge($files, $this->searchInDir($query, $dir.'/'.$item)); + } + } + return $files; + } + + /** + * check if a file or folder has been updated since $time + * @param string $path + * @param int $time + * @return bool + */ + public function hasUpdated($path, $time) { + return $this->filemtime($path)>$time; + } + + private function buildPath($path, $create=true) { + $path = $this->stripLeading($path); + $fullPath = $this->datadir.$path; + return $this->mapper->logicToPhysical($fullPath, $create); + } + + private function cleanMapper($path, $isLogicPath=true, $recursive=true) { + $fullPath = $path; + if ($isLogicPath) { + $fullPath = $this->datadir.$path; + } + $this->mapper->removePath($fullPath, $isLogicPath, $recursive); + } + + private function copyMapping($path1, $path2) { + $path1 = $this->stripLeading($path1); + $path2 = $this->stripLeading($path2); + + $fullPath1 = $this->datadir.$path1; + $fullPath2 = $this->datadir.$path2; + + $this->mapper->copy($fullPath1, $fullPath2); + } + + private function stripLeading($path) { + if(strpos($path, '/') === 0) { + $path = substr($path, 1); + } + if ($path === false) { + return ''; + } + + return $path; + } +} diff --git a/lib/files/storage/temporary.php b/lib/files/storage/temporary.php index 542d2cd9f48..d84dbda2e39 100644 --- a/lib/files/storage/temporary.php +++ b/lib/files/storage/temporary.php @@ -21,6 +21,7 @@ class Temporary extends Local{ } public function __destruct() { + parent::__destruct(); $this->cleanUp(); } } diff --git a/lib/files/view.php b/lib/files/view.php index dfcb770328b..3e2cb080e1d 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -92,7 +92,9 @@ class View { /** * get the mountpoint of the storage object for a path - ( note: because a storage is not always mounted inside the fakeroot, the returned mountpoint is relative to the absolute root of the filesystem and doesn't take the chroot into account + * ( note: because a storage is not always mounted inside the fakeroot, the + * returned mountpoint is relative to the absolute root of the filesystem + * and doesn't take the chroot into account ) * * @param string $path * @return string @@ -113,7 +115,8 @@ class View { /** * return the path to a local version of the file - * we need this because we can't know if a file is stored local or not from outside the filestorage and for some purposes a local file is needed + * we need this because we can't know if a file is stored local or not from + * outside the filestorage and for some purposes a local file is needed * * @param string $path * @return string @@ -196,7 +199,7 @@ class View { @ob_end_clean(); $handle = $this->fopen($path, 'rb'); if ($handle) { - $chunkSize = 8192; // 8 MB chunks + $chunkSize = 8192; // 8 kB chunks while (!feof($handle)) { echo fread($handle, $chunkSize); flush(); @@ -252,7 +255,8 @@ class View { public function file_put_contents($path, $data) { if (is_resource($data)) { //not having to deal with streams in file_put_contents makes life easier $absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path)); - if (\OC_FileProxy::runPreProxies('file_put_contents', $absolutePath, $data) && Filesystem::isValidPath($path)) { + if (\OC_FileProxy::runPreProxies('file_put_contents', $absolutePath, $data) + && Filesystem::isValidPath($path)) { $path = $this->getRelativePath($absolutePath); $exists = $this->file_exists($path); $run = true; @@ -281,7 +285,7 @@ class View { } $target = $this->fopen($path, 'w'); if ($target) { - $count = \OC_Helper::streamCopy($data, $target); + list ($count, $result) = \OC_Helper::streamCopy($data, $target); fclose($target); fclose($data); if ($this->fakeRoot == Filesystem::getRoot()) { @@ -299,7 +303,7 @@ class View { ); } \OC_FileProxy::runPostProxies('file_put_contents', $absolutePath, $count); - return $count > 0; + return $result; } else { return false; } @@ -324,7 +328,8 @@ class View { $postFix2 = (substr($path2, -1, 1) === '/') ? '/' : ''; $absolutePath1 = Filesystem::normalizePath($this->getAbsolutePath($path1)); $absolutePath2 = Filesystem::normalizePath($this->getAbsolutePath($path2)); - if (\OC_FileProxy::runPreProxies('rename', $absolutePath1, $absolutePath2) and Filesystem::isValidPath($path2)) { + if (\OC_FileProxy::runPreProxies('rename', $absolutePath1, $absolutePath2) + and Filesystem::isValidPath($path2)) { $path1 = $this->getRelativePath($absolutePath1); $path2 = $this->getRelativePath($absolutePath2); @@ -356,10 +361,9 @@ class View { } else { $source = $this->fopen($path1 . $postFix1, 'r'); $target = $this->fopen($path2 . $postFix2, 'w'); - $count = \OC_Helper::streamCopy($source, $target); + list($count, $result) = \OC_Helper::streamCopy($source, $target); list($storage1, $internalPath1) = Filesystem::resolvePath($absolutePath1 . $postFix1); $storage1->unlink($internalPath1); - $result = $count > 0; } if ($this->fakeRoot == Filesystem::getRoot()) { \OC_Hook::emit( @@ -439,7 +443,7 @@ class View { } else { $source = $this->fopen($path1 . $postFix1, 'r'); $target = $this->fopen($path2 . $postFix2, 'w'); - $result = \OC_Helper::streamCopy($source, $target); + list($count, $result) = \OC_Helper::streamCopy($source, $target); } if ($this->fakeRoot == Filesystem::getRoot()) { \OC_Hook::emit( @@ -509,11 +513,7 @@ class View { if (Filesystem::isValidPath($path)) { $source = $this->fopen($path, 'r'); if ($source) { - $extension = ''; - $extOffset = strpos($path, '.'); - if ($extOffset !== false) { - $extension = substr($path, strrpos($path, '.')); - } + $extension = pathinfo($path, PATHINFO_EXTENSION); $tmpFile = \OC_Helper::tmpFile($extension); file_put_contents($tmpFile, $source); return $tmpFile; @@ -780,7 +780,8 @@ class View { $rootEntry = $subCache->get(''); if ($rootEntry) { $relativePath = trim(substr($mountPoint, $dirLength), '/'); - if ($pos = strpos($relativePath, '/')) { //mountpoint inside subfolder add size to the correct folder + if ($pos = strpos($relativePath, '/')) { + //mountpoint inside subfolder add size to the correct folder $entryName = substr($relativePath, 0, $pos); foreach ($files as &$entry) { if ($entry['name'] === $entryName) { diff --git a/lib/filesystem.php b/lib/filesystem.php index 57cca902303..34f92b357ca 100644 --- a/lib/filesystem.php +++ b/lib/filesystem.php @@ -34,7 +34,9 @@ class OC_Filesystem { /** * get the mountpoint of the storage object for a path - ( note: because a storage is not always mounted inside the fakeroot, the returned mountpoint is relative to the absolute root of the filesystem and doesn't take the chroot into account + * ( note: because a storage is not always mounted inside the fakeroot, the + * returned mountpoint is relative to the absolute root of the filesystem + * and doesn't take the chroot into account ) * * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem * @param string $path @@ -58,8 +60,8 @@ class OC_Filesystem { /** * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem */ - static public function init($root) { - return \OC\Files\Filesystem::init($root); + static public function init($user, $root) { + return \OC\Files\Filesystem::init($user, $root); } /** @@ -115,7 +117,8 @@ class OC_Filesystem { /** * return the path to a local version of the file - * we need this because we can't know if a file is stored local or not from outside the filestorage and for some purposes a local file is needed + * we need this because we can't know if a file is stored local or not from + * outside the filestorage and for some purposes a local file is needed * * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem * @param string $path diff --git a/lib/group.php b/lib/group.php index 5afef769361..88f0a2a032c 100644 --- a/lib/group.php +++ b/lib/group.php @@ -286,33 +286,39 @@ class OC_Group { } return $users; } - - /**
- * @brief get a list of all display names in a group
- * @returns array with display names (value) and user ids(key)
- */
- public static function displayNamesInGroup($gid, $search = '', $limit = -1, $offset = 0) {
- $displayNames=array();
- foreach(self::$_usedBackends as $backend) {
- $displayNames = array_merge($backend->displayNamesInGroup($gid, $search, $limit, $offset), $displayNames);
- }
- return $displayNames;
+ + /** + * @brief get a list of all display names in a group + * @returns array with display names (value) and user ids(key) + */ + public static function displayNamesInGroup($gid, $search = '', $limit = -1, $offset = 0) { + $displayNames=array(); + foreach(self::$_usedBackends as $backend) { + $displayNames = array_merge($backend->displayNamesInGroup($gid, $search, $limit, $offset), $displayNames); + } + return $displayNames; } - - /**
- * @brief get a list of all display names in several groups
- * @param array $gids
- * @param string $search
- * @param int $limit
- * @param int $offset
- * @return array with display names (Key) user ids (value)
- */
- public static function displayNamesInGroups($gids, $search = '', $limit = -1, $offset = 0) {
- $displayNames = array();
- foreach ($gids as $gid) {
- // TODO Need to apply limits to groups as total
- $displayNames = array_merge(array_diff(self::displayNamesInGroup($gid, $search, $limit, $offset), $displayNames), $displayNames);
- }
- return $displayNames;
+ + /** + * @brief get a list of all display names in several groups + * @param array $gids + * @param string $search + * @param int $limit + * @param int $offset + * @return array with display names (Key) user ids (value) + */ + public static function displayNamesInGroups($gids, $search = '', $limit = -1, $offset = 0) { + $displayNames = array(); + foreach ($gids as $gid) { + // TODO Need to apply limits to groups as total + $diff = array_diff( + self::displayNamesInGroup($gid, $search, $limit, $offset), + $displayNames + ); + if ($diff) { + $displayNames = array_merge($diff, $displayNames); + } + } + return $displayNames; } } diff --git a/lib/group/backend.php b/lib/group/backend.php index 4f6570c3be3..e7b7b21d957 100644 --- a/lib/group/backend.php +++ b/lib/group/backend.php @@ -133,23 +133,23 @@ abstract class OC_Group_Backend implements OC_Group_Interface { public function usersInGroup($gid, $search = '', $limit = -1, $offset = 0) { return array(); } - - /**
- * @brief get a list of all display names in a group
- * @param string $gid
- * @param string $search
- * @param int $limit
- * @param int $offset
- * @return array with display names (value) and user ids (key)
- */
- public function DisplayNamesInGroup($gid, $search = '', $limit = -1, $offset = 0) {
- $displayNames = '';
- $users = $this->usersInGroup($gid, $search, $limit, $offset);
- foreach ( $users as $user ) {
- $DisplayNames[$user] = $user;
- }
-
- return $DisplayNames;
+ + /** + * @brief get a list of all display names in a group + * @param string $gid + * @param string $search + * @param int $limit + * @param int $offset + * @return array with display names (value) and user ids (key) + */ + public function DisplayNamesInGroup($gid, $search = '', $limit = -1, $offset = 0) { + $displayNames = ''; + $users = $this->usersInGroup($gid, $search, $limit, $offset); + foreach ( $users as $user ) { + $DisplayNames[$user] = $user; + } + + return $DisplayNames; } } diff --git a/lib/group/database.php b/lib/group/database.php index 1e2328f4c08..40e9b0d4147 100644 --- a/lib/group/database.php +++ b/lib/group/database.php @@ -200,7 +200,9 @@ class OC_Group_Database extends OC_Group_Backend { * @return array with user ids */ public function usersInGroup($gid, $search = '', $limit = null, $offset = null) { - $stmt = OC_DB::prepare('SELECT `uid` FROM `*PREFIX*group_user` WHERE `gid` = ? AND `uid` LIKE ?', $limit, $offset); + $stmt = OC_DB::prepare('SELECT `uid` FROM `*PREFIX*group_user` WHERE `gid` = ? AND `uid` LIKE ?', + $limit, + $offset); $result = $stmt->execute(array($gid, $search.'%')); $users = array(); while ($row = $result->fetchRow()) { @@ -208,25 +210,30 @@ class OC_Group_Database extends OC_Group_Backend { } return $users; } - - /**
- * @brief get a list of all display names in a group
- * @param string $gid
- * @param string $search
- * @param int $limit
- * @param int $offset
- * @return array with display names (value) and user ids (key)
- */
- public function DisplayNamesInGroup($gid, $search = '', $limit = -1, $offset = 0) {
+ + /** + * @brief get a list of all display names in a group + * @param string $gid + * @param string $search + * @param int $limit + * @param int $offset + * @return array with display names (value) and user ids (key) + */ + public function DisplayNamesInGroup($gid, $search = '', $limit = -1, $offset = 0) { $displayNames = ''; - $stmt = OC_DB::prepare('SELECT `*PREFIX*users`.`uid`, `*PREFIX*users`.`displayname` FROM `*PREFIX*users` INNER JOIN `*PREFIX*group_user` ON `*PREFIX*group_user`.`uid` = `*PREFIX*users`.`uid` WHERE `gid` = ? AND `*PREFIX*group_user.uid` LIKE ?', $limit, $offset);
- $result = $stmt->execute(array($gid, $search.'%'));
- $users = array();
+ $stmt = OC_DB::prepare('SELECT `*PREFIX*users`.`uid`, `*PREFIX*users`.`displayname`' + .' FROM `*PREFIX*users`' + .' INNER JOIN `*PREFIX*group_user` ON `*PREFIX*group_user`.`uid` = `*PREFIX*users`.`uid`' + .' WHERE `gid` = ? AND `*PREFIX*group_user`.`uid` LIKE ?', + $limit, + $offset); + $result = $stmt->execute(array($gid, $search.'%')); + $users = array(); while ($row = $result->fetchRow()) { - $displayName = trim($row['displayname'], ' ');
- $displayNames[$row['uid']] = empty($displayName) ? $row['uid'] : $displayName;
- }
- return $displayNames;
+ $displayName = trim($row['displayname'], ' '); + $displayNames[$row['uid']] = empty($displayName) ? $row['uid'] : $displayName; + } + return $displayNames; } } diff --git a/lib/helper.php b/lib/helper.php index a0fbdd10394..41985ca57a7 100644 --- a/lib/helper.php +++ b/lib/helper.php @@ -132,7 +132,8 @@ class OC_Helper { * Returns a absolute url to the given service. */ public static function linkToRemote( $service, $add_slash = true ) { - return self::makeURLAbsolute(self::linkToRemoteBase($service)) . (($add_slash && $service[strlen($service)-1]!='/')?'/':''); + return self::makeURLAbsolute(self::linkToRemoteBase($service)) + . (($add_slash && $service[strlen($service)-1]!='/')?'/':''); } /** @@ -144,7 +145,8 @@ class OC_Helper { * Returns a absolute url to the given service. */ public static function linkToPublic($service, $add_slash = false) { - return self::linkToAbsolute( '', 'public.php') . '?service=' . $service . (($add_slash && $service[strlen($service)-1]!='/')?'/':''); + return self::linkToAbsolute( '', 'public.php') . '?service=' . $service + . (($add_slash && $service[strlen($service)-1]!='/')?'/':''); } /** @@ -379,7 +381,8 @@ class OC_Helper { $mimeType='application/octet-stream'; } - if($mimeType=='application/octet-stream' and function_exists('finfo_open') and function_exists('finfo_file') and $finfo=finfo_open(FILEINFO_MIME)) { + if($mimeType=='application/octet-stream' and function_exists('finfo_open') + and function_exists('finfo_file') and $finfo=finfo_open(FILEINFO_MIME)) { $info = @strtolower(finfo_file($finfo, $path)); if($info) { $mimeType=substr($info, 0, strpos($info, ';')); @@ -436,14 +439,16 @@ class OC_Helper { //FIXME: should also check for value validation (i.e. the email is an email). public static function init_var($s, $d="") { $r = $d; - if(isset($_REQUEST[$s]) && !empty($_REQUEST[$s])) - $r = stripslashes(htmlspecialchars($_REQUEST[$s])); + if(isset($_REQUEST[$s]) && !empty($_REQUEST[$s])) { + $r = OC_Util::sanitizeHTML($_REQUEST[$s]); + } return $r; } /** - * returns "checked"-attribute if request contains selected radio element OR if radio element is the default one -- maybe? + * returns "checked"-attribute if request contains selected radio element + * OR if radio element is the default one -- maybe? * @param string $s Name of radio-button element name * @param string $v Value of current radio-button element * @param string $d Value of default radio-button element @@ -508,11 +513,16 @@ class OC_Helper { if(!$source or !$target) { return false; } - $count=0; + $result = true; + $count = 0; while(!feof($source)) { - $count+=fwrite($target, fread($source, 8192)); + if ( ( $c = fwrite($target, fread($source, 8192)) ) === false) { + $result = false; + } else { + $count += $c; + } } - return $count; + return array($count, $result); } /** @@ -757,9 +767,13 @@ class OC_Helper { $maxUploadFilesize = min($upload_max_filesize, $post_max_size); $freeSpace = \OC\Files\Filesystem::free_space($dir); - $freeSpace = max($freeSpace, 0); + if($freeSpace !== \OC\Files\FREE_SPACE_UNKNOWN){ + $freeSpace = max($freeSpace, 0); - return min($maxUploadFilesize, $freeSpace); + return min($maxUploadFilesize, $freeSpace); + } else { + return $maxUploadFilesize; + } } /** diff --git a/lib/hook.php b/lib/hook.php index e30aefb5e18..8516cf0dcff 100644 --- a/lib/hook.php +++ b/lib/hook.php @@ -20,22 +20,23 @@ class OC_Hook{ * TODO: write example */ static public function connect( $signalclass, $signalname, $slotclass, $slotname ) { - // If we're trying to connect to an emitting class that isn't + // If we're trying to connect to an emitting class that isn't // yet registered, register it if( !array_key_exists( $signalclass, self::$registered )) { self::$registered[$signalclass] = array(); } - // If we're trying to connect to an emitting method that isn't + // If we're trying to connect to an emitting method that isn't // yet registered, register it with the emitting class - if( !array_key_exists( $signalname, self::$registered[$signalclass] )) { + if( !array_key_exists( $signalname, self::$registered[$signalclass] )) { self::$registered[$signalclass][$signalname] = array(); } - + // Connect the hook handler to the requested emitter self::$registered[$signalclass][$signalname][] = array( - "class" => $slotclass, - "name" => $slotname ); - + "class" => $slotclass, + "name" => $slotname + ); + // No chance for failure ;-) return true; } @@ -52,25 +53,27 @@ class OC_Hook{ * TODO: write example */ static public function emit( $signalclass, $signalname, $params = array()) { - + // Return false if no hook handlers are listening to this // emitting class if( !array_key_exists( $signalclass, self::$registered )) { return false; } - + // Return false if no hook handlers are listening to this // emitting method if( !array_key_exists( $signalname, self::$registered[$signalclass] )) { return false; } - + // Call all slots foreach( self::$registered[$signalclass][$signalname] as $i ) { try { call_user_func( array( $i["class"], $i["name"] ), $params ); } catch (Exception $e){ - OC_Log::write('hook', 'error while running hook (' . $i["class"] . '::' . $i["name"] . '): '.$e->getMessage(), OC_Log::ERROR); + OC_Log::write('hook', + 'error while running hook (' . $i["class"] . '::' . $i["name"] . '): '.$e->getMessage(), + OC_Log::ERROR); } } diff --git a/lib/image.php b/lib/image.php index eaa35350bcb..c1b187608a6 100644 --- a/lib/image.php +++ b/lib/image.php @@ -35,7 +35,13 @@ class OC_Image { * @returns string The mime type if the it could be determined, otherwise an empty string. */ static public function getMimeTypeForFile($filepath) { - $imagetype = exif_imagetype($filepath); + // exif_imagetype throws "read error!" if file is less than 12 byte + if (filesize($filepath) > 11) { + $imagetype = exif_imagetype($filepath); + } + else { + $imagetype = false; + } return $imagetype ? image_type_to_mime_type($imagetype) : ''; } @@ -169,7 +175,9 @@ class OC_Image { if (!file_exists(dirname($filepath))) mkdir(dirname($filepath), 0777, true); if(!is_writable(dirname($filepath))) { - OC_Log::write('core', __METHOD__.'(): Directory \''.dirname($filepath).'\' is not writable.', OC_Log::ERROR); + OC_Log::write('core', + __METHOD__.'(): Directory \''.dirname($filepath).'\' is not writable.', + OC_Log::ERROR); return false; } elseif(is_writable(dirname($filepath)) && file_exists($filepath) && !is_writable($filepath)) { OC_Log::write('core', __METHOD__.'(): File \''.$filepath.'\' is not writable.', OC_Log::ERROR); @@ -383,7 +391,8 @@ class OC_Image { * @returns An image resource or false on error */ public function loadFromFile($imagepath=false) { - if(!is_file($imagepath) || !file_exists($imagepath) || !is_readable($imagepath)) { + // exif_imagetype throws "read error!" if file is less than 12 byte + if(!is_file($imagepath) || !file_exists($imagepath) || filesize($imagepath) < 12 || !is_readable($imagepath)) { // Debug output disabled because this method is tried before loadFromBase64? OC_Log::write('core', 'OC_Image->loadFromFile, couldn\'t load: '.$imagepath, OC_Log::DEBUG); return false; @@ -394,35 +403,45 @@ class OC_Image { if (imagetypes() & IMG_GIF) { $this->resource = imagecreatefromgif($imagepath); } else { - OC_Log::write('core', 'OC_Image->loadFromFile, GIF images not supported: '.$imagepath, OC_Log::DEBUG); + OC_Log::write('core', + 'OC_Image->loadFromFile, GIF images not supported: '.$imagepath, + OC_Log::DEBUG); } break; case IMAGETYPE_JPEG: if (imagetypes() & IMG_JPG) { $this->resource = imagecreatefromjpeg($imagepath); } else { - OC_Log::write('core', 'OC_Image->loadFromFile, JPG images not supported: '.$imagepath, OC_Log::DEBUG); + OC_Log::write('core', + 'OC_Image->loadFromFile, JPG images not supported: '.$imagepath, + OC_Log::DEBUG); } break; case IMAGETYPE_PNG: if (imagetypes() & IMG_PNG) { $this->resource = imagecreatefrompng($imagepath); } else { - OC_Log::write('core', 'OC_Image->loadFromFile, PNG images not supported: '.$imagepath, OC_Log::DEBUG); + OC_Log::write('core', + 'OC_Image->loadFromFile, PNG images not supported: '.$imagepath, + OC_Log::DEBUG); } break; case IMAGETYPE_XBM: if (imagetypes() & IMG_XPM) { $this->resource = imagecreatefromxbm($imagepath); } else { - OC_Log::write('core', 'OC_Image->loadFromFile, XBM/XPM images not supported: '.$imagepath, OC_Log::DEBUG); + OC_Log::write('core', + 'OC_Image->loadFromFile, XBM/XPM images not supported: '.$imagepath, + OC_Log::DEBUG); } break; case IMAGETYPE_WBMP: if (imagetypes() & IMG_WBMP) { $this->resource = imagecreatefromwbmp($imagepath); } else { - OC_Log::write('core', 'OC_Image->loadFromFile, WBMP images not supported: '.$imagepath, OC_Log::DEBUG); + OC_Log::write('core', + 'OC_Image->loadFromFile, WBMP images not supported: '.$imagepath, + OC_Log::DEBUG); } break; case IMAGETYPE_BMP: @@ -633,7 +652,9 @@ class OC_Image { $color[1] = $palette[ $color[1] + 1 ]; break; default: - trigger_error('imagecreatefrombmp: ' . $filename . ' has ' . $meta['bits'] . ' bits and this is not supported!', E_USER_WARNING); + trigger_error('imagecreatefrombmp: ' + . $filename . ' has ' . $meta['bits'] . ' bits and this is not supported!', + E_USER_WARNING); return false; } imagesetpixel($im, $x, $y, $color[1]); @@ -688,6 +709,13 @@ class OC_Image { return false; } + // preserve transparency + if($this->imagetype == IMAGETYPE_GIF or $this->imagetype == IMAGETYPE_PNG) { + imagecolortransparent($process, imagecolorallocatealpha($process, 0, 0, 0, 127)); + imagealphablending($process, false); + imagesavealpha($process, true); + } + imagecopyresampled($process, $this->resource, 0, 0, 0, 0, $width, $height, $width_orig, $height_orig); if ($process == false) { OC_Log::write('core', __METHOD__.'(): Error resampling process image '.$width.'x'.$height, OC_Log::ERROR); @@ -737,9 +765,19 @@ class OC_Image { imagedestroy($process); return false; } + + // preserve transparency + if($this->imagetype == IMAGETYPE_GIF or $this->imagetype == IMAGETYPE_PNG) { + imagecolortransparent($process, imagecolorallocatealpha($process, 0, 0, 0, 127)); + imagealphablending($process, false); + imagesavealpha($process, true); + } + imagecopyresampled($process, $this->resource, 0, 0, $x, $y, $targetWidth, $targetHeight, $width, $height); if ($process == false) { - OC_Log::write('core', 'OC_Image->centerCrop. Error resampling process image '.$width.'x'.$height, OC_Log::ERROR); + OC_Log::write('core', + 'OC_Image->centerCrop. Error resampling process image '.$width.'x'.$height, + OC_Log::ERROR); imagedestroy($process); return false; } diff --git a/lib/installer.php b/lib/installer.php index c86f801b5fc..251d115b76c 100644 --- a/lib/installer.php +++ b/lib/installer.php @@ -136,21 +136,29 @@ class OC_Installer{ // check if the app is compatible with this version of ownCloud $version=OC_Util::getVersion(); if(!isset($info['require']) or ($version[0]>$info['require'])) { - OC_Log::write('core', 'App can\'t be installed because it is not compatible with this version of ownCloud', OC_Log::ERROR); + OC_Log::write('core', + 'App can\'t be installed because it is not compatible with this version of ownCloud', + OC_Log::ERROR); OC_Helper::rmdirr($extractDir); return false; } // check if shipped tag is set which is only allowed for apps that are shipped with ownCloud if(isset($info['shipped']) and ($info['shipped']=='true')) { - OC_Log::write('core', 'App can\'t be installed because it contains the <shipped>true</shippe> tag which is not allowed for non shipped apps', OC_Log::ERROR); + OC_Log::write('core', + 'App can\'t be installed because it contains the <shipped>true</shippe>' + .' tag which is not allowed for non shipped apps', + OC_Log::ERROR); OC_Helper::rmdirr($extractDir); return false; } // 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'])) { - OC_Log::write('core', 'App can\'t be installed because the version in info.xml/version is not the same as the version reported from the app store', OC_Log::ERROR); + OC_Log::write('core', + 'App can\'t be installed because the version in info.xml/version is not the same' + .' as the version reported from the app store', + OC_Log::ERROR); OC_Helper::rmdirr($extractDir); return false; } @@ -251,7 +259,8 @@ class OC_Installer{ * -# including appinfo/upgrade.php * -# setting the installed version * - * upgrade.php can determine the current installed version of the app using "OC_Appconfig::getValue($appid, 'installed_version')" + * upgrade.php can determine the current installed version of the app using + * "OC_Appconfig::getValue($appid, 'installed_version')" */ public static function updateApp( $app ) { $ocsid=OC_Appconfig::getValue( $app, 'ocsid'); @@ -270,12 +279,12 @@ class OC_Installer{ public static function isUpdateAvailable( $app ) { $ocsid=OC_Appconfig::getValue( $app, 'ocsid', ''); - if($ocsid<>''){ + if($ocsid<>'') { $ocsdata=OC_OCSClient::getApplication($ocsid); $ocsversion= (string) $ocsdata['version']; $currentversion=OC_App::getAppVersion($app); - if($ocsversion<>$currentversion){ + if($ocsversion<>$currentversion) { return($ocsversion); }else{ @@ -326,22 +335,22 @@ class OC_Installer{ */ public static function removeApp( $name, $options = array()) { - if(isset($options['keeppreferences']) and $options['keeppreferences']==false ){ + if(isset($options['keeppreferences']) and $options['keeppreferences']==false ) { // todo // remove preferences } - if(isset($options['keepappconfig']) and $options['keepappconfig']==false ){ + if(isset($options['keepappconfig']) and $options['keepappconfig']==false ) { // todo // remove app config } - if(isset($options['keeptables']) and $options['keeptables']==false ){ + if(isset($options['keeptables']) and $options['keeptables']==false ) { // todo // remove app database tables } - if(isset($options['keepfiles']) and $options['keepfiles']==false ){ + if(isset($options['keepfiles']) and $options['keepfiles']==false ) { // todo // remove user files } @@ -437,7 +446,9 @@ class OC_Installer{ // check if grep is installed $grep = exec('which grep'); if($grep=='') { - OC_Log::write('core', 'grep not installed. So checking the code of the app "'.$appname.'" was not possible', OC_Log::ERROR); + OC_Log::write('core', + 'grep not installed. So checking the code of the app "'.$appname.'" was not possible', + OC_Log::ERROR); return true; } @@ -447,7 +458,9 @@ class OC_Installer{ $result = exec($cmd); // bad pattern found if($result<>'') { - OC_Log::write('core', 'App "'.$appname.'" is using a not allowed call "'.$bl.'". Installation refused.', OC_Log::ERROR); + OC_Log::write('core', + 'App "'.$appname.'" is using a not allowed call "'.$bl.'". Installation refused.', + OC_Log::ERROR); return false; } } diff --git a/lib/l10n.php b/lib/l10n.php index ee879009265..1e07a9b9557 100644 --- a/lib/l10n.php +++ b/lib/l10n.php @@ -97,7 +97,7 @@ class OC_L10N{ if ($this->app === true) { return; } - $app = $this->app; + $app = OC_App::cleanAppId($this->app); $lang = $this->lang; $this->app = true; // Find the right language @@ -343,7 +343,7 @@ class OC_L10N{ if(is_dir($dir)) { $files=scandir($dir); foreach($files as $file) { - if(substr($file, -4, 4) == '.php') { + if(substr($file, -4, 4) === '.php' && substr($file, 0, 4) !== 'l10n') { $i = substr($file, 0, -4); $available[] = $i; } diff --git a/lib/l10n/bg_BG.php b/lib/l10n/bg_BG.php index 31f37458b81..d32e2aadfc5 100644 --- a/lib/l10n/bg_BG.php +++ b/lib/l10n/bg_BG.php @@ -9,12 +9,30 @@ "Files need to be downloaded one by one." => "Файловете трябва да се изтеглят един по един.", "Back to Files" => "Назад към файловете", "Selected files too large to generate zip file." => "Избраните файлове са прекалено големи за генерирането на ZIP архив.", +"couldn't be determined" => "не може да се определи", "Application is not enabled" => "Приложението не е включено.", "Authentication error" => "Възникна проблем с идентификацията", "Token expired. Please reload page." => "Ключът е изтекъл, моля презаредете страницата", "Files" => "Файлове", "Text" => "Текст", "Images" => "Снимки", +"Set an admin username." => "Въведете потребителско име за администратор.", +"Set an admin password." => "Въведете парола за администратор.", +"Specify a data folder." => "Укажете папка за данни", +"%s enter the database username." => "%s въведете потребителско име за базата с данни.", +"%s enter the database name." => "%s въведете име на базата с данни.", +"%s you may not use dots in the database name" => "%s, не можете да ползвате точки в името на базата от данни", +"PostgreSQL username and/or password not valid" => "Невалидно PostgreSQL потребителско име и/или парола", +"You need to enter either an existing account or the administrator." => "Необходимо е да влезете в всъществуващ акаунт или като администратора", +"Oracle username and/or password not valid" => "Невалидно Oracle потребителско име и/или парола", +"MySQL username and/or password not valid" => "Невалидно MySQL потребителско име и/или парола", +"DB Error: \"%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.", +"MS SQL username and/or password not valid: %s" => "Невалидно MS SQL потребителско име и/или парола: %s", +"Please double check the <a href='%s'>installation guides</a>." => "Моля направете повторна справка с <a href='%s'>ръководството за инсталиране</a>.", "seconds ago" => "преди секунди", "1 minute ago" => "преди 1 минута", "%d minutes ago" => "преди %d минути", diff --git a/lib/l10n/ca.php b/lib/l10n/ca.php index f6401fa39b6..108bb5c09be 100644 --- a/lib/l10n/ca.php +++ b/lib/l10n/ca.php @@ -16,6 +16,27 @@ "Files" => "Fitxers", "Text" => "Text", "Images" => "Imatges", +"Set an admin username." => "Establiu un nom d'usuari per l'administrador.", +"Set an admin password." => "Establiu una contrasenya per l'administrador.", +"Specify a data folder." => "Especifiqueu una carpeta de dades.", +"%s enter the database username." => "%s escriviu el nom d'usuari de la base de dades.", +"%s enter the database name." => "%s escriviu el nom de la base de dades.", +"%s you may not use dots in the database name" => "%s no podeu usar punts en el nom de la base de dades", +"%s set the database host." => "%s establiu l'ordinador central de la base de dades.", +"PostgreSQL username and/or password not valid" => "Nom d'usuari i/o contrasenya PostgreSQL no vàlids", +"You need to enter either an existing account or the administrator." => "Heu d'escriure un compte existent o el d'administrador.", +"Oracle username and/or password not valid" => "Nom d'usuari i/o contrasenya Oracle no vàlids", +"MySQL username and/or password not valid" => "Nom d'usuari i/o contrasenya MySQL no vàlids", +"DB Error: \"%s\"" => "Error DB: \"%s\"", +"Offending command was: \"%s\"" => "L'ordre en conflicte és: \"%s\"", +"MySQL user '%s'@'localhost' exists already." => "L'usuari MySQL '%s'@'localhost' ja existeix.", +"Drop this user from MySQL" => "Elimina aquest usuari de MySQL", +"MySQL user '%s'@'%%' already exists" => "L'usuari MySQL '%s'@'%%' ja existeix", +"Drop this user from MySQL." => "Elimina aquest usuari de MySQL.", +"Offending command was: \"%s\", name: %s, password: %s" => "L'ordre en conflicte és: \"%s\", nom: %s, contrasenya: %s", +"MS SQL username and/or password not valid: %s" => "Nom d'usuari i/o contrasenya MS SQL no vàlids: %s", +"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>.", "seconds ago" => "segons enrere", "1 minute ago" => "fa 1 minut", "%d minutes ago" => "fa %d minuts", diff --git a/lib/l10n/cs_CZ.php b/lib/l10n/cs_CZ.php index 2c823194b96..d9ec3d82cf7 100644 --- a/lib/l10n/cs_CZ.php +++ b/lib/l10n/cs_CZ.php @@ -16,6 +16,27 @@ "Files" => "Soubory", "Text" => "Text", "Images" => "Obrázky", +"Set an admin username." => "Zadejte uživatelské jméno správce.", +"Set an admin password." => "Zadejte heslo správce.", +"Specify a data folder." => "Určete složku dat.", +"%s enter the database username." => "Zadejte uživatelské jméno %s databáze.", +"%s enter the database name." => "Zadejte název databáze pro %s databáze.", +"%s you may not use dots in the database name" => "V názvu databáze %s nesmíte používat tečky.", +"%s set the database host." => "Zadejte název počítače s databází %s.", +"PostgreSQL username and/or password not valid" => "Uživatelské jméno, či heslo PostgreSQL není platné", +"You need to enter either an existing account or the administrator." => "Musíte zadat existující účet, či správce.", +"Oracle username and/or password not valid" => "Uživatelské jméno, či heslo Oracle není platné", +"MySQL username and/or password not valid" => "Uživatelské jméno, či heslo MySQL není platné", +"DB Error: \"%s\"" => "Chyba DB: \"%s\"", +"Offending command was: \"%s\"" => "Podezřelý příkaz byl: \"%s\"", +"MySQL user '%s'@'localhost' exists already." => "Uživatel '%s'@'localhost' již v MySQL existuje.", +"Drop this user from MySQL" => "Zahodit uživatele z MySQL", +"MySQL user '%s'@'%%' already exists" => "Uživatel '%s'@'%%' již v MySQL existuje", +"Drop this user from MySQL." => "Zahodit uživatele z MySQL.", +"Offending command was: \"%s\", name: %s, password: %s" => "Podezřelý příkaz byl: \"%s\", jméno: %s, heslo: %s", +"MS SQL username and/or password not valid: %s" => "Uživatelské jméno, či heslo MSSQL není platné: %s", +"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, protože rozhraní WebDAV je rozbité.", +"Please double check the <a href='%s'>installation guides</a>." => "Zkonzultujte, prosím, <a href='%s'>průvodce instalací</a>.", "seconds ago" => "před vteřinami", "1 minute ago" => "před 1 minutou", "%d minutes ago" => "před %d minutami", diff --git a/lib/l10n/da.php b/lib/l10n/da.php index 8f22be5e823..e61fba30ff3 100644 --- a/lib/l10n/da.php +++ b/lib/l10n/da.php @@ -16,6 +16,26 @@ "Files" => "Filer", "Text" => "SMS", "Images" => "Billeder", +"Set an admin username." => "Angiv et admin brugernavn.", +"Set an admin password." => "Angiv et admin kodeord.", +"Specify a data folder." => "Specificer en data mappe.", +"%s enter the database username." => "%s indtast database brugernavnet.", +"%s enter the database name." => "%s indtast database navnet.", +"%s you may not use dots in the database name" => "%s du må ikke bruge punktummer i databasenavnet.", +"%s set the database host." => "%s sæt database værten.", +"PostgreSQL username and/or password not valid" => "PostgreSQL brugernavn og/eller kodeord er ikke gyldigt.", +"You need to enter either an existing account or the administrator." => "Du bliver nødt til at indtaste en eksisterende bruger eller en administrator.", +"Oracle username and/or password not valid" => "Oracle brugernavn og/eller kodeord er ikke gyldigt.", +"MySQL username and/or password not valid" => "MySQL brugernavn og/eller kodeord er ikke gyldigt.", +"DB Error: \"%s\"" => "Databasefejl: \"%s\"", +"Offending command was: \"%s\"" => "Fejlende kommando var: \"%s\"", +"MySQL user '%s'@'localhost' exists already." => "MySQL brugeren '%s'@'localhost' eksisterer allerede.", +"Drop this user from MySQL" => "Slet denne bruger fra MySQL", +"MySQL user '%s'@'%%' already exists" => "MySQL brugeren '%s'@'%%' eksisterer allerede.", +"Drop this user from MySQL." => "Slet denne bruger fra MySQL", +"Offending command was: \"%s\", name: %s, password: %s" => "Fejlende kommando var: \"%s\", navn: %s, password: %s", +"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>.", "seconds ago" => "sekunder siden", "1 minute ago" => "1 minut siden", "%d minutes ago" => "%d minutter siden", diff --git a/lib/l10n/de.php b/lib/l10n/de.php index c285a07f63a..3c2069d4637 100644 --- a/lib/l10n/de.php +++ b/lib/l10n/de.php @@ -9,13 +9,34 @@ "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.", -"couldn't be determined" => "Konnte nicht festgestellt werden", +"couldn't be determined" => "konnte nicht festgestellt werden", "Application is not enabled" => "Die Anwendung ist nicht aktiviert", "Authentication error" => "Authentifizierungs-Fehler", "Token expired. Please reload page." => "Token abgelaufen. Bitte lade die Seite neu.", "Files" => "Dateien", "Text" => "Text", "Images" => "Bilder", +"Set an admin username." => "Setze Administrator Benutzername.", +"Set an admin password." => "Setze Administrator Passwort", +"Specify a data folder." => "Datei-Verzeichnis angeben.", +"%s enter the database username." => "%s gib den Datenbank-Benutzernamen an.", +"%s enter the database name." => "%s gib den Datenbank-Namen an.", +"%s you may not use dots in the database name" => "%s Der Datenbank-Name darf keine Punkte enthalten", +"%s set the database host." => "%s setze den Datenbank-Host", +"PostgreSQL username and/or password not valid" => "PostgreSQL Benutzername und/oder Passwort ungültig", +"You need to enter either an existing account or the administrator." => "Du musst entweder ein existierendes Benutzerkonto oder das Administratoren-Konto angeben.", +"Oracle username and/or password not valid" => "Oracle Benutzername und/oder Passwort ungültig", +"MySQL username and/or password not valid" => "MySQL Benutzername und/oder Passwort ungültig", +"DB Error: \"%s\"" => "DB Fehler: \"%s\"", +"Offending command was: \"%s\"" => "Fehlerhafter Befehl war: \"%s\"", +"MySQL user '%s'@'localhost' exists already." => "MySQL Benutzer '%s'@'localhost' existiert bereits.", +"Drop this user from MySQL" => "Lösche diesen Benutzer von MySQL", +"MySQL user '%s'@'%%' already exists" => "MySQL Benutzer '%s'@'%%' existiert bereits", +"Drop this user from MySQL." => "Lösche diesen Benutzer aus MySQL.", +"Offending command was: \"%s\", name: %s, password: %s" => "Fehlerhafter Befehl war: \"%s\", Name: %s, Passwort: %s", +"MS SQL username and/or password not valid: %s" => "MS SQL Benutzername und/oder Password ungültig: %s", +"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'>Instalationsanleitungen</a>.", "seconds ago" => "Gerade eben", "1 minute ago" => "Vor einer Minute", "%d minutes ago" => "Vor %d Minuten", diff --git a/lib/l10n/de_DE.php b/lib/l10n/de_DE.php index 625ba2ecf20..bbff4948096 100644 --- a/lib/l10n/de_DE.php +++ b/lib/l10n/de_DE.php @@ -16,6 +16,27 @@ "Files" => "Dateien", "Text" => "Text", "Images" => "Bilder", +"Set an admin username." => "Setze Administrator Benutzername.", +"Set an admin password." => "Setze Administrator Passwort", +"Specify a data folder." => "Datei-Verzeichnis angeben", +"%s enter the database username." => "%s geben Sie den Datenbank-Benutzernamen an.", +"%s enter the database name." => "%s geben Sie den Datenbank-Namen an.", +"%s you may not use dots in the database name" => "%s Der Datenbank-Name darf keine Punkte enthalten", +"%s set the database host." => "%s setze den Datenbank-Host", +"PostgreSQL username and/or password not valid" => "PostgreSQL Benutzername und/oder Passwort ungültig", +"You need to enter either an existing account or the administrator." => "Sie müssen entweder ein existierendes Benutzerkonto oder das Administratoren-Konto angeben.", +"Oracle username and/or password not valid" => "Oracle Benutzername und/oder Passwort ungültig", +"MySQL username and/or password not valid" => "MySQL Benutzername und/oder Passwort ungültig", +"DB Error: \"%s\"" => "DB Fehler: \"%s\"", +"Offending command was: \"%s\"" => "Fehlerhafter Befehl war: \"%s\"", +"MySQL user '%s'@'localhost' exists already." => "MySQL Benutzer '%s'@'localhost' existiert bereits.", +"Drop this user from MySQL" => "Lösche diesen Benutzer aus MySQL", +"MySQL user '%s'@'%%' already exists" => "MySQL Benutzer '%s'@'%%' existiert bereits", +"Drop this user from MySQL." => "Lösche diesen Benutzer aus MySQL.", +"Offending command was: \"%s\", name: %s, password: %s" => "Fehlerhafter Befehl war: \"%s\", Name: %s, Passwort: %s", +"MS SQL username and/or password not valid: %s" => "MS SQL Benutzername und/oder Passwort nicht valide: %s", +"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 Datei-Synchronisation bereit, 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'>Instalationsanleitungen</a>.", "seconds ago" => "Gerade eben", "1 minute ago" => "Vor einer Minute", "%d minutes ago" => "Vor %d Minuten", diff --git a/lib/l10n/el.php b/lib/l10n/el.php index cf0be24b432..c17a33dfee1 100644 --- a/lib/l10n/el.php +++ b/lib/l10n/el.php @@ -16,6 +16,23 @@ "Files" => "Αρχεία", "Text" => "Κείμενο", "Images" => "Εικόνες", +"Set an admin username." => "Εισάγετε όνομα χρήστη διαχειριστή.", +"Set an admin password." => "Εισάγετε συνθηματικό διαχειριστή.", +"Specify a data folder." => "Καθορίστε τον φάκελο δεδομένων.", +"%s enter the database username." => "%s εισάγετε το όνομα χρήστη της βάσης δεδομένων.", +"%s enter the database name." => "%s εισάγετε το όνομα της βάσης δεδομένων.", +"%s you may not use dots in the database name" => "%s μάλλον δεν χρησιμοποιείτε τελείες στο όνομα της βάσης δεδομένων", +"PostgreSQL username and/or password not valid" => "Μη έγκυρος χρήστης και/ή συνθηματικό της PostgreSQL", +"You need to enter either an existing account or the administrator." => "Χρειάζεται να εισάγετε είτε έναν υπάρχον λογαριασμό ή του διαχειριστή.", +"Oracle username and/or password not valid" => "Μη έγκυρος χρήστης και/ή συνθηματικό της Oracle", +"MySQL username and/or password not valid" => "Μη έγκυρος χρήστης και/ή συνθηματικό της MySQL", +"DB Error: \"%s\"" => "Σφάλμα Βάσης Δεδομένων: \"%s\"", +"MySQL user '%s'@'localhost' exists already." => "Υπάρχει ήδη ο χρήστης '%s'@'localhost' της MySQL.", +"Drop this user from MySQL" => "Απόρριψη αυτού του χρήστη από την MySQL", +"MySQL user '%s'@'%%' already exists" => "Ο χρήστης '%s'@'%%' της MySQL υπάρχει ήδη", +"Drop this user from MySQL." => "Απόρριψη αυτού του χρήστη από την MySQL", +"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>.", "seconds ago" => "δευτερόλεπτα πριν", "1 minute ago" => "1 λεπτό πριν", "%d minutes ago" => "%d λεπτά πριν", @@ -28,7 +45,7 @@ "%d months ago" => "%d μήνες πριν", "last year" => "τον προηγούμενο χρόνο", "years ago" => "χρόνια πριν", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s είναι διαθέσιμα. Δείτε <a href=\"%s\">περισσότερες πληροφορίες</a>", +"%s is available. Get <a href=\"%s\">more information</a>" => "%s είναι διαθέσιμο. Δείτε <a href=\"%s\">περισσότερες πληροφορίες</a>", "up to date" => "ενημερωμένο", "updates check is disabled" => "ο έλεγχος ενημερώσεων είναι απενεργοποιημένος", "Could not find category \"%s\"" => "Αδυναμία εύρεσης κατηγορίας \"%s\"" diff --git a/lib/l10n/es.php b/lib/l10n/es.php index 8bbc8a8f7b4..37b15a375c4 100644 --- a/lib/l10n/es.php +++ b/lib/l10n/es.php @@ -16,6 +16,27 @@ "Files" => "Archivos", "Text" => "Texto", "Images" => "Imágenes", +"Set an admin username." => "Configurar un nombre de usuario del administrador", +"Set an admin password." => "Configurar la contraseña del administrador.", +"Specify a data folder." => "Especificar la carpeta de datos.", +"%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 no se puede utilizar puntos en el nombre de la base de datos", +"%s set the database host." => "%s ingresar el host de la base de datos.", +"PostgreSQL username and/or password not valid" => "Usuario y/o contraseña de PostgreSQL no válidos", +"You need to enter either an existing account or the administrator." => "Tiene que ingresar una cuenta existente o la del administrador.", +"Oracle username and/or password not valid" => "Usuario y/o contraseña de Oracle no válidos", +"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.", +"Offending command was: \"%s\", name: %s, password: %s" => "Comando infractor: \"%s\", nombre: %s, contraseña: %s", +"MS SQL username and/or password not valid: %s" => "Usuario y/o contraseña de MS SQL no válidos: %s", +"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>.", "seconds ago" => "hace segundos", "1 minute ago" => "hace 1 minuto", "%d minutes ago" => "hace %d minutos", diff --git a/lib/l10n/es_AR.php b/lib/l10n/es_AR.php index c32017a10f8..ff3d47285fc 100644 --- a/lib/l10n/es_AR.php +++ b/lib/l10n/es_AR.php @@ -16,6 +16,27 @@ "Files" => "Archivos", "Text" => "Texto", "Images" => "Imágenes", +"Set an admin username." => "Configurar un nombre de administrador", +"Set an admin password." => "Configurar una palabra clave de administrador", +"Specify a data folder." => "Especificar un directorio de datos", +"%s enter the database username." => "%s Entre el Usuario de la Base de Datos", +"%s enter the database name." => "%s Entre el Nombre de la Base de Datos", +"%s you may not use dots in the database name" => "%s no puede usar puntos en el nombre de la Base de Datos", +"%s set the database host." => "%s Especifique la dirección de la Base de Datos", +"PostgreSQL username and/or password not valid" => "Nombre de usuario o contraseña de PostgradeSQL no válido.", +"You need to enter either an existing account or the administrator." => "Debe ingresar una cuenta existente o el administrador", +"Oracle username and/or password not valid" => "El nombre de usuario y contraseña no son válidos", +"MySQL username and/or password not valid" => "Usuario y/o contraseña MySQL no válido", +"DB Error: \"%s\"" => "Error DB: \"%s\"", +"Offending command was: \"%s\"" => "El comando no comprendido es: \"%s\"", +"MySQL user '%s'@'localhost' exists already." => "Usuario MySQL '%s'@'localhost' ya existente", +"Drop this user from MySQL" => "Borrar este usuario de MySQL", +"MySQL user '%s'@'%%' already exists" => "Usuario MySQL '%s'@'%%' ya existente", +"Drop this user from MySQL." => "Borrar este usuario de MySQL", +"Offending command was: \"%s\", name: %s, password: %s" => "El comando no comprendido es: \"%s\", nombre: \"%s\", contraseña: \"%s\"", +"MS SQL username and/or password not valid: %s" => "Nombre de usuario y contraseña de MS SQL no son válidas: %s", +"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>.", "seconds ago" => "hace unos segundos", "1 minute ago" => "hace 1 minuto", "%d minutes ago" => "hace %d minutos", diff --git a/lib/l10n/et_EE.php b/lib/l10n/et_EE.php index 906abf9430a..cdcf762d9a6 100644 --- a/lib/l10n/et_EE.php +++ b/lib/l10n/et_EE.php @@ -15,13 +15,22 @@ "Files" => "Failid", "Text" => "Tekst", "Images" => "Pildid", +"Set an admin username." => "Määra admin kasutajanimi.", +"Set an admin password." => "Määra admini parool.", +"Specify a data folder." => "Määra andmete kaust.", +"DB Error: \"%s\"" => "Andmebaasi viga: \"%s\"", +"Drop this user from MySQL" => "Kustuta see kasutaja MySQL-ist", +"Drop this user from MySQL." => "Kustuta see kasutaja MySQL-ist.", "seconds ago" => "sekundit tagasi", "1 minute ago" => "1 minut tagasi", "%d minutes ago" => "%d minutit tagasi", +"1 hour ago" => "1 tund tagasi", +"%d hours ago" => "%d tundi tagasi", "today" => "täna", "yesterday" => "eile", "%d days ago" => "%d päeva tagasi", "last month" => "eelmisel kuul", +"%d months ago" => "%d kuud tagasi", "last year" => "eelmisel aastal", "years ago" => "aastat tagasi", "%s is available. Get <a href=\"%s\">more information</a>" => "%s on saadaval. Vaata <a href=\"%s\">lisainfot</a>", diff --git a/lib/l10n/eu.php b/lib/l10n/eu.php index 1941551b176..36eb397e425 100644 --- a/lib/l10n/eu.php +++ b/lib/l10n/eu.php @@ -16,6 +16,27 @@ "Files" => "Fitxategiak", "Text" => "Testua", "Images" => "Irudiak", +"Set an admin username." => "Ezarri administraziorako erabiltzaile izena.", +"Set an admin password." => "Ezarri administraziorako pasahitza.", +"Specify a data folder." => "Zehaztu data karpeta.", +"%s enter the database username." => "%s sartu datu basearen erabiltzaile izena.", +"%s enter the database name." => "%s sartu datu basearen izena.", +"%s you may not use dots in the database name" => "%s ezin duzu punturik erabili datu basearen izenean.", +"%s set the database host." => "%s sartu datu basearen hostalaria.", +"PostgreSQL username and/or password not valid" => "PostgreSQL erabiltzaile edota pasahitza ez dira egokiak.", +"You need to enter either an existing account or the administrator." => "Existitzen den kontu bat edo administradorearena jarri behar duzu.", +"Oracle username and/or password not valid" => "Oracle erabiltzaile edota pasahitza ez dira egokiak.", +"MySQL username and/or password not valid" => "MySQL erabiltzaile edota pasahitza ez dira egokiak.", +"DB Error: \"%s\"" => "DB errorea: \"%s\"", +"Offending command was: \"%s\"" => "Errorea komando honek sortu du: \"%s\"", +"MySQL user '%s'@'localhost' exists already." => "MySQL '%s'@'localhost' erabiltzailea dagoeneko existitzen da.", +"Drop this user from MySQL" => "Ezabatu erabiltzaile hau MySQLtik", +"MySQL user '%s'@'%%' already exists" => "MySQL '%s'@'%%' erabiltzailea dagoeneko existitzen da", +"Drop this user from MySQL." => "Ezabatu erabiltzaile hau MySQLtik.", +"Offending command was: \"%s\", name: %s, password: %s" => "Errorea komando honek sortu du: \"%s\", izena: %s, pasahitza: %s", +"MS SQL username and/or password not valid: %s" => "MS SQL erabiltzaile izena edota pasahitza ez dira egokiak: %s", +"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>.", "seconds ago" => "orain dela segundu batzuk", "1 minute ago" => "orain dela minutu 1", "%d minutes ago" => "orain dela %d minutu", diff --git a/lib/l10n/fi_FI.php b/lib/l10n/fi_FI.php index b8d4b137431..89a584d389d 100644 --- a/lib/l10n/fi_FI.php +++ b/lib/l10n/fi_FI.php @@ -16,6 +16,20 @@ "Files" => "Tiedostot", "Text" => "Teksti", "Images" => "Kuvat", +"Set an admin username." => "Aseta ylläpitäjän käyttäjätunnus.", +"Set an admin password." => "Aseta ylläpitäjän salasana.", +"Specify a data folder." => "Määritä datakansio.", +"%s enter the database username." => "%s anna tietokannan käyttäjätunnus.", +"%s enter the database name." => "%s anna tietokannan nimi.", +"%s you may not use dots in the database name" => "%s et voi käyttää pisteitä tietokannan nimessä", +"PostgreSQL username and/or password not valid" => "PostgreSQL:n käyttäjätunnus ja/tai salasana on väärin", +"Oracle username and/or password not valid" => "Oraclen käyttäjätunnus ja/tai salasana on väärin", +"MySQL username and/or password not valid" => "MySQL:n käyttäjätunnus ja/tai salasana on väärin", +"DB Error: \"%s\"" => "Tietokantavirhe: \"%s\"", +"MySQL user '%s'@'localhost' exists already." => "MySQL-käyttäjä '%s'@'localhost' on jo olemassa.", +"MySQL user '%s'@'%%' already exists" => "MySQL-käyttäjä '%s'@'%%' on jo olemassa", +"MS SQL username and/or password not valid: %s" => "MS SQL -käyttäjätunnus ja/tai -salasana on väärin: %s", +"Please double check the <a href='%s'>installation guides</a>." => "Lue tarkasti <a href='%s'>asennusohjeet</a>.", "seconds ago" => "sekuntia sitten", "1 minute ago" => "1 minuutti sitten", "%d minutes ago" => "%d minuuttia sitten", diff --git a/lib/l10n/fr.php b/lib/l10n/fr.php index c6bf8f7f9c3..9448502df6a 100644 --- a/lib/l10n/fr.php +++ b/lib/l10n/fr.php @@ -16,6 +16,27 @@ "Files" => "Fichiers", "Text" => "Texte", "Images" => "Images", +"Set an admin username." => "Spécifiez un nom d'utilisateur pour l'administrateur.", +"Set an admin password." => "Spécifiez un mot de passe administrateur.", +"Specify a data folder." => "Spécifiez un répertoire pour les données.", +"%s enter the database username." => "%s entrez le nom d'utilisateur de la base de données.", +"%s enter the database name." => "%s entrez le nom de la base de données.", +"%s you may not use dots in the database name" => "%s vous nez pouvez pas utiliser de points dans le nom de la base de données", +"%s set the database host." => "%s spécifiez l'hôte de la base de données.", +"PostgreSQL username and/or password not valid" => "Nom d'utilisateur et/ou mot de passe de la base PostgreSQL invalide", +"You need to enter either an existing account or the administrator." => "Vous devez spécifier soit le nom d'un compte existant, soit celui de l'administrateur.", +"Oracle username and/or password not valid" => "Nom d'utilisateur et/ou mot de passe de la base Oracle invalide", +"MySQL username and/or password not valid" => "Nom d'utilisateur et/ou mot de passe de la base MySQL invalide", +"DB Error: \"%s\"" => "Erreur de la base de données : \"%s\"", +"Offending command was: \"%s\"" => "La requête en cause est : \"%s\"", +"MySQL user '%s'@'localhost' exists already." => "L'utilisateur MySQL '%s'@'localhost' existe déjà.", +"Drop this user from MySQL" => "Retirer cet utilisateur de la base MySQL", +"MySQL user '%s'@'%%' already exists" => "L'utilisateur MySQL '%s'@'%%' existe déjà", +"Drop this user from MySQL." => "Retirer cet utilisateur de la base MySQL.", +"Offending command was: \"%s\", name: %s, password: %s" => "La requête en cause est : \"%s\", nom : %s, mot de passe : %s", +"MS SQL username and/or password not valid: %s" => "Le nom d'utilisateur et/ou le mot de passe de la base MS SQL est invalide : %s", +"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>.", "seconds ago" => "à l'instant", "1 minute ago" => "il y a 1 minute", "%d minutes ago" => "il y a %d minutes", diff --git a/lib/l10n/gl.php b/lib/l10n/gl.php index 532b3443b44..a11724fef43 100644 --- a/lib/l10n/gl.php +++ b/lib/l10n/gl.php @@ -5,18 +5,39 @@ "Users" => "Usuarios", "Apps" => "Aplicativos", "Admin" => "Administración", -"ZIP download is turned off." => "As descargas ZIP están desactivadas", -"Files need to be downloaded one by one." => "Os ficheiros necesitan seren descargados de un en un.", +"ZIP download is turned off." => "As descargas ZIP están desactivadas.", +"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.", -"couldn't be determined" => "non puido ser determinado", +"couldn't be determined" => "non foi posíbel determinalo", "Application is not enabled" => "O aplicativo non está activado", "Authentication error" => "Produciuse un erro na autenticación", "Token expired. Please reload page." => "Testemuña caducada. Recargue a páxina.", "Files" => "Ficheiros", "Text" => "Texto", "Images" => "Imaxes", -"seconds ago" => "hai segundos", +"Set an admin username." => "Estabeleza un nome de usuario administrador", +"Set an admin password." => "Estabeleza un contrasinal de administrador", +"Specify a data folder." => "Especifique un cartafol de datos.", +"%s enter the database username." => "%s introduza o nome de usuario da base de datos", +"%s enter the database name." => "%s introduza o nome da base de datos", +"%s you may not use dots in the database name" => "%s non se poden empregar puntos na base de datos", +"%s set the database host." => "%s estabeleza o servidor da base de datos", +"PostgreSQL username and/or password not valid" => "Nome de usuario e/ou contrasinal de PostgreSQL incorrecto", +"You need to enter either an existing account or the administrator." => "Deberá introducir unha conta existente ou o administrador.", +"Oracle username and/or password not valid" => "Nome de usuario e/ou contrasinal de Oracle incorrecto", +"MySQL username and/or password not valid" => "Nome de usuario e/ou contrasinal de MySQL incorrecto", +"DB Error: \"%s\"" => "Produciuse un erro na base de datos: «%s»", +"Offending command was: \"%s\"" => "A orde ofensiva foi: «%s»", +"MySQL user '%s'@'localhost' exists already." => "O usuario MySQL '%s'@'localhost' xa existe.", +"Drop this user from MySQL" => "Omitir este usuario de MySQL", +"MySQL user '%s'@'%%' already exists" => "O usuario MySQL «%s»@«%%» xa existe.", +"Drop this user from MySQL." => "Omitir este usuario de MySQL.", +"Offending command was: \"%s\", name: %s, password: %s" => "A orde ofensiva foi: «%s», nome: %s, contrasinal: %s", +"MS SQL username and/or password not valid: %s" => "Nome de usuario e/ou contrasinal de MS SQL incorrecto: %s", +"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>", +"seconds ago" => "segundos atrás", "1 minute ago" => "hai 1 minuto", "%d minutes ago" => "hai %d minutos", "1 hour ago" => "Vai 1 hora", @@ -29,7 +50,7 @@ "last year" => "último ano", "years ago" => "anos atrás", "%s is available. Get <a href=\"%s\">more information</a>" => "%s está dispoñíbel. Obtéña <a href=\"%s\">máis información</a>", -"up to date" => "ao día", +"up to date" => "actualizado", "updates check is disabled" => "a comprobación de actualizacións está desactivada", "Could not find category \"%s\"" => "Non foi posíbel atopar a categoría «%s»" ); diff --git a/lib/l10n/hi.php b/lib/l10n/hi.php new file mode 100644 index 00000000000..f507993f494 --- /dev/null +++ b/lib/l10n/hi.php @@ -0,0 +1,7 @@ +<?php $TRANSLATIONS = array( +"Help" => "सहयोग", +"Personal" => "यक्तिगत", +"Settings" => "सेटिंग्स", +"Users" => "उपयोगकर्ता", +"Apps" => "Apps" +); diff --git a/lib/l10n/hu_HU.php b/lib/l10n/hu_HU.php index e25de3e1ed6..537066c6fea 100644 --- a/lib/l10n/hu_HU.php +++ b/lib/l10n/hu_HU.php @@ -4,9 +4,9 @@ "Settings" => "Beállítások", "Users" => "Felhasználók", "Apps" => "Alkalmazások", -"Admin" => "Admin", +"Admin" => "Adminsztráció", "ZIP download is turned off." => "A ZIP-letöltés nincs engedélyezve.", -"Files need to be downloaded one by one." => "A fájlokat egyenként kell letölteni", +"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.", "couldn't be determined" => "nem határozható meg", @@ -16,6 +16,27 @@ "Files" => "Fájlok", "Text" => "Szöveg", "Images" => "Képek", +"Set an admin username." => "Állítson be egy felhasználói nevet az adminisztrációhoz.", +"Set an admin password." => "Állítson be egy jelszót az adminisztrációhoz.", +"Specify a data folder." => "Adja meg az adatokat tartalmazó könyvtár nevét.", +"%s enter the database username." => "%s adja meg az adatbázist elérő felhasználó login nevét.", +"%s enter the database name." => "%s adja meg az adatbázis nevét.", +"%s you may not use dots in the database name" => "%s az adatbázis neve nem tartalmazhat pontot", +"%s set the database host." => "%s adja meg az adatbázist szolgáltató számítógép nevét.", +"PostgreSQL username and/or password not valid" => "A PostgreSQL felhasználói név és/vagy jelszó érvénytelen", +"You need to enter either an existing account or the administrator." => "Vagy egy létező felhasználó vagy az adminisztrátor bejelentkezési nevét kell megadnia", +"Oracle username and/or password not valid" => "Az Oracle felhasználói név és/vagy jelszó érvénytelen", +"MySQL username and/or password not valid" => "A MySQL felhasználói név és/vagy jelszó érvénytelen", +"DB Error: \"%s\"" => "Adatbázis hiba: \"%s\"", +"Offending command was: \"%s\"" => "A hibát ez a parancs okozta: \"%s\"", +"MySQL user '%s'@'localhost' exists already." => "A '%s'@'localhost' MySQL felhasználó már létezik.", +"Drop this user from MySQL" => "Törölje ezt a felhasználót a MySQL-ből", +"MySQL user '%s'@'%%' already exists" => "A '%s'@'%%' MySQL felhasználó már létezik", +"Drop this user from MySQL." => "Törölje ezt a felhasználót a MySQL-ből.", +"Offending command was: \"%s\", name: %s, password: %s" => "A hibát okozó parancs ez volt: \"%s\", login név: %s, jelszó: %s", +"MS SQL username and/or password not valid: %s" => "Az MS SQL felhasználónév és/vagy jelszó érvénytelen: %s", +"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Az Ön webkiszolgálója nincs megfelelően beállítva az állományok szinkronizálásához, mert a WebDAV-elérés úgy tűnik, nem működik.", +"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>.", "seconds ago" => "másodperce", "1 minute ago" => "1 perce", "%d minutes ago" => "%d perce", diff --git a/lib/l10n/it.php b/lib/l10n/it.php index eb404db7fb5..297f1efde05 100644 --- a/lib/l10n/it.php +++ b/lib/l10n/it.php @@ -16,6 +16,27 @@ "Files" => "File", "Text" => "Testo", "Images" => "Immagini", +"Set an admin username." => "Imposta un nome utente di amministrazione.", +"Set an admin password." => "Imposta una password di amministrazione.", +"Specify a data folder." => "Specifica una cartella dei dati.", +"%s enter the database username." => "%s digita il nome utente del database.", +"%s enter the database name." => "%s digita il nome del database.", +"%s you may not use dots in the database name" => "%s non dovresti utilizzare punti nel nome del database", +"%s set the database host." => "%s imposta l'host del database.", +"PostgreSQL username and/or password not valid" => "Nome utente e/o password di PostgreSQL non validi", +"You need to enter either an existing account or the administrator." => "È necessario inserire un account esistente o l'amministratore.", +"Oracle username and/or password not valid" => "Nome utente e/o password di Oracle non validi", +"MySQL username and/or password not valid" => "Nome utente e/o password di MySQL non validi", +"DB Error: \"%s\"" => "Errore DB: \"%s\"", +"Offending command was: \"%s\"" => "Il comando non consentito era: \"%s\"", +"MySQL user '%s'@'localhost' exists already." => "L'utente MySQL '%s'@'localhost' esiste già.", +"Drop this user from MySQL" => "Elimina questo utente da MySQL", +"MySQL user '%s'@'%%' already exists" => "L'utente MySQL '%s'@'%%' esiste già", +"Drop this user from MySQL." => "Elimina questo utente da MySQL.", +"Offending command was: \"%s\", name: %s, password: %s" => "Il comando non consentito era: \"%s\", nome: %s, password: %s", +"MS SQL username and/or password not valid: %s" => "Nome utente e/o password MS SQL non validi: %s", +"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>.", "seconds ago" => "secondi fa", "1 minute ago" => "1 minuto fa", "%d minutes ago" => "%d minuti fa", diff --git a/lib/l10n/ja_JP.php b/lib/l10n/ja_JP.php index 11cefe900c2..529eec3ac52 100644 --- a/lib/l10n/ja_JP.php +++ b/lib/l10n/ja_JP.php @@ -16,6 +16,27 @@ "Files" => "ファイル", "Text" => "TTY TDD", "Images" => "画像", +"Set an admin username." => "管理者のユーザ名を設定。", +"Set an admin password." => "管理者のパスワードを設定。", +"Specify a data folder." => "データフォルダを指定。", +"%s enter the database username." => "%s のデータベースのユーザ名を入力してください。", +"%s enter the database name." => "%s のデータベース名を入力してください。", +"%s you may not use dots in the database name" => "%s ではデータベース名にドットを利用できないかもしれません。", +"%s set the database host." => "%s にデータベースホストを設定します。", +"PostgreSQL username and/or password not valid" => "PostgreSQLのユーザ名もしくはパスワードは有効ではありません", +"You need to enter either an existing account or the administrator." => "既存のアカウントもしくは管理者のどちらかを入力する必要があります。", +"Oracle username and/or password not valid" => "Oracleのユーザ名もしくはパスワードは有効ではありません", +"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からこのユーザを削除する。", +"Offending command was: \"%s\", name: %s, password: %s" => "違反コマンド: \"%s\"、名前: %s、パスワード: %s", +"MS SQL username and/or password not valid: %s" => "MS SQL サーバーのユーザー名/パスワードが正しくありません: %s", +"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>をよく確認してください。", "seconds ago" => "秒前", "1 minute ago" => "1分前", "%d minutes ago" => "%d 分前", diff --git a/lib/l10n/ka.php b/lib/l10n/ka.php new file mode 100644 index 00000000000..e5a3e659668 --- /dev/null +++ b/lib/l10n/ka.php @@ -0,0 +1,15 @@ +<?php $TRANSLATIONS = array( +"Help" => "შველა", +"Personal" => "პერსონა", +"Users" => "მომხმარებლები", +"Admin" => "ადმინისტრატორი", +"ZIP download is turned off." => "ZIP გადმოწერა გამორთულია", +"Files" => "ფაილები", +"seconds ago" => "წამის წინ", +"1 minute ago" => "1 წუთის წინ", +"%d minutes ago" => "%d წუთის წინ", +"1 hour ago" => "1 საათის წინ", +"today" => "დღეს", +"yesterday" => "გუშინ", +"%d days ago" => "%d დღის წინ" +); diff --git a/lib/l10n/lv.php b/lib/l10n/lv.php index 9f2a0dea749..c73d306ca0a 100644 --- a/lib/l10n/lv.php +++ b/lib/l10n/lv.php @@ -16,6 +16,27 @@ "Files" => "Datnes", "Text" => "Teksts", "Images" => "Attēli", +"Set an admin username." => "Iestatiet administratora lietotājvārdu.", +"Set an admin password." => "Iestatiet administratora paroli.", +"Specify a data folder." => "Norādiet datu mapi.", +"%s enter the database username." => "%s ievadiet datubāzes lietotājvārdu.", +"%s enter the database name." => "%s ievadiet datubāzes nosaukumu.", +"%s you may not use dots in the database name" => "%s datubāžu nosaukumos nedrīkst izmantot punktus", +"%s set the database host." => "%s iestatiet datubāžu serveri.", +"PostgreSQL username and/or password not valid" => "Nav derīga PostgreSQL parole un/vai lietotājvārds", +"You need to enter either an existing account or the administrator." => "Jums jāievada vai nu esošs vai administratora konts.", +"Oracle username and/or password not valid" => "Nav derīga Oracle parole un/vai lietotājvārds", +"MySQL username and/or password not valid" => "Nav derīga MySQL parole un/vai lietotājvārds", +"DB Error: \"%s\"" => "DB kļūda — “%s”", +"Offending command was: \"%s\"" => "Vainīgā komanda bija “%s”", +"MySQL user '%s'@'localhost' exists already." => "MySQL lietotājs %s'@'localhost' jau eksistē.", +"Drop this user from MySQL" => "Izmest šo lietotāju no MySQL", +"MySQL user '%s'@'%%' already exists" => "MySQL lietotājs '%s'@'%%' jau eksistē", +"Drop this user from MySQL." => "Izmest šo lietotāju no MySQL.", +"Offending command was: \"%s\", name: %s, password: %s" => "Vainīgā komanda bija \"%s\", vārds: %s, parole: %s", +"MS SQL username and/or password not valid: %s" => "Nav derīga MySQL parole un/vai lietotājvārds — %s", +"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>.", "seconds ago" => "sekundes atpakaļ", "1 minute ago" => "pirms 1 minūtes", "%d minutes ago" => "pirms %d minūtēm", diff --git a/lib/l10n/my_MM.php b/lib/l10n/my_MM.php new file mode 100644 index 00000000000..d725a06a3a9 --- /dev/null +++ b/lib/l10n/my_MM.php @@ -0,0 +1,31 @@ +<?php $TRANSLATIONS = array( +"Help" => "အကူအညီ", +"Users" => "သုံးစွဲသူ", +"Apps" => "Apps", +"Admin" => "အက်ဒမင်", +"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 ဖိုင်အဖြစ်ပြုလုပ်ရန် ရွေးချယ်ထားသောဖိုင်များသည် အရမ်းကြီးလွန်းသည်", +"couldn't be determined" => "မဆုံးဖြတ်နိုင်ပါ။", +"Authentication error" => "ခွင့်ပြုချက်မအောင်မြင်", +"Files" => "ဖိုင်များ", +"Text" => "စာသား", +"Images" => "ပုံရိပ်များ", +"seconds ago" => "စက္ကန့်အနည်းငယ်က", +"1 minute ago" => "၁ မိနစ်အရင်က", +"%d minutes ago" => "%d မိနစ်အရင်က", +"1 hour ago" => "၁ နာရီ အရင်က", +"%d hours ago" => "%d နာရီအရင်က", +"today" => "ယနေ့", +"yesterday" => "မနေ့က", +"%d days ago" => "%d ရက် အရင်က", +"last month" => "ပြီးခဲ့သောလ", +"%d months ago" => "%d လအရင်က", +"last year" => "မနှစ်က", +"years ago" => "နှစ် အရင်က", +"%s is available. Get <a href=\"%s\">more information</a>" => "%s ကိုရရှိနိုင်ပါပြီ။ <a href=\"%s\">နောက်ထပ်အချက်အလက်များ</a>ရယူပါ။", +"up to date" => "နောက်ဆုံးပေါ်", +"updates check is disabled" => "နောက်ဆုံးပေါ်စစ်ဆေးခြင်းကိုပိတ်ထားသည်", +"Could not find category \"%s\"" => "\"%s\"ခေါင်းစဉ်ကို ရှာမတွေ့ပါ" +); diff --git a/lib/l10n/nl.php b/lib/l10n/nl.php index 7ce134e3621..4a357889fdc 100644 --- a/lib/l10n/nl.php +++ b/lib/l10n/nl.php @@ -16,6 +16,26 @@ "Files" => "Bestanden", "Text" => "Tekst", "Images" => "Afbeeldingen", +"Set an admin username." => "Stel de gebruikersnaam van de beheerder in.", +"Set an admin password." => "Stel een beheerderswachtwoord in.", +"Specify a data folder." => "Geef een datamap op.", +"%s enter the database username." => "%s opgeven database gebruikersnaam.", +"%s enter the database name." => "%s opgeven databasenaam.", +"%s you may not use dots in the database name" => "%s er mogen geen puntjes in de databasenaam voorkomen", +"%s set the database host." => "%s instellen databaseservernaam.", +"PostgreSQL username and/or password not valid" => "PostgreSQL gebruikersnaam en/of wachtwoord ongeldig", +"You need to enter either an existing account or the administrator." => "Geef of een bestaand account op of het beheerdersaccount.", +"Oracle username and/or password not valid" => "Oracle gebruikersnaam en/of wachtwoord ongeldig", +"MySQL username and/or password not valid" => "MySQL gebruikersnaam en/of wachtwoord ongeldig", +"DB Error: \"%s\"" => "DB Fout: \"%s\"", +"Offending command was: \"%s\"" => "Onjuiste commande was: \"%s\"", +"MySQL user '%s'@'localhost' exists already." => "MySQL gebruiker '%s'@'localhost' bestaat al.", +"Drop this user from MySQL" => "Verwijder deze gebruiker uit MySQL", +"MySQL user '%s'@'%%' already exists" => "MySQL gebruiker '%s'@'%%' bestaat al", +"Drop this user from MySQL." => "Verwijder deze gebruiker uit MySQL.", +"Offending command was: \"%s\", name: %s, password: %s" => "Onjuiste commando was: \"%s\", naam: %s, wachtwoord: %s", +"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>." => "Conntroleer de <a href='%s'>installatie handleiding</a> goed.", "seconds ago" => "seconden geleden", "1 minute ago" => "1 minuut geleden", "%d minutes ago" => "%d minuten geleden", diff --git a/lib/l10n/pl.php b/lib/l10n/pl.php index 6ec35445bc2..9a1a5e836c9 100644 --- a/lib/l10n/pl.php +++ b/lib/l10n/pl.php @@ -16,6 +16,27 @@ "Files" => "Pliki", "Text" => "Połączenie tekstowe", "Images" => "Obrazy", +"Set an admin username." => "Ustaw nazwę administratora.", +"Set an admin password." => "Ustaw hasło administratora.", +"Specify a data folder." => "Określ folder danych.", +"%s enter the database username." => "%s wpisz nazwę użytkownika do bazy", +"%s enter the database name." => "%s wpisz nazwę bazy.", +"%s you may not use dots in the database name" => "%s nie można używać kropki w nazwie bazy danych", +"%s set the database host." => "%s ustaw hosta bazy danych.", +"PostgreSQL username and/or password not valid" => "PostgreSQL: Nazwa użytkownika i/lub hasło jest niepoprawne", +"You need to enter either an existing account or the administrator." => "Należy wprowadzić istniejące konto użytkownika lub administratora.", +"Oracle username and/or password not valid" => "Oracle: Nazwa użytkownika i/lub hasło jest niepoprawne", +"MySQL username and/or password not valid" => "MySQL: Nazwa użytkownika i/lub hasło jest niepoprawne", +"DB Error: \"%s\"" => "Błąd DB: \"%s\"", +"Offending command was: \"%s\"" => "Niepoprawna komenda: \"%s\"", +"MySQL user '%s'@'localhost' exists already." => "Użytkownik MySQL '%s'@'localhost' już istnieje", +"Drop this user from MySQL" => "Usuń tego użytkownika z MySQL", +"MySQL user '%s'@'%%' already exists" => "Użytkownik MySQL '%s'@'%%t' już istnieje", +"Drop this user from MySQL." => "Usuń tego użytkownika z MySQL.", +"Offending command was: \"%s\", name: %s, password: %s" => "Niepoprawne polecania: \"%s\", nazwa: %s, hasło: %s", +"MS SQL username and/or password not valid: %s" => "Nazwa i/lub hasło serwera MS SQL jest niepoprawne: %s.", +"Your web server is not yet properly setup to allow files synchronization because the WebDAV interface seems to be broken." => "Serwer www nie jest jeszcze poprawnie ustawiony, aby umożliwić synchronizację plików, ponieważ interfejs WebDAV wydaje się być uszkodzony. Sprawdź ustawienia serwera.", +"Please double check the <a href='%s'>installation guides</a>." => "Proszę sprawdź ponownie <a href='%s'>przewodnik instalacji</a>.", "seconds ago" => "sekund temu", "1 minute ago" => "1 minutę temu", "%d minutes ago" => "%d minut temu", diff --git a/lib/l10n/pt_BR.php b/lib/l10n/pt_BR.php index fb7087d35d7..d4f410d8885 100644 --- a/lib/l10n/pt_BR.php +++ b/lib/l10n/pt_BR.php @@ -9,12 +9,34 @@ "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.", +"couldn't be determined" => "não pôde ser determinado", "Application is not enabled" => "Aplicação não está habilitada", "Authentication error" => "Erro de autenticação", "Token expired. Please reload page." => "Token expirou. Por favor recarregue a página.", "Files" => "Arquivos", "Text" => "Texto", "Images" => "Imagens", +"Set an admin username." => "Defina um nome de usuário de administrador.", +"Set an admin password." => "Defina uma senha de administrador.", +"Specify a data folder." => "Especifique uma pasta de dados.", +"%s enter the database username." => "%s insira o nome de usuário do banco de dados.", +"%s enter the database name." => "%s insira o nome do banco de dados.", +"%s you may not use dots in the database name" => "%s você não pode usar pontos no nome do banco de dados", +"%s set the database host." => "%s defina o host do banco de dados.", +"PostgreSQL username and/or password not valid" => "Nome de usuário e/ou senha PostgreSQL inválido(s)", +"You need to enter either an existing account or the administrator." => "Você precisa inserir uma conta existente ou o administrador.", +"Oracle username and/or password not valid" => "Nome de usuário e/ou senha Oracle inválido(s)", +"MySQL username and/or password not valid" => "Nome de usuário e/ou senha MySQL inválido(s)", +"DB Error: \"%s\"" => "Erro no BD: \"%s\"", +"Offending command was: \"%s\"" => "Comando ofensivo era: \"%s\"", +"MySQL user '%s'@'localhost' exists already." => "O usuário MySQL '%s'@'localhost' já existe.", +"Drop this user from MySQL" => "Derrubar este usuário do MySQL", +"MySQL user '%s'@'%%' already exists" => "Usuário MySQL '%s'@'%%' já existe", +"Drop this user from MySQL." => "Derrube este usuário do MySQL.", +"Offending command was: \"%s\", name: %s, password: %s" => "Comando ofensivo era: \"%s\", nome: %s, senha: %s", +"MS SQL username and/or password not valid: %s" => "Nome de usuário e/ou senha MS SQL inválido(s): %s", +"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>.", "seconds ago" => "segundos atrás", "1 minute ago" => "1 minuto atrás", "%d minutes ago" => "%d minutos atrás", diff --git a/lib/l10n/pt_PT.php b/lib/l10n/pt_PT.php index e35bb489c49..9bdcfcc9ced 100644 --- a/lib/l10n/pt_PT.php +++ b/lib/l10n/pt_PT.php @@ -16,6 +16,26 @@ "Files" => "Ficheiros", "Text" => "Texto", "Images" => "Imagens", +"Set an admin username." => "Definir um nome de utilizador de administrador", +"Set an admin password." => "Definiar uma password de administrador", +"Specify a data folder." => "Especificar a pasta para os dados.", +"%s enter the database username." => "%s introduza o nome de utilizador da base de dados", +"%s enter the database name." => "%s introduza o nome da base de dados", +"%s you may not use dots in the database name" => "%s não é permitido utilizar pontos (.) no nome da base de dados", +"%s set the database host." => "%s defina o servidor da base de dados (geralmente localhost)", +"PostgreSQL username and/or password not valid" => "Nome de utilizador/password do PostgreSQL inválido", +"You need to enter either an existing account or the administrator." => "Precisa de introduzir uma conta existente ou de administrador", +"Oracle username and/or password not valid" => "Nome de utilizador/password do Oracle inválida", +"MySQL username and/or password not valid" => "Nome de utilizador/password do MySQL inválida", +"DB Error: \"%s\"" => "Erro na BD: \"%s\"", +"Offending command was: \"%s\"" => "O comando gerador de erro foi: \"%s\"", +"MySQL user '%s'@'localhost' exists already." => "O utilizador '%s'@'localhost' do MySQL já existe.", +"Drop this user from MySQL" => "Eliminar este utilizador do MySQL", +"MySQL user '%s'@'%%' already exists" => "O utilizador '%s'@'%%' do MySQL já existe", +"Drop this user from MySQL." => "Eliminar este utilizador do MySQL", +"Offending command was: \"%s\", name: %s, password: %s" => "O comando gerador de erro foi: \"%s\", nome: %s, password: %s", +"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>.", "seconds ago" => "há alguns segundos", "1 minute ago" => "há 1 minuto", "%d minutes ago" => "há %d minutos", diff --git a/lib/l10n/ru.php b/lib/l10n/ru.php index 5ef2cca3be3..25a88d5efc2 100644 --- a/lib/l10n/ru.php +++ b/lib/l10n/ru.php @@ -16,6 +16,27 @@ "Files" => "Файлы", "Text" => "Текст", "Images" => "Изображения", +"Set an admin username." => "Установить имя пользователя для admin.", +"Set an admin password." => "становит пароль для admin.", +"Specify a data folder." => "Указать папку данных.", +"%s enter the database username." => "%s введите имя пользователя базы данных.", +"%s enter the database name." => "%s введите имя базы данных.", +"%s you may not use dots in the database name" => "%s Вы не можете использовать точки в имени базы данных", +"%s set the database host." => "%s задайте хост базы данных.", +"PostgreSQL username and/or password not valid" => "Неверное имя пользователя и/или пароль PostgreSQL", +"You need to enter either an existing account or the administrator." => "Вы должны войти или в существующий аккаунт или под администратором.", +"Oracle username and/or password not valid" => "Неверное имя пользователя и/или пароль Oracle", +"MySQL username and/or password not valid" => "Неверное имя пользователя и/или пароль MySQL", +"DB Error: \"%s\"" => "Ошибка БД: \"%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.", +"Offending command was: \"%s\", name: %s, password: %s" => "Вызываемая команда была: \"%s\", имя: %s, пароль: %s", +"MS SQL username and/or password not valid: %s" => "Имя пользователя и/или пароль MS SQL не подходит: %s", +"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>.", "seconds ago" => "менее минуты", "1 minute ago" => "1 минуту назад", "%d minutes ago" => "%d минут назад", diff --git a/lib/l10n/ru_RU.php b/lib/l10n/ru_RU.php index 03da09236ea..de770563662 100644 --- a/lib/l10n/ru_RU.php +++ b/lib/l10n/ru_RU.php @@ -16,6 +16,8 @@ "Files" => "Файлы", "Text" => "Текст", "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>.", "seconds ago" => "секунд назад", "1 minute ago" => "1 минуту назад", "%d minutes ago" => "%d минут назад", diff --git a/lib/l10n/sk_SK.php b/lib/l10n/sk_SK.php index 81f23ffdc50..8c9ce61622c 100644 --- a/lib/l10n/sk_SK.php +++ b/lib/l10n/sk_SK.php @@ -2,13 +2,13 @@ "Help" => "Pomoc", "Personal" => "Osobné", "Settings" => "Nastavenia", -"Users" => "Užívatelia", +"Users" => "Používatelia", "Apps" => "Aplikácie", -"Admin" => "Správca", +"Admin" => "Administrátor", "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.", +"Selected files too large to generate zip file." => "Zvolené súbory sú príliš veľké na vygenerovanie zip súboru.", "couldn't be determined" => "nedá sa zistiť", "Application is not enabled" => "Aplikácia nie je zapnutá", "Authentication error" => "Chyba autentifikácie", @@ -16,6 +16,27 @@ "Files" => "Súbory", "Text" => "Text", "Images" => "Obrázky", +"Set an admin username." => "Zadajte používateľské meno administrátora.", +"Set an admin password." => "Zadajte heslo administrátora.", +"Specify a data folder." => "Zadajte priečinok pre dáta.", +"%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", +"%s set the database host." => "Zadajte názov počítača s databázou %s.", +"PostgreSQL username and/or password not valid" => "Používateľské meno a/alebo heslo pre PostgreSQL databázu je neplatné", +"You need to enter either an existing account or the administrator." => "Musíte zadať jestvujúci účet alebo administrátora.", +"Oracle username and/or password not valid" => "Používateľské meno a/alebo heslo pre Oracle databázu je neplatné", +"MySQL username and/or password not valid" => "Používateľské meno a/alebo heslo pre MySQL databázu je neplatné", +"DB Error: \"%s\"" => "Chyba DB: \"%s\"", +"Offending command was: \"%s\"" => "Podozrivý príkaz bol: \"%s\"", +"MySQL user '%s'@'localhost' exists already." => "Používateľ '%s'@'localhost' už v MySQL existuje.", +"Drop this user from MySQL" => "Zahodiť používateľa z MySQL.", +"MySQL user '%s'@'%%' already exists" => "Používateľ '%s'@'%%' už v MySQL existuje", +"Drop this user from MySQL." => "Zahodiť používateľa z MySQL.", +"Offending command was: \"%s\", name: %s, password: %s" => "Podozrivý príkaz bol: \"%s\", meno: %s, heslo: %s", +"MS SQL username and/or password not valid: %s" => "Používateľské meno, alebo heslo MS SQL nie je platné: %s", +"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>.", "seconds ago" => "pred sekundami", "1 minute ago" => "pred 1 minútou", "%d minutes ago" => "pred %d minútami", @@ -28,7 +49,7 @@ "%d months ago" => "Pred %d mesiacmi.", "last year" => "minulý rok", "years ago" => "pred rokmi", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s je dostupné. Získať <a href=\"%s\">viac informácií</a>", +"%s is available. Get <a href=\"%s\">more information</a>" => "%s je dostupné. Získať <a href=\"%s\">pre viac informácií</a>", "up to date" => "aktuálny", "updates check is disabled" => "sledovanie aktualizácií je vypnuté", "Could not find category \"%s\"" => "Nemožno nájsť danú kategóriu \"%s\"" diff --git a/lib/l10n/sv.php b/lib/l10n/sv.php index 36f00636b2b..63ca60e89cd 100644 --- a/lib/l10n/sv.php +++ b/lib/l10n/sv.php @@ -16,6 +16,8 @@ "Files" => "Filer", "Text" => "Text", "Images" => "Bilder", +"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>.", "seconds ago" => "sekunder sedan", "1 minute ago" => "1 minut sedan", "%d minutes ago" => "%d minuter sedan", diff --git a/lib/l10n/uk.php b/lib/l10n/uk.php index 053644ddede..415c0a80c27 100644 --- a/lib/l10n/uk.php +++ b/lib/l10n/uk.php @@ -16,6 +16,26 @@ "Files" => "Файли", "Text" => "Текст", "Images" => "Зображення", +"Set an admin username." => "Встановіть ім'я адміністратора.", +"Set an admin password." => "Встановіть пароль адміністратора.", +"Specify a data folder." => "Вкажіть теку для даних.", +"%s enter the database username." => "%s введіть ім'я користувача бази даних.", +"%s enter the database name." => "%s введіть назву бази даних.", +"%s you may not use dots in the database name" => "%s не можна використовувати крапки в назві бази даних", +"%s set the database host." => "%s встановити хост бази даних.", +"PostgreSQL username and/or password not valid" => "PostgreSQL ім'я користувача та/або пароль не дійсні", +"You need to enter either an existing account or the administrator." => "Вам потрібно ввести або існуючий обліковий запис або administrator.", +"Oracle username and/or password not valid" => "Oracle ім'я користувача та/або пароль не дійсні", +"MySQL username and/or password not valid" => "MySQL ім'я користувача та/або пароль не дійсні", +"DB Error: \"%s\"" => "Помилка БД: \"%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.", +"Offending command was: \"%s\", name: %s, password: %s" => "Команда, що викликала проблему: \"%s\", ім'я: %s, пароль: %s", +"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>.", "seconds ago" => "секунди тому", "1 minute ago" => "1 хвилину тому", "%d minutes ago" => "%d хвилин тому", diff --git a/lib/l10n/ur_PK.php b/lib/l10n/ur_PK.php new file mode 100644 index 00000000000..7e09d79bc68 --- /dev/null +++ b/lib/l10n/ur_PK.php @@ -0,0 +1,8 @@ +<?php $TRANSLATIONS = array( +"Help" => "مدد", +"Personal" => "ذاتی", +"Settings" => "سیٹینگز", +"Users" => "یوزرز", +"Apps" => "ایپز", +"Admin" => "ایڈمن" +); diff --git a/lib/l10n/vi.php b/lib/l10n/vi.php index 8b7242ae611..ea9660093ae 100644 --- a/lib/l10n/vi.php +++ b/lib/l10n/vi.php @@ -9,6 +9,7 @@ "Files need to be downloaded one by one." => "Tập tin cần phải được tải về từng người một.", "Back to Files" => "Trở lại tập tin", "Selected files too large to generate zip file." => "Tập tin được chọn quá lớn để tạo tập tin ZIP.", +"couldn't be determined" => "không thể phát hiện được", "Application is not enabled" => "Ứng dụng không được BẬT", "Authentication error" => "Lỗi xác thực", "Token expired. Please reload page." => "Mã Token đã hết hạn. Hãy tải lại trang.", diff --git a/lib/l10n/zh_TW.php b/lib/l10n/zh_TW.php index 62ab8fedd52..91b0329e246 100644 --- a/lib/l10n/zh_TW.php +++ b/lib/l10n/zh_TW.php @@ -16,6 +16,8 @@ "Files" => "檔案", "Text" => "文字", "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>。", "seconds ago" => "幾秒前", "1 minute ago" => "1 分鐘前", "%d minutes ago" => "%d 分鐘前", diff --git a/lib/log.php b/lib/log.php index e869282e88c..3f3334801e5 100644 --- a/lib/log.php +++ b/lib/log.php @@ -53,7 +53,9 @@ class OC_Log { // Uncaught exception handler public static function onException($exception) { - self::write('PHP', $exception->getMessage() . ' at ' . $exception->getFile() . '#' . $exception->getLine(), self::FATAL); + self::write('PHP', + $exception->getMessage() . ' at ' . $exception->getFile() . '#' . $exception->getLine(), + self::FATAL); } //Recoverable errors handler diff --git a/lib/log/owncloud.php b/lib/log/owncloud.php index e53dd5fefcd..20df52c27bb 100644 --- a/lib/log/owncloud.php +++ b/lib/log/owncloud.php @@ -81,7 +81,8 @@ class OC_Log_Owncloud { $ch = fgetc($handle); if ($ch == "\n" || $pos == 0) { if ($line != '') { - // Add the first character if at the start of the file, because it doesn't hit the else in the loop + // Add the first character if at the start of the file, + // because it doesn't hit the else in the loop if ($pos == 0) { $line = $ch.$line; } diff --git a/lib/mail.php b/lib/mail.php index 1bb202ac977..22194045a76 100644 --- a/lib/mail.php +++ b/lib/mail.php @@ -32,7 +32,8 @@ class OC_Mail { * @param string $bcc * @throws Exception */ - public static function send($toaddress,$toname,$subject,$mailtext,$fromaddress,$fromname,$html=0,$altbody='',$ccaddress='',$ccname='', $bcc='') { + public static function send($toaddress, $toname, $subject, $mailtext, $fromaddress, $fromname, + $html=0, $altbody='', $ccaddress='', $ccname='', $bcc='') { $SMTPMODE = OC_Config::getValue( 'mail_smtpmode', 'sendmail' ); $SMTPHOST = OC_Config::getValue( 'mail_smtphost', '127.0.0.1' ); @@ -97,7 +98,9 @@ class OC_Mail { $mailo->Send(); unset($mailo); - OC_Log::write('mail', 'Mail from '.$fromname.' ('.$fromaddress.')'.' to: '.$toname.'('.$toaddress.')'.' subject: '.$subject, OC_Log::DEBUG); + OC_Log::write('mail', + 'Mail from '.$fromname.' ('.$fromaddress.')'.' to: '.$toname.'('.$toaddress.')'.' subject: '.$subject, + OC_Log::DEBUG); } catch (Exception $exception) { OC_Log::write('mail', $exception->getMessage(), OC_Log::ERROR); throw($exception); diff --git a/lib/migrate.php b/lib/migrate.php index 87bdd016fe4..a0a329705a3 100644 --- a/lib/migrate.php +++ b/lib/migrate.php @@ -167,7 +167,19 @@ class OC_Migrate{ self::$content = new OC_Migration_Content( self::$zip ); // Creates a zip with the owncloud system files self::$content->addDir( OC::$SERVERROOT . '/', false, '/'); - foreach (array(".git", "3rdparty", "apps", "core", "files", "l10n", "lib", "ocs", "search", "settings", "tests") as $dir) { + foreach (array( + ".git", + "3rdparty", + "apps", + "core", + "files", + "l10n", + "lib", + "ocs", + "search", + "settings", + "tests" + ) as $dir) { self::$content->addDir( OC::$SERVERROOT . '/' . $dir, true, "/"); } break; @@ -181,7 +193,7 @@ class OC_Migrate{ return json_encode( array( 'success' => false ) ); } return json_encode( array( 'success' => true, 'data' => self::$zippath ) ); - } + } /** * @brief imports a user, or owncloud instance @@ -245,7 +257,9 @@ class OC_Migrate{ } // Import user app data if(file_exists($extractpath . $json->exporteduser . '/migration.db')) { - if( !$appsimported = self::importAppData( $extractpath . $json->exporteduser . '/migration.db', $json, self::$uid ) ) { + if( !$appsimported = self::importAppData( $extractpath . $json->exporteduser . '/migration.db', + $json, + self::$uid ) ) { return json_encode( array( 'success' => false ) ); } } @@ -553,7 +567,9 @@ class OC_Migrate{ return false; } if ( self::$zip->open( self::$zippath, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE ) !== true ) { - OC_Log::write('migration', 'Failed to create the zip with error: '.self::$zip->getStatusString(), OC_Log::ERROR); + OC_Log::write('migration', + 'Failed to create the zip with error: '.self::$zip->getStatusString(), + OC_Log::ERROR); return false; } else { return true; @@ -610,7 +626,9 @@ class OC_Migrate{ if( isset( $info->apps->$id ) ) { // Is the app installed if( !OC_App::isEnabled( $id ) ) { - OC_Log::write( 'migration', 'App: ' . $id . ' is not installed, can\'t import data.', OC_Log::INFO ); + OC_Log::write( 'migration', + 'App: ' . $id . ' is not installed, can\'t import data.', + OC_Log::INFO ); $appsstatus[$id] = 'notsupported'; } else { // Did it succeed on export? @@ -624,7 +642,9 @@ class OC_Migrate{ // Then do the import if( !$appsstatus[$id] = $provider->import( $info->apps->$id, $importinfo ) ) { // Failed to import app - OC_Log::write( 'migration', 'Failed to import app data for user: ' . self::$uid . ' for app: ' . $id, OC_Log::ERROR ); + OC_Log::write( 'migration', + 'Failed to import app data for user: ' . self::$uid . ' for app: ' . $id, + OC_Log::ERROR ); } } else { // Add to failed list diff --git a/lib/migration/content.php b/lib/migration/content.php index e81c8f217ff..400a46a4340 100644 --- a/lib/migration/content.php +++ b/lib/migration/content.php @@ -185,13 +185,13 @@ class OC_Migration_Content{ * @return bool */ public function addDir( $dir, $recursive=true, $internaldir='' ) { - $dirname = basename($dir); - $this->zip->addEmptyDir($internaldir . $dirname); - $internaldir.=$dirname.='/'; + $dirname = basename($dir); + $this->zip->addEmptyDir($internaldir . $dirname); + $internaldir.=$dirname.='/'; if( !file_exists( $dir ) ) { return false; } - if ($dirhandle = opendir($dir)) { + if ($dirhandle = opendir($dir)) { while (false !== ( $file = readdir($dirhandle))) { if (( $file != '.' ) && ( $file != '..' )) { @@ -204,11 +204,11 @@ class OC_Migration_Content{ } } closedir($dirhandle); - } else { + } else { OC_Log::write('admin_export', "Was not able to open directory: " . $dir, OC_Log::ERROR); return false; - } - return true; + } + return true; } /** @@ -236,7 +236,9 @@ class OC_Migration_Content{ */ public function finish() { if( !$this->zip->close() ) { - OC_Log::write( 'migration', 'Failed to write the zip file with error: '.$this->zip->getStatusString(), OC_Log::ERROR ); + OC_Log::write( 'migration', + 'Failed to write the zip file with error: '.$this->zip->getStatusString(), + OC_Log::ERROR ); return false; } $this->cleanup(); diff --git a/lib/mimetypes.list.php b/lib/mimetypes.list.php index fc87d011ecd..86ce9c6c237 100644 --- a/lib/mimetypes.list.php +++ b/lib/mimetypes.list.php @@ -97,4 +97,6 @@ return array( 'ai' => 'application/illustrator', 'epub' => 'application/epub+zip', 'mobi' => 'application/x-mobipocket-ebook', + 'exe' => 'application', + 'msi' => 'application' ); diff --git a/lib/ocs.php b/lib/ocs.php index 879aaa76687..93e8931ce2e 100644 --- a/lib/ocs.php +++ b/lib/ocs.php @@ -87,9 +87,10 @@ class OC_OCS { } $format = self::readData($method, 'format', 'text', ''); - $txt='Invalid query, please check the syntax. API specifications are here: http://www.freedesktop.org/wiki/Specifications/open-collaboration-services. DEBUG OUTPUT:'."\n"; + $txt='Invalid query, please check the syntax. API specifications are here:' + .' http://www.freedesktop.org/wiki/Specifications/open-collaboration-services. DEBUG OUTPUT:'."\n"; $txt.=OC_OCS::getDebugOutput(); - echo(OC_OCS::generateXml($format,'failed',999,$txt)); + echo(OC_OCS::generateXml($format, 'failed', 999, $txt)); } @@ -122,7 +123,8 @@ class OC_OCS { * @param int $itemsperpage * @return string xml/json */ - private static function generateXml($format, $status, $statuscode, $message, $data=array(), $tag='', $tagattribute='', $dimension=-1, $itemscount='', $itemsperpage='') { + private static function generateXml($format, $status, $statuscode, + $message, $data=array(), $tag='', $tagattribute='', $dimension=-1, $itemscount='', $itemsperpage='') { if($format=='json') { $json=array(); $json['status']=$status; @@ -173,7 +175,7 @@ class OC_OCS { } } xmlwriter_end_element($writer); - } + } xmlwriter_end_element($writer); }elseif($dimension=='3') { diff --git a/lib/ocs/privatedata.php b/lib/ocs/privatedata.php index 311b24269dd..4dfd0a6e66e 100644 --- a/lib/ocs/privatedata.php +++ b/lib/ocs/privatedata.php @@ -29,7 +29,7 @@ class OC_OCS_Privatedata { $user = OC_User::getUser(); $app = addslashes(strip_tags($parameters['app'])); $key = addslashes(strip_tags($parameters['key'])); - $result = OC_OCS::getData($user,$app,$key); + $result = OC_OCS::getData($user, $app, $key); $xml = array(); foreach($result as $i=>$log) { $xml[$i]['key']=$log['key']; @@ -46,7 +46,7 @@ class OC_OCS_Privatedata { $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)){ + if(OC_Preferences::setValue($user, $app, $key, $value)) { return new OC_OCS_Result(null, 100); } } diff --git a/lib/ocsclient.php b/lib/ocsclient.php index 30163c1e403..bd0302a2a81 100644 --- a/lib/ocsclient.php +++ b/lib/ocsclient.php @@ -32,7 +32,8 @@ class OC_OCSClient{ * @brief Get the url of the OCS AppStore server. * @returns string of the AppStore server * - * This function returns the url of the OCS AppStore server. It´s possible to set it in the config file or it will fallback to the default + * This function returns the url of the OCS AppStore server. It´s possible + * to set it in the config file or it will fallback to the default */ private static function getAppStoreURL() { $url = OC_Config::getValue('appstoreurl', 'http://api.apps.owncloud.com/v1'); @@ -42,7 +43,8 @@ class OC_OCSClient{ /** * @brief Get the url of the OCS KB server. * @returns string of the KB server - * This function returns the url of the OCS knowledge base server. It´s possible to set it in the config file or it will fallback to the default + * This function returns the url of the OCS knowledge base server. It´s + * possible to set it in the config file or it will fallback to the default */ private static function getKBURL() { $url = OC_Config::getValue('knowledgebaseurl', 'http://api.apps.owncloud.com/v1'); @@ -109,7 +111,8 @@ class OC_OCSClient{ $version='&version='.implode('x', \OC_Util::getVersion()); $filterurl='&filter='.urlencode($filter); - $url=OC_OCSClient::getAppStoreURL().'/content/data?categories='.urlencode($categoriesstring).'&sortmode=new&page='.urlencode($page).'&pagesize=100'.$filterurl.$version; + $url=OC_OCSClient::getAppStoreURL().'/content/data?categories='.urlencode($categoriesstring) + .'&sortmode=new&page='.urlencode($page).'&pagesize=100'.$filterurl.$version; $apps=array(); $xml=OC_OCSClient::getOCSresponse($url); diff --git a/lib/preferences.php b/lib/preferences.php index 6270457834d..5f6434bcf9c 100644 --- a/lib/preferences.php +++ b/lib/preferences.php @@ -114,7 +114,8 @@ class OC_Preferences{ */ public static function getValue( $user, $app, $key, $default = null ) { // Try to fetch the value, return default if not exists. - $query = OC_DB::prepare( 'SELECT `configvalue` FROM `*PREFIX*preferences` WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?' ); + $query = OC_DB::prepare( 'SELECT `configvalue` FROM `*PREFIX*preferences`' + .' WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?' ); $result = $query->execute( array( $user, $app, $key )); $row = $result->fetchRow(); @@ -138,16 +139,19 @@ class OC_Preferences{ */ public static function setValue( $user, $app, $key, $value ) { // Check if the key does exist - $query = OC_DB::prepare( 'SELECT `configvalue` FROM `*PREFIX*preferences` WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?' ); + $query = OC_DB::prepare( 'SELECT `configvalue` FROM `*PREFIX*preferences`' + .' WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?' ); $values=$query->execute(array($user, $app, $key))->fetchAll(); $exists=(count($values)>0); if( !$exists ) { - $query = OC_DB::prepare( 'INSERT INTO `*PREFIX*preferences` ( `userid`, `appid`, `configkey`, `configvalue` ) VALUES( ?, ?, ?, ? )' ); + $query = OC_DB::prepare( 'INSERT INTO `*PREFIX*preferences`' + .' ( `userid`, `appid`, `configkey`, `configvalue` ) VALUES( ?, ?, ?, ? )' ); $query->execute( array( $user, $app, $key, $value )); } else{ - $query = OC_DB::prepare( 'UPDATE `*PREFIX*preferences` SET `configvalue` = ? WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?' ); + $query = OC_DB::prepare( 'UPDATE `*PREFIX*preferences` SET `configvalue` = ?' + .' WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?' ); $query->execute( array( $value, $user, $app, $key )); } return true; @@ -164,7 +168,8 @@ class OC_Preferences{ */ public static function deleteKey( $user, $app, $key ) { // No need for more comments - $query = OC_DB::prepare( 'DELETE FROM `*PREFIX*preferences` WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?' ); + $query = OC_DB::prepare( 'DELETE FROM `*PREFIX*preferences`' + .' WHERE `userid` = ? AND `appid` = ? AND `configkey` = ?' ); $query->execute( array( $user, $app, $key )); return true; diff --git a/lib/public/api.php b/lib/public/api.php index 95d333f2165..d94b68e908a 100644 --- a/lib/public/api.php +++ b/lib/public/api.php @@ -37,7 +37,8 @@ class API { * @param array $defaults * @param array $requirements */ - public static function register($method, $url, $action, $app, $authLevel = OC_API::USER_AUTH, $defaults = array(), $requirements = array()){ + public static function register($method, $url, $action, $app, $authLevel = OC_API::USER_AUTH, + $defaults = array(), $requirements = array()){ \OC_API::register($method, $url, $action, $app, $authLevel, $defaults, $requirements); } diff --git a/lib/public/config.php b/lib/public/config.php index 1f163d52617..8076d640b49 100644 --- a/lib/public/config.php +++ b/lib/public/config.php @@ -35,7 +35,8 @@ namespace OCP; /** - * This class provides functions to read and write configuration data. configuration can be on a system, application or user level + * This class provides functions to read and write configuration data. + * configuration can be on a system, application or user level */ class Config { /** diff --git a/lib/public/files.php b/lib/public/files.php index f6b3e0ee38a..700bf574537 100644 --- a/lib/public/files.php +++ b/lib/public/files.php @@ -31,7 +31,8 @@ namespace OCP; /** - * This class provides access to the internal filesystem abstraction layer. Use this class exlusively if you want to access files + * This class provides access to the internal filesystem abstraction layer. Use + * this class exlusively if you want to access files */ class Files { /** @@ -61,7 +62,8 @@ class Files { * @return int the number of bytes copied */ public static function streamCopy( $source, $target ) { - return(\OC_Helper::streamCopy( $source, $target )); + list($count, $result) = \OC_Helper::streamCopy( $source, $target ); + return $count; } /** diff --git a/lib/public/iaddressbook.php b/lib/public/iaddressbook.php index 14943747f48..77e8750d9da 100644 --- a/lib/public/iaddressbook.php +++ b/lib/public/iaddressbook.php @@ -43,22 +43,22 @@ namespace OCP { * @return array of contacts which are arrays of key-value-pairs */ public function search($pattern, $searchProperties, $options); -// // dummy results -// return array( -// array('id' => 0, 'FN' => 'Thomas Müller', 'EMAIL' => 'a@b.c', 'GEO' => '37.386013;-122.082932'), -// array('id' => 5, 'FN' => 'Thomas Tanghus', 'EMAIL' => array('d@e.f', 'g@h.i')), -// ); + // // dummy results + // return array( + // array('id' => 0, 'FN' => 'Thomas Müller', 'EMAIL' => 'a@b.c', 'GEO' => '37.386013;-122.082932'), + // array('id' => 5, 'FN' => 'Thomas Tanghus', 'EMAIL' => array('d@e.f', 'g@h.i')), + // ); /** * @param array $properties this array if key-value-pairs defines a contact * @return array representing the contact just created or updated */ public function createOrUpdate($properties); -// // dummy -// return array('id' => 0, 'FN' => 'Thomas Müller', 'EMAIL' => 'a@b.c', -// 'PHOTO' => 'VALUE=uri:http://www.abc.com/pub/photos/jqpublic.gif', -// 'ADR' => ';;123 Main Street;Any Town;CA;91921-1234' -// ); + // // dummy + // return array('id' => 0, 'FN' => 'Thomas Müller', 'EMAIL' => 'a@b.c', + // 'PHOTO' => 'VALUE=uri:http://www.abc.com/pub/photos/jqpublic.gif', + // 'ADR' => ';;123 Main Street;Any Town;CA;91921-1234' + // ); /** * @return mixed diff --git a/lib/public/share.php b/lib/public/share.php index af2a538e252..8146a23f360 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -37,10 +37,17 @@ 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 + * 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 */ @@ -54,6 +61,7 @@ class Share { private static $shareTypeGroupUserUnique = 2; private static $backends = array(); private static $backendTypes = array(); + private static $isResharingAllowed; /** * @brief Register a sharing backend class that implements OCP\Share_Backend for an item type @@ -66,14 +74,21 @@ class Share { public static function registerBackend($itemType, $class, $collectionOf = null, $supportedFileExtensions = null) { if (self::isEnabled()) { if (!isset(self::$backendTypes[$itemType])) { - self::$backendTypes[$itemType] = array('class' => $class, 'collectionOf' => $collectionOf, 'supportedFileExtensions' => $supportedFileExtensions); + self::$backendTypes[$itemType] = array( + 'class' => $class, + 'collectionOf' => $collectionOf, + 'supportedFileExtensions' => $supportedFileExtensions + ); if(count(self::$backendTypes) === 1) { \OC_Util::addScript('core', 'share'); \OC_Util::addStyle('core', 'share'); } return true; } - \OC_Log::write('OCP\Share', 'Sharing backend '.$class.' not registered, '.self::$backendTypes[$itemType]['class'].' is already registered for '.$itemType, \OC_Log::WARN); + \OC_Log::write('OCP\Share', + 'Sharing backend '.$class.' not registered, '.self::$backendTypes[$itemType]['class'] + .' is already registered for '.$itemType, + \OC_Log::WARN); } return false; } @@ -99,8 +114,10 @@ class Share { * @param int Number of items to return (optional) Returns all by default * @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, $parameters, $limit, $includeCollections); + 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, + $parameters, $limit, $includeCollections); } /** @@ -110,8 +127,10 @@ class Share { * @param int Format (optional) Format type must be defined by the backend * @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, $parameters, 1, $includeCollections); + 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, + $parameters, 1, $includeCollections); } /** @@ -121,8 +140,10 @@ class Share { * @param int Format (optional) Format type must be defined by the backend * @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, $parameters, 1, $includeCollections, true); + 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, + $parameters, 1, $includeCollections, true); } /** @@ -133,7 +154,8 @@ class Share { * @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); + return self::getItems($itemType, $itemSource, self::SHARE_TYPE_LINK, null, $uidOwner, self::FORMAT_NONE, + null, 1); } /** @@ -142,7 +164,7 @@ class Share { * @return Item */ public static function getShareByToken($token) { - $query = \OC_DB::prepare('SELECT * FROM `*PREFIX*share` WHERE `token` = ?',1); + $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); @@ -157,8 +179,10 @@ class Share { * @param int Number of items to return (optional) Returns all by default * @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, $parameters, $limit, $includeCollections); + 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, + $parameters, $limit, $includeCollections); } /** @@ -168,8 +192,10 @@ class Share { * @param int Format (optional) Format type must be defined by the backend * @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, $parameters, -1, $includeCollections); + 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, + $parameters, -1, $includeCollections); } /** @@ -199,14 +225,18 @@ class Share { 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 '.$shareWith.' is not a member of any groups that '.$uidOwner.' is a member of'; + $message = 'Sharing '.$itemSource.' 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); } } // Check if the item source is already shared with the user, either from the same owner or a different user - if ($checkExists = self::getItems($itemType, $itemSource, self::$shareTypeUserAndGroups, $shareWith, null, self::FORMAT_NONE, null, 1, true, true)) { - // Only allow the same share to occur again if it is the same owner and is not a user share, this use case is for increasing permissions for a specific user + if ($checkExists = self::getItems($itemType, $itemSource, self::$shareTypeUserAndGroups, + $shareWith, null, self::FORMAT_NONE, null, 1, true, true)) { + // Only allow the same share to occur again if it is the same + // 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; \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR); @@ -220,14 +250,18 @@ class Share { throw new \Exception($message); } if ($sharingPolicy == 'groups_only' && !\OC_Group::inGroup($uidOwner, $shareWith)) { - $message = 'Sharing '.$itemSource.' failed, because '.$uidOwner.' is not a member of the group '.$shareWith; + $message = 'Sharing '.$itemSource.' failed, because ' + .$uidOwner.' is not a member of the group '.$shareWith; \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR); throw new \Exception($message); } // Check if the item source is already shared with the group, either from the same owner or a different user // The check for each user in the group is done inside the put() function - if ($checkExists = self::getItems($itemType, $itemSource, self::SHARE_TYPE_GROUP, $shareWith, null, self::FORMAT_NONE, null, 1, true, true)) { - // Only allow the same share to occur again if it is the same owner and is not a group share, this use case is for increasing permissions for a specific user + if ($checkExists = self::getItems($itemType, $itemSource, self::SHARE_TYPE_GROUP, $shareWith, + null, self::FORMAT_NONE, null, 1, true, true)) { + // Only allow the same share to occur again if it is the same + // 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; \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR); @@ -242,7 +276,8 @@ class Share { } else if ($shareType === self::SHARE_TYPE_LINK) { if (\OC_Appconfig::getValue('core', 'shareapi_allow_links', 'yes') == 'yes') { // when updating a link share - if ($checkExists = self::getItems($itemType, $itemSource, self::SHARE_TYPE_LINK, null, $uidOwner, self::FORMAT_NONE, null, 1)) { + if ($checkExists = self::getItems($itemType, $itemSource, self::SHARE_TYPE_LINK, null, + $uidOwner, self::FORMAT_NONE, null, 1)) { // remember old token $oldToken = $checkExists['token']; //delete the old share @@ -262,7 +297,8 @@ class Share { } else { $token = \OC_Util::generate_random_bytes(self::TOKEN_LENGTH); } - $result = self::put($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions, null, $token); + $result = self::put($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions, + null, $token); if ($result) { return $token; } else { @@ -341,14 +377,15 @@ class Share { * @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)) { + 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, 'shareType' => $shareType, 'shareWith' => $shareWith, - )); + )); self::delete($item['id']); return true; } @@ -368,7 +405,7 @@ class Share { 'itemType' => $itemType, 'itemSource' => $itemSource, 'shares' => $shares - )); + )); foreach ($shares as $share) { self::delete($share['id']); } @@ -389,9 +426,16 @@ class Share { public static function unshareFromSelf($itemType, $itemTarget) { if ($item = self::getItemSharedWith($itemType, $itemTarget)) { if ((int)$item['share_type'] === self::SHARE_TYPE_GROUP) { - // Insert an extra row for the group share and set permission to 0 to prevent it from showing up for the user - $query = \OC_DB::prepare('INSERT INTO `*PREFIX*share` (`item_type`, `item_source`, `item_target`, `parent`, `share_type`, `share_with`, `uid_owner`, `permissions`, `stime`, `file_source`, `file_target`) VALUES (?,?,?,?,?,?,?,?,?,?,?)'); - $query->execute(array($item['item_type'], $item['item_source'], $item['item_target'], $item['id'], self::$shareTypeGroupUserUnique, \OC_User::getUser(), $item['uid_owner'], 0, $item['stime'], $item['file_source'], $item['file_target'])); + // Insert an extra row for the group share and set permission + // to 0 to prevent it from showing up for the user + $query = \OC_DB::prepare('INSERT INTO `*PREFIX*share`' + .' (`item_type`, `item_source`, `item_target`, `parent`, `share_type`,' + .' `share_with`, `uid_owner`, `permissions`, `stime`, `file_source`, `file_target`)' + .' VALUES (?,?,?,?,?,?,?,?,?,?,?)'); + $query->execute(array($item['item_type'], $item['item_source'], $item['item_target'], + $item['id'], self::$shareTypeGroupUserUnique, + \OC_User::getUser(), $item['uid_owner'], 0, $item['stime'], $item['file_source'], + $item['file_target'])); \OC_DB::insertid('*PREFIX*share'); // Delete all reshares by this user of the group share self::delete($item['id'], true, \OC_User::getUser()); @@ -418,13 +462,16 @@ class Share { * @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)) { - // Check if this item is a reshare and verify that the permissions granted don't exceed the parent shared item + if ($item = self::getItems($itemType, $itemSource, $shareType, $shareWith, + \OC_User::getUser(), self::FORMAT_NONE, null, 1, false)) { + // Check if this item is a reshare and verify that the permissions + // granted don't exceed the parent shared item if (isset($item['parent'])) { $query = \OC_DB::prepare('SELECT `permissions` FROM `*PREFIX*share` WHERE `id` = ?', 1); $result = $query->execute(array($item['parent']))->fetchRow(); if (~(int)$result['permissions'] & $permissions) { - $message = 'Setting permissions for '.$itemSource.' failed, because the permissions exceed permissions granted to '.\OC_User::getUser(); + $message = 'Setting permissions for '.$itemSource.' failed,' + .' because the permissions exceed permissions granted to '.\OC_User::getUser(); \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR); throw new \Exception($message); } @@ -441,9 +488,11 @@ class Share { $parents = array($item['id']); while (!empty($parents)) { $parents = "'".implode("','", $parents)."'"; - $query = \OC_DB::prepare('SELECT `id`, `permissions` FROM `*PREFIX*share` WHERE `parent` IN ('.$parents.')'); + $query = \OC_DB::prepare('SELECT `id`, `permissions` FROM `*PREFIX*share`' + .' WHERE `parent` IN ('.$parents.')'); $result = $query->execute(); - // Reset parents array, only go through loop again if items are found that need permissions removed + // Reset parents array, only go through loop again if + // items are found that need permissions removed $parents = array(); while ($item = $result->fetchRow()) { // Check if permissions need to be removed @@ -457,7 +506,8 @@ class Share { // Remove the permissions for all reshares of this item if (!empty($ids)) { $ids = "'".implode("','", $ids)."'"; - $query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `permissions` = `permissions` & ? WHERE `id` IN ('.$ids.')'); + $query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `permissions` = `permissions` & ?' + .' WHERE `id` IN ('.$ids.')'); $query->execute(array($permissions)); } } @@ -470,7 +520,8 @@ class Share { } public static function setExpirationDate($itemType, $itemSource, $date) { - if ($items = self::getItems($itemType, $itemSource, null, null, \OC_User::getUser(), self::FORMAT_NONE, null, -1, false)) { + if ($items = self::getItems($itemType, $itemSource, null, null, \OC_User::getUser(), + self::FORMAT_NONE, null, -1, false)) { if (!empty($items)) { if ($date == '') { $date = null; @@ -518,6 +569,24 @@ class Share { } /** + * @brief 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') { + self::$isResharingAllowed = true; + } else { + self::$isResharingAllowed = false; + } + } + return self::$isResharingAllowed; + } + + /** * @brief Get a list of collection item types for the specified item type * @param string Item type * @return array @@ -533,7 +602,8 @@ class Share { if (!self::getBackend($itemType) instanceof Share_Backend_Collection || $itemType != 'folder') { unset($collectionTypes[0]); } - // Return array if collections were found or the item type is a collection itself - collections can be inside collections + // Return array if collections were found or the item type is a + // collection itself - collections can be inside collections if (count($collectionTypes) > 0) { return $collectionTypes; } @@ -556,7 +626,9 @@ class Share { * 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) { + 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) { if (!self::isEnabled()) { if ($limit == 1 || (isset($uidOwner) && isset($item))) { return false; @@ -565,7 +637,8 @@ class Share { } } $backend = self::getBackend($itemType); - // Get filesystem root to add it to the file target and remove from the file source, match file_source with the file cache + // Get filesystem root to add it to the file target and remove from the + // file source, match file_source with the file cache if ($itemType == 'file' || $itemType == 'folder') { $root = \OC\Files\Filesystem::getRoot(); $where = 'INNER JOIN `*PREFIX*filecache` ON `file_source` = `*PREFIX*filecache`.`fileid`'; @@ -668,7 +741,8 @@ class Share { } if ($limit != -1 && !$includeCollections) { if ($shareType == self::$shareTypeUserAndGroups) { - // Make sure the unique user target is returned if it exists, unique targets should follow the group share in the database + // Make sure the unique user target is returned if it exists, + // unique targets should follow the group share in the database // If the limit is not 1, the filtering can be done later $where .= ' ORDER BY `*PREFIX*share`.`id` DESC'; } @@ -684,16 +758,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`'; + $select = '`*PREFIX*share`.`id`, `item_type`, `*PREFIX*share`.`parent`,' + .' `share_type`, `file_source`, `path`, `expiration`'; } else { $select = '`id`, `item_type`, `item_source`, `parent`, `share_type`, `expiration`'; } } else { if (isset($uidOwner)) { if ($itemType == 'file' || $itemType == 'folder') { - $select = '`*PREFIX*share`.`id`, `item_type`, `*PREFIX*share`.`parent`, `share_type`, `share_with`, `file_source`, `path`, `permissions`, `stime`, `expiration`, `token`'; + $select = '`*PREFIX*share`.`id`, `item_type`, `*PREFIX*share`.`parent`,' + .' `share_type`, `share_with`, `file_source`, `path`, `permissions`, `stime`,' + .' `expiration`, `token`'; } else { - $select = '`id`, `item_type`, `item_source`, `parent`, `share_type`, `share_with`, `permissions`, `stime`, `file_source`, `expiration`, `token`'; + $select = '`id`, `item_type`, `item_source`, `parent`, `share_type`, `share_with`, `permissions`,' + .' `stime`, `file_source`, `expiration`, `token`'; } } else { if ($fileDependent) { @@ -702,11 +780,13 @@ class Share { || $format == \OC_Share_Backend_File::FORMAT_FILE_APP_ROOT ) { $select = '`*PREFIX*share`.`id`, `item_type`, `*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`'; + .'`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`'; } 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`'; + $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`'; } } else { $select = '*'; @@ -717,7 +797,9 @@ class Share { $query = \OC_DB::prepare('SELECT '.$select.' FROM `*PREFIX*share` '.$where, $queryLimit); $result = $query->execute($queryArgs); if (\OC_DB::isError($result)) { - \OC_Log::write('OCP\Share', \OC_DB::getErrorMessage($result) . ', select=' . $select . ' where=' . $where, \OC_Log::ERROR); + \OC_Log::write('OCP\Share', + \OC_DB::getErrorMessage($result) . ', select=' . $select . ' where=' . $where, + \OC_Log::ERROR); } $items = array(); $targets = array(); @@ -735,7 +817,8 @@ class Share { } else if (!isset($uidOwner)) { // Check if the same target already exists if (isset($targets[$row[$column]])) { - // Check if the same owner shared with the user twice through a group and user share - this is allowed + // Check if the same owner shared with the user twice + // through a group and user share - this is allowed $id = $targets[$row[$column]]; if ($items[$id]['uid_owner'] == $row['uid_owner']) { // Switch to group share type to ensure resharing conditions aren't bypassed @@ -743,8 +826,10 @@ class Share { $items[$id]['share_type'] = self::SHARE_TYPE_GROUP; $items[$id]['share_with'] = $row['share_with']; } - // Switch ids if sharing permission is granted on only one share to ensure correct parent is used if resharing - if (~(int)$items[$id]['permissions'] & PERMISSION_SHARE && (int)$row['permissions'] & PERMISSION_SHARE) { + // Switch ids if sharing permission is granted on only + // one share to ensure correct parent is used if resharing + if (~(int)$items[$id]['permissions'] & PERMISSION_SHARE + && (int)$row['permissions'] & PERMISSION_SHARE) { $items[$row['id']] = $items[$id]; $switchedItems[$id] = $row['id']; unset($items[$id]); @@ -774,7 +859,10 @@ class Share { continue; } } - + // Check if resharing is allowed, if not remove share permission + if (isset($row['permissions']) && !self::isResharingAllowed()) { + $row['permissions'] &= ~PERMISSION_SHARE; + } // Add display names to result if ( isset($row['share_with']) && $row['share_with'] != '') { $row['share_with_displayname'] = \OCP\User::getDisplayName($row['share_with']); @@ -782,7 +870,7 @@ class Share { if ( isset($row['uid_owner']) && $row['uid_owner'] != '') { $row['displayname_owner'] = \OCP\User::getDisplayName($row['uid_owner']); } - + $items[$row['id']] = $row; } if (!empty($items)) { @@ -798,7 +886,8 @@ class Share { } // Check if this is a collection of the requested item type if ($includeCollections && $collectionTypes && in_array($row['item_type'], $collectionTypes)) { - if (($collectionBackend = self::getBackend($row['item_type'])) && $collectionBackend instanceof Share_Backend_Collection) { + if (($collectionBackend = self::getBackend($row['item_type'])) + && $collectionBackend instanceof Share_Backend_Collection) { // Collections can be inside collections, check if the item is a collection if (isset($item) && $row['item_type'] == $itemType && $row[$column] == $item) { $collectionItems[] = $row; @@ -825,7 +914,8 @@ class Share { $meta = \OC\Files\Filesystem::getFileInfo($child['file_path']); $childItem['file_source'] = $meta['fileid']; } - $childItem['file_target'] = \OC\Files\Filesystem::normalizePath($child['file_path']); + $childItem['file_target'] = + \OC\Files\Filesystem::normalizePath($child['file_path']); } if (isset($item)) { if ($childItem[$column] == $item) { @@ -898,7 +988,8 @@ class Share { * @param bool|array Parent folder target (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) { + private static function put($itemType, $itemSource, $shareType, $shareWith, $uidOwner, + $permissions, $parentFolder = null, $token = null) { $backend = self::getBackend($itemType); // Check if this is a reshare if ($checkReshare = self::getItemSharedWithBySource($itemType, $itemSource, self::FORMAT_NONE, null, true)) { @@ -909,9 +1000,10 @@ class Share { throw new \Exception($message); } // Check if share permissions is granted - if ((int)$checkReshare['permissions'] & PERMISSION_SHARE) { + if (self::isResharingAllowed() && (int)$checkReshare['permissions'] & PERMISSION_SHARE) { if (~(int)$checkReshare['permissions'] & $permissions) { - $message = 'Sharing '.$itemSource.' failed, because the permissions exceed permissions granted to '.$uidOwner; + $message = 'Sharing '.$itemSource + .' failed, because the permissions exceed permissions granted to '.$uidOwner; \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR); throw new \Exception($message); } else { @@ -933,7 +1025,8 @@ class Share { $suggestedItemTarget = null; $suggestedFileTarget = null; if (!$backend->isValidSource($itemSource, $uidOwner)) { - $message = 'Sharing '.$itemSource.' failed, because the sharing backend for '.$itemType.' could not find its source'; + $message = 'Sharing '.$itemSource.' failed, because the sharing backend for ' + .$itemType.' could not find its source'; \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR); throw new \Exception($message); } @@ -956,14 +1049,18 @@ class Share { $fileSource = null; } } - $query = \OC_DB::prepare('INSERT INTO `*PREFIX*share` (`item_type`, `item_source`, `item_target`, `parent`, `share_type`, `share_with`, `uid_owner`, `permissions`, `stime`, `file_source`, `file_target`, `token`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)'); + $query = \OC_DB::prepare('INSERT INTO `*PREFIX*share` (`item_type`, `item_source`, `item_target`,' + .' `parent`, `share_type`, `share_with`, `uid_owner`, `permissions`, `stime`, `file_source`,' + .' `file_target`, `token`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)'); // Share with a group if ($shareType == self::SHARE_TYPE_GROUP) { - $groupItemTarget = self::generateTarget($itemType, $itemSource, $shareType, $shareWith['group'], $uidOwner, $suggestedItemTarget); + $groupItemTarget = self::generateTarget($itemType, $itemSource, $shareType, $shareWith['group'], + $uidOwner, $suggestedItemTarget); if (isset($fileSource)) { if ($parentFolder) { if ($parentFolder === true) { - $groupFileTarget = self::generateTarget('file', $filePath, $shareType, $shareWith['group'], $uidOwner, $suggestedFileTarget); + $groupFileTarget = self::generateTarget('file', $filePath, $shareType, + $shareWith['group'], $uidOwner, $suggestedFileTarget); // Set group default file target for future use $parentFolders[0]['folder'] = $groupFileTarget; } else { @@ -972,21 +1069,25 @@ class Share { $parent = $parentFolder[0]['id']; } } else { - $groupFileTarget = self::generateTarget('file', $filePath, $shareType, $shareWith['group'], $uidOwner, $suggestedFileTarget); + $groupFileTarget = self::generateTarget('file', $filePath, $shareType, $shareWith['group'], + $uidOwner, $suggestedFileTarget); } } else { $groupFileTarget = null; } - $query->execute(array($itemType, $itemSource, $groupItemTarget, $parent, $shareType, $shareWith['group'], $uidOwner, $permissions, time(), $fileSource, $groupFileTarget, $token)); + $query->execute(array($itemType, $itemSource, $groupItemTarget, $parent, $shareType, + $shareWith['group'], $uidOwner, $permissions, time(), $fileSource, $groupFileTarget, $token)); // Save this id, any extra rows for this group share will need to reference it $parent = \OC_DB::insertid('*PREFIX*share'); // Loop through all users of this group in case we need to add an extra row foreach ($shareWith['users'] as $uid) { - $itemTarget = self::generateTarget($itemType, $itemSource, self::SHARE_TYPE_USER, $uid, $uidOwner, $suggestedItemTarget, $parent); + $itemTarget = self::generateTarget($itemType, $itemSource, self::SHARE_TYPE_USER, $uid, + $uidOwner, $suggestedItemTarget, $parent); if (isset($fileSource)) { if ($parentFolder) { if ($parentFolder === true) { - $fileTarget = self::generateTarget('file', $filePath, self::SHARE_TYPE_USER, $uid, $uidOwner, $suggestedFileTarget, $parent); + $fileTarget = self::generateTarget('file', $filePath, self::SHARE_TYPE_USER, $uid, + $uidOwner, $suggestedFileTarget, $parent); if ($fileTarget != $groupFileTarget) { $parentFolders[$uid]['folder'] = $fileTarget; } @@ -995,7 +1096,8 @@ class Share { $parent = $parentFolder[$uid]['id']; } } else { - $fileTarget = self::generateTarget('file', $filePath, self::SHARE_TYPE_USER, $uid, $uidOwner, $suggestedFileTarget, $parent); + $fileTarget = self::generateTarget('file', $filePath, self::SHARE_TYPE_USER, + $uid, $uidOwner, $suggestedFileTarget, $parent); } } else { $fileTarget = null; @@ -1016,7 +1118,9 @@ class Share { )); // Insert an extra row for the group share if the item or file target is unique for this user if ($itemTarget != $groupItemTarget || (isset($fileSource) && $fileTarget != $groupFileTarget)) { - $query->execute(array($itemType, $itemSource, $itemTarget, $parent, self::$shareTypeGroupUserUnique, $uid, $uidOwner, $permissions, time(), $fileSource, $fileTarget, $token)); + $query->execute(array($itemType, $itemSource, $itemTarget, $parent, + self::$shareTypeGroupUserUnique, $uid, $uidOwner, $permissions, time(), + $fileSource, $fileTarget, $token)); $id = \OC_DB::insertid('*PREFIX*share'); } } @@ -1025,23 +1129,27 @@ class Share { return $parentFolders; } } else { - $itemTarget = self::generateTarget($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $suggestedItemTarget); + $itemTarget = self::generateTarget($itemType, $itemSource, $shareType, $shareWith, $uidOwner, + $suggestedItemTarget); if (isset($fileSource)) { if ($parentFolder) { if ($parentFolder === true) { - $fileTarget = self::generateTarget('file', $filePath, $shareType, $shareWith, $uidOwner, $suggestedFileTarget); + $fileTarget = self::generateTarget('file', $filePath, $shareType, $shareWith, + $uidOwner, $suggestedFileTarget); $parentFolders['folder'] = $fileTarget; } else { $fileTarget = $parentFolder['folder'].$itemSource; $parent = $parentFolder['id']; } } else { - $fileTarget = self::generateTarget('file', $filePath, $shareType, $shareWith, $uidOwner, $suggestedFileTarget); + $fileTarget = self::generateTarget('file', $filePath, $shareType, $shareWith, $uidOwner, + $suggestedFileTarget); } } else { $fileTarget = null; } - $query->execute(array($itemType, $itemSource, $itemTarget, $parent, $shareType, $shareWith, $uidOwner, $permissions, time(), $fileSource, $fileTarget, $token)); + $query->execute(array($itemType, $itemSource, $itemTarget, $parent, $shareType, $shareWith, $uidOwner, + $permissions, time(), $fileSource, $fileTarget, $token)); $id = \OC_DB::insertid('*PREFIX*share'); \OC_Hook::emit('OCP\Share', 'post_shared', array( 'itemType' => $itemType, @@ -1076,7 +1184,8 @@ class Share { * @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) { + private static function generateTarget($itemType, $itemSource, $shareType, $shareWith, $uidOwner, + $suggestedTarget = null, $groupParent = null) { $backend = self::getBackend($itemType); if ($shareType == self::SHARE_TYPE_LINK) { if (isset($suggestedTarget)) { @@ -1143,18 +1252,28 @@ class Share { // Find similar targets to improve backend's chances to generate a unqiue target if ($userAndGroups) { if ($column == 'file_target') { - $checkTargets = \OC_DB::prepare('SELECT `'.$column.'` FROM `*PREFIX*share` WHERE `item_type` IN (\'file\', \'folder\') AND `share_type` IN (?,?,?) AND `share_with` IN (\''.implode('\',\'', $userAndGroups).'\')'); - $result = $checkTargets->execute(array(self::SHARE_TYPE_USER, self::SHARE_TYPE_GROUP, self::$shareTypeGroupUserUnique)); + $checkTargets = \OC_DB::prepare('SELECT `'.$column.'` FROM `*PREFIX*share`' + .' WHERE `item_type` IN (\'file\', \'folder\')' + .' AND `share_type` IN (?,?,?)' + .' AND `share_with` IN (\''.implode('\',\'', $userAndGroups).'\')'); + $result = $checkTargets->execute(array(self::SHARE_TYPE_USER, self::SHARE_TYPE_GROUP, + self::$shareTypeGroupUserUnique)); } else { - $checkTargets = \OC_DB::prepare('SELECT `'.$column.'` FROM `*PREFIX*share` WHERE `item_type` = ? AND `share_type` IN (?,?,?) AND `share_with` IN (\''.implode('\',\'', $userAndGroups).'\')'); - $result = $checkTargets->execute(array($itemType, self::SHARE_TYPE_USER, self::SHARE_TYPE_GROUP, self::$shareTypeGroupUserUnique)); + $checkTargets = \OC_DB::prepare('SELECT `'.$column.'` FROM `*PREFIX*share`' + .' WHERE `item_type` = ? AND `share_type` IN (?,?,?)' + .' AND `share_with` IN (\''.implode('\',\'', $userAndGroups).'\')'); + $result = $checkTargets->execute(array($itemType, self::SHARE_TYPE_USER, + self::SHARE_TYPE_GROUP, self::$shareTypeGroupUserUnique)); } } else { if ($column == 'file_target') { - $checkTargets = \OC_DB::prepare('SELECT `'.$column.'` FROM `*PREFIX*share` WHERE `item_type` IN (\'file\', \'folder\') AND `share_type` = ? AND `share_with` = ?'); + $checkTargets = \OC_DB::prepare('SELECT `'.$column.'` FROM `*PREFIX*share`' + .' WHERE `item_type` IN (\'file\', \'folder\')' + .' AND `share_type` = ? AND `share_with` = ?'); $result = $checkTargets->execute(array(self::SHARE_TYPE_GROUP, $shareWith)); } else { - $checkTargets = \OC_DB::prepare('SELECT `'.$column.'` FROM `*PREFIX*share` WHERE `item_type` = ? AND `share_type` = ? AND `share_with` = ?'); + $checkTargets = \OC_DB::prepare('SELECT `'.$column.'` FROM `*PREFIX*share`' + .' WHERE `item_type` = ? AND `share_type` = ? AND `share_with` = ?'); $result = $checkTargets->execute(array($itemType, self::SHARE_TYPE_GROUP, $shareWith)); } } @@ -1182,21 +1301,33 @@ class Share { $parents = array($parent); while (!empty($parents)) { $parents = "'".implode("','", $parents)."'"; - // Check the owner on the first search of reshares, useful for finding and deleting the reshares by a single user of a group share + // Check the owner on the first search of reshares, useful for + // finding and deleting the reshares by a single user of a group share if (count($ids) == 1 && isset($uidOwner)) { - $query = \OC_DB::prepare('SELECT `id`, `uid_owner`, `item_type`, `item_target`, `parent` FROM `*PREFIX*share` WHERE `parent` IN ('.$parents.') AND `uid_owner` = ?'); + $query = \OC_DB::prepare('SELECT `id`, `uid_owner`, `item_type`, `item_target`, `parent`' + .' FROM `*PREFIX*share` WHERE `parent` IN ('.$parents.') AND `uid_owner` = ?'); $result = $query->execute(array($uidOwner)); } else { - $query = \OC_DB::prepare('SELECT `id`, `item_type`, `item_target`, `parent`, `uid_owner` FROM `*PREFIX*share` WHERE `parent` IN ('.$parents.')'); + $query = \OC_DB::prepare('SELECT `id`, `item_type`, `item_target`, `parent`, `uid_owner`' + .' FROM `*PREFIX*share` WHERE `parent` IN ('.$parents.')'); $result = $query->execute(); } // Reset parents array, only go through loop again if items are found $parents = array(); while ($item = $result->fetchRow()) { - // Search for a duplicate parent share, this occurs when an item is shared to the same user through a group and user or the same item is shared by different users + // Search for a duplicate parent share, this occurs when an + // item is shared to the same user through a group and user or the + // same item is shared by different users $userAndGroups = array_merge(array($item['uid_owner']), \OC_Group::getUserGroups($item['uid_owner'])); - $query = \OC_DB::prepare('SELECT `id`, `permissions` FROM `*PREFIX*share` WHERE `item_type` = ? AND `item_target` = ? AND `share_type` IN (?,?,?) AND `share_with` IN (\''.implode('\',\'', $userAndGroups).'\') AND `uid_owner` != ? AND `id` != ?'); - $duplicateParent = $query->execute(array($item['item_type'], $item['item_target'], self::SHARE_TYPE_USER, self::SHARE_TYPE_GROUP, self::$shareTypeGroupUserUnique, $item['uid_owner'], $item['parent']))->fetchRow(); + $query = \OC_DB::prepare('SELECT `id`, `permissions` FROM `*PREFIX*share`' + .' WHERE `item_type` = ?' + .' AND `item_target` = ?' + .' AND `share_type` IN (?,?,?)' + .' AND `share_with` IN (\''.implode('\',\'', $userAndGroups).'\')' + .' AND `uid_owner` != ? AND `id` != ?'); + $duplicateParent = $query->execute(array($item['item_type'], $item['item_target'], + self::SHARE_TYPE_USER, self::SHARE_TYPE_GROUP, self::$shareTypeGroupUserUnique, + $item['uid_owner'], $item['parent']))->fetchRow(); if ($duplicateParent) { // Change the parent to the other item id if share permission is granted if ($duplicateParent['permissions'] & PERMISSION_SHARE) { @@ -1225,7 +1356,8 @@ class Share { public static function post_deleteUser($arguments) { // Delete any items shared with the deleted user - $query = \OC_DB::prepare('DELETE FROM `*PREFIX*share` WHERE `share_with` = ? AND `share_type` = ? OR `share_type` = ?'); + $query = \OC_DB::prepare('DELETE FROM `*PREFIX*share`' + .' WHERE `share_with` = ? AND `share_type` = ? OR `share_type` = ?'); $result = $query->execute(array($arguments['uid'], self::SHARE_TYPE_USER, self::$shareTypeGroupUserUnique)); // Delete any items the deleted user shared $query = \OC_DB::prepare('SELECT `id` FROM `*PREFIX*share` WHERE `uid_owner` = ?'); @@ -1239,21 +1371,27 @@ class Share { // 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` = ?'); $result = $query->execute(array(self::SHARE_TYPE_GROUP, $arguments['gid'])); - $query = \OC_DB::prepare('INSERT INTO `*PREFIX*share` (`item_type`, `item_source`, `item_target`, `parent`, `share_type`, `share_with`, `uid_owner`, `permissions`, `stime`, `file_source`, `file_target`) VALUES (?,?,?,?,?,?,?,?,?,?,?)'); + $query = \OC_DB::prepare('INSERT INTO `*PREFIX*share` (`item_type`, `item_source`,' + .' `item_target`, `parent`, `share_type`, `share_with`, `uid_owner`, `permissions`,' + .' `stime`, `file_source`, `file_target`) VALUES (?,?,?,?,?,?,?,?,?,?,?)'); while ($item = $result->fetchRow()) { if ($item['item_type'] == 'file' || $item['item_type'] == 'file') { $itemTarget = null; } else { - $itemTarget = self::generateTarget($item['item_type'], $item['item_source'], self::SHARE_TYPE_USER, $arguments['uid'], $item['uid_owner'], $item['item_target'], $item['id']); + $itemTarget = self::generateTarget($item['item_type'], $item['item_source'], self::SHARE_TYPE_USER, + $arguments['uid'], $item['uid_owner'], $item['item_target'], $item['id']); } if (isset($item['file_source'])) { - $fileTarget = self::generateTarget($item['item_type'], $item['item_source'], self::SHARE_TYPE_USER, $arguments['uid'], $item['uid_owner'], $item['file_target'], $item['id']); + $fileTarget = self::generateTarget($item['item_type'], $item['item_source'], self::SHARE_TYPE_USER, + $arguments['uid'], $item['uid_owner'], $item['file_target'], $item['id']); } else { $fileTarget = null; } // Insert an extra row for the group share if the item or file target is unique for this user if ($itemTarget != $item['item_target'] || $fileTarget != $item['file_target']) { - $query->execute(array($item['item_type'], $item['item_source'], $itemTarget, $item['id'], self::$shareTypeGroupUserUnique, $arguments['uid'], $item['uid_owner'], $item['permissions'], $item['stime'], $item['file_source'], $fileTarget)); + $query->execute(array($item['item_type'], $item['item_source'], $itemTarget, $item['id'], + self::$shareTypeGroupUserUnique, $arguments['uid'], $item['uid_owner'], $item['permissions'], + $item['stime'], $item['file_source'], $fileTarget)); \OC_DB::insertid('*PREFIX*share'); } } @@ -1261,8 +1399,10 @@ class Share { public static function post_removeFromGroup($arguments) { // TODO Don't call if user deleted? - $query = \OC_DB::prepare('SELECT `id`, `share_type` FROM `*PREFIX*share` WHERE (`share_type` = ? AND `share_with` = ?) OR (`share_type` = ? AND `share_with` = ?)'); - $result = $query->execute(array(self::SHARE_TYPE_GROUP, $arguments['gid'], self::$shareTypeGroupUserUnique, $arguments['uid'])); + $query = \OC_DB::prepare('SELECT `id`, `share_type` FROM `*PREFIX*share`' + .' WHERE (`share_type` = ? AND `share_with` = ?) OR (`share_type` = ? AND `share_with` = ?)'); + $result = $query->execute(array(self::SHARE_TYPE_GROUP, $arguments['gid'], self::$shareTypeGroupUserUnique, + $arguments['uid'])); while ($item = $result->fetchRow()) { if ($item['share_type'] == self::SHARE_TYPE_GROUP) { // Delete all reshares by this user of the group share @@ -1319,10 +1459,18 @@ interface Share_Backend { * @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 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 + * 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. */ diff --git a/lib/public/template.php b/lib/public/template.php index 4cda3650866..ccf19cf052c 100644 --- a/lib/public/template.php +++ b/lib/public/template.php @@ -99,7 +99,8 @@ function html_select_options($options, $selected, $params=array()) { /** - * This class provides the template system for owncloud. You can use it to load specific templates, add data and generate the html code + * This class provides the template system for owncloud. You can use it to load + * specific templates, add data and generate the html code */ class Template extends \OC_Template { diff --git a/lib/public/user.php b/lib/public/user.php index de52055a4c5..9edebe0e7cf 100644 --- a/lib/public/user.php +++ b/lib/public/user.php @@ -31,7 +31,8 @@ namespace OCP; /** - * This class provides access to the user management. You can get information about the currently logged in user and the permissions for example + * This class provides access to the user management. You can get information + * about the currently logged in user and the permissions for example */ class User { /** @@ -51,25 +52,25 @@ class User { public static function getUsers($search = '', $limit = null, $offset = null) { return \OC_USER::getUsers(); } - - /**
- * @brief get the user display name of the user currently logged in.
- * @return string display name
- */
- public static function getDisplayName($user=null) {
- return \OC_USER::getDisplayName($user);
+ + /** + * @brief get the user display name of the user currently logged in. + * @return string display name + */ + 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.
- */
- public static function getDisplayNames($search = '', $limit = null, $offset = null) {
- return \OC_USER::getDisplayNames($search, $limit, $offset);
+ + /** + * @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. + */ + 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 diff --git a/lib/public/util.php b/lib/public/util.php index 5f6ede4460e..5d814114a24 100644 --- a/lib/public/util.php +++ b/lib/public/util.php @@ -59,9 +59,11 @@ class Util { * @param string $fromname * @param bool $html */ - public static function sendMail( $toaddress, $toname, $subject, $mailtext, $fromaddress, $fromname, $html = 0, $altbody = '', $ccaddress = '', $ccname = '', $bcc = '') { + public static function sendMail( $toaddress, $toname, $subject, $mailtext, $fromaddress, $fromname, + $html = 0, $altbody = '', $ccaddress = '', $ccname = '', $bcc = '') { // call the internal mail class - \OC_MAIL::send($toaddress, $toname, $subject, $mailtext, $fromaddress, $fromname, $html, $altbody, $ccaddress, $ccname, $bcc); + \OC_MAIL::send($toaddress, $toname, $subject, $mailtext, $fromaddress, $fromname, + $html, $altbody, $ccaddress, $ccname, $bcc); } /** @@ -215,11 +217,14 @@ class Util { */ public static function getDefaultEmailAddress($user_part) { $host_name = self::getServerHostName(); - // handle localhost installations - if ($host_name === 'localhost') { - $host_name = "example.com"; + $defaultEmailAddress = $user_part.'@'.$host_name; + + if (\PHPMailer::ValidateAddress($defaultEmailAddress)) { + return $defaultEmailAddress; } - return $user_part.'@'.$host_name; + + // incase we cannot build a valid email address from the hostname let's fallback to 'localhost.localdomain' + return $user_part.'@localhost.localdomain'; } /** @@ -340,7 +345,8 @@ class Util { /** * @brief 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. + * 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. * * @param string|array of strings * @return array with sanitized strings or a single sinitized string, depends on the input parameter. diff --git a/lib/request.php b/lib/request.php index 1661a1406ca..9f74cf9beb5 100755 --- a/lib/request.php +++ b/lib/request.php @@ -107,15 +107,15 @@ class OC_Request { if (array_key_exists('PATH_INFO', $_SERVER)) { $path_info = $_SERVER['PATH_INFO']; }else{ - $path_info = substr($_SERVER['REQUEST_URI'], strlen($_SERVER['SCRIPT_NAME'])); + $path_info = self::getRawPathInfo(); // following is taken from Sabre_DAV_URLUtil::decodePathSegment $path_info = rawurldecode($path_info); $encoding = mb_detect_encoding($path_info, array('UTF-8', 'ISO-8859-1')); switch($encoding) { - case 'ISO-8859-1' : - $path_info = utf8_encode($path_info); + case 'ISO-8859-1' : + $path_info = utf8_encode($path_info); } // end copy @@ -124,6 +124,19 @@ class OC_Request { } /** + * @brief get Path info from request, not urldecoded + * @returns string Path info or false when not found + */ + public static function getRawPathInfo() { + $path_info = substr($_SERVER['REQUEST_URI'], strlen($_SERVER['SCRIPT_NAME'])); + // Remove the query string from REQUEST_URI + if ($pos = strpos($path_info, '?')) { + $path_info = substr($path_info, 0, $pos); + } + return $path_info; + } + + /** * @brief Check if this is a no-cache request * @returns true for no-cache */ @@ -149,4 +162,16 @@ class OC_Request { return 'gzip'; return false; } + + /** + * @brief Check if the requester sent along an mtime + * @returns false or an mtime + */ + static public function hasModificationTime () { + if (isset($_SERVER['HTTP_X_OC_MTIME'])) { + return $_SERVER['HTTP_X_OC_MTIME']; + } else { + return false; + } + } } diff --git a/lib/search.php b/lib/search.php index e5a65f7157d..b9c75dfc333 100644 --- a/lib/search.php +++ b/lib/search.php @@ -57,14 +57,14 @@ class OC_Search{ } return $results; } - + /** * remove an existing search provider * @param string $provider class name of a OC_Search_Provider */ public static function removeProvider($provider) { self::$registeredProviders = array_filter( - self::$registeredProviders, + self::$registeredProviders, function ($element) use ($provider) { return ($element['class'] != $provider); } diff --git a/lib/setup.php b/lib/setup.php index 4dd190b99fb..8814447f52f 100644 --- a/lib/setup.php +++ b/lib/setup.php @@ -19,40 +19,49 @@ class DatabaseSetupException extends Exception } class OC_Setup { + + public static function getTrans(){ + return OC_L10N::get('lib'); + } + public static function install($options) { + $l = self::getTrans(); + $error = array(); $dbtype = $options['dbtype']; if(empty($options['adminlogin'])) { - $error[] = 'Set an admin username.'; + $error[] = $l->t('Set an admin username.'); } if(empty($options['adminpass'])) { - $error[] = 'Set an admin password.'; + $error[] = $l->t('Set an admin password.'); } if(empty($options['directory'])) { - $error[] = 'Specify a data folder.'; + $error[] = $l->t('Specify a data folder.'); } - if($dbtype=='mysql' or $dbtype == 'pgsql' or $dbtype == 'oci') { //mysql and postgresql needs more config options - if($dbtype=='mysql') + if($dbtype == 'mysql' or $dbtype == 'pgsql' or $dbtype == 'oci' or $dbtype == 'mssql') { //mysql and postgresql needs more config options + if($dbtype == 'mysql') $dbprettyname = 'MySQL'; - else if($dbtype=='pgsql') + else if($dbtype == 'pgsql') $dbprettyname = 'PostgreSQL'; + else if ($dbtype == 'mssql') + $dbprettyname = 'MS SQL Server'; else $dbprettyname = 'Oracle'; if(empty($options['dbuser'])) { - $error[] = "$dbprettyname enter the database username."; + $error[] = $l->t("%s enter the database username.", array($dbprettyname)); } if(empty($options['dbname'])) { - $error[] = "$dbprettyname enter the database name."; + $error[] = $l->t("%s enter the database name.", array($dbprettyname)); } if(substr_count($options['dbname'], '.') >= 1) { - $error[] = "$dbprettyname you may not use dots in the database name"; + $error[] = $l->t("%s you may not use dots in the database name", array($dbprettyname)); } if($dbtype != 'oci' && empty($options['dbhost'])) { - $error[] = "$dbprettyname set the database host."; + $error[] = $l->t("%s set the database host.", array($dbprettyname)); } } @@ -91,7 +100,7 @@ class OC_Setup { $error[] = array( 'error' => $e->getMessage(), 'hint' => $e->getHint() - ); + ); return($error); } catch (Exception $e) { $error[] = array( @@ -116,8 +125,8 @@ class OC_Setup { self::setupPostgreSQLDatabase($dbhost, $dbuser, $dbpass, $dbname, $dbtableprefix, $username); } catch (Exception $e) { $error[] = array( - 'error' => 'PostgreSQL username and/or password not valid', - 'hint' => 'You need to enter either an existing account or the administrator.' + 'error' => $l->t('PostgreSQL username and/or password not valid'), + 'hint' => $l->t('You need to enter either an existing account or the administrator.') ); return $error; } @@ -139,7 +148,30 @@ class OC_Setup { self::setupOCIDatabase($dbhost, $dbuser, $dbpass, $dbname, $dbtableprefix, $dbtablespace, $username); } catch (Exception $e) { $error[] = array( - 'error' => 'Oracle username and/or password not valid', + 'error' => $l->t('Oracle username and/or password not valid'), + 'hint' => $l->t('You need to enter either an existing account or the administrator.') + ); + return $error; + } + } + elseif ($dbtype == 'mssql') { + $dbuser = $options['dbuser']; + $dbpass = $options['dbpass']; + $dbname = $options['dbname']; + $dbhost = $options['dbhost']; + $dbtableprefix = isset($options['dbtableprefix']) ? $options['dbtableprefix'] : 'oc_'; + + OC_Config::setValue('dbname', $dbname); + OC_Config::setValue('dbhost', $dbhost); + OC_Config::setValue('dbuser', $dbuser); + OC_Config::setValue('dbpassword', $dbpass); + OC_Config::setValue('dbtableprefix', $dbtableprefix); + + try { + self::setupMSSQLDatabase($dbhost, $dbuser, $dbpass, $dbname, $dbtableprefix); + } catch (Exception $e) { + $error[] = array( + 'error' => 'MS SQL username and/or password not valid', 'hint' => 'You need to enter either an existing account or the administrator.' ); return $error; @@ -167,7 +199,7 @@ class OC_Setup { OC_Appconfig::setValue('core', 'lastupdatedat', microtime(true)); OC_AppConfig::setValue('core', 'remote_core.css', '/core/minimizer.php'); OC_AppConfig::setValue('core', 'remote_core.js', '/core/minimizer.php'); - + OC_Group::createGroup('admin'); OC_Group::addToGroup($username, 'admin'); OC_User::login($username, $password); @@ -190,13 +222,16 @@ class OC_Setup { private static function setupMySQLDatabase($dbhost, $dbuser, $dbpass, $dbname, $dbtableprefix, $username) { //check if the database user has admin right + $l = self::getTrans(); $connection = @mysql_connect($dbhost, $dbuser, $dbpass); if(!$connection) { - throw new DatabaseSetupException('MySQL username and/or password not valid','You need to enter either an existing account or the administrator.'); + throw new DatabaseSetupException($l->t('MySQL username and/or password not valid'), + $l->t('You need to enter either an existing account or the administrator.')); } $oldUser=OC_Config::getValue('dbuser', false); - $query="SELECT user FROM mysql.user WHERE user='$dbuser'"; //this should be enough to check for admin rights in mysql + //this should be enough to check for admin rights in mysql + $query="SELECT user FROM mysql.user WHERE user='$dbuser'"; if(mysql_query($query, $connection)) { //use the admin login data for the new database user @@ -226,7 +261,8 @@ class OC_Setup { } //fill the database if needed - $query="select count(*) from information_schema.tables where table_schema='$dbname' AND table_name = '{$dbtableprefix}users';"; + $query='select count(*) from information_schema.tables' + ." where table_schema='$dbname' AND table_name = '{$dbtableprefix}users';"; $result = mysql_query($query, $connection); if($result) { $row=mysql_fetch_row($result); @@ -239,29 +275,35 @@ class OC_Setup { private static function createMySQLDatabase($name, $user, $connection) { //we cant use OC_BD functions here because we need to connect as the administrative user. + $l = self::getTrans(); $query = "CREATE DATABASE IF NOT EXISTS `$name`"; $result = mysql_query($query, $connection); if(!$result) { - $entry='DB Error: "'.mysql_error($connection).'"<br />'; - $entry.='Offending command was: '.$query.'<br />'; - echo($entry); + $entry = $l->t('DB Error: "%s"', array(mysql_error($connection))) . '<br />'; + $entry .= $l->t('Offending command was: "%s"', array($query)) . '<br />'; + \OC_Log::write('setup.mssql', $entry, \OC_Log::WARN); } $query="GRANT ALL PRIVILEGES ON `$name` . * TO '$user'"; - $result = mysql_query($query, $connection); //this query will fail if there aren't the right permissons, ignore the error + + //this query will fail if there aren't the right permissions, ignore the error + mysql_query($query, $connection); } private static function createDBUser($name, $password, $connection) { // we need to create 2 accounts, one for global use and one for local user. if we don't specify the local one, // the anonymous user would take precedence when there is one. + $l = self::getTrans(); $query = "CREATE USER '$name'@'localhost' IDENTIFIED BY '$password'"; $result = mysql_query($query, $connection); if (!$result) { - throw new DatabaseSetupException("MySQL user '" . "$name" . "'@'localhost' already exists","Delete this user from MySQL."); + throw new DatabaseSetupException($l->t("MySQL user '%s'@'localhost' exists already.", + array($name)), $l->t("Drop this user from MySQL", array($name))); } $query = "CREATE USER '$name'@'%' IDENTIFIED BY '$password'"; $result = mysql_query($query, $connection); if (!$result) { - throw new DatabaseSetupException("MySQL user '" . "$name" . "'@'%' already exists","Delete this user from MySQL."); + throw new DatabaseSetupException($l->t("MySQL user '%s'@'%%' already exists", array($name)), + $l->t("Drop this user from MySQL.")); } } @@ -269,12 +311,13 @@ class OC_Setup { $e_host = addslashes($dbhost); $e_user = addslashes($dbuser); $e_password = addslashes($dbpass); + $l = self::getTrans(); //check if the database user has admin rights $connection_string = "host='$e_host' dbname=postgres user='$e_user' password='$e_password'"; $connection = @pg_connect($connection_string); if(!$connection) { - throw new Exception('PostgreSQL username and/or password not valid'); + throw new Exception($l->t('PostgreSQL username and/or password not valid')); } $e_user = pg_escape_string($dbuser); //check for roles creation rights in postgresql @@ -319,7 +362,7 @@ class OC_Setup { $connection_string = "host='$e_host' dbname='$e_dbname' user='$e_user' password='$e_password'"; $connection = @pg_connect($connection_string); if(!$connection) { - throw new Exception('PostgreSQL username and/or password not valid'); + throw new Exception($l->t('PostgreSQL username and/or password not valid')); } $query = "select count(*) FROM pg_class WHERE relname='{$dbtableprefix}users' limit 1"; $result = pg_query($connection, $query); @@ -332,41 +375,44 @@ class OC_Setup { } private static function pg_createDatabase($name, $user, $connection) { + //we cant use OC_BD functions here because we need to connect as the administrative user. + $l = self::getTrans(); $e_name = pg_escape_string($name); $e_user = pg_escape_string($user); $query = "select datname from pg_database where datname = '$e_name'"; $result = pg_query($connection, $query); if(!$result) { - $entry='DB Error: "'.pg_last_error($connection).'"<br />'; - $entry.='Offending command was: '.$query.'<br />'; - echo($entry); + $entry = $l->t('DB Error: "%s"', array(pg_last_error($connection))) . '<br />'; + $entry .= $l->t('Offending command was: "%s"', array($query)) . '<br />'; + \OC_Log::write('setup.pg', $entry, \OC_Log::WARN); } if(! pg_fetch_row($result)) { //The database does not exists... let's create it $query = "CREATE DATABASE \"$e_name\" OWNER \"$e_user\""; $result = pg_query($connection, $query); if(!$result) { - $entry='DB Error: "'.pg_last_error($connection).'"<br />'; - $entry.='Offending command was: '.$query.'<br />'; - echo($entry); + $entry = $l->t('DB Error: "%s"', array(pg_last_error($connection))) . '<br />'; + $entry .= $l->t('Offending command was: "%s"', array($query)) . '<br />'; + \OC_Log::write('setup.pg', $entry, \OC_Log::WARN); } else { $query = "REVOKE ALL PRIVILEGES ON DATABASE \"$e_name\" FROM PUBLIC"; - $result = pg_query($connection, $query); + pg_query($connection, $query); } } } private static function pg_createDBUser($name, $password, $connection) { + $l = self::getTrans(); $e_name = pg_escape_string($name); $e_password = pg_escape_string($password); $query = "select * from pg_roles where rolname='$e_name';"; $result = pg_query($connection, $query); if(!$result) { - $entry='DB Error: "'.pg_last_error($connection).'"<br />'; - $entry.='Offending command was: '.$query.'<br />'; - echo($entry); + $entry = $l->t('DB Error: "%s"', array(pg_last_error($connection))) . '<br />'; + $entry .= $l->t('Offending command was: "%s"', array($query)) . '<br />'; + \OC_Log::write('setup.pg', $entry, \OC_Log::WARN); } if(! pg_fetch_row($result)) { @@ -374,23 +420,25 @@ class OC_Setup { $query = "CREATE USER \"$e_name\" CREATEDB PASSWORD '$e_password';"; $result = pg_query($connection, $query); if(!$result) { - $entry='DB Error: "'.pg_last_error($connection).'"<br />'; - $entry.='Offending command was: '.$query.'<br />'; - echo($entry); + $entry = $l->t('DB Error: "%s"', array(pg_last_error($connection))) . '<br />'; + $entry .= $l->t('Offending command was: "%s"', array($query)) . '<br />'; + \OC_Log::write('setup.pg', $entry, \OC_Log::WARN); } } else { // change password of the existing role $query = "ALTER ROLE \"$e_name\" WITH PASSWORD '$e_password';"; $result = pg_query($connection, $query); if(!$result) { - $entry='DB Error: "'.pg_last_error($connection).'"<br />'; - $entry.='Offending command was: '.$query.'<br />'; - echo($entry); + $entry = $l->t('DB Error: "%s"', array(pg_last_error($connection))) . '<br />'; + $entry .= $l->t('Offending command was: "%s"', array($query)) . '<br />'; + \OC_Log::write('setup.pg', $entry, \OC_Log::WARN); } } } - private static function setupOCIDatabase($dbhost, $dbuser, $dbpass, $dbname, $dbtableprefix, $dbtablespace, $username) { + private static function setupOCIDatabase($dbhost, $dbuser, $dbpass, $dbname, $dbtableprefix, $dbtablespace, + $username) { + $l = self::getTrans(); $e_host = addslashes($dbhost); $e_dbname = addslashes($dbname); //check if the database user has admin right @@ -402,16 +450,17 @@ class OC_Setup { $connection = @oci_connect($dbuser, $dbpass, $easy_connect_string); if(!$connection) { $e = oci_error(); - throw new Exception('Oracle username and/or password not valid'); + throw new Exception($l->t('Oracle username and/or password not valid')); } //check for roles creation rights in oracle - $query="SELECT count(*) FROM user_role_privs, role_sys_privs WHERE user_role_privs.granted_role = role_sys_privs.role AND privilege = 'CREATE ROLE'"; + $query='SELECT count(*) FROM user_role_privs, role_sys_privs' + ." WHERE user_role_privs.granted_role = role_sys_privs.role AND privilege = 'CREATE ROLE'"; $stmt = oci_parse($connection, $query); if (!$stmt) { - $entry='DB Error: "'.oci_last_error($connection).'"<br />'; - $entry.='Offending command was: '.$query.'<br />'; - echo($entry); + $entry = $l->t('DB Error: "%s"', array(oci_last_error($connection))) . '<br />'; + $entry .= $l->t('Offending command was: "%s"', array($query)) . '<br />'; + \OC_Log::write('setup.oci', $entry, \OC_Log::WARN); } $result = oci_execute($stmt); if($result) { @@ -468,16 +517,16 @@ class OC_Setup { } $connection = @oci_connect($dbuser, $dbpass, $easy_connect_string); if(!$connection) { - throw new Exception('Oracle username and/or password not valid'); + throw new Exception($l->t('Oracle username and/or password not valid')); } $query = "SELECT count(*) FROM user_tables WHERE table_name = :un"; $stmt = oci_parse($connection, $query); $un = $dbtableprefix.'users'; oci_bind_by_name($stmt, ':un', $un); if (!$stmt) { - $entry='DB Error: "'.oci_last_error($connection).'"<br />'; - $entry.='Offending command was: '.$query.'<br />'; - echo($entry); + $entry = $l->t('DB Error: "%s"', array(oci_error($connection))) . '<br />'; + $entry .= $l->t('Offending command was: "%s"', array($query)) . '<br />'; + \OC_Log::write('setup.oci', $entry, \OC_Log::WARN); } $result = oci_execute($stmt); @@ -497,20 +546,20 @@ class OC_Setup { * @param resource $connection */ private static function oci_createDBUser($name, $password, $tablespace, $connection) { - + $l = self::getTrans(); $query = "SELECT * FROM all_users WHERE USERNAME = :un"; $stmt = oci_parse($connection, $query); if (!$stmt) { - $entry='DB Error: "'.oci_error($connection).'"<br />'; - $entry.='Offending command was: '.$query.'<br />'; - echo($entry); + $entry = $l->t('DB Error: "%s"', array(oci_error($connection))) . '<br />'; + $entry .= $l->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='DB Error: "'.oci_error($connection).'"<br />'; - $entry.='Offending command was: '.$query.'<br />'; - echo($entry); + $entry = $l->t('DB Error: "%s"', array(oci_error($connection))) . '<br />'; + $entry .= $l->t('Offending command was: "%s"', array($query)) . '<br />'; + \OC_Log::write('setup.oci', $entry, \OC_Log::WARN); } if(! oci_fetch_row($stmt)) { @@ -519,50 +568,226 @@ class OC_Setup { $query = 'CREATE USER '.$name.' IDENTIFIED BY "'.$password.'" DEFAULT TABLESPACE '.$tablespace; //TODO set default tablespace $stmt = oci_parse($connection, $query); if (!$stmt) { - $entry='DB Error: "'.oci_error($connection).'"<br />'; - $entry.='Offending command was: '.$query.'<br />'; - echo($entry); + $entry = $l->t('DB Error: "%s"', array(oci_error($connection))) . '<br />'; + $entry .= $l->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='DB Error: "'.oci_error($connection).'"<br />'; - $entry.='Offending command was: '.$query.', name:'.$name.', password:'.$password.'<br />'; - echo($entry); + $entry = $l->t('DB Error: "%s"', array(oci_error($connection))) . '<br />'; + $entry .= $l->t('Offending command was: "%s", name: %s, password: %s', + array($query, $name, $password)) . '<br />'; + \OC_Log::write('setup.oci', $entry, \OC_Log::WARN); } } else { // change password of the existing role $query = "ALTER USER :un IDENTIFIED BY :pw"; $stmt = oci_parse($connection, $query); if (!$stmt) { - $entry='DB Error: "'.oci_error($connection).'"<br />'; - $entry.='Offending command was: '.$query.'<br />'; - echo($entry); + $entry = $l->t('DB Error: "%s"', array(oci_error($connection))) . '<br />'; + $entry .= $l->t('Offending command was: "%s"', array($query)) . '<br />'; + \OC_Log::write('setup.oci', $entry, \OC_Log::WARN); } oci_bind_by_name($stmt, ':un', $name); oci_bind_by_name($stmt, ':pw', $password); $result = oci_execute($stmt); if(!$result) { - $entry='DB Error: "'.oci_error($connection).'"<br />'; - $entry.='Offending command was: '.$query.'<br />'; - echo($entry); + $entry = $l->t('DB Error: "%s"', array(oci_error($connection))) . '<br />'; + $entry .= $l->t('Offending command was: "%s"', array($query)) . '<br />'; + \OC_Log::write('setup.oci', $entry, \OC_Log::WARN); } } - // grant neccessary roles + // grant necessary roles $query = 'GRANT CREATE SESSION, CREATE TABLE, CREATE SEQUENCE, CREATE TRIGGER, UNLIMITED TABLESPACE TO '.$name; $stmt = oci_parse($connection, $query); if (!$stmt) { - $entry='DB Error: "'.oci_error($connection).'"<br />'; - $entry.='Offending command was: '.$query.'<br />'; - echo($entry); + $entry = $l->t('DB Error: "%s"', array(oci_error($connection))) . '<br />'; + $entry .= $l->t('Offending command was: "%s"', array($query)) . '<br />'; + \OC_Log::write('setup.oci', $entry, \OC_Log::WARN); } $result = oci_execute($stmt); if(!$result) { - $entry='DB Error: "'.oci_error($connection).'"<br />'; - $entry.='Offending command was: '.$query.', name:'.$name.', password:'.$password.'<br />'; - echo($entry); + $entry = $l->t('DB Error: "%s"', array(oci_error($connection))) . '<br />'; + $entry .= $l->t('Offending command was: "%s", name: %s, password: %s', + array($query, $name, $password)) . '<br />'; + \OC_Log::write('setup.oci', $entry, \OC_Log::WARN); } } + private static function setupMSSQLDatabase($dbhost, $dbuser, $dbpass, $dbname, $dbtableprefix) { + $l = self::getTrans(); + + //check if the database user has admin right + $masterConnectionInfo = array( "Database" => "master", "UID" => $dbuser, "PWD" => $dbpass); + + $masterConnection = @sqlsrv_connect($dbhost, $masterConnectionInfo); + if(!$masterConnection) { + $entry = null; + if( ($errors = sqlsrv_errors() ) != null) { + $entry='DB Error: "'.print_r(sqlsrv_errors()).'"<br />'; + } else { + $entry = ''; + } + throw new Exception($l->t('MS SQL username and/or password not valid: %s', array($entry))); + } + + OC_Config::setValue('dbuser', $dbuser); + OC_Config::setValue('dbpassword', $dbpass); + + self::mssql_createDBLogin($dbuser, $dbpass, $masterConnection); + + self::mssql_createDatabase($dbname, $masterConnection); + + self::mssql_createDBUser($dbuser, $dbname, $masterConnection); + + sqlsrv_close($masterConnection); + + self::mssql_createDatabaseStructure($dbhost, $dbname, $dbuser, $dbpass, $dbtableprefix); + } + + private static function mssql_createDBLogin($name, $password, $connection) { + $query = "SELECT * FROM master.sys.server_principals WHERE name = '".$name."';"; + $result = sqlsrv_query($connection, $query); + if ($result === false) { + if ( ($errors = sqlsrv_errors() ) != null) { + $entry='DB Error: "'.print_r(sqlsrv_errors()).'"<br />'; + } else { + $entry = ''; + } + $entry.='Offending command was: '.$query.'<br />'; + \OC_Log::write('setup.mssql', $entry, \OC_Log::WARN); + } else { + $row = sqlsrv_fetch_array($result); + + if ($row === false) { + if ( ($errors = sqlsrv_errors() ) != null) { + $entry='DB Error: "'.print_r(sqlsrv_errors()).'"<br />'; + } else { + $entry = ''; + } + $entry.='Offending command was: '.$query.'<br />'; + \OC_Log::write('setup.mssql', $entry, \OC_Log::WARN); + } else { + if ($row == null) { + $query = "CREATE LOGIN [".$name."] WITH PASSWORD = '".$password."';"; + $result = sqlsrv_query($connection, $query); + if (!$result or $result === false) { + if ( ($errors = sqlsrv_errors() ) != null) { + $entry='DB Error: "'.print_r(sqlsrv_errors()).'"<br />'; + } else { + $entry = ''; + } + $entry.='Offending command was: '.$query.'<br />'; + \OC_Log::write('setup.mssql', $entry, \OC_Log::WARN); + } + } + } + } + } + + private static function mssql_createDBUser($name, $dbname, $connection) { + $query = "SELECT * FROM [".$dbname."].sys.database_principals WHERE name = '".$name."';"; + $result = sqlsrv_query($connection, $query); + if ($result === false) { + if ( ($errors = sqlsrv_errors() ) != null) { + $entry='DB Error: "'.print_r(sqlsrv_errors()).'"<br />'; + } else { + $entry = ''; + } + $entry.='Offending command was: '.$query.'<br />'; + \OC_Log::write('setup.mssql', $entry, \OC_Log::WARN); + } else { + $row = sqlsrv_fetch_array($result); + + if ($row === false) { + if ( ($errors = sqlsrv_errors() ) != null) { + $entry='DB Error: "'.print_r(sqlsrv_errors()).'"<br />'; + } else { + $entry = ''; + } + $entry.='Offending command was: '.$query.'<br />'; + \OC_Log::write('setup.mssql', $entry, \OC_Log::WARN); + } else { + if ($row == null) { + $query = "USE [".$dbname."]; CREATE USER [".$name."] FOR LOGIN [".$name."];"; + $result = sqlsrv_query($connection, $query); + if (!$result || $result === false) { + if ( ($errors = sqlsrv_errors() ) != null) { + $entry = 'DB Error: "'.print_r(sqlsrv_errors()).'"<br />'; + } else { + $entry = ''; + } + $entry.='Offending command was: '.$query.'<br />'; + \OC_Log::write('setup.mssql', $entry, \OC_Log::WARN); + } + } + + $query = "USE [".$dbname."]; EXEC sp_addrolemember 'db_owner', '".$name."';"; + $result = sqlsrv_query($connection, $query); + if (!$result || $result === false) { + if ( ($errors = sqlsrv_errors() ) != null) { + $entry='DB Error: "'.print_r(sqlsrv_errors()).'"<br />'; + } else { + $entry = ''; + } + $entry.='Offending command was: '.$query.'<br />'; + \OC_Log::write('setup.mssql', $entry, \OC_Log::WARN); + } + } + } + } + + private static function mssql_createDatabase($dbname, $connection) { + $query = "CREATE DATABASE [".$dbname."];"; + $result = sqlsrv_query($connection, $query); + if (!$result || $result === false) { + if ( ($errors = sqlsrv_errors() ) != null) { + $entry='DB Error: "'.print_r(sqlsrv_errors()).'"<br />'; + } else { + $entry = ''; + } + $entry.='Offending command was: '.$query.'<br />'; + \OC_Log::write('setup.mssql', $entry, \OC_Log::WARN); + } + } + + private static function mssql_createDatabaseStructure($dbhost, $dbname, $dbuser, $dbpass, $dbtableprefix) { + $connectionInfo = array( "Database" => $dbname, "UID" => $dbuser, "PWD" => $dbpass); + + $connection = @sqlsrv_connect($dbhost, $connectionInfo); + + //fill the database if needed + $query = "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '{$dbname}' AND TABLE_NAME = '{$dbtableprefix}users'"; + $result = sqlsrv_query($connection, $query); + if ($result === false) { + if ( ($errors = sqlsrv_errors() ) != null) { + $entry='DB Error: "'.print_r(sqlsrv_errors()).'"<br />'; + } else { + $entry = ''; + } + $entry.='Offending command was: '.$query.'<br />'; + \OC_Log::write('setup.mssql', $entry, \OC_Log::WARN); + } else { + $row = sqlsrv_fetch_array($result); + + if ($row === false) { + if ( ($errors = sqlsrv_errors() ) != null) { + $entry='DB Error: "'.print_r(sqlsrv_errors()).'"<br />'; + } else { + $entry = ''; + } + $entry.='Offending command was: '.$query.'<br />'; + \OC_Log::write('setup.mssql', $entry, \OC_Log::WARN); + } else { + if ($row == null) { + OC_DB::createDbFromStructure('db_structure.xml'); + } + } + } + + sqlsrv_close($connection); + } + /** * create .htaccess files for apache hosts */ @@ -610,4 +835,25 @@ class OC_Setup { file_put_contents(OC_Config::getValue('datadirectory', OC::$SERVERROOT.'/data').'/.htaccess', $content); file_put_contents(OC_Config::getValue('datadirectory', OC::$SERVERROOT.'/data').'/index.html', ''); } + + /** + * @brief Post installation checks + */ + public static function postSetupCheck($params) { + // setup was successful -> webdav testing now + $l = self::getTrans(); + if (OC_Util::isWebDAVWorking()) { + header("Location: ".OC::$WEBROOT.'/'); + } else { + + $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'); + + $tmpl = new OC_Template('', 'error', 'guest'); + $tmpl->assign('errors', array(1 => array('error' => $error, 'hint' => $hint))); + $tmpl->printPage(); + exit(); + } + } } diff --git a/lib/template.php b/lib/template.php index fb9f7ad62d9..b2d1f0c0292 100644 --- a/lib/template.php +++ b/lib/template.php @@ -147,7 +147,7 @@ function html_select_options($options, $selected, $params=array()) { $label = $label[$label_name]; } $select = in_array($value, $selected) ? ' selected="selected"' : ''; - $html .= '<option value="' . $value . '"' . $select . '>' . $label . '</option>'."\n"; + $html .= '<option value="' . OC_Util::sanitizeHTML($value) . '"' . $select . '>' . OC_Util::sanitizeHTML($label) . '</option>'."\n"; } return $html; } @@ -192,7 +192,13 @@ class OC_Template{ // Content Security Policy // If you change the standard policy, please also change it in config.sample.php - $policy = OC_Config::getValue('custom_csp_policy', 'default-src \'self\'; script-src \'self\' \'unsafe-eval\'; style-src \'self\' \'unsafe-inline\'; frame-src *; img-src *; font-src \'self\' data:'); + $policy = OC_Config::getValue('custom_csp_policy', + 'default-src \'self\'; ' + .'script-src \'self\' \'unsafe-eval\'; ' + .'style-src \'self\' \'unsafe-inline\'; ' + .'frame-src *; ' + .'img-src *; ' + .'font-src \'self\' data:'); header('Content-Security-Policy:'.$policy); // Standard header('X-WebKit-CSP:'.$policy); // Older webkit browsers @@ -215,7 +221,8 @@ class OC_Template{ $mode='tablet'; }elseif(stripos($_SERVER['HTTP_USER_AGENT'], 'iphone')>0) { $mode='mobile'; - }elseif((stripos($_SERVER['HTTP_USER_AGENT'], 'N9')>0) and (stripos($_SERVER['HTTP_USER_AGENT'], 'nokia')>0)) { + }elseif((stripos($_SERVER['HTTP_USER_AGENT'], 'N9')>0) + and (stripos($_SERVER['HTTP_USER_AGENT'], 'nokia')>0)) { $mode='mobile'; }else{ $mode='default'; @@ -285,7 +292,8 @@ class OC_Template{ if ($this->checkPathForTemplate(OC::$SERVERROOT."/themes/$theme/$app/templates/", $name, $fext)) { }elseif ($this->checkPathForTemplate(OC::$SERVERROOT."/$app/templates/", $name, $fext)) { }else{ - echo('template not found: template:'.$name.' formfactor:'.$fext.' webroot:'.OC::$WEBROOT.' serverroot:'.OC::$SERVERROOT); + echo('template not found: template:'.$name.' formfactor:'.$fext + .' webroot:'.OC::$WEBROOT.' serverroot:'.OC::$SERVERROOT); die(); } @@ -295,7 +303,8 @@ class OC_Template{ if ($this->checkPathForTemplate(OC::$SERVERROOT."/themes/$theme/core/templates/", $name, $fext)) { } elseif ($this->checkPathForTemplate(OC::$SERVERROOT."/core/templates/", $name, $fext)) { }else{ - echo('template not found: template:'.$name.' formfactor:'.$fext.' webroot:'.OC::$WEBROOT.' serverroot:'.OC::$SERVERROOT); + echo('template not found: template:'.$name.' formfactor:'.$fext + .' webroot:'.OC::$WEBROOT.' serverroot:'.OC::$SERVERROOT); die(); } } @@ -332,7 +341,6 @@ class OC_Template{ * @brief Assign variables * @param string $key key * @param string $value value - * @param bool $sanitizeHTML false, if data shouldn't get passed through htmlentities * @return bool * * This function assigns a variable. It can be accessed via $_[$key] in @@ -340,8 +348,7 @@ class OC_Template{ * * If the key existed before, it will be overwritten */ - public function assign( $key, $value, $sanitizeHTML=true ) { - if($sanitizeHTML == true) $value=OC_Util::sanitizeHTML($value); + public function assign( $key, $value) { $this->vars[$key] = $value; return true; } @@ -404,9 +411,6 @@ class OC_Template{ if( $this->renderas ) { $page = new OC_TemplateLayout($this->renderas); - if($this->renderas == 'user') { - $page->assign('requesttoken', $this->vars['requesttoken']); - } // Add custom headers $page->assign('headers', $this->headers, false); @@ -478,7 +482,7 @@ class OC_Template{ public static function printUserPage( $application, $name, $parameters = array() ) { $content = new OC_Template( $application, $name, "user" ); foreach( $parameters as $key => $value ) { - $content->assign( $key, $value, false ); + $content->assign( $key, $value ); } print $content->printPage(); } @@ -493,7 +497,7 @@ class OC_Template{ public static function printAdminPage( $application, $name, $parameters = array() ) { $content = new OC_Template( $application, $name, "admin" ); foreach( $parameters as $key => $value ) { - $content->assign( $key, $value, false ); + $content->assign( $key, $value ); } return $content->printPage(); } @@ -508,7 +512,7 @@ class OC_Template{ public static function printGuestPage( $application, $name, $parameters = array() ) { $content = new OC_Template( $application, $name, "guest" ); foreach( $parameters as $key => $value ) { - $content->assign( $key, $value, false ); + $content->assign( $key, $value ); } return $content->printPage(); } @@ -519,8 +523,10 @@ class OC_Template{ * @param string $hint An option hint message */ public static function printErrorPage( $error_msg, $hint = '' ) { + $content = new OC_Template( '', 'error', 'error' ); $errors = array(array('error' => $error_msg, 'hint' => $hint)); - OC_Template::printGuestPage("", "error", array("errors" => $errors)); + $content->assign( 'errors', $errors, false ); + $content->printPage(); die(); } } diff --git a/lib/templatelayout.php b/lib/templatelayout.php index 345f540af04..29f120a6041 100644 --- a/lib/templatelayout.php +++ b/lib/templatelayout.php @@ -13,25 +13,26 @@ class OC_TemplateLayout extends OC_Template { if( $renderas == 'user' ) { parent::__construct( 'core', 'layout.user' ); if(in_array(OC_APP::getCurrentApp(), array('settings','admin', 'help'))!==false) { - $this->assign('bodyid', 'body-settings', false); + $this->assign('bodyid', 'body-settings'); }else{ - $this->assign('bodyid', 'body-user', false); + $this->assign('bodyid', 'body-user'); } // Add navigation entry $this->assign( 'application', '', false ); $navigation = OC_App::getNavigation(); - $this->assign( 'navigation', $navigation, false); - $this->assign( 'settingsnavigation', OC_App::getSettingsNavigation(), false); + $this->assign( 'navigation', $navigation); + $this->assign( 'settingsnavigation', OC_App::getSettingsNavigation()); foreach($navigation as $entry) { if ($entry['active']) { - $this->assign( 'application', $entry['name'], false ); + $this->assign( 'application', $entry['name'] ); break; } } $user_displayname = OC_User::getDisplayName(); $this->assign( 'user_displayname', $user_displayname ); - } else if ($renderas == 'guest') { + $this->assign( 'user_uid', OC_User::getUser() ); + } else if ($renderas == 'guest' || $renderas == 'error') { parent::__construct('core', 'layout.guest'); } else { parent::__construct('core', 'layout.base'); @@ -39,7 +40,7 @@ class OC_TemplateLayout extends OC_Template { // Add the js files $jsfiles = self::findJavascriptFiles(OC_Util::$scripts); $this->assign('jsfiles', array(), false); - if (OC_Config::getValue('installed', false)) { + if (OC_Config::getValue('installed', false) && $renderas!='error') { $this->append( 'jsfiles', OC_Helper::linkToRoute('js_config')); } if (!empty(OC_Util::$core_scripts)) { @@ -134,7 +135,8 @@ class OC_TemplateLayout extends OC_Template { } } if(! $append) { - echo('css file not found: style:'.$style.' formfactor:'.$fext.' webroot:'.OC::$WEBROOT.' serverroot:'.OC::$SERVERROOT); + echo('css file not found: style:'.$style.' formfactor:'.$fext + .' webroot:'.OC::$WEBROOT.' serverroot:'.OC::$SERVERROOT); die(); } } @@ -202,7 +204,8 @@ class OC_TemplateLayout extends OC_Template { } } if(! $append) { - echo('js file not found: script:'.$script.' formfactor:'.$fext.' webroot:'.OC::$WEBROOT.' serverroot:'.OC::$SERVERROOT); + echo('js file not found: script:'.$script.' formfactor:'.$fext + .' webroot:'.OC::$WEBROOT.' serverroot:'.OC::$SERVERROOT); die(); } } diff --git a/lib/updater.php b/lib/updater.php index d44ac108380..e7d33ac2bb9 100644 --- a/lib/updater.php +++ b/lib/updater.php @@ -30,7 +30,9 @@ class OC_Updater{ */ public static function check() { OC_Appconfig::setValue('core', 'lastupdatedat', microtime(true)); - if(OC_Appconfig::getValue('core', 'installedat', '')=='') OC_Appconfig::setValue('core', 'installedat', microtime(true)); + if(OC_Appconfig::getValue('core', 'installedat', '')=='') { + OC_Appconfig::setValue('core', 'installedat', microtime(true)); + } $updaterurl='http://apps.owncloud.com/updater.php'; $version=OC_Util::getVersion(); @@ -72,7 +74,9 @@ class OC_Updater{ if(OC_Config::getValue('updatechecker', true)==true) { $data=OC_Updater::check(); if(isset($data['version']) and $data['version']<>'') { - $txt='<span style="color:#AA0000; font-weight:bold;">'.$l->t('%s is available. Get <a href="%s">more information</a>', array($data['versionstring'], $data['web'])).'</span>'; + $txt='<span style="color:#AA0000; font-weight:bold;">' + .$l->t('%s is available. Get <a href="%s">more information</a>', + array($data['versionstring'], $data['web'])).'</span>'; }else{ $txt=$l->t('up to date'); } diff --git a/lib/user.php b/lib/user.php index 9dc8cca97a6..6144f0f6bf9 100644 --- a/lib/user.php +++ b/lib/user.php @@ -160,7 +160,8 @@ class OC_User { // Check the name for bad characters // 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 "_.@-"'); + throw new Exception('Only the following characters are allowed in a username:' + .' "a-z", "A-Z", "0-9", and "_.@-"'); } // No empty username if(trim($uid) == '') { @@ -172,7 +173,7 @@ class OC_User { } // Check if user already exists - if( self::userExists($uid) ) { + if( self::userExistsForCreation($uid) ) { throw new Exception('The username is already being used'); } @@ -436,7 +437,7 @@ class OC_User { } return false; } - + /** * @brief Check whether user can change his display name * @param $uid The username @@ -445,10 +446,12 @@ class OC_User { * Check whether a specified user can change his display name */ public static function canUserChangeDisplayName($uid) { - foreach(self::$_usedBackends as $backend) { - if($backend->implementsActions(OC_USER_BACKEND_SET_DISPLAYNAME)) { - if($backend->userExists($uid)) { - return true; + if (OC_Config::getValue('allow_user_to_change_display_name', true)) { + foreach(self::$_usedBackends as $backend) { + if($backend->implementsActions(OC_USER_BACKEND_SET_DISPLAYNAME)) { + if($backend->userExists($uid)) { + return true; + } } } } @@ -485,7 +488,7 @@ class OC_User { */ public static function getHome($uid) { foreach(self::$_usedBackends as $backend) { - if($backend->implementsActions(OC_USER_BACKEND_GET_HOME)) { + if($backend->implementsActions(OC_USER_BACKEND_GET_HOME) && $backend->userExists($uid)) { $result=$backend->getHome($uid); if($result) { return $result; @@ -527,7 +530,7 @@ class OC_User { $displayNames = array_merge($displayNames, $backendDisplayNames); } } - ksort($displayNames); + asort($displayNames); return $displayNames; } @@ -539,9 +542,9 @@ class OC_User { */ public static function userExists($uid, $excludingBackend=null) { foreach(self::$_usedBackends as $backend) { - if (!is_null($excludingBackend) && !strcmp(get_class($backend),$excludingBackend)) { - OC_Log::write('OC_User', $excludingBackend . 'excluded from user existance check.', OC_Log::DEBUG); - continue; + if (!is_null($excludingBackend) && !strcmp(get_class($backend), $excludingBackend)) { + OC_Log::write('OC_User', $excludingBackend . 'excluded from user existance check.', OC_Log::DEBUG); + continue; } $result=$backend->userExists($uid); if($result===true) { @@ -551,6 +554,19 @@ class OC_User { return false; } + public static function userExistsForCreation($uid) { + foreach(self::$_usedBackends as $backend) { + if(!$backend->hasUserListings()) + continue; + + $result=$backend->userExists($uid); + if($result===true) { + return true; + } + } + return false; + } + /** * disables a user * @param string $userid the user to disable @@ -573,7 +589,8 @@ class OC_User { * @param string $userid */ public static function enableUser($userid) { - $sql = "DELETE FROM `*PREFIX*preferences` WHERE `userid` = ? AND `appid` = ? AND `configkey` = ? AND `configvalue` = ?"; + $sql = 'DELETE FROM `*PREFIX*preferences`' + ." WHERE `userid` = ? AND `appid` = ? AND `configkey` = ? AND `configvalue` = ?"; $stmt = OC_DB::prepare($sql); if ( ! OC_DB::isError($stmt) ) { $result = $stmt->execute(array($userid, 'core', 'enabled', 'false')); @@ -591,14 +608,17 @@ class OC_User { * @return bool */ public static function isEnabled($userid) { - $sql = "SELECT `userid` FROM `*PREFIX*preferences` WHERE `userid` = ? AND `appid` = ? AND `configkey` = ? AND `configvalue` = ?"; + $sql = 'SELECT `userid` FROM `*PREFIX*preferences`' + .' WHERE `userid` = ? AND `appid` = ? AND `configkey` = ? AND `configvalue` = ?'; $stmt = OC_DB::prepare($sql); if ( ! OC_DB::isError($stmt) ) { $result = $stmt->execute(array($userid, 'core', 'enabled', 'false')); if ( ! OC_DB::isError($result) ) { return $result->numRows() ? false : true; } else { - OC_Log::write('OC_User', 'could not check if enabled: '. OC_DB::getErrorMessage($result), OC_Log::ERROR); + OC_Log::write('OC_User', + 'could not check if enabled: '. OC_DB::getErrorMessage($result), + OC_Log::ERROR); } } else { OC_Log::write('OC_User', 'could not check if enabled: '. OC_DB::getErrorMessage($stmt), OC_Log::ERROR); diff --git a/lib/user/backend.php b/lib/user/backend.php index 56fa3195978..93e8f17ca98 100644 --- a/lib/user/backend.php +++ b/lib/user/backend.php @@ -36,7 +36,7 @@ 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', 0x010000); +define('OC_USER_BACKEND_SET_DISPLAYNAME', 0x100000); /** @@ -124,7 +124,7 @@ abstract class OC_User_Backend implements OC_User_Interface { public function getHome($uid) { return false; } - + /** * @brief get display name of the user * @param $uid user ID of the user @@ -133,19 +133,27 @@ abstract class OC_User_Backend implements OC_User_Interface { public function getDisplayName($uid) { return $uid; } - - /**
- * @brief Get a list of all display names
- * @returns array with all displayNames (value) and the correspondig uids (key)
- *
- * Get a list of all display names and user ids.
- */
- public function getDisplayNames($search = '', $limit = null, $offset = null) {
+ + /** + * @brief Get a list of all display names + * @returns array with all displayNames (value) and the corresponding uids (key) + * + * Get a list of all display names and user ids. + */ + public function getDisplayNames($search = '', $limit = null, $offset = null) { $displayNames = array(); $users = $this->getUsers($search, $limit, $offset); foreach ( $users as $user) { $displayNames[$user] = $user; } - return $displayNames;
+ return $displayNames; + } + + /** + * @brief Check if a user list is available or not + * @return boolean if users can be listed or not + */ + public function hasUserListings() { + return false; } } diff --git a/lib/user/database.php b/lib/user/database.php index 8dfd9534a96..210c7f3e1eb 100644 --- a/lib/user/database.php +++ b/lib/user/database.php @@ -110,31 +110,31 @@ class OC_User_Database extends OC_User_Backend { return false; } } - - /**
- * @brief Set display name
- * @param $uid The username
- * @param $displayName The new display name
- * @returns true/false
- *
- * Change the display name of a user
+ + /** + * @brief Set display name + * @param $uid The username + * @param $displayName The new display name + * @returns true/false + * + * 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 ));
- return true;
- }else{
- return false;
- }
+ if( $this->userExists($uid) ) { + $query = OC_DB::prepare( 'UPDATE `*PREFIX*users` SET `displayname` = ? WHERE `uid` = ?' ); + $query->execute( array( $displayName, $uid )); + return true; + }else{ + return false; + } } - /**
- * @brief get display name of the user
- * @param $uid user ID of the user
- * @return display name
- */
- public function getDisplayName($uid) {
+ /** + * @brief get display name of the user + * @param $uid user ID of the user + * @return 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(); @@ -144,38 +144,40 @@ class OC_User_Database extends OC_User_Backend { } else { return $uid; } - }
+ } } - - /**
- * @brief Get a list of all display names
- * @returns array with all displayNames (value) and the correspondig uids (key)
- *
- * Get a list of all display names and user ids.
- */
+ + /** + * @brief Get a list of all display names + * @returns array with all displayNames (value) and the correspondig uids (key) + * + * Get a list of all display names and user ids. + */ 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);
+ $query = OC_DB::prepare('SELECT `uid`, `displayname` FROM `*PREFIX*users`' + .' WHERE LOWER(`displayname`) LIKE LOWER(?)', $limit, $offset); $result = $query->execute(array($search.'%')); - $users = array();
- while ($row = $result->fetchRow()) {
- $displayNames[$row['uid']] = $row['displayname'];
+ $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);
+ $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()) {
+ while ($row = $result->fetchRow()) { $displayName = trim($row['displayname'], ' '); - if ( empty($displayName) ) {
+ if ( empty($displayName) ) { $displayNames[$row['uid']] = $row['uid']; - }
+ } } - -
- return $displayNames;
+ + + return $displayNames; } - + /** * @brief Check if the password is correct * @param $uid The username @@ -256,4 +258,12 @@ class OC_User_Database extends OC_User_Backend { return false; } } + + /** + * @return bool + */ + public function hasUserListings() { + return true; + } + } diff --git a/lib/user/dummy.php b/lib/user/dummy.php index 4dbbc02b888..d63f60efbeb 100644 --- a/lib/user/dummy.php +++ b/lib/user/dummy.php @@ -112,4 +112,11 @@ class OC_User_Dummy extends OC_User_Backend { public function userExists($uid) { return isset($this->users[$uid]); } + + /** + * @return bool + */ + public function hasUserListings() { + return true; + } } diff --git a/lib/user/interface.php b/lib/user/interface.php index b4667633b50..b1e19aea7fb 100644 --- a/lib/user/interface.php +++ b/lib/user/interface.php @@ -66,10 +66,15 @@ interface OC_User_Interface { /** * @brief Get a list of all display names - * @returns array with all displayNames (value) and the correspondig uids (key) + * @returns array with all displayNames (value) and the corresponding uids (key) * * Get a list of all display names and user ids. */ public function getDisplayNames($search = '', $limit = null, $offset = null); + /** + * @brief Check if a user list is available or not + * @return boolean if users can be listed or not + */ + public function hasUserListings(); }
\ No newline at end of file diff --git a/lib/util.php b/lib/util.php index 9ce974619bc..de1f870fd7e 100755 --- a/lib/util.php +++ b/lib/util.php @@ -51,7 +51,7 @@ class OC_Util { mkdir( $userdirectory, 0755, true ); } //jail the user into his "home" directory - \OC\Files\Filesystem::init($user_dir); + \OC\Files\Filesystem::init($user, $user_dir); $quotaProxy=new OC_FileProxy_Quota(); $fileOperationProxy = new OC_FileProxy_FileOperations(); @@ -73,8 +73,9 @@ class OC_Util { * @return array */ public static function getVersion() { - // hint: We only can count up. So the internal version number of ownCloud 4.5 will be 4.90.0. This is not visible to the user - return array(4, 91, 9); + // hint: We only can count up. Reset minor/patchlevel when + // updating major/minor version number. + return array(4, 95, 10); } /** @@ -82,11 +83,13 @@ class OC_Util { * @return string */ public static function getVersionString() { - return '5.0 pre alpha'; + return '5.0 RC 1'; } /** - * get the current installed edition of ownCloud. There is the community edition that just returns an empty string and the enterprise edition that returns "Enterprise". + * get the current installed edition of ownCloud. There is the community + * edition that just returns an empty string and the enterprise edition + * that returns "Enterprise". * @return string */ public static function getEditionString() { @@ -166,24 +169,33 @@ class OC_Util { $web_server_restart= false; //check for database drivers - if(!(is_callable('sqlite_open') or class_exists('SQLite3')) and !is_callable('mysql_connect') and !is_callable('pg_connect')) { - $errors[]=array('error'=>'No database drivers (sqlite, mysql, or postgresql) installed.<br/>', 'hint'=>'');//TODO: sane hint + if(!(is_callable('sqlite_open') or class_exists('SQLite3')) + and !is_callable('mysql_connect') + and !is_callable('pg_connect')) { + $errors[]=array('error'=>'No database drivers (sqlite, mysql, or postgresql) installed.<br/>', + 'hint'=>'');//TODO: sane hint $web_server_restart= true; } //common hint for all file permissons error messages - $permissionsHint="Permissions can usually be fixed by giving the webserver write access to the ownCloud directory"; + $permissionsHint='Permissions can usually be fixed by giving the webserver write access' + .' to the ownCloud directory'; // Check if config folder is writable. if(!is_writable(OC::$SERVERROOT."/config/") or !is_readable(OC::$SERVERROOT."/config/")) { - $errors[]=array('error'=>"Can't write into config directory 'config'", 'hint'=>"You can usually fix this by giving the webserver user write access to the config directory in owncloud"); + $errors[]=array('error'=>"Can't write into config directory 'config'", + 'hint'=>'You can usually fix this by giving the webserver user write access' + .' to the config directory in owncloud'); } // Check if there is a writable install folder. if(OC_Config::getValue('appstoreenabled', true)) { - if( OC_App::getInstallPath() === null || !is_writable(OC_App::getInstallPath()) || !is_readable(OC_App::getInstallPath()) ) { - $errors[]=array('error'=>"Can't write into apps directory", 'hint'=>"You can usually fix this by giving the webserver user write access to the apps directory - in owncloud or disabling the appstore in the config file."); + if( OC_App::getInstallPath() === null + || !is_writable(OC_App::getInstallPath()) + || !is_readable(OC_App::getInstallPath()) ) { + $errors[]=array('error'=>"Can't write into apps directory", + 'hint'=>'You can usually fix this by giving the webserver user write access' + .' to the apps directory in owncloud or disabling the appstore in the config file.'); } } $CONFIG_DATADIRECTORY = OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" ); @@ -193,69 +205,88 @@ class OC_Util { if ($success) { $errors = array_merge($errors, self::checkDataDirectoryPermissions($CONFIG_DATADIRECTORY)); } else { - $errors[]=array('error'=>"Can't create data directory (".$CONFIG_DATADIRECTORY.")", 'hint'=>"You can usually fix this by giving the webserver write access to the ownCloud directory '".OC::$SERVERROOT."' (in a terminal, use the command 'chown -R www-data:www-data /path/to/your/owncloud/install/data' "); + $errors[]=array('error'=>"Can't create data directory (".$CONFIG_DATADIRECTORY.")", + 'hint'=>"You can usually fix this by giving the webserver write access to the ownCloud directory '" + .OC::$SERVERROOT."' (in a terminal, use the command " + ."'chown -R www-data:www-data /path/to/your/owncloud/install/data' "); } } else if(!is_writable($CONFIG_DATADIRECTORY) or !is_readable($CONFIG_DATADIRECTORY)) { - $errors[]=array('error'=>'Data directory ('.$CONFIG_DATADIRECTORY.') not writable by ownCloud<br/>', 'hint'=>$permissionsHint); + $errors[]=array('error'=>'Data directory ('.$CONFIG_DATADIRECTORY.') not writable by ownCloud<br/>', + 'hint'=>$permissionsHint); } else { $errors = array_merge($errors, self::checkDataDirectoryPermissions($CONFIG_DATADIRECTORY)); } // check if all required php modules are present if(!class_exists('ZipArchive')) { - $errors[]=array('error'=>'PHP module zip not installed.<br/>', 'hint'=>'Please ask your server administrator to install the module.'); + $errors[]=array('error'=>'PHP module zip not installed.<br/>', + 'hint'=>'Please ask your server administrator to install the module.'); $web_server_restart= false; } - + if(!class_exists('DOMDocument')) { + $errors[] = array('error' => 'PHP module dom not installed.<br/>', + 'hint' => 'Please ask your server administrator to install the module.'); + $web_server_restart = false; + } + if(!function_exists('xml_parser_create')) { + $errors[] = array('error' => 'PHP module libxml not installed.<br/>', + 'hint' => 'Please ask your server administrator to install the module.'); + $web_server_restart = false; + } if(!function_exists('mb_detect_encoding')) { - $errors[]=array('error'=>'PHP module mb multibyte not installed.<br/>', 'hint'=>'Please ask your server administrator to install the module.'); + $errors[]=array('error'=>'PHP module mb multibyte not installed.<br/>', + 'hint'=>'Please ask your server administrator to install the module.'); $web_server_restart= false; } if(!function_exists('ctype_digit')) { - $errors[]=array('error'=>'PHP module ctype is not installed.<br/>', 'hint'=>'Please ask your server administrator to install the module.'); + $errors[]=array('error'=>'PHP module ctype is not installed.<br/>', + 'hint'=>'Please ask your server administrator to install the module.'); $web_server_restart= false; } if(!function_exists('json_encode')) { - $errors[]=array('error'=>'PHP module JSON is not installed.<br/>', 'hint'=>'Please ask your server administrator to install the module.'); + $errors[]=array('error'=>'PHP module JSON is not installed.<br/>', + 'hint'=>'Please ask your server administrator to install the module.'); $web_server_restart= false; } if(!function_exists('imagepng')) { - $errors[]=array('error'=>'PHP module GD is not installed.<br/>', 'hint'=>'Please ask your server administrator to install the module.'); + $errors[]=array('error'=>'PHP module GD is not installed.<br/>', + 'hint'=>'Please ask your server administrator to install the module.'); $web_server_restart= false; } if(!function_exists('gzencode')) { - $errors[]=array('error'=>'PHP module zlib is not installed.<br/>', 'hint'=>'Please ask your server administrator to install the module.'); + $errors[]=array('error'=>'PHP module zlib is not installed.<br/>', + 'hint'=>'Please ask your server administrator to install the module.'); $web_server_restart= false; } if(!function_exists('iconv')) { - $errors[]=array('error'=>'PHP module iconv is not installed.<br/>', 'hint'=>'Please ask your server administrator to install the module.'); + $errors[]=array('error'=>'PHP module iconv is not installed.<br/>', + 'hint'=>'Please ask your server administrator to install the module.'); $web_server_restart= false; } if(!function_exists('simplexml_load_string')) { - $errors[]=array('error'=>'PHP module SimpleXML is not installed.<br/>', 'hint'=>'Please ask your server administrator to install the module.'); + $errors[]=array('error'=>'PHP module SimpleXML is not installed.<br/>', + 'hint'=>'Please ask your server administrator to install the module.'); $web_server_restart= false; } if(floatval(phpversion())<5.3) { - $errors[]=array('error'=>'PHP 5.3 is required.<br/>', '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.'); + $errors[]=array('error'=>'PHP 5.3 is required.<br/>', + '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.'); $web_server_restart= false; } if(!defined('PDO::ATTR_DRIVER_NAME')) { - $errors[]=array('error'=>'PHP PDO module is not installed.<br/>', 'hint'=>'Please ask your server administrator to install the module.'); + $errors[]=array('error'=>'PHP PDO module is not installed.<br/>', + 'hint'=>'Please ask your server administrator to install the module.'); $web_server_restart= false; } - - $handler = ini_get("session.save_handler"); - if($handler == "files") { - $tmpDir = session_save_path(); - if($tmpDir != ""){ - if(!@is_writable($tmpDir)){ - $errors[]=array('error' => 'The temporary folder used by PHP to save the session data is either incorrect or not writable! Please check : '.session_save_path().'<br/>', - 'hint'=>'Please ask your server administrator to grant write access or define another temporary folder.'); - } - } + if(ini_get('safe_mode')) { + $errors[]=array('error'=>'PHP Safe Mode is enabled. ownCloud requires that it is disabled to work properly.<br/>', + 'hint'=>'PHP Safe Mode is a deprecated and mostly useless setting that should be disabled. Please ask your server administrator to disable it in php.ini or in your webserver config.'); + $web_server_restart= false; } if($web_server_restart) { - $errors[]=array('error'=>'PHP modules have been installed, but they are still listed as missing?<br/>', 'hint'=>'Please ask your server administrator to restart the web server.'); + $errors[]=array('error'=>'PHP modules have been installed, but they are still listed as missing?<br/>', + 'hint'=>'Please ask your server administrator to restart the web server.'); } return $errors; @@ -270,14 +301,16 @@ class OC_Util { if (stristr(PHP_OS, 'WIN')) { //TODO: permissions checks for windows hosts } else { - $permissionsModHint = 'Please change the permissions to 0770 so that the directory cannot be listed by other users.'; + $permissionsModHint = 'Please change the permissions to 0770 so that the directory' + .' cannot be listed by other users.'; $prems = substr(decoct(@fileperms($dataDirectory)), -3); if (substr($prems, -1) != '0') { OC_Helper::chmodr($dataDirectory, 0770); clearstatcache(); $prems = substr(decoct(@fileperms($dataDirectory)), -3); if (substr($prems, 2, 1) != '0') { - $errors[] = array('error' => 'Data directory ('.$dataDirectory.') is readable for other users<br/>', 'hint' => $permissionsModHint); + $errors[] = array('error' => 'Data directory ('.$dataDirectory.') is readable for other users<br/>', + 'hint' => $permissionsModHint); } } } @@ -290,14 +323,14 @@ class OC_Util { $parameters[$value] = true; } if (!empty($_POST['user'])) { - $parameters["username"] = OC_Util::sanitizeHTML($_POST['user']).'"'; + $parameters["username"] = $_POST['user']; $parameters['user_autofocus'] = false; } else { $parameters["username"] = ''; $parameters['user_autofocus'] = true; } if (isset($_REQUEST['redirect_url'])) { - $redirect_url = OC_Util::sanitizeHTML($_REQUEST['redirect_url']); + $redirect_url = $_REQUEST['redirect_url']; $parameters['redirect_url'] = urlencode($redirect_url); } @@ -323,7 +356,8 @@ class OC_Util { public static function checkLoggedIn() { // Check if we are a user if( !OC_User::isLoggedIn()) { - header( 'Location: '.OC_Helper::linkToAbsolute( '', 'index.php', array('redirect_url' => OC_Request::requestUri()))); + header( 'Location: '.OC_Helper::linkToAbsolute( '', 'index.php', + array('redirect_url' => OC_Request::requestUri()))); exit(); } } @@ -430,13 +464,17 @@ class OC_Util { * @see OC_Util::callRegister() */ public static function isCallRegistered() { + if(!isset($_SESSION['requesttoken'])) { + return false; + } + if(isset($_GET['requesttoken'])) { $token=$_GET['requesttoken']; - }elseif(isset($_POST['requesttoken'])) { + } elseif(isset($_POST['requesttoken'])) { $token=$_POST['requesttoken']; - }elseif(isset($_SERVER['HTTP_REQUESTTOKEN'])) { + } elseif(isset($_SERVER['HTTP_REQUESTTOKEN'])) { $token=$_SERVER['HTTP_REQUESTTOKEN']; - }else{ + } else { //no token found. return false; } @@ -471,10 +509,10 @@ class OC_Util { * @return array with sanitized strings or a single sanitized string, depends on the input parameter. */ public static function sanitizeHTML( &$value ) { - if (is_array($value) || is_object($value)) { + if (is_array($value)) { array_walk_recursive($value, 'OC_Util::sanitizeHTML'); } else { - $value = htmlentities($value, ENT_QUOTES, 'UTF-8'); //Specify encoding for PHP<5.4 + $value = htmlentities((string)$value, ENT_QUOTES, 'UTF-8'); //Specify encoding for PHP<5.4 } return $value; } @@ -516,9 +554,56 @@ class OC_Util { } } + /** + * we test if webDAV is working properly + * + * The basic assumption is that if the server returns 401/Not Authenticated for an unauthenticated PROPFIND + * the web server it self is setup properly. + * + * Why not an authenticated PROFIND and other verbs? + * - We don't have the password available + * - We have no idea about other auth methods implemented (e.g. OAuth with Bearer header) + * + */ + public static function isWebDAVWorking() { + if (!function_exists('curl_init')) { + return true; + } + $settings = array( + 'baseUri' => OC_Helper::linkToRemote('webdav'), + ); + + // save the old timeout so that we can restore it later + $old_timeout=ini_get("default_socket_timeout"); + + // use a 5 sec timeout for the check. Should be enough for local requests. + ini_set("default_socket_timeout", 5); + + $client = new \Sabre_DAV_Client($settings); + + // for this self test we don't care if the ssl certificate is self signed and the peer cannot be verified. + $client->setVerifyPeer(false); + + $return = true; + try { + // test PROPFIND + $client->propfind('', array('{DAV:}resourcetype')); + } catch(\Sabre_DAV_Exception_NotAuthenticated $e) { + $return = true; + } catch(\Exception $e) { + OC_Log::write('core', 'isWebDAVWorking: NO - Reason: '.$e, OC_Log::WARN); + $return = false; + } + + // restore the original timeout + ini_set("default_socket_timeout", $old_timeout); + + return $return; + } /** - * Check if the setlocal call doesn't work. This can happen if the right local packages are not available on the server. + * Check if the setlocal call doesn't work. This can happen if the right + * local packages are not available on the server. */ public static function issetlocaleworking() { // setlocale test is pointless on Windows @@ -526,12 +611,11 @@ class OC_Util { return true; } - $result=setlocale(LC_ALL, 'en_US.UTF-8'); - if($result==false) { - return(false); - }else{ - return(true); - } + $result = setlocale(LC_ALL, 'en_US.UTF-8', 'en_US.UTF8'); + if($result == false) { + return false; + } + return true; } /** @@ -658,10 +742,10 @@ class OC_Util { curl_setopt($curl, CURLOPT_MAXREDIRS, 10); curl_setopt($curl, CURLOPT_USERAGENT, "ownCloud Server Crawler"); - if(OC_Config::getValue('proxy','')<>'') { + if(OC_Config::getValue('proxy', '')<>'') { curl_setopt($curl, CURLOPT_PROXY, OC_Config::getValue('proxy')); } - if(OC_Config::getValue('proxyuserpwd','')<>'') { + if(OC_Config::getValue('proxyuserpwd', '')<>'') { curl_setopt($curl, CURLOPT_PROXYUSERPWD, OC_Config::getValue('proxyuserpwd')); } $data = curl_exec($curl); @@ -670,7 +754,7 @@ class OC_Util { } else { $contextArray = null; - if(OC_Config::getValue('proxy','')<>'') { + if(OC_Config::getValue('proxy', '')<>'') { $contextArray = array( 'http' => array( 'timeout' => 10, diff --git a/lib/vcategories.php b/lib/vcategories.php index 1700870f91f..f94a0a55d3b 100644 --- a/lib/vcategories.php +++ b/lib/vcategories.php @@ -306,12 +306,18 @@ class OC_VCategories { OCP\Util::writeLog('core', __METHOD__.', name: ' . $name. ' exists already', OCP\Util::DEBUG); return false; } - OCP\DB::insertIfNotExist(self::CATEGORY_TABLE, - array( - 'uid' => $this->user, - 'type' => $this->type, - 'category' => $name, - )); + try { + OCP\DB::insertIfNotExist(self::CATEGORY_TABLE, + array( + 'uid' => $this->user, + 'type' => $this->type, + 'category' => $name, + )); + } catch(Exception $e) { + OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), + OCP\Util::ERROR); + return false; + } $id = OCP\DB::insertid(self::CATEGORY_TABLE); OCP\Util::writeLog('core', __METHOD__.', id: ' . $id, OCP\Util::DEBUG); $this->categories[$id] = $name; @@ -436,12 +442,17 @@ class OC_VCategories { private function save() { if(is_array($this->categories)) { foreach($this->categories as $category) { - OCP\DB::insertIfNotExist(self::CATEGORY_TABLE, - array( - 'uid' => $this->user, - 'type' => $this->type, - 'category' => $category, - )); + try { + OCP\DB::insertIfNotExist(self::CATEGORY_TABLE, + array( + 'uid' => $this->user, + 'type' => $this->type, + 'category' => $category, + )); + } catch(Exception $e) { + OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), + OCP\Util::ERROR); + } } // reload categories to get the proper ids. $this->loadCategories(); @@ -454,12 +465,17 @@ class OC_VCategories { $catid = $this->array_searchi($relation['category'], $categories); OC_Log::write('core', __METHOD__ . 'catid, ' . $relation['category'] . ' ' . $catid, OC_Log::DEBUG); if($catid) { - OCP\DB::insertIfNotExist(self::RELATION_TABLE, - array( - 'objid' => $relation['objid'], - 'categoryid' => $catid, - 'type' => $this->type, - )); + try { + OCP\DB::insertIfNotExist(self::RELATION_TABLE, + array( + 'objid' => $relation['objid'], + 'categoryid' => $catid, + 'type' => $this->type, + )); + } catch(Exception $e) { + OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), + OCP\Util::ERROR); + } } } self::$relations = array(); // reset @@ -689,7 +705,9 @@ class OC_VCategories { $stmt = OCP\DB::prepare($sql); $result = $stmt->execute(array($id)); if (OC_DB::isError($result)) { - OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR); + OC_Log::write('core', + __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), + OC_Log::ERROR); } } catch(Exception $e) { OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), |