diff options
author | Brice Maron <brice@bmaron.net> | 2012-06-21 17:15:35 +0000 |
---|---|---|
committer | Brice Maron <brice@bmaron.net> | 2012-06-21 17:15:35 +0000 |
commit | e5c56b2433b1987e4b6b8020e01f4da03623c4b8 (patch) | |
tree | a650870f7bbc497833b8ea00051f9046e1779f5e /lib | |
parent | df83df5263db57056d0bd70edfa3b28e7b5e6b6b (diff) | |
parent | 6707e4187e4c1186eff8dfe06999c4539ab80de7 (diff) | |
download | nextcloud-server-e5c56b2433b1987e4b6b8020e01f4da03623c4b8.tar.gz nextcloud-server-e5c56b2433b1987e4b6b8020e01f4da03623c4b8.zip |
Merge branch 'master' into multi_app_dir
Conflicts:
lib/app.php
lib/base.php
lib/minimizer/css.php
lib/minimizer/js.php
lib/template.php
lib/util.php
Diffstat (limited to 'lib')
-rwxr-xr-x | lib/app.php | 30 | ||||
-rw-r--r-- | lib/base.php | 61 | ||||
-rw-r--r-- | lib/cache/fileglobal.php | 78 | ||||
-rw-r--r-- | lib/connector/sabre/directory.php | 49 | ||||
-rw-r--r-- | lib/connector/sabre/file.php | 7 | ||||
-rw-r--r-- | lib/connector/sabre/node.php | 56 | ||||
-rw-r--r-- | lib/filecache.php | 432 | ||||
-rw-r--r-- | lib/filecache/cached.php | 70 | ||||
-rw-r--r-- | lib/filecache/update.php | 215 | ||||
-rw-r--r-- | lib/fileproxy/quota.php | 11 | ||||
-rw-r--r-- | lib/files.php | 7 | ||||
-rw-r--r-- | lib/filestorage.php | 9 | ||||
-rw-r--r-- | lib/filestorage/common.php | 9 | ||||
-rw-r--r-- | lib/filestorage/local.php | 9 | ||||
-rw-r--r-- | lib/filesystem.php | 15 | ||||
-rw-r--r-- | lib/filesystemview.php | 13 | ||||
-rw-r--r-- | lib/helper.php | 6 | ||||
-rw-r--r-- | lib/l10n.php | 63 | ||||
-rw-r--r-- | lib/l10n/string.php | 25 | ||||
-rw-r--r-- | lib/migrate.php | 40 | ||||
-rw-r--r-- | lib/mimetypes.fixlist.php | 3 | ||||
-rw-r--r-- | lib/minimizer.php | 35 | ||||
-rw-r--r-- | lib/minimizer/css.php | 52 | ||||
-rw-r--r-- | lib/minimizer/js.php | 52 | ||||
-rw-r--r-- | lib/public/util.php | 12 | ||||
-rw-r--r-- | lib/request.php | 28 | ||||
-rw-r--r-- | lib/template.php | 209 | ||||
-rw-r--r-- | lib/templatelayout.php | 170 | ||||
-rw-r--r-- | lib/user.php | 8 | ||||
-rwxr-xr-x | lib/util.php | 151 |
30 files changed, 1061 insertions, 864 deletions
diff --git a/lib/app.php b/lib/app.php index 1dcccee1da0..1a2dc370d69 100755 --- a/lib/app.php +++ b/lib/app.php @@ -536,32 +536,33 @@ class OC_App{ $currentVersion=OC_App::getAppVersion($app); if ($currentVersion) { if (version_compare($currentVersion, $installedVersion, '>')) { - OC_Log::write($app,'starting app upgrade from '.$installedVersion.' to '.$currentVersion,OC_Log::DEBUG); + OC_Log::write($app, 'starting app upgrade from '.$installedVersion.' to '.$currentVersion,OC_Log::DEBUG); OC_App::updateApp($app); - OC_Appconfig::setValue($app,'installed_version',OC_App::getAppVersion($app)); + OC_Appconfig::setValue($app, 'installed_version', OC_App::getAppVersion($app)); } } } + } - // check if the current enabled apps are compatible with the current ownCloud version. disable them if not. - // this is important if you upgrade ownCloud and have non ported 3rd party apps installed - $apps =OC_App::getEnabledApps(); - $version=OC_Util::getVersion(); + /** + * check if the current enabled apps are compatible with the current + * ownCloud version. disable them if not. + * This is important if you upgrade ownCloud and have non ported 3rd + * party apps installed. + */ + public static function checkAppsRequirements($apps = array()){ + if (empty($apps)) { + $apps = OC_App::getEnabledApps(); + } + $version = OC_Util::getVersion(); foreach($apps as $app) { - // check if the app is compatible with this version of ownCloud - $info=OC_App::getAppInfo($app); + $info = OC_App::getAppInfo($app); if(!isset($info['require']) or ($version[0]>$info['require'])){ OC_Log::write('core','App "'.$info['name'].'" can\'t be used because it is not compatible with this version of ownCloud',OC_Log::ERROR); OC_App::disable( $app ); } - - - } - - - } /** @@ -589,6 +590,7 @@ class OC_App{ return; } if(file_exists(self::getAppPath($appid).'/appinfo/update.php')){ + self::loadApp($appid); include self::getAppPath($appid).'/appinfo/update.php'; } diff --git a/lib/base.php b/lib/base.php index a0f5e83dd47..2f16f7dab4c 100644 --- a/lib/base.php +++ b/lib/base.php @@ -43,10 +43,6 @@ class OC{ */ public static $WEBROOT = ''; /** - * the folder that stores that data files for the filesystem of the user (e.g. /srv/http/owncloud/data/myusername/files) - */ - public static $CONFIG_DATADIRECTORY = ''; - /** * The installation path of the 3rdparty folder on the server (e.g. /srv/http/owncloud/3rdparty) */ public static $THIRDPARTYROOT = ''; @@ -91,34 +87,8 @@ class OC{ } } - /** - * autodetects the formfactor of the used device - * default -> the normal desktop browser interface - * mobile -> interface for smartphones - * tablet -> interface for tablets - * standalone -> the default interface but without header, footer and sidebar. just the application. useful to ue just a specific app on the desktop in a standalone window. - */ - 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) { - $mode='tablet'; - }elseif(stripos($_SERVER['HTTP_USER_AGENT'],'iphone')>0){ - $mode='mobile'; - }elseif((stripos($_SERVER['HTTP_USER_AGENT'],'N9')>0) and (stripos($_SERVER['HTTP_USER_AGENT'],'nokia')>0)){ - $mode='mobile'; - }else{ - $mode='default'; - } - }else{ - $mode='default'; - } - return($mode); - } - public static function initPaths(){ - // calculate the documentroot - $DOCUMENTROOT=realpath($_SERVER['DOCUMENT_ROOT']); + // calculate the root directories OC::$SERVERROOT=str_replace("\\",'/',substr(__FILE__,0,-13)); OC::$SUBURI= str_replace("\\","/",substr(realpath($_SERVER["SCRIPT_FILENAME"]),strlen(OC::$SERVERROOT))); $scriptName=$_SERVER["SCRIPT_NAME"]; @@ -133,9 +103,6 @@ class OC{ } } OC::$WEBROOT=substr($scriptName,0,strlen($scriptName)-strlen(OC::$SUBURI)); - // try a new way to detect the WEBROOT which is simpler and also works with the app directory outside the owncloud folder. letÂīs see if this works for everybody -// OC::$WEBROOT=substr(OC::$SERVERROOT,strlen($DOCUMENTROOT)); - if(OC::$WEBROOT!='' and OC::$WEBROOT[0]!=='/'){ OC::$WEBROOT='/'.OC::$WEBROOT; @@ -234,6 +201,7 @@ class OC{ } OC_Config::setValue('version',implode('.',OC_Util::getVersion())); + OC_App::checkAppsRequirements(); } OC_App::updateApps(); @@ -241,15 +209,6 @@ class OC{ } public static function initTemplateEngine() { - // if the formfactor is not yet autodetected do the autodetection now. For possible forfactors check the detectFormfactor documentation - if(!isset($_SESSION['formfactor'])){ - $_SESSION['formfactor']=OC::detectFormfactor(); - } - // allow manual override via GET parameter - if(isset($_GET['formfactor'])){ - $_SESSION['formfactor']=$_GET['formfactor']; - } - // Add the stuff we need always OC_Util::addScript( "jquery-1.7.2.min" ); OC_Util::addScript( "jquery-ui-1.8.16.custom.min" ); @@ -286,7 +245,7 @@ class OC{ 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))); + $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); @@ -388,28 +347,14 @@ class OC{ exit; } - // TODO: we should get rid of this one, too - // WARNING: to make everything even more confusing, - // DATADIRECTORY is a var that changes and DATADIRECTORY_ROOT - // stays the same, but is set by "datadirectory". - // Any questions? - OC::$CONFIG_DATADIRECTORY = OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" ); - // User and Groups if( !OC_Config::getValue( "installed", false )){ $_SESSION['user_id'] = ''; } - OC_User::useBackend( OC_Config::getValue( "userbackend", "database" )); OC_Group::useBackend(new OC_Group_Database()); - // Set up file system unless forbidden - global $RUNTIME_NOSETUPFS; - if(!$RUNTIME_NOSETUPFS ){ - OC_Util::setupFS(); - } - // Load Apps // This includes plugins for users and filesystems as well global $RUNTIME_NOAPPS; diff --git a/lib/cache/fileglobal.php b/lib/cache/fileglobal.php new file mode 100644 index 00000000000..1c2c9bdc82d --- /dev/null +++ b/lib/cache/fileglobal.php @@ -0,0 +1,78 @@ +<?php +/** + * Copyright (c) 2012 Bart Visscher <bartv@thisnet.nl> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + + +class OC_Cache_FileGlobal{ + protected function getCacheDir() { + $cache_dir = get_temp_dir().'/owncloud-'.OC_Util::getInstanceId().'/'; + if (!is_dir($cache_dir)) { + mkdir($cache_dir); + } + return $cache_dir; + } + + protected function fixKey($key) { + return str_replace('/', '_', $key); + } + + public function get($key) { + $key = $this->fixKey($key); + if ($this->hasKey($key)) { + $cache_dir = $this->getCacheDir(); + return file_get_contents($cache_dir.$key); + } + return null; + } + + public function set($key, $value, $ttl=0) { + $key = $this->fixKey($key); + $cache_dir = $this->getCacheDir(); + if ($cache_dir and file_put_contents($cache_dir.$key, $value)) { + if ($ttl === 0) { + $ttl = 86400; // 60*60*24 + } + return touch($cache_dir.$key, time() + $ttl); + } + return false; + } + + public function hasKey($key) { + $key = $this->fixKey($key); + $cache_dir = $this->getCacheDir(); + if ($cache_dir && is_file($cache_dir.$key)) { + $mtime = filemtime($cache_dir.$key); + if ($mtime < time()) { + unlink($cache_dir.$key); + return false; + } + return true; + } + return false; + } + + public function remove($key) { + $cache_dir = $this->getCacheDir(); + if(!$cache_dir){ + return false; + } + $key = $this->fixKey($key); + return unlink($cache_dir.$key); + } + + public function clear(){ + $cache_dir = $this->getCacheDir(); + if($cache_dir and is_dir($cache_dir)){ + $dh=opendir($cache_dir); + while($file=readdir($dh)){ + if($file!='.' and $file!='..'){ + unlink($cache_dir.$file); + } + } + } + } +} diff --git a/lib/connector/sabre/directory.php b/lib/connector/sabre/directory.php index e74d832cb00..9832449af3a 100644 --- a/lib/connector/sabre/directory.php +++ b/lib/connector/sabre/directory.php @@ -59,22 +59,23 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa * @throws Sabre_DAV_Exception_FileNotFound * @return Sabre_DAV_INode */ - public function getChild($name) { + public function getChild($name, $info = null) { $path = $this->path . '/' . $name; + if (is_null($info)) { + $info = OC_FileCache::get($path); + } - if (!OC_Filesystem::file_exists($path)) throw new Sabre_DAV_Exception_NotFound('File with name ' . $path . ' could not be located'); - - if (OC_Filesystem::is_dir($path)) { - - return new OC_Connector_Sabre_Directory($path); + if (!$info) throw new Sabre_DAV_Exception_NotFound('File with name ' . $path . ' could not be located'); + if ($info['mimetype'] == 'httpd/unix-directory') { + $node = new OC_Connector_Sabre_Directory($path); } else { - - return new OC_Connector_Sabre_File($path); - + $node = new OC_Connector_Sabre_File($path); } + $node->setFileinfoCache($info); + return $node; } /** @@ -84,18 +85,30 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa */ public function getChildren() { + $folder_content = OC_FileCache::getFolderContent($this->path); + $paths = array(); + foreach($folder_content as $info) { + $paths[] = $this->path.'/'.$info['name']; + } + $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 ); + $properties = array_fill_keys($paths, array()); + while($row = $result->fetchRow()) { + $propertypath = $row['propertypath']; + $propertyname = $row['propertyname']; + $propertyvalue = $row['propertyvalue']; + $properties[$propertypath][$propertyname] = $propertyvalue; + } + $nodes = array(); - // foreach(scandir($this->path) as $node) if($node!='.' && $node!='..') $nodes[] = $this->getChild($node); - if( OC_Filesystem::is_dir($this->path . '/')){ - $dh = OC_Filesystem::opendir($this->path . '/'); - while(( $node = readdir($dh)) !== false ){ - if($node!='.' && $node!='..'){ - $nodes[] = $this->getChild($node); - } - } + foreach($folder_content as $info) { + $node = $this->getChild($info['name'], $info); + $node->setPropertyCache($properties[$this->path.'/'.$info['name']]); + $nodes[] = $node; } return $nodes; - } /** diff --git a/lib/connector/sabre/file.php b/lib/connector/sabre/file.php index 3ba1b3355f2..dd25df78c29 100644 --- a/lib/connector/sabre/file.php +++ b/lib/connector/sabre/file.php @@ -63,8 +63,8 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D * @return int */ public function getSize() { - $this->stat(); - return $this->stat_cache['size']; + $this->getFileinfoCache(); + return $this->fileinfo_cache['size']; } @@ -92,6 +92,9 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D * @return mixed */ public function getContentType() { + if (isset($this->fileinfo_cache['mimetype'])) { + return $this->fileinfo_cache['mimetype']; + } return OC_Filesystem::getMimeType($this->path); diff --git a/lib/connector/sabre/node.php b/lib/connector/sabre/node.php index e7bcea3171d..be315a0ffd9 100644 --- a/lib/connector/sabre/node.php +++ b/lib/connector/sabre/node.php @@ -30,10 +30,15 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr */ protected $path; /** - * file stat cache + * node fileinfo cache * @var array */ - protected $stat_cache; + protected $fileinfo_cache; + /** + * node properties cache + * @var array + */ + protected $property_cache = null; /** * Sets up the node, expects a full path name @@ -82,23 +87,38 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr } + public function setFileinfoCache($fileinfo_cache) + { + $this->fileinfo_cache = $fileinfo_cache; + } + /** - * Set the stat cache + * Make sure the fileinfo cache is filled. Uses OC_FileCache or a direct stat */ - protected function stat() { - if (!isset($this->stat_cache)) { - $this->stat_cache = OC_Filesystem::stat($this->path); + protected function getFileinfoCache() { + if (!isset($this->fileinfo_cache)) { + if ($fileinfo_cache = OC_FileCache::get($this->path)) { + } else { + $fileinfo_cache = OC_Filesystem::stat($this->path); + } + + $this->fileinfo_cache = $fileinfo_cache; } } + public function setPropertyCache($property_cache) + { + $this->property_cache = $property_cache; + } + /** * Returns the last modification time, as a unix timestamp * * @return int */ public function getLastModified() { - $this->stat(); - return $this->stat_cache['mtime']; + $this->getFileinfoCache(); + return $this->fileinfo_cache['mtime']; } @@ -129,7 +149,7 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr } } else { - if( strcmp( $propertyName, "lastmodified")) { + if( strcmp( $propertyName, "lastmodified") === 0) { $this->touch($propertyValue); } else { if(!array_key_exists( $propertyName, $existing )){ @@ -143,6 +163,7 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr } } + $this->setPropertyCache(null); return true; } @@ -158,23 +179,24 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr * @return void */ function getProperties($properties) { - // At least some magic in here :-) - $query = OC_DB::prepare( 'SELECT * FROM *PREFIX*properties WHERE userid = ? AND propertypath = ?' ); - $result = $query->execute( array( OC_User::getUser(), $this->path )); + if (is_null($this->property_cache)) { + $query = OC_DB::prepare( 'SELECT * FROM *PREFIX*properties WHERE userid = ? AND propertypath = ?' ); + $result = $query->execute( array( OC_User::getUser(), $this->path )); - $existing = array(); - while( $row = $result->fetchRow()){ - $existing[$row['propertyname']] = $row['propertyvalue']; + $this->property_cache = array(); + while( $row = $result->fetchRow()){ + $this->property_cache[$row['propertyname']] = $row['propertyvalue']; + } } // if the array was empty, we need to return everything if(count($properties) == 0){ - return $existing; + return $this->property_cache; } $props = array(); foreach($properties as $property) { - if (isset($existing[$property])) $props[$property] = $existing[$property]; + if (isset($this->property_cache[$property])) $props[$property] = $this->property_cache[$property]; } return $props; } diff --git a/lib/filecache.php b/lib/filecache.php index 3fb8e4113cb..e3bcc7d0000 100644 --- a/lib/filecache.php +++ b/lib/filecache.php @@ -28,15 +28,13 @@ * It will try to keep the data up to date but changes from outside ownCloud can invalidate the cache */ class OC_FileCache{ - private static $savedData=array(); - /** * get the filesystem info from the cache * @param string path * @param string root (optional) * @return array * - * returns an assiciative array with the following keys: + * returns an associative array with the following keys: * - size * - mtime * - ctime @@ -44,29 +42,15 @@ class OC_FileCache{ * - encrypted * - versioned */ - public static function get($path,$root=''){ - if(self::isUpdated($path,$root)){ - if(!$root){//filesystem hooks are only valid for the default root + 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)); }else{ - self::fileSystemWatcherWrite(array('path'=>$path),$root); + OC_FileCache_Update::update($path,$root); } } - if(!$root){ - $root=OC_Filesystem::getRoot(); - } - if($root=='/'){ - $root=''; - } - $path=$root.$path; - $query=OC_DB::prepare('SELECT ctime,mtime,mimetype,size,encrypted,versioned,writable FROM *PREFIX*fscache WHERE path_hash=?'); - $result=$query->execute(array(md5($path)))->fetchRow(); - if(is_array($result)){ - return $result; - }else{ - OC_Log::write('files','get(): file not found in cache ('.$path.')',OC_Log::DEBUG); - return false; - } + return OC_FileCache_Cached::get($path,$root); } /** @@ -77,30 +61,23 @@ class OC_FileCache{ * * $data is an assiciative array in the same format as returned by get */ - public static function put($path,$data,$root=''){ - if(!$root){ + public static function put($path,$data,$root=false){ + if($root===false){ $root=OC_Filesystem::getRoot(); } - if($root=='/'){ - $root=''; - } $path=$root.$path; - if($path=='/'){ - $parent=-1; - }else{ - $parent=self::getFileId(dirname($path)); + $parent=self::getParentId($path); + $id=self::getId($path,''); + if(isset(OC_FileCache_Cached::$savedData[$path])){ + $data=array_merge(OC_FileCache_Cached::$savedData[$path],$data); + unset(OC_FileCache_Cached::$savedData[$path]); } - $id=self::getFileId($path); if($id!=-1){ self::update($id,$data); return; } - if(isset(self::$savedData[$path])){ - $data=array_merge($data,self::$savedData[$path]); - unset(self::$savedData[$path]); - } if(!isset($data['size']) or !isset($data['mtime'])){//save incomplete data for the next time we write it - self::$savedData[$path]=$data; + OC_FileCache_Cached::$savedData[$path]=$data; return; } if(!isset($data['encrypted'])){ @@ -157,13 +134,10 @@ class OC_FileCache{ * @param string newPath * @param string root (optional) */ - public static function move($oldPath,$newPath,$root=''){ - if(!$root){ + public static function move($oldPath,$newPath,$root=false){ + if($root===false){ $root=OC_Filesystem::getRoot(); } - if($root=='/'){ - $root=''; - } $oldPath=$root.$oldPath; $newPath=$root.$newPath; $newParent=self::getParentId($newPath); @@ -182,28 +156,19 @@ class OC_FileCache{ /** * delete info from the cache - * @param string/int $file + * @param string path * @param string root (optional) */ - public static function delete($file,$root=''){ - if(!is_numeric($file)){ - if(!$root){ - $root=OC_Filesystem::getRoot(); - } - if($root=='/'){ - $root=''; - } - $path=$root.$file; - self::delete(self::getFileId($path)); - }elseif($file!=-1){ - $query=OC_DB::prepare('SELECT id FROM *PREFIX*fscache WHERE parent=?'); - $result=$query->execute(array($file)); - while($child=$result->fetchRow()){ - self::delete(intval($child['id'])); - } - $query=OC_DB::prepare('DELETE FROM *PREFIX*fscache WHERE id=?'); - $query->execute(array($file)); + public static function delete($path,$root=false){ + if($root===false){ + $root=OC_Filesystem::getRoot(); } + $query=OC_DB::prepare('DELETE FROM *PREFIX*fscache WHERE path_hash=?'); + $query->execute(array(md5($root.$path))); + + //delete everything inside the folder + $query=OC_DB::prepare('DELETE FROM *PREFIX*fscache WHERE path LIKE ?'); + $query->execute(array($root.$path.'/%')); } /** @@ -213,13 +178,10 @@ class OC_FileCache{ * @param string root (optional) * @return array of filepaths */ - public static function search($search,$returnData=false,$root=''){ - if(!$root){ + public static function search($search,$returnData=false,$root=false){ + if($root===false){ $root=OC_Filesystem::getRoot(); } - if($root=='/'){ - $root=''; - } $rootLen=strlen($root); if(!$returnData){ $query=OC_DB::prepare('SELECT path FROM *PREFIX*fscache WHERE name LIKE ? AND `user`=?'); @@ -254,26 +216,11 @@ class OC_FileCache{ * - encrypted * - versioned */ - public static function getFolderContent($path,$root='',$mimetype_filter=''){ - if(self::isUpdated($path,$root)){ - self::updateFolder($path,$root); - } - if(!$root){ - $root=OC_Filesystem::getRoot(); - } - if($root=='/'){ - $root=''; - } - $path=$root.$path; - $parent=self::getFileId($path); - $query=OC_DB::prepare('SELECT name,ctime,mtime,mimetype,size,encrypted,versioned,writable FROM *PREFIX*fscache WHERE parent=? AND (mimetype LIKE ? OR mimetype = ?)'); - $result=$query->execute(array($parent, $mimetype_filter.'%', 'httpd/unix-directory'))->fetchAll(); - if(is_array($result)){ - return $result; - }else{ - OC_Log::write('files','getFolderContent(): file not found in cache ('.$path.')',OC_Log::DEBUG); - return false; + public static function getFolderContent($path,$root=false,$mimetype_filter=''){ + if(OC_FileCache_Update::hasUpdated($path,$root,true)){ + OC_FileCache_Update::updateFolder($path,$root); } + return OC_FileCache_Cached::getFolderContent($path,$root,$mimetype_filter); } /** @@ -282,61 +229,37 @@ class OC_FileCache{ * @param string root (optional) * @return bool */ - public static function inCache($path,$root=''){ - if(!$root){ - $root=OC_Filesystem::getRoot(); - } - if($root=='/'){ - $root=''; - } - $path=$root.$path; - return self::getFileId($path)!=-1; + public static function inCache($path,$root=false){ + return self::getId($path,$root)!=-1; } /** * get the file id as used in the cache - * unlike the public getId, full paths are used here (/usename/files/foo instead of /foo) - * @param string $path + * @param string path + * @param string root (optional) * @return int */ - private static function getFileId($path){ - $query=OC_DB::prepare('SELECT id FROM *PREFIX*fscache WHERE path_hash=?'); - if(OC_DB::isError($query)){ - OC_Log::write('files','error while getting file id of '.$path,OC_Log::ERROR); - return -1; + public static function getId($path,$root=false){ + if($root===false){ + $root=OC_Filesystem::getRoot(); } - $result=$query->execute(array(md5($path))); + + $query=OC_DB::prepare('SELECT id FROM *PREFIX*fscache WHERE path_hash=?'); + $result=$query->execute(array(md5($root.$path))); if(OC_DB::isError($result)){ OC_Log::write('files','error while getting file id of '.$path,OC_Log::ERROR); return -1; } + $result=$result->fetchRow(); if(is_array($result)){ return $result['id']; }else{ - OC_Log::write('files','getFileId(): file not found in cache ('.$path.')',OC_Log::DEBUG); return -1; } } /** - * get the file id as used in the cache - * @param string path - * @param string root (optional) - * @return int - */ - public static function getId($path,$root=''){ - if(!$root){ - $root=OC_Filesystem::getRoot(); - } - if($root=='/'){ - $root=''; - } - $path=$root.$path; - return self::getFileId($path); - } - - /** * get the file path from the id, relative to the home folder of the user * @param int id * @param string user (optional) @@ -366,154 +289,23 @@ class OC_FileCache{ if($path=='/'){ return -1; }else{ - return self::getFileId(dirname($path)); - } - } - - /** - * called when changes are made to files - * @param array $params - * @param string root (optional) - */ - public static function fileSystemWatcherWrite($params,$root=''){ - if(!$root){ - $view=OC_Filesystem::getView(); - }else{ - $view=new OC_FilesystemView(($root=='/')?'':$root); - } - - $path=$params['path']; - $fullPath=$view->getRoot().$path; - $mimetype=$view->getMimeType($path); - $dir=$view->is_dir($path.'/'); - //dont use self::get here, we don't want inifinte loops when a file has changed - $cachedSize=self::getCachedSize($path,$root); - $size=0; - if($dir){ - if(self::inCache($path,$root)){ - $parent=self::getFileId($fullPath); - $query=OC_DB::prepare('SELECT size FROM *PREFIX*fscache WHERE parent=?'); - $result=$query->execute(array($parent)); - while($row=$result->fetchRow()){ - $size+=$row['size']; - } - $mtime=$view->filemtime($path); - $ctime=$view->filectime($path); - $writable=$view->is_writable($path); - self::put($path,array('size'=>$size,'mtime'=>$mtime,'ctime'=>$ctime,'mimetype'=>$mimetype,'writable'=>$writable)); - }else{ - $count=0; - self::scan($path,null,$count,$root); - } - }else{ - $size=self::scanFile($path,$root); - } - self::increaseSize(dirname($fullPath),$size-$cachedSize); - } - - public static function getCached($path,$root=''){ - if(!$root){ - $root=OC_Filesystem::getRoot(); - }else{ - if($root=='/'){ - $root=''; - } - } - $path=$root.$path; - $query=OC_DB::prepare('SELECT ctime,mtime,mimetype,size,encrypted,versioned,writable FROM *PREFIX*fscache WHERE path_hash=?'); - $result=$query->execute(array(md5($path)))->fetchRow(); - if(is_array($result)){ - if(isset(self::$savedData[$path])){ - $result=array_merge($result,self::$savedData[$path]); - } - return $result; - }else{ - OC_Log::write('files','getCached(): file not found in cache ('.$path.')',OC_Log::DEBUG); - if(isset(self::$savedData[$path])){ - return self::$savedData[$path]; - }else{ - return array(); - } + return self::getId(dirname($path),''); } } - private static function getCachedSize($path,$root){ - if(!$root){ - $root=OC_Filesystem::getRoot(); - }else{ - if($root=='/'){ - $root=''; - } - } - $path=$root.$path; - $query=OC_DB::prepare('SELECT size FROM *PREFIX*fscache WHERE path_hash=?'); - $result=$query->execute(array(md5($path))); - if($row=$result->fetchRow()){ - return $row['size']; - }else{//file not in cache - return 0; - } - } - - /** - * called when files are deleted - * @param array $params - * @param string root (optional) - */ - public static function fileSystemWatcherDelete($params,$root=''){ - if(!$root){ - $root=OC_Filesystem::getRoot(); - } - if($root=='/'){ - $root=''; - } - $path=$params['path']; - $fullPath=$root.$path; - if(self::getFileId($fullPath)==-1){ - return; - } - $size=self::getCachedSize($path,$root); - self::increaseSize(dirname($fullPath),-$size); - self::delete($path); - } - - /** - * called when files are deleted - * @param array $params - * @param string root (optional) - */ - public static function fileSystemWatcherRename($params,$root=''){ - if(!$root){ - $root=OC_Filesystem::getRoot(); - } - if($root=='/'){ - $root=''; - } - $oldPath=$params['oldpath']; - $newPath=$params['newpath']; - $fullOldPath=$root.$oldPath; - $fullNewPath=$root.$newPath; - if(($id=self::getFileId($fullOldPath))!=-1){ - $oldSize=self::getCachedSize($oldPath,$root); - }else{ - return; - } - $size=OC_Filesystem::filesize($newPath); - self::increaseSize(dirname($fullOldPath),-$oldSize); - self::increaseSize(dirname($fullNewPath),$oldSize); - self::move($oldPath,$newPath); - } - /** * adjust the size of the parent folders * @param string $path * @param int $sizeDiff + * @param string root (optinal) */ - private static function increaseSize($path,$sizeDiff){ + public static function increaseSize($path,$sizeDiff, $root=false){ if($sizeDiff==0) return; - while(($id=self::getFileId($path))!=-1){//walk up the filetree increasing the size of all parent folders + $id=self::getId($path,''); + 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); $path=dirname($path); } } @@ -525,15 +317,15 @@ class OC_FileCache{ * @param int count (optional) * @param string root (optionak) */ - public static function scan($path,$eventSource=false,&$count=0,$root=''){ + public static function scan($path,$eventSource=false,&$count=0,$root=false){ if($eventSource){ $eventSource->send('scanning',array('file'=>$path,'count'=>$count)); } $lastSend=$count; - if(!$root){ + if($root===false){ $view=OC_Filesystem::getView(); }else{ - $view=new OC_FilesystemView(($root=='/')?'':$root); + $view=new OC_FilesystemView($root); } self::scanFile($path,$root); $dh=$view->opendir($path.'/'); @@ -555,8 +347,9 @@ class OC_FileCache{ } } } - self::cleanFolder($path,$root); - self::increaseSize($view->getRoot().$path,$totalSize); + + OC_FileCache_Update::cleanFolder($path,$root); + self::increaseSize($path,$totalSize,$root); } /** @@ -565,11 +358,11 @@ class OC_FileCache{ * @param string root (optional) * @return int size of the scanned file */ - public static function scanFile($path,$root=''){ - if(!$root){ + public static function scanFile($path,$root=false){ + if($root===false){ $view=OC_Filesystem::getView(); }else{ - $view=new OC_FilesystemView(($root=='/')?'':$root); + $view=new OC_FilesystemView($root); } if(!$view->is_readable($path)) return; //cant read, nothing we can do clearstatcache(); @@ -602,11 +395,9 @@ class OC_FileCache{ * seccond mimetype part can be ommited * e.g. searchByMime('audio') */ - public static function searchByMime($part1,$part2=null,$root=null){ - if(!$root){ + public static function searchByMime($part1,$part2=null,$root=false){ + if($root===false){ $root=OC_Filesystem::getRoot(); - }elseif($root=='/'){ - $root=''; } $rootLen=strlen($root); $root .= '%'; @@ -626,103 +417,6 @@ class OC_FileCache{ } /** - * check if a file or folder is updated outside owncloud - * @param string path - * @param string root (optional) - * @return bool - */ - public static function isUpdated($path,$root=''){ - if(!$root){ - $root=OC_Filesystem::getRoot(); - $view=OC_Filesystem::getView(); - }else{ - if($root=='/'){ - $root=''; - } - $view=new OC_FilesystemView($root); - } - if(!$view->file_exists($path)){ - return false; - } - $mtime=$view->filemtime($path); - $isDir=$view->is_dir($path); - $fullPath=$root.$path; - $query=OC_DB::prepare('SELECT mtime FROM *PREFIX*fscache WHERE path_hash=?'); - $result=$query->execute(array(md5($fullPath))); - if($row=$result->fetchRow()){ - $cachedMTime=$row['mtime']; - return ($mtime>$cachedMTime); - }else{//file not in cache, so it has to be updated - if($path=='/' or $path==''){//dont auto update the root folder, it will be scanned - return false; - } - return true; - } - } - - /** - * update the cache according to changes in the folder - * @param string path - * @param string root (optional) - */ - private static function updateFolder($path,$root=''){ - if(!$root){ - $view=OC_Filesystem::getView(); - }else{ - $view=new OC_FilesystemView(($root=='/')?'':$root); - } - $dh=$view->opendir($path.'/'); - if($dh){//check for changed/new files - while (($filename = readdir($dh)) !== false) { - if($filename != '.' and $filename != '..'){ - $file=$path.'/'.$filename; - if(self::isUpdated($file,$root)){ - if(!$root){//filesystem hooks are only valid for the default root - OC_Hook::emit('OC_Filesystem','post_write',array('path'=>$file)); - }else{ - self::fileSystemWatcherWrite(array('path'=>$file),$root); - } - } - } - } - } - - self::cleanFolder($path,$root); - - //update the folder last, so we can calculate the size correctly - if(!$root){//filesystem hooks are only valid for the default root - OC_Hook::emit('OC_Filesystem','post_write',array('path'=>$path)); - }else{ - self::fileSystemWatcherWrite(array('path'=>$path),$root); - } - } - - /** - * delete non existing files from the cache - */ - private static function cleanFolder($path,$root=''){ - if(!$root){ - $view=OC_Filesystem::getView(); - }else{ - $view=new OC_FilesystemView(($root=='/')?'':$root); - } - //check for removed files, not using getFolderContent to prevent loops - $parent=self::getFileId($view->getRoot().$path); - $query=OC_DB::prepare('SELECT name FROM *PREFIX*fscache WHERE parent=?'); - $result=$query->execute(array($parent)); - while($row=$result->fetchRow()){ - $file=$path.'/'.$row['name']; - if(!$view->file_exists($file)){ - if(!$root){//filesystem hooks are only valid for the default root - OC_Hook::emit('OC_Filesystem','post_delete',array('path'=>$file)); - }else{ - self::fileSystemWatcherDelete(array('path'=>$file),$root); - } - } - } - } - - /** * clean old pre-path_hash entries */ public static function clean(){ @@ -732,6 +426,6 @@ class OC_FileCache{ } //watch for changes and try to keep the cache up to date -OC_Hook::connect('OC_Filesystem','post_write','OC_FileCache','fileSystemWatcherWrite'); -OC_Hook::connect('OC_Filesystem','post_delete','OC_FileCache','fileSystemWatcherDelete'); -OC_Hook::connect('OC_Filesystem','post_rename','OC_FileCache','fileSystemWatcherRename'); +OC_Hook::connect('OC_Filesystem','post_write','OC_FileCache_Update','fileSystemWatcherWrite'); +OC_Hook::connect('OC_Filesystem','post_delete','OC_FileCache_Update','fileSystemWatcherDelete'); +OC_Hook::connect('OC_Filesystem','post_rename','OC_FileCache_Update','fileSystemWatcherRename'); diff --git a/lib/filecache/cached.php b/lib/filecache/cached.php new file mode 100644 index 00000000000..17a792a23d4 --- /dev/null +++ b/lib/filecache/cached.php @@ -0,0 +1,70 @@ +<?php +/** + * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + + +/** + * get data from the filecache without checking for updates + */ +class OC_FileCache_Cached{ + public static $savedData=array(); + + public static function get($path,$root=false){ + if($root===false){ + $root=OC_Filesystem::getRoot(); + } + $path=$root.$path; + $query=OC_DB::prepare('SELECT path,ctime,mtime,mimetype,size,encrypted,versioned,writable FROM *PREFIX*fscache WHERE path_hash=?'); + $result=$query->execute(array(md5($path)))->fetchRow(); + if(is_array($result)){ + if(isset(self::$savedData[$path])){ + $result=array_merge($result,self::$savedData[$path]); + } + return $result; + }else{ + if(isset(self::$savedData[$path])){ + return self::$savedData[$path]; + }else{ + return array(); + } + } + } + + /** + * get all files and folders in a folder + * @param string path + * @param string root (optional) + * @return array + * + * returns an array of assiciative arrays with the following keys: + * - path + * - name + * - size + * - mtime + * - ctime + * - mimetype + * - encrypted + * - versioned + */ + public static function getFolderContent($path,$root=false,$mimetype_filter=''){ + if($root===false){ + $root=OC_Filesystem::getRoot(); + } + $parent=OC_FileCache::getId($path,$root); + if($parent==-1){ + return array(); + } + $query=OC_DB::prepare('SELECT path,name,ctime,mtime,mimetype,size,encrypted,versioned,writable FROM *PREFIX*fscache WHERE parent=? AND (mimetype LIKE ? OR mimetype = ?)'); + $result=$query->execute(array($parent, $mimetype_filter.'%', 'httpd/unix-directory'))->fetchAll(); + if(is_array($result)){ + return $result; + }else{ + OC_Log::write('files','getFolderContent(): file not found in cache ('.$path.')',OC_Log::DEBUG); + return false; + } + } +}
\ No newline at end of file diff --git a/lib/filecache/update.php b/lib/filecache/update.php new file mode 100644 index 00000000000..dd77f491ca0 --- /dev/null +++ b/lib/filecache/update.php @@ -0,0 +1,215 @@ +<?php +/** + * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + + +/** + * handles updating the filecache according to outside changes + */ +class OC_FileCache_Update{ + /** + * check if a file or folder is updated outside owncloud + * @param string path + * @param string root (optional) + * @param boolean folder + * @return bool + */ + public static function hasUpdated($path,$root=false,$folder=false){ + if($root===false){ + $view=OC_Filesystem::getView(); + }else{ + $view=new OC_FilesystemView($root); + } + if(!$view->file_exists($path)){ + return false; + } + $cachedData=OC_FileCache_Cached::get($path,$root); + if(isset($cachedData['mtime'])){ + $cachedMTime=$cachedData['mtime']; + if($folder){ + return $view->hasUpdated($path.'/',$cachedMTime); + }else{ + return $view->hasUpdated($path,$cachedMTime); + } + }else{//file not in cache, so it has to be updated + if(($path=='/' or $path=='') and $root===false){//dont auto update the home folder, it will be scanned + return false; + } + return true; + } + } + + /** + * delete non existing files from the cache + */ + 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); + foreach($cachedContent as $fileData){ + $path=$fileData['path']; + $file=$view->getRelativePath($path); + if(!$view->file_exists($file)){ + if($root===false){//filesystem hooks are only valid for the default root + OC_Hook::emit('OC_Filesystem','post_delete',array('path'=>$file)); + }else{ + self::delete($file,$root); + } + } + } + } + + /** + * update the cache according to changes in the folder + * @param string path + * @param string root (optional) + */ + public static function updateFolder($path,$root=false){ + if($root===false){ + $view=OC_Filesystem::getView(); + }else{ + $view=new OC_FilesystemView($root); + } + $dh=$view->opendir($path.'/'); + if($dh){//check for changed/new files + while (($filename = readdir($dh)) !== false) { + if($filename != '.' and $filename != '..'){ + $file=$path.'/'.$filename; + if(self::hasUpdated($file,$root)){ + if($root===false){//filesystem hooks are only valid for the default root + OC_Hook::emit('OC_Filesystem','post_write',array('path'=>$file)); + }else{ + self::update($file,$root); + } + } + } + } + } + + self::cleanFolder($path,$root); + + //update the folder last, so we can calculate the size correctly + if($root===false){//filesystem hooks are only valid for the default root + OC_Hook::emit('OC_Filesystem','post_write',array('path'=>$path)); + }else{ + self::update($path,$root); + } + } + + /** + * called when changes are made to files + * @param array $params + * @param string root (optional) + */ + public static function fileSystemWatcherWrite($params){ + $path=$params['path']; + self::update($path); + } + + /** + * called when files are deleted + * @param array $params + * @param string root (optional) + */ + public static function fileSystemWatcherDelete($params){ + $path=$params['path']; + self::delete($path); + } + + /** + * called when files are deleted + * @param array $params + * @param string root (optional) + */ + public static function fileSystemWatcherRename($params){ + $oldPath=$params['oldpath']; + $newPath=$params['newpath']; + self::rename($oldPath,$newPath); + } + + /** + * update the filecache according to changes to the fileysystem + * @param string path + * @param string root (optional) + */ + public static function update($path,$root=false){ + if($root===false){ + $view=OC_Filesystem::getView(); + }else{ + $view=new OC_FilesystemView($root); + } + + $mimetype=$view->getMimeType($path); + + $size=0; + $cached=OC_FileCache_Cached::get($path,$root); + $cachedSize=isset($cached['size'])?$cached['size']:0; + + if($mimetype=='httpd/unix-directory'){ + if(OC_FileCache::inCache($path,$root)){ + $cachedContent=OC_FileCache_Cached::getFolderContent($path,$root); + foreach($cachedContent as $file){ + $size+=$file['size']; + } + $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)); + }else{ + $count=0; + OC_FileCache::scan($path,null,$count,$root); + return; //increaseSize is already called inside scan + } + }else{ + $size=OC_FileCache::scanFile($path,$root); + } + OC_FileCache::increaseSize(dirname($path),$size-$cachedSize,$root); + } + + /** + * update the filesystem after a delete has been detected + * @param string path + * @param string root (optional) + */ + public static function delete($path,$root=false){ + $cached=OC_FileCache_Cached::get($path,$root); + if(!isset($cached['size'])){ + return; + } + $size=$cached['size']; + OC_FileCache::increaseSize(dirname($path),-$size,$root); + OC_FileCache::delete($path,$root); + } + + /** + * update the filesystem after a rename has been detected + * @param string oldPath + * @param string newPath + * @param string root (optional) + */ + public static function rename($oldPath,$newPath,$root=false){ + if(!OC_FileCache::inCache($oldPath,$root)){ + return; + } + if($root===false){ + $view=OC_Filesystem::getView(); + }else{ + $view=new OC_FilesystemView($root); + } + + $cached=OC_FileCache_Cached::get($oldPath,$root); + $oldSize=$cached['size']; + $size=$view->filesize($newPath); + OC_FileCache::increaseSize(dirname($oldPath),-$oldSize,$root); + OC_FileCache::increaseSize(dirname($newPath),$oldSize,$root); + OC_FileCache::move($oldPath,$newPath); + } +}
\ No newline at end of file diff --git a/lib/fileproxy/quota.php b/lib/fileproxy/quota.php index 9e4c2d0643e..7316224cc61 100644 --- a/lib/fileproxy/quota.php +++ b/lib/fileproxy/quota.php @@ -54,8 +54,15 @@ class OC_FileProxy_Quota extends OC_FileProxy{ * @return int */ private function getFreeSpace(){ - $rootInfo=OC_FileCache::get(''); - $usedSpace=$rootInfo['size']; + $rootInfo=OC_FileCache_Cached::get(''); + // TODO Remove after merge of share_api + if (OC_FileCache::inCache('/Shared')) { + $sharedInfo=OC_FileCache_Cached::get('/Shared'); + } else { + $sharedInfo = null; + } + $usedSpace=isset($rootInfo['size'])?$rootInfo['size']:0; + $usedSpace=isset($sharedInfo['size'])?$usedSpace-$sharedInfo['size']:$usedSpace; $totalSpace=$this->getQuota(); if($totalSpace==0){ return 0; diff --git a/lib/files.php b/lib/files.php index 705b7a6ca66..469c3a15b8e 100644 --- a/lib/files.php +++ b/lib/files.php @@ -30,13 +30,10 @@ class OC_Files { /** * get the content of a directory - * @param dir $directory + * @param dir $directory path under datadirectory */ public static function getDirectoryContent($directory, $mimetype_filter = ''){ - if(strpos($directory,OC::$CONFIG_DATADIRECTORY)===0){ - $directory=substr($directory,strlen(OC::$CONFIG_DATADIRECTORY)); - } - $files=OC_FileCache::getFolderContent($directory, '', $mimetype_filter); + $files=OC_FileCache::getFolderContent($directory, false, $mimetype_filter); foreach($files as &$file){ $file['directory']=$directory; $file['type']=($file['mimetype']=='httpd/unix-directory')?'dir':'file'; diff --git a/lib/filestorage.php b/lib/filestorage.php index 1d7e004af3b..71ef4aed00b 100644 --- a/lib/filestorage.php +++ b/lib/filestorage.php @@ -50,4 +50,13 @@ abstract class OC_Filestorage{ abstract public function search($query); abstract public function touch($path, $mtime=null); abstract public function getLocalFile($path);// get a path to a local version of the file, whether the original file is local or remote + /** + * check if a file or folder has been updated since $time + * @param int $time + * @return bool + * + * hasUpdated for folders should return at least true if a file inside the folder is add, removed or renamed. + * returning true for other changes in the folder is optional + */ + abstract public function hasUpdated($path,$time); } diff --git a/lib/filestorage/common.php b/lib/filestorage/common.php index f0bfc064cb5..f2a5775fd19 100644 --- a/lib/filestorage/common.php +++ b/lib/filestorage/common.php @@ -156,4 +156,13 @@ abstract class OC_Filestorage_Common extends OC_Filestorage { } return $files; } + + /** + * check if a file or folder has been updated since $time + * @param int $time + * @return bool + */ + public function hasUpdated($path,$time){ + return $this->filemtime($path)>$time; + } } diff --git a/lib/filestorage/local.php b/lib/filestorage/local.php index ea9a9070263..44a2ab0f634 100644 --- a/lib/filestorage/local.php +++ b/lib/filestorage/local.php @@ -194,4 +194,13 @@ class OC_Filestorage_Local extends OC_Filestorage{ public function getFolderSize($path){ return 0;//depricated, use OC_FileCach instead } + + /** + * check if a file or folder has been updated since $time + * @param int $time + * @return bool + */ + public function hasUpdated($path,$time){ + return $this->filemtime($path)>$time; + } } diff --git a/lib/filesystem.php b/lib/filesystem.php index 28bd7d52900..0ab3bd69acd 100644 --- a/lib/filesystem.php +++ b/lib/filesystem.php @@ -25,7 +25,7 @@ /** * Class for abstraction of filesystem functions * This class won't call any filesystem functions for itself but but will pass them to the correct OC_Filestorage object - * this class should also handle all the file premission related stuff + * this class should also handle all the file permission related stuff * * Hooks provided: * read(path) @@ -399,6 +399,9 @@ class OC_Filesystem{ static public function opendir($path){ return self::$defaultInstance->opendir($path); } + static public function readdir($path){ + return self::$defaultInstance->readdir($path); + } static public function is_dir($path){ return self::$defaultInstance->is_dir($path); } @@ -474,6 +477,16 @@ class OC_Filesystem{ static public function search($query){ return OC_FileCache::search($query); } + + /** + * check if a file or folder has been updated since $time + * @param int $time + * @return bool + */ + static public function hasUpdated($path,$time){ + return self::$defaultInstance->hasUpdated($path); + } } +OC_Util::setupFS(); require_once('filecache.php'); diff --git a/lib/filesystemview.php b/lib/filesystemview.php index 58657671b98..da622bcf920 100644 --- a/lib/filesystemview.php +++ b/lib/filesystemview.php @@ -158,6 +158,10 @@ class OC_FilesystemView { public function opendir($path){ return $this->basicOperation('opendir',$path,array('read')); } + public function readdir($handle){ + $fsLocal= new OC_Filestorage_Local( array( 'datadir' => '/' ) ); + return $fsLocal->readdir( $handle ); + } public function is_dir($path){ if($path=='/'){ return true; @@ -444,4 +448,13 @@ class OC_FilesystemView { } return null; } + + /** + * check if a file or folder has been updated since $time + * @param int $time + * @return bool + */ + public function hasUpdated($path,$time){ + return $this->basicOperation('hasUpdated',$path,array(),$time); + } } diff --git a/lib/helper.php b/lib/helper.php index 73d4b659a34..37914b73e17 100644 --- a/lib/helper.php +++ b/lib/helper.php @@ -378,6 +378,12 @@ class OC_Helper { //trim the character set from the end of the response $mimeType=substr($reply,0,strrpos($reply,' ')); + + //trim ; + if (strpos($mimeType, ';') !== false) { + $mimeType = strstr($mimeType, ';', true); + } + } if ($mimeType=='application/octet-stream') { // Fallback solution: (try to guess the type by the file extension diff --git a/lib/l10n.php b/lib/l10n.php index 887652e2b85..4acbc5dcebc 100644 --- a/lib/l10n.php +++ b/lib/l10n.php @@ -40,6 +40,16 @@ class OC_L10N{ protected static $language = ''; /** + * App of this object + */ + protected $app; + + /** + * Language of this object + */ + protected $lang; + + /** * Translations */ private $translations = array(); @@ -77,10 +87,17 @@ class OC_L10N{ * language. */ public function __construct($app, $lang = null){ - $this->init($app, $lang); + $this->app = $app; + $this->lang = $lang; } - protected function init($app, $lang = null){ + protected function init(){ + if ($this->app === true) { + return; + } + $app = $this->app; + $lang = $this->lang; + $this->app = true; // Find the right language if(is_null($lang)){ $lang = self::findLanguage($app); @@ -127,10 +144,7 @@ class OC_L10N{ * returned. */ public function t($text, $parameters = array()){ - if(array_key_exists($text, $this->translations)){ - return vsprintf($this->translations[$text], $parameters); - } - return vsprintf($text, $parameters); + return new OC_L10N_String($this, $text, $parameters); } /** @@ -144,7 +158,7 @@ class OC_L10N{ public function tA($textArray){ $result = array(); foreach($textArray as $key => $text){ - $result[$key] = $this->t($text); + $result[$key] = (string)$this->t($text); } return $result; } @@ -156,6 +170,7 @@ class OC_L10N{ * Returns an associative array with all translations */ public function getTranslations(){ + $this->init(); return $this->translations; } @@ -182,6 +197,7 @@ class OC_L10N{ * - params: timestamp (int/string) */ public function l($type, $data){ + $this->init(); switch($type){ // If you add something don't forget to add it to $localizations // at the top of the page @@ -228,23 +244,29 @@ class OC_L10N{ return self::$language; } - $available = array(); - if(is_array($app)){ - $available = $app; - } - else{ - $available=self::findAvailableLanguages($app); - } if(OC_User::getUser() && OC_Preferences::getValue(OC_User::getUser(), 'core', 'lang')){ $lang = OC_Preferences::getValue(OC_User::getUser(), 'core', 'lang'); self::$language = $lang; - if(array_search($lang, $available) !== false){ + if(is_array($app)){ + $available = $app; + $lang_exists = array_search($lang, $available) !== false; + } + else { + $lang_exists = self::languageExists($app, $lang); + } + if($lang_exists){ return $lang; } } if(isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])){ $accepted_languages = preg_split('/,\s*/', $_SERVER['HTTP_ACCEPT_LANGUAGE']); + if(is_array($app)){ + $available = $app; + } + else{ + $available = self::findAvailableLanguages($app); + } foreach($accepted_languages as $i){ $temp = explode(';', $i); if(array_search($temp[0], $available) !== false){ @@ -296,4 +318,15 @@ class OC_L10N{ } return $available; } + + public static function languageExists($app, $lang){ + if ($lang == 'en'){//english is always available + return true; + } + $dir = self::findI18nDir($app); + if(is_dir($dir)){ + return file_exists($dir.'/'.$lang.'.php'); + } + return false; + } } diff --git a/lib/l10n/string.php b/lib/l10n/string.php new file mode 100644 index 00000000000..4769790a16d --- /dev/null +++ b/lib/l10n/string.php @@ -0,0 +1,25 @@ +<?php +/** + * Copyright (c) 2012 Bart Visscher <bartv@thisnet.nl> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +class OC_L10N_String{ + protected $l10n; + public function __construct($l10n, $text, $parameters){ + $this->l10n = $l10n; + $this->text = $text; + $this->parameters = $parameters; + + } + + public function __toString(){ + $translations = $this->l10n->getTranslations(); + if(array_key_exists($this->text, $translations)){ + return vsprintf($translations[$this->text], $this->parameters); + } + return vsprintf($this->text, $this->parameters); + } +} diff --git a/lib/migrate.php b/lib/migrate.php index f9cab915d04..5939ba32e50 100644 --- a/lib/migrate.php +++ b/lib/migrate.php @@ -196,7 +196,7 @@ class OC_Migrate{ * @param optional $uid userid of new user */ public static function import( $path, $type='user', $uid=null ){ - OC_Util::checkAdminUser(); + $datadir = OC_Config::getValue( 'datadirectory' ); // Extract the zip if( !$extractpath = self::extractZip( $path ) ){ @@ -216,12 +216,19 @@ class OC_Migrate{ } self::$exporttype = $type; + $currentuser = OC_User::getUser(); + // Have we got a user if type is user if( self::$exporttype == 'user' ){ - if( !$uid ){ - self::$uid = $json->exporteduser; - } else { - self::$uid = $uid; + self::$uid = !is_null($uid) ? $uid : $currentuser; + } + + // We need to be an admin if we are not importing our own data + if(($type == 'user' && self::$uid != $currentuser) || $type != 'user' ){ + if( !OC_Group::inGroup( OC_User::getUser(), 'admin' )){ + // Naughty. + OC_Log::write( 'migration', 'Import not permitted.', OC_Log::ERROR ); + return json_encode( array( 'success' => false ) ); } } @@ -229,27 +236,8 @@ class OC_Migrate{ switch( self::$exporttype ){ case 'user': // Check user availability - if( OC_User::userExists( self::$uid ) ){ - OC_Log::write( 'migration', 'User already exists', OC_Log::ERROR ); - return json_encode( array( 'success' => false ) ); - } - $run = true; - OC_Hook::emit( "OC_User", "pre_createUser", array( "run" => &$run, "uid" => self::$uid, "password" => $json->hash )); - if( !$run ){ - // Something stopped the user creation - OC_Log::write( 'migration', 'User creation failed', OC_Log::ERROR ); - return json_encode( array( 'success' => false ) ); - } - // Create the user - if( !self::createUser( self::$uid, $json->hash ) ){ - return json_encode( array( 'success' => false ) ); - } - // Emit the post_createUser hook (password is already hashed, will cause problems - OC_Hook::emit( "OC_User", "post_createUser", array( "uid" => self::$uid, "password" => $json->hash )); - // Make the new users data dir - $path = $datadir . '/' . self::$uid; - if( !mkdir( $path, 0755, true ) ){ - OC_Log::write( 'migration', 'Failed to create users data dir: '.$path, OC_Log::ERROR ); + if( !OC_User::userExists( self::$uid ) ){ + OC_Log::write( 'migration', 'User doesn\'t exist', OC_Log::ERROR ); return json_encode( array( 'success' => false ) ); } // Copy data diff --git a/lib/mimetypes.fixlist.php b/lib/mimetypes.fixlist.php index a40fbd9e228..13e3f16b369 100644 --- a/lib/mimetypes.fixlist.php +++ b/lib/mimetypes.fixlist.php @@ -17,5 +17,6 @@ return array( 'xlsx'=>'application/msexcel', 'ppt'=>'application/mspowerpoint', 'pptx'=>'application/mspowerpoint', - 'sgf' => 'application/sgf' + 'sgf' => 'application/sgf', + 'cdr' => 'application/coreldraw' ); diff --git a/lib/minimizer.php b/lib/minimizer.php index 9f9ef086c4a..e17c114f065 100644 --- a/lib/minimizer.php +++ b/lib/minimizer.php @@ -1,17 +1,6 @@ <?php -abstract class OC_Minimizer -{ - protected $files = array(); - - protected function appendIfExist($root, $webroot, $file) { - if (is_file($root.'/'.$file)) { - $this->files[] = array($root, $webroot, $file); - return true; - } - return false; - } - +abstract class OC_Minimizer { public function getLastModified($files) { $last_modified = 0; foreach($files as $file_info) { @@ -26,14 +15,30 @@ abstract class OC_Minimizer abstract public function minimizeFiles($files); - public function output($files) { + public function output($files, $cache_key) { header('Content-Type: '.$this->contentType); OC_Response::enableCaching(); $last_modified = $this->getLastModified($files); OC_Response::setLastModifiedHeader($last_modified); - $out = $this->minimizeFiles($files); - OC_Response::setETagHeader(md5($out)); + $gzout = false; + $cache = new OC_Cache_FileGlobal(); + if (!OC_Request::isNoCache() && (!defined('DEBUG') || !DEBUG)){ + $gzout = $cache->get($cache_key.'.gz'); + OC_Response::setETagHeader(md5($gzout)); + } + + if (!$gzout) { + $out = $this->minimizeFiles($files); + $gzout = gzencode($out); + $cache->set($cache_key.'.gz', $gzout); + } + if ($encoding = OC_Request::acceptGZip()) { + header('Content-Encoding: '.$encoding); + $out = $gzout; + } else { + $out = gzdecode($gzout); + } header('Content-Length: '.strlen($out)); echo $out; } diff --git a/lib/minimizer/css.php b/lib/minimizer/css.php index c7e5d96e06b..97099adbdf6 100644 --- a/lib/minimizer/css.php +++ b/lib/minimizer/css.php @@ -6,54 +6,6 @@ class OC_Minimizer_CSS extends OC_Minimizer { protected $contentType = 'text/css'; - public function findFiles($styles) { - // Read the selected theme from the config file - $theme=OC_Config::getValue( "theme" ); - - // Read the detected formfactor and use the right file name. - $fext = OC_Template::getFormFactorExtension(); - foreach($styles as $style){ - // is it in 3rdparty? - if($this->appendIfExist(OC::$THIRDPARTYROOT, OC::$THIRDPARTYWEBROOT, $style.'.css')) { - - // or in the owncloud root? - }elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "$style$fext.css" )) { - }elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "$style.css" )) { - - // or in core ? - }elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "core/$style$fext.css" )) { - }elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "core/$style.css" )) { - - }else{ - $append = false; - foreach( OC::$APPSROOTS as $apps_dir) - { - if($this->appendIfExist($apps_dir['path'], $apps_dir['url'], "$style$fext.css", true)) { $append =true; break; } - elseif($this->appendIfExist($apps_dir['path'], $apps_dir['url'], "$style.css", true )) { $append =true; break; } - } - if(! $append) { - echo('css file not found: style:'.$script.' formfactor:'.$fext.' webroot:'.OC::$WEBROOT.' serverroot:'.OC::$SERVERROOT); - die(); - } - } - } - // Add the theme css files. you can override the default values here - if(!empty($theme)) { - foreach($styles as $style){ - if($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/apps/$style$fext.css" )) { - }elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/apps/$style.css" )) { - - }elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/$style$fext.css" )) { - }elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/$style.css" )) { - - }elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/core/$style$fext.css" )) { - }elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/core/$style.css" )) { - } - } - } - return $this->files; - } - public function minimizeFiles($files) { $css_out = ''; $webroot = (string) OC::$WEBROOT; @@ -78,7 +30,9 @@ class OC_Minimizer_CSS extends OC_Minimizer $remote .= dirname($file_info[2]); $css_out .= CSSMin::remap($css, dirname($file), $remote, true); } - $css_out = CSSMin::minify($css_out); + if (!defined('DEBUG') || !DEBUG){ + $css_out = CSSMin::minify($css_out); + } return $css_out; } } diff --git a/lib/minimizer/js.php b/lib/minimizer/js.php index dd7d15de061..0f5cb7e5577 100644 --- a/lib/minimizer/js.php +++ b/lib/minimizer/js.php @@ -6,54 +6,6 @@ class OC_Minimizer_JS extends OC_Minimizer { protected $contentType = 'application/javascript'; - public function findFiles($scripts) { - // Read the selected theme from the config file - $theme=OC_Config::getValue( "theme" ); - - // Read the detected formfactor and use the right file name. - $fext = OC_Template::getFormFactorExtension(); - // Add the core js files or the js files provided by the selected theme - foreach($scripts as $script){ - // Is it in 3rd party? - if($this->appendIfExist(OC::$THIRDPARTYROOT, OC::$THIRDPARTYWEBROOT, $script.'.js')) { - - // Is it in apps and overwritten by the theme? - }elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/apps/$script$fext.js" )) { - }elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/apps/$script.js" )) { - - // Is it in the owncloud root but overwritten by the theme? - }elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/$script$fext.js" )) { - }elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/$script.js" )) { - - // Is it in the owncloud root ? - }elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "$script$fext.js" )) { - }elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "$script.js" )) { - - // Is in core but overwritten by a theme? - }elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/core/$script$fext.js" )) { - }elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/core/$script.js" )) { - - // Is it in core? - }elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "core/$script$fext.js" )) { - }elseif($this->appendIfExist(OC::$SERVERROOT, OC::$WEBROOT, "core/$script.js" )) { - - }else{ - // Is it part of an app? - $append = false; - foreach( OC::$APPSROOTS as $apps_dir) - { - if($this->appendIfExist($apps_dir['path'], $apps_dir['url'], "$script$fext.js" , true)) { $append =true; break; } - elseif($this->appendIfExist($apps_dir['path'], $apps_dir['url'], "$script.js", true )) { $append =true; break; } - } - if(! $append) { - echo('js file not found: script:'.$script.' formfactor:'.$fext.' webroot:'.OC::$WEBROOT.' serverroot:'.OC::$SERVERROOT); - die(); - } - } - } - return $this->files; - } - public function minimizeFiles($files) { $js_out = ''; foreach($files as $file_info) { @@ -61,7 +13,9 @@ class OC_Minimizer_JS extends OC_Minimizer $js_out .= '/* ' . $file . ' */' . "\n"; $js_out .= file_get_contents($file); } - $js_out = JavaScriptMinifier::minify($js_out); + if (!defined('DEBUG') || !DEBUG){ + $js_out = JavaScriptMinifier::minify($js_out); + } return $js_out; } } diff --git a/lib/public/util.php b/lib/public/util.php index d79d3f26b1e..c611d59a533 100644 --- a/lib/public/util.php +++ b/lib/public/util.php @@ -264,6 +264,18 @@ class Util { public static function callCheck(){ return(\OC_Util::callCheck()); } + + /**
+ * @brief Used to sanitize HTML
+ *
+ * This function is used to sanitize HTML and should be applied on any string or array of strings before displaying it on a web page.
+ *
+ * @param string or array of strings
+ * @return array with sanitized strings or a single sinitized string, depends on the input parameter.
+ */
+ public static function sanitizeHTML( $value ){
+ return(\OC_Util::sanitizeHTML($value));
+ } } ?> diff --git a/lib/request.php b/lib/request.php new file mode 100644 index 00000000000..0b5aaf8ef30 --- /dev/null +++ b/lib/request.php @@ -0,0 +1,28 @@ +<?php +/** + * Copyright (c) 2012 Bart Visscher <bartv@thisnet.nl> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +class OC_Request { + static public function isNoCache() { + if (!isset($_SERVER['HTTP_CACHE_CONTROL'])) { + return false; + } + return $_SERVER['HTTP_CACHE_CONTROL'] == 'no-cache'; + } + + static public function acceptGZip() { + if (!isset($_SERVER['HTTP_ACCEPT_ENCODING'])) { + return false; + } + $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 ) + return 'gzip'; + return false; + } +} diff --git a/lib/template.php b/lib/template.php index 149859aa8a5..3b48c27b9b4 100644 --- a/lib/template.php +++ b/lib/template.php @@ -167,10 +167,47 @@ class OC_Template{ } /** + * autodetects the formfactor of the used device + * default -> the normal desktop browser interface + * mobile -> interface for smartphones + * tablet -> interface for tablets + * standalone -> the default interface but without header, footer and + * sidebar, just the application. Useful to use just a specific + * app on the desktop in a standalone window. + */ + 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) { + $mode='tablet'; + }elseif(stripos($_SERVER['HTTP_USER_AGENT'],'iphone')>0){ + $mode='mobile'; + }elseif((stripos($_SERVER['HTTP_USER_AGENT'],'N9')>0) and (stripos($_SERVER['HTTP_USER_AGENT'],'nokia')>0)){ + $mode='mobile'; + }else{ + $mode='default'; + } + }else{ + $mode='default'; + } + return($mode); + } + + /** * @brief Returns the formfactor extension for current formfactor */ static public function getFormFactorExtension() { + // if the formfactor is not yet autodetected do the + // autodetection now. For possible formfactors check the + // detectFormfactor documentation + if(!isset($_SESSION['formfactor'])){ + $_SESSION['formfactor'] = self::detectFormfactor(); + } + // allow manual override via GET parameter + if(isset($_GET['formfactor'])){ + $_SESSION['formfactor']=$_GET['formfactor']; + } $formfactor=$_SESSION['formfactor']; if($formfactor=='default') { $fext=''; @@ -270,29 +307,12 @@ class OC_Template{ * * If the key existed before, it will be overwritten */ - public function assign( $key, $value, $sanitizeHTML=true ){ - if($sanitizeHTML == true) { - if(is_array($value)) { - array_walk_recursive($value,'OC_Template::sanitizeHTML'); - } else { - $value = OC_Template::sanitizeHTML($value); - } - } + public function assign( $key, $value, $sanitizeHTML=true ){ + if($sanitizeHTML == true) $value=OC_Util::sanitizeHTML($value); $this->vars[$key] = $value; return true; } - - /** - * @brief Internaly used to sanitze HTML - * - * This function is internally used to sanitize HTML. - */ - private static function sanitizeHTML( &$value ){ - $value = htmlentities( $value ); - return $value; - } - /** * @brief Appends a variable * @param $key key @@ -340,38 +360,6 @@ class OC_Template{ } /** - * @brief append the $file-url if exist at $root - * @param $type of collection to use when appending - * @param $root path to check - * @param $web base for path - * @param $file the filename - * @param $in_app boolean is part of an app? (default false) - */ - public function appendIfExist($type, $root, $web, $file, $in_app = false) { - - if (is_file($root.'/'.$file)) { - $pathes = explode('/', $file); - $in_root = false; - foreach(OC::$APPSROOTS as $app_root) { - if($root == $app_root['path']) { - $in_root = true; - break; - } - } - if($type == 'cssfiles' && $in_root && $in_app){ - $app = $pathes[0]; - unset($pathes[0]); - $path = implode('/', $pathes); - $this->append( $type, OC_Helper::linkTo($app, $path)); - }else{ - $this->append( $type, $web.'/'.$file); - } - return true; - } - return false; - } - - /** * @brief Proceeds the template * @returns content * @@ -382,123 +370,9 @@ class OC_Template{ $data = $this->_fetch(); if( $this->renderas ){ - // Decide which page we show - if( $this->renderas == "user" ){ - $page = new OC_Template( "core", "layout.user" ); - $page->assign('searchurl',OC_Helper::linkTo( 'search', 'index.php' ), false); + $page = new OC_TemplateLayout($this->renderas); + if($this->renderas == 'user') { $page->assign('requesttoken', $this->vars['requesttoken']); - if(array_search(OC_APP::getCurrentApp(),array('settings','admin','help'))!==false){ - $page->assign('bodyid','body-settings', false); - }else{ - $page->assign('bodyid','body-user', false); - } - - // Add navigation entry - $navigation = OC_App::getNavigation(); - $page->assign( "navigation", $navigation, false); - $page->assign( "settingsnavigation", OC_App::getSettingsNavigation(), false); - foreach($navigation as $entry) { - if ($entry['active']) { - $page->assign( 'application', $entry['name'], false ); - break; - } - } - }else{ - $page = new OC_Template( "core", "layout.guest" ); - } - $apps_paths = array(); - foreach(OC_App::getEnabledApps() as $app){ - $apps_paths[$app] = OC_App::getAppWebPath($app); - } - $page->assign( 'apps_paths', str_replace('\\/', '/',json_encode($apps_paths)) , false); // Ugly unescape slashes waiting for better solution - - // Read the selected theme from the config file - $theme=OC_Config::getValue( "theme" ); - - // Read the detected formfactor and use the right file name. - $fext = self::getFormFactorExtension(); - - $page->assign('jsfiles', array(), false); - // Add the core js files or the js files provided by the selected theme - foreach(OC_Util::$scripts as $script){ - // Is it in 3rd party? - if($page->appendIfExist('jsfiles', OC::$THIRDPARTYROOT, OC::$THIRDPARTYWEBROOT, $script.'.js')) { - - // Is it in apps and overwritten by the theme? - }elseif($page->appendIfExist('jsfiles', OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/apps/$script$fext.js" )) { - }elseif($page->appendIfExist('jsfiles', OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/apps/$script.js" )) { - - // Is it in the owncloud root but overwritten by the theme? - }elseif($page->appendIfExist('jsfiles', OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/$script$fext.js" )) { - }elseif($page->appendIfExist('jsfiles', OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/$script.js" )) { - - // Is it in the owncloud root ? - }elseif($page->appendIfExist('jsfiles', OC::$SERVERROOT, OC::$WEBROOT, "$script$fext.js" )) { - }elseif($page->appendIfExist('jsfiles', OC::$SERVERROOT, OC::$WEBROOT, "$script.js" )) { - - // Is in core but overwritten by a theme? - }elseif($page->appendIfExist('jsfiles', OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/core/$script$fext.js" )) { - }elseif($page->appendIfExist('jsfiles', OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/core/$script.js" )) { - - // Is it in core? - }elseif($page->appendIfExist('jsfiles', OC::$SERVERROOT, OC::$WEBROOT, "core/$script$fext.js" )) { - }elseif($page->appendIfExist('jsfiles', OC::$SERVERROOT, OC::$WEBROOT, "core/$script.js" )) { - - }else{ - // Is it part of an app? - $append = false; - foreach( OC::$APPSROOTS as $apps_dir) - { - if($page->appendIfExist('jsfiles', $apps_dir['path'], $apps_dir['url'], "$script$fext.js" , true)) { $append =true; break; } - elseif($page->appendIfExist('jsfiles', $apps_dir['path'], $apps_dir['url'], "$script.js", true )) { $append =true; break; } - } - if(! $append) { - echo('js file not found: script:'.$script.' formfactor:'.$fext.' webroot:'.OC::$WEBROOT.' serverroot:'.OC::$SERVERROOT); - die(); - } - } - } - // Add the css files - $page->assign('cssfiles', array()); - foreach(OC_Util::$styles as $style){ - // is it in 3rdparty? - if($page->appendIfExist('cssfiles', OC::$THIRDPARTYROOT, OC::$THIRDPARTYWEBROOT, $style.'.css')) { - - // or in the owncloud root? - }elseif($page->appendIfExist('cssfiles', OC::$SERVERROOT, OC::$WEBROOT, "$style$fext.css" )) { - }elseif($page->appendIfExist('cssfiles', OC::$SERVERROOT, OC::$WEBROOT, "$style.css" )) { - - // or in core ? - }elseif($page->appendIfExist('cssfiles', OC::$SERVERROOT, OC::$WEBROOT, "core/$style$fext.css" )) { - }elseif($page->appendIfExist('cssfiles', OC::$SERVERROOT, OC::$WEBROOT, "core/$style.css" )) { - - }else{ - // or in apps? - $append = false; - foreach( OC::$APPSROOTS as $apps_dir) - { - if($page->appendIfExist('cssfiles', $apps_dir['path'], $apps_dir['url'], "$style$fext.css", true)) { $append =true; break; } - elseif($page->appendIfExist('cssfiles', $apps_dir['path'], $apps_dir['url'], "$style.css", true )) { $append =true; break; } - } - if(! $append) { - echo('css file not found: style:'.$script.' formfactor:'.$fext.' webroot:'.OC::$WEBROOT.' serverroot:'.OC::$SERVERROOT); - die(); - } - } - } - // Add the theme css files. you can override the default values here - if(!empty($theme)) { - foreach(OC_Util::$styles as $style){ - if($page->appendIfExist('cssfiles', OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/apps/$style$fext.css" )) { - }elseif($page->appendIfExist('cssfiles', OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/apps/$style.css" )) { - - }elseif($page->appendIfExist('cssfiles', OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/$style$fext.css" )) { - }elseif($page->appendIfExist('cssfiles', OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/$style.css" )) { - - }elseif($page->appendIfExist('cssfiles', OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/core/$style$fext.css" )) { - }elseif($page->appendIfExist('cssfiles', OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/core/$style.css" )) { - } - } } // Add custom headers @@ -507,7 +381,6 @@ class OC_Template{ $page->append('headers',$header); } - // Add css files and js files $page->assign( "content", $data, false ); return $page->fetchPage(); } diff --git a/lib/templatelayout.php b/lib/templatelayout.php new file mode 100644 index 00000000000..1f82e82be74 --- /dev/null +++ b/lib/templatelayout.php @@ -0,0 +1,170 @@ +<?php +/** + * Copyright (c) 2012 Bart Visscher <bartv@thisnet.nl> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +class OC_TemplateLayout extends OC_Template { + public function __construct( $renderas ){ + // Decide which page we show + if( $renderas == 'user' ){ + parent::__construct( 'core', 'layout.user' ); + $this->assign('searchurl',OC_Helper::linkTo( 'search', 'index.php' ), false); + if(array_search(OC_APP::getCurrentApp(),array('settings','admin','help'))!==false){ + $this->assign('bodyid','body-settings', false); + }else{ + $this->assign('bodyid','body-user', false); + } + + // Add navigation entry + $navigation = OC_App::getNavigation(); + $this->assign( 'navigation', $navigation, false); + $this->assign( 'settingsnavigation', OC_App::getSettingsNavigation(), false); + foreach($navigation as $entry) { + if ($entry['active']) { + $this->assign( 'application', $entry['name'], false ); + break; + } + } + }else{ + parent::__construct( 'core', 'layout.guest' ); + } + + // Add the js files + $jsfiles = self::findJavascriptFiles(OC_Util::$scripts); + $this->assign('jsfiles', array(), false); + foreach($jsfiles as $info) { + $root = $info[0]; + $web = $info[1]; + $file = $info[2]; + $this->append( 'jsfiles', $web.'/'.$file); + } + + // Add the css files + $cssfiles = self::findStylesheetFiles(OC_Util::$styles); + $this->assign('cssfiles', array()); + foreach($cssfiles as $info) { + $root = $info[0]; + $web = $info[1]; + $file = $info[2]; + $paths = explode('/', $file); + if($root == OC::$APPSROOT && $paths[0] == 'apps'){ + $app = $paths[1]; + unset($paths[0]); + unset($paths[1]); + $path = implode('/', $paths); + $this->append( 'cssfiles', OC_Helper::linkTo($app, $path)); + }else{ + $this->append( 'cssfiles', $web.'/'.$file); + } + } + } + + /* + * @brief append the $file-url if exist at $root + * @param $files array to append file info to + * @param $root path to check + * @param $web base for path + * @param $file the filename + */ + static public function appendIfExist(&$files, $root, $webroot, $file) { + if (is_file($root.'/'.$file)) { + $files[] = array($root, $webroot, $file); + return true; + } + return false; + } + + static public function findStylesheetFiles($styles){ + // Read the selected theme from the config file + $theme=OC_Config::getValue( 'theme' ); + + // Read the detected formfactor and use the right file name. + $fext = self::getFormFactorExtension(); + + $files = array(); + foreach($styles as $style){ + // is it in 3rdparty? + if(self::appendIfExist($files, OC::$THIRDPARTYROOT, OC::$THIRDPARTYWEBROOT, $style.'.css')) { + + // or in apps? + }elseif(self::appendIfExist($files, OC::$APPSROOT, OC::$APPSWEBROOT, "apps/$style$fext.css" )) { + }elseif(self::appendIfExist($files, OC::$APPSROOT, OC::$APPSWEBROOT, "apps/$style.css" )) { + + // or in the owncloud root? + }elseif(self::appendIfExist($files, OC::$SERVERROOT, OC::$WEBROOT, "$style$fext.css" )) { + }elseif(self::appendIfExist($files, OC::$SERVERROOT, OC::$WEBROOT, "$style.css" )) { + + // or in core ? + }elseif(self::appendIfExist($files, OC::$SERVERROOT, OC::$WEBROOT, "core/$style$fext.css" )) { + }elseif(self::appendIfExist($files, OC::$SERVERROOT, OC::$WEBROOT, "core/$style.css" )) { + + }else{ + echo('css file not found: style:'.$style.' formfactor:'.$fext.' webroot:'.OC::$WEBROOT.' serverroot:'.OC::$SERVERROOT); + die(); + } + } + // Add the theme css files. you can override the default values here + if(!empty($theme)) { + foreach($styles as $style){ + if(self::appendIfExist($files, OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/apps/$style$fext.css" )) { + }elseif(self::appendIfExist($files, OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/apps/$style.css" )) { + + }elseif(self::appendIfExist($files, OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/$style$fext.css" )) { + }elseif(self::appendIfExist($files, OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/$style.css" )) { + + }elseif(self::appendIfExist($files, OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/core/$style$fext.css" )) { + }elseif(self::appendIfExist($files, OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/core/$style.css" )) { + } + } + } + return $files; + } + + static public function findJavascriptFiles($scripts){ + // Read the selected theme from the config file + $theme=OC_Config::getValue( 'theme' ); + + // Read the detected formfactor and use the right file name. + $fext = self::getFormFactorExtension(); + + $files = array(); + foreach($scripts as $script){ + // Is it in 3rd party? + if(self::appendIfExist($files, OC::$THIRDPARTYROOT, OC::$THIRDPARTYWEBROOT, $script.'.js')) { + + // Is it in apps and overwritten by the theme? + }elseif(self::appendIfExist($files, OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/apps/$script$fext.js" )) { + }elseif(self::appendIfExist($files, OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/apps/$script.js" )) { + + // Is it part of an app? + }elseif(self::appendIfExist($files, OC::$APPSROOT, OC::$APPSWEBROOT, "apps/$script$fext.js" )) { + }elseif(self::appendIfExist($files, OC::$APPSROOT, OC::$APPSWEBROOT, "apps/$script.js" )) { + + // Is it in the owncloud root but overwritten by the theme? + }elseif(self::appendIfExist($files, OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/$script$fext.js" )) { + }elseif(self::appendIfExist($files, OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/$script.js" )) { + + // Is it in the owncloud root ? + }elseif(self::appendIfExist($files, OC::$SERVERROOT, OC::$WEBROOT, "$script$fext.js" )) { + }elseif(self::appendIfExist($files, OC::$SERVERROOT, OC::$WEBROOT, "$script.js" )) { + + // Is in core but overwritten by a theme? + }elseif(self::appendIfExist($files, OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/core/$script$fext.js" )) { + }elseif(self::appendIfExist($files, OC::$SERVERROOT, OC::$WEBROOT, "themes/$theme/core/$script.js" )) { + + // Is it in core? + }elseif(self::appendIfExist($files, OC::$SERVERROOT, OC::$WEBROOT, "core/$script$fext.js" )) { + }elseif(self::appendIfExist($files, OC::$SERVERROOT, OC::$WEBROOT, "core/$script.js" )) { + + }else{ + echo('js file not found: script:'.$script.' formfactor:'.$fext.' webroot:'.OC::$WEBROOT.' serverroot:'.OC::$SERVERROOT); + die(); + + } + } + return $files; + } +} diff --git a/lib/user.php b/lib/user.php index f1903093d6d..23b88aa1d06 100644 --- a/lib/user.php +++ b/lib/user.php @@ -240,13 +240,17 @@ class OC_User { * Checks if the user is logged in */ public static function isLoggedIn(){ + static $is_login_checked = null; + if (!is_null($is_login_checked)) { + return $is_login_checked; + } if( isset($_SESSION['user_id']) AND $_SESSION['user_id']) { OC_App::loadApps(array('authentication')); if (self::userExists($_SESSION['user_id']) ){ - return true; + return $is_login_checked = true; } } - return false; + return $is_login_checked = false; } /** diff --git a/lib/util.php b/lib/util.php index cedbe3fa460..8a2d913109d 100755 --- a/lib/util.php +++ b/lib/util.php @@ -14,41 +14,16 @@ class OC_Util { public static $core_scripts=array(); // Can be set up - public static function setupFS( $user = "", $root = "files" ){// configure the initial filesystem based on the configuration + public static function setupFS( $user = '' ){// configure the initial filesystem based on the configuration if(self::$fsSetup){//setting up the filesystem twice can only lead to trouble return false; } - $CONFIG_DATADIRECTORY_ROOT = OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" ); - $CONFIG_BACKUPDIRECTORY = OC_Config::getValue( "backupdirectory", OC::$SERVERROOT."/backup" ); - - // Check if config folder is writable. - if(!is_writable(OC::$SERVERROOT."/config/")) { - $tmpl = new OC_Template( '', 'error', 'guest' ); - $tmpl->assign('errors',array(1=>array('error'=>"Can't write into config directory 'config'",'hint'=>"You can usually fix this by giving the webserver user write access to the config directory in owncloud"))); - $tmpl->printPage(); - exit; - } - - // Check if there is a writable install folder. - if(OC_Config::getValue('appstoreenabled', true)) { - if( OC_App::getInstallPath() === null || !is_writable(OC_App::getInstallPath())) { - $tmpl = new OC_Template( '', 'error', 'guest' ); - $tmpl->assign('errors',array(1=>array('error'=>"Can't write into apps directory 'apps'",'hint'=>"You can usually fix this by giving the webserver user write access to the config directory in owncloud"))); - $tmpl->printPage(); - exit; - } - } - - // Create root dir. - if(!is_dir($CONFIG_DATADIRECTORY_ROOT)){ - $success=@mkdir($CONFIG_DATADIRECTORY_ROOT); - if(!$success) { - $tmpl = new OC_Template( '', 'error', 'guest' ); - $tmpl->assign('errors',array(1=>array('error'=>"Can't create data directory (".$CONFIG_DATADIRECTORY_ROOT.")",'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' "))); - $tmpl->printPage(); - exit; - } + $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),'/'); + self::$rootMounted=true; } // If we are not forced to load a specific user we load the one that is logged in @@ -56,31 +31,28 @@ class OC_Util { $user = OC_User::getUser(); } - //first set up the local "root" storage - if(!self::$rootMounted){ - OC_Filesystem::mount('OC_Filestorage_Local',array('datadir'=>$CONFIG_DATADIRECTORY_ROOT),'/'); - self::$rootMounted=true; - } if( $user != "" ){ //if we aren't logged in, there is no use to set up the filesystem - OC::$CONFIG_DATADIRECTORY = $CONFIG_DATADIRECTORY_ROOT."/$user/$root"; - if( !is_dir( OC::$CONFIG_DATADIRECTORY )){ - mkdir( OC::$CONFIG_DATADIRECTORY, 0755, true ); + $user_dir = '/'.$user.'/files'; + $userdirectory = $CONFIG_DATADIRECTORY.$user_dir; + if( !is_dir( $userdirectory )){ + mkdir( $userdirectory, 0755, true ); } //jail the user into his "home" directory - OC_Filesystem::init('/'.$user.'/'.$root); + OC_Filesystem::init($user_dir); $quotaProxy=new OC_FileProxy_Quota(); OC_FileProxy::register($quotaProxy); self::$fsSetup=true; // Load personal mount config - if (is_file($CONFIG_DATADIRECTORY_ROOT.'/'.$user.'/mount.php')) { - $mountConfig = include($CONFIG_DATADIRECTORY_ROOT.'/'.$user.'/mount.php'); + if (is_file($CONFIG_DATADIRECTORY.'/'.$user.'/mount.php')) { + $mountConfig = include($CONFIG_DATADIRECTORY.'/'.$user.'/mount.php'); if (isset($mountConfig['user'][$user])) { foreach ($mountConfig['user'][$user] as $mountPoint => $options) { OC_Filesystem::mount($options['class'], $options['options'], $mountPoint); } } } + OC_Hook::emit('OC_Filesystem', 'setup', array('user' => $user, 'user_dir' => $user_dir)); } } @@ -211,9 +183,6 @@ class OC_Util { * @return array arrays with error messages and hints */ public static function checkServer(){ - $CONFIG_DATADIRECTORY_ROOT = OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" ); - $CONFIG_BACKUPDIRECTORY = OC_Config::getValue( "backupdirectory", OC::$SERVERROOT."/backup" ); - $CONFIG_INSTALLED = OC_Config::getValue( "installed", false ); $errors=array(); //check for database drivers @@ -226,19 +195,31 @@ class OC_Util { //common hint for all file permissons error messages $permissionsHint="Permissions can usually be fixed by giving the webserver write access to the ownCloud directory"; + // Check if config folder is writable. + if(!is_writable(OC::$SERVERROOT."/config/")) { + $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 apps folder is writable. + if(OC_Config::getValue('writable_appsdir', true) && !is_writable(OC::$SERVERROOT."/apps/")) { + $errors[]=array('error'=>"Can't write into apps directory 'apps'",'hint'=>"You can usually fix this by giving the webserver user write access to the config directory in owncloud"); + } + + $CONFIG_DATADIRECTORY = OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" ); //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_ROOT)),-3); + $prems=substr(decoct(@fileperms($CONFIG_DATADIRECTORY)),-3); if(substr($prems,-1)!='0'){ - OC_Helper::chmodr($CONFIG_DATADIRECTORY_ROOT,0770); + OC_Helper::chmodr($CONFIG_DATADIRECTORY,0770); clearstatcache(); - $prems=substr(decoct(@fileperms($CONFIG_DATADIRECTORY_ROOT)),-3); + $prems=substr(decoct(@fileperms($CONFIG_DATADIRECTORY)),-3); if(substr($prems,2,1)!='0'){ - $errors[]=array('error'=>'Data directory ('.$CONFIG_DATADIRECTORY_ROOT.') is readable for other users<br/>','hint'=>$permissionsModHint); + $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); @@ -252,8 +233,14 @@ class OC_Util { }else{ //TODO: permissions checks for windows hosts } - if(is_dir($CONFIG_DATADIRECTORY_ROOT) and !is_writable($CONFIG_DATADIRECTORY_ROOT)){ - $errors[]=array('error'=>'Data directory ('.$CONFIG_DATADIRECTORY_ROOT.') not writable by ownCloud<br/>','hint'=>$permissionsHint); + // Create root dir. + 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' "); + } + } else if(!is_writable($CONFIG_DATADIRECTORY)){ + $errors[]=array('error'=>'Data directory ('.$CONFIG_DATADIRECTORY.') not writable by ownCloud<br/>','hint'=>$permissionsHint); } // check if all required php modules are present @@ -337,7 +324,11 @@ class OC_Util { OC_Log::write('core','redirectToDefaultPage',OC_Log::DEBUG); if(isset($_REQUEST['redirect_url']) && (substr($_REQUEST['redirect_url'], 0, strlen(OC::$WEBROOT)) == OC::$WEBROOT || $_REQUEST['redirect_url'][0] == '/')) { header( 'Location: '.$_REQUEST['redirect_url']); - } else { + } + else if (isset(OC::$REQUESTEDAPP) && !empty(OC::$REQUESTEDAPP)) { + header( 'Location: '.OC::$WEBROOT.'/?app='.OC::$REQUESTEDAPP ); + } + else { header( 'Location: '.OC::$WEBROOT.'/'.OC_Appconfig::getValue('core', 'defaultpage', '?app=files')); } exit(); @@ -372,7 +363,7 @@ class OC_Util { $_SESSION['requesttoken-'.$token]=time(); // cleanup old tokens garbage collector - // only run every 20th time so we donīt waste cpu cycles + // 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 @@ -428,4 +419,58 @@ class OC_Util { exit; } } + + /** + * @brief Public function to sanitize HTML + * + * This function is used to sanitize HTML and should be applied on any string or array of strings before displaying it on a web page. + * + * @param string or array of strings + * @return array with sanitized strings or a single sinitized 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'); + else $value = htmlentities($value, ENT_QUOTES, 'UTF-8'); //Specify encoding for PHP<5.4 + return $value; + } + + + /** + * Check if the htaccess file is working buy creating a test file in the data directory and trying to access via http + */ + public static function ishtaccessworking() { + + // testdata + $filename='/htaccesstest.txt'; + $testcontent='testcontent'; + + // creating a test file + $testfile = OC_Config::getValue( "datadirectory", OC::$SERVERROOT."/data" ).'/'.$filename; + $fp = @fopen($testfile, 'w'); + @fwrite($fp, $testcontent); + @fclose($fp); + + // accessing the file via http + $url = OC_Helper::serverProtocol(). '://' . OC_Helper::serverHost() . OC::$WEBROOT.'/data'.$filename; + $fp = @fopen($url, 'r'); + $content=@fread($fp, 2048); + @fclose($fp); + + // cleanup + @unlink($testfile); + + // does it work ? + if($content==$testcontent) { + return(false); + }else{ + return(true); + + } + + } + + + + + } |