diff options
Diffstat (limited to 'lib')
126 files changed, 2987 insertions, 1146 deletions
diff --git a/lib/MDB2/Driver/Function/sqlite3.php b/lib/MDB2/Driver/Function/sqlite3.php index 0bddde5bf3f..4147a48199f 100644 --- a/lib/MDB2/Driver/Function/sqlite3.php +++ b/lib/MDB2/Driver/Function/sqlite3.php @@ -92,7 +92,7 @@ class MDB2_Driver_Function_sqlite3 extends MDB2_Driver_Function_Common function substring($value, $position = 1, $length = null) { if (!is_null($length)) { - return "substr($value,$position,$length)"; + return "substr($value, $position, $length)"; } return "substr($value, $position, length($value))"; } diff --git a/lib/MDB2/Driver/Reverse/sqlite3.php b/lib/MDB2/Driver/Reverse/sqlite3.php index 36626478ce8..97037809549 100644 --- a/lib/MDB2/Driver/Reverse/sqlite3.php +++ b/lib/MDB2/Driver/Reverse/sqlite3.php @@ -476,7 +476,7 @@ class MDB2_Driver_Reverse_sqlite3 extends MDB2_Driver_Reverse_Common $definition['unique'] = true; $count = count($column_names); for ($i=0; $i<$count; ++$i) { - $column_name = strtok($column_names[$i]," "); + $column_name = strtok($column_names[$i], " "); $collation = strtok(" "); $definition['fields'][$column_name] = array( 'position' => $i+1 diff --git a/lib/MDB2/Driver/sqlite3.php b/lib/MDB2/Driver/sqlite3.php index 9757e4faf94..fa4c91c1269 100644 --- a/lib/MDB2/Driver/sqlite3.php +++ b/lib/MDB2/Driver/sqlite3.php @@ -153,7 +153,7 @@ class MDB2_Driver_sqlite3 extends MDB2_Driver_Common if($this->connection) { return $this->connection->escapeString($text); }else{ - return str_replace("'","''",$text);//TODO; more + return str_replace("'", "''", $text);//TODO; more } } @@ -276,7 +276,7 @@ class MDB2_Driver_sqlite3 extends MDB2_Driver_Common * @access public * @since 2.1.1 */ - function setTransactionIsolation($isolation,$options=array()) + function setTransactionIsolation($isolation, $options=array()) { $this->debug('Setting transaction isolation level', __FUNCTION__, array('is_manip' => true)); switch ($isolation) { @@ -351,7 +351,7 @@ class MDB2_Driver_sqlite3 extends MDB2_Driver_Common } if ($database_file !== ':memory:') { - if(!strpos($database_file,'.db')) { + if(!strpos($database_file, '.db')) { $database_file="$datadir/$database_file.db"; } if (!file_exists($database_file)) { @@ -387,7 +387,7 @@ class MDB2_Driver_sqlite3 extends MDB2_Driver_Common $php_errormsg = ''; $this->connection = new SQLite3($database_file); - if(is_callable(array($this->connection,'busyTimeout'))) {//busy timout is only available in php>=5.3 + if(is_callable(array($this->connection, 'busyTimeout'))) {//busy timout is only available in php>=5.3 $this->connection->busyTimeout(100); } $this->_lasterror = $this->connection->lastErrorMsg(); @@ -397,8 +397,7 @@ class MDB2_Driver_sqlite3 extends MDB2_Driver_Common } if ($this->fix_assoc_fields_names || - $this->options['portability'] & MDB2_PORTABILITY_FIX_ASSOC_FIELD_NAMES) - { + $this->options['portability'] & MDB2_PORTABILITY_FIX_ASSOC_FIELD_NAMES) { $this->connection->exec("PRAGMA short_column_names = 1"); $this->fix_assoc_fields_names = true; } @@ -1142,9 +1141,9 @@ class MDB2_Statement_sqlite3 extends MDB2_Statement_Common function bindValue($parameter, $value, $type = null) { if($type) { $type=$this->getParamType($type); - $this->statement->bindValue($parameter,$value,$type); + $this->statement->bindValue($parameter, $value, $type); }else{ - $this->statement->bindValue($parameter,$value); + $this->statement->bindValue($parameter, $value); } return MDB2_OK; } @@ -1165,9 +1164,9 @@ class MDB2_Statement_sqlite3 extends MDB2_Statement_Common function bindParam($parameter, &$value, $type = null) { if($type) { $type=$this->getParamType($type); - $this->statement->bindParam($parameter,$value,$type); + $this->statement->bindParam($parameter, $value, $type); }else{ - $this->statement->bindParam($parameter,$value); + $this->statement->bindParam($parameter, $value); } return MDB2_OK; } @@ -1318,7 +1317,7 @@ class MDB2_Statement_sqlite3 extends MDB2_Statement_Common }else{ $types=null; } - $err = $this->bindValueArray($values,$types); + $err = $this->bindValueArray($values, $types); if (PEAR::isError($err)) { return $this->db->raiseError(MDB2_ERROR, null, null, 'Binding Values failed with message: ' . $err->getMessage(), __FUNCTION__); diff --git a/lib/app.php b/lib/app.php index 3d2ceb1729f..ccd0958cd01 100644 --- a/lib/app.php +++ b/lib/app.php @@ -92,7 +92,7 @@ class OC_App{ * @param string/array $types * @return bool */ - public static function isType($app,$types) { + public static function isType($app, $types) { if(is_string($types)) { $types=array($types); } @@ -199,7 +199,7 @@ class OC_App{ }else{ $download=OC_OCSClient::getApplicationDownload($app, 1); if(isset($download['downloadlink']) and $download['downloadlink']!='') { - $app=OC_Installer::installApp(array('source'=>'http','href'=>$download['downloadlink'])); + $app=OC_Installer::installApp(array('source'=>'http', 'href'=>$download['downloadlink'])); } } } @@ -267,6 +267,8 @@ class OC_App{ * highlighting the current position of the user. */ public static function setActiveNavigationEntry( $id ) { + // load all the apps, to make sure we have all the navigation entries + self::loadApps(); self::$activeapp = $id; return true; } @@ -296,33 +298,33 @@ 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::linkTo( "settings", "help.php" ), "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::linkTo( "settings", "personal.php" ), "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)) // settings menu - $settings[]=array( "id" => "settings", "order" => 1000, "href" => OC_Helper::linkTo( "settings", "settings.php" ), "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($_SESSION["user_id"]) || OC_Group::inGroup( $_SESSION["user_id"], "admin" )) { // admin users menu - $settings[] = array( "id" => "core_users", "order" => 2, "href" => OC_Helper::linkTo( "settings", "users.php" ), "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_Group::inGroup( $_SESSION["user_id"], "admin" )) { // admin apps menu - $settings[] = array( "id" => "core_apps", "order" => 3, "href" => OC_Helper::linkTo( "settings", "apps.php" ).'?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::linkTo( "settings", "admin.php" ), "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" )); } } @@ -333,7 +335,6 @@ class OC_App{ /// This is private as well. It simply works, so don't ask for more details private static function proceedNavigation( $list ) { foreach( $list as &$naventry ) { - $naventry['subnavigation'] = array(); if( $naventry['id'] == self::$activeapp ) { $naventry['active'] = true; } @@ -419,7 +420,7 @@ class OC_App{ * @return array * @note all data is read from info.xml, not just pre-defined fields */ - public static function getAppInfo($appid,$path=false) { + public static function getAppInfo($appid, $path=false) { if($path) { $file=$appid; }else{ @@ -483,8 +484,6 @@ class OC_App{ * entries are sorted by the key 'order' ascending. Additional to the keys * given for each app the following keys exist: * - active: boolean, signals if the user is on this navigation entry - * - children: array that is empty if the key 'active' is false or - * contains the subentries if the key 'active' is true */ public static function getNavigation() { $navigation = self::proceedNavigation( self::$navigation ); @@ -498,6 +497,12 @@ class OC_App{ public static function getCurrentApp() { $script=substr($_SERVER["SCRIPT_NAME"], strlen(OC::$WEBROOT)+1); $topFolder=substr($script, 0, strpos($script, '/')); + if (empty($topFolder)) { + $path_info = OC_Request::getPathInfo(); + if ($path_info) { + $topFolder=substr($path_info, 1, strpos($path_info, '/', 1)-1); + } + } if($topFolder=='apps') { $length=strlen($topFolder); return substr($script, $length+1, strpos($script, '/', $length+1)-$length-1); @@ -534,21 +539,21 @@ class OC_App{ /** * register a settings form to be shown */ - public static function registerSettings($app,$page) { + public static function registerSettings($app, $page) { self::$settingsForms[]= $app.'/'.$page.'.php'; } /** * register an admin form to be shown */ - public static function registerAdmin($app,$page) { + public static function registerAdmin($app, $page) { self::$adminForms[]= $app.'/'.$page.'.php'; } /** * register a personal form to be shown */ - public static function registerPersonal($app,$page) { + public static function registerPersonal($app, $page) { self::$personalForms[]= $app.'/'.$page.'.php'; } diff --git a/lib/appconfig.php b/lib/appconfig.php index ed0e8f1d0bd..1f2d576af87 100644 --- a/lib/appconfig.php +++ b/lib/appconfig.php @@ -107,7 +107,7 @@ class OC_Appconfig{ * @param string $key * @return bool */ - public static function hasKey($app,$key) { + public static function hasKey($app, $key) { $exists = self::getKeys( $app ); return in_array( $key, $exists ); } @@ -170,7 +170,7 @@ class OC_Appconfig{ * @param key * @return array */ - public static function getValues($app,$key) { + public static function getValues($app, $key) { if($app!==false and $key!==false) { return false; } diff --git a/lib/archive.php b/lib/archive.php index a9c245eaf43..61239c82076 100644 --- a/lib/archive.php +++ b/lib/archive.php @@ -42,14 +42,14 @@ abstract class OC_Archive{ * @param string source either a local file or string data * @return bool */ - abstract function addFile($path,$source=''); + abstract function addFile($path, $source=''); /** * rename a file or folder in the archive * @param string source * @param string dest * @return bool */ - abstract function rename($source,$dest); + abstract function rename($source, $dest); /** * get the uncompressed size of a file in the archive * @param string path @@ -85,7 +85,7 @@ abstract class OC_Archive{ * @param string dest * @return bool */ - abstract function extractFile($path,$dest); + abstract function extractFile($path, $dest); /** * extract the archive * @param string path @@ -111,14 +111,14 @@ abstract class OC_Archive{ * @param string mode * @return resource */ - abstract function getStream($path,$mode); + abstract function getStream($path, $mode); /** * add a folder and all it's content * @param string $path * @param string source * @return bool */ - function addRecursive($path,$source) { + function addRecursive($path, $source) { if($dh=opendir($source)) { $this->addFolder($path); while($file=readdir($dh)) { diff --git a/lib/archive/tar.php b/lib/archive/tar.php index 86d39b88968..0fa633c6038 100644 --- a/lib/archive/tar.php +++ b/lib/archive/tar.php @@ -6,7 +6,7 @@ * See the COPYING-README file. */ -require_once '3rdparty/Archive/Tar.php'; +require_once 'Archive/Tar.php'; class OC_Archive_TAR extends OC_Archive{ const PLAIN=0; @@ -23,7 +23,7 @@ class OC_Archive_TAR extends OC_Archive{ private $path; function __construct($source) { - $types=array(null,'gz','bz'); + $types=array(null, 'gz', 'bz'); $this->path=$source; $this->tar=new Archive_Tar($source, $types[self::getTarType($source)]); } @@ -84,7 +84,7 @@ class OC_Archive_TAR extends OC_Archive{ * @param string source either a local file or string data * @return bool */ - function addFile($path,$source='') { + function addFile($path, $source='') { if($this->fileExists($path)) { $this->remove($path); } @@ -107,7 +107,7 @@ class OC_Archive_TAR extends OC_Archive{ * @param string dest * @return bool */ - function rename($source,$dest) { + function rename($source, $dest) { //no proper way to delete, rename entire archive, rename file and remake archive $tmp=OCP\Files::tmpFolder(); $this->tar->extract($tmp); @@ -130,8 +130,7 @@ class OC_Archive_TAR extends OC_Archive{ if( $file == $header['filename'] or $file.'/' == $header['filename'] or '/'.$file.'/' == $header['filename'] - or '/'.$file == $header['filename']) - { + or '/'.$file == $header['filename']) { return $header; } } @@ -214,7 +213,7 @@ class OC_Archive_TAR extends OC_Archive{ * @param string dest * @return bool */ - function extractFile($path,$dest) { + function extractFile($path, $dest) { $tmp=OCP\Files::tmpFolder(); if(!$this->fileExists($path)) { return false; @@ -294,7 +293,7 @@ class OC_Archive_TAR extends OC_Archive{ * @param string mode * @return resource */ - function getStream($path,$mode) { + function getStream($path, $mode) { if(strrpos($path, '.')!==false) { $ext=substr($path, strrpos($path, '.')); }else{ @@ -309,7 +308,7 @@ class OC_Archive_TAR extends OC_Archive{ if($mode=='r' or $mode=='rb') { return fopen($tmpFile, $mode); }else{ - OC_CloseStreamWrapper::$callBacks[$tmpFile]=array($this,'writeBack'); + OC_CloseStreamWrapper::$callBacks[$tmpFile]=array($this, 'writeBack'); self::$tempFiles[$tmpFile]=$path; return fopen('close://'.$tmpFile, $mode); } @@ -334,7 +333,7 @@ class OC_Archive_TAR extends OC_Archive{ $this->tar->_close(); $this->tar=null; } - $types=array(null,'gz','bz'); + $types=array(null, 'gz', 'bz'); $this->tar=new Archive_Tar($this->path, $types[self::getTarType($this->path)]); } } diff --git a/lib/archive/zip.php b/lib/archive/zip.php index d016c692e35..1c967baa08f 100644 --- a/lib/archive/zip.php +++ b/lib/archive/zip.php @@ -35,7 +35,7 @@ class OC_Archive_ZIP extends OC_Archive{ * @param string source either a local file or string data * @return bool */ - function addFile($path,$source='') { + function addFile($path, $source='') { if($source and $source[0]=='/' and file_exists($source)) { $result=$this->zip->addFile($source, $path); }else{ @@ -53,7 +53,7 @@ class OC_Archive_ZIP extends OC_Archive{ * @param string dest * @return bool */ - function rename($source,$dest) { + function rename($source, $dest) { $source=$this->stripPath($source); $dest=$this->stripPath($dest); $this->zip->renameName($source, $dest); @@ -119,7 +119,7 @@ class OC_Archive_ZIP extends OC_Archive{ * @param string dest * @return bool */ - function extractFile($path,$dest) { + function extractFile($path, $dest) { $fp = $this->zip->getStream($path); file_put_contents($dest, $fp); } @@ -158,7 +158,7 @@ class OC_Archive_ZIP extends OC_Archive{ * @param string mode * @return resource */ - function getStream($path,$mode) { + function getStream($path, $mode) { if($mode=='r' or $mode=='rb') { return $this->zip->getStream($path); } else { @@ -171,7 +171,7 @@ class OC_Archive_ZIP extends OC_Archive{ $ext=''; } $tmpFile=OCP\Files::tmpFile($ext); - OC_CloseStreamWrapper::$callBacks[$tmpFile]=array($this,'writeBack'); + OC_CloseStreamWrapper::$callBacks[$tmpFile]=array($this, 'writeBack'); if($this->fileExists($path)) { $this->extractFile($path, $tmpFile); } diff --git a/lib/backgroundjob.php b/lib/backgroundjob.php index 6415f5b84aa..28b5ce3af20 100644 --- a/lib/backgroundjob.php +++ b/lib/backgroundjob.php @@ -40,11 +40,11 @@ class OC_BackgroundJob{ * @param $type execution type * @return boolean * - * This method sets the execution type of the background jobs. Possible types + * This method sets the execution type of the background jobs. Possible types * are "none", "ajax", "webcron", "cron" */ public static function setExecutionType( $type ) { - if( !in_array( $type, array('none', 'ajax', 'webcron', 'cron'))){ + if( !in_array( $type, array('none', 'ajax', 'webcron', 'cron'))) { return false; } return OC_Appconfig::setValue( 'core', 'backgroundjobs_mode', $type ); diff --git a/lib/base.php b/lib/base.php index d47c1d30dd0..0b75f6f085e 100644 --- a/lib/base.php +++ b/lib/base.php @@ -20,6 +20,8 @@ * */ +require_once 'public/constants.php'; + /** * Class that is a namespace for all global OC variables * No, we can not put this class in its own file because it is used by @@ -88,6 +90,9 @@ class OC{ elseif(strpos($className, 'OC_')===0) { $path = strtolower(str_replace('_', '/', substr($className, 3)) . '.php'); } + elseif(strpos($className, 'OC\\')===0) { + $path = strtolower(str_replace('\\', '/', substr($className, 3)) . '.php'); + } elseif(strpos($className, 'OCP\\')===0) { $path = 'public/'.strtolower(str_replace('\\', '/', substr($className, 3)) . '.php'); } @@ -97,13 +102,15 @@ class OC{ elseif(strpos($className, 'Sabre_')===0) { $path = str_replace('_', '/', $className) . '.php'; } - elseif(strpos($className,'Symfony\\')===0){ - $path = str_replace('\\','/',$className) . '.php'; + elseif(strpos($className, 'Symfony\\Component\\Routing\\')===0) { + $path = 'symfony/routing/'.str_replace('\\', '/', $className) . '.php'; } - elseif(strpos($className,'Test_')===0){ - $path = 'tests/lib/'.strtolower(str_replace('_','/',substr($className,5)) . '.php'); - - } else { + elseif(strpos($className, 'Sabre\\VObject')===0) { + $path = str_replace('\\', '/', $className) . '.php'; + } + elseif(strpos($className, 'Test_')===0) { + $path = 'tests/lib/'.strtolower(str_replace('_', '/', substr($className, 5)) . '.php'); + }else{ return false; } @@ -219,6 +226,14 @@ class OC{ $installedVersion=OC_Config::getValue('version', '0.0.0'); $currentVersion=implode('.', OC_Util::getVersion()); if (version_compare($currentVersion, $installedVersion, '>')) { + // Check if the .htaccess is existing - this is needed for upgrades from really old ownCloud versions + if (isset($_SERVER['SERVER_SOFTWARE']) && strstr($_SERVER['SERVER_SOFTWARE'], 'Apache')) { + if(!OC_Util::ishtaccessworking()) { + if(!file_exists(OC::$SERVERROOT.'/data/.htaccess')) { + OC_Setup::protectDataDirectory(); + } + } + } OC_Log::write('core', 'starting upgrade from '.$installedVersion.' to '.$currentVersion, OC_Log::DEBUG); $result=OC_DB::updateDbFromStructure(OC::$SERVERROOT.'/db_structure.xml'); if(!$result) { @@ -227,7 +242,7 @@ class OC{ } 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; } @@ -248,16 +263,15 @@ class OC{ OC_Util::addScript( "jquery-1.7.2.min" ); OC_Util::addScript( "jquery-ui-1.8.16.custom.min" ); OC_Util::addScript( "jquery-showpassword" ); - OC_Util::addScript( "jquery.infieldlabel.min" ); + OC_Util::addScript( "jquery.infieldlabel" ); OC_Util::addScript( "jquery-tipsy" ); OC_Util::addScript( "oc-dialogs" ); OC_Util::addScript( "js" ); - // request protection token MUST be defined after the jquery library but before any $('document').ready() - OC_Util::addScript( "requesttoken" ); OC_Util::addScript( "eventsource" ); OC_Util::addScript( "config" ); //OC_Util::addScript( "multiselect" ); OC_Util::addScript('search', 'result'); + OC_Util::addScript('router'); if( OC_Config::getValue( 'installed', false )) { if( OC_Appconfig::getValue( 'core', 'backgroundjobs_mode', 'ajax' ) == 'ajax' ) { @@ -275,9 +289,12 @@ class OC{ // prevents javascript from accessing php session cookies ini_set('session.cookie_httponly', '1;'); + // set the session name to the instance id - which is unique + session_name(OC_Util::getInstanceId()); + // (re)-initialize session session_start(); - + // regenerate session id periodically to avoid session fixation if (!isset($_SESSION['SID_CREATED'])) { $_SESSION['SID_CREATED'] = time(); @@ -298,31 +315,6 @@ class OC{ $_SESSION['LAST_ACTIVITY'] = time(); } - public static function loadapp(){ - if(file_exists(OC_App::getAppPath(OC::$REQUESTEDAPP) . '/index.php')){ - require_once(OC_App::getAppPath(OC::$REQUESTEDAPP) . '/index.php'); - }else{ - trigger_error('The requested App was not found.', E_USER_ERROR);//load default app instead? - } - } - - public static function loadfile(){ - if(file_exists(OC_App::getAppPath(OC::$REQUESTEDAPP) . '/' . OC::$REQUESTEDFILE)){ - if(substr(OC::$REQUESTEDFILE, -3) == 'css'){ - $file = OC_App::getAppWebPath(OC::$REQUESTEDAPP). '/' . OC::$REQUESTEDFILE; - $minimizer = new OC_Minimizer_CSS(); - $minimizer->output(array(array(OC_App::getAppPath(OC::$REQUESTEDAPP), OC_App::getAppWebPath(OC::$REQUESTEDAPP), OC::$REQUESTEDFILE)),$file); - exit; - }elseif(substr(OC::$REQUESTEDFILE, -3) == 'php'){ - require_once(OC_App::getAppPath(OC::$REQUESTEDAPP). '/' . OC::$REQUESTEDFILE); - } - }else{ - die(); - header('HTTP/1.0 404 Not Found'); - exit; - } - } - public static function getRouter() { if (!isset(OC::$router)) { OC::$router = new OC_Router(); @@ -332,10 +324,9 @@ class OC{ return OC::$router; } - public static function init(){ - + public static function init() { // register autoloader - spl_autoload_register(array('OC','autoload')); + spl_autoload_register(array('OC', 'autoload')); setlocale(LC_ALL, 'en_US.UTF-8'); // set some stuff @@ -371,6 +362,10 @@ class OC{ //try to set the session lifetime to 60min @ini_set('gc_maxlifetime', '3600'); + //copy http auth headers for apache+php-fcgid work around + if (isset($_SERVER['HTTP_XAUTHORIZATION']) && !isset($_SERVER['HTTP_AUTHORIZATION'])) { + $_SERVER['HTTP_AUTHORIZATION'] = $_SERVER['HTTP_XAUTHORIZATION']; + } //set http auth headers for apache+php-cgi work around if (isset($_SERVER['HTTP_AUTHORIZATION']) && preg_match('/Basic\s+(.*)$/i', $_SERVER['HTTP_AUTHORIZATION'], $matches)) { @@ -444,16 +439,12 @@ class OC{ //setup extra user backends OC_User::setupBackends(); - // register cache cleanup jobs - OC_BackgroundJob_RegularTask::register('OC_Cache_FileGlobal', 'gc'); - OC_Hook::connect('OC_User', 'post_login', 'OC_Cache_File', 'loginListener'); - - // Check for blacklisted files - OC_Hook::connect('OC_Filesystem', 'write', 'OC_Filesystem', 'isBlacklisted'); - OC_Hook::connect('OC_Filesystem', 'rename', 'OC_Filesystem', 'isBlacklisted'); + self::registerCacheHooks(); + self::registerFilesystemHooks(); + self::registerShareHooks(); //make sure temporary files are cleaned up - register_shutdown_function(array('OC_Helper','cleanTmp')); + 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')); @@ -486,31 +477,67 @@ class OC{ } /** + * register hooks for the cache + */ + public static function registerCacheHooks() { + // register cache cleanup jobs + OC_BackgroundJob_RegularTask::register('OC_Cache_FileGlobal', 'gc'); + OC_Hook::connect('OC_User', 'post_login', 'OC_Cache_File', 'loginListener'); + } + + /** + * register hooks for the filesystem + */ + public static function registerFilesystemHooks() { + // Check for blacklisted files + OC_Hook::connect('OC_Filesystem', 'write', 'OC_Filesystem', 'isBlacklisted'); + OC_Hook::connect('OC_Filesystem', 'rename', 'OC_Filesystem', 'isBlacklisted'); + } + + /** + * register hooks for sharing + */ + public static function registerShareHooks() { + OC_Hook::connect('OC_User', 'post_deleteUser', 'OCP\Share', 'post_deleteUser'); + OC_Hook::connect('OC_User', 'post_addToGroup', 'OCP\Share', 'post_addToGroup'); + OC_Hook::connect('OC_User', 'post_removeFromGroup', 'OCP\Share', 'post_removeFromGroup'); + OC_Hook::connect('OC_User', 'post_deleteGroup', 'OCP\Share', 'post_deleteGroup'); + } + + /** * @brief Handle the request */ public static function handleRequest() { if (!OC_Config::getValue('installed', false)) { - // Check for autosetup: - $autosetup_file = OC::$SERVERROOT."/config/autoconfig.php"; - if( file_exists( $autosetup_file )) { - OC_Log::write('core', 'Autoconfig file found, setting up owncloud...', OC_Log::INFO); - include $autosetup_file; - $_POST['install'] = 'true'; - $_POST = array_merge ($_POST, $AUTOCONFIG); - unlink($autosetup_file); - } - OC_Util::addScript('setup'); - require_once 'setup.php'; + require_once 'core/setup.php'; exit(); } + // Handle redirect URL for logged in users + if(isset($_REQUEST['redirect_url']) && OC_User::isLoggedIn()) { + $location = OC_Helper::makeURLAbsolute(urldecode($_REQUEST['redirect_url'])); + header( 'Location: '.$location ); + return; + } // Handle WebDAV if($_SERVER['REQUEST_METHOD']=='PROPFIND') { header('location: '.OC_Helper::linkToRemote('webdav')); return; } + try { + OC::getRouter()->match(OC_Request::getPathInfo()); + return; + } catch (Symfony\Component\Routing\Exception\ResourceNotFoundException $e) { + //header('HTTP/1.0 404 Not Found'); + } catch (Symfony\Component\Routing\Exception\MethodNotAllowedException $e) { + OC_Response::setStatus(405); + return; + } + $app = OC::$REQUESTEDAPP; + $file = OC::$REQUESTEDFILE; + $param = array('app' => $app, 'file' => $file); // Handle app css files - if(substr(OC::$REQUESTEDFILE, -3) == 'css') { - self::loadCSSFile(); + if(substr($file, -3) == 'css') { + self::loadCSSFile($param); return; } // Someone is logged in : @@ -522,13 +549,12 @@ class OC{ OC_User::logout(); header("Location: ".OC::$WEBROOT.'/'); }else{ - $app = OC::$REQUESTEDAPP; - $file = OC::$REQUESTEDFILE; if(is_null($file)) { - $file = 'index.php'; + $param['file'] = 'index.php'; } - $file_ext = substr($file, -3); - if ($file_ext != 'php'|| !self::loadAppScriptFile($app, $file)) { + $file_ext = substr($param['file'], -3); + if ($file_ext != 'php' + || !self::loadAppScriptFile($param)) { header('HTTP/1.0 404 Not Found'); } } @@ -538,7 +564,10 @@ class OC{ self::handleLogin(); } - protected static function loadAppScriptFile($app, $file) { + public static function loadAppScriptFile($param) { + OC_App::loadApps(); + $app = $param['app']; + $file = $param['file']; $app_path = OC_App::getAppPath($app); $file = $app_path . '/' . $file; unset($app, $app_path); @@ -549,9 +578,9 @@ class OC{ return false; } - protected static function loadCSSFile() { - $app = OC::$REQUESTEDAPP; - $file = OC::$REQUESTEDFILE; + public static function loadCSSFile($param) { + $app = $param['app']; + $file = $param['file']; $app_path = OC_App::getAppPath($app); if (file_exists($app_path . '/' . $file)) { $app_web_path = OC_App::getAppWebPath($app); @@ -595,8 +624,7 @@ class OC{ if(!isset($_COOKIE["oc_remember_login"]) || !isset($_COOKIE["oc_token"]) || !isset($_COOKIE["oc_username"]) - || !$_COOKIE["oc_remember_login"]) - { + || !$_COOKIE["oc_remember_login"]) { return false; } OC_App::loadApps(array('authentication')); @@ -621,9 +649,9 @@ class OC{ OC_Util::redirectToDefaultPage(); // doesn't return } - // if you reach this point you have changed your password + // if you reach this point you have changed your password // or you are an attacker - // we can not delete tokens here because users may reach + // we can not delete tokens here because users may reach // this point multiple times after a password change OC_Log::write('core', 'Authentication cookie rejected for user '.$_COOKIE['oc_username'], OC_Log::WARN); } @@ -654,7 +682,7 @@ class OC{ else { OC_User::unsetMagicInCookie(); } - header( 'Location: '.$_SERVER['REQUEST_URI'] ); + OC_Util::redirectToDefaultPage(); exit(); } return true; @@ -667,7 +695,7 @@ class OC{ } OC_App::loadApps(array('authentication')); if (OC_User::login($_SERVER["PHP_AUTH_USER"], $_SERVER["PHP_AUTH_PW"])) { - //OC_Log::write('core',"Logged in with HTTP Authentication",OC_Log::DEBUG); + //OC_Log::write('core',"Logged in with HTTP Authentication", OC_Log::DEBUG); OC_User::unsetMagicInCookie(); $_REQUEST['redirect_url'] = (isset($_SERVER['REQUEST_URI'])?$_SERVER['REQUEST_URI']:''); OC_Util::redirectToDefaultPage(); diff --git a/lib/cache.php b/lib/cache.php index 62003793d5f..bc74ed83f8b 100644 --- a/lib/cache.php +++ b/lib/cache.php @@ -144,4 +144,13 @@ class OC_Cache { return self::$isFast; } + static public function generateCacheKeyFromFiles($files) { + $key = ''; + sort($files); + foreach($files as $file) { + $stat = stat($file); + $key .= $file.$stat['mtime'].$stat['size']; + } + return md5($key); + } } diff --git a/lib/connector/sabre/auth.php b/lib/connector/sabre/auth.php index db8f005745a..6990d928cff 100644 --- a/lib/connector/sabre/auth.php +++ b/lib/connector/sabre/auth.php @@ -32,7 +32,7 @@ class OC_Connector_Sabre_Auth extends Sabre_DAV_Auth_Backend_AbstractBasic { */ protected function validateUserPass($username, $password) { if (OC_User::isLoggedIn()) { - OC_Util::setupFS($username); + OC_Util::setupFS(OC_User::getUser()); return true; } else { OC_Util::setUpFS();//login hooks may need early access to the filesystem @@ -45,4 +45,19 @@ class OC_Connector_Sabre_Auth extends Sabre_DAV_Auth_Backend_AbstractBasic { } } } + + /** + * Returns information about the currently logged in username. + * + * If nobody is currently logged in, this method should return null. + * + * @return string|null + */ + public function getCurrentUser() { + $user = OC_User::getUser(); + if(!$user) { + return null; + } + return $user; + } } diff --git a/lib/connector/sabre/directory.php b/lib/connector/sabre/directory.php index b6e02569d2a..6076aed6fcd 100644 --- a/lib/connector/sabre/directory.php +++ b/lib/connector/sabre/directory.php @@ -116,7 +116,6 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa * @return Sabre_DAV_INode[] */ public function getChildren() { - $folder_content = OC_Files::getDirectoryContent($this->path); $paths = array(); foreach($folder_content as $info) { @@ -124,15 +123,22 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa } $properties = array_fill_keys($paths, array()); if(count($paths)>0) { - $placeholders = join(',', array_fill(0, count($paths), '?')); - $query = OC_DB::prepare( 'SELECT * FROM `*PREFIX*properties` WHERE `userid` = ?' . ' AND `propertypath` IN ('.$placeholders.')' ); - array_unshift($paths, OC_User::getUser()); // prepend userid - $result = $query->execute( $paths ); - while($row = $result->fetchRow()) { - $propertypath = $row['propertypath']; - $propertyname = $row['propertyname']; - $propertyvalue = $row['propertyvalue']; - $properties[$propertypath][$propertyname] = $propertyvalue; + // + // the number of arguments within IN conditions are limited in most databases + // we chunk $paths into arrays of 200 items each to meet this criteria + // + $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.')' ); + array_unshift($pack, OC_User::getUser()); // prepend userid + $result = $query->execute( $pack ); + while($row = $result->fetchRow()) { + $propertypath = $row['propertypath']; + $propertyname = $row['propertyname']; + $propertyvalue = $row['propertyvalue']; + $properties[$propertypath][$propertyname] = $propertyvalue; + } } } diff --git a/lib/connector/sabre/file.php b/lib/connector/sabre/file.php index 5bd38240d44..8d963a1cf8d 100644 --- a/lib/connector/sabre/file.php +++ b/lib/connector/sabre/file.php @@ -45,7 +45,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D */ public function put($data) { - OC_Filesystem::file_put_contents($this->path,$data); + OC_Filesystem::file_put_contents($this->path, $data); return OC_Connector_Sabre_Node::getETagPropertyForPath($this->path); } @@ -57,7 +57,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D */ public function get() { - return OC_Filesystem::fopen($this->path,'rb'); + return OC_Filesystem::fopen($this->path, 'rb'); } diff --git a/lib/connector/sabre/locks.php b/lib/connector/sabre/locks.php index 8ebe324602c..a72d003bc72 100644 --- a/lib/connector/sabre/locks.php +++ b/lib/connector/sabre/locks.php @@ -45,10 +45,10 @@ class OC_Connector_Sabre_Locks extends Sabre_DAV_Locks_Backend_Abstract { // but otherwise reading locks from SQLite Databases will return // nothing $query = 'SELECT * FROM `*PREFIX*locks` WHERE `userid` = ? AND (`created` + `timeout`) > '.time().' AND (( `uri` = ?)'; - $params = array(OC_User::getUser(),$uri); + $params = array(OC_User::getUser(), $uri); // We need to check locks for every part in the uri. - $uriParts = explode('/',$uri); + $uriParts = explode('/', $uri); // We already covered the last part of the uri array_pop($uriParts); @@ -102,7 +102,7 @@ class OC_Connector_Sabre_Locks extends Sabre_DAV_Locks_Backend_Abstract { * @param Sabre_DAV_Locks_LockInfo $lockInfo * @return bool */ - public function lock($uri,Sabre_DAV_Locks_LockInfo $lockInfo) { + public function lock($uri, Sabre_DAV_Locks_LockInfo $lockInfo) { // We're making the lock timeout 5 minutes $lockInfo->timeout = 300; @@ -134,10 +134,10 @@ class OC_Connector_Sabre_Locks extends Sabre_DAV_Locks_Backend_Abstract { * @param Sabre_DAV_Locks_LockInfo $lockInfo * @return bool */ - public function unlock($uri,Sabre_DAV_Locks_LockInfo $lockInfo) { + public function unlock($uri, Sabre_DAV_Locks_LockInfo $lockInfo) { $query = OC_DB::prepare( 'DELETE FROM `*PREFIX*locks` WHERE `userid` = ? AND `uri` = ? AND `token` = ?' ); - $result = $query->execute( array(OC_User::getUser(),$uri,$lockInfo->token)); + $result = $query->execute( array(OC_User::getUser(), $uri, $lockInfo->token)); return $result->numRows() === 1; diff --git a/lib/connector/sabre/node.php b/lib/connector/sabre/node.php index 72de9723774..52350072fb2 100644 --- a/lib/connector/sabre/node.php +++ b/lib/connector/sabre/node.php @@ -26,6 +26,13 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr const LASTMODIFIED_PROPERTYNAME = '{DAV:}lastmodified'; /** + * Allow configuring the method used to generate Etags + * + * @var array(class_name, function_name) + */ + public static $ETagFunction = null; + + /** * The path to the current node * * @var string @@ -43,8 +50,7 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr protected $property_cache = null; /** - * Sets up the node, expects a full path name - * + * @brief Sets up the node, expects a full path name * @param string $path * @return void */ @@ -55,8 +61,7 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr /** - * Returns the name of the node - * + * @brief Returns the name of the node * @return string */ public function getName() { @@ -67,8 +72,7 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr } /** - * Renames the node - * + * @brief Renames the node * @param string $name The new name * @return void */ @@ -80,12 +84,12 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr $newPath = $parentPath . '/' . $newName; $oldPath = $this->path; - OC_Filesystem::rename($this->path,$newPath); + OC_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->execute( array( $newPath, OC_User::getUser(), $oldPath )); } @@ -95,7 +99,8 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr } /** - * Make sure the fileinfo cache is filled. Uses OC_FileCache or a direct stat + * @brief Ensure that the fileinfo cache is filled + & @note Uses OC_FileCache or a direct stat */ protected function getFileinfoCache() { if (!isset($this->fileinfo_cache)) { @@ -114,8 +119,7 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr } /** - * Returns the last modification time, as a unix timestamp - * + * @brief Returns the last modification time, as a unix timestamp * @return int */ public function getLastModified() { @@ -134,8 +138,7 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr } /** - * Updates properties on this node, - * + * @brief Updates properties on this node, * @param array $mutations * @see Sabre_DAV_IProperties::updateProperties * @return bool|array @@ -156,10 +159,10 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr } else { if(!array_key_exists( $propertyName, $existing )) { $query = OC_DB::prepare( 'INSERT INTO `*PREFIX*properties` (`userid`,`propertypath`,`propertyname`,`propertyvalue`) VALUES(?,?,?,?)' ); - $query->execute( array( OC_User::getUser(), $this->path, $propertyName,$propertyValue )); + $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->execute( array( $propertyValue,OC_User::getUser(), $this->path, $propertyName )); + $query->execute( array( $propertyValue, OC_User::getUser(), $this->path, $propertyName )); } } } @@ -170,15 +173,13 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr } /** - * Returns a list of properties for this nodes.; - * - * The properties list is a list of propertynames the client requested, - * encoded as xmlnamespace#tagName, for example: - * http://www.example.org/namespace#author - * If the array is empty, all properties should be returned - * + * @brief Returns a list of properties for this nodes.; * @param array $properties - * @return void + * @return array + * @note The properties list is a list of propertynames the client + * requested, encoded as xmlnamespace#tagName, for example: + * http://www.example.org/namespace#author If the array is empty, all + * properties should be returned */ public function getProperties($properties) { if (is_null($this->property_cache)) { @@ -204,16 +205,21 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr } /** - * Creates a ETag for this path. + * @brief Creates a ETag for this path. * @param string $path Path of the file * @return string|null Returns null if the ETag can not effectively be determined */ static protected function createETag($path) { - return uniqid('', true); + if(self::$ETagFunction) { + $hash = call_user_func(self::$ETagFunction, $path); + return $hash; + }else{ + return uniqid('', true); + } } /** - * Returns the ETag surrounded by double-quotes for this path. + * @brief Returns the ETag surrounded by double-quotes for this path. * @param string $path Path of the file * @return string|null Returns null if the ETag can not effectively be determined */ @@ -229,7 +235,7 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr } /** - * Remove the ETag from the cache. + * @brief Remove the ETag from the cache. * @param string $path Path of the file */ static public function removeETagPropertyForPath($path) { diff --git a/lib/connector/sabre/principal.php b/lib/connector/sabre/principal.php index 763503721f8..04be410ac85 100644 --- a/lib/connector/sabre/principal.php +++ b/lib/connector/sabre/principal.php @@ -46,7 +46,7 @@ class OC_Connector_Sabre_Principal implements Sabre_DAVACL_IPrincipalBackend { * @return array */ public function getPrincipalByPath($path) { - list($prefix,$name) = explode('/', $path); + list($prefix, $name) = explode('/', $path); if ($prefix == 'principals' && OC_User::userExists($name)) { return array( @@ -83,7 +83,7 @@ class OC_Connector_Sabre_Principal implements Sabre_DAVACL_IPrincipalBackend { * @return array */ public function getGroupMembership($principal) { - list($prefix,$name) = Sabre_DAV_URLUtil::splitPath($principal); + list($prefix, $name) = Sabre_DAV_URLUtil::splitPath($principal); $group_membership = array(); if ($prefix == 'principals') { diff --git a/lib/connector/sabre/quotaplugin.php b/lib/connector/sabre/quotaplugin.php new file mode 100644 index 00000000000..fbbb4a3cf6f --- /dev/null +++ b/lib/connector/sabre/quotaplugin.php @@ -0,0 +1,59 @@ +<?php + +/** + * This plugin check user quota and deny creating files when they exceeds the quota. + * + * @copyright Copyright (C) 2012 entreCables S.L. All rights reserved. + * @author Sergio Cambra + * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License + */ +class OC_Connector_Sabre_QuotaPlugin extends Sabre_DAV_ServerPlugin { + + /** + * Reference to main server object + * + * @var Sabre_DAV_Server + */ + private $server; + + /** + * This initializes the plugin. + * + * This function is called by Sabre_DAV_Server, after + * addPlugin is called. + * + * This method should set up the requires event subscriptions. + * + * @param Sabre_DAV_Server $server + * @return void + */ + public function initialize(Sabre_DAV_Server $server) { + + $this->server = $server; + $this->server->subscribeEvent('beforeWriteContent', array($this, 'checkQuota'), 10); + $this->server->subscribeEvent('beforeCreateFile', array($this, 'checkQuota'), 10); + + } + + /** + * This method is called before any HTTP method and forces users to be authenticated + * + * @param string $method + * @throws Sabre_DAV_Exception + * @return bool + */ + public function checkQuota($uri, $data = null) { + $expected = $this->server->httpRequest->getHeader('X-Expected-Entity-Length'); + $length = $expected ? $expected : $this->server->httpRequest->getHeader('Content-Length'); + if ($length) { + if (substr($uri, 0, 1)!=='/') { + $uri='/'.$uri; + } + list($parentUri, $newName) = Sabre_DAV_URLUtil::splitPath($uri); + if ($length > OC_Filesystem::free_space($parentUri)) { + throw new Sabre_DAV_Exception_InsufficientStorage(); + } + } + return true; + } +} diff --git a/lib/db.php b/lib/db.php index a43f2ad20b2..6524db7581a 100644 --- a/lib/db.php +++ b/lib/db.php @@ -20,6 +20,19 @@ * */ +class DatabaseException extends Exception{ + private $query; + + public function __construct($message, $query){ + parent::__construct($message); + $this->query = $query; + } + + public function getQuery(){ + return $this->query; + } +} + /** * This class manages the access to the database. It basically is a wrapper for * MDB2 with some adaptions. @@ -115,7 +128,7 @@ class OC_DB { $pass = OC_Config::getValue( "dbpassword", "" ); $type = OC_Config::getValue( "dbtype", "sqlite" ); if(strpos($host, ':')) { - list($host, $port)=explode(':', $host,2); + list($host, $port)=explode(':', $host, 2); }else{ $port=false; } @@ -168,8 +181,7 @@ class OC_DB { try{ self::$PDO=new PDO($dsn, $user, $pass, $opts); }catch(PDOException $e) { - echo( '<b>can not connect to database, using '.$type.'. ('.$e->getMessage().')</center>'); - die(); + OC_Template::printErrorPage( 'can not connect to database, using '.$type.'. ('.$e->getMessage().')' ); } // We always, really always want associative arrays self::$PDO->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); @@ -263,10 +275,9 @@ class OC_DB { // Die if we could not connect if( PEAR::isError( self::$MDB2 )) { - echo( '<b>can not connect to database, using '.$type.'. ('.self::$MDB2->getUserInfo().')</center>'); OC_Log::write('core', self::$MDB2->getUserInfo(), OC_Log::FATAL); OC_Log::write('core', self::$MDB2->getMessage(), OC_Log::FATAL); - die(); + OC_Template::printErrorPage( 'can not connect to database, using '.$type.'. ('.self::$MDB2->getUserInfo().')' ); } // We always, really always want associative arrays @@ -322,21 +333,13 @@ class OC_DB { // Die if we have an error (error means: bad query, not 0 results!) if( PEAR::isError($result)) { - $entry = 'DB Error: "'.$result->getMessage().'"<br />'; - $entry .= 'Offending command was: '.htmlentities($query).'<br />'; - OC_Log::write('core', $entry,OC_Log::FATAL); - error_log('DB error: '.$entry); - die( $entry ); + throw new DatabaseException($result->getMessage(), $query); } }else{ try{ $result=self::$connection->prepare($query); }catch(PDOException $e) { - $entry = 'DB Error: "'.$e->getMessage().'"<br />'; - $entry .= 'Offending command was: '.htmlentities($query).'<br />'; - OC_Log::write('core', $entry,OC_Log::FATAL); - error_log('DB error: '.$entry); - die( $entry ); + throw new DatabaseException($e->getMessage(), $query); } $result=new PDOStatementWrapper($result); } @@ -355,12 +358,19 @@ class OC_DB { */ public static function insertid($table=null) { self::connect(); - if($table !== null) { - $prefix = OC_Config::getValue( "dbtableprefix", "oc_" ); - $suffix = OC_Config::getValue( "dbsequencesuffix", "_id_seq" ); - $table = str_replace( '*PREFIX*', $prefix, $table ).$suffix; + $type = OC_Config::getValue( "dbtype", "sqlite" ); + if( $type == 'pgsql' ) { + $query = self::prepare('SELECT lastval() AS id'); + $row = $query->execute()->fetchRow(); + return $row['id']; + }else{ + if($table !== null) { + $prefix = OC_Config::getValue( "dbtableprefix", "oc_" ); + $suffix = OC_Config::getValue( "dbsequencesuffix", "_id_seq" ); + $table = str_replace( '*PREFIX*', $prefix, $table ).$suffix; + } + return self::$connection->lastInsertId($table); } - return self::$connection->lastInsertId($table); } /** @@ -449,7 +459,7 @@ class OC_DB { // Die in case something went wrong if( $definition instanceof MDB2_Schema_Error ) { - die( $definition->getMessage().': '.$definition->getUserInfo()); + OC_Template::printErrorPage( $definition->getMessage().': '.$definition->getUserInfo() ); } if(OC_Config::getValue('dbtype', 'sqlite')==='oci') { unset($definition['charset']); //or MDB2 tries SHUTDOWN IMMEDIATE @@ -461,8 +471,7 @@ class OC_DB { // Die in case something went wrong if( $ret instanceof MDB2_Error ) { - echo (self::$MDB2->getDebugOutput()); - die ($ret->getMessage() . ': ' . $ret->getUserInfo()); + OC_Template::printErrorPage( self::$MDB2->getDebugOutput().' '.$ret->getMessage() . ': ' . $ret->getUserInfo() ); } return true; @@ -542,6 +551,78 @@ class OC_DB { } /** + * @brief Insert a row if a matching row doesn't exists. + * @param string $table. The table to insert into in the form '*PREFIX*tableName' + * @param array $input. An array of fieldname/value pairs + * @returns The return value from PDOStatementWrapper->execute() + */ + public static function insertIfNotExist($table, $input) { + self::connect(); + $prefix = OC_Config::getValue( "dbtableprefix", "oc_" ); + $table = str_replace( '*PREFIX*', $prefix, $table ); + + if(is_null(self::$type)) { + self::$type=OC_Config::getValue( "dbtype", "sqlite" ); + } + $type = self::$type; + + $query = ''; + // differences in escaping of table names ('`' for mysql) and getting the current timestamp + if( $type == 'sqlite' || $type == 'sqlite3' ) { + // NOTE: For SQLite we have to use this clumsy approach + // otherwise all fieldnames used must have a unique key. + $query = 'SELECT * FROM "' . $table . '" WHERE '; + foreach($input as $key => $value) { + $query .= $key . " = '" . $value . '\' AND '; + } + $query = substr($query, 0, strlen($query) - 5); + try { + $stmt = self::prepare($query); + $result = $stmt->execute(); + } catch(PDOException $e) { + $entry = 'DB Error: "'.$e->getMessage() . '"<br />'; + $entry .= 'Offending command was: ' . $query . '<br />'; + OC_Log::write('core', $entry, OC_Log::FATAL); + error_log('DB error: '.$entry); + OC_Template::printErrorPage( $entry ); + } + + if($result->numRows() == 0) { + $query = 'INSERT INTO "' . $table . '" ("' + . implode('","', array_keys($input)) . '") VALUES("' + . implode('","', array_values($input)) . '")'; + } else { + return true; + } + } elseif( $type == 'pgsql' || $type == 'oci' || $type == 'mysql') { + $query = 'INSERT INTO `' .$table . '` (' + . implode(',', array_keys($input)) . ') SELECT \'' + . implode('\',\'', array_values($input)) . '\' FROM ' . $table . ' WHERE '; + + foreach($input as $key => $value) { + $query .= $key . " = '" . $value . '\' AND '; + } + $query = substr($query, 0, strlen($query) - 5); + $query .= ' HAVING COUNT(*) = 0'; + } + + // TODO: oci should be use " (quote) instead of ` (backtick). + //OC_Log::write('core', __METHOD__ . ', type: ' . $type . ', query: ' . $query, OC_Log::DEBUG); + + try { + $result = self::prepare($query); + } catch(PDOException $e) { + $entry = 'DB Error: "'.$e->getMessage() . '"<br />'; + $entry .= 'Offending command was: ' . $query.'<br />'; + OC_Log::write('core', $entry, OC_Log::FATAL); + error_log('DB error: ' . $entry); + OC_Template::printErrorPage( $entry ); + } + + return $result->execute(); + } + + /** * @brief does minor changes to query * @param string $query Query string * @return string corrected query string @@ -767,8 +848,8 @@ class PDOStatementWrapper{ /** * pass all other function directly to the PDOStatement */ - public function __call($name,$arguments) { - return call_user_func_array(array($this->statement,$name), $arguments); + public function __call($name, $arguments) { + return call_user_func_array(array($this->statement, $name), $arguments); } /** diff --git a/lib/eventsource.php b/lib/eventsource.php index 3bada131bdd..1b8033943a1 100644 --- a/lib/eventsource.php +++ b/lib/eventsource.php @@ -32,7 +32,7 @@ class OC_EventSource{ private $fallBackId=0; public function __construct() { - @ob_end_clean(); + OC_Util::obEnd(); header('Cache-Control: no-cache'); $this->fallback=isset($_GET['fallback']) and $_GET['fallback']=='true'; if($this->fallback) { @@ -56,7 +56,7 @@ class OC_EventSource{ * * if only one paramater is given, a typeless message will be send with that paramater as data */ - public function send($type,$data=null) { + public function send($type, $data=null) { if(is_null($data)) { $data=$type; $type=null; diff --git a/lib/filecache.php b/lib/filecache.php index fee3b398251..bbf55bc1f86 100644 --- a/lib/filecache.php +++ b/lib/filecache.php @@ -28,6 +28,7 @@ * It will try to keep the data up to date but changes from outside ownCloud can invalidate the cache */ class OC_FileCache{ + /** * get the filesystem info from the cache * @param string path @@ -42,7 +43,7 @@ class OC_FileCache{ * - encrypted * - versioned */ - public static function get($path,$root=false) { + public static function get($path, $root=false) { if(OC_FileCache_Update::hasUpdated($path, $root)) { if($root===false) {//filesystem hooks are only valid for the default root OC_Hook::emit('OC_Filesystem', 'post_write', array('path'=>$path)); @@ -58,10 +59,10 @@ class OC_FileCache{ * @param string $path * @param array data * @param string root (optional) - * - * $data is an assiciative array in the same format as returned by get + * @note $data is an associative array in the same format as returned + * by get */ - public static function put($path,$data,$root=false) { + public static function put($path, $data, $root=false) { if($root===false) { $root=OC_Filesystem::getRoot(); } @@ -117,10 +118,10 @@ class OC_FileCache{ * @param int $id * @param array $data */ - private static function update($id,$data) { + private static function update($id, $data) { $arguments=array(); $queryParts=array(); - foreach(array('size','mtime','ctime','mimetype','encrypted','versioned','writable') as $attribute) { + foreach(array('size','mtime','ctime','mimetype','encrypted','versioned', 'writable') as $attribute) { if(isset($data[$attribute])) { //Convert to int it args are false if($data[$attribute] === false) { @@ -137,11 +138,13 @@ class OC_FileCache{ } $arguments[]=$id; - $sql = 'UPDATE `*PREFIX*fscache` SET '.implode(' , ', $queryParts).' WHERE `id`=?'; - $query=OC_DB::prepare($sql); - $result=$query->execute($arguments); - if(OC_DB::isError($result)) { - OC_Log::write('files', 'error while updating file('.$id.') in cache', OC_Log::ERROR); + if(!empty($queryParts)) { + $sql = 'UPDATE `*PREFIX*fscache` SET '.implode(' , ', $queryParts).' WHERE `id`=?'; + $query=OC_DB::prepare($sql); + $result=$query->execute($arguments); + if(OC_DB::isError($result)) { + OC_Log::write('files', 'error while updating file('.$id.') in cache', OC_Log::ERROR); + } } } @@ -151,7 +154,7 @@ class OC_FileCache{ * @param string newPath * @param string root (optional) */ - public static function move($oldPath,$newPath,$root=false) { + public static function move($oldPath, $newPath, $root=false) { if($root===false) { $root=OC_Filesystem::getRoot(); } @@ -190,7 +193,7 @@ class OC_FileCache{ * @param string path * @param string root (optional) */ - public static function delete($path,$root=false) { + public static function delete($path, $root=false) { if($root===false) { $root=OC_Filesystem::getRoot(); } @@ -211,7 +214,7 @@ class OC_FileCache{ * @param string root (optional) * @return array of filepaths */ - public static function search($search,$returnData=false,$root=false) { + public static function search($search, $returnData=false, $root=false) { if($root===false) { $root=OC_Filesystem::getRoot(); } @@ -227,7 +230,7 @@ class OC_FileCache{ $where = '`name` LIKE ? AND `user`=?'; } $query=OC_DB::prepare('SELECT '.$select.' FROM `*PREFIX*fscache` WHERE '.$where); - $result=$query->execute(array("%$search%",OC_User::getUser())); + $result=$query->execute(array("%$search%", OC_User::getUser())); $names=array(); while($row=$result->fetchRow()) { if(!$returnData) { @@ -255,7 +258,7 @@ class OC_FileCache{ * - encrypted * - versioned */ - public static function getFolderContent($path,$root=false,$mimetype_filter='') { + public static function getFolderContent($path, $root=false, $mimetype_filter='') { if(OC_FileCache_Update::hasUpdated($path, $root, true)) { OC_FileCache_Update::updateFolder($path, $root); } @@ -268,7 +271,7 @@ class OC_FileCache{ * @param string root (optional) * @return bool */ - public static function inCache($path,$root=false) { + public static function inCache($path, $root=false) { return self::getId($path, $root)!=-1; } @@ -278,7 +281,7 @@ class OC_FileCache{ * @param string root (optional) * @return int */ - public static function getId($path,$root=false) { + public static function getId($path, $root=false) { if($root===false) { $root=OC_Filesystem::getRoot(); } @@ -314,7 +317,7 @@ class OC_FileCache{ * @param string user (optional) * @return string */ - public static function getPath($id,$user='') { + public static function getPath($id, $user='') { if(!$user) { $user=OC_User::getUser(); } @@ -348,25 +351,38 @@ class OC_FileCache{ * @param int $sizeDiff * @param string root (optinal) */ - public static function increaseSize($path,$sizeDiff, $root=false) { + public static function increaseSize($path, $sizeDiff, $root=false) { if($sizeDiff==0) return; - $id=self::getId($path, $root); + $item = OC_FileCache_Cached::get($path); + //stop walking up the filetree if we hit a non-folder or reached to root folder + if($path == '/' || $path=='' || $item['mimetype'] !== 'httpd/unix-directory'){ + return; + } + $id = $item['id']; while($id!=-1) {//walk up the filetree increasing the size of all parent folders $query=OC_DB::prepare('UPDATE `*PREFIX*fscache` SET `size`=`size`+? WHERE `id`=?'); - $query->execute(array($sizeDiff,$id)); - $id=self::getParentId($path); + $query->execute(array($sizeDiff, $id)); $path=dirname($path); + if($path == '' or $path =='/'){ + return; + } + $parent = OC_FileCache_Cached::get($path); + $id = $parent['id']; + //stop walking up the filetree if we hit a non-folder + if($parent['mimetype'] !== 'httpd/unix-directory'){ + return; + } } } /** * recursively scan the filesystem and fill the cache * @param string $path - * @param OC_EventSource $enventSource (optional) - * @param int count (optional) - * @param string root (optional) + * @param OC_EventSource $eventSource (optional) + * @param int $count (optional) + * @param string $root (optional) */ - public static function scan($path,$eventSource=false,&$count=0,$root=false) { + public static function scan($path, $eventSource=false,&$count=0, $root=false) { if($eventSource) { $eventSource->send('scanning', array('file'=>$path, 'count'=>$count)); } @@ -401,8 +417,8 @@ class OC_FileCache{ } } - OC_FileCache_Update::cleanFolder($path,$root); - self::increaseSize($path,$totalSize,$root); + OC_FileCache_Update::cleanFolder($path, $root); + self::increaseSize($path, $totalSize, $root); } /** @@ -411,7 +427,7 @@ class OC_FileCache{ * @param string root (optional) * @return int size of the scanned file */ - public static function scanFile($path,$root=false) { + public static function scanFile($path, $root=false) { // NOTE: Ugly hack to prevent shared files from going into the cache (the source already exists somewhere in the cache) if (substr($path, 0, 7) == '/Shared') { return; @@ -448,12 +464,12 @@ class OC_FileCache{ * @return array of file paths * * $part1 and $part2 together form the complete mimetype. - * e.g. searchByMime('text','plain') + * e.g. searchByMime('text', 'plain') * * seccond mimetype part can be ommited * e.g. searchByMime('audio') */ - public static function searchByMime($part1,$part2=null,$root=false) { + public static function searchByMime($part1, $part2=null, $root=false) { if($root===false) { $root=OC_Filesystem::getRoot(); } @@ -500,13 +516,13 @@ class OC_FileCache{ * trigger an update for the cache by setting the mtimes to 0 * @param string $user (optional) */ - public static function triggerUpdate($user=''){ + public static function triggerUpdate($user='') { if($user) { - $query=OC_DB::prepare('UPDATE `*PREFIX*fscache` SET `mtime`=0 WHERE `user`=? AND `mimetype`="httpd/unix-directory"'); - $query->execute(array($user)); + $query=OC_DB::prepare('UPDATE `*PREFIX*fscache` SET `mtime`=0 WHERE `user`=? AND `mimetype`= ? '); + $query->execute(array($user,'httpd/unix-directory')); }else{ - $query=OC_DB::prepare('UPDATE `*PREFIX*fscache` SET `mtime`=0 AND `mimetype`="httpd/unix-directory"'); - $query->execute(); + $query=OC_DB::prepare('UPDATE `*PREFIX*fscache` SET `mtime`=0 AND `mimetype`= ? '); + $query->execute(array('httpd/unix-directory')); } } } diff --git a/lib/filecache/cached.php b/lib/filecache/cached.php index 9b1eb4f7803..5e0a00746b9 100644 --- a/lib/filecache/cached.php +++ b/lib/filecache/cached.php @@ -13,12 +13,12 @@ class OC_FileCache_Cached{ public static $savedData=array(); - public static function get($path,$root=false) { + public static function get($path, $root=false) { if($root===false) { $root=OC_Filesystem::getRoot(); } $path=$root.$path; - $stmt=OC_DB::prepare('SELECT `path`,`ctime`,`mtime`,`mimetype`,`size`,`encrypted`,`versioned`,`writable` FROM `*PREFIX*fscache` WHERE `path_hash`=?'); + $stmt=OC_DB::prepare('SELECT `id`, `path`,`ctime`,`mtime`,`mimetype`,`size`,`encrypted`,`versioned`,`writable` FROM `*PREFIX*fscache` WHERE `path_hash`=?'); if ( ! OC_DB::isError($stmt) ) { $result=$stmt->execute(array(md5($path))); if ( ! OC_DB::isError($result) ) { @@ -61,7 +61,7 @@ class OC_FileCache_Cached{ * - encrypted * - versioned */ - public static function getFolderContent($path,$root=false,$mimetype_filter='') { + public static function getFolderContent($path, $root=false, $mimetype_filter='') { if($root===false) { $root=OC_Filesystem::getRoot(); } @@ -78,4 +78,4 @@ class OC_FileCache_Cached{ return false; } } -}
\ No newline at end of file +} diff --git a/lib/filecache/update.php b/lib/filecache/update.php index f9d64d0ae99..bc403113e7c 100644 --- a/lib/filecache/update.php +++ b/lib/filecache/update.php @@ -18,7 +18,7 @@ class OC_FileCache_Update{ * @param boolean folder * @return bool */ - public static function hasUpdated($path,$root=false,$folder=false) { + public static function hasUpdated($path, $root=false, $folder=false) { if($root===false) { $view=OC_Filesystem::getView(); }else{ @@ -46,14 +46,14 @@ class OC_FileCache_Update{ /** * delete non existing files from the cache */ - public static function cleanFolder($path,$root=false) { + public static function cleanFolder($path, $root=false) { if($root===false) { $view=OC_Filesystem::getView(); }else{ $view=new OC_FilesystemView($root); } - $cachedContent=OC_FileCache_Cached::getFolderContent($path,$root); + $cachedContent=OC_FileCache_Cached::getFolderContent($path, $root); foreach($cachedContent as $fileData) { $path=$fileData['path']; $file=$view->getRelativePath($path); @@ -72,7 +72,7 @@ class OC_FileCache_Update{ * @param string path * @param string root (optional) */ - public static function updateFolder($path,$root=false) { + public static function updateFolder($path, $root=false) { if($root===false) { $view=OC_Filesystem::getView(); }else{ @@ -85,7 +85,7 @@ class OC_FileCache_Update{ $file=$path.'/'.$filename; $isDir=$view->is_dir($file); if(self::hasUpdated($file, $root, $isDir)) { - if($isDir){ + if($isDir) { self::updateFolder($file, $root); }elseif($root===false) {//filesystem hooks are only valid for the default root OC_Hook::emit('OC_Filesystem', 'post_write', array('path'=>$file)); @@ -143,7 +143,7 @@ class OC_FileCache_Update{ * @param string path * @param string root (optional) */ - public static function update($path,$root=false) { + public static function update($path, $root=false) { if($root===false) { $view=OC_Filesystem::getView(); }else{ @@ -153,7 +153,7 @@ class OC_FileCache_Update{ $mimetype=$view->getMimeType($path); $size=0; - $cached=OC_FileCache_Cached::get($path,$root); + $cached=OC_FileCache_Cached::get($path, $root); $cachedSize=isset($cached['size'])?$cached['size']:0; if($view->is_dir($path.'/')) { @@ -165,7 +165,7 @@ class OC_FileCache_Update{ $mtime=$view->filemtime($path.'/'); $ctime=$view->filectime($path.'/'); $writable=$view->is_writable($path.'/'); - OC_FileCache::put($path, array('size'=>$size,'mtime'=>$mtime,'ctime'=>$ctime,'mimetype'=>$mimetype,'writable'=>$writable)); + OC_FileCache::put($path, array('size'=>$size,'mtime'=>$mtime,'ctime'=>$ctime,'mimetype'=>$mimetype, 'writable'=>$writable)); }else{ $count=0; OC_FileCache::scan($path, null, $count, $root); @@ -174,7 +174,7 @@ class OC_FileCache_Update{ }else{ $size=OC_FileCache::scanFile($path, $root); } - if($path !== '' and $path !== '/'){ + if($path !== '' and $path !== '/') { OC_FileCache::increaseSize(dirname($path), $size-$cachedSize, $root); } } @@ -184,7 +184,7 @@ class OC_FileCache_Update{ * @param string path * @param string root (optional) */ - public static function delete($path,$root=false) { + public static function delete($path, $root=false) { $cached=OC_FileCache_Cached::get($path, $root); if(!isset($cached['size'])) { return; @@ -200,7 +200,7 @@ class OC_FileCache_Update{ * @param string newPath * @param string root (optional) */ - public static function rename($oldPath,$newPath,$root=false) { + public static function rename($oldPath, $newPath, $root=false) { if(!OC_FileCache::inCache($oldPath, $root)) { return; } diff --git a/lib/fileproxy.php b/lib/fileproxy.php index 3e7f1aa1c41..2f81bde64a1 100644 --- a/lib/fileproxy.php +++ b/lib/fileproxy.php @@ -51,7 +51,7 @@ class OC_FileProxy{ * * this implements a dummy proxy for all operations */ - public function __call($function,$arguments) { + public function __call($function, $arguments) { if(substr($function, 0, 3)=='pre') { return true; }else{ @@ -85,7 +85,7 @@ class OC_FileProxy{ $proxies=self::getProxies($operation); foreach($proxies as $proxy) { if(!is_null($filepath2)) { - if($proxy->$operation($filepath,$filepath2)===false) { + if($proxy->$operation($filepath, $filepath2)===false) { return false; } }else{ @@ -97,14 +97,14 @@ class OC_FileProxy{ return true; } - public static function runPostProxies($operation,$path,$result) { + public static function runPostProxies($operation, $path, $result) { if(!self::$enabled) { return $result; } $operation='post'.$operation; $proxies=self::getProxies($operation); foreach($proxies as $proxy) { - $result=$proxy->$operation($path,$result); + $result=$proxy->$operation($path, $result); } return $result; } diff --git a/lib/fileproxy/fileoperations.php b/lib/fileproxy/fileoperations.php index 23fb63fcfb1..516629adaec 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_FilesystemView(''); } return !self::$rootView->file_exists($path); diff --git a/lib/fileproxy/quota.php b/lib/fileproxy/quota.php index 012be582a51..742e02d471b 100644 --- a/lib/fileproxy/quota.php +++ b/lib/fileproxy/quota.php @@ -38,12 +38,12 @@ class OC_FileProxy_Quota extends OC_FileProxy{ if(in_array($user, $this->userQuota)) { return $this->userQuota[$user]; } - $userQuota=OC_Preferences::getValue($user,'files','quota','default'); + $userQuota=OC_Preferences::getValue($user, 'files', 'quota', 'default'); if($userQuota=='default') { - $userQuota=OC_AppConfig::getValue('files','default_quota','none'); + $userQuota=OC_AppConfig::getValue('files', 'default_quota', 'none'); } if($userQuota=='none') { - $this->userQuota[$user]=0; + $this->userQuota[$user]=-1; }else{ $this->userQuota[$user]=OC_Helper::computerFileSize($userQuota); } @@ -61,8 +61,8 @@ class OC_FileProxy_Quota extends OC_FileProxy{ $owner=$storage->getOwner($path); $totalSpace=$this->getQuota($owner); - if($totalSpace==0) { - return 0; + if($totalSpace==-1) { + return -1; } $rootInfo=OC_FileCache::get('', "/".$owner."/files"); @@ -77,33 +77,33 @@ class OC_FileProxy_Quota extends OC_FileProxy{ return $totalSpace-$usedSpace; } - public function postFree_space($path,$space) { + public function postFree_space($path, $space) { $free=$this->getFreeSpace($path); - if($free==0) { + if($free==-1) { return $space; } - return min($free,$space); + return min($free, $space); } - public function preFile_put_contents($path,$data) { + public function preFile_put_contents($path, $data) { if (is_resource($data)) { $data = '';//TODO: find a way to get the length of the stream without emptying it } - return (strlen($data)<$this->getFreeSpace($path) or $this->getFreeSpace($path)==0); + return (strlen($data)<$this->getFreeSpace($path) or $this->getFreeSpace($path)==-1); } - public function preCopy($path1,$path2) { - if(!self::$rootView){ + public function preCopy($path1, $path2) { + if(!self::$rootView) { self::$rootView = new OC_FilesystemView(''); } - return (self::$rootView->filesize($path1)<$this->getFreeSpace($path2) or $this->getFreeSpace($path2)==0); + return (self::$rootView->filesize($path1)<$this->getFreeSpace($path2) or $this->getFreeSpace($path2)==-1); } - public function preFromTmpFile($tmpfile,$path) { - return (filesize($tmpfile)<$this->getFreeSpace($path) or $this->getFreeSpace($path)==0); + public function preFromTmpFile($tmpfile, $path) { + return (filesize($tmpfile)<$this->getFreeSpace($path) or $this->getFreeSpace($path)==-1); } - public function preFromUploadedFile($tmpfile,$path) { - return (filesize($tmpfile)<$this->getFreeSpace($path) or $this->getFreeSpace($path)==0); + public function preFromUploadedFile($tmpfile, $path) { + return (filesize($tmpfile)<$this->getFreeSpace($path) or $this->getFreeSpace($path)==-1); } } diff --git a/lib/files.php b/lib/files.php index b4d4de1c995..b4a4145a493 100644 --- a/lib/files.php +++ b/lib/files.php @@ -42,16 +42,20 @@ class OC_Files { * - versioned */ public static function getFileInfo($path) { + $path = OC_Filesystem::normalizePath($path); if (($path == '/Shared' || substr($path, 0, 8) == '/Shared/') && OC_App::isEnabled('files_sharing')) { if ($path == '/Shared') { list($info) = OCP\Share::getItemsSharedWith('file', OC_Share_Backend_File::FORMAT_FILE_APP_ROOT); - }else{ - $info['size'] = OC_Filesystem::filesize($path); - $info['mtime'] = OC_Filesystem::filemtime($path); - $info['ctime'] = OC_Filesystem::filectime($path); - $info['mimetype'] = OC_Filesystem::getMimeType($path); - $info['encrypted'] = false; - $info['versioned'] = false; + } else { + $info = array(); + if (OC_Filesystem::file_exists($path)) { + $info['size'] = OC_Filesystem::filesize($path); + $info['mtime'] = OC_Filesystem::filemtime($path); + $info['ctime'] = OC_Filesystem::filectime($path); + $info['mimetype'] = OC_Filesystem::getMimeType($path); + $info['encrypted'] = false; + $info['versioned'] = false; + } } } else { $info = OC_FileCache::get($path); @@ -87,16 +91,16 @@ class OC_Files { foreach ($files as &$file) { $file['directory'] = $directory; $file['type'] = ($file['mimetype'] == 'httpd/unix-directory') ? 'dir' : 'file'; - $permissions = OCP\Share::PERMISSION_READ; + $permissions = OCP\PERMISSION_READ; // NOTE: Remove check when new encryption is merged if (!$file['encrypted']) { - $permissions |= OCP\Share::PERMISSION_SHARE; + $permissions |= OCP\PERMISSION_SHARE; } if ($file['type'] == 'dir' && $file['writable']) { - $permissions |= OCP\Share::PERMISSION_CREATE; + $permissions |= OCP\PERMISSION_CREATE; } if ($file['writable']) { - $permissions |= OCP\Share::PERMISSION_UPDATE | OCP\Share::PERMISSION_DELETE; + $permissions |= OCP\PERMISSION_UPDATE | OCP\PERMISSION_DELETE; } $file['permissions'] = $permissions; } @@ -135,7 +139,12 @@ class OC_Files { * @param file $file ; seperated list of files to download * @param boolean $only_header ; boolean to only send header of the request */ - public static function get($dir,$files, $only_header = false) { + public static function get($dir, $files, $only_header = false) { + $xsendfile = false; + if (isset($_SERVER['MOD_X_SENDFILE_ENABLED']) || + isset($_SERVER['MOD_X_ACCEL_REDIRECT_ENABLED'])) { + $xsendfile = true; + } if(strpos($files, ';')) { $files=explode(';', $files); } @@ -145,7 +154,11 @@ class OC_Files { $executionTime = intval(ini_get('max_execution_time')); set_time_limit(0); $zip = new ZipArchive(); - $filename = OC_Helper::tmpFile('.zip'); + if ($xsendfile) { + $filename = OC_Helper::tmpFileNoClean('.zip'); + }else{ + $filename = OC_Helper::tmpFile('.zip'); + } if ($zip->open($filename, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE)!==true) { exit("cannot open <$filename>\n"); } @@ -166,7 +179,11 @@ class OC_Files { $executionTime = intval(ini_get('max_execution_time')); set_time_limit(0); $zip = new ZipArchive(); - $filename = OC_Helper::tmpFile('.zip'); + if ($xsendfile) { + $filename = OC_Helper::tmpFileNoClean('.zip'); + }else{ + $filename = OC_Helper::tmpFile('.zip'); + } if ($zip->open($filename, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE)!==true) { exit("cannot open <$filename>\n"); } @@ -178,7 +195,7 @@ class OC_Files { $zip=false; $filename=$dir.'/'.$files; } - @ob_end_clean(); + OC_Util::obEnd(); if($zip or OC_Filesystem::is_readable($filename)) { header('Content-Disposition: attachment; filename="'.basename($filename).'"'); header('Content-Transfer-Encoding: binary'); @@ -187,8 +204,13 @@ class OC_Files { ini_set('zlib.output_compression', 'off'); header('Content-Type: application/zip'); header('Content-Length: ' . filesize($filename)); + self::addSendfileHeader($filename); }else{ header('Content-Type: '.OC_Filesystem::getMimeType($filename)); + $storage = OC_Filesystem::getStorage($filename); + if ($storage instanceof OC_Filestorage_Local) { + self::addSendfileHeader(OC_Filesystem::getLocalFile($filename)); + } } }elseif($zip or !OC_Filesystem::file_exists($filename)) { header("HTTP/1.0 404 Not Found"); @@ -213,7 +235,9 @@ class OC_Files { flush(); } } - unlink($filename); + if (!$xsendfile) { + unlink($filename); + } }else{ OC_Filesystem::readfile($filename); } @@ -224,11 +248,20 @@ class OC_Files { } } - public static function zipAddDir($dir,$zip,$internalDir='') { + private static function addSendfileHeader($filename) { + if (isset($_SERVER['MOD_X_SENDFILE_ENABLED'])) { + header("X-Sendfile: " . $filename); + } + if (isset($_SERVER['MOD_X_ACCEL_REDIRECT_ENABLED'])) { + header("X-Accel-Redirect: " . $filename); + } + } + + public static function zipAddDir($dir, $zip, $internalDir='') { $dirname=basename($dir); $zip->addEmptyDir($internalDir.$dirname); $internalDir.=$dirname.='/'; - $files=OC_Files::getdirectorycontent($dir); + $files=OC_Files::getDirectoryContent($dir); foreach($files as $file) { $filename=$file['name']; $file=$dir.'/'.$filename; @@ -249,7 +282,7 @@ class OC_Files { * @param dir $targetDir * @param file $target */ - public static function move($sourceDir,$source,$targetDir,$target) { + public static function move($sourceDir, $source, $targetDir, $target) { if(OC_User::isLoggedIn() && ($sourceDir != '' || $source != 'Shared')) { $targetFile=self::normalizePath($targetDir.'/'.$target); $sourceFile=self::normalizePath($sourceDir.'/'.$source); @@ -267,7 +300,7 @@ class OC_Files { * @param dir $targetDir * @param file $target */ - public static function copy($sourceDir,$source,$targetDir,$target) { + public static function copy($sourceDir, $source, $targetDir, $target) { if(OC_User::isLoggedIn()) { $targetFile=$targetDir.'/'.$target; $sourceFile=$sourceDir.'/'.$source; @@ -282,7 +315,7 @@ class OC_Files { * @param file $name * @param type $type */ - public static function newFile($dir,$name,$type) { + public static function newFile($dir, $name, $type) { if(OC_User::isLoggedIn()) { $file=$dir.'/'.$name; if($type=='dir') { @@ -305,7 +338,7 @@ class OC_Files { * @param dir $dir * @param file $name */ - public static function delete($dir,$file) { + public static function delete($dir, $file) { if(OC_User::isLoggedIn() && ($dir!= '' || $file != 'Shared')) { $file=$dir.'/'.$file; return OC_Filesystem::unlink($file); @@ -389,9 +422,9 @@ class OC_Files { * @param string file * @return string guessed mime type */ - static function pull($source,$token,$dir,$file) { + static function pull($source, $token, $dir, $file) { $tmpfile=tempnam(get_temp_dir(), 'remoteCloudFile'); - $fp=fopen($tmpfile,'w+'); + $fp=fopen($tmpfile, 'w+'); $url=$source.="/files/pull.php?token=$token"; $ch=curl_init(); curl_setopt($ch, CURLOPT_URL, $url); @@ -480,7 +513,7 @@ class OC_Files { } } -function fileCmp($a,$b) { +function fileCmp($a, $b) { if($a['type']=='dir' and $b['type']!='dir') { return -1; }elseif($a['type']!='dir' and $b['type']=='dir') { diff --git a/lib/filestorage.php b/lib/filestorage.php index 146cecf4efa..dd65f4421b7 100644 --- a/lib/filestorage.php +++ b/lib/filestorage.php @@ -42,13 +42,13 @@ abstract class OC_Filestorage{ abstract public function filectime($path); abstract public function filemtime($path); abstract public function file_get_contents($path); - abstract public function file_put_contents($path,$data); + abstract public function file_put_contents($path, $data); abstract public function unlink($path); - abstract public function rename($path1,$path2); - abstract public function copy($path1,$path2); - abstract public function fopen($path,$mode); + abstract public function rename($path1, $path2); + abstract public function copy($path1, $path2); + abstract public function fopen($path, $mode); abstract public function getMimeType($path); - abstract public function hash($type,$path,$raw = false); + abstract public function hash($type, $path, $raw = false); abstract public function free_space($path); abstract public function search($query); abstract public function touch($path, $mtime=null); @@ -62,6 +62,6 @@ abstract class OC_Filestorage{ * hasUpdated for folders should return at least true if a file inside the folder is add, removed or renamed. * returning true for other changes in the folder is optional */ - abstract public function hasUpdated($path,$time); + abstract public function hasUpdated($path, $time); abstract public function getOwner($path); } diff --git a/lib/filestorage/common.php b/lib/filestorage/common.php index f24a5704913..b97eb79d8d4 100644 --- a/lib/filestorage/common.php +++ b/lib/filestorage/common.php @@ -89,25 +89,25 @@ abstract class OC_Filestorage_Common extends OC_Filestorage { } 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); } // abstract public function unlink($path); - 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{ return false; } } - public function copy($path1,$path2) { - $source=$this->fopen($path1,'r'); - $target=$this->fopen($path2,'w'); - $count=OC_Helper::streamCopy($source,$target); + public function copy($path1, $path2) { + $source=$this->fopen($path1, 'r'); + $target=$this->fopen($path2, 'w'); + $count=OC_Helper::streamCopy($source, $target); return $count>0; } -// abstract public function fopen($path,$mode); +// abstract public function fopen($path, $mode); /** * @brief Deletes all files and folders recursively within a directory @@ -188,25 +188,25 @@ abstract class OC_Filestorage_Common extends OC_Filestorage { if($this->is_dir($path)) { return 'httpd/unix-directory'; } - $source=$this->fopen($path,'r'); + $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); + $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); + file_put_contents($tmpFile, $head); $mime=OC_Helper::getMimeType($tmpFile); unlink($tmpFile); return $mime; } - public function hash($type,$path,$raw = false) { + public function hash($type, $path, $raw = false) { $tmpFile=$this->getLocalFile(); - $hash=hash($type,$tmpFile,$raw); + $hash=hash($type, $tmpFile, $raw); unlink($tmpFile); return $hash; } @@ -218,35 +218,35 @@ abstract class OC_Filestorage_Common extends OC_Filestorage { return $this->toTmpFile($path); } private function toTmpFile($path) {//no longer in the storage api, still usefull here - $source=$this->fopen($path,'r'); + $source=$this->fopen($path, 'r'); if(!$source) { return false; } - if($pos=strrpos($path,'.')) { - $extension=substr($path,$pos); + if($pos=strrpos($path, '.')) { + $extension=substr($path, $pos); }else{ $extension=''; } $tmpFile=OC_Helper::tmpFile($extension); - $target=fopen($tmpFile,'w'); - OC_Helper::streamCopy($source,$target); + $target=fopen($tmpFile, 'w'); + OC_Helper::streamCopy($source, $target); return $tmpFile; } public function getLocalFolder($path) { $baseDir=OC_Helper::tmpFolder(); - $this->addLocalFolder($path,$baseDir); + $this->addLocalFolder($path, $baseDir); return $baseDir; } - private function addLocalFolder($path,$target) { + 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); + $this->addLocalFolder($path.'/'.$file, $target.'/'.$file); }else{ $tmp=$this->toTmpFile($path.'/'.$file); - rename($tmp,$target.'/'.$file); + rename($tmp, $target.'/'.$file); } } } @@ -254,7 +254,7 @@ abstract class OC_Filestorage_Common extends OC_Filestorage { } // abstract public function touch($path, $mtime=null); - protected function searchInDir($query,$dir='') { + protected function searchInDir($query, $dir='') { $files=array(); $dh=$this->opendir($dir); if($dh) { @@ -264,7 +264,7 @@ abstract class OC_Filestorage_Common extends OC_Filestorage { $files[]=$dir.'/'.$item; } if($this->is_dir($dir.'/'.$item)) { - $files=array_merge($files,$this->searchInDir($query,$dir.'/'.$item)); + $files=array_merge($files, $this->searchInDir($query, $dir.'/'.$item)); } } } @@ -276,7 +276,7 @@ abstract class OC_Filestorage_Common extends OC_Filestorage { * @param int $time * @return bool */ - public function hasUpdated($path,$time) { + public function hasUpdated($path, $time) { return $this->filemtime($path)>$time; } diff --git a/lib/filestorage/commontest.php b/lib/filestorage/commontest.php index b88bb232c36..3b038b3fda9 100644 --- a/lib/filestorage/commontest.php +++ b/lib/filestorage/commontest.php @@ -63,13 +63,13 @@ class OC_Filestorage_CommonTest extends OC_Filestorage_Common{ public function unlink($path) { return $this->storage->unlink($path); } - public function fopen($path,$mode) { - return $this->storage->fopen($path,$mode); + public function fopen($path, $mode) { + return $this->storage->fopen($path, $mode); } public function free_space($path) { return $this->storage->free_space($path); } public function touch($path, $mtime=null) { - return $this->storage->touch($path,$mtime); + return $this->storage->touch($path, $mtime); } }
\ No newline at end of file diff --git a/lib/filestorage/local.php b/lib/filestorage/local.php index 731ac4a3c72..6fe45acf8c5 100644 --- a/lib/filestorage/local.php +++ b/lib/filestorage/local.php @@ -6,7 +6,7 @@ class OC_Filestorage_Local extends OC_Filestorage_Common{ protected $datadir; public function __construct($arguments) { $this->datadir=$arguments['datadir']; - if(substr($this->datadir,-1)!=='/') { + if(substr($this->datadir, -1)!=='/') { $this->datadir.='/'; } } @@ -20,8 +20,8 @@ class OC_Filestorage_Local extends OC_Filestorage_Common{ return opendir($this->datadir.$path); } public function is_dir($path) { - if(substr($path,-1)=='/') { - $path=substr($path,0,-1); + if(substr($path, -1)=='/') { + $path=substr($path, 0, -1); } return is_dir($this->datadir.$path); } @@ -78,38 +78,38 @@ class OC_Filestorage_Local extends OC_Filestorage_Common{ public function file_get_contents($path) { return file_get_contents($this->datadir.$path); } - public function file_put_contents($path,$data) { - return file_put_contents($this->datadir.$path,$data); + public function file_put_contents($path, $data) { + return file_put_contents($this->datadir.$path, $data); } public function unlink($path) { return $this->delTree($path); } - public function rename($path1,$path2) { + 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; } - if($return=rename($this->datadir.$path1,$this->datadir.$path2)) { + if($return=rename($this->datadir.$path1, $this->datadir.$path2)) { } return $return; } - public function copy($path1,$path2) { + public function copy($path1, $path2) { if($this->is_dir($path2)) { if(!$this->file_exists($path2)) { $this->mkdir($path2); } - $source=substr($path1, strrpos($path1,'/')+1); + $source=substr($path1, strrpos($path1, '/')+1); $path2.=$source; } - return copy($this->datadir.$path1,$this->datadir.$path2); + return copy($this->datadir.$path1, $this->datadir.$path2); } - public function fopen($path,$mode) { - if($return=fopen($this->datadir.$path,$mode)) { + public function fopen($path, $mode) { + if($return=fopen($this->datadir.$path, $mode)) { switch($mode) { case 'r': break; @@ -156,8 +156,8 @@ class OC_Filestorage_Local extends OC_Filestorage_Common{ return $return; } - public function hash($path,$type,$raw=false) { - return hash_file($type,$this->datadir.$path,$raw); + public function hash($path, $type, $raw=false) { + return hash_file($type, $this->datadir.$path, $raw); } public function free_space($path) { @@ -174,7 +174,7 @@ class OC_Filestorage_Local extends OC_Filestorage_Common{ return $this->datadir.$path; } - protected function searchInDir($query,$dir='') { + protected function searchInDir($query, $dir='') { $files=array(); foreach (scandir($this->datadir.$dir) as $item) { if ($item == '.' || $item == '..') continue; @@ -182,7 +182,7 @@ class OC_Filestorage_Local extends OC_Filestorage_Common{ $files[]=$dir.'/'.$item; } if(is_dir($this->datadir.$dir.'/'.$item)) { - $files=array_merge($files,$this->searchInDir($query,$dir.'/'.$item)); + $files=array_merge($files, $this->searchInDir($query, $dir.'/'.$item)); } } return $files; @@ -193,7 +193,7 @@ class OC_Filestorage_Local extends OC_Filestorage_Common{ * @param int $time * @return bool */ - public function hasUpdated($path,$time) { + public function hasUpdated($path, $time) { return $this->filemtime($path)>$time; } } diff --git a/lib/filesystem.php b/lib/filesystem.php index bc30dac7fa1..aa03593908d 100644 --- a/lib/filesystem.php +++ b/lib/filesystem.php @@ -35,10 +35,10 @@ * post_create(path) * delete(path, &run) * post_delete(path) - * rename(oldpath,newpath, &run) - * post_rename(oldpath,newpath) - * copy(oldpath,newpath, &run) (if the newpath doesn't exists yes, copy, create and write will be emited in that order) - * post_rename(oldpath,newpath) + * rename(oldpath, newpath, &run) + * post_rename(oldpath, newpath) + * copy(oldpath, newpath, &run) (if the newpath doesn't exists yes, copy, create and write will be emited in that order) + * post_rename(oldpath, newpath) * * the &run parameter can be set to false to prevent the operation from occuring */ @@ -148,21 +148,21 @@ class OC_Filesystem{ * @return string */ static public function getMountPoint($path) { - OC_Hook::emit(self::CLASSNAME,'get_mountpoint', array('path'=>$path)); + OC_Hook::emit(self::CLASSNAME, 'get_mountpoint', array('path'=>$path)); if(!$path) { $path='/'; } if($path[0]!=='/') { $path='/'.$path; } - $path=str_replace('//', '/',$path); + $path=str_replace('//', '/', $path); $foundMountPoint=''; $mountPoints=array_keys(OC_Filesystem::$mounts); foreach($mountPoints as $mountpoint) { if($mountpoint==$path) { return $mountpoint; } - if(strpos($path,$mountpoint)===0 and strlen($mountpoint)>strlen($foundMountPoint)) { + if(strpos($path, $mountpoint)===0 and strlen($mountpoint)>strlen($foundMountPoint)) { $foundMountPoint=$mountpoint; } } @@ -202,55 +202,55 @@ class OC_Filesystem{ if($mountpoint) { if(!isset(OC_Filesystem::$storages[$mountpoint])) { $mount=OC_Filesystem::$mounts[$mountpoint]; - OC_Filesystem::$storages[$mountpoint]=OC_Filesystem::createStorage($mount['class'],$mount['arguments']); + OC_Filesystem::$storages[$mountpoint]=OC_Filesystem::createStorage($mount['class'], $mount['arguments']); } return OC_Filesystem::$storages[$mountpoint]; } } static private function loadSystemMountPoints($user) { - if(is_file(OC::$SERVERROOT.'/config/mount.php')) {
- $mountConfig=include OC::$SERVERROOT.'/config/mount.php';
- if(isset($mountConfig['global'])) {
- foreach($mountConfig['global'] as $mountPoint=>$options) {
- self::mount($options['class'],$options['options'],$mountPoint);
- }
- }
-
- if(isset($mountConfig['group'])) {
- foreach($mountConfig['group'] as $group=>$mounts) {
- if(OC_Group::inGroup($user,$group)) {
- foreach($mounts as $mountPoint=>$options) {
- $mountPoint=self::setUserVars($mountPoint, $user);
- foreach($options as &$option) {
- $option=self::setUserVars($option, $user);
- }
- self::mount($options['class'],$options['options'],$mountPoint);
- }
- }
- }
- }
-
- if(isset($mountConfig['user'])) {
- foreach($mountConfig['user'] as $user=>$mounts) {
- if($user==='all' or strtolower($user)===strtolower($user)) {
- foreach($mounts as $mountPoint=>$options) {
- $mountPoint=self::setUserVars($mountPoint, $user);
- foreach($options as &$option) {
- $option=self::setUserVars($option, $user);
- }
- self::mount($options['class'],$options['options'],$mountPoint);
- }
- }
- }
- }
-
- $mtime=filemtime(OC::$SERVERROOT.'/config/mount.php');
- $previousMTime=OC_Appconfig::getValue('files','mountconfigmtime',0);
- if($mtime>$previousMTime) {//mount config has changed, filecache needs to be updated
- OC_FileCache::triggerUpdate();
- OC_Appconfig::setValue('files','mountconfigmtime',$mtime);
- }
+ if(is_file(OC::$SERVERROOT.'/config/mount.php')) { + $mountConfig=include OC::$SERVERROOT.'/config/mount.php'; + if(isset($mountConfig['global'])) { + foreach($mountConfig['global'] as $mountPoint=>$options) { + self::mount($options['class'], $options['options'], $mountPoint); + } + } + + if(isset($mountConfig['group'])) { + foreach($mountConfig['group'] as $group=>$mounts) { + if(OC_Group::inGroup($user, $group)) { + foreach($mounts as $mountPoint=>$options) { + $mountPoint=self::setUserVars($mountPoint, $user); + foreach($options as &$option) { + $option=self::setUserVars($option, $user); + } + self::mount($options['class'], $options['options'], $mountPoint); + } + } + } + } + + if(isset($mountConfig['user'])) { + foreach($mountConfig['user'] as $mountUser=>$mounts) { + if($user==='all' or strtolower($mountUser)===strtolower($user)) { + foreach($mounts as $mountPoint=>$options) { + $mountPoint=self::setUserVars($mountPoint, $user); + foreach($options as &$option) { + $option=self::setUserVars($option, $user); + } + self::mount($options['class'], $options['options'], $mountPoint); + } + } + } + } + + $mtime=filemtime(OC::$SERVERROOT.'/config/mount.php'); + $previousMTime=OC_Appconfig::getValue('files', 'mountconfigmtime', 0); + if($mtime>$previousMTime) {//mount config has changed, filecache needs to be updated + OC_FileCache::triggerUpdate(); + OC_Appconfig::setValue('files', 'mountconfigmtime', $mtime); + } } } @@ -276,9 +276,9 @@ class OC_Filesystem{ */ private static function setUserVars($input, $user) { if (isset($user)) { - return str_replace('$user', $user,$input); + return str_replace('$user', $user, $input); } else { - return str_replace('$user',OC_User::getUser(),$input); + return str_replace('$user', OC_User::getUser(), $input); } } @@ -303,7 +303,7 @@ class OC_Filesystem{ * @param array arguments * @return OC_Filestorage */ - static private function createStorage($class,$arguments) { + static private function createStorage($class, $arguments) { if(class_exists($class)) { try { return new $class($arguments); @@ -312,7 +312,7 @@ class OC_Filesystem{ return false; } }else{ - OC_Log::write('core','storage backend '.$class.' not found',OC_Log::ERROR); + OC_Log::write('core', 'storage backend '.$class.' not found', OC_Log::ERROR); return false; } } @@ -349,14 +349,14 @@ class OC_Filesystem{ * @param OC_Filestorage storage * @param string mountpoint */ - static public function mount($class,$arguments,$mountpoint) { + static public function mount($class, $arguments, $mountpoint) { if($mountpoint[0]!='/') { $mountpoint='/'.$mountpoint; } - if(substr($mountpoint,-1)!=='/') { + if(substr($mountpoint, -1)!=='/') { $mountpoint=$mountpoint.'/'; } - self::$mounts[$mountpoint]=array('class'=>$class,'arguments'=>$arguments); + self::$mounts[$mountpoint]=array('class'=>$class, 'arguments'=>$arguments); } /** @@ -396,10 +396,14 @@ class OC_Filesystem{ * @return bool */ static public function isValidPath($path) { + $path = self::normalizePath($path); if(!$path || $path[0]!=='/') { $path='/'.$path; } - if(strstr($path,'/../') || strrchr($path, '/') === '/..' ) { + if(strstr($path, '/../') || strrchr($path, '/') === '/..' ) { + return false; + } + if(self::isFileBlacklisted($path)) { return false; } return true; @@ -411,20 +415,22 @@ class OC_Filesystem{ * @param array $data from hook */ static public function isBlacklisted($data) { - $blacklist = 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)) { - $data['run'] = false; - } + $data['run'] = !self::isFileBlacklisted($path); } } + static public function isFileBlacklisted($path) { + $blacklist = array('.htaccess'); + $filename = strtolower(basename($path)); + return in_array($filename, $blacklist); + } + /** * following functions are equivilent to their php buildin equivilents for arguments/return values. */ @@ -500,33 +506,33 @@ class OC_Filesystem{ static public function file_get_contents($path) { return self::$defaultInstance->file_get_contents($path); } - static public function file_put_contents($path,$data) { - return self::$defaultInstance->file_put_contents($path,$data); + static public function file_put_contents($path, $data) { + return self::$defaultInstance->file_put_contents($path, $data); } static public function unlink($path) { return self::$defaultInstance->unlink($path); } - static public function rename($path1,$path2) { - return self::$defaultInstance->rename($path1,$path2); + static public function rename($path1, $path2) { + return self::$defaultInstance->rename($path1, $path2); } - static public function copy($path1,$path2) { - return self::$defaultInstance->copy($path1,$path2); + static public function copy($path1, $path2) { + return self::$defaultInstance->copy($path1, $path2); } - static public function fopen($path,$mode) { - return self::$defaultInstance->fopen($path,$mode); + static public function fopen($path, $mode) { + return self::$defaultInstance->fopen($path, $mode); } static public function toTmpFile($path) { return self::$defaultInstance->toTmpFile($path); } - static public function fromTmpFile($tmpFile,$path) { - return self::$defaultInstance->fromTmpFile($tmpFile,$path); + static public function fromTmpFile($tmpFile, $path) { + return self::$defaultInstance->fromTmpFile($tmpFile, $path); } static public function getMimeType($path) { return self::$defaultInstance->getMimeType($path); } - static public function hash($type,$path, $raw = false) { - return self::$defaultInstance->hash($type,$path, $raw); + static public function hash($type, $path, $raw = false) { + return self::$defaultInstance->hash($type, $path, $raw); } static public function free_space($path='/') { @@ -542,8 +548,8 @@ class OC_Filesystem{ * @param int $time * @return bool */ - static public function hasUpdated($path,$time) { - return self::$defaultInstance->hasUpdated($path,$time); + static public function hasUpdated($path, $time) { + return self::$defaultInstance->hasUpdated($path, $time); } static public function removeETagHook($params, $root = false) { @@ -569,23 +575,23 @@ class OC_Filesystem{ * @param bool $stripTrailingSlash * @return string */ - public static function normalizePath($path,$stripTrailingSlash=true) { + public static function normalizePath($path, $stripTrailingSlash=true) { if($path=='') { return '/'; } //no windows style slashes - $path=str_replace('\\','/',$path); + $path=str_replace('\\', '/', $path); //add leading slash if($path[0]!=='/') { $path='/'.$path; } //remove trainling slash - if($stripTrailingSlash and strlen($path)>1 and substr($path,-1,1)==='/') { - $path=substr($path,0,-1); + if($stripTrailingSlash and strlen($path)>1 and substr($path, -1, 1)==='/') { + $path=substr($path, 0, -1); } //remove duplicate slashes - while(strpos($path,'//')!==false) { - $path=str_replace('//','/',$path); + while(strpos($path, '//')!==false) { + $path=str_replace('//', '/', $path); } //normalize unicode if possible if(class_exists('Normalizer')) { @@ -594,9 +600,9 @@ class OC_Filesystem{ return $path; } } -OC_Hook::connect('OC_Filesystem','post_write', 'OC_Filesystem','removeETagHook'); -OC_Hook::connect('OC_Filesystem','post_delete','OC_Filesystem','removeETagHook'); -OC_Hook::connect('OC_Filesystem','post_rename','OC_Filesystem','removeETagHook'); +OC_Hook::connect('OC_Filesystem', 'post_write', 'OC_Filesystem', 'removeETagHook'); +OC_Hook::connect('OC_Filesystem', 'post_delete', 'OC_Filesystem', 'removeETagHook'); +OC_Hook::connect('OC_Filesystem', 'post_rename', 'OC_Filesystem', 'removeETagHook'); OC_Util::setupFS(); require_once 'filecache.php'; diff --git a/lib/filesystemview.php b/lib/filesystemview.php index 872da992fab..e944ae5045d 100644 --- a/lib/filesystemview.php +++ b/lib/filesystemview.php @@ -47,11 +47,8 @@ class OC_FilesystemView { $this->fakeRoot=$root; } - public function getAbsolutePath($path) { - if(!$path) { - $path='/'; - } - if($path[0]!=='/') { + public function getAbsolutePath($path = '/') { + if(!$path || $path[0]!=='/') { $path='/'.$path; } return $this->fakeRoot.$path; @@ -142,7 +139,7 @@ class OC_FilesystemView { * @return string */ public function getLocalFile($path) { - $parent=substr($path, 0, strrpos($path,'/')); + $parent=substr($path, 0, strrpos($path, '/')); if(OC_Filesystem::isValidPath($parent) and $storage=$this->getStorage($path)) { return $storage->getLocalFile($this->getInternalPath($path)); } @@ -152,7 +149,7 @@ class OC_FilesystemView { * @return string */ public function getLocalFolder($path) { - $parent=substr($path, 0, strrpos($path,'/')); + $parent=substr($path, 0, strrpos($path, '/')); if(OC_Filesystem::isValidPath($parent) and $storage=$this->getStorage($path)) { return $storage->getLocalFolder($this->getInternalPath($path)); } @@ -198,7 +195,7 @@ class OC_FilesystemView { return $this->basicOperation('filesize', $path); } public function readfile($path) { - @ob_end_clean(); + OC_Util::obEnd(); $handle=$this->fopen($path, 'rb'); if ($handle) { $chunkSize = 8192;// 8 MB chunks @@ -215,13 +212,13 @@ class OC_FilesystemView { * @deprecated Replaced by isReadable() as part of CRUDS */ public function is_readable($path) { - return $this->basicOperation('isReadable',$path); + return $this->basicOperation('isReadable', $path); } /** * @deprecated Replaced by isCreatable(), isUpdatable(), isDeletable() as part of CRUDS */ public function is_writable($path) { - return $this->basicOperation('isUpdatable',$path); + return $this->basicOperation('isUpdatable', $path); } public function isCreatable($path) { return $this->basicOperation('isCreatable', $path); @@ -251,7 +248,7 @@ class OC_FilesystemView { return $this->basicOperation('filemtime', $path); } public function touch($path, $mtime=null) { - if(!is_null($mtime) and !is_numeric($mtime)){ + if(!is_null($mtime) and !is_numeric($mtime)) { $mtime = strtotime($mtime); } return $this->basicOperation('touch', $path, array('write'), $mtime); @@ -266,7 +263,7 @@ class OC_FilesystemView { $path = $this->getRelativePath($absolutePath); $exists = $this->file_exists($path); $run = true; - if( $this->fakeRoot==OC_Filesystem::getRoot() ){ + if( $this->fakeRoot==OC_Filesystem::getRoot() ) { if(!$exists) { OC_Hook::emit( OC_Filesystem::CLASSNAME, @@ -294,7 +291,7 @@ class OC_FilesystemView { $count=OC_Helper::streamCopy($data, $target); fclose($target); fclose($data); - if( $this->fakeRoot==OC_Filesystem::getRoot() ){ + if( $this->fakeRoot==OC_Filesystem::getRoot() ) { if(!$exists) { OC_Hook::emit( OC_Filesystem::CLASSNAME, @@ -325,8 +322,8 @@ class OC_FilesystemView { return $this->basicOperation( 'deleteAll', $directory, array('delete'), $empty ); } public function rename($path1, $path2) { - $postFix1=(substr($path1,-1,1)==='/')?'/':''; - $postFix2=(substr($path2,-1,1)==='/')?'/':''; + $postFix1=(substr($path1, -1, 1)==='/')?'/':''; + $postFix2=(substr($path2, -1, 1)==='/')?'/':''; $absolutePath1 = OC_Filesystem::normalizePath($this->getAbsolutePath($path1)); $absolutePath2 = OC_Filesystem::normalizePath($this->getAbsolutePath($path2)); if(OC_FileProxy::runPreProxies('rename', $absolutePath1, $absolutePath2) and OC_Filesystem::isValidPath($path2)) { @@ -337,7 +334,7 @@ class OC_FilesystemView { return false; } $run=true; - if( $this->fakeRoot==OC_Filesystem::getRoot() ){ + if( $this->fakeRoot==OC_Filesystem::getRoot() ) { OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_rename, array( @@ -362,7 +359,7 @@ class OC_FilesystemView { $storage1->unlink($this->getInternalPath($path1.$postFix1)); $result = $count>0; } - if( $this->fakeRoot==OC_Filesystem::getRoot() ){ + if( $this->fakeRoot==OC_Filesystem::getRoot() ) { OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_rename, @@ -377,8 +374,8 @@ class OC_FilesystemView { } } public function copy($path1, $path2) { - $postFix1=(substr($path1,-1,1)==='/')?'/':''; - $postFix2=(substr($path2,-1,1)==='/')?'/':''; + $postFix1=(substr($path1, -1, 1)==='/')?'/':''; + $postFix2=(substr($path2, -1, 1)==='/')?'/':''; $absolutePath1 = OC_Filesystem::normalizePath($this->getAbsolutePath($path1)); $absolutePath2 = OC_Filesystem::normalizePath($this->getAbsolutePath($path2)); if(OC_FileProxy::runPreProxies('copy', $absolutePath1, $absolutePath2) and OC_Filesystem::isValidPath($path2)) { @@ -389,7 +386,7 @@ class OC_FilesystemView { return false; } $run=true; - if( $this->fakeRoot==OC_Filesystem::getRoot() ){ + if( $this->fakeRoot==OC_Filesystem::getRoot() ) { OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_copy, @@ -433,7 +430,10 @@ class OC_FilesystemView { $target = $this->fopen($path2.$postFix2, 'w'); $result = OC_Helper::streamCopy($source, $target); } - if( $this->fakeRoot==OC_Filesystem::getRoot() ){ + if( $this->fakeRoot==OC_Filesystem::getRoot() ) { + // If the file to be copied originates within + // the user's data directory + OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_copy, @@ -454,11 +454,33 @@ class OC_FilesystemView { OC_Filesystem::signal_post_write, array( OC_Filesystem::signal_param_path => $path2) ); - } else { // no real copy, file comes from somewhere else, e.g. version rollback -> just update the file cache and the webdav properties without all the other post_write actions - OC_FileCache_Update::update($path2, $this->fakeRoot); + + } else { + // If this is not a normal file copy operation + // and the file originates somewhere else + // (e.g. a version rollback operation), do not + // perform all the other post_write actions + + // Update webdav properties OC_Filesystem::removeETagHook(array("path" => $path2), $this->fakeRoot); + + $splitPath2 = explode( '/', $path2 ); + + // Only cache information about files + // that are being copied from within + // the user files directory. Caching + // other files, like VCS backup files, + // serves no purpose + if ( $splitPath2[1] == 'files' ) { + + OC_FileCache_Update::update($path2, $this->fakeRoot); + + } + } + return $result; + } } } @@ -489,7 +511,7 @@ class OC_FilesystemView { $hooks[]='write'; break; default: - OC_Log::write('core','invalid mode ('.$mode.') for '.$path,OC_Log::ERROR); + OC_Log::write('core', 'invalid mode ('.$mode.') for '.$path, OC_Log::ERROR); } return $this->basicOperation('fopen', $path, $hooks, $mode); @@ -501,7 +523,7 @@ class OC_FilesystemView { $extension=''; $extOffset=strpos($path, '.'); if($extOffset !== false) { - $extension=substr($path, strrpos($path,'.')); + $extension=substr($path, strrpos($path, '.')); } $tmpFile = OC_Helper::tmpFile($extension); file_put_contents($tmpFile, $source); @@ -530,7 +552,7 @@ class OC_FilesystemView { return $this->basicOperation('getMimeType', $path); } public function hash($type, $path, $raw = false) { - $postFix=(substr($path,-1,1)==='/')?'/':''; + $postFix=(substr($path, -1, 1)==='/')?'/':''; $absolutePath = OC_Filesystem::normalizePath($this->getAbsolutePath($path)); if (OC_FileProxy::runPreProxies('hash', $absolutePath) && OC_Filesystem::isValidPath($path)) { $path = $this->getRelativePath($absolutePath); @@ -570,7 +592,7 @@ class OC_FilesystemView { * OC_Filestorage for delegation to a storage backend for execution */ private function basicOperation($operation, $path, $hooks=array(), $extraParam=null) { - $postFix=(substr($path,-1,1)==='/')?'/':''; + $postFix=(substr($path, -1, 1)==='/')?'/':''; $absolutePath = OC_Filesystem::normalizePath($this->getAbsolutePath($path)); if(OC_FileProxy::runPreProxies($operation, $absolutePath, $extraParam) and OC_Filesystem::isValidPath($path)) { $path = $this->getRelativePath($absolutePath); @@ -578,7 +600,7 @@ class OC_FilesystemView { return false; } $internalPath = $this->getInternalPath($path.$postFix); - $run=$this->runHooks($hooks,$path); + $run=$this->runHooks($hooks, $path); if($run and $storage = $this->getStorage($path.$postFix)) { if(!is_null($extraParam)) { $result = $storage->$operation($internalPath, $extraParam); @@ -588,7 +610,7 @@ class OC_FilesystemView { $result = OC_FileProxy::runPostProxies($operation, $this->getAbsolutePath($path), $result); if(OC_Filesystem::$loaded and $this->fakeRoot==OC_Filesystem::getRoot()) { if($operation!='fopen') {//no post hooks for fopen, the file stream is still open - $this->runHooks($hooks,$path, true); + $this->runHooks($hooks, $path, true); } } return $result; @@ -597,7 +619,7 @@ class OC_FilesystemView { return null; } - private function runHooks($hooks,$path,$post=false) { + private function runHooks($hooks, $path, $post=false) { $prefix=($post)?'post_':''; $run=true; if(OC_Filesystem::$loaded and $this->fakeRoot==OC_Filesystem::getRoot()) { diff --git a/lib/group.php b/lib/group.php index a89c6c55e36..ed9482418bd 100644 --- a/lib/group.php +++ b/lib/group.php @@ -139,7 +139,7 @@ class OC_Group { */ public static function inGroup( $uid, $gid ) { foreach(self::$_usedBackends as $backend) { - if($backend->inGroup($uid,$gid)) { + if($backend->inGroup($uid, $gid)) { return true; } } @@ -223,7 +223,7 @@ class OC_Group { public static function getUserGroups( $uid ) { $groups=array(); foreach(self::$_usedBackends as $backend) { - $groups=array_merge($backend->getUserGroups($uid),$groups); + $groups=array_merge($backend->getUserGroups($uid), $groups); } asort($groups); return $groups; diff --git a/lib/group/dummy.php b/lib/group/dummy.php index 8116dcbd675..9516fd52ff8 100644 --- a/lib/group/dummy.php +++ b/lib/group/dummy.php @@ -69,7 +69,7 @@ class OC_Group_Dummy extends OC_Group_Backend { */ public function inGroup($uid, $gid) { if(isset($this->groups[$gid])) { - return (array_search($uid,$this->groups[$gid])!==false); + return (array_search($uid, $this->groups[$gid])!==false); }else{ return false; } @@ -85,7 +85,7 @@ class OC_Group_Dummy extends OC_Group_Backend { */ public function addToGroup($uid, $gid) { if(isset($this->groups[$gid])) { - if(array_search($uid,$this->groups[$gid])===false) { + if(array_search($uid, $this->groups[$gid])===false) { $this->groups[$gid][]=$uid; return true; }else{ @@ -104,9 +104,9 @@ class OC_Group_Dummy extends OC_Group_Backend { * * removes the user from a group. */ - public function removeFromGroup($uid,$gid) { + public function removeFromGroup($uid, $gid) { if(isset($this->groups[$gid])) { - if(($index=array_search($uid,$this->groups[$gid]))!==false) { + if(($index=array_search($uid, $this->groups[$gid]))!==false) { unset($this->groups[$gid][$index]); }else{ return false; @@ -128,7 +128,7 @@ class OC_Group_Dummy extends OC_Group_Backend { $groups=array(); $allGroups=array_keys($this->groups); foreach($allGroups as $group) { - if($this->inGroup($uid,$group)) { + if($this->inGroup($uid, $group)) { $groups[]=$group; } } diff --git a/lib/group/example.php b/lib/group/example.php index 76d12629763..3519b9ed92f 100644 --- a/lib/group/example.php +++ b/lib/group/example.php @@ -73,7 +73,7 @@ abstract class OC_Group_Example { * * removes the user from a group. */ - abstract public static function removeFromGroup($uid,$gid); + abstract public static function removeFromGroup($uid, $gid); /** * @brief Get all groups a user belongs to diff --git a/lib/helper.php b/lib/helper.php index 2da06c4cc45..5dec7fadfb4 100644 --- a/lib/helper.php +++ b/lib/helper.php @@ -29,6 +29,20 @@ class OC_Helper { private static $tmpFiles=array(); /** + * @brief Creates an url using a defined route + * @param $route + * @param $parameters + * @param $args array with param=>value, will be appended to the returned url + * @returns the url + * + * Returns a url to the given app and file. + */ + public static function linkToRoute( $route, $parameters = array() ) { + $urlLinkTo = OC::getRouter()->generate($route, $parameters); + return $urlLinkTo; + } + + /** * @brief Creates an url * @param string $app app * @param string $file file @@ -44,8 +58,8 @@ class OC_Helper { // Check if the app is in the app folder if( $app_path && file_exists( $app_path.'/'.$file )) { if(substr($file, -3) == 'php' || substr($file, -3) == 'css') { - $urlLinkTo = OC::$WEBROOT . '/?app=' . $app; - $urlLinkTo .= ($file!='index.php')?'&getfile=' . urlencode($file):''; + $urlLinkTo = OC::$WEBROOT . '/index.php/apps/' . $app; + $urlLinkTo .= ($file!='index.php') ? '/' . $file : ''; }else{ $urlLinkTo = OC_App::getAppWebPath($app) . '/' . $file; } @@ -189,7 +203,7 @@ class OC_Helper { return OC::$WEBROOT."/core/img/filetypes/$mimetype.png"; } //try only the first part of the filetype - $mimetype=substr($mimetype,0, strpos($mimetype,'-')); + $mimetype=substr($mimetype, 0, strpos($mimetype, '-')); if( file_exists( OC::$SERVERROOT."/core/img/filetypes/$mimetype.png" )) { return OC::$WEBROOT."/core/img/filetypes/$mimetype.png"; } @@ -305,7 +319,7 @@ class OC_Helper { self::copyr("$src/$file", "$dest/$file"); } } - }elseif(file_exists($src)) { + }elseif(file_exists($src) && !OC_Filesystem::isFileBlacklisted($src)) { copy($src, $dest); } } @@ -341,29 +355,29 @@ class OC_Helper { * does NOT work for ownClouds filesystem, use OC_FileSystem::getMimeType instead */ static function getMimeType($path) { - $isWrapped=(strpos($path,'://')!==false) and (substr($path,0,7)=='file://'); + $isWrapped=(strpos($path, '://')!==false) and (substr($path, 0, 7)=='file://'); if (@is_dir($path)) { // directories are easy return "httpd/unix-directory"; } - if(strpos($path,'.')) { + if(strpos($path, '.')) { //try to guess the type by the file extension if(!self::$mimetypes || self::$mimetypes != include 'mimetypes.list.php') { self::$mimetypes=include 'mimetypes.list.php'; } $extension=strtolower(strrchr(basename($path), ".")); - $extension=substr($extension,1);//remove leading . + $extension=substr($extension, 1);//remove leading . $mimeType=(isset(self::$mimetypes[$extension]))?self::$mimetypes[$extension]:'application/octet-stream'; }else{ $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)) { - $info = @strtolower(finfo_file($finfo,$path)); + $info = @strtolower(finfo_file($finfo, $path)); if($info) { - $mimeType=substr($info,0, strpos($info,';')); + $mimeType=substr($info, 0, strpos($info, ';')); } finfo_close($finfo); } @@ -398,8 +412,8 @@ class OC_Helper { return finfo_buffer($finfo, $data); }else{ $tmpFile=OC_Helper::tmpFile(); - $fh=fopen($tmpFile,'wb'); - fwrite($fh,$data,8024); + $fh=fopen($tmpFile, 'wb'); + fwrite($fh, $data, 8024); fclose($fh); $mime=self::getMimeType($tmpFile); unset($tmpFile); @@ -461,16 +475,16 @@ class OC_Helper { $dirs = explode(PATH_SEPARATOR, $path); // WARNING : We have to check if open_basedir is enabled : $obd = ini_get('open_basedir'); - if($obd != "none"){ + if($obd != "none") { $obd_values = explode(PATH_SEPARATOR, $obd); - if(count($obd_values) > 0 and $obd_values[0]){ + if(count($obd_values) > 0 and $obd_values[0]) { // open_basedir is in effect ! // We need to check if the program is in one of these dirs : $dirs = $obd_values; } } - foreach($dirs as $dir){ - foreach($exts as $ext){ + foreach($dirs as $dir) { + foreach($exts as $ext) { if($check_fn("$dir/$name".$ext)) return true; } @@ -484,13 +498,13 @@ class OC_Helper { * @param resource $target * @return int the number of bytes copied */ - public static function streamCopy($source,$target) { + public static function streamCopy($source, $target) { if(!$source or !$target) { return false; } $count=0; while(!feof($source)) { - $count+=fwrite($target, fread($source,8192)); + $count+=fwrite($target, fread($source, 8192)); } return $count; } @@ -504,13 +518,34 @@ class OC_Helper { */ public static function tmpFile($postfix='') { $file=get_temp_dir().'/'.md5(time().rand()).$postfix; - $fh=fopen($file,'w'); + $fh=fopen($file, 'w'); fclose($fh); self::$tmpFiles[]=$file; return $file; } /** + * create a temporary file with an unique filename. It will not be deleted + * automatically + * @param string $postfix + * @return string + * + */ + public static function tmpFileNoClean($postfix='') { + $tmpDirNoClean=get_temp_dir().'/oc-noclean/'; + if (!file_exists($tmpDirNoClean) || !is_dir($tmpDirNoClean)) { + if (file_exists($tmpDirNoClean)) { + unlink($tmpDirNoClean); + } + mkdir($tmpDirNoClean); + } + $file=$tmpDirNoClean.md5(time().rand()).$postfix; + $fh=fopen($file,'w'); + fclose($fh); + return $file; + } + + /** * create a temporary folder with an unique filename * @return string * @@ -546,6 +581,16 @@ class OC_Helper { } /** + * remove all files created by self::tmpFileNoClean + */ + public static function cleanTmpNoClean() { + $tmpDirNoCleanFile=get_temp_dir().'/oc-noclean/'; + if(file_exists($tmpDirNoCleanFile)) { + self::rmdirr($tmpDirNoCleanFile); + } + } + + /** * Adds a suffix to the name in case the file exists * * @param $path @@ -698,4 +743,19 @@ class OC_Helper { return false; } + + /** + * Shortens str to maxlen by replacing characters in the middle with '...', eg. + * ellipsis('a very long string with lots of useless info to make a better example', 14) becomes 'a very ...example' + * @param string $str the string + * @param string $maxlen the maximum length of the result + * @return string with at most maxlen characters + */ + public static function ellipsis($str, $maxlen) { + if (strlen($str) > $maxlen) { + $characters = floor($maxlen / 2); + return substr($str, 0, $characters) . '...' . substr($str, -1 * $characters); + } + return $str; + } } diff --git a/lib/image.php b/lib/image.php index 016d20599b2..2043a452541 100644 --- a/lib/image.php +++ b/lib/image.php @@ -20,32 +20,13 @@ * License along with this library. If not, see <http://www.gnu.org/licenses/>. * */ - -//From user comments at http://dk2.php.net/manual/en/function.exif-imagetype.php -if ( ! function_exists( 'exif_imagetype' ) ) { - function exif_imagetype ( $filename ) { - if ( ( $info = getimagesize( $filename ) ) !== false ) { - return $info[2]; - } - return false; - } -} - -function ellipsis($str, $maxlen) { - if (strlen($str) > $maxlen) { - $characters = floor($maxlen / 2); - return substr($str, 0, $characters) . '...' . substr($str, -1 * $characters); - } - return $str; -} - /** * Class for basic image manipulation - * */ class OC_Image { protected $resource = false; // tmp resource. protected $imagetype = IMAGETYPE_PNG; // Default to png if file type isn't evident. + protected $bit_depth = 24; protected $filepath = null; /** @@ -66,7 +47,7 @@ class OC_Image { public function __construct($imageref = null) { //OC_Log::write('core',__METHOD__.'(): start', OC_Log::DEBUG); if(!extension_loaded('gd') || !function_exists('gd_info')) { - OC_Log::write('core',__METHOD__.'(): GD module not installed', OC_Log::ERROR); + OC_Log::write('core', __METHOD__.'(): GD module not installed', OC_Log::ERROR); return false; } if(!is_null($imageref)) { @@ -112,7 +93,7 @@ class OC_Image { */ public function widthTopLeft() { $o = $this->getOrientation(); - OC_Log::write('core','OC_Image->widthTopLeft() Orientation: '.$o, OC_Log::DEBUG); + OC_Log::write('core', 'OC_Image->widthTopLeft() Orientation: '.$o, OC_Log::DEBUG); switch($o) { case -1: case 1: @@ -137,7 +118,7 @@ class OC_Image { */ public function heightTopLeft() { $o = $this->getOrientation(); - OC_Log::write('core','OC_Image->heightTopLeft() Orientation: '.$o, OC_Log::DEBUG); + OC_Log::write('core', 'OC_Image->heightTopLeft() Orientation: '.$o, OC_Log::DEBUG); switch($o) { case -1: case 1: @@ -172,7 +153,7 @@ class OC_Image { public function save($filepath=null) { if($filepath === null && $this->filepath === null) { - OC_Log::write('core',__METHOD__.'(): called with no path.', OC_Log::ERROR); + OC_Log::write('core', __METHOD__.'(): called with no path.', OC_Log::ERROR); return false; } elseif($filepath === null && $this->filepath !== null) { $filepath = $this->filepath; @@ -188,10 +169,10 @@ 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); + OC_Log::write('core', __METHOD__.'(): File \''.$filepath.'\' is not writable.', OC_Log::ERROR); return false; } } @@ -214,9 +195,11 @@ class OC_Image { $retval = imagexbm($this->resource, $filepath); break; case IMAGETYPE_WBMP: - case IMAGETYPE_BMP: $retval = imagewbmp($this->resource, $filepath); break; + case IMAGETYPE_BMP: + $retval = imagebmp($this->resource, $filepath, $this->bit_depth); + break; default: $retval = imagepng($this->resource, $filepath); } @@ -244,7 +227,7 @@ class OC_Image { ob_start(); $res = imagepng($this->resource); if (!$res) { - OC_Log::write('core','OC_Image->data. Error getting image data.',OC_Log::ERROR); + OC_Log::write('core', 'OC_Image->data. Error getting image data.', OC_Log::ERROR); } return ob_get_clean(); } @@ -263,15 +246,15 @@ class OC_Image { */ public function getOrientation() { if(!is_callable('exif_read_data')) { - OC_Log::write('core','OC_Image->fixOrientation() Exif module not enabled.', OC_Log::DEBUG); + OC_Log::write('core', 'OC_Image->fixOrientation() Exif module not enabled.', OC_Log::DEBUG); return -1; } if(!$this->valid()) { - OC_Log::write('core','OC_Image->fixOrientation() No image loaded.', OC_Log::DEBUG); + OC_Log::write('core', 'OC_Image->fixOrientation() No image loaded.', OC_Log::DEBUG); return -1; } if(is_null($this->filepath) || !is_readable($this->filepath)) { - OC_Log::write('core','OC_Image->fixOrientation() No readable file path set.', OC_Log::DEBUG); + OC_Log::write('core', 'OC_Image->fixOrientation() No readable file path set.', OC_Log::DEBUG); return -1; } $exif = @exif_read_data($this->filepath, 'IFD0'); @@ -291,7 +274,7 @@ class OC_Image { */ public function fixOrientation() { $o = $this->getOrientation(); - OC_Log::write('core','OC_Image->fixOrientation() Orientation: '.$o, OC_Log::DEBUG); + OC_Log::write('core', 'OC_Image->fixOrientation() Orientation: '.$o, OC_Log::DEBUG); $rotate = 0; $flip = false; switch($o) { @@ -341,15 +324,15 @@ class OC_Image { $this->resource = $res; return true; } else { - OC_Log::write('core','OC_Image->fixOrientation() Error during alphasaving.', OC_Log::DEBUG); + OC_Log::write('core', 'OC_Image->fixOrientation() Error during alphasaving.', OC_Log::DEBUG); return false; } } else { - OC_Log::write('core','OC_Image->fixOrientation() Error during alphablending.', OC_Log::DEBUG); + OC_Log::write('core', 'OC_Image->fixOrientation() Error during alphablending.', OC_Log::DEBUG); return false; } } else { - OC_Log::write('core','OC_Image->fixOrientation() Error during oriention fixing.', OC_Log::DEBUG); + OC_Log::write('core', 'OC_Image->fixOrientation() Error during oriention fixing.', OC_Log::DEBUG); return false; } } @@ -365,7 +348,7 @@ class OC_Image { if(get_resource_type($imageref) == 'gd') { $this->resource = $imageref; return $this->resource; - } elseif(in_array(get_resource_type($imageref), array('file','stream'))) { + } elseif(in_array(get_resource_type($imageref), array('file', 'stream'))) { return $this->loadFromFileHandle($imageref); } } elseif($this->loadFromFile($imageref) !== false) { @@ -375,7 +358,7 @@ class OC_Image { } elseif($this->loadFromData($imageref) !== false) { return $this->resource; } else { - OC_Log::write('core',__METHOD__.'(): couldn\'t load anything. Giving up!', OC_Log::DEBUG); + OC_Log::write('core', __METHOD__.'(): couldn\'t load anything. Giving up!', OC_Log::DEBUG); return false; } } @@ -387,7 +370,7 @@ class OC_Image { * @returns An image resource or false on error */ public function loadFromFileHandle($handle) { - OC_Log::write('core',__METHOD__.'(): Trying', OC_Log::DEBUG); + OC_Log::write('core', __METHOD__.'(): Trying', OC_Log::DEBUG); $contents = stream_get_contents($handle); if($this->loadFromData($contents)) { return $this->resource; @@ -402,7 +385,7 @@ class OC_Image { public function loadFromFile($imagepath=false) { if(!is_file($imagepath) || !file_exists($imagepath) || !is_readable($imagepath)) { // Debug output disabled because this method is tried before loadFromBase64? - OC_Log::write('core','OC_Image->loadFromFile, couldn\'t load: '.ellipsis($imagepath, 50), OC_Log::DEBUG); + OC_Log::write('core', 'OC_Image->loadFromFile, couldn\'t load: '.$imagepath, OC_Log::DEBUG); return false; } $itype = exif_imagetype($imagepath); @@ -411,38 +394,40 @@ 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: - case IMAGETYPE_BMP: if (imagetypes() & IMG_WBMP) { $this->resource = imagecreatefromwbmp($imagepath); } else { - OC_Log::write('core','OC_Image->loadFromFile, (W)BMP 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: + $this->resource = $this->imagecreatefrombmp($imagepath); + break; /* case IMAGETYPE_TIFF_II: // (intel byte order) break; @@ -472,7 +457,7 @@ class OC_Image { // this is mostly file created from encrypted file $this->resource = imagecreatefromstring(\OC_Filesystem::file_get_contents(\OC_Filesystem::getLocalPath($imagepath))); $itype = IMAGETYPE_PNG; - OC_Log::write('core','OC_Image->loadFromFile, Default', OC_Log::DEBUG); + OC_Log::write('core', 'OC_Image->loadFromFile, Default', OC_Log::DEBUG); break; } if($this->valid()) { @@ -493,7 +478,7 @@ class OC_Image { } $this->resource = @imagecreatefromstring($str); if(!$this->resource) { - OC_Log::write('core','OC_Image->loadFromData, couldn\'t load', OC_Log::DEBUG); + OC_Log::write('core', 'OC_Image->loadFromData, couldn\'t load', OC_Log::DEBUG); return false; } return $this->resource; @@ -512,7 +497,7 @@ class OC_Image { if($data) { // try to load from string data $this->resource = @imagecreatefromstring($data); if(!$this->resource) { - OC_Log::write('core','OC_Image->loadFromBase64, couldn\'t load', OC_Log::DEBUG); + OC_Log::write('core', 'OC_Image->loadFromBase64, couldn\'t load', OC_Log::DEBUG); return false; } return $this->resource; @@ -522,13 +507,154 @@ class OC_Image { } /** + * Create a new image from file or URL + * @link http://www.programmierer-forum.de/function-imagecreatefrombmp-laeuft-mit-allen-bitraten-t143137.htm + * @version 1.00 + * @param string $filename <p> + * Path to the BMP image. + * </p> + * @return resource an image resource identifier on success, <b>FALSE</b> on errors. + */ + private function imagecreatefrombmp($filename) { + if (!($fh = fopen($filename, 'rb'))) { + trigger_error('imagecreatefrombmp: Can not open ' . $filename, E_USER_WARNING); + return false; + } + // read file header + $meta = unpack('vtype/Vfilesize/Vreserved/Voffset', fread($fh, 14)); + // check for bitmap + if ($meta['type'] != 19778) { + trigger_error('imagecreatefrombmp: ' . $filename . ' is not a bitmap!', E_USER_WARNING); + return false; + } + // read image header + $meta += unpack('Vheadersize/Vwidth/Vheight/vplanes/vbits/Vcompression/Vimagesize/Vxres/Vyres/Vcolors/Vimportant', fread($fh, 40)); + // read additional 16bit header + if ($meta['bits'] == 16) { + $meta += unpack('VrMask/VgMask/VbMask', fread($fh, 12)); + } + // set bytes and padding + $meta['bytes'] = $meta['bits'] / 8; + $this->bit_depth = $meta['bits']; //remember the bit depth for the imagebmp call + $meta['decal'] = 4 - (4 * (($meta['width'] * $meta['bytes'] / 4)- floor($meta['width'] * $meta['bytes'] / 4))); + if ($meta['decal'] == 4) { + $meta['decal'] = 0; + } + // obtain imagesize + if ($meta['imagesize'] < 1) { + $meta['imagesize'] = $meta['filesize'] - $meta['offset']; + // in rare cases filesize is equal to offset so we need to read physical size + if ($meta['imagesize'] < 1) { + $meta['imagesize'] = @filesize($filename) - $meta['offset']; + if ($meta['imagesize'] < 1) { + trigger_error('imagecreatefrombmp: Can not obtain filesize of ' . $filename . '!', E_USER_WARNING); + return false; + } + } + } + // calculate colors + $meta['colors'] = !$meta['colors'] ? pow(2, $meta['bits']) : $meta['colors']; + // read color palette + $palette = array(); + if ($meta['bits'] < 16) { + $palette = unpack('l' . $meta['colors'], fread($fh, $meta['colors'] * 4)); + // in rare cases the color value is signed + if ($palette[1] < 0) { + foreach ($palette as $i => $color) { + $palette[$i] = $color + 16777216; + } + } + } + // create gd image + $im = imagecreatetruecolor($meta['width'], $meta['height']); + $data = fread($fh, $meta['imagesize']); + $p = 0; + $vide = chr(0); + $y = $meta['height'] - 1; + $error = 'imagecreatefrombmp: ' . $filename . ' has not enough data!'; + // loop through the image data beginning with the lower left corner + while ($y >= 0) { + $x = 0; + while ($x < $meta['width']) { + switch ($meta['bits']) { + case 32: + case 24: + if (!($part = substr($data, $p, 3))) { + trigger_error($error, E_USER_WARNING); + return $im; + } + $color = unpack('V', $part . $vide); + break; + case 16: + if (!($part = substr($data, $p, 2))) { + trigger_error($error, E_USER_WARNING); + return $im; + } + $color = unpack('v', $part); + $color[1] = (($color[1] & 0xf800) >> 8) * 65536 + (($color[1] & 0x07e0) >> 3) * 256 + (($color[1] & 0x001f) << 3); + break; + case 8: + $color = unpack('n', $vide . substr($data, $p, 1)); + $color[1] = $palette[ $color[1] + 1 ]; + break; + case 4: + $color = unpack('n', $vide . substr($data, floor($p), 1)); + $color[1] = ($p * 2) % 2 == 0 ? $color[1] >> 4 : $color[1] & 0x0F; + $color[1] = $palette[ $color[1] + 1 ]; + break; + case 1: + $color = unpack('n', $vide . substr($data, floor($p), 1)); + switch (($p * 8) % 8) { + case 0: + $color[1] = $color[1] >> 7; + break; + case 1: + $color[1] = ($color[1] & 0x40) >> 6; + break; + case 2: + $color[1] = ($color[1] & 0x20) >> 5; + break; + case 3: + $color[1] = ($color[1] & 0x10) >> 4; + break; + case 4: + $color[1] = ($color[1] & 0x8) >> 3; + break; + case 5: + $color[1] = ($color[1] & 0x4) >> 2; + break; + case 6: + $color[1] = ($color[1] & 0x2) >> 1; + break; + case 7: + $color[1] = ($color[1] & 0x1); + break; + } + $color[1] = $palette[ $color[1] + 1 ]; + break; + default: + trigger_error('imagecreatefrombmp: ' . $filename . ' has ' . $meta['bits'] . ' bits and this is not supported!', E_USER_WARNING); + return false; + } + imagesetpixel($im, $x, $y, $color[1]); + $x++; + $p += $meta['bytes']; + } + $y--; + $p += $meta['decal']; + } + fclose($fh); + return $im; + } + + /** * @brief Resizes the image preserving ratio. * @param $maxsize The maximum size of either the width or height. * @returns bool */ public function resize($maxsize) { if(!$this->valid()) { - OC_Log::write('core',__METHOD__.'(): No image loaded', OC_Log::ERROR); + OC_Log::write('core', __METHOD__.'(): No image loaded', OC_Log::ERROR); return false; } $width_orig=imageSX($this->resource); @@ -549,7 +675,7 @@ class OC_Image { public function preciseResize($width, $height) { if (!$this->valid()) { - OC_Log::write('core',__METHOD__.'(): No image loaded', OC_Log::ERROR); + OC_Log::write('core', __METHOD__.'(): No image loaded', OC_Log::ERROR); return false; } $width_orig=imageSX($this->resource); @@ -557,14 +683,14 @@ class OC_Image { $process = imagecreatetruecolor($width, $height); if ($process == false) { - OC_Log::write('core',__METHOD__.'(): Error creating true color image',OC_Log::ERROR); + OC_Log::write('core', __METHOD__.'(): Error creating true color image', OC_Log::ERROR); imagedestroy($process); return false; } 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); + OC_Log::write('core', __METHOD__.'(): Error resampling process image '.$width.'x'.$height, OC_Log::ERROR); imagedestroy($process); return false; } @@ -580,7 +706,7 @@ class OC_Image { */ public function centerCrop($size=0) { if(!$this->valid()) { - OC_Log::write('core','OC_Image->centerCrop, No image loaded', OC_Log::ERROR); + OC_Log::write('core', 'OC_Image->centerCrop, No image loaded', OC_Log::ERROR); return false; } $width_orig=imageSX($this->resource); @@ -607,13 +733,13 @@ class OC_Image { } $process = imagecreatetruecolor($targetWidth, $targetHeight); if ($process == false) { - OC_Log::write('core','OC_Image->centerCrop. Error creating true color image',OC_Log::ERROR); + OC_Log::write('core', 'OC_Image->centerCrop. Error creating true color image', OC_Log::ERROR); imagedestroy($process); return false; } 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; } @@ -627,23 +753,23 @@ class OC_Image { * @param $x Horizontal position * @param $y Vertical position * @param $w Width - * @param $h Hight + * @param $h Height * @returns bool for success or failure */ public function crop($x, $y, $w, $h) { if(!$this->valid()) { - OC_Log::write('core',__METHOD__.'(): No image loaded', OC_Log::ERROR); + OC_Log::write('core', __METHOD__.'(): No image loaded', OC_Log::ERROR); return false; } $process = imagecreatetruecolor($w, $h); if ($process == false) { - OC_Log::write('core',__METHOD__.'(): Error creating true color image',OC_Log::ERROR); + OC_Log::write('core', __METHOD__.'(): Error creating true color image', OC_Log::ERROR); imagedestroy($process); return false; } imagecopyresampled($process, $this->resource, 0, 0, $x, $y, $w, $h, $w, $h); if ($process == false) { - OC_Log::write('core',__METHOD__.'(): Error resampling process image '.$w.'x'.$h,OC_Log::ERROR); + OC_Log::write('core', __METHOD__.'(): Error resampling process image '.$w.'x'.$h, OC_Log::ERROR); imagedestroy($process); return false; } @@ -660,7 +786,7 @@ class OC_Image { */ public function fitIn($maxWidth, $maxHeight) { if(!$this->valid()) { - OC_Log::write('core',__METHOD__.'(): No image loaded', OC_Log::ERROR); + OC_Log::write('core', __METHOD__.'(): No image loaded', OC_Log::ERROR); return false; } $width_orig=imageSX($this->resource); @@ -685,3 +811,138 @@ class OC_Image { $this->destroy(); } } +if ( ! function_exists( 'imagebmp') ) { + /** + * Output a BMP image to either the browser or a file + * @link http://www.ugia.cn/wp-data/imagebmp.php + * @author legend <legendsky@hotmail.com> + * @link http://www.programmierer-forum.de/imagebmp-gute-funktion-gefunden-t143716.htm + * @author mgutt <marc@gutt.it> + * @version 1.00 + * @param resource $image + * @param string $filename [optional] <p>The path to save the file to.</p> + * @param int $bit [optional] <p>Bit depth, (default is 24).</p> + * @param int $compression [optional] + * @return bool <b>TRUE</b> on success or <b>FALSE</b> on failure. + */ + function imagebmp($im, $filename='', $bit=24, $compression=0) { + if (!in_array($bit, array(1, 4, 8, 16, 24, 32))) { + $bit = 24; + } + else if ($bit == 32) { + $bit = 24; + } + $bits = pow(2, $bit); + imagetruecolortopalette($im, true, $bits); + $width = imagesx($im); + $height = imagesy($im); + $colors_num = imagecolorstotal($im); + $rgb_quad = ''; + if ($bit <= 8) { + for ($i = 0; $i < $colors_num; $i++) { + $colors = imagecolorsforindex($im, $i); + $rgb_quad .= chr($colors['blue']) . chr($colors['green']) . chr($colors['red']) . "\0"; + } + $bmp_data = ''; + if ($compression == 0 || $bit < 8) { + $compression = 0; + $extra = ''; + $padding = 4 - ceil($width / (8 / $bit)) % 4; + if ($padding % 4 != 0) { + $extra = str_repeat("\0", $padding); + } + for ($j = $height - 1; $j >= 0; $j --) { + $i = 0; + while ($i < $width) { + $bin = 0; + $limit = $width - $i < 8 / $bit ? (8 / $bit - $width + $i) * $bit : 0; + for ($k = 8 - $bit; $k >= $limit; $k -= $bit) { + $index = imagecolorat($im, $i, $j); + $bin |= $index << $k; + $i++; + } + $bmp_data .= chr($bin); + } + $bmp_data .= $extra; + } + } + // RLE8 + else if ($compression == 1 && $bit == 8) { + for ($j = $height - 1; $j >= 0; $j--) { + $last_index = "\0"; + $same_num = 0; + for ($i = 0; $i <= $width; $i++) { + $index = imagecolorat($im, $i, $j); + if ($index !== $last_index || $same_num > 255) { + if ($same_num != 0) { + $bmp_data .= chr($same_num) . chr($last_index); + } + $last_index = $index; + $same_num = 1; + } + else { + $same_num++; + } + } + $bmp_data .= "\0\0"; + } + $bmp_data .= "\0\1"; + } + $size_quad = strlen($rgb_quad); + $size_data = strlen($bmp_data); + } + else { + $extra = ''; + $padding = 4 - ($width * ($bit / 8)) % 4; + if ($padding % 4 != 0) { + $extra = str_repeat("\0", $padding); + } + $bmp_data = ''; + for ($j = $height - 1; $j >= 0; $j--) { + for ($i = 0; $i < $width; $i++) { + $index = imagecolorat($im, $i, $j); + $colors = imagecolorsforindex($im, $index); + if ($bit == 16) { + $bin = 0 << $bit; + $bin |= ($colors['red'] >> 3) << 10; + $bin |= ($colors['green'] >> 3) << 5; + $bin |= $colors['blue'] >> 3; + $bmp_data .= pack("v", $bin); + } + else { + $bmp_data .= pack("c*", $colors['blue'], $colors['green'], $colors['red']); + } + } + $bmp_data .= $extra; + } + $size_quad = 0; + $size_data = strlen($bmp_data); + $colors_num = 0; + } + $file_header = 'BM' . pack('V3', 54 + $size_quad + $size_data, 0, 54 + $size_quad); + $info_header = pack('V3v2V*', 0x28, $width, $height, 1, $bit, $compression, $size_data, 0, 0, $colors_num, 0); + if ($filename != '') { + $fp = fopen($filename, 'wb'); + fwrite($fp, $file_header . $info_header . $rgb_quad . $bmp_data); + fclose($fp); + return true; + } + echo $file_header . $info_header. $rgb_quad . $bmp_data; + return true; + } +} + +if ( ! function_exists( 'exif_imagetype' ) ) { + /** + * Workaround if exif_imagetype does not exist + * @link http://www.php.net/manual/en/function.exif-imagetype.php#80383 + * @param string $filename + * @return string|boolean + */ + function exif_imagetype ( $filename ) { + if ( ( $info = getimagesize( $filename ) ) !== false ) { + return $info[2]; + } + return false; + } +} diff --git a/lib/installer.php b/lib/installer.php index 83d082b804a..7dc8b0cef8d 100644 --- a/lib/installer.php +++ b/lib/installer.php @@ -57,7 +57,7 @@ class OC_Installer{ */ public static function installApp( $data = array()) { if(!isset($data['source'])) { - OC_Log::write('core','No source specified when installing app',OC_Log::ERROR); + OC_Log::write('core', 'No source specified when installing app', OC_Log::ERROR); return false; } @@ -65,13 +65,13 @@ class OC_Installer{ if($data['source']=='http') { $path=OC_Helper::tmpFile(); if(!isset($data['href'])) { - OC_Log::write('core','No href specified when installing app from http',OC_Log::ERROR); + OC_Log::write('core', 'No href specified when installing app from http', OC_Log::ERROR); return false; } - copy($data['href'],$path); + copy($data['href'], $path); }else{ if(!isset($data['path'])) { - OC_Log::write('core','No path specified when installing app from local file',OC_Log::ERROR); + OC_Log::write('core', 'No path specified when installing app from local file', OC_Log::ERROR); return false; } $path=$data['path']; @@ -80,13 +80,13 @@ class OC_Installer{ //detect the archive type $mime=OC_Helper::getMimeType($path); if($mime=='application/zip') { - rename($path,$path.'.zip'); + rename($path, $path.'.zip'); $path.='.zip'; }elseif($mime=='application/x-gzip') { - rename($path,$path.'.tgz'); + rename($path, $path.'.tgz'); $path.='.tgz'; }else{ - OC_Log::write('core','Archives of type '.$mime.' are not supported',OC_Log::ERROR); + OC_Log::write('core', 'Archives of type '.$mime.' are not supported', OC_Log::ERROR); return false; } @@ -97,7 +97,7 @@ class OC_Installer{ if($archive=OC_Archive::open($path)) { $archive->extract($extractDir); } else { - OC_Log::write('core','Failed to open archive when installing app',OC_Log::ERROR); + OC_Log::write('core', 'Failed to open archive when installing app', OC_Log::ERROR); OC_Helper::rmdirr($extractDir); if($data['source']=='http') { unlink($path); @@ -118,7 +118,7 @@ class OC_Installer{ } } if(!is_file($extractDir.'/appinfo/info.xml')) { - OC_Log::write('core','App does not provide an info.xml file',OC_Log::ERROR); + OC_Log::write('core', 'App does not provide an info.xml file', OC_Log::ERROR); OC_Helper::rmdirr($extractDir); if($data['source']=='http') { unlink($path); @@ -127,8 +127,8 @@ class OC_Installer{ } $info=OC_App::getAppInfo($extractDir.'/appinfo/info.xml', true); // check the code for not allowed calls - if(!OC_Installer::checkCode($info['id'],$extractDir)) { - OC_Log::write('core','App can\'t be installed because of not allowed code in the App',OC_Log::ERROR); + if(!OC_Installer::checkCode($info['id'], $extractDir)) { + OC_Log::write('core', 'App can\'t be installed because of not allowed code in the App', OC_Log::ERROR); OC_Helper::rmdirr($extractDir); return false; } @@ -136,14 +136,14 @@ 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 an app with the same id is already installed if(self::isInstalled( $info['id'] )) { - OC_Log::write('core','App already installed',OC_Log::WARN); + OC_Log::write('core', 'App already installed', OC_Log::WARN); OC_Helper::rmdirr($extractDir); if($data['source']=='http') { unlink($path); @@ -154,7 +154,7 @@ class OC_Installer{ $basedir=OC_App::getInstallPath().'/'.$info['id']; //check if the destination directory already exists if(is_dir($basedir)) { - OC_Log::write('core','App directory already exists',OC_Log::WARN); + OC_Log::write('core', 'App directory already exists', OC_Log::WARN); OC_Helper::rmdirr($extractDir); if($data['source']=='http') { unlink($path); @@ -168,14 +168,14 @@ class OC_Installer{ //copy the app to the correct place if(@!mkdir($basedir)) { - OC_Log::write('core','Can\'t create app folder. Please fix permissions. ('.$basedir.')',OC_Log::ERROR); + OC_Log::write('core', 'Can\'t create app folder. Please fix permissions. ('.$basedir.')', OC_Log::ERROR); OC_Helper::rmdirr($extractDir); if($data['source']=='http') { unlink($path); } return false; } - OC_Helper::copyr($extractDir,$basedir); + OC_Helper::copyr($extractDir, $basedir); //remove temporary files OC_Helper::rmdirr($extractDir); @@ -191,8 +191,8 @@ class OC_Installer{ } //set the installed version - OC_Appconfig::setValue($info['id'],'installed_version',OC_App::getAppVersion($info['id'])); - OC_Appconfig::setValue($info['id'],'enabled','no'); + OC_Appconfig::setValue($info['id'], 'installed_version', OC_App::getAppVersion($info['id'])); + OC_Appconfig::setValue($info['id'], 'enabled', 'no'); //set remote/public handelers foreach($info['remote'] as $name=>$path) { @@ -248,7 +248,7 @@ 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 upgradeApp( $data = array()) { // TODO: write function @@ -296,7 +296,7 @@ class OC_Installer{ $enabled = isset($info['default_enable']); if( $enabled ) { OC_Installer::installShippedApp($filename); - OC_Appconfig::setValue($filename,'enabled','yes'); + OC_Appconfig::setValue($filename, 'enabled', 'yes'); } } } @@ -323,7 +323,7 @@ class OC_Installer{ include OC_App::getAppPath($app)."/appinfo/install.php"; } $info=OC_App::getAppInfo($app); - OC_Appconfig::setValue($app,'installed_version',OC_App::getAppVersion($app)); + OC_Appconfig::setValue($app, 'installed_version', OC_App::getAppVersion($app)); //set remote/public handelers foreach($info['remote'] as $name=>$path) { @@ -344,7 +344,7 @@ class OC_Installer{ * @param string $folder the folder of the app to check * @returns true for app is o.k. and false for app is not o.k. */ - public static function checkCode($appname,$folder) { + public static function checkCode($appname, $folder) { $blacklist=array( 'exec(', @@ -360,7 +360,7 @@ 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; } @@ -370,7 +370,7 @@ 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/json.php b/lib/json.php index cc6cee6caff..204430411c0 100644 --- a/lib/json.php +++ b/lib/json.php @@ -72,7 +72,7 @@ class OC_JSON{ public static function checkSubAdminUser() { self::checkLoggedIn(); self::verifyUser(); - if(!OC_Group::inGroup(OC_User::getUser(),'admin') && !OC_SubAdmin::isSubAdmin(OC_User::getUser())) { + if(!OC_Group::inGroup(OC_User::getUser(), 'admin') && !OC_SubAdmin::isSubAdmin(OC_User::getUser())) { $l = OC_L10N::get('lib'); self::error(array( 'data' => array( 'message' => $l->t('Authentication error') ))); exit(); @@ -120,7 +120,7 @@ class OC_JSON{ /** * Encode and print $data in json format */ - public static function encodedPrint($data,$setContentType=true) { + public static function encodedPrint($data, $setContentType=true) { // Disable mimesniffing, don't move this to setContentTypeHeader! header( 'X-Content-Type-Options: nosniff' ); if($setContentType) { diff --git a/lib/l10n.php b/lib/l10n.php index f1a2523c307..b83d8ff86db 100644 --- a/lib/l10n.php +++ b/lib/l10n.php @@ -68,14 +68,14 @@ class OC_L10N{ * get an L10N instance * @return OC_L10N */ - public static function get($app,$lang=null) { + public static function get($app, $lang=null) { if(is_null($lang)) { if(!isset(self::$instances[$app])) { self::$instances[$app]=new OC_L10N($app); } return self::$instances[$app]; }else{ - return new OC_L10N($app,$lang); + return new OC_L10N($app, $lang); } } @@ -167,7 +167,7 @@ class OC_L10N{ * */ public function tA($textArray) { - OC_Log::write('core', 'DEPRECATED: the method tA is deprecated and will be removed soon.',OC_Log::WARN); + OC_Log::write('core', 'DEPRECATED: the method tA is deprecated and will be removed soon.', OC_Log::WARN); $result = array(); foreach($textArray as $key => $text) { $result[$key] = (string)$this->t($text); @@ -294,8 +294,14 @@ class OC_L10N{ } foreach($accepted_languages as $i) { $temp = explode(';', $i); - if(array_search($temp[0], $available) !== false) { - return $temp[0]; + $temp[0] = str_replace('-','_',$temp[0]); + if( ($key = array_search($temp[0], $available)) !== false) { + return $available[$key]; + } + foreach($available as $l) { + if ( $temp[0] == substr($l,0,2) ) { + return $l; + } } } } diff --git a/lib/l10n/ar.php b/lib/l10n/ar.php index 4934e25a5f6..3ae226f04fd 100644 --- a/lib/l10n/ar.php +++ b/lib/l10n/ar.php @@ -4,5 +4,6 @@ "Settings" => "تعديلات", "Users" => "المستخدمين", "Authentication error" => "لم يتم التأكد من الشخصية بنجاح", +"Files" => "الملفات", "Text" => "معلومات إضافية" ); diff --git a/lib/l10n/ca.php b/lib/l10n/ca.php index fa7c27af5a5..b3321ef82e1 100644 --- a/lib/l10n/ca.php +++ b/lib/l10n/ca.php @@ -18,14 +18,17 @@ "seconds ago" => "segons enrere", "1 minute ago" => "fa 1 minut", "%d minutes ago" => "fa %d minuts", +"1 hour ago" => "fa 1 hora", +"%d hours ago" => "fa %d hores", "today" => "avui", "yesterday" => "ahir", "%d days ago" => "fa %d dies", "last month" => "el mes passat", -"months ago" => "mesos enrere", +"%d months ago" => "fa %d mesos", "last year" => "l'any passat", "years ago" => "fa anys", "%s is available. Get <a href=\"%s\">more information</a>" => "%s està disponible. Obtén <a href=\"%s\">més informació</a>", "up to date" => "actualitzat", -"updates check is disabled" => "la comprovació d'actualitzacions està desactivada" +"updates check is disabled" => "la comprovació d'actualitzacions està desactivada", +"Could not find category \"%s\"" => "No s'ha trobat la categoria \"%s\"" ); diff --git a/lib/l10n/cs_CZ.php b/lib/l10n/cs_CZ.php index 72d9b955a41..fa11e886774 100644 --- a/lib/l10n/cs_CZ.php +++ b/lib/l10n/cs_CZ.php @@ -18,14 +18,17 @@ "seconds ago" => "před vteřinami", "1 minute ago" => "před 1 minutou", "%d minutes ago" => "před %d minutami", +"1 hour ago" => "před hodinou", +"%d hours ago" => "před %d hodinami", "today" => "dnes", "yesterday" => "včera", "%d days ago" => "před %d dny", "last month" => "minulý měsíc", -"months ago" => "před měsíci", +"%d months ago" => "Před %d měsíci", "last year" => "loni", "years ago" => "před lety", "%s is available. Get <a href=\"%s\">more information</a>" => "%s je dostupná. Získat <a href=\"%s\">více informací</a>", "up to date" => "aktuální", -"updates check is disabled" => "kontrola aktualizací je vypnuta" +"updates check is disabled" => "kontrola aktualizací je vypnuta", +"Could not find category \"%s\"" => "Nelze nalézt kategorii \"%s\"" ); diff --git a/lib/l10n/da.php b/lib/l10n/da.php index ca4a6c6eca6..7458b329782 100644 --- a/lib/l10n/da.php +++ b/lib/l10n/da.php @@ -21,7 +21,6 @@ "yesterday" => "I går", "%d days ago" => "%d dage siden", "last month" => "Sidste måned", -"months ago" => "måneder siden", "last year" => "Sidste år", "years ago" => "år siden", "%s is available. Get <a href=\"%s\">more information</a>" => "%s er tilgængelig. Få <a href=\"%s\">mere information</a>", diff --git a/lib/l10n/de.php b/lib/l10n/de.php index 4f415e7cbfd..4b77bf7210d 100644 --- a/lib/l10n/de.php +++ b/lib/l10n/de.php @@ -15,17 +15,20 @@ "Files" => "Dateien", "Text" => "Text", "Images" => "Bilder", -"seconds ago" => "Vor wenigen Sekunden", +"seconds ago" => "Gerade eben", "1 minute ago" => "Vor einer Minute", "%d minutes ago" => "Vor %d Minuten", +"1 hour ago" => "Vor einer Stunde", +"%d hours ago" => "Vor %d Stunden", "today" => "Heute", "yesterday" => "Gestern", "%d days ago" => "Vor %d Tag(en)", "last month" => "Letzten Monat", -"months ago" => "Vor wenigen Monaten", +"%d months ago" => "Vor %d Monaten", "last year" => "Letztes Jahr", -"years ago" => "Vor wenigen Jahren", +"years ago" => "Vor Jahren", "%s is available. Get <a href=\"%s\">more information</a>" => "%s ist verfügbar. <a href=\"%s\">Weitere Informationen</a>", "up to date" => "aktuell", -"updates check is disabled" => "Die Update-Überprüfung ist ausgeschaltet" +"updates check is disabled" => "Die Update-Überprüfung ist ausgeschaltet", +"Could not find category \"%s\"" => "Die Kategorie \"%s\" konnte nicht gefunden werden." ); diff --git a/lib/l10n/de_DE.php b/lib/l10n/de_DE.php index 0f08a3ea71d..e9f0f34a0e1 100644 --- a/lib/l10n/de_DE.php +++ b/lib/l10n/de_DE.php @@ -15,17 +15,20 @@ "Files" => "Dateien", "Text" => "Text", "Images" => "Bilder", -"seconds ago" => "Vor wenigen Sekunden", +"seconds ago" => "Gerade eben", "1 minute ago" => "Vor einer Minute", "%d minutes ago" => "Vor %d Minuten", +"1 hour ago" => "Vor einer Stunde", +"%d hours ago" => "Vor %d Stunden", "today" => "Heute", "yesterday" => "Gestern", "%d days ago" => "Vor %d Tag(en)", "last month" => "Letzten Monat", -"months ago" => "Vor wenigen Monaten", +"%d months ago" => "Vor %d Monaten", "last year" => "Letztes Jahr", -"years ago" => "Vor wenigen Jahren", +"years ago" => "Vor Jahren", "%s is available. Get <a href=\"%s\">more information</a>" => "%s ist verfügbar. <a href=\"%s\">Weitere Informationen</a>", "up to date" => "aktuell", -"updates check is disabled" => "Die Update-Überprüfung ist ausgeschaltet" +"updates check is disabled" => "Die Update-Überprüfung ist ausgeschaltet", +"Could not find category \"%s\"" => "Die Kategorie \"%s\" konnte nicht gefunden werden." ); diff --git a/lib/l10n/el.php b/lib/l10n/el.php index e6475ec08aa..315b995ecc9 100644 --- a/lib/l10n/el.php +++ b/lib/l10n/el.php @@ -14,17 +14,21 @@ "Token expired. Please reload page." => "Το αναγνωριστικό έληξε. Παρακαλώ φορτώστε ξανά την σελίδα.", "Files" => "Αρχεία", "Text" => "Κείμενο", +"Images" => "Εικόνες", "seconds ago" => "δευτερόλεπτα πριν", "1 minute ago" => "1 λεπτό πριν", "%d minutes ago" => "%d λεπτά πριν", +"1 hour ago" => "1 ώρα πριν", +"%d hours ago" => "%d ώρες πριν", "today" => "σήμερα", "yesterday" => "χθές", "%d days ago" => "%d ημέρες πριν", "last month" => "τον προηγούμενο μήνα", -"months ago" => "μήνες πριν", +"%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" => "ο έλεγχος ενημερώσεων είναι απενεργοποιημένος" +"updates check is disabled" => "ο έλεγχος ενημερώσεων είναι απενεργοποιημένος", +"Could not find category \"%s\"" => "Αδυναμία εύρεσης κατηγορίας \"%s\"" ); diff --git a/lib/l10n/eo.php b/lib/l10n/eo.php index e569101fc6b..dac11ffe7e6 100644 --- a/lib/l10n/eo.php +++ b/lib/l10n/eo.php @@ -14,17 +14,21 @@ "Token expired. Please reload page." => "Ĵetono eksvalidiĝis. Bonvolu reŝargi la paĝon.", "Files" => "Dosieroj", "Text" => "Teksto", +"Images" => "Bildoj", "seconds ago" => "sekundojn antaŭe", "1 minute ago" => "antaŭ 1 minuto", "%d minutes ago" => "antaŭ %d minutoj", +"1 hour ago" => "antaŭ 1 horo", +"%d hours ago" => "antaŭ %d horoj", "today" => "hodiaŭ", "yesterday" => "hieraŭ", "%d days ago" => "antaŭ %d tagoj", "last month" => "lasta monato", -"months ago" => "monatojn antaŭe", +"%d months ago" => "antaŭ %d monatoj", "last year" => "lasta jaro", "years ago" => "jarojn antaŭe", "%s is available. Get <a href=\"%s\">more information</a>" => "%s haveblas. Ekhavu <a href=\"%s\">pli da informo</a>", "up to date" => "ĝisdata", -"updates check is disabled" => "ĝisdateckontrolo estas malkapabligita" +"updates check is disabled" => "ĝisdateckontrolo estas malkapabligita", +"Could not find category \"%s\"" => "Ne troviĝis kategorio “%s”" ); diff --git a/lib/l10n/es.php b/lib/l10n/es.php index 5064fe2d2f0..f843c42dfd3 100644 --- a/lib/l10n/es.php +++ b/lib/l10n/es.php @@ -14,17 +14,21 @@ "Token expired. Please reload page." => "Token expirado. Por favor, recarga la página.", "Files" => "Archivos", "Text" => "Texto", +"Images" => "Imágenes", "seconds ago" => "hace segundos", "1 minute ago" => "hace 1 minuto", "%d minutes ago" => "hace %d minutos", +"1 hour ago" => "Hace 1 hora", +"%d hours ago" => "Hace %d horas", "today" => "hoy", "yesterday" => "ayer", "%d days ago" => "hace %d días", "last month" => "este mes", -"months ago" => "hace meses", +"%d months ago" => "Hace %d meses", "last year" => "este año", "years ago" => "hace años", "%s is available. Get <a href=\"%s\">more information</a>" => "%s está disponible. Obtén <a href=\"%s\">más información</a>", "up to date" => "actualizado", -"updates check is disabled" => "comprobar actualizaciones está desactivado" +"updates check is disabled" => "comprobar actualizaciones está desactivado", +"Could not find category \"%s\"" => "No puede encontrar la categoria \"%s\"" ); diff --git a/lib/l10n/es_AR.php b/lib/l10n/es_AR.php index a9d9b35b265..2bbffd39e9e 100644 --- a/lib/l10n/es_AR.php +++ b/lib/l10n/es_AR.php @@ -18,14 +18,17 @@ "seconds ago" => "hace unos segundos", "1 minute ago" => "hace 1 minuto", "%d minutes ago" => "hace %d minutos", +"1 hour ago" => "1 hora atrás", +"%d hours ago" => "%d horas atrás", "today" => "hoy", "yesterday" => "ayer", "%d days ago" => "hace %d días", "last month" => "este mes", -"months ago" => "hace meses", +"%d months ago" => "%d meses atrás", "last year" => "este año", "years ago" => "hace años", "%s is available. Get <a href=\"%s\">more information</a>" => "%s está disponible. Conseguí <a href=\"%s\">más información</a>", "up to date" => "actualizado", -"updates check is disabled" => "comprobar actualizaciones está desactivado" +"updates check is disabled" => "comprobar actualizaciones está desactivado", +"Could not find category \"%s\"" => "No fue posible encontrar la categoría \"%s\"" ); diff --git a/lib/l10n/et_EE.php b/lib/l10n/et_EE.php index 52d91d37655..906abf9430a 100644 --- a/lib/l10n/et_EE.php +++ b/lib/l10n/et_EE.php @@ -14,6 +14,7 @@ "Token expired. Please reload page." => "Kontrollkood aegus. Paelun lae leht uuesti.", "Files" => "Failid", "Text" => "Tekst", +"Images" => "Pildid", "seconds ago" => "sekundit tagasi", "1 minute ago" => "1 minut tagasi", "%d minutes ago" => "%d minutit tagasi", @@ -21,7 +22,6 @@ "yesterday" => "eile", "%d days ago" => "%d päeva tagasi", "last month" => "eelmisel kuul", -"months ago" => "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 c6c0e18ea99..5d47ecbda23 100644 --- a/lib/l10n/eu.php +++ b/lib/l10n/eu.php @@ -14,17 +14,21 @@ "Token expired. Please reload page." => "Tokena iraungitu da. Mesedez birkargatu orria.", "Files" => "Fitxategiak", "Text" => "Testua", +"Images" => "Irudiak", "seconds ago" => "orain dela segundu batzuk", "1 minute ago" => "orain dela minutu 1", "%d minutes ago" => "orain dela %d minutu", +"1 hour ago" => "orain dela ordu bat", +"%d hours ago" => "orain dela %d ordu", "today" => "gaur", "yesterday" => "atzo", "%d days ago" => "orain dela %d egun", "last month" => "joan den hilabetea", -"months ago" => "orain dela hilabete batzuk", +"%d months ago" => "orain dela %d hilabete", "last year" => "joan den urtea", "years ago" => "orain dela urte batzuk", "%s is available. Get <a href=\"%s\">more information</a>" => "%s eskuragarri dago. Lortu <a href=\"%s\">informazio gehiago</a>", "up to date" => "eguneratuta", -"updates check is disabled" => "eguneraketen egiaztapena ez dago gaituta" +"updates check is disabled" => "eguneraketen egiaztapena ez dago gaituta", +"Could not find category \"%s\"" => "Ezin da \"%s\" kategoria aurkitu" ); diff --git a/lib/l10n/fa.php b/lib/l10n/fa.php index 31f936b8c98..ce7c7c6e970 100644 --- a/lib/l10n/fa.php +++ b/lib/l10n/fa.php @@ -4,6 +4,7 @@ "Settings" => "تنظیمات", "Users" => "کاربران", "Admin" => "مدیر", +"Authentication error" => "خطا در اعتبار سنجی", "Files" => "پروندهها", "Text" => "متن", "seconds ago" => "ثانیهها پیش", @@ -12,7 +13,6 @@ "today" => "امروز", "yesterday" => "دیروز", "last month" => "ماه قبل", -"months ago" => "ماههای قبل", "last year" => "سال قبل", "years ago" => "سالهای قبل" ); diff --git a/lib/l10n/fi_FI.php b/lib/l10n/fi_FI.php index 47d734ca365..6a5734e978d 100644 --- a/lib/l10n/fi_FI.php +++ b/lib/l10n/fi_FI.php @@ -14,17 +14,21 @@ "Token expired. Please reload page." => "Valtuutus vanheni. Lataa sivu uudelleen.", "Files" => "Tiedostot", "Text" => "Teksti", +"Images" => "Kuvat", "seconds ago" => "sekuntia sitten", "1 minute ago" => "1 minuutti sitten", "%d minutes ago" => "%d minuuttia sitten", +"1 hour ago" => "1 tunti sitten", +"%d hours ago" => "%d tuntia sitten", "today" => "tänään", "yesterday" => "eilen", "%d days ago" => "%d päivää sitten", "last month" => "viime kuussa", -"months ago" => "kuukautta sitten", +"%d months ago" => "%d kuukautta sitten", "last year" => "viime vuonna", "years ago" => "vuotta sitten", "%s is available. Get <a href=\"%s\">more information</a>" => "%s on saatavilla. Lue <a href=\"%s\">lisätietoja</a>", "up to date" => "ajan tasalla", -"updates check is disabled" => "päivitysten tarkistus on pois käytöstä" +"updates check is disabled" => "päivitysten tarkistus on pois käytöstä", +"Could not find category \"%s\"" => "Luokkaa \"%s\" ei löytynyt" ); diff --git a/lib/l10n/fr.php b/lib/l10n/fr.php index ff2356464a2..218c22c1d53 100644 --- a/lib/l10n/fr.php +++ b/lib/l10n/fr.php @@ -18,14 +18,17 @@ "seconds ago" => "à l'instant", "1 minute ago" => "il y a 1 minute", "%d minutes ago" => "il y a %d minutes", +"1 hour ago" => "Il y a une heure", +"%d hours ago" => "Il y a %d heures", "today" => "aujourd'hui", "yesterday" => "hier", "%d days ago" => "il y a %d jours", "last month" => "le mois dernier", -"months ago" => "il y a plusieurs mois", +"%d months ago" => "Il y a %d mois", "last year" => "l'année dernière", "years ago" => "il y a plusieurs années", "%s is available. Get <a href=\"%s\">more information</a>" => "%s est disponible. Obtenez <a href=\"%s\">plus d'informations</a>", "up to date" => "À jour", -"updates check is disabled" => "la vérification des mises à jour est désactivée" +"updates check is disabled" => "la vérification des mises à jour est désactivée", +"Could not find category \"%s\"" => "Impossible de trouver la catégorie \"%s\"" ); diff --git a/lib/l10n/gl.php b/lib/l10n/gl.php index 96368ef03db..1e897959e41 100644 --- a/lib/l10n/gl.php +++ b/lib/l10n/gl.php @@ -1,29 +1,34 @@ <?php $TRANSLATIONS = array( "Help" => "Axuda", -"Personal" => "Personal", -"Settings" => "Preferencias", +"Personal" => "Persoal", +"Settings" => "Configuracións", "Users" => "Usuarios", -"Apps" => "Apps", +"Apps" => "Aplicativos", "Admin" => "Administración", -"ZIP download is turned off." => "Descargas ZIP está deshabilitadas", -"Files need to be downloaded one by one." => "Os ficheiros necesitan ser descargados de un en un", -"Back to Files" => "Voltar a ficheiros", -"Selected files too large to generate zip file." => "Os ficheiros seleccionados son demasiado grandes para xerar un ficheiro ZIP", -"Application is not enabled" => "O aplicativo non está habilitado", -"Authentication error" => "Erro na autenticación", -"Token expired. Please reload page." => "Testemuño caducado. Por favor recargue a páxina.", +"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.", +"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.", +"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", "1 minute ago" => "hai 1 minuto", "%d minutes ago" => "hai %d minutos", +"1 hour ago" => "Vai 1 hora", +"%d hours ago" => "Vai %d horas", "today" => "hoxe", "yesterday" => "onte", "%d days ago" => "hai %d días", "last month" => "último mes", -"months ago" => "meses atrás", +"%d months ago" => "Vai %d meses", "last year" => "último ano", "years ago" => "anos atrás", -"%s is available. Get <a href=\"%s\">more information</a>" => "%s está dispoñible. Obteña <a href=\"%s\">máis información</a>", +"%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", -"updates check is disabled" => "comprobación de actualizacións está deshabilitada" +"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/he.php b/lib/l10n/he.php index 27bcf7655d5..078a731afc0 100644 --- a/lib/l10n/he.php +++ b/lib/l10n/he.php @@ -12,18 +12,23 @@ "Application is not enabled" => "יישומים אינם מופעלים", "Authentication error" => "שגיאת הזדהות", "Token expired. Please reload page." => "פג תוקף. נא לטעון שוב את הדף.", +"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" => "חודש שעבר", -"months ago" => "חודשים", +"%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" => "בדיקת עדכונים מנוטרלת" +"updates check is disabled" => "בדיקת עדכונים מנוטרלת", +"Could not find category \"%s\"" => "לא ניתן למצוא את הקטגוריה „%s“" ); diff --git a/lib/l10n/hr.php b/lib/l10n/hr.php index 0d2a0f46248..62305c15711 100644 --- a/lib/l10n/hr.php +++ b/lib/l10n/hr.php @@ -10,7 +10,6 @@ "today" => "danas", "yesterday" => "jučer", "last month" => "prošli mjesec", -"months ago" => "mjeseci", "last year" => "prošlu godinu", "years ago" => "godina" ); diff --git a/lib/l10n/hu_HU.php b/lib/l10n/hu_HU.php index 3abf96e85a8..63704a978c5 100644 --- a/lib/l10n/hu_HU.php +++ b/lib/l10n/hu_HU.php @@ -21,7 +21,6 @@ "yesterday" => "tegnap", "%d days ago" => "%d évvel ezelőtt", "last month" => "múlt hónapban", -"months ago" => "hónappal ezelőtt", "last year" => "tavaly", "years ago" => "évvel ezelőtt" ); diff --git a/lib/l10n/ia.php b/lib/l10n/ia.php index fb7595d564e..05b2c88e1ed 100644 --- a/lib/l10n/ia.php +++ b/lib/l10n/ia.php @@ -3,5 +3,6 @@ "Personal" => "Personal", "Settings" => "Configurationes", "Users" => "Usatores", +"Files" => "Files", "Text" => "Texto" ); diff --git a/lib/l10n/id.php b/lib/l10n/id.php index 40c4532bdd0..e31b4caf4f5 100644 --- a/lib/l10n/id.php +++ b/lib/l10n/id.php @@ -20,7 +20,6 @@ "yesterday" => "kemarin", "%d days ago" => "%d hari lalu", "last month" => "bulan kemarin", -"months ago" => "beberapa bulan lalu", "last year" => "tahun kemarin", "years ago" => "beberapa tahun lalu", "%s is available. Get <a href=\"%s\">more information</a>" => "%s tersedia. dapatkan <a href=\"%s\"> info lebih lanjut</a>", diff --git a/lib/l10n/it.php b/lib/l10n/it.php index 98ba5973a4a..c0fb0babfb3 100644 --- a/lib/l10n/it.php +++ b/lib/l10n/it.php @@ -18,14 +18,17 @@ "seconds ago" => "secondi fa", "1 minute ago" => "1 minuto fa", "%d minutes ago" => "%d minuti fa", +"1 hour ago" => "1 ora fa", +"%d hours ago" => "%d ore fa", "today" => "oggi", "yesterday" => "ieri", "%d days ago" => "%d giorni fa", "last month" => "il mese scorso", -"months ago" => "mesi fa", +"%d months ago" => "%d mesi fa", "last year" => "l'anno scorso", "years ago" => "anni fa", "%s is available. Get <a href=\"%s\">more information</a>" => "%s è disponibile. Ottieni <a href=\"%s\">ulteriori informazioni</a>", "up to date" => "aggiornato", -"updates check is disabled" => "il controllo degli aggiornamenti è disabilitato" +"updates check is disabled" => "il controllo degli aggiornamenti è disabilitato", +"Could not find category \"%s\"" => "Impossibile trovare la categoria \"%s\"" ); diff --git a/lib/l10n/ja_JP.php b/lib/l10n/ja_JP.php index eb3316b4ab1..854734c9764 100644 --- a/lib/l10n/ja_JP.php +++ b/lib/l10n/ja_JP.php @@ -18,14 +18,17 @@ "seconds ago" => "秒前", "1 minute ago" => "1分前", "%d minutes ago" => "%d 分前", +"1 hour ago" => "1 時間前", +"%d hours ago" => "%d 時間前", "today" => "今日", "yesterday" => "昨日", "%d days ago" => "%d 日前", "last month" => "先月", -"months ago" => "月前", +"%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" => "更新チェックは無効です" +"updates check is disabled" => "更新チェックは無効です", +"Could not find category \"%s\"" => "カテゴリ \"%s\" が見つかりませんでした" ); diff --git a/lib/l10n/ka_GE.php b/lib/l10n/ka_GE.php index 69b72e04130..ff623827216 100644 --- a/lib/l10n/ka_GE.php +++ b/lib/l10n/ka_GE.php @@ -6,13 +6,13 @@ "Apps" => "აპლიკაციები", "Admin" => "ადმინისტრატორი", "Authentication error" => "ავთენტიფიკაციის შეცდომა", +"Files" => "ფაილები", "Text" => "ტექსტი", "seconds ago" => "წამის წინ", "1 minute ago" => "1 წუთის წინ", "today" => "დღეს", "yesterday" => "გუშინ", "last month" => "გასულ თვეში", -"months ago" => "თვის წინ", "last year" => "ბოლო წელს", "years ago" => "წლის წინ", "up to date" => "განახლებულია", diff --git a/lib/l10n/ko.php b/lib/l10n/ko.php index 8648eba63b2..c4716f9f8bd 100644 --- a/lib/l10n/ko.php +++ b/lib/l10n/ko.php @@ -1,8 +1,34 @@ <?php $TRANSLATIONS = array( "Help" => "도움말", -"Personal" => "개인의", +"Personal" => "개인", "Settings" => "설정", "Users" => "사용자", +"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 파일을 생성하기에 너무 큽니다.", +"Application is not enabled" => "앱이 활성화되지 않았습니다", "Authentication error" => "인증 오류", -"Text" => "문자 번호" +"Token expired. Please reload page." => "토큰이 만료되었습니다. 페이지를 새로 고치십시오.", +"Files" => "파일", +"Text" => "텍스트", +"Images" => "그림", +"seconds ago" => "초 전", +"1 minute ago" => "1분 전", +"%d minutes ago" => "%d분 전", +"1 hour ago" => "1시간 전", +"%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/lt_LT.php b/lib/l10n/lt_LT.php index b34c602af2a..b84c155633b 100644 --- a/lib/l10n/lt_LT.php +++ b/lib/l10n/lt_LT.php @@ -21,7 +21,6 @@ "yesterday" => "vakar", "%d days ago" => "prieš %d dienų", "last month" => "praėjusį mėnesį", -"months ago" => "prieš mėnesį", "last year" => "pereitais metais", "years ago" => "prieš metus", "%s is available. Get <a href=\"%s\">more information</a>" => "%s yra galimas. Platesnė <a href=\"%s\">informacija čia</a>", diff --git a/lib/l10n/lv.php b/lib/l10n/lv.php index fb333bd55c3..3330d0e6b70 100644 --- a/lib/l10n/lv.php +++ b/lib/l10n/lv.php @@ -3,5 +3,6 @@ "Personal" => "Personīgi", "Settings" => "Iestatījumi", "Users" => "Lietotāji", -"Authentication error" => "Ielogošanās kļūme" +"Authentication error" => "Ielogošanās kļūme", +"Files" => "Faili" ); diff --git a/lib/l10n/mk.php b/lib/l10n/mk.php index 55e010d61ad..a06073e808a 100644 --- a/lib/l10n/mk.php +++ b/lib/l10n/mk.php @@ -3,5 +3,6 @@ "Personal" => "Лично", "Settings" => "Параметри", "Users" => "Корисници", +"Files" => "Датотеки", "Text" => "Текст" ); diff --git a/lib/l10n/nb_NO.php b/lib/l10n/nb_NO.php index afb80288b53..b01e0979889 100644 --- a/lib/l10n/nb_NO.php +++ b/lib/l10n/nb_NO.php @@ -14,6 +14,7 @@ "Token expired. Please reload page." => "Symbol utløpt. Vennligst last inn siden på nytt.", "Files" => "Filer", "Text" => "Tekst", +"Images" => "Bilder", "seconds ago" => "sekunder siden", "1 minute ago" => "1 minuitt siden", "%d minutes ago" => "%d minutter siden", @@ -21,7 +22,6 @@ "yesterday" => "i går", "%d days ago" => "%d dager siden", "last month" => "forrige måned", -"months ago" => "måneder siden", "last year" => "i fjor", "years ago" => "år siden", "%s is available. Get <a href=\"%s\">more information</a>" => "%s er tilgjengelig. Få <a href=\"%s\">mer informasjon</a>", diff --git a/lib/l10n/nl.php b/lib/l10n/nl.php index e209592d96d..087cf23a627 100644 --- a/lib/l10n/nl.php +++ b/lib/l10n/nl.php @@ -18,14 +18,17 @@ "seconds ago" => "seconden geleden", "1 minute ago" => "1 minuut geleden", "%d minutes ago" => "%d minuten geleden", +"1 hour ago" => "1 uur geleden", +"%d hours ago" => "%d uren geleden", "today" => "vandaag", "yesterday" => "gisteren", "%d days ago" => "%d dagen geleden", "last month" => "vorige maand", -"months ago" => "maanden geleden", +"%d months ago" => "%d maanden geleden", "last year" => "vorig jaar", "years ago" => "jaar geleden", "%s is available. Get <a href=\"%s\">more information</a>" => "%s is beschikbaar. Verkrijg <a href=\"%s\">meer informatie</a>", "up to date" => "bijgewerkt", -"updates check is disabled" => "Meest recente versie controle is uitgeschakeld" +"updates check is disabled" => "Meest recente versie controle is uitgeschakeld", +"Could not find category \"%s\"" => "Kon categorie \"%s\" niet vinden" ); diff --git a/lib/l10n/nn_NO.php b/lib/l10n/nn_NO.php index 56ce733fc19..faf7440320a 100644 --- a/lib/l10n/nn_NO.php +++ b/lib/l10n/nn_NO.php @@ -4,5 +4,6 @@ "Settings" => "Innstillingar", "Users" => "Brukarar", "Authentication error" => "Feil i autentisering", +"Files" => "Filer", "Text" => "Tekst" ); diff --git a/lib/l10n/oc.php b/lib/l10n/oc.php index 2ac89fc74c1..89161393380 100644 --- a/lib/l10n/oc.php +++ b/lib/l10n/oc.php @@ -17,7 +17,6 @@ "yesterday" => "ièr", "%d days ago" => "%d jorns a", "last month" => "mes passat", -"months ago" => "meses a", "last year" => "an passat", "years ago" => "ans a", "up to date" => "a jorn", diff --git a/lib/l10n/pl.php b/lib/l10n/pl.php index 0fb29cbedbf..6f84a328ed9 100644 --- a/lib/l10n/pl.php +++ b/lib/l10n/pl.php @@ -18,14 +18,17 @@ "seconds ago" => "sekund temu", "1 minute ago" => "1 minutę temu", "%d minutes ago" => "%d minut temu", +"1 hour ago" => "1 godzine temu", +"%d hours ago" => "%d godzin temu", "today" => "dzisiaj", "yesterday" => "wczoraj", "%d days ago" => "%d dni temu", "last month" => "ostatni miesiąc", -"months ago" => "miesięcy temu", +"%d months ago" => "%d miesiecy temu", "last year" => "ostatni rok", "years ago" => "lat temu", "%s is available. Get <a href=\"%s\">more information</a>" => "%s jest dostępna. Uzyskaj <a href=\"%s\">więcej informacji</a>", "up to date" => "Aktualne", -"updates check is disabled" => "wybór aktualizacji jest wyłączony" +"updates check is disabled" => "wybór aktualizacji jest wyłączony", +"Could not find category \"%s\"" => "Nie można odnaleźć kategorii \"%s\"" ); diff --git a/lib/l10n/pt_BR.php b/lib/l10n/pt_BR.php index 5eb2348100a..fb7087d35d7 100644 --- a/lib/l10n/pt_BR.php +++ b/lib/l10n/pt_BR.php @@ -14,17 +14,21 @@ "Token expired. Please reload page." => "Token expirou. Por favor recarregue a página.", "Files" => "Arquivos", "Text" => "Texto", +"Images" => "Imagens", "seconds ago" => "segundos atrás", "1 minute ago" => "1 minuto atrás", "%d minutes ago" => "%d minutos atrás", +"1 hour ago" => "1 hora atrás", +"%d hours ago" => "%d horas atrás", "today" => "hoje", "yesterday" => "ontem", "%d days ago" => "%d dias atrás", "last month" => "último mês", -"months ago" => "meses atrás", +"%d months ago" => "%d meses atrás", "last year" => "último ano", "years ago" => "anos atrás", "%s is available. Get <a href=\"%s\">more information</a>" => "%s está disponível. Obtenha <a href=\"%s\">mais informações</a>", "up to date" => "atualizado", -"updates check is disabled" => "checagens de atualização estão desativadas" +"updates check is disabled" => "checagens de atualização estão desativadas", +"Could not find category \"%s\"" => "Impossível localizar categoria \"%s\"" ); diff --git a/lib/l10n/pt_PT.php b/lib/l10n/pt_PT.php index 3809e4bdbcc..84867c4c37c 100644 --- a/lib/l10n/pt_PT.php +++ b/lib/l10n/pt_PT.php @@ -18,14 +18,17 @@ "seconds ago" => "há alguns segundos", "1 minute ago" => "há 1 minuto", "%d minutes ago" => "há %d minutos", +"1 hour ago" => "Há 1 horas", +"%d hours ago" => "Há %d horas", "today" => "hoje", "yesterday" => "ontem", "%d days ago" => "há %d dias", "last month" => "mês passado", -"months ago" => "há meses", +"%d months ago" => "Há %d meses atrás", "last year" => "ano passado", "years ago" => "há anos", "%s is available. Get <a href=\"%s\">more information</a>" => "%s está disponível. Obtenha <a href=\"%s\">mais informação</a>", "up to date" => "actualizado", -"updates check is disabled" => "a verificação de actualizações está desligada" +"updates check is disabled" => "a verificação de actualizações está desligada", +"Could not find category \"%s\"" => "Não foi encontrado a categoria \"%s\"" ); diff --git a/lib/l10n/ro.php b/lib/l10n/ro.php index 818b3f3eeed..27912550e17 100644 --- a/lib/l10n/ro.php +++ b/lib/l10n/ro.php @@ -21,7 +21,6 @@ "yesterday" => "ieri", "%d days ago" => "%d zile în urmă", "last month" => "ultima lună", -"months ago" => "luni în urmă", "last year" => "ultimul an", "years ago" => "ani în urmă", "%s is available. Get <a href=\"%s\">more information</a>" => "%s este disponibil. Vezi <a href=\"%s\">mai multe informații</a>", diff --git a/lib/l10n/ru.php b/lib/l10n/ru.php index c703c30ac44..3ed55f8e9dc 100644 --- a/lib/l10n/ru.php +++ b/lib/l10n/ru.php @@ -14,17 +14,21 @@ "Token expired. Please reload page." => "Токен просрочен. Перезагрузите страницу.", "Files" => "Файлы", "Text" => "Текст", +"Images" => "Изображения", "seconds ago" => "менее минуты", "1 minute ago" => "1 минуту назад", "%d minutes ago" => "%d минут назад", +"1 hour ago" => "час назад", +"%d hours ago" => "%d часов назад", "today" => "сегодня", "yesterday" => "вчера", "%d days ago" => "%d дней назад", "last month" => "в прошлом месяце", -"months ago" => "месяцы назад", +"%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" => "проверка обновлений отключена" +"updates check is disabled" => "проверка обновлений отключена", +"Could not find category \"%s\"" => "Категория \"%s\" не найдена" ); diff --git a/lib/l10n/ru_RU.php b/lib/l10n/ru_RU.php index 36cc85e8d28..ba7d39f9eb0 100644 --- a/lib/l10n/ru_RU.php +++ b/lib/l10n/ru_RU.php @@ -14,17 +14,21 @@ "Token expired. Please reload page." => "Маркер истек. Пожалуйста, перезагрузите страницу.", "Files" => "Файлы", "Text" => "Текст", +"Images" => "Изображения", "seconds ago" => "секунд назад", "1 minute ago" => "1 минуту назад", "%d minutes ago" => "%d минут назад", +"1 hour ago" => "1 час назад", +"%d hours ago" => "%d часов назад", "today" => "сегодня", "yesterday" => "вчера", "%d days ago" => "%d дней назад", "last month" => "в прошлом месяце", -"months ago" => "месяц назад", +"%d months ago" => "%d месяцев назад", "last year" => "в прошлом году", "years ago" => "год назад", "%s is available. Get <a href=\"%s\">more information</a>" => "%s доступно. Получите <a href=\"%s\">more information</a>", "up to date" => "до настоящего времени", -"updates check is disabled" => "Проверка обновлений отключена" +"updates check is disabled" => "Проверка обновлений отключена", +"Could not find category \"%s\"" => "Не удалось найти категорию \"%s\"" ); diff --git a/lib/l10n/si_LK.php b/lib/l10n/si_LK.php index 040c6d2d171..25624acf705 100644 --- a/lib/l10n/si_LK.php +++ b/lib/l10n/si_LK.php @@ -22,7 +22,6 @@ "yesterday" => "ඊයේ", "%d days ago" => "%d දිනකට පෙර", "last month" => "පෙර මාසයේ", -"months ago" => "මාස කීපයකට පෙර", "last year" => "පෙර අවුරුද්දේ", "years ago" => "අවුරුදු කීපයකට පෙර", "%s is available. Get <a href=\"%s\">more information</a>" => "%s යොදාගත හැක. <a href=\"%s\">තව විස්තර</a> ලබාගන්න", diff --git a/lib/l10n/sk_SK.php b/lib/l10n/sk_SK.php index 9d5e4b9013b..98a5b5ca677 100644 --- a/lib/l10n/sk_SK.php +++ b/lib/l10n/sk_SK.php @@ -18,14 +18,17 @@ "seconds ago" => "pred sekundami", "1 minute ago" => "pred 1 minútou", "%d minutes ago" => "pred %d minútami", +"1 hour ago" => "Pred 1 hodinou", +"%d hours ago" => "Pred %d hodinami.", "today" => "dnes", "yesterday" => "včera", "%d days ago" => "pred %d dňami", "last month" => "minulý mesiac", -"months ago" => "pred mesiacmi", +"%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>", "up to date" => "aktuálny", -"updates check is disabled" => "sledovanie aktualizácií je vypnuté" +"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/sl.php b/lib/l10n/sl.php index 3dc8753a436..391d932c4ee 100644 --- a/lib/l10n/sl.php +++ b/lib/l10n/sl.php @@ -14,17 +14,21 @@ "Token expired. Please reload page." => "Žeton je potekel. Spletišče je traba znova naložiti.", "Files" => "Datoteke", "Text" => "Besedilo", +"Images" => "Slike", "seconds ago" => "pred nekaj sekundami", "1 minute ago" => "pred minuto", "%d minutes ago" => "pred %d minutami", +"1 hour ago" => "Pred 1 uro", +"%d hours ago" => "Pred %d urami", "today" => "danes", "yesterday" => "včeraj", "%d days ago" => "pred %d dnevi", "last month" => "prejšnji mesec", -"months ago" => "pred nekaj meseci", +"%d months ago" => "Pred %d meseci", "last year" => "lani", "years ago" => "pred nekaj leti", "%s is available. Get <a href=\"%s\">more information</a>" => "%s je na voljo. <a href=\"%s\">Več podrobnosti.</a>", "up to date" => "posodobljeno", -"updates check is disabled" => "preverjanje za posodobitve je onemogočeno" +"updates check is disabled" => "preverjanje za posodobitve je onemogočeno", +"Could not find category \"%s\"" => "Kategorije \"%s\" ni bilo mogoče najti." ); diff --git a/lib/l10n/sr.php b/lib/l10n/sr.php index cec7ea703fb..2ae7400ba79 100644 --- a/lib/l10n/sr.php +++ b/lib/l10n/sr.php @@ -3,6 +3,32 @@ "Personal" => "Лично", "Settings" => "Подешавања", "Users" => "Корисници", -"Authentication error" => "Грешка при аутентификацији", -"Text" => "Текст" +"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 датотеку.", +"Application is not enabled" => "Апликација није омогућена", +"Authentication error" => "Грешка при провери идентитета", +"Token expired. Please reload page." => "Жетон је истекао. Поново учитајте страницу.", +"Files" => "Датотеке", +"Text" => "Текст", +"Images" => "Слике", +"seconds ago" => "пре неколико секунди", +"1 minute ago" => "пре 1 минут", +"%d minutes ago" => "пре %d минута", +"1 hour ago" => "пре 1 сат", +"%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/sr@latin.php b/lib/l10n/sr@latin.php index c692ec3c4b7..3fc1f61eafa 100644 --- a/lib/l10n/sr@latin.php +++ b/lib/l10n/sr@latin.php @@ -4,5 +4,6 @@ "Settings" => "Podešavanja", "Users" => "Korisnici", "Authentication error" => "Greška pri autentifikaciji", +"Files" => "Fajlovi", "Text" => "Tekst" ); diff --git a/lib/l10n/sv.php b/lib/l10n/sv.php index cc1e09ea76a..5799e2dd1a8 100644 --- a/lib/l10n/sv.php +++ b/lib/l10n/sv.php @@ -18,14 +18,17 @@ "seconds ago" => "sekunder sedan", "1 minute ago" => "1 minut sedan", "%d minutes ago" => "%d minuter sedan", +"1 hour ago" => "1 timme sedan", +"%d hours ago" => "%d timmar sedan", "today" => "idag", "yesterday" => "igår", "%d days ago" => "%d dagar sedan", "last month" => "förra månaden", -"months ago" => "månader sedan", +"%d months ago" => "%d månader sedan", "last year" => "förra året", "years ago" => "år sedan", "%s is available. Get <a href=\"%s\">more information</a>" => "%s finns. Få <a href=\"%s\">mer information</a>", "up to date" => "uppdaterad", -"updates check is disabled" => "uppdateringskontroll är inaktiverad" +"updates check is disabled" => "uppdateringskontroll är inaktiverad", +"Could not find category \"%s\"" => "Kunde inte hitta kategorin \"%s\"" ); diff --git a/lib/l10n/ta_LK.php b/lib/l10n/ta_LK.php index 3c82233cb69..c76394bcb4f 100644 --- a/lib/l10n/ta_LK.php +++ b/lib/l10n/ta_LK.php @@ -18,14 +18,17 @@ "seconds ago" => "செக்கன்களுக்கு முன்", "1 minute ago" => "1 நிமிடத்திற்கு முன் ", "%d minutes ago" => "%d நிமிடங்களுக்கு முன்", +"1 hour ago" => "1 மணித்தியாலத்திற்கு முன்", +"%d hours ago" => "%d மணித்தியாலத்திற்கு முன்", "today" => "இன்று", "yesterday" => "நேற்று", "%d days ago" => "%d நாட்களுக்கு முன்", "last month" => "கடந்த மாதம்", -"months ago" => "மாதங்களுக்கு முன்", +"%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" => "இற்றைப்படுத்தலை சரிபார்ப்பதை செயலற்றதாக்குக" +"updates check is disabled" => "இற்றைப்படுத்தலை சரிபார்ப்பதை செயலற்றதாக்குக", +"Could not find category \"%s\"" => "பிரிவு \"%s\" ஐ கண்டுப்பிடிக்க முடியவில்லை" ); diff --git a/lib/l10n/th_TH.php b/lib/l10n/th_TH.php index 2767ed643a6..75fa02f84b0 100644 --- a/lib/l10n/th_TH.php +++ b/lib/l10n/th_TH.php @@ -14,17 +14,21 @@ "Token expired. Please reload page." => "รหัสยืนยันความถูกต้องหมดอายุแล้ว กรุณาโหลดหน้าเว็บใหม่อีกครั้ง", "Files" => "ไฟล์", "Text" => "ข้อความ", +"Images" => "รูปภาพ", "seconds ago" => "วินาทีที่ผ่านมา", "1 minute ago" => "1 นาทีมาแล้ว", "%d minutes ago" => "%d นาทีที่ผ่านมา", +"1 hour ago" => "1 ชั่วโมงก่อนหน้านี้", +"%d hours ago" => "%d ชั่วโมงก่อนหน้านี้", "today" => "วันนี้", "yesterday" => "เมื่อวานนี้", "%d days ago" => "%d วันที่ผ่านมา", "last month" => "เดือนที่แล้ว", -"months ago" => "เดือนมาแล้ว", +"%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" => "การตรวจสอบชุดอัพเดทถูกปิดใช้งานไว้" +"updates check is disabled" => "การตรวจสอบชุดอัพเดทถูกปิดใช้งานไว้", +"Could not find category \"%s\"" => "ไม่พบหมวดหมู่ \"%s\"" ); diff --git a/lib/l10n/uk.php b/lib/l10n/uk.php index b08f559595b..f5d52f8682d 100644 --- a/lib/l10n/uk.php +++ b/lib/l10n/uk.php @@ -11,17 +11,24 @@ "Selected files too large to generate zip file." => "Вибрані фали завеликі для генерування zip файлу.", "Application is not enabled" => "Додаток не увімкнений", "Authentication error" => "Помилка автентифікації", +"Token expired. Please reload page." => "Строк дії токена скінчився. Будь ласка, перезавантажте сторінку.", "Files" => "Файли", "Text" => "Текст", +"Images" => "Зображення", "seconds ago" => "секунди тому", "1 minute ago" => "1 хвилину тому", "%d minutes ago" => "%d хвилин тому", +"1 hour ago" => "1 годину тому", +"%d hours ago" => "%d годин тому", "today" => "сьогодні", "yesterday" => "вчора", "%d days ago" => "%d днів тому", "last month" => "минулого місяця", -"months ago" => "місяці тому", +"%d months ago" => "%d місяців тому", "last year" => "минулого року", "years ago" => "роки тому", -"updates check is disabled" => "перевірка оновлень відключена" +"%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/vi.php b/lib/l10n/vi.php index cfc39e5b7a8..8b7242ae611 100644 --- a/lib/l10n/vi.php +++ b/lib/l10n/vi.php @@ -18,14 +18,17 @@ "seconds ago" => "1 giây trước", "1 minute ago" => "1 phút trước", "%d minutes ago" => "%d phút trước", +"1 hour ago" => "1 giờ trước", +"%d hours ago" => "%d giờ trước", "today" => "hôm nay", "yesterday" => "hôm qua", "%d days ago" => "%d ngày trước", "last month" => "tháng trước", -"months ago" => "tháng trước", +"%d months ago" => "%d tháng trước", "last year" => "năm trước", "years ago" => "năm trước", "%s is available. Get <a href=\"%s\">more information</a>" => "%s có sẵn. <a href=\"%s\">xem thêm ở đây</a>", "up to date" => "đến ngày", -"updates check is disabled" => "đã TĂT chức năng cập nhật " +"updates check is disabled" => "đã TĂT chức năng cập nhật ", +"Could not find category \"%s\"" => "không thể tìm thấy mục \"%s\"" ); diff --git a/lib/l10n/zh_CN.GB2312.php b/lib/l10n/zh_CN.GB2312.php index adc5c3bc6a9..08975e44598 100644 --- a/lib/l10n/zh_CN.GB2312.php +++ b/lib/l10n/zh_CN.GB2312.php @@ -14,6 +14,7 @@ "Token expired. Please reload page." => "会话过期。请刷新页面。", "Files" => "文件", "Text" => "文本", +"Images" => "图片", "seconds ago" => "秒前", "1 minute ago" => "1 分钟前", "%d minutes ago" => "%d 分钟前", @@ -21,7 +22,6 @@ "yesterday" => "昨天", "%d days ago" => "%d 天前", "last month" => "上个月", -"months ago" => "月前", "last year" => "去年", "years ago" => "年前", "%s is available. Get <a href=\"%s\">more information</a>" => "%s 不可用。获知 <a href=\"%s\">详情</a>", diff --git a/lib/l10n/zh_CN.php b/lib/l10n/zh_CN.php index 6cdfd472510..c3af288b727 100644 --- a/lib/l10n/zh_CN.php +++ b/lib/l10n/zh_CN.php @@ -18,14 +18,17 @@ "seconds ago" => "几秒前", "1 minute ago" => "1分钟前", "%d minutes ago" => "%d 分钟前", +"1 hour ago" => "1小时前", +"%d hours ago" => "%d小时前", "today" => "今天", "yesterday" => "昨天", "%d days ago" => "%d 天前", "last month" => "上月", -"months ago" => "几月前", +"%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" => "检查更新功能被关闭。" +"updates check is disabled" => "检查更新功能被关闭。", +"Could not find category \"%s\"" => "无法找到分类 \"%s\"" ); diff --git a/lib/l10n/zh_TW.php b/lib/l10n/zh_TW.php index 3122695033a..4dbf89c2e0e 100644 --- a/lib/l10n/zh_TW.php +++ b/lib/l10n/zh_TW.php @@ -14,17 +14,21 @@ "Token expired. Please reload page." => "Token 過期. 請重新整理頁面", "Files" => "檔案", "Text" => "文字", +"Images" => "圖片", "seconds ago" => "幾秒前", "1 minute ago" => "1 分鐘前", "%d minutes ago" => "%d 分鐘前", +"1 hour ago" => "1小時之前", +"%d hours ago" => "%d小時之前", "today" => "今天", "yesterday" => "昨天", "%d days ago" => "%d 天前", "last month" => "上個月", -"months ago" => "幾個月前", +"%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" => "檢查更新已停用" +"updates check is disabled" => "檢查更新已停用", +"Could not find category \"%s\"" => "找不到分類-\"%s\"" ); diff --git a/lib/log.php b/lib/log.php index 4bba62cf4b2..e9cededa5c0 100644 --- a/lib/log.php +++ b/lib/log.php @@ -41,23 +41,26 @@ class OC_Log { } //Fatal errors handler - public static function onShutdown(){ + public static function onShutdown() { $error = error_get_last(); if($error) { //ob_end_clean(); self::write('PHP', $error['message'] . ' at ' . $error['file'] . '#' . $error['line'], self::FATAL); } else { - return true; + return true; } } // Uncaught exception handler - public static function onException($exception){ + public static function onException($exception) { self::write('PHP', $exception->getMessage() . ' at ' . $exception->getFile() . '#' . $exception->getLine(), self::FATAL); } //Recoverable errors handler - public static function onError($number, $message, $file, $line){ + public static function onError($number, $message, $file, $line) { + if (error_reporting() === 0) { + return; + } self::write('PHP', $message . ' at ' . $file . '#' . $line, self::WARN); } diff --git a/lib/log/owncloud.php b/lib/log/owncloud.php index d4644163ad5..ec43208d833 100644 --- a/lib/log/owncloud.php +++ b/lib/log/owncloud.php @@ -44,9 +44,9 @@ class OC_Log_Owncloud { * @param int level */ public static function write($app, $message, $level) { - $minLevel=min(OC_Config::getValue( "loglevel", OC_Log::WARN ),OC_Log::ERROR); + $minLevel=min(OC_Config::getValue( "loglevel", OC_Log::WARN ), OC_Log::ERROR); if($level>=$minLevel) { - $entry=array('app'=>$app, 'message'=>$message, 'level'=>$level,'time'=>time()); + $entry=array('app'=>$app, 'message'=>$message, 'level'=>$level, 'time'=>time()); $fh=fopen(self::$logFile, 'a'); fwrite($fh, json_encode($entry)."\n"); fclose($fh); diff --git a/lib/mail.php b/lib/mail.php index 8d30fff9f28..c78fcce88d4 100644 --- a/lib/mail.php +++ b/lib/mail.php @@ -27,7 +27,7 @@ class OC_Mail { * @param string $fromname * @param bool $html */ - 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' ); @@ -56,13 +56,13 @@ class OC_Mail { $mailo->From =$fromaddress; $mailo->FromName = $fromname;; $mailo->Sender =$fromaddress; - $a=explode(' ',$toaddress); + $a=explode(' ', $toaddress); try { foreach($a as $ad) { - $mailo->AddAddress($ad,$toname); + $mailo->AddAddress($ad, $toname); } - if($ccaddress<>'') $mailo->AddCC($ccaddress,$ccname); + if($ccaddress<>'') $mailo->AddCC($ccaddress, $ccname); if($bcc<>'') $mailo->AddBCC($bcc); $mailo->AddReplyTo($fromaddress, $fromname); diff --git a/lib/migrate.php b/lib/migrate.php index 409d77a1a96..2cc0a3067b8 100644 --- a/lib/migrate.php +++ b/lib/migrate.php @@ -91,7 +91,7 @@ class OC_Migrate{ if( self::$exporttype == 'user' ) { // Check user exists self::$uid = is_null($uid) ? OC_User::getUser() : $uid; - if(!OC_User::userExists(self::$uid)){ + if(!OC_User::userExists(self::$uid)) { return json_encode( array( 'success' => false) ); } } @@ -200,7 +200,7 @@ class OC_Migrate{ $scan = scandir( $extractpath ); // Check for export_info.json if( !in_array( 'export_info.json', $scan ) ) { - OC_Log::write( 'migration', 'Invalid import file, export_info.json note found', OC_Log::ERROR ); + OC_Log::write( 'migration', 'Invalid import file, export_info.json not found', OC_Log::ERROR ); return json_encode( array( 'success' => false ) ); } $json = json_decode( file_get_contents( $extractpath . 'export_info.json' ) ); @@ -235,12 +235,19 @@ class OC_Migrate{ return json_encode( array( 'success' => false ) ); } // Copy data - if( !self::copy_r( $extractpath . $json->exporteduser, $datadir . '/' . self::$uid ) ) { - return json_encode( array( 'success' => false ) ); + $userfolder = $extractpath . $json->exporteduser; + $newuserfolder = $datadir . '/' . self::$uid; + foreach(scandir($userfolder) as $file){ + if($file !== '.' && $file !== '..' && is_dir($file)) { + // Then copy the folder over + OC_Helper::copyr($userfolder.'/'.$file, $newuserfolder.'/'.$file); + } } // Import user app data - if( !$appsimported = self::importAppData( $extractpath . $json->exporteduser . '/migration.db', $json, self::$uid ) ) { - return json_encode( array( 'success' => false ) ); + if(file_exists($extractpath . $json->exporteduser . '/migration.db')) { + if( !$appsimported = self::importAppData( $extractpath . $json->exporteduser . '/migration.db', $json, self::$uid ) ) { + return json_encode( array( 'success' => false ) ); + } } // All done! if( !self::unlink_r( $extractpath ) ) { @@ -305,37 +312,6 @@ class OC_Migrate{ } /** - * @brief copies recursively - * @param $path string path to source folder - * @param $dest string path to destination - * @return bool - */ - private static function copy_r( $path, $dest ) { - if( is_dir($path) ) { - @mkdir( $dest ); - $objects = scandir( $path ); - if( sizeof( $objects ) > 0 ) { - foreach( $objects as $file ) { - if( $file == "." || $file == ".." || $file == ".htaccess") - continue; - // go on - if( is_dir( $path . '/' . $file ) ) { - self::copy_r( $path .'/' . $file, $dest . '/' . $file ); - } else { - copy( $path . '/' . $file, $dest . '/' . $file ); - } - } - } - return true; - } - elseif( is_file( $path ) ) { - return copy( $path, $dest ); - } else { - return false; - } - } - - /** * @brief tries to extract the import zip * @param $path string path to the zip * @return string path to extract location (with a trailing slash) or false on failure @@ -611,11 +587,11 @@ class OC_Migrate{ if( file_exists( $db ) ) { // Connect to the db if(!self::connectDB( $db )) { - OC_Log::write('migration','Failed to connect to migration.db',OC_Log::ERROR); + OC_Log::write('migration', 'Failed to connect to migration.db', OC_Log::ERROR); return false; } } else { - OC_Log::write('migration','Migration.db not found at: '.$db, OC_Log::FATAL ); + OC_Log::write('migration', 'Migration.db not found at: '.$db, OC_Log::FATAL ); return false; } diff --git a/lib/migration/content.php b/lib/migration/content.php index 87f8da68c9d..00df62f0c7f 100644 --- a/lib/migration/content.php +++ b/lib/migration/content.php @@ -53,7 +53,7 @@ class OC_Migration_Content{ if( !is_null( $this->db ) ) { // Get db path $db = $this->db->getDatabase(); - if(!in_array($db, $this->tmpfiles)){ + if(!in_array($db, $this->tmpfiles)) { $this->tmpfiles[] = $db; } } @@ -152,7 +152,7 @@ class OC_Migration_Content{ $sql = "INSERT INTO `" . $options['table'] . '` ( `'; $fieldssql = implode( '`, `', $fields ); $sql .= $fieldssql . "` ) VALUES( "; - $valuessql = substr( str_repeat( '?, ', count( $fields ) ),0,-2 ); + $valuessql = substr( str_repeat( '?, ', count( $fields ) ), 0, -2 ); $sql .= $valuessql . " )"; // Make the query $query = $this->prepare( $sql ); @@ -205,7 +205,7 @@ class OC_Migration_Content{ } closedir($dirhandle); } else { - OC_Log::write('admin_export',"Was not able to open directory: " . $dir,OC_Log::ERROR); + OC_Log::write('admin_export', "Was not able to open directory: " . $dir, OC_Log::ERROR); return false; } return true; diff --git a/lib/minimizer.php b/lib/minimizer.php index d50ab0d2397..db522de74dc 100644 --- a/lib/minimizer.php +++ b/lib/minimizer.php @@ -2,14 +2,11 @@ abstract class OC_Minimizer { public function generateETag($files) { - $etag = ''; - sort($files); + $fullpath_files = array(); foreach($files as $file_info) { - $file = $file_info[0] . '/' . $file_info[2]; - $stat = stat($file); - $etag .= $file.$stat['mtime'].$stat['size']; + $fullpath_files[] = $file_info[0] . '/' . $file_info[2]; } - return md5($etag); + return OC_Cache::generateCacheKeyFromFiles($fullpath_files); } abstract public function minimizeFiles($files); @@ -33,6 +30,12 @@ abstract class OC_Minimizer { $cache->set($cache_key.'.gz', $gzout); OC_Response::setETagHeader($etag); } + // on some systems (e.g. SLES 11, but not Ubuntu) mod_deflate and zlib compression will compress the output twice. + // This results in broken core.css and core.js. To avoid it, we switch off zlib compression. + // Since mod_deflate is still active, Apache will compress what needs to be compressed, i.e. no disadvantage. + if(function_exists('apache_get_modules') && ini_get('zlib.output_compression') && in_array('mod_deflate', apache_get_modules())) { + ini_set('zlib.output_compression', 'Off'); + } if ($encoding = OC_Request::acceptGZip()) { header('Content-Encoding: '.$encoding); $out = $gzout; @@ -51,11 +54,11 @@ abstract class OC_Minimizer { } if (!function_exists('gzdecode')) { - function gzdecode($data,$maxlength=null,&$filename='',&$error='') + function gzdecode($data, $maxlength=null, &$filename='', &$error='') { - if (strcmp(substr($data,0,9),"\x1f\x8b\x8\0\0\0\0\0\0")) { + if (strcmp(substr($data, 0, 9),"\x1f\x8b\x8\0\0\0\0\0\0")) { return null; // Not the GZIP format we expect (See RFC 1952) } - return gzinflate(substr($data,10,-8)); + return gzinflate(substr($data, 10, -8)); } } diff --git a/lib/ocs.php b/lib/ocs.php index 001965d45e3..879aaa76687 100644 --- a/lib/ocs.php +++ b/lib/ocs.php @@ -23,6 +23,9 @@ * */ +use Symfony\Component\Routing\Exception\ResourceNotFoundException; +use Symfony\Component\Routing\Exception\MethodNotAllowedException; + /** * Class to handle open collaboration services API requests * @@ -82,6 +85,7 @@ class OC_OCS { echo('internal server error: method not supported'); exit(); } + $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.=OC_OCS::getDebugOutput(); @@ -118,7 +122,7 @@ 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; @@ -138,7 +142,7 @@ class OC_OCS { xmlwriter_write_element($writer, 'status', $status); xmlwriter_write_element($writer, 'statuscode', $statuscode); xmlwriter_write_element($writer, 'message', $message); - if($itemscount<>'') xmlwriter_write_element($writer,'totalitems',$itemscount); + if($itemscount<>'') xmlwriter_write_element($writer, 'totalitems', $itemscount); if(!empty($itemsperpage)) xmlwriter_write_element($writer, 'itemsperpage', $itemsperpage); xmlwriter_end_element($writer); if($dimension=='0') { @@ -153,7 +157,7 @@ class OC_OCS { xmlwriter_end_element($writer); }elseif($dimension=='2') { - xmlwriter_start_element($writer,'data'); + xmlwriter_start_element($writer, 'data'); foreach($data as $entry) { xmlwriter_start_element($writer, $tag); if(!empty($tagattribute)) { @@ -208,14 +212,14 @@ class OC_OCS { } } - public static function toXml($writer,$data,$node) { + public static function toXml($writer, $data, $node) { foreach($data as $key => $value) { if (is_numeric($key)) { $key = $node; } if (is_array($value)) { xmlwriter_start_element($writer, $key); - OC_OCS::toxml($writer,$value, $node); + OC_OCS::toxml($writer, $value, $node); xmlwriter_end_element($writer); }else{ xmlwriter_write_element($writer, $key, $value); @@ -254,28 +258,4 @@ class OC_OCS { return $result; } - /** - * set the quota of a user - * @param string $format - * @param string $user - * @param string $quota - * @return string xml/json - */ - private static function quotaSet($format,$user,$quota) { - $login=OC_OCS::checkpassword(); - if(OC_Group::inGroup($login, 'admin')) { - - // todo - // not yet implemented - // add logic here - error_log('OCS call: user:'.$user.' quota:'.$quota); - - $xml=array(); - $txt=OC_OCS::generatexml($format, 'ok', 100, '', $xml, 'cloud', '', 1, 0, 0); - echo($txt); - }else{ - echo self::generateXml('', 'fail', 300, 'You don´t have permission to access this ressource.'); - } - } - } diff --git a/lib/ocsclient.php b/lib/ocsclient.php index 32c2cfe6e48..12e5026a877 100644 --- a/lib/ocsclient.php +++ b/lib/ocsclient.php @@ -55,20 +55,11 @@ class OC_OCSClient{ * This function calls an OCS server and returns the response. It also sets a sane timeout */ private static function getOCSresponse($url) { - // set a sensible timeout of 10 sec to stay responsive even if the server is down. - $ctx = stream_context_create( - array( - 'http' => array( - 'timeout' => 10 - ) - ) - ); - $data=@file_get_contents($url, 0, $ctx); + $data = \OC_Util::getUrlContent($url); return($data); } - - /** + /** * @brief Get all the categories from the OCS server * @returns array with category ids * @note returns NULL if config value appstoreenabled is set to false @@ -105,18 +96,18 @@ class OC_OCSClient{ * * This function returns a list of all the applications on the OCS server */ - public static function getApplications($categories,$page,$filter) { + public static function getApplications($categories, $page, $filter) { if(OC_Config::getValue('appstoreenabled', true)==false) { return(array()); } if(is_array($categories)) { - $categoriesstring=implode('x',$categories); + $categoriesstring=implode('x', $categories); }else{ $categoriesstring=$categories; } - $version='&version='.implode('x',\OC_Util::getVersion()); + $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; $apps=array(); @@ -162,7 +153,7 @@ class OC_OCSClient{ $xml=OC_OCSClient::getOCSresponse($url); if($xml==false) { - OC_Log::write('core','Unable to parse OCS content',OC_Log::FATAL); + OC_Log::write('core', 'Unable to parse OCS content', OC_Log::FATAL); return null; } $data=simplexml_load_string($xml); @@ -192,7 +183,7 @@ class OC_OCSClient{ * * This function returns an download url for an applications from the OCS server */ - public static function getApplicationDownload($id,$item) { + public static function getApplicationDownload($id, $item) { if(OC_Config::getValue('appstoreenabled', true)==false) { return null; } @@ -200,7 +191,7 @@ class OC_OCSClient{ $xml=OC_OCSClient::getOCSresponse($url); if($xml==false) { - OC_Log::write('core','Unable to parse OCS content',OC_Log::FATAL); + OC_Log::write('core', 'Unable to parse OCS content', OC_Log::FATAL); return null; } $data=simplexml_load_string($xml); @@ -222,40 +213,35 @@ class OC_OCSClient{ * * This function returns a list of all the knowledgebase entries from the OCS server */ - public static function getKnownledgebaseEntries($page,$pagesize,$search='') { - if(OC_Config::getValue('knowledgebaseenabled', true)==false) { - $kbe=array(); - $kbe['totalitems']=0; - return $kbe; - } - - $p= (int) $page; - $s= (int) $pagesize; - if($search<>'') $searchcmd='&search='.urlencode($search); else $searchcmd=''; - $url=OC_OCSClient::getKBURL().'/knowledgebase/data?type=150&page='.$p.'&pagesize='.$s.$searchcmd; - - $kbe=array(); - $xml=OC_OCSClient::getOCSresponse($url); - - if($xml==false) { - OC_Log::write('core','Unable to parse knowledgebase content',OC_Log::FATAL); - return null; - } - $data=simplexml_load_string($xml); - - $tmp=$data->data->content; - for($i = 0; $i < count($tmp); $i++) { - $kb=array(); - $kb['id']=$tmp[$i]->id; - $kb['name']=$tmp[$i]->name; - $kb['description']=$tmp[$i]->description; - $kb['answer']=$tmp[$i]->answer; - $kb['preview1']=$tmp[$i]->smallpreviewpic1; - $kb['detailpage']=$tmp[$i]->detailpage; - $kbe[]=$kb; + public static function getKnownledgebaseEntries($page, $pagesize, $search='') { + $kbe = array('totalitems' => 0); + if(OC_Config::getValue('knowledgebaseenabled', true)) { + $p = (int) $page; + $s = (int) $pagesize; + $searchcmd = ''; + if ($search) { + $searchcmd = '&search='.urlencode($search); + } + $url = OC_OCSClient::getKBURL().'/knowledgebase/data?type=150&page='. $p .'&pagesize='. $s . $searchcmd; + $xml = OC_OCSClient::getOCSresponse($url); + $data = @simplexml_load_string($xml); + if($data===false) { + OC_Log::write('core', 'Unable to parse knowledgebase content', OC_Log::FATAL); + return null; + } + $tmp = $data->data->content; + for($i = 0; $i < count($tmp); $i++) { + $kbe[] = array( + 'id' => $tmp[$i]->id, + 'name' => $tmp[$i]->name, + 'description' => $tmp[$i]->description, + 'answer' => $tmp[$i]->answer, + 'preview1' => $tmp[$i]->smallpreviewpic1, + 'detailpage' => $tmp[$i]->detailpage + ); + } + $kbe['totalitems'] = $data->meta->totalitems; } - $total=$data->meta->totalitems; - $kbe['totalitems']=$total; return $kbe; } diff --git a/lib/preferences.php b/lib/preferences.php index b198a18415c..6270457834d 100644 --- a/lib/preferences.php +++ b/lib/preferences.php @@ -139,7 +139,7 @@ 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` = ?' ); - $values=$query->execute(array($user,$app,$key))->fetchAll(); + $values=$query->execute(array($user, $app, $key))->fetchAll(); $exists=(count($values)>0); if( !$exists ) { diff --git a/lib/public/backgroundjob.php b/lib/public/backgroundjob.php index 24a17836f7f..601046fe691 100644 --- a/lib/public/backgroundjob.php +++ b/lib/public/backgroundjob.php @@ -62,7 +62,7 @@ class BackgroundJob { * @param $type execution type * @return boolean * - * This method sets the execution type of the background jobs. Possible types + * This method sets the execution type of the background jobs. Possible types * are "none", "ajax", "webcron", "cron" */ public static function setExecutionType( $type ) { diff --git a/lib/public/constants.php b/lib/public/constants.php new file mode 100644 index 00000000000..bc979c9031f --- /dev/null +++ b/lib/public/constants.php @@ -0,0 +1,38 @@ +<?php +/** + * ownCloud + * + * @author Thomas Tanghus + * @copyright 2012 Thomas Tanghus (thomas@tanghus.net) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ + +/** + * This file defines common constants used in ownCloud + */ + +namespace OCP; + +/** + * CRUDS permissions. + */ +const PERMISSION_CREATE = 4; +const PERMISSION_READ = 1; +const PERMISSION_UPDATE = 2; +const PERMISSION_DELETE = 8; +const PERMISSION_SHARE = 16; +const PERMISSION_ALL = 31; + diff --git a/lib/public/contacts.php b/lib/public/contacts.php new file mode 100644 index 00000000000..4cf57ed8ff2 --- /dev/null +++ b/lib/public/contacts.php @@ -0,0 +1,186 @@ +<?php +/** + * ownCloud + * + * @author Thomas Müller + * @copyright 2012 Thomas Müller thomas.mueller@tmit.eu + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + */ + +/** + * Public interface of ownCloud for apps to use. + * Contacts Class + * + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes +namespace OCP { + + /** + * This class provides access to the contacts app. Use this class exclusively if you want to access contacts. + * + * Contacts in general will be expressed as an array of key-value-pairs. + * The keys will match the property names defined in https://tools.ietf.org/html/rfc2426#section-1 + * + * Proposed workflow for working with contacts: + * - search for the contacts + * - manipulate the results array + * - createOrUpdate will save the given contacts overwriting the existing data + * + * For updating it is mandatory to keep the id. + * Without an id a new contact will be created. + * + */ + class Contacts { + + /** + * This function is used to search and find contacts within the users address books. + * In case $pattern is empty all contacts will be returned. + * + * Example: + * Following function shows how to search for contacts for the name and the email address. + * + * public static function getMatchingRecipient($term) { + * // The API is not active -> nothing to do + * if (!\OCP\Contacts::isEnabled()) { + * return array(); + * } + * + * $result = \OCP\Contacts::search($term, array('FN', 'EMAIL')); + * $receivers = array(); + * foreach ($result as $r) { + * $id = $r['id']; + * $fn = $r['FN']; + * $email = $r['EMAIL']; + * if (!is_array($email)) { + * $email = array($email); + * } + * + * // loop through all email addresses of this contact + * foreach ($email as $e) { + * $displayName = $fn . " <$e>"; + * $receivers[] = array('id' => $id, + * 'label' => $displayName, + * 'value' => $displayName); + * } + * } + * + * return $receivers; + * } + * + * + * @param string $pattern which should match within the $searchProperties + * @param array $searchProperties defines the properties within the query pattern should match + * @param array $options - for future use. One should always have options! + * @return array of contacts which are arrays of key-value-pairs + */ + public static function search($pattern, $searchProperties = array(), $options = array()) { + $result = array(); + foreach(self::$address_books as $address_book) { + $r = $address_book->search($pattern, $searchProperties, $options); + $result = array_merge($result, $r); + } + + return $result; + } + + /** + * This function can be used to delete the contact identified by the given id + * + * @param object $id the unique identifier to a contact + * @param $address_book_key + * @return bool successful or not + */ + public static function delete($id, $address_book_key) { + if (!array_key_exists($address_book_key, self::$address_books)) + return null; + + $address_book = self::$address_books[$address_book_key]; + if ($address_book->getPermissions() & \OCP\PERMISSION_DELETE) + return null; + + return $address_book->delete($id); + } + + /** + * This function is used to create a new contact if 'id' is not given or not present. + * Otherwise the contact will be updated by replacing the entire data set. + * + * @param array $properties this array if key-value-pairs defines a contact + * @param $address_book_key string to identify the address book in which the contact shall be created or updated + * @return array representing the contact just created or updated + */ + public static function createOrUpdate($properties, $address_book_key) { + + if (!array_key_exists($address_book_key, self::$address_books)) + return null; + + $address_book = self::$address_books[$address_book_key]; + if ($address_book->getPermissions() & \OCP\PERMISSION_CREATE) + return null; + + return $address_book->createOrUpdate($properties); + } + + /** + * Check if contacts are available (e.g. contacts app enabled) + * + * @return bool true if enabled, false if not + */ + public static function isEnabled() { + return !empty(self::$address_books); + } + + /** + * @param \OCP\IAddressBook $address_book + */ + public static function registerAddressBook(\OCP\IAddressBook $address_book) { + self::$address_books[$address_book->getKey()] = $address_book; + } + + /** + * @param \OCP\IAddressBook $address_book + */ + public static function unregisterAddressBook(\OCP\IAddressBook $address_book) { + unset(self::$address_books[$address_book->getKey()]); + } + + /** + * @return array + */ + public static function getAddressBooks() { + $result = array(); + foreach(self::$address_books as $address_book) { + $result[$address_book->getKey()] = $address_book->getDisplayName(); + } + + return $result; + } + + /** + * removes all registered address book instances + */ + public static function clear() { + self::$address_books = array(); + } + + /** + * @var \OCP\IAddressBook[] which holds all registered address books + */ + private static $address_books = array(); + } +} diff --git a/lib/public/db.php b/lib/public/db.php index 6ce62b27ca2..92ff8f93a22 100644 --- a/lib/public/db.php +++ b/lib/public/db.php @@ -42,10 +42,31 @@ class DB { * SQL query via MDB2 prepare(), needs to be execute()'d! */ static public function prepare( $query, $limit=null, $offset=null ) { - return(\OC_DB::prepare($query,$limit,$offset)); + return(\OC_DB::prepare($query, $limit, $offset)); } /** + * @brief Insert a row if a matching row doesn't exists. + * @param $table string The table name (will replace *PREFIX*) to perform the replace on. + * @param $input array + * + * The input array if in the form: + * + * array ( 'id' => array ( 'value' => 6, + * 'key' => true + * ), + * 'name' => array ('value' => 'Stoyan'), + * 'family' => array ('value' => 'Stefanov'), + * 'birth_date' => array ('value' => '1975-06-20') + * ); + * @returns true/false + * + */ + public static function insertIfNotExist($table, $input) { + return(\OC_DB::insertIfNotExist($table, $input)); + } + + /** * @brief gets last value of autoincrement * @param $table string The optional table name (will replace *PREFIX*) and add sequence suffix * @returns id diff --git a/lib/public/iaddressbook.php b/lib/public/iaddressbook.php new file mode 100644 index 00000000000..14943747f48 --- /dev/null +++ b/lib/public/iaddressbook.php @@ -0,0 +1,74 @@ +<?php +/** + * ownCloud + * + * @author Thomas Müller + * @copyright 2012 Thomas Müller thomas.mueller@tmit.eu + * + * 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/>. + * + */ + +// use OCP namespace for all classes that are considered public. +// This means that they should be used by apps instead of the internal ownCloud classes +namespace OCP { + interface IAddressBook { + + /** + * @return string defining the technical unique key + */ + public function getKey(); + + /** + * In comparison to getKey() this function returns a human readable (maybe translated) name + * @return mixed + */ + public function getDisplayName(); + + /** + * @param string $pattern which should match within the $searchProperties + * @param array $searchProperties defines the properties within the query pattern should match + * @param array $options - for future use. One should always have options! + * @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')), +// ); + + /** + * @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' +// ); + + /** + * @return mixed + */ + public function getPermissions(); + + /** + * @param object $id the unique identifier to a contact + * @return bool successful or not + */ + public function delete($id); + } +} diff --git a/lib/public/share.php b/lib/public/share.php index da1c0616390..d736871d244 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -20,15 +20,10 @@ */ namespace OCP; -\OC_Hook::connect('OC_User', 'post_deleteUser', 'OCP\Share', 'post_deleteUser'); -\OC_Hook::connect('OC_User', 'post_addToGroup', 'OCP\Share', 'post_addToGroup'); -\OC_Hook::connect('OC_User', 'post_removeFromGroup', 'OCP\Share', 'post_removeFromGroup'); -\OC_Hook::connect('OC_User', 'post_deleteGroup', 'OCP\Share', 'post_deleteGroup'); - /** * This class provides the ability for apps to share their content between users. * Apps must create a backend class that implements OCP\Share_Backend and register it with this class. -* +* * It provides the following hooks: * - post_shared */ @@ -46,17 +41,15 @@ class Share { * Check if permission is granted with And (&) e.g. Check if delete is granted: if ($permissions & PERMISSION_DELETE) * Remove permissions with And (&) and Not (~) e.g. Remove the update permission: $permissions &= ~PERMISSION_UPDATE * Apps are required to handle permissions on their own, this class only stores and manages the permissions of shares + * @see lib/public/constants.php */ - const PERMISSION_CREATE = 4; - const PERMISSION_READ = 1; - const PERMISSION_UPDATE = 2; - const PERMISSION_DELETE = 8; - const PERMISSION_SHARE = 16; const FORMAT_NONE = -1; const FORMAT_STATUSES = -2; const FORMAT_SOURCES = -3; + const TOKEN_LENGTH = 32; // see db_structure.xml + private static $shareTypeUserAndGroups = -1; private static $shareTypeGroupUserUnique = 2; private static $backends = array(); @@ -144,6 +137,20 @@ class Share { } /** + * @brief Get the item shared by a token + * @param string token + * @return Item + */ + public static function getShareByToken($token) { + $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); + } + return $result->fetchRow(); + } + + /** * @brief Get the shared items of item type owned by the current user * @param string Item type * @param int Format (optional) Format type must be defined by the backend @@ -172,7 +179,7 @@ class Share { * @param int SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK * @param string User or group the item is being shared with * @param int CRUDS permissions - * @return bool Returns true on success or false on failure + * @return bool|string Returns true on success or false on failure, Returns token on success for links */ public static function shareItem($itemType, $itemSource, $shareType, $shareWith, $permissions) { $uidOwner = \OC_User::getUser(); @@ -234,23 +241,33 @@ class Share { $shareWith['users'] = array_diff(\OC_Group::usersInGroup($group), array($uidOwner)); } 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 password is set delete the old link - if (isset($shareWith)) { - self::delete($checkExists['id']); - } else { - $message = 'Sharing '.$itemSource.' failed, because this item is already shared with a link'; - \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR); - throw new \Exception($message); - } + // remember old token + $oldToken = $checkExists['token']; + //delete the old share + self::delete($checkExists['id']); } + // Generate hash of password - same method as user passwords if (isset($shareWith)) { $forcePortable = (CRYPT_BLOWFISH != 1); $hasher = new \PasswordHash(8, $forcePortable); $shareWith = $hasher->HashPassword($shareWith.\OC_Config::getValue('passwordsalt', '')); } - return self::put($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions); + + // Generate token + if (isset($oldToken)) { + $token = $oldToken; + } else { + $token = \OC_Util::generate_random_bytes(self::TOKEN_LENGTH); + } + $result = self::put($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions, null, $token); + if ($result) { + return $token; + } else { + return false; + } } $message = 'Sharing '.$itemSource.' failed, because sharing with links is not allowed'; \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR); @@ -402,7 +419,7 @@ class Share { // Check if permissions were removed if ($item['permissions'] & ~$permissions) { // If share permission is removed all reshares must be deleted - if (($item['permissions'] & self::PERMISSION_SHARE) && (~$permissions & self::PERMISSION_SHARE)) { + if (($item['permissions'] & PERMISSION_SHARE) && (~$permissions & PERMISSION_SHARE)) { self::delete($item['id'], true); } else { $ids = array(); @@ -552,7 +569,7 @@ class Share { $itemTypes = $collectionTypes; } $placeholders = join(',', array_fill(0, count($itemTypes), '?')); - $where .= ' WHERE item_type IN ('.$placeholders.'))'; + $where .= ' WHERE `item_type` IN ('.$placeholders.'))'; $queryArgs = $itemTypes; } else { $where = ' WHERE `item_type` = ?'; @@ -629,7 +646,7 @@ class Share { $queryArgs[] = $item; if ($includeCollections && $collectionTypes) { $placeholders = join(',', array_fill(0, count($collectionTypes), '?')); - $where .= ' OR item_type IN ('.$placeholders.'))'; + $where .= ' OR `item_type` IN ('.$placeholders.'))'; $queryArgs = array_merge($queryArgs, $collectionTypes); } } @@ -658,16 +675,16 @@ class Share { } 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`'; + $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`'; + $select = '`id`, `item_type`, `item_source`, `parent`, `share_type`, `share_with`, `permissions`, `stime`, `file_source`, `expiration`, `token`'; } } else { if ($fileDependent) { if (($itemType == 'file' || $itemType == 'folder') && $format == \OC_Share_Backend_File::FORMAT_FILE_APP || $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`, `name`, `ctime`, `mtime`, `mimetype`, `size`, `encrypted`, `versioned`, `writable`'; } 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`'; + $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 = '*'; @@ -677,6 +694,9 @@ class Share { $root = strlen($root); $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); + } $items = array(); $targets = array(); while ($row = $result->fetchRow()) { @@ -701,7 +721,7 @@ class Share { $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'] & self::PERMISSION_SHARE && (int)$row['permissions'] & self::PERMISSION_SHARE) { + if (~(int)$items[$id]['permissions'] & PERMISSION_SHARE && (int)$row['permissions'] & PERMISSION_SHARE) { $items[$row['id']] = $items[$id]; unset($items[$id]); $id = $row['id']; @@ -836,7 +856,7 @@ 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) { + 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)) { @@ -847,7 +867,7 @@ class Share { throw new \Exception($message); } // Check if share permissions is granted - if ((int)$checkReshare['permissions'] & self::PERMISSION_SHARE) { + if ((int)$checkReshare['permissions'] & PERMISSION_SHARE) { if (~(int)$checkReshare['permissions'] & $permissions) { $message = 'Sharing '.$itemSource.' failed, because the permissions exceed permissions granted to '.$uidOwner; \OC_Log::write('OCP\Share', $message, \OC_Log::ERROR); @@ -893,7 +913,7 @@ 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`) 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); @@ -914,7 +934,7 @@ class Share { } else { $groupFileTarget = null; } - $query->execute(array($itemType, $itemSource, $groupItemTarget, $parent, $shareType, $shareWith['group'], $uidOwner, $permissions, time(), $fileSource, $groupFileTarget)); + $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 @@ -948,11 +968,12 @@ class Share { 'permissions' => $permissions, 'fileSource' => $fileSource, 'fileTarget' => $fileTarget, - 'id' => $parent + 'id' => $parent, + 'token' => $token )); // 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)); + $query->execute(array($itemType, $itemSource, $itemTarget, $parent, self::$shareTypeGroupUserUnique, $uid, $uidOwner, $permissions, time(), $fileSource, $fileTarget, $token)); $id = \OC_DB::insertid('*PREFIX*share'); } } @@ -977,7 +998,7 @@ class Share { } else { $fileTarget = null; } - $query->execute(array($itemType, $itemSource, $itemTarget, $parent, $shareType, $shareWith, $uidOwner, $permissions, time(), $fileSource, $fileTarget)); + $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, @@ -990,7 +1011,8 @@ class Share { 'permissions' => $permissions, 'fileSource' => $fileSource, 'fileTarget' => $fileTarget, - 'id' => $id + 'id' => $id, + 'token' => $token )); if ($parentFolder === true) { $parentFolders['id'] = $id; @@ -1133,7 +1155,7 @@ class Share { $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'] & self::PERMISSION_SHARE) { + if ($duplicateParent['permissions'] & PERMISSION_SHARE) { $query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `parent` = ? WHERE `id` = ?'); $query->execute(array($duplicateParent['id'], $item['id'])); continue; diff --git a/lib/public/user.php b/lib/public/user.php index b320ce8ea0c..9e50115ab70 100644 --- a/lib/public/user.php +++ b/lib/public/user.php @@ -65,12 +65,12 @@ class User { /** * @brief check if a user exists * @param string $uid the username + * @param string $excludingBackend (default none) * @return boolean */ - public static function userExists( $uid ) { - return \OC_USER::userExists( $uid ); + public static function userExists( $uid, $excludingBackend = null ) { + return \OC_USER::userExists( $uid, $excludingBackend ); } - /** * @brief Loggs the user out including all the session data * @returns true diff --git a/lib/public/util.php b/lib/public/util.php index 38da7e82171..7b5b1abbded 100644 --- a/lib/public/util.php +++ b/lib/public/util.php @@ -61,7 +61,7 @@ class Util { */ 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=0, $altbody='', $ccaddress='', $ccname='', $bcc=''); + \OC_MAIL::send($toaddress, $toname, $subject, $mailtext, $fromaddress, $fromname, $html = 0, $altbody = '', $ccaddress = '', $ccname = '', $bcc = ''); } /** @@ -107,8 +107,8 @@ class Util { * @param int timestamp $timestamp * @param bool dateOnly option to ommit time from the result */ - public static function formatDate( $timestamp,$dateOnly=false) { - return(\OC_Util::formatDate( $timestamp,$dateOnly )); + public static function formatDate( $timestamp, $dateOnly=false) { + return(\OC_Util::formatDate( $timestamp, $dateOnly )); } /** diff --git a/lib/request.php b/lib/request.php index 87262d98625..c975c84a711 100644..100755 --- a/lib/request.php +++ b/lib/request.php @@ -18,6 +18,9 @@ class OC_Request { if(OC::$CLI) { return 'localhost'; } + if(OC_Config::getValue('overwritehost', '')<>''){ + return OC_Config::getValue('overwritehost'); + } if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) { if (strpos($_SERVER['HTTP_X_FORWARDED_HOST'], ",") !== false) { $host = trim(array_pop(explode(",", $_SERVER['HTTP_X_FORWARDED_HOST']))); @@ -40,6 +43,9 @@ class OC_Request { * Returns the server protocol. It respects reverse proxy servers and load balancers */ public static function serverProtocol() { + if(OC_Config::getValue('overwriteprotocol', '')<>''){ + return OC_Config::getValue('overwriteprotocol'); + } if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) { $proto = strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']); }else{ @@ -63,7 +69,7 @@ class OC_Request { $path_info = substr($_SERVER['REQUEST_URI'], strlen($_SERVER['SCRIPT_NAME'])); // 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')); + $encoding = mb_detect_encoding($path_info, array('UTF-8', 'ISO-8859-1')); switch($encoding) { @@ -98,7 +104,7 @@ class OC_Request { $HTTP_ACCEPT_ENCODING = $_SERVER["HTTP_ACCEPT_ENCODING"]; if( strpos($HTTP_ACCEPT_ENCODING, 'x-gzip') !== false ) return 'x-gzip'; - else if( strpos($HTTP_ACCEPT_ENCODING,'gzip') !== false ) + else if( strpos($HTTP_ACCEPT_ENCODING, 'gzip') !== false ) return 'gzip'; return false; } diff --git a/lib/route.php b/lib/route.php index df3a18e844f..5901717c094 100644 --- a/lib/route.php +++ b/lib/route.php @@ -9,31 +9,53 @@ use Symfony\Component\Routing\Route; class OC_Route extends Route { + /** + * Specify the method when this route is to be used + * + * @param string $method HTTP method (uppercase) + */ public function method($method) { $this->setRequirement('_method', strtoupper($method)); return $this; } + /** + * Specify POST as the method to use with this route + */ public function post() { $this->method('POST'); return $this; } + /** + * Specify GET as the method to use with this route + */ public function get() { $this->method('GET'); return $this; } + /** + * Specify PUT as the method to use with this route + */ public function put() { $this->method('PUT'); return $this; } + /** + * Specify DELETE as the method to use with this route + */ public function delete() { $this->method('DELETE'); return $this; } + /** + * Defaults to use for this route + * + * @param array $defaults The defaults + */ public function defaults($defaults) { $action = $this->getDefault('action'); $this->setDefaults($defaults); @@ -44,16 +66,31 @@ class OC_Route extends Route { return $this; } + /** + * Requirements for this route + * + * @param array $requirements The requirements + */ public function requirements($requirements) { $method = $this->getRequirement('_method'); $this->setRequirements($requirements); if (isset($requirements['_method'])) { $method = $requirements['_method']; } - $this->method($method); + if ($method) { + $this->method($method); + } return $this; } + /** + * The action to execute when this route matches + * @param string|callable $class the class or a callable + * @param string $function the function to use with the class + * + * This function is called with $class set to a callable or + * to the class with $function + */ public function action($class, $function = null) { $action = array($class, $function); if (is_null($function)) { @@ -62,4 +99,18 @@ class OC_Route extends Route { $this->setDefault('action', $action); return $this; } + + /** + * The action to execute when this route matches, includes a file like + * it is called directly + * @param $file + */ + public function actionInclude($file) { + $function = create_function('$param', + 'unset($param["_route"]);' + .'$_GET=array_merge($_GET, $param);' + .'unset($param);' + .'require_once "'.$file.'";'); + $this->action($function); + } } diff --git a/lib/router.php b/lib/router.php index 12cd55df414..27e14c38abf 100644 --- a/lib/router.php +++ b/lib/router.php @@ -7,20 +7,58 @@ */ use Symfony\Component\Routing\Matcher\UrlMatcher; +use Symfony\Component\Routing\Generator\UrlGenerator; use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\RouteCollection; //use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\Exception\ResourceNotFoundException; class OC_Router { protected $collections = array(); protected $collection = null; protected $root = null; + protected $generator = null; + protected $routing_files; + protected $cache_key; + + public function __construct() { + $baseUrl = OC_Helper::linkTo('', 'index.php'); + $method = $_SERVER['REQUEST_METHOD']; + $host = OC_Request::serverHost(); + $schema = OC_Request::serverProtocol(); + $this->context = new RequestContext($baseUrl, $method, $host, $schema); + // TODO cache + $this->root = $this->getCollection('root'); + } + + public function getRoutingFiles() { + if (!isset($this->routing_files)) { + $this->routing_files = array(); + foreach(OC_APP::getEnabledApps() as $app) { + $file = OC_App::getAppPath($app).'/appinfo/routes.php'; + if(file_exists($file)) { + $this->routing_files[$app] = $file; + } + } + } + return $this->routing_files; + } + + public function getCacheKey() { + if (!isset($this->cache_key)) { + $files = $this->getRoutingFiles(); + $files[] = 'settings/routes.php'; + $files[] = 'core/routes.php'; + $this->cache_key = OC_Cache::generateCacheKeyFromFiles($files); + } + return $this->cache_key; + } + /** * loads the api routes */ public function loadRoutes() { + // TODO cache $this->root = $this->getCollection('root'); foreach(OC_APP::getEnabledApps() as $app){ @@ -36,6 +74,17 @@ class OC_Router { require_once(OC::$SERVERROOT.'/ocs/routes.php'); $collection = $this->getCollection('ocs'); $this->root->addCollection($collection, '/ocs'); + + foreach($this->getRoutingFiles() as $app => $file) { + $this->useCollection($app); + require_once $file; + $collection = $this->getCollection($app); + $this->root->addCollection($collection, '/apps/'.$app); + } + $this->useCollection('root'); + require_once 'settings/routes.php'; + require_once 'core/routes.php'; + } protected function getCollection($name) { @@ -45,19 +94,36 @@ class OC_Router { return $this->collections[$name]; } + /** + * Sets the collection to use for adding routes + * + * @param string $name Name of the colletion to use. + */ public function useCollection($name) { $this->collection = $this->getCollection($name); } + /** + * Create a OC_Route. + * + * @param string $name Name of the route to create. + * @param string $pattern The pattern to match + * @param array $defaults An array of default parameter values + * @param array $requirements An array of requirements for parameters (regexes) + */ public function create($name, $pattern, array $defaults = array(), array $requirements = array()) { $route = new OC_Route($pattern, $defaults, $requirements); $this->collection->add($name, $route); return $route; } - public function match($url) { - $context = new RequestContext($_SERVER['REQUEST_URI'], $_SERVER['REQUEST_METHOD']); - $matcher = new UrlMatcher($this->root, $context); + /** + * Find the route matching $url. + * + * @param string $url The url to find + */ + public function match($url) { + $matcher = new UrlMatcher($this->root, $this->context); $parameters = $matcher->match($url); if (isset($parameters['action'])) { $action = $parameters['action']; @@ -68,9 +134,58 @@ class OC_Router { unset($parameters['action']); call_user_func($action, $parameters); } elseif (isset($parameters['file'])) { - include ($parameters['file']); + include $parameters['file']; } else { throw new Exception('no action available'); } } + + /** + * Get the url generator + * + */ + public function getGenerator() + { + if (null !== $this->generator) { + return $this->generator; + } + + return $this->generator = new UrlGenerator($this->root, $this->context); + } + + /** + * Generate url based on $name and $parameters + * + * @param string $name Name of the route to use. + * @param array $parameters Parameters for the route + */ + public function generate($name, $parameters = array(), $absolute = false) + { + return $this->getGenerator()->generate($name, $parameters, $absolute); + } + + /** + * Generate JSON response for routing in javascript + */ + public static function JSRoutes() + { + $router = OC::getRouter(); + + $etag = $router->getCacheKey(); + OC_Response::enableCaching(); + OC_Response::setETagHeader($etag); + + $root = $router->getCollection('root'); + $routes = array(); + foreach($root->all() as $name => $route) { + $compiled_route = $route->compile(); + $defaults = $route->getDefaults(); + unset($defaults['action']); + $routes[$name] = array( + 'tokens' => $compiled_route->getTokens(), + 'defaults' => $defaults, + ); + } + OCP\JSON::success ( array( 'data' => $routes ) ); + } } diff --git a/lib/search.php b/lib/search.php index 0b6ad050024..3c3378ad13c 100644 --- a/lib/search.php +++ b/lib/search.php @@ -40,8 +40,8 @@ class OC_Search{ * register a new search provider to be used * @param string $provider class name of a OC_Search_Provider */ - public static function registerProvider($class,$options=array()) { - self::$registeredProviders[]=array('class'=>$class,'options'=>$options); + public static function registerProvider($class, $options=array()) { + self::$registeredProviders[]=array('class'=>$class, 'options'=>$options); } /** diff --git a/lib/search/provider/file.php b/lib/search/provider/file.php index 0d4b332b792..ea536ef77de 100644 --- a/lib/search/provider/file.php +++ b/lib/search/provider/file.php @@ -16,7 +16,7 @@ class OC_Search_Provider_File extends OC_Search_Provider{ $link = OC_Helper::linkTo( 'files', 'index.php', array('dir' => $path)); $type = (string)$l->t('Files'); }else{ - $link = OC_Helper::linkTo( 'files', 'download.php', array('file' => $path)); + $link = OC_Helper::linkToRoute( 'download', array('file' => $path)); $mimeBase = $fileData['mimepart']; switch($mimeBase) { case 'audio': diff --git a/lib/search/result.php b/lib/search/result.php index 63b5cfabce6..08beaea151c 100644 --- a/lib/search/result.php +++ b/lib/search/result.php @@ -15,7 +15,7 @@ class OC_Search_Result{ * @param string $link link for the result * @param string $type the type of result as human readable string ('File', 'Music', etc) */ - public function __construct($name,$text,$link,$type) { + public function __construct($name, $text, $link, $type) { $this->name=$name; $this->text=$text; $this->link=$link; diff --git a/lib/setup.php b/lib/setup.php index a072e00f91e..fdd10be6824 100644 --- a/lib/setup.php +++ b/lib/setup.php @@ -1,45 +1,5 @@ <?php -$hasSQLite = (is_callable('sqlite_open') or class_exists('SQLite3')); -$hasMySQL = is_callable('mysql_connect'); -$hasPostgreSQL = is_callable('pg_connect'); -$hasOracle = is_callable('oci_connect'); -$datadir = OC_Config::getValue('datadirectory', OC::$SERVERROOT.'/data'); - -// Test if .htaccess is working -$content = "deny from all"; -file_put_contents(OC::$SERVERROOT.'/data/.htaccess', $content); - -$opts = array( - 'hasSQLite' => $hasSQLite, - 'hasMySQL' => $hasMySQL, - 'hasPostgreSQL' => $hasPostgreSQL, - 'hasOracle' => $hasOracle, - 'directory' => $datadir, - 'secureRNG' => OC_Util::secureRNG_available(), - 'htaccessWorking' => OC_Util::ishtaccessworking(), - 'errors' => array(), -); - -if(isset($_POST['install']) AND $_POST['install']=='true') { - // We have to launch the installation process : - $e = OC_Setup::install($_POST); - $errors = array('errors' => $e); - - if(count($e) > 0) { - //OC_Template::printGuestPage("", "error", array("errors" => $errors)); - $options = array_merge($_POST, $opts, $errors); - OC_Template::printGuestPage("", "installation", $options); - } - else { - header("Location: ".OC::$WEBROOT.'/'); - exit(); - } -} -else { - OC_Template::printGuestPage("", "installation", $opts); -} - class OC_Setup { public static function install($options) { $error = array(); @@ -70,6 +30,9 @@ class OC_Setup { if(empty($options['dbname'])) { $error[] = "$dbprettyname enter the database name."; } + if(substr_count($options['dbname'], '.') >= 1) { + $error[] = "$dbprettyname you may not use dots in the database name"; + } if($dbtype != 'oci' && empty($options['dbhost'])) { $error[] = "$dbprettyname set the database host."; } @@ -92,7 +55,7 @@ class OC_Setup { //write the config file OC_Config::setValue('datadirectory', $datadir); OC_Config::setValue('dbtype', $dbtype); - OC_Config::setValue('version', implode('.',OC_Util::getVersion())); + OC_Config::setValue('version', implode('.', OC_Util::getVersion())); if($dbtype == 'mysql') { $dbuser = $options['dbuser']; $dbpass = $options['dbpass']; @@ -199,7 +162,7 @@ class OC_Setup { return $error; } - private static function setupMySQLDatabase($dbhost, $dbuser, $dbpass, $dbtableprefix, $username) { + private static function setupMySQLDatabase($dbhost, $dbuser, $dbpass, $dbname, $dbtableprefix, $username) { //check if the database user has admin right $connection = @mysql_connect($dbhost, $dbuser, $dbpass); if(!$connection) { @@ -215,7 +178,7 @@ class OC_Setup { $dbusername=substr('oc_'.$username, 0, 16); if($dbusername!=$oldUser) { //hash the password so we don't need to store the admin config in the config file - $dbpassword=md5(time().$password); + $dbpassword=md5(time().$dbpass); self::createDBUser($dbusername, $dbpassword, $connection); @@ -248,7 +211,7 @@ class OC_Setup { mysql_close($connection); } - private static function createMySQLDatabase($name,$user,$connection) { + private static function createMySQLDatabase($name, $user, $connection) { //we cant use OC_BD functions here because we need to connect as the administrative user. $query = "CREATE DATABASE IF NOT EXISTS `$name`"; $result = mysql_query($query, $connection); @@ -261,7 +224,7 @@ class OC_Setup { $result = mysql_query($query, $connection); //this query will fail if there aren't the right permissons, ignore the error } - private static function createDBUser($name,$password,$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. $query = "CREATE USER '$name'@'localhost' IDENTIFIED BY '$password'"; @@ -336,7 +299,7 @@ class OC_Setup { } } - private static function pg_createDatabase($name,$user,$connection) { + private static function pg_createDatabase($name, $user, $connection) { //we cant use OC_BD functions here because we need to connect as the administrative user. $e_name = pg_escape_string($name); $e_user = pg_escape_string($user); @@ -356,12 +319,14 @@ class OC_Setup { $entry.='Offending command was: '.$query.'<br />'; echo($entry); } + else { + $query = "REVOKE ALL PRIVILEGES ON DATABASE \"$e_name\" FROM PUBLIC"; + $result = pg_query($connection, $query); + } } - $query = "REVOKE ALL PRIVILEGES ON DATABASE \"$e_name\" FROM PUBLIC"; - $result = pg_query($connection, $query); } - private static function pg_createDBUser($name,$password,$connection) { + private static function pg_createDBUser($name, $password, $connection) { $e_name = pg_escape_string($name); $e_password = pg_escape_string($password); $query = "select * from pg_roles where rolname='$e_name';"; @@ -570,7 +535,15 @@ class OC_Setup { * create .htaccess files for apache hosts */ private static function createHtaccess() { - $content = "ErrorDocument 403 ".OC::$WEBROOT."/core/templates/403.php\n";//custom 403 error page + $content = "<IfModule mod_fcgid.c>\n"; + $content.= "<IfModule mod_setenvif.c>\n"; + $content.= "<IfModule mod_headers.c>\n"; + $content.= "SetEnvIfNoCase ^Authorization$ \"(.+)\" XAUTHORIZATION=$1\n"; + $content.= "RequestHeader set XAuthorization %{XAUTHORIZATION}e env=XAUTHORIZATION\n"; + $content.= "</IfModule>\n"; + $content.= "</IfModule>\n"; + $content.= "</IfModule>\n"; + $content.= "ErrorDocument 403 ".OC::$WEBROOT."/core/templates/403.php\n";//custom 403 error page $content.= "ErrorDocument 404 ".OC::$WEBROOT."/core/templates/404.php\n";//custom 404 error page $content.= "<IfModule mod_php5.c>\n"; $content.= "php_value upload_max_filesize 512M\n";//upload limit @@ -589,9 +562,17 @@ class OC_Setup { $content.= "RewriteRule ^apps/([^/]*)/(.*\.(css|php))$ index.php?app=$1&getfile=$2 [QSA,L]\n"; $content.= "RewriteRule ^remote/(.*) remote.php [QSA,L]\n"; $content.= "</IfModule>\n"; + $content.= "<IfModule mod_mime.c>\n"; + $content.= "AddType image/svg+xml svg svgz\n"; + $content.= "AddEncoding gzip svgz\n"; + $content.= "</IfModule>\n"; $content.= "Options -Indexes\n"; @file_put_contents(OC::$SERVERROOT.'/.htaccess', $content); //supress errors in case we don't have permissions for it + self::protectDataDirectory(); + } + + public static function protectDataDirectory() { $content = "deny from all\n"; $content.= "IndexIgnore *"; file_put_contents(OC_Config::getValue('datadirectory', OC::$SERVERROOT.'/data').'/.htaccess', $content); diff --git a/lib/streamwrappers.php b/lib/streamwrappers.php index 63b795f4c4d..981c280f0dd 100644 --- a/lib/streamwrappers.php +++ b/lib/streamwrappers.php @@ -5,7 +5,7 @@ class OC_FakeDirStream{ private $name; private $index; - public function dir_opendir($path,$options) { + public function dir_opendir($path, $options) { $this->name=substr($path, strlen('fakedir://')); $this->index=0; if(!isset(self::$dirs[$this->name])) { @@ -225,7 +225,7 @@ class OC_CloseStreamWrapper{ public function stream_open($path, $mode, $options, &$opened_path) { $path=substr($path, strlen('close://')); $this->path=$path; - $this->source=fopen($path,$mode); + $this->source=fopen($path, $mode); if(is_resource($this->source)) { $this->meta=stream_get_meta_data($this->source); } @@ -234,7 +234,7 @@ class OC_CloseStreamWrapper{ } public function stream_seek($offset, $whence=SEEK_SET) { - fseek($this->source,$offset,$whence); + fseek($this->source, $offset, $whence); } public function stream_tell() { @@ -242,23 +242,23 @@ class OC_CloseStreamWrapper{ } public function stream_read($count) { - return fread($this->source,$count); + return fread($this->source, $count); } public function stream_write($data) { - return fwrite($this->source,$data); + return fwrite($this->source, $data); } - public function stream_set_option($option,$arg1,$arg2) { + public function stream_set_option($option, $arg1, $arg2) { switch($option) { case STREAM_OPTION_BLOCKING: - stream_set_blocking($this->source,$arg1); + stream_set_blocking($this->source, $arg1); break; case STREAM_OPTION_READ_TIMEOUT: - stream_set_timeout($this->source,$arg1,$arg2); + stream_set_timeout($this->source, $arg1, $arg2); break; case STREAM_OPTION_WRITE_BUFFER: - stream_set_write_buffer($this->source,$arg1,$arg2); + stream_set_write_buffer($this->source, $arg1, $arg2); } } @@ -267,7 +267,7 @@ class OC_CloseStreamWrapper{ } public function stream_lock($mode) { - flock($this->source,$mode); + flock($this->source, $mode); } public function stream_flush() { @@ -290,7 +290,7 @@ class OC_CloseStreamWrapper{ public function stream_close() { fclose($this->source); if(isset(self::$callBacks[$this->path])) { - call_user_func(self::$callBacks[$this->path],$this->path); + call_user_func(self::$callBacks[$this->path], $this->path); } } diff --git a/lib/template.php b/lib/template.php index 972d75807c7..04667d73a2c 100644 --- a/lib/template.php +++ b/lib/template.php @@ -22,6 +22,22 @@ */ /** + * Prints an XSS escaped string + * @param string $string the string which will be escaped and printed + */ +function p($string) { + print(OC_Util::sanitizeHTML($string)); +} + +/** + * Prints an unescaped string + * @param string $string the string which will be printed as it is + */ +function print_unescaped($string) { + print($string); +} + +/** * @brief make OC_Helper::linkTo available as a simple function * @param string $app app * @param string $file file @@ -69,7 +85,7 @@ function human_file_size( $bytes ) { } function simple_file_size($bytes) { - $mbytes = round($bytes/(1024*1024),1); + $mbytes = round($bytes/(1024*1024), 1); if($bytes == 0) { return '0'; } else if($mbytes < 0.1) { return '< 0.1'; } else if($mbytes > 1000) { return '> 1000'; } @@ -86,14 +102,14 @@ function relative_modified_date($timestamp) { if($timediff < 60) { return $l->t('seconds ago'); } else if($timediff < 120) { return $l->t('1 minute ago'); } - else if($timediff < 3600) { return $l->t('%d minutes ago',$diffminutes); } - //else if($timediff < 7200) { return '1 hour ago'; } - //else if($timediff < 86400) { return $diffhours.' hours ago'; } + else if($timediff < 3600) { return $l->t('%d minutes ago', $diffminutes); } + else if($timediff < 7200) { return $l->t('1 hour ago'); } + else if($timediff < 86400) { return $l->t('%d hours ago', $diffhours); } else if((date('G')-$diffhours) > 0) { return $l->t('today'); } else if((date('G')-$diffhours) > -24) { return $l->t('yesterday'); } - else if($timediff < 2678400) { return $l->t('%d days ago',$diffdays); } + else if($timediff < 2678400) { return $l->t('%d days ago', $diffdays); } else if($timediff < 5184000) { return $l->t('last month'); } - else if((date('n')-$diffmonths) > 0) { return $l->t('months ago'); } + else if((date('n')-$diffmonths) > 0) { return $l->t('%d months ago', $diffmonths); } else if($timediff < 63113852) { return $l->t('last year'); } else { return $l->t('years ago'); } } @@ -156,7 +172,6 @@ class OC_Template{ $this->application = $app; $this->vars = array(); $this->vars['requesttoken'] = OC_Util::callRegister(); - $this->vars['requestlifespan'] = OC_Util::$callLifespan; $parts = explode('/', $app); // fix translation when app is something like core/lostpassword $this->l10n = OC_L10N::get($parts[0]); @@ -180,11 +195,11 @@ class OC_Template{ public static function detectFormfactor() { // please add more useragent strings for other devices if(isset($_SERVER['HTTP_USER_AGENT'])) { - if(stripos($_SERVER['HTTP_USER_AGENT'],'ipad')>0) { + if(stripos($_SERVER['HTTP_USER_AGENT'], 'ipad')>0) { $mode='tablet'; - }elseif(stripos($_SERVER['HTTP_USER_AGENT'],'iphone')>0) { + }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'; @@ -341,7 +356,7 @@ class OC_Template{ * @param string $text the text content for the element */ public function addHeader( $tag, $attributes, $text='') { - $this->headers[]=array('tag'=>$tag,'attributes'=>$attributes,'text'=>$text); + $this->headers[]=array('tag'=>$tag,'attributes'=>$attributes, 'text'=>$text); } /** @@ -375,13 +390,12 @@ class OC_Template{ $page = new OC_TemplateLayout($this->renderas); if($this->renderas == 'user') { $page->assign('requesttoken', $this->vars['requesttoken']); - $page->assign('requestlifespan', $this->vars['requestlifespan']); } // Add custom headers - $page->assign('headers',$this->headers, false); + $page->assign('headers', $this->headers, false); foreach(OC_Util::$headers as $header) { - $page->append('headers',$header); + $page->append('headers', $header); } $page->assign( "content", $data, false ); @@ -482,4 +496,15 @@ class OC_Template{ } return $content->printPage(); } + + /** + * @brief Print a fatal error page and terminates the script + * @param string $error The error message to show + * @param string $hint An option hint message + */ + public static function printErrorPage( $error_msg, $hint = '' ) { + $errors = array(array('error' => $error_msg, 'hint' => $hint)); + OC_Template::printGuestPage("", "error", array("errors" => $errors)); + die(); + } } diff --git a/lib/templatelayout.php b/lib/templatelayout.php index c3da172a7c1..1a0570a270d 100644 --- a/lib/templatelayout.php +++ b/lib/templatelayout.php @@ -12,10 +12,10 @@ 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); + if(in_array(OC_APP::getCurrentApp(), array('settings','admin', 'help'))!==false) { + $this->assign('bodyid', 'body-settings', false); }else{ - $this->assign('bodyid','body-user', false); + $this->assign('bodyid', 'body-user', false); } // Add navigation entry diff --git a/lib/updater.php b/lib/updater.php index f55e55985d9..11081eded63 100644 --- a/lib/updater.php +++ b/lib/updater.php @@ -30,7 +30,7 @@ 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(); @@ -38,7 +38,7 @@ class OC_Updater{ $version['updated']=OC_Appconfig::getValue('core', 'lastupdatedat'); $version['updatechannel']='stable'; $version['edition']=OC_Util::getEditionString(); - $versionstring=implode('x',$version); + $versionstring=implode('x', $version); //fetch xml data from updater $url=$updaterurl.'?version='.$versionstring; diff --git a/lib/user.php b/lib/user.php index 064fcbad96f..80f88ca7052 100644 --- a/lib/user.php +++ b/lib/user.php @@ -86,8 +86,9 @@ class OC_User { */ public static function useBackend( $backend = 'database' ) { if($backend instanceof OC_User_Interface) { + OC_Log::write('core', 'Adding user backend instance of '.get_class($backend).'.', OC_Log::DEBUG); self::$_usedBackends[get_class($backend)]=$backend; - }else{ + } else { // You'll never know what happens if( null === $backend OR !is_string( $backend )) { $backend = 'database'; @@ -98,15 +99,17 @@ class OC_User { case 'database': case 'mysql': case 'sqlite': + OC_Log::write('core', 'Adding user backend '.$backend.'.', OC_Log::DEBUG); self::$_usedBackends[$backend] = new OC_User_Database(); break; default: + OC_Log::write('core', 'Adding default user backend '.$backend.'.', OC_Log::DEBUG); $className = 'OC_USER_' . strToUpper($backend); self::$_usedBackends[$backend] = new $className(); break; } } - true; + return true; } /** @@ -124,16 +127,20 @@ class OC_User { foreach($backends as $i=>$config) { $class=$config['class']; $arguments=$config['arguments']; - if(class_exists($class) and array_search($i, self::$_setupedBackends)===false) { - // make a reflection object - $reflectionObj = new ReflectionClass($class); - - // use Reflection to create a new instance, using the $args - $backend = $reflectionObj->newInstanceArgs($arguments); - self::useBackend($backend); - $_setupedBackends[]=$i; - }else{ - OC_Log::write('core','User backend '.$class.' not found.',OC_Log::ERROR); + if(class_exists($class)) { + if(array_search($i, self::$_setupedBackends)===false) { + // make a reflection object + $reflectionObj = new ReflectionClass($class); + + // use Reflection to create a new instance, using the $args + $backend = $reflectionObj->newInstanceArgs($arguments); + self::useBackend($backend); + $_setupedBackends[]=$i; + } else { + OC_Log::write('core', 'User backend '.$class.' already initialized.', OC_Log::DEBUG); + } + } else { + OC_Log::write('core', 'User backend '.$class.' not found.', OC_Log::ERROR); } } } @@ -179,10 +186,10 @@ class OC_User { if(!$backend->implementsActions(OC_USER_BACKEND_CREATE_USER)) continue; - $backend->createUser($uid,$password); + $backend->createUser($uid, $password); OC_Hook::emit( "OC_User", "post_createUser", array( "uid" => $uid, "password" => $password )); - return true; + return self::userExists($uid); } } return false; @@ -204,6 +211,9 @@ class OC_User { foreach(self::$_usedBackends as $backend) { $backend->deleteUser($uid); } + if (self::userExists($uid)) { + return false; + } // We have to delete the user from all groups foreach( OC_Group::getUserGroups( $uid ) as $i ) { OC_Group::removeFromGroup( $uid, $i ); @@ -329,7 +339,7 @@ class OC_User { foreach(self::$_usedBackends as $backend) { if($backend->implementsActions(OC_USER_BACKEND_SET_PASSWORD)) { if($backend->userExists($uid)) { - $success |= $backend->setPassword($uid,$password); + $success |= $backend->setPassword($uid, $password); } } } @@ -369,8 +379,7 @@ class OC_User { * @param $password The password * @returns string * - * Check if the password is correct without logging in the user - * returns the user id or false + * returns the path to the users home directory */ public static function getHome($uid) { foreach(self::$_usedBackends as $backend) { @@ -405,10 +414,15 @@ class OC_User { /** * @brief check if a user exists * @param string $uid the username + * @param string $excludingBackend (default none) * @return boolean */ - public static function userExists($uid) { + 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; + } $result=$backend->userExists($uid); if($result===true) { return true; diff --git a/lib/user/database.php b/lib/user/database.php index 25e24fcf7e4..f33e338e2e4 100644 --- a/lib/user/database.php +++ b/lib/user/database.php @@ -48,7 +48,7 @@ class OC_User_Database extends OC_User_Backend { if(!self::$hasher) { //we don't want to use DES based crypt(), since it doesn't return a has with a recognisable prefix $forcePortable=(CRYPT_BLOWFISH!=1); - self::$hasher=new PasswordHash(8,$forcePortable); + self::$hasher=new PasswordHash(8, $forcePortable); } return self::$hasher; @@ -137,7 +137,7 @@ class OC_User_Database extends OC_User_Backend { }else{//old sha1 based hashing if(sha1($password)==$storedHash) { //upgrade to new hashing - $this->setPassword($row['uid'],$password); + $this->setPassword($row['uid'], $password); return $row['uid']; }else{ return false; @@ -155,7 +155,7 @@ class OC_User_Database extends OC_User_Backend { * Get a list of all users. */ public function getUsers($search = '', $limit = null, $offset = null) { - $query = OC_DB::prepare('SELECT `uid` FROM `*PREFIX*users` WHERE LOWER(`uid`) LIKE LOWER(?)',$limit,$offset); + $query = OC_DB::prepare('SELECT `uid` FROM `*PREFIX*users` WHERE LOWER(`uid`) LIKE LOWER(?)', $limit, $offset); $result = $query->execute(array($search.'%')); $users = array(); while ($row = $result->fetchRow()) { @@ -172,7 +172,10 @@ class OC_User_Database extends OC_User_Backend { public function userExists($uid) { $query = OC_DB::prepare( 'SELECT * FROM `*PREFIX*users` WHERE LOWER(`uid`) = LOWER(?)' ); $result = $query->execute( array( $uid )); - + if (OC_DB::isError($result)) { + OC_Log::write('core', OC_DB::getErrorMessage($result), OC_Log::ERROR); + return false; + } return $result->numRows() > 0; } diff --git a/lib/user/http.php b/lib/user/http.php index 2668341408d..944ede73a0b 100644 --- a/lib/user/http.php +++ b/lib/user/http.php @@ -40,7 +40,7 @@ class OC_User_HTTP extends OC_User_Backend { if(isset($parts['query'])) { $url.='?'.$parts['query']; } - return array($parts['user'],$url); + return array($parts['user'], $url); } @@ -50,7 +50,7 @@ class OC_User_HTTP extends OC_User_Backend { * @return boolean */ private function matchUrl($url) { - return ! is_null(parse_url($url,PHP_URL_USER)); + return ! is_null(parse_url($url, PHP_URL_USER)); } /** @@ -66,7 +66,7 @@ class OC_User_HTTP extends OC_User_Backend { if(!$this->matchUrl($uid)) { return false; } - list($user,$url)=$this->parseUrl($uid); + list($user, $url)=$this->parseUrl($uid); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); diff --git a/lib/util.php b/lib/util.php index 4ca84ba75af..34c4d4f9b11 100755 --- a/lib/util.php +++ b/lib/util.php @@ -24,6 +24,11 @@ class OC_Util { $user = OC_User::getUser(); } + // load all filesystem apps before, so no setup-hook gets lost + if(!isset($RUNTIME_NOAPPS) || !$RUNTIME_NOAPPS) { + OC_App::loadApps(array('filesystem')); + } + // the filesystem will finish when $user is not empty, // mark fs setup here to avoid doing the setup from loading // OC_Filesystem @@ -34,7 +39,7 @@ class OC_Util { $CONFIG_DATADIRECTORY = OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" ); //first set up the local "root" storage if(!self::$rootMounted) { - OC_Filesystem::mount('OC_Filestorage_Local', array('datadir'=>$CONFIG_DATADIRECTORY),'/'); + OC_Filesystem::mount('OC_Filestorage_Local', array('datadir'=>$CONFIG_DATADIRECTORY), '/'); self::$rootMounted=true; } @@ -62,7 +67,7 @@ class OC_Util { OC_Filesystem::tearDown(); self::$fsSetup=false; } - + public static function loadUserMountPoints($user) { $user_dir = '/'.$user.'/files'; $user_root = OC_User::getHome($user); @@ -74,14 +79,14 @@ class OC_Util { OC_Filesystem::mount($options['class'], $options['options'], $mountPoint); } } - + $mtime=filemtime($user_root.'/mount.php'); - $previousMTime=OC_Preferences::getValue($user,'files','mountconfigmtime',0); + $previousMTime=OC_Preferences::getValue($user, 'files', 'mountconfigmtime', 0); if($mtime>$previousMTime) {//mount config has changed, filecache needs to be updated OC_FileCache::triggerUpdate($user); - OC_Preferences::setValue($user,'files','mountconfigmtime',$mtime); + OC_Preferences::setValue($user, 'files', 'mountconfigmtime', $mtime); } - } + } } /** @@ -90,7 +95,7 @@ class OC_Util { */ 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,00); + return array(4, 91, 02); } /** @@ -152,7 +157,7 @@ class OC_Util { * @param string $text the text content for the element */ public static function addHeader( $tag, $attributes, $text='') { - self::$headers[]=array('tag'=>$tag,'attributes'=>$attributes,'text'=>$text); + self::$headers[]=array('tag'=>$tag,'attributes'=>$attributes, 'text'=>$text); } /** @@ -161,10 +166,10 @@ class OC_Util { * @param int timestamp $timestamp * @param bool dateOnly option to ommit time from the result */ - public static function formatDate( $timestamp,$dateOnly=false) { + public static function formatDate( $timestamp, $dateOnly=false) { if(isset($_SESSION['timezone'])) {//adjust to clients timezone if we know it $systemTimeZone = intval(date('O')); - $systemTimeZone=(round($systemTimeZone/100,0)*60)+($systemTimeZone%100); + $systemTimeZone=(round($systemTimeZone/100, 0)*60)+($systemTimeZone%100); $clientTimeZone=$_SESSION['timezone']*60; $offset=$clientTimeZone-$systemTimeZone; $timestamp=$timestamp+$offset*60; @@ -181,7 +186,7 @@ class OC_Util { * @param string $url * @return OC_Template */ - public static function getPageNavi($pagecount,$page,$url) { + public static function getPageNavi($pagecount, $page, $url) { $pagelinkcount=8; if ($pagecount>1) { @@ -191,11 +196,11 @@ class OC_Util { if($pagestop>$pagecount) $pagestop=$pagecount; $tmpl = new OC_Template( '', 'part.pagenavi', '' ); - $tmpl->assign('page',$page); - $tmpl->assign('pagecount',$pagecount); - $tmpl->assign('pagestart',$pagestart); - $tmpl->assign('pagestop',$pagestop); - $tmpl->assign('url',$url); + $tmpl->assign('page', $page); + $tmpl->assign('pagecount', $pagecount); + $tmpl->assign('pagestart', $pagestart); + $tmpl->assign('pagestop', $pagestop); + $tmpl->assign('url', $url); return $tmpl; } } @@ -212,7 +217,7 @@ 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 + $errors[]=array('error'=>'No database drivers (sqlite, mysql, or postgresql) installed.<br/>', 'hint'=>'');//TODO: sane hint $web_server_restart= true; } @@ -221,13 +226,13 @@ class OC_Util { // 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 + $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."); } } @@ -236,24 +241,24 @@ class OC_Util { //check for correct file permissions if(!stristr(PHP_OS, 'WIN')) { $permissionsModHint="Please change the permissions to 0770 so that the directory cannot be listed by other users."; - $prems=substr(decoct(@fileperms($CONFIG_DATADIRECTORY)),-3); - if(substr($prems,-1)!='0') { - OC_Helper::chmodr($CONFIG_DATADIRECTORY,0770); + $prems=substr(decoct(@fileperms($CONFIG_DATADIRECTORY)), -3); + if(substr($prems, -1)!='0') { + OC_Helper::chmodr($CONFIG_DATADIRECTORY, 0770); clearstatcache(); - $prems=substr(decoct(@fileperms($CONFIG_DATADIRECTORY)),-3); - if(substr($prems,2,1)!='0') { - $errors[]=array('error'=>'Data directory ('.$CONFIG_DATADIRECTORY.') is readable for other users<br/>','hint'=>$permissionsModHint); + $prems=substr(decoct(@fileperms($CONFIG_DATADIRECTORY)), -3); + if(substr($prems, 2, 1)!='0') { + $errors[]=array('error'=>'Data directory ('.$CONFIG_DATADIRECTORY.') is readable for other users<br/>', 'hint'=>$permissionsModHint); } } if( OC_Config::getValue( "enablebackup", false )) { $CONFIG_BACKUPDIRECTORY = OC_Config::getValue( "backupdirectory", OC::$SERVERROOT."/backup" ); - $prems=substr(decoct(@fileperms($CONFIG_BACKUPDIRECTORY)),-3); - if(substr($prems,-1)!='0') { - OC_Helper::chmodr($CONFIG_BACKUPDIRECTORY,0770); + $prems=substr(decoct(@fileperms($CONFIG_BACKUPDIRECTORY)), -3); + if(substr($prems, -1)!='0') { + OC_Helper::chmodr($CONFIG_BACKUPDIRECTORY, 0770); clearstatcache(); - $prems=substr(decoct(@fileperms($CONFIG_BACKUPDIRECTORY)),-3); - if(substr($prems,2,1)!='0') { - $errors[]=array('error'=>'Data directory ('.$CONFIG_BACKUPDIRECTORY.') is readable for other users<br/>','hint'=>$permissionsModHint); + $prems=substr(decoct(@fileperms($CONFIG_BACKUPDIRECTORY)), -3); + if(substr($prems, 2, 1)!='0') { + $errors[]=array('error'=>'Data directory ('.$CONFIG_BACKUPDIRECTORY.') is readable for other users<br/>', 'hint'=>$permissionsModHint); } } } @@ -264,57 +269,57 @@ class OC_Util { if(!is_dir($CONFIG_DATADIRECTORY)) { $success=@mkdir($CONFIG_DATADIRECTORY); if(!$success) { - $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); } // 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(!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; } 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; @@ -335,10 +340,8 @@ class OC_Util { } if (isset($_REQUEST['redirect_url'])) { $redirect_url = OC_Util::sanitizeHTML($_REQUEST['redirect_url']); - } else { - $redirect_url = $_SERVER['REQUEST_URI']; - } - $parameters['redirect_url'] = $redirect_url; + $parameters['redirect_url'] = urlencode($redirect_url); + } OC_Template::printGuestPage("", "login", $parameters); } @@ -386,7 +389,7 @@ class OC_Util { // Check if we are a user self::checkLoggedIn(); self::verifyUser(); - if(OC_Group::inGroup(OC_User::getUser(),'admin')) { + if(OC_Group::inGroup(OC_User::getUser(), 'admin')) { return true; } if(!OC_SubAdmin::isSubAdmin(OC_User::getUser())) { @@ -429,13 +432,13 @@ class OC_Util { } return true; } - + /** * Redirect to the user default page */ public static function redirectToDefaultPage() { - if(isset($_REQUEST['redirect_url']) && (substr($_REQUEST['redirect_url'], 0, strlen(OC::$WEBROOT)) == OC::$WEBROOT || $_REQUEST['redirect_url'][0] == '/')) { - $location = $_REQUEST['redirect_url']; + if(isset($_REQUEST['redirect_url'])) { + $location = OC_Helper::makeURLAbsolute(urldecode($_REQUEST['redirect_url'])); } else if (isset(OC::$REQUESTEDAPP) && !empty(OC::$REQUESTEDAPP)) { $location = OC_Helper::linkToAbsolute( OC::$REQUESTEDAPP, 'index.php' ); @@ -462,23 +465,12 @@ class OC_Util { $id=OC_Config::getValue('instanceid', null); if(is_null($id)) { $id=uniqid(); - OC_Config::setValue('instanceid',$id); + OC_Config::setValue('instanceid', $id); } return $id; } /** - * @brief Static lifespan (in seconds) when a request token expires. - * @see OC_Util::callRegister() - * @see OC_Util::isCallRegistered() - * @description - * Also required for the client side to compute the piont in time when to - * request a fresh token. The client will do so when nearly 97% of the - * timespan coded here has expired. - */ - public static $callLifespan = 3600; // 3600 secs = 1 hour - - /** * @brief Register an get/post call. Important to prevent CSRF attacks. * @todo Write howto: CSRF protection guide * @return $token Generated token. @@ -486,40 +478,25 @@ class OC_Util { * Creates a 'request token' (random) and stores it inside the session. * Ever subsequent (ajax) request must use such a valid token to succeed, * otherwise the request will be denied as a protection against CSRF. - * The tokens expire after a fixed lifespan. - * @see OC_Util::$callLifespan * @see OC_Util::isCallRegistered() */ public static function callRegister() { - // generate a random token. - $token = self::generate_random_bytes(20); - - // store the token together with a timestamp in the session. - $_SESSION['requesttoken-'.$token]=time(); - - // cleanup old tokens garbage collector - // only run every 20th time so we don't waste cpu cycles - if(rand(0,20)==0) { - foreach($_SESSION as $key=>$value) { - // search all tokens in the session - if(substr($key,0,12)=='requesttoken') { - // check if static lifespan has expired - if($value+self::$callLifespan<time()) { - // remove outdated tokens - unset($_SESSION[$key]); - } - } - } + // Check if a token exists + if(!isset($_SESSION['requesttoken'])) { + // No valid token found, generate a new one. + $requestToken = self::generate_random_bytes(20); + $_SESSION['requesttoken']=$requestToken; + } else { + // Valid token already exists, send it + $requestToken = $_SESSION['requesttoken']; } - // return the token - return($token); + return($requestToken); } /** * @brief Check an ajax get/post call if the request token is valid. * @return boolean False if request token is not set or is invalid. - * @see OC_Util::$callLifespan - * @see OC_Util::calLRegister() + * @see OC_Util::callRegister() */ public static function isCallRegistered() { if(isset($_GET['requesttoken'])) { @@ -532,17 +509,14 @@ class OC_Util { //no token found. return false; } - if(isset($_SESSION['requesttoken-'.$token])) { - $timestamp=$_SESSION['requesttoken-'.$token]; - // check if static lifespan has expired - if($timestamp+self::$callLifespan<time()) { - return false; - }else{ - //token valid - return true; - } - }else{ + + // Check if the token is valid + if($token !== $_SESSION['requesttoken']) { + // Not valid return false; + } else { + // Valid token + return true; } } @@ -566,7 +540,7 @@ 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)) array_walk_recursive($value,'OC_Util::sanitizeHTML'); + if (is_array($value) || is_object($value)) array_walk_recursive($value, 'OC_Util::sanitizeHTML'); else $value = htmlentities($value, ENT_QUOTES, 'UTF-8'); //Specify encoding for PHP<5.4 return $value; } @@ -583,7 +557,7 @@ class OC_Util { // creating a test file $testfile = OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" ).'/'.$filename; - if(file_exists($testfile)){// already running this test, possible recursive call + if(file_exists($testfile)) {// already running this test, possible recursive call return false; } @@ -608,6 +582,42 @@ class OC_Util { } } + + /** + * Check if the ownCloud server can connect to the internet + */ + public static function isinternetconnectionworking() { + + // try to connect to owncloud.org to see if http connections to the internet are possible. + $connected = @fsockopen("www.owncloud.org", 80); + if ($connected) { + fclose($connected); + return true; + }else{ + + // second try in case one server is down + $connected = @fsockopen("apps.owncloud.com", 80); + if ($connected) { + fclose($connected); + return true; + }else{ + return false; + } + + } + + } + + /** + * clear all levels of output buffering + */ + public static function obEnd(){ + while (ob_get_level()) { + ob_end_clean(); + } + } + + /** * @brief Generates a cryptographical secure pseudorandom string * @param Int with the length of the random string @@ -666,4 +676,43 @@ class OC_Util { return false; } + + /** + * @Brief Get file content via curl. + * @param string $url Url to get content + * @return string of the response or false on error + * This function get the content of a page via curl, if curl is enabled. + * If not, file_get_element is used. + */ + + public static function getUrlContent($url){ + + if (function_exists('curl_init')) { + + $curl = curl_init(); + + curl_setopt($curl, CURLOPT_HEADER, 0); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 10); + curl_setopt($curl, CURLOPT_URL, $url); + curl_setopt($curl, CURLOPT_USERAGENT, "ownCloud Server Crawler"); + $data = curl_exec($curl); + curl_close($curl); + + } else { + + $ctx = stream_context_create( + array( + 'http' => array( + 'timeout' => 10 + ) + ) + ); + $data=@file_get_contents($url, 0, $ctx); + + } + + return $data; + } + } diff --git a/lib/vcategories.php b/lib/vcategories.php index ba6569a244d..406a4eb1074 100644 --- a/lib/vcategories.php +++ b/lib/vcategories.php @@ -21,6 +21,7 @@ * */ +OC_Hook::connect('OC_User', 'post_deleteUser', 'OC_VCategories', 'post_deleteUser'); /** * Class for easy access to categories in VCARD, VEVENT, VTODO and VJOURNAL. @@ -28,50 +29,261 @@ * anything else that is either parsed from a vobject or that the user chooses * to add. * Category names are not case-sensitive, but will be saved with the case they - * are entered in. If a user already has a category 'family' for an app, and + * are entered in. If a user already has a category 'family' for a type, and * tries to add a category named 'Family' it will be silently ignored. - * NOTE: There is a limitation in that the the configvalue field in the - * preferences table is a varchar(255). */ class OC_VCategories { - const PREF_CATEGORIES_LABEL = 'extra_categories'; + /** * Categories */ private $categories = array(); - private $app = null; + /** + * Used for storing objectid/categoryname pairs while rescanning. + */ + private static $relations = array(); + + private $type = null; private $user = null; + const CATEGORY_TABLE = '*PREFIX*vcategory'; + const RELATION_TABLE = '*PREFIX*vcategory_to_object'; + + const CATEGORY_FAVORITE = '_$!<Favorite>!$_'; + + const FORMAT_LIST = 0; + const FORMAT_MAP = 1; + /** * @brief Constructor. - * @param $app The application identifier e.g. 'contacts' or 'calendar'. + * @param $type The type identifier e.g. 'contact' or 'event'. * @param $user The user whos data the object will operate on. This * parameter should normally be omitted but to make an app able to * update categories for all users it is made possible to provide it. * @param $defcategories An array of default categories to be used if none is stored. */ - public function __construct($app, $user=null, $defcategories=array()) { - $this->app = $app; + public function __construct($type, $user=null, $defcategories=array()) { + $this->type = $type; $this->user = is_null($user) ? OC_User::getUser() : $user; - $categories = trim(OC_Preferences::getValue($this->user, $app, self::PREF_CATEGORIES_LABEL, '')); - if ($categories) { - $categories = @unserialize($categories); + + $this->loadCategories(); + OCP\Util::writeLog('core', __METHOD__ . ', categories: ' + . print_r($this->categories, true), + OCP\Util::DEBUG + ); + + if($defcategories && count($this->categories) === 0) { + $this->addMulti($defcategories, true); + } + } + + /** + * @brief Load categories from db. + */ + private function loadCategories() { + $this->categories = array(); + $result = null; + $sql = 'SELECT `id`, `category` FROM `' . self::CATEGORY_TABLE . '` ' + . 'WHERE `uid` = ? AND `type` = ? ORDER BY `category`'; + try { + $stmt = OCP\DB::prepare($sql); + $result = $stmt->execute(array($this->user, $this->type)); + if (OC_DB::isError($result)) { + 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(), + OCP\Util::ERROR); + } + + if(!is_null($result)) { + while( $row = $result->fetchRow()) { + // The keys are prefixed because array_search wouldn't work otherwise :-/ + $this->categories[$row['id']] = $row['category']; + } + } + OCP\Util::writeLog('core', __METHOD__.', categories: ' . print_r($this->categories, true), + OCP\Util::DEBUG); + } + + + /** + * @brief Check if any categories are saved for this type and user. + * @returns boolean. + * @param $type The type identifier e.g. 'contact' or 'event'. + * @param $user The user whos categories will be checked. If not set current user will be used. + */ + public static function isEmpty($type, $user = null) { + $user = is_null($user) ? OC_User::getUser() : $user; + $sql = 'SELECT COUNT(*) FROM `' . self::CATEGORY_TABLE . '` ' + . 'WHERE `uid` = ? AND `type` = ?'; + try { + $stmt = OCP\DB::prepare($sql); + $result = $stmt->execute(array($user, $type)); + if (OC_DB::isError($result)) { + OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR); + return false; + } + return ($result->numRows() == 0); + } catch(Exception $e) { + OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), + OCP\Util::ERROR); + return false; } - $this->categories = is_array($categories) ? $categories : $defcategories; } /** * @brief Get the categories for a specific user. + * @param * @returns array containing the categories as strings. */ - public function categories() { - //OC_Log::write('core','OC_VCategories::categories: '.print_r($this->categories, true), OC_Log::DEBUG); + public function categories($format = null) { if(!$this->categories) { return array(); } - usort($this->categories, 'strnatcasecmp'); // usort to also renumber the keys - return $this->categories; + $categories = array_values($this->categories); + uasort($categories, 'strnatcasecmp'); + if($format == self::FORMAT_MAP) { + $catmap = array(); + foreach($categories as $category) { + if($category !== self::CATEGORY_FAVORITE) { + $catmap[] = array( + 'id' => $this->array_searchi($category, $this->categories), + 'name' => $category + ); + } + } + return $catmap; + } + + // Don't add favorites to normal categories. + $favpos = array_search(self::CATEGORY_FAVORITE, $categories); + if($favpos !== false) { + return array_splice($categories, $favpos); + } else { + return $categories; + } + } + + /** + * Get the a list if items belonging to $category. + * + * Throws an exception if the category could not be found. + * + * @param string|integer $category Category id or name. + * @returns array An array of object ids or false on error. + */ + public function idsForCategory($category) { + $result = null; + if(is_numeric($category)) { + $catid = $category; + } elseif(is_string($category)) { + $catid = $this->array_searchi($category, $this->categories); + } + OCP\Util::writeLog('core', __METHOD__.', category: '.$catid.' '.$category, OCP\Util::DEBUG); + if($catid === false) { + $l10n = OC_L10N::get('core'); + throw new Exception( + $l10n->t('Could not find category "%s"', $category) + ); + } + + $ids = array(); + $sql = 'SELECT `objid` FROM `' . self::RELATION_TABLE + . '` WHERE `categoryid` = ?'; + + try { + $stmt = OCP\DB::prepare($sql); + $result = $stmt->execute(array($catid)); + if (OC_DB::isError($result)) { + OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR); + return false; + } + } catch(Exception $e) { + OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), + OCP\Util::ERROR); + return false; + } + + if(!is_null($result)) { + while( $row = $result->fetchRow()) { + $ids[] = (int)$row['objid']; + } + } + + return $ids; + } + + /** + * Get the a list if items belonging to $category. + * + * Throws an exception if the category could not be found. + * + * @param string|integer $category Category id or name. + * @param array $tableinfo Array in the form {'tablename' => table, 'fields' => ['field1', 'field2']} + * @param int $limit + * @param int $offset + * + * This generic method queries a table assuming that the id + * field is called 'id' and the table name provided is in + * the form '*PREFIX*table_name'. + * + * If the category name cannot be resolved an exception is thrown. + * + * TODO: Maybe add the getting permissions for objects? + * + * @returns array containing the resulting items or false on error. + */ + public function itemsForCategory($category, $tableinfo, $limit = null, $offset = null) { + $result = null; + if(is_numeric($category)) { + $catid = $category; + } elseif(is_string($category)) { + $catid = $this->array_searchi($category, $this->categories); + } + OCP\Util::writeLog('core', __METHOD__.', category: '.$catid.' '.$category, OCP\Util::DEBUG); + if($catid === false) { + $l10n = OC_L10N::get('core'); + throw new Exception( + $l10n->t('Could not find category "%s"', $category) + ); + } + $fields = ''; + foreach($tableinfo['fields'] as $field) { + $fields .= '`' . $tableinfo['tablename'] . '`.`' . $field . '`,'; + } + $fields = substr($fields, 0, -1); + + $items = array(); + $sql = 'SELECT `' . self::RELATION_TABLE . '`.`categoryid`, ' . $fields + . ' FROM `' . $tableinfo['tablename'] . '` JOIN `' + . self::RELATION_TABLE . '` ON `' . $tableinfo['tablename'] + . '`.`id` = `' . self::RELATION_TABLE . '`.`objid` WHERE `' + . self::RELATION_TABLE . '`.`categoryid` = ?'; + + try { + $stmt = OCP\DB::prepare($sql, $limit, $offset); + $result = $stmt->execute(array($catid)); + if (OC_DB::isError($result)) { + OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR); + return false; + } + } catch(Exception $e) { + OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), + OCP\Util::ERROR); + return false; + } + + if(!is_null($result)) { + while( $row = $result->fetchRow()) { + $items[] = $row; + } + } + //OCP\Util::writeLog('core', __METHOD__.', count: ' . count($items), OCP\Util::DEBUG); + //OCP\Util::writeLog('core', __METHOD__.', sql: ' . $sql, OCP\Util::DEBUG); + + return $items; } /** @@ -84,22 +296,51 @@ class OC_VCategories { } /** - * @brief Add a new category name. + * @brief Add a new category. + * @param $name A string with a name of the category + * @returns int the id of the added category or false if it already exists. + */ + public function add($name) { + OCP\Util::writeLog('core', __METHOD__.', name: ' . $name, OCP\Util::DEBUG); + if($this->hasCategory($name)) { + 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, + )); + $id = OCP\DB::insertid(self::CATEGORY_TABLE); + OCP\Util::writeLog('core', __METHOD__.', id: ' . $id, OCP\Util::DEBUG); + $this->categories[$id] = $name; + return $id; + } + + /** + * @brief Add a new category. * @param $names A string with a name or an array of strings containing * the name(s) of the categor(y|ies) to add. * @param $sync bool When true, save the categories + * @param $id int Optional object id to add to this|these categor(y|ies) * @returns bool Returns false on error. */ - public function add($names, $sync=false) { + public function addMulti($names, $sync=false, $id = null) { if(!is_array($names)) { $names = array($names); } $names = array_map('trim', $names); $newones = array(); foreach($names as $name) { - if(($this->in_arrayi($name, $this->categories) == false) && $name != '') { + if(($this->in_arrayi( + $name, $this->categories) == false) && $name != '') { $newones[] = $name; } + if(!is_null($id) ) { + // Insert $objectid, $categoryid pairs if not exist. + self::$relations[] = array('objid' => $id, 'category' => $name); + } } if(count($newones) > 0) { $this->categories = array_merge($this->categories, $newones); @@ -114,8 +355,8 @@ class OC_VCategories { * @brief Extracts categories from a vobject and add the ones not already present. * @param $vobject The instance of OC_VObject to load the categories from. */ - public function loadFromVObject($vobject, $sync=false) { - $this->add($vobject->getAsArray('CATEGORIES'), $sync); + public function loadFromVObject($id, $vobject, $sync=false) { + $this->addMulti($vobject->getAsArray('CATEGORIES'), $sync, $id); } /** @@ -128,23 +369,62 @@ class OC_VCategories { * $result = $stmt->execute(); * $objects = array(); * if(!is_null($result)) { - * while( $row = $result->fetchRow()) { - * $objects[] = $row['carddata']; + * while( $row = $result->fetchRow()){ + * $objects[] = array($row['id'], $row['carddata']); * } * } * $categories->rescan($objects); */ public function rescan($objects, $sync=true, $reset=true) { + if($reset === true) { + $result = null; + // Find all objectid/categoryid pairs. + try { + $stmt = OCP\DB::prepare('SELECT `id` FROM `' . self::CATEGORY_TABLE . '` ' + . 'WHERE `uid` = ? AND `type` = ?'); + $result = $stmt->execute(array($this->user, $this->type)); + if (OC_DB::isError($result)) { + OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR); + return false; + } + } catch(Exception $e) { + OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), + OCP\Util::ERROR); + } + + // And delete them. + if(!is_null($result)) { + $stmt = OCP\DB::prepare('DELETE FROM `' . self::RELATION_TABLE . '` ' + . 'WHERE `categoryid` = ? AND `type`= ?'); + while( $row = $result->fetchRow()) { + $stmt->execute(array($row['id'], $this->type)); + } + } + try { + $stmt = OCP\DB::prepare('DELETE FROM `' . self::CATEGORY_TABLE . '` ' + . 'WHERE `uid` = ? AND `type` = ?'); + $result = $stmt->execute(array($this->user, $this->type)); + if (OC_DB::isError($result)) { + OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR); + return; + } + } catch(Exception $e) { + OCP\Util::writeLog('core', __METHOD__ . ', exception: ' + . $e->getMessage(), OCP\Util::ERROR); + return; + } $this->categories = array(); } + // Parse all the VObjects foreach($objects as $object) { - //OC_Log::write('core','OC_VCategories::rescan: '.substr($object, 0, 100).'(...)', OC_Log::DEBUG); - $vobject = OC_VObject::parse($object); + $vobject = OC_VObject::parse($object[1]); if(!is_null($vobject)) { - $this->loadFromVObject($vobject, $sync); + // Load the categories + $this->loadFromVObject($object[0], $vobject, $sync); } else { - OC_Log::write('core','OC_VCategories::rescan, unable to parse. ID: '.', '.substr($object, 0, 100).'(...)', OC_Log::DEBUG); + OC_Log::write('core', __METHOD__ . ', unable to parse. ID: ' . ', ' + . substr($object, 0, 100) . '(...)', OC_Log::DEBUG); } } $this->save(); @@ -155,16 +435,224 @@ class OC_VCategories { */ private function save() { if(is_array($this->categories)) { - usort($this->categories, 'strnatcasecmp'); // usort to also renumber the keys - $escaped_categories = serialize($this->categories); - OC_Preferences::setValue($this->user, $this->app, self::PREF_CATEGORIES_LABEL, $escaped_categories); - OC_Log::write('core','OC_VCategories::save: '.print_r($this->categories, true), OC_Log::DEBUG); + foreach($this->categories as $category) { + OCP\DB::insertIfNotExist(self::CATEGORY_TABLE, + array( + 'uid' => $this->user, + 'type' => $this->type, + 'category' => $category, + )); + } + // reload categories to get the proper ids. + $this->loadCategories(); + // Loop through temporarily cached objectid/categoryname pairs + // and save relations. + $categories = $this->categories; + // For some reason this is needed or array_search(i) will return 0..? + ksort($categories); + foreach(self::$relations as $relation) { + $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, + )); + } + } + self::$relations = array(); // reset } else { - OC_Log::write('core','OC_VCategories::save: $this->categories is not an array! '.print_r($this->categories, true), OC_Log::ERROR); + OC_Log::write('core', __METHOD__.', $this->categories is not an array! ' + . print_r($this->categories, true), OC_Log::ERROR); } } /** + * @brief Delete categories and category/object relations for a user. + * For hooking up on post_deleteUser + * @param string $uid The user id for which entries should be purged. + */ + public static function post_deleteUser($arguments) { + // Find all objectid/categoryid pairs. + $result = null; + try { + $stmt = OCP\DB::prepare('SELECT `id` FROM `' . self::CATEGORY_TABLE . '` ' + . 'WHERE `uid` = ?'); + $result = $stmt->execute(array($arguments['uid'])); + if (OC_DB::isError($result)) { + 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(), + OCP\Util::ERROR); + } + + if(!is_null($result)) { + try { + $stmt = OCP\DB::prepare('DELETE FROM `' . self::RELATION_TABLE . '` ' + . 'WHERE `categoryid` = ?'); + while( $row = $result->fetchRow()) { + try { + $stmt->execute(array($row['id'])); + } catch(Exception $e) { + OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), + OCP\Util::ERROR); + } + } + } catch(Exception $e) { + OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), + OCP\Util::ERROR); + } + } + try { + $stmt = OCP\DB::prepare('DELETE FROM `' . self::CATEGORY_TABLE . '` ' + . 'WHERE `uid` = ? AND'); + $result = $stmt->execute(array($arguments['uid'])); + if (OC_DB::isError($result)) { + 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(), OCP\Util::ERROR); + } + } + + /** + * @brief Delete category/object relations from the db + * @param int $id The id of the object + * @param string $type The type of object (event/contact/task/journal). + * Defaults to the type set in the instance + * @returns boolean Returns false on error. + */ + public function purgeObject($id, $type = null) { + $type = is_null($type) ? $this->type : $type; + try { + $stmt = OCP\DB::prepare('DELETE FROM `' . self::RELATION_TABLE . '` ' + . 'WHERE `objid` = ? AND `type`= ?'); + $result = $stmt->execute(array($id, $type)); + if (OC_DB::isError($result)) { + OC_Log::write('core', __METHOD__. 'DB error: ' . OC_DB::getErrorMessage($result), OC_Log::ERROR); + return false; + } + } catch(Exception $e) { + OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), + OCP\Util::ERROR); + return false; + } + return true; + } + + /** + * Get favorites for an object type + * + * @param string $type The type of object (event/contact/task/journal). + * Defaults to the type set in the instance + * @returns array An array of object ids. + */ + public function getFavorites($type = null) { + $type = is_null($type) ? $this->type : $type; + + try { + return $this->idsForCategory(self::CATEGORY_FAVORITE); + } catch(Exception $e) { + // No favorites + return array(); + } + } + + /** + * Add an object to favorites + * + * @param int $objid The id of the object + * @param string $type The type of object (event/contact/task/journal). + * Defaults to the type set in the instance + * @returns boolean + */ + public function addToFavorites($objid, $type = null) { + $type = is_null($type) ? $this->type : $type; + if(!$this->hasCategory(self::CATEGORY_FAVORITE)) { + $this->add(self::CATEGORY_FAVORITE, true); + } + return $this->addToCategory($objid, self::CATEGORY_FAVORITE, $type); + } + + /** + * Remove an object from favorites + * + * @param int $objid The id of the object + * @param string $type The type of object (event/contact/task/journal). + * Defaults to the type set in the instance + * @returns boolean + */ + public function removeFromFavorites($objid, $type = null) { + $type = is_null($type) ? $this->type : $type; + return $this->removeFromCategory($objid, self::CATEGORY_FAVORITE, $type); + } + + /** + * @brief Creates a category/object relation. + * @param int $objid The id of the object + * @param int|string $category The id or name of the category + * @param string $type The type of object (event/contact/task/journal). + * Defaults to the type set in the instance + * @returns boolean Returns false on database error. + */ + public function addToCategory($objid, $category, $type = null) { + $type = is_null($type) ? $this->type : $type; + if(is_string($category) && !is_numeric($category)) { + if(!$this->hasCategory($category)) { + $this->add($category, true); + } + $categoryid = $this->array_searchi($category, $this->categories); + } else { + $categoryid = $category; + } + try { + OCP\DB::insertIfNotExist(self::RELATION_TABLE, + array( + 'objid' => $objid, + 'categoryid' => $categoryid, + 'type' => $type, + )); + } catch(Exception $e) { + OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), + OCP\Util::ERROR); + return false; + } + return true; + } + + /** + * @brief Delete single category/object relation from the db + * @param int $objid The id of the object + * @param int|string $category The id or name of the category + * @param string $type The type of object (event/contact/task/journal). + * Defaults to the type set in the instance + * @returns boolean + */ + public function removeFromCategory($objid, $category, $type = null) { + $type = is_null($type) ? $this->type : $type; + $categoryid = (is_string($category) && !is_numeric($category)) + ? $this->array_searchi($category, $this->categories) + : $category; + try { + $sql = 'DELETE FROM `' . self::RELATION_TABLE . '` ' + . 'WHERE `objid` = ? AND `categoryid` = ? AND `type` = ?'; + OCP\Util::writeLog('core', __METHOD__.', sql: ' . $objid . ' ' . $categoryid . ' ' . $type, + OCP\Util::DEBUG); + $stmt = OCP\DB::prepare($sql); + $stmt->execute(array($objid, $categoryid, $type)); + } catch(Exception $e) { + OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), + OCP\Util::ERROR); + return false; + } + return true; + } + + /** * @brief Delete categories from the db and from all the vobject supplied * @param $names An array of categories to delete * @param $objects An array of arrays with [id,vobject] (as text) pairs suitable for updating the apps object table. @@ -173,37 +661,87 @@ class OC_VCategories { if(!is_array($names)) { $names = array($names); } - OC_Log::write('core','OC_VCategories::delete, before: '.print_r($this->categories, true), OC_Log::DEBUG); + + OC_Log::write('core', __METHOD__ . ', before: ' + . print_r($this->categories, true), OC_Log::DEBUG); foreach($names as $name) { - OC_Log::write('core','OC_VCategories::delete: '.$name, OC_Log::DEBUG); + $id = null; + OC_Log::write('core', __METHOD__.', '.$name, OC_Log::DEBUG); if($this->hasCategory($name)) { - //OC_Log::write('core','OC_VCategories::delete: '.$name.' got it', OC_Log::DEBUG); - unset($this->categories[$this->array_searchi($name, $this->categories)]); + $id = $this->array_searchi($name, $this->categories); + unset($this->categories[$id]); + } + try { + $stmt = OCP\DB::prepare('DELETE FROM `' . self::CATEGORY_TABLE . '` WHERE ' + . '`uid` = ? AND `type` = ? AND `category` = ?'); + $result = $stmt->execute(array($this->user, $this->type, $name)); + if (OC_DB::isError($result)) { + 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(), OCP\Util::ERROR); + } + if(!is_null($id) && $id !== false) { + try { + $sql = 'DELETE FROM `' . self::RELATION_TABLE . '` ' + . 'WHERE `categoryid` = ?'; + $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); + } + } catch(Exception $e) { + OCP\Util::writeLog('core', __METHOD__.', exception: '.$e->getMessage(), + OCP\Util::ERROR); + return false; + } } } - $this->save(); - OC_Log::write('core','OC_VCategories::delete, after: '.print_r($this->categories, true), OC_Log::DEBUG); + OC_Log::write('core', __METHOD__.', after: ' + . print_r($this->categories, true), OC_Log::DEBUG); if(!is_null($objects)) { foreach($objects as $key=>&$value) { $vobject = OC_VObject::parse($value[1]); if(!is_null($vobject)) { - $categories = $vobject->getAsArray('CATEGORIES'); - //OC_Log::write('core','OC_VCategories::delete, before: '.$key.': '.print_r($categories, true), OC_Log::DEBUG); + $object = null; + $componentname = ''; + if (isset($vobject->VEVENT)) { + $object = $vobject->VEVENT; + $componentname = 'VEVENT'; + } else + if (isset($vobject->VTODO)) { + $object = $vobject->VTODO; + $componentname = 'VTODO'; + } else + if (isset($vobject->VJOURNAL)) { + $object = $vobject->VJOURNAL; + $componentname = 'VJOURNAL'; + } else { + $object = $vobject; + } + $categories = $object->getAsArray('CATEGORIES'); foreach($names as $name) { $idx = $this->array_searchi($name, $categories); - //OC_Log::write('core','OC_VCategories::delete, loop: '.$name.', '.print_r($idx, true), OC_Log::DEBUG); if($idx !== false) { - OC_Log::write('core','OC_VCategories::delete, unsetting: '.$categories[$this->array_searchi($name, $categories)], OC_Log::DEBUG); + OC_Log::write('core', __METHOD__ + .', unsetting: ' + . $categories[$this->array_searchi($name, $categories)], + OC_Log::DEBUG); unset($categories[$this->array_searchi($name, $categories)]); - //unset($categories[$idx]); } } - //OC_Log::write('core','OC_VCategories::delete, after: '.$key.': '.print_r($categories, true), OC_Log::DEBUG); - $vobject->setString('CATEGORIES', implode(',', $categories)); + + $object->setString('CATEGORIES', implode(',', $categories)); + if($vobject !== $object) { + $vobject[$componentname] = $object; + } $value[1] = $vobject->serialize(); $objects[$key] = $value; } else { - OC_Log::write('core','OC_VCategories::delete, unable to parse. ID: '.$value[0].', '.substr($value[1], 0, 50).'(...)', OC_Log::DEBUG); + OC_Log::write('core', __METHOD__ + .', unable to parse. ID: ' . $value[0] . ', ' + . substr($value[1], 0, 50) . '(...)', OC_Log::DEBUG); } } } @@ -222,7 +760,7 @@ class OC_VCategories { if(!is_array($haystack)) { return false; } - return array_search(strtolower($needle), array_map('strtolower',$haystack)); + return array_search(strtolower($needle), array_map('strtolower', $haystack)); } - } + diff --git a/lib/vobject.php b/lib/vobject.php index 2ccf8eda685..267176ebc07 100644 --- a/lib/vobject.php +++ b/lib/vobject.php @@ -24,11 +24,11 @@ * This class provides a streamlined interface to the Sabre VObject classes */ class OC_VObject{ - /** @var Sabre_VObject_Component */ + /** @var Sabre\VObject\Component */ protected $vobject; /** - * @returns Sabre_VObject_Component + * @returns Sabre\VObject\Component */ public function getVObject() { return $this->vobject; @@ -41,9 +41,9 @@ class OC_VObject{ */ public static function parse($data) { try { - Sabre_VObject_Property::$classMap['LAST-MODIFIED'] = 'Sabre_VObject_Property_DateTime'; - $vobject = Sabre_VObject_Reader::read($data); - if ($vobject instanceof Sabre_VObject_Component) { + Sabre\VObject\Property::$classMap['LAST-MODIFIED'] = 'Sabre\VObject\Property\DateTime'; + $vobject = Sabre\VObject\Reader::read($data); + if ($vobject instanceof Sabre\VObject\Component) { $vobject = new OC_VObject($vobject); } return $vobject; @@ -89,13 +89,13 @@ class OC_VObject{ /** * Constuctor - * @param Sabre_VObject_Component or string + * @param Sabre\VObject\Component or string */ public function __construct($vobject_or_name) { if (is_object($vobject_or_name)) { $this->vobject = $vobject_or_name; } else { - $this->vobject = new Sabre_VObject_Component($vobject_or_name); + $this->vobject = new Sabre\VObject\Component($vobject_or_name); } } @@ -117,9 +117,9 @@ class OC_VObject{ if(is_array($value)) { $value = OC_VObject::escapeSemicolons($value); } - $property = new Sabre_VObject_Property( $name, $value ); + $property = new Sabre\VObject\Property( $name, $value ); foreach($parameters as $name => $value) { - $property->parameters[] = new Sabre_VObject_Parameter($name, $value); + $property->parameters[] = new Sabre\VObject\Parameter($name, $value); } $this->vobject->add($property); @@ -150,12 +150,12 @@ class OC_VObject{ * @param int $dateType * @return void */ - public function setDateTime($name, $datetime, $dateType=Sabre_VObject_Property_DateTime::LOCALTZ) { + public function setDateTime($name, $datetime, $dateType=Sabre\VObject\Property\DateTime::LOCALTZ) { if ($datetime == 'now') { $datetime = new DateTime(); } if ($datetime instanceof DateTime) { - $datetime_element = new Sabre_VObject_Property_DateTime($name); + $datetime_element = new Sabre\VObject\Property\DateTime($name); $datetime_element->setDateTime($datetime, $dateType); $this->vobject->__set($name, $datetime_element); }else{ @@ -183,7 +183,7 @@ class OC_VObject{ return $this->vobject->children; } $return = $this->vobject->__get($name); - if ($return instanceof Sabre_VObject_Component) { + if ($return instanceof Sabre\VObject\Component) { $return = new OC_VObject($return); } return $return; @@ -201,7 +201,7 @@ class OC_VObject{ return $this->vobject->__isset($name); } - public function __call($function,$arguments) { + public function __call($function, $arguments) { return call_user_func_array(array($this->vobject, $function), $arguments); } } |