From bd834220959bf7edcc4cce4bfe6c77e0a4649b8b Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 7 Sep 2012 18:30:48 +0200 Subject: [PATCH 001/347] put filestorages in a namespace --- apps/files_encryption/tests/proxy.php | 2 +- apps/files_external/appinfo/app.php | 16 ++--- apps/files_external/lib/amazons3.php | 14 ++-- apps/files_external/lib/config.php | 18 ++--- apps/files_external/lib/dropbox.php | 18 ++--- apps/files_external/lib/ftp.php | 6 +- apps/files_external/lib/google.php | 18 ++--- apps/files_external/lib/smb.php | 4 +- apps/files_external/lib/streamwrapper.php | 5 +- apps/files_external/lib/swift.php | 12 ++-- apps/files_external/lib/webdav.php | 12 ++-- apps/files_external/personal.php | 2 +- apps/files_external/tests/amazons3.php | 2 +- apps/files_external/tests/ftp.php | 2 +- apps/files_external/tests/google.php | 2 +- apps/files_external/tests/smb.php | 2 +- apps/files_external/tests/swift.php | 2 +- apps/files_external/tests/webdav.php | 2 +- apps/files_sharing/appinfo/app.php | 4 +- apps/files_sharing/lib/sharedstorage.php | 68 ++++++++++--------- lib/base.php | 3 + lib/{filestorage => files/storage}/common.php | 44 +++++------- .../storage}/commontest.php | 10 +-- lib/{filestorage => files/storage}/local.php | 17 +++-- .../storage/storage.php} | 28 +++----- lib/files/storage/temporary.php | 26 +++++++ lib/filestorage/temporary.php | 17 ----- lib/filesystem.php | 12 ++-- lib/filesystemview.php | 12 ++-- lib/util.php | 4 +- tests/lib/cache/file.php | 2 +- tests/lib/filestorage.php | 2 +- tests/lib/filestorage/commontest.php | 2 +- tests/lib/filestorage/local.php | 2 +- tests/lib/filesystem.php | 4 +- 35 files changed, 205 insertions(+), 191 deletions(-) rename lib/{filestorage => files/storage}/common.php (83%) rename lib/{filestorage => files/storage}/commontest.php (88%) rename lib/{filestorage => files/storage}/local.php (90%) rename lib/{filestorage.php => files/storage/storage.php} (71%) create mode 100644 lib/files/storage/temporary.php delete mode 100644 lib/filestorage/temporary.php diff --git a/apps/files_encryption/tests/proxy.php b/apps/files_encryption/tests/proxy.php index 042011a6c8..d600bbc407 100644 --- a/apps/files_encryption/tests/proxy.php +++ b/apps/files_encryption/tests/proxy.php @@ -30,7 +30,7 @@ class Test_CryptProxy extends UnitTestCase { //set up temporary storage OC_Filesystem::clearMounts(); - OC_Filesystem::mount('OC_Filestorage_Temporary',array(),'/'); + OC_Filesystem::mount('\OC\Files\Storage\Temporary',array(),'/'); OC_Filesystem::init('/'.$user.'/files'); diff --git a/apps/files_external/appinfo/app.php b/apps/files_external/appinfo/app.php index 837d35c9c6..c58cfcd0f5 100644 --- a/apps/files_external/appinfo/app.php +++ b/apps/files_external/appinfo/app.php @@ -6,14 +6,14 @@ * See the COPYING-README file. */ -OC::$CLASSPATH['OC_FileStorage_StreamWrapper']='apps/files_external/lib/streamwrapper.php'; -OC::$CLASSPATH['OC_Filestorage_FTP']='apps/files_external/lib/ftp.php'; -OC::$CLASSPATH['OC_Filestorage_DAV']='apps/files_external/lib/webdav.php'; -OC::$CLASSPATH['OC_Filestorage_Google']='apps/files_external/lib/google.php'; -OC::$CLASSPATH['OC_Filestorage_SWIFT']='apps/files_external/lib/swift.php'; -OC::$CLASSPATH['OC_Filestorage_SMB']='apps/files_external/lib/smb.php'; -OC::$CLASSPATH['OC_Filestorage_AmazonS3']='apps/files_external/lib/amazons3.php'; -OC::$CLASSPATH['OC_Filestorage_Dropbox']='apps/files_external/lib/dropbox.php'; +OC::$CLASSPATH['OC\Files\Storage\StreamWrapper']='apps/files_external/lib/streamwrapper.php'; +OC::$CLASSPATH['OC\Files\Storage\FTP']='apps/files_external/lib/ftp.php'; +OC::$CLASSPATH['OC\Files\Storage\DAV']='apps/files_external/lib/webdav.php'; +OC::$CLASSPATH['OC\Files\Storage\Google']='apps/files_external/lib/google.php'; +OC::$CLASSPATH['OC\Files\Storage\SWIFT']='apps/files_external/lib/swift.php'; +OC::$CLASSPATH['OC\Files\Storage\SMB']='apps/files_external/lib/smb.php'; +OC::$CLASSPATH['OC\Files\Storage\AmazonS3']='apps/files_external/lib/amazons3.php'; +OC::$CLASSPATH['OC\Files\Storage\Dropbox']='apps/files_external/lib/dropbox.php'; OC::$CLASSPATH['OC_Mount_Config']='apps/files_external/lib/config.php'; OCP\App::registerAdmin('files_external', 'settings'); diff --git a/apps/files_external/lib/amazons3.php b/apps/files_external/lib/amazons3.php index 41ec3c70b4..a17a70ed38 100644 --- a/apps/files_external/lib/amazons3.php +++ b/apps/files_external/lib/amazons3.php @@ -22,7 +22,9 @@ require_once 'aws-sdk/sdk.class.php'; -class OC_Filestorage_AmazonS3 extends OC_Filestorage_Common { +namespace OC\Files\Storage; + +class AmazonS3 extends \OC\Files\Storage\Common { private $s3; private $bucket; @@ -33,7 +35,7 @@ class OC_Filestorage_AmazonS3 extends OC_Filestorage_Common { // TODO options: storage class, encryption server side, encrypt before upload? public function __construct($params) { - $this->s3 = new AmazonS3(array('key' => $params['key'], 'secret' => $params['secret'])); + $this->s3 = new \AmazonS3(array('key' => $params['key'], 'secret' => $params['secret'])); $this->bucket = $params['bucket']; } @@ -96,7 +98,7 @@ class OC_Filestorage_AmazonS3 extends OC_Filestorage_Common { foreach ($response->body->CommonPrefixes as $object) { $files[] = basename($object->Prefix); } - OC_FakeDirStream::$dirs['amazons3'.$path] = $files; + \OC_FakeDirStream::$dirs['amazons3'.$path] = $files; return opendir('fakedir://amazons3'.$path); } return false; @@ -160,7 +162,7 @@ class OC_Filestorage_AmazonS3 extends OC_Filestorage_Common { switch ($mode) { case 'r': case 'rb': - $tmpFile = OC_Helper::tmpFile(); + $tmpFile = \OC_Helper::tmpFile(); $handle = fopen($tmpFile, 'w'); $response = $this->s3->get_object($this->bucket, $path, array('fileDownload' => $handle)); if ($response->isOK()) { @@ -184,8 +186,8 @@ class OC_Filestorage_AmazonS3 extends OC_Filestorage_Common { } else { $ext = ''; } - $tmpFile = OC_Helper::tmpFile($ext); - OC_CloseStreamWrapper::$callBacks[$tmpFile] = array($this, 'writeBack'); + $tmpFile = \OC_Helper::tmpFile($ext); + \OC_CloseStreamWrapper::$callBacks[$tmpFile] = array($this, 'writeBack'); if ($this->file_exists($path)) { $source = $this->fopen($path, 'r'); file_put_contents($tmpFile, $source); diff --git a/apps/files_external/lib/config.php b/apps/files_external/lib/config.php index eec31ec2ef..db09fbdd82 100755 --- a/apps/files_external/lib/config.php +++ b/apps/files_external/lib/config.php @@ -39,14 +39,14 @@ class OC_Mount_Config { */ public static function getBackends() { return array( - 'OC_Filestorage_Local' => array('backend' => 'Local', 'configuration' => array('datadir' => 'Location')), - 'OC_Filestorage_AmazonS3' => array('backend' => 'Amazon S3', 'configuration' => array('key' => 'Key', 'secret' => '*Secret', 'bucket' => 'Bucket')), - 'OC_Filestorage_Dropbox' => array('backend' => 'Dropbox', 'configuration' => array('configured' => '#configured','app_key' => 'App key', 'app_secret' => 'App secret', 'token' => '#token', 'token_secret' => '#token_secret'), 'custom' => 'dropbox'), - 'OC_Filestorage_FTP' => array('backend' => 'FTP', 'configuration' => array('host' => 'URL', 'user' => 'Username', 'password' => '*Password', 'root' => '&Root', 'secure' => '!Secure ftps://')), - 'OC_Filestorage_Google' => array('backend' => 'Google Drive', 'configuration' => array('configured' => '#configured', 'token' => '#token', 'token_secret' => '#token secret'), 'custom' => 'google'), - 'OC_Filestorage_SWIFT' => array('backend' => 'OpenStack Swift', 'configuration' => array('host' => 'URL', 'user' => 'Username', 'token' => '*Token', 'root' => '&Root', 'secure' => '!Secure ftps://')), - 'OC_Filestorage_SMB' => array('backend' => 'SMB', 'configuration' => array('host' => 'URL', 'user' => 'Username', 'password' => '*Password', 'share' => 'Share', 'root' => '&Root')), - 'OC_Filestorage_DAV' => array('backend' => 'WebDAV', 'configuration' => array('host' => 'URL', 'user' => 'Username', 'password' => '*Password', 'root' => '&Root', 'secure' => '!Secure https://')) + '\OC\Files\Storage\Local' => array('backend' => 'Local', 'configuration' => array('datadir' => 'Location')), + '\OC\Files\Storage\AmazonS3' => array('backend' => 'Amazon S3', 'configuration' => array('key' => 'Key', 'secret' => '*Secret', 'bucket' => 'Bucket')), + '\OC\Files\Storage\Dropbox' => array('backend' => 'Dropbox', 'configuration' => array('configured' => '#configured','app_key' => 'App key', 'app_secret' => 'App secret', 'token' => '#token', 'token_secret' => '#token_secret'), 'custom' => 'dropbox'), + '\OC\Files\Storage\FTP' => array('backend' => 'FTP', 'configuration' => array('host' => 'URL', 'user' => 'Username', 'password' => '*Password', 'root' => '&Root', 'secure' => '!Secure ftps://')), + '\OC\Files\Storage\Google' => array('backend' => 'Google Drive', 'configuration' => array('configured' => '#configured', 'token' => '#token', 'token_secret' => '#token secret'), 'custom' => 'google'), + '\OC\Files\Storage\SWIFT' => array('backend' => 'OpenStack Swift', 'configuration' => array('host' => 'URL', 'user' => 'Username', 'token' => '*Token', 'root' => '&Root', 'secure' => '!Secure ftps://')), + '\OC\Files\Storage\SMB' => array('backend' => 'SMB', 'configuration' => array('host' => 'URL', 'user' => 'Username', 'password' => '*Password', 'share' => 'Share', 'root' => '&Root')), + '\OC\Files\Storage\DAV' => array('backend' => 'WebDAV', 'configuration' => array('host' => 'URL', 'user' => 'Username', 'password' => '*Password', 'root' => '&Root', 'secure' => '!Secure https://')) ); } @@ -124,7 +124,7 @@ class OC_Mount_Config { if ($isPersonal) { // Verify that the mount point applies for the current user // Prevent non-admin users from mounting local storage - if ($applicable != OCP\User::getUser() || $class == 'OC_Filestorage_Local') { + if ($applicable != OCP\User::getUser() || $class == '\OC\Files\Storage\Local') { return false; } $mountPoint = '/'.$applicable.'/files/'.ltrim($mountPoint, '/'); diff --git a/apps/files_external/lib/dropbox.php b/apps/files_external/lib/dropbox.php index bb86894e55..746364668f 100755 --- a/apps/files_external/lib/dropbox.php +++ b/apps/files_external/lib/dropbox.php @@ -22,7 +22,9 @@ require_once 'Dropbox/autoload.php'; -class OC_Filestorage_Dropbox extends OC_Filestorage_Common { +namespace OC\Files\Storage; + +class Dropbox extends \OC\Files\Storage\Common { private $dropbox; private $metaData = array(); @@ -31,11 +33,11 @@ class OC_Filestorage_Dropbox extends OC_Filestorage_Common { public function __construct($params) { if (isset($params['configured']) && $params['configured'] == 'true' && isset($params['app_key']) && isset($params['app_secret']) && isset($params['token']) && isset($params['token_secret'])) { - $oauth = new Dropbox_OAuth_Curl($params['app_key'], $params['app_secret']); + $oauth = new \Dropbox_OAuth_Curl($params['app_key'], $params['app_secret']); $oauth->setToken($params['token'], $params['token_secret']); - $this->dropbox = new Dropbox_API($oauth, 'dropbox'); + $this->dropbox = new \Dropbox_API($oauth, 'dropbox'); } else { - throw new Exception('Creating OC_Filestorage_Dropbox storage failed'); + throw new \Exception('Creating \OC\Files\Storage\Dropbox storage failed'); } } @@ -95,7 +97,7 @@ class OC_Filestorage_Dropbox extends OC_Filestorage_Common { foreach ($contents as $file) { $files[] = basename($file['path']); } - OC_FakeDirStream::$dirs['dropbox'.$path] = $files; + \OC_FakeDirStream::$dirs['dropbox'.$path] = $files; return opendir('fakedir://dropbox'.$path); } return false; @@ -177,7 +179,7 @@ class OC_Filestorage_Dropbox extends OC_Filestorage_Common { switch ($mode) { case 'r': case 'rb': - $tmpFile = OC_Helper::tmpFile(); + $tmpFile = \OC_Helper::tmpFile(); try { $data = $this->dropbox->getFile($path); file_put_contents($tmpFile, $data); @@ -203,8 +205,8 @@ class OC_Filestorage_Dropbox extends OC_Filestorage_Common { } else { $ext = ''; } - $tmpFile = OC_Helper::tmpFile($ext); - OC_CloseStreamWrapper::$callBacks[$tmpFile] = array($this, 'writeBack'); + $tmpFile = \OC_Helper::tmpFile($ext); + \OC_CloseStreamWrapper::$callBacks[$tmpFile] = array($this, 'writeBack'); if ($this->file_exists($path)) { $source = $this->fopen($path, 'r'); file_put_contents($tmpFile, $source); diff --git a/apps/files_external/lib/ftp.php b/apps/files_external/lib/ftp.php index 261141455c..140a21ffe1 100644 --- a/apps/files_external/lib/ftp.php +++ b/apps/files_external/lib/ftp.php @@ -6,7 +6,9 @@ * See the COPYING-README file. */ -class OC_FileStorage_FTP extends OC_FileStorage_StreamWrapper{ +namespace OC\Files\Storage; + +class FTP extends \OC\Files\Storage\StreamWrapper{ private $password; private $user; private $host; @@ -69,7 +71,7 @@ class OC_FileStorage_FTP extends OC_FileStorage_StreamWrapper{ $ext=''; } $tmpFile=OCP\Files::tmpFile($ext); - OC_CloseStreamWrapper::$callBacks[$tmpFile]=array($this,'writeBack'); + \OC_CloseStreamWrapper::$callBacks[$tmpFile]=array($this,'writeBack'); if($this->file_exists($path)) { $this->getFile($path,$tmpFile); } diff --git a/apps/files_external/lib/google.php b/apps/files_external/lib/google.php index 9b83dcee53..51c5d219aa 100644 --- a/apps/files_external/lib/google.php +++ b/apps/files_external/lib/google.php @@ -22,7 +22,9 @@ require_once 'Google/common.inc.php'; -class OC_Filestorage_Google extends OC_Filestorage_Common { +namespace OC\Files\Storage; + +class Google extends \OC\Files\Storage\Common { private $consumer; private $oauth_token; @@ -35,12 +37,12 @@ class OC_Filestorage_Google extends OC_Filestorage_Common { if (isset($params['configured']) && $params['configured'] == 'true' && isset($params['token']) && isset($params['token_secret'])) { $consumer_key = isset($params['consumer_key']) ? $params['consumer_key'] : 'anonymous'; $consumer_secret = isset($params['consumer_secret']) ? $params['consumer_secret'] : 'anonymous'; - $this->consumer = new OAuthConsumer($consumer_key, $consumer_secret); - $this->oauth_token = new OAuthToken($params['token'], $params['token_secret']); - $this->sig_method = new OAuthSignatureMethod_HMAC_SHA1(); + $this->consumer = new \OAuthConsumer($consumer_key, $consumer_secret); + $this->oauth_token = new \OAuthToken($params['token'], $params['token_secret']); + $this->sig_method = new \OAuthSignatureMethod_HMAC_SHA1(); $this->entries = array(); } else { - throw new Exception('Creating OC_Filestorage_Google storage failed'); + throw new \Exception('Creating \OC\Files\Storage\Google storage failed'); } } @@ -96,7 +98,7 @@ class OC_Filestorage_Google extends OC_Filestorage_Common { curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); } if ($isDownload) { - $tmpFile = OC_Helper::tmpFile(); + $tmpFile = \OC_Helper::tmpFile(); $handle = fopen($tmpFile, 'w'); curl_setopt($curl, CURLOPT_FILE, $handle); } @@ -399,7 +401,7 @@ class OC_Filestorage_Google extends OC_Filestorage_Common { } else { $ext = ''; } - $tmpFile = OC_Helper::tmpFile($ext); + $tmpFile = \OC_Helper::tmpFile($ext); OC_CloseStreamWrapper::$callBacks[$tmpFile] = array($this, 'writeBack'); if ($this->file_exists($path)) { $source = $this->fopen($path, 'r'); @@ -438,7 +440,7 @@ class OC_Filestorage_Google extends OC_Filestorage_Common { } if (isset($uploadUri) && $handle = fopen($path, 'r')) { $uploadUri .= '?convert=false'; - $mimetype = OC_Helper::getMimeType($path); + $mimetype = \OC_Helper::getMimeType($path); $size = filesize($path); $headers = array('X-Upload-Content-Type: ' => $mimetype, 'X-Upload-Content-Length: ' => $size); $postData = ''; diff --git a/apps/files_external/lib/smb.php b/apps/files_external/lib/smb.php index e5ba7a1774..d4882ed024 100644 --- a/apps/files_external/lib/smb.php +++ b/apps/files_external/lib/smb.php @@ -8,7 +8,9 @@ require_once 'smb4php/smb.php'; -class OC_FileStorage_SMB extends OC_FileStorage_StreamWrapper{ +namespace OC\Files\Storage; + +class SMB extends \OC\Files\Storage\StreamWrapper{ private $password; private $user; private $host; diff --git a/apps/files_external/lib/streamwrapper.php b/apps/files_external/lib/streamwrapper.php index 7263ef2325..750bdbaf4d 100644 --- a/apps/files_external/lib/streamwrapper.php +++ b/apps/files_external/lib/streamwrapper.php @@ -6,8 +6,9 @@ * See the COPYING-README file. */ +namespace OC\Files\Storage; -abstract class OC_FileStorage_StreamWrapper extends OC_Filestorage_Common{ +abstract class StreamWrapper extends \OC\Files\Storage\Common{ abstract public function constructUrl($path); public function mkdir($path) { @@ -84,6 +85,4 @@ abstract class OC_FileStorage_StreamWrapper extends OC_Filestorage_Common{ return stat($this->constructUrl($path)); } - - } diff --git a/apps/files_external/lib/swift.php b/apps/files_external/lib/swift.php index c29d28b44c..c67cf59df6 100644 --- a/apps/files_external/lib/swift.php +++ b/apps/files_external/lib/swift.php @@ -8,7 +8,9 @@ require_once 'php-cloudfiles/cloudfiles.php'; -class OC_FileStorage_SWIFT extends OC_Filestorage_Common{ +namespace OC\Files\Storage; + +class SWIFT extends \OC\Files\Storage\Common{ private $host; private $root; private $user; @@ -272,10 +274,10 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{ if(!$this->root || $this->root[0]!='/') { $this->root='/'.$this->root; } - $this->auth = new CF_Authentication($this->user, $this->token, null, $this->host); + $this->auth = new \CF_Authentication($this->user, $this->token, null, $this->host); $this->auth->authenticate(); - $this->conn = new CF_Connection($this->auth); + $this->conn = new \CF_Connection($this->auth); if(!$this->containerExists($this->root)) { $this->rootContainer=$this->createContainer('/'); @@ -341,7 +343,7 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{ $subContainers=$this->getSubContainers($container); $files=array_merge($files,$subContainers); $id=$this->getContainerName($path); - OC_FakeDirStream::$dirs[$id]=$files; + \OC_FakeDirStream::$dirs[$id]=$files; return opendir('fakedir://'.$id); } @@ -426,7 +428,7 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{ case 'c': case 'c+': $tmpFile=$this->getTmpFile($path); - OC_CloseStreamWrapper::$callBacks[$tmpFile]=array($this,'writeBack'); + \OC_CloseStreamWrapper::$callBacks[$tmpFile]=array($this,'writeBack'); self::$tempFiles[$tmpFile]=$path; return fopen('close://'.$tmpFile,$mode); } diff --git a/apps/files_external/lib/webdav.php b/apps/files_external/lib/webdav.php index 3c18b227fa..70210b49ee 100644 --- a/apps/files_external/lib/webdav.php +++ b/apps/files_external/lib/webdav.php @@ -6,7 +6,9 @@ * See the COPYING-README file. */ -class OC_FileStorage_DAV extends OC_Filestorage_Common{ +namespace OC\Files\Storage; + +class DAV extends \OC\Files\Storage\Common{ private $password; private $user; private $host; @@ -42,7 +44,7 @@ class OC_FileStorage_DAV extends OC_Filestorage_Common{ 'password' => $this->password, ); - $this->client = new OC_Connector_Sabre_Client($settings); + $this->client = new \OC_Connector_Sabre_Client($settings); if($caview = \OCP\Files::getStorage('files_external')) { $certPath=\OCP\Config::getSystemValue('datadirectory').$caview->getAbsolutePath("").'rootcerts.crt'; @@ -78,12 +80,12 @@ class OC_FileStorage_DAV extends OC_Filestorage_Common{ try{ $response=$this->client->propfind($path, array(),1); $id=md5('webdav'.$this->root.$path); - OC_FakeDirStream::$dirs[$id]=array(); + \OC_FakeDirStream::$dirs[$id]=array(); $files=array_keys($response); array_shift($files);//the first entry is the current directory foreach($files as $file) { $file = urldecode(basename($file)); - OC_FakeDirStream::$dirs[$id][]=$file; + \OC_FakeDirStream::$dirs[$id][]=$file; } return opendir('fakedir://'.$id); }catch(Exception $e) { @@ -161,7 +163,7 @@ class OC_FileStorage_DAV extends OC_Filestorage_Common{ $ext=''; } $tmpFile=OCP\Files::tmpFile($ext); - OC_CloseStreamWrapper::$callBacks[$tmpFile]=array($this,'writeBack'); + \OC_CloseStreamWrapper::$callBacks[$tmpFile]=array($this,'writeBack'); if($this->file_exists($path)) { $this->getFile($path,$tmpFile); } diff --git a/apps/files_external/personal.php b/apps/files_external/personal.php index f0d76460f5..a678f345c8 100755 --- a/apps/files_external/personal.php +++ b/apps/files_external/personal.php @@ -24,7 +24,7 @@ OCP\Util::addScript('files_external', 'settings'); OCP\Util::addStyle('files_external', 'settings'); $backends = OC_Mount_Config::getBackends(); // Remove local storage -unset($backends['OC_Filestorage_Local']); +unset($backends['\OC\Files\Storage\Local']); $tmpl = new OCP\Template('files_external', 'settings'); $tmpl->assign('isAdminPage', false, false); $tmpl->assign('mounts', OC_Mount_Config::getPersonalMountPoints()); diff --git a/apps/files_external/tests/amazons3.php b/apps/files_external/tests/amazons3.php index b9b4cf65bd..ad1c453abb 100644 --- a/apps/files_external/tests/amazons3.php +++ b/apps/files_external/tests/amazons3.php @@ -34,7 +34,7 @@ if (!is_array($config) or !isset($config['amazons3']) or !$config['amazons3']['r $id = uniqid(); $this->config = include('apps/files_external/tests/config.php'); $this->config['amazons3']['bucket'] = $id; // Make sure we have a new empty bucket to work in - $this->instance = new OC_Filestorage_AmazonS3($this->config['amazons3']); + $this->instance = new \OC\Files\Storage\AmazonS3($this->config['amazons3']); } public function tearDown() { diff --git a/apps/files_external/tests/ftp.php b/apps/files_external/tests/ftp.php index 12f3ec3908..105f7b485b 100644 --- a/apps/files_external/tests/ftp.php +++ b/apps/files_external/tests/ftp.php @@ -18,7 +18,7 @@ if(!is_array($config) or !isset($config['ftp']) or !$config['ftp']['run']) { $id=uniqid(); $this->config=include('apps/files_external/tests/config.php'); $this->config['ftp']['root'].='/'.$id;//make sure we have an new empty folder to work in - $this->instance=new OC_Filestorage_FTP($this->config['ftp']); + $this->instance=new \OC\Files\Storage\FTP($this->config['ftp']); } public function tearDown() { diff --git a/apps/files_external/tests/google.php b/apps/files_external/tests/google.php index d2a6358ade..e96c2263e1 100644 --- a/apps/files_external/tests/google.php +++ b/apps/files_external/tests/google.php @@ -33,7 +33,7 @@ if(!is_array($config) or !isset($config['google']) or !$config['google']['run']) $id=uniqid(); $this->config=include('apps/files_external/tests/config.php'); $this->config['google']['root'].='/'.$id;//make sure we have an new empty folder to work in - $this->instance=new OC_Filestorage_Google($this->config['google']); + $this->instance=new \OC\Files\Storage\Google($this->config['google']); } public function tearDown() { diff --git a/apps/files_external/tests/smb.php b/apps/files_external/tests/smb.php index 7de4fddbb3..a0c5d83473 100644 --- a/apps/files_external/tests/smb.php +++ b/apps/files_external/tests/smb.php @@ -19,7 +19,7 @@ if(!is_array($config) or !isset($config['smb']) or !$config['smb']['run']) { $id=uniqid(); $this->config=include('apps/files_external/tests/config.php'); $this->config['smb']['root'].=$id;//make sure we have an new empty folder to work in - $this->instance=new OC_Filestorage_SMB($this->config['smb']); + $this->instance=new \OC\Files\Storage\SMB($this->config['smb']); } public function tearDown() { diff --git a/apps/files_external/tests/swift.php b/apps/files_external/tests/swift.php index a6f5eace1c..3e1485b0f3 100644 --- a/apps/files_external/tests/swift.php +++ b/apps/files_external/tests/swift.php @@ -18,7 +18,7 @@ if(!is_array($config) or !isset($config['swift']) or !$config['swift']['run']) { $id=uniqid(); $this->config=include('apps/files_external/tests/config.php'); $this->config['swift']['root'].='/'.$id;//make sure we have an new empty folder to work in - $this->instance=new OC_Filestorage_SWIFT($this->config['swift']); + $this->instance=new \OC\Files\Storage\SWIFT($this->config['swift']); } diff --git a/apps/files_external/tests/webdav.php b/apps/files_external/tests/webdav.php index 74d980aa3f..6b1121c9d0 100644 --- a/apps/files_external/tests/webdav.php +++ b/apps/files_external/tests/webdav.php @@ -18,7 +18,7 @@ if(!is_array($config) or !isset($config['webdav']) or !$config['webdav']['run']) $id=uniqid(); $this->config=include('apps/files_external/tests/config.php'); $this->config['webdav']['root'].='/'.$id;//make sure we have an new empty folder to work in - $this->instance=new OC_Filestorage_DAV($this->config['webdav']); + $this->instance=new \OC\Files\Storage\DAV($this->config['webdav']); } public function tearDown() { diff --git a/apps/files_sharing/appinfo/app.php b/apps/files_sharing/appinfo/app.php index 109f86b2e8..210c78ad17 100644 --- a/apps/files_sharing/appinfo/app.php +++ b/apps/files_sharing/appinfo/app.php @@ -2,8 +2,8 @@ OC::$CLASSPATH['OC_Share_Backend_File'] = "apps/files_sharing/lib/share/file.php"; OC::$CLASSPATH['OC_Share_Backend_Folder'] = 'apps/files_sharing/lib/share/folder.php'; -OC::$CLASSPATH['OC_Filestorage_Shared'] = "apps/files_sharing/lib/sharedstorage.php"; -OCP\Util::connectHook('OC_Filesystem', 'setup', 'OC_Filestorage_Shared', 'setup'); +OC::$CLASSPATH['OC\Files\Storage\Shared'] = "apps/files_sharing/lib/sharedstorage.php"; +OCP\Util::connectHook('OC_Filesystem', 'setup', '\OC\Files\Storage\Shared', 'setup'); OCP\Share::registerBackend('file', 'OC_Share_Backend_File'); OCP\Share::registerBackend('folder', 'OC_Share_Backend_Folder', 'file'); OCP\Util::addScript('files_sharing', 'share'); diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php index 6dba76955a..f1539610b0 100644 --- a/apps/files_sharing/lib/sharedstorage.php +++ b/apps/files_sharing/lib/sharedstorage.php @@ -20,10 +20,12 @@ * */ +namespace OC\Files\Storage; + /** * Convert target path to source path and pass the function call to the correct storage provider */ -class OC_Filestorage_Shared extends OC_Filestorage_Common { +class Shared extends \OC\Files\Storage\Common { private $sharedFolder; private $files = array(); @@ -50,7 +52,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { if (isset($this->files[$folder])) { $file = $this->files[$folder]; } else { - $file = OCP\Share::getItemSharedWith('folder', $folder, OC_Share_Backend_File::FORMAT_SHARED_STORAGE); + $file = OCP\Share::getItemSharedWith('folder', $folder, \OC_Share_Backend_File::FORMAT_SHARED_STORAGE); } if ($file) { $this->files[$target]['path'] = $file['path'].substr($target, strlen($folder)); @@ -58,7 +60,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { return $this->files[$target]; } } else { - $file = OCP\Share::getItemSharedWith('file', $target, OC_Share_Backend_File::FORMAT_SHARED_STORAGE); + $file = OCP\Share::getItemSharedWith('file', $target, \OC_Share_Backend_File::FORMAT_SHARED_STORAGE); if ($file) { $this->files[$target] = $file; return $this->files[$target]; @@ -78,7 +80,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { $file = $this->getFile($target); if (isset($file['path'])) { $uid = substr($file['path'], 1, strpos($file['path'], '/', 1) - 1); - OC_Filesystem::mount('OC_Filestorage_Local', array('datadir' => OC_User::getHome($uid)), $uid); + \OC_Filesystem::mount('\OC\Files\Storage\Local', array('datadir' => \OC_User::getHome($uid)), $uid); return $file['path']; } return false; @@ -103,7 +105,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { * @return Source file path with mount point stripped out */ private function getInternalPath($path) { - $mountPoint = OC_Filesystem::getMountPoint($path); + $mountPoint = \OC_Filesystem::getMountPoint($path); $internalPath = substr($path, strlen($mountPoint)); return $internalPath; } @@ -112,7 +114,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { if ($path == '' || $path == '/' || !$this->isCreatable(dirname($path))) { return false; } else if ($source = $this->getSourcePath($path)) { - $storage = OC_Filesystem::getStorage($source); + $storage = \OC_Filesystem::getStorage($source); return $storage->mkdir($this->getInternalPath($source)); } return false; @@ -120,7 +122,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { public function rmdir($path) { if (($source = $this->getSourcePath($path)) && $this->isDeletable($path)) { - $storage = OC_Filesystem::getStorage($source); + $storage = \OC_Filesystem::getStorage($source); return $storage->rmdir($this->getInternalPath($source)); } return false; @@ -128,11 +130,11 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { public function opendir($path) { if ($path == '' || $path == '/') { - $files = OCP\Share::getItemsSharedWith('file', OC_Share_Backend_Folder::FORMAT_OPENDIR); - OC_FakeDirStream::$dirs['shared'] = $files; + $files = OCP\Share::getItemsSharedWith('file', \OC_Share_Backend_Folder::FORMAT_OPENDIR); + \OC_FakeDirStream::$dirs['shared'] = $files; return opendir('fakedir://shared'); } else if ($source = $this->getSourcePath($path)) { - $storage = OC_Filesystem::getStorage($source); + $storage = \OC_Filesystem::getStorage($source); return $storage->opendir($this->getInternalPath($source)); } return false; @@ -142,7 +144,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { if ($path == '' || $path == '/') { return true; } else if ($source = $this->getSourcePath($path)) { - $storage = OC_Filesystem::getStorage($source); + $storage = \OC_Filesystem::getStorage($source); return $storage->is_dir($this->getInternalPath($source)); } return false; @@ -150,7 +152,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { public function is_file($path) { if ($source = $this->getSourcePath($path)) { - $storage = OC_Filesystem::getStorage($source); + $storage = \OC_Filesystem::getStorage($source); return $storage->is_file($this->getInternalPath($source)); } return false; @@ -163,7 +165,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { $stat['ctime'] = $this->filectime($path); return $stat; } else if ($source = $this->getSourcePath($path)) { - $storage = OC_Filesystem::getStorage($source); + $storage = \OC_Filesystem::getStorage($source); return $storage->stat($this->getInternalPath($source)); } return false; @@ -173,7 +175,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { if ($path == '' || $path == '/') { return 'dir'; } else if ($source = $this->getSourcePath($path)) { - $storage = OC_Filesystem::getStorage($source); + $storage = \OC_Filesystem::getStorage($source); return $storage->filetype($this->getInternalPath($source)); } return false; @@ -183,7 +185,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { if ($path == '' || $path == '/' || $this->is_dir($path)) { return 0; } else if ($source = $this->getSourcePath($path)) { - $storage = OC_Filesystem::getStorage($source); + $storage = \OC_Filesystem::getStorage($source); return $storage->filesize($this->getInternalPath($source)); } return false; @@ -225,7 +227,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { if ($path == '' || $path == '/') { return true; } else if ($source = $this->getSourcePath($path)) { - $storage = OC_Filesystem::getStorage($source); + $storage = \OC_Filesystem::getStorage($source); return $storage->file_exists($this->getInternalPath($source)); } return false; @@ -246,7 +248,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { } else { $source = $this->getSourcePath($path); if ($source) { - $storage = OC_Filesystem::getStorage($source); + $storage = \OC_Filesystem::getStorage($source); return $storage->filectime($this->getInternalPath($source)); } } @@ -267,7 +269,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { } else { $source = $this->getSourcePath($path); if ($source) { - $storage = OC_Filesystem::getStorage($source); + $storage = \OC_Filesystem::getStorage($source); return $storage->filemtime($this->getInternalPath($source)); } } @@ -280,8 +282,8 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { 'target' => $this->sharedFolder.$path, 'source' => $source, ); - OCP\Util::emitHook('OC_Filestorage_Shared', 'file_get_contents', $info); - $storage = OC_Filesystem::getStorage($source); + OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_get_contents', $info); + $storage = \OC_Filesystem::getStorage($source); return $storage->file_get_contents($this->getInternalPath($source)); } } @@ -296,8 +298,8 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { 'target' => $this->sharedFolder.$path, 'source' => $source, ); - OCP\Util::emitHook('OC_Filestorage_Shared', 'file_put_contents', $info); - $storage = OC_Filesystem::getStorage($source); + OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_put_contents', $info); + $storage = \OC_Filesystem::getStorage($source); $result = $storage->file_put_contents($this->getInternalPath($source), $data); return $result; } @@ -308,7 +310,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { // Delete the file if DELETE permission is granted if ($source = $this->getSourcePath($path)) { if ($this->isDeletable($path)) { - $storage = OC_Filesystem::getStorage($source); + $storage = \OC_Filesystem::getStorage($source); return $storage->unlink($this->getInternalPath($source)); } else if (dirname($path) == '/' || dirname($path) == '.') { // Unshare the file from the user if in the root of the Shared folder @@ -332,7 +334,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { if (dirname($path1) == dirname($path2)) { // Rename the file if UPDATE permission is granted if ($this->isUpdatable($path1)) { - $storage = OC_Filesystem::getStorage($oldSource); + $storage = \OC_Filesystem::getStorage($oldSource); return $storage->rename($this->getInternalPath($oldSource), $this->getInternalPath($newSource)); } } else { @@ -347,7 +349,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { return $this->unlink($path1); } } else { - $storage = OC_Filesystem::getStorage($oldSource); + $storage = \OC_Filesystem::getStorage($oldSource); return $storage->rename($this->getInternalPath($oldSource), $this->getInternalPath($newSource)); } } @@ -361,7 +363,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { if ($this->isCreatable(dirname($path2))) { $source = $this->fopen($path1, 'r'); $target = $this->fopen($path2, 'w'); - return OC_Helper::streamCopy($source, $target); + return \OC_Helper::streamCopy($source, $target); } return false; } @@ -392,8 +394,8 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { 'source' => $source, 'mode' => $mode, ); - OCP\Util::emitHook('OC_Filestorage_Shared', 'fopen', $info); - $storage = OC_Filesystem::getStorage($source); + OCP\Util::emitHook('\OC\Files\Storage\Shared', 'fopen', $info); + $storage = \OC_Filesystem::getStorage($source); return $storage->fopen($this->getInternalPath($source), $mode); } return false; @@ -404,7 +406,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { return 'httpd/unix-directory'; } if ($source = $this->getSourcePath($path)) { - $storage = OC_Filesystem::getStorage($source); + $storage = \OC_Filesystem::getStorage($source); return $storage->getMimeType($this->getInternalPath($source)); } return false; @@ -413,21 +415,21 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { public function free_space($path) { $source = $this->getSourcePath($path); if ($source) { - $storage = OC_Filesystem::getStorage($source); + $storage = \OC_Filesystem::getStorage($source); return $storage->free_space($this->getInternalPath($source)); } } public function getLocalFile($path) { if ($source = $this->getSourcePath($path)) { - $storage = OC_Filesystem::getStorage($source); + $storage = \OC_Filesystem::getStorage($source); return $storage->getLocalFile($this->getInternalPath($source)); } return false; } public function touch($path, $mtime = null) { if ($source = $this->getSourcePath($path)) { - $storage = OC_Filesystem::getStorage($source); + $storage = \OC_Filesystem::getStorage($source); return $storage->touch($this->getInternalPath($source), $mtime); } return false; @@ -435,7 +437,7 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common { public static function setup($options) { $user_dir = $options['user_dir']; - OC_Filesystem::mount('OC_Filestorage_Shared', array('sharedFolder' => '/Shared'), $user_dir.'/Shared/'); + \OC_Filesystem::mount('\OC\Files\Storage\Shared', array('sharedFolder' => '/Shared'), $user_dir.'/Shared/'); } /** diff --git a/lib/base.php b/lib/base.php index 1c6cc70b0e..3b2ab8d5eb 100644 --- a/lib/base.php +++ b/lib/base.php @@ -81,6 +81,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'); } diff --git a/lib/filestorage/common.php b/lib/files/storage/common.php similarity index 83% rename from lib/filestorage/common.php rename to lib/files/storage/common.php index 351714437c..0a60ff757e 100644 --- a/lib/filestorage/common.php +++ b/lib/files/storage/common.php @@ -1,38 +1,26 @@ . -*/ + * Copyright (c) 2012 Robin Appelman + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Files\Storage; /** * Storage backend class for providing common filesystem operation methods * which are not storage-backend specific. * - * OC_Filestorage_Common is never used directly; it is extended by all other + * \OC\Files\Storage\Common is never used directly; it is extended by all other * storage backends, where its methods may be overridden, and additional * (backend-specific) methods are defined. * - * Some OC_Filestorage_Common methods call functions which are first defined + * Some \OC\Files\Storage\Common methods call functions which are first defined * in classes which extend it, e.g. $this->stat() . */ -abstract class OC_Filestorage_Common extends OC_Filestorage { +abstract class Common extends \OC\Files\Storage\Storage { public function __construct($parameters) {} // abstract public function mkdir($path); @@ -104,7 +92,7 @@ abstract class OC_Filestorage_Common extends OC_Filestorage { public function copy($path1,$path2) { $source=$this->fopen($path1,'r'); $target=$this->fopen($path2,'w'); - $count=OC_Helper::streamCopy($source,$target); + $count=\OC_Helper::streamCopy($source,$target); return $count>0; } // abstract public function fopen($path,$mode); @@ -198,9 +186,9 @@ abstract class OC_Filestorage_Common extends OC_Filestorage { }else{ $extension=''; } - $tmpFile=OC_Helper::tmpFile($extension); + $tmpFile=\OC_Helper::tmpFile($extension); file_put_contents($tmpFile,$head); - $mime=OC_Helper::getMimeType($tmpFile); + $mime=\OC_Helper::getMimeType($tmpFile); unlink($tmpFile); return $mime; } @@ -227,13 +215,13 @@ abstract class OC_Filestorage_Common extends OC_Filestorage { }else{ $extension=''; } - $tmpFile=OC_Helper::tmpFile($extension); + $tmpFile=\OC_Helper::tmpFile($extension); $target=fopen($tmpFile,'w'); - OC_Helper::streamCopy($source,$target); + \OC_Helper::streamCopy($source,$target); return $tmpFile; } public function getLocalFolder($path) { - $baseDir=OC_Helper::tmpFolder(); + $baseDir=\OC_Helper::tmpFolder(); $this->addLocalFolder($path,$baseDir); return $baseDir; } diff --git a/lib/filestorage/commontest.php b/lib/files/storage/commontest.php similarity index 88% rename from lib/filestorage/commontest.php rename to lib/files/storage/commontest.php index b88bb232c3..773bfffcb4 100644 --- a/lib/filestorage/commontest.php +++ b/lib/files/storage/commontest.php @@ -22,18 +22,20 @@ */ /** - * test implementation for OC_FileStorage_Common with OC_FileStorage_Local + * test implementation for \OC\Files\Storage\Common with \OC\Files\Storage\Local */ -class OC_Filestorage_CommonTest extends OC_Filestorage_Common{ +namespace OC\Files\Storage; + +class CommonTest extends \OC\Files\Storage\Common{ /** * underlying local storage used for missing functions - * @var OC_FileStorage_Local + * @var \OC\Files\Storage\Local */ private $storage; public function __construct($params) { - $this->storage=new OC_Filestorage_Local($params); + $this->storage=new \OC\Files\Storage\Local($params); } public function mkdir($path) { diff --git a/lib/filestorage/local.php b/lib/files/storage/local.php similarity index 90% rename from lib/filestorage/local.php rename to lib/files/storage/local.php index e26d3d3ef9..e47441499a 100644 --- a/lib/filestorage/local.php +++ b/lib/files/storage/local.php @@ -1,8 +1,17 @@ + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Files\Storage; + /** * for local filestore, we only have to map the paths */ -class OC_Filestorage_Local extends OC_Filestorage_Common{ +class Local extends \OC\Files\Storage\Common{ protected $datadir; public function __construct($arguments) { $this->datadir=$arguments['datadir']; @@ -86,11 +95,11 @@ class OC_Filestorage_Local extends OC_Filestorage_Common{ } public function rename($path1,$path2) { if (!$this->isUpdatable($path1)) { - OC_Log::write('core','unable to rename, file is not writable : '.$path1,OC_Log::ERROR); + \OC_Log::write('core','unable to rename, file is not writable : '.$path1,\OC_Log::ERROR); return false; } if(! $this->file_exists($path1)) { - OC_Log::write('core','unable to rename, file does not exists : '.$path1,OC_Log::ERROR); + \OC_Log::write('core','unable to rename, file does not exists : '.$path1,\OC_Log::ERROR); return false; } @@ -129,7 +138,7 @@ class OC_Filestorage_Local extends OC_Filestorage_Common{ public function getMimeType($path) { if($this->isReadable($path)) { - return OC_Helper::getMimeType($this->datadir.$path); + return \OC_Helper::getMimeType($this->datadir.$path); }else{ return false; } diff --git a/lib/filestorage.php b/lib/files/storage/storage.php similarity index 71% rename from lib/filestorage.php rename to lib/files/storage/storage.php index 5bfd09253d..a2f6cb7ec3 100644 --- a/lib/filestorage.php +++ b/lib/files/storage/storage.php @@ -1,29 +1,17 @@ . -*/ + * Copyright (c) 2012 Robin Appelman + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Files\Storage; /** * Provde a common interface to all different storage options */ -abstract class OC_Filestorage{ +abstract class Storage{ abstract public function __construct($parameters); abstract public function mkdir($path); abstract public function rmdir($path); diff --git a/lib/files/storage/temporary.php b/lib/files/storage/temporary.php new file mode 100644 index 0000000000..0e69c9112a --- /dev/null +++ b/lib/files/storage/temporary.php @@ -0,0 +1,26 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Files\Storage; + +/** + * local storage backnd in temporary folder for testing purpores + */ +class Temporary extends OC\Files\Storage\Local{ + public function __construct($arguments) { + $this->datadir=\OC_Helper::tmpFolder(); + } + + public function cleanUp() { + \OC_Helper::rmdirr($this->datadir); + } + + public function __destruct() { + $this->cleanUp(); + } +} diff --git a/lib/filestorage/temporary.php b/lib/filestorage/temporary.php deleted file mode 100644 index 876ba045a6..0000000000 --- a/lib/filestorage/temporary.php +++ /dev/null @@ -1,17 +0,0 @@ -datadir=OC_Helper::tmpFolder(); - } - - public function cleanUp() { - OC_Helper::rmdirr($this->datadir); - } - - public function __destruct() { - $this->cleanUp(); - } -} diff --git a/lib/filesystem.php b/lib/filesystem.php index 92eb4fa477..9b022d8fef 100644 --- a/lib/filesystem.php +++ b/lib/filesystem.php @@ -48,7 +48,7 @@ class OC_Filesystem{ static private $mounts=array(); public static $loaded=false; /** - * @var OC_Filestorage $defaultInstance + * @var \OC\Files\Storage\Storage $defaultInstance */ static private $defaultInstance; @@ -181,7 +181,7 @@ class OC_Filesystem{ /** * get the storage object for a path * @param string path - * @return OC_Filestorage + * @return \OC\Files\Storage\Storage */ static public function getStorage($path) { $mountpoint=self::getMountPoint($path); @@ -276,7 +276,7 @@ class OC_Filesystem{ * create a new storage of a specific type * @param string type * @param array arguments - * @return OC_Filestorage + * @return \OC\Files\Storage\Storage */ static private function createStorage($class,$arguments) { if(class_exists($class)) { @@ -320,9 +320,9 @@ class OC_Filesystem{ } /** - * mount an OC_Filestorage in our virtual filesystem - * @param OC_Filestorage storage - * @param string mountpoint + * mount an \OC\Files\Storage\Storage in our virtual filesystem + * @param \OC\Files\Storage\Storage storage + * @param string mountpoint */ static public function mount($class,$arguments,$mountpoint) { if($mountpoint[0]!='/') { diff --git a/lib/filesystemview.php b/lib/filesystemview.php index 743f940301..36fef48551 100644 --- a/lib/filesystemview.php +++ b/lib/filesystemview.php @@ -35,7 +35,7 @@ * are triggered correctly. * * Filesystem functions are not called directly; they are passed to the correct - * OC_Filestorage object + * \OC\Files\Storage\Storage object */ class OC_FilesystemView { @@ -115,7 +115,7 @@ class OC_FilesystemView { /** * get the storage object for a path * @param string path - * @return OC_Filestorage + * @return \OC\Files\Storage\Storage */ public function getStorage($path) { if (!isset($this->storage_cache[$path])) { @@ -161,7 +161,7 @@ class OC_FilesystemView { /** * the following functions operate with arguments and return values identical * to those of their PHP built-in equivalents. Mostly they are merely wrappers - * for OC_Filestorage via basicOperation(). + * for \OC\Files\Storage\Storage via basicOperation(). */ public function mkdir($path) { return $this->basicOperation('mkdir', $path, array('create', 'write')); @@ -173,7 +173,7 @@ class OC_FilesystemView { return $this->basicOperation('opendir', $path, array('read')); } public function readdir($handle) { - $fsLocal= new OC_Filestorage_Local( array( 'datadir' => '/' ) ); + $fsLocal= new \OC\Files\Storage\Local( array( 'datadir' => '/' ) ); return $fsLocal->readdir( $handle ); } public function is_dir($path) { @@ -540,7 +540,7 @@ class OC_FilesystemView { } /** - * @brief abstraction layer for basic filesystem functions: wrapper for OC_Filestorage + * @brief abstraction layer for basic filesystem functions: wrapper for \OC\Files\Storage\Storage * @param string $operation * @param string #path * @param array (optional) hooks @@ -549,7 +549,7 @@ class OC_FilesystemView { * * This method takes requests for basic filesystem functions (e.g. reading & writing * files), processes hooks and proxies, sanitises paths, and finally passes them on to - * OC_Filestorage for delegation to a storage backend for execution + * \OC\Files\Storage\Storage for delegation to a storage backend for execution */ private function basicOperation($operation, $path, $hooks=array(), $extraParam=null) { $postFix=(substr($path,-1,1)==='/')?'/':''; diff --git a/lib/util.php b/lib/util.php index 5046550d6a..78976c9660 100755 --- a/lib/util.php +++ b/lib/util.php @@ -34,7 +34,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\Files\Storage\Local',array('datadir'=>$CONFIG_DATADIRECTORY),'/'); self::$rootMounted=true; } @@ -46,7 +46,7 @@ class OC_Util { mkdir( $userdirectory, 0755, true ); } //jail the user into his "home" directory - OC_Filesystem::mount('OC_Filestorage_Local', array('datadir' => $user_root), $user); + OC_Filesystem::mount('\OC\Files\Storage\Local', array('datadir' => $user_root), $user); OC_Filesystem::init($user_dir); $quotaProxy=new OC_FileProxy_Quota(); OC_FileProxy::register($quotaProxy); diff --git a/tests/lib/cache/file.php b/tests/lib/cache/file.php index 00be005d08..1dd1ff7fa8 100644 --- a/tests/lib/cache/file.php +++ b/tests/lib/cache/file.php @@ -39,7 +39,7 @@ class Test_Cache_File extends Test_Cache { //set up temporary storage OC_Filesystem::clearMounts(); - OC_Filesystem::mount('OC_Filestorage_Temporary',array(),'/'); + OC_Filesystem::mount('\OC\Files\Storage\Temporary',array(),'/'); OC_User::clearBackends(); OC_User::useBackend(new OC_User_Dummy()); diff --git a/tests/lib/filestorage.php b/tests/lib/filestorage.php index 3f7bb7b62d..bfb40bcd67 100644 --- a/tests/lib/filestorage.php +++ b/tests/lib/filestorage.php @@ -22,7 +22,7 @@ abstract class Test_FileStorage extends UnitTestCase { /** - * @var OC_Filestorage instance + * @var \OC\Files\Storage\Storage instance */ protected $instance; diff --git a/tests/lib/filestorage/commontest.php b/tests/lib/filestorage/commontest.php index 89e83589e5..0e52e91678 100644 --- a/tests/lib/filestorage/commontest.php +++ b/tests/lib/filestorage/commontest.php @@ -30,7 +30,7 @@ class Test_Filestorage_CommonTest extends Test_FileStorage { if(!file_exists($this->tmpDir)) { mkdir($this->tmpDir); } - $this->instance=new OC_Filestorage_CommonTest(array('datadir'=>$this->tmpDir)); + $this->instance=new \OC\Files\Storage\CommonTest(array('datadir'=>$this->tmpDir)); } public function tearDown() { diff --git a/tests/lib/filestorage/local.php b/tests/lib/filestorage/local.php index f68fb69b97..7bb27830ba 100644 --- a/tests/lib/filestorage/local.php +++ b/tests/lib/filestorage/local.php @@ -27,7 +27,7 @@ class Test_Filestorage_Local extends Test_FileStorage { private $tmpDir; public function setUp() { $this->tmpDir=OC_Helper::tmpFolder(); - $this->instance=new OC_Filestorage_Local(array('datadir'=>$this->tmpDir)); + $this->instance=new \OC\Files\Storage\Local(array('datadir'=>$this->tmpDir)); } public function tearDown() { diff --git a/tests/lib/filesystem.php b/tests/lib/filesystem.php index 1cfa35e305..5f5d393ed5 100644 --- a/tests/lib/filesystem.php +++ b/tests/lib/filesystem.php @@ -46,13 +46,13 @@ class Test_Filesystem extends UnitTestCase{ } public function testMount() { - OC_Filesystem::mount('OC_Filestorage_Local',self::getStorageData(),'/'); + OC_Filesystem::mount('\OC\Files\Storage\Local',self::getStorageData(),'/'); $this->assertEqual('/',OC_Filesystem::getMountPoint('/')); $this->assertEqual('/',OC_Filesystem::getMountPoint('/some/folder')); $this->assertEqual('',OC_Filesystem::getInternalPath('/')); $this->assertEqual('some/folder',OC_Filesystem::getInternalPath('/some/folder')); - OC_Filesystem::mount('OC_Filestorage_Local',self::getStorageData(),'/some'); + OC_Filesystem::mount('\OC\Files\Storage\Local',self::getStorageData(),'/some'); $this->assertEqual('/',OC_Filesystem::getMountPoint('/')); $this->assertEqual('/some/',OC_Filesystem::getMountPoint('/some/folder')); $this->assertEqual('/some/',OC_Filesystem::getMountPoint('/some/')); From e8d3a4768541980fcc391117e5a173875b2f75e0 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 12 Sep 2012 22:50:10 +0200 Subject: [PATCH 002/347] add getId to storage backends --- lib/files/storage/common.php | 1 + lib/files/storage/commontest.php | 3 +++ lib/files/storage/local.php | 3 +++ lib/files/storage/storage.php | 1 + 4 files changed, 8 insertions(+) diff --git a/lib/files/storage/common.php b/lib/files/storage/common.php index 0a60ff757e..1f8b620480 100644 --- a/lib/files/storage/common.php +++ b/lib/files/storage/common.php @@ -23,6 +23,7 @@ namespace OC\Files\Storage; abstract class Common extends \OC\Files\Storage\Storage { public function __construct($parameters) {} +// abstract public function getId(); // abstract public function mkdir($path); // abstract public function rmdir($path); // abstract public function opendir($path); diff --git a/lib/files/storage/commontest.php b/lib/files/storage/commontest.php index 773bfffcb4..2b42cfe115 100644 --- a/lib/files/storage/commontest.php +++ b/lib/files/storage/commontest.php @@ -38,6 +38,9 @@ class CommonTest extends \OC\Files\Storage\Common{ $this->storage=new \OC\Files\Storage\Local($params); } + public function getId(){ + return 'test::'.$this->storage->getId(); + } public function mkdir($path) { return $this->storage->mkdir($path); } diff --git a/lib/files/storage/local.php b/lib/files/storage/local.php index e47441499a..78e4877a00 100644 --- a/lib/files/storage/local.php +++ b/lib/files/storage/local.php @@ -19,6 +19,9 @@ class Local extends \OC\Files\Storage\Common{ $this->datadir.='/'; } } + public function getId(){ + return 'local::'.$this->datadir; + } public function mkdir($path) { return @mkdir($this->datadir.$path); } diff --git a/lib/files/storage/storage.php b/lib/files/storage/storage.php index a2f6cb7ec3..bd4cc4743b 100644 --- a/lib/files/storage/storage.php +++ b/lib/files/storage/storage.php @@ -13,6 +13,7 @@ namespace OC\Files\Storage; */ abstract class Storage{ abstract public function __construct($parameters); + abstract public function getId(); abstract public function mkdir($path); abstract public function rmdir($path); abstract public function opendir($path); From 68f65b657c398d44508d20b56ccf9ddbee8e3521 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 12 Sep 2012 22:53:10 +0200 Subject: [PATCH 003/347] add OC_Filesystem::resolvePath to get the storage backend and internal path for a file in one go --- lib/filesystem.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lib/filesystem.php b/lib/filesystem.php index 9b022d8fef..ef8b3fef5b 100644 --- a/lib/filesystem.php +++ b/lib/filesystem.php @@ -194,6 +194,24 @@ class OC_Filesystem{ } } + /** + * resolve a path to a storage and internal path + * @param string $path + * @return array consisting of the storage and the internal path + */ + static public function resolvePath($path){ + $mountpoint=self::getMountPoint($path); + if($mountpoint) { + if(!isset(OC_Filesystem::$storages[$mountpoint])) { + $mount=OC_Filesystem::$mounts[$mountpoint]; + OC_Filesystem::$storages[$mountpoint]=OC_Filesystem::createStorage($mount['class'],$mount['arguments']); + } + $storage = OC_Filesystem::$storages[$mountpoint]; + $internalPath=substr($path,strlen($mountpoint)); + return array($storage, $internalPath); + } + } + static public function init($root) { if(self::$defaultInstance) { return false; From c94fe38d3900acff474c909aaa730d7ab51f914d Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 12 Sep 2012 23:25:57 +0200 Subject: [PATCH 004/347] add getPermissions to storage backends to get all permission flags in one go --- lib/files/storage/common.php | 19 +++++++++++++++++++ lib/files/storage/storage.php | 1 + 2 files changed, 20 insertions(+) diff --git a/lib/files/storage/common.php b/lib/files/storage/common.php index 1f8b620480..b2b4ea8eee 100644 --- a/lib/files/storage/common.php +++ b/lib/files/storage/common.php @@ -54,6 +54,25 @@ abstract class Common extends \OC\Files\Storage\Storage { public function isSharable($path) { return $this->isReadable($path); } + public function getPermissions($path){ + $permissions = 0; + if($this->isCreatable($path)){ + $permissions |= OCP\Share::PERMISSION_CREATE; + } + if($this->isReadable($path)){ + $permissions |= OCP\Share::PERMISSION_READ; + } + if($this->isUpdatable($path)){ + $permissions |= OCP\Share::PERMISSION_UPDATE; + } + if($this->isDeletable($path)){ + $permissions |= OCP\Share::PERMISSION_DELETE; + } + if($this->isSharable($path)){ + $permissions |= OCP\Share::PERMISSION_SHARE; + } + return $permissions; + } // abstract public function file_exists($path); public function filectime($path) { $stat = $this->stat($path); diff --git a/lib/files/storage/storage.php b/lib/files/storage/storage.php index bd4cc4743b..f149c61830 100644 --- a/lib/files/storage/storage.php +++ b/lib/files/storage/storage.php @@ -27,6 +27,7 @@ abstract class Storage{ abstract public function isUpdatable($path); abstract public function isDeletable($path); abstract public function isSharable($path); + abstract public function getPermissions($path); abstract public function file_exists($path); abstract public function filectime($path); abstract public function filemtime($path); From 954596c251cb3132878d8d5eafcc37c47b3f520e Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sun, 16 Sep 2012 16:52:32 +0200 Subject: [PATCH 005/347] rework filecache to work directly on storage backends wip --- lib/files/cache/cache.php | 189 ++++++++++++++++++++++++++++++++++++ lib/files/cache/scanner.php | 78 +++++++++++++++ lib/files/file.php | 61 ++++++++++++ 3 files changed, 328 insertions(+) create mode 100644 lib/files/cache/cache.php create mode 100644 lib/files/cache/scanner.php create mode 100644 lib/files/file.php diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php new file mode 100644 index 0000000000..8fc575948d --- /dev/null +++ b/lib/files/cache/cache.php @@ -0,0 +1,189 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Files\Cache; + +class Cache { + /** + * @var array partial data for the cache + */ + private static $partial = array(); + + /** + * get the stored metadata of a file or folder + * + * @param \OC\Files\File or int $file + * @return array + */ + static public function get($file) { + if ($file instanceof \OC\Files\File) { + $where = 'WHERE `storage` = ? AND `path_hash` = ?'; + $params = array($file->getStorageId(), $file->getInternalPath()); + } else { //file id + $where = 'WHERE `fileid` = ?'; + $params = array($file); + } + $query = \OC_DB::prepare( + 'SELECT `id`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime` + FROM `*PREFIX*filecache` ' . $where); + $result=$query->execute($params); + return $result->fetchRow(); + } + + /** + * store meta data for a file or folder + * + * @param \OC\Files\File $file + * @param array $data + * + * @return int file id + */ + static public function put(\OC\Files\File $file, array $data) { + if ($id = self::getId($file) > -1) { + self::update($id, $data); + return $id; + } else { + $key = $file->getStorageId() . '::' . $file->getInternalPath(); + if (isset(self::$partial[$key])) { //add any saved partial data + $data = array_merge($data, self::$partial[$key]); + unset(self::$partial[$key]); + } + + $requiredFields = array('size', 'mtime', 'mimetype'); + foreach ($requiredFields as $field) { + if (!isset($data[$field])) { //data not complete save as partial and return + self::$partial[$key] = $data; + return -1; + } + } + + $data['path'] = $file->getInternalPath(); + $data['parent'] = self::getParentId($file); + $data['name'] = basename($file->getInternalPath()); + + list($queryParts, $params) = self::buildParts($data); + $queryParts[] = '`storage`'; + $params[] = $file->getStorageId(); + $valuesPlaceholder = array_fill(0, count($queryParts), '?'); + + $query = \OC_DB::prepare('INSERT INTO `*PREFIX*filecache`(' . implode(', ', $queryParts) . ' VALUES(' . implode(', ', $valuesPlaceholder) . ')'); + $query->execute($params); + + return \OC_DB::insertid('*PREFIX*filecache'); + } + } + + /** + * update the metadata in the cache + * + * @param int $id + * @param array $data + */ + static public function update($id, array $data) { + list($queryParts, $params) = self::buildParts($data); + $params[] = $id; + + $query = \OC_DB::prepare('UPDATE `*PREFIX*filecache` SET ' . implode(' = ?, ', $queryParts) . '=? WHERE fileid = ?'); + $query->execute($params); + } + + /** + * extract query parts and params array from data array + * + * @param array $data + * @return array + */ + private static function buildParts(array $data) { + $fields = array('path', 'parent', 'name', 'mimetype', 'size', 'mtime'); + + $params = array(); + $queryParts = array(); + foreach ($data as $name => $value) { + if (array_search($name, $fields) !== false) { + $params[] = $value; + $queryParts[] = '`' . $name . '`'; + if ($name === 'path') { + $params[] = md5($value); + $queryParts[] = '`path_hash`'; + } elseif ($name === 'mimetype') { + $params[] = substr($value, 0, strpos($value, '/')); + $queryParts[] = '`mimepart`'; + } + } + } + return array($queryParts, $params); + } + + /** + * get the file id for a file + * + * @param \OC\Files\File $file + * @return int + */ + static public function getId(\OC\Files\File $file) { + $storageId = $file->getStorageId(); + $pathHash = md5($file->getInternalPath()); + + $query = \OC_DB::prepare('SELECT id FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path_hash` = ?'); + $result = $query->execute(array($storageId, $pathHash)); + + if ($row = $result->fetchRow()) { + return $row['id']; + } else { + return -1; + } + } + + /** + * get the id of the parent folder of a file + * + * @param \OC\Files\File $file + * return int + */ + static public function getParentId(\OC\Files\File $file) { + $path = $file->getInternalPath(); + if ($path === '/' or $path === '') { + return -1; + } else { + return self::getId(new \OC\Files\File($file->getStorage(), dirname($path))); + } + } + + /** + * check if a file is available in the cache + * + * @param \OC\Files\File $file + * @return bool + */ + static public function inCache(\OC\Files\File $file) { + return self::getId($file) != -1; + } + + /** + * remove a file or folder from the cache + * + * @param \OC\Files\File $file + */ + public function remove(\OC\Files\File $file) { + $storageId = $file->getStorageId(); + $pathHash = md5($file->getInternalPath()); + $query = \OC_DB::prepare('DELETE FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path_hash` = ?'); + $query->execute(array($storageId, $pathHash)); + } + + /** + * remove all entries for files that are stored on $storage form the cache + * + * @param \OC\Files\Storage\Storage $storage + */ + public function removeStorage(\OC\Files\Storage\Storage $storage) { + $storageId = $storage->getId(); + $query = \OC_DB::prepare('DELETE FROM `*PREFIX*filecache` WHERE storage=?'); + $query->execute(array($storageId)); + } +} diff --git a/lib/files/cache/scanner.php b/lib/files/cache/scanner.php new file mode 100644 index 0000000000..8f2c5bda5c --- /dev/null +++ b/lib/files/cache/scanner.php @@ -0,0 +1,78 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Files\Cache; + +class Scanner { + const SCAN_RECURSIVE = true; + const SCAN_SHALLOW = false; + + /** + * get all the metadata of a file or folder + * * + * @param \OC\Files\File $file + * @return array with metadata of the file + */ + public static function getData(\OC\Files\File $file) { + $data = array(); + $storage = $file->getStorage(); + $path = $file->getInternalPath(); + if (!$storage->isReadable($path)) return null; //cant read, nothing we can do + clearstatcache(); + $data['mimetype'] = $storage->getMimeType($path); + $data['mtime'] = $storage->filemtime($path); + if ($data['mimetype'] == 'httpd/unix-directory') { + $data['size'] = -1; //unknown + $data['permissions'] = $storage->getPermissions($path . '/'); + } else { + $data['size'] = $storage->filesize($path); + $data['permissions'] = $storage->getPermissions($path); + } + return $data; + } + + /** + * scan a single file and store it in the cache + * + * @param \OC\Files\File $file + * @return array with metadata of the scanned file + */ + public static function scanFile(\OC\Files\File $file) { + $data = self::getData($file); + Cache::put($file, $data); + return $data; + } + + /** + * scan all the files in a folder and store them in the cache + * + * @param \OC\Files\File $folder + * @param SCAN_RECURSIVE/SCAN_SHALLOW $recursive + * @return int the size of the scanned folder or -1 if the size is unknown at this stage + */ + public static function scan(\OC\Files\File $folder, $recursive) { + $size = 0; + $storage = $folder->getStorage(); + $path = $folder->getInternalPath(); + if ($dh = $storage->opendir($path)) { + while ($file = readdir($dh)) { + if ($file !== '.' and $file !== '..') { + $child = new \OC\Files\File($storage, $path . '/' . $file); + $data = self::scanFile($child); + if ($recursive === self::SCAN_RECURSIVE and $data['mimetype'] === 'httpd/unix-directory') { + $data['size'] = self::scan($child, self::SCAN_RECURSIVE); + } + if ($data['size'] >= 0 and $size >= 0) { + $size += $data['size']; + } + } + } + } + return $size; + } +} diff --git a/lib/files/file.php b/lib/files/file.php new file mode 100644 index 0000000000..b6432e6345 --- /dev/null +++ b/lib/files/file.php @@ -0,0 +1,61 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Files; + +/** + * representation of the location a file or folder is stored + */ + +class File{ + /** + * @var Storage\Storage $storage + */ + private $storage; + /** + * @var string internalPath + */ + private $internalPath; + + public function __construct(Storage\Storage $storage, $internalPath){ + $this->storage = $storage; + $this->internalPath = $internalPath; + } + + public static function resolve($fullPath){ + $storage = null; + $internalPath = ''; + list($storage, $internalPath) = \OC_Filesystem::resolvePath($fullPath); + return new File($storage, $internalPath); + } + + /** + * get the internal path of the file inside the filestorage + * @return string + */ + public function getInternalPath(){ + return $this->internalPath; + } + + /** + * get the storage the file is stored in + * @return \OC\Files\Storage\Storage + */ + public function getStorage(){ + return $this->storage; + } + + /** + * get the id of the storage the file is stored in + * @return string + */ + public function getStorageId(){ + return $this->storage->getId(); + } + +} From 153cd802a9bbc0f5a5f67fe428af7ca78185011f Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sat, 22 Sep 2012 14:40:04 +0200 Subject: [PATCH 006/347] add partial file data to the result of Cache::get --- lib/files/cache/cache.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index 8fc575948d..9d90ab041f 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -31,7 +31,13 @@ class Cache { $query = \OC_DB::prepare( 'SELECT `id`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime` FROM `*PREFIX*filecache` ' . $where); - $result=$query->execute($params); + $result = $query->execute($params); + + //merge partial data + $key = $file->getStorageId() . '::' . $file->getInternalPath(); + if (isset(self::$partial[$key])) { + $result=array_merge($result, self::$partial[$key]); + } return $result->fetchRow(); } From 96b798a59f236f4251ced87ecac9da55e82d1685 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sat, 22 Sep 2012 14:51:15 +0200 Subject: [PATCH 007/347] move storage backend test cases to their own namespace --- apps/files_external/tests/amazons3.php | 8 +++--- apps/files_external/tests/ftp.php | 8 +++--- apps/files_external/tests/google.php | 6 +++-- apps/files_external/tests/smb.php | 8 +++--- apps/files_external/tests/swift.php | 6 +++-- apps/files_external/tests/webdav.php | 6 +++-- .../storage}/commontest.php | 8 +++--- .../{filestorage => files/storage}/local.php | 10 ++++---- .../storage/storage.php} | 25 ++++++++++--------- 9 files changed, 50 insertions(+), 35 deletions(-) rename tests/lib/{filestorage => files/storage}/commontest.php (91%) rename tests/lib/{filestorage => files/storage}/local.php (87%) rename tests/lib/{filestorage.php => files/storage/storage.php} (93%) diff --git a/apps/files_external/tests/amazons3.php b/apps/files_external/tests/amazons3.php index ad1c453abb..cf372aecbd 100644 --- a/apps/files_external/tests/amazons3.php +++ b/apps/files_external/tests/amazons3.php @@ -20,12 +20,14 @@ * License along with this library. If not, see . */ +namespace Test\Files\Storage; + $config = include('apps/files_external/tests/config.php'); if (!is_array($config) or !isset($config['amazons3']) or !$config['amazons3']['run']) { - abstract class Test_Filestorage_AmazonS3 extends Test_FileStorage{} + abstract class AmazonS3 extends Storage{} return; } else { - class Test_Filestorage_AmazonS3 extends Test_FileStorage { + class AmazonS3 extends Storage { private $config; private $id; @@ -38,7 +40,7 @@ if (!is_array($config) or !isset($config['amazons3']) or !$config['amazons3']['r } public function tearDown() { - $s3 = new AmazonS3(array('key' => $this->config['amazons3']['key'], 'secret' => $this->config['amazons3']['secret'])); + $s3 = new \AmazonS3(array('key' => $this->config['amazons3']['key'], 'secret' => $this->config['amazons3']['secret'])); if ($s3->delete_all_objects($this->id)) { $s3->delete_bucket($this->id); } diff --git a/apps/files_external/tests/ftp.php b/apps/files_external/tests/ftp.php index 105f7b485b..8a0821e25a 100644 --- a/apps/files_external/tests/ftp.php +++ b/apps/files_external/tests/ftp.php @@ -6,12 +6,14 @@ * See the COPYING-README file. */ +namespace Test\Files\Storage; + $config=include('apps/files_external/tests/config.php'); if(!is_array($config) or !isset($config['ftp']) or !$config['ftp']['run']) { - abstract class Test_Filestorage_FTP extends Test_FileStorage{} + abstract class FTP extends Storage{} return; }else{ - class Test_Filestorage_FTP extends Test_FileStorage { + class FTP extends Storage { private $config; public function setUp() { @@ -22,7 +24,7 @@ if(!is_array($config) or !isset($config['ftp']) or !$config['ftp']['run']) { } public function tearDown() { - OCP\Files::rmdirr($this->instance->constructUrl('')); + \OCP\Files::rmdirr($this->instance->constructUrl('')); } } } diff --git a/apps/files_external/tests/google.php b/apps/files_external/tests/google.php index e96c2263e1..fff6461c91 100644 --- a/apps/files_external/tests/google.php +++ b/apps/files_external/tests/google.php @@ -20,12 +20,14 @@ * License along with this library. If not, see . */ +namespace Test\Files\Storage; + $config=include('apps/files_external/tests/config.php'); if(!is_array($config) or !isset($config['google']) or !$config['google']['run']) { - abstract class Test_Filestorage_Google extends Test_FileStorage{} + abstract class Google extends Storage{} return; }else{ - class Test_Filestorage_Google extends Test_FileStorage { + class Google extends Storage { private $config; diff --git a/apps/files_external/tests/smb.php b/apps/files_external/tests/smb.php index a0c5d83473..87b110a241 100644 --- a/apps/files_external/tests/smb.php +++ b/apps/files_external/tests/smb.php @@ -8,11 +8,13 @@ $config=include('apps/files_external/tests/config.php'); +namespace Test\Files\Storage; + if(!is_array($config) or !isset($config['smb']) or !$config['smb']['run']) { - abstract class Test_Filestorage_SMB extends Test_FileStorage{} + abstract class SMB extends Storage{} return; }else{ - class Test_Filestorage_SMB extends Test_FileStorage { + class SMB extends Storage { private $config; public function setUp() { @@ -23,7 +25,7 @@ if(!is_array($config) or !isset($config['smb']) or !$config['smb']['run']) { } public function tearDown() { - OCP\Files::rmdirr($this->instance->constructUrl('')); + \OCP\Files::rmdirr($this->instance->constructUrl('')); } } } diff --git a/apps/files_external/tests/swift.php b/apps/files_external/tests/swift.php index 3e1485b0f3..98a97f99b5 100644 --- a/apps/files_external/tests/swift.php +++ b/apps/files_external/tests/swift.php @@ -6,12 +6,14 @@ * See the COPYING-README file. */ +namespace Test\Files\Storage; + $config=include('apps/files_external/tests/config.php'); if(!is_array($config) or !isset($config['swift']) or !$config['swift']['run']) { - abstract class Test_Filestorage_SWIFT extends Test_FileStorage{} + abstract class SWIFT extends Storage{} return; }else{ - class Test_Filestorage_SWIFT extends Test_FileStorage { + class SWIFT extends Storage { private $config; public function setUp() { diff --git a/apps/files_external/tests/webdav.php b/apps/files_external/tests/webdav.php index 6b1121c9d0..cddd0d513e 100644 --- a/apps/files_external/tests/webdav.php +++ b/apps/files_external/tests/webdav.php @@ -6,12 +6,14 @@ * See the COPYING-README file. */ +namespace Test\Files\Storage; + $config=include('apps/files_external/tests/config.php'); if(!is_array($config) or !isset($config['webdav']) or !$config['webdav']['run']) { - abstract class Test_Filestorage_DAV extends Test_FileStorage{} + abstract class DAV extends Storage{} return; }else{ - class Test_Filestorage_DAV extends Test_FileStorage { + class DAV extends Storage { private $config; public function setUp() { diff --git a/tests/lib/filestorage/commontest.php b/tests/lib/files/storage/commontest.php similarity index 91% rename from tests/lib/filestorage/commontest.php rename to tests/lib/files/storage/commontest.php index 0e52e91678..2e3808e2d9 100644 --- a/tests/lib/filestorage/commontest.php +++ b/tests/lib/files/storage/commontest.php @@ -20,7 +20,9 @@ * */ -class Test_Filestorage_CommonTest extends Test_FileStorage { +namespace Test\Files\Storage; + +class CommonTest extends Storage { /** * @var string tmpDir */ @@ -34,8 +36,8 @@ class Test_Filestorage_CommonTest extends Test_FileStorage { } public function tearDown() { - OC_Helper::rmdirr($this->tmpDir); + \OC_Helper::rmdirr($this->tmpDir); } } -?> \ No newline at end of file +?> diff --git a/tests/lib/filestorage/local.php b/tests/lib/files/storage/local.php similarity index 87% rename from tests/lib/filestorage/local.php rename to tests/lib/files/storage/local.php index 7bb27830ba..6672368e67 100644 --- a/tests/lib/filestorage/local.php +++ b/tests/lib/files/storage/local.php @@ -20,19 +20,19 @@ * */ -class Test_Filestorage_Local extends Test_FileStorage { +namespace Test\Files\Storage; + +class Local extends Storage { /** * @var string tmpDir */ private $tmpDir; public function setUp() { - $this->tmpDir=OC_Helper::tmpFolder(); + $this->tmpDir=\OC_Helper::tmpFolder(); $this->instance=new \OC\Files\Storage\Local(array('datadir'=>$this->tmpDir)); } public function tearDown() { - OC_Helper::rmdirr($this->tmpDir); + \OC_Helper::rmdirr($this->tmpDir); } } - -?> \ No newline at end of file diff --git a/tests/lib/filestorage.php b/tests/lib/files/storage/storage.php similarity index 93% rename from tests/lib/filestorage.php rename to tests/lib/files/storage/storage.php index bfb40bcd67..9c8581b259 100644 --- a/tests/lib/filestorage.php +++ b/tests/lib/files/storage/storage.php @@ -20,7 +20,9 @@ * */ -abstract class Test_FileStorage extends UnitTestCase { +namespace Test\Files\Storage; + +abstract class Storage extends \UnitTestCase { /** * @var \OC\Files\Storage\Storage instance */ @@ -83,7 +85,7 @@ abstract class Test_FileStorage extends UnitTestCase { * test the various uses of file_get_contents and file_put_contents */ public function testGetPutContents() { - $sourceFile=OC::$SERVERROOT.'/tests/data/lorem.txt'; + $sourceFile=\OC::$SERVERROOT.'/tests/data/lorem.txt'; $sourceText=file_get_contents($sourceFile); //fill a file with string data @@ -103,21 +105,21 @@ abstract class Test_FileStorage extends UnitTestCase { $this->assertEqual('httpd/unix-directory',$this->instance->getMimeType('/')); $this->assertEqual(false,$this->instance->getMimeType('/non/existing/file')); - $textFile=OC::$SERVERROOT.'/tests/data/lorem.txt'; + $textFile=\OC::$SERVERROOT.'/tests/data/lorem.txt'; $this->instance->file_put_contents('/lorem.txt',file_get_contents($textFile,'r')); $this->assertEqual('text/plain',$this->instance->getMimeType('/lorem.txt')); - $pngFile=OC::$SERVERROOT.'/tests/data/logo-wide.png'; + $pngFile=\OC::$SERVERROOT.'/tests/data/logo-wide.png'; $this->instance->file_put_contents('/logo-wide.png',file_get_contents($pngFile,'r')); $this->assertEqual('image/png',$this->instance->getMimeType('/logo-wide.png')); - $svgFile=OC::$SERVERROOT.'/tests/data/logo-wide.svg'; + $svgFile=\OC::$SERVERROOT.'/tests/data/logo-wide.svg'; $this->instance->file_put_contents('/logo-wide.svg',file_get_contents($svgFile,'r')); $this->assertEqual('image/svg+xml',$this->instance->getMimeType('/logo-wide.svg')); } public function testCopyAndMove() { - $textFile=OC::$SERVERROOT.'/tests/data/lorem.txt'; + $textFile=\OC::$SERVERROOT.'/tests/data/lorem.txt'; $this->instance->file_put_contents('/source.txt',file_get_contents($textFile)); $this->instance->copy('/source.txt','/target.txt'); $this->assertTrue($this->instance->file_exists('/target.txt')); @@ -130,7 +132,7 @@ abstract class Test_FileStorage extends UnitTestCase { } public function testLocal() { - $textFile=OC::$SERVERROOT.'/tests/data/lorem.txt'; + $textFile=\OC::$SERVERROOT.'/tests/data/lorem.txt'; $this->instance->file_put_contents('/lorem.txt',file_get_contents($textFile)); $localFile=$this->instance->getLocalFile('/lorem.txt'); $this->assertTrue(file_exists($localFile)); @@ -151,7 +153,7 @@ abstract class Test_FileStorage extends UnitTestCase { } public function testStat() { - $textFile=OC::$SERVERROOT.'/tests/data/lorem.txt'; + $textFile=\OC::$SERVERROOT.'/tests/data/lorem.txt'; $ctimeStart=time(); $this->instance->file_put_contents('/lorem.txt',file_get_contents($textFile)); $this->assertTrue($this->instance->isReadable('/lorem.txt')); @@ -198,7 +200,6 @@ abstract class Test_FileStorage extends UnitTestCase { fclose($fh); clearstatcache(); $mtimeEnd=time(); - $originalCTime=$cTime; $mTime=$this->instance->filemtime('/lorem.txt'); $this->assertTrue(($mtimeStart-1)<=$mTime); $this->assertTrue($mTime<=($mtimeEnd+1)); @@ -208,11 +209,11 @@ abstract class Test_FileStorage extends UnitTestCase { } public function testSearch() { - $textFile=OC::$SERVERROOT.'/tests/data/lorem.txt'; + $textFile=\OC::$SERVERROOT.'/tests/data/lorem.txt'; $this->instance->file_put_contents('/lorem.txt',file_get_contents($textFile,'r')); - $pngFile=OC::$SERVERROOT.'/tests/data/logo-wide.png'; + $pngFile=\OC::$SERVERROOT.'/tests/data/logo-wide.png'; $this->instance->file_put_contents('/logo-wide.png',file_get_contents($pngFile,'r')); - $svgFile=OC::$SERVERROOT.'/tests/data/logo-wide.svg'; + $svgFile=\OC::$SERVERROOT.'/tests/data/logo-wide.svg'; $this->instance->file_put_contents('/logo-wide.svg',file_get_contents($svgFile,'r')); $result=$this->instance->search('logo'); $this->assertEqual(2,count($result)); From b206d16b104f0474cfd41944b857a3981948b94d Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sat, 22 Sep 2012 14:51:34 +0200 Subject: [PATCH 008/347] add support for loading namespaced test cases --- lib/base.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/base.php b/lib/base.php index 7a09946b9d..38568e2749 100644 --- a/lib/base.php +++ b/lib/base.php @@ -95,6 +95,9 @@ class OC{ } elseif(strpos($className, 'Test_')===0) { $path = 'tests/lib/'.strtolower(str_replace('_', '/', substr($className, 5)) . '.php'); + } + elseif(strpos($className, 'Test\\')===0) { + $path = 'tests/lib/'.strtolower(str_replace('\\', '/', substr($className, 5)) . '.php'); }else{ return false; } From 46896be0d482f5dcec85ec32b232dd8a205f3e41 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sat, 22 Sep 2012 15:03:17 +0200 Subject: [PATCH 009/347] fix namespace error in temporary storage backend --- lib/files/storage/temporary.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/files/storage/temporary.php b/lib/files/storage/temporary.php index 0e69c9112a..ffc55e2750 100644 --- a/lib/files/storage/temporary.php +++ b/lib/files/storage/temporary.php @@ -11,7 +11,7 @@ namespace OC\Files\Storage; /** * local storage backnd in temporary folder for testing purpores */ -class Temporary extends OC\Files\Storage\Local{ +class Temporary extends Local{ public function __construct($arguments) { $this->datadir=\OC_Helper::tmpFolder(); } From 73eedd8fc8326616a356c8b8c40826d9dba92f31 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sat, 22 Sep 2012 15:43:10 +0200 Subject: [PATCH 010/347] some simple test cases for the new filecache --- tests/lib/files/cache/cache.php | 88 +++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 tests/lib/files/cache/cache.php diff --git a/tests/lib/files/cache/cache.php b/tests/lib/files/cache/cache.php new file mode 100644 index 0000000000..168489a721 --- /dev/null +++ b/tests/lib/files/cache/cache.php @@ -0,0 +1,88 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\Files\Cache; + +use \OC\Files\Cache\Cache as FileCache; + +class Cache extends \UnitTestCase { + /** + * @var \OC\Files\Storage\Temporary $storage; + */ + private $storage; + + private function createPath($path) { + return new \OC\Files\File($this->storage, $path); + } + + public function testSimple() { + $file1 = $this->createPath('foo'); + $file2 = $this->createPath('foo/bar'); + $data1 = array('size' => 100, 'mtime' => 50, 'mimetype' => 'foo/folder'); + $data2 = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'foo/file'); + + $this->assertFalse(FileCache::inCache($file1)); + $this->assertEqual(FileCache::get($file1), null); + + $id1 = FileCache::put($file1, $data1); + $this->assertTrue(FileCache::inCache($file1)); + $cacheData1 = FileCache::get($file1); + foreach ($data1 as $key => $value) { + $this->assertEqual($value, $cacheData1[$key]); + } + $this->assertEqual($cacheData1['fileid'], $id1); + $this->assertEqual($id1, FileCache::getId($file1)); + + $this->assertFalse(FileCache::inCache($file2)); + $id2 = FileCache::put($file2, $data2); + $this->assertTrue(FileCache::inCache($file2)); + $cacheData2 = FileCache::get($file2); + foreach ($data2 as $key => $value) { + $this->assertEqual($value, $cacheData2[$key]); + } + $this->assertEqual($cacheData1['fileid'], $cacheData2['parent']); + $this->assertEqual($cacheData2['fileid'], $id2); + $this->assertEqual($id2, FileCache::getId($file2)); + $this->assertEqual($id1, FileCache::getParentId($file2)); + + $newSize = 1050; + $newId2 = FileCache::put($file2, array('size' => $newSize)); + $cacheData2 = FileCache::get($file2); + $this->assertEqual($newId2, $id2); + $this->assertEqual($cacheData2['size'], $newSize); + $this->assertEqual($cacheData1, FileCache::get($file1)); + + FileCache::remove($file2); + $this->assertFalse(FileCache::inCache($file2)); + $this->assertEqual(FileCache::get($file2), null); + $this->assertTrue(FileCache::inCache($file1)); + + $this->assertEqual($cacheData1, FileCache::get($id1)); + } + + public function testPartial() { + $file1 = $this->createPath('foo'); + + FileCache::put($file1, array('size' => 10)); + $this->assertEqual(array('size' => 10), FileCache::get($file1)); + + FileCache::put($file1, array('mtime' => 15)); + $this->assertEqual(array('size' => 10, 'mtime' => 15), FileCache::get($file1)); + + FileCache::put($file1, array('size' => 12)); + $this->assertEqual(array('size' => 12, 'mtime' => 15), FileCache::get($file1)); + } + + public function tearDown() { + FileCache::removeStorage($this->storage); + } + + public function setUp() { + $this->storage = new \OC\Files\Storage\Temporary(array()); + } +} From 97b0eabc850f64949282b471288c93d7148c72ff Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sat, 22 Sep 2012 15:43:48 +0200 Subject: [PATCH 011/347] fix several problems in the new filecache in order to complete the tests --- lib/files/cache/cache.php | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index 9d90ab041f..5d4cb9dd2b 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -23,22 +23,25 @@ class Cache { static public function get($file) { if ($file instanceof \OC\Files\File) { $where = 'WHERE `storage` = ? AND `path_hash` = ?'; - $params = array($file->getStorageId(), $file->getInternalPath()); + $params = array($file->getStorageId(), md5($file->getInternalPath())); } else { //file id $where = 'WHERE `fileid` = ?'; $params = array($file); } $query = \OC_DB::prepare( - 'SELECT `id`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime` + 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime` FROM `*PREFIX*filecache` ' . $where); $result = $query->execute($params); + $data = $result->fetchRow(); //merge partial data - $key = $file->getStorageId() . '::' . $file->getInternalPath(); - if (isset(self::$partial[$key])) { - $result=array_merge($result, self::$partial[$key]); + if (!$data and $file instanceof \OC\Files\File) { + $key = $file->getStorageId() . '::' . $file->getInternalPath(); + if (isset(self::$partial[$key])) { + $data = self::$partial[$key]; + } } - return $result->fetchRow(); + return $data; } /** @@ -50,13 +53,13 @@ class Cache { * @return int file id */ static public function put(\OC\Files\File $file, array $data) { - if ($id = self::getId($file) > -1) { + if (($id = self::getId($file)) > -1) { self::update($id, $data); return $id; } else { $key = $file->getStorageId() . '::' . $file->getInternalPath(); if (isset(self::$partial[$key])) { //add any saved partial data - $data = array_merge($data, self::$partial[$key]); + $data = array_merge(self::$partial[$key], $data); unset(self::$partial[$key]); } @@ -77,7 +80,7 @@ class Cache { $params[] = $file->getStorageId(); $valuesPlaceholder = array_fill(0, count($queryParts), '?'); - $query = \OC_DB::prepare('INSERT INTO `*PREFIX*filecache`(' . implode(', ', $queryParts) . ' VALUES(' . implode(', ', $valuesPlaceholder) . ')'); + $query = \OC_DB::prepare('INSERT INTO `*PREFIX*filecache`(' . implode(', ', $queryParts) . ') VALUES(' . implode(', ', $valuesPlaceholder) . ')'); $query->execute($params); return \OC_DB::insertid('*PREFIX*filecache'); @@ -135,11 +138,11 @@ class Cache { $storageId = $file->getStorageId(); $pathHash = md5($file->getInternalPath()); - $query = \OC_DB::prepare('SELECT id FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path_hash` = ?'); + $query = \OC_DB::prepare('SELECT `fileid` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path_hash` = ?'); $result = $query->execute(array($storageId, $pathHash)); if ($row = $result->fetchRow()) { - return $row['id']; + return $row['fileid']; } else { return -1; } @@ -175,7 +178,7 @@ class Cache { * * @param \OC\Files\File $file */ - public function remove(\OC\Files\File $file) { + static public function remove(\OC\Files\File $file) { $storageId = $file->getStorageId(); $pathHash = md5($file->getInternalPath()); $query = \OC_DB::prepare('DELETE FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path_hash` = ?'); @@ -187,7 +190,7 @@ class Cache { * * @param \OC\Files\Storage\Storage $storage */ - public function removeStorage(\OC\Files\Storage\Storage $storage) { + static public function removeStorage(\OC\Files\Storage\Storage $storage) { $storageId = $storage->getId(); $query = \OC_DB::prepare('DELETE FROM `*PREFIX*filecache` WHERE storage=?'); $query->execute(array($storageId)); From 6fafd5d4e9d23cd98738a3b00ce0053d6b6e3dff Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sat, 22 Sep 2012 15:48:39 +0200 Subject: [PATCH 012/347] this should be done elsewhere if needed --- lib/files/cache/cache.php | 2 +- lib/files/cache/scanner.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index 5d4cb9dd2b..0c1d6788ec 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -152,7 +152,7 @@ class Cache { * get the id of the parent folder of a file * * @param \OC\Files\File $file - * return int + * @return int */ static public function getParentId(\OC\Files\File $file) { $path = $file->getInternalPath(); diff --git a/lib/files/cache/scanner.php b/lib/files/cache/scanner.php index 8f2c5bda5c..e8e9c71c4e 100644 --- a/lib/files/cache/scanner.php +++ b/lib/files/cache/scanner.php @@ -23,7 +23,6 @@ class Scanner { $storage = $file->getStorage(); $path = $file->getInternalPath(); if (!$storage->isReadable($path)) return null; //cant read, nothing we can do - clearstatcache(); $data['mimetype'] = $storage->getMimeType($path); $data['mtime'] = $storage->filemtime($path); if ($data['mimetype'] == 'httpd/unix-directory') { From f360d7c736b08f48f1abcea1e0b93dc890178c94 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sun, 23 Sep 2012 01:51:00 +0200 Subject: [PATCH 013/347] add getId to shared storage backend --- apps/files_sharing/lib/sharedstorage.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php index f1539610b0..876e719956 100644 --- a/apps/files_sharing/lib/sharedstorage.php +++ b/apps/files_sharing/lib/sharedstorage.php @@ -91,7 +91,7 @@ class Shared extends \OC\Files\Storage\Common { * @param string Shared target file path * @return Returns CRUDS permissions granted or false if not found */ - private function getPermissions($target) { + public function getPermissions($target) { $file = $this->getFile($target); if (isset($file['permissions'])) { return $file['permissions']; @@ -449,4 +449,8 @@ class Shared extends \OC\Files\Storage\Common { //TODO return false; } + + public function getId(){ + return 'shared::' . $this->sharedFolder; + } } From dcf995fff3ecc2780d3187744397461d1a14c041 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sun, 23 Sep 2012 15:25:03 +0200 Subject: [PATCH 014/347] add Cache::getFolderContent --- lib/files/cache/cache.php | 19 +++++++++++++++++++ tests/lib/files/cache/cache.php | 23 +++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index 0c1d6788ec..f8808ad0b4 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -44,6 +44,25 @@ class Cache { return $data; } + /** + * get the metadata of all files stored in $folder + * + * @param \OC\Files\File $folder + * @return array + */ + static public function getFolderContents($folder) { + $fileId = self::getId($folder); + if ($fileId > -1) { + $query = \OC_DB::prepare( + 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime` + FROM `*PREFIX*filecache` WHERE parent = ?'); + $result = $query->execute(array($fileId)); + return $result->fetchAll(); + } else { + return array(); + } + } + /** * store meta data for a file or folder * diff --git a/tests/lib/files/cache/cache.php b/tests/lib/files/cache/cache.php index 168489a721..9f35cd889a 100644 --- a/tests/lib/files/cache/cache.php +++ b/tests/lib/files/cache/cache.php @@ -78,6 +78,29 @@ class Cache extends \UnitTestCase { $this->assertEqual(array('size' => 12, 'mtime' => 15), FileCache::get($file1)); } + public function testFolder() { + $file1 = $this->createPath('folder'); + $file2 = $this->createPath('folder/bar'); + $file3 = $this->createPath('folder/foo'); + $data1 = array('size' => 100, 'mtime' => 50, 'mimetype' => 'foo/folder'); + $fileData = array(); + $fileData['bar'] = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'foo/file'); + $fileData['foo'] = array('size' => 20, 'mtime' => 25, 'mimetype' => 'foo/file'); + + FileCache::put($file1, $data1); + FileCache::put($file2, $fileData['bar']); + FileCache::put($file3, $fileData['foo']); + + $content = FileCache::getFolderContents($file1); + $this->assertEqual(count($content), 2); + foreach ($content as $cachedData) { + $data = $fileData[$cachedData['name']]; + foreach ($data as $name => $value) { + $this->assertEqual($value, $cachedData[$name]); + } + } + } + public function tearDown() { FileCache::removeStorage($this->storage); } From 522d7df860fb47d3cc56e315850dda2797569ac5 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 26 Sep 2012 17:52:02 +0200 Subject: [PATCH 015/347] convert Cache to a non-static class that handles the cache for a single storage backend --- lib/files/cache/cache.php | 121 ++++++++++++++++++-------------- lib/files/cache/scanner.php | 1 + tests/lib/files/cache/cache.php | 82 +++++++++++----------- 3 files changed, 110 insertions(+), 94 deletions(-) diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index f8808ad0b4..167cc5d13f 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -9,21 +9,36 @@ namespace OC\Files\Cache; class Cache { + /** + * @var \OC\Files\Storage\Storage + */ + private $storage; + /** * @var array partial data for the cache */ - private static $partial = array(); + private $partial = array(); + + private $storageId; + + /** + * @param \OC\Files\Storage\Storage $storage + */ + public function __construct(\OC\Files\Storage\Storage $storage) { + $this->storage = $storage; + $this->storageId = $storage->getId(); + } /** * get the stored metadata of a file or folder * - * @param \OC\Files\File or int $file + * @param string/int $file * @return array */ - static public function get($file) { - if ($file instanceof \OC\Files\File) { + public function get($file) { + if (is_string($file)) { $where = 'WHERE `storage` = ? AND `path_hash` = ?'; - $params = array($file->getStorageId(), md5($file->getInternalPath())); + $params = array($this->storageId, md5($file)); } else { //file id $where = 'WHERE `fileid` = ?'; $params = array($file); @@ -35,23 +50,28 @@ class Cache { $data = $result->fetchRow(); //merge partial data - if (!$data and $file instanceof \OC\Files\File) { - $key = $file->getStorageId() . '::' . $file->getInternalPath(); - if (isset(self::$partial[$key])) { - $data = self::$partial[$key]; + if (!$data and is_string($file)) { + if (isset($this->partial[$file])) { + $data = $this->partial[$file]; } + } else { + //fix types + $data['fileid'] = (int)$data['fileid']; + $data['size'] = (int)$data['size']; + $data['mtime'] = (int)$data['mtime']; } + return $data; } /** * get the metadata of all files stored in $folder * - * @param \OC\Files\File $folder + * @param string $folder * @return array */ - static public function getFolderContents($folder) { - $fileId = self::getId($folder); + public function getFolderContents($folder) { + $fileId = $this->getId($folder); if ($fileId > -1) { $query = \OC_DB::prepare( 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime` @@ -66,43 +86,42 @@ class Cache { /** * store meta data for a file or folder * - * @param \OC\Files\File $file + * @param string $file * @param array $data * * @return int file id */ - static public function put(\OC\Files\File $file, array $data) { - if (($id = self::getId($file)) > -1) { - self::update($id, $data); + public function put($file, array $data) { + if (($id = $this->getId($file)) > -1) { + $this->update($id, $data); return $id; } else { - $key = $file->getStorageId() . '::' . $file->getInternalPath(); - if (isset(self::$partial[$key])) { //add any saved partial data - $data = array_merge(self::$partial[$key], $data); - unset(self::$partial[$key]); + if (isset($this->partial[$file])) { //add any saved partial data + $data = array_merge($this->partial[$file], $data); + unset($this->partial[$file]); } $requiredFields = array('size', 'mtime', 'mimetype'); foreach ($requiredFields as $field) { if (!isset($data[$field])) { //data not complete save as partial and return - self::$partial[$key] = $data; + $this->partial[$file] = $data; return -1; } } - $data['path'] = $file->getInternalPath(); - $data['parent'] = self::getParentId($file); - $data['name'] = basename($file->getInternalPath()); + $data['path'] = $file; + $data['parent'] = $this->getParentId($file); + $data['name'] = basename($file); - list($queryParts, $params) = self::buildParts($data); + list($queryParts, $params) = $this->buildParts($data); $queryParts[] = '`storage`'; - $params[] = $file->getStorageId(); + $params[] = $this->storageId; $valuesPlaceholder = array_fill(0, count($queryParts), '?'); $query = \OC_DB::prepare('INSERT INTO `*PREFIX*filecache`(' . implode(', ', $queryParts) . ') VALUES(' . implode(', ', $valuesPlaceholder) . ')'); $query->execute($params); - return \OC_DB::insertid('*PREFIX*filecache'); + return (int) \OC_DB::insertid('*PREFIX*filecache'); } } @@ -112,8 +131,8 @@ class Cache { * @param int $id * @param array $data */ - static public function update($id, array $data) { - list($queryParts, $params) = self::buildParts($data); + public function update($id, array $data) { + list($queryParts, $params) = $this->buildParts($data); $params[] = $id; $query = \OC_DB::prepare('UPDATE `*PREFIX*filecache` SET ' . implode(' = ?, ', $queryParts) . '=? WHERE fileid = ?'); @@ -126,7 +145,7 @@ class Cache { * @param array $data * @return array */ - private static function buildParts(array $data) { + static function buildParts(array $data) { $fields = array('path', 'parent', 'name', 'mimetype', 'size', 'mtime'); $params = array(); @@ -150,15 +169,14 @@ class Cache { /** * get the file id for a file * - * @param \OC\Files\File $file + * @param string $file * @return int */ - static public function getId(\OC\Files\File $file) { - $storageId = $file->getStorageId(); - $pathHash = md5($file->getInternalPath()); + public function getId($file) { + $pathHash = md5($file); $query = \OC_DB::prepare('SELECT `fileid` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path_hash` = ?'); - $result = $query->execute(array($storageId, $pathHash)); + $result = $query->execute(array($this->storageId, $pathHash)); if ($row = $result->fetchRow()) { return $row['fileid']; @@ -170,48 +188,43 @@ class Cache { /** * get the id of the parent folder of a file * - * @param \OC\Files\File $file + * @param string $file * @return int */ - static public function getParentId(\OC\Files\File $file) { - $path = $file->getInternalPath(); - if ($path === '/' or $path === '') { + public function getParentId($file) { + if ($file === '/' or $file === '') { return -1; } else { - return self::getId(new \OC\Files\File($file->getStorage(), dirname($path))); + return $this->getId(dirname($file)); } } /** * check if a file is available in the cache * - * @param \OC\Files\File $file + * @param string $file * @return bool */ - static public function inCache(\OC\Files\File $file) { - return self::getId($file) != -1; + public function inCache($file) { + return $this->getId($file) != -1; } /** * remove a file or folder from the cache * - * @param \OC\Files\File $file + * @param string $file */ - static public function remove(\OC\Files\File $file) { - $storageId = $file->getStorageId(); - $pathHash = md5($file->getInternalPath()); + public function remove($file) { + $pathHash = md5($file); $query = \OC_DB::prepare('DELETE FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path_hash` = ?'); - $query->execute(array($storageId, $pathHash)); + $query->execute(array($this->storageId, $pathHash)); } /** - * remove all entries for files that are stored on $storage form the cache - * - * @param \OC\Files\Storage\Storage $storage + * remove all entries for files that are stored on the storage from the cache */ - static public function removeStorage(\OC\Files\Storage\Storage $storage) { - $storageId = $storage->getId(); + public function clear() { $query = \OC_DB::prepare('DELETE FROM `*PREFIX*filecache` WHERE storage=?'); - $query->execute(array($storageId)); + $query->execute(array($this->storageId)); } } diff --git a/lib/files/cache/scanner.php b/lib/files/cache/scanner.php index e8e9c71c4e..17fc0fb2e8 100644 --- a/lib/files/cache/scanner.php +++ b/lib/files/cache/scanner.php @@ -15,6 +15,7 @@ class Scanner { /** * get all the metadata of a file or folder * * + * * @param \OC\Files\File $file * @return array with metadata of the file */ diff --git a/tests/lib/files/cache/cache.php b/tests/lib/files/cache/cache.php index 9f35cd889a..24dd38fa73 100644 --- a/tests/lib/files/cache/cache.php +++ b/tests/lib/files/cache/cache.php @@ -16,82 +16,83 @@ class Cache extends \UnitTestCase { */ private $storage; - private function createPath($path) { - return new \OC\Files\File($this->storage, $path); - } + /** + * @var \OC\Files\Cache\Cache $cache + */ + private $cache; public function testSimple() { - $file1 = $this->createPath('foo'); - $file2 = $this->createPath('foo/bar'); + $file1 = 'foo'; + $file2 = 'foo/bar'; $data1 = array('size' => 100, 'mtime' => 50, 'mimetype' => 'foo/folder'); $data2 = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'foo/file'); - $this->assertFalse(FileCache::inCache($file1)); - $this->assertEqual(FileCache::get($file1), null); + $this->assertFalse($this->cache->inCache($file1)); + $this->assertEqual($this->cache->get($file1), null); - $id1 = FileCache::put($file1, $data1); - $this->assertTrue(FileCache::inCache($file1)); - $cacheData1 = FileCache::get($file1); + $id1 = $this->cache->put($file1, $data1); + $this->assertTrue($this->cache->inCache($file1)); + $cacheData1 = $this->cache->get($file1); foreach ($data1 as $key => $value) { $this->assertEqual($value, $cacheData1[$key]); } $this->assertEqual($cacheData1['fileid'], $id1); - $this->assertEqual($id1, FileCache::getId($file1)); + $this->assertEqual($id1, $this->cache->getId($file1)); - $this->assertFalse(FileCache::inCache($file2)); - $id2 = FileCache::put($file2, $data2); - $this->assertTrue(FileCache::inCache($file2)); - $cacheData2 = FileCache::get($file2); + $this->assertFalse($this->cache->inCache($file2)); + $id2 = $this->cache->put($file2, $data2); + $this->assertTrue($this->cache->inCache($file2)); + $cacheData2 = $this->cache->get($file2); foreach ($data2 as $key => $value) { $this->assertEqual($value, $cacheData2[$key]); } $this->assertEqual($cacheData1['fileid'], $cacheData2['parent']); $this->assertEqual($cacheData2['fileid'], $id2); - $this->assertEqual($id2, FileCache::getId($file2)); - $this->assertEqual($id1, FileCache::getParentId($file2)); + $this->assertEqual($id2, $this->cache->getId($file2)); + $this->assertEqual($id1, $this->cache->getParentId($file2)); $newSize = 1050; - $newId2 = FileCache::put($file2, array('size' => $newSize)); - $cacheData2 = FileCache::get($file2); + $newId2 = $this->cache->put($file2, array('size' => $newSize)); + $cacheData2 = $this->cache->get($file2); $this->assertEqual($newId2, $id2); $this->assertEqual($cacheData2['size'], $newSize); - $this->assertEqual($cacheData1, FileCache::get($file1)); + $this->assertEqual($cacheData1, $this->cache->get($file1)); - FileCache::remove($file2); - $this->assertFalse(FileCache::inCache($file2)); - $this->assertEqual(FileCache::get($file2), null); - $this->assertTrue(FileCache::inCache($file1)); + $this->cache->remove($file2); + $this->assertFalse($this->cache->inCache($file2)); + $this->assertEqual($this->cache->get($file2), null); + $this->assertTrue($this->cache->inCache($file1)); - $this->assertEqual($cacheData1, FileCache::get($id1)); + $this->assertEqual($cacheData1, $this->cache->get($id1)); } public function testPartial() { - $file1 = $this->createPath('foo'); + $file1 = 'foo'; - FileCache::put($file1, array('size' => 10)); - $this->assertEqual(array('size' => 10), FileCache::get($file1)); + $this->cache->put($file1, array('size' => 10)); + $this->assertEqual(array('size' => 10), $this->cache->get($file1)); - FileCache::put($file1, array('mtime' => 15)); - $this->assertEqual(array('size' => 10, 'mtime' => 15), FileCache::get($file1)); + $this->cache->put($file1, array('mtime' => 15)); + $this->assertEqual(array('size' => 10, 'mtime' => 15), $this->cache->get($file1)); - FileCache::put($file1, array('size' => 12)); - $this->assertEqual(array('size' => 12, 'mtime' => 15), FileCache::get($file1)); + $this->cache->put($file1, array('size' => 12)); + $this->assertEqual(array('size' => 12, 'mtime' => 15), $this->cache->get($file1)); } public function testFolder() { - $file1 = $this->createPath('folder'); - $file2 = $this->createPath('folder/bar'); - $file3 = $this->createPath('folder/foo'); + $file1 = 'folder'; + $file2 = 'folder/bar'; + $file3 = 'folder/foo'; $data1 = array('size' => 100, 'mtime' => 50, 'mimetype' => 'foo/folder'); $fileData = array(); $fileData['bar'] = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'foo/file'); $fileData['foo'] = array('size' => 20, 'mtime' => 25, 'mimetype' => 'foo/file'); - FileCache::put($file1, $data1); - FileCache::put($file2, $fileData['bar']); - FileCache::put($file3, $fileData['foo']); + $this->cache->put($file1, $data1); + $this->cache->put($file2, $fileData['bar']); + $this->cache->put($file3, $fileData['foo']); - $content = FileCache::getFolderContents($file1); + $content = $this->cache->getFolderContents($file1); $this->assertEqual(count($content), 2); foreach ($content as $cachedData) { $data = $fileData[$cachedData['name']]; @@ -102,10 +103,11 @@ class Cache extends \UnitTestCase { } public function tearDown() { - FileCache::removeStorage($this->storage); + $this->cache->clear(); } public function setUp() { $this->storage = new \OC\Files\Storage\Temporary(array()); + $this->cache = new \OC\Files\Cache\Cache($this->storage); } } From 92555eff711ff391f3af5ef6fb6f6414bfe012cf Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 2 Oct 2012 23:34:45 +0200 Subject: [PATCH 016/347] add encrypted column to the new filecache --- lib/files/cache/cache.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index 167cc5d13f..9d8275e5e0 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -44,7 +44,7 @@ class Cache { $params = array($file); } $query = \OC_DB::prepare( - 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime` + 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted` FROM `*PREFIX*filecache` ' . $where); $result = $query->execute($params); $data = $result->fetchRow(); @@ -59,6 +59,7 @@ class Cache { $data['fileid'] = (int)$data['fileid']; $data['size'] = (int)$data['size']; $data['mtime'] = (int)$data['mtime']; + $data['encrypted'] = (bool)$data['encrypted']; } return $data; @@ -74,7 +75,7 @@ class Cache { $fileId = $this->getId($folder); if ($fileId > -1) { $query = \OC_DB::prepare( - 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime` + 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted` FROM `*PREFIX*filecache` WHERE parent = ?'); $result = $query->execute(array($fileId)); return $result->fetchAll(); @@ -112,6 +113,7 @@ class Cache { $data['path'] = $file; $data['parent'] = $this->getParentId($file); $data['name'] = basename($file); + $data['encrypted'] = isset($data['encrypted']) ? ((int)$data['encrypted']) : 0; list($queryParts, $params) = $this->buildParts($data); $queryParts[] = '`storage`'; @@ -121,7 +123,7 @@ class Cache { $query = \OC_DB::prepare('INSERT INTO `*PREFIX*filecache`(' . implode(', ', $queryParts) . ') VALUES(' . implode(', ', $valuesPlaceholder) . ')'); $query->execute($params); - return (int) \OC_DB::insertid('*PREFIX*filecache'); + return (int)\OC_DB::insertid('*PREFIX*filecache'); } } @@ -146,7 +148,7 @@ class Cache { * @return array */ static function buildParts(array $data) { - $fields = array('path', 'parent', 'name', 'mimetype', 'size', 'mtime'); + $fields = array('path', 'parent', 'name', 'mimetype', 'size', 'mtime', 'encrypted'); $params = array(); $queryParts = array(); From 1ed89760be5e1c5cf5b3fa7d40d845750b2840ab Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 2 Oct 2012 23:35:51 +0200 Subject: [PATCH 017/347] dont need this anymore --- tests/lib/files/cache/cache.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/lib/files/cache/cache.php b/tests/lib/files/cache/cache.php index 24dd38fa73..48cdc1c8c8 100644 --- a/tests/lib/files/cache/cache.php +++ b/tests/lib/files/cache/cache.php @@ -8,8 +8,6 @@ namespace Test\Files\Cache; -use \OC\Files\Cache\Cache as FileCache; - class Cache extends \UnitTestCase { /** * @var \OC\Files\Storage\Temporary $storage; From 6134e554f2306c5309a793d4d3149a0f9b05ea5f Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 2 Oct 2012 23:46:35 +0200 Subject: [PATCH 018/347] new filecache table --- db_structure.xml | 114 +++++++++++++++++------------------------------ lib/util.php | 2 +- 2 files changed, 41 insertions(+), 75 deletions(-) diff --git a/db_structure.xml b/db_structure.xml index 99a30cb613..8bbc6e5cc6 100644 --- a/db_structure.xml +++ b/db_structure.xml @@ -53,19 +53,27 @@ - *dbprefix*fscache + *dbprefix*filecache - id - 1 + fileid integer 0 true + 1 4 + + storage + text + + true + 64 + + path text @@ -85,9 +93,9 @@ parent integer - 0 + true - 8 + 4 @@ -95,39 +103,7 @@ text true - 300 - - - - user - text - - true - 64 - - - - size - integer - 0 - true - 8 - - - - ctime - integer - 0 - true - 8 - - - - mtime - integer - 0 - true - 8 + 250 @@ -135,7 +111,7 @@ text true - 96 + 64 @@ -146,32 +122,37 @@ 32 + + size + integer + + true + 4 + + + + mtime + integer + + true + 4 + + encrypted integer 0 true - 1 - - - - versioned - integer - 0 - true - 1 - - - - writable - integer - 0 - true - 1 + 4 - fscache_path_hash_index + storage_path_hash + true + + storage + ascending + path_hash ascending @@ -179,23 +160,8 @@ - parent_index - - parent - ascending - - - - - name_index - - name - ascending - - - - - parent_name_index + parent_name_hash + true parent ascending diff --git a/lib/util.php b/lib/util.php index 31dd376b9c..264d61319d 100755 --- a/lib/util.php +++ b/lib/util.php @@ -81,7 +81,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.9.0. This is not visible to the user - return array(4,86,11); + return array(4,86,12); } /** From 636c75ce061492751d0fb001e0bf7219df379f09 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 3 Oct 2012 11:23:33 +0200 Subject: [PATCH 019/347] better parent path bahaviour for the filecache --- lib/files/cache/cache.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index 9d8275e5e0..79673771e5 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -194,10 +194,14 @@ class Cache { * @return int */ public function getParentId($file) { - if ($file === '/' or $file === '') { + if ($file === '') { return -1; } else { - return $this->getId(dirname($file)); + $parent = dirname($file); + if ($parent === '.') { + $parent = ''; + } + return $this->getId($parent); } } From 96d7cd59978cc416bc0d9c5ac487af23692ef1d8 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 3 Oct 2012 11:24:10 +0200 Subject: [PATCH 020/347] correct namespace usage in common filestorage backend --- lib/files/storage/common.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/files/storage/common.php b/lib/files/storage/common.php index b2b4ea8eee..3886a04182 100644 --- a/lib/files/storage/common.php +++ b/lib/files/storage/common.php @@ -57,19 +57,19 @@ abstract class Common extends \OC\Files\Storage\Storage { public function getPermissions($path){ $permissions = 0; if($this->isCreatable($path)){ - $permissions |= OCP\Share::PERMISSION_CREATE; + $permissions |= \OCP\Share::PERMISSION_CREATE; } if($this->isReadable($path)){ - $permissions |= OCP\Share::PERMISSION_READ; + $permissions |= \OCP\Share::PERMISSION_READ; } if($this->isUpdatable($path)){ - $permissions |= OCP\Share::PERMISSION_UPDATE; + $permissions |= \OCP\Share::PERMISSION_UPDATE; } if($this->isDeletable($path)){ - $permissions |= OCP\Share::PERMISSION_DELETE; + $permissions |= \OCP\Share::PERMISSION_DELETE; } if($this->isSharable($path)){ - $permissions |= OCP\Share::PERMISSION_SHARE; + $permissions |= \OCP\Share::PERMISSION_SHARE; } return $permissions; } From e415e90c6d8a2e8bb129be7c63a7077c56ab3da8 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 3 Oct 2012 11:24:49 +0200 Subject: [PATCH 021/347] make filestorage scanner non-static and add a simple test case --- lib/files/cache/scanner.php | 64 ++++++++++++++++++++----------- tests/lib/files/cache/cache.php | 1 + tests/lib/files/cache/scanner.php | 47 +++++++++++++++++++++++ 3 files changed, 90 insertions(+), 22 deletions(-) create mode 100644 tests/lib/files/cache/scanner.php diff --git a/lib/files/cache/scanner.php b/lib/files/cache/scanner.php index 17fc0fb2e8..721d0d825e 100644 --- a/lib/files/cache/scanner.php +++ b/lib/files/cache/scanner.php @@ -9,29 +9,42 @@ namespace OC\Files\Cache; class Scanner { + /** + * @var \OC\Files\Storage\Storage $storage + */ + private $storage; + + /** + * @var \OC\Files\Cache\Cache $cache + */ + private $cache; + const SCAN_RECURSIVE = true; const SCAN_SHALLOW = false; + public function __construct(\OC\Files\Storage\Storage $storage) { + $this->storage = $storage; + $this->cache = new Cache($storage); + } + /** * get all the metadata of a file or folder * * * - * @param \OC\Files\File $file + * @param string $path * @return array with metadata of the file */ - public static function getData(\OC\Files\File $file) { + public function getData($path) { $data = array(); - $storage = $file->getStorage(); - $path = $file->getInternalPath(); - if (!$storage->isReadable($path)) return null; //cant read, nothing we can do - $data['mimetype'] = $storage->getMimeType($path); - $data['mtime'] = $storage->filemtime($path); + if (!$this->storage->isReadable($path)) return null; //cant read, nothing we can do + $data['mimetype'] = $this->storage->getMimeType($path); + $data['mtime'] = $this->storage->filemtime($path); if ($data['mimetype'] == 'httpd/unix-directory') { $data['size'] = -1; //unknown - $data['permissions'] = $storage->getPermissions($path . '/'); + $data['permissions'] = $this->storage->getPermissions($path . '/'); } else { - $data['size'] = $storage->filesize($path); - $data['permissions'] = $storage->getPermissions($path); + $data['size'] = $this->storage->filesize($path); + $data['permissions'] = $this->storage->getPermissions($path); } return $data; } @@ -39,33 +52,40 @@ class Scanner { /** * scan a single file and store it in the cache * - * @param \OC\Files\File $file + * @param string $file * @return array with metadata of the scanned file */ - public static function scanFile(\OC\Files\File $file) { - $data = self::getData($file); - Cache::put($file, $data); + public function scanFile($file) { + $data = $this->getData($file); + if ($file !== '') { + $parent = dirname($file); + if ($parent === '.') { + $parent = ''; + } + if (!$this->cache->inCache($parent)) { + $this->scanFile($parent); + } + } + $this->cache->put($file, $data); return $data; } /** * scan all the files in a folder and store them in the cache * - * @param \OC\Files\File $folder + * @param string $path * @param SCAN_RECURSIVE/SCAN_SHALLOW $recursive * @return int the size of the scanned folder or -1 if the size is unknown at this stage */ - public static function scan(\OC\Files\File $folder, $recursive) { + public function scan($path, $recursive) { $size = 0; - $storage = $folder->getStorage(); - $path = $folder->getInternalPath(); - if ($dh = $storage->opendir($path)) { + if ($dh = $this->storage->opendir($path)) { while ($file = readdir($dh)) { if ($file !== '.' and $file !== '..') { - $child = new \OC\Files\File($storage, $path . '/' . $file); - $data = self::scanFile($child); + $child = $path . '/' . $file; + $data = $this->scanFile($child); if ($recursive === self::SCAN_RECURSIVE and $data['mimetype'] === 'httpd/unix-directory') { - $data['size'] = self::scan($child, self::SCAN_RECURSIVE); + $data['size'] = $this->scan($child, self::SCAN_RECURSIVE); } if ($data['size'] >= 0 and $size >= 0) { $size += $data['size']; diff --git a/tests/lib/files/cache/cache.php b/tests/lib/files/cache/cache.php index 48cdc1c8c8..8cedadbf19 100644 --- a/tests/lib/files/cache/cache.php +++ b/tests/lib/files/cache/cache.php @@ -34,6 +34,7 @@ class Cache extends \UnitTestCase { foreach ($data1 as $key => $value) { $this->assertEqual($value, $cacheData1[$key]); } + $this->assertEqual($cacheData1['mimepart'], 'foo'); $this->assertEqual($cacheData1['fileid'], $id1); $this->assertEqual($id1, $this->cache->getId($file1)); diff --git a/tests/lib/files/cache/scanner.php b/tests/lib/files/cache/scanner.php new file mode 100644 index 0000000000..3d1c1546ab --- /dev/null +++ b/tests/lib/files/cache/scanner.php @@ -0,0 +1,47 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\Files\Cache; + +class Scanner extends \UnitTestCase { + /** + * @var \OC\Files\Storage\Storage $storage + */ + private $storage; + + /** + * @var \OC\Files\Cache\Scanner $scanner + */ + private $scanner; + + /** + * @var \OC\Files\Cache\Cache $cache + */ + private $cache; + + function testFile() { + $data = "dummy file data\n"; + $this->storage->file_put_contents('foo.txt', $data); + $this->scanner->scanFile('foo.txt'); + + $this->assertEqual($this->cache->inCache('foo.txt'), true); + $cachedData = $this->cache->get('foo.txt'); + $this->assertEqual($cachedData['size'], strlen($data)); + $this->assertEqual($cachedData['mimetype'], 'text/plain'); + } + + function setUp() { + $this->storage = new \OC\Files\Storage\Temporary(array()); + $this->scanner = new \OC\Files\Cache\Scanner($this->storage); + $this->cache = new \OC\Files\Cache\Cache($this->storage); + } + + function tearDown() { +// $this->cache->clear(); + } +} From 3c8e5ea3581cbbfc5acd3c229080bc63548d2827 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 3 Oct 2012 11:31:13 +0200 Subject: [PATCH 022/347] this index cant be unique due to collisions of the root of different storages --- db_structure.xml | 1 - lib/util.php | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/db_structure.xml b/db_structure.xml index 8bbc6e5cc6..e0b9dc11e9 100644 --- a/db_structure.xml +++ b/db_structure.xml @@ -161,7 +161,6 @@ parent_name_hash - true parent ascending diff --git a/lib/util.php b/lib/util.php index 264d61319d..be9d1f4fb5 100755 --- a/lib/util.php +++ b/lib/util.php @@ -81,7 +81,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.9.0. This is not visible to the user - return array(4,86,12); + return array(4,86,13); } /** From 85be00be6595a3af168f6df963ffdeac8c3c6d5e Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 3 Oct 2012 11:40:09 +0200 Subject: [PATCH 023/347] add some more test cases for the scanner --- lib/files/cache/scanner.php | 6 ++++-- tests/lib/files/cache/scanner.php | 23 ++++++++++++++++++++++- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/lib/files/cache/scanner.php b/lib/files/cache/scanner.php index 721d0d825e..7d449204e8 100644 --- a/lib/files/cache/scanner.php +++ b/lib/files/cache/scanner.php @@ -77,12 +77,14 @@ class Scanner { * @param SCAN_RECURSIVE/SCAN_SHALLOW $recursive * @return int the size of the scanned folder or -1 if the size is unknown at this stage */ - public function scan($path, $recursive) { + public function scan($path, $recursive = self::SCAN_RECURSIVE) { + $this->scanFile($path); + $size = 0; if ($dh = $this->storage->opendir($path)) { while ($file = readdir($dh)) { if ($file !== '.' and $file !== '..') { - $child = $path . '/' . $file; + $child = ($path !== '') ? $path . '/' . $file : $file; $data = $this->scanFile($child); if ($recursive === self::SCAN_RECURSIVE and $data['mimetype'] === 'httpd/unix-directory') { $data['size'] = $this->scan($child, self::SCAN_RECURSIVE); diff --git a/tests/lib/files/cache/scanner.php b/tests/lib/files/cache/scanner.php index 3d1c1546ab..7ee28dfc3f 100644 --- a/tests/lib/files/cache/scanner.php +++ b/tests/lib/files/cache/scanner.php @@ -33,6 +33,27 @@ class Scanner extends \UnitTestCase { $cachedData = $this->cache->get('foo.txt'); $this->assertEqual($cachedData['size'], strlen($data)); $this->assertEqual($cachedData['mimetype'], 'text/plain'); + $this->assertNotEqual($cachedData['parent'], -1); //parent folders should be scanned automatically + + $data = file_get_contents(\OC::$SERVERROOT . '/core/img/logo.png'); + $this->storage->file_put_contents('foo.png', $data); + $this->scanner->scanFile('foo.png'); + + $this->assertEqual($this->cache->inCache('foo.png'), true); + $cachedData = $this->cache->get('foo.png'); + $this->assertEqual($cachedData['size'], strlen($data)); + $this->assertEqual($cachedData['mimetype'], 'image/png'); + } + + function testFolder() { + $textData = "dummy file data\n"; + $imgData = file_get_contents(\OC::$SERVERROOT . '/core/img/logo.png'); + $this->storage->file_put_contents('foo.txt', $textData); + $this->storage->file_put_contents('foo.png', $imgData); + + $this->scanner->scan(''); + $this->assertEqual($this->cache->inCache('foo.txt'), true); + $this->assertEqual($this->cache->inCache('foo.png'), true); } function setUp() { @@ -42,6 +63,6 @@ class Scanner extends \UnitTestCase { } function tearDown() { -// $this->cache->clear(); + $this->cache->clear(); } } From b9b9fd9dbaae47b3a15aed9694c18b95404550b0 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 3 Oct 2012 13:07:19 +0200 Subject: [PATCH 024/347] more tests and fixes for the filesystem scanner --- lib/files/cache/scanner.php | 15 +++++++++--- tests/lib/files/cache/scanner.php | 39 ++++++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/lib/files/cache/scanner.php b/lib/files/cache/scanner.php index 7d449204e8..e8f54c34be 100644 --- a/lib/files/cache/scanner.php +++ b/lib/files/cache/scanner.php @@ -86,15 +86,24 @@ class Scanner { if ($file !== '.' and $file !== '..') { $child = ($path !== '') ? $path . '/' . $file : $file; $data = $this->scanFile($child); - if ($recursive === self::SCAN_RECURSIVE and $data['mimetype'] === 'httpd/unix-directory') { - $data['size'] = $this->scan($child, self::SCAN_RECURSIVE); + if ($data['mimetype'] === 'httpd/unix-directory') { + if ($recursive === self::SCAN_RECURSIVE) { + $data['size'] = $this->scan($child, self::SCAN_RECURSIVE); + } else { + $data['size'] = -1; + } } - if ($data['size'] >= 0 and $size >= 0) { + if ($data['size'] === -1) { + $size = -1; + } elseif ($size !== -1) { $size += $data['size']; } } } } + if ($size !== -1) { + $this->cache->put($path, array('size' => $size)); + } return $size; } } diff --git a/tests/lib/files/cache/scanner.php b/tests/lib/files/cache/scanner.php index 7ee28dfc3f..41286e69d3 100644 --- a/tests/lib/files/cache/scanner.php +++ b/tests/lib/files/cache/scanner.php @@ -45,15 +45,52 @@ class Scanner extends \UnitTestCase { $this->assertEqual($cachedData['mimetype'], 'image/png'); } - function testFolder() { + private function fillTestFolders() { $textData = "dummy file data\n"; $imgData = file_get_contents(\OC::$SERVERROOT . '/core/img/logo.png'); + $this->storage->mkdir('folder'); $this->storage->file_put_contents('foo.txt', $textData); $this->storage->file_put_contents('foo.png', $imgData); + $this->storage->file_put_contents('folder/bar.txt', $textData); + } + + function testFolder() { + $this->fillTestFolders(); $this->scanner->scan(''); + $this->assertEqual($this->cache->inCache(''), true); $this->assertEqual($this->cache->inCache('foo.txt'), true); $this->assertEqual($this->cache->inCache('foo.png'), true); + $this->assertEqual($this->cache->inCache('folder'), true); + $this->assertEqual($this->cache->inCache('folder/bar.txt'), true); + + $cachedDataText = $this->cache->get('foo.txt'); + $cachedDataText2 = $this->cache->get('foo.txt'); + $cachedDataImage = $this->cache->get('foo.png'); + $cachedDataFolder = $this->cache->get(''); + $cachedDataFolder2 = $this->cache->get('folder'); + + $this->assertEqual($cachedDataImage['parent'], $cachedDataText['parent']); + $this->assertEqual($cachedDataFolder['fileid'], $cachedDataImage['parent']); + $this->assertEqual($cachedDataFolder['size'], $cachedDataImage['size'] + $cachedDataText['size'] + $cachedDataText2['size']); + $this->assertEqual($cachedDataFolder2['size'], $cachedDataText2['size']); + } + + function testShallow() { + $this->fillTestFolders(); + + $this->scanner->scan('', \OC\Files\Cache\Scanner::SCAN_SHALLOW); + $this->assertEqual($this->cache->inCache(''), true); + $this->assertEqual($this->cache->inCache('foo.txt'), true); + $this->assertEqual($this->cache->inCache('foo.png'), true); + $this->assertEqual($this->cache->inCache('folder'), true); + $this->assertEqual($this->cache->inCache('folder/bar.txt'), false); + + $cachedDataFolder = $this->cache->get(''); + $cachedDataFolder2 = $this->cache->get('folder'); + + $this->assertEqual($cachedDataFolder['size'], -1); + $this->assertEqual($cachedDataFolder2['size'], -1); } function setUp() { From c815fd5a5c8cba52b24327584e689498cb03fb3e Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 8 Oct 2012 14:31:13 +0200 Subject: [PATCH 025/347] fix files_external test cases --- apps/files_external/tests/dropbox.php | 8 +++++--- apps/files_external/tests/smb.php | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/apps/files_external/tests/dropbox.php b/apps/files_external/tests/dropbox.php index 64eb2556c9..e77e0767c9 100644 --- a/apps/files_external/tests/dropbox.php +++ b/apps/files_external/tests/dropbox.php @@ -6,19 +6,21 @@ * See the COPYING-README file. */ +namespace Test\Files\Storage; + $config=include('files_external/tests/config.php'); if(!is_array($config) or !isset($config['dropbox']) or !$config['dropbox']['run']) { - abstract class Test_Filestorage_Dropbox extends Test_FileStorage{} + abstract class Dropbox extends Storage{} return; }else{ - class Test_Filestorage_Dropbox extends Test_FileStorage { + class Dropbox extends Storage { private $config; public function setUp() { $id=uniqid(); $this->config=include('files_external/tests/config.php'); $this->config['dropbox']['root'].='/'.$id;//make sure we have an new empty folder to work in - $this->instance=new OC_Filestorage_Dropbox($this->config['dropbox']); + $this->instance=new \OC\Files\Storage\Dropbox($this->config['dropbox']); } public function tearDown() { diff --git a/apps/files_external/tests/smb.php b/apps/files_external/tests/smb.php index 87b110a241..24728dc237 100644 --- a/apps/files_external/tests/smb.php +++ b/apps/files_external/tests/smb.php @@ -6,9 +6,10 @@ * See the COPYING-README file. */ +namespace Test\Files\Storage; + $config=include('apps/files_external/tests/config.php'); -namespace Test\Files\Storage; if(!is_array($config) or !isset($config['smb']) or !$config['smb']['run']) { abstract class SMB extends Storage{} From 13515effc99bfad7e776d00476e897fa396a8c6c Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 8 Oct 2012 14:58:21 +0200 Subject: [PATCH 026/347] add Cache::getStatus --- lib/files/cache/cache.php | 29 +++++++++++++++++++++++++++++ tests/lib/files/cache/cache.php | 10 ++++++++++ 2 files changed, 39 insertions(+) diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index 79673771e5..5ef49246ea 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -9,6 +9,11 @@ namespace OC\Files\Cache; class Cache { + const NOT_FOUND = 0; + const PARTIAL = 1; //only partial data available, file not cached in the database + const SHALLOW = 2; //folder in cache, but not all child files are completely scanned + const COMPLETE = 3; + /** * @var \OC\Files\Storage\Storage */ @@ -233,4 +238,28 @@ class Cache { $query = \OC_DB::prepare('DELETE FROM `*PREFIX*filecache` WHERE storage=?'); $query->execute(array($this->storageId)); } + + /** + * @param string $file + * + * @return int, Cache::NOT_FOUND, Cache::PARTIAL, Cache::SHALLOW or Cache::COMPLETE + */ + public function getStatus($file) { + $pathHash = md5($file); + $query = \OC_DB::prepare('SELECT * FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path_hash` = ?'); + $result = $query->execute(array($this->storageId, $pathHash)); + if ($row = $result->fetchRow()) { + if ((int)$row['size'] === -1) { + return self::SHALLOW; + } else { + return self::COMPLETE; + } + } else { + if (isset($this->partial[$file])) { + return self::PARTIAL; + } else { + return self::NOT_FOUND; + } + } + } } diff --git a/tests/lib/files/cache/cache.php b/tests/lib/files/cache/cache.php index 8cedadbf19..177cf1c045 100644 --- a/tests/lib/files/cache/cache.php +++ b/tests/lib/files/cache/cache.php @@ -101,6 +101,16 @@ class Cache extends \UnitTestCase { } } + function testStatus() { + $this->assertEquals(\OC\Files\Cache\Cache::NOT_FOUND, $this->cache->getStatus('foo')); + $this->cache->put('foo', array('size' => -1)); + $this->assertEquals(\OC\Files\Cache\Cache::PARTIAL, $this->cache->getStatus('foo')); + $this->cache->put('foo', array('size' => -1, 'mtime' => 20, 'mimetype' => 'foo/file')); + $this->assertEquals(\OC\Files\Cache\Cache::SHALLOW, $this->cache->getStatus('foo')); + $this->cache->put('foo', array('size' => 10)); + $this->assertEquals(\OC\Files\Cache\Cache::COMPLETE, $this->cache->getStatus('foo')); + } + public function tearDown() { $this->cache->clear(); } From d717a5e55ca54c6ddbaf2f35f0f19b707dcfe1c8 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 10 Oct 2012 11:51:14 +0200 Subject: [PATCH 027/347] remove old filecache --- lib/filecache.php | 511 --------------------------------------- lib/filecache/cached.php | 81 ------- lib/filecache/update.php | 217 ----------------- lib/filesystem.php | 12 +- lib/util.php | 7 - 5 files changed, 2 insertions(+), 826 deletions(-) delete mode 100644 lib/filecache.php delete mode 100644 lib/filecache/cached.php delete mode 100644 lib/filecache/update.php diff --git a/lib/filecache.php b/lib/filecache.php deleted file mode 100644 index 8fcb6fd940..0000000000 --- a/lib/filecache.php +++ /dev/null @@ -1,511 +0,0 @@ -. -* -*/ - -/** - * provide caching for filesystem info in the database - * - * not used by OC_Filesystem for reading filesystem info, - * instread apps should use OC_FileCache::get where possible - * - * 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 - * @param string root (optional) - * @return array - * - * returns an associative array with the following keys: - * - size - * - mtime - * - ctime - * - mimetype - * - encrypted - * - versioned - */ - 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{ - OC_FileCache_Update::update($path,$root); - } - } - return OC_FileCache_Cached::get($path,$root); - } - - /** - * put filesystem info in the cache - * @param string $path - * @param array data - * @param string root (optional) - * - * $data is an assiciative array in the same format as returned by get - */ - public static function put($path,$data,$root=false) { - if($root===false) { - $root=OC_Filesystem::getRoot(); - } - $fullpath=$root.$path; - $parent=self::getParentId($fullpath); - $id=self::getId($fullpath,''); - if(isset(OC_FileCache_Cached::$savedData[$fullpath])) { - $data=array_merge(OC_FileCache_Cached::$savedData[$fullpath],$data); - unset(OC_FileCache_Cached::$savedData[$fullpath]); - } - if($id!=-1) { - self::update($id,$data); - return; - } - - // add parent directory to the file cache if it does not exist yet. - if ($parent == -1 && $fullpath != $root) { - $parentDir = dirname($path); - self::scanFile($parentDir); - $parent = self::getParentId($fullpath); - } - - if(!isset($data['size']) or !isset($data['mtime'])) {//save incomplete data for the next time we write it - OC_FileCache_Cached::$savedData[$fullpath]=$data; - return; - } - if(!isset($data['encrypted'])) { - $data['encrypted']=false; - } - if(!isset($data['versioned'])) { - $data['versioned']=false; - } - $mimePart=dirname($data['mimetype']); - $data['size']=(int)$data['size']; - $data['ctime']=(int)$data['mtime']; - $data['writable']=(int)$data['writable']; - $data['encrypted']=(int)$data['encrypted']; - $data['versioned']=(int)$data['versioned']; - $user=OC_User::getUser(); - $query=OC_DB::prepare('INSERT INTO `*PREFIX*fscache`(`parent`, `name`, `path`, `path_hash`, `size`, `mtime`, `ctime`, `mimetype`, `mimepart`,`user`,`writable`,`encrypted`,`versioned`) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?)'); - $result=$query->execute(array($parent,basename($fullpath),$fullpath,md5($fullpath),$data['size'],$data['mtime'],$data['ctime'],$data['mimetype'],$mimePart,$user,$data['writable'],$data['encrypted'],$data['versioned'])); - if(OC_DB::isError($result)) { - OC_Log::write('files','error while writing file('.$fullpath.') to cache',OC_Log::ERROR); - } - - if($cache=OC_Cache::getUserCache(true)) { - $cache->remove('fileid/'.$fullpath);//ensure we don't have -1 cached - } - } - - /** - * update filesystem info of a file - * @param int $id - * @param array $data - */ - private static function update($id,$data) { - $arguments=array(); - $queryParts=array(); - 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) { - $arguments[] = 0; - }else{ - $arguments[] = $data[$attribute]; - } - $queryParts[]='`'.$attribute.'`=?'; - } - } - if(isset($data['mimetype'])) { - $arguments[]=dirname($data['mimetype']); - $queryParts[]='`mimepart`=?'; - } - $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); - } - } - - /** - * register a file move in the cache - * @param string oldPath - * @param string newPath - * @param string root (optional) - */ - public static function move($oldPath,$newPath,$root=false) { - if($root===false) { - $root=OC_Filesystem::getRoot(); - } - // If replacing an existing file, delete the file - if (self::inCache($newPath, $root)) { - self::delete($newPath, $root); - } - $oldPath=$root.$oldPath; - $newPath=$root.$newPath; - $newParent=self::getParentId($newPath); - $query=OC_DB::prepare('UPDATE `*PREFIX*fscache` SET `parent`=? ,`name`=?, `path`=?, `path_hash`=? WHERE `path_hash`=?'); - $query->execute(array($newParent,basename($newPath),$newPath,md5($newPath),md5($oldPath))); - - if(($cache=OC_Cache::getUserCache(true)) && $cache->hasKey('fileid/'.$oldPath)) { - $cache->set('fileid/'.$newPath,$cache->get('fileid/'.$oldPath)); - $cache->remove('fileid/'.$oldPath); - } - - $query=OC_DB::prepare('SELECT `path` FROM `*PREFIX*fscache` WHERE `path` LIKE ?'); - $oldLength=strlen($oldPath); - $updateQuery=OC_DB::prepare('UPDATE `*PREFIX*fscache` SET `path`=?, `path_hash`=? WHERE `path_hash`=?'); - while($row= $query->execute(array($oldPath.'/%'))->fetchRow()) { - $old=$row['path']; - $new=$newPath.substr($old,$oldLength); - $updateQuery->execute(array($new,md5($new),md5($old))); - - if(($cache=OC_Cache::getUserCache(true)) && $cache->hasKey('fileid/'.$old)) { - $cache->set('fileid/'.$new,$cache->get('fileid/'.$old)); - $cache->remove('fileid/'.$old); - } - } - } - - /** - * delete info from the cache - * @param string path - * @param string root (optional) - */ - 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.'/%')); - - OC_Cache::remove('fileid/'.$root.$path); - } - - /** - * return array of filenames matching the querty - * @param string $query - * @param boolean $returnData - * @param string root (optional) - * @return array of filepaths - */ - public static function search($search,$returnData=false,$root=false) { - if($root===false) { - $root=OC_Filesystem::getRoot(); - } - $rootLen=strlen($root); - if(!$returnData) { - $query=OC_DB::prepare('SELECT `path` FROM `*PREFIX*fscache` WHERE `name` LIKE ? AND `user`=?'); - }else{ - $query=OC_DB::prepare('SELECT * FROM `*PREFIX*fscache` WHERE `name` LIKE ? AND `user`=?'); - } - $result=$query->execute(array("%$search%",OC_User::getUser())); - $names=array(); - while($row=$result->fetchRow()) { - if(!$returnData) { - $names[]=substr($row['path'],$rootLen); - }else{ - $row['path']=substr($row['path'],$rootLen); - $names[]=$row; - } - } - return $names; - } - - /** - * 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: - * - name - * - size - * - mtime - * - ctime - * - mimetype - * - encrypted - * - versioned - */ - 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); - } - - /** - * check if a file or folder is in the cache - * @param string $path - * @param string root (optional) - * @return bool - */ - public static function inCache($path,$root=false) { - return self::getId($path,$root)!=-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=false) { - if($root===false) { - $root=OC_Filesystem::getRoot(); - } - - $fullPath=$root.$path; - if(($cache=OC_Cache::getUserCache(true)) && $cache->hasKey('fileid/'.$fullPath)) { - return $cache->get('fileid/'.$fullPath); - } - - $query=OC_DB::prepare('SELECT `id` FROM `*PREFIX*fscache` WHERE `path_hash`=?'); - $result=$query->execute(array(md5($fullPath))); - 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)) { - $id=$result['id']; - }else{ - $id=-1; - } - if($cache=OC_Cache::getUserCache(true)) { - $cache->set('fileid/'.$fullPath,$id); - } - - return $id; - } - - /** - * get the file path from the id, relative to the home folder of the user - * @param int id - * @param string user (optional) - * @return string - */ - public static function getPath($id,$user='') { - if(!$user) { - $user=OC_User::getUser(); - } - $query=OC_DB::prepare('SELECT `path` FROM `*PREFIX*fscache` WHERE `id`=? AND `user`=?'); - $result=$query->execute(array($id,$user)); - $row=$result->fetchRow(); - $path=$row['path']; - $root='/'.$user.'/files'; - if(substr($path,0,strlen($root))!=$root) { - return false; - } - return substr($path,strlen($root)); - } - - /** - * get the file id of the parent folder, taking into account '/' has no parent - * @param string $path - * @return int - */ - private static function getParentId($path) { - if($path=='/') { - return -1; - }else{ - return self::getId(dirname($path),''); - } - } - - /** - * adjust the size of the parent folders - * @param string $path - * @param int $sizeDiff - * @param string root (optinal) - */ - public static function increaseSize($path,$sizeDiff, $root=false) { - if($sizeDiff==0) return; - $id=self::getId($path,$root); - 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); - } - } - - /** - * recursively scan the filesystem and fill the cache - * @param string $path - * @param OC_EventSource $enventSource (optional) - * @param int count (optional) - * @param string root (optional) - */ - public static function scan($path,$eventSource=false,&$count=0,$root=false) { - if($eventSource) { - $eventSource->send('scanning',array('file'=>$path,'count'=>$count)); - } - $lastSend=$count; - // 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; - } - if($root===false) { - $view=OC_Filesystem::getView(); - }else{ - $view=new OC_FilesystemView($root); - } - self::scanFile($path,$root); - $dh=$view->opendir($path.'/'); - $totalSize=0; - if($dh) { - while (($filename = readdir($dh)) !== false) { - if($filename != '.' and $filename != '..') { - $file=$path.'/'.$filename; - if($view->is_dir($file.'/')) { - self::scan($file,$eventSource,$count,$root); - }else{ - $totalSize+=self::scanFile($file,$root); - $count++; - if($count>$lastSend+25 and $eventSource) { - $lastSend=$count; - $eventSource->send('scanning',array('file'=>$path,'count'=>$count)); - } - } - } - } - } - - OC_FileCache_Update::cleanFolder($path,$root); - self::increaseSize($path,$totalSize,$root); - } - - /** - * scan a single file - * @param string path - * @param string root (optional) - * @return int size of the scanned file - */ - 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; - } - if($root===false) { - $view=OC_Filesystem::getView(); - }else{ - $view=new OC_FilesystemView($root); - } - if(!$view->is_readable($path)) return; //cant read, nothing we can do - clearstatcache(); - $mimetype=$view->getMimeType($path); - $stat=$view->stat($path); - if($mimetype=='httpd/unix-directory') { - $stat['size'] = 0; - $writable=$view->is_writable($path.'/'); - }else{ - $writable=$view->is_writable($path); - } - $stat['mimetype']=$mimetype; - $stat['writable']=$writable; - if($path=='/') { - $path=''; - } - self::put($path,$stat,$root); - return $stat['size']; - } - - /** - * find files by mimetype - * @param string $part1 - * @param string $part2 (optional) - * @param string root (optional) - * @return array of file paths - * - * $part1 and $part2 together form the complete mimetype. - * e.g. searchByMime('text','plain') - * - * seccond mimetype part can be ommited - * e.g. searchByMime('audio') - */ - public static function searchByMime($part1,$part2=null,$root=false) { - if($root===false) { - $root=OC_Filesystem::getRoot(); - } - $rootLen=strlen($root); - $root .= '%'; - $user=OC_User::getUser(); - if(!$part2) { - $query=OC_DB::prepare('SELECT `path` FROM `*PREFIX*fscache` WHERE `mimepart`=? AND `user`=? AND `path` LIKE ?'); - $result=$query->execute(array($part1,$user, $root)); - }else{ - $query=OC_DB::prepare('SELECT `path` FROM `*PREFIX*fscache` WHERE `mimetype`=? AND `user`=? AND `path` LIKE ? '); - $result=$query->execute(array($part1.'/'.$part2,$user, $root)); - } - $names=array(); - while($row=$result->fetchRow()) { - $names[]=substr($row['path'],$rootLen); - } - return $names; - } - - /** - * clean old pre-path_hash entries - */ - public static function clean() { - $query=OC_DB::prepare('DELETE FROM `*PREFIX*fscache` WHERE LENGTH(`path_hash`)<30'); - $query->execute(); - } - - /** - * clear filecache entries - * @param string user (optonal) - */ - public static function clear($user='') { - if($user) { - $query=OC_DB::prepare('DELETE FROM `*PREFIX*fscache` WHERE `user`=?'); - $query->execute(array($user)); - }else{ - $query=OC_DB::prepare('DELETE FROM `*PREFIX*fscache`'); - $query->execute(); - } - } - - /** - * trigger an update for the cache by setting the mtimes to 0 - * @param string $user (optional) - */ - 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)); - }else{ - $query=OC_DB::prepare('UPDATE `*PREFIX*fscache` SET `mtime`=0 AND `mimetype`="httpd/unix-directory"'); - $query->execute(); - } - } -} - -//watch for changes and try to keep the cache up to date -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 deleted file mode 100644 index 9b1eb4f780..0000000000 --- a/lib/filecache/cached.php +++ /dev/null @@ -1,81 +0,0 @@ - - * 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; - $stmt=OC_DB::prepare('SELECT `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) ) { - $result = $result->fetchRow(); - } else { - OC:Log::write('OC_FileCache_Cached', 'could not execute get: '. OC_DB::getErrorMessage($result), OC_Log::ERROR); - $result = false; - } - } else { - OC_Log::write('OC_FileCache_Cached', 'could not prepare get: '. OC_DB::getErrorMessage($stmt), OC_Log::ERROR); - $result = false; - } - 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 `id`,`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 deleted file mode 100644 index 1b81f70d77..0000000000 --- a/lib/filecache/update.php +++ /dev/null @@ -1,217 +0,0 @@ - - * 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 != '..' and $filename != '') { - $file=$path.'/'.$filename; - $isDir=$view->is_dir($file); - if(self::hasUpdated($file, $root, $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)); - }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 filesystem - * @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($view->is_dir($path.'/')) { - 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']; - OC_FileCache::increaseSize(dirname($oldPath), -$oldSize, $root); - OC_FileCache::increaseSize(dirname($newPath), $oldSize, $root); - OC_FileCache::move($oldPath, $newPath); - } -} diff --git a/lib/filesystem.php b/lib/filesystem.php index 0d24b7203b..b73b52d420 100644 --- a/lib/filesystem.php +++ b/lib/filesystem.php @@ -254,13 +254,6 @@ class OC_Filesystem{ } } } - - $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); - } } self::$loaded=true; @@ -399,7 +392,7 @@ class OC_Filesystem{ } /** - * checks if a file is blacklsited for storage in the filesystem + * checks if a file is blacklisted for storage in the filesystem * Listens to write and rename hooks * @param array $data from hook */ @@ -419,7 +412,7 @@ class OC_Filesystem{ } /** - * following functions are equivilent to their php buildin equivilents for arguments/return values. + * following functions are equivalent to their php builtin equivalents for arguments/return values. */ static public function mkdir($path) { return self::$defaultInstance->mkdir($path); @@ -592,4 +585,3 @@ 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/util.php b/lib/util.php index b21580cb01..557f731522 100755 --- a/lib/util.php +++ b/lib/util.php @@ -58,13 +58,6 @@ 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); - if($mtime>$previousMTime) {//mount config has changed, filecache needs to be updated - OC_FileCache::triggerUpdate($user); - OC_Preferences::setValue($user,'files','mountconfigmtime',$mtime); - } } OC_Hook::emit('OC_Filesystem', 'setup', array('user' => $user, 'user_dir' => $user_dir)); } From 9df60d27bd9dad6a37a0d763b808a5b1c5ade5c5 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 10 Oct 2012 11:54:44 +0200 Subject: [PATCH 028/347] move some code around --- lib/files/filesystem.php | 629 +++++++++++++++++++++ lib/{filesystemview.php => files/view.php} | 387 +++++++------ lib/filesystem.php | 562 ------------------ 3 files changed, 835 insertions(+), 743 deletions(-) create mode 100644 lib/files/filesystem.php rename lib/{filesystemview.php => files/view.php} (62%) diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php new file mode 100644 index 0000000000..d0a96b59a0 --- /dev/null +++ b/lib/files/filesystem.php @@ -0,0 +1,629 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +/** + * 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 permission related stuff + * + * Hooks provided: + * read(path) + * write(path, &run) + * post_write(path) + * create(path, &run) (when a file is created, both create and write will be emited in that order) + * 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) + * + * the &run parameter can be set to false to prevent the operation from occuring + */ + +namespace OC\Files; + +class Filesystem { + static private $storages = array(); + static private $mounts = array(); + public static $loaded = false; + /** + * @var \OC\Files\Storage\Storage $defaultInstance + */ + static private $defaultInstance; + + + /** + * classname which used for hooks handling + * used as signalclass in OC_Hooks::emit() + */ + const CLASSNAME = 'OC_Filesystem'; + + /** + * signalname emited before file renaming + * + * @param oldpath + * @param newpath + */ + const signal_rename = 'rename'; + + /** + * signal emited after file renaming + * + * @param oldpath + * @param newpath + */ + const signal_post_rename = 'post_rename'; + + /** + * signal emited before file/dir creation + * + * @param path + * @param run changing this flag to false in hook handler will cancel event + */ + const signal_create = 'create'; + + /** + * signal emited after file/dir creation + * + * @param path + * @param run changing this flag to false in hook handler will cancel event + */ + const signal_post_create = 'post_create'; + + /** + * signal emits before file/dir copy + * + * @param oldpath + * @param newpath + * @param run changing this flag to false in hook handler will cancel event + */ + const signal_copy = 'copy'; + + /** + * signal emits after file/dir copy + * + * @param oldpath + * @param newpath + */ + const signal_post_copy = 'post_copy'; + + /** + * signal emits before file/dir save + * + * @param path + * @param run changing this flag to false in hook handler will cancel event + */ + const signal_write = 'write'; + + /** + * signal emits after file/dir save + * + * @param path + */ + const signal_post_write = 'post_write'; + + /** + * signal emits when reading file/dir + * + * @param path + */ + const signal_read = 'read'; + + /** + * signal emits when removing file/dir + * + * @param path + */ + const signal_delete = 'delete'; + + /** + * parameters definitions for signals + */ + const signal_param_path = 'path'; + const signal_param_oldpath = 'oldpath'; + const signal_param_newpath = 'newpath'; + + /** + * run - changing this flag to false in hook handler will cancel event + */ + const signal_param_run = 'run'; + + /** + * get the mountpoint of the storage object for a path + ( note: because a storage is not always mounted inside the fakeroot, the returned mountpoint is relative to the absolute root of the filesystem and doesn't take the chroot into account + * + * @param string path + * @return string + */ + static public function getMountPoint($path) { + OC_Hook::emit(self::CLASSNAME, 'get_mountpoint', array('path' => $path)); + if (!$path) { + $path = '/'; + } + if ($path[0] !== '/') { + $path = '/' . $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)) { + $foundMountPoint = $mountpoint; + } + } + return $foundMountPoint; + } + + /** + * get the part of the path relative to the mountpoint of the storage it's stored in + * + * @param string path + * @return bool + */ + static public function getInternalPath($path) { + $mountPoint = self::getMountPoint($path); + $internalPath = substr($path, strlen($mountPoint)); + return $internalPath; + } + + /** + * get the storage object for a path + * + * @param string path + * @return \OC\Files\Storage\Storage + */ + static public function getStorage($path) { + $mountpoint = self::getMountPoint($path); + if ($mountpoint) { + if (!isset(OC_Filesystem::$storages[$mountpoint])) { + $mount = OC_Filesystem::$mounts[$mountpoint]; + OC_Filesystem::$storages[$mountpoint] = OC_Filesystem::createStorage($mount['class'], $mount['arguments']); + } + return OC_Filesystem::$storages[$mountpoint]; + } + } + + /** + * resolve a path to a storage and internal path + * + * @param string $path + * @return array consisting of the storage and the internal path + */ + static public function resolvePath($path) { + $mountpoint = self::getMountPoint($path); + if ($mountpoint) { + if (!isset(OC_Filesystem::$storages[$mountpoint])) { + $mount = OC_Filesystem::$mounts[$mountpoint]; + OC_Filesystem::$storages[$mountpoint] = OC_Filesystem::createStorage($mount['class'], $mount['arguments']); + } + $storage = OC_Filesystem::$storages[$mountpoint]; + $internalPath = substr($path, strlen($mountpoint)); + return array($storage, $internalPath); + } + } + + static public function init($root) { + if (self::$defaultInstance) { + return false; + } + self::$defaultInstance = new OC_FilesystemView($root); + +//load custom mount config + 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(OC_User::getUser(), $group)) { + foreach ($mounts as $mountPoint => $options) { + $mountPoint = self::setUserVars($mountPoint); + foreach ($options as &$option) { + $option = self::setUserVars($option); + } + self::mount($options['class'], $options['options'], $mountPoint); + } + } + } + } + + if (isset($mountConfig['user'])) { + foreach ($mountConfig['user'] as $user => $mounts) { + if ($user === 'all' or strtolower($user) === strtolower(OC_User::getUser())) { + foreach ($mounts as $mountPoint => $options) { + $mountPoint = self::setUserVars($mountPoint); + foreach ($options as &$option) { + $option = self::setUserVars($option); + } + self::mount($options['class'], $options['options'], $mountPoint); + } + } + } + } + } + + self::$loaded = true; + } + + /** + * fill in the correct values for $user, and $password placeholders + * + * @param string intput + * @return string + */ + private static function setUserVars($input) { + return str_replace('$user', OC_User::getUser(), $input); + } + + /** + * get the default filesystem view + * + * @return OC_FilesystemView + */ + static public function getView() { + return self::$defaultInstance; + } + + /** + * tear down the filesystem, removing all storage providers + */ + static public function tearDown() { + self::$storages = array(); + } + + /** + * create a new storage of a specific type + * + * @param string type + * @param array arguments + * @return \OC\Files\Storage\Storage + */ + static private function createStorage($class, $arguments) { + if (class_exists($class)) { + try { + return new $class($arguments); + } catch (Exception $exception) { + OC_Log::write('core', $exception->getMessage(), OC_Log::ERROR); + return false; + } + } else { + OC_Log::write('core', 'storage backend ' . $class . ' not found', OC_Log::ERROR); + return false; + } + } + + /** + * change the root to a fake root + * + * @param string fakeRoot + * @return bool + */ + static public function chroot($fakeRoot) { + return self::$defaultInstance->chroot($fakeRoot); + } + + /** + * @brief get the relative path of the root data directory for the current user + * @return string + * + * Returns path like /admin/files + */ + static public function getRoot() { + return self::$defaultInstance->getRoot(); + } + + /** + * clear all mounts and storage backends + */ + public static function clearMounts() { + self::$mounts = array(); + self::$storages = array(); + } + + /** + * mount an \OC\Files\Storage\Storage in our virtual filesystem + * + * @param \OC\Files\Storage\Storage storage + * @param string mountpoint + */ + static public function mount($class, $arguments, $mountpoint) { + if ($mountpoint[0] != '/') { + $mountpoint = '/' . $mountpoint; + } + if (substr($mountpoint, -1) !== '/') { + $mountpoint = $mountpoint . '/'; + } + self::$mounts[$mountpoint] = array('class' => $class, 'arguments' => $arguments); + } + + /** + * return the path to a local version of the file + * we need this because we can't know if a file is stored local or not from outside the filestorage and for some purposes a local file is needed + * + * @param string path + * @return string + */ + static public function getLocalFile($path) { + return self::$defaultInstance->getLocalFile($path); + } + + /** + * @param string path + * @return string + */ + static public function getLocalFolder($path) { + return self::$defaultInstance->getLocalFolder($path); + } + + /** + * return path to file which reflects one visible in browser + * + * @param string path + * @return string + */ + static public function getLocalPath($path) { + $datadir = OC_User::getHome(OC_User::getUser()) . '/files'; + $newpath = $path; + if (strncmp($newpath, $datadir, strlen($datadir)) == 0) { + $newpath = substr($path, strlen($datadir)); + } + return $newpath; + } + + /** + * check if the requested path is valid + * + * @param string path + * @return bool + */ + static public function isValidPath($path) { + if (!$path || $path[0] !== '/') { + $path = '/' . $path; + } + if (strstr($path, '/../') || strrchr($path, '/') === '/..') { + return false; + } + return true; + } + + /** + * checks if a file is blacklisted for storage in the filesystem + * Listens to write and rename hooks + * + * @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; + } + } + } + + /** + * following functions are equivalent to their php builtin equivalents for arguments/return values. + */ + static public function mkdir($path) { + return self::$defaultInstance->mkdir($path); + } + + static public function rmdir($path) { + return self::$defaultInstance->rmdir($path); + } + + 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); + } + + static public function is_file($path) { + return self::$defaultInstance->is_file($path); + } + + static public function stat($path) { + return self::$defaultInstance->stat($path); + } + + static public function filetype($path) { + return self::$defaultInstance->filetype($path); + } + + static public function filesize($path) { + return self::$defaultInstance->filesize($path); + } + + static public function readfile($path) { + return self::$defaultInstance->readfile($path); + } + + /** + * @deprecated Replaced by isReadable() as part of CRUDS + */ + static public function is_readable($path) { + return self::$defaultInstance->is_readable($path); + } + + /** + * @deprecated Replaced by isCreatable(), isUpdatable(), isDeletable() as part of CRUDS + */ + static public function is_writable($path) { + return self::$defaultInstance->is_writable($path); + } + + static public function isCreatable($path) { + return self::$defaultInstance->isCreatable($path); + } + + static public function isReadable($path) { + return self::$defaultInstance->isReadable($path); + } + + static public function isUpdatable($path) { + return self::$defaultInstance->isUpdatable($path); + } + + static public function isDeletable($path) { + return self::$defaultInstance->isDeletable($path); + } + + static public function isSharable($path) { + return self::$defaultInstance->isSharable($path); + } + + static public function file_exists($path) { + return self::$defaultInstance->file_exists($path); + } + + static public function filectime($path) { + return self::$defaultInstance->filectime($path); + } + + static public function filemtime($path) { + return self::$defaultInstance->filemtime($path); + } + + static public function touch($path, $mtime = null) { + return self::$defaultInstance->touch($path, $mtime); + } + + 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 unlink($path) { + return self::$defaultInstance->unlink($path); + } + + 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 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 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 free_space($path = '/') { + return self::$defaultInstance->free_space($path); + } + + 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, $time); + } + + static public function removeETagHook($params, $root = false) { + if (isset($params['path'])) { + $path = $params['path']; + } else { + $path = $params['oldpath']; + } + + if ($root) { // reduce path to the required part of it (no 'username/files') + $fakeRootView = new OC_FilesystemView($root); + $count = 1; + $path = str_replace(OC_App::getStorage("files")->getAbsolutePath($path), "", $fakeRootView->getAbsolutePath($path), $count); + } + + $path = self::normalizePath($path); + OC_Connector_Sabre_Node::removeETagPropertyForPath($path); + } + + /** + * normalize a path + * + * @param string path + * @param bool $stripTrailingSlash + * @return string + */ + public static function normalizePath($path, $stripTrailingSlash = true) { + if ($path == '') { + return '/'; + } +//no windows style slashes + $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); + } +//remove duplicate slashes + while (strpos($path, '//') !== false) { + $path = str_replace('//', '/', $path); + } +//normalize unicode if possible + if (class_exists('Normalizer')) { + $path = Normalizer::normalize($path); + } + 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_Util::setupFS(); diff --git a/lib/filesystemview.php b/lib/files/view.php similarity index 62% rename from lib/filesystemview.php rename to lib/files/view.php index 071fc781f1..8c3f288f44 100644 --- a/lib/filesystemview.php +++ b/lib/files/view.php @@ -1,26 +1,11 @@ . + * Copyright (c) 2012 Robin Appelman + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. */ - /** * Class to provide access to ownCloud filesystem via a "view", and methods for * working with files within that view (e.g. read, write, delete, etc.). Each @@ -38,41 +23,45 @@ * \OC\Files\Storage\Storage object */ -class OC_FilesystemView { - private $fakeRoot=''; - private $internal_path_cache=array(); - private $storage_cache=array(); +namespace OC\Files; + +class View { + private $fakeRoot = ''; + private $internal_path_cache = array(); + private $storage_cache = array(); public function __construct($root) { - $this->fakeRoot=$root; + $this->fakeRoot = $root; } public function getAbsolutePath($path) { - if(!$path) { - $path='/'; + if (!$path) { + $path = '/'; } - if($path[0]!=='/') { - $path='/'.$path; + if ($path[0] !== '/') { + $path = '/' . $path; } - return $this->fakeRoot.$path; + return $this->fakeRoot . $path; } /** - * change the root to a fake toor - * @param string fakeRoot - * @return bool - */ + * change the root to a fake toor + * + * @param string fakeRoot + * @return bool + */ public function chroot($fakeRoot) { - if(!$fakeRoot=='') { - if($fakeRoot[0]!=='/') { - $fakeRoot='/'.$fakeRoot; + if (!$fakeRoot == '') { + if ($fakeRoot[0] !== '/') { + $fakeRoot = '/' . $fakeRoot; } } - $this->fakeRoot=$fakeRoot; + $this->fakeRoot = $fakeRoot; } /** * get the fake root + * * @return string */ public function getRoot() { @@ -80,10 +69,11 @@ class OC_FilesystemView { } /** - * get the part of the path relative to the mountpoint of the storage it's stored in - * @param string path - * @return bool - */ + * get the part of the path relative to the mountpoint of the storage it's stored in + * + * @param string path + * @return bool + */ public function getInternalPath($path) { if (!isset($this->internal_path_cache[$path])) { $this->internal_path_cache[$path] = OC_Filesystem::getInternalPath($this->getAbsolutePath($path)); @@ -93,30 +83,32 @@ class OC_FilesystemView { /** * get path relative to the root of the view + * * @param string path * @return string */ public function getRelativePath($path) { - if($this->fakeRoot=='') { + if ($this->fakeRoot == '') { return $path; } - if(strpos($path, $this->fakeRoot)!==0) { + if (strpos($path, $this->fakeRoot) !== 0) { return null; - }else{ - $path=substr($path, strlen($this->fakeRoot)); - if(strlen($path)===0) { + } else { + $path = substr($path, strlen($this->fakeRoot)); + if (strlen($path) === 0) { return '/'; - }else{ + } else { return $path; } } } /** - * get the storage object for a path - * @param string path - * @return \OC\Files\Storage\Storage - */ + * get the storage object for a path + * + * @param string path + * @return \OC\Files\Storage\Storage + */ public function getStorage($path) { if (!isset($this->storage_cache[$path])) { $this->storage_cache[$path] = OC_Filesystem::getStorage($this->getAbsolutePath($path)); @@ -125,35 +117,37 @@ class OC_FilesystemView { } /** - * get the mountpoint of the storage object for a path + * get the mountpoint of the storage object for a path ( note: because a storage is not always mounted inside the fakeroot, the returned mountpoint is relative to the absolute root of the filesystem and doesn't take the chroot into account - * - * @param string path - * @return string - */ + * + * @param string path + * @return string + */ public function getMountPoint($path) { return OC_Filesystem::getMountPoint($this->getAbsolutePath($path)); } /** - * return the path to a local version of the file - * we need this because we can't know if a file is stored local or not from outside the filestorage and for some purposes a local file is needed - * @param string path - * @return string - */ + * return the path to a local version of the file + * we need this because we can't know if a file is stored local or not from outside the filestorage and for some purposes a local file is needed + * + * @param string path + * @return string + */ public function getLocalFile($path) { - $parent=substr($path, 0, strrpos($path,'/')); - if(OC_Filesystem::isValidPath($parent) and $storage=$this->getStorage($path)) { + $parent = substr($path, 0, strrpos($path, '/')); + if (OC_Filesystem::isValidPath($parent) and $storage = $this->getStorage($path)) { return $storage->getLocalFile($this->getInternalPath($path)); } } + /** * @param string path * @return string */ public function getLocalFolder($path) { - $parent=substr($path, 0, strrpos($path,'/')); - if(OC_Filesystem::isValidPath($parent) and $storage=$this->getStorage($path)) { + $parent = substr($path, 0, strrpos($path, '/')); + if (OC_Filesystem::isValidPath($parent) and $storage = $this->getStorage($path)) { return $storage->getLocalFolder($this->getInternalPath($path)); } } @@ -166,105 +160,127 @@ class OC_FilesystemView { public function mkdir($path) { return $this->basicOperation('mkdir', $path, array('create', 'write')); } + public function rmdir($path) { return $this->basicOperation('rmdir', $path, array('delete')); } + public function opendir($path) { return $this->basicOperation('opendir', $path, array('read')); } + public function readdir($handle) { - $fsLocal= new \OC\Files\Storage\Local( array( 'datadir' => '/' ) ); - return $fsLocal->readdir( $handle ); + $fsLocal = new \OC\Files\Storage\Local(array('datadir' => '/')); + return $fsLocal->readdir($handle); } + public function is_dir($path) { - if($path=='/') { + if ($path == '/') { return true; } return $this->basicOperation('is_dir', $path); } + public function is_file($path) { - if($path=='/') { + if ($path == '/') { return false; } return $this->basicOperation('is_file', $path); } + public function stat($path) { return $this->basicOperation('stat', $path); } + public function filetype($path) { return $this->basicOperation('filetype', $path); } + public function filesize($path) { return $this->basicOperation('filesize', $path); } + public function readfile($path) { @ob_end_clean(); - $handle=$this->fopen($path, 'rb'); + $handle = $this->fopen($path, 'rb'); if ($handle) { - $chunkSize = 8192;// 8 MB chunks + $chunkSize = 8192; // 8 MB chunks while (!feof($handle)) { echo fread($handle, $chunkSize); flush(); } - $size=$this->filesize($path); + $size = $this->filesize($path); return $size; } return false; } + /** - * @deprecated Replaced by isReadable() as part of CRUDS - */ + * @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 - */ + * @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); } + public function isReadable($path) { return $this->basicOperation('isReadable', $path); } + public function isUpdatable($path) { return $this->basicOperation('isUpdatable', $path); } + public function isDeletable($path) { return $this->basicOperation('isDeletable', $path); } + public function isSharable($path) { return $this->basicOperation('isSharable', $path); } + public function file_exists($path) { - if($path=='/') { + if ($path == '/') { return true; } return $this->basicOperation('file_exists', $path); } + public function filectime($path) { return $this->basicOperation('filectime', $path); } + public function filemtime($path) { return $this->basicOperation('filemtime', $path); } - public function touch($path, $mtime=null) { + + public function touch($path, $mtime = null) { return $this->basicOperation('touch', $path, array('write'), $mtime); } + public function file_get_contents($path) { return $this->basicOperation('file_get_contents', $path, array('read')); } + public function file_put_contents($path, $data) { - if(is_resource($data)) {//not having to deal with streams in file_put_contents makes life easier + if (is_resource($data)) { //not having to deal with streams in file_put_contents makes life easier $absolutePath = OC_Filesystem::normalizePath($this->getAbsolutePath($path)); if (OC_FileProxy::runPreProxies('file_put_contents', $absolutePath, $data) && OC_Filesystem::isValidPath($path)) { $path = $this->getRelativePath($absolutePath); $exists = $this->file_exists($path); $run = true; - if( $this->fakeRoot==OC_Filesystem::getRoot() ){ - if(!$exists) { + if ($this->fakeRoot == OC_Filesystem::getRoot()) { + if (!$exists) { OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_create, @@ -283,83 +299,86 @@ class OC_FilesystemView { ) ); } - if(!$run) { + if (!$run) { return false; } - $target=$this->fopen($path, 'w'); - if($target) { - $count=OC_Helper::streamCopy($data, $target); + $target = $this->fopen($path, 'w'); + if ($target) { + $count = OC_Helper::streamCopy($data, $target); fclose($target); fclose($data); - if( $this->fakeRoot==OC_Filesystem::getRoot() ){ - if(!$exists) { + if ($this->fakeRoot == OC_Filesystem::getRoot()) { + if (!$exists) { OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_create, - array( OC_Filesystem::signal_param_path => $path) + array(OC_Filesystem::signal_param_path => $path) ); } OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_write, - array( OC_Filesystem::signal_param_path => $path) + array(OC_Filesystem::signal_param_path => $path) ); } OC_FileProxy::runPostProxies('file_put_contents', $absolutePath, $count); return $count > 0; - }else{ + } else { return false; } } - }else{ + } else { return $this->basicOperation('file_put_contents', $path, array('create', 'write'), $data); } } + public function unlink($path) { return $this->basicOperation('unlink', $path, array('delete')); } - public function deleteAll( $directory, $empty = false ) { - return $this->basicOperation( 'deleteAll', $directory, array('delete'), $empty ); + + public function deleteAll($directory, $empty = false) { + 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)) { + if (OC_FileProxy::runPreProxies('rename', $absolutePath1, $absolutePath2) and OC_Filesystem::isValidPath($path2)) { $path1 = $this->getRelativePath($absolutePath1); $path2 = $this->getRelativePath($absolutePath2); - if($path1 == null or $path2 == null) { + if ($path1 == null or $path2 == null) { return false; } - $run=true; - if( $this->fakeRoot==OC_Filesystem::getRoot() ){ + $run = true; + if ($this->fakeRoot == OC_Filesystem::getRoot()) { OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_rename, - array( - OC_Filesystem::signal_param_oldpath => $path1, - OC_Filesystem::signal_param_newpath => $path2, - OC_Filesystem::signal_param_run => &$run - ) + array( + OC_Filesystem::signal_param_oldpath => $path1, + OC_Filesystem::signal_param_newpath => $path2, + OC_Filesystem::signal_param_run => &$run + ) ); } - if($run) { - $mp1 = $this->getMountPoint($path1.$postFix1); - $mp2 = $this->getMountPoint($path2.$postFix2); - if($mp1 == $mp2) { - if($storage = $this->getStorage($path1)) { - $result = $storage->rename($this->getInternalPath($path1.$postFix1), $this->getInternalPath($path2.$postFix2)); + if ($run) { + $mp1 = $this->getMountPoint($path1 . $postFix1); + $mp2 = $this->getMountPoint($path2 . $postFix2); + if ($mp1 == $mp2) { + if ($storage = $this->getStorage($path1)) { + $result = $storage->rename($this->getInternalPath($path1 . $postFix1), $this->getInternalPath($path2 . $postFix2)); } } else { - $source = $this->fopen($path1.$postFix1, 'r'); - $target = $this->fopen($path2.$postFix2, 'w'); + $source = $this->fopen($path1 . $postFix1, 'r'); + $target = $this->fopen($path2 . $postFix2, 'w'); $count = OC_Helper::streamCopy($source, $target); $storage1 = $this->getStorage($path1); - $storage1->unlink($this->getInternalPath($path1.$postFix1)); - $result = $count>0; + $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, @@ -373,31 +392,32 @@ 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)) { + if (OC_FileProxy::runPreProxies('copy', $absolutePath1, $absolutePath2) and OC_Filesystem::isValidPath($path2)) { $path1 = $this->getRelativePath($absolutePath1); $path2 = $this->getRelativePath($absolutePath2); - if($path1 == null or $path2 == null) { + if ($path1 == null or $path2 == null) { return false; } - $run=true; - if( $this->fakeRoot==OC_Filesystem::getRoot() ){ + $run = true; + if ($this->fakeRoot == OC_Filesystem::getRoot()) { OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_copy, array( OC_Filesystem::signal_param_oldpath => $path1, - OC_Filesystem::signal_param_newpath=>$path2, + OC_Filesystem::signal_param_newpath => $path2, OC_Filesystem::signal_param_run => &$run ) ); - $exists=$this->file_exists($path2); - if($run and !$exists) { + $exists = $this->file_exists($path2); + if ($run and !$exists) { OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_create, @@ -407,7 +427,7 @@ class OC_FilesystemView { ) ); } - if($run) { + if ($run) { OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_write, @@ -418,28 +438,28 @@ class OC_FilesystemView { ); } } - if($run) { - $mp1=$this->getMountPoint($path1.$postFix1); - $mp2=$this->getMountPoint($path2.$postFix2); - if($mp1 == $mp2) { - if($storage = $this->getStorage($path1.$postFix1)) { - $result=$storage->copy($this->getInternalPath($path1.$postFix1), $this->getInternalPath($path2.$postFix2)); + if ($run) { + $mp1 = $this->getMountPoint($path1 . $postFix1); + $mp2 = $this->getMountPoint($path2 . $postFix2); + if ($mp1 == $mp2) { + if ($storage = $this->getStorage($path1 . $postFix1)) { + $result = $storage->copy($this->getInternalPath($path1 . $postFix1), $this->getInternalPath($path2 . $postFix2)); } } else { - $source = $this->fopen($path1.$postFix1, 'r'); - $target = $this->fopen($path2.$postFix2, 'w'); + $source = $this->fopen($path1 . $postFix1, 'r'); + $target = $this->fopen($path2 . $postFix2, 'w'); $result = OC_Helper::streamCopy($source, $target); } - if( $this->fakeRoot==OC_Filesystem::getRoot() ){ + if ($this->fakeRoot == OC_Filesystem::getRoot()) { OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_copy, array( OC_Filesystem::signal_param_oldpath => $path1, - OC_Filesystem::signal_param_newpath=>$path2 + OC_Filesystem::signal_param_newpath => $path2 ) ); - if(!$exists) { + if (!$exists) { OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_create, @@ -449,7 +469,7 @@ class OC_FilesystemView { OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_post_write, - array( OC_Filesystem::signal_param_path => $path2) + 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); @@ -459,12 +479,13 @@ class OC_FilesystemView { } } } + public function fopen($path, $mode) { - $hooks=array(); - switch($mode) { + $hooks = array(); + switch ($mode) { case 'r': case 'rb': - $hooks[]='read'; + $hooks[] = 'read'; break; case 'r+': case 'rb+': @@ -474,8 +495,8 @@ class OC_FilesystemView { case 'xb+': case 'a+': case 'ab+': - $hooks[]='read'; - $hooks[]='write'; + $hooks[] = 'read'; + $hooks[] = 'write'; break; case 'w': case 'wb': @@ -483,22 +504,23 @@ class OC_FilesystemView { case 'xb': case 'a': case 'ab': - $hooks[]='write'; + $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); } + public function toTmpFile($path) { - if(OC_Filesystem::isValidPath($path)) { + if (OC_Filesystem::isValidPath($path)) { $source = $this->fopen($path, 'r'); - if($source) { - $extension=''; - $extOffset=strpos($path, '.'); - if($extOffset !== false) { - $extension=substr($path, strrpos($path,'.')); + if ($source) { + $extension = ''; + $extOffset = strpos($path, '.'); + if ($extOffset !== false) { + $extension = substr($path, strrpos($path, '.')); } $tmpFile = OC_Helper::tmpFile($extension); file_put_contents($tmpFile, $source); @@ -506,13 +528,14 @@ class OC_FilesystemView { } } } + public function fromTmpFile($tmpFile, $path) { - if(OC_Filesystem::isValidPath($path)) { - if(!$tmpFile) { + if (OC_Filesystem::isValidPath($path)) { + if (!$tmpFile) { debug_print_backtrace(); } - $source=fopen($tmpFile, 'r'); - if($source) { + $source = fopen($tmpFile, 'r'); + if ($source) { $this->file_put_contents($path, $source); unlink($tmpFile); return true; @@ -526,8 +549,9 @@ class OC_FilesystemView { public function getMimeType($path) { 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); @@ -538,11 +562,11 @@ class OC_FilesystemView { OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_read, - array( OC_Filesystem::signal_param_path => $path) + array(OC_Filesystem::signal_param_path => $path) ); } - if ($storage = $this->getStorage($path.$postFix)) { - $result = $storage->hash($type, $this->getInternalPath($path.$postFix), $raw); + if ($storage = $this->getStorage($path . $postFix)) { + $result = $storage->hash($type, $this->getInternalPath($path . $postFix), $raw); $result = OC_FileProxy::runPostProxies('hash', $absolutePath, $result); return $result; } @@ -550,7 +574,7 @@ class OC_FilesystemView { return null; } - public function free_space($path='/') { + public function free_space($path = '/') { return $this->basicOperation('free_space', $path); } @@ -566,26 +590,26 @@ class OC_FilesystemView { * files), processes hooks and proxies, sanitises paths, and finally passes them on to * \OC\Files\Storage\Storage for delegation to a storage backend for execution */ - private function basicOperation($operation, $path, $hooks=array(), $extraParam=null) { - $postFix=(substr($path,-1,1)==='/')?'/':''; + private function basicOperation($operation, $path, $hooks = array(), $extraParam = null) { + $postFix = (substr($path, -1, 1) === '/') ? '/' : ''; $absolutePath = OC_Filesystem::normalizePath($this->getAbsolutePath($path)); - if(OC_FileProxy::runPreProxies($operation, $absolutePath, $extraParam) and OC_Filesystem::isValidPath($path)) { + if (OC_FileProxy::runPreProxies($operation, $absolutePath, $extraParam) and OC_Filesystem::isValidPath($path)) { $path = $this->getRelativePath($absolutePath); - if($path == null) { + if ($path == null) { return false; } - $internalPath = $this->getInternalPath($path.$postFix); - $run=$this->runHooks($hooks,$path); - if($run and $storage = $this->getStorage($path.$postFix)) { - if(!is_null($extraParam)) { + $internalPath = $this->getInternalPath($path . $postFix); + $run = $this->runHooks($hooks, $path); + if ($run and $storage = $this->getStorage($path . $postFix)) { + if (!is_null($extraParam)) { $result = $storage->$operation($internalPath, $extraParam); } else { $result = $storage->$operation($internalPath); } $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); + 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); } } return $result; @@ -594,24 +618,24 @@ class OC_FilesystemView { return null; } - private function runHooks($hooks,$path,$post=false) { - $prefix=($post)?'post_':''; - $run=true; - if(OC_Filesystem::$loaded and $this->fakeRoot==OC_Filesystem::getRoot()) { - foreach($hooks as $hook) { - if($hook!='read') { + private function runHooks($hooks, $path, $post = false) { + $prefix = ($post) ? 'post_' : ''; + $run = true; + if (OC_Filesystem::$loaded and $this->fakeRoot == OC_Filesystem::getRoot()) { + foreach ($hooks as $hook) { + if ($hook != 'read') { OC_Hook::emit( OC_Filesystem::CLASSNAME, - $prefix.$hook, + $prefix . $hook, array( OC_Filesystem::signal_param_run => &$run, OC_Filesystem::signal_param_path => $path ) ); - } elseif(!$post) { + } elseif (!$post) { OC_Hook::emit( OC_Filesystem::CLASSNAME, - $prefix.$hook, + $prefix . $hook, array( OC_Filesystem::signal_param_path => $path ) @@ -624,6 +648,7 @@ class OC_FilesystemView { /** * check if a file or folder has been updated since $time + * * @param int $time * @return bool */ diff --git a/lib/filesystem.php b/lib/filesystem.php index b73b52d420..b1200f95bf 100644 --- a/lib/filesystem.php +++ b/lib/filesystem.php @@ -22,566 +22,4 @@ */ -/** - * 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 permission related stuff - * - * Hooks provided: - * read(path) - * write(path, &run) - * post_write(path) - * create(path, &run) (when a file is created, both create and write will be emited in that order) - * 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) - * - * the &run parameter can be set to false to prevent the operation from occuring - */ -class OC_Filesystem{ - static private $storages=array(); - static private $mounts=array(); - public static $loaded=false; - /** - * @var \OC\Files\Storage\Storage $defaultInstance - */ - static private $defaultInstance; - - - /** - * classname which used for hooks handling - * used as signalclass in OC_Hooks::emit() - */ - const CLASSNAME = 'OC_Filesystem'; - - /** - * signalname emited before file renaming - * @param oldpath - * @param newpath - */ - const signal_rename = 'rename'; - - /** - * signal emited after file renaming - * @param oldpath - * @param newpath - */ - const signal_post_rename = 'post_rename'; - - /** - * signal emited before file/dir creation - * @param path - * @param run changing this flag to false in hook handler will cancel event - */ - const signal_create = 'create'; - - /** - * signal emited after file/dir creation - * @param path - * @param run changing this flag to false in hook handler will cancel event - */ - const signal_post_create = 'post_create'; - - /** - * signal emits before file/dir copy - * @param oldpath - * @param newpath - * @param run changing this flag to false in hook handler will cancel event - */ - const signal_copy = 'copy'; - - /** - * signal emits after file/dir copy - * @param oldpath - * @param newpath - */ - const signal_post_copy = 'post_copy'; - - /** - * signal emits before file/dir save - * @param path - * @param run changing this flag to false in hook handler will cancel event - */ - const signal_write = 'write'; - - /** - * signal emits after file/dir save - * @param path - */ - const signal_post_write = 'post_write'; - - /** - * signal emits when reading file/dir - * @param path - */ - const signal_read = 'read'; - - /** - * signal emits when removing file/dir - * @param path - */ - const signal_delete = 'delete'; - - /** - * parameters definitions for signals - */ - const signal_param_path = 'path'; - const signal_param_oldpath = 'oldpath'; - const signal_param_newpath = 'newpath'; - - /** - * run - changing this flag to false in hook handler will cancel event - */ - const signal_param_run = 'run'; - - /** - * get the mountpoint of the storage object for a path - ( note: because a storage is not always mounted inside the fakeroot, the returned mountpoint is relative to the absolute root of the filesystem and doesn't take the chroot into account - * - * @param string path - * @return string - */ - static public function getMountPoint($path) { - OC_Hook::emit(self::CLASSNAME,'get_mountpoint',array('path'=>$path)); - if(!$path) { - $path='/'; - } - if($path[0]!=='/') { - $path='/'.$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)) { - $foundMountPoint=$mountpoint; - } - } - return $foundMountPoint; - } - - /** - * get the part of the path relative to the mountpoint of the storage it's stored in - * @param string path - * @return bool - */ - static public function getInternalPath($path) { - $mountPoint=self::getMountPoint($path); - $internalPath=substr($path,strlen($mountPoint)); - return $internalPath; - } - /** - * get the storage object for a path - * @param string path - * @return \OC\Files\Storage\Storage - */ - static public function getStorage($path) { - $mountpoint=self::getMountPoint($path); - if($mountpoint) { - if(!isset(OC_Filesystem::$storages[$mountpoint])) { - $mount=OC_Filesystem::$mounts[$mountpoint]; - OC_Filesystem::$storages[$mountpoint]=OC_Filesystem::createStorage($mount['class'],$mount['arguments']); - } - return OC_Filesystem::$storages[$mountpoint]; - } - } - - /** - * resolve a path to a storage and internal path - * @param string $path - * @return array consisting of the storage and the internal path - */ - static public function resolvePath($path){ - $mountpoint=self::getMountPoint($path); - if($mountpoint) { - if(!isset(OC_Filesystem::$storages[$mountpoint])) { - $mount=OC_Filesystem::$mounts[$mountpoint]; - OC_Filesystem::$storages[$mountpoint]=OC_Filesystem::createStorage($mount['class'],$mount['arguments']); - } - $storage = OC_Filesystem::$storages[$mountpoint]; - $internalPath=substr($path,strlen($mountpoint)); - return array($storage, $internalPath); - } - } - - static public function init($root) { - if(self::$defaultInstance) { - return false; - } - self::$defaultInstance=new OC_FilesystemView($root); - - //load custom mount config - 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(OC_User::getUser(),$group)) { - foreach($mounts as $mountPoint=>$options) { - $mountPoint=self::setUserVars($mountPoint); - foreach($options as &$option) { - $option=self::setUserVars($option); - } - self::mount($options['class'],$options['options'],$mountPoint); - } - } - } - } - - if(isset($mountConfig['user'])) { - foreach($mountConfig['user'] as $user=>$mounts) { - if($user==='all' or strtolower($user)===strtolower(OC_User::getUser())) { - foreach($mounts as $mountPoint=>$options) { - $mountPoint=self::setUserVars($mountPoint); - foreach($options as &$option) { - $option=self::setUserVars($option); - } - self::mount($options['class'],$options['options'],$mountPoint); - } - } - } - } - } - - self::$loaded=true; - } - - /** - * fill in the correct values for $user, and $password placeholders - * @param string intput - * @return string - */ - private static function setUserVars($input) { - return str_replace('$user',OC_User::getUser(),$input); - } - - /** - * get the default filesystem view - * @return OC_FilesystemView - */ - static public function getView() { - return self::$defaultInstance; - } - - /** - * tear down the filesystem, removing all storage providers - */ - static public function tearDown() { - self::$storages=array(); - } - - /** - * create a new storage of a specific type - * @param string type - * @param array arguments - * @return \OC\Files\Storage\Storage - */ - static private function createStorage($class,$arguments) { - if(class_exists($class)) { - try { - return new $class($arguments); - } catch (Exception $exception) { - OC_Log::write('core', $exception->getMessage(), OC_Log::ERROR); - return false; - } - }else{ - OC_Log::write('core','storage backend '.$class.' not found',OC_Log::ERROR); - return false; - } - } - - /** - * change the root to a fake root - * @param string fakeRoot - * @return bool - */ - static public function chroot($fakeRoot) { - return self::$defaultInstance->chroot($fakeRoot); - } - - /** - * @brief get the relative path of the root data directory for the current user - * @return string - * - * Returns path like /admin/files - */ - static public function getRoot() { - return self::$defaultInstance->getRoot(); - } - - /** - * clear all mounts and storage backends - */ - public static function clearMounts() { - self::$mounts=array(); - self::$storages=array(); - } - - /** - * mount an \OC\Files\Storage\Storage in our virtual filesystem - * @param \OC\Files\Storage\Storage storage - * @param string mountpoint - */ - static public function mount($class,$arguments,$mountpoint) { - if($mountpoint[0]!='/') { - $mountpoint='/'.$mountpoint; - } - if(substr($mountpoint,-1)!=='/') { - $mountpoint=$mountpoint.'/'; - } - self::$mounts[$mountpoint]=array('class'=>$class,'arguments'=>$arguments); - } - - /** - * return the path to a local version of the file - * we need this because we can't know if a file is stored local or not from outside the filestorage and for some purposes a local file is needed - * @param string path - * @return string - */ - static public function getLocalFile($path) { - return self::$defaultInstance->getLocalFile($path); - } - /** - * @param string path - * @return string - */ - static public function getLocalFolder($path) { - return self::$defaultInstance->getLocalFolder($path); - } - - /** - * return path to file which reflects one visible in browser - * @param string path - * @return string - */ - static public function getLocalPath($path) { - $datadir = OC_User::getHome(OC_User::getUser()).'/files'; - $newpath = $path; - if (strncmp($newpath, $datadir, strlen($datadir)) == 0) { - $newpath = substr($path, strlen($datadir)); - } - return $newpath; - } - - /** - * check if the requested path is valid - * @param string path - * @return bool - */ - static public function isValidPath($path) { - if(!$path || $path[0]!=='/') { - $path='/'.$path; - } - if(strstr($path,'/../') || strrchr($path, '/') === '/..' ) { - return false; - } - return true; - } - - /** - * checks if a file is blacklisted for storage in the filesystem - * Listens to write and rename hooks - * @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; - } - } - } - - /** - * following functions are equivalent to their php builtin equivalents for arguments/return values. - */ - static public function mkdir($path) { - return self::$defaultInstance->mkdir($path); - } - static public function rmdir($path) { - return self::$defaultInstance->rmdir($path); - } - 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); - } - static public function is_file($path) { - return self::$defaultInstance->is_file($path); - } - static public function stat($path) { - return self::$defaultInstance->stat($path); - } - static public function filetype($path) { - return self::$defaultInstance->filetype($path); - } - static public function filesize($path) { - return self::$defaultInstance->filesize($path); - } - static public function readfile($path) { - return self::$defaultInstance->readfile($path); - } - /** - * @deprecated Replaced by isReadable() as part of CRUDS - */ - static public function is_readable($path) { - return self::$defaultInstance->is_readable($path); - } - /** - * @deprecated Replaced by isCreatable(), isUpdatable(), isDeletable() as part of CRUDS - */ - static public function is_writable($path) { - return self::$defaultInstance->is_writable($path); - } - static public function isCreatable($path) { - return self::$defaultInstance->isCreatable($path); - } - static public function isReadable($path) { - return self::$defaultInstance->isReadable($path); - } - static public function isUpdatable($path) { - return self::$defaultInstance->isUpdatable($path); - } - static public function isDeletable($path) { - return self::$defaultInstance->isDeletable($path); - } - static public function isSharable($path) { - return self::$defaultInstance->isSharable($path); - } - static public function file_exists($path) { - return self::$defaultInstance->file_exists($path); - } - static public function filectime($path) { - return self::$defaultInstance->filectime($path); - } - static public function filemtime($path) { - return self::$defaultInstance->filemtime($path); - } - static public function touch($path, $mtime=null) { - return self::$defaultInstance->touch($path, $mtime); - } - 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 unlink($path) { - return self::$defaultInstance->unlink($path); - } - 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 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 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 free_space($path='/') { - return self::$defaultInstance->free_space($path); - } - - 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,$time); - } - - static public function removeETagHook($params, $root = false) { - if (isset($params['path'])) { - $path=$params['path']; - } else { - $path=$params['oldpath']; - } - - if ($root) { // reduce path to the required part of it (no 'username/files') - $fakeRootView = new OC_FilesystemView($root); - $count = 1; - $path=str_replace(OC_App::getStorage("files")->getAbsolutePath($path), "", $fakeRootView->getAbsolutePath($path), $count); - } - - $path = self::normalizePath($path); - OC_Connector_Sabre_Node::removeETagPropertyForPath($path); - } - - /** - * normalize a path - * @param string path - * @param bool $stripTrailingSlash - * @return string - */ - public static function normalizePath($path,$stripTrailingSlash=true) { - if($path=='') { - return '/'; - } - //no windows style slashes - $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); - } - //remove duplicate slashes - while(strpos($path,'//')!==false) { - $path=str_replace('//','/',$path); - } - //normalize unicode if possible - if(class_exists('Normalizer')) { - $path=Normalizer::normalize($path); - } - 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_Util::setupFS(); From 07c53841899262fdd34304302ffaaf2704800c38 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 10 Oct 2012 12:25:46 +0200 Subject: [PATCH 029/347] fix namespaces in filesystem and filesystemview --- lib/app.php | 6 +- lib/files/filesystem.php | 153 ++++++++++++----------- lib/files/view.php | 260 +++++++++++++++++++++------------------ 3 files changed, 225 insertions(+), 194 deletions(-) diff --git a/lib/app.php b/lib/app.php index 395230156f..4d7353e99d 100755 --- a/lib/app.php +++ b/lib/app.php @@ -714,16 +714,16 @@ class OC_App{ /** * @param string $appid - * @return OC_FilesystemView + * @return \OC\Files\View */ public static function getStorage($appid) { if(OC_App::isEnabled($appid)) {//sanity check if(OC_User::isLoggedIn()) { - $view = new OC_FilesystemView('/'.OC_User::getUser()); + $view = new \OC\Files\View('/'.OC_User::getUser()); if(!$view->file_exists($appid)) { $view->mkdir($appid); } - return new OC_FilesystemView('/'.OC_User::getUser().'/'.$appid); + return new \OC\Files\View('/'.OC_User::getUser().'/'.$appid); }else{ OC_Log::write('core', 'Can\'t get app storage, app, user not logged in', OC_Log::ERROR); return false; diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php index d0a96b59a0..f23f3a79e9 100644 --- a/lib/files/filesystem.php +++ b/lib/files/filesystem.php @@ -15,16 +15,16 @@ * read(path) * write(path, &run) * post_write(path) - * create(path, &run) (when a file is created, both create and write will be emited in that order) + * create(path, &run) (when a file is created, both create and write will be emitted in that order) * 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) + * copy(oldpath,newpath, &run) (if the newpath doesn't exists yes, copy, create and write will be emitted in that order) * post_rename(oldpath,newpath) * - * the &run parameter can be set to false to prevent the operation from occuring + * the &run parameter can be set to false to prevent the operation from occurring */ namespace OC\Files; @@ -34,7 +34,7 @@ class Filesystem { static private $mounts = array(); public static $loaded = false; /** - * @var \OC\Files\Storage\Storage $defaultInstance + * @var \OC\Files\View $defaultInstance */ static private $defaultInstance; @@ -46,80 +46,80 @@ class Filesystem { const CLASSNAME = 'OC_Filesystem'; /** - * signalname emited before file renaming + * signalname emitted before file renaming * - * @param oldpath - * @param newpath + * @param string $oldpath + * @param string $newpath */ const signal_rename = 'rename'; /** - * signal emited after file renaming + * signal emitted after file renaming * - * @param oldpath - * @param newpath + * @param string $oldpath + * @param string $newpath */ const signal_post_rename = 'post_rename'; /** - * signal emited before file/dir creation + * signal emitted before file/dir creation * - * @param path - * @param run changing this flag to false in hook handler will cancel event + * @param string $path + * @param bool $run changing this flag to false in hook handler will cancel event */ const signal_create = 'create'; /** - * signal emited after file/dir creation + * signal emitted after file/dir creation * - * @param path - * @param run changing this flag to false in hook handler will cancel event + * @param string $path + * @param bool $run changing this flag to false in hook handler will cancel event */ const signal_post_create = 'post_create'; /** * signal emits before file/dir copy * - * @param oldpath - * @param newpath - * @param run changing this flag to false in hook handler will cancel event + * @param string $oldpath + * @param string $newpath + * @param bool $run changing this flag to false in hook handler will cancel event */ const signal_copy = 'copy'; /** * signal emits after file/dir copy * - * @param oldpath - * @param newpath + * @param string $oldpath + * @param string $newpath */ const signal_post_copy = 'post_copy'; /** * signal emits before file/dir save * - * @param path - * @param run changing this flag to false in hook handler will cancel event + * @param string $path + * @param bool $run changing this flag to false in hook handler will cancel event */ const signal_write = 'write'; /** * signal emits after file/dir save * - * @param path + * @param string $path */ const signal_post_write = 'post_write'; /** * signal emits when reading file/dir * - * @param path + * @param string $path */ const signal_read = 'read'; /** * signal emits when removing file/dir * - * @param path + * @param string $path */ const signal_delete = 'delete'; @@ -139,11 +139,11 @@ class Filesystem { * get the mountpoint of the storage object for a path ( note: because a storage is not always mounted inside the fakeroot, the returned mountpoint is relative to the absolute root of the filesystem and doesn't take the chroot into account * - * @param string path + * @param string $path * @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 = '/'; } @@ -152,7 +152,7 @@ class Filesystem { } $path = str_replace('//', '/', $path); $foundMountPoint = ''; - $mountPoints = array_keys(OC_Filesystem::$mounts); + $mountPoints = array_keys(self::$mounts); foreach ($mountPoints as $mountpoint) { if ($mountpoint == $path) { return $mountpoint; @@ -167,7 +167,7 @@ class Filesystem { /** * get the part of the path relative to the mountpoint of the storage it's stored in * - * @param string path + * @param string $path * @return bool */ static public function getInternalPath($path) { @@ -179,17 +179,19 @@ class Filesystem { /** * get the storage object for a path * - * @param string path + * @param string $path * @return \OC\Files\Storage\Storage */ static public function getStorage($path) { $mountpoint = self::getMountPoint($path); if ($mountpoint) { - if (!isset(OC_Filesystem::$storages[$mountpoint])) { - $mount = OC_Filesystem::$mounts[$mountpoint]; - OC_Filesystem::$storages[$mountpoint] = OC_Filesystem::createStorage($mount['class'], $mount['arguments']); + if (!isset(self::$storages[$mountpoint])) { + $mount = self::$mounts[$mountpoint]; + self::$storages[$mountpoint] = self::createStorage($mount['class'], $mount['arguments']); } - return OC_Filesystem::$storages[$mountpoint]; + return self::$storages[$mountpoint]; + }else{ + return null; } } @@ -202,13 +204,15 @@ class Filesystem { static public function resolvePath($path) { $mountpoint = self::getMountPoint($path); if ($mountpoint) { - if (!isset(OC_Filesystem::$storages[$mountpoint])) { - $mount = OC_Filesystem::$mounts[$mountpoint]; - OC_Filesystem::$storages[$mountpoint] = OC_Filesystem::createStorage($mount['class'], $mount['arguments']); + if (!isset(self::$storages[$mountpoint])) { + $mount = self::$mounts[$mountpoint]; + self::$storages[$mountpoint] = self::createStorage($mount['class'], $mount['arguments']); } - $storage = OC_Filesystem::$storages[$mountpoint]; + $storage = self::$storages[$mountpoint]; $internalPath = substr($path, strlen($mountpoint)); return array($storage, $internalPath); + }else{ + return array(null, null); } } @@ -216,11 +220,11 @@ class Filesystem { if (self::$defaultInstance) { return false; } - self::$defaultInstance = new OC_FilesystemView($root); + self::$defaultInstance = new View($root); -//load custom mount config - if (is_file(OC::$SERVERROOT . '/config/mount.php')) { - $mountConfig = include(OC::$SERVERROOT . '/config/mount.php'); + //load custom mount config + if (is_file(\OC::$SERVERROOT . '/config/mount.php')) { + $mountConfig = include 'config/mount.php'; if (isset($mountConfig['global'])) { foreach ($mountConfig['global'] as $mountPoint => $options) { self::mount($options['class'], $options['options'], $mountPoint); @@ -229,7 +233,7 @@ class Filesystem { if (isset($mountConfig['group'])) { foreach ($mountConfig['group'] as $group => $mounts) { - if (OC_Group::inGroup(OC_User::getUser(), $group)) { + if (\OC_Group::inGroup(\OC_User::getUser(), $group)) { foreach ($mounts as $mountPoint => $options) { $mountPoint = self::setUserVars($mountPoint); foreach ($options as &$option) { @@ -243,7 +247,7 @@ class Filesystem { if (isset($mountConfig['user'])) { foreach ($mountConfig['user'] as $user => $mounts) { - if ($user === 'all' or strtolower($user) === strtolower(OC_User::getUser())) { + if ($user === 'all' or strtolower($user) === strtolower(\OC_User::getUser())) { foreach ($mounts as $mountPoint => $options) { $mountPoint = self::setUserVars($mountPoint); foreach ($options as &$option) { @@ -257,22 +261,24 @@ class Filesystem { } self::$loaded = true; + + return true; } /** * fill in the correct values for $user, and $password placeholders * - * @param string intput + * @param string $input * @return string */ private static function setUserVars($input) { - return str_replace('$user', OC_User::getUser(), $input); + return str_replace('$user', \OC_User::getUser(), $input); } /** * get the default filesystem view * - * @return OC_FilesystemView + * @return View */ static public function getView() { return self::$defaultInstance; @@ -288,20 +294,20 @@ class Filesystem { /** * create a new storage of a specific type * - * @param string type - * @param array arguments + * @param string $type + * @param array $arguments * @return \OC\Files\Storage\Storage */ static private function createStorage($class, $arguments) { if (class_exists($class)) { try { return new $class($arguments); - } catch (Exception $exception) { - OC_Log::write('core', $exception->getMessage(), OC_Log::ERROR); + } catch (\Exception $exception) { + \OC_Log::write('core', $exception->getMessage(), \OC_Log::ERROR); 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; } } @@ -309,7 +315,7 @@ class Filesystem { /** * change the root to a fake root * - * @param string fakeRoot + * @param string $fakeRoot * @return bool */ static public function chroot($fakeRoot) { @@ -337,8 +343,9 @@ class Filesystem { /** * mount an \OC\Files\Storage\Storage in our virtual filesystem * - * @param \OC\Files\Storage\Storage storage - * @param string mountpoint + * @param \OC\Files\Storage\Storage $storage + * @param array $arguments + * @param string $mountpoint */ static public function mount($class, $arguments, $mountpoint) { if ($mountpoint[0] != '/') { @@ -354,7 +361,7 @@ class Filesystem { * return the path to a local version of the file * we need this because we can't know if a file is stored local or not from outside the filestorage and for some purposes a local file is needed * - * @param string path + * @param string $path * @return string */ static public function getLocalFile($path) { @@ -362,7 +369,7 @@ class Filesystem { } /** - * @param string path + * @param string $path * @return string */ static public function getLocalFolder($path) { @@ -372,11 +379,11 @@ class Filesystem { /** * return path to file which reflects one visible in browser * - * @param string path + * @param string $path * @return string */ static public function getLocalPath($path) { - $datadir = OC_User::getHome(OC_User::getUser()) . '/files'; + $datadir = \OC_User::getHome(\OC_User::getUser()) . '/files'; $newpath = $path; if (strncmp($newpath, $datadir, strlen($datadir)) == 0) { $newpath = substr($path, strlen($datadir)); @@ -387,7 +394,7 @@ class Filesystem { /** * check if the requested path is valid * - * @param string path + * @param string $path * @return bool */ static public function isValidPath($path) { @@ -468,7 +475,7 @@ class Filesystem { * @deprecated Replaced by isReadable() as part of CRUDS */ static public function is_readable($path) { - return self::$defaultInstance->is_readable($path); + return self::$defaultInstance->isReadable($path); } /** @@ -559,7 +566,7 @@ class Filesystem { } static public function search($query) { - return OC_FileCache::search($query); + return Cache\Cache::search($query); } /** @@ -580,19 +587,19 @@ class Filesystem { } if ($root) { // reduce path to the required part of it (no 'username/files') - $fakeRootView = new OC_FilesystemView($root); + $fakeRootView = new View($root); $count = 1; - $path = str_replace(OC_App::getStorage("files")->getAbsolutePath($path), "", $fakeRootView->getAbsolutePath($path), $count); + $path = str_replace(\OC_App::getStorage("files")->getAbsolutePath($path), "", $fakeRootView->getAbsolutePath($path), $count); } $path = self::normalizePath($path); - OC_Connector_Sabre_Node::removeETagPropertyForPath($path); + \OC_Connector_Sabre_Node::removeETagPropertyForPath($path); } /** * normalize a path * - * @param string path + * @param string $path * @param bool $stripTrailingSlash * @return string */ @@ -606,7 +613,7 @@ class Filesystem { if ($path[0] !== '/') { $path = '/' . $path; } -//remove trainling slash +//remove trailing slash if ($stripTrailingSlash and strlen($path) > 1 and substr($path, -1, 1) === '/') { $path = substr($path, 0, -1); } @@ -616,14 +623,14 @@ class Filesystem { } //normalize unicode if possible if (class_exists('Normalizer')) { - $path = Normalizer::normalize($path); + $path = \Normalizer::normalize($path); } 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(); +\OC_Util::setupFS(); diff --git a/lib/files/view.php b/lib/files/view.php index 8c3f288f44..230455479c 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -45,9 +45,9 @@ class View { } /** - * change the root to a fake toor + * change the root to a fake root * - * @param string fakeRoot + * @param string $fakeRoot * @return bool */ public function chroot($fakeRoot) { @@ -71,12 +71,12 @@ class View { /** * get the part of the path relative to the mountpoint of the storage it's stored in * - * @param string path + * @param string $path * @return bool */ public function getInternalPath($path) { if (!isset($this->internal_path_cache[$path])) { - $this->internal_path_cache[$path] = OC_Filesystem::getInternalPath($this->getAbsolutePath($path)); + $this->internal_path_cache[$path] = Filesystem::getInternalPath($this->getAbsolutePath($path)); } return $this->internal_path_cache[$path]; } @@ -84,7 +84,7 @@ class View { /** * get path relative to the root of the view * - * @param string path + * @param string $path * @return string */ public function getRelativePath($path) { @@ -106,12 +106,12 @@ class View { /** * get the storage object for a path * - * @param string path + * @param string $path * @return \OC\Files\Storage\Storage */ public function getStorage($path) { if (!isset($this->storage_cache[$path])) { - $this->storage_cache[$path] = OC_Filesystem::getStorage($this->getAbsolutePath($path)); + $this->storage_cache[$path] = Filesystem::getStorage($this->getAbsolutePath($path)); } return $this->storage_cache[$path]; } @@ -120,35 +120,39 @@ class View { * get the mountpoint of the storage object for a path ( note: because a storage is not always mounted inside the fakeroot, the returned mountpoint is relative to the absolute root of the filesystem and doesn't take the chroot into account * - * @param string path + * @param string $path * @return string */ public function getMountPoint($path) { - return OC_Filesystem::getMountPoint($this->getAbsolutePath($path)); + return Filesystem::getMountPoint($this->getAbsolutePath($path)); } /** * return the path to a local version of the file * we need this because we can't know if a file is stored local or not from outside the filestorage and for some purposes a local file is needed * - * @param string path + * @param string $path * @return string */ public function getLocalFile($path) { $parent = substr($path, 0, strrpos($path, '/')); - if (OC_Filesystem::isValidPath($parent) and $storage = $this->getStorage($path)) { + if (Filesystem::isValidPath($parent) and $storage = $this->getStorage($path)) { return $storage->getLocalFile($this->getInternalPath($path)); + } else { + return null; } } /** - * @param string path + * @param string $path * @return string */ public function getLocalFolder($path) { $parent = substr($path, 0, strrpos($path, '/')); - if (OC_Filesystem::isValidPath($parent) and $storage = $this->getStorage($path)) { + if (Filesystem::isValidPath($parent) and $storage = $this->getStorage($path)) { return $storage->getLocalFolder($this->getInternalPath($path)); + } else { + return null; } } @@ -274,28 +278,28 @@ class View { public function file_put_contents($path, $data) { if (is_resource($data)) { //not having to deal with streams in file_put_contents makes life easier - $absolutePath = OC_Filesystem::normalizePath($this->getAbsolutePath($path)); - if (OC_FileProxy::runPreProxies('file_put_contents', $absolutePath, $data) && OC_Filesystem::isValidPath($path)) { + $absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path)); + if (\OC_FileProxy::runPreProxies('file_put_contents', $absolutePath, $data) && Filesystem::isValidPath($path)) { $path = $this->getRelativePath($absolutePath); $exists = $this->file_exists($path); $run = true; - if ($this->fakeRoot == OC_Filesystem::getRoot()) { + if ($this->fakeRoot == Filesystem::getRoot()) { if (!$exists) { - OC_Hook::emit( - OC_Filesystem::CLASSNAME, - OC_Filesystem::signal_create, + \OC_Hook::emit( + Filesystem::CLASSNAME, + Filesystem::signal_create, array( - OC_Filesystem::signal_param_path => $path, - OC_Filesystem::signal_param_run => &$run + Filesystem::signal_param_path => $path, + Filesystem::signal_param_run => &$run ) ); } - OC_Hook::emit( - OC_Filesystem::CLASSNAME, - OC_Filesystem::signal_write, + \OC_Hook::emit( + Filesystem::CLASSNAME, + Filesystem::signal_write, array( - OC_Filesystem::signal_param_path => $path, - OC_Filesystem::signal_param_run => &$run + Filesystem::signal_param_path => $path, + Filesystem::signal_param_run => &$run ) ); } @@ -304,28 +308,30 @@ class View { } $target = $this->fopen($path, 'w'); if ($target) { - $count = OC_Helper::streamCopy($data, $target); + $count = \OC_Helper::streamCopy($data, $target); fclose($target); fclose($data); - if ($this->fakeRoot == OC_Filesystem::getRoot()) { + if ($this->fakeRoot == Filesystem::getRoot()) { if (!$exists) { - OC_Hook::emit( - OC_Filesystem::CLASSNAME, - OC_Filesystem::signal_post_create, - array(OC_Filesystem::signal_param_path => $path) + \OC_Hook::emit( + Filesystem::CLASSNAME, + Filesystem::signal_post_create, + array(Filesystem::signal_param_path => $path) ); } - OC_Hook::emit( - OC_Filesystem::CLASSNAME, - OC_Filesystem::signal_post_write, - array(OC_Filesystem::signal_param_path => $path) + \OC_Hook::emit( + Filesystem::CLASSNAME, + Filesystem::signal_post_write, + array(Filesystem::signal_param_path => $path) ); } - OC_FileProxy::runPostProxies('file_put_contents', $absolutePath, $count); + \OC_FileProxy::runPostProxies('file_put_contents', $absolutePath, $count); return $count > 0; } else { return false; } + } else { + return false; } } else { return $this->basicOperation('file_put_contents', $path, array('create', 'write'), $data); @@ -343,9 +349,9 @@ class View { public function rename($path1, $path2) { $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)) { + $absolutePath1 = Filesystem::normalizePath($this->getAbsolutePath($path1)); + $absolutePath2 = Filesystem::normalizePath($this->getAbsolutePath($path2)); + if (\OC_FileProxy::runPreProxies('rename', $absolutePath1, $absolutePath2) and Filesystem::isValidPath($path2)) { $path1 = $this->getRelativePath($absolutePath1); $path2 = $this->getRelativePath($absolutePath2); @@ -353,13 +359,13 @@ class View { return false; } $run = true; - if ($this->fakeRoot == OC_Filesystem::getRoot()) { - OC_Hook::emit( - OC_Filesystem::CLASSNAME, OC_Filesystem::signal_rename, + if ($this->fakeRoot == Filesystem::getRoot()) { + \OC_Hook::emit( + Filesystem::CLASSNAME, Filesystem::signal_rename, array( - OC_Filesystem::signal_param_oldpath => $path1, - OC_Filesystem::signal_param_newpath => $path2, - OC_Filesystem::signal_param_run => &$run + Filesystem::signal_param_oldpath => $path1, + Filesystem::signal_param_newpath => $path2, + Filesystem::signal_param_run => &$run ) ); } @@ -369,36 +375,42 @@ class View { if ($mp1 == $mp2) { if ($storage = $this->getStorage($path1)) { $result = $storage->rename($this->getInternalPath($path1 . $postFix1), $this->getInternalPath($path2 . $postFix2)); + } else { + $result = false; } } else { $source = $this->fopen($path1 . $postFix1, 'r'); $target = $this->fopen($path2 . $postFix2, 'w'); - $count = OC_Helper::streamCopy($source, $target); + $count = \OC_Helper::streamCopy($source, $target); $storage1 = $this->getStorage($path1); $storage1->unlink($this->getInternalPath($path1 . $postFix1)); $result = $count > 0; } - if ($this->fakeRoot == OC_Filesystem::getRoot()) { - OC_Hook::emit( - OC_Filesystem::CLASSNAME, - OC_Filesystem::signal_post_rename, + if ($this->fakeRoot == Filesystem::getRoot()) { + \OC_Hook::emit( + Filesystem::CLASSNAME, + Filesystem::signal_post_rename, array( - OC_Filesystem::signal_param_oldpath => $path1, - OC_Filesystem::signal_param_newpath => $path2 + Filesystem::signal_param_oldpath => $path1, + Filesystem::signal_param_newpath => $path2 ) ); } return $result; + } else { + return false; } + } else { + return false; } } public function copy($path1, $path2) { $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)) { + $absolutePath1 = Filesystem::normalizePath($this->getAbsolutePath($path1)); + $absolutePath2 = Filesystem::normalizePath($this->getAbsolutePath($path2)); + if (\OC_FileProxy::runPreProxies('copy', $absolutePath1, $absolutePath2) and Filesystem::isValidPath($path2)) { $path1 = $this->getRelativePath($absolutePath1); $path2 = $this->getRelativePath($absolutePath2); @@ -406,34 +418,34 @@ class View { return false; } $run = true; - if ($this->fakeRoot == OC_Filesystem::getRoot()) { - OC_Hook::emit( - OC_Filesystem::CLASSNAME, - OC_Filesystem::signal_copy, + $exists = $this->file_exists($path2); + if ($this->fakeRoot == Filesystem::getRoot()) { + \OC_Hook::emit( + Filesystem::CLASSNAME, + Filesystem::signal_copy, array( - OC_Filesystem::signal_param_oldpath => $path1, - OC_Filesystem::signal_param_newpath => $path2, - OC_Filesystem::signal_param_run => &$run + Filesystem::signal_param_oldpath => $path1, + Filesystem::signal_param_newpath => $path2, + Filesystem::signal_param_run => &$run ) ); - $exists = $this->file_exists($path2); if ($run and !$exists) { - OC_Hook::emit( - OC_Filesystem::CLASSNAME, - OC_Filesystem::signal_create, + \OC_Hook::emit( + Filesystem::CLASSNAME, + Filesystem::signal_create, array( - OC_Filesystem::signal_param_path => $path2, - OC_Filesystem::signal_param_run => &$run + Filesystem::signal_param_path => $path2, + Filesystem::signal_param_run => &$run ) ); } if ($run) { - OC_Hook::emit( - OC_Filesystem::CLASSNAME, - OC_Filesystem::signal_write, + \OC_Hook::emit( + Filesystem::CLASSNAME, + Filesystem::signal_write, array( - OC_Filesystem::signal_param_path => $path2, - OC_Filesystem::signal_param_run => &$run + Filesystem::signal_param_path => $path2, + Filesystem::signal_param_run => &$run ) ); } @@ -444,39 +456,45 @@ class View { if ($mp1 == $mp2) { if ($storage = $this->getStorage($path1 . $postFix1)) { $result = $storage->copy($this->getInternalPath($path1 . $postFix1), $this->getInternalPath($path2 . $postFix2)); + } else { + $result = false; } } else { $source = $this->fopen($path1 . $postFix1, 'r'); $target = $this->fopen($path2 . $postFix2, 'w'); - $result = OC_Helper::streamCopy($source, $target); + $result = \OC_Helper::streamCopy($source, $target); } - if ($this->fakeRoot == OC_Filesystem::getRoot()) { - OC_Hook::emit( - OC_Filesystem::CLASSNAME, - OC_Filesystem::signal_post_copy, + if ($this->fakeRoot == Filesystem::getRoot()) { + \OC_Hook::emit( + Filesystem::CLASSNAME, + Filesystem::signal_post_copy, array( - OC_Filesystem::signal_param_oldpath => $path1, - OC_Filesystem::signal_param_newpath => $path2 + Filesystem::signal_param_oldpath => $path1, + Filesystem::signal_param_newpath => $path2 ) ); if (!$exists) { - OC_Hook::emit( - OC_Filesystem::CLASSNAME, - OC_Filesystem::signal_post_create, - array(OC_Filesystem::signal_param_path => $path2) + \OC_Hook::emit( + Filesystem::CLASSNAME, + Filesystem::signal_post_create, + array(Filesystem::signal_param_path => $path2) ); } - OC_Hook::emit( - OC_Filesystem::CLASSNAME, - OC_Filesystem::signal_post_write, - array(OC_Filesystem::signal_param_path => $path2) + \OC_Hook::emit( + Filesystem::CLASSNAME, + Filesystem::signal_post_write, + array(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); - OC_Filesystem::removeETagHook(array("path" => $path2), $this->fakeRoot); +// OC_FileCache_Update::update($path2, $this->fakeRoot); + Filesystem::removeETagHook(array("path" => $path2), $this->fakeRoot); } return $result; + } else { + return false; } + } else { + return false; } } @@ -507,14 +525,14 @@ class View { $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); } public function toTmpFile($path) { - if (OC_Filesystem::isValidPath($path)) { + if (Filesystem::isValidPath($path)) { $source = $this->fopen($path, 'r'); if ($source) { $extension = ''; @@ -522,15 +540,19 @@ class View { if ($extOffset !== false) { $extension = substr($path, strrpos($path, '.')); } - $tmpFile = OC_Helper::tmpFile($extension); + $tmpFile = \OC_Helper::tmpFile($extension); file_put_contents($tmpFile, $source); return $tmpFile; + } else { + return false; } + } else { + return false; } } public function fromTmpFile($tmpFile, $path) { - if (OC_Filesystem::isValidPath($path)) { + if (Filesystem::isValidPath($path)) { if (!$tmpFile) { debug_print_backtrace(); } @@ -540,6 +562,7 @@ class View { unlink($tmpFile); return true; } else { + return false; } } else { return false; @@ -552,22 +575,22 @@ class View { public function hash($type, $path, $raw = false) { $postFix = (substr($path, -1, 1) === '/') ? '/' : ''; - $absolutePath = OC_Filesystem::normalizePath($this->getAbsolutePath($path)); - if (OC_FileProxy::runPreProxies('hash', $absolutePath) && OC_Filesystem::isValidPath($path)) { + $absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path)); + if (\OC_FileProxy::runPreProxies('hash', $absolutePath) && Filesystem::isValidPath($path)) { $path = $this->getRelativePath($absolutePath); if ($path == null) { return false; } - if (OC_Filesystem::$loaded && $this->fakeRoot == OC_Filesystem::getRoot()) { - OC_Hook::emit( - OC_Filesystem::CLASSNAME, - OC_Filesystem::signal_read, - array(OC_Filesystem::signal_param_path => $path) + if (Filesystem::$loaded && $this->fakeRoot == Filesystem::getRoot()) { + \OC_Hook::emit( + Filesystem::CLASSNAME, + Filesystem::signal_read, + array(Filesystem::signal_param_path => $path) ); } if ($storage = $this->getStorage($path . $postFix)) { $result = $storage->hash($type, $this->getInternalPath($path . $postFix), $raw); - $result = OC_FileProxy::runPostProxies('hash', $absolutePath, $result); + $result = \OC_FileProxy::runPostProxies('hash', $absolutePath, $result); return $result; } } @@ -581,9 +604,9 @@ class View { /** * @brief abstraction layer for basic filesystem functions: wrapper for \OC\Files\Storage\Storage * @param string $operation - * @param string #path - * @param array (optional) hooks - * @param mixed (optional) $extraParam + * @param string $path + * @param array $hooks (optional) + * @param mixed $extraParam (optional) * @return mixed * * This method takes requests for basic filesystem functions (e.g. reading & writing @@ -592,8 +615,8 @@ class View { */ private function basicOperation($operation, $path, $hooks = array(), $extraParam = null) { $postFix = (substr($path, -1, 1) === '/') ? '/' : ''; - $absolutePath = OC_Filesystem::normalizePath($this->getAbsolutePath($path)); - if (OC_FileProxy::runPreProxies($operation, $absolutePath, $extraParam) and OC_Filesystem::isValidPath($path)) { + $absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path)); + if (\OC_FileProxy::runPreProxies($operation, $absolutePath, $extraParam) and Filesystem::isValidPath($path)) { $path = $this->getRelativePath($absolutePath); if ($path == null) { return false; @@ -606,8 +629,8 @@ class View { } else { $result = $storage->$operation($internalPath); } - $result = OC_FileProxy::runPostProxies($operation, $this->getAbsolutePath($path), $result); - if (OC_Filesystem::$loaded and $this->fakeRoot == OC_Filesystem::getRoot()) { + $result = \OC_FileProxy::runPostProxies($operation, $this->getAbsolutePath($path), $result); + if (Filesystem::$loaded and $this->fakeRoot == Filesystem::getRoot()) { if ($operation != 'fopen') { //no post hooks for fopen, the file stream is still open $this->runHooks($hooks, $path, true); } @@ -621,23 +644,23 @@ class View { private function runHooks($hooks, $path, $post = false) { $prefix = ($post) ? 'post_' : ''; $run = true; - if (OC_Filesystem::$loaded and $this->fakeRoot == OC_Filesystem::getRoot()) { + if (Filesystem::$loaded and $this->fakeRoot == Filesystem::getRoot()) { foreach ($hooks as $hook) { if ($hook != 'read') { - OC_Hook::emit( - OC_Filesystem::CLASSNAME, + \OC_Hook::emit( + Filesystem::CLASSNAME, $prefix . $hook, array( - OC_Filesystem::signal_param_run => &$run, - OC_Filesystem::signal_param_path => $path + Filesystem::signal_param_run => &$run, + Filesystem::signal_param_path => $path ) ); } elseif (!$post) { - OC_Hook::emit( - OC_Filesystem::CLASSNAME, + \OC_Hook::emit( + Filesystem::CLASSNAME, $prefix . $hook, array( - OC_Filesystem::signal_param_path => $path + Filesystem::signal_param_path => $path ) ); } @@ -649,6 +672,7 @@ class View { /** * check if a file or folder has been updated since $time * + * @param string $path * @param int $time * @return bool */ From 4b9fbf46e554f8bb368e6cf5a8f75ca5c56e8228 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 10 Oct 2012 12:50:57 +0200 Subject: [PATCH 030/347] add depricated OC_Filessystem for compatibility --- lib/filesystem.php | 479 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 460 insertions(+), 19 deletions(-) diff --git a/lib/filesystem.php b/lib/filesystem.php index b1200f95bf..4189fe36c2 100644 --- a/lib/filesystem.php +++ b/lib/filesystem.php @@ -1,25 +1,466 @@ . -* -*/ + * Copyright (c) 2012 Robin Appelman + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ +/** + * 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 permission related stuff + * + * Hooks provided: + * read(path) + * write(path, &run) + * post_write(path) + * create(path, &run) (when a file is created, both create and write will be emitted in that order) + * 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 emitted in that order) + * post_rename(oldpath,newpath) + * + * the &run parameter can be set to false to prevent the operation from occurring + */ +/** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ +class OC_Filesystem { + /** + * get the mountpoint of the storage object for a path + ( note: because a storage is not always mounted inside the fakeroot, the returned mountpoint is relative to the absolute root of the filesystem and doesn't take the chroot into account + * + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + * @param string $path + * @return string + */ + static public function getMountPoint($path) { + return \OC\Files\Filesystem::getMountPoint($path); + } + /** + * get the part of the path relative to the mountpoint of the storage it's stored in + * + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + * @param string $path + * @return bool + */ + static public function getInternalPath($path) { + return \OC\Files\Filesystem::getInternalPath($path); + } + + /** + * get the storage object for a path + * + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + * @param string $path + * @return \OC\Files\Storage\Storage + */ + static public function getStorage($path) { + return \OC\Files\Filesystem::getStorage($path); + } + + /** + * resolve a path to a storage and internal path + * + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + * @param string $path + * @return array consisting of the storage and the internal path + */ + static public function resolvePath($path) { + return \OC\Files\Filesystem::resolvePath($path); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function init($root) { + return \OC\Files\Filesystem::init($root); + } + + /** + * get the default filesystem view + * + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + * @return \OC\Files\View + */ + static public function getView() { + return \OC\Files\Filesystem::getView(); + } + + /** + * tear down the filesystem, removing all storage providers + * + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function tearDown() { + \OC\Files\Filesystem::tearDown(); + } + + /** + * change the root to a fake root + * + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + * @param string $fakeRoot + * @return bool + */ + static public function chroot($fakeRoot) { + return \OC\Files\Filesystem::chroot($fakeRoot); + } + + /** + * @brief get the relative path of the root data directory for the current user + * @return string + * + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + * Returns path like /admin/files + */ + static public function getRoot() { + return \OC\Files\Filesystem::getRoot(); + } + + /** + * clear all mounts and storage backends + * + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + public static function clearMounts() { + \OC\Files\Filesystem::clearMounts(); + } + + /** + * mount an \OC\Files\Storage\Storage in our virtual filesystem + * + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + * @param \OC\Files\Storage\Storage $class + * @param array $arguments + * @param string $mountpoint + */ + static public function mount($class, $arguments, $mountpoint) { + \OC\Files\Filesystem::mount($class, $arguments, $mountpoint); + } + + /** + * return the path to a local version of the file + * we need this because we can't know if a file is stored local or not from outside the filestorage and for some purposes a local file is needed + * + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + * @param string $path + * @return string + */ + static public function getLocalFile($path) { + return \OC\Files\Filesystem::getLocalFile($path); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + * @param string $path + * @return string + */ + static public function getLocalFolder($path) { + return \OC\Files\Filesystem::getLocalFolder($path); + } + + /** + * return path to file which reflects one visible in browser + * + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + * @param string $path + * @return string + */ + static public function getLocalPath($path) { + return \OC\Files\Filesystem::getLocalPath($path); + } + + /** + * check if the requested path is valid + * + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + * @param string $path + * @return bool + */ + static public function isValidPath($path) { + return \OC\Files\Filesystem::isValidPath($path); + } + + /** + * checks if a file is blacklisted for storage in the filesystem + * Listens to write and rename hooks + * + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + * @param array $data from hook + */ + static public function isBlacklisted($data) { + \OC\Files\Filesystem::isBlacklisted($data); + } + + /** + * following functions are equivalent to their php builtin equivalents for arguments/return values. + * + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function mkdir($path) { + return \OC\Files\Filesystem::mkdir($path); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function rmdir($path) { + return \OC\Files\Filesystem::rmdir($path); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function opendir($path) { + return \OC\Files\Filesystem::opendir($path); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function readdir($path) { + return \OC\Files\Filesystem::readdir($path); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function is_dir($path) { + return \OC\Files\Filesystem::is_dir($path); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function is_file($path) { + return \OC\Files\Filesystem::is_file($path); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function stat($path) { + return \OC\Files\Filesystem::stat($path); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function filetype($path) { + return \OC\Files\Filesystem::filetype($path); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function filesize($path) { + return \OC\Files\Filesystem::filesize($path); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function readfile($path) { + return \OC\Files\Filesystem::readfile($path); + } + + /** + * @deprecated Replaced by isReadable() as part of CRUDS + */ + static public function is_readable($path) { + return \OC\Files\Filesystem::isReadable($path); + } + + /** + * @deprecated Replaced by isCreatable(), isUpdatable(), isDeletable() as part of CRUDS + */ + static public function is_writable($path) { + return \OC\Files\Filesystem::is_writable($path); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function isCreatable($path) { + return \OC\Files\Filesystem::isCreatable($path); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function isReadable($path) { + return \OC\Files\Filesystem::isReadable($path); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function isUpdatable($path) { + return \OC\Files\Filesystem::isUpdatable($path); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function isDeletable($path) { + return \OC\Files\Filesystem::isDeletable($path); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function isSharable($path) { + return \OC\Files\Filesystem::isSharable($path); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function file_exists($path) { + return \OC\Files\Filesystem::file_exists($path); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function filectime($path) { + return \OC\Files\Filesystem::filectime($path); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function filemtime($path) { + return \OC\Files\Filesystem::filemtime($path); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function touch($path, $mtime = null) { + return \OC\Files\Filesystem::touch($path, $mtime); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function file_get_contents($path) { + return \OC\Files\Filesystem::file_get_contents($path); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function file_put_contents($path, $data) { + return \OC\Files\Filesystem::file_put_contents($path, $data); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function unlink($path) { + return \OC\Files\Filesystem::unlink($path); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function rename($path1, $path2) { + return \OC\Files\Filesystem::rename($path1, $path2); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function copy($path1, $path2) { + return \OC\Files\Filesystem::copy($path1, $path2); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function fopen($path, $mode) { + return \OC\Files\Filesystem::fopen($path, $mode); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function toTmpFile($path) { + return \OC\Files\Filesystem::toTmpFile($path); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function fromTmpFile($tmpFile, $path) { + return \OC\Files\Filesystem::fromTmpFile($tmpFile, $path); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function getMimeType($path) { + return \OC\Files\Filesystem::getMimeType($path); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function hash($type, $path, $raw = false) { + return \OC\Files\Filesystem::hash($type, $path, $raw); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function free_space($path = '/') { + return \OC\Files\Filesystem::free_space($path); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function search($query) { + return \OC\Files\Filesystem::search($query); + } + + /** + * check if a file or folder has been updated since $time + * + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + * @param string $path + * @param int $time + * @return bool + */ + static public function hasUpdated($path, $time) { + return \OC\Files\Filesystem::hasUpdated($path, $time); + } + + /** + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + */ + static public function removeETagHook($params, $root = false) { + \OC\Files\Filesystem::removeETagHook($params, $root); + } + + /** + * normalize a path + * + * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem + * @param string $path + * @param bool $stripTrailingSlash + * @return string + */ + public static function normalizePath($path, $stripTrailingSlash = true) { + return \OC\Files\Filesystem::normalizePath($path, $stripTrailingSlash); + } +} From c88c54bbb054fe2d79b3a93604989d527b5dd444 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 10 Oct 2012 12:51:15 +0200 Subject: [PATCH 031/347] make sure we can do our tests again --- lib/cache/file.php | 4 ++-- tests/lib/cache/file.php | 2 +- tests/lib/filesystem.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/cache/file.php b/lib/cache/file.php index 27d8b19f36..f9ecf41dca 100644 --- a/lib/cache/file.php +++ b/lib/cache/file.php @@ -15,11 +15,11 @@ class OC_Cache_File{ } if(OC_User::isLoggedIn()) { $subdir = 'cache'; - $view = new OC_FilesystemView('/'.OC_User::getUser()); + $view = new \OC\Files\View('/'.OC_User::getUser()); if(!$view->file_exists($subdir)) { $view->mkdir($subdir); } - $this->storage = new OC_FilesystemView('/'.OC_User::getUser().'/'.$subdir); + $this->storage = new \OC\Files\View('/'.OC_User::getUser().'/'.$subdir); return $this->storage; }else{ OC_Log::write('core', 'Can\'t get cache storage, user not logged in', OC_Log::ERROR); diff --git a/tests/lib/cache/file.php b/tests/lib/cache/file.php index 1dd1ff7fa8..3e8fd8c1bb 100644 --- a/tests/lib/cache/file.php +++ b/tests/lib/cache/file.php @@ -51,7 +51,7 @@ class Test_Cache_File extends Test_Cache { OC_User::setUserId('test'); //set up the users dir - $rootView=new OC_FilesystemView(''); + $rootView=new \OC\Files\View(''); $rootView->mkdir('/test'); $this->instance=new OC_Cache_File(); diff --git a/tests/lib/filesystem.php b/tests/lib/filesystem.php index 8fc3ce641d..b402b86af1 100644 --- a/tests/lib/filesystem.php +++ b/tests/lib/filesystem.php @@ -84,7 +84,7 @@ class Test_Filesystem extends UnitTestCase { OC_Filesystem::mount('OC\Files\Storage\Temporary', array(), '/'); - $rootView=new OC_FilesystemView(''); + $rootView=new \OC\Files\View(''); $rootView->mkdir('/'.$user); $rootView->mkdir('/'.$user.'/files'); From aaa1b733642c41821a53bc6d04fab246bfe7f1e6 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 10 Oct 2012 13:18:36 +0200 Subject: [PATCH 032/347] don't use depricated OC_Filesystem --- apps/files/ajax/autocomplete.php | 6 +- apps/files/ajax/newfile.php | 6 +- apps/files/ajax/upload.php | 4 +- apps/files/appinfo/filesync.php | 4 +- apps/files/download.php | 8 +-- apps/files/index.php | 14 ++-- apps/files_encryption/lib/crypt.php | 6 +- apps/files_encryption/lib/cryptstream.php | 2 +- apps/files_encryption/lib/proxy.php | 6 +- apps/files_encryption/tests/proxy.php | 30 ++++----- .../ajax/addRootCertificate.php | 12 ++-- apps/files_external/lib/config.php | 12 ++-- apps/files_sharing/lib/sharedstorage.php | 66 +++++++++---------- apps/files_sharing/public.php | 8 +-- apps/files_versions/lib/hooks.php | 4 +- apps/files_versions/lib/versions.php | 16 ++--- lib/connector/sabre/directory.php | 10 +-- lib/connector/sabre/file.php | 10 +-- lib/connector/sabre/node.php | 8 +-- lib/filechunking.php | 38 +++++------ lib/fileproxy/quota.php | 2 +- lib/files.php | 54 +++++++-------- lib/files/file.php | 2 +- lib/helper.php | 2 +- lib/image.php | 2 +- lib/ocs.php | 4 +- lib/public/files.php | 2 +- lib/public/share.php | 6 +- lib/util.php | 10 +-- settings/personal.php | 2 +- tests/lib/cache/file.php | 4 +- tests/lib/filesystem.php | 56 ++++++++-------- 32 files changed, 209 insertions(+), 207 deletions(-) diff --git a/apps/files/ajax/autocomplete.php b/apps/files/ajax/autocomplete.php index fae38368a8..d0dab9c2bd 100644 --- a/apps/files/ajax/autocomplete.php +++ b/apps/files/ajax/autocomplete.php @@ -33,8 +33,8 @@ $query=strtolower($query); $files=array(); -if(OC_Filesystem::file_exists($base) and OC_Filesystem::is_dir($base)) { - $dh = OC_Filesystem::opendir($base); +if(\OC\Files\Filesystem::file_exists($base) and \OC\Files\Filesystem::is_dir($base)) { + $dh = \OC\Files\Filesystem::opendir($base); if($dh) { if(substr($base, -1, 1)!='/') { $base=$base.'/'; @@ -43,7 +43,7 @@ if(OC_Filesystem::file_exists($base) and OC_Filesystem::is_dir($base)) { if ($file != "." && $file != "..") { if(substr(strtolower($file), 0, $queryLen)==$query) { $item=$base.$file; - if((!$dirOnly or OC_Filesystem::is_dir($item))) { + if((!$dirOnly or \OC\Files\Filesystem::is_dir($item))) { $files[]=(object)array('id'=>$item,'label'=>$item,'name'=>$item); } } diff --git a/apps/files/ajax/newfile.php b/apps/files/ajax/newfile.php index 77d866979c..4d73970b68 100644 --- a/apps/files/ajax/newfile.php +++ b/apps/files/ajax/newfile.php @@ -63,12 +63,12 @@ if($source) { $ctx = stream_context_create(null, array('notification' =>'progress')); $sourceStream=fopen($source, 'rb', false, $ctx); $target=$dir.'/'.$filename; - $result=OC_Filesystem::file_put_contents($target, $sourceStream); + $result=\OC\Files\Filesystem::file_put_contents($target, $sourceStream); if($result) { $meta = OC_FileCache::get($target); $mime=$meta['mimetype']; $id = OC_FileCache::getId($target); - $eventSource->send('success', array('mime'=>$mime, 'size'=>OC_Filesystem::filesize($target), 'id' => $id)); + $eventSource->send('success', array('mime'=>$mime, 'size'=>\OC\Files\Filesystem::filesize($target), 'id' => $id)); } else { $eventSource->send('error', "Error while downloading ".$source. ' to '.$target); } @@ -76,7 +76,7 @@ if($source) { exit(); } else { if($content) { - if(OC_Filesystem::file_put_contents($dir.'/'.$filename, $content)) { + if(\OC\Files\Filesystem::file_put_contents($dir.'/'.$filename, $content)) { $meta = OC_FileCache::get($dir.'/'.$filename); $id = OC_FileCache::getId($dir.'/'.$filename); OCP\JSON::success(array("data" => array('content'=>$content, 'id' => $id))); diff --git a/apps/files/ajax/upload.php b/apps/files/ajax/upload.php index a4dcd80a2e..8bf7f10e18 100644 --- a/apps/files/ajax/upload.php +++ b/apps/files/ajax/upload.php @@ -38,7 +38,7 @@ $totalSize=0; foreach($files['size'] as $size) { $totalSize+=$size; } -if($totalSize>OC_Filesystem::free_space('/')) { +if($totalSize>\OC\Files\Filesystem::free_space('/')) { OCP\JSON::error(array("data" => array( "message" => "Not enough space available" ))); exit(); } @@ -48,7 +48,7 @@ if(strpos($dir, '..') === false) { $fileCount=count($files['name']); for($i=0;$i<$fileCount;$i++) { $target = OCP\Files::buildNotExistingFileName(stripslashes($dir), $files['name'][$i]); - if(is_uploaded_file($files['tmp_name'][$i]) and OC_Filesystem::fromTmpFile($files['tmp_name'][$i], $target)) { + if(is_uploaded_file($files['tmp_name'][$i]) and \OC\Files\Filesystem::fromTmpFile($files['tmp_name'][$i], $target)) { $meta = OC_FileCache::get($target); $id = OC_FileCache::getId($target); $result[]=array( "status" => "success", 'mime'=>$meta['mimetype'],'size'=>$meta['size'], 'id'=>$id, 'name'=>basename($target)); diff --git a/apps/files/appinfo/filesync.php b/apps/files/appinfo/filesync.php index c1fe444cec..e755771de6 100644 --- a/apps/files/appinfo/filesync.php +++ b/apps/files/appinfo/filesync.php @@ -43,7 +43,7 @@ if ($type != 'oc_chunked') { die; } -if (!OC_Filesystem::is_file($file)) { +if (!\OC\Files\Filesystem::is_file($file)) { OC_Response::setStatus(OC_Response::STATUS_NOT_FOUND); die; } @@ -51,7 +51,7 @@ if (!OC_Filesystem::is_file($file)) { switch($_SERVER['REQUEST_METHOD']) { case 'PUT': $input = fopen("php://input", "r"); - $org_file = OC_Filesystem::fopen($file, 'rb'); + $org_file = \OC\Files\Filesystem::fopen($file, 'rb'); $info = array( 'name' => basename($file), ); diff --git a/apps/files/download.php b/apps/files/download.php index ff6aefbbe0..b00a50a045 100644 --- a/apps/files/download.php +++ b/apps/files/download.php @@ -29,7 +29,7 @@ OCP\User::checkLoggedIn(); $filename = $_GET["file"]; -if(!OC_Filesystem::file_exists($filename)) { +if(!\OC\Files\Filesystem::file_exists($filename)) { header("HTTP/1.0 404 Not Found"); $tmpl = new OCP\Template( '', '404', 'guest' ); $tmpl->assign('file',$filename); @@ -37,12 +37,12 @@ if(!OC_Filesystem::file_exists($filename)) { exit; } -$ftype=OC_Filesystem::getMimeType( $filename ); +$ftype=\OC\Files\Filesystem::getMimeType( $filename ); header('Content-Type:'.$ftype); header('Content-Disposition: attachment; filename="'.basename($filename).'"'); OCP\Response::disableCaching(); -header('Content-Length: '.OC_Filesystem::filesize($filename)); +header('Content-Length: '.\OC\Files\Filesystem::filesize($filename)); @ob_end_clean(); -OC_Filesystem::readfile( $filename ); +\OC\Files\Filesystem::readfile( $filename ); diff --git a/apps/files/index.php b/apps/files/index.php index 493087d26f..b02aaf81c0 100644 --- a/apps/files/index.php +++ b/apps/files/index.php @@ -38,7 +38,7 @@ OCP\App::setActiveNavigationEntry( 'files_index' ); // Load the files $dir = isset( $_GET['dir'] ) ? stripslashes($_GET['dir']) : ''; // Redirect if directory does not exist -if(!OC_Filesystem::is_dir($dir.'/')) { +if(!\OC\Files\Filesystem::is_dir($dir.'/')) { header('Location: '.$_SERVER['SCRIPT_NAME'].''); exit(); } @@ -85,26 +85,26 @@ $upload_max_filesize = OCP\Util::computerFileSize(ini_get('upload_max_filesize') $post_max_size = OCP\Util::computerFileSize(ini_get('post_max_size')); $maxUploadFilesize = min($upload_max_filesize, $post_max_size); -$freeSpace=OC_Filesystem::free_space('/'); +$freeSpace=\OC\Files\Filesystem::free_space('/'); $freeSpace=max($freeSpace,0); $maxUploadFilesize = min($maxUploadFilesize ,$freeSpace); $permissions = OCP\Share::PERMISSION_READ; -if (OC_Filesystem::isUpdatable($dir.'/')) { +if (\OC\Files\Filesystem::isUpdatable($dir.'/')) { $permissions |= OCP\Share::PERMISSION_UPDATE; } -if (OC_Filesystem::isDeletable($dir.'/')) { +if (\OC\Files\Filesystem::isDeletable($dir.'/')) { $permissions |= OCP\Share::PERMISSION_DELETE; } -if (OC_Filesystem::isSharable($dir.'/')) { +if (\OC\Files\Filesystem::isSharable($dir.'/')) { $permissions |= OCP\Share::PERMISSION_SHARE; } $tmpl = new OCP\Template( 'files', 'index', 'user' ); $tmpl->assign( 'fileList', $list->fetchPage(), false ); $tmpl->assign( 'breadcrumb', $breadcrumbNav->fetchPage(), false ); -$tmpl->assign( 'dir', OC_Filesystem::normalizePath($dir)); -$tmpl->assign( 'isCreatable', OC_Filesystem::isCreatable($dir.'/')); +$tmpl->assign( 'dir', \OC\Files\Filesystem::normalizePath($dir)); +$tmpl->assign( 'isCreatable', \OC\Files\Filesystem::isCreatable($dir.'/')); $tmpl->assign('permissions', $permissions); $tmpl->assign( 'files', $files ); $tmpl->assign( 'uploadMaxFilesize', $maxUploadFilesize); diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index 38d8edf28c..6bee8accf7 100644 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -44,7 +44,7 @@ class OC_Crypt { } public static function init($login,$password) { - $view=new OC_FilesystemView('/'); + $view=new \OC\Files\View('/'); if(!$view->file_exists('/'.$login)) { $view->mkdir('/'.$login); } @@ -90,7 +90,7 @@ class OC_Crypt { // Write the file $proxyEnabled=OC_FileProxy::$enabled; OC_FileProxy::$enabled=false; - $view=new OC_FilesystemView('/'.$username); + $view=new \OC\Files\View('/'.$username); $view->file_put_contents('/encryption.key',$enckey); OC_FileProxy::$enabled=$proxyEnabled; } @@ -98,7 +98,7 @@ class OC_Crypt { public static function changekeypasscode($oldPassword, $newPassword) { if(OCP\User::isLoggedIn()) { $username=OCP\USER::getUser(); - $view=new OC_FilesystemView('/'.$username); + $view=new \OC\Files\View('/'.$username); // read old key $key=$view->file_get_contents('/encryption.key'); diff --git a/apps/files_encryption/lib/cryptstream.php b/apps/files_encryption/lib/cryptstream.php index 721a1b955d..89a071327a 100644 --- a/apps/files_encryption/lib/cryptstream.php +++ b/apps/files_encryption/lib/cryptstream.php @@ -38,7 +38,7 @@ class OC_CryptStream{ public function stream_open($path, $mode, $options, &$opened_path) { if(!self::$rootView) { - self::$rootView=new OC_FilesystemView(''); + self::$rootView=new \OC\Files\View(''); } $path=str_replace('crypt://','',$path); if(dirname($path)=='streams' and isset(self::$sourceStreams[basename($path)])) { diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index f61cd1e377..27abe3bb19 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -90,13 +90,13 @@ class OC_FileProxy_Encryption extends OC_FileProxy{ fclose($result); $result=fopen('crypt://'.$path,$meta['mode']); }elseif(self::shouldEncrypt($path) and $meta['mode']!='r' and $meta['mode']!='rb') { - if(OC_Filesystem::file_exists($path) and OC_Filesystem::filesize($path)>0) { + if(\OC\Files\Filesystem::file_exists($path) and \OC\Files\Filesystem::filesize($path)>0) { //first encrypt the target file so we don't end up with a half encrypted file OCP\Util::writeLog('files_encryption','Decrypting '.$path.' before writing',OCP\Util::DEBUG); - $tmp=fopen('php://temp'); + $tmp=fopen('php://temp', 'w+'); OCP\Files::streamCopy($result,$tmp); fclose($result); - OC_Filesystem::file_put_contents($path,$tmp); + \OC\Files\Filesystem::file_put_contents($path,$tmp); fclose($tmp); } $result=fopen('crypt://'.$path,$meta['mode']); diff --git a/apps/files_encryption/tests/proxy.php b/apps/files_encryption/tests/proxy.php index d600bbc407..c04e0e5c4f 100644 --- a/apps/files_encryption/tests/proxy.php +++ b/apps/files_encryption/tests/proxy.php @@ -29,13 +29,13 @@ class Test_CryptProxy extends UnitTestCase { OC_FileProxy::register(new OC_FileProxy_Encryption()); //set up temporary storage - OC_Filesystem::clearMounts(); - OC_Filesystem::mount('\OC\Files\Storage\Temporary',array(),'/'); + \OC\Files\Filesystem::clearMounts(); + \OC\Files\Filesystem::mount('\OC\Files\Storage\Temporary',array(),'/'); - OC_Filesystem::init('/'.$user.'/files'); + \OC\Files\Filesystem::init('/'.$user.'/files'); //set up the users home folder in the temp storage - $rootView=new OC_FilesystemView(''); + $rootView=new \OC\Files\View(''); $rootView->mkdir('/'.$user); $rootView->mkdir('/'.$user.'/files'); } @@ -51,13 +51,13 @@ class Test_CryptProxy extends UnitTestCase { $file=OC::$SERVERROOT.'/3rdparty/MDB2.php'; $original=file_get_contents($file); - OC_Filesystem::file_put_contents('/file',$original); + \OC\Files\Filesystem::file_put_contents('/file',$original); OC_FileProxy::$enabled=false; - $stored=OC_Filesystem::file_get_contents('/file'); + $stored=\OC\Files\Filesystem::file_get_contents('/file'); OC_FileProxy::$enabled=true; - $fromFile=OC_Filesystem::file_get_contents('/file'); + $fromFile=\OC\Files\Filesystem::file_get_contents('/file'); $this->assertNotEqual($original,$stored); $this->assertEqual(strlen($original),strlen($fromFile)); $this->assertEqual($original,$fromFile); @@ -68,8 +68,8 @@ class Test_CryptProxy extends UnitTestCase { $file=OC::$SERVERROOT.'/3rdparty/MDB2.php'; $original=file_get_contents($file); - $rootView=new OC_FilesystemView(''); - $view=new OC_FilesystemView('/'.OC_User::getUser()); + $rootView=new \OC\Files\View(''); + $view=new \OC\Files\View('/'.OC_User::getUser()); $userDir='/'.OC_User::getUser().'/files'; $rootView->file_put_contents($userDir.'/file',$original); @@ -90,13 +90,13 @@ class Test_CryptProxy extends UnitTestCase { $file=__DIR__.'/binary'; $original=file_get_contents($file); - OC_Filesystem::file_put_contents('/file',$original); + \OC\Files\Filesystem::file_put_contents('/file',$original); OC_FileProxy::$enabled=false; - $stored=OC_Filesystem::file_get_contents('/file'); + $stored=\OC\Files\Filesystem::file_get_contents('/file'); OC_FileProxy::$enabled=true; - $fromFile=OC_Filesystem::file_get_contents('/file'); + $fromFile=\OC\Files\Filesystem::file_get_contents('/file'); $this->assertNotEqual($original,$stored); $this->assertEqual(strlen($original),strlen($fromFile)); $this->assertEqual($original,$fromFile); @@ -104,13 +104,13 @@ class Test_CryptProxy extends UnitTestCase { $file=__DIR__.'/zeros'; $original=file_get_contents($file); - OC_Filesystem::file_put_contents('/file',$original); + \OC\Files\Filesystem::file_put_contents('/file',$original); OC_FileProxy::$enabled=false; - $stored=OC_Filesystem::file_get_contents('/file'); + $stored=\OC\Files\Filesystem::file_get_contents('/file'); OC_FileProxy::$enabled=true; - $fromFile=OC_Filesystem::file_get_contents('/file'); + $fromFile=\OC\Files\Filesystem::file_get_contents('/file'); $this->assertNotEqual($original,$stored); $this->assertEqual(strlen($original),strlen($fromFile)); } diff --git a/apps/files_external/ajax/addRootCertificate.php b/apps/files_external/ajax/addRootCertificate.php index e0a0239c95..6fef9aac1e 100644 --- a/apps/files_external/ajax/addRootCertificate.php +++ b/apps/files_external/ajax/addRootCertificate.php @@ -3,23 +3,23 @@ OCP\JSON::checkAppEnabled('files_external'); if ( !($filename = $_FILES['rootcert_import']['name']) ) { - header("Location: settings/personal.php"); + header("Location: settings/personal.php"); exit; } -$fh = fopen($_FILES['rootcert_import']['tmp_name'], 'r'); -$data = fread($fh, filesize($_FILES['rootcert_import']['tmp_name'])); +$fh = fopen($_FILES['rootcert_import']['tmp_name'], 'r'); +$data = fread($fh, filesize($_FILES['rootcert_import']['tmp_name'])); fclose($fh); $filename = $_FILES['rootcert_import']['name']; - -$view = new \OC_FilesystemView('/'.\OCP\User::getUser().'/files_external/uploads'); + +$view = new \OC\Files\View('/'.\OCP\User::getUser().'/files_external/uploads'); if (!$view->file_exists('')) $view->mkdir(''); $isValid = openssl_pkey_get_public($data); //maybe it was just the wrong file format, try to convert it... if ($isValid == false) { - $data = chunk_split(base64_encode($data), 64, "\n"); + $data = chunk_split(base64_encode($data), 64, "\n"); $data = "-----BEGIN CERTIFICATE-----\n".$data."-----END CERTIFICATE-----\n"; $isValid = openssl_pkey_get_public($data); } diff --git a/apps/files_external/lib/config.php b/apps/files_external/lib/config.php index cb32fed203..7be2336019 100755 --- a/apps/files_external/lib/config.php +++ b/apps/files_external/lib/config.php @@ -109,10 +109,10 @@ class OC_Mount_Config { return $personal; } - /** - * Add directory for mount point to the filesystem - * @param OC_Fileview instance $view - * @param string path to mount point + /** + * Add directory for mount point to the filesystem + * @param OC_Fileview instance $view + * @param string path to mount point */ private static function addMountPointDirectory($view, $path) { $dir = ''; @@ -142,11 +142,11 @@ class OC_Mount_Config { if ($applicable != OCP\User::getUser() || $class == '\OC\Files\Storage\Local') { return false; } - $view = new OC_FilesystemView('/'.OCP\User::getUser().'/files'); + $view = new \OC\Files\View('/'.OCP\User::getUser().'/files'); self::addMountPointDirectory($view, ltrim($mountPoint, '/')); $mountPoint = '/'.$applicable.'/files/'.ltrim($mountPoint, '/'); } else { - $view = new OC_FilesystemView('/'); + $view = new \OC\Files\View('/'); switch ($mountType) { case 'user': if ($applicable == "all") { diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php index 876e719956..e17c4b6e04 100644 --- a/apps/files_sharing/lib/sharedstorage.php +++ b/apps/files_sharing/lib/sharedstorage.php @@ -80,7 +80,7 @@ class Shared extends \OC\Files\Storage\Common { $file = $this->getFile($target); if (isset($file['path'])) { $uid = substr($file['path'], 1, strpos($file['path'], '/', 1) - 1); - \OC_Filesystem::mount('\OC\Files\Storage\Local', array('datadir' => \OC_User::getHome($uid)), $uid); + \\OC\Files\Filesystem::mount('\OC\Files\Storage\Local', array('datadir' => \OC_User::getHome($uid)), $uid); return $file['path']; } return false; @@ -105,7 +105,7 @@ class Shared extends \OC\Files\Storage\Common { * @return Source file path with mount point stripped out */ private function getInternalPath($path) { - $mountPoint = \OC_Filesystem::getMountPoint($path); + $mountPoint = \OC\Files\Filesystem::getMountPoint($path); $internalPath = substr($path, strlen($mountPoint)); return $internalPath; } @@ -114,7 +114,7 @@ class Shared extends \OC\Files\Storage\Common { if ($path == '' || $path == '/' || !$this->isCreatable(dirname($path))) { return false; } else if ($source = $this->getSourcePath($path)) { - $storage = \OC_Filesystem::getStorage($source); + $storage = \OC\Files\Filesystem::getStorage($source); return $storage->mkdir($this->getInternalPath($source)); } return false; @@ -122,7 +122,7 @@ class Shared extends \OC\Files\Storage\Common { public function rmdir($path) { if (($source = $this->getSourcePath($path)) && $this->isDeletable($path)) { - $storage = \OC_Filesystem::getStorage($source); + $storage = \OC\Files\Filesystem::getStorage($source); return $storage->rmdir($this->getInternalPath($source)); } return false; @@ -130,11 +130,11 @@ class Shared extends \OC\Files\Storage\Common { public function opendir($path) { if ($path == '' || $path == '/') { - $files = OCP\Share::getItemsSharedWith('file', \OC_Share_Backend_Folder::FORMAT_OPENDIR); + $files = \OCP\Share::getItemsSharedWith('file', \OC_Share_Backend_Folder::FORMAT_OPENDIR); \OC_FakeDirStream::$dirs['shared'] = $files; return opendir('fakedir://shared'); } else if ($source = $this->getSourcePath($path)) { - $storage = \OC_Filesystem::getStorage($source); + $storage = \OC\Files\Filesystem::getStorage($source); return $storage->opendir($this->getInternalPath($source)); } return false; @@ -144,7 +144,7 @@ class Shared extends \OC\Files\Storage\Common { if ($path == '' || $path == '/') { return true; } else if ($source = $this->getSourcePath($path)) { - $storage = \OC_Filesystem::getStorage($source); + $storage = \OC\Files\Filesystem::getStorage($source); return $storage->is_dir($this->getInternalPath($source)); } return false; @@ -152,7 +152,7 @@ class Shared extends \OC\Files\Storage\Common { public function is_file($path) { if ($source = $this->getSourcePath($path)) { - $storage = \OC_Filesystem::getStorage($source); + $storage = \OC\Files\Filesystem::getStorage($source); return $storage->is_file($this->getInternalPath($source)); } return false; @@ -165,7 +165,7 @@ class Shared extends \OC\Files\Storage\Common { $stat['ctime'] = $this->filectime($path); return $stat; } else if ($source = $this->getSourcePath($path)) { - $storage = \OC_Filesystem::getStorage($source); + $storage = \OC\Files\Filesystem::getStorage($source); return $storage->stat($this->getInternalPath($source)); } return false; @@ -175,7 +175,7 @@ class Shared extends \OC\Files\Storage\Common { if ($path == '' || $path == '/') { return 'dir'; } else if ($source = $this->getSourcePath($path)) { - $storage = \OC_Filesystem::getStorage($source); + $storage = \OC\Files\Filesystem::getStorage($source); return $storage->filetype($this->getInternalPath($source)); } return false; @@ -185,7 +185,7 @@ class Shared extends \OC\Files\Storage\Common { if ($path == '' || $path == '/' || $this->is_dir($path)) { return 0; } else if ($source = $this->getSourcePath($path)) { - $storage = \OC_Filesystem::getStorage($source); + $storage = \OC\Files\Filesystem::getStorage($source); return $storage->filesize($this->getInternalPath($source)); } return false; @@ -195,7 +195,7 @@ class Shared extends \OC\Files\Storage\Common { if ($path == '') { return false; } - return ($this->getPermissions($path) & OCP\Share::PERMISSION_CREATE); + return ($this->getPermissions($path) & \OCP\Share::PERMISSION_CREATE); } public function isReadable($path) { @@ -206,28 +206,28 @@ class Shared extends \OC\Files\Storage\Common { if ($path == '') { return false; } - return ($this->getPermissions($path) & OCP\Share::PERMISSION_UPDATE); + return ($this->getPermissions($path) & \OCP\Share::PERMISSION_UPDATE); } public function isDeletable($path) { if ($path == '') { return true; } - return ($this->getPermissions($path) & OCP\Share::PERMISSION_DELETE); + return ($this->getPermissions($path) & \OCP\Share::PERMISSION_DELETE); } public function isSharable($path) { if ($path == '') { return false; } - return ($this->getPermissions($path) & OCP\Share::PERMISSION_SHARE); + return ($this->getPermissions($path) & \OCP\Share::PERMISSION_SHARE); } public function file_exists($path) { if ($path == '' || $path == '/') { return true; } else if ($source = $this->getSourcePath($path)) { - $storage = \OC_Filesystem::getStorage($source); + $storage = \OC\Files\Filesystem::getStorage($source); return $storage->file_exists($this->getInternalPath($source)); } return false; @@ -248,7 +248,7 @@ class Shared extends \OC\Files\Storage\Common { } else { $source = $this->getSourcePath($path); if ($source) { - $storage = \OC_Filesystem::getStorage($source); + $storage = \OC\Files\Filesystem::getStorage($source); return $storage->filectime($this->getInternalPath($source)); } } @@ -269,7 +269,7 @@ class Shared extends \OC\Files\Storage\Common { } else { $source = $this->getSourcePath($path); if ($source) { - $storage = \OC_Filesystem::getStorage($source); + $storage = \OC\Files\Filesystem::getStorage($source); return $storage->filemtime($this->getInternalPath($source)); } } @@ -282,8 +282,8 @@ class Shared extends \OC\Files\Storage\Common { 'target' => $this->sharedFolder.$path, 'source' => $source, ); - OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_get_contents', $info); - $storage = \OC_Filesystem::getStorage($source); + \OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_get_contents', $info); + $storage = \OC\Files\Filesystem::getStorage($source); return $storage->file_get_contents($this->getInternalPath($source)); } } @@ -298,8 +298,8 @@ class Shared extends \OC\Files\Storage\Common { 'target' => $this->sharedFolder.$path, 'source' => $source, ); - OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_put_contents', $info); - $storage = \OC_Filesystem::getStorage($source); + \OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_put_contents', $info); + $storage = \OC\Files\Filesystem::getStorage($source); $result = $storage->file_put_contents($this->getInternalPath($source), $data); return $result; } @@ -310,7 +310,7 @@ class Shared extends \OC\Files\Storage\Common { // Delete the file if DELETE permission is granted if ($source = $this->getSourcePath($path)) { if ($this->isDeletable($path)) { - $storage = \OC_Filesystem::getStorage($source); + $storage = \OC\Files\Filesystem::getStorage($source); return $storage->unlink($this->getInternalPath($source)); } else if (dirname($path) == '/' || dirname($path) == '.') { // Unshare the file from the user if in the root of the Shared folder @@ -319,7 +319,7 @@ class Shared extends \OC\Files\Storage\Common { } else { $itemType = 'file'; } - return OCP\Share::unshareFromSelf($itemType, $path); + return \OCP\Share::unshareFromSelf($itemType, $path); } } return false; @@ -334,7 +334,7 @@ class Shared extends \OC\Files\Storage\Common { if (dirname($path1) == dirname($path2)) { // Rename the file if UPDATE permission is granted if ($this->isUpdatable($path1)) { - $storage = \OC_Filesystem::getStorage($oldSource); + $storage = \OC\Files\Filesystem::getStorage($oldSource); return $storage->rename($this->getInternalPath($oldSource), $this->getInternalPath($newSource)); } } else { @@ -349,7 +349,7 @@ class Shared extends \OC\Files\Storage\Common { return $this->unlink($path1); } } else { - $storage = \OC_Filesystem::getStorage($oldSource); + $storage = \OC\Files\Filesystem::getStorage($oldSource); return $storage->rename($this->getInternalPath($oldSource), $this->getInternalPath($newSource)); } } @@ -394,8 +394,8 @@ class Shared extends \OC\Files\Storage\Common { 'source' => $source, 'mode' => $mode, ); - OCP\Util::emitHook('\OC\Files\Storage\Shared', 'fopen', $info); - $storage = \OC_Filesystem::getStorage($source); + \OCP\Util::emitHook('\OC\Files\Storage\Shared', 'fopen', $info); + $storage = \OC\Files\Filesystem::getStorage($source); return $storage->fopen($this->getInternalPath($source), $mode); } return false; @@ -406,7 +406,7 @@ class Shared extends \OC\Files\Storage\Common { return 'httpd/unix-directory'; } if ($source = $this->getSourcePath($path)) { - $storage = \OC_Filesystem::getStorage($source); + $storage = \OC\Files\Filesystem::getStorage($source); return $storage->getMimeType($this->getInternalPath($source)); } return false; @@ -415,21 +415,21 @@ class Shared extends \OC\Files\Storage\Common { public function free_space($path) { $source = $this->getSourcePath($path); if ($source) { - $storage = \OC_Filesystem::getStorage($source); + $storage = \OC\Files\Filesystem::getStorage($source); return $storage->free_space($this->getInternalPath($source)); } } public function getLocalFile($path) { if ($source = $this->getSourcePath($path)) { - $storage = \OC_Filesystem::getStorage($source); + $storage = \OC\Files\Filesystem::getStorage($source); return $storage->getLocalFile($this->getInternalPath($source)); } return false; } public function touch($path, $mtime = null) { if ($source = $this->getSourcePath($path)) { - $storage = \OC_Filesystem::getStorage($source); + $storage = \OC\Files\Filesystem::getStorage($source); return $storage->touch($this->getInternalPath($source), $mtime); } return false; @@ -437,7 +437,7 @@ class Shared extends \OC\Files\Storage\Common { public static function setup($options) { $user_dir = $options['user_dir']; - \OC_Filesystem::mount('\OC\Files\Storage\Shared', array('sharedFolder' => '/Shared'), $user_dir.'/Shared/'); + \OC\Files\Filesystem::mount('\OC\Files\Storage\Shared', array('sharedFolder' => '/Shared'), $user_dir.'/Shared/'); } /** diff --git a/apps/files_sharing/public.php b/apps/files_sharing/public.php index 34340102a9..c5f4b39d70 100644 --- a/apps/files_sharing/public.php +++ b/apps/files_sharing/public.php @@ -73,7 +73,7 @@ if (isset($_GET['file']) || isset($_GET['dir'])) { if (isset($_GET['path'])) { $path .= $_GET['path']; $dir .= $_GET['path']; - if (!OC_Filesystem::file_exists($path)) { + if (!\OC\Files\Filesystem::file_exists($path)) { header('HTTP/1.0 404 Not Found'); $tmpl = new OCP\Template('', '404', 'guest'); $tmpl->printPage(); @@ -101,7 +101,7 @@ if (isset($_GET['file']) || isset($_GET['dir'])) { $tmpl = new OCP\Template('files_sharing', 'public', 'base'); $tmpl->assign('owner', $uidOwner); // Show file list - if (OC_Filesystem::is_dir($path)) { + if (\OC\Files\Filesystem::is_dir($path)) { OCP\Util::addStyle('files', 'files'); OCP\Util::addScript('files', 'files'); OCP\Util::addScript('files', 'filelist'); @@ -157,7 +157,7 @@ if (isset($_GET['file']) || isset($_GET['dir'])) { $tmpl->assign('uidOwner', $uidOwner); $tmpl->assign('dir', basename($dir)); $tmpl->assign('filename', basename($path)); - $tmpl->assign('mimetype', OC_Filesystem::getMimeType($path)); + $tmpl->assign('mimetype', \OC\Files\Filesystem::getMimeType($path)); $tmpl->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true))); if (isset($_GET['path'])) { $getPath = $_GET['path']; @@ -170,7 +170,7 @@ if (isset($_GET['file']) || isset($_GET['dir'])) { $tmpl->assign('uidOwner', $uidOwner); $tmpl->assign('dir', dirname($path)); $tmpl->assign('filename', basename($path)); - $tmpl->assign('mimetype', OC_Filesystem::getMimeType($path)); + $tmpl->assign('mimetype', \OC\Files\Filesystem::getMimeType($path)); if ($type == 'file') { $tmpl->assign('downloadURL', OCP\Util::linkToPublic('files').'&file='.$_GET['file'].'&download'); } else { diff --git a/apps/files_versions/lib/hooks.php b/apps/files_versions/lib/hooks.php index 9ec0b01a7f..7cb3170df2 100644 --- a/apps/files_versions/lib/hooks.php +++ b/apps/files_versions/lib/hooks.php @@ -21,9 +21,9 @@ class Hooks { if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') { - $versions = new Storage( new \OC_FilesystemView('') ); + $versions = new Storage( new \OC\Files\View('') ); - $path = $params[\OC_Filesystem::signal_param_path]; + $path = $params[\OC\Files\Filesystem::signal_param_path]; if($path<>'') $versions->store( $path ); diff --git a/apps/files_versions/lib/versions.php b/apps/files_versions/lib/versions.php index 7d12e58f94..7f7837a742 100644 --- a/apps/files_versions/lib/versions.php +++ b/apps/files_versions/lib/versions.php @@ -58,8 +58,8 @@ class Storage { public function store($filename) { if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') { list($uid, $filename) = self::getUidAndFilename($filename); - $files_view = new \OC_FilesystemView('/'.$uid.'/files'); - $users_view = new \OC_FilesystemView('/'.$uid); + $files_view = new \OC\Files\View('/'.$uid.'/files'); + $users_view = new \OC\Files\View('/'.$uid); //check if source file already exist as version to avoid recursions. // todo does this check work? @@ -94,7 +94,7 @@ class Storage { // check mininterval if the file is being modified by the owner (all shared files should be versioned despite mininterval) if ($uid == \OCP\User::getUser()) { - $versions_fileview = new \OC_FilesystemView('/'.$uid.'/files_versions'); + $versions_fileview = new \OC\Files\View('/'.$uid.'/files_versions'); $versionsFolderName=\OCP\Config::getSystemValue('datadirectory'). $versions_fileview->getAbsolutePath(''); $matches=glob($versionsFolderName.'/'.$filename.'.v*'); sort($matches); @@ -127,7 +127,7 @@ class Storage { if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') { list($uid, $filename) = self::getUidAndFilename($filename); - $users_view = new \OC_FilesystemView('/'.$uid); + $users_view = new \OC\Files\View('/'.$uid); // rollback if( @$users_view->copy('files_versions'.$filename.'.v'.$revision, 'files'.$filename) ) { @@ -150,7 +150,7 @@ class Storage { public static function isversioned($filename) { if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') { list($uid, $filename) = self::getUidAndFilename($filename); - $versions_fileview = new \OC_FilesystemView('/'.$uid.'/files_versions'); + $versions_fileview = new \OC\Files\View('/'.$uid.'/files_versions'); $versionsFolderName=\OCP\Config::getSystemValue('datadirectory'). $versions_fileview->getAbsolutePath(''); @@ -178,7 +178,7 @@ class Storage { if( \OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true' ) { list($uid, $filename) = self::getUidAndFilename($filename); - $versions_fileview = new \OC_FilesystemView('/'.$uid.'/files_versions'); + $versions_fileview = new \OC\Files\View('/'.$uid.'/files_versions'); $versionsFolderName = \OCP\Config::getSystemValue('datadirectory'). $versions_fileview->getAbsolutePath(''); $versions = array(); @@ -190,7 +190,7 @@ class Storage { $i = 0; - $files_view = new \OC_FilesystemView('/'.$uid.'/files'); + $files_view = new \OC\Files\View('/'.$uid.'/files'); $local_file = $files_view->getLocalFile($filename); foreach( $matches as $ma ) { @@ -245,7 +245,7 @@ class Storage { public static function expire($filename) { if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') { list($uid, $filename) = self::getUidAndFilename($filename); - $versions_fileview = new \OC_FilesystemView('/'.$uid.'/files_versions'); + $versions_fileview = new \OC\Files\View('/'.$uid.'/files_versions'); $versionsFolderName=\OCP\Config::getSystemValue('datadirectory'). $versions_fileview->getAbsolutePath(''); diff --git a/lib/connector/sabre/directory.php b/lib/connector/sabre/directory.php index 413efef73b..4fff3ba51b 100644 --- a/lib/connector/sabre/directory.php +++ b/lib/connector/sabre/directory.php @@ -62,7 +62,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa } } else { $newPath = $this->path . '/' . $name; - OC_Filesystem::file_put_contents($newPath, $data); + \OC\Files\Filesystem::file_put_contents($newPath, $data); return OC_Connector_Sabre_Node::getETagPropertyForPath($newPath); } @@ -78,7 +78,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa public function createDirectory($name) { $newPath = $this->path . '/' . $name; - OC_Filesystem::mkdir($newPath); + \OC\Files\Filesystem::mkdir($newPath); } @@ -154,7 +154,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa public function childExists($name) { $path = $this->path . '/' . $name; - return OC_Filesystem::file_exists($path); + return \OC\Files\Filesystem::file_exists($path); } @@ -167,7 +167,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa if ($this->path != "/Shared") { foreach($this->getChildren() as $child) $child->delete(); - OC_Filesystem::rmdir($this->path); + \OC\Files\Filesystem::rmdir($this->path); } } @@ -181,7 +181,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa $rootInfo=OC_FileCache_Cached::get(''); return array( $rootInfo['size'], - OC_Filesystem::free_space() + \OC\Files\Filesystem::free_space() ); } diff --git a/lib/connector/sabre/file.php b/lib/connector/sabre/file.php index 5bd38240d4..1770b49128 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\Files\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\Files\Filesystem::fopen($this->path,'rb'); } @@ -68,7 +68,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D */ public function delete() { - OC_Filesystem::unlink($this->path); + \OC\Files\Filesystem::unlink($this->path); } @@ -107,7 +107,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D * @return string|null Returns null if the ETag can not effectively be determined */ static protected function createETag($path) { - return OC_Filesystem::hash('md5', $path); + return \OC\Files\Filesystem::hash('md5', $path); } /** @@ -122,7 +122,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D return $this->fileinfo_cache['mimetype']; } - return OC_Filesystem::getMimeType($this->path); + return \OC\Files\Filesystem::getMimeType($this->path); } } diff --git a/lib/connector/sabre/node.php b/lib/connector/sabre/node.php index 72de972377..e7e83507ea 100644 --- a/lib/connector/sabre/node.php +++ b/lib/connector/sabre/node.php @@ -80,7 +80,7 @@ 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\Files\Filesystem::rename($this->path,$newPath); $this->path = $newPath; @@ -99,9 +99,9 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr */ protected function getFileinfoCache() { if (!isset($this->fileinfo_cache)) { - if ($fileinfo_cache = OC_FileCache::get($this->path)) { + if ($fileinfo_cache = \OC\Files\Filesystem::get($this->path)) { } else { - $fileinfo_cache = OC_Filesystem::stat($this->path); + $fileinfo_cache = \OC\Files\Filesystem::stat($this->path); } $this->fileinfo_cache = $fileinfo_cache; @@ -130,7 +130,7 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr * Even if the modification time is set to a custom value the access time is set to now. */ public function touch($mtime) { - OC_Filesystem::touch($this->path, $mtime); + \OC\Files\Filesystem::touch($this->path, $mtime); } /** diff --git a/lib/filechunking.php b/lib/filechunking.php index 5ab33c77ad..e616e3b12d 100644 --- a/lib/filechunking.php +++ b/lib/filechunking.php @@ -94,49 +94,49 @@ class OC_FileChunking { } public function file_assemble($path) { - $absolutePath = OC_Filesystem::normalizePath(OC_Filesystem::getView()->getAbsolutePath($path)); + $absolutePath = \OC\Files\Filesystem::normalizePath(\OC\Files\Filesystem::getView()->getAbsolutePath($path)); $data = ''; // use file_put_contents as method because that best matches what this function does - if (OC_FileProxy::runPreProxies('file_put_contents', $absolutePath, $data) && OC_Filesystem::isValidPath($path)) { - $path = OC_Filesystem::getView()->getRelativePath($absolutePath); - $exists = OC_Filesystem::file_exists($path); + if (OC_FileProxy::runPreProxies('file_put_contents', $absolutePath, $data) && \OC\Files\Filesystem::isValidPath($path)) { + $path = \OC\Files\Filesystem::getView()->getRelativePath($absolutePath); + $exists = \OC\Files\Filesystem::file_exists($path); $run = true; if(!$exists) { OC_Hook::emit( - OC_Filesystem::CLASSNAME, - OC_Filesystem::signal_create, + \OC\Files\Filesystem::CLASSNAME, + \OC\Files\Filesystem::signal_create, array( - OC_Filesystem::signal_param_path => $path, - OC_Filesystem::signal_param_run => &$run + \OC\Files\Filesystem::signal_param_path => $path, + \OC\Files\Filesystem::signal_param_run => &$run ) ); } OC_Hook::emit( - OC_Filesystem::CLASSNAME, - OC_Filesystem::signal_write, + \OC\Files\Filesystem::CLASSNAME, + \OC\Files\Filesystem::signal_write, array( - OC_Filesystem::signal_param_path => $path, - OC_Filesystem::signal_param_run => &$run + \OC\Files\Filesystem::signal_param_path => $path, + \OC\Files\Filesystem::signal_param_run => &$run ) ); if(!$run) { return false; } - $target = OC_Filesystem::fopen($path, 'w'); + $target = \OC\Files\Filesystem::fopen($path, 'w'); if($target) { $count = $this->assemble($target); fclose($target); if(!$exists) { OC_Hook::emit( - OC_Filesystem::CLASSNAME, - OC_Filesystem::signal_post_create, - array( OC_Filesystem::signal_param_path => $path) + \OC\Files\Filesystem::CLASSNAME, + \OC\Files\Filesystem::signal_post_create, + array( \OC\Files\Filesystem::signal_param_path => $path) ); } OC_Hook::emit( - OC_Filesystem::CLASSNAME, - OC_Filesystem::signal_post_write, - array( OC_Filesystem::signal_param_path => $path) + \OC\Files\Filesystem::CLASSNAME, + \OC\Files\Filesystem::signal_post_write, + array( \OC\Files\Filesystem::signal_param_path => $path) ); OC_FileProxy::runPostProxies('file_put_contents', $absolutePath, $count); return $count > 0; diff --git a/lib/fileproxy/quota.php b/lib/fileproxy/quota.php index 5a0dbdb6fe..bc5ef9c8df 100644 --- a/lib/fileproxy/quota.php +++ b/lib/fileproxy/quota.php @@ -88,7 +88,7 @@ class OC_FileProxy_Quota extends OC_FileProxy{ public function preCopy($path1,$path2) { if(!self::$rootView){ - self::$rootView = new OC_FilesystemView(''); + self::$rootView = new \OC\Files\View(''); } return (self::$rootView->filesize($path1)<$this->getFreeSpace() or $this->getFreeSpace()==0); } diff --git a/lib/files.php b/lib/files.php index 2b2b8b42dc..29322cf2d0 100644 --- a/lib/files.php +++ b/lib/files.php @@ -46,10 +46,10 @@ class OC_Files { 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['size'] = \OC\Files\Filesystem::filesize($path); + $info['mtime'] = \OC\Files\Filesystem::filemtime($path); + $info['ctime'] = \OC\Files\Filesystem::filectime($path); + $info['mimetype'] = \OC\Files\Filesystem::getMimeType($path); $info['encrypted'] = false; $info['versioned'] = false; } @@ -64,7 +64,7 @@ class OC_Files { * @param dir $directory path under datadirectory */ public static function getDirectoryContent($directory, $mimetype_filter = '') { - $directory=OC_Filesystem::normalizePath($directory); + $directory=\OC\Files\Filesystem::normalizePath($directory); if($directory=='/') { $directory=''; } @@ -151,17 +151,17 @@ class OC_Files { } foreach($files as $file) { $file=$dir.'/'.$file; - if(OC_Filesystem::is_file($file)) { - $tmpFile=OC_Filesystem::toTmpFile($file); + if(\OC\Files\Filesystem::is_file($file)) { + $tmpFile=OC_F\OC\Files\Filesystemilesystem::toTmpFile($file); self::$tmpFiles[]=$tmpFile; $zip->addFile($tmpFile,basename($file)); - }elseif(OC_Filesystem::is_dir($file)) { + }elseif(\OC\Files\Filesystem::is_dir($file)) { self::zipAddDir($file,$zip); } } $zip->close(); set_time_limit($executionTime); - }elseif(OC_Filesystem::is_dir($dir.'/'.$files)) { + }elseif(\OC\Files\Filesystem::is_dir($dir.'/'.$files)) { self::validateZipDownload($dir,$files); $executionTime = intval(ini_get('max_execution_time')); set_time_limit(0); @@ -179,7 +179,7 @@ class OC_Files { $filename=$dir.'/'.$files; } @ob_end_clean(); - if($zip or OC_Filesystem::is_readable($filename)) { + if($zip or \OC\Files\Filesystem::is_readable($filename)) { header('Content-Disposition: attachment; filename="'.basename($filename).'"'); header('Content-Transfer-Encoding: binary'); OC_Response::disableCaching(); @@ -188,9 +188,9 @@ class OC_Files { header('Content-Type: application/zip'); header('Content-Length: ' . filesize($filename)); }else{ - header('Content-Type: '.OC_Filesystem::getMimeType($filename)); + header('Content-Type: '.\OC\Files\Filesystem::getMimeType($filename)); } - }elseif($zip or !OC_Filesystem::file_exists($filename)) { + }elseif($zip or !\OC\Files\Filesystem::file_exists($filename)) { header("HTTP/1.0 404 Not Found"); $tmpl = new OC_Template( '', '404', 'guest' ); $tmpl->assign('file',$filename); @@ -201,7 +201,7 @@ class OC_Files { } if($only_header) { if(!$zip) - header("Content-Length: ".OC_Filesystem::filesize($filename)); + header("Content-Length: ".\OC\Files\Filesystem::filesize($filename)); return ; } if($zip) { @@ -215,7 +215,7 @@ class OC_Files { } unlink($filename); }else{ - OC_Filesystem::readfile($filename); + \OC\Files\Filesystem::readfile($filename); } foreach(self::$tmpFiles as $tmpFile) { if(file_exists($tmpFile) and is_file($tmpFile)) { @@ -232,11 +232,11 @@ class OC_Files { foreach($files as $file) { $filename=$file['name']; $file=$dir.'/'.$filename; - if(OC_Filesystem::is_file($file)) { - $tmpFile=OC_Filesystem::toTmpFile($file); + if(\OC\Files\Filesystem::is_file($file)) { + $tmpFile=\OC\Files\Filesystem::toTmpFile($file); OC_Files::$tmpFiles[]=$tmpFile; $zip->addFile($tmpFile,$internalDir.$filename); - }elseif(OC_Filesystem::is_dir($file)) { + }elseif(\OC\Files\Filesystem::is_dir($file)) { self::zipAddDir($file,$zip,$internalDir); } } @@ -253,7 +253,7 @@ class OC_Files { if(OC_User::isLoggedIn() && ($sourceDir != '' || $source != 'Shared')) { $targetFile=self::normalizePath($targetDir.'/'.$target); $sourceFile=self::normalizePath($sourceDir.'/'.$source); - return OC_Filesystem::rename($sourceFile,$targetFile); + return \OC\Files\Filesystem::rename($sourceFile,$targetFile); } else { return false; } @@ -271,7 +271,7 @@ class OC_Files { if(OC_User::isLoggedIn()) { $targetFile=$targetDir.'/'.$target; $sourceFile=$sourceDir.'/'.$source; - return OC_Filesystem::copy($sourceFile,$targetFile); + return \OC\Files\Filesystem::copy($sourceFile,$targetFile); } } @@ -286,9 +286,9 @@ class OC_Files { if(OC_User::isLoggedIn()) { $file=$dir.'/'.$name; if($type=='dir') { - return OC_Filesystem::mkdir($file); + return \OC\Files\Filesystem::mkdir($file); }elseif($type=='file') { - $fileHandle=OC_Filesystem::fopen($file, 'w'); + $fileHandle=\OC\Files\Filesystem::fopen($file, 'w'); if($fileHandle) { fclose($fileHandle); return true; @@ -308,7 +308,7 @@ class OC_Files { public static function delete($dir,$file) { if(OC_User::isLoggedIn() && ($dir!= '' || $file != 'Shared')) { $file=$dir.'/'.$file; - return OC_Filesystem::unlink($file); + return \OC\Files\Filesystem::unlink($file); } } @@ -339,10 +339,10 @@ class OC_Files { $totalsize = 0; if(is_array($files)) { foreach($files as $file) { - $totalsize += OC_Filesystem::filesize($dir.'/'.$file); + $totalsize += \OC\Files\Filesystem::filesize($dir.'/'.$file); } }else{ - $totalsize += OC_Filesystem::filesize($dir.'/'.$files); + $totalsize += \OC\Files\Filesystem::filesize($dir.'/'.$files); } if($totalsize > $zipLimit) { $l = OC_L10N::get('lib'); @@ -368,7 +368,7 @@ class OC_Files { * @return string guessed mime type */ static function getMimeType($path) { - return OC_Filesystem::getMimeType($path); + return \OC\Files\Filesystem::getMimeType($path); } /** @@ -378,7 +378,7 @@ class OC_Files { * @return array */ static function getTree($path) { - return OC_Filesystem::getTree($path); + return \OC\Files\Filesystem::getTree($path); } /** @@ -402,7 +402,7 @@ class OC_Files { $httpCode=$info['http_code']; curl_close($ch); if($httpCode==200 or $httpCode==0) { - OC_Filesystem::fromTmpFile($tmpfile,$dir.'/'.$file); + \OC\Files\Filesystem::fromTmpFile($tmpfile,$dir.'/'.$file); return true; }else{ return false; diff --git a/lib/files/file.php b/lib/files/file.php index b6432e6345..0d33cea7ee 100644 --- a/lib/files/file.php +++ b/lib/files/file.php @@ -30,7 +30,7 @@ class File{ public static function resolve($fullPath){ $storage = null; $internalPath = ''; - list($storage, $internalPath) = \OC_Filesystem::resolvePath($fullPath); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($fullPath); return new File($storage, $internalPath); } diff --git a/lib/helper.php b/lib/helper.php index 908a61b5a2..48e16cebd0 100644 --- a/lib/helper.php +++ b/lib/helper.php @@ -560,7 +560,7 @@ class OC_Helper { $newpath = $path . '/' . $filename; $counter = 2; - while (OC_Filesystem::file_exists($newpath)) { + while (\OC\Files\Filesystem::file_exists($newpath)) { $newname = $name . ' (' . $counter . ')' . $ext; $newpath = $path . '/' . $newname; $counter++; diff --git a/lib/image.php b/lib/image.php index 861353e039..94fe3ce827 100644 --- a/lib/image.php +++ b/lib/image.php @@ -470,7 +470,7 @@ class OC_Image { default: // this is mostly file created from encrypted file - $this->resource = imagecreatefromstring(\OC_Filesystem::file_get_contents(\OC_Filesystem::getLocalPath($imagepath))); + $this->resource = imagecreatefromstring(\OC\Files\Filesystem::file_get_contents(\OC\Files\Filesystem::getLocalPath($imagepath))); $itype = IMAGETYPE_PNG; OC_Log::write('core','OC_Image->loadFromFile, Default', OC_Log::DEBUG); break; diff --git a/lib/ocs.php b/lib/ocs.php index 7350c3c882..645380ddba 100644 --- a/lib/ocs.php +++ b/lib/ocs.php @@ -589,11 +589,11 @@ class OC_OCS { if(OC_User::userExists($user)) { // calculate the disc space $user_dir = '/'.$user.'/files'; - OC_Filesystem::init($user_dir); + \OC\Files\Filesystem::init($user_dir); $rootInfo=OC_FileCache::get(''); $sharedInfo=OC_FileCache::get('/Shared'); $used=$rootInfo['size']-$sharedInfo['size']; - $free=OC_Filesystem::free_space(); + $free=\OC\Files\Filesystem::free_space(); $total=$free+$used; if($total==0) $total=1; // prevent division by zero $relative=round(($used/$total)*10000)/100; diff --git a/lib/public/files.php b/lib/public/files.php index 90889c59ad..2d6775e01f 100644 --- a/lib/public/files.php +++ b/lib/public/files.php @@ -98,7 +98,7 @@ class Files { /** * @param string appid * @param $app app - * @return OC_FilesystemView + * @return \OC\Files\View */ public static function getStorage( $app ) { return \OC_App::getStorage( $app ); diff --git a/lib/public/share.php b/lib/public/share.php index 1db3a0b2c1..7c4ede5e88 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -515,7 +515,7 @@ class Share { $backend = self::getBackend($itemType); // Get filesystem root to add it to the file target and remove from the file source, match file_source with the file cache if ($itemType == 'file' || $itemType == 'folder') { - $root = \OC_Filesystem::getRoot(); + $root = \OC\Files\Filesystem::getRoot(); $where = 'INNER JOIN `*PREFIX*fscache` ON `file_source` = `*PREFIX*fscache`.`id`'; if (!isset($item)) { $where .= ' WHERE `file_target` IS NOT NULL'; @@ -602,7 +602,7 @@ class Share { } else { if ($itemType == 'file' || $itemType == 'folder') { $where .= ' `file_target` = ?'; - $item = \OC_Filesystem::normalizePath($item); + $item = \OC\Files\Filesystem::normalizePath($item); } else { $where .= ' `item_target` = ?'; } @@ -751,7 +751,7 @@ class Share { } else { $childItem['file_source'] = \OC_FileCache::getId($child['file_path']); } - $childItem['file_target'] = \OC_Filesystem::normalizePath($child['file_path']); + $childItem['file_target'] = \OC\Files\Filesystem::normalizePath($child['file_path']); } if (isset($item)) { if ($childItem[$column] == $item) { diff --git a/lib/util.php b/lib/util.php index 557f731522..5cf7657457 100755 --- a/lib/util.php +++ b/lib/util.php @@ -34,7 +34,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\Files\Storage\Local',array('datadir'=>$CONFIG_DATADIRECTORY),'/'); + \OC\Files\Filesystem::mount('\OC\Files\Storage\Local',array('datadir'=>$CONFIG_DATADIRECTORY),'/'); self::$rootMounted=true; } @@ -46,8 +46,8 @@ class OC_Util { mkdir( $userdirectory, 0755, true ); } //jail the user into his "home" directory - OC_Filesystem::mount('\OC\Files\Storage\Local', array('datadir' => $user_root), $user); - OC_Filesystem::init($user_dir); + \OC\Files\Filesystem::mount('\OC\Files\Storage\Local', array('datadir' => $user_root), $user); + \OC\Files\Filesystem::init($user_dir); $quotaProxy=new OC_FileProxy_Quota(); OC_FileProxy::register($quotaProxy); // Load personal mount config @@ -55,7 +55,7 @@ class OC_Util { $mountConfig = include($user_root.'/mount.php'); if (isset($mountConfig['user'][$user])) { foreach ($mountConfig['user'][$user] as $mountPoint => $options) { - OC_Filesystem::mount($options['class'], $options['options'], $mountPoint); + \OC\Files\Filesystem::mount($options['class'], $options['options'], $mountPoint); } } } @@ -64,7 +64,7 @@ class OC_Util { } public static function tearDownFS() { - OC_Filesystem::tearDown(); + \OC\Files\Filesystem::tearDown(); self::$fsSetup=false; } diff --git a/settings/personal.php b/settings/personal.php index 9297f5d91c..54002d87c5 100644 --- a/settings/personal.php +++ b/settings/personal.php @@ -25,7 +25,7 @@ if (!isset($sharedInfo['size'])) { } $used=$rootInfo['size']-$sharedSize; if($used<0) $used=0; -$free=OC_Filesystem::free_space(); +$free=\OC\Files\Filesystem::free_space(); $total=$free+$used; if($total==0) $total=1; // prevent division by zero $relative=round(($used/$total)*10000)/100; diff --git a/tests/lib/cache/file.php b/tests/lib/cache/file.php index 3e8fd8c1bb..5dcd326880 100644 --- a/tests/lib/cache/file.php +++ b/tests/lib/cache/file.php @@ -38,8 +38,8 @@ class Test_Cache_File extends Test_Cache { } //set up temporary storage - OC_Filesystem::clearMounts(); - OC_Filesystem::mount('\OC\Files\Storage\Temporary',array(),'/'); + \OC\Files\Filesystem::clearMounts(); + \OC\Files\Filesystem::mount('\OC\Files\Storage\Temporary',array(),'/'); OC_User::clearBackends(); OC_User::useBackend(new OC_User_Dummy()); diff --git a/tests/lib/filesystem.php b/tests/lib/filesystem.php index b402b86af1..af3620f570 100644 --- a/tests/lib/filesystem.php +++ b/tests/lib/filesystem.php @@ -20,6 +20,8 @@ * */ +use \OC\Files\Filesystem as Filesystem; + class Test_Filesystem extends UnitTestCase { /** * @var array tmpDirs @@ -42,64 +44,64 @@ class Test_Filesystem extends UnitTestCase { } public function setUp() { - OC_Filesystem::clearMounts(); + Filesystem::clearMounts(); } public function testMount() { - OC_Filesystem::mount('\OC\Files\Storage\Local',self::getStorageData(),'/'); - $this->assertEqual('/',OC_Filesystem::getMountPoint('/')); - $this->assertEqual('/',OC_Filesystem::getMountPoint('/some/folder')); - $this->assertEqual('',OC_Filesystem::getInternalPath('/')); - $this->assertEqual('some/folder',OC_Filesystem::getInternalPath('/some/folder')); + Filesystem::mount('\OC\Files\Storage\Local',self::getStorageData(),'/'); + $this->assertEqual('/',Filesystem::getMountPoint('/')); + $this->assertEqual('/',Filesystem::getMountPoint('/some/folder')); + $this->assertEqual('',Filesystem::getInternalPath('/')); + $this->assertEqual('some/folder',Filesystem::getInternalPath('/some/folder')); - OC_Filesystem::mount('\OC\Files\Storage\Local',self::getStorageData(),'/some'); - $this->assertEqual('/',OC_Filesystem::getMountPoint('/')); - $this->assertEqual('/some/',OC_Filesystem::getMountPoint('/some/folder')); - $this->assertEqual('/some/',OC_Filesystem::getMountPoint('/some/')); - $this->assertEqual('/',OC_Filesystem::getMountPoint('/some')); - $this->assertEqual('folder',OC_Filesystem::getInternalPath('/some/folder')); + Filesystem::mount('\OC\Files\Storage\Local',self::getStorageData(),'/some'); + $this->assertEqual('/',Filesystem::getMountPoint('/')); + $this->assertEqual('/some/',Filesystem::getMountPoint('/some/folder')); + $this->assertEqual('/some/',Filesystem::getMountPoint('/some/')); + $this->assertEqual('/',Filesystem::getMountPoint('/some')); + $this->assertEqual('folder',Filesystem::getInternalPath('/some/folder')); } public function testNormalize() { - $this->assertEqual('/path', OC_Filesystem::normalizePath('/path/')); - $this->assertEqual('/path/', OC_Filesystem::normalizePath('/path/', false)); - $this->assertEqual('/path', OC_Filesystem::normalizePath('path')); - $this->assertEqual('/path', OC_Filesystem::normalizePath('\path')); - $this->assertEqual('/foo/bar', OC_Filesystem::normalizePath('/foo//bar/')); - $this->assertEqual('/foo/bar', OC_Filesystem::normalizePath('/foo////bar')); + $this->assertEqual('/path', Filesystem::normalizePath('/path/')); + $this->assertEqual('/path/', Filesystem::normalizePath('/path/', false)); + $this->assertEqual('/path', Filesystem::normalizePath('path')); + $this->assertEqual('/path', Filesystem::normalizePath('\path')); + $this->assertEqual('/foo/bar', Filesystem::normalizePath('/foo//bar/')); + $this->assertEqual('/foo/bar', Filesystem::normalizePath('/foo////bar')); if (class_exists('Normalizer')) { - $this->assertEqual("/foo/bar\xC3\xBC", OC_Filesystem::normalizePath("/foo/baru\xCC\x88")); + $this->assertEqual("/foo/bar\xC3\xBC", Filesystem::normalizePath("/foo/baru\xCC\x88")); } } public function testHooks() { - if(OC_Filesystem::getView()){ + if(Filesystem::getView()){ $user = OC_User::getUser(); }else{ $user=uniqid(); - OC_Filesystem::init('/'.$user.'/files'); + Filesystem::init('/'.$user.'/files'); } OC_Hook::clear('OC_Filesystem'); OC_Hook::connect('OC_Filesystem', 'post_write', $this, 'dummyHook'); - OC_Filesystem::mount('OC\Files\Storage\Temporary', array(), '/'); + Filesystem::mount('OC\Files\Storage\Temporary', array(), '/'); $rootView=new \OC\Files\View(''); $rootView->mkdir('/'.$user); $rootView->mkdir('/'.$user.'/files'); - OC_Filesystem::file_put_contents('/foo', 'foo'); - OC_Filesystem::mkdir('/bar'); - OC_Filesystem::file_put_contents('/bar//foo', 'foo'); + Filesystem::file_put_contents('/foo', 'foo'); + Filesystem::mkdir('/bar'); + Filesystem::file_put_contents('/bar//foo', 'foo'); $tmpFile = OC_Helper::tmpFile(); file_put_contents($tmpFile, 'foo'); $fh = fopen($tmpFile, 'r'); - OC_Filesystem::file_put_contents('/bar//foo', $fh); + Filesystem::file_put_contents('/bar//foo', $fh); } public function dummyHook($arguments) { $path = $arguments['path']; - $this->assertEqual($path, OC_Filesystem::normalizePath($path)); //the path passed to the hook should already be normalized + $this->assertEqual($path, Filesystem::normalizePath($path)); //the path passed to the hook should already be normalized } } From 08bb5dbe3a9b2bf502e5c6e0c944867015c3795b Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 3 Oct 2012 18:19:45 +0200 Subject: [PATCH 033/347] few more test cases for scanning folders --- tests/lib/files/cache/scanner.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/lib/files/cache/scanner.php b/tests/lib/files/cache/scanner.php index 41286e69d3..1f11b9d01d 100644 --- a/tests/lib/files/cache/scanner.php +++ b/tests/lib/files/cache/scanner.php @@ -91,6 +91,13 @@ class Scanner extends \UnitTestCase { $this->assertEqual($cachedDataFolder['size'], -1); $this->assertEqual($cachedDataFolder2['size'], -1); + + $this->scanner->scan('folder', \OC\Files\Cache\Scanner::SCAN_SHALLOW); + + $cachedDataFolder = $this->cache->get(''); + $cachedDataFolder2 = $this->cache->get('folder'); + + $this->assertNotEqual($cachedDataFolder['size'], -1); } function setUp() { From a2785f57d2335d06f3fa9900298343c1d7f9253a Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 10 Oct 2012 17:45:47 +0200 Subject: [PATCH 034/347] fix cache scanner test case --- tests/lib/files/cache/scanner.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/lib/files/cache/scanner.php b/tests/lib/files/cache/scanner.php index 1f11b9d01d..e3f47047f5 100644 --- a/tests/lib/files/cache/scanner.php +++ b/tests/lib/files/cache/scanner.php @@ -94,10 +94,9 @@ class Scanner extends \UnitTestCase { $this->scanner->scan('folder', \OC\Files\Cache\Scanner::SCAN_SHALLOW); - $cachedDataFolder = $this->cache->get(''); $cachedDataFolder2 = $this->cache->get('folder'); - $this->assertNotEqual($cachedDataFolder['size'], -1); + $this->assertNotEqual($cachedDataFolder2['size'], -1); } function setUp() { From 5c6e9518edde10e0c23d0d734d2cc6d161fc15c0 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 10 Oct 2012 17:46:29 +0200 Subject: [PATCH 035/347] drop Filesystem::getInternalPath and Filesystem::getStorage in favor of Filesystem::resolvePath --- apps/files_sharing/lib/sharedstorage.php | 86 ++++++++++++------------ lib/files/filesystem.php | 31 --------- lib/files/view.php | 61 ++++++----------- lib/filesystem.php | 22 ------ tests/lib/filesystem.php | 9 ++- 5 files changed, 71 insertions(+), 138 deletions(-) diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php index e17c4b6e04..e12027a4f2 100644 --- a/apps/files_sharing/lib/sharedstorage.php +++ b/apps/files_sharing/lib/sharedstorage.php @@ -114,16 +114,16 @@ class Shared extends \OC\Files\Storage\Common { if ($path == '' || $path == '/' || !$this->isCreatable(dirname($path))) { return false; } else if ($source = $this->getSourcePath($path)) { - $storage = \OC\Files\Filesystem::getStorage($source); - return $storage->mkdir($this->getInternalPath($source)); + list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + return $storage->mkdir($internalPath); } return false; } public function rmdir($path) { if (($source = $this->getSourcePath($path)) && $this->isDeletable($path)) { - $storage = \OC\Files\Filesystem::getStorage($source); - return $storage->rmdir($this->getInternalPath($source)); + list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + return $storage->rmdir($internalPath); } return false; } @@ -134,8 +134,8 @@ class Shared extends \OC\Files\Storage\Common { \OC_FakeDirStream::$dirs['shared'] = $files; return opendir('fakedir://shared'); } else if ($source = $this->getSourcePath($path)) { - $storage = \OC\Files\Filesystem::getStorage($source); - return $storage->opendir($this->getInternalPath($source)); + list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + return $storage->opendir($internalPath); } return false; } @@ -144,16 +144,16 @@ class Shared extends \OC\Files\Storage\Common { if ($path == '' || $path == '/') { return true; } else if ($source = $this->getSourcePath($path)) { - $storage = \OC\Files\Filesystem::getStorage($source); - return $storage->is_dir($this->getInternalPath($source)); + list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + return $storage->is_dir($internalPath); } return false; } public function is_file($path) { if ($source = $this->getSourcePath($path)) { - $storage = \OC\Files\Filesystem::getStorage($source); - return $storage->is_file($this->getInternalPath($source)); + list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + return $storage->is_file($internalPath); } return false; } @@ -165,8 +165,8 @@ class Shared extends \OC\Files\Storage\Common { $stat['ctime'] = $this->filectime($path); return $stat; } else if ($source = $this->getSourcePath($path)) { - $storage = \OC\Files\Filesystem::getStorage($source); - return $storage->stat($this->getInternalPath($source)); + list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + return $storage->stat($internalPath); } return false; } @@ -175,8 +175,8 @@ class Shared extends \OC\Files\Storage\Common { if ($path == '' || $path == '/') { return 'dir'; } else if ($source = $this->getSourcePath($path)) { - $storage = \OC\Files\Filesystem::getStorage($source); - return $storage->filetype($this->getInternalPath($source)); + list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + return $storage->filetype($internalPath); } return false; } @@ -185,8 +185,8 @@ class Shared extends \OC\Files\Storage\Common { if ($path == '' || $path == '/' || $this->is_dir($path)) { return 0; } else if ($source = $this->getSourcePath($path)) { - $storage = \OC\Files\Filesystem::getStorage($source); - return $storage->filesize($this->getInternalPath($source)); + list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + return $storage->filesize($internalPath); } return false; } @@ -227,8 +227,8 @@ class Shared extends \OC\Files\Storage\Common { if ($path == '' || $path == '/') { return true; } else if ($source = $this->getSourcePath($path)) { - $storage = \OC\Files\Filesystem::getStorage($source); - return $storage->file_exists($this->getInternalPath($source)); + list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + return $storage->file_exists($internalPath); } return false; } @@ -248,8 +248,8 @@ class Shared extends \OC\Files\Storage\Common { } else { $source = $this->getSourcePath($path); if ($source) { - $storage = \OC\Files\Filesystem::getStorage($source); - return $storage->filectime($this->getInternalPath($source)); + list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + return $storage->filectime($internalPath); } } } @@ -269,8 +269,8 @@ class Shared extends \OC\Files\Storage\Common { } else { $source = $this->getSourcePath($path); if ($source) { - $storage = \OC\Files\Filesystem::getStorage($source); - return $storage->filemtime($this->getInternalPath($source)); + list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + return $storage->filemtime($internalPath); } } } @@ -283,8 +283,8 @@ class Shared extends \OC\Files\Storage\Common { 'source' => $source, ); \OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_get_contents', $info); - $storage = \OC\Files\Filesystem::getStorage($source); - return $storage->file_get_contents($this->getInternalPath($source)); + list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + return $storage->file_get_contents($internalPath); } } @@ -299,8 +299,8 @@ class Shared extends \OC\Files\Storage\Common { 'source' => $source, ); \OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_put_contents', $info); - $storage = \OC\Files\Filesystem::getStorage($source); - $result = $storage->file_put_contents($this->getInternalPath($source), $data); + list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + $result = $storage->file_put_contents($internalPath, $data); return $result; } return false; @@ -310,8 +310,8 @@ class Shared extends \OC\Files\Storage\Common { // Delete the file if DELETE permission is granted if ($source = $this->getSourcePath($path)) { if ($this->isDeletable($path)) { - $storage = \OC\Files\Filesystem::getStorage($source); - return $storage->unlink($this->getInternalPath($source)); + list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + return $storage->unlink($internalPath); } else if (dirname($path) == '/' || dirname($path) == '.') { // Unshare the file from the user if in the root of the Shared folder if ($this->is_dir($path)) { @@ -334,8 +334,9 @@ class Shared extends \OC\Files\Storage\Common { if (dirname($path1) == dirname($path2)) { // Rename the file if UPDATE permission is granted if ($this->isUpdatable($path1)) { - $storage = \OC\Files\Filesystem::getStorage($oldSource); - return $storage->rename($this->getInternalPath($oldSource), $this->getInternalPath($newSource)); + list($storage, $oldInternalPath)=\OC\Files\Filesystem::resolvePath($oldSource); + list( , $newInternalPath)=\OC\Files\Filesystem::resolvePath($newSource); + return $storage->rename($oldInternalPath, $newInternalPath); } } else { // Move the file if DELETE and CREATE permissions are granted @@ -349,8 +350,9 @@ class Shared extends \OC\Files\Storage\Common { return $this->unlink($path1); } } else { - $storage = \OC\Files\Filesystem::getStorage($oldSource); - return $storage->rename($this->getInternalPath($oldSource), $this->getInternalPath($newSource)); + list($storage, $oldInternalPath)=\OC\Files\Filesystem::resolvePath($oldSource); + list( , $newInternalPath)=\OC\Files\Filesystem::resolvePath($newSource); + return $storage->rename($oldInternalPath, $newInternalPath); } } } @@ -395,8 +397,8 @@ class Shared extends \OC\Files\Storage\Common { 'mode' => $mode, ); \OCP\Util::emitHook('\OC\Files\Storage\Shared', 'fopen', $info); - $storage = \OC\Files\Filesystem::getStorage($source); - return $storage->fopen($this->getInternalPath($source), $mode); + list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + return $storage->fopen($internalPath, $mode); } return false; } @@ -406,8 +408,8 @@ class Shared extends \OC\Files\Storage\Common { return 'httpd/unix-directory'; } if ($source = $this->getSourcePath($path)) { - $storage = \OC\Files\Filesystem::getStorage($source); - return $storage->getMimeType($this->getInternalPath($source)); + list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + return $storage->getMimeType($internalPath); } return false; } @@ -415,22 +417,22 @@ class Shared extends \OC\Files\Storage\Common { public function free_space($path) { $source = $this->getSourcePath($path); if ($source) { - $storage = \OC\Files\Filesystem::getStorage($source); - return $storage->free_space($this->getInternalPath($source)); + list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + return $storage->free_space($internalPath); } } public function getLocalFile($path) { if ($source = $this->getSourcePath($path)) { - $storage = \OC\Files\Filesystem::getStorage($source); - return $storage->getLocalFile($this->getInternalPath($source)); + list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + return $storage->getLocalFile($internalPath); } return false; } public function touch($path, $mtime = null) { if ($source = $this->getSourcePath($path)) { - $storage = \OC\Files\Filesystem::getStorage($source); - return $storage->touch($this->getInternalPath($source), $mtime); + list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + return $storage->touch($internalPath, $mtime); } return false; } diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php index f23f3a79e9..841f30c767 100644 --- a/lib/files/filesystem.php +++ b/lib/files/filesystem.php @@ -164,37 +164,6 @@ class Filesystem { return $foundMountPoint; } - /** - * get the part of the path relative to the mountpoint of the storage it's stored in - * - * @param string $path - * @return bool - */ - static public function getInternalPath($path) { - $mountPoint = self::getMountPoint($path); - $internalPath = substr($path, strlen($mountPoint)); - return $internalPath; - } - - /** - * get the storage object for a path - * - * @param string $path - * @return \OC\Files\Storage\Storage - */ - static public function getStorage($path) { - $mountpoint = self::getMountPoint($path); - if ($mountpoint) { - if (!isset(self::$storages[$mountpoint])) { - $mount = self::$mounts[$mountpoint]; - self::$storages[$mountpoint] = self::createStorage($mount['class'], $mount['arguments']); - } - return self::$storages[$mountpoint]; - }else{ - return null; - } - } - /** * resolve a path to a storage and internal path * diff --git a/lib/files/view.php b/lib/files/view.php index 230455479c..bffeb434f2 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -68,19 +68,6 @@ class View { return $this->fakeRoot; } - /** - * get the part of the path relative to the mountpoint of the storage it's stored in - * - * @param string $path - * @return bool - */ - public function getInternalPath($path) { - if (!isset($this->internal_path_cache[$path])) { - $this->internal_path_cache[$path] = Filesystem::getInternalPath($this->getAbsolutePath($path)); - } - return $this->internal_path_cache[$path]; - } - /** * get path relative to the root of the view * @@ -103,19 +90,6 @@ class View { } } - /** - * get the storage object for a path - * - * @param string $path - * @return \OC\Files\Storage\Storage - */ - public function getStorage($path) { - if (!isset($this->storage_cache[$path])) { - $this->storage_cache[$path] = Filesystem::getStorage($this->getAbsolutePath($path)); - } - return $this->storage_cache[$path]; - } - /** * get the mountpoint of the storage object for a path ( note: because a storage is not always mounted inside the fakeroot, the returned mountpoint is relative to the absolute root of the filesystem and doesn't take the chroot into account @@ -136,8 +110,9 @@ class View { */ public function getLocalFile($path) { $parent = substr($path, 0, strrpos($path, '/')); - if (Filesystem::isValidPath($parent) and $storage = $this->getStorage($path)) { - return $storage->getLocalFile($this->getInternalPath($path)); + list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($path); + if (Filesystem::isValidPath($parent) and $storage) { + return $storage->getLocalFile($internalPath); } else { return null; } @@ -149,8 +124,9 @@ class View { */ public function getLocalFolder($path) { $parent = substr($path, 0, strrpos($path, '/')); - if (Filesystem::isValidPath($parent) and $storage = $this->getStorage($path)) { - return $storage->getLocalFolder($this->getInternalPath($path)); + list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($path); + if (Filesystem::isValidPath($parent) and $storage) { + return $storage->getLocalFolder($internalPath); } else { return null; } @@ -373,8 +349,10 @@ class View { $mp1 = $this->getMountPoint($path1 . $postFix1); $mp2 = $this->getMountPoint($path2 . $postFix2); if ($mp1 == $mp2) { - if ($storage = $this->getStorage($path1)) { - $result = $storage->rename($this->getInternalPath($path1 . $postFix1), $this->getInternalPath($path2 . $postFix2)); + list($storage, $internalPath1)=\OC\Files\Filesystem::resolvePath($path1 . $postFix1); + list( , $internalPath2)=\OC\Files\Filesystem::resolvePath($path2 . $postFix2); + if ($storage) { + $result = $storage->rename($internalPath1, $internalPath2); } else { $result = false; } @@ -382,8 +360,8 @@ class View { $source = $this->fopen($path1 . $postFix1, 'r'); $target = $this->fopen($path2 . $postFix2, 'w'); $count = \OC_Helper::streamCopy($source, $target); - $storage1 = $this->getStorage($path1); - $storage1->unlink($this->getInternalPath($path1 . $postFix1)); + list($storage1, $internalPath1)=\OC\Files\Filesystem::resolvePath($path1 . $postFix1); + $storage1->unlink($internalPath1); $result = $count > 0; } if ($this->fakeRoot == Filesystem::getRoot()) { @@ -454,8 +432,10 @@ class View { $mp1 = $this->getMountPoint($path1 . $postFix1); $mp2 = $this->getMountPoint($path2 . $postFix2); if ($mp1 == $mp2) { - if ($storage = $this->getStorage($path1 . $postFix1)) { - $result = $storage->copy($this->getInternalPath($path1 . $postFix1), $this->getInternalPath($path2 . $postFix2)); + list($storage, $internalPath1)=\OC\Files\Filesystem::resolvePath($path1 . $postFix1); + list( , $internalPath2)=\OC\Files\Filesystem::resolvePath($path2 . $postFix2); + if ($storage) { + $result = $storage->copy($internalPath1, $internalPath2); } else { $result = false; } @@ -588,8 +568,9 @@ class View { array(Filesystem::signal_param_path => $path) ); } - if ($storage = $this->getStorage($path . $postFix)) { - $result = $storage->hash($type, $this->getInternalPath($path . $postFix), $raw); + list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($path . $postFix); + if ($storage) { + $result = $storage->hash($type, $internalPath, $raw); $result = \OC_FileProxy::runPostProxies('hash', $absolutePath, $result); return $result; } @@ -621,9 +602,9 @@ class View { if ($path == null) { return false; } - $internalPath = $this->getInternalPath($path . $postFix); $run = $this->runHooks($hooks, $path); - if ($run and $storage = $this->getStorage($path . $postFix)) { + list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($path . $postFix); + if ($run and $storage) { if (!is_null($extraParam)) { $result = $storage->$operation($internalPath, $extraParam); } else { diff --git a/lib/filesystem.php b/lib/filesystem.php index 4189fe36c2..587eb50d9e 100644 --- a/lib/filesystem.php +++ b/lib/filesystem.php @@ -44,28 +44,6 @@ class OC_Filesystem { return \OC\Files\Filesystem::getMountPoint($path); } - /** - * get the part of the path relative to the mountpoint of the storage it's stored in - * - * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem - * @param string $path - * @return bool - */ - static public function getInternalPath($path) { - return \OC\Files\Filesystem::getInternalPath($path); - } - - /** - * get the storage object for a path - * - * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem - * @param string $path - * @return \OC\Files\Storage\Storage - */ - static public function getStorage($path) { - return \OC\Files\Filesystem::getStorage($path); - } - /** * resolve a path to a storage and internal path * diff --git a/tests/lib/filesystem.php b/tests/lib/filesystem.php index af3620f570..6e7b4fb781 100644 --- a/tests/lib/filesystem.php +++ b/tests/lib/filesystem.php @@ -51,15 +51,18 @@ class Test_Filesystem extends UnitTestCase { Filesystem::mount('\OC\Files\Storage\Local',self::getStorageData(),'/'); $this->assertEqual('/',Filesystem::getMountPoint('/')); $this->assertEqual('/',Filesystem::getMountPoint('/some/folder')); - $this->assertEqual('',Filesystem::getInternalPath('/')); - $this->assertEqual('some/folder',Filesystem::getInternalPath('/some/folder')); + list( , $internalPath)=\OC\Files\Filesystem::resolvePath('/'); + $this->assertEqual('',$internalPath); + list( , $internalPath)=\OC\Files\Filesystem::resolvePath('/some/folder'); + $this->assertEqual('some/folder',$internalPath); Filesystem::mount('\OC\Files\Storage\Local',self::getStorageData(),'/some'); $this->assertEqual('/',Filesystem::getMountPoint('/')); $this->assertEqual('/some/',Filesystem::getMountPoint('/some/folder')); $this->assertEqual('/some/',Filesystem::getMountPoint('/some/')); $this->assertEqual('/',Filesystem::getMountPoint('/some')); - $this->assertEqual('folder',Filesystem::getInternalPath('/some/folder')); + list( , $internalPath)=\OC\Files\Filesystem::resolvePath('/some/folder'); + $this->assertEqual('folder',$internalPath); } public function testNormalize() { From 542869114ad67295d61450e637b15a1f4d3ae209 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 11 Oct 2012 23:06:57 +0200 Subject: [PATCH 036/347] implement getId for the external storage providers --- apps/files_external/lib/amazons3.php | 6 ++++++ apps/files_external/lib/dropbox.php | 6 ++++++ apps/files_external/lib/ftp.php | 4 ++++ apps/files_external/lib/google.php | 7 ++++++- apps/files_external/lib/smb.php | 4 ++++ apps/files_external/lib/swift.php | 7 +++++++ apps/files_external/lib/webdav.php | 4 ++++ 7 files changed, 37 insertions(+), 1 deletion(-) diff --git a/apps/files_external/lib/amazons3.php b/apps/files_external/lib/amazons3.php index a17a70ed38..2f7c8b35be 100644 --- a/apps/files_external/lib/amazons3.php +++ b/apps/files_external/lib/amazons3.php @@ -29,12 +29,14 @@ class AmazonS3 extends \OC\Files\Storage\Common { private $s3; private $bucket; private $objects = array(); + private $id; private static $tempFiles = array(); // TODO options: storage class, encryption server side, encrypt before upload? public function __construct($params) { + $this->id = 'amazon::'.$params['key'] . md5($params['secret']); $this->s3 = new \AmazonS3(array('key' => $params['key'], 'secret' => $params['secret'])); $this->bucket = $params['bucket']; } @@ -59,6 +61,10 @@ class AmazonS3 extends \OC\Files\Storage\Common { return false; } + public function getId(){ + return $this->id; + } + public function mkdir($path) { // Folders in Amazon S3 are 0 byte objects with a '/' at the end of the name if (substr($path, -1) != '/') { diff --git a/apps/files_external/lib/dropbox.php b/apps/files_external/lib/dropbox.php index 86dbdab9ca..351a2840d9 100755 --- a/apps/files_external/lib/dropbox.php +++ b/apps/files_external/lib/dropbox.php @@ -28,12 +28,14 @@ class Dropbox extends \OC\Files\Storage\Common { private $dropbox; private $root; + private $id; private $metaData = array(); private static $tempFiles = array(); public function __construct($params) { if (isset($params['configured']) && $params['configured'] == 'true' && isset($params['app_key']) && isset($params['app_secret']) && isset($params['token']) && isset($params['token_secret'])) { + $this->id = 'dropbox::'.$params['app_key'] . $params['token']. '/' . $params['root']; $this->root=isset($params['root'])?$params['root']:''; $oauth = new \Dropbox_OAuth_Curl($params['app_key'], $params['app_secret']); $oauth->setToken($params['token'], $params['token_secret']); @@ -81,6 +83,10 @@ class Dropbox extends \OC\Files\Storage\Common { } } + public function getId(){ + return $this->id; + } + public function mkdir($path) { $path = $this->root.$path; try { diff --git a/apps/files_external/lib/ftp.php b/apps/files_external/lib/ftp.php index 140a21ffe1..731581dacc 100644 --- a/apps/files_external/lib/ftp.php +++ b/apps/files_external/lib/ftp.php @@ -32,6 +32,10 @@ class FTP extends \OC\Files\Storage\StreamWrapper{ } } + public function getId(){ + return 'ftp::' . $this->user . '@' . $this->host . '/' . $this->root; + } + /** * construct the ftp url * @param string path diff --git a/apps/files_external/lib/google.php b/apps/files_external/lib/google.php index 51c5d219aa..e4be4de5a0 100644 --- a/apps/files_external/lib/google.php +++ b/apps/files_external/lib/google.php @@ -30,6 +30,7 @@ class Google extends \OC\Files\Storage\Common { private $oauth_token; private $sig_method; private $entries; + private $id; private static $tempFiles = array(); @@ -37,6 +38,7 @@ class Google extends \OC\Files\Storage\Common { if (isset($params['configured']) && $params['configured'] == 'true' && isset($params['token']) && isset($params['token_secret'])) { $consumer_key = isset($params['consumer_key']) ? $params['consumer_key'] : 'anonymous'; $consumer_secret = isset($params['consumer_secret']) ? $params['consumer_secret'] : 'anonymous'; + $this->id = 'google::' . $consumer_key . $consumer_secret; $this->consumer = new \OAuthConsumer($consumer_key, $consumer_secret); $this->oauth_token = new \OAuthToken($params['token'], $params['token_secret']); $this->sig_method = new \OAuthSignatureMethod_HMAC_SHA1(); @@ -177,6 +179,9 @@ class Google extends \OC\Files\Storage\Common { } } + public function getId(){ + return $this->id; + } public function mkdir($path) { $collection = dirname($path); @@ -539,4 +544,4 @@ class Google extends \OC\Files\Storage\Common { } -} \ No newline at end of file +} diff --git a/apps/files_external/lib/smb.php b/apps/files_external/lib/smb.php index 8fcdd1f722..71c7a91ec9 100644 --- a/apps/files_external/lib/smb.php +++ b/apps/files_external/lib/smb.php @@ -42,6 +42,10 @@ class SMB extends \OC\Files\Storage\StreamWrapper{ } } + public function getId(){ + return 'smb::' . $this->user . '@' . $this->host . '/' . $this->share . '/' . $this->root; + } + public function constructUrl($path) { if(substr($path,-1)=='/') { $path=substr($path,0,-1); diff --git a/apps/files_external/lib/swift.php b/apps/files_external/lib/swift.php index 8d402b2521..61f58766e8 100644 --- a/apps/files_external/lib/swift.php +++ b/apps/files_external/lib/swift.php @@ -11,6 +11,7 @@ require_once 'php-cloudfiles/cloudfiles.php'; namespace OC\Files\Storage; class SWIFT extends \OC\Files\Storage\Common{ + private $id; private $host; private $root; private $user; @@ -274,6 +275,8 @@ class SWIFT extends \OC\Files\Storage\Common{ $this->user=$params['user']; $this->root=isset($params['root'])?$params['root']:'/'; $this->secure=isset($params['secure'])?(bool)$params['secure']:true; + + $this->id = 'swift::' . $this->user . '@' . $this->host . '/' . $this->root; if(!$this->root || $this->root[0]!='/') { $this->root='/'.$this->root; } @@ -289,6 +292,10 @@ class SWIFT extends \OC\Files\Storage\Common{ } } + public function getId(){ + return $this->id; + } + public function mkdir($path) { if($this->containerExists($path)) { diff --git a/apps/files_external/lib/webdav.php b/apps/files_external/lib/webdav.php index 7c61d06a01..6ed93e9035 100644 --- a/apps/files_external/lib/webdav.php +++ b/apps/files_external/lib/webdav.php @@ -56,6 +56,10 @@ class DAV extends \OC\Files\Storage\Common{ $this->mkdir(''); } + public function getId(){ + return 'webdav::' . $this->user . '@' . $this->host . '/' . $this->root; + } + private function createBaseUri() { $baseUri='http'; if($this->secure) { From 141ff806c6cfbd349ffa232502a89a620882c409 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 11 Oct 2012 23:17:59 +0200 Subject: [PATCH 037/347] fix namespace problems for external storage backends --- apps/files_external/lib/amazons3.php | 4 +- apps/files_external/lib/dropbox.php | 4 +- apps/files_external/lib/ftp.php | 7 +-- apps/files_external/lib/google.php | 12 ++--- apps/files_external/lib/smb.php | 5 +- apps/files_external/lib/swift.php | 69 ++++++++++++++-------------- apps/files_external/lib/webdav.php | 32 ++++++------- apps/files_external/tests/config.php | 2 +- 8 files changed, 65 insertions(+), 70 deletions(-) diff --git a/apps/files_external/lib/amazons3.php b/apps/files_external/lib/amazons3.php index 2f7c8b35be..832127d3e7 100644 --- a/apps/files_external/lib/amazons3.php +++ b/apps/files_external/lib/amazons3.php @@ -20,10 +20,10 @@ * License along with this library. If not, see . */ -require_once 'aws-sdk/sdk.class.php'; - namespace OC\Files\Storage; +require_once 'aws-sdk/sdk.class.php'; + class AmazonS3 extends \OC\Files\Storage\Common { private $s3; diff --git a/apps/files_external/lib/dropbox.php b/apps/files_external/lib/dropbox.php index 351a2840d9..0f7593162e 100755 --- a/apps/files_external/lib/dropbox.php +++ b/apps/files_external/lib/dropbox.php @@ -20,10 +20,10 @@ * License along with this library. If not, see . */ -require_once 'Dropbox/autoload.php'; - namespace OC\Files\Storage; +require_once 'Dropbox/autoload.php'; + class Dropbox extends \OC\Files\Storage\Common { private $dropbox; diff --git a/apps/files_external/lib/ftp.php b/apps/files_external/lib/ftp.php index 731581dacc..dea44728f3 100644 --- a/apps/files_external/lib/ftp.php +++ b/apps/files_external/lib/ftp.php @@ -26,7 +26,7 @@ class FTP extends \OC\Files\Storage\StreamWrapper{ if(!$this->root || $this->root[0]!='/') { $this->root='/'.$this->root; } - //create the root folder if necesary + //create the root folder if necessary if (!$this->is_dir('')) { $this->mkdir(''); } @@ -38,7 +38,7 @@ class FTP extends \OC\Files\Storage\StreamWrapper{ /** * construct the ftp url - * @param string path + * @param string $path * @return string */ public function constructUrl($path) { @@ -74,7 +74,7 @@ class FTP extends \OC\Files\Storage\StreamWrapper{ }else{ $ext=''; } - $tmpFile=OCP\Files::tmpFile($ext); + $tmpFile=\OCP\Files::tmpFile($ext); \OC_CloseStreamWrapper::$callBacks[$tmpFile]=array($this,'writeBack'); if($this->file_exists($path)) { $this->getFile($path,$tmpFile); @@ -82,6 +82,7 @@ class FTP extends \OC\Files\Storage\StreamWrapper{ self::$tempFiles[$tmpFile]=$path; return fopen('close://'.$tmpFile,$mode); } + return false; } public function writeBack($tmpFile) { diff --git a/apps/files_external/lib/google.php b/apps/files_external/lib/google.php index e4be4de5a0..141fc619e3 100644 --- a/apps/files_external/lib/google.php +++ b/apps/files_external/lib/google.php @@ -20,10 +20,10 @@ * License along with this library. If not, see . */ -require_once 'Google/common.inc.php'; - namespace OC\Files\Storage; +require_once 'Google/common.inc.php'; + class Google extends \OC\Files\Storage\Common { private $consumer; @@ -62,7 +62,7 @@ class Google extends \OC\Files\Storage\Common { $tempStr .= '&' . urlencode($key) . '=' . urlencode($value); } $uri = preg_replace('/&/', '?', $tempStr, 1); - $request = OAuthRequest::from_consumer_and_token($this->consumer, $this->oauth_token, $httpMethod, $uri, $params); + $request = \OAuthRequest::from_consumer_and_token($this->consumer, $this->oauth_token, $httpMethod, $uri, $params); $request->sign_request($this->sig_method, $this->consumer, $this->oauth_token); $auth_header = $request->to_header(); $headers = array($auth_header, 'GData-Version: 3.0'); @@ -129,7 +129,7 @@ class Google extends \OC\Files\Storage\Common { private function getFeed($feedUri, $httpMethod, $postData = null) { $result = $this->sendRequest($feedUri, $httpMethod, $postData); if ($result) { - $dom = new DOMDocument(); + $dom = new \DOMDocument(); $dom->loadXML($result); return $dom; } @@ -248,7 +248,7 @@ class Google extends \OC\Files\Storage\Common { $this->entries[$name] = $entry; } } - OC_FakeDirStream::$dirs['google'.$path] = $files; + \OC_FakeDirStream::$dirs['google'.$path] = $files; return opendir('fakedir://google'.$path); } @@ -407,7 +407,7 @@ class Google extends \OC\Files\Storage\Common { $ext = ''; } $tmpFile = \OC_Helper::tmpFile($ext); - OC_CloseStreamWrapper::$callBacks[$tmpFile] = array($this, 'writeBack'); + \OC_CloseStreamWrapper::$callBacks[$tmpFile] = array($this, 'writeBack'); if ($this->file_exists($path)) { $source = $this->fopen($path, 'r'); file_put_contents($tmpFile, $source); diff --git a/apps/files_external/lib/smb.php b/apps/files_external/lib/smb.php index 71c7a91ec9..dfba3105ec 100644 --- a/apps/files_external/lib/smb.php +++ b/apps/files_external/lib/smb.php @@ -6,10 +6,10 @@ * See the COPYING-README file. */ -require_once 'smb4php/smb.php'; - namespace OC\Files\Storage; +require_once 'smb4php/smb.php'; + class SMB extends \OC\Files\Storage\StreamWrapper{ private $password; private $user; @@ -70,6 +70,7 @@ class SMB extends \OC\Files\Storage\StreamWrapper{ /** * check if a file or folder has been updated since $time + * @param string $path * @param int $time * @return bool */ diff --git a/apps/files_external/lib/swift.php b/apps/files_external/lib/swift.php index 61f58766e8..4b3f38166d 100644 --- a/apps/files_external/lib/swift.php +++ b/apps/files_external/lib/swift.php @@ -6,10 +6,10 @@ * See the COPYING-README file. */ -require_once 'php-cloudfiles/cloudfiles.php'; - namespace OC\Files\Storage; +require_once 'php-cloudfiles/cloudfiles.php'; + class SWIFT extends \OC\Files\Storage\Common{ private $id; private $host; @@ -18,15 +18,15 @@ class SWIFT extends \OC\Files\Storage\Common{ private $token; private $secure; /** - * @var CF_Authentication auth + * @var \CF_Authentication auth */ private $auth; /** - * @var CF_Connection conn + * @var \CF_Connection conn */ private $conn; /** - * @var CF_Container rootContainer + * @var \CF_Container rootContainer */ private $rootContainer; @@ -38,7 +38,7 @@ class SWIFT extends \OC\Files\Storage\Common{ /** * translate directory path to container name - * @param string path + * @param string $path * @return string */ private function getContainerName($path) { @@ -48,8 +48,8 @@ class SWIFT extends \OC\Files\Storage\Common{ /** * get container by path - * @param string path - * @return CF_Container + * @param string $path + * @return \CF_Container */ private function getContainer($path) { if($path=='' or $path=='/') { @@ -62,15 +62,15 @@ class SWIFT extends \OC\Files\Storage\Common{ $container=$this->conn->get_container($this->getContainerName($path)); $this->containers[$path]=$container; return $container; - }catch(NoSuchContainerException $e) { + }catch(\NoSuchContainerException $e) { return null; } } /** * create container - * @param string path - * @return CF_Container + * @param string $path + * @return \CF_Container */ private function createContainer($path) { if($path=='' or $path=='/' or $path=='.') { @@ -92,8 +92,8 @@ class SWIFT extends \OC\Files\Storage\Common{ /** * get object by path - * @param string path - * @return CF_Object + * @param string $path + * @return \CF_Object */ private function getObject($path) { if(isset($this->objects[$path])) { @@ -110,7 +110,7 @@ class SWIFT extends \OC\Files\Storage\Common{ $obj=$container->get_object(basename($path)); $this->objects[$path]=$obj; return $obj; - }catch(NoSuchObjectException $e) { + }catch(\NoSuchObjectException $e) { return null; } } @@ -135,8 +135,8 @@ class SWIFT extends \OC\Files\Storage\Common{ /** * create object - * @param string path - * @return CF_Object + * @param string $path + * @return \CF_Object */ private function createObject($path) { $container=$this->getContainer(dirname($path)); @@ -157,7 +157,7 @@ class SWIFT extends \OC\Files\Storage\Common{ /** * check if container for path exists - * @param string path + * @param string $path * @return bool */ private function containerExists($path) { @@ -166,15 +166,15 @@ class SWIFT extends \OC\Files\Storage\Common{ /** * get the list of emulated sub containers - * @param CF_Container container + * @param \CF_Container $container * @return array */ private function getSubContainers($container) { - $tmpFile=OCP\Files::tmpFile(); + $tmpFile=\OCP\Files::tmpFile(); $obj=$this->getSubContainerFile($container); try{ $obj->save_to_filename($tmpFile); - }catch(Exception $e) { + }catch(\Exception $e) { return array(); } $obj->save_to_filename($tmpFile); @@ -188,15 +188,15 @@ class SWIFT extends \OC\Files\Storage\Common{ /** * add an emulated sub container - * @param CF_Container container - * @param string name + * @param CF_Container $container + * @param string $name * @return bool */ private function addSubContainer($container,$name) { if(!$name) { return false; } - $tmpFile=OCP\Files::tmpFile(); + $tmpFile=\OCP\Files::tmpFile(); $obj=$this->getSubContainerFile($container); try{ $obj->save_to_filename($tmpFile); @@ -211,8 +211,7 @@ class SWIFT extends \OC\Files\Storage\Common{ $fh=fopen($tmpFile,'a'); fwrite($fh,$name."\n"); } - }catch(Exception $e) { - $containers=array(); + }catch(\Exception $e) { file_put_contents($tmpFile,$name."\n"); } @@ -223,20 +222,20 @@ class SWIFT extends \OC\Files\Storage\Common{ /** * remove an emulated sub container - * @param CF_Container container - * @param string name + * @param CF_Container $container + * @param string $name * @return bool */ private function removeSubContainer($container,$name) { if(!$name) { return false; } - $tmpFile=OCP\Files::tmpFile(); + $tmpFile=\OCP\Files::tmpFile(); $obj=$this->getSubContainerFile($container); try{ $obj->save_to_filename($tmpFile); $containers=file($tmpFile); - }catch(Exception $e) { + }catch(\Exception $e) { return false; } foreach($containers as &$sub) { @@ -258,13 +257,13 @@ class SWIFT extends \OC\Files\Storage\Common{ /** * ensure a subcontainer file exists and return it's object - * @param CF_Container container - * @return CF_Object + * @param \CF_Container $container + * @return \CF_Object */ private function getSubContainerFile($container) { try{ return $container->get_object(self::SUBCONTAINER_FILE); - }catch(NoSuchObjectException $e) { + }catch(\NoSuchObjectException $e) { return $container->create_object(self::SUBCONTAINER_FILE); } } @@ -526,11 +525,11 @@ class SWIFT extends \OC\Files\Storage\Common{ private function getTmpFile($path) { $obj=$this->getObject($path); if(!is_null($obj)) { - $tmpFile=OCP\Files::tmpFile(); + $tmpFile=\OCP\Files::tmpFile(); $obj->save_to_filename($tmpFile); return $tmpFile; }else{ - return OCP\Files::tmpFile(); + return \OCP\Files::tmpFile(); } } @@ -545,7 +544,7 @@ class SWIFT extends \OC\Files\Storage\Common{ /** * remove custom mtime metadata - * @param CF_Object obj + * @param \CF_Object $obj */ private function resetMTime($obj) { if(isset($obj->metadata['Mtime'])) { diff --git a/apps/files_external/lib/webdav.php b/apps/files_external/lib/webdav.php index 6ed93e9035..73231b6ad8 100644 --- a/apps/files_external/lib/webdav.php +++ b/apps/files_external/lib/webdav.php @@ -15,7 +15,7 @@ class DAV extends \OC\Files\Storage\Common{ private $secure; private $root; /** - * @var Sabre_DAV_Client + * @var \Sabre_DAV_Client */ private $client; @@ -92,7 +92,7 @@ class DAV extends \OC\Files\Storage\Common{ \OC_FakeDirStream::$dirs[$id][]=$file; } return opendir('fakedir://'.$id); - }catch(Exception $e) { + }catch(\Exception $e) { return false; } } @@ -103,7 +103,7 @@ class DAV extends \OC\Files\Storage\Common{ $response=$this->client->propfind($path, array('{DAV:}resourcetype')); $responseType=$response["{DAV:}resourcetype"]->resourceType; return (count($responseType)>0 and $responseType[0]=="{DAV:}collection")?'dir':'file'; - }catch(Exception $e) { + }catch(\Exception $e) { error_log($e->getMessage()); \OCP\Util::writeLog("webdav client", \OCP\Util::sanitizeHTML($e->getMessage()), \OCP\Util::ERROR); return false; @@ -123,7 +123,7 @@ class DAV extends \OC\Files\Storage\Common{ try{ $this->client->propfind($path, array('{DAV:}resourcetype')); return true;//no 404 exception - }catch(Exception $e) { + }catch(\Exception $e) { return false; } } @@ -169,7 +169,7 @@ class DAV extends \OC\Files\Storage\Common{ }else{ $ext=''; } - $tmpFile=OCP\Files::tmpFile($ext); + $tmpFile=\OCP\Files::tmpFile($ext); \OC_CloseStreamWrapper::$callBacks[$tmpFile]=array($this,'writeBack'); if($this->file_exists($path)) { $this->getFile($path,$tmpFile); @@ -195,7 +195,7 @@ class DAV extends \OC\Files\Storage\Common{ }else{ return 0; } - }catch(Exception $e) { + }catch(\Exception $e) { return 0; } } @@ -231,12 +231,9 @@ class DAV extends \OC\Files\Storage\Common{ $path1=$this->cleanPath($path1); $path2=$this->root.$this->cleanPath($path2); try{ - $response=$this->client->request('MOVE',$path1,null,array('Destination'=>$path2)); + $this->client->request('MOVE',$path1,null,array('Destination'=>$path2)); return true; - }catch(Exception $e) { - echo $e; - echo 'fail'; - var_dump($response); + }catch(\Exception $e) { return false; } } @@ -245,12 +242,9 @@ class DAV extends \OC\Files\Storage\Common{ $path1=$this->cleanPath($path1); $path2=$this->root.$this->cleanPath($path2); try{ - $response=$this->client->request('COPY',$path1,null,array('Destination'=>$path2)); + $this->client->request('COPY',$path1,null,array('Destination'=>$path2)); return true; - }catch(Exception $e) { - echo $e; - echo 'fail'; - var_dump($response); + }catch(\Exception $e) { return false; } } @@ -264,7 +258,7 @@ class DAV extends \OC\Files\Storage\Common{ 'size'=>(int)isset($response['{DAV:}getcontentlength']) ? $response['{DAV:}getcontentlength'] : 0, 'ctime'=>-1, ); - }catch(Exception $e) { + }catch(\Exception $e) { return array(); } } @@ -282,7 +276,7 @@ class DAV extends \OC\Files\Storage\Common{ }else{ return false; } - }catch(Exception $e) { + }catch(\Exception $e) { return false; } } @@ -300,7 +294,7 @@ class DAV extends \OC\Files\Storage\Common{ try{ $response=$this->client->request($method,$path,$body); return $response['statusCode']==$expected; - }catch(Exception $e) { + }catch(\Exception $e) { return false; } } diff --git a/apps/files_external/tests/config.php b/apps/files_external/tests/config.php index ff16b1c1d8..5af317675c 100644 --- a/apps/files_external/tests/config.php +++ b/apps/files_external/tests/config.php @@ -8,7 +8,7 @@ return array( 'root'=>'/test', ), 'webdav'=>array( - 'run'=>false, + 'run'=>true, 'host'=>'localhost', 'user'=>'test', 'password'=>'test', From cfa036eaa916c1adf38fb161a16c50cd050c0a3b Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sat, 20 Oct 2012 23:54:37 +0200 Subject: [PATCH 038/347] drop filectime from the filesystem api's --- apps/files_external/lib/amazons3.php | 2 -- apps/files_external/lib/dropbox.php | 1 - apps/files_external/lib/google.php | 2 -- apps/files_external/lib/swift.php | 2 -- apps/files_external/lib/webdav.php | 1 - apps/files_sharing/lib/sharedstorage.php | 22 ---------------------- lib/files.php | 3 +-- lib/files/filesystem.php | 4 ---- lib/files/storage/common.php | 4 ---- lib/files/storage/local.php | 3 --- lib/files/storage/storage.php | 1 - lib/files/view.php | 4 ---- lib/filesystem.php | 7 ------- 13 files changed, 1 insertion(+), 55 deletions(-) diff --git a/apps/files_external/lib/amazons3.php b/apps/files_external/lib/amazons3.php index 832127d3e7..c3fa4651f6 100644 --- a/apps/files_external/lib/amazons3.php +++ b/apps/files_external/lib/amazons3.php @@ -115,12 +115,10 @@ class AmazonS3 extends \OC\Files\Storage\Common { $stat['size'] = $this->s3->get_bucket_filesize($this->bucket); $stat['atime'] = time(); $stat['mtime'] = $stat['atime']; - $stat['ctime'] = $stat['atime']; } else if ($object = $this->getObject($path)) { $stat['size'] = $object['Size']; $stat['atime'] = time(); $stat['mtime'] = strtotime($object['LastModified']); - $stat['ctime'] = $stat['mtime']; } if (isset($stat)) { return $stat; diff --git a/apps/files_external/lib/dropbox.php b/apps/files_external/lib/dropbox.php index 0f7593162e..0e82f80668 100755 --- a/apps/files_external/lib/dropbox.php +++ b/apps/files_external/lib/dropbox.php @@ -119,7 +119,6 @@ class Dropbox extends \OC\Files\Storage\Common { $stat['size'] = $metaData['bytes']; $stat['atime'] = time(); $stat['mtime'] = (isset($metaData['modified'])) ? strtotime($metaData['modified']) : time(); - $stat['ctime'] = $stat['mtime']; return $stat; } return false; diff --git a/apps/files_external/lib/google.php b/apps/files_external/lib/google.php index 141fc619e3..7ee5b97f8b 100644 --- a/apps/files_external/lib/google.php +++ b/apps/files_external/lib/google.php @@ -257,14 +257,12 @@ class Google extends \OC\Files\Storage\Common { $stat['size'] = $this->free_space($path); $stat['atime'] = time(); $stat['mtime'] = time(); - $stat['ctime'] = time(); } else if ($entry = $this->getResource($path)) { // NOTE: Native resources don't have a file size $stat['size'] = $entry->getElementsByTagNameNS('http://schemas.google.com/g/2005', 'quotaBytesUsed')->item(0)->nodeValue; // if (isset($atime = $entry->getElementsByTagNameNS('http://schemas.google.com/g/2005', 'lastViewed')->item(0)->nodeValue)) // $stat['atime'] = strtotime($entry->getElementsByTagNameNS('http://schemas.google.com/g/2005', 'lastViewed')->item(0)->nodeValue); $stat['mtime'] = strtotime($entry->getElementsByTagName('updated')->item(0)->nodeValue); - $stat['ctime'] = strtotime($entry->getElementsByTagName('published')->item(0)->nodeValue); } if (isset($stat)) { return $stat; diff --git a/apps/files_external/lib/swift.php b/apps/files_external/lib/swift.php index 4b3f38166d..c3578b0c23 100644 --- a/apps/files_external/lib/swift.php +++ b/apps/files_external/lib/swift.php @@ -500,7 +500,6 @@ class SWIFT extends \OC\Files\Storage\Common{ return array( 'mtime'=>-1, 'size'=>$container->bytes_used, - 'ctime'=>-1 ); } @@ -518,7 +517,6 @@ class SWIFT extends \OC\Files\Storage\Common{ return array( 'mtime'=>$mtime, 'size'=>$obj->content_length, - 'ctime'=>-1, ); } diff --git a/apps/files_external/lib/webdav.php b/apps/files_external/lib/webdav.php index 73231b6ad8..c9785f3eb1 100644 --- a/apps/files_external/lib/webdav.php +++ b/apps/files_external/lib/webdav.php @@ -256,7 +256,6 @@ class DAV extends \OC\Files\Storage\Common{ return array( 'mtime'=>strtotime($response['{DAV:}getlastmodified']), 'size'=>(int)isset($response['{DAV:}getcontentlength']) ? $response['{DAV:}getcontentlength'] : 0, - 'ctime'=>-1, ); }catch(\Exception $e) { return array(); diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php index e12027a4f2..521dfb69f2 100644 --- a/apps/files_sharing/lib/sharedstorage.php +++ b/apps/files_sharing/lib/sharedstorage.php @@ -162,7 +162,6 @@ class Shared extends \OC\Files\Storage\Common { if ($path == '' || $path == '/') { $stat['size'] = $this->filesize($path); $stat['mtime'] = $this->filemtime($path); - $stat['ctime'] = $this->filectime($path); return $stat; } else if ($source = $this->getSourcePath($path)) { list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); @@ -233,27 +232,6 @@ class Shared extends \OC\Files\Storage\Common { return false; } - public function filectime($path) { - if ($path == '' || $path == '/') { - $ctime = 0; - if ($dh = $this->opendir($path)) { - while (($filename = readdir($dh)) !== false) { - $tempctime = $this->filectime($filename); - if ($tempctime < $ctime) { - $ctime = $tempctime; - } - } - } - return $ctime; - } else { - $source = $this->getSourcePath($path); - if ($source) { - list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); - return $storage->filectime($internalPath); - } - } - } - public function filemtime($path) { if ($path == '' || $path == '/') { $mtime = 0; diff --git a/lib/files.php b/lib/files.php index 29322cf2d0..28c8d0b449 100644 --- a/lib/files.php +++ b/lib/files.php @@ -30,13 +30,12 @@ class OC_Files { /** * get the filesystem info - * @param string path + * @param string $path * @return array * * returns an associative array with the following keys: * - size * - mtime - * - ctime * - mimetype * - encrypted * - versioned diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php index e4c269257c..94e8a56256 100644 --- a/lib/files/filesystem.php +++ b/lib/files/filesystem.php @@ -478,10 +478,6 @@ class Filesystem { return self::$defaultInstance->file_exists($path); } - static public function filectime($path) { - return self::$defaultInstance->filectime($path); - } - static public function filemtime($path) { return self::$defaultInstance->filemtime($path); } diff --git a/lib/files/storage/common.php b/lib/files/storage/common.php index 3886a04182..1740584555 100644 --- a/lib/files/storage/common.php +++ b/lib/files/storage/common.php @@ -74,10 +74,6 @@ abstract class Common extends \OC\Files\Storage\Storage { return $permissions; } // abstract public function file_exists($path); - public function filectime($path) { - $stat = $this->stat($path); - return $stat['ctime']; - } public function filemtime($path) { $stat = $this->stat($path); return $stat['mtime']; diff --git a/lib/files/storage/local.php b/lib/files/storage/local.php index 66ae5542e3..ccd69e3971 100644 --- a/lib/files/storage/local.php +++ b/lib/files/storage/local.php @@ -66,9 +66,6 @@ class Local extends \OC\Files\Storage\Common{ public function file_exists($path) { return file_exists($this->datadir.$path); } - public function filectime($path) { - return filectime($this->datadir.$path); - } public function filemtime($path) { return filemtime($this->datadir.$path); } diff --git a/lib/files/storage/storage.php b/lib/files/storage/storage.php index f149c61830..941bc3b077 100644 --- a/lib/files/storage/storage.php +++ b/lib/files/storage/storage.php @@ -29,7 +29,6 @@ abstract class Storage{ abstract public function isSharable($path); abstract public function getPermissions($path); abstract public function file_exists($path); - 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); diff --git a/lib/files/view.php b/lib/files/view.php index bffeb434f2..58e3ee6f05 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -236,10 +236,6 @@ class View { return $this->basicOperation('file_exists', $path); } - public function filectime($path) { - return $this->basicOperation('filectime', $path); - } - public function filemtime($path) { return $this->basicOperation('filemtime', $path); } diff --git a/lib/filesystem.php b/lib/filesystem.php index 587eb50d9e..9ce75aaf8c 100644 --- a/lib/filesystem.php +++ b/lib/filesystem.php @@ -306,13 +306,6 @@ class OC_Filesystem { return \OC\Files\Filesystem::file_exists($path); } - /** - * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem - */ - static public function filectime($path) { - return \OC\Files\Filesystem::filectime($path); - } - /** * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem */ From 1901ac8b17c99eef3ccd99edf877fd0a86737d17 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sun, 21 Oct 2012 00:13:16 +0200 Subject: [PATCH 039/347] drop depricated is_readable and is_writable --- lib/files.php | 2 +- lib/files/filesystem.php | 14 -------------- lib/files/view.php | 14 -------------- lib/filesystem.php | 7 ------- 4 files changed, 1 insertion(+), 36 deletions(-) diff --git a/lib/files.php b/lib/files.php index 28c8d0b449..ba111bee96 100644 --- a/lib/files.php +++ b/lib/files.php @@ -178,7 +178,7 @@ class OC_Files { $filename=$dir.'/'.$files; } @ob_end_clean(); - if($zip or \OC\Files\Filesystem::is_readable($filename)) { + if($zip or \OC\Files\Filesystem::isReadable($filename)) { header('Content-Disposition: attachment; filename="'.basename($filename).'"'); header('Content-Transfer-Encoding: binary'); OC_Response::disableCaching(); diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php index 94e8a56256..0dae774feb 100644 --- a/lib/files/filesystem.php +++ b/lib/files/filesystem.php @@ -440,20 +440,6 @@ class Filesystem { return self::$defaultInstance->readfile($path); } - /** - * @deprecated Replaced by isReadable() as part of CRUDS - */ - static public function is_readable($path) { - return self::$defaultInstance->isReadable($path); - } - - /** - * @deprecated Replaced by isCreatable(), isUpdatable(), isDeletable() as part of CRUDS - */ - static public function is_writable($path) { - return self::$defaultInstance->is_writable($path); - } - static public function isCreatable($path) { return self::$defaultInstance->isCreatable($path); } diff --git a/lib/files/view.php b/lib/files/view.php index 58e3ee6f05..a59ad8105d 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -195,20 +195,6 @@ class View { return false; } - /** - * @deprecated Replaced by isReadable() as part of CRUDS - */ - public function is_readable($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); - } - public function isCreatable($path) { return $this->basicOperation('isCreatable', $path); } diff --git a/lib/filesystem.php b/lib/filesystem.php index 9ce75aaf8c..ea0a289c8d 100644 --- a/lib/filesystem.php +++ b/lib/filesystem.php @@ -257,13 +257,6 @@ class OC_Filesystem { return \OC\Files\Filesystem::isReadable($path); } - /** - * @deprecated Replaced by isCreatable(), isUpdatable(), isDeletable() as part of CRUDS - */ - static public function is_writable($path) { - return \OC\Files\Filesystem::is_writable($path); - } - /** * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem */ From 6f1fbf97f7678f7a9a8b2e92d1cdd24fc5710d17 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sun, 21 Oct 2012 00:27:55 +0200 Subject: [PATCH 040/347] some namespaces fixed for the shared backend --- apps/files_sharing/lib/sharedstorage.php | 25 +++++++----------------- 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php index 521dfb69f2..e354314cc3 100644 --- a/apps/files_sharing/lib/sharedstorage.php +++ b/apps/files_sharing/lib/sharedstorage.php @@ -37,7 +37,7 @@ class Shared extends \OC\Files\Storage\Common { /** * @brief Get the source file path and the permissions granted for a shared file * @param string Shared target file path - * @return Returns array with the keys path and permissions or false if not found + * @return array with the keys path and permissions or false if not found */ private function getFile($target) { $target = '/'.$target; @@ -52,7 +52,7 @@ class Shared extends \OC\Files\Storage\Common { if (isset($this->files[$folder])) { $file = $this->files[$folder]; } else { - $file = OCP\Share::getItemSharedWith('folder', $folder, \OC_Share_Backend_File::FORMAT_SHARED_STORAGE); + $file = \OCP\Share::getItemSharedWith('folder', $folder, \OC_Share_Backend_File::FORMAT_SHARED_STORAGE); } if ($file) { $this->files[$target]['path'] = $file['path'].substr($target, strlen($folder)); @@ -60,13 +60,13 @@ class Shared extends \OC\Files\Storage\Common { return $this->files[$target]; } } else { - $file = OCP\Share::getItemSharedWith('file', $target, \OC_Share_Backend_File::FORMAT_SHARED_STORAGE); + $file = \OCP\Share::getItemSharedWith('file', $target, \OC_Share_Backend_File::FORMAT_SHARED_STORAGE); if ($file) { $this->files[$target] = $file; return $this->files[$target]; } } - OCP\Util::writeLog('files_sharing', 'File source not found for: '.$target, OCP\Util::ERROR); + \OCP\Util::writeLog('files_sharing', 'File source not found for: '.$target, \OCP\Util::ERROR); return false; } } @@ -74,13 +74,13 @@ class Shared extends \OC\Files\Storage\Common { /** * @brief Get the source file path for a shared file * @param string Shared target file path - * @return Returns source file path or false if not found + * @return string source file path or false if not found */ private function getSourcePath($target) { $file = $this->getFile($target); if (isset($file['path'])) { $uid = substr($file['path'], 1, strpos($file['path'], '/', 1) - 1); - \\OC\Files\Filesystem::mount('\OC\Files\Storage\Local', array('datadir' => \OC_User::getHome($uid)), $uid); + \OC\Files\Filesystem::mount('\OC\Files\Storage\Local', array('datadir' => \OC_User::getHome($uid)), $uid); return $file['path']; } return false; @@ -89,7 +89,7 @@ class Shared extends \OC\Files\Storage\Common { /** * @brief Get the permissions granted for a shared file * @param string Shared target file path - * @return Returns CRUDS permissions granted or false if not found + * @return int CRUDS permissions granted or false if not found */ public function getPermissions($target) { $file = $this->getFile($target); @@ -99,17 +99,6 @@ class Shared extends \OC\Files\Storage\Common { return false; } - /** - * @brief Get the internal path to pass to the storage filesystem call - * @param string Source file path - * @return Source file path with mount point stripped out - */ - private function getInternalPath($path) { - $mountPoint = \OC\Files\Filesystem::getMountPoint($path); - $internalPath = substr($path, strlen($mountPoint)); - return $internalPath; - } - public function mkdir($path) { if ($path == '' || $path == '/' || !$this->isCreatable(dirname($path))) { return false; From 3ff0772a05c70592360c7b11b280cc4cf45a385e Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sun, 21 Oct 2012 00:31:32 +0200 Subject: [PATCH 041/347] add getCache and getScanner to storage api in order to allow storage backends to overwride caching behaviour --- lib/files/storage/common.php | 50 ++++++------------------- lib/files/storage/storage.php | 70 ++++++++++++++++++----------------- 2 files changed, 48 insertions(+), 72 deletions(-) diff --git a/lib/files/storage/common.php b/lib/files/storage/common.php index 1740584555..de02c0d5d8 100644 --- a/lib/files/storage/common.php +++ b/lib/files/storage/common.php @@ -20,7 +20,7 @@ namespace OC\Files\Storage; * in classes which extend it, e.g. $this->stat() . */ -abstract class Common extends \OC\Files\Storage\Storage { +abstract class Common implements \OC\Files\Storage\Storage { public function __construct($parameters) {} // abstract public function getId(); @@ -123,64 +123,30 @@ abstract class Common extends \OC\Files\Storage\Storage { * deleted together with its contents. To avoid this set $empty to true */ public function deleteAll( $directory, $empty = false ) { - - // strip leading slash - if( substr( $directory, 0, 1 ) == "/" ) { - - $directory = substr( $directory, 1 ); - - } - - // strip trailing slash - if( substr( $directory, -1) == "/" ) { - - $directory = substr( $directory, 0, -1 ); - - } + $directory = trim($directory,'/'); if ( !$this->file_exists( \OCP\USER::getUser() . '/' . $directory ) || !$this->is_dir( \OCP\USER::getUser() . '/' . $directory ) ) { - return false; - } elseif( !$this->is_readable( \OCP\USER::getUser() . '/' . $directory ) ) { - return false; - } else { - $directoryHandle = $this->opendir( \OCP\USER::getUser() . '/' . $directory ); - while ( $contents = readdir( $directoryHandle ) ) { - if ( $contents != '.' && $contents != '..') { - $path = $directory . "/" . $contents; - if ( $this->is_dir( $path ) ) { - deleteAll( $path ); - } else { - $this->unlink( \OCP\USER::getUser() .'/' . $path ); // TODO: make unlink use same system path as is_dir - } } - } - //$this->closedir( $directoryHandle ); // TODO: implement closedir in OC_FSV - if ( $empty == false ) { - if ( !$this->rmdir( $directory ) ) { - - return false; - + return false; } - } - return true; } @@ -209,7 +175,7 @@ abstract class Common extends \OC\Files\Storage\Storage { return $mime; } public function hash($type,$path,$raw = false) { - $tmpFile=$this->getLocalFile(); + $tmpFile=$this->getLocalFile($path); $hash=hash($type,$tmpFile,$raw); unlink($tmpFile); return $hash; @@ -283,4 +249,12 @@ abstract class Common extends \OC\Files\Storage\Storage { public function hasUpdated($path,$time) { return $this->filemtime($path)>$time; } + + public function getCache(){ + return new \OC\Files\Cache\Cache($this); + } + + public function getScanner(){ + return new \OC\Files\Cache\Scanner($this); + } } diff --git a/lib/files/storage/storage.php b/lib/files/storage/storage.php index 941bc3b077..b1ec0bdb50 100644 --- a/lib/files/storage/storage.php +++ b/lib/files/storage/storage.php @@ -9,40 +9,40 @@ namespace OC\Files\Storage; /** - * Provde a common interface to all different storage options + * Provide a common interface to all different storage options */ -abstract class Storage{ - abstract public function __construct($parameters); - abstract public function getId(); - abstract public function mkdir($path); - abstract public function rmdir($path); - abstract public function opendir($path); - abstract public function is_dir($path); - abstract public function is_file($path); - abstract public function stat($path); - abstract public function filetype($path); - abstract public function filesize($path); - abstract public function isCreatable($path); - abstract public function isReadable($path); - abstract public function isUpdatable($path); - abstract public function isDeletable($path); - abstract public function isSharable($path); - abstract public function getPermissions($path); - abstract public function file_exists($path); - abstract public function filemtime($path); - abstract public function file_get_contents($path); - 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 getMimeType($path); - 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); - abstract public function getLocalFile($path);// get a path to a local version of the file, whether the original file is local or remote - abstract public function getLocalFolder($path);// get a path to a local version of the folder, whether the original file is local or remote +interface Storage{ + public function __construct($parameters); + public function getId(); + public function mkdir($path); + public function rmdir($path); + public function opendir($path); + public function is_dir($path); + public function is_file($path); + public function stat($path); + public function filetype($path); + public function filesize($path); + public function isCreatable($path); + public function isReadable($path); + public function isUpdatable($path); + public function isDeletable($path); + public function isSharable($path); + public function getPermissions($path); + public function file_exists($path); + public function filemtime($path); + public function file_get_contents($path); + public function file_put_contents($path,$data); + public function unlink($path); + public function rename($path1,$path2); + public function copy($path1,$path2); + public function fopen($path,$mode); + public function getMimeType($path); + public function hash($type,$path,$raw = false); + public function free_space($path); + public function search($query); + public function touch($path, $mtime=null); + public function getLocalFile($path);// get a path to a local version of the file, whether the original file is local or remote + public function getLocalFolder($path);// get a path to a local version of the folder, whether the original file is local or remote /** * check if a file or folder has been updated since $time * @param int $time @@ -51,5 +51,7 @@ abstract class Storage{ * 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); + public function hasUpdated($path,$time); + public function getCache(); + public function getScanner(); } From 01594b8610ce4f08e28010994d9cbecda4c52e35 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sun, 21 Oct 2012 00:54:34 +0200 Subject: [PATCH 042/347] remove chroot from filesystem api --- lib/files/filesystem.php | 10 ---------- lib/filesystem.php | 11 ----------- 2 files changed, 21 deletions(-) diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php index 0dae774feb..05dd698ab4 100644 --- a/lib/files/filesystem.php +++ b/lib/files/filesystem.php @@ -281,16 +281,6 @@ class Filesystem { } } - /** - * change the root to a fake root - * - * @param string $fakeRoot - * @return bool - */ - static public function chroot($fakeRoot) { - return self::$defaultInstance->chroot($fakeRoot); - } - /** * @brief get the relative path of the root data directory for the current user * @return string diff --git a/lib/filesystem.php b/lib/filesystem.php index ea0a289c8d..20b5ab2790 100644 --- a/lib/filesystem.php +++ b/lib/filesystem.php @@ -81,17 +81,6 @@ class OC_Filesystem { \OC\Files\Filesystem::tearDown(); } - /** - * change the root to a fake root - * - * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem - * @param string $fakeRoot - * @return bool - */ - static public function chroot($fakeRoot) { - return \OC\Files\Filesystem::chroot($fakeRoot); - } - /** * @brief get the relative path of the root data directory for the current user * @return string From 2522c25af726a8487ac13855e8a035b990cd69a4 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sun, 21 Oct 2012 02:12:58 +0200 Subject: [PATCH 043/347] use OC_Files::getFileInfo and OC_Files::getDirectoryContent as high level api for the filecache most apps would want to use this api instead of using the cache directly --- lib/files.php | 108 +++++++++++++++++----------------- lib/files/filesystem.php | 73 ++++++++++++++++++----- lib/files/storage/storage.php | 7 +++ tests/lib/files.php | 87 +++++++++++++++++++++++++++ 4 files changed, 204 insertions(+), 71 deletions(-) create mode 100644 tests/lib/files.php diff --git a/lib/files.php b/lib/files.php index ba111bee96..8d402c0001 100644 --- a/lib/files.php +++ b/lib/files.php @@ -41,69 +41,67 @@ class OC_Files { * - versioned */ public static function getFileInfo($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\Files\Filesystem::filesize($path); - $info['mtime'] = \OC\Files\Filesystem::filemtime($path); - $info['ctime'] = \OC\Files\Filesystem::filectime($path); - $info['mimetype'] = \OC\Files\Filesystem::getMimeType($path); - $info['encrypted'] = false; - $info['versioned'] = false; + $path=\OC\Files\Filesystem::normalizePath($path); + /** + * @var \OC\Files\Storage\Storage $storage + * @var string $path + */ + list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($path); + $cache=$storage->getCache(); + $data = $cache->get($internalPath); + + if($data['mimetype'] === 'httpd/unix-directory'){ + //add the sizes of other mountpoints to the folder + $mountPoints = \OC\Files\Filesystem::getMountPoints($path); + foreach($mountPoints as $mountPoint){ + $subStorage = \OC\Files\Filesystem::getStorage($mountPoint); + $subCache = $subStorage->getCache(); + $rootEntry = $subCache->get(''); + + $data['size'] += $rootEntry['size']; } - } else { - $info = OC_FileCache::get($path); } - return $info; + + return $data; } /** * get the content of a directory - * @param dir $directory path under datadirectory + * @param string $directory path under datadirectory + * @return array */ public static function getDirectoryContent($directory, $mimetype_filter = '') { - $directory=\OC\Files\Filesystem::normalizePath($directory); - if($directory=='/') { - $directory=''; - } - $files = array(); - if (($directory == '/Shared' || substr($directory, 0, 8) == '/Shared/') && OC_App::isEnabled('files_sharing')) { - if ($directory == '/Shared') { - $files = OCP\Share::getItemsSharedWith('file', OC_Share_Backend_File::FORMAT_FILE_APP, array('folder' => $directory, 'mimetype_filter' => $mimetype_filter)); - } else { - $pos = strpos($directory, '/', 8); - // Get shared folder name - if ($pos !== false) { - $itemTarget = substr($directory, 7, $pos - 7); - } else { - $itemTarget = substr($directory, 7); + $path=\OC\Files\Filesystem::normalizePath($directory); + /** + * @var \OC\Files\Storage\Storage $storage + * @var string $path + */ + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($path); + $cache=$storage->getCache(); + $files=$cache->getFolderContents($internalPath); //TODO: mimetype_filter + + //add a folder for any mountpoint in this directory and add the sizes of other mountpoints to the folders + $mountPoints = \OC\Files\Filesystem::getMountPoints($directory); + $dirLength = strlen($path); + foreach($mountPoints as $mountPoint){ + $subStorage = \OC\Files\Filesystem::getStorage($mountPoint); + $subCache = $subStorage->getCache(); + $rootEntry = $subCache->get(''); + + $relativePath = trim(substr($mountPoint, $dirLength), '/'); + if($pos = strpos($relativePath, '/')){ //mountpoint inside subfolder add size to the correct folder + $entryName = substr($relativePath, 0, $pos); + foreach($files as &$entry){ + if($entry['name'] === $entryName){ + $entry['size'] += $rootEntry['size']; + } } - $files = OCP\Share::getItemSharedWith('folder', $itemTarget, OC_Share_Backend_File::FORMAT_FILE_APP, array('folder' => $directory, 'mimetype_filter' => $mimetype_filter)); - } - } else { - $files = OC_FileCache::getFolderContent($directory, false, $mimetype_filter); - foreach ($files as &$file) { - $file['directory'] = $directory; - $file['type'] = ($file['mimetype'] == 'httpd/unix-directory') ? 'dir' : 'file'; - $permissions = OCP\Share::PERMISSION_READ; - // NOTE: Remove check when new encryption is merged - if (!$file['encrypted']) { - $permissions |= OCP\Share::PERMISSION_SHARE; - } - if ($file['type'] == 'dir' && $file['writable']) { - $permissions |= OCP\Share::PERMISSION_CREATE; - } - if ($file['writable']) { - $permissions |= OCP\Share::PERMISSION_UPDATE | OCP\Share::PERMISSION_DELETE; - } - $file['permissions'] = $permissions; - } - if ($directory == '' && OC_App::isEnabled('files_sharing')) { - // Add 'Shared' folder - $files = array_merge($files, OCP\Share::getItemsSharedWith('file', OC_Share_Backend_File::FORMAT_FILE_APP_ROOT)); + }else{ //mountpoint in this folder, add an entry for it + $rootEntry['name'] = $relativePath; + $files[] = $rootEntry; } } + usort($files, "fileCmp");//TODO: remove this once ajax is merged return $files; } @@ -145,7 +143,7 @@ class OC_Files { set_time_limit(0); $zip = new ZipArchive(); $filename = OC_Helper::tmpFile('.zip'); - if ($zip->open($filename, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE)!==TRUE) { + if ($zip->open($filename, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE)!==true) { exit("cannot open <$filename>\n"); } foreach($files as $file) { @@ -166,7 +164,7 @@ class OC_Files { set_time_limit(0); $zip = new ZipArchive(); $filename = OC_Helper::tmpFile('.zip'); - if ($zip->open($filename, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE)!==TRUE) { + if ($zip->open($filename, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE)!==true) { exit("cannot open <$filename>\n"); } $file=$dir.'/'.$files; @@ -446,7 +444,7 @@ class OC_Files { $setting = 'php_value '.$key.' '.$size; $hasReplaced = 0; $content = preg_replace($pattern, $setting, $htaccess, 1, $hasReplaced); - if($content !== NULL) { + if($content !== null) { $htaccess = $content; } if($hasReplaced == 0) { diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php index 05dd698ab4..b7f8483fbf 100644 --- a/lib/files/filesystem.php +++ b/lib/files/filesystem.php @@ -164,6 +164,43 @@ class Filesystem { return $foundMountPoint; } + /** + * get a list of all mount points in a directory + * + * @param string $path + * @return string[] + */ + static public function getMountPoints($path) { + $path = self::normalizePath($path); + if (strlen($path) > 1) { + $path .= '/'; + } + $pathLength = strlen($path); + + $mountPoints = array_keys(self::$mounts); + $result = array(); + foreach ($mountPoints as $mountPoint) { + if (substr($mountPoint, 0, $pathLength) === $path and strlen($mountPoint) > $pathLength) { + $result[] = $mountPoint; + } + } + return $result; + } + + /** + * get the storage mounted at $mountPoint + * + * @param string $mountPoint + * @return \OC\Files\Storage\Storage + */ + public static function getStorage($mountPoint) { + if (!isset(self::$storages[$mountPoint])) { + $mount = self::$mounts[$mountPoint]; + self::$storages[$mountPoint] = self::createStorage($mount['class'], $mount['arguments']); + } + return self::$storages[$mountPoint]; + } + /** * resolve a path to a storage and internal path * @@ -173,14 +210,14 @@ class Filesystem { static public function resolvePath($path) { $mountpoint = self::getMountPoint($path); if ($mountpoint) { - if (!isset(self::$storages[$mountpoint])) { - $mount = self::$mounts[$mountpoint]; - self::$storages[$mountpoint] = self::createStorage($mount['class'], $mount['arguments']); + $storage = self::getStorage($mountpoint); + if ($mountpoint === $path) { + $internalPath = ''; + } else { + $internalPath = substr($path, strlen($mountpoint)); } - $storage = self::$storages[$mountpoint]; - $internalPath = substr($path, strlen($mountpoint)); return array($storage, $internalPath); - }else{ + } else { return array(null, null); } } @@ -302,18 +339,22 @@ class Filesystem { /** * mount an \OC\Files\Storage\Storage in our virtual filesystem * - * @param \OC\Files\Storage\Storage $storage + * @param \OC\Files\Storage\Storage|string $class * @param array $arguments * @param string $mountpoint */ static public function mount($class, $arguments, $mountpoint) { - if ($mountpoint[0] != '/') { - $mountpoint = '/' . $mountpoint; + $mountpoint = self::normalizePath($mountpoint); + if (strlen($mountpoint) > 1) { + $mountpoint .= '/'; } - if (substr($mountpoint, -1) !== '/') { - $mountpoint = $mountpoint . '/'; + + if ($class instanceof \OC\Files\Storage\Storage) { + self::$mounts[$mountpoint] = array('class' => get_class($class), 'arguments' => $arguments); + self::$storages[$mountpoint] = $class; + } else { + self::$mounts[$mountpoint] = array('class' => $class, 'arguments' => $arguments); } - self::$mounts[$mountpoint] = array('class' => $class, 'arguments' => $arguments); } /** @@ -522,15 +563,15 @@ class Filesystem { static public function removeETagHook($params, $root = false) { if (isset($params['path'])) { - $path=$params['path']; + $path = $params['path']; } else { - $path=$params['oldpath']; + $path = $params['oldpath']; } if ($root) { // reduce path to the required part of it (no 'username/files') - $fakeRootView = new OC_FilesystemView($root); + $fakeRootView = new View($root); $count = 1; - $path=str_replace(OC_App::getStorage("files")->getAbsolutePath(), "", $fakeRootView->getAbsolutePath($path), $count); + $path = str_replace(\OC_App::getStorage("files")->getAbsolutePath(''), "", $fakeRootView->getAbsolutePath($path), $count); } $path = self::normalizePath($path); diff --git a/lib/files/storage/storage.php b/lib/files/storage/storage.php index b1ec0bdb50..853e8ba519 100644 --- a/lib/files/storage/storage.php +++ b/lib/files/storage/storage.php @@ -52,6 +52,13 @@ interface Storage{ * returning true for other changes in the folder is optional */ public function hasUpdated($path,$time); + + /** + * @return \OC\Files\Cache\Cache + */ public function getCache(); + /** + * @return \OC\Files\Cache\Scanner + */ public function getScanner(); } diff --git a/tests/lib/files.php b/tests/lib/files.php new file mode 100644 index 0000000000..9cb5276845 --- /dev/null +++ b/tests/lib/files.php @@ -0,0 +1,87 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. */ + +use \OC\Files\Filesystem as Filesystem; + +class Test_Files extends PHPUnit_Framework_TestCase { + /** + * @var \OC\Files\Storage\Storage[] $storages; + */ + private $storages = array(); + + public function setUp() { + Filesystem::clearMounts(); + } + + public function tearDown() { + foreach ($this->storages as $storage) { + $cache = $storage->getCache(); + $cache->clear(); + } + } + + public function testCacheAPI() { + $storage1 = $this->getTestStorage(); + $storage2 = $this->getTestStorage(); + $storage3 = $this->getTestStorage(); + Filesystem::mount($storage1, array(), '/'); + Filesystem::mount($storage2, array(), '/substorage'); + Filesystem::mount($storage3, array(), '/folder/anotherstorage'); + $textSize = strlen("dummy file data\n"); + $imageSize = filesize(\OC::$SERVERROOT . '/core/img/logo.png'); + $storageSize = $textSize * 2 + $imageSize; + + $cachedData = OC_Files::getFileInfo('/foo.txt'); + $this->assertEquals($textSize, $cachedData['size']); + $this->assertEquals('text/plain', $cachedData['mimetype']); + + $cachedData = OC_Files::getFileInfo('/'); + $this->assertEquals($storageSize * 3, $cachedData['size']); + $this->assertEquals('httpd/unix-directory', $cachedData['mimetype']); + + $cachedData = OC_Files::getFileInfo('/folder'); + $this->assertEquals($storageSize + $textSize, $cachedData['size']); + $this->assertEquals('httpd/unix-directory', $cachedData['mimetype']); + + $folderData = OC_Files::getDirectoryContent('/'); + /** + * expected entries: + * folder + * foo.png + * foo.txt + * substorage + */ + $this->assertEquals(4, count($folderData)); + $this->assertEquals('folder', $folderData[0]['name']); + $this->assertEquals('foo.png', $folderData[1]['name']); + $this->assertEquals('foo.txt', $folderData[2]['name']); + $this->assertEquals('substorage', $folderData[3]['name']); + + $this->assertEquals($storageSize + $textSize, $folderData[0]['size']); + $this->assertEquals($imageSize, $folderData[1]['size']); + $this->assertEquals($textSize, $folderData[2]['size']); + $this->assertEquals($storageSize, $folderData[3]['size']); + } + + /** + * @return OC\Files\Storage\Storage + */ + private function getTestStorage() { + $storage = new \OC\Files\Storage\Temporary(array()); + $textData = "dummy file data\n"; + $imgData = file_get_contents(\OC::$SERVERROOT . '/core/img/logo.png'); + $storage->mkdir('folder'); + $storage->file_put_contents('foo.txt', $textData); + $storage->file_put_contents('foo.png', $imgData); + $storage->file_put_contents('folder/bar.txt', $textData); + + $scanner = $storage->getScanner(); + $scanner->scan(''); + $this->storages[] = $storage; + return $storage; + } +} From 33cabcf590401763609570a86f7bc7540dbf1fc5 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sun, 21 Oct 2012 22:04:45 +0200 Subject: [PATCH 044/347] postpone the cost of setting up some of the external storage backends untill we actually need it --- apps/files_external/lib/ftp.php | 2 ++ apps/files_external/lib/smb.php | 7 ++---- apps/files_external/lib/streamwrapper.php | 26 ++++++++++++++++++++ apps/files_external/lib/swift.php | 29 +++++++++++++++++++++-- apps/files_external/lib/webdav.php | 23 ++++++++++++++++++ apps/files_external/tests/config.php | 2 +- 6 files changed, 81 insertions(+), 8 deletions(-) diff --git a/apps/files_external/lib/ftp.php b/apps/files_external/lib/ftp.php index dea44728f3..e76eca0be3 100644 --- a/apps/files_external/lib/ftp.php +++ b/apps/files_external/lib/ftp.php @@ -50,6 +50,7 @@ class FTP extends \OC\Files\Storage\StreamWrapper{ return $url; } public function fopen($path,$mode) { + $this->init(); switch($mode) { case 'r': case 'rb': @@ -86,6 +87,7 @@ class FTP extends \OC\Files\Storage\StreamWrapper{ } public function writeBack($tmpFile) { + $this->init(); if(isset(self::$tempFiles[$tmpFile])) { $this->uploadFile($tmpFile,self::$tempFiles[$tmpFile]); unlink($tmpFile); diff --git a/apps/files_external/lib/smb.php b/apps/files_external/lib/smb.php index dfba3105ec..4382f63003 100644 --- a/apps/files_external/lib/smb.php +++ b/apps/files_external/lib/smb.php @@ -35,11 +35,6 @@ class SMB extends \OC\Files\Storage\StreamWrapper{ if(substr($this->share,-1,1)=='/') { $this->share=substr($this->share,0,-1); } - - //create the root folder if necesary - if(!$this->is_dir('')) { - $this->mkdir(''); - } } public function getId(){ @@ -54,6 +49,7 @@ class SMB extends \OC\Files\Storage\StreamWrapper{ } public function stat($path) { + $this->init(); if(!$path and $this->root=='/') {//mtime doesn't work for shares $mtime=$this->shareMTime(); $stat=stat($this->constructUrl($path)); @@ -75,6 +71,7 @@ class SMB extends \OC\Files\Storage\StreamWrapper{ * @return bool */ public function hasUpdated($path,$time) { + $this->init(); if(!$path and $this->root=='/') { //mtime doesn't work for shares, but giving the nature of the backend, doing a full update is still just fast enough return true; diff --git a/apps/files_external/lib/streamwrapper.php b/apps/files_external/lib/streamwrapper.php index 750bdbaf4d..bc1c95c5e8 100644 --- a/apps/files_external/lib/streamwrapper.php +++ b/apps/files_external/lib/streamwrapper.php @@ -9,13 +9,29 @@ namespace OC\Files\Storage; abstract class StreamWrapper extends \OC\Files\Storage\Common{ + private $ready = false; + + protected function init(){ + if($this->ready){ + return; + } + $this->ready = true; + + //create the root folder if necesary + if(!$this->is_dir('')) { + $this->mkdir(''); + } + } + abstract public function constructUrl($path); public function mkdir($path) { + $this->init(); return mkdir($this->constructUrl($path)); } public function rmdir($path) { + $this->init(); if($this->file_exists($path)) { $succes=rmdir($this->constructUrl($path)); clearstatcache(); @@ -26,10 +42,12 @@ abstract class StreamWrapper extends \OC\Files\Storage\Common{ } public function opendir($path) { + $this->init(); return opendir($this->constructUrl($path)); } public function filetype($path) { + $this->init(); return filetype($this->constructUrl($path)); } @@ -42,16 +60,19 @@ abstract class StreamWrapper extends \OC\Files\Storage\Common{ } public function file_exists($path) { + $this->init(); return file_exists($this->constructUrl($path)); } public function unlink($path) { + $this->init(); $succes=unlink($this->constructUrl($path)); clearstatcache(); return $succes; } public function fopen($path,$mode) { + $this->init(); return fopen($this->constructUrl($path),$mode); } @@ -60,6 +81,7 @@ abstract class StreamWrapper extends \OC\Files\Storage\Common{ } public function touch($path,$mtime=null) { + $this->init(); if(is_null($mtime)) { $fh=$this->fopen($path,'a'); fwrite($fh,''); @@ -70,18 +92,22 @@ abstract class StreamWrapper extends \OC\Files\Storage\Common{ } public function getFile($path,$target) { + $this->init(); return copy($this->constructUrl($path),$target); } public function uploadFile($path,$target) { + $this->init(); return copy($path,$this->constructUrl($target)); } public function rename($path1,$path2) { + $this->init(); return rename($this->constructUrl($path1),$this->constructUrl($path2)); } public function stat($path) { + $this->init(); return stat($this->constructUrl($path)); } diff --git a/apps/files_external/lib/swift.php b/apps/files_external/lib/swift.php index c3578b0c23..55c2c3e0ac 100644 --- a/apps/files_external/lib/swift.php +++ b/apps/files_external/lib/swift.php @@ -17,6 +17,7 @@ class SWIFT extends \OC\Files\Storage\Common{ private $user; private $token; private $secure; + private $ready = false; /** * @var \CF_Authentication auth */ @@ -188,7 +189,7 @@ class SWIFT extends \OC\Files\Storage\Common{ /** * add an emulated sub container - * @param CF_Container $container + * @param \CF_Container $container * @param string $name * @return bool */ @@ -222,7 +223,7 @@ class SWIFT extends \OC\Files\Storage\Common{ /** * remove an emulated sub container - * @param CF_Container $container + * @param \CF_Container $container * @param string $name * @return bool */ @@ -279,6 +280,15 @@ class SWIFT extends \OC\Files\Storage\Common{ if(!$this->root || $this->root[0]!='/') { $this->root='/'.$this->root; } + + } + + private function init(){ + if($this->ready){ + return; + } + $this->ready = true; + $this->auth = new \CF_Authentication($this->user, $this->token, null, $this->host); $this->auth->authenticate(); @@ -297,6 +307,7 @@ class SWIFT extends \OC\Files\Storage\Common{ public function mkdir($path) { + $this->init(); if($this->containerExists($path)) { return false; }else{ @@ -306,6 +317,7 @@ class SWIFT extends \OC\Files\Storage\Common{ } public function rmdir($path) { + $this->init(); if(!$this->containerExists($path)) { return false; }else{ @@ -343,6 +355,7 @@ class SWIFT extends \OC\Files\Storage\Common{ } public function opendir($path) { + $this->init(); $container=$this->getContainer($path); $files=$this->getObjects($container); $i=array_search(self::SUBCONTAINER_FILE,$files); @@ -357,6 +370,7 @@ class SWIFT extends \OC\Files\Storage\Common{ } public function filetype($path) { + $this->init(); if($this->containerExists($path)) { return 'dir'; }else{ @@ -373,6 +387,7 @@ class SWIFT extends \OC\Files\Storage\Common{ } public function file_exists($path) { + $this->init(); if($this->is_dir($path)) { return true; }else{ @@ -381,6 +396,7 @@ class SWIFT extends \OC\Files\Storage\Common{ } public function file_get_contents($path) { + $this->init(); $obj=$this->getObject($path); if(is_null($obj)) { return false; @@ -389,6 +405,7 @@ class SWIFT extends \OC\Files\Storage\Common{ } public function file_put_contents($path,$content) { + $this->init(); $obj=$this->getObject($path); if(is_null($obj)) { $container=$this->getContainer(dirname($path)); @@ -402,6 +419,7 @@ class SWIFT extends \OC\Files\Storage\Common{ } public function unlink($path) { + $this->init(); if($this->containerExists($path)) { return $this->rmdir($path); } @@ -415,6 +433,7 @@ class SWIFT extends \OC\Files\Storage\Common{ } public function fopen($path,$mode) { + $this->init(); switch($mode) { case 'r': case 'rb': @@ -458,6 +477,7 @@ class SWIFT extends \OC\Files\Storage\Common{ } public function touch($path,$mtime=null) { + $this->init(); $obj=$this->getObject($path); if(is_null($obj)) { return false; @@ -472,6 +492,7 @@ class SWIFT extends \OC\Files\Storage\Common{ } public function rename($path1,$path2) { + $this->init(); $sourceContainer=$this->getContainer(dirname($path1)); $targetContainer=$this->getContainer(dirname($path2)); $result=$sourceContainer->move_object_to(basename($path1),$targetContainer,basename($path2)); @@ -484,6 +505,7 @@ class SWIFT extends \OC\Files\Storage\Common{ } public function copy($path1,$path2) { + $this->init(); $sourceContainer=$this->getContainer(dirname($path1)); $targetContainer=$this->getContainer(dirname($path2)); $result=$sourceContainer->copy_object_to(basename($path1),$targetContainer,basename($path2)); @@ -495,6 +517,7 @@ class SWIFT extends \OC\Files\Storage\Common{ } public function stat($path) { + $this->init(); $container=$this->getContainer($path); if (!is_null($container)) { return array( @@ -521,6 +544,7 @@ class SWIFT extends \OC\Files\Storage\Common{ } private function getTmpFile($path) { + $this->init(); $obj=$this->getObject($path); if(!is_null($obj)) { $tmpFile=\OCP\Files::tmpFile(); @@ -532,6 +556,7 @@ class SWIFT extends \OC\Files\Storage\Common{ } private function fromTmpFile($tmpFile,$path) { + $this->init(); $obj=$this->getObject($path); if(is_null($obj)) { $obj=$this->createObject($path); diff --git a/apps/files_external/lib/webdav.php b/apps/files_external/lib/webdav.php index c9785f3eb1..470a80f8cf 100644 --- a/apps/files_external/lib/webdav.php +++ b/apps/files_external/lib/webdav.php @@ -14,6 +14,7 @@ class DAV extends \OC\Files\Storage\Common{ private $host; private $secure; private $root; + private $ready; /** * @var \Sabre_DAV_Client */ @@ -37,6 +38,13 @@ class DAV extends \OC\Files\Storage\Common{ if(substr($this->root,-1,1)!='/') { $this->root.='/'; } + } + + private function init(){ + if($this->ready){ + return; + } + $this->ready = true; $settings = array( 'baseUri' => $this->createBaseUri(), @@ -70,16 +78,19 @@ class DAV extends \OC\Files\Storage\Common{ } public function mkdir($path) { + $this->init(); $path=$this->cleanPath($path); return $this->simpleResponse('MKCOL',$path,null,201); } public function rmdir($path) { + $this->init(); $path=$this->cleanPath($path); return $this->simpleResponse('DELETE',$path,null,204); } public function opendir($path) { + $this->init(); $path=$this->cleanPath($path); try{ $response=$this->client->propfind($path, array(),1); @@ -98,6 +109,7 @@ class DAV extends \OC\Files\Storage\Common{ } public function filetype($path) { + $this->init(); $path=$this->cleanPath($path); try{ $response=$this->client->propfind($path, array('{DAV:}resourcetype')); @@ -119,6 +131,7 @@ class DAV extends \OC\Files\Storage\Common{ } public function file_exists($path) { + $this->init(); $path=$this->cleanPath($path); try{ $this->client->propfind($path, array('{DAV:}resourcetype')); @@ -129,10 +142,12 @@ class DAV extends \OC\Files\Storage\Common{ } public function unlink($path) { + $this->init(); return $this->simpleResponse('DELETE',$path,null,204); } public function fopen($path,$mode) { + $this->init(); $path=$this->cleanPath($path); switch($mode) { case 'r': @@ -187,6 +202,7 @@ class DAV extends \OC\Files\Storage\Common{ } public function free_space($path) { + $this->init(); $path=$this->cleanPath($path); try{ $response=$this->client->propfind($path, array('{DAV:}quota-available-bytes')); @@ -201,6 +217,7 @@ class DAV extends \OC\Files\Storage\Common{ } public function touch($path,$mtime=null) { + $this->init(); if(is_null($mtime)) { $mtime=time(); } @@ -209,11 +226,13 @@ class DAV extends \OC\Files\Storage\Common{ } public function getFile($path,$target) { + $this->init(); $source=$this->fopen($path,'r'); file_put_contents($target,$source); } public function uploadFile($path,$target) { + $this->init(); $source=fopen($path,'r'); $curl = curl_init(); @@ -228,6 +247,7 @@ class DAV extends \OC\Files\Storage\Common{ } public function rename($path1,$path2) { + $this->init(); $path1=$this->cleanPath($path1); $path2=$this->root.$this->cleanPath($path2); try{ @@ -239,6 +259,7 @@ class DAV extends \OC\Files\Storage\Common{ } public function copy($path1,$path2) { + $this->init(); $path1=$this->cleanPath($path1); $path2=$this->root.$this->cleanPath($path2); try{ @@ -250,6 +271,7 @@ class DAV extends \OC\Files\Storage\Common{ } public function stat($path) { + $this->init(); $path=$this->cleanPath($path); try{ $response=$this->client->propfind($path, array('{DAV:}getlastmodified','{DAV:}getcontentlength')); @@ -263,6 +285,7 @@ class DAV extends \OC\Files\Storage\Common{ } public function getMimeType($path) { + $this->init(); $path=$this->cleanPath($path); try{ $response=$this->client->propfind($path, array('{DAV:}getcontenttype','{DAV:}resourcetype')); diff --git a/apps/files_external/tests/config.php b/apps/files_external/tests/config.php index 5af317675c..65127175ad 100644 --- a/apps/files_external/tests/config.php +++ b/apps/files_external/tests/config.php @@ -30,7 +30,7 @@ return array( 'root'=>'/', ), 'smb'=>array( - 'run'=>false, + 'run'=>true, 'user'=>'test', 'password'=>'test', 'host'=>'localhost', From 707bd68bb4e77b4184b578699d508750653e2d42 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sun, 21 Oct 2012 22:05:29 +0200 Subject: [PATCH 045/347] automatically scan files when needed --- lib/files.php | 463 +++++++++++++++++++++++--------------------- tests/lib/files.php | 27 ++- 2 files changed, 265 insertions(+), 225 deletions(-) diff --git a/lib/files.php b/lib/files.php index 8d402c0001..a5eec1f2a6 100644 --- a/lib/files.php +++ b/lib/files.php @@ -1,35 +1,36 @@ . -* -*/ + * ownCloud + * + * @author Frank Karlitschek + * @copyright 2012 Frank Karlitschek frank@owncloud.org + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with this library. If not, see . + * + */ /** * Class for fileserver access * */ class OC_Files { - static $tmpFiles=array(); + static $tmpFiles = array(); /** * get the filesystem info + * * @param string $path * @return array * @@ -41,19 +42,25 @@ class OC_Files { * - versioned */ public static function getFileInfo($path) { - $path=\OC\Files\Filesystem::normalizePath($path); + $path = \OC\Files\Filesystem::normalizePath($path); /** * @var \OC\Files\Storage\Storage $storage * @var string $path */ - list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($path); - $cache=$storage->getCache(); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($path); + $cache = $storage->getCache(); + + if (!$cache->inCache($internalPath)) { + $scanner = $storage->getScanner(); + $scanner->scan($internalPath, \OC\Files\Cache\Scanner::SCAN_SHALLOW); + } + $data = $cache->get($internalPath); - if($data['mimetype'] === 'httpd/unix-directory'){ + if ($data['mimetype'] === 'httpd/unix-directory') { //add the sizes of other mountpoints to the folder $mountPoints = \OC\Files\Filesystem::getMountPoints($path); - foreach($mountPoints as $mountPoint){ + foreach ($mountPoints as $mountPoint) { $subStorage = \OC\Files\Filesystem::getStorage($mountPoint); $subCache = $subStorage->getCache(); $rootEntry = $subCache->get(''); @@ -66,43 +73,50 @@ class OC_Files { } /** - * get the content of a directory - * @param string $directory path under datadirectory - * @return array - */ + * get the content of a directory + * + * @param string $directory path under datadirectory + * @return array + */ public static function getDirectoryContent($directory, $mimetype_filter = '') { - $path=\OC\Files\Filesystem::normalizePath($directory); + $path = \OC\Files\Filesystem::normalizePath($directory); /** * @var \OC\Files\Storage\Storage $storage * @var string $path */ list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($path); - $cache=$storage->getCache(); - $files=$cache->getFolderContents($internalPath); //TODO: mimetype_filter + $cache = $storage->getCache(); + + if (!$cache->inCache($internalPath)) { + $scanner = $storage->getScanner(); + $scanner->scan($internalPath, \OC\Files\Cache\Scanner::SCAN_SHALLOW); + } + + $files = $cache->getFolderContents($internalPath); //TODO: mimetype_filter //add a folder for any mountpoint in this directory and add the sizes of other mountpoints to the folders $mountPoints = \OC\Files\Filesystem::getMountPoints($directory); $dirLength = strlen($path); - foreach($mountPoints as $mountPoint){ + foreach ($mountPoints as $mountPoint) { $subStorage = \OC\Files\Filesystem::getStorage($mountPoint); $subCache = $subStorage->getCache(); $rootEntry = $subCache->get(''); $relativePath = trim(substr($mountPoint, $dirLength), '/'); - if($pos = strpos($relativePath, '/')){ //mountpoint inside subfolder add size to the correct folder + if ($pos = strpos($relativePath, '/')) { //mountpoint inside subfolder add size to the correct folder $entryName = substr($relativePath, 0, $pos); - foreach($files as &$entry){ - if($entry['name'] === $entryName){ + foreach ($files as &$entry) { + if ($entry['name'] === $entryName) { $entry['size'] += $rootEntry['size']; } } - }else{ //mountpoint in this folder, add an entry for it + } else { //mountpoint in this folder, add an entry for it $rootEntry['name'] = $relativePath; $files[] = $rootEntry; } } - usort($files, "fileCmp");//TODO: remove this once ajax is merged + usort($files, "fileCmp"); //TODO: remove this once ajax is merged return $files; } @@ -113,12 +127,11 @@ class OC_Files { // get next subdir to check $dir = array_pop($dirs_to_check); $dir_content = self::getDirectoryContent($dir, $mimetype_filter); - foreach($dir_content as $file) { + foreach ($dir_content as $file) { if ($file['type'] == 'file') { - $files[] = $dir.'/'.$file['name']; - } - else { - $dirs_to_check[] = $dir.'/'.$file['name']; + $files[] = $dir . '/' . $file['name']; + } else { + $dirs_to_check[] = $dir . '/' . $file['name']; } } } @@ -126,170 +139,171 @@ class OC_Files { } /** - * return the content of a file or return a zip file containning multiply files - * - * @param dir $dir - * @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) { - if(strpos($files,';')) { - $files=explode(';',$files); + * return the content of a file or return a zip file containning multiply files + * + * @param dir $dir + * @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) { + if (strpos($files, ';')) { + $files = explode(';', $files); } - if(is_array($files)) { - self::validateZipDownload($dir,$files); + if (is_array($files)) { + self::validateZipDownload($dir, $files); $executionTime = intval(ini_get('max_execution_time')); set_time_limit(0); $zip = new ZipArchive(); $filename = OC_Helper::tmpFile('.zip'); - if ($zip->open($filename, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE)!==true) { + if ($zip->open($filename, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE) !== true) { exit("cannot open <$filename>\n"); } - foreach($files as $file) { - $file=$dir.'/'.$file; - if(\OC\Files\Filesystem::is_file($file)) { - $tmpFile=OC_F\OC\Files\Filesystemilesystem::toTmpFile($file); - self::$tmpFiles[]=$tmpFile; - $zip->addFile($tmpFile,basename($file)); - }elseif(\OC\Files\Filesystem::is_dir($file)) { - self::zipAddDir($file,$zip); + foreach ($files as $file) { + $file = $dir . '/' . $file; + if (\OC\Files\Filesystem::is_file($file)) { + $tmpFile = OC_F\OC\Files\Filesystemilesystem::toTmpFile($file); + self::$tmpFiles[] = $tmpFile; + $zip->addFile($tmpFile, basename($file)); + } elseif (\OC\Files\Filesystem::is_dir($file)) { + self::zipAddDir($file, $zip); } } $zip->close(); set_time_limit($executionTime); - }elseif(\OC\Files\Filesystem::is_dir($dir.'/'.$files)) { - self::validateZipDownload($dir,$files); + } elseif (\OC\Files\Filesystem::is_dir($dir . '/' . $files)) { + self::validateZipDownload($dir, $files); $executionTime = intval(ini_get('max_execution_time')); set_time_limit(0); $zip = new ZipArchive(); $filename = OC_Helper::tmpFile('.zip'); - if ($zip->open($filename, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE)!==true) { + if ($zip->open($filename, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE) !== true) { exit("cannot open <$filename>\n"); } - $file=$dir.'/'.$files; - self::zipAddDir($file,$zip); + $file = $dir . '/' . $files; + self::zipAddDir($file, $zip); $zip->close(); set_time_limit($executionTime); - }else{ - $zip=false; - $filename=$dir.'/'.$files; + } else { + $zip = false; + $filename = $dir . '/' . $files; } @ob_end_clean(); - if($zip or \OC\Files\Filesystem::isReadable($filename)) { - header('Content-Disposition: attachment; filename="'.basename($filename).'"'); + if ($zip or \OC\Files\Filesystem::isReadable($filename)) { + header('Content-Disposition: attachment; filename="' . basename($filename) . '"'); header('Content-Transfer-Encoding: binary'); OC_Response::disableCaching(); - if($zip) { + if ($zip) { ini_set('zlib.output_compression', 'off'); header('Content-Type: application/zip'); header('Content-Length: ' . filesize($filename)); - }else{ - header('Content-Type: '.\OC\Files\Filesystem::getMimeType($filename)); + } else { + header('Content-Type: ' . \OC\Files\Filesystem::getMimeType($filename)); } - }elseif($zip or !\OC\Files\Filesystem::file_exists($filename)) { + } elseif ($zip or !\OC\Files\Filesystem::file_exists($filename)) { header("HTTP/1.0 404 Not Found"); - $tmpl = new OC_Template( '', '404', 'guest' ); - $tmpl->assign('file',$filename); + $tmpl = new OC_Template('', '404', 'guest'); + $tmpl->assign('file', $filename); $tmpl->printPage(); - }else{ + } else { header("HTTP/1.0 403 Forbidden"); die('403 Forbidden'); } - if($only_header) { - if(!$zip) - header("Content-Length: ".\OC\Files\Filesystem::filesize($filename)); - return ; + if ($only_header) { + if (!$zip) + header("Content-Length: " . \OC\Files\Filesystem::filesize($filename)); + return; } - if($zip) { - $handle=fopen($filename,'r'); + if ($zip) { + $handle = fopen($filename, 'r'); if ($handle) { - $chunkSize = 8*1024;// 1 MB chunks + $chunkSize = 8 * 1024; // 1 MB chunks while (!feof($handle)) { echo fread($handle, $chunkSize); flush(); } } unlink($filename); - }else{ + } else { \OC\Files\Filesystem::readfile($filename); } - foreach(self::$tmpFiles as $tmpFile) { - if(file_exists($tmpFile) and is_file($tmpFile)) { + foreach (self::$tmpFiles as $tmpFile) { + if (file_exists($tmpFile) and is_file($tmpFile)) { unlink($tmpFile); } } } - public static function zipAddDir($dir,$zip,$internalDir='') { - $dirname=basename($dir); - $zip->addEmptyDir($internalDir.$dirname); - $internalDir.=$dirname.='/'; - $files=OC_Files::getdirectorycontent($dir); - foreach($files as $file) { - $filename=$file['name']; - $file=$dir.'/'.$filename; - if(\OC\Files\Filesystem::is_file($file)) { - $tmpFile=\OC\Files\Filesystem::toTmpFile($file); - OC_Files::$tmpFiles[]=$tmpFile; - $zip->addFile($tmpFile,$internalDir.$filename); - }elseif(\OC\Files\Filesystem::is_dir($file)) { - self::zipAddDir($file,$zip,$internalDir); + public static function zipAddDir($dir, $zip, $internalDir = '') { + $dirname = basename($dir); + $zip->addEmptyDir($internalDir . $dirname); + $internalDir .= $dirname .= '/'; + $files = OC_Files::getdirectorycontent($dir); + foreach ($files as $file) { + $filename = $file['name']; + $file = $dir . '/' . $filename; + if (\OC\Files\Filesystem::is_file($file)) { + $tmpFile = \OC\Files\Filesystem::toTmpFile($file); + OC_Files::$tmpFiles[] = $tmpFile; + $zip->addFile($tmpFile, $internalDir . $filename); + } elseif (\OC\Files\Filesystem::is_dir($file)) { + self::zipAddDir($file, $zip, $internalDir); } } } + /** - * move a file or folder - * - * @param dir $sourceDir - * @param file $source - * @param dir $targetDir - * @param file $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); - return \OC\Files\Filesystem::rename($sourceFile,$targetFile); + * move a file or folder + * + * @param dir $sourceDir + * @param file $source + * @param dir $targetDir + * @param file $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); + return \OC\Files\Filesystem::rename($sourceFile, $targetFile); } else { return false; } } /** - * copy a file or folder - * - * @param dir $sourceDir - * @param file $source - * @param dir $targetDir - * @param file $target - */ - public static function copy($sourceDir,$source,$targetDir,$target) { - if(OC_User::isLoggedIn()) { - $targetFile=$targetDir.'/'.$target; - $sourceFile=$sourceDir.'/'.$source; - return \OC\Files\Filesystem::copy($sourceFile,$targetFile); + * copy a file or folder + * + * @param dir $sourceDir + * @param file $source + * @param dir $targetDir + * @param file $target + */ + public static function copy($sourceDir, $source, $targetDir, $target) { + if (OC_User::isLoggedIn()) { + $targetFile = $targetDir . '/' . $target; + $sourceFile = $sourceDir . '/' . $source; + return \OC\Files\Filesystem::copy($sourceFile, $targetFile); } } /** - * create a new file or folder - * - * @param dir $dir - * @param file $name - * @param type $type - */ - public static function newFile($dir,$name,$type) { - if(OC_User::isLoggedIn()) { - $file=$dir.'/'.$name; - if($type=='dir') { + * create a new file or folder + * + * @param dir $dir + * @param file $name + * @param type $type + */ + public static function newFile($dir, $name, $type) { + if (OC_User::isLoggedIn()) { + $file = $dir . '/' . $name; + if ($type == 'dir') { return \OC\Files\Filesystem::mkdir($file); - }elseif($type=='file') { - $fileHandle=\OC\Files\Filesystem::fopen($file, 'w'); - if($fileHandle) { + } elseif ($type == 'file') { + $fileHandle = \OC\Files\Filesystem::fopen($file, 'w'); + if ($fileHandle) { fclose($fileHandle); return true; - }else{ + } else { return false; } } @@ -297,29 +311,29 @@ class OC_Files { } /** - * deletes a file or folder - * - * @param dir $dir - * @param file $name - */ - public static function delete($dir,$file) { - if(OC_User::isLoggedIn() && ($dir!= '' || $file != 'Shared')) { - $file=$dir.'/'.$file; + * deletes a file or folder + * + * @param dir $dir + * @param file $name + */ + public static function delete($dir, $file) { + if (OC_User::isLoggedIn() && ($dir != '' || $file != 'Shared')) { + $file = $dir . '/' . $file; return \OC\Files\Filesystem::unlink($file); } } /** - * checks if the selected files are within the size constraint. If not, outputs an error page. - * - * @param dir $dir - * @param files $files - */ + * checks if the selected files are within the size constraint. If not, outputs an error page. + * + * @param dir $dir + * @param files $files + */ static function validateZipDownload($dir, $files) { - if(!OC_Config::getValue('allowZipDownload', true)) { + if (!OC_Config::getValue('allowZipDownload', true)) { $l = OC_L10N::get('lib'); header("HTTP/1.0 409 Conflict"); - $tmpl = new OC_Template( '', 'error', 'user' ); + $tmpl = new OC_Template('', 'error', 'user'); $errors = array( array( 'error' => $l->t('ZIP download is turned off.'), @@ -332,19 +346,19 @@ class OC_Files { } $zipLimit = OC_Config::getValue('maxZipInputSize', OC_Helper::computerFileSize('800 MB')); - if($zipLimit > 0) { + if ($zipLimit > 0) { $totalsize = 0; - if(is_array($files)) { - foreach($files as $file) { - $totalsize += \OC\Files\Filesystem::filesize($dir.'/'.$file); + if (is_array($files)) { + foreach ($files as $file) { + $totalsize += \OC\Files\Filesystem::filesize($dir . '/' . $file); } - }else{ - $totalsize += \OC\Files\Filesystem::filesize($dir.'/'.$files); + } else { + $totalsize += \OC\Files\Filesystem::filesize($dir . '/' . $files); } - if($totalsize > $zipLimit) { + if ($totalsize > $zipLimit) { $l = OC_L10N::get('lib'); header("HTTP/1.0 409 Conflict"); - $tmpl = new OC_Template( '', 'error', 'user' ); + $tmpl = new OC_Template('', 'error', 'user'); $errors = array( array( 'error' => $l->t('Selected files too large to generate zip file.'), @@ -359,78 +373,80 @@ class OC_Files { } /** - * try to detect the mime type of a file - * - * @param string path - * @return string guessed mime type - */ + * try to detect the mime type of a file + * + * @param string path + * @return string guessed mime type + */ static function getMimeType($path) { return \OC\Files\Filesystem::getMimeType($path); } /** - * get a file tree - * - * @param string path - * @return array - */ + * get a file tree + * + * @param string path + * @return array + */ static function getTree($path) { return \OC\Files\Filesystem::getTree($path); } /** - * pull a file from a remote server - * @param string source - * @param string token - * @param string dir - * @param string file - * @return string guessed mime type - */ - static function pull($source,$token,$dir,$file) { - $tmpfile=tempnam(get_temp_dir(),'remoteCloudFile'); - $fp=fopen($tmpfile,'w+'); - $url=$source.="/files/pull.php?token=$token"; - $ch=curl_init(); - curl_setopt($ch,CURLOPT_URL,$url); + * pull a file from a remote server + * + * @param string source + * @param string token + * @param string dir + * @param string file + * @return string guessed mime type + */ + static function pull($source, $token, $dir, $file) { + $tmpfile = tempnam(get_temp_dir(), 'remoteCloudFile'); + $fp = fopen($tmpfile, 'w+'); + $url = $source .= "/files/pull.php?token=$token"; + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_FILE, $fp); curl_exec($ch); fclose($fp); - $info=curl_getinfo($ch); - $httpCode=$info['http_code']; + $info = curl_getinfo($ch); + $httpCode = $info['http_code']; curl_close($ch); - if($httpCode==200 or $httpCode==0) { - \OC\Files\Filesystem::fromTmpFile($tmpfile,$dir.'/'.$file); + if ($httpCode == 200 or $httpCode == 0) { + \OC\Files\Filesystem::fromTmpFile($tmpfile, $dir . '/' . $file); return true; - }else{ + } else { return false; } } /** * set the maximum upload size limit for apache hosts using .htaccess + * * @param int size filesisze in bytes * @return false on failure, size on success */ static function setUploadLimit($size) { //don't allow user to break his config -- upper boundary - if($size > PHP_INT_MAX) { + if ($size > PHP_INT_MAX) { //max size is always 1 byte lower than computerFileSize returns - if($size > PHP_INT_MAX+1) + if ($size > PHP_INT_MAX + 1) return false; - $size -=1; + $size -= 1; } else { - $size=OC_Helper::humanFileSize($size); - $size=substr($size,0,-1);//strip the B - $size=str_replace(' ','',$size); //remove the space between the size and the postfix + $size = OC_Helper::humanFileSize($size); + $size = substr($size, 0, -1); //strip the B + $size = str_replace(' ', '', $size); //remove the space between the size and the postfix } //don't allow user to break his config -- broken or malicious size input - if(intval($size) == 0) { + if (intval($size) == 0) { return false; } - $htaccess = @file_get_contents(OC::$SERVERROOT.'/.htaccess'); //supress errors in case we don't have permissions for - if(!$htaccess) { + $htaccess = @file_get_contents(OC::$SERVERROOT . '/.htaccess'); //supress errors in case we don't have permissions for + if (!$htaccess) { return false; } @@ -439,50 +455,53 @@ class OC_Files { 'post_max_size' ); - foreach($phpValueKeys as $key) { - $pattern = '/php_value '.$key.' (\S)*/'; - $setting = 'php_value '.$key.' '.$size; - $hasReplaced = 0; - $content = preg_replace($pattern, $setting, $htaccess, 1, $hasReplaced); - if($content !== null) { + foreach ($phpValueKeys as $key) { + $pattern = '/php_value ' . $key . ' (\S)*/'; + $setting = 'php_value ' . $key . ' ' . $size; + $hasReplaced = 0; + $content = preg_replace($pattern, $setting, $htaccess, 1, $hasReplaced); + if ($content !== null) { $htaccess = $content; } - if($hasReplaced == 0) { + if ($hasReplaced == 0) { $htaccess .= "\n" . $setting; } } //check for write permissions - if(is_writable(OC::$SERVERROOT.'/.htaccess')) { - file_put_contents(OC::$SERVERROOT.'/.htaccess', $htaccess); + if (is_writable(OC::$SERVERROOT . '/.htaccess')) { + file_put_contents(OC::$SERVERROOT . '/.htaccess', $htaccess); return OC_Helper::computerFileSize($size); - } else { OC_Log::write('files','Can\'t write upload limit to '.OC::$SERVERROOT.'/.htaccess. Please check the file permissions',OC_Log::WARN); } + } else { + OC_Log::write('files', 'Can\'t write upload limit to ' . OC::$SERVERROOT . '/.htaccess. Please check the file permissions', OC_Log::WARN); + } return false; } /** * normalize a path, removing any double, add leading /, etc + * * @param string $path * @return string */ static public function normalizePath($path) { - $path='/'.$path; - $old=''; - while($old!=$path) {//replace any multiplicity of slashes with a single one - $old=$path; - $path=str_replace('//','/',$path); + $path = '/' . $path; + $old = ''; + while ($old != $path) { //replace any multiplicity of slashes with a single one + $old = $path; + $path = str_replace('//', '/', $path); } return $path; } } -function fileCmp($a,$b) { - if($a['type']=='dir' and $b['type']!='dir') { +function fileCmp($a, $b) { + if ($a['type'] == 'dir' and $b['type'] != 'dir') { return -1; - }elseif($a['type']!='dir' and $b['type']=='dir') { + } elseif ($a['type'] != 'dir' and $b['type'] == 'dir') { return 1; - }else{ - return strnatcasecmp($a['name'],$b['name']); + } else { + return strnatcasecmp($a['name'], $b['name']); } } diff --git a/tests/lib/files.php b/tests/lib/files.php index 9cb5276845..d978ac3fd1 100644 --- a/tests/lib/files.php +++ b/tests/lib/files.php @@ -67,10 +67,29 @@ class Test_Files extends PHPUnit_Framework_TestCase { $this->assertEquals($storageSize, $folderData[3]['size']); } + public function testAutoScan() { + $storage1 = $this->getTestStorage(false); + $storage2 = $this->getTestStorage(false); + Filesystem::mount($storage1, array(), '/'); + Filesystem::mount($storage2, array(), '/substorage'); + $textSize = strlen("dummy file data\n"); + $imageSize = filesize(\OC::$SERVERROOT . '/core/img/logo.png'); + $storageSize = $textSize * 2 + $imageSize; + + $cachedData = \OC_Files::getFileInfo('/'); + $this->assertEquals('httpd/unix-directory', $cachedData['mimetype']); + $this->assertEquals(-1, $cachedData['size']); + + $folderData = \OC_Files::getDirectoryContent('/substorage/folder'); + $this->assertEquals('text/plain', $folderData[0]['mimetype']); + $this->assertEquals($textSize, $folderData[0]['size']); + } + /** + * @param bool $scan * @return OC\Files\Storage\Storage */ - private function getTestStorage() { + private function getTestStorage($scan = true) { $storage = new \OC\Files\Storage\Temporary(array()); $textData = "dummy file data\n"; $imgData = file_get_contents(\OC::$SERVERROOT . '/core/img/logo.png'); @@ -79,8 +98,10 @@ class Test_Files extends PHPUnit_Framework_TestCase { $storage->file_put_contents('foo.png', $imgData); $storage->file_put_contents('folder/bar.txt', $textData); - $scanner = $storage->getScanner(); - $scanner->scan(''); + if ($scan) { + $scanner = $storage->getScanner(); + $scanner->scan(''); + } $this->storages[] = $storage; return $storage; } From 56c7ee799cb13f7a4db60663f60b76cdf223614b Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 23 Oct 2012 16:34:58 +0200 Subject: [PATCH 046/347] use strtotime on non-nummeric times in oc_filesystem::touch --- lib/files/view.php | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/lib/files/view.php b/lib/files/view.php index a59ad8105d..18d9193035 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -110,7 +110,7 @@ class View { */ public function getLocalFile($path) { $parent = substr($path, 0, strrpos($path, '/')); - list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($path); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($path); if (Filesystem::isValidPath($parent) and $storage) { return $storage->getLocalFile($internalPath); } else { @@ -124,7 +124,7 @@ class View { */ public function getLocalFolder($path) { $parent = substr($path, 0, strrpos($path, '/')); - list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($path); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($path); if (Filesystem::isValidPath($parent) and $storage) { return $storage->getLocalFolder($internalPath); } else { @@ -227,6 +227,9 @@ class View { } public function touch($path, $mtime = null) { + if (!is_null($mtime) and !is_numeric($mtime)) { + $mtime = strtotime($mtime); + } return $this->basicOperation('touch', $path, array('write'), $mtime); } @@ -331,8 +334,8 @@ class View { $mp1 = $this->getMountPoint($path1 . $postFix1); $mp2 = $this->getMountPoint($path2 . $postFix2); if ($mp1 == $mp2) { - list($storage, $internalPath1)=\OC\Files\Filesystem::resolvePath($path1 . $postFix1); - list( , $internalPath2)=\OC\Files\Filesystem::resolvePath($path2 . $postFix2); + list($storage, $internalPath1) = \OC\Files\Filesystem::resolvePath($path1 . $postFix1); + list(, $internalPath2) = \OC\Files\Filesystem::resolvePath($path2 . $postFix2); if ($storage) { $result = $storage->rename($internalPath1, $internalPath2); } else { @@ -342,7 +345,7 @@ class View { $source = $this->fopen($path1 . $postFix1, 'r'); $target = $this->fopen($path2 . $postFix2, 'w'); $count = \OC_Helper::streamCopy($source, $target); - list($storage1, $internalPath1)=\OC\Files\Filesystem::resolvePath($path1 . $postFix1); + list($storage1, $internalPath1) = \OC\Files\Filesystem::resolvePath($path1 . $postFix1); $storage1->unlink($internalPath1); $result = $count > 0; } @@ -414,8 +417,8 @@ class View { $mp1 = $this->getMountPoint($path1 . $postFix1); $mp2 = $this->getMountPoint($path2 . $postFix2); if ($mp1 == $mp2) { - list($storage, $internalPath1)=\OC\Files\Filesystem::resolvePath($path1 . $postFix1); - list( , $internalPath2)=\OC\Files\Filesystem::resolvePath($path2 . $postFix2); + list($storage, $internalPath1) = \OC\Files\Filesystem::resolvePath($path1 . $postFix1); + list(, $internalPath2) = \OC\Files\Filesystem::resolvePath($path2 . $postFix2); if ($storage) { $result = $storage->copy($internalPath1, $internalPath2); } else { @@ -550,7 +553,7 @@ class View { array(Filesystem::signal_param_path => $path) ); } - list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($path . $postFix); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($path . $postFix); if ($storage) { $result = $storage->hash($type, $internalPath, $raw); $result = \OC_FileProxy::runPostProxies('hash', $absolutePath, $result); @@ -585,7 +588,7 @@ class View { return false; } $run = $this->runHooks($hooks, $path); - list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($path . $postFix); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($path . $postFix); if ($run and $storage) { if (!is_null($extraParam)) { $result = $storage->$operation($internalPath, $extraParam); From 5a3d6805a2613c4f55daa971e112cc77f17b060f Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 24 Oct 2012 15:52:30 +0200 Subject: [PATCH 047/347] cleanup OC_Files a bit --- apps/files/ajax/delete.php | 23 +++--- apps/files/ajax/move.php | 13 +++- apps/files/ajax/newfile.php | 2 +- apps/files/ajax/newfolder.php | 2 +- apps/files/ajax/rename.php | 14 ++-- lib/files.php | 136 ---------------------------------- 6 files changed, 34 insertions(+), 156 deletions(-) diff --git a/apps/files/ajax/delete.php b/apps/files/ajax/delete.php index 57c8c15c19..ae6158a05a 100644 --- a/apps/files/ajax/delete.php +++ b/apps/files/ajax/delete.php @@ -12,17 +12,22 @@ $files = isset($_POST["file"]) ? stripslashes($_POST["file"]) : stripslashes($_P $files = explode(';', $files); $filesWithError = ''; -$success = true; -//Now delete -foreach($files as $file) { - if( !OC_Files::delete( $dir, $file )) { - $filesWithError .= $file . "\n"; - $success = false; +if (OC_User::isLoggedIn()) { + $success = true; + + //Now delete + foreach ($files as $file) { + if ($dir != '' || $file != 'Shared' && !\OC\Files\Filesystem::unlink($dir . '/' . $file)) { + $filesWithError .= $file . "\n"; + $success = false; + } } +} else { + $success = false; } -if($success) { - OCP\JSON::success(array("data" => array( "dir" => $dir, "files" => $files ))); +if ($success) { + OCP\JSON::success(array("data" => array("dir" => $dir, "files" => $files))); } else { - OCP\JSON::error(array("data" => array( "message" => "Could not delete:\n" . $filesWithError ))); + OCP\JSON::error(array("data" => array("message" => "Could not delete:\n" . $filesWithError))); } diff --git a/apps/files/ajax/move.php b/apps/files/ajax/move.php index 8b3149ef14..f872783122 100644 --- a/apps/files/ajax/move.php +++ b/apps/files/ajax/move.php @@ -11,9 +11,14 @@ $dir = stripslashes($_GET["dir"]); $file = stripslashes($_GET["file"]); $target = stripslashes($_GET["target"]); - -if(OC_Files::move($dir, $file, $target, $file)) { - OCP\JSON::success(array("data" => array( "dir" => $dir, "files" => $file ))); -} else { +if (OC_User::isLoggedIn() && ($dir != '' || $file != 'Shared')) { + $targetFile = \OC\Files\Filesystem::normalizePath($dir . '/' . $file); + $sourceFile = \OC\Files\Filesystem::normalizePath($target . '/' . $file); + if(\OC\Files\Filesystem::rename($sourceFile, $targetFile)) { + OCP\JSON::success(array("data" => array( "dir" => $dir, "files" => $file ))); + } else { + OCP\JSON::error(array("data" => array( "message" => "Could not move $file" ))); + } +}else{ OCP\JSON::error(array("data" => array( "message" => "Could not move $file" ))); } diff --git a/apps/files/ajax/newfile.php b/apps/files/ajax/newfile.php index 4d73970b68..f94d984d5b 100644 --- a/apps/files/ajax/newfile.php +++ b/apps/files/ajax/newfile.php @@ -82,7 +82,7 @@ if($source) { OCP\JSON::success(array("data" => array('content'=>$content, 'id' => $id))); exit(); } - }elseif(OC_Files::newFile($dir, $filename, 'file')) { + }elseif(\OC\Files\Filesystem::touch($dir . '/' . $filename)) { $meta = OC_FileCache::get($dir.'/'.$filename); $id = OC_FileCache::getId($dir.'/'.$filename); OCP\JSON::success(array("data" => array('content'=>$content, 'id' => $id))); diff --git a/apps/files/ajax/newfolder.php b/apps/files/ajax/newfolder.php index 0f1f2f14eb..c36c208455 100644 --- a/apps/files/ajax/newfolder.php +++ b/apps/files/ajax/newfolder.php @@ -19,7 +19,7 @@ if(strpos($foldername, '/')!==false) { exit(); } -if(OC_Files::newFile($dir, stripslashes($foldername), 'dir')) { +if(\OC\Files\Filesystem::mkdir($dir . '/' . stripslashes($foldername))) { if ( $dir != '/') { $path = $dir.'/'.$foldername; } else { diff --git a/apps/files/ajax/rename.php b/apps/files/ajax/rename.php index 45448279fa..a2b9b8de25 100644 --- a/apps/files/ajax/rename.php +++ b/apps/files/ajax/rename.php @@ -11,10 +11,14 @@ $dir = stripslashes($_GET["dir"]); $file = stripslashes($_GET["file"]); $newname = stripslashes($_GET["newname"]); -// Delete -if( OC_Files::move( $dir, $file, $dir, $newname )) { - OCP\JSON::success(array("data" => array( "dir" => $dir, "file" => $file, "newname" => $newname ))); -} -else{ +if (OC_User::isLoggedIn() && ($dir != '' || $file != 'Shared')) { + $targetFile = \OC\Files\Filesystem::normalizePath($dir . '/' . $file); + $sourceFile = \OC\Files\Filesystem::normalizePath($dir . '/' . $newname); + if(\OC\Files\Filesystem::rename($sourceFile, $targetFile)) { + OCP\JSON::success(array("data" => array( "dir" => $dir, "file" => $file, "newname" => $newname ))); + } else { + OCP\JSON::error(array("data" => array( "message" => "Unable to rename file" ))); + } +}else{ OCP\JSON::error(array("data" => array( "message" => "Unable to rename file" ))); } diff --git a/lib/files.php b/lib/files.php index ff9befa89e..7ab7c89201 100644 --- a/lib/files.php +++ b/lib/files.php @@ -252,77 +252,6 @@ class OC_Files { } } - /** - * move a file or folder - * - * @param dir $sourceDir - * @param file $source - * @param dir $targetDir - * @param file $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); - return \OC\Files\Filesystem::rename($sourceFile, $targetFile); - } else { - return false; - } - } - - /** - * copy a file or folder - * - * @param dir $sourceDir - * @param file $source - * @param dir $targetDir - * @param file $target - */ - public static function copy($sourceDir, $source, $targetDir, $target) { - if (OC_User::isLoggedIn()) { - $targetFile = $targetDir . '/' . $target; - $sourceFile = $sourceDir . '/' . $source; - return \OC\Files\Filesystem::copy($sourceFile, $targetFile); - } - } - - /** - * create a new file or folder - * - * @param dir $dir - * @param file $name - * @param type $type - */ - public static function newFile($dir, $name, $type) { - if (OC_User::isLoggedIn()) { - $file = $dir . '/' . $name; - if ($type == 'dir') { - return \OC\Files\Filesystem::mkdir($file); - } elseif ($type == 'file') { - $fileHandle = \OC\Files\Filesystem::fopen($file, 'w'); - if ($fileHandle) { - fclose($fileHandle); - return true; - } else { - return false; - } - } - } - } - - /** - * deletes a file or folder - * - * @param dir $dir - * @param file $name - */ - public static function delete($dir, $file) { - if (OC_User::isLoggedIn() && ($dir != '' || $file != 'Shared')) { - $file = $dir . '/' . $file; - return \OC\Files\Filesystem::unlink($file); - } - } - /** * checks if the selected files are within the size constraint. If not, outputs an error page. * @@ -372,55 +301,6 @@ class OC_Files { } } - /** - * try to detect the mime type of a file - * - * @param string path - * @return string guessed mime type - */ - static function getMimeType($path) { - return \OC\Files\Filesystem::getMimeType($path); - } - - /** - * get a file tree - * - * @param string path - * @return array - */ - static function getTree($path) { - return \OC\Files\Filesystem::getTree($path); - } - - /** - * pull a file from a remote server - * - * @param string source - * @param string token - * @param string dir - * @param string file - * @return string guessed mime type - */ - static function pull($source, $token, $dir, $file) { - $tmpfile = tempnam(get_temp_dir(), 'remoteCloudFile'); - $fp = fopen($tmpfile, 'w+'); - $url = $source .= "/files/pull.php?token=$token"; - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_FILE, $fp); - curl_exec($ch); - fclose($fp); - $info = curl_getinfo($ch); - $httpCode = $info['http_code']; - curl_close($ch); - if ($httpCode == 200 or $httpCode == 0) { - \OC\Files\Filesystem::fromTmpFile($tmpfile, $dir . '/' . $file); - return true; - } else { - return false; - } - } - /** * set the maximum upload size limit for apache hosts using .htaccess * @@ -478,22 +358,6 @@ class OC_Files { return false; } - - /** - * normalize a path, removing any double, add leading /, etc - * - * @param string $path - * @return string - */ - static public function normalizePath($path) { - $path = '/' . $path; - $old = ''; - while ($old != $path) { //replace any multiplicity of slashes with a single one - $old = $path; - $path = str_replace('//', '/', $path); - } - return $path; - } } function fileCmp($a, $b) { From 39adadd3e3e50dcf3bf577a22870aaec52f63052 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 26 Oct 2012 12:30:25 +0200 Subject: [PATCH 048/347] move the cache api from OC_Files to filesystem(view) --- lib/files.php | 92 ------------------------- lib/files/cache/cache.php | 5 ++ lib/files/filesystem.php | 27 ++++++++ lib/files/view.php | 92 +++++++++++++++++++++++++ tests/lib/{files.php => files/view.php} | 23 ++++--- 5 files changed, 138 insertions(+), 101 deletions(-) rename tests/lib/{files.php => files/view.php} (86%) diff --git a/lib/files.php b/lib/files.php index 7ab7c89201..422e7f4ffe 100644 --- a/lib/files.php +++ b/lib/files.php @@ -28,98 +28,6 @@ class OC_Files { static $tmpFiles = array(); - /** - * get the filesystem info - * - * @param string $path - * @return array - * - * returns an associative array with the following keys: - * - size - * - mtime - * - mimetype - * - encrypted - * - versioned - */ - public static function getFileInfo($path) { - $path = \OC\Files\Filesystem::normalizePath($path); - /** - * @var \OC\Files\Storage\Storage $storage - * @var string $path - */ - list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($path); - $cache = $storage->getCache(); - - if (!$cache->inCache($internalPath)) { - $scanner = $storage->getScanner(); - $scanner->scan($internalPath, \OC\Files\Cache\Scanner::SCAN_SHALLOW); - } - - $data = $cache->get($internalPath); - - if ($data['mimetype'] === 'httpd/unix-directory') { - //add the sizes of other mountpoints to the folder - $mountPoints = \OC\Files\Filesystem::getMountPoints($path); - foreach ($mountPoints as $mountPoint) { - $subStorage = \OC\Files\Filesystem::getStorage($mountPoint); - $subCache = $subStorage->getCache(); - $rootEntry = $subCache->get(''); - - $data['size'] += $rootEntry['size']; - } - } - - return $data; - } - - /** - * get the content of a directory - * - * @param string $directory path under datadirectory - * @return array - */ - public static function getDirectoryContent($directory, $mimetype_filter = '') { - $path = \OC\Files\Filesystem::normalizePath($directory); - /** - * @var \OC\Files\Storage\Storage $storage - * @var string $path - */ - list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($path); - $cache = $storage->getCache(); - - if (!$cache->inCache($internalPath)) { - $scanner = $storage->getScanner(); - $scanner->scan($internalPath, \OC\Files\Cache\Scanner::SCAN_SHALLOW); - } - - $files = $cache->getFolderContents($internalPath); //TODO: mimetype_filter - - //add a folder for any mountpoint in this directory and add the sizes of other mountpoints to the folders - $mountPoints = \OC\Files\Filesystem::getMountPoints($directory); - $dirLength = strlen($path); - foreach ($mountPoints as $mountPoint) { - $subStorage = \OC\Files\Filesystem::getStorage($mountPoint); - $subCache = $subStorage->getCache(); - $rootEntry = $subCache->get(''); - - $relativePath = trim(substr($mountPoint, $dirLength), '/'); - if ($pos = strpos($relativePath, '/')) { //mountpoint inside subfolder add size to the correct folder - $entryName = substr($relativePath, 0, $pos); - foreach ($files as &$entry) { - if ($entry['name'] === $entryName) { - $entry['size'] += $rootEntry['size']; - } - } - } else { //mountpoint in this folder, add an entry for it - $rootEntry['name'] = $relativePath; - $files[] = $rootEntry; - } - } - - usort($files, "fileCmp"); //TODO: remove this once ajax is merged - return $files; - } - public static function searchByMime($mimetype_filter) { $files = array(); $dirs_to_check = array(''); diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index 5ef49246ea..9b55666f95 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -8,6 +8,11 @@ namespace OC\Files\Cache; +/** + * Metadata cache for the filesystem + * + * don't use this class directly if you need to get metadata, use \OC\Files\Filesystem::getFileInfo instead + */ class Cache { const NOT_FOUND = 0; const PARTIAL = 1; //only partial data available, file not cached in the database diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php index b7f8483fbf..d735cf8626 100644 --- a/lib/files/filesystem.php +++ b/lib/files/filesystem.php @@ -609,6 +609,33 @@ class Filesystem { } return $path; } + + /** + * get the filesystem info + * + * @param string $path + * @return array + * + * returns an associative array with the following keys: + * - size + * - mtime + * - mimetype + * - encrypted + * - versioned + */ + public static function getFileInfo($path) { + return self::$defaultInstance->getFileInfo($path); + } + + /** + * get the content of a directory + * + * @param string $directory path under datadirectory + * @return array + */ + public static function getDirectoryContent($directory, $mimetype_filter = '') { + return self::$defaultInstance->getDirectoryContent($directory, $mimetype_filter); + } } \OC_Hook::connect('OC_Filesystem', 'post_write', 'OC_Filesystem', 'removeETagHook'); diff --git a/lib/files/view.php b/lib/files/view.php index 18d9193035..aaca1618ac 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -645,4 +645,96 @@ class View { public function hasUpdated($path, $time) { return $this->basicOperation('hasUpdated', $path, array(), $time); } + + /** + * get the filesystem info + * + * @param string $path + * @return array + * + * returns an associative array with the following keys: + * - size + * - mtime + * - mimetype + * - encrypted + * - versioned + */ + public function getFileInfo($path) { + $path = \OC\Files\Filesystem::normalizePath($this->fakeRoot . '/' . $path); + /** + * @var \OC\Files\Storage\Storage $storage + * @var string $path + */ + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($path); + $cache = $storage->getCache(); + + if (!$cache->inCache($internalPath)) { + $scanner = $storage->getScanner(); + $scanner->scan($internalPath, \OC\Files\Cache\Scanner::SCAN_SHALLOW); + } + + $data = $cache->get($internalPath); + + if ($data['mimetype'] === 'httpd/unix-directory') { + //add the sizes of other mountpoints to the folder + $mountPoints = \OC\Files\Filesystem::getMountPoints($path); + foreach ($mountPoints as $mountPoint) { + $subStorage = \OC\Files\Filesystem::getStorage($mountPoint); + $subCache = $subStorage->getCache(); + $rootEntry = $subCache->get(''); + + $data['size'] += $rootEntry['size']; + } + } + + return $data; + } + + /** + * get the content of a directory + * + * @param string $directory path under datadirectory + * @return array + */ + public function getDirectoryContent($directory, $mimetype_filter = '') { + $path = \OC\Files\Filesystem::normalizePath($this->fakeRoot . '/' . $directory); + /** + * @var \OC\Files\Storage\Storage $storage + * @var string $path + */ + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($path); + $cache = $storage->getCache(); + + if (!$cache->inCache($internalPath)) { + $scanner = $storage->getScanner(); + $scanner->scan($internalPath, \OC\Files\Cache\Scanner::SCAN_SHALLOW); + } + + $files = $cache->getFolderContents($internalPath); //TODO: mimetype_filter + + //add a folder for any mountpoint in this directory and add the sizes of other mountpoints to the folders + $mountPoints = \OC\Files\Filesystem::getMountPoints($directory); + $dirLength = strlen($path); + foreach ($mountPoints as $mountPoint) { + $subStorage = \OC\Files\Filesystem::getStorage($mountPoint); + $subCache = $subStorage->getCache(); + $rootEntry = $subCache->get(''); + + $relativePath = trim(substr($mountPoint, $dirLength), '/'); + if ($pos = strpos($relativePath, '/')) { //mountpoint inside subfolder add size to the correct folder + $entryName = substr($relativePath, 0, $pos); + foreach ($files as &$entry) { + if ($entry['name'] === $entryName) { + $entry['size'] += $rootEntry['size']; + } + } + } else { //mountpoint in this folder, add an entry for it + $rootEntry['name'] = $relativePath; + $files[] = $rootEntry; + } + } + + usort($files, "fileCmp"); //TODO: remove this once ajax is merged + return $files; + } } diff --git a/tests/lib/files.php b/tests/lib/files/view.php similarity index 86% rename from tests/lib/files.php rename to tests/lib/files/view.php index d978ac3fd1..6e7608f596 100644 --- a/tests/lib/files.php +++ b/tests/lib/files/view.php @@ -5,9 +5,11 @@ * later. * See the COPYING-README file. */ +namespace Test\Files; + use \OC\Files\Filesystem as Filesystem; -class Test_Files extends PHPUnit_Framework_TestCase { +class View extends \PHPUnit_Framework_TestCase { /** * @var \OC\Files\Storage\Storage[] $storages; */ @@ -35,19 +37,21 @@ class Test_Files extends PHPUnit_Framework_TestCase { $imageSize = filesize(\OC::$SERVERROOT . '/core/img/logo.png'); $storageSize = $textSize * 2 + $imageSize; - $cachedData = OC_Files::getFileInfo('/foo.txt'); + $rootView = new \OC\Files\View(''); + + $cachedData = $rootView->getFileInfo('/foo.txt'); $this->assertEquals($textSize, $cachedData['size']); $this->assertEquals('text/plain', $cachedData['mimetype']); - $cachedData = OC_Files::getFileInfo('/'); + $cachedData = $rootView->getFileInfo('/'); $this->assertEquals($storageSize * 3, $cachedData['size']); $this->assertEquals('httpd/unix-directory', $cachedData['mimetype']); - $cachedData = OC_Files::getFileInfo('/folder'); + $cachedData = $rootView->getFileInfo('/folder'); $this->assertEquals($storageSize + $textSize, $cachedData['size']); $this->assertEquals('httpd/unix-directory', $cachedData['mimetype']); - $folderData = OC_Files::getDirectoryContent('/'); + $folderData = $rootView->getDirectoryContent('/'); /** * expected entries: * folder @@ -74,20 +78,21 @@ class Test_Files extends PHPUnit_Framework_TestCase { Filesystem::mount($storage2, array(), '/substorage'); $textSize = strlen("dummy file data\n"); $imageSize = filesize(\OC::$SERVERROOT . '/core/img/logo.png'); - $storageSize = $textSize * 2 + $imageSize; - $cachedData = \OC_Files::getFileInfo('/'); + $rootView = new \OC\Files\View(''); + + $cachedData = $rootView->getFileInfo('/'); $this->assertEquals('httpd/unix-directory', $cachedData['mimetype']); $this->assertEquals(-1, $cachedData['size']); - $folderData = \OC_Files::getDirectoryContent('/substorage/folder'); + $folderData = $rootView->getDirectoryContent('/substorage/folder'); $this->assertEquals('text/plain', $folderData[0]['mimetype']); $this->assertEquals($textSize, $folderData[0]['size']); } /** * @param bool $scan - * @return OC\Files\Storage\Storage + * @return \OC\Files\Storage\Storage */ private function getTestStorage($scan = true) { $storage = new \OC\Files\Storage\Temporary(array()); From e63e246c4894aa7f72feb550d98747890838af0b Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 26 Oct 2012 12:37:49 +0200 Subject: [PATCH 049/347] fix problem with normalizePath when there was a double leading slash --- lib/files/filesystem.php | 8 ++++---- tests/lib/files/view.php | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php index d735cf8626..2b51131b20 100644 --- a/lib/files/filesystem.php +++ b/lib/files/filesystem.php @@ -595,14 +595,14 @@ class Filesystem { if ($path[0] !== '/') { $path = '/' . $path; } -//remove trailing slash - 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); } +//remove trailing slash + if ($stripTrailingSlash and strlen($path) > 1 and substr($path, -1, 1) === '/') { + $path = substr($path, 0, -1); + } //normalize unicode if possible if (class_exists('Normalizer')) { $path = \Normalizer::normalize($path); diff --git a/tests/lib/files/view.php b/tests/lib/files/view.php index 6e7608f596..adbed5a18b 100644 --- a/tests/lib/files/view.php +++ b/tests/lib/files/view.php @@ -69,6 +69,9 @@ class View extends \PHPUnit_Framework_TestCase { $this->assertEquals($imageSize, $folderData[1]['size']); $this->assertEquals($textSize, $folderData[2]['size']); $this->assertEquals($storageSize, $folderData[3]['size']); + + $folderView = new \OC\Files\View('/folder'); + $this->assertEquals($rootView->getFileInfo('/folder'), $folderView->getFileInfo('/')); } public function testAutoScan() { From 7ef0ffe8ad8f95b023f95f80e7b91c2a3ee50c67 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 26 Oct 2012 12:43:23 +0200 Subject: [PATCH 050/347] add View->putFileInfo to the filecache api --- lib/files/view.php | 30 ++++++++++++++++++++++++++++-- tests/lib/files/view.php | 7 +++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/lib/files/view.php b/lib/files/view.php index aaca1618ac..094a7d92a4 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -663,7 +663,7 @@ class View { $path = \OC\Files\Filesystem::normalizePath($this->fakeRoot . '/' . $path); /** * @var \OC\Files\Storage\Storage $storage - * @var string $path + * @var string $internalPath */ list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($path); $cache = $storage->getCache(); @@ -700,7 +700,7 @@ class View { $path = \OC\Files\Filesystem::normalizePath($this->fakeRoot . '/' . $directory); /** * @var \OC\Files\Storage\Storage $storage - * @var string $path + * @var string $internalPath */ list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($path); $cache = $storage->getCache(); @@ -737,4 +737,30 @@ class View { usort($files, "fileCmp"); //TODO: remove this once ajax is merged return $files; } + + /** + * change file metadata + * + * @param string $path + * @param array $data + * @return int + * + * returns the fileid of the updated file + */ + public function putFileInfo($path, $data) { + $path = \OC\Files\Filesystem::normalizePath($this->fakeRoot . '/' . $path); + /** + * @var \OC\Files\Storage\Storage $storage + * @var string $internalPath + */ + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($path); + $cache = $storage->getCache(); + + if (!$cache->inCache($internalPath)) { + $scanner = $storage->getScanner(); + $scanner->scan($internalPath, \OC\Files\Cache\Scanner::SCAN_SHALLOW); + } + + return $cache->put($internalPath, $data); + } } diff --git a/tests/lib/files/view.php b/tests/lib/files/view.php index adbed5a18b..051ae25162 100644 --- a/tests/lib/files/view.php +++ b/tests/lib/files/view.php @@ -72,6 +72,13 @@ class View extends \PHPUnit_Framework_TestCase { $folderView = new \OC\Files\View('/folder'); $this->assertEquals($rootView->getFileInfo('/folder'), $folderView->getFileInfo('/')); + + $cachedData = $rootView->getFileInfo('/foo.txt'); + $this->assertFalse($cachedData['encrypted']); + $id = $rootView->putFileInfo('/foo.txt', array('encrypted' => true)); + $cachedData = $rootView->getFileInfo('/foo.txt'); + $this->assertTrue($cachedData['encrypted']); + $this->assertEquals($cachedData['fileid'], $id); } public function testAutoScan() { From 8bce661e4ddedb611d5873c578203dfda631ce7e Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 26 Oct 2012 13:23:15 +0200 Subject: [PATCH 051/347] add search to the filecache api --- lib/files/cache/cache.php | 21 ++++++++- lib/files/filesystem.php | 2 +- lib/files/view.php | 84 ++++++++++++++++++++++++--------- tests/lib/files/cache/cache.php | 20 ++++++++ tests/lib/files/view.php | 45 +++++++++++++++++- 5 files changed, 146 insertions(+), 26 deletions(-) diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index 9b55666f95..7e0c5cb21f 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -251,7 +251,7 @@ class Cache { */ public function getStatus($file) { $pathHash = md5($file); - $query = \OC_DB::prepare('SELECT * FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path_hash` = ?'); + $query = \OC_DB::prepare('SELECT `size` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path_hash` = ?'); $result = $query->execute(array($this->storageId, $pathHash)); if ($row = $result->fetchRow()) { if ((int)$row['size'] === -1) { @@ -267,4 +267,23 @@ class Cache { } } } + + /** + * search for files matching $pattern + * + * @param string $pattern + * @return array of file data + */ + public function search($pattern) { + $query = \OC_DB::prepare(' + SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted` + FROM `*PREFIX*filecache` WHERE `name` LIKE ? AND `storage` = ?' + ); + $result = $query->execute(array($pattern, $this->storageId)); + $files = array(); + while ($row = $result->fetchRow()) { + $files[] = $row; + } + return $files; + } } diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php index 2b51131b20..4031c0c5b8 100644 --- a/lib/files/filesystem.php +++ b/lib/files/filesystem.php @@ -548,7 +548,7 @@ class Filesystem { } static public function search($query) { - return Cache\Cache::search($query); + return self::$defaultInstance->search($query); } /** diff --git a/lib/files/view.php b/lib/files/view.php index 094a7d92a4..ee95cce0c1 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -110,7 +110,7 @@ class View { */ public function getLocalFile($path) { $parent = substr($path, 0, strrpos($path, '/')); - list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($path); + list($storage, $internalPath) = Filesystem::resolvePath($path); if (Filesystem::isValidPath($parent) and $storage) { return $storage->getLocalFile($internalPath); } else { @@ -124,7 +124,7 @@ class View { */ public function getLocalFolder($path) { $parent = substr($path, 0, strrpos($path, '/')); - list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($path); + list($storage, $internalPath) = Filesystem::resolvePath($path); if (Filesystem::isValidPath($parent) and $storage) { return $storage->getLocalFolder($internalPath); } else { @@ -150,7 +150,7 @@ class View { } public function readdir($handle) { - $fsLocal = new \OC\Files\Storage\Local(array('datadir' => '/')); + $fsLocal = new Storage\Local(array('datadir' => '/')); return $fsLocal->readdir($handle); } @@ -334,8 +334,8 @@ class View { $mp1 = $this->getMountPoint($path1 . $postFix1); $mp2 = $this->getMountPoint($path2 . $postFix2); if ($mp1 == $mp2) { - list($storage, $internalPath1) = \OC\Files\Filesystem::resolvePath($path1 . $postFix1); - list(, $internalPath2) = \OC\Files\Filesystem::resolvePath($path2 . $postFix2); + list($storage, $internalPath1) = Filesystem::resolvePath($path1 . $postFix1); + list(, $internalPath2) = Filesystem::resolvePath($path2 . $postFix2); if ($storage) { $result = $storage->rename($internalPath1, $internalPath2); } else { @@ -345,7 +345,7 @@ class View { $source = $this->fopen($path1 . $postFix1, 'r'); $target = $this->fopen($path2 . $postFix2, 'w'); $count = \OC_Helper::streamCopy($source, $target); - list($storage1, $internalPath1) = \OC\Files\Filesystem::resolvePath($path1 . $postFix1); + list($storage1, $internalPath1) = Filesystem::resolvePath($path1 . $postFix1); $storage1->unlink($internalPath1); $result = $count > 0; } @@ -417,8 +417,8 @@ class View { $mp1 = $this->getMountPoint($path1 . $postFix1); $mp2 = $this->getMountPoint($path2 . $postFix2); if ($mp1 == $mp2) { - list($storage, $internalPath1) = \OC\Files\Filesystem::resolvePath($path1 . $postFix1); - list(, $internalPath2) = \OC\Files\Filesystem::resolvePath($path2 . $postFix2); + list($storage, $internalPath1) = Filesystem::resolvePath($path1 . $postFix1); + list(, $internalPath2) = Filesystem::resolvePath($path2 . $postFix2); if ($storage) { $result = $storage->copy($internalPath1, $internalPath2); } else { @@ -553,7 +553,7 @@ class View { array(Filesystem::signal_param_path => $path) ); } - list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($path . $postFix); + list($storage, $internalPath) = Filesystem::resolvePath($path . $postFix); if ($storage) { $result = $storage->hash($type, $internalPath, $raw); $result = \OC_FileProxy::runPostProxies('hash', $absolutePath, $result); @@ -588,7 +588,7 @@ class View { return false; } $run = $this->runHooks($hooks, $path); - list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($path . $postFix); + list($storage, $internalPath) = Filesystem::resolvePath($path . $postFix); if ($run and $storage) { if (!is_null($extraParam)) { $result = $storage->$operation($internalPath, $extraParam); @@ -660,26 +660,26 @@ class View { * - versioned */ public function getFileInfo($path) { - $path = \OC\Files\Filesystem::normalizePath($this->fakeRoot . '/' . $path); + $path = Filesystem::normalizePath($this->fakeRoot . '/' . $path); /** * @var \OC\Files\Storage\Storage $storage * @var string $internalPath */ - list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($path); + list($storage, $internalPath) = Filesystem::resolvePath($path); $cache = $storage->getCache(); if (!$cache->inCache($internalPath)) { $scanner = $storage->getScanner(); - $scanner->scan($internalPath, \OC\Files\Cache\Scanner::SCAN_SHALLOW); + $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW); } $data = $cache->get($internalPath); if ($data['mimetype'] === 'httpd/unix-directory') { //add the sizes of other mountpoints to the folder - $mountPoints = \OC\Files\Filesystem::getMountPoints($path); + $mountPoints = Filesystem::getMountPoints($path); foreach ($mountPoints as $mountPoint) { - $subStorage = \OC\Files\Filesystem::getStorage($mountPoint); + $subStorage = Filesystem::getStorage($mountPoint); $subCache = $subStorage->getCache(); $rootEntry = $subCache->get(''); @@ -697,26 +697,26 @@ class View { * @return array */ public function getDirectoryContent($directory, $mimetype_filter = '') { - $path = \OC\Files\Filesystem::normalizePath($this->fakeRoot . '/' . $directory); + $path = Filesystem::normalizePath($this->fakeRoot . '/' . $directory); /** * @var \OC\Files\Storage\Storage $storage * @var string $internalPath */ - list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($path); + list($storage, $internalPath) = Filesystem::resolvePath($path); $cache = $storage->getCache(); if (!$cache->inCache($internalPath)) { $scanner = $storage->getScanner(); - $scanner->scan($internalPath, \OC\Files\Cache\Scanner::SCAN_SHALLOW); + $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW); } $files = $cache->getFolderContents($internalPath); //TODO: mimetype_filter //add a folder for any mountpoint in this directory and add the sizes of other mountpoints to the folders - $mountPoints = \OC\Files\Filesystem::getMountPoints($directory); + $mountPoints = Filesystem::getMountPoints($directory); $dirLength = strlen($path); foreach ($mountPoints as $mountPoint) { - $subStorage = \OC\Files\Filesystem::getStorage($mountPoint); + $subStorage = Filesystem::getStorage($mountPoint); $subCache = $subStorage->getCache(); $rootEntry = $subCache->get(''); @@ -748,19 +748,57 @@ class View { * returns the fileid of the updated file */ public function putFileInfo($path, $data) { - $path = \OC\Files\Filesystem::normalizePath($this->fakeRoot . '/' . $path); + $path = Filesystem::normalizePath($this->fakeRoot . '/' . $path); /** * @var \OC\Files\Storage\Storage $storage * @var string $internalPath */ - list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($path); + list($storage, $internalPath) = Filesystem::resolvePath($path); $cache = $storage->getCache(); if (!$cache->inCache($internalPath)) { $scanner = $storage->getScanner(); - $scanner->scan($internalPath, \OC\Files\Cache\Scanner::SCAN_SHALLOW); + $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW); } return $cache->put($internalPath, $data); } + + /** + * search for files with the name matching $query + * + * @param string $query + * @return array + */ + public function search($query) { + $files = array(); + $rootLength = strlen($this->fakeRoot); + + $mountPoint = Filesystem::getMountPoint($this->fakeRoot); + $storage = Filesystem::getStorage($mountPoint); + $cache = $storage->getCache(); + + $results = $cache->search('%' . $query . '%'); + foreach ($results as $result) { + if (substr($mountPoint . $result['path'], 0, $rootLength) === $this->fakeRoot) { + $result['path'] = substr($mountPoint . $result['path'], $rootLength); + $files[] = $result; + } + } + + $mountPoints = Filesystem::getMountPoints($this->fakeRoot); + foreach ($mountPoints as $mountPoint) { + $storage = Filesystem::getStorage($mountPoint); + $cache = $storage->getCache(); + + $relativeMountPoint = substr($mountPoint, $rootLength); + $results = $cache->search('%' . $query . '%'); + foreach ($results as $result) { + $result['path'] = $relativeMountPoint . $result['path']; + $files[] = $result; + } + } + + return $files; + } } diff --git a/tests/lib/files/cache/cache.php b/tests/lib/files/cache/cache.php index 177cf1c045..839e06e93f 100644 --- a/tests/lib/files/cache/cache.php +++ b/tests/lib/files/cache/cache.php @@ -111,6 +111,26 @@ class Cache extends \UnitTestCase { $this->assertEquals(\OC\Files\Cache\Cache::COMPLETE, $this->cache->getStatus('foo')); } + function testSearch() { + $file1 = 'folder'; + $file2 = 'folder/foobar'; + $file3 = 'folder/foo'; + $data1 = array('size' => 100, 'mtime' => 50, 'mimetype' => 'foo/folder'); + $fileData = array(); + $fileData['foobar'] = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'foo/file'); + $fileData['foo'] = array('size' => 20, 'mtime' => 25, 'mimetype' => 'foo/file'); + + $this->cache->put($file1, $data1); + $this->cache->put($file2, $fileData['foobar']); + $this->cache->put($file3, $fileData['foo']); + + $this->assertEquals(2, count($this->cache->search('%foo%'))); + $this->assertEquals(1, count($this->cache->search('foo'))); + $this->assertEquals(1, count($this->cache->search('%folder%'))); + $this->assertEquals(1, count($this->cache->search('folder%'))); + $this->assertEquals(3, count($this->cache->search('%'))); + } + public function tearDown() { $this->cache->clear(); } diff --git a/tests/lib/files/view.php b/tests/lib/files/view.php index 051ae25162..fc872ea5e2 100644 --- a/tests/lib/files/view.php +++ b/tests/lib/files/view.php @@ -87,7 +87,6 @@ class View extends \PHPUnit_Framework_TestCase { Filesystem::mount($storage1, array(), '/'); Filesystem::mount($storage2, array(), '/substorage'); $textSize = strlen("dummy file data\n"); - $imageSize = filesize(\OC::$SERVERROOT . '/core/img/logo.png'); $rootView = new \OC\Files\View(''); @@ -100,6 +99,50 @@ class View extends \PHPUnit_Framework_TestCase { $this->assertEquals($textSize, $folderData[0]['size']); } + function testSearch() { + $storage1 = $this->getTestStorage(); + $storage2 = $this->getTestStorage(); + $storage3 = $this->getTestStorage(); + Filesystem::mount($storage1, array(), '/'); + Filesystem::mount($storage2, array(), '/substorage'); + Filesystem::mount($storage3, array(), '/folder/anotherstorage'); + + $rootView = new \OC\Files\View(''); + + $results = $rootView->search('foo'); + $this->assertEquals(6, count($results)); + $paths = array(); + foreach ($results as $result) { + $this->assertEquals($result['path'], Filesystem::normalizePath($result['path'])); + $paths[] = $result['path']; + } + $this->assertContains('/foo.txt', $paths); + $this->assertContains('/foo.png', $paths); + $this->assertContains('/substorage/foo.txt', $paths); + $this->assertContains('/substorage/foo.png', $paths); + $this->assertContains('/folder/anotherstorage/foo.txt', $paths); + $this->assertContains('/folder/anotherstorage/foo.png', $paths); + + $folderView = new \OC\Files\View('/folder'); + $results = $folderView->search('bar'); + $this->assertEquals(2, count($results)); + $paths = array(); + foreach ($results as $result) { + $paths[] = $result['path']; + } + $this->assertContains('/anotherstorage/folder/bar.txt', $paths); + $this->assertContains('/bar.txt', $paths); + + $results = $folderView->search('foo'); + $this->assertEquals(2, count($results)); + $paths = array(); + foreach ($results as $result) { + $paths[] = $result['path']; + } + $this->assertContains('/anotherstorage/foo.txt', $paths); + $this->assertContains('/anotherstorage/foo.png', $paths); + } + /** * @param bool $scan * @return \OC\Files\Storage\Storage From 7ad8bf3156a794e47ee223efd2e1cf9191cc8a97 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 26 Oct 2012 18:07:01 +0200 Subject: [PATCH 052/347] move filesystem test case --- tests/lib/files/filesystem.php | 110 +++++++++++++++++++++++++++++++++ tests/lib/files/view.php | 22 +++---- tests/lib/filesystem.php | 110 --------------------------------- 3 files changed, 120 insertions(+), 122 deletions(-) create mode 100644 tests/lib/files/filesystem.php delete mode 100644 tests/lib/filesystem.php diff --git a/tests/lib/files/filesystem.php b/tests/lib/files/filesystem.php new file mode 100644 index 0000000000..363426511b --- /dev/null +++ b/tests/lib/files/filesystem.php @@ -0,0 +1,110 @@ +. + * + */ + +namespace Test\Files; + +class Filesystem extends \PHPUnit_Framework_TestCase { + /** + * @var array tmpDirs + */ + private $tmpDirs=array(); + + /** + * @return array + */ + private function getStorageData() { + $dir = \OC_Helper::tmpFolder(); + $this->tmpDirs[] = $dir; + return array('datadir' => $dir); + } + + public function tearDown() { + foreach ($this->tmpDirs as $dir) { + \OC_Helper::rmdirr($dir); + } + } + + public function setUp() { + \OC\Files\Filesystem::clearMounts(); + } + + public function testMount() { + \OC\Files\Filesystem::mount('\OC\Files\Storage\Local',self::getStorageData(),'/'); + $this->assertEquals('/',\OC\Files\Filesystem::getMountPoint('/')); + $this->assertEquals('/',\OC\Files\Filesystem::getMountPoint('/some/folder')); + list( , $internalPath)=\OC\Files\Filesystem::resolvePath('/'); + $this->assertEquals('',$internalPath); + list( , $internalPath)=\OC\Files\Filesystem::resolvePath('/some/folder'); + $this->assertEquals('some/folder',$internalPath); + + \OC\Files\Filesystem::mount('\OC\Files\Storage\Local',self::getStorageData(),'/some'); + $this->assertEquals('/',\OC\Files\Filesystem::getMountPoint('/')); + $this->assertEquals('/some/',\OC\Files\Filesystem::getMountPoint('/some/folder')); + $this->assertEquals('/some/',\OC\Files\Filesystem::getMountPoint('/some/')); + $this->assertEquals('/',\OC\Files\Filesystem::getMountPoint('/some')); + list( , $internalPath)=\OC\Files\Filesystem::resolvePath('/some/folder'); + $this->assertEquals('folder',$internalPath); + } + + public function testNormalize() { + $this->assertEquals('/path', \OC\Files\Filesystem::normalizePath('/path/')); + $this->assertEquals('/path/', \OC\Files\Filesystem::normalizePath('/path/', false)); + $this->assertEquals('/path', \OC\Files\Filesystem::normalizePath('path')); + $this->assertEquals('/path', \OC\Files\Filesystem::normalizePath('\path')); + $this->assertEquals('/foo/bar', \OC\Files\Filesystem::normalizePath('/foo//bar/')); + $this->assertEquals('/foo/bar', \OC\Files\Filesystem::normalizePath('/foo////bar')); + if (class_exists('Normalizer')) { + $this->assertEquals("/foo/bar\xC3\xBC", \OC\Files\Filesystem::normalizePath("/foo/baru\xCC\x88")); + } + } + + public function testHooks() { + if(\OC\Files\Filesystem::getView()){ + $user = \OC_User::getUser(); + }else{ + $user=uniqid(); + \OC\Files\Filesystem::init('/'.$user.'/files'); + } + \OC_Hook::clear('OC_Filesystem'); + \OC_Hook::connect('OC_Filesystem', 'post_write', $this, 'dummyHook'); + + \OC\Files\Filesystem::mount('OC\Files\Storage\Temporary', array(), '/'); + + $rootView=new \OC\Files\View(''); + $rootView->mkdir('/'.$user); + $rootView->mkdir('/'.$user.'/files'); + + \OC\Files\Filesystem::file_put_contents('/foo', 'foo'); + \OC\Files\Filesystem::mkdir('/bar'); + \OC\Files\Filesystem::file_put_contents('/bar//foo', 'foo'); + + $tmpFile = \OC_Helper::tmpFile(); + file_put_contents($tmpFile, 'foo'); + $fh = fopen($tmpFile, 'r'); + \OC\Files\Filesystem::file_put_contents('/bar//foo', $fh); + } + + public function dummyHook($arguments) { + $path = $arguments['path']; + $this->assertEquals($path, \OC\Files\Filesystem::normalizePath($path)); //the path passed to the hook should already be normalized + } +} diff --git a/tests/lib/files/view.php b/tests/lib/files/view.php index fc872ea5e2..980c5298fb 100644 --- a/tests/lib/files/view.php +++ b/tests/lib/files/view.php @@ -7,8 +7,6 @@ namespace Test\Files; -use \OC\Files\Filesystem as Filesystem; - class View extends \PHPUnit_Framework_TestCase { /** * @var \OC\Files\Storage\Storage[] $storages; @@ -16,7 +14,7 @@ class View extends \PHPUnit_Framework_TestCase { private $storages = array(); public function setUp() { - Filesystem::clearMounts(); + \OC\Files\Filesystem::clearMounts(); } public function tearDown() { @@ -30,9 +28,9 @@ class View extends \PHPUnit_Framework_TestCase { $storage1 = $this->getTestStorage(); $storage2 = $this->getTestStorage(); $storage3 = $this->getTestStorage(); - Filesystem::mount($storage1, array(), '/'); - Filesystem::mount($storage2, array(), '/substorage'); - Filesystem::mount($storage3, array(), '/folder/anotherstorage'); + \OC\Files\Filesystem::mount($storage1, array(), '/'); + \OC\Files\Filesystem::mount($storage2, array(), '/substorage'); + \OC\Files\Filesystem::mount($storage3, array(), '/folder/anotherstorage'); $textSize = strlen("dummy file data\n"); $imageSize = filesize(\OC::$SERVERROOT . '/core/img/logo.png'); $storageSize = $textSize * 2 + $imageSize; @@ -84,8 +82,8 @@ class View extends \PHPUnit_Framework_TestCase { public function testAutoScan() { $storage1 = $this->getTestStorage(false); $storage2 = $this->getTestStorage(false); - Filesystem::mount($storage1, array(), '/'); - Filesystem::mount($storage2, array(), '/substorage'); + \OC\Files\Filesystem::mount($storage1, array(), '/'); + \OC\Files\Filesystem::mount($storage2, array(), '/substorage'); $textSize = strlen("dummy file data\n"); $rootView = new \OC\Files\View(''); @@ -103,9 +101,9 @@ class View extends \PHPUnit_Framework_TestCase { $storage1 = $this->getTestStorage(); $storage2 = $this->getTestStorage(); $storage3 = $this->getTestStorage(); - Filesystem::mount($storage1, array(), '/'); - Filesystem::mount($storage2, array(), '/substorage'); - Filesystem::mount($storage3, array(), '/folder/anotherstorage'); + \OC\Files\Filesystem::mount($storage1, array(), '/'); + \OC\Files\Filesystem::mount($storage2, array(), '/substorage'); + \OC\Files\Filesystem::mount($storage3, array(), '/folder/anotherstorage'); $rootView = new \OC\Files\View(''); @@ -113,7 +111,7 @@ class View extends \PHPUnit_Framework_TestCase { $this->assertEquals(6, count($results)); $paths = array(); foreach ($results as $result) { - $this->assertEquals($result['path'], Filesystem::normalizePath($result['path'])); + $this->assertEquals($result['path'], \OC\Files\Filesystem::normalizePath($result['path'])); $paths[] = $result['path']; } $this->assertContains('/foo.txt', $paths); diff --git a/tests/lib/filesystem.php b/tests/lib/filesystem.php deleted file mode 100644 index 6e7b4fb781..0000000000 --- a/tests/lib/filesystem.php +++ /dev/null @@ -1,110 +0,0 @@ -. - * - */ - -use \OC\Files\Filesystem as Filesystem; - -class Test_Filesystem extends UnitTestCase { - /** - * @var array tmpDirs - */ - private $tmpDirs=array(); - - /** - * @return array - */ - private function getStorageData() { - $dir = OC_Helper::tmpFolder(); - $this->tmpDirs[] = $dir; - return array('datadir' => $dir); - } - - public function tearDown() { - foreach ($this->tmpDirs as $dir) { - OC_Helper::rmdirr($dir); - } - } - - public function setUp() { - Filesystem::clearMounts(); - } - - public function testMount() { - Filesystem::mount('\OC\Files\Storage\Local',self::getStorageData(),'/'); - $this->assertEqual('/',Filesystem::getMountPoint('/')); - $this->assertEqual('/',Filesystem::getMountPoint('/some/folder')); - list( , $internalPath)=\OC\Files\Filesystem::resolvePath('/'); - $this->assertEqual('',$internalPath); - list( , $internalPath)=\OC\Files\Filesystem::resolvePath('/some/folder'); - $this->assertEqual('some/folder',$internalPath); - - Filesystem::mount('\OC\Files\Storage\Local',self::getStorageData(),'/some'); - $this->assertEqual('/',Filesystem::getMountPoint('/')); - $this->assertEqual('/some/',Filesystem::getMountPoint('/some/folder')); - $this->assertEqual('/some/',Filesystem::getMountPoint('/some/')); - $this->assertEqual('/',Filesystem::getMountPoint('/some')); - list( , $internalPath)=\OC\Files\Filesystem::resolvePath('/some/folder'); - $this->assertEqual('folder',$internalPath); - } - - public function testNormalize() { - $this->assertEqual('/path', Filesystem::normalizePath('/path/')); - $this->assertEqual('/path/', Filesystem::normalizePath('/path/', false)); - $this->assertEqual('/path', Filesystem::normalizePath('path')); - $this->assertEqual('/path', Filesystem::normalizePath('\path')); - $this->assertEqual('/foo/bar', Filesystem::normalizePath('/foo//bar/')); - $this->assertEqual('/foo/bar', Filesystem::normalizePath('/foo////bar')); - if (class_exists('Normalizer')) { - $this->assertEqual("/foo/bar\xC3\xBC", Filesystem::normalizePath("/foo/baru\xCC\x88")); - } - } - - public function testHooks() { - if(Filesystem::getView()){ - $user = OC_User::getUser(); - }else{ - $user=uniqid(); - Filesystem::init('/'.$user.'/files'); - } - OC_Hook::clear('OC_Filesystem'); - OC_Hook::connect('OC_Filesystem', 'post_write', $this, 'dummyHook'); - - Filesystem::mount('OC\Files\Storage\Temporary', array(), '/'); - - $rootView=new \OC\Files\View(''); - $rootView->mkdir('/'.$user); - $rootView->mkdir('/'.$user.'/files'); - - Filesystem::file_put_contents('/foo', 'foo'); - Filesystem::mkdir('/bar'); - Filesystem::file_put_contents('/bar//foo', 'foo'); - - $tmpFile = OC_Helper::tmpFile(); - file_put_contents($tmpFile, 'foo'); - $fh = fopen($tmpFile, 'r'); - Filesystem::file_put_contents('/bar//foo', $fh); - } - - public function dummyHook($arguments) { - $path = $arguments['path']; - $this->assertEqual($path, Filesystem::normalizePath($path)); //the path passed to the hook should already be normalized - } -} From c22a723785f80671548b89c543e9163c2fff9264 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 26 Oct 2012 19:07:29 +0200 Subject: [PATCH 053/347] add file permissions cache --- db_structure.xml | 47 +++++++++++++++ lib/files/cache/permissions.php | 85 +++++++++++++++++++++++++++ lib/util.php | 2 +- tests/lib/files/cache/permissions.php | 47 +++++++++++++++ 4 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 lib/files/cache/permissions.php create mode 100644 tests/lib/files/cache/permissions.php diff --git a/db_structure.xml b/db_structure.xml index e0b9dc11e9..e420a9f0e4 100644 --- a/db_structure.xml +++ b/db_structure.xml @@ -175,6 +175,53 @@
+ + + *dbprefix*permissions + + + + + fileid + integer + 0 + true + 4 + + + + user + text + + true + 64 + + + + permissions + integer + 0 + true + 4 + + + + id_user_index + true + + fileid + ascending + + + user + ascending + + + + + +
+ *dbprefix*group_user diff --git a/lib/files/cache/permissions.php b/lib/files/cache/permissions.php new file mode 100644 index 0000000000..e3fa63c464 --- /dev/null +++ b/lib/files/cache/permissions.php @@ -0,0 +1,85 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Files\Cache; + +class Permissions { + /** + * get the permissions for a single file + * + * @param int $fileId + * @param string $user + * @return int (-1 if file no permissions set) + */ + static public function get($fileId, $user) { + $query = \OC_DB::prepare('SELECT `permissions` FROM `*PREFIX*permissions` WHERE `user` = ? AND `fileid` = ?'); + $result = $query->execute(array($user, $fileId)); + if ($row = $result->fetchRow()) { + return $row['permissions']; + } else { + return -1; + } + } + + /** + * set the permissions of a file + * + * @param int $fileId + * @param string $user + * @param int $permissions + */ + static public function set($fileId, $user, $permissions) { + if (self::get($fileId, $user) !== -1) { + $query = \OC_DB::prepare('UPDATE `*PREFIX*permissions` SET `permissions` = ? WHERE `user` = ? AND `fileid` = ?'); + } else { + $query = \OC_DB::prepare('INSERT INTO `*PREFIX*permissions`(`permissions`, `user`, `fileid`) VALUES(?, ?,? )'); + } + $query->execute(array($permissions, $user, $fileId)); + } + + /** + * get the permissions of multiply files + * + * @param int[] $fileIds + * @param string $user + * @return int[] + */ + static public function getMultiple($fileIds, $user) { + $params = $fileIds; + $params[] = $user; + $inPart = implode(', ', array_fill(0, count($fileIds), '?')); + + $query = \OC_DB::prepare('SELECT `fileid`, `permissions` FROM `*PREFIX*permissions` WHERE `fileid` IN (' . $inPart . ') AND `user` = ?'); + $result = $query->execute($params); + $filePermissions = array(); + while ($row = $result->fetchRow()) { + $filePermissions[$row['fileid']] = $row['permissions']; + } + return $filePermissions; + } + + /** + * remove the permissions for a file + * + * @param int $fileId + * @param string $user + */ + static public function remove($fileId, $user) { + $query = \OC_DB::prepare('DELETE FROM `*PREFIX*permissions` WHERE `fileid` = ? AND `user` = ?'); + $query->execute(array($fileId, $user)); + } + + static public function removeMultiple($fileIds, $user) { + $params = $fileIds; + $params[] = $user; + $inPart = implode(', ', array_fill(0, count($fileIds), '?')); + + $query = \OC_DB::prepare('DELETE FROM `*PREFIX*permissions` WHERE `fileid` IN (' . $inPart . ') AND `user` = ?'); + $query->execute($params); + } +} diff --git a/lib/util.php b/lib/util.php index 137766d012..a2e0422c97 100755 --- a/lib/util.php +++ b/lib/util.php @@ -86,7 +86,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,01); } /** diff --git a/tests/lib/files/cache/permissions.php b/tests/lib/files/cache/permissions.php new file mode 100644 index 0000000000..4d47929a3e --- /dev/null +++ b/tests/lib/files/cache/permissions.php @@ -0,0 +1,47 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\Files\Cache; + +class Permissions extends \PHPUnit_Framework_TestCase { + function testSimple() { + $ids = range(1, 10); + $user = uniqid(); + + $this->assertEquals(-1, \OC\Files\Cache\Permissions::get(1, $user)); + \OC\Files\Cache\Permissions::set(1, $user, 1); + $this->assertEquals(1, \OC\Files\Cache\Permissions::get(1, $user)); + $this->assertEquals(-1, \OC\Files\Cache\Permissions::get(2, $user)); + $this->assertEquals(-1, \OC\Files\Cache\Permissions::get(1, $user . '2')); + + \OC\Files\Cache\Permissions::set(1, $user, 2); + $this->assertEquals(2, \OC\Files\Cache\Permissions::get(1, $user)); + + \OC\Files\Cache\Permissions::set(2, $user, 1); + $this->assertEquals(1, \OC\Files\Cache\Permissions::get(2, $user)); + + \OC\Files\Cache\Permissions::remove(1, $user); + $this->assertEquals(-1, \OC\Files\Cache\Permissions::get(1, $user)); + \OC\Files\Cache\Permissions::remove(1, $user . '2'); + $this->assertEquals(1, \OC\Files\Cache\Permissions::get(2, $user)); + + $expected = array(); + foreach ($ids as $id) { + \OC\Files\Cache\Permissions::set($id, $user, 10 + $id); + $expected[$id] = 10 + $id; + } + $this->assertEquals($expected, \OC\Files\Cache\Permissions::getMultiple($ids, $user)); + + \OC\Files\Cache\Permissions::removeMultiple(array(10, 9), $user); + unset($expected[9]); + unset($expected[10]); + $this->assertEquals($expected, \OC\Files\Cache\Permissions::getMultiple($ids, $user)); + + \OC\Files\Cache\Permissions::removeMultiple($ids, $user); + } +} From 6db81afab9d68ccd50c1e164622252e47ae76c2f Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 26 Oct 2012 23:05:02 +0200 Subject: [PATCH 054/347] move some stuff to the new api --- apps/files/ajax/list.php | 2 +- apps/files/ajax/newfile.php | 12 ++++++------ apps/files/ajax/newfolder.php | 3 ++- apps/files/ajax/rawlist.php | 2 +- apps/files/ajax/upload.php | 2 +- apps/files/index.php | 2 +- apps/files/settings.php | 2 +- apps/files_encryption/lib/cryptstream.php | 2 +- apps/files_encryption/lib/proxy.php | 10 +++++----- apps/files_sharing/appinfo/update.php | 3 ++- lib/connector/sabre/directory.php | 6 +++--- lib/connector/sabre/node.php | 4 ++-- lib/fileproxy/quota.php | 12 ++++-------- lib/files.php | 2 +- lib/files/filesystem.php | 13 +++++++++++++ lib/files/view.php | 1 - lib/ocs.php | 4 ++-- lib/public/share.php | 15 +++++++++------ lib/search/provider/file.php | 2 +- settings/personal.php | 4 ++-- 20 files changed, 58 insertions(+), 45 deletions(-) diff --git a/apps/files/ajax/list.php b/apps/files/ajax/list.php index 568fe754c0..92091f4213 100644 --- a/apps/files/ajax/list.php +++ b/apps/files/ajax/list.php @@ -32,7 +32,7 @@ if($doBreadcrumb) { // make filelist $files = array(); -foreach( OC_Files::getdirectorycontent( $dir ) as $i ) { +foreach( \OC\Files\Filesystem::getDirectoryContent( $dir ) as $i ) { $i["date"] = OCP\Util::formatDate($i["mtime"] ); $files[] = $i; } diff --git a/apps/files/ajax/newfile.php b/apps/files/ajax/newfile.php index 5f3f3d88f2..38714f34a6 100644 --- a/apps/files/ajax/newfile.php +++ b/apps/files/ajax/newfile.php @@ -65,9 +65,9 @@ if($source) { $target=$dir.'/'.$filename; $result=\OC\Files\Filesystem::file_put_contents($target, $sourceStream); if($result) { - $meta = OC_FileCache::get($target); + $meta = \OC\Files\Filesystem::getFileInfo($target); $mime=$meta['mimetype']; - $id = OC_FileCache::getId($target); + $id = $meta['fileid']; $eventSource->send('success', array('mime'=>$mime, 'size'=>\OC\Files\Filesystem::filesize($target), 'id' => $id)); } else { $eventSource->send('error', "Error while downloading ".$source. ' to '.$target); @@ -77,14 +77,14 @@ if($source) { } else { if($content) { if(\OC\Files\Filesystem::file_put_contents($dir.'/'.$filename, $content)) { - $meta = OC_FileCache::get($dir.'/'.$filename); - $id = OC_FileCache::getId($dir.'/'.$filename); + $meta = \OC\Files\Filesystem::getFileInfo($dir.'/'.$filename); + $id = $meta['fileid']; OCP\JSON::success(array("data" => array('content'=>$content, 'id' => $id))); exit(); } }elseif(\OC\Files\Filesystem::touch($dir . '/' . $filename)) { - $meta = OC_FileCache::get($dir.'/'.$filename); - $id = OC_FileCache::getId($dir.'/'.$filename); + $meta = \OC\Files\Filesystem::getFileInfo($dir.'/'.$filename); + $id = $meta['fileid']; OCP\JSON::success(array("data" => array('content'=>$content, 'id' => $id))); exit(); } diff --git a/apps/files/ajax/newfolder.php b/apps/files/ajax/newfolder.php index c36c208455..e26e1238bc 100644 --- a/apps/files/ajax/newfolder.php +++ b/apps/files/ajax/newfolder.php @@ -25,7 +25,8 @@ if(\OC\Files\Filesystem::mkdir($dir . '/' . stripslashes($foldername))) { } else { $path = '/'.$foldername; } - $id = OC_FileCache::getId($path); + $meta = \OC\Files\Filesystem::getFileInfo($path); + $id = $meta['fileid']; OCP\JSON::success(array("data" => array('id'=>$id))); exit(); } diff --git a/apps/files/ajax/rawlist.php b/apps/files/ajax/rawlist.php index e0aa0bdac5..1cd2944483 100644 --- a/apps/files/ajax/rawlist.php +++ b/apps/files/ajax/rawlist.php @@ -15,7 +15,7 @@ $mimetype = isset($_GET['mimetype']) ? $_GET['mimetype'] : ''; // make filelist $files = array(); -foreach( OC_Files::getdirectorycontent( $dir, $mimetype ) as $i ) { +foreach( \OC\Files\Filesystem::getDirectoryContent( $dir, $mimetype ) as $i ) { $i["date"] = OCP\Util::formatDate($i["mtime"] ); $i['mimetype_icon'] = $i['type'] == 'dir' ? \mimetype_icon('dir'): \mimetype_icon($i['mimetype']); $files[] = $i; diff --git a/apps/files/ajax/upload.php b/apps/files/ajax/upload.php index b6b8c7f7b4..2a784d6169 100644 --- a/apps/files/ajax/upload.php +++ b/apps/files/ajax/upload.php @@ -49,7 +49,7 @@ if(strpos($dir, '..') === false) { for($i=0;$i<$fileCount;$i++) { $target = OCP\Files::buildNotExistingFileName(stripslashes($dir), $files['name'][$i]); if(is_uploaded_file($files['tmp_name'][$i]) and \OC\Files\Filesystem::fromTmpFile($files['tmp_name'][$i], $target)) { - $meta = \OC_Files::getFileInfo($target); + $meta = \OC\Files\Filesystem::getFileInfo($target); $id = $meta['fileid']; $result[]=array( "status" => "success", 'mime'=>$meta['mimetype'],'size'=>$meta['size'], 'id'=>$id, 'name'=>basename($target)); } diff --git a/apps/files/index.php b/apps/files/index.php index 192cd2696f..4676ebc602 100644 --- a/apps/files/index.php +++ b/apps/files/index.php @@ -44,7 +44,7 @@ if(!\OC\Files\Filesystem::is_dir($dir.'/')) { } $files = array(); -foreach( OC_Files::getdirectorycontent( $dir ) as $i ) { +foreach( \OC\Files\Filesystem::getDirectoryContent( $dir ) as $i ) { $i['date'] = OCP\Util::formatDate($i['mtime'] ); if($i['type']=='file') { $fileinfo=pathinfo($i['name']); diff --git a/apps/files/settings.php b/apps/files/settings.php index 52ec9fd0fe..30463210f7 100644 --- a/apps/files/settings.php +++ b/apps/files/settings.php @@ -36,7 +36,7 @@ OCP\Util::addscript( "files", "files" ); $dir = isset( $_GET['dir'] ) ? $_GET['dir'] : ''; $files = array(); -foreach( OC_Files::getdirectorycontent( $dir ) as $i ) { +foreach( \OC\Files\Filesystem::getDirectoryContent( $dir ) as $i ) { $i["date"] = date( $CONFIG_DATEFORMAT, $i["mtime"] ); $files[] = $i; } diff --git a/apps/files_encryption/lib/cryptstream.php b/apps/files_encryption/lib/cryptstream.php index e98013e1f4..c429838264 100644 --- a/apps/files_encryption/lib/cryptstream.php +++ b/apps/files_encryption/lib/cryptstream.php @@ -167,7 +167,7 @@ class OC_CryptStream{ public function stream_close() { $this->flush(); if($this->meta['mode']!='r' and $this->meta['mode']!='rb') { - OC_FileCache::put($this->path, array('encrypted'=>true,'size'=>$this->size),''); + \OC\Files\Filesystem::putFileInfo($this->path, array('encrypted'=>true,'size'=>$this->size),''); } return fclose($this->source); } diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 7b7bafe73e..49fb30ac29 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -59,7 +59,7 @@ class OC_FileProxy_Encryption extends OC_FileProxy{ * @return bool */ private static function isEncrypted($path) { - $metadata=OC_FileCache_Cached::get($path,''); + $metadata=\OC\Files\Filesystem::getFileInfo($path,''); return isset($metadata['encrypted']) and (bool)$metadata['encrypted']; } @@ -68,14 +68,14 @@ class OC_FileProxy_Encryption extends OC_FileProxy{ if (!is_resource($data)) {//stream put contents should have been converter to fopen $size=strlen($data); $data=OC_Crypt::blockEncrypt($data); - OC_FileCache::put($path, array('encrypted'=>true,'size'=>$size),''); + \OC\Files\Filesystem::putFileInfo($path, array('encrypted'=>true,'size'=>$size),''); } } } public function postFile_get_contents($path,$data) { if(self::isEncrypted($path)) { - $cached=OC_FileCache_Cached::get($path,''); + $cached=\OC\Files\Filesystem::getFileInfo($path,''); $data=OC_Crypt::blockDecrypt($data,'',$cached['size']); } return $data; @@ -113,7 +113,7 @@ class OC_FileProxy_Encryption extends OC_FileProxy{ public function postStat($path,$data) { if(self::isEncrypted($path)) { - $cached=OC_FileCache_Cached::get($path,''); + $cached=\OC\Files\Filesystem::getFileInfo($path,''); $data['size']=$cached['size']; } return $data; @@ -121,7 +121,7 @@ class OC_FileProxy_Encryption extends OC_FileProxy{ public function postFileSize($path,$size) { if(self::isEncrypted($path)) { - $cached=OC_FileCache_Cached::get($path,''); + $cached=\OC\Files\Filesystem::getFileInfo($path,''); return $cached['size']; }else{ return $size; diff --git a/apps/files_sharing/appinfo/update.php b/apps/files_sharing/appinfo/update.php index e75c538b15..51048bd178 100644 --- a/apps/files_sharing/appinfo/update.php +++ b/apps/files_sharing/appinfo/update.php @@ -10,6 +10,7 @@ if (version_compare($installedVersion, '0.3', '<')) { OC_Group::useBackend(new OC_Group_Database()); OC_App::loadApps(array('authentication')); while ($row = $result->fetchRow()) { + $meta = \OC\Files\Filesystem::getId($path, ''); $itemSource = OC_FileCache::getId($row['source'], ''); if ($itemSource != -1) { $file = OC_FileCache::get($row['source'], ''); @@ -70,4 +71,4 @@ if (version_compare($installedVersion, '0.3.3', '<')) { foreach ($users as $user) { OC_FileCache::delete('Shared', '/'.$user.'/files/'); } -} \ No newline at end of file +} diff --git a/lib/connector/sabre/directory.php b/lib/connector/sabre/directory.php index 3df85b2bbb..d4f58527d2 100644 --- a/lib/connector/sabre/directory.php +++ b/lib/connector/sabre/directory.php @@ -93,7 +93,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa $path = $this->path . '/' . $name; if (is_null($info)) { - $info = OC_Files::getFileInfo($path); + $info = \OC\Files\Filesystem::getFileInfo($path); } if (!$info) { @@ -117,7 +117,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa */ public function getChildren() { - $folder_content = OC_Files::getDirectoryContent($this->path); + $folder_content = \OC\Files\Filesystem::getDirectoryContent($this->path); $paths = array(); foreach($folder_content as $info) { $paths[] = $this->path.'/'.$info['name']; @@ -178,7 +178,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa * @return array */ public function getQuotaInfo() { - $rootInfo=OC_FileCache_Cached::get(''); + $rootInfo=\OC\Files\Filesystem::getFileInfo(''); return array( $rootInfo['size'], \OC\Files\Filesystem::free_space() diff --git a/lib/connector/sabre/node.php b/lib/connector/sabre/node.php index e7e83507ea..2095c956e5 100644 --- a/lib/connector/sabre/node.php +++ b/lib/connector/sabre/node.php @@ -95,11 +95,11 @@ 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 + * Make sure the fileinfo cache is filled. Uses the file cache or a direct stat */ protected function getFileinfoCache() { if (!isset($this->fileinfo_cache)) { - if ($fileinfo_cache = \OC\Files\Filesystem::get($this->path)) { + if ($fileinfo_cache = \OC\Files\Filesystem::getFileInfo($this->path)) { } else { $fileinfo_cache = \OC\Files\Filesystem::stat($this->path); } diff --git a/lib/fileproxy/quota.php b/lib/fileproxy/quota.php index d120f30999..cd9a2f4a19 100644 --- a/lib/fileproxy/quota.php +++ b/lib/fileproxy/quota.php @@ -57,7 +57,7 @@ class OC_FileProxy_Quota extends OC_FileProxy{ * @return int */ private function getFreeSpace($path) { - $storage=OC_Filesystem::getStorage($path); + list($storage,)=\OC\Files\Filesystem::resolvePath($path); $owner=$storage->getOwner($path); $totalSpace=$this->getQuota($owner); @@ -65,13 +65,9 @@ class OC_FileProxy_Quota extends OC_FileProxy{ return 0; } - $rootInfo=OC_FileCache::get('', "/".$owner."/files"); - // TODO Remove after merge of share_api - if (OC_FileCache::inCache('/Shared', "/".$owner."/files")) { - $sharedInfo=OC_FileCache::get('/Shared', "/".$owner."/files"); - } else { - $sharedInfo = null; - } + $view = new \OC\Files\View("/".$owner."/files"); + + $rootInfo=$view->getFileInfo('/'); $usedSpace=isset($rootInfo['size'])?$rootInfo['size']:0; $usedSpace=isset($sharedInfo['size'])?$usedSpace-$sharedInfo['size']:$usedSpace; return $totalSpace-$usedSpace; diff --git a/lib/files.php b/lib/files.php index 422e7f4ffe..6a063f216d 100644 --- a/lib/files.php +++ b/lib/files.php @@ -146,7 +146,7 @@ class OC_Files { $dirname = basename($dir); $zip->addEmptyDir($internalDir . $dirname); $internalDir .= $dirname .= '/'; - $files = OC_Files::getdirectorycontent($dir); + $files = \OC\Files\Filesystem::getDirectoryContent($dir); foreach ($files as $file) { $filename = $file['name']; $file = $dir . '/' . $filename; diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php index 4031c0c5b8..b3c92f3855 100644 --- a/lib/files/filesystem.php +++ b/lib/files/filesystem.php @@ -627,6 +627,19 @@ class Filesystem { return self::$defaultInstance->getFileInfo($path); } + /** + * change file metadata + * + * @param string $path + * @param array $data + * @return int + * + * returns the fileid of the updated file + */ + public static function putFileInfo($path, $data) { + return self::$defaultInstance->putFileInfo($path, $data); + } + /** * get the content of a directory * diff --git a/lib/files/view.php b/lib/files/view.php index ee95cce0c1..e9b583f8ae 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -451,7 +451,6 @@ class View { array(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); Filesystem::removeETagHook(array("path" => $path2), $this->fakeRoot); } return $result; diff --git a/lib/ocs.php b/lib/ocs.php index 645380ddba..c6bcd2c06e 100644 --- a/lib/ocs.php +++ b/lib/ocs.php @@ -590,8 +590,8 @@ class OC_OCS { // calculate the disc space $user_dir = '/'.$user.'/files'; \OC\Files\Filesystem::init($user_dir); - $rootInfo=OC_FileCache::get(''); - $sharedInfo=OC_FileCache::get('/Shared'); + $rootInfo=\OC\Files\Filesystem::getFileInfo(''); + $sharedInfo=\OC\Files\Filesystem::getFileInfo('/Shared'); $used=$rootInfo['size']-$sharedInfo['size']; $free=\OC\Files\Filesystem::free_space(); $total=$free+$used; diff --git a/lib/public/share.php b/lib/public/share.php index 7a9a087d1b..dd6c841c99 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -285,10 +285,10 @@ class Share { // If the item is a folder, scan through the folder looking for equivalent item types if ($itemType == 'folder') { $parentFolder = self::put('folder', $itemSource, $shareType, $shareWith, $uidOwner, $permissions, true); - if ($parentFolder && $files = \OC_Files::getDirectoryContent($itemSource)) { + if ($parentFolder && $files = \OC\Files\Filesystem::getDirectoryContent($itemSource)) { for ($i = 0; $i < count($files); $i++) { $name = substr($files[$i]['name'], strpos($files[$i]['name'], $itemSource) - strlen($itemSource)); - if ($files[$i]['mimetype'] == 'httpd/unix-directory' && $children = \OC_Files::getDirectoryContent($name, '/')) { + if ($files[$i]['mimetype'] == 'httpd/unix-directory' && $children = \OC\Files\Filesystem::getDirectoryContent($name, '/')) { // Continue scanning into child folders array_push($files, $children); } else { @@ -768,9 +768,10 @@ class Share { if ($row['item_type'] == 'file' || $row['item_type'] == 'folder') { $childItem['file_source'] = $child['source']; } else { - $childItem['file_source'] = \OC_FileCache::getId($child['file_path']); + $meta = \OC\Files\Filesystem::getFileInfo($child['file_path']); + $childItem['file_source'] = $meta['fileid']; } - $childItem['file_target'] = \OC_Filesystem::normalizePath($child['file_path']); + $childItem['file_target'] = \OC\Files\Filesystem::normalizePath($child['file_path']); } if (isset($item)) { if ($childItem[$column] == $item) { @@ -881,7 +882,8 @@ class Share { if ($itemType == 'file' || $itemType == 'folder') { $fileSource = $itemSource; } else { - $fileSource = \OC_FileCache::getId($filePath); + $meta = \OC\Files\Filesystem::getFileInfo($filePath); + $fileSource = $meta['fileid']; } if ($fileSource == -1) { $message = 'Sharing '.$itemSource.' failed, because the file could not be found in the file cache'; @@ -1063,7 +1065,8 @@ class Share { } if ($item['uid_owner'] == $uidOwner) { if ($itemType == 'file' || $itemType == 'folder') { - if ($item['file_source'] == \OC_FileCache::getId($itemSource)) { + $meta = \OC\Files\Filesystem::getFileInfo($itemSource); + if ($item['file_source'] == $meta['fileid']) { return $target; } } else if ($item['item_source'] == $itemSource) { diff --git a/lib/search/provider/file.php b/lib/search/provider/file.php index 0d4b332b79..456e12b5ec 100644 --- a/lib/search/provider/file.php +++ b/lib/search/provider/file.php @@ -2,7 +2,7 @@ class OC_Search_Provider_File extends OC_Search_Provider{ function search($query) { - $files=OC_FileCache::search($query, true); + $files=\OC\Files\Filesystem::search($query, true); $results=array(); $l=OC_L10N::get('lib'); foreach($files as $fileData) { diff --git a/settings/personal.php b/settings/personal.php index c73a3dd370..5a267ec284 100644 --- a/settings/personal.php +++ b/settings/personal.php @@ -16,8 +16,8 @@ OC_Util::addStyle( '3rdparty', 'chosen' ); OC_App::setActiveNavigationEntry( 'personal' ); // calculate the disc space -$rootInfo=OC_FileCache::get(''); -$sharedInfo=OC_FileCache::get('/Shared'); +$rootInfo=\OC\Files\Filesystem::getFileInfo(''); +$sharedInfo=\OC\Files\Filesystem::getFileInfo('/Shared'); $used=$rootInfo['size']; if($used<0) $used=0; $free=\OC\Files\Filesystem::free_space(); From 7d6da68d532fe1b1299f3a724e70b8ec3960ec8d Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 26 Oct 2012 23:25:52 +0200 Subject: [PATCH 055/347] prove some compatibility with the old cache api --- lib/files/view.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/files/view.php b/lib/files/view.php index e9b583f8ae..04b7dca8af 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -712,7 +712,7 @@ class View { $files = $cache->getFolderContents($internalPath); //TODO: mimetype_filter //add a folder for any mountpoint in this directory and add the sizes of other mountpoints to the folders - $mountPoints = Filesystem::getMountPoints($directory); + $mountPoints = Filesystem::getMountPoints($path); $dirLength = strlen($path); foreach ($mountPoints as $mountPoint) { $subStorage = Filesystem::getStorage($mountPoint); @@ -733,6 +733,10 @@ class View { } } + foreach($files as $i => $file){ + $files[$i]['type'] = $file['mimetype'] === 'httpd/unix-directory' ? 'dir' : 'file'; + } + usort($files, "fileCmp"); //TODO: remove this once ajax is merged return $files; } From 99534271977ef5a4fd35ce119d6627bbcde45096 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 26 Oct 2012 23:26:12 +0200 Subject: [PATCH 056/347] also use new cache api here --- lib/fileproxy/fileoperations.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/fileproxy/fileoperations.php b/lib/fileproxy/fileoperations.php index 23fb63fcfb..47ccd8f8c2 100644 --- a/lib/fileproxy/fileoperations.php +++ b/lib/fileproxy/fileoperations.php @@ -29,9 +29,9 @@ class OC_FileProxy_FileOperations extends OC_FileProxy{ public function premkdir($path) { if(!self::$rootView){ - self::$rootView = new OC_FilesystemView(''); + self::$rootView = new \OC\Files\View(''); } return !self::$rootView->file_exists($path); } -} \ No newline at end of file +} From 695405dfeb4da3733df1b1be239a97100f2ce66f Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sat, 27 Oct 2012 10:01:20 +0200 Subject: [PATCH 057/347] add permissions data to the results of the cache api --- lib/files/cache/cache.php | 15 +++++++++++++++ lib/files/cache/scanner.php | 3 ++- lib/files/view.php | 12 +++++++++++- tests/lib/files/cache/scanner.php | 2 ++ 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index 7e0c5cb21f..5efc7d67c4 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -286,4 +286,19 @@ class Cache { } return $files; } + + /** + * get all file ids on the files on the storage + * + * @return int[] + */ + public function getAll() { + $query = \OC_DB::prepare('SELECT `fileid` FROM `*PREFIX*filecache` WHERE `storage` = ?'); + $result = $query->execute(array($this->storageId)); + $ids = array(); + while ($row = $result->fetchRow()) { + $ids[] = $row['fileid']; + } + return $ids; + } } diff --git a/lib/files/cache/scanner.php b/lib/files/cache/scanner.php index e8f54c34be..0adde1d354 100644 --- a/lib/files/cache/scanner.php +++ b/lib/files/cache/scanner.php @@ -66,7 +66,8 @@ class Scanner { $this->scanFile($parent); } } - $this->cache->put($file, $data); + $id = $this->cache->put($file, $data); + Permissions::set($id, \OC_User::getUser(), $data['permissions']); return $data; } diff --git a/lib/files/view.php b/lib/files/view.php index 04b7dca8af..82455d582e 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -686,6 +686,8 @@ class View { } } + $data['permissions'] = Cache\Permissions::get($data['fileid'], \OC_User::getUser()); + return $data; } @@ -733,8 +735,16 @@ class View { } } - foreach($files as $i => $file){ + $ids = array(); + + foreach ($files as $i => $file) { $files[$i]['type'] = $file['mimetype'] === 'httpd/unix-directory' ? 'dir' : 'file'; + $ids[] = $file['fileid']; + } + + $permissions = Cache\Permissions::getMultiple($ids, \OC_User::getUser()); + foreach ($files as $i => $file) { + $files[$i]['permissions'] = $permissions[$file['fileid']]; } usort($files, "fileCmp"); //TODO: remove this once ajax is merged diff --git a/tests/lib/files/cache/scanner.php b/tests/lib/files/cache/scanner.php index e3f47047f5..34fefc784d 100644 --- a/tests/lib/files/cache/scanner.php +++ b/tests/lib/files/cache/scanner.php @@ -106,6 +106,8 @@ class Scanner extends \UnitTestCase { } function tearDown() { + $ids = $this->cache->getAll(); + \OC\Files\Cache\Permissions::removeMultiple($ids, \OC_User::getUser()); $this->cache->clear(); } } From fcc92a9f43e75ecdb15adb0e948d45eac119306f Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sat, 27 Oct 2012 10:34:25 +0200 Subject: [PATCH 058/347] add searchByMime to new cache api --- lib/files/cache/cache.php | 21 +++++++++++++++++++++ lib/files/filesystem.php | 4 ++++ lib/files/view.php | 25 ++++++++++++++++++++++--- tests/lib/files/cache/cache.php | 3 +++ tests/lib/files/view.php | 3 +++ 5 files changed, 53 insertions(+), 3 deletions(-) diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index 5efc7d67c4..6604525477 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -287,6 +287,27 @@ class Cache { return $files; } + /** + * search for files by mimetype + * + * @param string $part1 + * @param string $part2 + * @return array + */ + public function searchByMime($mimetype) { + if (strpos($mimetype, '/')) { + $where = '`mimetype` = ?'; + } else { + $where = '`mimepart` = ?'; + } + $query = \OC_DB::prepare(' + SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted` + FROM `*PREFIX*filecache` WHERE ' . $where . ' AND `storage` = ?' + ); + $result = $query->execute(array($mimetype, $this->storageId)); + return $result->fetchAll(); + } + /** * get all file ids on the files on the storage * diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php index b3c92f3855..96660a8ce3 100644 --- a/lib/files/filesystem.php +++ b/lib/files/filesystem.php @@ -551,6 +551,10 @@ class Filesystem { return self::$defaultInstance->search($query); } + static public function searchByMime($query) { + return self::$defaultInstance->searchByMime($query); + } + /** * check if a file or folder has been updated since $time * diff --git a/lib/files/view.php b/lib/files/view.php index 82455d582e..0a5a6436c2 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -747,7 +747,7 @@ class View { $files[$i]['permissions'] = $permissions[$file['fileid']]; } - usort($files, "fileCmp"); //TODO: remove this once ajax is merged + usort($files, "fileCmp"); return $files; } @@ -784,6 +784,25 @@ class View { * @return array */ public function search($query) { + return $this->searchCommon('%' . $query . '%', 'search'); + } + + /** + * search for files by mimetype + * + * @param string $query + * @return array + */ + public function searchByMime($mimetype) { + return $this->searchCommon($mimetype, 'searchByMime'); + } + + /** + * @param string $query + * @param string $method + * @return array + */ + private function searchCommon($query, $method) { $files = array(); $rootLength = strlen($this->fakeRoot); @@ -791,7 +810,7 @@ class View { $storage = Filesystem::getStorage($mountPoint); $cache = $storage->getCache(); - $results = $cache->search('%' . $query . '%'); + $results = $cache->$method($query); foreach ($results as $result) { if (substr($mountPoint . $result['path'], 0, $rootLength) === $this->fakeRoot) { $result['path'] = substr($mountPoint . $result['path'], $rootLength); @@ -805,7 +824,7 @@ class View { $cache = $storage->getCache(); $relativeMountPoint = substr($mountPoint, $rootLength); - $results = $cache->search('%' . $query . '%'); + $results = $cache->$method($query); foreach ($results as $result) { $result['path'] = $relativeMountPoint . $result['path']; $files[] = $result; diff --git a/tests/lib/files/cache/cache.php b/tests/lib/files/cache/cache.php index 839e06e93f..5a8d79b902 100644 --- a/tests/lib/files/cache/cache.php +++ b/tests/lib/files/cache/cache.php @@ -129,6 +129,9 @@ class Cache extends \UnitTestCase { $this->assertEquals(1, count($this->cache->search('%folder%'))); $this->assertEquals(1, count($this->cache->search('folder%'))); $this->assertEquals(3, count($this->cache->search('%'))); + + $this->assertEquals(3, count($this->cache->searchByMime('foo'))); + $this->assertEquals(2, count($this->cache->searchByMime('foo/file'))); } public function tearDown() { diff --git a/tests/lib/files/view.php b/tests/lib/files/view.php index 980c5298fb..5144fb1caa 100644 --- a/tests/lib/files/view.php +++ b/tests/lib/files/view.php @@ -139,6 +139,9 @@ class View extends \PHPUnit_Framework_TestCase { } $this->assertContains('/anotherstorage/foo.txt', $paths); $this->assertContains('/anotherstorage/foo.png', $paths); + + $this->assertEquals(6, count($rootView->searchByMime('text'))); + $this->assertEquals(3, count($folderView->searchByMime('text'))); } /** From 3437071cf1776288d9239a89b1a6ceb9c5ddbce1 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sat, 27 Oct 2012 10:40:27 +0200 Subject: [PATCH 059/347] remove old searchByMime --- lib/files.php | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/lib/files.php b/lib/files.php index 6a063f216d..28df225580 100644 --- a/lib/files.php +++ b/lib/files.php @@ -28,24 +28,6 @@ class OC_Files { static $tmpFiles = array(); - public static function searchByMime($mimetype_filter) { - $files = array(); - $dirs_to_check = array(''); - while (!empty($dirs_to_check)) { - // get next subdir to check - $dir = array_pop($dirs_to_check); - $dir_content = self::getDirectoryContent($dir, $mimetype_filter); - foreach ($dir_content as $file) { - if ($file['type'] == 'file') { - $files[] = $dir . '/' . $file['name']; - } else { - $dirs_to_check[] = $dir . '/' . $file['name']; - } - } - } - return $files; - } - /** * return the content of a file or return a zip file containning multiply files * From 5bfff6c56e8d4d911c7a5265bb5462c7122ca495 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sat, 27 Oct 2012 12:17:35 +0200 Subject: [PATCH 060/347] use absolute paths when resolving mount points --- lib/files.php | 10 ---------- lib/files/cache/permissions.php | 3 +++ lib/files/view.php | 35 ++++++++++++++++++++++++--------- lib/public/share.php | 4 ++-- 4 files changed, 31 insertions(+), 21 deletions(-) diff --git a/lib/files.php b/lib/files.php index 28df225580..e6b324f062 100644 --- a/lib/files.php +++ b/lib/files.php @@ -249,13 +249,3 @@ class OC_Files { return false; } } - -function fileCmp($a, $b) { - if ($a['type'] == 'dir' and $b['type'] != 'dir') { - return -1; - } elseif ($a['type'] != 'dir' and $b['type'] == 'dir') { - return 1; - } else { - return strnatcasecmp($a['name'], $b['name']); - } -} diff --git a/lib/files/cache/permissions.php b/lib/files/cache/permissions.php index e3fa63c464..dd7233abc7 100644 --- a/lib/files/cache/permissions.php +++ b/lib/files/cache/permissions.php @@ -50,6 +50,9 @@ class Permissions { * @return int[] */ static public function getMultiple($fileIds, $user) { + if (count($fileIds) === 0) { + return array(); + } $params = $fileIds; $params[] = $user; $inPart = implode(', ', array_fill(0, count($fileIds), '?')); diff --git a/lib/files/view.php b/lib/files/view.php index 0a5a6436c2..0f9a5feb5d 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -110,6 +110,7 @@ class View { */ public function getLocalFile($path) { $parent = substr($path, 0, strrpos($path, '/')); + $path = $this->getAbsolutePath($path); list($storage, $internalPath) = Filesystem::resolvePath($path); if (Filesystem::isValidPath($parent) and $storage) { return $storage->getLocalFile($internalPath); @@ -124,6 +125,7 @@ class View { */ public function getLocalFolder($path) { $parent = substr($path, 0, strrpos($path, '/')); + $path = $this->getAbsolutePath($path); list($storage, $internalPath) = Filesystem::resolvePath($path); if (Filesystem::isValidPath($parent) and $storage) { return $storage->getLocalFolder($internalPath); @@ -334,8 +336,8 @@ class View { $mp1 = $this->getMountPoint($path1 . $postFix1); $mp2 = $this->getMountPoint($path2 . $postFix2); if ($mp1 == $mp2) { - list($storage, $internalPath1) = Filesystem::resolvePath($path1 . $postFix1); - list(, $internalPath2) = Filesystem::resolvePath($path2 . $postFix2); + list($storage, $internalPath1) = Filesystem::resolvePath($absolutePath1 . $postFix1); + list(, $internalPath2) = Filesystem::resolvePath($absolutePath2 . $postFix2); if ($storage) { $result = $storage->rename($internalPath1, $internalPath2); } else { @@ -345,7 +347,7 @@ class View { $source = $this->fopen($path1 . $postFix1, 'r'); $target = $this->fopen($path2 . $postFix2, 'w'); $count = \OC_Helper::streamCopy($source, $target); - list($storage1, $internalPath1) = Filesystem::resolvePath($path1 . $postFix1); + list($storage1, $internalPath1) = Filesystem::resolvePath($absolutePath1 . $postFix1); $storage1->unlink($internalPath1); $result = $count > 0; } @@ -417,8 +419,8 @@ class View { $mp1 = $this->getMountPoint($path1 . $postFix1); $mp2 = $this->getMountPoint($path2 . $postFix2); if ($mp1 == $mp2) { - list($storage, $internalPath1) = Filesystem::resolvePath($path1 . $postFix1); - list(, $internalPath2) = Filesystem::resolvePath($path2 . $postFix2); + list($storage, $internalPath1) = Filesystem::resolvePath($absolutePath1 . $postFix1); + list(, $internalPath2) = Filesystem::resolvePath($absolutePath2 . $postFix2); if ($storage) { $result = $storage->copy($internalPath1, $internalPath2); } else { @@ -552,7 +554,7 @@ class View { array(Filesystem::signal_param_path => $path) ); } - list($storage, $internalPath) = Filesystem::resolvePath($path . $postFix); + list($storage, $internalPath) = Filesystem::resolvePath($absolutePath . $postFix); if ($storage) { $result = $storage->hash($type, $internalPath, $raw); $result = \OC_FileProxy::runPostProxies('hash', $absolutePath, $result); @@ -587,7 +589,7 @@ class View { return false; } $run = $this->runHooks($hooks, $path); - list($storage, $internalPath) = Filesystem::resolvePath($path . $postFix); + list($storage, $internalPath) = Filesystem::resolvePath($absolutePath . $postFix); if ($run and $storage) { if (!is_null($extraParam)) { $result = $storage->$operation($internalPath, $extraParam); @@ -747,8 +749,23 @@ class View { $files[$i]['permissions'] = $permissions[$file['fileid']]; } - usort($files, "fileCmp"); - return $files; + if ($mimetype_filter) { + foreach ($files as $file) { + if (strpos($mimetype_filter, '/')) { + if ($file['mimetype'] === $mimetype_filter) { + $result[] = $file; + } + } else { + if ($file['mimepart'] === $mimetype_filter) { + $result[] = $file; + } + } + } + } else { + $result = $files; + } + + return $result; } /** diff --git a/lib/public/share.php b/lib/public/share.php index 060f67c9e9..707d5abe44 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -534,7 +534,7 @@ class Share { $backend = self::getBackend($itemType); // Get filesystem root to add it to the file target and remove from the file source, match file_source with the file cache if ($itemType == 'file' || $itemType == 'folder') { - $root = \OC_Filesystem::getRoot(); + $root = \OC\Files\Filesystem::getRoot(); $where = 'INNER JOIN `*PREFIX*fscache` ON `file_source` = `*PREFIX*fscache`.`id`'; if (!isset($item)) { $where .= ' WHERE `file_target` IS NOT NULL'; @@ -621,7 +621,7 @@ class Share { } else { if ($itemType == 'file' || $itemType == 'folder') { $where .= ' `file_target` = ?'; - $item = \OC_Filesystem::normalizePath($item); + $item = \OC\Files\Filesystem::normalizePath($item); } else { $where .= ' `item_target` = ?'; } From dea0d20a9ad0270896e57a7459d6276798658d7c Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sat, 27 Oct 2012 12:18:01 +0200 Subject: [PATCH 061/347] fix delete and sort files --- apps/files/ajax/delete.php | 17 +++++++---------- apps/files/ajax/scan.php | 2 ++ apps/files/index.php | 12 ++++++++++++ apps/files_sharing/public.php | 4 ++-- 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/apps/files/ajax/delete.php b/apps/files/ajax/delete.php index ae6158a05a..fdd0c0c491 100644 --- a/apps/files/ajax/delete.php +++ b/apps/files/ajax/delete.php @@ -12,18 +12,15 @@ $files = isset($_POST["file"]) ? stripslashes($_POST["file"]) : stripslashes($_P $files = explode(';', $files); $filesWithError = ''; -if (OC_User::isLoggedIn()) { - $success = true; - //Now delete - foreach ($files as $file) { - if ($dir != '' || $file != 'Shared' && !\OC\Files\Filesystem::unlink($dir . '/' . $file)) { - $filesWithError .= $file . "\n"; - $success = false; - } +$success = true; + +//Now delete +foreach ($files as $file) { + if (($dir === '' && $file === 'Shared') || !\OC\Files\Filesystem::unlink($dir . '/' . $file)) { + $filesWithError .= $file . "\n"; + $success = false; } -} else { - $success = false; } if ($success) { diff --git a/apps/files/ajax/scan.php b/apps/files/ajax/scan.php index 5cd9572d7f..91b20fa836 100644 --- a/apps/files/ajax/scan.php +++ b/apps/files/ajax/scan.php @@ -1,5 +1,7 @@ assign('uidOwner', $uidOwner); $tmpl->assign('dir', basename($dir)); $tmpl->assign('filename', basename($path)); - $tmpl->assign('mimetype', OC_Filesystem::getMimeType($path)); + $tmpl->assign('mimetype', \OC\Files\Filesystem::getMimeType($path)); $tmpl->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true))); if (isset($_GET['path'])) { $getPath = $_GET['path']; @@ -200,7 +200,7 @@ if (isset($_GET['file']) || isset($_GET['dir'])) { $tmpl->assign('uidOwner', $uidOwner); $tmpl->assign('dir', dirname($path)); $tmpl->assign('filename', basename($path)); - $tmpl->assign('mimetype', OC_Filesystem::getMimeType($path)); + $tmpl->assign('mimetype', \OC\Files\Filesystem::getMimeType($path)); if ($type == 'file') { $tmpl->assign('downloadURL', OCP\Util::linkToPublic('files').'&file='.urlencode($_GET['file']).'&download', false); } else { From 86be7e88721ada34e7b230a0e5dfb4df546bc38a Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sat, 27 Oct 2012 12:23:13 +0200 Subject: [PATCH 062/347] remove last uses of depricated OC_Filesystem --- apps/files_sharing/public.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/files_sharing/public.php b/apps/files_sharing/public.php index 143edd23c4..35e7734e2d 100644 --- a/apps/files_sharing/public.php +++ b/apps/files_sharing/public.php @@ -24,7 +24,7 @@ if (isset($_GET['token'])) { function getID($path) { // use the share table from the db to find the item source if the file was reshared because shared files //are not stored in the file cache. - if (substr(OC_Filesystem::getMountPoint($path), -7, 6) == "Shared") { + if (substr(\OC\Files\Filesystem::getMountPoint($path), -7, 6) == "Shared") { $path_parts = explode('/', $path, 5); $user = $path_parts[1]; $intPath = '/'.$path_parts[4]; @@ -33,7 +33,9 @@ function getID($path) { $row = $result->fetchRow(); $fileSource = $row['item_source']; } else { - $fileSource = OC_Filecache::getId($path, ''); + $rootView = new \OC\Files\View(''); + $meta = $rootView->getFileInfo($path); + $fileSource = $meta['fileid']; } return $fileSource; @@ -102,7 +104,7 @@ if (isset($_GET['file']) || isset($_GET['dir'])) { if (isset($_GET['path'])) { $path .= $_GET['path']; $dir .= $_GET['path']; - if (!OC_Filesystem::file_exists($path)) { + if (!\OC\Files\Filesystem::file_exists($path)) { header('HTTP/1.0 404 Not Found'); $tmpl = new OCP\Template('', '404', 'guest'); $tmpl->printPage(); @@ -130,7 +132,7 @@ if (isset($_GET['file']) || isset($_GET['dir'])) { $tmpl = new OCP\Template('files_sharing', 'public', 'base'); $tmpl->assign('owner', $uidOwner); // Show file list - if (OC_Filesystem::is_dir($path)) { + if (\OC\Files\Filesystem::is_dir($path)) { OCP\Util::addStyle('files', 'files'); OCP\Util::addScript('files', 'files'); OCP\Util::addScript('files', 'filelist'); From 0fb707d2c90846c1231cdefac79e9b58c8351c81 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sat, 27 Oct 2012 14:25:15 +0200 Subject: [PATCH 063/347] some more porting of the sharing --- apps/files_sharing/appinfo/update.php | 9 +++++---- apps/files_sharing/public.php | 3 ++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/apps/files_sharing/appinfo/update.php b/apps/files_sharing/appinfo/update.php index 51048bd178..69c526eae0 100644 --- a/apps/files_sharing/appinfo/update.php +++ b/apps/files_sharing/appinfo/update.php @@ -9,11 +9,12 @@ if (version_compare($installedVersion, '0.3', '<')) { OC_User::useBackend(new OC_User_Database()); OC_Group::useBackend(new OC_Group_Database()); OC_App::loadApps(array('authentication')); + $rootView = new \OC\Files\View(''); while ($row = $result->fetchRow()) { - $meta = \OC\Files\Filesystem::getId($path, ''); - $itemSource = OC_FileCache::getId($row['source'], ''); + $meta = $rootView->getFileInfo($$row['source']); + $itemSource = $meta['fileid']; if ($itemSource != -1) { - $file = OC_FileCache::get($row['source'], ''); + $file = $meta; if ($file['mimetype'] == 'httpd/unix-directory') { $itemType = 'folder'; } else { @@ -69,6 +70,6 @@ if (version_compare($installedVersion, '0.3.3', '<')) { OC_App::loadApps(array('authentication')); $users = OC_User::getUsers(); foreach ($users as $user) { - OC_FileCache::delete('Shared', '/'.$user.'/files/'); +// OC_FileCache::delete('Shared', '/'.$user.'/files/'); } } diff --git a/apps/files_sharing/public.php b/apps/files_sharing/public.php index 35e7734e2d..1fe7311002 100644 --- a/apps/files_sharing/public.php +++ b/apps/files_sharing/public.php @@ -10,7 +10,8 @@ if (isset($_GET['token'])) { $qry = \OC_DB::prepare('SELECT `source` FROM `*PREFIX*sharing` WHERE `target` = ? LIMIT 1'); $filepath = $qry->execute(array($_GET['token']))->fetchOne(); if(isset($filepath)) { - $info = OC_FileCache_Cached::get($filepath, ''); + $rootView = new \OC\Files\View(''); + $info = $rootView->getFileInfo($filepath, ''); if(strtolower($info['mimetype']) == 'httpd/unix-directory') { $_GET['dir'] = $filepath; } else { From 7891add28655c7f39b388ac0a889b246b23ad934 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Sat, 27 Oct 2012 15:26:28 +0200 Subject: [PATCH 064/347] don't call $('#found_versions').chosen(); after opening the history drop-down since no version is selected at the beginning --- apps/files_versions/js/versions.js | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/files_versions/js/versions.js b/apps/files_versions/js/versions.js index 426d521df8..b9c5468981 100644 --- a/apps/files_versions/js/versions.js +++ b/apps/files_versions/js/versions.js @@ -73,7 +73,6 @@ function createVersionsDropdown(filename, files) { $.each( versions, function(index, row ) { addVersion( row ); }); - $('#found_versions').chosen(); } else { $('#found_versions').hide(); $('#makelink').hide(); From 72aebe3aa3ce51ef47ef6005b528c4d296e208c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Sat, 27 Oct 2012 15:24:01 +0200 Subject: [PATCH 065/347] fix broken paths in versions app --- apps/files_versions/lib/versions.php | 41 +++++++++++++--------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/apps/files_versions/lib/versions.php b/apps/files_versions/lib/versions.php index 47e514d9d7..e83310172a 100644 --- a/apps/files_versions/lib/versions.php +++ b/apps/files_versions/lib/versions.php @@ -58,10 +58,8 @@ class Storage { public function store($filename) { if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') { list($uid, $filename) = self::getUidAndFilename($filename); - - $userHome = \OC_User::getHome($uid); - $files_view = new \OC\Files\View($userHome.'/files'); - $users_view = new \OC\Files\View($userHome); + $files_view = new \OC\Files\View('/'.\OCP\User::getUser() .'/files'); + $users_view = new \OC\Files\View('/'.\OCP\User::getUser()); //check if source file already exist as version to avoid recursions. // todo does this check work? @@ -96,11 +94,12 @@ class Storage { // check mininterval if the file is being modified by the owner (all shared files should be versioned despite mininterval) if ($uid == \OCP\User::getUser()) { - $versions_fileview = new \OC\Files\View($userHome.'/files_versions'); - $versionsFolderName=\OCP\Config::getSystemValue('datadirectory'). $versions_fileview->getAbsolutePath(''); - $matches=glob($versionsFolderName.'/'.$filename.'.v*'); + $versions_fileview = new \OC\Files\View('/'.\OCP\User::getUser().'/files_versions'); + $versionsName=\OCP\Config::getSystemValue('datadirectory').$versions_fileview->getAbsolutePath($filename); + $versionsFolderName=\OCP\Config::getSystemValue('datadirectory').$versions_fileview->getAbsolutePath(''); + $matches=glob($versionsName.'.v*'); sort($matches); - $parts=explode('.v', end($matches)); + $parts=explode('.v',end($matches)); if((end($parts)+Storage::DEFAULTMININTERVAL)>time()) { return false; } @@ -110,7 +109,7 @@ class Storage { // create all parent folders $info=pathinfo($filename); if(!file_exists($versionsFolderName.'/'.$info['dirname'])) { - mkdir($versionsFolderName.'/'.$info['dirname'],0750, true); + mkdir($versionsFolderName.'/'.$info['dirname'],0750,true); } // store a new version of a file @@ -129,7 +128,7 @@ class Storage { if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') { list($uid, $filename) = self::getUidAndFilename($filename); - $users_view = new \OC\Files\View(\OC_User::getHome($uid)); + $users_view = new \OC\Files\View('/'.\OCP\User::getUser()); // rollback if( @$users_view->copy('files_versions'.$filename.'.v'.$revision, 'files'.$filename) ) { @@ -152,12 +151,12 @@ class Storage { public static function isversioned($filename) { if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') { list($uid, $filename) = self::getUidAndFilename($filename); - $versions_fileview = new \OC\Files\View(\OC_User::getHome($uid).'/files_versions'); + $versions_fileview = new \OC\Files\View('/'.\OCP\User::getUser().'/files_versions'); - $versionsFolderName=\OCP\Config::getSystemValue('datadirectory'). $versions_fileview->getAbsolutePath(''); + $versionsName=\OCP\Config::getSystemValue('datadirectory').$versions_fileview->getAbsolutePath($filename); // check for old versions - $matches=glob($versionsFolderName.$filename.'.v*'); + $matches=glob($versionsName.'.v*'); if(count($matches)>0) { return true; }else{ @@ -177,22 +176,20 @@ class Storage { * @returns array */ public static function getVersions( $filename, $count = 0 ) { - if( \OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true' ) { list($uid, $filename) = self::getUidAndFilename($filename); - $versions_fileview = new \OC\Files\View(\OC_User::getHome($uid).'/files_versions'); + $versions_fileview = new \OC\Files\View('/'.\OCP\User::getUser().'/files_versions'); - $versionsFolderName = \OCP\Config::getSystemValue('datadirectory'). $versions_fileview->getAbsolutePath(''); + $versionsName = \OCP\Config::getSystemValue('datadirectory').$versions_fileview->getAbsolutePath($filename); $versions = array(); - // fetch for old versions - $matches = glob( $versionsFolderName.'/'.$filename.'.v*' ); + $matches = glob( $versionsName.'.v*' ); sort( $matches ); $i = 0; - $files_view = new \OC\Files\View(\OC_User::getHome($uid).'/files'); + $files_view = new \OC\Files\View('/'.\OCP\User::getUser().'/files'); $local_file = $files_view->getLocalFile($filename); foreach( $matches as $ma ) { @@ -249,10 +246,10 @@ class Storage { list($uid, $filename) = self::getUidAndFilename($filename); $versions_fileview = new \OC\Files\View('/'.$uid.'/files_versions'); - $versionsFolderName=\OCP\Config::getSystemValue('datadirectory'). $versions_fileview->getAbsolutePath(''); + $versionsName=\OCP\Config::getSystemValue('datadirectory').$versions_fileview->getAbsolutePath($filename); // check for old versions - $matches = glob( $versionsFolderName.'/'.$filename.'.v*' ); + $matches = glob( $versionsName.'.v*' ); if( count( $matches ) > \OCP\Config::getSystemValue( 'files_versionmaxversions', Storage::DEFAULTMAXVERSIONS ) ) { @@ -263,7 +260,7 @@ class Storage { foreach( $deleteItems as $de ) { - unlink( $versionsFolderName.'/'.$filename.'.v'.$de ); + unlink( $versionsName.'.v'.$de ); } } From 0d3f68cc7a425410e498e9946ab9847348dcdc55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Sat, 27 Oct 2012 15:23:35 +0200 Subject: [PATCH 066/347] fix function documentation --- lib/user.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/user.php b/lib/user.php index 064fcbad96..869984a16e 100644 --- a/lib/user.php +++ b/lib/user.php @@ -369,8 +369,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) { From 2dc1b778b47c7a765b1c4b56aa928c74f7116946 Mon Sep 17 00:00:00 2001 From: Bart Visscher Date: Sat, 27 Oct 2012 16:24:24 +0200 Subject: [PATCH 067/347] Include copy of Symfony routing component, and don't use composer --- .gitignore | 4 - 3rdparty/bin/composer | Bin 631359 -> 0 bytes .../Component/Routing/Annotation/Route.php | 103 ++++++ .../Component/Routing/CompiledRoute.php | 134 ++++++++ .../Routing/Exception/ExceptionInterface.php | 23 ++ .../Exception/InvalidParameterException.php | 23 ++ .../Exception/MethodNotAllowedException.php | 38 +++ .../MissingMandatoryParametersException.php | 24 ++ .../Exception/ResourceNotFoundException.php | 25 ++ .../Exception/RouteNotFoundException.php | 23 ++ .../Generator/Dumper/GeneratorDumper.php | 39 +++ .../Dumper/GeneratorDumperInterface.php | 45 +++ .../Generator/Dumper/PhpGeneratorDumper.php | 150 +++++++++ .../Routing/Generator/UrlGenerator.php | 176 ++++++++++ .../Generator/UrlGeneratorInterface.php | 37 +++ .../routing/Symfony/Component/Routing/LICENSE | 19 ++ .../Routing/Loader/AnnotationClassLoader.php | 213 ++++++++++++ .../Loader/AnnotationDirectoryLoader.php | 77 +++++ .../Routing/Loader/AnnotationFileLoader.php | 125 +++++++ .../Routing/Loader/ClosureLoader.php | 54 +++ .../Routing/Loader/PhpFileLoader.php | 64 ++++ .../Routing/Loader/XmlFileLoader.php | 224 +++++++++++++ .../Routing/Loader/YamlFileLoader.php | 142 ++++++++ .../Loader/schema/routing/routing-1.0.xsd | 38 +++ .../Routing/Matcher/ApacheUrlMatcher.php | 76 +++++ .../Matcher/Dumper/ApacheMatcherDumper.php | 155 +++++++++ .../Routing/Matcher/Dumper/MatcherDumper.php | 44 +++ .../Matcher/Dumper/MatcherDumperInterface.php | 41 +++ .../Matcher/Dumper/PhpMatcherDumper.php | 293 ++++++++++++++++ .../Matcher/RedirectableUrlMatcher.php | 53 +++ .../RedirectableUrlMatcherInterface.php | 35 ++ .../Component/Routing/Matcher/UrlMatcher.php | 151 +++++++++ .../Routing/Matcher/UrlMatcherInterface.php | 38 +++ .../Symfony/Component/Routing/README.md | 32 ++ .../Component/Routing/RequestContext.php | 250 ++++++++++++++ .../Routing/RequestContextAwareInterface.php | 27 ++ .../Symfony/Component/Routing/Route.php | 312 ++++++++++++++++++ .../Component/Routing/RouteCollection.php | 259 +++++++++++++++ .../Component/Routing/RouteCompiler.php | 128 +++++++ .../Routing/RouteCompilerInterface.php | 29 ++ .../Symfony/Component/Routing/Router.php | 263 +++++++++++++++ .../Component/Routing/RouterInterface.php | 26 ++ .../Symfony/Component/Routing/composer.json | 29 ++ composer.json | 18 - 44 files changed, 4037 insertions(+), 22 deletions(-) delete mode 100755 3rdparty/bin/composer create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Annotation/Route.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/CompiledRoute.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Exception/ExceptionInterface.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Exception/InvalidParameterException.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Exception/MethodNotAllowedException.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Exception/MissingMandatoryParametersException.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Exception/ResourceNotFoundException.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Exception/RouteNotFoundException.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Generator/Dumper/GeneratorDumper.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Generator/Dumper/GeneratorDumperInterface.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Generator/UrlGenerator.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Generator/UrlGeneratorInterface.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/LICENSE create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Loader/AnnotationClassLoader.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Loader/AnnotationFileLoader.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Loader/ClosureLoader.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Loader/PhpFileLoader.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Loader/XmlFileLoader.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Loader/YamlFileLoader.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/ApacheUrlMatcher.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/MatcherDumper.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/MatcherDumperInterface.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/RedirectableUrlMatcherInterface.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/UrlMatcher.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/UrlMatcherInterface.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/README.md create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/RequestContext.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/RequestContextAwareInterface.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Route.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/RouteCollection.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/RouteCompiler.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/RouteCompilerInterface.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/Router.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/RouterInterface.php create mode 100644 3rdparty/symfony/routing/Symfony/Component/Routing/composer.json delete mode 100644 composer.json diff --git a/.gitignore b/.gitignore index 4ae39ed7fa..4749dea19d 100644 --- a/.gitignore +++ b/.gitignore @@ -54,7 +54,3 @@ nbproject # WebFinger .well-known /.buildpath -3rdparty/autoload.php -3rdparty/composer/ -3rdparty/symfony/ -composer.lock diff --git a/3rdparty/bin/composer b/3rdparty/bin/composer deleted file mode 100755 index 7999bd4ff6875d721d50c01d28e4b371c78d21d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 631359 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≧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

J{fW+SfXRq-eaET&qYo^DAbnH>1R3g` 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 diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Annotation/Route.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Annotation/Route.php new file mode 100644 index 0000000000..f60af463f2 --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Annotation/Route.php @@ -0,0 +1,103 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Annotation; + +/** + * Annotation class for @Route(). + * + * @Annotation + * + * @author Fabien Potencier + */ +class Route +{ + private $pattern; + private $name; + private $requirements; + private $options; + private $defaults; + + /** + * Constructor. + * + * @param array $data An array of key/value parameters. + */ + public function __construct(array $data) + { + $this->requirements = array(); + $this->options = array(); + $this->defaults = array(); + + if (isset($data['value'])) { + $data['pattern'] = $data['value']; + unset($data['value']); + } + + foreach ($data as $key => $value) { + $method = 'set'.$key; + if (!method_exists($this, $method)) { + throw new \BadMethodCallException(sprintf("Unknown property '%s' on annotation '%s'.", $key, get_class($this))); + } + $this->$method($value); + } + } + + public function setPattern($pattern) + { + $this->pattern = $pattern; + } + + public function getPattern() + { + return $this->pattern; + } + + public function setName($name) + { + $this->name = $name; + } + + public function getName() + { + return $this->name; + } + + public function setRequirements($requirements) + { + $this->requirements = $requirements; + } + + public function getRequirements() + { + return $this->requirements; + } + + public function setOptions($options) + { + $this->options = $options; + } + + public function getOptions() + { + return $this->options; + } + + public function setDefaults($defaults) + { + $this->defaults = $defaults; + } + + public function getDefaults() + { + return $this->defaults; + } +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/CompiledRoute.php b/3rdparty/symfony/routing/Symfony/Component/Routing/CompiledRoute.php new file mode 100644 index 0000000000..c86c9eca5b --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/CompiledRoute.php @@ -0,0 +1,134 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing; + +/** + * CompiledRoutes are returned by the RouteCompiler class. + * + * @author Fabien Potencier + */ +class CompiledRoute +{ + private $route; + private $variables; + private $tokens; + private $staticPrefix; + private $regex; + + /** + * Constructor. + * + * @param Route $route A original Route instance + * @param string $staticPrefix The static prefix of the compiled route + * @param string $regex The regular expression to use to match this route + * @param array $tokens An array of tokens to use to generate URL for this route + * @param array $variables An array of variables + */ + public function __construct(Route $route, $staticPrefix, $regex, array $tokens, array $variables) + { + $this->route = $route; + $this->staticPrefix = $staticPrefix; + $this->regex = $regex; + $this->tokens = $tokens; + $this->variables = $variables; + } + + /** + * Returns the Route instance. + * + * @return Route A Route instance + */ + public function getRoute() + { + return $this->route; + } + + /** + * Returns the static prefix. + * + * @return string The static prefix + */ + public function getStaticPrefix() + { + return $this->staticPrefix; + } + + /** + * Returns the regex. + * + * @return string The regex + */ + public function getRegex() + { + return $this->regex; + } + + /** + * Returns the tokens. + * + * @return array The tokens + */ + public function getTokens() + { + return $this->tokens; + } + + /** + * Returns the variables. + * + * @return array The variables + */ + public function getVariables() + { + return $this->variables; + } + + /** + * Returns the pattern. + * + * @return string The pattern + */ + public function getPattern() + { + return $this->route->getPattern(); + } + + /** + * Returns the options. + * + * @return array The options + */ + public function getOptions() + { + return $this->route->getOptions(); + } + + /** + * Returns the defaults. + * + * @return array The defaults + */ + public function getDefaults() + { + return $this->route->getDefaults(); + } + + /** + * Returns the requirements. + * + * @return array The requirements + */ + public function getRequirements() + { + return $this->route->getRequirements(); + } +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Exception/ExceptionInterface.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Exception/ExceptionInterface.php new file mode 100644 index 0000000000..5289f525fc --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Exception/ExceptionInterface.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Exception; + +/** + * ExceptionInterface + * + * @author Alexandre Salomé + * + * @api + */ +interface ExceptionInterface +{ +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Exception/InvalidParameterException.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Exception/InvalidParameterException.php new file mode 100644 index 0000000000..4f12469529 --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Exception/InvalidParameterException.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Exception; + +/** + * Exception thrown when a parameter is not valid + * + * @author Alexandre Salomé + * + * @api + */ +class InvalidParameterException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Exception/MethodNotAllowedException.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Exception/MethodNotAllowedException.php new file mode 100644 index 0000000000..470ce52216 --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Exception/MethodNotAllowedException.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Exception; + +/** + * The resource was found but the request method is not allowed. + * + * This exception should trigger an HTTP 405 response in your application code. + * + * @author Kris Wallsmith + * + * @api + */ +class MethodNotAllowedException extends \RuntimeException implements ExceptionInterface +{ + protected $allowedMethods; + + public function __construct(array $allowedMethods, $message = null, $code = 0, \Exception $previous = null) + { + $this->allowedMethods = array_map('strtoupper', $allowedMethods); + + parent::__construct($message, $code, $previous); + } + + public function getAllowedMethods() + { + return $this->allowedMethods; + } +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Exception/MissingMandatoryParametersException.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Exception/MissingMandatoryParametersException.php new file mode 100644 index 0000000000..5a523fa559 --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Exception/MissingMandatoryParametersException.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Exception; + +/** + * Exception thrown when a route cannot be generated because of missing + * mandatory parameters. + * + * @author Alexandre Salomé + * + * @api + */ +class MissingMandatoryParametersException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Exception/ResourceNotFoundException.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Exception/ResourceNotFoundException.php new file mode 100644 index 0000000000..362a0d61f3 --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Exception/ResourceNotFoundException.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Exception; + +/** + * The resource was not found. + * + * This exception should trigger an HTTP 404 response in your application code. + * + * @author Kris Wallsmith + * + * @api + */ +class ResourceNotFoundException extends \RuntimeException implements ExceptionInterface +{ +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Exception/RouteNotFoundException.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Exception/RouteNotFoundException.php new file mode 100644 index 0000000000..4d5f288e7e --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Exception/RouteNotFoundException.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Exception; + +/** + * Exception thrown when a route does not exists + * + * @author Alexandre Salomé + * + * @api + */ +class RouteNotFoundException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Generator/Dumper/GeneratorDumper.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Generator/Dumper/GeneratorDumper.php new file mode 100644 index 0000000000..1291bd12d0 --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Generator/Dumper/GeneratorDumper.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Generator\Dumper; + +use Symfony\Component\Routing\RouteCollection; + +/** + * GeneratorDumper is the base class for all built-in generator dumpers. + * + * @author Fabien Potencier + */ +abstract class GeneratorDumper implements GeneratorDumperInterface +{ + private $routes; + + /** + * Constructor. + * + * @param RouteCollection $routes The RouteCollection to dump + */ + public function __construct(RouteCollection $routes) + { + $this->routes = $routes; + } + + public function getRoutes() + { + return $this->routes; + } +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Generator/Dumper/GeneratorDumperInterface.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Generator/Dumper/GeneratorDumperInterface.php new file mode 100644 index 0000000000..6f5353caf2 --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Generator/Dumper/GeneratorDumperInterface.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Generator\Dumper; + +use Symfony\Component\Routing\RouteCollection; + +/** + * GeneratorDumperInterface is the interface that all generator dumper classes must implement. + * + * @author Fabien Potencier + * + * @api + */ +interface GeneratorDumperInterface +{ + /** + * Dumps a set of routes to a PHP class. + * + * Available options: + * + * * class: The class name + * * base_class: The base class name + * + * @param array $options An array of options + * + * @return string A PHP class representing the generator class + */ + public function dump(array $options = array()); + + /** + * Gets the routes to dump. + * + * @return RouteCollection A RouteCollection instance + */ + public function getRoutes(); +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php new file mode 100644 index 0000000000..080dd3a253 --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php @@ -0,0 +1,150 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Generator\Dumper; + +use Symfony\Component\Routing\Route; + +/** + * PhpGeneratorDumper creates a PHP class able to generate URLs for a given set of routes. + * + * @author Fabien Potencier + * + * @api + */ +class PhpGeneratorDumper extends GeneratorDumper +{ + /** + * Dumps a set of routes to a PHP class. + * + * Available options: + * + * * class: The class name + * * base_class: The base class name + * + * @param array $options An array of options + * + * @return string A PHP class representing the generator class + * + * @api + */ + public function dump(array $options = array()) + { + $options = array_merge(array( + 'class' => 'ProjectUrlGenerator', + 'base_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator', + ), $options); + + return + $this->startClass($options['class'], $options['base_class']). + $this->addConstructor(). + $this->addGenerator(). + $this->endClass() + ; + } + + private function addGenerator() + { + $methods = array(); + foreach ($this->getRoutes()->all() as $name => $route) { + $compiledRoute = $route->compile(); + + $variables = str_replace("\n", '', var_export($compiledRoute->getVariables(), true)); + $defaults = str_replace("\n", '', var_export($compiledRoute->getDefaults(), true)); + $requirements = str_replace("\n", '', var_export($compiledRoute->getRequirements(), true)); + $tokens = str_replace("\n", '', var_export($compiledRoute->getTokens(), true)); + + $escapedName = str_replace('.', '__', $name); + + $methods[] = <<{'get'.\$escapedName.'RouteInfo'}(); + + return \$this->doGenerate(\$variables, \$defaults, \$requirements, \$tokens, \$parameters, \$name, \$absolute); + } + +$methods +EOF; + } + + private function startClass($class, $baseClass) + { + $routes = array(); + foreach ($this->getRoutes()->all() as $name => $route) { + $routes[] = " '$name' => true,"; + } + $routes = implode("\n", $routes); + + return <<context = \$context; + } + +EOF; + } + + private function endClass() + { + return << + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Generator; + +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; +use Symfony\Component\Routing\RequestContext; +use Symfony\Component\Routing\Exception\InvalidParameterException; +use Symfony\Component\Routing\Exception\RouteNotFoundException; +use Symfony\Component\Routing\Exception\MissingMandatoryParametersException; + +/** + * UrlGenerator generates URL based on a set of routes. + * + * @author Fabien Potencier + * + * @api + */ +class UrlGenerator implements UrlGeneratorInterface +{ + protected $context; + protected $decodedChars = array( + // %2F is not valid in a URL, so we don't encode it (which is fine as the requirements explicitly allowed it) + '%2F' => '/', + ); + + protected $routes; + protected $cache; + + /** + * Constructor. + * + * @param RouteCollection $routes A RouteCollection instance + * @param RequestContext $context The context + * + * @api + */ + public function __construct(RouteCollection $routes, RequestContext $context) + { + $this->routes = $routes; + $this->context = $context; + $this->cache = array(); + } + + /** + * Sets the request context. + * + * @param RequestContext $context The context + * + * @api + */ + public function setContext(RequestContext $context) + { + $this->context = $context; + } + + /** + * Gets the request context. + * + * @return RequestContext The context + */ + public function getContext() + { + return $this->context; + } + + /** + * Generates a URL from the given parameters. + * + * @param string $name The name of the route + * @param mixed $parameters An array of parameters + * @param Boolean $absolute Whether to generate an absolute URL + * + * @return string The generated URL + * + * @throws Symfony\Component\Routing\Exception\RouteNotFoundException When route doesn't exist + * + * @api + */ + public function generate($name, $parameters = array(), $absolute = false) + { + if (null === $route = $this->routes->get($name)) { + throw new RouteNotFoundException(sprintf('Route "%s" does not exist.', $name)); + } + + if (!isset($this->cache[$name])) { + $this->cache[$name] = $route->compile(); + } + + return $this->doGenerate($this->cache[$name]->getVariables(), $route->getDefaults(), $route->getRequirements(), $this->cache[$name]->getTokens(), $parameters, $name, $absolute); + } + + /** + * @throws Symfony\Component\Routing\Exception\MissingMandatoryParametersException When route has some missing mandatory parameters + * @throws Symfony\Component\Routing\Exception\InvalidParameterException When a parameter value is not correct + */ + protected function doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $absolute) + { + $variables = array_flip($variables); + + $originParameters = $parameters; + $parameters = array_replace($this->context->getParameters(), $parameters); + $tparams = array_replace($defaults, $parameters); + + // all params must be given + if ($diff = array_diff_key($variables, $tparams)) { + throw new MissingMandatoryParametersException(sprintf('The "%s" route has some missing mandatory parameters ("%s").', $name, implode('", "', array_keys($diff)))); + } + + $url = ''; + $optional = true; + foreach ($tokens as $token) { + if ('variable' === $token[0]) { + if (false === $optional || !array_key_exists($token[3], $defaults) || (isset($parameters[$token[3]]) && (string) $parameters[$token[3]] != (string) $defaults[$token[3]])) { + if (!$isEmpty = in_array($tparams[$token[3]], array(null, '', false), true)) { + // check requirement + if ($tparams[$token[3]] && !preg_match('#^'.$token[2].'$#', $tparams[$token[3]])) { + throw new InvalidParameterException(sprintf('Parameter "%s" for route "%s" must match "%s" ("%s" given).', $token[3], $name, $token[2], $tparams[$token[3]])); + } + } + + if (!$isEmpty || !$optional) { + $url = $token[1].strtr(rawurlencode($tparams[$token[3]]), $this->decodedChars).$url; + } + + $optional = false; + } + } elseif ('text' === $token[0]) { + $url = $token[1].$url; + $optional = false; + } + } + + if (!$url) { + $url = '/'; + } + + // add a query string if needed + $extra = array_diff_key($originParameters, $variables, $defaults); + if ($extra && $query = http_build_query($extra, '', '&')) { + $url .= '?'.$query; + } + + $url = $this->context->getBaseUrl().$url; + + if ($this->context->getHost()) { + $scheme = $this->context->getScheme(); + if (isset($requirements['_scheme']) && ($req = strtolower($requirements['_scheme'])) && $scheme != $req) { + $absolute = true; + $scheme = $req; + } + + if ($absolute) { + $port = ''; + if ('http' === $scheme && 80 != $this->context->getHttpPort()) { + $port = ':'.$this->context->getHttpPort(); + } elseif ('https' === $scheme && 443 != $this->context->getHttpsPort()) { + $port = ':'.$this->context->getHttpsPort(); + } + + $url = $scheme.'://'.$this->context->getHost().$port.$url; + } + } + + return $url; + } +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Generator/UrlGeneratorInterface.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Generator/UrlGeneratorInterface.php new file mode 100644 index 0000000000..6f2800c27c --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Generator/UrlGeneratorInterface.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Generator; + +use Symfony\Component\Routing\RequestContextAwareInterface; + +/** + * UrlGeneratorInterface is the interface that all URL generator classes must implements. + * + * @author Fabien Potencier + * + * @api + */ +interface UrlGeneratorInterface extends RequestContextAwareInterface +{ + /** + * Generates a URL from the given parameters. + * + * @param string $name The name of the route + * @param mixed $parameters An array of parameters + * @param Boolean $absolute Whether to generate an absolute URL + * + * @return string The generated URL + * + * @api + */ + public function generate($name, $parameters = array(), $absolute = false); +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/LICENSE b/3rdparty/symfony/routing/Symfony/Component/Routing/LICENSE new file mode 100644 index 0000000000..cdffe7aebc --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2004-2012 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/AnnotationClassLoader.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/AnnotationClassLoader.php new file mode 100644 index 0000000000..5f292d4589 --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/AnnotationClassLoader.php @@ -0,0 +1,213 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader; + +use Doctrine\Common\Annotations\Reader; +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; +use Symfony\Component\Config\Loader\LoaderInterface; +use Symfony\Component\Config\Loader\LoaderResolver; + +/** + * AnnotationClassLoader loads routing information from a PHP class and its methods. + * + * You need to define an implementation for the getRouteDefaults() method. Most of the + * time, this method should define some PHP callable to be called for the route + * (a controller in MVC speak). + * + * The @Route annotation can be set on the class (for global parameters), + * and on each method. + * + * The @Route annotation main value is the route pattern. The annotation also + * recognizes three parameters: requirements, options, and name. The name parameter + * is mandatory. Here is an example of how you should be able to use it: + * + * /** + * * @Route("/Blog") + * * / + * class Blog + * { + * /** + * * @Route("/", name="blog_index") + * * / + * public function index() + * { + * } + * + * /** + * * @Route("/{id}", name="blog_post", requirements = {"id" = "\d+"}) + * * / + * public function show() + * { + * } + * } + * + * @author Fabien Potencier + */ +abstract class AnnotationClassLoader implements LoaderInterface +{ + protected $reader; + protected $routeAnnotationClass = 'Symfony\\Component\\Routing\\Annotation\\Route'; + protected $defaultRouteIndex; + + /** + * Constructor. + * + * @param Reader $reader + */ + public function __construct(Reader $reader) + { + $this->reader = $reader; + } + + /** + * Sets the annotation class to read route properties from. + * + * @param string $class A fully-qualified class name + */ + public function setRouteAnnotationClass($class) + { + $this->routeAnnotationClass = $class; + } + + /** + * Loads from annotations from a class. + * + * @param string $class A class name + * @param string $type The resource type + * + * @return RouteCollection A RouteCollection instance + * + * @throws \InvalidArgumentException When route can't be parsed + */ + public function load($class, $type = null) + { + if (!class_exists($class)) { + throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class)); + } + + $globals = array( + 'pattern' => '', + 'requirements' => array(), + 'options' => array(), + 'defaults' => array(), + ); + + $class = new \ReflectionClass($class); + if ($class->isAbstract()) { + throw new \InvalidArgumentException(sprintf('Annotations from class "%s" cannot be read as it is abstract.', $class)); + } + + if ($annot = $this->reader->getClassAnnotation($class, $this->routeAnnotationClass)) { + if (null !== $annot->getPattern()) { + $globals['pattern'] = $annot->getPattern(); + } + + if (null !== $annot->getRequirements()) { + $globals['requirements'] = $annot->getRequirements(); + } + + if (null !== $annot->getOptions()) { + $globals['options'] = $annot->getOptions(); + } + + if (null !== $annot->getDefaults()) { + $globals['defaults'] = $annot->getDefaults(); + } + } + + $collection = new RouteCollection(); + $collection->addResource(new FileResource($class->getFileName())); + + foreach ($class->getMethods() as $method) { + $this->defaultRouteIndex = 0; + foreach ($this->reader->getMethodAnnotations($method) as $annot) { + if ($annot instanceof $this->routeAnnotationClass) { + $this->addRoute($collection, $annot, $globals, $class, $method); + } + } + } + + return $collection; + } + + protected function addRoute(RouteCollection $collection, $annot, $globals, \ReflectionClass $class, \ReflectionMethod $method) + { + $name = $annot->getName(); + if (null === $name) { + $name = $this->getDefaultRouteName($class, $method); + } + + $defaults = array_merge($globals['defaults'], $annot->getDefaults()); + $requirements = array_merge($globals['requirements'], $annot->getRequirements()); + $options = array_merge($globals['options'], $annot->getOptions()); + + $route = new Route($globals['pattern'].$annot->getPattern(), $defaults, $requirements, $options); + + $this->configureRoute($route, $class, $method, $annot); + + $collection->add($name, $route); + } + + /** + * Returns true if this class supports the given resource. + * + * @param mixed $resource A resource + * @param string $type The resource type + * + * @return Boolean True if this class supports the given resource, false otherwise + */ + public function supports($resource, $type = null) + { + return is_string($resource) && preg_match('/^(?:\\\\?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)+$/', $resource) && (!$type || 'annotation' === $type); + } + + /** + * Sets the loader resolver. + * + * @param LoaderResolver $resolver A LoaderResolver instance + */ + public function setResolver(LoaderResolver $resolver) + { + } + + /** + * Gets the loader resolver. + * + * @return LoaderResolver A LoaderResolver instance + */ + public function getResolver() + { + } + + /** + * Gets the default route name for a class method. + * + * @param \ReflectionClass $class + * @param \ReflectionMethod $method + * + * @return string + */ + protected function getDefaultRouteName(\ReflectionClass $class, \ReflectionMethod $method) + { + $name = strtolower(str_replace('\\', '_', $class->name).'_'.$method->name); + if ($this->defaultRouteIndex > 0) { + $name .= '_'.$this->defaultRouteIndex; + } + $this->defaultRouteIndex++; + + return $name; + } + + abstract protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, $annot); +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.php new file mode 100644 index 0000000000..8097cd67f9 --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader; + +use Symfony\Component\Routing\RouteCollection; +use Symfony\Component\Config\Resource\DirectoryResource; + +/** + * AnnotationDirectoryLoader loads routing information from annotations set + * on PHP classes and methods. + * + * @author Fabien Potencier + */ +class AnnotationDirectoryLoader extends AnnotationFileLoader +{ + /** + * Loads from annotations from a directory. + * + * @param string $path A directory path + * @param string $type The resource type + * + * @return RouteCollection A RouteCollection instance + * + * @throws \InvalidArgumentException When the directory does not exist or its routes cannot be parsed + */ + public function load($path, $type = null) + { + $dir = $this->locator->locate($path); + + $collection = new RouteCollection(); + $collection->addResource(new DirectoryResource($dir, '/\.php$/')); + foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) { + if (!$file->isFile() || '.php' !== substr($file->getFilename(), -4)) { + continue; + } + + if ($class = $this->findClass($file)) { + $refl = new \ReflectionClass($class); + if ($refl->isAbstract()) { + continue; + } + + $collection->addCollection($this->loader->load($class, $type)); + } + } + + return $collection; + } + + /** + * Returns true if this class supports the given resource. + * + * @param mixed $resource A resource + * @param string $type The resource type + * + * @return Boolean True if this class supports the given resource, false otherwise + */ + public function supports($resource, $type = null) + { + try { + $path = $this->locator->locate($resource); + } catch (\Exception $e) { + return false; + } + + return is_string($resource) && is_dir($path) && (!$type || 'annotation' === $type); + } +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/AnnotationFileLoader.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/AnnotationFileLoader.php new file mode 100644 index 0000000000..49e1cb2f77 --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/AnnotationFileLoader.php @@ -0,0 +1,125 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader; + +use Symfony\Component\Routing\RouteCollection; +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Config\Loader\FileLoader; +use Symfony\Component\Config\FileLocator; + +/** + * AnnotationFileLoader loads routing information from annotations set + * on a PHP class and its methods. + * + * @author Fabien Potencier + */ +class AnnotationFileLoader extends FileLoader +{ + protected $loader; + + /** + * Constructor. + * + * @param FileLocator $locator A FileLocator instance + * @param AnnotationClassLoader $loader An AnnotationClassLoader instance + * @param string|array $paths A path or an array of paths where to look for resources + */ + public function __construct(FileLocator $locator, AnnotationClassLoader $loader, $paths = array()) + { + if (!function_exists('token_get_all')) { + throw new \RuntimeException('The Tokenizer extension is required for the routing annotation loaders.'); + } + + parent::__construct($locator, $paths); + + $this->loader = $loader; + } + + /** + * Loads from annotations from a file. + * + * @param string $file A PHP file path + * @param string $type The resource type + * + * @return RouteCollection A RouteCollection instance + * + * @throws \InvalidArgumentException When the file does not exist or its routes cannot be parsed + */ + public function load($file, $type = null) + { + $path = $this->locator->locate($file); + + $collection = new RouteCollection(); + if ($class = $this->findClass($path)) { + $collection->addResource(new FileResource($path)); + $collection->addCollection($this->loader->load($class, $type)); + } + + return $collection; + } + + /** + * Returns true if this class supports the given resource. + * + * @param mixed $resource A resource + * @param string $type The resource type + * + * @return Boolean True if this class supports the given resource, false otherwise + */ + public function supports($resource, $type = null) + { + return is_string($resource) && 'php' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'annotation' === $type); + } + + /** + * Returns the full class name for the first class in the file. + * + * @param string $file A PHP file path + * + * @return string|false Full class name if found, false otherwise + */ + protected function findClass($file) + { + $class = false; + $namespace = false; + $tokens = token_get_all(file_get_contents($file)); + for ($i = 0, $count = count($tokens); $i < $count; $i++) { + $token = $tokens[$i]; + + if (!is_array($token)) { + continue; + } + + if (true === $class && T_STRING === $token[0]) { + return $namespace.'\\'.$token[1]; + } + + if (true === $namespace && T_STRING === $token[0]) { + $namespace = ''; + do { + $namespace .= $token[1]; + $token = $tokens[++$i]; + } while ($i < $count && is_array($token) && in_array($token[0], array(T_NS_SEPARATOR, T_STRING))); + } + + if (T_CLASS === $token[0]) { + $class = true; + } + + if (T_NAMESPACE === $token[0]) { + $namespace = true; + } + } + + return false; + } +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/ClosureLoader.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/ClosureLoader.php new file mode 100644 index 0000000000..ca49c8fa35 --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/ClosureLoader.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader; + +use Symfony\Component\Config\Loader\Loader; + +/** + * ClosureLoader loads routes from a PHP closure. + * + * The Closure must return a RouteCollection instance. + * + * @author Fabien Potencier + * + * @api + */ +class ClosureLoader extends Loader +{ + /** + * Loads a Closure. + * + * @param \Closure $closure A Closure + * @param string $type The resource type + * + * @api + */ + public function load($closure, $type = null) + { + return call_user_func($closure); + } + + /** + * Returns true if this class supports the given resource. + * + * @param mixed $resource A resource + * @param string $type The resource type + * + * @return Boolean True if this class supports the given resource, false otherwise + * + * @api + */ + public function supports($resource, $type = null) + { + return $resource instanceof \Closure && (!$type || 'closure' === $type); + } +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/PhpFileLoader.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/PhpFileLoader.php new file mode 100644 index 0000000000..ffd31f9444 --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/PhpFileLoader.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader; + +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Config\Loader\FileLoader; + +/** + * PhpFileLoader loads routes from a PHP file. + * + * The file must return a RouteCollection instance. + * + * @author Fabien Potencier + * + * @api + */ +class PhpFileLoader extends FileLoader +{ + /** + * Loads a PHP file. + * + * @param mixed $file A PHP file path + * @param string $type The resource type + * + * @api + */ + public function load($file, $type = null) + { + // the loader variable is exposed to the included file below + $loader = $this; + + $path = $this->locator->locate($file); + $this->setCurrentDir(dirname($path)); + + $collection = include $path; + $collection->addResource(new FileResource($path)); + + return $collection; + } + + /** + * Returns true if this class supports the given resource. + * + * @param mixed $resource A resource + * @param string $type The resource type + * + * @return Boolean True if this class supports the given resource, false otherwise + * + * @api + */ + public function supports($resource, $type = null) + { + return is_string($resource) && 'php' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'php' === $type); + } +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/XmlFileLoader.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/XmlFileLoader.php new file mode 100644 index 0000000000..5dad9db3fa --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/XmlFileLoader.php @@ -0,0 +1,224 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader; + +use Symfony\Component\Routing\RouteCollection; +use Symfony\Component\Routing\Route; +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Config\Loader\FileLoader; + +/** + * XmlFileLoader loads XML routing files. + * + * @author Fabien Potencier + * + * @api + */ +class XmlFileLoader extends FileLoader +{ + /** + * Loads an XML file. + * + * @param string $file An XML file path + * @param string $type The resource type + * + * @return RouteCollection A RouteCollection instance + * + * @throws \InvalidArgumentException When a tag can't be parsed + * + * @api + */ + public function load($file, $type = null) + { + $path = $this->locator->locate($file); + + $xml = $this->loadFile($path); + + $collection = new RouteCollection(); + $collection->addResource(new FileResource($path)); + + // process routes and imports + foreach ($xml->documentElement->childNodes as $node) { + if (!$node instanceof \DOMElement) { + continue; + } + + $this->parseNode($collection, $node, $path, $file); + } + + return $collection; + } + + /** + * Parses a node from a loaded XML file. + * + * @param RouteCollection $collection the collection to associate with the node + * @param DOMElement $node the node to parse + * @param string $path the path of the XML file being processed + * @param string $file + */ + protected function parseNode(RouteCollection $collection, \DOMElement $node, $path, $file) + { + switch ($node->tagName) { + case 'route': + $this->parseRoute($collection, $node, $path); + break; + case 'import': + $resource = (string) $node->getAttribute('resource'); + $type = (string) $node->getAttribute('type'); + $prefix = (string) $node->getAttribute('prefix'); + $this->setCurrentDir(dirname($path)); + $collection->addCollection($this->import($resource, ('' !== $type ? $type : null), false, $file), $prefix); + break; + default: + throw new \InvalidArgumentException(sprintf('Unable to parse tag "%s"', $node->tagName)); + } + } + + /** + * Returns true if this class supports the given resource. + * + * @param mixed $resource A resource + * @param string $type The resource type + * + * @return Boolean True if this class supports the given resource, false otherwise + * + * @api + */ + public function supports($resource, $type = null) + { + return is_string($resource) && 'xml' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'xml' === $type); + } + + /** + * Parses a route and adds it to the RouteCollection. + * + * @param RouteCollection $collection A RouteCollection instance + * @param \DOMElement $definition Route definition + * @param string $file An XML file path + * + * @throws \InvalidArgumentException When the definition cannot be parsed + */ + protected function parseRoute(RouteCollection $collection, \DOMElement $definition, $file) + { + $defaults = array(); + $requirements = array(); + $options = array(); + + foreach ($definition->childNodes as $node) { + if (!$node instanceof \DOMElement) { + continue; + } + + switch ($node->tagName) { + case 'default': + $defaults[(string) $node->getAttribute('key')] = trim((string) $node->nodeValue); + break; + case 'option': + $options[(string) $node->getAttribute('key')] = trim((string) $node->nodeValue); + break; + case 'requirement': + $requirements[(string) $node->getAttribute('key')] = trim((string) $node->nodeValue); + break; + default: + throw new \InvalidArgumentException(sprintf('Unable to parse tag "%s"', $node->tagName)); + } + } + + $route = new Route((string) $definition->getAttribute('pattern'), $defaults, $requirements, $options); + + $collection->add((string) $definition->getAttribute('id'), $route); + } + + /** + * Loads an XML file. + * + * @param string $file An XML file path + * + * @return \DOMDocument + * + * @throws \InvalidArgumentException When loading of XML file returns error + */ + protected function loadFile($file) + { + $internalErrors = libxml_use_internal_errors(true); + $disableEntities = libxml_disable_entity_loader(true); + libxml_clear_errors(); + + $dom = new \DOMDocument(); + $dom->validateOnParse = true; + if (!$dom->loadXML(file_get_contents($file), LIBXML_NONET | (defined('LIBXML_COMPACT') ? LIBXML_COMPACT : 0))) { + libxml_disable_entity_loader($disableEntities); + + throw new \InvalidArgumentException(implode("\n", $this->getXmlErrors($internalErrors))); + } + $dom->normalizeDocument(); + + libxml_use_internal_errors($internalErrors); + libxml_disable_entity_loader($disableEntities); + + foreach ($dom->childNodes as $child) { + if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) { + throw new \InvalidArgumentException('Document types are not allowed.'); + } + } + + $this->validate($dom); + + return $dom; + } + + /** + * Validates a loaded XML file. + * + * @param \DOMDocument $dom A loaded XML file + * + * @throws \InvalidArgumentException When XML doesn't validate its XSD schema + */ + protected function validate(\DOMDocument $dom) + { + $location = __DIR__.'/schema/routing/routing-1.0.xsd'; + + $current = libxml_use_internal_errors(true); + libxml_clear_errors(); + + if (!$dom->schemaValidate($location)) { + throw new \InvalidArgumentException(implode("\n", $this->getXmlErrors($current))); + } + libxml_use_internal_errors($current); + } + + /** + * Retrieves libxml errors and clears them. + * + * @return array An array of libxml error strings + */ + private function getXmlErrors($internalErrors) + { + $errors = array(); + foreach (libxml_get_errors() as $error) { + $errors[] = sprintf('[%s %s] %s (in %s - line %d, column %d)', + LIBXML_ERR_WARNING == $error->level ? 'WARNING' : 'ERROR', + $error->code, + trim($error->message), + $error->file ? $error->file : 'n/a', + $error->line, + $error->column + ); + } + + libxml_clear_errors(); + libxml_use_internal_errors($internalErrors); + + return $errors; + } +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/YamlFileLoader.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/YamlFileLoader.php new file mode 100644 index 0000000000..ee72383435 --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/YamlFileLoader.php @@ -0,0 +1,142 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader; + +use Symfony\Component\Routing\RouteCollection; +use Symfony\Component\Routing\Route; +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Yaml\Yaml; +use Symfony\Component\Config\Loader\FileLoader; + +/** + * YamlFileLoader loads Yaml routing files. + * + * @author Fabien Potencier + * + * @api + */ +class YamlFileLoader extends FileLoader +{ + private static $availableKeys = array( + 'type', 'resource', 'prefix', 'pattern', 'options', 'defaults', 'requirements' + ); + + /** + * Loads a Yaml file. + * + * @param string $file A Yaml file path + * @param string $type The resource type + * + * @return RouteCollection A RouteCollection instance + * + * @throws \InvalidArgumentException When route can't be parsed + * + * @api + */ + public function load($file, $type = null) + { + $path = $this->locator->locate($file); + + $config = Yaml::parse($path); + + $collection = new RouteCollection(); + $collection->addResource(new FileResource($path)); + + // empty file + if (null === $config) { + $config = array(); + } + + // not an array + if (!is_array($config)) { + throw new \InvalidArgumentException(sprintf('The file "%s" must contain a YAML array.', $file)); + } + + foreach ($config as $name => $config) { + $config = $this->normalizeRouteConfig($config); + + if (isset($config['resource'])) { + $type = isset($config['type']) ? $config['type'] : null; + $prefix = isset($config['prefix']) ? $config['prefix'] : null; + $this->setCurrentDir(dirname($path)); + $collection->addCollection($this->import($config['resource'], $type, false, $file), $prefix); + } else { + $this->parseRoute($collection, $name, $config, $path); + } + } + + return $collection; + } + + /** + * Returns true if this class supports the given resource. + * + * @param mixed $resource A resource + * @param string $type The resource type + * + * @return Boolean True if this class supports the given resource, false otherwise + * + * @api + */ + public function supports($resource, $type = null) + { + return is_string($resource) && 'yml' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'yaml' === $type); + } + + /** + * Parses a route and adds it to the RouteCollection. + * + * @param RouteCollection $collection A RouteCollection instance + * @param string $name Route name + * @param array $config Route definition + * @param string $file A Yaml file path + * + * @throws \InvalidArgumentException When config pattern is not defined for the given route + */ + protected function parseRoute(RouteCollection $collection, $name, $config, $file) + { + $defaults = isset($config['defaults']) ? $config['defaults'] : array(); + $requirements = isset($config['requirements']) ? $config['requirements'] : array(); + $options = isset($config['options']) ? $config['options'] : array(); + + if (!isset($config['pattern'])) { + throw new \InvalidArgumentException(sprintf('You must define a "pattern" for the "%s" route.', $name)); + } + + $route = new Route($config['pattern'], $defaults, $requirements, $options); + + $collection->add($name, $route); + } + + /** + * Normalize route configuration. + * + * @param array $config A resource config + * + * @return array + * + * @throws InvalidArgumentException if one of the provided config keys is not supported + */ + private function normalizeRouteConfig(array $config) + { + foreach ($config as $key => $value) { + if (!in_array($key, self::$availableKeys)) { + throw new \InvalidArgumentException(sprintf( + 'Yaml routing loader does not support given key: "%s". Expected one of the (%s).', + $key, implode(', ', self::$availableKeys) + )); + } + } + + return $config; + } +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd new file mode 100644 index 0000000000..a9554e64df --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/ApacheUrlMatcher.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/ApacheUrlMatcher.php new file mode 100644 index 0000000000..3003dfdebb --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/ApacheUrlMatcher.php @@ -0,0 +1,76 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Matcher; + +use Symfony\Component\Routing\Exception\MethodNotAllowedException; + +/** + * ApacheUrlMatcher matches URL based on Apache mod_rewrite matching (see ApacheMatcherDumper). + * + * @author Fabien Potencier + */ +class ApacheUrlMatcher extends UrlMatcher +{ + /** + * Tries to match a URL based on Apache mod_rewrite matching. + * + * Returns false if no route matches the URL. + * + * @param string $pathinfo The pathinfo to be parsed + * + * @return array An array of parameters + * + * @throws MethodNotAllowedException If the current method is not allowed + */ + public function match($pathinfo) + { + $parameters = array(); + $defaults = array(); + $allow = array(); + $match = false; + + foreach ($_SERVER as $key => $value) { + $name = $key; + + if (0 === strpos($name, 'REDIRECT_')) { + $name = substr($name, 9); + } + + if (0 === strpos($name, '_ROUTING_DEFAULTS_')) { + $name = substr($name, 18); + $defaults[$name] = $value; + } elseif (0 === strpos($name, '_ROUTING_')) { + $name = substr($name, 9); + if ('_route' == $name) { + $match = true; + $parameters[$name] = $value; + } elseif (0 === strpos($name, '_allow_')) { + $allow[] = substr($name, 7); + } else { + $parameters[$name] = $value; + } + } else { + continue; + } + + unset($_SERVER[$key]); + } + + if ($match) { + return $this->mergeDefaults($parameters, $defaults); + } elseif (0 < count($allow)) { + throw new MethodNotAllowedException($allow); + } else { + return parent::match($pathinfo); + } + } +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.php new file mode 100644 index 0000000000..4f03b8d393 --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.php @@ -0,0 +1,155 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Matcher\Dumper; + +/** + * Dumps a set of Apache mod_rewrite rules. + * + * @author Fabien Potencier + * @author Kris Wallsmith + */ +class ApacheMatcherDumper extends MatcherDumper +{ + /** + * Dumps a set of Apache mod_rewrite rules. + * + * Available options: + * + * * script_name: The script name (app.php by default) + * * base_uri: The base URI ("" by default) + * + * @param array $options An array of options + * + * @return string A string to be used as Apache rewrite rules + * + * @throws \LogicException When the route regex is invalid + */ + public function dump(array $options = array()) + { + $options = array_merge(array( + 'script_name' => 'app.php', + 'base_uri' => '', + ), $options); + + $options['script_name'] = self::escape($options['script_name'], ' ', '\\'); + + $rules = array("# skip \"real\" requests\nRewriteCond %{REQUEST_FILENAME} -f\nRewriteRule .* - [QSA,L]"); + $methodVars = array(); + + foreach ($this->getRoutes()->all() as $name => $route) { + $compiledRoute = $route->compile(); + + // prepare the apache regex + $regex = $compiledRoute->getRegex(); + $delimiter = $regex[0]; + $regexPatternEnd = strrpos($regex, $delimiter); + if (strlen($regex) < 2 || 0 === $regexPatternEnd) { + throw new \LogicException('The "%s" route regex "%s" is invalid', $name, $regex); + } + $regex = preg_replace('/\?P<.+?>/', '', substr($regex, 1, $regexPatternEnd - 1)); + $regex = '^'.self::escape(preg_quote($options['base_uri']).substr($regex, 1), ' ', '\\'); + + $hasTrailingSlash = '/$' == substr($regex, -2) && '^/$' != $regex; + + $variables = array('E=_ROUTING__route:'.$name); + foreach ($compiledRoute->getVariables() as $i => $variable) { + $variables[] = 'E=_ROUTING_'.$variable.':%'.($i + 1); + } + foreach ($route->getDefaults() as $key => $value) { + $variables[] = 'E=_ROUTING_DEFAULTS_'.$key.':'.strtr($value, array( + ':' => '\\:', + '=' => '\\=', + '\\' => '\\\\', + ' ' => '\\ ', + )); + } + $variables = implode(',', $variables); + + $rule = array("# $name"); + + // method mismatch + if ($req = $route->getRequirement('_method')) { + $methods = explode('|', strtoupper($req)); + // GET and HEAD are equivalent + if (in_array('GET', $methods) && !in_array('HEAD', $methods)) { + $methods[] = 'HEAD'; + } + $allow = array(); + foreach ($methods as $method) { + $methodVars[] = $method; + $allow[] = 'E=_ROUTING__allow_'.$method.':1'; + } + + $rule[] = "RewriteCond %{REQUEST_URI} $regex"; + $rule[] = sprintf("RewriteCond %%{REQUEST_METHOD} !^(%s)$ [NC]", implode('|', $methods)); + $rule[] = sprintf('RewriteRule .* - [S=%d,%s]', $hasTrailingSlash ? 2 : 1, implode(',', $allow)); + } + + // redirect with trailing slash appended + if ($hasTrailingSlash) { + $rule[] = 'RewriteCond %{REQUEST_URI} '.substr($regex, 0, -2).'$'; + $rule[] = 'RewriteRule .* $0/ [QSA,L,R=301]'; + } + + // the main rule + $rule[] = "RewriteCond %{REQUEST_URI} $regex"; + $rule[] = "RewriteRule .* {$options['script_name']} [QSA,L,$variables]"; + + $rules[] = implode("\n", $rule); + } + + if (0 < count($methodVars)) { + $rule = array('# 405 Method Not Allowed'); + $methodVars = array_values(array_unique($methodVars)); + foreach ($methodVars as $i => $methodVar) { + $rule[] = sprintf('RewriteCond %%{_ROUTING__allow_%s} !-z%s', $methodVar, isset($methodVars[$i + 1]) ? ' [OR]' : ''); + } + $rule[] = sprintf('RewriteRule .* %s [QSA,L]', $options['script_name']); + + $rules[] = implode("\n", $rule); + } + + return implode("\n\n", $rules)."\n"; + } + + /** + * Escapes a string. + * + * @param string $string The string to be escaped + * @param string $char The character to be escaped + * @param string $with The character to be used for escaping + * + * @return string The escaped string + */ + private static function escape($string, $char, $with) + { + $escaped = false; + $output = ''; + foreach (str_split($string) as $symbol) { + if ($escaped) { + $output .= $symbol; + $escaped = false; + continue; + } + if ($symbol === $char) { + $output .= $with.$char; + continue; + } + if ($symbol === $with) { + $escaped = true; + } + $output .= $symbol; + } + + return $output; + } +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/MatcherDumper.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/MatcherDumper.php new file mode 100644 index 0000000000..423368b57e --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/MatcherDumper.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Matcher\Dumper; + +use Symfony\Component\Routing\RouteCollection; + +/** + * MatcherDumper is the abstract class for all built-in matcher dumpers. + * + * @author Fabien Potencier + */ +abstract class MatcherDumper implements MatcherDumperInterface +{ + private $routes; + + /** + * Constructor. + * + * @param RouteCollection $routes The RouteCollection to dump + */ + public function __construct(RouteCollection $routes) + { + $this->routes = $routes; + } + + /** + * Gets the routes to dump. + * + * @return RouteCollection A RouteCollection instance + */ + public function getRoutes() + { + return $this->routes; + } +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/MatcherDumperInterface.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/MatcherDumperInterface.php new file mode 100644 index 0000000000..fe09e067d7 --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/MatcherDumperInterface.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Matcher\Dumper; + +/** + * MatcherDumperInterface is the interface that all matcher dumper classes must implement. + * + * @author Fabien Potencier + */ +interface MatcherDumperInterface +{ + /** + * Dumps a set of routes to a PHP class. + * + * Available options: + * + * * class: The class name + * * base_class: The base class name + * + * @param array $options An array of options + * + * @return string A PHP class representing the matcher class + */ + public function dump(array $options = array()); + + /** + * Gets the routes to match. + * + * @return RouteCollection A RouteCollection instance + */ + public function getRoutes(); +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php new file mode 100644 index 0000000000..fdaad513a1 --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php @@ -0,0 +1,293 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Matcher\Dumper; + +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +/** + * PhpMatcherDumper creates a PHP class able to match URLs for a given set of routes. + * + * @author Fabien Potencier + */ +class PhpMatcherDumper extends MatcherDumper +{ + /** + * Dumps a set of routes to a PHP class. + * + * Available options: + * + * * class: The class name + * * base_class: The base class name + * + * @param array $options An array of options + * + * @return string A PHP class representing the matcher class + */ + public function dump(array $options = array()) + { + $options = array_merge(array( + 'class' => 'ProjectUrlMatcher', + 'base_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher', + ), $options); + + // trailing slash support is only enabled if we know how to redirect the user + $interfaces = class_implements($options['base_class']); + $supportsRedirections = isset($interfaces['Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface']); + + return + $this->startClass($options['class'], $options['base_class']). + $this->addConstructor(). + $this->addMatcher($supportsRedirections). + $this->endClass() + ; + } + + private function addMatcher($supportsRedirections) + { + // we need to deep clone the routes as we will modify the structure to optimize the dump + $code = implode("\n", $this->compileRoutes(clone $this->getRoutes(), $supportsRedirections)); + + return <<getIterator(); + $keys = array_keys($routeIterator->getArrayCopy()); + $keysCount = count($keys); + + $i = 0; + foreach ($routeIterator as $name => $route) { + $i++; + + if ($route instanceof RouteCollection) { + $prefix = $route->getPrefix(); + $optimizable = $prefix && count($route->all()) > 1 && false === strpos($route->getPrefix(), '{'); + $indent = ''; + if ($optimizable) { + for ($j = $i; $j < $keysCount; $j++) { + if ($keys[$j] === null) { + continue; + } + + $testRoute = $routeIterator->offsetGet($keys[$j]); + $isCollection = ($testRoute instanceof RouteCollection); + + $testPrefix = $isCollection ? $testRoute->getPrefix() : $testRoute->getPattern(); + + if (0 === strpos($testPrefix, $prefix)) { + $routeIterator->offsetUnset($keys[$j]); + + if ($isCollection) { + $route->addCollection($testRoute); + } else { + $route->add($keys[$j], $testRoute); + } + + $i++; + $keys[$j] = null; + } + } + + if ($prefix !== $parentPrefix) { + $code[] = sprintf(" if (0 === strpos(\$pathinfo, %s)) {", var_export($prefix, true)); + $indent = ' '; + } + } + + foreach ($this->compileRoutes($route, $supportsRedirections, $prefix) as $line) { + foreach (explode("\n", $line) as $l) { + if ($l) { + $code[] = $indent.$l; + } else { + $code[] = $l; + } + } + } + + if ($optimizable && $prefix !== $parentPrefix) { + $code[] = " }\n"; + } + } else { + foreach ($this->compileRoute($route, $name, $supportsRedirections, $parentPrefix) as $line) { + $code[] = $line; + } + } + } + + return $code; + } + + private function compileRoute(Route $route, $name, $supportsRedirections, $parentPrefix = null) + { + $code = array(); + $compiledRoute = $route->compile(); + $conditions = array(); + $hasTrailingSlash = false; + $matches = false; + if (!count($compiledRoute->getVariables()) && false !== preg_match('#^(.)\^(?P.*?)\$\1#', $compiledRoute->getRegex(), $m)) { + if ($supportsRedirections && substr($m['url'], -1) === '/') { + $conditions[] = sprintf("rtrim(\$pathinfo, '/') === %s", var_export(rtrim(str_replace('\\', '', $m['url']), '/'), true)); + $hasTrailingSlash = true; + } else { + $conditions[] = sprintf("\$pathinfo === %s", var_export(str_replace('\\', '', $m['url']), true)); + } + } else { + if ($compiledRoute->getStaticPrefix() && $compiledRoute->getStaticPrefix() != $parentPrefix) { + $conditions[] = sprintf("0 === strpos(\$pathinfo, %s)", var_export($compiledRoute->getStaticPrefix(), true)); + } + + $regex = $compiledRoute->getRegex(); + if ($supportsRedirections && $pos = strpos($regex, '/$')) { + $regex = substr($regex, 0, $pos).'/?$'.substr($regex, $pos + 2); + $hasTrailingSlash = true; + } + $conditions[] = sprintf("preg_match(%s, \$pathinfo, \$matches)", var_export($regex, true)); + + $matches = true; + } + + $conditions = implode(' && ', $conditions); + + $gotoname = 'not_'.preg_replace('/[^A-Za-z0-9_]/', '', $name); + + $code[] = <<getRequirement('_method')) { + $methods = explode('|', strtoupper($req)); + // GET and HEAD are equivalent + if (in_array('GET', $methods) && !in_array('HEAD', $methods)) { + $methods[] = 'HEAD'; + } + if (1 === count($methods)) { + $code[] = <<context->getMethod() != '$methods[0]') { + \$allow[] = '$methods[0]'; + goto $gotoname; + } +EOF; + } else { + $methods = implode('\', \'', $methods); + $code[] = <<context->getMethod(), array('$methods'))) { + \$allow = array_merge(\$allow, array('$methods')); + goto $gotoname; + } +EOF; + } + } + + if ($hasTrailingSlash) { + $code[] = sprintf(<<redirect(\$pathinfo.'/', '%s'); + } +EOF + , $name); + } + + if ($scheme = $route->getRequirement('_scheme')) { + if (!$supportsRedirections) { + throw new \LogicException('The "_scheme" requirement is only supported for route dumper that implements RedirectableUrlMatcherInterface.'); + } + + $code[] = sprintf(<<context->getScheme() !== '$scheme') { + return \$this->redirect(\$pathinfo, '%s', '$scheme'); + } +EOF + , $name); + } + + // optimize parameters array + if (true === $matches && $compiledRoute->getDefaults()) { + $code[] = sprintf(" return array_merge(\$this->mergeDefaults(\$matches, %s), array('_route' => '%s'));" + , str_replace("\n", '', var_export($compiledRoute->getDefaults(), true)), $name); + } elseif (true === $matches) { + $code[] = sprintf(" \$matches['_route'] = '%s';", $name); + $code[] = sprintf(" return \$matches;", $name); + } elseif ($compiledRoute->getDefaults()) { + $code[] = sprintf(' return %s;', str_replace("\n", '', var_export(array_merge($compiledRoute->getDefaults(), array('_route' => $name)), true))); + } else { + $code[] = sprintf(" return array('_route' => '%s');", $name); + } + $code[] = " }"; + + if ($req) { + $code[] = " $gotoname:"; + } + + $code[] = ''; + + return $code; + } + + private function startClass($class, $baseClass) + { + return <<context = \$context; + } + +EOF; + } + + private function endClass() + { + return << + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Matcher; + +use Symfony\Component\Routing\Exception\ResourceNotFoundException; + +/** + * @author Fabien Potencier + * + * @api + */ +abstract class RedirectableUrlMatcher extends UrlMatcher implements RedirectableUrlMatcherInterface +{ + private $trailingSlashTest = false; + + /** + * @see UrlMatcher::match() + * + * @api + */ + public function match($pathinfo) + { + try { + $parameters = parent::match($pathinfo); + } catch (ResourceNotFoundException $e) { + if ('/' === substr($pathinfo, -1)) { + throw $e; + } + + // try with a / at the end + $this->trailingSlashTest = true; + + return $this->match($pathinfo.'/'); + } + + if ($this->trailingSlashTest) { + $this->trailingSlashTest = false; + + return $this->redirect($pathinfo, null); + } + + return $parameters; + } +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/RedirectableUrlMatcherInterface.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/RedirectableUrlMatcherInterface.php new file mode 100644 index 0000000000..929ae9cc78 --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/RedirectableUrlMatcherInterface.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Matcher; + +/** + * RedirectableUrlMatcherInterface knows how to redirect the user. + * + * @author Fabien Potencier + * + * @api + */ +interface RedirectableUrlMatcherInterface +{ + /** + * Redirects the user to another URL. + * + * @param string $path The path info to redirect to. + * @param string $route The route that matched + * @param string $scheme The URL scheme (null to keep the current one) + * + * @return array An array of parameters + * + * @api + */ + public function redirect($path, $route, $scheme = null); +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/UrlMatcher.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/UrlMatcher.php new file mode 100644 index 0000000000..5ff8070ea0 --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/UrlMatcher.php @@ -0,0 +1,151 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Matcher; + +use Symfony\Component\Routing\Exception\MethodNotAllowedException; +use Symfony\Component\Routing\Exception\ResourceNotFoundException; +use Symfony\Component\Routing\RouteCollection; +use Symfony\Component\Routing\RequestContext; + +/** + * UrlMatcher matches URL based on a set of routes. + * + * @author Fabien Potencier + * + * @api + */ +class UrlMatcher implements UrlMatcherInterface +{ + protected $context; + protected $allow; + + private $routes; + + /** + * Constructor. + * + * @param RouteCollection $routes A RouteCollection instance + * @param RequestContext $context The context + * + * @api + */ + public function __construct(RouteCollection $routes, RequestContext $context) + { + $this->routes = $routes; + $this->context = $context; + } + + /** + * Sets the request context. + * + * @param RequestContext $context The context + * + * @api + */ + public function setContext(RequestContext $context) + { + $this->context = $context; + } + + /** + * Gets the request context. + * + * @return RequestContext The context + */ + public function getContext() + { + return $this->context; + } + + /** + * Tries to match a URL with a set of routes. + * + * @param string $pathinfo The path info to be parsed + * + * @return array An array of parameters + * + * @throws ResourceNotFoundException If the resource could not be found + * @throws MethodNotAllowedException If the resource was found but the request method is not allowed + * + * @api + */ + public function match($pathinfo) + { + $this->allow = array(); + + if ($ret = $this->matchCollection($pathinfo, $this->routes)) { + return $ret; + } + + throw 0 < count($this->allow) + ? new MethodNotAllowedException(array_unique(array_map('strtoupper', $this->allow))) + : new ResourceNotFoundException(); + } + + protected function matchCollection($pathinfo, RouteCollection $routes) + { + $pathinfo = urldecode($pathinfo); + + foreach ($routes as $name => $route) { + if ($route instanceof RouteCollection) { + if (false === strpos($route->getPrefix(), '{') && $route->getPrefix() !== substr($pathinfo, 0, strlen($route->getPrefix()))) { + continue; + } + + if (!$ret = $this->matchCollection($pathinfo, $route)) { + continue; + } + + return $ret; + } + + $compiledRoute = $route->compile(); + + // check the static prefix of the URL first. Only use the more expensive preg_match when it matches + if ('' !== $compiledRoute->getStaticPrefix() && 0 !== strpos($pathinfo, $compiledRoute->getStaticPrefix())) { + continue; + } + + if (!preg_match($compiledRoute->getRegex(), $pathinfo, $matches)) { + continue; + } + + // check HTTP method requirement + if ($req = $route->getRequirement('_method')) { + // HEAD and GET are equivalent as per RFC + if ('HEAD' === $method = $this->context->getMethod()) { + $method = 'GET'; + } + + if (!in_array($method, $req = explode('|', strtoupper($req)))) { + $this->allow = array_merge($this->allow, $req); + + continue; + } + } + + return array_merge($this->mergeDefaults($matches, $route->getDefaults()), array('_route' => $name)); + } + } + + protected function mergeDefaults($params, $defaults) + { + $parameters = $defaults; + foreach ($params as $key => $value) { + if (!is_int($key)) { + $parameters[$key] = rawurldecode($value); + } + } + + return $parameters; + } +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/UrlMatcherInterface.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/UrlMatcherInterface.php new file mode 100644 index 0000000000..5823d3201b --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Matcher/UrlMatcherInterface.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Matcher; + +use Symfony\Component\Routing\RequestContextAwareInterface; + +/** + * UrlMatcherInterface is the interface that all URL matcher classes must implement. + * + * @author Fabien Potencier + * + * @api + */ +interface UrlMatcherInterface extends RequestContextAwareInterface +{ + /** + * Tries to match a URL with a set of routes. + * + * @param string $pathinfo The path info to be parsed + * + * @return array An array of parameters + * + * @throws ResourceNotFoundException If the resource could not be found + * @throws MethodNotAllowedException If the resource was found but the request method is not allowed + * + * @api + */ + public function match($pathinfo); +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/README.md b/3rdparty/symfony/routing/Symfony/Component/Routing/README.md new file mode 100644 index 0000000000..eb72334d2e --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/README.md @@ -0,0 +1,32 @@ +Routing Component +================= + +Routing associates a request with the code that will convert it to a response. + +The example below demonstrates how you can set up a fully working routing +system: + + use Symfony\Component\HttpFoundation\Request; + use Symfony\Component\Routing\Matcher\UrlMatcher; + use Symfony\Component\Routing\RequestContext; + use Symfony\Component\Routing\RouteCollection; + use Symfony\Component\Routing\Route; + + $routes = new RouteCollection(); + $routes->add('hello', new Route('/hello', array('controller' => 'foo'))); + + $context = new RequestContext(); + + // this is optional and can be done without a Request instance + $context->fromRequest(Request::createFromGlobals()); + + $matcher = new UrlMatcher($routes, $context); + + $parameters = $matcher->match('/hello'); + +Resources +--------- + +Unit tests: + +https://github.com/symfony/symfony/tree/master/tests/Symfony/Tests/Component/Routing diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/RequestContext.php b/3rdparty/symfony/routing/Symfony/Component/Routing/RequestContext.php new file mode 100644 index 0000000000..fef85b6bb3 --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/RequestContext.php @@ -0,0 +1,250 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing; + +/** + * Holds information about the current request. + * + * @author Fabien Potencier + * + * @api + */ +class RequestContext +{ + private $baseUrl; + private $method; + private $host; + private $scheme; + private $httpPort; + private $httpsPort; + private $parameters; + + /** + * Constructor. + * + * @param string $baseUrl The base URL + * @param string $method The HTTP method + * @param string $host The HTTP host name + * @param string $scheme The HTTP scheme + * @param integer $httpPort The HTTP port + * @param integer $httpsPort The HTTPS port + * + * @api + */ + public function __construct($baseUrl = '', $method = 'GET', $host = 'localhost', $scheme = 'http', $httpPort = 80, $httpsPort = 443) + { + $this->baseUrl = $baseUrl; + $this->method = strtoupper($method); + $this->host = $host; + $this->scheme = strtolower($scheme); + $this->httpPort = $httpPort; + $this->httpsPort = $httpsPort; + $this->parameters = array(); + } + + /** + * Gets the base URL. + * + * @return string The base URL + */ + public function getBaseUrl() + { + return $this->baseUrl; + } + + /** + * Sets the base URL. + * + * @param string $baseUrl The base URL + * + * @api + */ + public function setBaseUrl($baseUrl) + { + $this->baseUrl = $baseUrl; + } + + /** + * Gets the HTTP method. + * + * The method is always an uppercased string. + * + * @return string The HTTP method + */ + public function getMethod() + { + return $this->method; + } + + /** + * Sets the HTTP method. + * + * @param string $method The HTTP method + * + * @api + */ + public function setMethod($method) + { + $this->method = strtoupper($method); + } + + /** + * Gets the HTTP host. + * + * @return string The HTTP host + */ + public function getHost() + { + return $this->host; + } + + /** + * Sets the HTTP host. + * + * @param string $host The HTTP host + * + * @api + */ + public function setHost($host) + { + $this->host = $host; + } + + /** + * Gets the HTTP scheme. + * + * @return string The HTTP scheme + */ + public function getScheme() + { + return $this->scheme; + } + + /** + * Sets the HTTP scheme. + * + * @param string $scheme The HTTP scheme + * + * @api + */ + public function setScheme($scheme) + { + $this->scheme = strtolower($scheme); + } + + /** + * Gets the HTTP port. + * + * @return string The HTTP port + */ + public function getHttpPort() + { + return $this->httpPort; + } + + /** + * Sets the HTTP port. + * + * @param string $httpPort The HTTP port + * + * @api + */ + public function setHttpPort($httpPort) + { + $this->httpPort = $httpPort; + } + + /** + * Gets the HTTPS port. + * + * @return string The HTTPS port + */ + public function getHttpsPort() + { + return $this->httpsPort; + } + + /** + * Sets the HTTPS port. + * + * @param string $httpsPort The HTTPS port + * + * @api + */ + public function setHttpsPort($httpsPort) + { + $this->httpsPort = $httpsPort; + } + + /** + * Returns the parameters. + * + * @return array The parameters + */ + public function getParameters() + { + return $this->parameters; + } + + /** + * Sets the parameters. + * + * This method implements a fluent interface. + * + * @param array $parameters The parameters + * + * @return Route The current Route instance + */ + public function setParameters(array $parameters) + { + $this->parameters = $parameters; + + return $this; + } + + /** + * Gets a parameter value. + * + * @param string $name A parameter name + * + * @return mixed The parameter value + */ + public function getParameter($name) + { + return isset($this->parameters[$name]) ? $this->parameters[$name] : null; + } + + /** + * Checks if a parameter value is set for the given parameter. + * + * @param string $name A parameter name + * + * @return Boolean true if the parameter value is set, false otherwise + */ + public function hasParameter($name) + { + return array_key_exists($name, $this->parameters); + } + + /** + * Sets a parameter value. + * + * @param string $name A parameter name + * @param mixed $parameter The parameter value + * + * @api + */ + public function setParameter($name, $parameter) + { + $this->parameters[$name] = $parameter; + } +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/RequestContextAwareInterface.php b/3rdparty/symfony/routing/Symfony/Component/Routing/RequestContextAwareInterface.php new file mode 100644 index 0000000000..38443a88b7 --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/RequestContextAwareInterface.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing; + +/** + * @api + */ +interface RequestContextAwareInterface +{ + /** + * Sets the request context. + * + * @param RequestContext $context The context + * + * @api + */ + public function setContext(RequestContext $context); +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Route.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Route.php new file mode 100644 index 0000000000..548568334d --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Route.php @@ -0,0 +1,312 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing; + +/** + * A Route describes a route and its parameters. + * + * @author Fabien Potencier + * + * @api + */ +class Route +{ + private $pattern; + private $defaults; + private $requirements; + private $options; + private $compiled; + + private static $compilers = array(); + + /** + * Constructor. + * + * Available options: + * + * * compiler_class: A class name able to compile this route instance (RouteCompiler by default) + * + * @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) + * @param array $options An array of options + * + * @api + */ + public function __construct($pattern, array $defaults = array(), array $requirements = array(), array $options = array()) + { + $this->setPattern($pattern); + $this->setDefaults($defaults); + $this->setRequirements($requirements); + $this->setOptions($options); + } + + public function __clone() + { + $this->compiled = null; + } + + /** + * Returns the pattern. + * + * @return string The pattern + */ + public function getPattern() + { + return $this->pattern; + } + + /** + * Sets the pattern. + * + * This method implements a fluent interface. + * + * @param string $pattern The pattern + * + * @return Route The current Route instance + */ + public function setPattern($pattern) + { + $this->pattern = trim($pattern); + + // a route must start with a slash + if (empty($this->pattern) || '/' !== $this->pattern[0]) { + $this->pattern = '/'.$this->pattern; + } + + return $this; + } + + /** + * Returns the options. + * + * @return array The options + */ + public function getOptions() + { + return $this->options; + } + + /** + * Sets the options. + * + * This method implements a fluent interface. + * + * @param array $options The options + * + * @return Route The current Route instance + */ + public function setOptions(array $options) + { + $this->options = array_merge(array( + 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler', + ), $options); + + return $this; + } + + /** + * Sets an option value. + * + * This method implements a fluent interface. + * + * @param string $name An option name + * @param mixed $value The option value + * + * @return Route The current Route instance + * + * @api + */ + public function setOption($name, $value) + { + $this->options[$name] = $value; + + return $this; + } + + /** + * Get an option value. + * + * @param string $name An option name + * + * @return mixed The option value + */ + public function getOption($name) + { + return isset($this->options[$name]) ? $this->options[$name] : null; + } + + /** + * Returns the defaults. + * + * @return array The defaults + */ + public function getDefaults() + { + return $this->defaults; + } + + /** + * Sets the defaults. + * + * This method implements a fluent interface. + * + * @param array $defaults The defaults + * + * @return Route The current Route instance + */ + public function setDefaults(array $defaults) + { + $this->defaults = array(); + foreach ($defaults as $name => $default) { + $this->defaults[(string) $name] = $default; + } + + return $this; + } + + /** + * Gets a default value. + * + * @param string $name A variable name + * + * @return mixed The default value + */ + public function getDefault($name) + { + return isset($this->defaults[$name]) ? $this->defaults[$name] : null; + } + + /** + * Checks if a default value is set for the given variable. + * + * @param string $name A variable name + * + * @return Boolean true if the default value is set, false otherwise + */ + public function hasDefault($name) + { + return array_key_exists($name, $this->defaults); + } + + /** + * Sets a default value. + * + * @param string $name A variable name + * @param mixed $default The default value + * + * @return Route The current Route instance + * + * @api + */ + public function setDefault($name, $default) + { + $this->defaults[(string) $name] = $default; + + return $this; + } + + /** + * Returns the requirements. + * + * @return array The requirements + */ + public function getRequirements() + { + return $this->requirements; + } + + /** + * Sets the requirements. + * + * This method implements a fluent interface. + * + * @param array $requirements The requirements + * + * @return Route The current Route instance + */ + public function setRequirements(array $requirements) + { + $this->requirements = array(); + foreach ($requirements as $key => $regex) { + $this->requirements[$key] = $this->sanitizeRequirement($key, $regex); + } + + return $this; + } + + /** + * Returns the requirement for the given key. + * + * @param string $key The key + * + * @return string The regex + */ + public function getRequirement($key) + { + return isset($this->requirements[$key]) ? $this->requirements[$key] : null; + } + + /** + * Sets a requirement for the given key. + * + * @param string $key The key + * @param string $regex The regex + * + * @return Route The current Route instance + * + * @api + */ + public function setRequirement($key, $regex) + { + $this->requirements[$key] = $this->sanitizeRequirement($key, $regex); + + return $this; + } + + /** + * Compiles the route. + * + * @return CompiledRoute A CompiledRoute instance + */ + public function compile() + { + if (null !== $this->compiled) { + return $this->compiled; + } + + $class = $this->getOption('compiler_class'); + + if (!isset(self::$compilers[$class])) { + self::$compilers[$class] = new $class; + } + + return $this->compiled = self::$compilers[$class]->compile($this); + } + + private function sanitizeRequirement($key, $regex) + { + if (is_array($regex)) { + throw new \InvalidArgumentException(sprintf('Routing requirements must be a string, array given for "%s"', $key)); + } + + if ('^' == $regex[0]) { + $regex = substr($regex, 1); + } + + if ('$' == substr($regex, -1)) { + $regex = substr($regex, 0, -1); + } + + return $regex; + } +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/RouteCollection.php b/3rdparty/symfony/routing/Symfony/Component/Routing/RouteCollection.php new file mode 100644 index 0000000000..b3289d337c --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/RouteCollection.php @@ -0,0 +1,259 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing; + +use Symfony\Component\Config\Resource\ResourceInterface; + +/** + * A RouteCollection represents a set of Route instances. + * + * When adding a route, it overrides existing routes with the + * same name defined in the instance or its children and parents. + * + * @author Fabien Potencier + * + * @api + */ +class RouteCollection implements \IteratorAggregate +{ + private $routes; + private $resources; + private $prefix; + private $parent; + + /** + * Constructor. + * + * @api + */ + public function __construct() + { + $this->routes = array(); + $this->resources = array(); + $this->prefix = ''; + } + + public function __clone() + { + foreach ($this->routes as $name => $route) { + $this->routes[$name] = clone $route; + if ($route instanceof RouteCollection) { + $this->routes[$name]->setParent($this); + } + } + } + + /** + * Gets the parent RouteCollection. + * + * @return RouteCollection The parent RouteCollection + */ + public function getParent() + { + return $this->parent; + } + + /** + * Sets the parent RouteCollection. + * + * @param RouteCollection $parent The parent RouteCollection + */ + public function setParent(RouteCollection $parent) + { + $this->parent = $parent; + } + + /** + * Gets the current RouteCollection as an Iterator. + * + * @return \ArrayIterator An \ArrayIterator interface + */ + public function getIterator() + { + return new \ArrayIterator($this->routes); + } + + /** + * Adds a route. + * + * @param string $name The route name + * @param Route $route A Route instance + * + * @throws \InvalidArgumentException When route name contains non valid characters + * + * @api + */ + public function add($name, Route $route) + { + if (!preg_match('/^[a-z0-9A-Z_.]+$/', $name)) { + throw new \InvalidArgumentException(sprintf('The provided route name "%s" contains non valid characters. A route name must only contain digits (0-9), letters (a-z and A-Z), underscores (_) and dots (.).', $name)); + } + + $parent = $this; + while ($parent->getParent()) { + $parent = $parent->getParent(); + } + + if ($parent) { + $parent->remove($name); + } + + $this->routes[$name] = $route; + } + + /** + * Returns the array of routes. + * + * @return array An array of routes + */ + public function all() + { + $routes = array(); + foreach ($this->routes as $name => $route) { + if ($route instanceof RouteCollection) { + $routes = array_merge($routes, $route->all()); + } else { + $routes[$name] = $route; + } + } + + return $routes; + } + + /** + * Gets a route by name. + * + * @param string $name The route name + * + * @return Route $route A Route instance + */ + public function get($name) + { + // get the latest defined route + foreach (array_reverse($this->routes) as $routes) { + if (!$routes instanceof RouteCollection) { + continue; + } + + if (null !== $route = $routes->get($name)) { + return $route; + } + } + + if (isset($this->routes[$name])) { + return $this->routes[$name]; + } + } + + /** + * Removes a route by name. + * + * @param string $name The route name + */ + public function remove($name) + { + if (isset($this->routes[$name])) { + unset($this->routes[$name]); + } + + foreach ($this->routes as $routes) { + if ($routes instanceof RouteCollection) { + $routes->remove($name); + } + } + } + + /** + * Adds a route collection to the current set of routes (at the end of the current set). + * + * @param RouteCollection $collection A RouteCollection instance + * @param string $prefix An optional prefix to add before each pattern of the route collection + * + * @api + */ + public function addCollection(RouteCollection $collection, $prefix = '') + { + $collection->setParent($this); + $collection->addPrefix($prefix); + + // remove all routes with the same name in all existing collections + foreach (array_keys($collection->all()) as $name) { + $this->remove($name); + } + + $this->routes[] = $collection; + } + + /** + * Adds a prefix to all routes in the current set. + * + * @param string $prefix An optional prefix to add before each pattern of the route collection + * + * @api + */ + public function addPrefix($prefix) + { + // a prefix must not end with a slash + $prefix = rtrim($prefix, '/'); + + if (!$prefix) { + return; + } + + // a prefix must start with a slash + if ('/' !== $prefix[0]) { + $prefix = '/'.$prefix; + } + + $this->prefix = $prefix.$this->prefix; + + foreach ($this->routes as $name => $route) { + if ($route instanceof RouteCollection) { + $route->addPrefix($prefix); + } else { + $route->setPattern($prefix.$route->getPattern()); + } + } + } + + public function getPrefix() + { + return $this->prefix; + } + + /** + * Returns an array of resources loaded to build this collection. + * + * @return ResourceInterface[] An array of resources + */ + public function getResources() + { + $resources = $this->resources; + foreach ($this as $routes) { + if ($routes instanceof RouteCollection) { + $resources = array_merge($resources, $routes->getResources()); + } + } + + return array_unique($resources); + } + + /** + * Adds a resource for this collection. + * + * @param ResourceInterface $resource A resource instance + */ + public function addResource(ResourceInterface $resource) + { + $this->resources[] = $resource; + } +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/RouteCompiler.php b/3rdparty/symfony/routing/Symfony/Component/Routing/RouteCompiler.php new file mode 100644 index 0000000000..72ececc5ca --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/RouteCompiler.php @@ -0,0 +1,128 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing; + +/** + * RouteCompiler compiles Route instances to CompiledRoute instances. + * + * @author Fabien Potencier + */ +class RouteCompiler implements RouteCompilerInterface +{ + /** + * Compiles the current route instance. + * + * @param Route $route A Route instance + * + * @return CompiledRoute A CompiledRoute instance + */ + public function compile(Route $route) + { + $pattern = $route->getPattern(); + $len = strlen($pattern); + $tokens = array(); + $variables = array(); + $pos = 0; + preg_match_all('#.\{([\w\d_]+)\}#', $pattern, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER); + foreach ($matches as $match) { + if ($text = substr($pattern, $pos, $match[0][1] - $pos)) { + $tokens[] = array('text', $text); + } + $seps = array($pattern[$pos]); + $pos = $match[0][1] + strlen($match[0][0]); + $var = $match[1][0]; + + if ($req = $route->getRequirement($var)) { + $regexp = $req; + } else { + if ($pos !== $len) { + $seps[] = $pattern[$pos]; + } + $regexp = sprintf('[^%s]+?', preg_quote(implode('', array_unique($seps)), '#')); + } + + $tokens[] = array('variable', $match[0][0][0], $regexp, $var); + + if (in_array($var, $variables)) { + throw new \LogicException(sprintf('Route pattern "%s" cannot reference variable name "%s" more than once.', $route->getPattern(), $var)); + } + + $variables[] = $var; + } + + if ($pos < $len) { + $tokens[] = array('text', substr($pattern, $pos)); + } + + // find the first optional token + $firstOptional = INF; + for ($i = count($tokens) - 1; $i >= 0; $i--) { + $token = $tokens[$i]; + if ('variable' === $token[0] && $route->hasDefault($token[3])) { + $firstOptional = $i; + } else { + break; + } + } + + // compute the matching regexp + $regexp = ''; + for ($i = 0, $nbToken = count($tokens); $i < $nbToken; $i++) { + $regexp .= $this->computeRegexp($tokens, $i, $firstOptional); + } + + return new CompiledRoute( + $route, + 'text' === $tokens[0][0] ? $tokens[0][1] : '', + sprintf("#^%s$#s", $regexp), + array_reverse($tokens), + $variables + ); + } + + /** + * Computes the regexp used to match the token. + * + * @param array $tokens The route tokens + * @param integer $index The index of the current token + * @param integer $firstOptional The index of the first optional token + * + * @return string The regexp + */ + private function computeRegexp(array $tokens, $index, $firstOptional) + { + $token = $tokens[$index]; + if ('text' === $token[0]) { + // Text tokens + return preg_quote($token[1], '#'); + } else { + // Variable tokens + if (0 === $index && 0 === $firstOptional && 1 == count($tokens)) { + // When the only token is an optional variable token, the separator is required + return sprintf('%s(?P<%s>%s)?', preg_quote($token[1], '#'), $token[3], $token[2]); + } else { + $nbTokens = count($tokens); + $regexp = sprintf('%s(?P<%s>%s)', preg_quote($token[1], '#'), $token[3], $token[2]); + if ($index >= $firstOptional) { + // Enclose each optional tokens in a subpattern to make it optional + $regexp = "(?:$regexp"; + if ($nbTokens - 1 == $index) { + // Close the optional subpatterns + $regexp .= str_repeat(")?", $nbTokens - $firstOptional); + } + } + + return $regexp; + } + } + } +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/RouteCompilerInterface.php b/3rdparty/symfony/routing/Symfony/Component/Routing/RouteCompilerInterface.php new file mode 100644 index 0000000000..5c988adafb --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/RouteCompilerInterface.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing; + +/** + * RouteCompilerInterface is the interface that all RouteCompiler classes must implements. + * + * @author Fabien Potencier + */ +interface RouteCompilerInterface +{ + /** + * Compiles the current route instance. + * + * @param Route $route A Route instance + * + * @return CompiledRoute A CompiledRoute instance + */ + public function compile(Route $route); +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/Router.php b/3rdparty/symfony/routing/Symfony/Component/Routing/Router.php new file mode 100644 index 0000000000..eadb2231e1 --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/Router.php @@ -0,0 +1,263 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing; + +use Symfony\Component\Config\Loader\LoaderInterface; +use Symfony\Component\Config\ConfigCache; + +/** + * The Router class is an example of the integration of all pieces of the + * routing system for easier use. + * + * @author Fabien Potencier + */ +class Router implements RouterInterface +{ + protected $matcher; + protected $generator; + protected $defaults; + protected $context; + protected $loader; + protected $collection; + protected $resource; + protected $options; + + /** + * Constructor. + * + * @param LoaderInterface $loader A LoaderInterface instance + * @param mixed $resource The main resource to load + * @param array $options An array of options + * @param RequestContext $context The context + * @param array $defaults The default values + */ + public function __construct(LoaderInterface $loader, $resource, array $options = array(), RequestContext $context = null, array $defaults = array()) + { + $this->loader = $loader; + $this->resource = $resource; + $this->context = null === $context ? new RequestContext() : $context; + $this->defaults = $defaults; + $this->setOptions($options); + } + + /** + * Sets options. + * + * Available options: + * + * * cache_dir: The cache directory (or null to disable caching) + * * debug: Whether to enable debugging or not (false by default) + * * resource_type: Type hint for the main resource (optional) + * + * @param array $options An array of options + * + * @throws \InvalidArgumentException When unsupported option is provided + */ + public function setOptions(array $options) + { + $this->options = array( + 'cache_dir' => null, + 'debug' => false, + 'generator_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator', + 'generator_base_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator', + 'generator_dumper_class' => 'Symfony\\Component\\Routing\\Generator\\Dumper\\PhpGeneratorDumper', + 'generator_cache_class' => 'ProjectUrlGenerator', + 'matcher_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher', + 'matcher_base_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher', + 'matcher_dumper_class' => 'Symfony\\Component\\Routing\\Matcher\\Dumper\\PhpMatcherDumper', + 'matcher_cache_class' => 'ProjectUrlMatcher', + 'resource_type' => null, + ); + + // check option names and live merge, if errors are encountered Exception will be thrown + $invalid = array(); + $isInvalid = false; + foreach ($options as $key => $value) { + if (array_key_exists($key, $this->options)) { + $this->options[$key] = $value; + } else { + $isInvalid = true; + $invalid[] = $key; + } + } + + if ($isInvalid) { + throw new \InvalidArgumentException(sprintf('The Router does not support the following options: "%s".', implode('\', \'', $invalid))); + } + } + + /** + * Sets an option. + * + * @param string $key The key + * @param mixed $value The value + * + * @throws \InvalidArgumentException + */ + public function setOption($key, $value) + { + if (!array_key_exists($key, $this->options)) { + throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key)); + } + + $this->options[$key] = $value; + } + + /** + * Gets an option value. + * + * @param string $key The key + * + * @return mixed The value + * + * @throws \InvalidArgumentException + */ + public function getOption($key) + { + if (!array_key_exists($key, $this->options)) { + throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key)); + } + + return $this->options[$key]; + } + + /** + * Gets the RouteCollection instance associated with this Router. + * + * @return RouteCollection A RouteCollection instance + */ + public function getRouteCollection() + { + if (null === $this->collection) { + $this->collection = $this->loader->load($this->resource, $this->options['resource_type']); + } + + return $this->collection; + } + + /** + * Sets the request context. + * + * @param RequestContext $context The context + */ + public function setContext(RequestContext $context) + { + $this->context = $context; + + $this->getMatcher()->setContext($context); + $this->getGenerator()->setContext($context); + } + + /** + * Gets the request context. + * + * @return RequestContext The context + */ + public function getContext() + { + return $this->context; + } + + /** + * Generates a URL from the given parameters. + * + * @param string $name The name of the route + * @param mixed $parameters An array of parameters + * @param Boolean $absolute Whether to generate an absolute URL + * + * @return string The generated URL + */ + public function generate($name, $parameters = array(), $absolute = false) + { + return $this->getGenerator()->generate($name, $parameters, $absolute); + } + + /** + * Tries to match a URL with a set of routes. + * + * Returns false if no route matches the URL. + * + * @param string $url URL to be parsed + * + * @return array|false An array of parameters or false if no route matches + */ + public function match($url) + { + return $this->getMatcher()->match($url); + } + + /** + * Gets the UrlMatcher instance associated with this Router. + * + * @return UrlMatcherInterface A UrlMatcherInterface instance + */ + public function getMatcher() + { + if (null !== $this->matcher) { + return $this->matcher; + } + + if (null === $this->options['cache_dir'] || null === $this->options['matcher_cache_class']) { + return $this->matcher = new $this->options['matcher_class']($this->getRouteCollection(), $this->context, $this->defaults); + } + + $class = $this->options['matcher_cache_class']; + $cache = new ConfigCache($this->options['cache_dir'].'/'.$class.'.php', $this->options['debug']); + if (!$cache->isFresh($class)) { + $dumper = new $this->options['matcher_dumper_class']($this->getRouteCollection()); + + $options = array( + 'class' => $class, + 'base_class' => $this->options['matcher_base_class'], + ); + + $cache->write($dumper->dump($options), $this->getRouteCollection()->getResources()); + } + + require_once $cache; + + return $this->matcher = new $class($this->context, $this->defaults); + } + + /** + * Gets the UrlGenerator instance associated with this Router. + * + * @return UrlGeneratorInterface A UrlGeneratorInterface instance + */ + public function getGenerator() + { + if (null !== $this->generator) { + return $this->generator; + } + + if (null === $this->options['cache_dir'] || null === $this->options['generator_cache_class']) { + return $this->generator = new $this->options['generator_class']($this->getRouteCollection(), $this->context, $this->defaults); + } + + $class = $this->options['generator_cache_class']; + $cache = new ConfigCache($this->options['cache_dir'].'/'.$class.'.php', $this->options['debug']); + if (!$cache->isFresh($class)) { + $dumper = new $this->options['generator_dumper_class']($this->getRouteCollection()); + + $options = array( + 'class' => $class, + 'base_class' => $this->options['generator_base_class'], + ); + + $cache->write($dumper->dump($options), $this->getRouteCollection()->getResources()); + } + + require_once $cache; + + return $this->generator = new $class($this->context, $this->defaults); + } +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/RouterInterface.php b/3rdparty/symfony/routing/Symfony/Component/Routing/RouterInterface.php new file mode 100644 index 0000000000..961342bf09 --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/RouterInterface.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing; + +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\Routing\Matcher\UrlMatcherInterface; + +/** + * RouterInterface is the interface that all Router classes must implements. + * + * This interface is the concatenation of UrlMatcherInterface and UrlGeneratorInterface. + * + * @author Fabien Potencier + */ +interface RouterInterface extends UrlMatcherInterface, UrlGeneratorInterface +{ +} diff --git a/3rdparty/symfony/routing/Symfony/Component/Routing/composer.json b/3rdparty/symfony/routing/Symfony/Component/Routing/composer.json new file mode 100644 index 0000000000..8d29398b24 --- /dev/null +++ b/3rdparty/symfony/routing/Symfony/Component/Routing/composer.json @@ -0,0 +1,29 @@ +{ + "name": "symfony/routing", + "type": "library", + "description": "Symfony Routing Component", + "keywords": [], + "homepage": "http://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "require": { + "php": ">=5.3.2" + }, + "suggest": { + "symfony/config": "self.version", + "symfony/yaml": "self.version" + }, + "autoload": { + "psr-0": { "Symfony\\Component\\Routing": "" } + }, + "target-dir": "Symfony/Component/Routing" +} diff --git a/composer.json b/composer.json deleted file mode 100644 index 7916b15cb9..0000000000 --- a/composer.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "description": "ownCloud gives you universal access to your files/contacts/calendar through a web interface or WebDAV.", - "homepage": "http://owncloud.org", - "license": "AGPL-3.0+", - "support": { - "email": "owncloud@kde.org", - "irc": "irc://irc.freenode.org/owncloud", - "forum": "http://forum.owncloud.org/", - "issues": "https://github.com/owncloud/core/issues" - }, - "require": { - "php": ">=5.3.2", - "symfony/routing": "2.0.*" - }, - "config": { - "vendor-dir": "3rdparty" - } -} From 56e9ce44c3ac18d6183a8959c690c6e3269bc79e Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sat, 27 Oct 2012 17:02:05 +0200 Subject: [PATCH 068/347] add a way to recalucale the size of a folder in the cache --- lib/files/cache/cache.php | 25 +++++++++++++++++++++++++ tests/lib/files/cache/cache.php | 11 +++++++++++ 2 files changed, 36 insertions(+) diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index 6604525477..734890329a 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -308,6 +308,31 @@ class Cache { return $result->fetchAll(); } + /** + * get the size of a folder and set it in the cache + * + * @param string $path + * @return int + */ + public function calculateFolderSize($path) { + $id = $this->getId($path); + $query = \OC_DB::prepare('SELECT `size` FROM `*PREFIX*filecache` WHERE `parent` = ? AND `storage` = ?'); + $result = $query->execute(array($id, $this->storageId)); + $totalSize = 0; + while ($row = $result->fetchRow()) { + $size = (int)$row['size']; + if ($size === -1) { + $totalSize = -1; + break; + } else { + $totalSize += $size; + } + } + + $this->update($id, array('size' => $totalSize)); + return $totalSize; + } + /** * get all file ids on the files on the storage * diff --git a/tests/lib/files/cache/cache.php b/tests/lib/files/cache/cache.php index 5a8d79b902..57a154d295 100644 --- a/tests/lib/files/cache/cache.php +++ b/tests/lib/files/cache/cache.php @@ -99,6 +99,17 @@ class Cache extends \UnitTestCase { $this->assertEqual($value, $cachedData[$name]); } } + + $file4 = 'folder/unkownSize'; + $fileData['unkownSize'] = array('size' => -1, 'mtime' => 25, 'mimetype' => 'foo/file'); + $this->cache->put($file4, $fileData['unkownSize']); + + $this->assertEquals(-1, $this->cache->calculateFolderSize($file1)); + + $fileData['unkownSize'] = array('size' => 5, 'mtime' => 25, 'mimetype' => 'foo/file'); + $this->cache->put($file4, $fileData['unkownSize']); + + $this->assertEquals(1025, $this->cache->calculateFolderSize($file1)); } function testStatus() { From 79d0ac21ccc65d12b6643ab525d45977644873e8 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sat, 27 Oct 2012 18:05:40 +0200 Subject: [PATCH 069/347] delete child entries when a folder gets removed from cache --- lib/files/cache/cache.php | 12 +++++++++--- lib/files/cache/scanner.php | 16 ++++++++++++++++ tests/lib/files/cache/cache.php | 6 +++++- tests/lib/files/cache/scanner.php | 9 +++++++-- 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index 734890329a..cba48e4dbe 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -231,9 +231,15 @@ class Cache { * @param string $file */ public function remove($file) { - $pathHash = md5($file); - $query = \OC_DB::prepare('DELETE FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path_hash` = ?'); - $query->execute(array($this->storageId, $pathHash)); + $entry = $this->get($file); + if ($entry['mimetype'] === 'httpd/unix-directory') { + $children = $this->getFolderContents($file); + foreach($children as $child){ + $this->remove($child['path']); + } + } + $query = \OC_DB::prepare('DELETE FROM `*PREFIX*filecache` WHERE `fileid` = ?'); + $query->execute(array($entry['fileid'])); } /** diff --git a/lib/files/cache/scanner.php b/lib/files/cache/scanner.php index 0adde1d354..7062888d74 100644 --- a/lib/files/cache/scanner.php +++ b/lib/files/cache/scanner.php @@ -107,4 +107,20 @@ class Scanner { } return $size; } + + /** + * update the folder size and the size of all parent folders + * + * @param $path + */ + public function correctFolderSize($path) { + $this->cache->calculateFolderSize($path); + if ($path !== '') { + $parent = dirname($path); + if ($parent === '.') { + $parent = ''; + } + $this->correctFolderSize($parent); + } + } } diff --git a/tests/lib/files/cache/cache.php b/tests/lib/files/cache/cache.php index 57a154d295..4f22e9bd1d 100644 --- a/tests/lib/files/cache/cache.php +++ b/tests/lib/files/cache/cache.php @@ -82,7 +82,7 @@ class Cache extends \UnitTestCase { $file1 = 'folder'; $file2 = 'folder/bar'; $file3 = 'folder/foo'; - $data1 = array('size' => 100, 'mtime' => 50, 'mimetype' => 'foo/folder'); + $data1 = array('size' => 100, 'mtime' => 50, 'mimetype' => 'httpd/unix-directory'); $fileData = array(); $fileData['bar'] = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'foo/file'); $fileData['foo'] = array('size' => 20, 'mtime' => 25, 'mimetype' => 'foo/file'); @@ -110,6 +110,10 @@ class Cache extends \UnitTestCase { $this->cache->put($file4, $fileData['unkownSize']); $this->assertEquals(1025, $this->cache->calculateFolderSize($file1)); + + $this->cache->remove('folder'); + $this->assertFalse($this->cache->inCache('folder/foo')); + $this->assertFalse($this->cache->inCache('folder/bar')); } function testStatus() { diff --git a/tests/lib/files/cache/scanner.php b/tests/lib/files/cache/scanner.php index 34fefc784d..34d38c4273 100644 --- a/tests/lib/files/cache/scanner.php +++ b/tests/lib/files/cache/scanner.php @@ -89,14 +89,19 @@ class Scanner extends \UnitTestCase { $cachedDataFolder = $this->cache->get(''); $cachedDataFolder2 = $this->cache->get('folder'); - $this->assertEqual($cachedDataFolder['size'], -1); - $this->assertEqual($cachedDataFolder2['size'], -1); + $this->assertEqual(-1, $cachedDataFolder['size']); + $this->assertEqual(-1, $cachedDataFolder2['size']); $this->scanner->scan('folder', \OC\Files\Cache\Scanner::SCAN_SHALLOW); $cachedDataFolder2 = $this->cache->get('folder'); $this->assertNotEqual($cachedDataFolder2['size'], -1); + + $this->scanner->correctFolderSize('folder'); + + $cachedDataFolder = $this->cache->get(''); + $this->assertNotEqual($cachedDataFolder['size'], -1); } function setUp() { From fba7be1194fd31da2cb71c56d0cd8e6ab1c1ff49 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sun, 28 Oct 2012 11:26:31 +0100 Subject: [PATCH 070/347] add filesystem watcher to detect updates --- lib/files/cache/cache.php | 8 ++- lib/files/cache/watcher.php | 70 +++++++++++++++++++++++++ tests/lib/files/cache/watcher.php | 86 +++++++++++++++++++++++++++++++ tests/lib/files/view.php | 2 + 4 files changed, 164 insertions(+), 2 deletions(-) create mode 100644 lib/files/cache/watcher.php create mode 100644 tests/lib/files/cache/watcher.php diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index cba48e4dbe..138a5e6e63 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -234,7 +234,7 @@ class Cache { $entry = $this->get($file); if ($entry['mimetype'] === 'httpd/unix-directory') { $children = $this->getFolderContents($file); - foreach($children as $child){ + foreach ($children as $child) { $this->remove($child['path']); } } @@ -325,7 +325,9 @@ class Cache { $query = \OC_DB::prepare('SELECT `size` FROM `*PREFIX*filecache` WHERE `parent` = ? AND `storage` = ?'); $result = $query->execute(array($id, $this->storageId)); $totalSize = 0; + $hasChilds = 0; while ($row = $result->fetchRow()) { + $hasChilds = true; $size = (int)$row['size']; if ($size === -1) { $totalSize = -1; @@ -335,7 +337,9 @@ class Cache { } } - $this->update($id, array('size' => $totalSize)); + if ($hasChilds) { + $this->update($id, array('size' => $totalSize)); + } return $totalSize; } diff --git a/lib/files/cache/watcher.php b/lib/files/cache/watcher.php new file mode 100644 index 0000000000..f04ca9b465 --- /dev/null +++ b/lib/files/cache/watcher.php @@ -0,0 +1,70 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Files\Cache; + +/** + * check the storage backends for updates and change the cache accordingly + */ +class Watcher { + /** + * @var \OC\Files\Storage\Storage $storage + */ + private $storage; + + /** + * @var Cache $cache + */ + private $cache; + + /** + * @var Scanner $scanner; + */ + private $scanner; + + /** + * @param \OC\Files\Storage\Storage $storage + */ + public function __construct(\OC\Files\Storage\Storage $storage) { + $this->storage = $storage; + $this->cache = $storage->getCache(); + $this->scanner = $storage->getScanner(); + } + + /** + * check $path for updates + * + * @param string $path + */ + public function checkUpdate($path) { + $cachedEntry = $this->cache->get($path); + if ($this->storage->hasUpdated($path, $cachedEntry['mtime'])) { + if ($cachedEntry['mimetype'] === 'httpd/unix-directory') { + $this->scanner->scan($path, Scanner::SCAN_SHALLOW); + $this->cleanFolder($path); + } else { + $this->scanner->scanFile($path); + } + $this->scanner->correctFolderSize($path); + } + } + + /** + * remove deleted files in $path from the cache + * + * @param string $path + */ + public function cleanFolder($path) { + $cachedContent = $this->cache->getFolderContents($path); + foreach ($cachedContent as $entry) { + if (!$this->storage->file_exists($entry['path'])) { + $this->cache->remove($entry['path']); + } + } + } +} diff --git a/tests/lib/files/cache/watcher.php b/tests/lib/files/cache/watcher.php new file mode 100644 index 0000000000..a7076d9b0b --- /dev/null +++ b/tests/lib/files/cache/watcher.php @@ -0,0 +1,86 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\Files\Cache; + +class Watcher extends \PHPUnit_Framework_TestCase { + + /** + * @var \OC\Files\Storage\Storage[] $storages; + */ + private $storages = array(); + + public function setUp() { + \OC\Files\Filesystem::clearMounts(); + } + + public function tearDown() { + foreach ($this->storages as $storage) { + $cache = $storage->getCache(); + $ids = $cache->getAll(); + \OC\Files\Cache\Permissions::removeMultiple($ids, \OC_User::getUser()); + $cache->clear(); + } + } + + function testWatcher() { + $storage = $this->getTestStorage(); + $cache = $storage->getCache(); + $updater = new \OC\Files\Cache\Watcher($storage); + + //set the mtime to the past so it can detect an mtime change + $cache->put('', array('mtime' => 10)); + + $this->assertTrue($cache->inCache('folder/bar.txt')); + $this->assertTrue($cache->inCache('folder/bar2.txt')); + + $this->assertFalse($cache->inCache('bar.test')); + $storage->file_put_contents('bar.test', 'foo'); + $updater->checkUpdate(''); + $this->assertTrue($cache->inCache('bar.test')); + $cachedData = $cache->get('bar.test'); + $this->assertEquals(3, $cachedData['size']); + + $cache->put('bar.test', array('mtime' => 10)); + $storage->file_put_contents('bar.test', 'test data'); + + $updater->checkUpdate('bar.test'); + $cachedData = $cache->get('bar.test'); + $this->assertEquals(9, $cachedData['size']); + + $cache->put('folder', array('mtime' => 10)); + + $storage->unlink('folder/bar2.txt'); + $updater->checkUpdate('folder'); + + $this->assertTrue($cache->inCache('folder/bar.txt')); + $this->assertFalse($cache->inCache('folder/bar2.txt')); + } + + /** + * @param bool $scan + * @return \OC\Files\Storage\Storage + */ + private function getTestStorage($scan = true) { + $storage = new \OC\Files\Storage\Temporary(array()); + $textData = "dummy file data\n"; + $imgData = file_get_contents(\OC::$SERVERROOT . '/core/img/logo.png'); + $storage->mkdir('folder'); + $storage->file_put_contents('foo.txt', $textData); + $storage->file_put_contents('foo.png', $imgData); + $storage->file_put_contents('folder/bar.txt', $textData); + $storage->file_put_contents('folder/bar2.txt', $textData); + + if ($scan) { + $scanner = $storage->getScanner(); + $scanner->scan(''); + } + $this->storages[] = $storage; + return $storage; + } +} diff --git a/tests/lib/files/view.php b/tests/lib/files/view.php index 5144fb1caa..8ff03963e4 100644 --- a/tests/lib/files/view.php +++ b/tests/lib/files/view.php @@ -20,6 +20,8 @@ class View extends \PHPUnit_Framework_TestCase { public function tearDown() { foreach ($this->storages as $storage) { $cache = $storage->getCache(); + $ids = $cache->getAll(); + \OC\Files\Cache\Permissions::removeMultiple($ids, \OC_User::getUser()); $cache->clear(); } } From b07672821bcdc1ce31e169d691cf9a94ad5fad21 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sun, 28 Oct 2012 11:43:45 +0100 Subject: [PATCH 071/347] check for changes when using the cache api --- lib/files/view.php | 6 ++++++ tests/lib/files/view.php | 17 +++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/lib/files/view.php b/lib/files/view.php index 0f9a5feb5d..c5e470b438 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -672,6 +672,9 @@ class View { if (!$cache->inCache($internalPath)) { $scanner = $storage->getScanner(); $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW); + } else { + $watcher = new \OC\Files\Cache\Watcher($storage); + $watcher->checkUpdate($internalPath); } $data = $cache->get($internalPath); @@ -711,6 +714,9 @@ class View { if (!$cache->inCache($internalPath)) { $scanner = $storage->getScanner(); $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW); + } else { + $watcher = new \OC\Files\Cache\Watcher($storage); + $watcher->checkUpdate($internalPath); } $files = $cache->getFolderContents($internalPath); //TODO: mimetype_filter diff --git a/tests/lib/files/view.php b/tests/lib/files/view.php index 8ff03963e4..fa562cb15c 100644 --- a/tests/lib/files/view.php +++ b/tests/lib/files/view.php @@ -146,6 +146,23 @@ class View extends \PHPUnit_Framework_TestCase { $this->assertEquals(3, count($folderView->searchByMime('text'))); } + function testWatcher() { + $storage1 = $this->getTestStorage(); + \OC\Files\Filesystem::mount($storage1, array(), '/'); + + $rootView = new \OC\Files\View(''); + + $cachedData = $rootView->getFileInfo('foo.txt'); + $this->assertEquals(16, $cachedData['size']); + + $rootView->putFileInfo('foo.txt', array('mtime' => 10)); + $storage1->file_put_contents('foo.txt', 'foo'); + clearstatcache(); + + $cachedData = $rootView->getFileInfo('foo.txt'); + $this->assertEquals(3, $cachedData['size']); + } + /** * @param bool $scan * @return \OC\Files\Storage\Storage From 8a6bb7965d96b1c4297da8f5dbc9644fec7aeb0f Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 2 Nov 2012 22:25:33 +0100 Subject: [PATCH 072/347] add Cache::move --- lib/files/cache/cache.php | 29 +++++++++++++++++++++++++++-- tests/lib/files/cache/cache.php | 26 ++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index 138a5e6e63..9d13b56104 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -242,6 +242,32 @@ class Cache { $query->execute(array($entry['fileid'])); } + /** + * Move a file or folder in the cache + * + * @param string $source + * @param string $target + */ + public function move($source, $target) { + $sourceId = $this->getId($source); + $newParentId = $this->getParentId($target); + + //find all child entries + $query = \OC_DB::prepare('SELECT `path`, `fileid` FROM `*PREFIX*filecache` WHERE `path` LIKE ?'); + $result = $query->execute(array($source . '/%')); + $childEntries = $result->fetchAll(); + $sourceLength = strlen($source); + $query = \OC_DB::prepare('UPDATE `*PREFIX*filecache` SET `path` = ?, `path_hash` = ? WHERE `fileid` = ?'); + + foreach ($childEntries as $child) { + $targetPath = $target . substr($child['path'], $sourceLength); + $query->execute(array($targetPath, md5($targetPath), $child['fileid'])); + } + + $query = \OC_DB::prepare('UPDATE `*PREFIX*filecache` SET `path` = ?, `path_hash` = ?, `parent` =? WHERE `fileid` = ?'); + $query->execute(array($target, md5($target), $newParentId, $sourceId)); + } + /** * remove all entries for files that are stored on the storage from the cache */ @@ -296,8 +322,7 @@ class Cache { /** * search for files by mimetype * - * @param string $part1 - * @param string $part2 + * @param string $mimetype * @return array */ public function searchByMime($mimetype) { diff --git a/tests/lib/files/cache/cache.php b/tests/lib/files/cache/cache.php index 4f22e9bd1d..9c469aa937 100644 --- a/tests/lib/files/cache/cache.php +++ b/tests/lib/files/cache/cache.php @@ -149,6 +149,32 @@ class Cache extends \UnitTestCase { $this->assertEquals(2, count($this->cache->searchByMime('foo/file'))); } + function testMove() { + $file1 = 'folder'; + $file2 = 'folder/bar'; + $file3 = 'folder/foo'; + $file4 = 'folder/foo/1'; + $file5 = 'folder/foo/2'; + $data = array('size' => 100, 'mtime' => 50, 'mimetype' => 'foo/bar'); + + $this->cache->put($file1, $data); + $this->cache->put($file2, $data); + $this->cache->put($file3, $data); + $this->cache->put($file4, $data); + $this->cache->put($file5, $data); + + $this->cache->move('folder/foo', 'folder/foobar'); + + $this->assertFalse($this->cache->inCache('folder/foo')); + $this->assertFalse($this->cache->inCache('folder/foo/1')); + $this->assertFalse($this->cache->inCache('folder/foo/2')); + + $this->assertTrue($this->cache->inCache('folder/bar')); + $this->assertTrue($this->cache->inCache('folder/foobar')); + $this->assertTrue($this->cache->inCache('folder/foobar/1')); + $this->assertTrue($this->cache->inCache('folder/foobar/2')); + } + public function tearDown() { $this->cache->clear(); } From 72c38686449a8887d8441377a11f0bfc910bc31f Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 8 Nov 2012 17:42:26 +0100 Subject: [PATCH 073/347] add resolvePath to filesystem view api --- lib/files/view.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/files/view.php b/lib/files/view.php index 709e374d86..e3f9b762f7 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -101,6 +101,16 @@ class View { return Filesystem::getMountPoint($this->getAbsolutePath($path)); } + /** + * resolve a path to a storage and internal path + * + * @param string $path + * @return array consisting of the storage and the internal path + */ + public function resolvePath($path) { + return Filesystem::resolvePath($this->getAbsolutePath($path)); + } + /** * return the path to a local version of the file * we need this because we can't know if a file is stored local or not from outside the filestorage and for some purposes a local file is needed From 706bb3ccd654f76c0a6c5b7874fcc1e288b13f54 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 8 Nov 2012 17:47:00 +0100 Subject: [PATCH 074/347] move ETag generation to storage backends --- lib/connector/sabre/node.php | 16 +--------------- lib/files/filesystem.php | 10 ++++++++++ lib/files/storage/common.php | 16 ++++++++++++++++ lib/files/storage/storage.php | 8 ++++++++ lib/files/view.php | 15 +++++++++++++++ 5 files changed, 50 insertions(+), 15 deletions(-) diff --git a/lib/connector/sabre/node.php b/lib/connector/sabre/node.php index ebc9e53962..d0ab0c2498 100644 --- a/lib/connector/sabre/node.php +++ b/lib/connector/sabre/node.php @@ -210,27 +210,13 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr return $props; } - /** - * 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) { - 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. * @param string $path Path of the file * @return string|null Returns null if the ETag can not effectively be determined */ static public function getETagPropertyForPath($path) { - $tag = self::createETag($path); + $tag = \OC\Files\Filesystem::getETag($path); if (empty($tag)) { return null; } diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php index 76a188e412..ed2814211f 100644 --- a/lib/files/filesystem.php +++ b/lib/files/filesystem.php @@ -654,6 +654,16 @@ class Filesystem { public static function getDirectoryContent($directory, $mimetype_filter = '') { return self::$defaultInstance->getDirectoryContent($directory, $mimetype_filter); } + + /** + * get the ETag for a file or folder + * + * @param string $path + * @return string + */ + static public function getETag($path){ + return self::$defaultInstance->getETag($path); + } } \OC_Hook::connect('OC_Filesystem', 'post_write', 'OC_Filesystem', 'removeETagHook'); diff --git a/lib/files/storage/common.php b/lib/files/storage/common.php index e22264d0da..f471752d1f 100644 --- a/lib/files/storage/common.php +++ b/lib/files/storage/common.php @@ -267,4 +267,20 @@ abstract class Common implements \OC\Files\Storage\Storage { public function getOwner($path) { return \OC_User::getUser(); } + + /** + * get the ETag for a file or folder + * + * @param string $path + * @return string + */ + public function getETag($path){ + $ETagFunction = \OC_Connector_Sabre_Node::$ETagFunction; + if($ETagFunction) { + $hash = call_user_func($ETagFunction, $path); + return $hash; + }else{ + return uniqid('', true); + } + } } diff --git a/lib/files/storage/storage.php b/lib/files/storage/storage.php index 1f5c935629..bb1ba16984 100644 --- a/lib/files/storage/storage.php +++ b/lib/files/storage/storage.php @@ -63,4 +63,12 @@ interface Storage{ public function getScanner(); public function getOwner($path); + + /** + * get the ETag for a file or folder + * + * @param string $path + * @return string + */ + public function getETag($path); } diff --git a/lib/files/view.php b/lib/files/view.php index e3f9b762f7..a54c3ee356 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -866,4 +866,19 @@ class View { return $files; } + + /** + * get the ETag for a file or folder + * + * @param string $path + * @return string + */ + public function getETag($path){ + /** + * @var Storage\Storage $storage + * @var string $internalPath + */ + list($storage, $internalPath) = $this->resolvePath($path); + return $storage->getETag($internalPath); + } } From e7bed5ddabea5a3841d4a08082badaec025ed242 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 8 Nov 2012 17:59:08 +0100 Subject: [PATCH 075/347] allow creating Cache objects with only the storage id instead of the whole storage object --- lib/files/cache/cache.php | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index 9d13b56104..dba026a611 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -19,24 +19,25 @@ class Cache { const SHALLOW = 2; //folder in cache, but not all child files are completely scanned const COMPLETE = 3; - /** - * @var \OC\Files\Storage\Storage - */ - private $storage; - /** * @var array partial data for the cache */ private $partial = array(); + /** + * @var string + */ private $storageId; /** - * @param \OC\Files\Storage\Storage $storage + * @param \OC\Files\Storage\Storage|string $storage */ - public function __construct(\OC\Files\Storage\Storage $storage) { - $this->storage = $storage; - $this->storageId = $storage->getId(); + public function __construct($storage) { + if($storage instanceof \OC\Files\Storage\Storage){ + $this->storageId = $storage->getId(); + }else{ + $this->storageId = $storage; + } } /** From 3f644fe70c8451ab1ab877c4dd97f34366548b70 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 8 Nov 2012 18:07:30 +0100 Subject: [PATCH 076/347] fix calculateFolderSize for non existing files --- lib/files/cache/cache.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index dba026a611..83d3585bb5 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -348,6 +348,9 @@ class Cache { */ public function calculateFolderSize($path) { $id = $this->getId($path); + if($id === -1){ + return 0; + } $query = \OC_DB::prepare('SELECT `size` FROM `*PREFIX*filecache` WHERE `parent` = ? AND `storage` = ?'); $result = $query->execute(array($id, $this->storageId)); $totalSize = 0; From 15b8a3f98757f220db190c1e9489d5888b2b1015 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 8 Nov 2012 18:10:54 +0100 Subject: [PATCH 077/347] move correctFolderSize from Scanner to Cache --- lib/files/cache/cache.php | 16 ++++++++++++++++ lib/files/cache/scanner.php | 16 ---------------- lib/files/cache/watcher.php | 2 +- tests/lib/files/cache/scanner.php | 2 +- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index 83d3585bb5..7c6bba4fad 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -340,6 +340,22 @@ class Cache { return $result->fetchAll(); } + /** + * update the folder size and the size of all parent folders + * + * @param $path + */ + public function correctFolderSize($path) { + $this->calculateFolderSize($path); + if ($path !== '') { + $parent = dirname($path); + if ($parent === '.') { + $parent = ''; + } + $this->correctFolderSize($parent); + } + } + /** * get the size of a folder and set it in the cache * diff --git a/lib/files/cache/scanner.php b/lib/files/cache/scanner.php index 7062888d74..0adde1d354 100644 --- a/lib/files/cache/scanner.php +++ b/lib/files/cache/scanner.php @@ -107,20 +107,4 @@ class Scanner { } return $size; } - - /** - * update the folder size and the size of all parent folders - * - * @param $path - */ - public function correctFolderSize($path) { - $this->cache->calculateFolderSize($path); - if ($path !== '') { - $parent = dirname($path); - if ($parent === '.') { - $parent = ''; - } - $this->correctFolderSize($parent); - } - } } diff --git a/lib/files/cache/watcher.php b/lib/files/cache/watcher.php index f04ca9b465..d6039d9945 100644 --- a/lib/files/cache/watcher.php +++ b/lib/files/cache/watcher.php @@ -50,7 +50,7 @@ class Watcher { } else { $this->scanner->scanFile($path); } - $this->scanner->correctFolderSize($path); + $this->cache->correctFolderSize($path); } } diff --git a/tests/lib/files/cache/scanner.php b/tests/lib/files/cache/scanner.php index 34d38c4273..f784a82dad 100644 --- a/tests/lib/files/cache/scanner.php +++ b/tests/lib/files/cache/scanner.php @@ -98,7 +98,7 @@ class Scanner extends \UnitTestCase { $this->assertNotEqual($cachedDataFolder2['size'], -1); - $this->scanner->correctFolderSize('folder'); + $this->cache->correctFolderSize('folder'); $cachedDataFolder = $this->cache->get(''); $this->assertNotEqual($cachedDataFolder['size'], -1); From 5a173b901f90dba3465847cde4477be9994a1341 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 8 Nov 2012 20:47:40 +0100 Subject: [PATCH 078/347] fix Scanner->scan setting the filesize to 0 for files --- lib/files/cache/scanner.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/files/cache/scanner.php b/lib/files/cache/scanner.php index 0adde1d354..eb947a2d53 100644 --- a/lib/files/cache/scanner.php +++ b/lib/files/cache/scanner.php @@ -101,9 +101,9 @@ class Scanner { } } } - } - if ($size !== -1) { - $this->cache->put($path, array('size' => $size)); + if ($size !== -1) { + $this->cache->put($path, array('size' => $size)); + } } return $size; } From fedff3eafe73a3eafbc1bc7af364297e8135d086 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 8 Nov 2012 21:12:40 +0100 Subject: [PATCH 079/347] add cache updater --- lib/files/cache/updater.php | 71 ++++++++++++++++++ tests/lib/files/cache/updater.php | 116 ++++++++++++++++++++++++++++++ 2 files changed, 187 insertions(+) create mode 100644 lib/files/cache/updater.php create mode 100644 tests/lib/files/cache/updater.php diff --git a/lib/files/cache/updater.php b/lib/files/cache/updater.php new file mode 100644 index 0000000000..fb9783023e --- /dev/null +++ b/lib/files/cache/updater.php @@ -0,0 +1,71 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Files\Cache; + +/** + * listen to filesystem hooks and change the cache accordingly + */ +class Updater { + + /** + * resolve a path to a storage and internal path + * + * @param string $path + * @return array consisting of the storage and the internal path + */ + static public function resolvePath($path) { + $view = \OC\Files\Filesystem::getView(); + return $view->resolvePath($path); + } + + static public function writeUpdate($path) { + /** + * @var \OC\Files\Storage\Storage $storage + * @var string $internalPath + */ + list($storage, $internalPath) = self::resolvePath($path); + $cache = new Cache($storage); + $scanner = new Scanner($storage); + $scanner->scan($internalPath, Scanner::SCAN_SHALLOW); + $cache->correctFolderSize($internalPath); + } + + static public function deleteUpdate($path) { + /** + * @var \OC\Files\Storage\Storage $storage + * @var string $internalPath + */ + list($storage, $internalPath) = self::resolvePath($path); + $cache = new Cache($storage); + $cache->remove($internalPath); + $cache->correctFolderSize($internalPath); + } + + /** + * @param array $params + */ + static public function writeHook($params) { + self::writeUpdate($params['path']); + } + + /** + * @param array $params + */ + static public function renameHook($params) { + self::deleteUpdate($params['oldpath']); + self::writeUpdate($params['newpath']); + } + + /** + * @param array $params + */ + static public function deleteHook($params) { + self::deleteUpdate($params['path']); + } +} diff --git a/tests/lib/files/cache/updater.php b/tests/lib/files/cache/updater.php new file mode 100644 index 0000000000..8059418dc1 --- /dev/null +++ b/tests/lib/files/cache/updater.php @@ -0,0 +1,116 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\Files\Cache; + +use \OC\Files\Filesystem as Filesystem; + +class Updater extends \PHPUnit_Framework_TestCase { + /** + * @var \OC\Files\Storage\Storage $storage + */ + private $storage; + + /** + * @var \OC\Files\Cache\Scanner $scanner + */ + private $scanner; + + /** + * @var \OC\Files\Cache\Cache $cache + */ + private $cache; + + private static $user; + + public function setUp() { + $this->storage = new \OC\Files\Storage\Temporary(array()); + $textData = "dummy file data\n"; + $imgData = file_get_contents(\OC::$SERVERROOT . '/core/img/logo.png'); + $this->storage->mkdir('folder'); + $this->storage->file_put_contents('foo.txt', $textData); + $this->storage->file_put_contents('foo.png', $imgData); + $this->storage->file_put_contents('folder/bar.txt', $textData); + $this->storage->file_put_contents('folder/bar2.txt', $textData); + + $this->scanner = $this->storage->getScanner(); + $this->scanner->scan(''); + $this->cache = $this->storage->getCache(); + + if (!self::$user) { + if (!\OC\Files\Filesystem::getView()) { + self::$user = uniqid(); + \OC\Files\Filesystem::init('/' . self::$user . '/files'); + } else { + self::$user = \OC_User::getUser(); + } + } + + Filesystem::clearMounts(); + Filesystem::mount($this->storage, array(), '/' . self::$user . '/files'); + + \OC_Hook::connect('OC_Filesystem', 'post_write', '\OC\Files\Cache\Updater', 'writeHook'); + \OC_Hook::connect('OC_Filesystem', 'post_delete', '\OC\Files\Cache\Updater', 'deleteHook'); + \OC_Hook::connect('OC_Filesystem', 'post_rename', '\OC\Files\Cache\Updater', 'renameHook'); + + } + + public function tearDown() { + $this->cache->clear(); + Filesystem::tearDown(); + } + + public function testWrite() { + $textSize = strlen("dummy file data\n"); + $imageSize = filesize(\OC::$SERVERROOT . '/core/img/logo.png'); + $cachedData = $this->cache->get(''); + $this->assertEquals(3 * $textSize + $imageSize, $cachedData['size']); + + Filesystem::file_put_contents('foo.txt', 'asd'); + $cachedData = $this->cache->get('foo.txt'); + $this->assertEquals(3, $cachedData['size']); + $cachedData = $this->cache->get(''); + $this->assertEquals(2 * $textSize + $imageSize + 3, $cachedData['size']); + + $this->assertFalse($this->cache->inCache('bar.txt')); + Filesystem::file_put_contents('bar.txt', 'asd'); + $this->assertTrue($this->cache->inCache('bar.txt')); + $cachedData = $this->cache->get('bar.txt'); + $this->assertEquals(3, $cachedData['size']); + $cachedData = $this->cache->get(''); + $this->assertEquals(2 * $textSize + $imageSize + 2 * 3, $cachedData['size']); + } + + public function testDelete() { + $textSize = strlen("dummy file data\n"); + $imageSize = filesize(\OC::$SERVERROOT . '/core/img/logo.png'); + $cachedData = $this->cache->get(''); + $this->assertEquals(3 * $textSize + $imageSize, $cachedData['size']); + + $this->assertTrue($this->cache->inCache('foo.txt')); + Filesystem::unlink('foo.txt', 'asd'); + $this->assertFalse($this->cache->inCache('foo.txt')); + $cachedData = $this->cache->get(''); + $this->assertEquals(2 * $textSize + $imageSize, $cachedData['size']); + } + + public function testRename() { + $textSize = strlen("dummy file data\n"); + $imageSize = filesize(\OC::$SERVERROOT . '/core/img/logo.png'); + $cachedData = $this->cache->get(''); + $this->assertEquals(3 * $textSize + $imageSize, $cachedData['size']); + + $this->assertTrue($this->cache->inCache('foo.txt')); + $this->assertFalse($this->cache->inCache('bar.txt')); + Filesystem::rename('foo.txt', 'bar.txt'); + $this->assertFalse($this->cache->inCache('foo.txt')); + $this->assertTrue($this->cache->inCache('bar.txt')); + $cachedData = $this->cache->get(''); + $this->assertEquals(3 * $textSize + $imageSize, $cachedData['size']); + } +} From d4858527c2fae4b58c5a9bc1c3aae9ada0ee7b24 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 8 Nov 2012 21:35:30 +0100 Subject: [PATCH 080/347] fix rename parameter order --- apps/files/ajax/rename.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/files/ajax/rename.php b/apps/files/ajax/rename.php index a2b9b8de25..470ee635a2 100644 --- a/apps/files/ajax/rename.php +++ b/apps/files/ajax/rename.php @@ -11,9 +11,9 @@ $dir = stripslashes($_GET["dir"]); $file = stripslashes($_GET["file"]); $newname = stripslashes($_GET["newname"]); -if (OC_User::isLoggedIn() && ($dir != '' || $file != 'Shared')) { - $targetFile = \OC\Files\Filesystem::normalizePath($dir . '/' . $file); - $sourceFile = \OC\Files\Filesystem::normalizePath($dir . '/' . $newname); +if (($dir != '' || $file != 'Shared')) { + $targetFile = \OC\Files\Filesystem::normalizePath($dir . '/' . $newname); + $sourceFile = \OC\Files\Filesystem::normalizePath($dir . '/' . $file); if(\OC\Files\Filesystem::rename($sourceFile, $targetFile)) { OCP\JSON::success(array("data" => array( "dir" => $dir, "file" => $file, "newname" => $newname ))); } else { From 46071fed80c7375edf4788578776a6b313b6dca3 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 8 Nov 2012 21:35:40 +0100 Subject: [PATCH 081/347] fix quota proxy --- lib/fileproxy/quota.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/fileproxy/quota.php b/lib/fileproxy/quota.php index b359b9ae02..a8219191bf 100644 --- a/lib/fileproxy/quota.php +++ b/lib/fileproxy/quota.php @@ -22,7 +22,7 @@ */ /** - * user quota managment + * user quota management */ class OC_FileProxy_Quota extends OC_FileProxy{ @@ -39,10 +39,8 @@ class OC_FileProxy_Quota extends OC_FileProxy{ 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; @@ -59,8 +57,12 @@ class OC_FileProxy_Quota extends OC_FileProxy{ * @return int */ private function getFreeSpace($path) { - $storage=OC_Filesystem::getStorage($path); - $owner=$storage->getOwner($path); + /** + * @var \OC\Files\Storage\Storage $storage + * @var string $internalPath + */ + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($path); + $owner=$storage->getOwner($internalPath); $totalSpace=$this->getQuota($owner); if($totalSpace==0) { From 41a61bc637c3d60efc5abe81c39fc726fd78cd1d Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 8 Nov 2012 21:36:13 +0100 Subject: [PATCH 082/347] fix undefined index when loading files app --- apps/files/index.php | 4 +--- apps/files/templates/part.list.php | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/files/index.php b/apps/files/index.php index cdb88ab83f..4e5f4cd93a 100644 --- a/apps/files/index.php +++ b/apps/files/index.php @@ -66,9 +66,7 @@ foreach( \OC\Files\Filesystem::getDirectoryContent( $dir ) as $i ) { $i['extension']=''; } } - if($i['directory']=='/') { - $i['directory']=''; - } + $i['directory'] = $dir; $files[] = $i; } diff --git a/apps/files/templates/part.list.php b/apps/files/templates/part.list.php index 4b5ac32567..9c9d9926e5 100644 --- a/apps/files/templates/part.list.php +++ b/apps/files/templates/part.list.php @@ -18,7 +18,7 @@ $name = str_replace('%2F', '/', $name); $directory = str_replace('+', '%20', urlencode($file['directory'])); $directory = str_replace('%2F', '/', $directory); ?> -

' data-permissions=''> + ' data-permissions=''>
From cbcd9ba84ada830d91a6f1d7bee0ac59762835ed Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 15 Nov 2012 00:57:30 +0100 Subject: [PATCH 083/347] allow storage backends to implement custom permission management --- lib/files/cache/permissions.php | 36 ++++++++++++++------- lib/files/storage/common.php | 14 ++++++--- lib/files/storage/storage.php | 5 +++ lib/files/view.php | 6 ++-- tests/lib/files/cache/permissions.php | 45 ++++++++++++++++----------- tests/lib/files/cache/scanner.php | 3 +- tests/lib/files/cache/watcher.php | 3 +- tests/lib/files/view.php | 3 +- 8 files changed, 76 insertions(+), 39 deletions(-) diff --git a/lib/files/cache/permissions.php b/lib/files/cache/permissions.php index dd7233abc7..d0968337f0 100644 --- a/lib/files/cache/permissions.php +++ b/lib/files/cache/permissions.php @@ -9,6 +9,22 @@ namespace OC\Files\Cache; class Permissions { + /** + * @var string $storageId + */ + private $storageId; + + /** + * @param \OC\Files\Storage\Storage|string $storage + */ + public function __construct($storage){ + if($storage instanceof \OC\Files\Storage\Storage){ + $this->storageId = $storage->getId(); + }else{ + $this->storageId = $storage; + } + } + /** * get the permissions for a single file * @@ -16,7 +32,7 @@ class Permissions { * @param string $user * @return int (-1 if file no permissions set) */ - static public function get($fileId, $user) { + public function get($fileId, $user) { $query = \OC_DB::prepare('SELECT `permissions` FROM `*PREFIX*permissions` WHERE `user` = ? AND `fileid` = ?'); $result = $query->execute(array($user, $fileId)); if ($row = $result->fetchRow()) { @@ -33,7 +49,7 @@ class Permissions { * @param string $user * @param int $permissions */ - static public function set($fileId, $user, $permissions) { + public function set($fileId, $user, $permissions) { if (self::get($fileId, $user) !== -1) { $query = \OC_DB::prepare('UPDATE `*PREFIX*permissions` SET `permissions` = ? WHERE `user` = ? AND `fileid` = ?'); } else { @@ -49,7 +65,7 @@ class Permissions { * @param string $user * @return int[] */ - static public function getMultiple($fileIds, $user) { + public function getMultiple($fileIds, $user) { if (count($fileIds) === 0) { return array(); } @@ -72,17 +88,15 @@ class Permissions { * @param int $fileId * @param string $user */ - static public function remove($fileId, $user) { + public function remove($fileId, $user) { $query = \OC_DB::prepare('DELETE FROM `*PREFIX*permissions` WHERE `fileid` = ? AND `user` = ?'); $query->execute(array($fileId, $user)); } - static public function removeMultiple($fileIds, $user) { - $params = $fileIds; - $params[] = $user; - $inPart = implode(', ', array_fill(0, count($fileIds), '?')); - - $query = \OC_DB::prepare('DELETE FROM `*PREFIX*permissions` WHERE `fileid` IN (' . $inPart . ') AND `user` = ?'); - $query->execute($params); + public function removeMultiple($fileIds, $user) { + $query = \OC_DB::prepare('DELETE FROM `*PREFIX*permissions` WHERE `fileid` = ? AND `user` = ?'); + foreach($fileIds as $fileId){ + $query->execute(array($fileId, $user)); + } } } diff --git a/lib/files/storage/common.php b/lib/files/storage/common.php index f471752d1f..cf6fe64a4f 100644 --- a/lib/files/storage/common.php +++ b/lib/files/storage/common.php @@ -57,19 +57,19 @@ abstract class Common implements \OC\Files\Storage\Storage { public function getPermissions($path){ $permissions = 0; if($this->isCreatable($path)){ - $permissions |= \OCP\Share::PERMISSION_CREATE; + $permissions |= \OCP\PERMISSION_CREATE; } if($this->isReadable($path)){ - $permissions |= \OCP\Share::PERMISSION_READ; + $permissions |= \OCP\PERMISSION_READ; } if($this->isUpdatable($path)){ - $permissions |= \OCP\Share::PERMISSION_UPDATE; + $permissions |= \OCP\PERMISSION_UPDATE; } if($this->isDeletable($path)){ - $permissions |= \OCP\Share::PERMISSION_DELETE; + $permissions |= \OCP\PERMISSION_DELETE; } if($this->isSharable($path)){ - $permissions |= \OCP\Share::PERMISSION_SHARE; + $permissions |= \OCP\PERMISSION_SHARE; } return $permissions; } @@ -259,6 +259,10 @@ abstract class Common implements \OC\Files\Storage\Storage { return new \OC\Files\Cache\Scanner($this); } + public function getPermissionsCache(){ + return new \OC\Files\Cache\Permissions($this); + } + /** * get the owner of a path * @param string $path The path to get the owner diff --git a/lib/files/storage/storage.php b/lib/files/storage/storage.php index bb1ba16984..73dcb8fe36 100644 --- a/lib/files/storage/storage.php +++ b/lib/files/storage/storage.php @@ -64,6 +64,11 @@ interface Storage{ public function getOwner($path); + /** + * @return \OC\Files\Cache\Permissions + */ + public function getPermissionsCache(); + /** * get the ETag for a file or folder * diff --git a/lib/files/view.php b/lib/files/view.php index a54c3ee356..e516a4fed6 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -701,7 +701,8 @@ class View { } } - $data['permissions'] = Cache\Permissions::get($data['fileid'], \OC_User::getUser()); + $permissionsCache = $storage->getPermissionsCache(); + $data['permissions'] = $permissionsCache->get($data['fileid'], \OC_User::getUser()); return $data; } @@ -759,8 +760,9 @@ class View { $files[$i]['type'] = $file['mimetype'] === 'httpd/unix-directory' ? 'dir' : 'file'; $ids[] = $file['fileid']; } + $permissionsCache = $storage->getPermissionsCache(); - $permissions = Cache\Permissions::getMultiple($ids, \OC_User::getUser()); + $permissions = $permissionsCache->getMultiple($ids, \OC_User::getUser()); foreach ($files as $i => $file) { $files[$i]['permissions'] = $permissions[$file['fileid']]; } diff --git a/tests/lib/files/cache/permissions.php b/tests/lib/files/cache/permissions.php index 4d47929a3e..56dbbc4518 100644 --- a/tests/lib/files/cache/permissions.php +++ b/tests/lib/files/cache/permissions.php @@ -9,39 +9,48 @@ namespace Test\Files\Cache; class Permissions extends \PHPUnit_Framework_TestCase { + /*** + * @var \OC\Files\Cache\Permissions $permissionsCache + */ + private $permissionsCache; + + function setUp(){ + $this->permissionsCache=new \OC\Files\Cache\Permissions('dummy'); + } + function testSimple() { $ids = range(1, 10); $user = uniqid(); - $this->assertEquals(-1, \OC\Files\Cache\Permissions::get(1, $user)); - \OC\Files\Cache\Permissions::set(1, $user, 1); - $this->assertEquals(1, \OC\Files\Cache\Permissions::get(1, $user)); - $this->assertEquals(-1, \OC\Files\Cache\Permissions::get(2, $user)); - $this->assertEquals(-1, \OC\Files\Cache\Permissions::get(1, $user . '2')); + $this->assertEquals(-1, $this->permissionsCache->get(1, $user)); + $this->permissionsCache->set(1, $user, 1); + $this->assertEquals(1, $this->permissionsCache->get(1, $user)); + $this->assertEquals(-1, $this->permissionsCache->get(2, $user)); + $this->assertEquals(-1, $this->permissionsCache->get(1, $user . '2')); - \OC\Files\Cache\Permissions::set(1, $user, 2); - $this->assertEquals(2, \OC\Files\Cache\Permissions::get(1, $user)); + $this->permissionsCache->set(1, $user, 2); + $this->assertEquals(2, $this->permissionsCache->get(1, $user)); - \OC\Files\Cache\Permissions::set(2, $user, 1); - $this->assertEquals(1, \OC\Files\Cache\Permissions::get(2, $user)); + $this->permissionsCache->set(2, $user, 1); + $this->assertEquals(1, $this->permissionsCache->get(2, $user)); - \OC\Files\Cache\Permissions::remove(1, $user); - $this->assertEquals(-1, \OC\Files\Cache\Permissions::get(1, $user)); - \OC\Files\Cache\Permissions::remove(1, $user . '2'); - $this->assertEquals(1, \OC\Files\Cache\Permissions::get(2, $user)); + $this->permissionsCache->remove(1, $user); + $this->assertEquals(-1, $this->permissionsCache->get(1, $user)); + $this->permissionsCache->remove(1, $user . '2'); + $this->assertEquals(1, $this->permissionsCache->get(2, $user)); $expected = array(); foreach ($ids as $id) { - \OC\Files\Cache\Permissions::set($id, $user, 10 + $id); + $this->permissionsCache->set($id, $user, 10 + $id); $expected[$id] = 10 + $id; } - $this->assertEquals($expected, \OC\Files\Cache\Permissions::getMultiple($ids, $user)); + $this->assertEquals($expected, $this->permissionsCache->getMultiple($ids, $user)); - \OC\Files\Cache\Permissions::removeMultiple(array(10, 9), $user); + $this->permissionsCache->removeMultiple(array(10, 9), $user); unset($expected[9]); unset($expected[10]); - $this->assertEquals($expected, \OC\Files\Cache\Permissions::getMultiple($ids, $user)); + $this->assertEquals($expected, $this->permissionsCache->getMultiple($ids, $user)); - \OC\Files\Cache\Permissions::removeMultiple($ids, $user); + $this->permissionsCache->removeMultiple($ids, $user); } } diff --git a/tests/lib/files/cache/scanner.php b/tests/lib/files/cache/scanner.php index f784a82dad..c53da92727 100644 --- a/tests/lib/files/cache/scanner.php +++ b/tests/lib/files/cache/scanner.php @@ -112,7 +112,8 @@ class Scanner extends \UnitTestCase { function tearDown() { $ids = $this->cache->getAll(); - \OC\Files\Cache\Permissions::removeMultiple($ids, \OC_User::getUser()); + $permissionsCache = $this->storage->getPermissionsCache(); + $permissionsCache->removeMultiple($ids, \OC_User::getUser()); $this->cache->clear(); } } diff --git a/tests/lib/files/cache/watcher.php b/tests/lib/files/cache/watcher.php index a7076d9b0b..0125dd843b 100644 --- a/tests/lib/files/cache/watcher.php +++ b/tests/lib/files/cache/watcher.php @@ -23,7 +23,8 @@ class Watcher extends \PHPUnit_Framework_TestCase { foreach ($this->storages as $storage) { $cache = $storage->getCache(); $ids = $cache->getAll(); - \OC\Files\Cache\Permissions::removeMultiple($ids, \OC_User::getUser()); + $permissionsCache = $storage->getPermissionsCache(); + $permissionsCache->removeMultiple($ids, \OC_User::getUser()); $cache->clear(); } } diff --git a/tests/lib/files/view.php b/tests/lib/files/view.php index fa562cb15c..a173094b1c 100644 --- a/tests/lib/files/view.php +++ b/tests/lib/files/view.php @@ -21,7 +21,8 @@ class View extends \PHPUnit_Framework_TestCase { foreach ($this->storages as $storage) { $cache = $storage->getCache(); $ids = $cache->getAll(); - \OC\Files\Cache\Permissions::removeMultiple($ids, \OC_User::getUser()); + $permissionsCache = $storage->getPermissionsCache(); + $permissionsCache->removeMultiple($ids, \OC_User::getUser()); $cache->clear(); } } From 5569f07e8d68716f01267c9f41e5f0be299cc67a Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 15 Nov 2012 22:04:48 +0100 Subject: [PATCH 084/347] add OC_FilesystemView alias for compatibility --- lib/filesystemview.php | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 lib/filesystemview.php diff --git a/lib/filesystemview.php b/lib/filesystemview.php new file mode 100644 index 0000000000..37e2a737e0 --- /dev/null +++ b/lib/filesystemview.php @@ -0,0 +1,8 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. */ + +class OC_FilesystemView extends \OC\Files\View {} From 288ecf318cbb742b2c6a40d6c6afedfafb3cafd4 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 15 Nov 2012 22:08:08 +0100 Subject: [PATCH 085/347] add getFileInfo and getDirectoryContent to OC_Files for compatibility --- lib/files.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/files.php b/lib/files.php index e6b324f062..3abc8c4aaf 100644 --- a/lib/files.php +++ b/lib/files.php @@ -28,6 +28,14 @@ class OC_Files { static $tmpFiles = array(); + public function getFileInfo($path){ + return \OC\Files\Filesystem::getFileInfo($path); + } + + public function getDirectoryContent($path){ + return \OC\Files\Filesystem::getDirectoryContent($path); + } + /** * return the content of a file or return a zip file containning multiply files * From 54240140b10f2d718753445b656c9607967d7c64 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 16 Nov 2012 12:14:29 +0100 Subject: [PATCH 086/347] fix incorectly merged smb.php --- apps/files_external/lib/smb.php | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/files_external/lib/smb.php b/apps/files_external/lib/smb.php index bf0d780d27..a4b2338e3b 100644 --- a/apps/files_external/lib/smb.php +++ b/apps/files_external/lib/smb.php @@ -35,6 +35,7 @@ class SMB extends \OC\Files\Storage\StreamWrapper{ if(substr($this->share, -1, 1)=='/') { $this->share = substr($this->share,0,-1); } + } public function getId(){ return 'smb::' . $this->user . '@' . $this->host . '/' . $this->share . '/' . $this->root; From 3358bface5c20aeb4ad41dc1edffb895bc24af71 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 16 Nov 2012 12:24:28 +0100 Subject: [PATCH 087/347] fix incorectly merged versions.php --- apps/files_versions/lib/versions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_versions/lib/versions.php b/apps/files_versions/lib/versions.php index b365f45679..7fe3d5549e 100644 --- a/apps/files_versions/lib/versions.php +++ b/apps/files_versions/lib/versions.php @@ -189,7 +189,7 @@ class Storage { $i = 0; - $files_view = new \OC\Files\View('/' \OCP\User::getUser() . '/files'); + $files_view = new \OC\Files\View('/' . \OCP\User::getUser() . '/files'); $local_file = $files_view->getLocalFile($filename); foreach( $matches as $ma ) { From 40fae0acbf2e84782c273a82eb10a2ed9fdf8162 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sun, 18 Nov 2012 14:10:28 +0100 Subject: [PATCH 088/347] fix outdated permissions cache use in scanner --- lib/files/cache/scanner.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/files/cache/scanner.php b/lib/files/cache/scanner.php index eb947a2d53..404029ee2e 100644 --- a/lib/files/cache/scanner.php +++ b/lib/files/cache/scanner.php @@ -19,12 +19,18 @@ class Scanner { */ private $cache; + /** + * @var \OC\Files\Cache\Permissions $permissionsCache + */ + private $permissionsCache; + const SCAN_RECURSIVE = true; const SCAN_SHALLOW = false; public function __construct(\OC\Files\Storage\Storage $storage) { $this->storage = $storage; - $this->cache = new Cache($storage); + $this->cache = $storage->getCache(); + $this->permissionsCache = $storage->getPermissionsCache(); } /** @@ -67,7 +73,7 @@ class Scanner { } } $id = $this->cache->put($file, $data); - Permissions::set($id, \OC_User::getUser(), $data['permissions']); + $this->permissionsCache->set($id, \OC_User::getUser(), $data['permissions']); return $data; } From 77fdb16b7cb97f4e68949baf6796ef0e290b03f5 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Thu, 22 Nov 2012 00:22:27 -0500 Subject: [PATCH 089/347] Remove incorrect extra parameter for init() call --- lib/util.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/util.php b/lib/util.php index 89fbcd05cd..c79afe1957 100755 --- a/lib/util.php +++ b/lib/util.php @@ -52,7 +52,7 @@ class OC_Util { } //jail the user into his "home" directory \OC\Files\Filesystem::mount('\OC\Files\Storage\Local', array('datadir' => $user_root), $user); - \OC\Files\Filesystem::init($user_dir, $user); + \OC\Files\Filesystem::init($user_dir); $quotaProxy=new OC_FileProxy_Quota(); $fileOperationProxy = new OC_FileProxy_FileOperations(); From b76d1afe193fae3bf94aed9a95e270b452e62eb8 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Thu, 22 Nov 2012 00:44:48 -0500 Subject: [PATCH 090/347] Create public function initMountPoints() for initializing a specified user's mount points --- lib/files/filesystem.php | 53 ++++++++++++++++++++++++++++------------ lib/util.php | 16 ------------ 2 files changed, 37 insertions(+), 32 deletions(-) diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php index ed2814211f..cee3cd883b 100644 --- a/lib/files/filesystem.php +++ b/lib/files/filesystem.php @@ -229,35 +229,50 @@ class Filesystem { self::$defaultInstance = new View($root); //load custom mount config - if (is_file(\OC::$SERVERROOT . '/config/mount.php')) { + self::initMountPoints(); + + self::$loaded = true; + + return true; + } + + /** + * Initialize system and personal mount points for a user + * + * @param string $user + */ + public static function initMountPoints($user = '') { + if ($user == '') { + $user = \OC_User::getUser(); + } + // Load system mount points + if (is_file(\OC::$SERVERROOT.'/config/mount.php')) { $mountConfig = include '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(\OC_User::getUser(), $group)) { + if (\OC_Group::inGroup($user, $group)) { foreach ($mounts as $mountPoint => $options) { - $mountPoint = self::setUserVars($mountPoint); + $mountPoint = self::setUserVars($user, $mountPoint); foreach ($options as &$option) { - $option = self::setUserVars($option); + $option = self::setUserVars($user, $option); } self::mount($options['class'], $options['options'], $mountPoint); } } } } - if (isset($mountConfig['user'])) { - foreach ($mountConfig['user'] as $user => $mounts) { - if ($user === 'all' or strtolower($user) === strtolower(\OC_User::getUser())) { + foreach ($mountConfig['user'] as $mountUser => $mounts) { + if ($user === 'all' or strtolower($mountUser) === strtolower($user)) { foreach ($mounts as $mountPoint => $options) { - $mountPoint = self::setUserVars($mountPoint); + $mountPoint = self::setUserVars($user, $mountPoint); foreach ($options as &$option) { - $option = self::setUserVars($option); + $option = self::setUserVars($user, $option); } self::mount($options['class'], $options['options'], $mountPoint); } @@ -265,10 +280,16 @@ class Filesystem { } } } - - self::$loaded = true; - - return true; + // Load personal mount points + $root = OC_User::getHome($user); + if (is_file($root.'/mount.php')) { + $mountConfig = include $root.'/mount.php'; + if (isset($mountConfig['user'][$user])) { + foreach ($mountConfig['user'][$user] as $mountPoint => $options) { + self::mount($options['class'], $options['options'], $mountPoint); + } + } + } } /** @@ -277,8 +298,8 @@ class Filesystem { * @param string $input * @return string */ - private static function setUserVars($input) { - return str_replace('$user', \OC_User::getUser(), $input); + private static function setUserVars($user, $input) { + return str_replace('$user', $user, $input); } /** diff --git a/lib/util.php b/lib/util.php index c79afe1957..25fdcef1ae 100755 --- a/lib/util.php +++ b/lib/util.php @@ -58,8 +58,6 @@ class OC_Util { $fileOperationProxy = new OC_FileProxy_FileOperations(); OC_FileProxy::register($quotaProxy); OC_FileProxy::register($fileOperationProxy); - // Load personal mount config - self::loadUserMountPoints($user); OC_Hook::emit('OC_Filesystem', 'setup', array('user' => $user, 'user_dir' => $user_dir)); } @@ -71,20 +69,6 @@ class OC_Util { self::$fsSetup=false; } - public static function loadUserMountPoints($user) { - $user_dir = '/'.$user.'/files'; - $user_root = OC_User::getHome($user); - $userdirectory = $user_root . '/files'; - if (is_file($user_root.'/mount.php')) { - $mountConfig = include $user_root.'/mount.php'; - if (isset($mountConfig['user'][$user])) { - foreach ($mountConfig['user'][$user] as $mountPoint => $options) { - \OC\Files\Filesystem::mount($options['class'], $options['options'], $mountPoint); - } - } - } - } - /** * get the current installed version of ownCloud * @return array From 208c6fd966dd5f9f387cdd1b4f030a2723144347 Mon Sep 17 00:00:00 2001 From: Thomas Mueller Date: Thu, 22 Nov 2012 10:21:48 +0100 Subject: [PATCH 091/347] fixing namespace --- lib/files/filesystem.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php index cee3cd883b..9e8ce3ec18 100644 --- a/lib/files/filesystem.php +++ b/lib/files/filesystem.php @@ -281,7 +281,7 @@ class Filesystem { } } // Load personal mount points - $root = OC_User::getHome($user); + $root = \OC_User::getHome($user); if (is_file($root.'/mount.php')) { $mountConfig = include $root.'/mount.php'; if (isset($mountConfig['user'][$user])) { From e6cf082fe07e4e33c883bd5f9aaa0cc72b082741 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 21 Nov 2012 22:44:43 +0100 Subject: [PATCH 092/347] emit a hooks during the filesystem scan --- lib/files/cache/scanner.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/files/cache/scanner.php b/lib/files/cache/scanner.php index 404029ee2e..e650a220f5 100644 --- a/lib/files/cache/scanner.php +++ b/lib/files/cache/scanner.php @@ -14,6 +14,11 @@ class Scanner { */ private $storage; + /** + * @var string $storageId + */ + private $storageId; + /** * @var \OC\Files\Cache\Cache $cache */ @@ -29,6 +34,7 @@ class Scanner { public function __construct(\OC\Files\Storage\Storage $storage) { $this->storage = $storage; + $this->storageId = $this->storage->getId(); $this->cache = $storage->getCache(); $this->permissionsCache = $storage->getPermissionsCache(); } @@ -62,6 +68,7 @@ class Scanner { * @return array with metadata of the scanned file */ public function scanFile($file) { + \OC_Hook::emit('\OC\Files\Cache\Scanner', 'scan_file', array('path' => $file, 'storage' => $this->storageId)); $data = $this->getData($file); if ($file !== '') { $parent = dirname($file); @@ -85,6 +92,7 @@ class Scanner { * @return int the size of the scanned folder or -1 if the size is unknown at this stage */ public function scan($path, $recursive = self::SCAN_RECURSIVE) { + \OC_Hook::emit('\OC\Files\Cache\Scanner', 'scan_folder', array('path' => $path, 'storage' => $this->storageId)); $this->scanFile($path); $size = 0; From 186c9e77e89dcd057a311ed08df9e1bb9e13ea8f Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 21 Nov 2012 23:02:43 +0100 Subject: [PATCH 093/347] add Cache->getIncomplete for use in background scanning --- lib/files/cache/cache.php | 19 +++++++++++++++++++ tests/lib/files/cache/cache.php | 17 +++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index 7c6bba4fad..b52c0f4067 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -402,4 +402,23 @@ class Cache { } return $ids; } + + /** + * find a folder in the cache which has not been fully scanned + * + * If multiply incomplete folders are in the cache, the one with the highest id will be returned, + * use the one with the highest id gives the best result with the background scanner, since that is most + * likely the folder where we stopped scanning previously + * + * @return string|bool the path of the folder or false when no folder matched + */ + public function getIncomplete(){ + $query = \OC_DB::prepare('SELECT `path` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `size` = -1 ORDER BY `fileid` DESC LIMIT 1'); + $query->execute(array($this->storageId)); + if($row = $query->fetchRow()){ + return $row['path']; + }else{ + return false; + } + } } diff --git a/tests/lib/files/cache/cache.php b/tests/lib/files/cache/cache.php index 9c469aa937..e9105cd5ab 100644 --- a/tests/lib/files/cache/cache.php +++ b/tests/lib/files/cache/cache.php @@ -175,6 +175,23 @@ class Cache extends \UnitTestCase { $this->assertTrue($this->cache->inCache('folder/foobar/2')); } + function testGetIncomplete() { + $file1 = 'folder1'; + $file2 = 'folder2'; + $file3 = 'folder3'; + $file4 = 'folder4'; + $data = array('size' => 10, 'mtime' => 50, 'mimetype' => 'foo/bar'); + + $this->cache->put($file1, $data); + $data['size'] = -1; + $this->cache->put($file2, $data); + $this->cache->put($file3, $data); + $data['size'] = 12; + $this->cache->put($file4, $data); + + $this->assertEquals($file3, $this->cache->getIncomplete()); + } + public function tearDown() { $this->cache->clear(); } From 8687e0d346e7dad6890982c1a7b08befd8998aeb Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 21 Nov 2012 23:18:58 +0100 Subject: [PATCH 094/347] add Scanner->backgroundScan --- lib/files/cache/scanner.php | 10 ++++++++++ tests/lib/files/cache/scanner.php | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/lib/files/cache/scanner.php b/lib/files/cache/scanner.php index e650a220f5..3c83b6528a 100644 --- a/lib/files/cache/scanner.php +++ b/lib/files/cache/scanner.php @@ -121,4 +121,14 @@ class Scanner { } return $size; } + + /** + * walk over any folders that are not fully scanned yet and scan them + */ + public function backgroundScan() { + while ($path = $this->cache->getIncomplete()) { + $this->scan($path); + $this->cache->correctFolderSize($path); + } + } } diff --git a/tests/lib/files/cache/scanner.php b/tests/lib/files/cache/scanner.php index c53da92727..6d26150d82 100644 --- a/tests/lib/files/cache/scanner.php +++ b/tests/lib/files/cache/scanner.php @@ -104,6 +104,28 @@ class Scanner extends \UnitTestCase { $this->assertNotEqual($cachedDataFolder['size'], -1); } + function testBackgroundScan(){ + $this->fillTestFolders(); + $this->storage->mkdir('folder2'); + $this->storage->file_put_contents('folder2/bar.txt', 'foobar'); + + $this->scanner->scan('', \OC\Files\Cache\Scanner::SCAN_SHALLOW); + $this->assertFalse($this->cache->inCache('folder/bar.txt')); + $this->assertFalse($this->cache->inCache('folder/2bar.txt')); + $cachedData = $this->cache->get(''); + $this->assertEquals(-1, $cachedData['size']); + + $this->scanner->backgroundScan(); + + $this->assertTrue($this->cache->inCache('folder/bar.txt')); + $this->assertTrue($this->cache->inCache('folder/bar.txt')); + + $cachedData = $this->cache->get(''); + $this->assertnotEquals(-1, $cachedData['size']); + + $this->assertFalse($this->cache->getIncomplete()); + } + function setUp() { $this->storage = new \OC\Files\Storage\Temporary(array()); $this->scanner = new \OC\Files\Cache\Scanner($this->storage); From 810563ae8aa5884a101cc64226c4f8c3c897132e Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 22 Nov 2012 12:44:31 +0100 Subject: [PATCH 095/347] don't redefine inherited functions as abstract --- lib/files/storage/common.php | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/lib/files/storage/common.php b/lib/files/storage/common.php index cf6fe64a4f..9978cea571 100644 --- a/lib/files/storage/common.php +++ b/lib/files/storage/common.php @@ -23,18 +23,12 @@ namespace OC\Files\Storage; abstract class Common implements \OC\Files\Storage\Storage { public function __construct($parameters) {} - abstract public function getId(); - abstract public function mkdir($path); - abstract public function rmdir($path); - abstract public function opendir($path); public function is_dir($path) { return $this->filetype($path)=='dir'; } public function is_file($path) { return $this->filetype($path)=='file'; } - abstract public function stat($path); - abstract public function filetype($path); public function filesize($path) { if($this->is_dir($path)) { return 0;//by definition @@ -46,8 +40,6 @@ abstract class Common implements \OC\Files\Storage\Storage { public function isCreatable($path) { return $this->isUpdatable($path); } - abstract public function isReadable($path); - abstract public function isUpdatable($path); public function isDeletable($path) { return $this->isUpdatable($path); } @@ -73,7 +65,6 @@ abstract class Common implements \OC\Files\Storage\Storage { } return $permissions; } - abstract public function file_exists($path); public function filemtime($path) { $stat = $this->stat($path); return $stat['mtime']; @@ -97,7 +88,6 @@ abstract class Common implements \OC\Files\Storage\Storage { $handle = $this->fopen($path, "w"); return fwrite($handle, $data); } - abstract public function unlink($path); public function rename($path1,$path2) { if($this->copy($path1,$path2)) { return $this->unlink($path1); @@ -111,7 +101,6 @@ abstract class Common implements \OC\Files\Storage\Storage { $count=\OC_Helper::streamCopy($source,$target); return $count>0; } - abstract public function fopen($path,$mode); /** * @brief Deletes all files and folders recursively within a directory @@ -180,7 +169,6 @@ abstract class Common implements \OC\Files\Storage\Storage { unlink($tmpFile); return $hash; } - abstract public function free_space($path); public function search($query) { return $this->searchInDir($query); } @@ -222,7 +210,6 @@ abstract class Common implements \OC\Files\Storage\Storage { } } } - abstract public function touch($path, $mtime=null); protected function searchInDir($query,$dir='') { $files=array(); From 8ce5e0d30d874bf59a81aa01202a497ea4cb8492 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 22 Nov 2012 13:14:39 +0100 Subject: [PATCH 096/347] don't throw fatal error in updater cache if setup failed for some reason --- tests/lib/files/cache/updater.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/lib/files/cache/updater.php b/tests/lib/files/cache/updater.php index 8059418dc1..b2eccf9130 100644 --- a/tests/lib/files/cache/updater.php +++ b/tests/lib/files/cache/updater.php @@ -61,7 +61,9 @@ class Updater extends \PHPUnit_Framework_TestCase { } public function tearDown() { - $this->cache->clear(); + if($this->cache){ + $this->cache->clear(); + } Filesystem::tearDown(); } From ad706229f5dbc6382ade61493e9f100a2dc07293 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 23 Nov 2012 00:17:18 +0100 Subject: [PATCH 097/347] explicitly sort files when using getFolderContents --- lib/files/cache/cache.php | 14 +++++++------- tests/lib/files/view.php | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index b52c0f4067..6b93673097 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -33,9 +33,9 @@ class Cache { * @param \OC\Files\Storage\Storage|string $storage */ public function __construct($storage) { - if($storage instanceof \OC\Files\Storage\Storage){ + if ($storage instanceof \OC\Files\Storage\Storage) { $this->storageId = $storage->getId(); - }else{ + } else { $this->storageId = $storage; } } @@ -87,7 +87,7 @@ class Cache { if ($fileId > -1) { $query = \OC_DB::prepare( 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted` - FROM `*PREFIX*filecache` WHERE parent = ?'); + FROM `*PREFIX*filecache` WHERE parent = ? ORDER BY `fileid` ASC'); $result = $query->execute(array($fileId)); return $result->fetchAll(); } else { @@ -364,7 +364,7 @@ class Cache { */ public function calculateFolderSize($path) { $id = $this->getId($path); - if($id === -1){ + if ($id === -1) { return 0; } $query = \OC_DB::prepare('SELECT `size` FROM `*PREFIX*filecache` WHERE `parent` = ? AND `storage` = ?'); @@ -412,12 +412,12 @@ class Cache { * * @return string|bool the path of the folder or false when no folder matched */ - public function getIncomplete(){ + public function getIncomplete() { $query = \OC_DB::prepare('SELECT `path` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `size` = -1 ORDER BY `fileid` DESC LIMIT 1'); $query->execute(array($this->storageId)); - if($row = $query->fetchRow()){ + if ($row = $query->fetchRow()) { return $row['path']; - }else{ + } else { return false; } } diff --git a/tests/lib/files/view.php b/tests/lib/files/view.php index a173094b1c..ecfc803dc2 100644 --- a/tests/lib/files/view.php +++ b/tests/lib/files/view.php @@ -55,20 +55,20 @@ class View extends \PHPUnit_Framework_TestCase { $folderData = $rootView->getDirectoryContent('/'); /** * expected entries: - * folder * foo.png * foo.txt + * folder * substorage */ $this->assertEquals(4, count($folderData)); - $this->assertEquals('folder', $folderData[0]['name']); - $this->assertEquals('foo.png', $folderData[1]['name']); - $this->assertEquals('foo.txt', $folderData[2]['name']); + $this->assertEquals('foo.png', $folderData[0]['name']); + $this->assertEquals('foo.txt', $folderData[1]['name']); + $this->assertEquals('folder', $folderData[2]['name']); $this->assertEquals('substorage', $folderData[3]['name']); - $this->assertEquals($storageSize + $textSize, $folderData[0]['size']); - $this->assertEquals($imageSize, $folderData[1]['size']); - $this->assertEquals($textSize, $folderData[2]['size']); + $this->assertEquals($imageSize, $folderData[0]['size']); + $this->assertEquals($textSize, $folderData[1]['size']); + $this->assertEquals($storageSize + $textSize, $folderData[2]['size']); $this->assertEquals($storageSize, $folderData[3]['size']); $folderView = new \OC\Files\View('/folder'); From 8fb4dfd2eabcc267725d3c151d93644d6f28f010 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 23 Nov 2012 00:20:46 +0100 Subject: [PATCH 098/347] use background scanner --- apps/files/ajax/scan.php | 97 +++++++++++++++++++++++++--------------- apps/files/js/files.js | 38 +++++++--------- 2 files changed, 76 insertions(+), 59 deletions(-) diff --git a/apps/files/ajax/scan.php b/apps/files/ajax/scan.php index 91b20fa836..53ae4f5ff0 100644 --- a/apps/files/ajax/scan.php +++ b/apps/files/ajax/scan.php @@ -1,45 +1,70 @@ send('success', true); +OC_Hook::connect('\OC\Files\Cache\Scanner', 'scan_folder', 'ScanListener', 'folder'); +OC_Hook::connect('\OC\Files\Cache\Scanner', 'scan_file', 'ScanListener', 'file'); + +$absolutePath = \OC\Files\Filesystem::getView()->getAbsolutePath($dir); + +$mountPoints = \OC\Files\Filesystem::getMountPoints($absolutePath); +$mountPoints[] = \OC\Files\Filesystem::getMountPoint($absolutePath); +$mountPoints = array_reverse($mountPoints); //start with the mount point of $dir + +foreach ($mountPoints as $mountPoint) { + $storage = \OC\Files\Filesystem::getStorage($mountPoint); + error_log('scanning mp '.$mountPoint); + ScanListener::$mountPoints[$storage->getId()] = $mountPoint; + $scanner = $storage->getScanner(); + if ($force) { + $scanner->scan(''); } else { - OCP\JSON::success(array('data'=>array('done'=>true))); - exit; - } -} else { - if($checkOnly) { - OCP\JSON::success(array('data'=>array('done'=>false))); - exit; - } - if(isset($eventSource)) { - $eventSource->send('success', false); - } else { - exit; + $scanner->backgroundScan(); } } + +$eventSource->send('done', ScanListener::$fileCount); $eventSource->close(); + +class ScanListener { + + static public $fileCount = 0; + static public $lastCount = 0; + + /** + * @var \OC\Files\View $view + */ + static public $view; + + /** + * @var array $mountPoints map storage ids to mountpoints + */ + static public $mountPoints = array(); + + /** + * @var \OC_EventSource event source to pass events to + */ + static public $eventSource; + + static function folder($params) { + $internalPath = $params['path']; + $mountPoint = self::$mountPoints[$params['storage']]; + $path = self::$view->getRelativePath($mountPoint . $internalPath); + self::$eventSource->send('folder', $path); + } + + static function file() { + self::$fileCount++; + if (self::$fileCount > self::$lastCount + 20) { //send a count update every 20 files + self::$lastCount = self::$fileCount; + self::$eventSource->send('count', self::$fileCount); + } + } +} diff --git a/apps/files/js/files.js b/apps/files/js/files.js index bb80841055..f95bfa2bf8 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -602,12 +602,8 @@ $(document).ready(function() { }); }); - //check if we need to scan the filesystem - $.get(OC.filePath('files','ajax','scan.php'),{checkonly:'true'}, function(response) { - if(response.data.done){ - scanFiles(); - } - }, "json"); + //do a background scan if needed + scanFiles(); var lastWidth = 0; var breadcrumbs = []; @@ -676,27 +672,23 @@ $(document).ready(function() { resizeBreadcrumbs(true); }); -function scanFiles(force,dir){ +function scanFiles(force, dir){ if(!dir){ - dir=''; + dir = ''; } - force=!!force; //cast to bool - scanFiles.scanning=true; - $('#scanning-message').show(); - $('#fileList').remove(); - var scannerEventSource=new OC.EventSource(OC.filePath('files','ajax','scan.php'),{force:force,dir:dir}); - scanFiles.cancel=scannerEventSource.close.bind(scannerEventSource); - scannerEventSource.listen('scanning',function(data){ - $('#scan-count').text(t('files', '{count} files scanned', {count: data.count})); - $('#scan-current').text(data.file+'/'); + force = !!force; //cast to bool + scanFiles.scanning = true; + var scannerEventSource = new OC.EventSource(OC.filePath('files','ajax','scan.php'),{force:force,dir:dir}); + scanFiles.cancel = scannerEventSource.close.bind(scannerEventSource); + scannerEventSource.listen('count',function(count){ + console.log(count + 'files scanned') }); - scannerEventSource.listen('success',function(success){ + scannerEventSource.listen('folder',function(path){ + console.log('now scanning ' + path) + }); + scannerEventSource.listen('done',function(count){ scanFiles.scanning=false; - if(success){ - window.location.reload(); - }else{ - alert(t('files', 'error while scanning')); - } + console.log('done after ' + count + 'files'); }); } scanFiles.scanning=false; From c47bf9bbcefb0640c24ab0aa6ee79f4c52222b45 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Sat, 24 Nov 2012 16:42:54 -0500 Subject: [PATCH 099/347] Add checks for storage object --- apps/files/ajax/scan.php | 15 +-- lib/files/view.php | 221 +++++++++++++++++++++------------------ 2 files changed, 127 insertions(+), 109 deletions(-) diff --git a/apps/files/ajax/scan.php b/apps/files/ajax/scan.php index 53ae4f5ff0..391b98608b 100644 --- a/apps/files/ajax/scan.php +++ b/apps/files/ajax/scan.php @@ -20,13 +20,14 @@ $mountPoints = array_reverse($mountPoints); //start with the mount point of $dir foreach ($mountPoints as $mountPoint) { $storage = \OC\Files\Filesystem::getStorage($mountPoint); - error_log('scanning mp '.$mountPoint); - ScanListener::$mountPoints[$storage->getId()] = $mountPoint; - $scanner = $storage->getScanner(); - if ($force) { - $scanner->scan(''); - } else { - $scanner->backgroundScan(); + if ($storage) { + ScanListener::$mountPoints[$storage->getId()] = $mountPoint; + $scanner = $storage->getScanner(); + if ($force) { + $scanner->scan(''); + } else { + $scanner->backgroundScan(); + } } } diff --git a/lib/files/view.php b/lib/files/view.php index e516a4fed6..468808566a 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -671,39 +671,41 @@ class View { * - versioned */ public function getFileInfo($path) { + $data = array(); $path = Filesystem::normalizePath($this->fakeRoot . '/' . $path); /** * @var \OC\Files\Storage\Storage $storage * @var string $internalPath */ list($storage, $internalPath) = Filesystem::resolvePath($path); - $cache = $storage->getCache(); + if ($storage) { + $cache = $storage->getCache(); - if (!$cache->inCache($internalPath)) { - $scanner = $storage->getScanner(); - $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW); - } else { - $watcher = new \OC\Files\Cache\Watcher($storage); - $watcher->checkUpdate($internalPath); - } - - $data = $cache->get($internalPath); - - if ($data['mimetype'] === 'httpd/unix-directory') { - //add the sizes of other mountpoints to the folder - $mountPoints = Filesystem::getMountPoints($path); - foreach ($mountPoints as $mountPoint) { - $subStorage = Filesystem::getStorage($mountPoint); - $subCache = $subStorage->getCache(); - $rootEntry = $subCache->get(''); - - $data['size'] += $rootEntry['size']; + if (!$cache->inCache($internalPath)) { + $scanner = $storage->getScanner(); + $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW); + } else { + $watcher = new \OC\Files\Cache\Watcher($storage); + $watcher->checkUpdate($internalPath); } + + $data = $cache->get($internalPath); + + if ($data['mimetype'] === 'httpd/unix-directory') { + //add the sizes of other mountpoints to the folder + $mountPoints = Filesystem::getMountPoints($path); + foreach ($mountPoints as $mountPoint) { + $subStorage = Filesystem::getStorage($mountPoint); + $subCache = $subStorage->getCache(); + $rootEntry = $subCache->get(''); + + $data['size'] += $rootEntry['size']; + } + } + + $permissionsCache = $storage->getPermissionsCache(); + $data['permissions'] = $permissionsCache->get($data['fileid'], \OC_User::getUser()); } - - $permissionsCache = $storage->getPermissionsCache(); - $data['permissions'] = $permissionsCache->get($data['fileid'], \OC_User::getUser()); - return $data; } @@ -714,75 +716,79 @@ class View { * @return array */ public function getDirectoryContent($directory, $mimetype_filter = '') { + $result = array(); $path = Filesystem::normalizePath($this->fakeRoot . '/' . $directory); /** * @var \OC\Files\Storage\Storage $storage * @var string $internalPath */ list($storage, $internalPath) = Filesystem::resolvePath($path); - $cache = $storage->getCache(); + if ($storage) { + $cache = $storage->getCache(); - if (!$cache->inCache($internalPath)) { - $scanner = $storage->getScanner(); - $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW); - } else { - $watcher = new \OC\Files\Cache\Watcher($storage); - $watcher->checkUpdate($internalPath); - } - - $files = $cache->getFolderContents($internalPath); //TODO: mimetype_filter - - //add a folder for any mountpoint in this directory and add the sizes of other mountpoints to the folders - $mountPoints = Filesystem::getMountPoints($path); - $dirLength = strlen($path); - foreach ($mountPoints as $mountPoint) { - $subStorage = Filesystem::getStorage($mountPoint); - $subCache = $subStorage->getCache(); - $rootEntry = $subCache->get(''); - - $relativePath = trim(substr($mountPoint, $dirLength), '/'); - if ($pos = strpos($relativePath, '/')) { //mountpoint inside subfolder add size to the correct folder - $entryName = substr($relativePath, 0, $pos); - foreach ($files as &$entry) { - if ($entry['name'] === $entryName) { - $entry['size'] += $rootEntry['size']; - } - } - } else { //mountpoint in this folder, add an entry for it - $rootEntry['name'] = $relativePath; - $files[] = $rootEntry; + if (!$cache->inCache($internalPath)) { + $scanner = $storage->getScanner(); + $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW); + } else { + $watcher = new \OC\Files\Cache\Watcher($storage); + $watcher->checkUpdate($internalPath); } - } - $ids = array(); + $files = $cache->getFolderContents($internalPath); //TODO: mimetype_filter - foreach ($files as $i => $file) { - $files[$i]['type'] = $file['mimetype'] === 'httpd/unix-directory' ? 'dir' : 'file'; - $ids[] = $file['fileid']; - } - $permissionsCache = $storage->getPermissionsCache(); + //add a folder for any mountpoint in this directory and add the sizes of other mountpoints to the folders + $mountPoints = Filesystem::getMountPoints($path); + $dirLength = strlen($path); + foreach ($mountPoints as $mountPoint) { + $subStorage = Filesystem::getStorage($mountPoint); + if ($subStorage) { + $subCache = $subStorage->getCache(); + $rootEntry = $subCache->get(''); - $permissions = $permissionsCache->getMultiple($ids, \OC_User::getUser()); - foreach ($files as $i => $file) { - $files[$i]['permissions'] = $permissions[$file['fileid']]; - } - - if ($mimetype_filter) { - foreach ($files as $file) { - if (strpos($mimetype_filter, '/')) { - if ($file['mimetype'] === $mimetype_filter) { - $result[] = $file; - } - } else { - if ($file['mimepart'] === $mimetype_filter) { - $result[] = $file; + $relativePath = trim(substr($mountPoint, $dirLength), '/'); + if ($pos = strpos($relativePath, '/')) { //mountpoint inside subfolder add size to the correct folder + $entryName = substr($relativePath, 0, $pos); + foreach ($files as &$entry) { + if ($entry['name'] === $entryName) { + $entry['size'] += $rootEntry['size']; + } + } + } else { //mountpoint in this folder, add an entry for it + $rootEntry['name'] = $relativePath; + $files[] = $rootEntry; } } } - } else { - $result = $files; - } + $ids = array(); + + foreach ($files as $i => $file) { + $files[$i]['type'] = $file['mimetype'] === 'httpd/unix-directory' ? 'dir' : 'file'; + $ids[] = $file['fileid']; + } + $permissionsCache = $storage->getPermissionsCache(); + + $permissions = $permissionsCache->getMultiple($ids, \OC_User::getUser()); + foreach ($files as $i => $file) { + $files[$i]['permissions'] = $permissions[$file['fileid']]; + } + + if ($mimetype_filter) { + foreach ($files as $file) { + if (strpos($mimetype_filter, '/')) { + if ($file['mimetype'] === $mimetype_filter) { + $result[] = $file; + } + } else { + if ($file['mimepart'] === $mimetype_filter) { + $result[] = $file; + } + } + } + } else { + $result = $files; + } + } return $result; } @@ -802,14 +808,18 @@ class View { * @var string $internalPath */ list($storage, $internalPath) = Filesystem::resolvePath($path); - $cache = $storage->getCache(); + if ($storage) { + $cache = $storage->getCache(); - if (!$cache->inCache($internalPath)) { - $scanner = $storage->getScanner(); - $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW); + if (!$cache->inCache($internalPath)) { + $scanner = $storage->getScanner(); + $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW); + } + + return $cache->put($internalPath, $data); + } else { + return -1; } - - return $cache->put($internalPath, $data); } /** @@ -843,29 +853,32 @@ class View { $mountPoint = Filesystem::getMountPoint($this->fakeRoot); $storage = Filesystem::getStorage($mountPoint); - $cache = $storage->getCache(); - - $results = $cache->$method($query); - foreach ($results as $result) { - if (substr($mountPoint . $result['path'], 0, $rootLength) === $this->fakeRoot) { - $result['path'] = substr($mountPoint . $result['path'], $rootLength); - $files[] = $result; - } - } - - $mountPoints = Filesystem::getMountPoints($this->fakeRoot); - foreach ($mountPoints as $mountPoint) { - $storage = Filesystem::getStorage($mountPoint); + if ($storage) { $cache = $storage->getCache(); - $relativeMountPoint = substr($mountPoint, $rootLength); $results = $cache->$method($query); foreach ($results as $result) { - $result['path'] = $relativeMountPoint . $result['path']; - $files[] = $result; + if (substr($mountPoint . $result['path'], 0, $rootLength) === $this->fakeRoot) { + $result['path'] = substr($mountPoint . $result['path'], $rootLength); + $files[] = $result; + } + } + + $mountPoints = Filesystem::getMountPoints($this->fakeRoot); + foreach ($mountPoints as $mountPoint) { + $storage = Filesystem::getStorage($mountPoint); + if ($storage) { + $cache = $storage->getCache(); + + $relativeMountPoint = substr($mountPoint, $rootLength); + $results = $cache->$method($query); + foreach ($results as $result) { + $result['path'] = $relativeMountPoint . $result['path']; + $files[] = $result; + } + } } } - return $files; } @@ -881,6 +894,10 @@ class View { * @var string $internalPath */ list($storage, $internalPath) = $this->resolvePath($path); - return $storage->getETag($internalPath); + if ($storage) { + return $storage->getETag($internalPath); + } else { + return null; + } } } From d3e37fa157faa59598e92a9aa02c6bbf818b60e0 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 23 Nov 2012 16:23:52 +0100 Subject: [PATCH 100/347] remove fileatime from common storage backend --- lib/fileproxy.php | 2 +- lib/files/storage/common.php | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/fileproxy.php b/lib/fileproxy.php index 2f81bde64a..52ec79b4bd 100644 --- a/lib/fileproxy.php +++ b/lib/fileproxy.php @@ -36,7 +36,7 @@ * The return value of the post-proxy will be used as the new result of the operation * The operations that have a post-proxy are: * file_get_contents, is_file, is_dir, file_exists, stat, is_readable, - * is_writable, fileatime, filemtime, filectime, file_get_contents, + * is_writable, filemtime, filectime, file_get_contents, * getMimeType, hash, fopen, free_space and search */ diff --git a/lib/files/storage/common.php b/lib/files/storage/common.php index 9978cea571..c891d0c3ad 100644 --- a/lib/files/storage/common.php +++ b/lib/files/storage/common.php @@ -69,10 +69,6 @@ abstract class Common implements \OC\Files\Storage\Storage { $stat = $this->stat($path); return $stat['mtime']; } - public function fileatime($path) { - $stat = $this->stat($path); - return $stat['atime']; - } public function file_get_contents($path) { $handle = $this->fopen($path, "r"); if(!$handle) { From 709aacfa0fef29692bff231f09625db5ba0bef6f Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sat, 24 Nov 2012 23:41:39 +0100 Subject: [PATCH 101/347] change behaviour of Filesystem::getMountPoint when a mountpoint is passed as path without trailing slash --- lib/files/filesystem.php | 8 +------- tests/lib/files/filesystem.php | 2 +- tests/lib/files/view.php | 12 ++++++++++++ 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php index 9e8ce3ec18..4e3eb1989b 100644 --- a/lib/files/filesystem.php +++ b/lib/files/filesystem.php @@ -144,13 +144,7 @@ class Filesystem { */ static public function getMountPoint($path) { \OC_Hook::emit(self::CLASSNAME, 'get_mountpoint', array('path' => $path)); - if (!$path) { - $path = '/'; - } - if ($path[0] !== '/') { - $path = '/' . $path; - } - $path = str_replace('//', '/', $path); + $path = self::normalizePath($path) . '/'; $foundMountPoint = ''; $mountPoints = array_keys(self::$mounts); foreach ($mountPoints as $mountpoint) { diff --git a/tests/lib/files/filesystem.php b/tests/lib/files/filesystem.php index 363426511b..5837093fdd 100644 --- a/tests/lib/files/filesystem.php +++ b/tests/lib/files/filesystem.php @@ -60,7 +60,7 @@ class Filesystem extends \PHPUnit_Framework_TestCase { $this->assertEquals('/',\OC\Files\Filesystem::getMountPoint('/')); $this->assertEquals('/some/',\OC\Files\Filesystem::getMountPoint('/some/folder')); $this->assertEquals('/some/',\OC\Files\Filesystem::getMountPoint('/some/')); - $this->assertEquals('/',\OC\Files\Filesystem::getMountPoint('/some')); + $this->assertEquals('/some/',\OC\Files\Filesystem::getMountPoint('/some')); list( , $internalPath)=\OC\Files\Filesystem::resolvePath('/some/folder'); $this->assertEquals('folder',$internalPath); } diff --git a/tests/lib/files/view.php b/tests/lib/files/view.php index ecfc803dc2..6f8d29c25b 100644 --- a/tests/lib/files/view.php +++ b/tests/lib/files/view.php @@ -71,6 +71,18 @@ class View extends \PHPUnit_Framework_TestCase { $this->assertEquals($storageSize + $textSize, $folderData[2]['size']); $this->assertEquals($storageSize, $folderData[3]['size']); + $folderData = $rootView->getDirectoryContent('/substorage'); + /** + * expected entries: + * foo.png + * foo.txt + * folder + */ + $this->assertEquals(3, count($folderData)); + $this->assertEquals('foo.png', $folderData[0]['name']); + $this->assertEquals('foo.txt', $folderData[1]['name']); + $this->assertEquals('folder', $folderData[2]['name']); + $folderView = new \OC\Files\View('/folder'); $this->assertEquals($rootView->getFileInfo('/folder'), $folderView->getFileInfo('/')); From cc5d8e56098189f49fbd68c598c11be2b8354846 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Sat, 24 Nov 2012 20:29:57 -0500 Subject: [PATCH 102/347] Check if data variable in scanner isn't null before using it --- lib/files/cache/scanner.php | 42 ++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/lib/files/cache/scanner.php b/lib/files/cache/scanner.php index 3c83b6528a..9ee509bb13 100644 --- a/lib/files/cache/scanner.php +++ b/lib/files/cache/scanner.php @@ -70,17 +70,19 @@ class Scanner { public function scanFile($file) { \OC_Hook::emit('\OC\Files\Cache\Scanner', 'scan_file', array('path' => $file, 'storage' => $this->storageId)); $data = $this->getData($file); - if ($file !== '') { - $parent = dirname($file); - if ($parent === '.') { - $parent = ''; - } - if (!$this->cache->inCache($parent)) { - $this->scanFile($parent); + if ($data) { + if ($file !== '') { + $parent = dirname($file); + if ($parent === '.') { + $parent = ''; + } + if (!$this->cache->inCache($parent)) { + $this->scanFile($parent); + } } + $id = $this->cache->put($file, $data); + $this->permissionsCache->set($id, \OC_User::getUser(), $data['permissions']); } - $id = $this->cache->put($file, $data); - $this->permissionsCache->set($id, \OC_User::getUser(), $data['permissions']); return $data; } @@ -101,17 +103,19 @@ class Scanner { if ($file !== '.' and $file !== '..') { $child = ($path !== '') ? $path . '/' . $file : $file; $data = $this->scanFile($child); - if ($data['mimetype'] === 'httpd/unix-directory') { - if ($recursive === self::SCAN_RECURSIVE) { - $data['size'] = $this->scan($child, self::SCAN_RECURSIVE); - } else { - $data['size'] = -1; + if ($data) { + if ($data['mimetype'] === 'httpd/unix-directory') { + if ($recursive === self::SCAN_RECURSIVE) { + $data['size'] = $this->scan($child, self::SCAN_RECURSIVE); + } else { + $data['size'] = -1; + } + } + if ($data['size'] === -1) { + $size = -1; + } elseif ($size !== -1) { + $size += $data['size']; } - } - if ($data['size'] === -1) { - $size = -1; - } elseif ($size !== -1) { - $size += $data['size']; } } } From 0cfef83ed98951f852b07ce61dc10ee2e8266445 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sun, 25 Nov 2012 16:08:35 +0100 Subject: [PATCH 103/347] sort output of getFolderContent by name --- lib/files/cache/cache.php | 2 +- tests/lib/files/view.php | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index 6b93673097..bc52f21d91 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -87,7 +87,7 @@ class Cache { if ($fileId > -1) { $query = \OC_DB::prepare( 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted` - FROM `*PREFIX*filecache` WHERE parent = ? ORDER BY `fileid` ASC'); + FROM `*PREFIX*filecache` WHERE parent = ? ORDER BY `name` ASC'); $result = $query->execute(array($fileId)); return $result->fetchAll(); } else { diff --git a/tests/lib/files/view.php b/tests/lib/files/view.php index 6f8d29c25b..ed08dcc114 100644 --- a/tests/lib/files/view.php +++ b/tests/lib/files/view.php @@ -55,33 +55,33 @@ class View extends \PHPUnit_Framework_TestCase { $folderData = $rootView->getDirectoryContent('/'); /** * expected entries: + * folder * foo.png * foo.txt - * folder * substorage */ $this->assertEquals(4, count($folderData)); - $this->assertEquals('foo.png', $folderData[0]['name']); - $this->assertEquals('foo.txt', $folderData[1]['name']); - $this->assertEquals('folder', $folderData[2]['name']); + $this->assertEquals('folder', $folderData[0]['name']); + $this->assertEquals('foo.png', $folderData[1]['name']); + $this->assertEquals('foo.txt', $folderData[2]['name']); $this->assertEquals('substorage', $folderData[3]['name']); - $this->assertEquals($imageSize, $folderData[0]['size']); - $this->assertEquals($textSize, $folderData[1]['size']); - $this->assertEquals($storageSize + $textSize, $folderData[2]['size']); + $this->assertEquals($storageSize + $textSize, $folderData[0]['size']); + $this->assertEquals($imageSize, $folderData[1]['size']); + $this->assertEquals($textSize, $folderData[2]['size']); $this->assertEquals($storageSize, $folderData[3]['size']); $folderData = $rootView->getDirectoryContent('/substorage'); /** * expected entries: + * folder * foo.png * foo.txt - * folder */ $this->assertEquals(3, count($folderData)); - $this->assertEquals('foo.png', $folderData[0]['name']); - $this->assertEquals('foo.txt', $folderData[1]['name']); - $this->assertEquals('folder', $folderData[2]['name']); + $this->assertEquals('folder', $folderData[0]['name']); + $this->assertEquals('foo.png', $folderData[1]['name']); + $this->assertEquals('foo.txt', $folderData[2]['name']); $folderView = new \OC\Files\View('/folder'); $this->assertEquals($rootView->getFileInfo('/folder'), $folderView->getFileInfo('/')); From a609992a75d1dad15398f55e22ad2244c78650dc Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sun, 25 Nov 2012 16:30:57 +0100 Subject: [PATCH 104/347] better check if we are passing a fileid to Cache::get --- lib/files/cache/cache.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index bc52f21d91..5aeb6f25af 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -47,7 +47,7 @@ class Cache { * @return array */ public function get($file) { - if (is_string($file)) { + if (is_string($file) or $file == '') { $where = 'WHERE `storage` = ? AND `path_hash` = ?'; $params = array($this->storageId, md5($file)); } else { //file id From dbbb357f62c1ba86bdff0fbe63e4cea9bc2977fc Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 30 Nov 2012 01:41:30 +0100 Subject: [PATCH 105/347] add upgrade path from old cache to preserve file id's --- apps/files/appinfo/app.php | 14 +++++++++-- apps/files/appinfo/version | 2 +- lib/files/cache/upgrade.php | 50 +++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 lib/files/cache/upgrade.php diff --git a/apps/files/appinfo/app.php b/apps/files/appinfo/app.php index b431ddfec0..fb64a80ec0 100644 --- a/apps/files/appinfo/app.php +++ b/apps/files/appinfo/app.php @@ -1,8 +1,18 @@ "files_index", "order" => 0, "href" => OCP\Util::linkTo( "files", "index.php" ), "icon" => OCP\Util::imagePath( "core", "places/home.svg" ), "name" => $l->t("Files") )); +OCP\App::addNavigationEntry(array("id" => "files_index", "order" => 0, "href" => OCP\Util::linkTo("files", "index.php"), "icon" => OCP\Util::imagePath("core", "places/home.svg"), "name" => $l->t("Files"))); OC_Search::registerProvider('OC_Search_Provider_File'); + +if (OC_User::isLoggedIn()) { + // update OC4.5 filecache to OC5 filecache, can't do this in update.php since it needs to happen for each user individually + $cacheVersion = (int)OCP\Config::getUserValue(OC_User::getUser(), 'files', 'cache_version', 4); + if ($cacheVersion < 5) { + \OC_Log::write('files', 'updating filecache to 5.0 for user ' . OC_User::getUser(), \OC_Log::INFO); + \OC\Files\Cache\Upgrade::upgrade(); + OCP\Config::setUserValue(OC_User::getUser(), 'files', 'cache_version', 5); + } +} diff --git a/apps/files/appinfo/version b/apps/files/appinfo/version index 0664a8fd29..2bf1ca5f54 100644 --- a/apps/files/appinfo/version +++ b/apps/files/appinfo/version @@ -1 +1 @@ -1.1.6 +1.1.7 diff --git a/lib/files/cache/upgrade.php b/lib/files/cache/upgrade.php new file mode 100644 index 0000000000..5be04b4207 --- /dev/null +++ b/lib/files/cache/upgrade.php @@ -0,0 +1,50 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Files\Cache; + +class Upgrade { + static $permissionsCaches = array(); + + static function upgrade() { + $insertQuery = \OC_DB::prepare('INSERT INTO `*PREFIX*filecache`( `fileid`, `storage`, `path`, `path_hash`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted` ) + VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'); + + $oldEntriesQuery = \OC_DB::prepare('SELECT * FROM `*PREFIX*fscache` ORDER BY `id` ASC'); //sort ascending to ensure the parent gets inserted before a child + $oldEntriesResult = $oldEntriesQuery->execute(); + + while ($row = $oldEntriesResult->fetchRow()) { + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($row['path']); + /** + * @var \OC\Files\Storage\Storage $storage + * @var string $internalPath; + */ + $pathHash = md5($internalPath); + $storageId = $storage->getId(); + $parentId = ($internalPath === '') ? -1 : $row['parent']; + + $insertQuery->execute(array($row['id'], $storageId, $internalPath, $pathHash, $parentId, $row['name'], $row['mimetype'], $row['mimepart'], $row['size'], $row['mtime'], $row['encrypted'])); + + $permissions = ($row['writable']) ? \OCP\PERMISSION_ALL : \OCP\PERMISSION_READ; + $permissionsCache = self::getPermissionsCache($storage); + $permissionsCache->set($row['id'], $row['user'], $permissions); + } + } + + /** + * @param \OC\Files\Storage\Storage $storage + * @return Permissions + */ + static function getPermissionsCache($storage) { + $storageId = $storage->getId(); + if (!isset(self::$permissionsCaches[$storageId])) { + self::$permissionsCaches[$storageId] = $storage->getPermissionsCache(); + } + return self::$permissionsCaches[$storageId]; + } +} From 702444b2422326388e494091e815fd3d9b03cc87 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sat, 1 Dec 2012 00:59:49 +0100 Subject: [PATCH 106/347] fail gracefully when no old filecache is present during upgrade --- lib/files/cache/upgrade.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/files/cache/upgrade.php b/lib/files/cache/upgrade.php index 5be04b4207..899f6f7ac8 100644 --- a/lib/files/cache/upgrade.php +++ b/lib/files/cache/upgrade.php @@ -16,7 +16,14 @@ class Upgrade { VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'); $oldEntriesQuery = \OC_DB::prepare('SELECT * FROM `*PREFIX*fscache` ORDER BY `id` ASC'); //sort ascending to ensure the parent gets inserted before a child - $oldEntriesResult = $oldEntriesQuery->execute(); + try{ + $oldEntriesResult = $oldEntriesQuery->execute(); + }catch(\Exception $e){ + return; + } + if(!$oldEntriesResult){ + return; + } while ($row = $oldEntriesResult->fetchRow()) { list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($row['path']); From 01eb5d2790638ab836adc95a9726b6a1003562b9 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sun, 2 Dec 2012 03:43:51 +0100 Subject: [PATCH 107/347] fix some edge cases while scanning the root of a storage --- lib/files/cache/scanner.php | 4 ++-- lib/files/filesystem.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/files/cache/scanner.php b/lib/files/cache/scanner.php index 9ee509bb13..4c0ec9617f 100644 --- a/lib/files/cache/scanner.php +++ b/lib/files/cache/scanner.php @@ -71,7 +71,7 @@ class Scanner { \OC_Hook::emit('\OC\Files\Cache\Scanner', 'scan_file', array('path' => $file, 'storage' => $this->storageId)); $data = $this->getData($file); if ($data) { - if ($file !== '') { + if ($file) { $parent = dirname($file); if ($parent === '.') { $parent = ''; @@ -101,7 +101,7 @@ class Scanner { if ($dh = $this->storage->opendir($path)) { while ($file = readdir($dh)) { if ($file !== '.' and $file !== '..') { - $child = ($path !== '') ? $path . '/' . $file : $file; + $child = ($path) ? $path . '/' . $file : $file; $data = $this->scanFile($child); if ($data) { if ($data['mimetype'] === 'httpd/unix-directory') { diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php index 4e3eb1989b..724c83b361 100644 --- a/lib/files/filesystem.php +++ b/lib/files/filesystem.php @@ -143,8 +143,8 @@ class Filesystem { * @return string */ static public function getMountPoint($path) { - \OC_Hook::emit(self::CLASSNAME, 'get_mountpoint', array('path' => $path)); $path = self::normalizePath($path) . '/'; + \OC_Hook::emit(self::CLASSNAME, 'get_mountpoint', array('path' => $path)); $foundMountPoint = ''; $mountPoints = array_keys(self::$mounts); foreach ($mountPoints as $mountpoint) { @@ -205,7 +205,7 @@ class Filesystem { $mountpoint = self::getMountPoint($path); if ($mountpoint) { $storage = self::getStorage($mountpoint); - if ($mountpoint === $path) { + if ($mountpoint === $path or $mountpoint . '/' === $path) { $internalPath = ''; } else { $internalPath = substr($path, strlen($mountpoint)); From 18663100d9f68400fba1fc344874aacb62bb4659 Mon Sep 17 00:00:00 2001 From: Thomas Mueller Date: Sun, 2 Dec 2012 12:12:20 +0100 Subject: [PATCH 108/347] fixing syntax error + reformat the code --- apps/files_sharing/public.php | 358 ++++++++++++++++++---------------- 1 file changed, 185 insertions(+), 173 deletions(-) diff --git a/apps/files_sharing/public.php b/apps/files_sharing/public.php index fcf7063955..27d2b9dfa4 100644 --- a/apps/files_sharing/public.php +++ b/apps/files_sharing/public.php @@ -9,10 +9,10 @@ if (isset($_GET['token'])) { unset($_GET['file']); $qry = \OC_DB::prepare('SELECT `source` FROM `*PREFIX*sharing` WHERE `target` = ? LIMIT 1'); $filepath = $qry->execute(array($_GET['token']))->fetchOne(); - if(isset($filepath)) { + if (isset($filepath)) { $rootView = new \OC\Files\View(''); $info = $rootView->getFileInfo($filepath, ''); - if(strtolower($info['mimetype']) == 'httpd/unix-directory') { + if (strtolower($info['mimetype']) == 'httpd/unix-directory') { $_GET['dir'] = $filepath; } else { $_GET['file'] = $filepath; @@ -27,7 +27,7 @@ function getID($path) { if (substr(\OC\Files\Filesystem::getMountPoint($path), -7, 6) == "Shared") { $path_parts = explode('/', $path, 5); $user = $path_parts[1]; - $intPath = '/'.$path_parts[4]; + $intPath = '/' . $path_parts[4]; $query = \OC_DB::prepare('SELECT `item_source` FROM `*PREFIX*share` WHERE `uid_owner` = ? AND `file_target` = ? '); $result = $query->execute(array($user, $intPath)); $row = $result->fetchRow(); @@ -40,11 +40,12 @@ function getID($path) { return $fileSource; } + // Enf of backward compatibility /** * lookup file path and owner by fetching it from the fscache - * needed becaus OC_FileCache::getPath($id, $user) already requires the user + * needed because OC_FileCache::getPath($id, $user) already requires the user * @param int $id * @return array */ @@ -64,60 +65,62 @@ if (isset($_GET['t'])) { $type = $linkItem['item_type']; $fileSource = $linkItem['file_source']; $shareOwner = $linkItem['uid_owner']; - - if (OCP\User::userExists($shareOwner) && $fileSource != -1 ) { - + + if (OCP\User::userExists($shareOwner) && $fileSource != -1) { + $pathAndUser = getPathAndUser($linkItem['file_source']); $fileOwner = $pathAndUser['user']; - + //if this is a reshare check the file owner also exists - if ($shareOwner != $fileOwner && ! OCP\User::userExists($fileOwner)) { - OCP\Util::writeLog('share', 'original file owner '.$fileOwner.' does not exist for share '.$linkItem['id'], \OCP\Util::ERROR); - header('HTTP/1.0 404 Not Found'); - $tmpl = new OCP\Template('', '404', 'guest'); - $tmpl->printPage(); - exit(); + if ($shareOwner != $fileOwner && !OCP\User::userExists($fileOwner)) { + OCP\Util::writeLog('share', 'original file owner ' . $fileOwner . ' does not exist for share ' . $linkItem['id'], \OCP\Util::ERROR); + header('HTTP/1.0 404 Not Found'); + $tmpl = new OCP\Template('', '404', 'guest'); + $tmpl->printPage(); + exit(); } - + //mount filesystem of file owner OC_Util::setupFS($fileOwner); } } -} else if (isset($_GET['file']) || isset($_GET['dir'])) { - OCP\Util::writeLog('share', 'Missing token, trying fallback file/dir links', \OCP\Util::DEBUG); - if (isset($_GET['dir'])) { - $type = 'folder'; - $path = $_GET['dir']; - if(strlen($path)>1 and substr($path, -1, 1)==='/') { - $path=substr($path, 0, -1); +} else { + if (isset($_GET['file']) || isset($_GET['dir'])) { + OCP\Util::writeLog('share', 'Missing token, trying fallback file/dir links', \OCP\Util::DEBUG); + if (isset($_GET['dir'])) { + $type = 'folder'; + $path = $_GET['dir']; + if (strlen($path) > 1 and substr($path, -1, 1) === '/') { + $path = substr($path, 0, -1); + } + $baseDir = $path; + $dir = $baseDir; + } else { + $type = 'file'; + $path = $_GET['file']; + if (strlen($path) > 1 and substr($path, -1, 1) === '/') { + $path = substr($path, 0, -1); + } } - $baseDir = $path; - $dir = $baseDir; - } else { - $type = 'file'; - $path = $_GET['file']; - if(strlen($path)>1 and substr($path, -1, 1)==='/') { - $path=substr($path, 0, -1); - } - } - $shareOwner = substr($path, 1, strpos($path, '/', 1) - 1); - - if (OCP\User::userExists($shareOwner)) { - OC_Util::setupFS($shareOwner); - $fileSource = getId($path); - if ($fileSource != -1 ) { - $linkItem = OCP\Share::getItemSharedWithByLink($type, $fileSource, $shareOwner); - $pathAndUser['path'] = $path; - $path_parts = explode('/', $path, 5); - $pathAndUser['user'] = $path_parts[1]; - $fileOwner = $path_parts[1]; + $shareOwner = substr($path, 1, strpos($path, '/', 1) - 1); + + if (OCP\User::userExists($shareOwner)) { + OC_Util::setupFS($shareOwner); + $fileSource = getId($path); + if ($fileSource != -1) { + $linkItem = OCP\Share::getItemSharedWithByLink($type, $fileSource, $shareOwner); + $pathAndUser['path'] = $path; + $path_parts = explode('/', $path, 5); + $pathAndUser['user'] = $path_parts[1]; + $fileOwner = $path_parts[1]; + } } } } if ($linkItem) { if (!isset($linkItem['item_type'])) { - OCP\Util::writeLog('share', 'No item type set for share id: '.$linkItem['id'], \OCP\Util::ERROR); + OCP\Util::writeLog('share', 'No item type set for share id: ' . $linkItem['id'], \OCP\Util::ERROR); header('HTTP/1.0 404 Not Found'); $tmpl = new OCP\Template('', '404', 'guest'); $tmpl->printPage(); @@ -125,11 +128,13 @@ if ($linkItem) { } if (isset($linkItem['share_with'])) { // Authenticate share_with - $url = OCP\Util::linkToPublic('files').'&t='.$token; + $url = OCP\Util::linkToPublic('files') . '&t=' . $token; if (isset($_GET['file'])) { - $url .= '&file='.urlencode($_GET['file']); - } else if (isset($_GET['dir'])) { - $url .= '&dir='.urlencode($_GET['dir']); + $url .= '&file=' . urlencode($_GET['file']); + } else { + if (isset($_GET['dir'])) { + $url .= '&dir=' . urlencode($_GET['dir']); + } } if (isset($_POST['password'])) { $password = $_POST['password']; @@ -137,7 +142,7 @@ if ($linkItem) { // Check Password $forcePortable = (CRYPT_BLOWFISH != 1); $hasher = new PasswordHash(8, $forcePortable); - if (!($hasher->CheckPassword($password.OC_Config::getValue('passwordsalt', ''), $linkItem['share_with']))) { + if (!($hasher->CheckPassword($password . OC_Config::getValue('passwordsalt', ''), $linkItem['share_with']))) { $tmpl = new OCP\Template('files_sharing', 'authenticate', 'guest'); $tmpl->assign('URL', $url); $tmpl->assign('error', true); @@ -148,28 +153,30 @@ if ($linkItem) { $_SESSION['public_link_authenticated'] = $linkItem['id']; } } else { - OCP\Util::writeLog('share', 'Unknown share type '.$linkItem['share_type'].' for share id '.$linkItem['id'], \OCP\Util::ERROR); + OCP\Util::writeLog('share', 'Unknown share type ' . $linkItem['share_type'] . ' for share id ' . $linkItem['id'], \OCP\Util::ERROR); header('HTTP/1.0 404 Not Found'); $tmpl = new OCP\Template('', '404', 'guest'); $tmpl->printPage(); exit(); } - // Check if item id is set in session - } else if (!isset($_SESSION['public_link_authenticated']) || $_SESSION['public_link_authenticated'] !== $linkItem['id']) { - // Prompt for password - $tmpl = new OCP\Template('files_sharing', 'authenticate', 'guest'); - $tmpl->assign('URL', $url); - $tmpl->printPage(); - exit(); + // Check if item id is set in session + } else { + if (!isset($_SESSION['public_link_authenticated']) || $_SESSION['public_link_authenticated'] !== $linkItem['id']) { + // Prompt for password + $tmpl = new OCP\Template('files_sharing', 'authenticate', 'guest'); + $tmpl->assign('URL', $url); + $tmpl->printPage(); + exit(); + } } } - $basePath = substr($pathAndUser['path'] , strlen('/'.$fileOwner.'/files')); + $basePath = substr($pathAndUser['path'], strlen('/' . $fileOwner . '/files')); $path = $basePath; if (isset($_GET['path'])) { $path .= $_GET['path']; } if (!$path || !OC_Filesystem::isValidPath($path) || !OC_Filesystem::file_exists($path)) { - OCP\Util::writeLog('share', 'Invalid path '.$path.' for share id '.$linkItem['id'], \OCP\Util::ERROR); + OCP\Util::writeLog('share', 'Invalid path ' . $path . ' for share id ' . $linkItem['id'], \OCP\Util::ERROR); header('HTTP/1.0 404 Not Found'); $tmpl = new OCP\Template('', '404', 'guest'); $tmpl->printPage(); @@ -179,13 +186,15 @@ if ($linkItem) { $file = basename($path); // Download the file if (isset($_GET['download'])) { - if (isset($_GET['path']) && $_GET['path'] !== '' ) { - if ( isset($_GET['files']) ) { // download selected files + if (isset($_GET['path']) && $_GET['path'] !== '') { + if (isset($_GET['files'])) { // download selected files OC_Files::get($path, $_GET['files'], $_SERVER['REQUEST_METHOD'] == 'HEAD' ? true : false); - } else if (isset($_GET['path']) && $_GET['path'] != '' ) { // download a file from a shared directory - OC_Files::get($dir, $file, $_SERVER['REQUEST_METHOD'] == 'HEAD' ? true : false); - } else { // download the whole shared directory - OC_Files::get($dir, $file, $_SERVER['REQUEST_METHOD'] == 'HEAD' ? true : false); + } else { + if (isset($_GET['path']) && $_GET['path'] != '') { // download a file from a shared directory + OC_Files::get($dir, $file, $_SERVER['REQUEST_METHOD'] == 'HEAD' ? true : false); + } else { // download the whole shared directory + OC_Files::get($dir, $file, $_SERVER['REQUEST_METHOD'] == 'HEAD' ? true : false); + } } } else { // download a single shared file OC_Files::get($dir, $file, $_SERVER['REQUEST_METHOD'] == 'HEAD' ? true : false); @@ -206,7 +215,7 @@ if ($linkItem) { $getPath = ''; } // - $urlLinkIdentifiers= (isset($token)?'&t='.$token:'').(isset($_GET['dir'])?'&dir='.$_GET['dir']:'').(isset($_GET['file'])?'&file='.$_GET['file']:''); + $urlLinkIdentifiers = (isset($token) ? '&t=' . $token : '') . (isset($_GET['dir']) ? '&dir=' . $_GET['dir'] : '') . (isset($_GET['file']) ? '&file=' . $_GET['file'] : ''); // Show file list if (OC_Filesystem::is_dir($path)) { OCP\Util::addStyle('files', 'files'); @@ -219,9 +228,9 @@ if ($linkItem) { if ($i['type'] == 'file') { $fileinfo = pathinfo($i['name']); $i['basename'] = $fileinfo['filename']; - $i['extension'] = isset($fileinfo['extension']) ? ('.'.$fileinfo['extension']) : ''; + $i['extension'] = isset($fileinfo['extension']) ? ('.' . $fileinfo['extension']) : ''; } - $i['directory'] = '/'.substr($i['directory'], $rootLength); + $i['directory'] = '/' . substr($i['directory'], $rootLength); if ($i['directory'] == '/') { $i['directory'] = ''; } @@ -238,98 +247,31 @@ if ($linkItem) { //add subdir breadcrumbs foreach (explode('/', urldecode($_GET['path'])) as $i) { if ($i != '') { - $pathtohere .= '/'.$i; + $pathtohere .= '/' . $i; $breadcrumb[] = array('dir' => $pathtohere, 'name' => $i); - $path = $linkItem['path']; - if (isset($_GET['path'])) { - $path .= $_GET['path']; - $dir .= $_GET['path']; - if (!\OC\Files\Filesystem::file_exists($path)) { - header('HTTP/1.0 404 Not Found'); - $tmpl = new OCP\Template('', '404', 'guest'); - $tmpl->printPage(); - exit(); - } - } + $path = $linkItem['path']; + if (isset($_GET['path'])) { + $path .= $_GET['path']; + $dir .= $_GET['path']; + if (!\OC\Files\Filesystem::file_exists($path)) { + header('HTTP/1.0 404 Not Found'); + $tmpl = new OCP\Template('', '404', 'guest'); + $tmpl->printPage(); + exit(); + } + } - $list = new OCP\Template('files', 'part.list', ''); - $list->assign('files', $files, false); - $list->assign('publicListView', true); - $list->assign('baseURL', OCP\Util::linkToPublic('files').$urlLinkIdentifiers.'&path=', false); - $list->assign('downloadURL', OCP\Util::linkToPublic('files').$urlLinkIdentifiers.'&download&path=', false); - $breadcrumbNav = new OCP\Template('files', 'part.breadcrumb', '' ); - $breadcrumbNav->assign('breadcrumb', $breadcrumb, false); - $breadcrumbNav->assign('baseURL', OCP\Util::linkToPublic('files').$urlLinkIdentifiers.'&path=', false); - $folder = new OCP\Template('files', 'index', ''); - $folder->assign('fileList', $list->fetchPage(), false); - $folder->assign('breadcrumb', $breadcrumbNav->fetchPage(), false); - $folder->assign('isCreatable', false); - $folder->assign('permissions', 0); - $folder->assign('files', $files); - $folder->assign('uploadMaxFilesize', 0); - $folder->assign('uploadMaxHumanFilesize', 0); - $folder->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true))); - $tmpl->assign('folder', $folder->fetchPage(), false); - $tmpl->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true))); - $tmpl->assign('downloadURL', OCP\Util::linkToPublic('files').$urlLinkIdentifiers.'&download&path='.urlencode($getPath)); - } else { - // Show file preview if viewer is available - if ($type == 'file') { - $tmpl->assign('downloadURL', OCP\Util::linkToPublic('files').$urlLinkIdentifiers.'&download'); - } else { - OCP\Util::addStyle('files_sharing', 'public'); - OCP\Util::addScript('files_sharing', 'public'); - OCP\Util::addScript('files', 'fileactions'); - $tmpl = new OCP\Template('files_sharing', 'public', 'base'); - $tmpl->assign('owner', $uidOwner); - // Show file list - if (OC_Filesystem::is_dir($path)) { - OCP\Util::addStyle('files', 'files'); - OCP\Util::addScript('files', 'files'); - OCP\Util::addScript('files', 'filelist'); - $files = array(); - $rootLength = strlen($baseDir) + 1; - foreach (OC_Files::getDirectoryContent($path) as $i) { - $i['date'] = OCP\Util::formatDate($i['mtime']); - if ($i['type'] == 'file') { - $fileinfo = pathinfo($i['name']); - $i['basename'] = $fileinfo['filename']; - $i['extension'] = isset($fileinfo['extension']) ? ('.'.$fileinfo['extension']) : ''; - } - $i['directory'] = '/'.substr('/'.$uidOwner.'/files'.$i['directory'], $rootLength); - if ($i['directory'] == '/') { - $i['directory'] = ''; - } - $i['permissions'] = OCP\PERMISSION_READ; - $files[] = $i; - } - // Make breadcrumb - $breadcrumb = array(); - $pathtohere = ''; - $count = 1; - foreach (explode('/', $dir) as $i) { - if ($i != '') { - if ($i != $baseDir) { - $pathtohere .= '/'.$i; - } - if ( strlen($pathtohere) < strlen($_GET['dir'])) { - continue; - } - $breadcrumb[] = array('dir' => str_replace($_GET['dir'], "", $pathtohere, $count), 'name' => $i); - } - } $list = new OCP\Template('files', 'part.list', ''); $list->assign('files', $files, false); $list->assign('publicListView', true); - $list->assign('baseURL', OCP\Util::linkToPublic('files').'&dir='.urlencode($_GET['dir']).'&path=', false); - $list->assign('downloadURL', OCP\Util::linkToPublic('files').'&download&dir='.urlencode($_GET['dir']).'&path=', false); - $breadcrumbNav = new OCP\Template('files', 'part.breadcrumb', '' ); + $list->assign('baseURL', OCP\Util::linkToPublic('files') . $urlLinkIdentifiers . '&path=', false); + $list->assign('downloadURL', OCP\Util::linkToPublic('files') . $urlLinkIdentifiers . '&download&path=', false); + $breadcrumbNav = new OCP\Template('files', 'part.breadcrumb', ''); $breadcrumbNav->assign('breadcrumb', $breadcrumb, false); - $breadcrumbNav->assign('baseURL', OCP\Util::linkToPublic('files').'&dir='.urlencode($_GET['dir']).'&path=', false); + $breadcrumbNav->assign('baseURL', OCP\Util::linkToPublic('files') . $urlLinkIdentifiers . '&path=', false); $folder = new OCP\Template('files', 'index', ''); $folder->assign('fileList', $list->fetchPage(), false); $folder->assign('breadcrumb', $breadcrumbNav->fetchPage(), false); - $folder->assign('dir', basename($dir)); $folder->assign('isCreatable', false); $folder->assign('permissions', 0); $folder->assign('files', $files); @@ -337,43 +279,113 @@ if ($linkItem) { $folder->assign('uploadMaxHumanFilesize', 0); $folder->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true))); $tmpl->assign('folder', $folder->fetchPage(), false); - $tmpl->assign('uidOwner', $uidOwner); - $tmpl->assign('dir', basename($dir)); - $tmpl->assign('filename', basename($path)); - $tmpl->assign('mimetype', OC_Filesystem::getMimeType($path)); $tmpl->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true))); - if (isset($_GET['path'])) { - $getPath = $_GET['path']; - } else { - $getPath = ''; - } - $tmpl->assign('downloadURL', OCP\Util::linkToPublic('files').'&download&dir='.urlencode($_GET['dir']).'&path='.urlencode($getPath), false); + $tmpl->assign('downloadURL', OCP\Util::linkToPublic('files') . $urlLinkIdentifiers . '&download&path=' . urlencode($getPath)); } else { // Show file preview if viewer is available - $tmpl->assign('uidOwner', $uidOwner); - $tmpl->assign('dir', dirname($path)); - $tmpl->assign('filename', basename($path)); - $tmpl->assign('mimetype', OC_Filesystem::getMimeType($path)); if ($type == 'file') { - $tmpl->assign('downloadURL', OCP\Util::linkToPublic('files').'&file='.urlencode($_GET['file']).'&download', false); + $tmpl->assign('downloadURL', OCP\Util::linkToPublic('files') . $urlLinkIdentifiers . '&download'); } else { - if (isset($_GET['path'])) { - $getPath = $_GET['path']; + OCP\Util::addStyle('files_sharing', 'public'); + OCP\Util::addScript('files_sharing', 'public'); + OCP\Util::addScript('files', 'fileactions'); + $tmpl = new OCP\Template('files_sharing', 'public', 'base'); + $tmpl->assign('owner', $uidOwner); + // Show file list + if (OC_Filesystem::is_dir($path)) { + OCP\Util::addStyle('files', 'files'); + OCP\Util::addScript('files', 'files'); + OCP\Util::addScript('files', 'filelist'); + $files = array(); + $rootLength = strlen($baseDir) + 1; + foreach (OC_Files::getDirectoryContent($path) as $i) { + $i['date'] = OCP\Util::formatDate($i['mtime']); + if ($i['type'] == 'file') { + $fileinfo = pathinfo($i['name']); + $i['basename'] = $fileinfo['filename']; + $i['extension'] = isset($fileinfo['extension']) ? ('.' . $fileinfo['extension']) : ''; + } + $i['directory'] = '/' . substr('/' . $uidOwner . '/files' . $i['directory'], $rootLength); + if ($i['directory'] == '/') { + $i['directory'] = ''; + } + $i['permissions'] = OCP\PERMISSION_READ; + $files[] = $i; + } + // Make breadcrumb + $breadcrumb = array(); + $pathtohere = ''; + $count = 1; + foreach (explode('/', $dir) as $i) { + if ($i != '') { + if ($i != $baseDir) { + $pathtohere .= '/' . $i; + } + if (strlen($pathtohere) < strlen($_GET['dir'])) { + continue; + } + $breadcrumb[] = array('dir' => str_replace($_GET['dir'], "", $pathtohere, $count), 'name' => $i); + } + } + $list = new OCP\Template('files', 'part.list', ''); + $list->assign('files', $files, false); + $list->assign('publicListView', true); + $list->assign('baseURL', OCP\Util::linkToPublic('files') . '&dir=' . urlencode($_GET['dir']) . '&path=', false); + $list->assign('downloadURL', OCP\Util::linkToPublic('files') . '&download&dir=' . urlencode($_GET['dir']) . '&path=', false); + $breadcrumbNav = new OCP\Template('files', 'part.breadcrumb', ''); + $breadcrumbNav->assign('breadcrumb', $breadcrumb, false); + $breadcrumbNav->assign('baseURL', OCP\Util::linkToPublic('files') . '&dir=' . urlencode($_GET['dir']) . '&path=', false); + $folder = new OCP\Template('files', 'index', ''); + $folder->assign('fileList', $list->fetchPage(), false); + $folder->assign('breadcrumb', $breadcrumbNav->fetchPage(), false); + $folder->assign('dir', basename($dir)); + $folder->assign('isCreatable', false); + $folder->assign('permissions', 0); + $folder->assign('files', $files); + $folder->assign('uploadMaxFilesize', 0); + $folder->assign('uploadMaxHumanFilesize', 0); + $folder->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true))); + $tmpl->assign('folder', $folder->fetchPage(), false); + $tmpl->assign('uidOwner', $uidOwner); + $tmpl->assign('dir', basename($dir)); + $tmpl->assign('filename', basename($path)); + $tmpl->assign('mimetype', OC_Filesystem::getMimeType($path)); + $tmpl->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true))); + if (isset($_GET['path'])) { + $getPath = $_GET['path']; + } else { + $getPath = ''; + } + $tmpl->assign('downloadURL', OCP\Util::linkToPublic('files') . '&download&dir=' . urlencode($_GET['dir']) . '&path=' . urlencode($getPath), false); } else { - $getPath = ''; + // Show file preview if viewer is available + $tmpl->assign('uidOwner', $uidOwner); + $tmpl->assign('dir', dirname($path)); + $tmpl->assign('filename', basename($path)); + $tmpl->assign('mimetype', OC_Filesystem::getMimeType($path)); + if ($type == 'file') { + $tmpl->assign('downloadURL', OCP\Util::linkToPublic('files') . '&file=' . urlencode($_GET['file']) . '&download', false); + } else { + if (isset($_GET['path'])) { + $getPath = $_GET['path']; + } else { + $getPath = ''; + } + $tmpl->assign('downloadURL', OCP\Util::linkToPublic('files') . '&download&dir=' . urlencode($_GET['dir']) . '&path=' . urlencode($getPath), false); + } } - $tmpl->assign('downloadURL', OCP\Util::linkToPublic('files').'&download&dir='.urlencode($_GET['dir']).'&path='.urlencode($getPath), false); + $tmpl->printPage(); } } $tmpl->printPage(); } + exit(); + } else { + OCP\Util::writeLog('share', 'could not resolve linkItem', \OCP\Util::DEBUG); } - $tmpl->printPage(); } - exit(); -} else { - OCP\Util::writeLog('share', 'could not resolve linkItem', \OCP\Util::DEBUG); } header('HTTP/1.0 404 Not Found'); $tmpl = new OCP\Template('', '404', 'guest'); $tmpl->printPage(); + From 317cd4c70a3042c4e16424cafb4a8b34c8cd8c3c Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 6 Dec 2012 17:49:35 +0100 Subject: [PATCH 109/347] catch error if old filecache table is not present during upgrade --- lib/files/cache/upgrade.php | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/files/cache/upgrade.php b/lib/files/cache/upgrade.php index 899f6f7ac8..ebac387de9 100644 --- a/lib/files/cache/upgrade.php +++ b/lib/files/cache/upgrade.php @@ -15,13 +15,17 @@ class Upgrade { $insertQuery = \OC_DB::prepare('INSERT INTO `*PREFIX*filecache`( `fileid`, `storage`, `path`, `path_hash`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted` ) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'); - $oldEntriesQuery = \OC_DB::prepare('SELECT * FROM `*PREFIX*fscache` ORDER BY `id` ASC'); //sort ascending to ensure the parent gets inserted before a child - try{ - $oldEntriesResult = $oldEntriesQuery->execute(); - }catch(\Exception $e){ + try { + $oldEntriesQuery = \OC_DB::prepare('SELECT * FROM `*PREFIX*fscache` ORDER BY `id` ASC'); //sort ascending to ensure the parent gets inserted before a child + } catch (\Exception $e) { return; } - if(!$oldEntriesResult){ + try { + $oldEntriesResult = $oldEntriesQuery->execute(); + } catch (\Exception $e) { + return; + } + if (!$oldEntriesResult) { return; } From 8635699db932959ac147193473b014406b0e9e09 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 11 Dec 2012 01:06:21 +0100 Subject: [PATCH 110/347] fix cache behaviour for non existing files --- lib/files/view.php | 26 ++++++++++++++------------ tests/lib/files/cache/cache.php | 5 +++++ tests/lib/files/view.php | 3 +++ 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/lib/files/view.php b/lib/files/view.php index 468808566a..994dbcc85c 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -691,20 +691,22 @@ class View { $data = $cache->get($internalPath); - if ($data['mimetype'] === 'httpd/unix-directory') { - //add the sizes of other mountpoints to the folder - $mountPoints = Filesystem::getMountPoints($path); - foreach ($mountPoints as $mountPoint) { - $subStorage = Filesystem::getStorage($mountPoint); - $subCache = $subStorage->getCache(); - $rootEntry = $subCache->get(''); + if ($data) { + if ($data['mimetype'] === 'httpd/unix-directory') { + //add the sizes of other mountpoints to the folder + $mountPoints = Filesystem::getMountPoints($path); + foreach ($mountPoints as $mountPoint) { + $subStorage = Filesystem::getStorage($mountPoint); + $subCache = $subStorage->getCache(); + $rootEntry = $subCache->get(''); - $data['size'] += $rootEntry['size']; + $data['size'] += $rootEntry['size']; + } } - } - $permissionsCache = $storage->getPermissionsCache(); - $data['permissions'] = $permissionsCache->get($data['fileid'], \OC_User::getUser()); + $permissionsCache = $storage->getPermissionsCache(); + $data['permissions'] = $permissionsCache->get($data['fileid'], \OC_User::getUser()); + } } return $data; } @@ -888,7 +890,7 @@ class View { * @param string $path * @return string */ - public function getETag($path){ + public function getETag($path) { /** * @var Storage\Storage $storage * @var string $internalPath diff --git a/tests/lib/files/cache/cache.php b/tests/lib/files/cache/cache.php index e9105cd5ab..a2b131ac0a 100644 --- a/tests/lib/files/cache/cache.php +++ b/tests/lib/files/cache/cache.php @@ -192,6 +192,11 @@ class Cache extends \UnitTestCase { $this->assertEquals($file3, $this->cache->getIncomplete()); } + function testNonExisting() { + $this->assertFalse($this->cache->get('foo.txt')); + $this->assertEquals(array(), $this->cache->getFolderContents('foo')); + } + public function tearDown() { $this->cache->clear(); } diff --git a/tests/lib/files/view.php b/tests/lib/files/view.php index ed08dcc114..1b8f6dc1e8 100644 --- a/tests/lib/files/view.php +++ b/tests/lib/files/view.php @@ -92,6 +92,9 @@ class View extends \PHPUnit_Framework_TestCase { $cachedData = $rootView->getFileInfo('/foo.txt'); $this->assertTrue($cachedData['encrypted']); $this->assertEquals($cachedData['fileid'], $id); + + $this->assertFalse($rootView->getFileInfo('/non/existing')); + $this->assertEquals(array(), $rootView->getDirectoryContent('/non/existing')); } public function testAutoScan() { From 438d3c21f651240e416b6e50ad49f72dd079a9ae Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 11 Dec 2012 01:24:53 +0100 Subject: [PATCH 111/347] actually connect the filesystem hooks to the cache updater --- lib/files/filesystem.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php index 724c83b361..c5b56ba9f0 100644 --- a/lib/files/filesystem.php +++ b/lib/files/filesystem.php @@ -685,4 +685,8 @@ class Filesystem { \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\Files\Cache\Updater', 'writeHook'); +\OC_Hook::connect('OC_Filesystem', 'post_delete', '\OC\Files\Cache\Updater', 'deleteHook'); +\OC_Hook::connect('OC_Filesystem', 'post_rename', '\OC\Files\Cache\Updater', 'renameHook'); + \OC_Util::setupFS(); From cc0a0df88b3b6fdd2b1f9c85349683eb640f9670 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 11 Dec 2012 01:25:21 +0100 Subject: [PATCH 112/347] one additional test case for the cache updater --- tests/lib/files/cache/updater.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/lib/files/cache/updater.php b/tests/lib/files/cache/updater.php index b2eccf9130..d19966c191 100644 --- a/tests/lib/files/cache/updater.php +++ b/tests/lib/files/cache/updater.php @@ -99,6 +99,11 @@ class Updater extends \PHPUnit_Framework_TestCase { $this->assertFalse($this->cache->inCache('foo.txt')); $cachedData = $this->cache->get(''); $this->assertEquals(2 * $textSize + $imageSize, $cachedData['size']); + + Filesystem::mkdir('bar_folder'); + $this->assertTrue($this->cache->inCache('bar_folder')); + Filesystem::rmdir('bar_folder'); + $this->assertFalse($this->cache->inCache('bar_folder')); } public function testRename() { From c6a5ce54a706efe6d157ec30a3960a3ebf8719a7 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sat, 15 Dec 2012 02:22:09 +0100 Subject: [PATCH 113/347] these functions should be static --- lib/files.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/files.php b/lib/files.php index 768a2ad219..2d7e335e96 100644 --- a/lib/files.php +++ b/lib/files.php @@ -28,11 +28,11 @@ class OC_Files { static $tmpFiles = array(); - public function getFileInfo($path){ + static public function getFileInfo($path){ return \OC\Files\Filesystem::getFileInfo($path); } - public function getDirectoryContent($path){ + static public function getDirectoryContent($path){ return \OC\Files\Filesystem::getDirectoryContent($path); } From bc52f121626bb1bb1f67bc1f876d0420d153b3d1 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sat, 15 Dec 2012 02:29:34 +0100 Subject: [PATCH 114/347] dont insert and entry in the filecache during upgrade if the id already exists in the filecache most likely the result from an incompelte upgrade --- lib/files/cache/upgrade.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/files/cache/upgrade.php b/lib/files/cache/upgrade.php index ebac387de9..9219deebef 100644 --- a/lib/files/cache/upgrade.php +++ b/lib/files/cache/upgrade.php @@ -29,7 +29,13 @@ class Upgrade { return; } + $checkExistingQuery = \OC_DB::prepare('SELECT `fileid` FROM `*PREFIX*filecache` WHERE `fileid` = ?'); + while ($row = $oldEntriesResult->fetchRow()) { + if($checkExistingQuery->execute(array($row['id']))->fetchRow()){ + continue; + } + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($row['path']); /** * @var \OC\Files\Storage\Storage $storage From 4be039e6cbc0a826b07fc2af1a6c6d94888a9187 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sat, 15 Dec 2012 03:10:56 +0100 Subject: [PATCH 115/347] Filecache Watcher: use scan or scanFile based on the current item, not the cached item --- lib/files/cache/watcher.php | 6 ++++-- tests/lib/files/cache/watcher.php | 34 +++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/lib/files/cache/watcher.php b/lib/files/cache/watcher.php index d6039d9945..31059ec7f5 100644 --- a/lib/files/cache/watcher.php +++ b/lib/files/cache/watcher.php @@ -44,12 +44,14 @@ class Watcher { public function checkUpdate($path) { $cachedEntry = $this->cache->get($path); if ($this->storage->hasUpdated($path, $cachedEntry['mtime'])) { - if ($cachedEntry['mimetype'] === 'httpd/unix-directory') { + if ($this->storage->is_dir($path)) { $this->scanner->scan($path, Scanner::SCAN_SHALLOW); - $this->cleanFolder($path); } else { $this->scanner->scanFile($path); } + if ($cachedEntry['mimetype'] === 'httpd/unix-directory') { + $this->cleanFolder($path); + } $this->cache->correctFolderSize($path); } } diff --git a/tests/lib/files/cache/watcher.php b/tests/lib/files/cache/watcher.php index 0125dd843b..07c8ac3640 100644 --- a/tests/lib/files/cache/watcher.php +++ b/tests/lib/files/cache/watcher.php @@ -63,6 +63,40 @@ class Watcher extends \PHPUnit_Framework_TestCase { $this->assertFalse($cache->inCache('folder/bar2.txt')); } + public function testFileToFolder() { + $storage = $this->getTestStorage(); + $cache = $storage->getCache(); + $updater = new \OC\Files\Cache\Watcher($storage); + + //set the mtime to the past so it can detect an mtime change + $cache->put('', array('mtime' => 10)); + + $storage->unlink('foo.txt'); + $storage->rename('folder','foo.txt'); + $updater->checkUpdate(''); + + $entry= $cache->get('foo.txt'); + $this->assertEquals(-1, $entry['size']); + $this->assertEquals('httpd/unix-directory', $entry['mimetype']); + $this->assertFalse($cache->inCache('folder')); + $this->assertFalse($cache->inCache('folder/bar.txt')); + + $storage = $this->getTestStorage(); + $cache = $storage->getCache(); + $updater = new \OC\Files\Cache\Watcher($storage); + + //set the mtime to the past so it can detect an mtime change + $cache->put('foo.txt', array('mtime' => 10)); + + $storage->unlink('foo.txt'); + $storage->rename('folder','foo.txt'); + $updater->checkUpdate('foo.txt'); + + $entry= $cache->get('foo.txt'); + $this->assertEquals('httpd/unix-directory', $entry['mimetype']); + $this->assertTrue($cache->inCache('foo.txt/bar.txt')); + } + /** * @param bool $scan * @return \OC\Files\Storage\Storage From cf3665057c0c195bb3a0e2d9f8f8746f5d2f5787 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sat, 15 Dec 2012 03:20:50 +0100 Subject: [PATCH 116/347] make sure folders that are not fully scanned are at least shallow scanned when we open them the fact that they are in the cache does not mean they are scanned --- lib/files/view.php | 2 +- tests/lib/files/view.php | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/files/view.php b/lib/files/view.php index 994dbcc85c..6d917bb585 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -728,7 +728,7 @@ class View { if ($storage) { $cache = $storage->getCache(); - if (!$cache->inCache($internalPath)) { + if ($cache->getStatus($internalPath) < Cache\Cache::COMPLETE) { $scanner = $storage->getScanner(); $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW); } else { diff --git a/tests/lib/files/view.php b/tests/lib/files/view.php index 1b8f6dc1e8..712166ab32 100644 --- a/tests/lib/files/view.php +++ b/tests/lib/files/view.php @@ -97,6 +97,19 @@ class View extends \PHPUnit_Framework_TestCase { $this->assertEquals(array(), $rootView->getDirectoryContent('/non/existing')); } + function testCacheIncompleteFolder() { + $storage1 = $this->getTestStorage(false); + \OC\Files\Filesystem::mount($storage1, array(), '/'); + $rootView = new \OC\Files\View(''); + + $entries = $rootView->getDirectoryContent('/'); + $this->assertEquals(3, count($entries)); + + // /folder will already be in the cache but not scanned + $entries = $rootView->getDirectoryContent('/folder'); + $this->assertEquals(1, count($entries)); + } + public function testAutoScan() { $storage1 = $this->getTestStorage(false); $storage2 = $this->getTestStorage(false); From 8951769cae5f1acc9b709ac676fffe26513d14f6 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Sat, 15 Dec 2012 17:16:26 -0500 Subject: [PATCH 117/347] Check sub storage isn't null or false --- lib/files/view.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/files/view.php b/lib/files/view.php index 6d917bb585..592c484a21 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -697,10 +697,11 @@ class View { $mountPoints = Filesystem::getMountPoints($path); foreach ($mountPoints as $mountPoint) { $subStorage = Filesystem::getStorage($mountPoint); - $subCache = $subStorage->getCache(); - $rootEntry = $subCache->get(''); - - $data['size'] += $rootEntry['size']; + if ($subStorage) { + $subCache = $subStorage->getCache(); + $rootEntry = $subCache->get(''); + $data['size'] += $rootEntry['size']; + } } } From b12abb2c94072ab5b84d0477ecb7ce9789bdda0d Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sat, 15 Dec 2012 23:28:07 +0100 Subject: [PATCH 118/347] use numeric ids for storages in the filecache --- db_structure.xml | 40 +++++++++++++++++++++++++++++++-- lib/files/cache/cache.php | 44 ++++++++++++++++++++++++++++--------- lib/files/cache/upgrade.php | 21 ++++++++++++++++-- lib/util.php | 2 +- 4 files changed, 92 insertions(+), 15 deletions(-) diff --git a/db_structure.xml b/db_structure.xml index 2856ee4ff9..aa0916264c 100644 --- a/db_structure.xml +++ b/db_structure.xml @@ -58,6 +58,42 @@
+ + + *dbprefix*storages + + + + + id + text + + true + 64 + + + + numeric_id + integer + 0 + true + 1 + 4 + + + + storages_id_index + true + + id + ascending + + + + + +
+ *dbprefix*filecache @@ -75,10 +111,10 @@ storage - text + integer true - 64 + 4 diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index 5aeb6f25af..3ebae9baa5 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -29,6 +29,13 @@ class Cache { */ private $storageId; + /** + * numeric storage id + * + * @var int $numericId + */ + private $numericId; + /** * @param \OC\Files\Storage\Storage|string $storage */ @@ -38,6 +45,20 @@ class Cache { } else { $this->storageId = $storage; } + + $query = \OC_DB::prepare('SELECT `numeric_id` FROM `*PREFIX*storages` WHERE `id` = ?'); + $result = $query->execute(array($this->storageId)); + if ($row = $result->fetchRow()) { + $this->numericId = $row['numeric_id']; + } else { + $query = \OC_DB::prepare('INSERT INTO `*PREFIX*storages`(`id`) VALUES(?)'); + $query->execute(array($this->storageId)); + $this->numericId = \OC_DB::insertid('*PREFIX*filecache'); + } + } + + public function getNumericStorageId() { + return $this->numericId; } /** @@ -49,7 +70,7 @@ class Cache { public function get($file) { if (is_string($file) or $file == '') { $where = 'WHERE `storage` = ? AND `path_hash` = ?'; - $params = array($this->storageId, md5($file)); + $params = array($this->numericId, md5($file)); } else { //file id $where = 'WHERE `fileid` = ?'; $params = array($file); @@ -128,7 +149,7 @@ class Cache { list($queryParts, $params) = $this->buildParts($data); $queryParts[] = '`storage`'; - $params[] = $this->storageId; + $params[] = $this->numericId; $valuesPlaceholder = array_fill(0, count($queryParts), '?'); $query = \OC_DB::prepare('INSERT INTO `*PREFIX*filecache`(' . implode(', ', $queryParts) . ') VALUES(' . implode(', ', $valuesPlaceholder) . ')'); @@ -189,7 +210,7 @@ class Cache { $pathHash = md5($file); $query = \OC_DB::prepare('SELECT `fileid` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path_hash` = ?'); - $result = $query->execute(array($this->storageId, $pathHash)); + $result = $query->execute(array($this->numericId, $pathHash)); if ($row = $result->fetchRow()) { return $row['fileid']; @@ -273,7 +294,10 @@ class Cache { * remove all entries for files that are stored on the storage from the cache */ public function clear() { - $query = \OC_DB::prepare('DELETE FROM `*PREFIX*filecache` WHERE storage=?'); + $query = \OC_DB::prepare('DELETE FROM `*PREFIX*filecache` WHERE storage = ?'); + $query->execute(array($this->numericId)); + + $query = \OC_DB::prepare('DELETE FROM `*PREFIX*storages` WHERE id = ?'); $query->execute(array($this->storageId)); } @@ -285,7 +309,7 @@ class Cache { public function getStatus($file) { $pathHash = md5($file); $query = \OC_DB::prepare('SELECT `size` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `path_hash` = ?'); - $result = $query->execute(array($this->storageId, $pathHash)); + $result = $query->execute(array($this->numericId, $pathHash)); if ($row = $result->fetchRow()) { if ((int)$row['size'] === -1) { return self::SHALLOW; @@ -312,7 +336,7 @@ class Cache { SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted` FROM `*PREFIX*filecache` WHERE `name` LIKE ? AND `storage` = ?' ); - $result = $query->execute(array($pattern, $this->storageId)); + $result = $query->execute(array($pattern, $this->numericId)); $files = array(); while ($row = $result->fetchRow()) { $files[] = $row; @@ -336,7 +360,7 @@ class Cache { SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted` FROM `*PREFIX*filecache` WHERE ' . $where . ' AND `storage` = ?' ); - $result = $query->execute(array($mimetype, $this->storageId)); + $result = $query->execute(array($mimetype, $this->numericId)); return $result->fetchAll(); } @@ -368,7 +392,7 @@ class Cache { return 0; } $query = \OC_DB::prepare('SELECT `size` FROM `*PREFIX*filecache` WHERE `parent` = ? AND `storage` = ?'); - $result = $query->execute(array($id, $this->storageId)); + $result = $query->execute(array($id, $this->numericId)); $totalSize = 0; $hasChilds = 0; while ($row = $result->fetchRow()) { @@ -395,7 +419,7 @@ class Cache { */ public function getAll() { $query = \OC_DB::prepare('SELECT `fileid` FROM `*PREFIX*filecache` WHERE `storage` = ?'); - $result = $query->execute(array($this->storageId)); + $result = $query->execute(array($this->numericId)); $ids = array(); while ($row = $result->fetchRow()) { $ids[] = $row['fileid']; @@ -414,7 +438,7 @@ class Cache { */ public function getIncomplete() { $query = \OC_DB::prepare('SELECT `path` FROM `*PREFIX*filecache` WHERE `storage` = ? AND `size` = -1 ORDER BY `fileid` DESC LIMIT 1'); - $query->execute(array($this->storageId)); + $query->execute(array($this->numericId)); if ($row = $query->fetchRow()) { return $row['path']; } else { diff --git a/lib/files/cache/upgrade.php b/lib/files/cache/upgrade.php index 9219deebef..77db4c2339 100644 --- a/lib/files/cache/upgrade.php +++ b/lib/files/cache/upgrade.php @@ -11,6 +11,8 @@ namespace OC\Files\Cache; class Upgrade { static $permissionsCaches = array(); + static $numericIds = array(); + static function upgrade() { $insertQuery = \OC_DB::prepare('INSERT INTO `*PREFIX*filecache`( `fileid`, `storage`, `path`, `path_hash`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted` ) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'); @@ -32,7 +34,7 @@ class Upgrade { $checkExistingQuery = \OC_DB::prepare('SELECT `fileid` FROM `*PREFIX*filecache` WHERE `fileid` = ?'); while ($row = $oldEntriesResult->fetchRow()) { - if($checkExistingQuery->execute(array($row['id']))->fetchRow()){ + if ($checkExistingQuery->execute(array($row['id']))->fetchRow()) { continue; } @@ -42,7 +44,7 @@ class Upgrade { * @var string $internalPath; */ $pathHash = md5($internalPath); - $storageId = $storage->getId(); + $storageId = self::getNumericId($storage); $parentId = ($internalPath === '') ? -1 : $row['parent']; $insertQuery->execute(array($row['id'], $storageId, $internalPath, $pathHash, $parentId, $row['name'], $row['mimetype'], $row['mimepart'], $row['size'], $row['mtime'], $row['encrypted'])); @@ -64,4 +66,19 @@ class Upgrade { } return self::$permissionsCaches[$storageId]; } + + /** + * get the numeric storage id + * + * @param \OC\Files\Storage\Storage $storage + * @return int + */ + static function getNumericId($storage) { + $storageId = $storage->getId(); + if (!isset(self::$numericIds[$storageId])) { + $cache = new Cache($storage); + self::$numericIds[$storageId] = $cache->getNumericStorageId(); + } + return self::$numericIds[$storageId]; + } } diff --git a/lib/util.php b/lib/util.php index 0f6ead2419..4411b32731 100755 --- a/lib/util.php +++ b/lib/util.php @@ -75,7 +75,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,02); + return array(4,91,04); } /** From bf05ff351faa693337107ed4a316e36e9aacd296 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Sat, 15 Dec 2012 19:44:46 -0500 Subject: [PATCH 119/347] Initial support for file sharing with filesystem branch --- apps/files_sharing/appinfo/app.php | 3 + apps/files_sharing/lib/cache.php | 220 +++++++++++++++++++++++ apps/files_sharing/lib/permissions.php | 82 +++++++++ apps/files_sharing/lib/scanner.php | 69 +++++++ apps/files_sharing/lib/share/file.php | 74 ++++---- apps/files_sharing/lib/share/folder.php | 28 --- apps/files_sharing/lib/sharedstorage.php | 148 ++++++--------- lib/public/share.php | 8 +- 8 files changed, 475 insertions(+), 157 deletions(-) create mode 100644 apps/files_sharing/lib/cache.php create mode 100644 apps/files_sharing/lib/permissions.php create mode 100644 apps/files_sharing/lib/scanner.php diff --git a/apps/files_sharing/appinfo/app.php b/apps/files_sharing/appinfo/app.php index 210c78ad17..189fd20cae 100644 --- a/apps/files_sharing/appinfo/app.php +++ b/apps/files_sharing/appinfo/app.php @@ -3,6 +3,9 @@ OC::$CLASSPATH['OC_Share_Backend_File'] = "apps/files_sharing/lib/share/file.php"; OC::$CLASSPATH['OC_Share_Backend_Folder'] = 'apps/files_sharing/lib/share/folder.php'; OC::$CLASSPATH['OC\Files\Storage\Shared'] = "apps/files_sharing/lib/sharedstorage.php"; +OC::$CLASSPATH['OC\Files\Cache\Shared_Cache'] = 'apps/files_sharing/lib/cache.php'; +OC::$CLASSPATH['OC\Files\Cache\Shared_Permissions'] = 'apps/files_sharing/lib/permissions.php'; +OC::$CLASSPATH['OC\Files\Cache\Shared_Scanner'] = 'apps/files_sharing/lib/scanner.php'; OCP\Util::connectHook('OC_Filesystem', 'setup', '\OC\Files\Storage\Shared', 'setup'); OCP\Share::registerBackend('file', 'OC_Share_Backend_File'); OCP\Share::registerBackend('folder', 'OC_Share_Backend_Folder', 'file'); diff --git a/apps/files_sharing/lib/cache.php b/apps/files_sharing/lib/cache.php new file mode 100644 index 0000000000..196e767cf6 --- /dev/null +++ b/apps/files_sharing/lib/cache.php @@ -0,0 +1,220 @@ +. +*/ + +namespace OC\Files\Cache; + +/** + * Metadata cache for shared files + * + * don't use this class directly if you need to get metadata, use \OC\Files\Filesystem::getFileInfo instead + */ +class Shared_Cache extends Cache { + + private $files = array(); + + /** + * @brief Get the source cache of a shared file or folder + * @param string Shared target file path + * @return \OC\Files\Storage\Cache + */ + private function getSourceCache($target) { + $source = \OC_Share_Backend_File::getSource($target); + if (isset($source['path'])) { + $source['path'] = '/'.$source['uid_owner'].'/'.$source['path']; + \OC\Files\Filesystem::initMountPoints($source['uid_owner']); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source['path']); + $this->files[$target] = $internalPath; + return $storage->getCache(); + } + return false; + } + + /** + * get the stored metadata of a file or folder + * + * @param string/int $file + * @return array + */ + public function get($file) { + if (is_string($file)) { + if ($cache = $this->getSourceCache($file)) { + return $cache->get($this->files[$file]); + } + } else { + $query = \OC_DB::prepare( + 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted` + FROM `*PREFIX*filecache` WHERE `fileid` = ?'); + $result = $query->execute(array($file)); + $data = $result->fetchRow(); + $data['fileid'] = (int)$data['fileid']; + $data['size'] = (int)$data['size']; + $data['mtime'] = (int)$data['mtime']; + $data['encrypted'] = (bool)$data['encrypted']; + return $data; + } + return false; + } + + /** + * get the metadata of all files stored in $folder + * + * @param string $folder + * @return array + */ + public function getFolderContents($folder) { + if ($folder == '') { + return \OCP\Share::getItemsSharedWith('file', \OC_Share_Backend_File::FORMAT_GET_FOLDER_CONTENTS); + } else { + return $this->getSourceCache($folder)->getFolderContents('/'.$this->files[$folder]); + } + } + + /** + * store meta data for a file or folder + * + * @param string $file + * @param array $data + * + * @return int file id + */ + public function put($file, array $data) { + if ($cache = $this->getSourceCache($file)) { + return $cache->put($this->files[$file]); + } + return false; + } + + /** + * get the file id for a file + * + * @param string $file + * @return int + */ + public function getId($file) { + if ($cache = $this->getSourceCache($file)) { + return $cache->getId($this->files[$file]); + } + return -1; + } + + /** + * remove a file or folder from the cache + * + * @param string $file + */ + public function remove($file) { + if ($cache = $this->getSourceCache($file)) { + $cache->remove($this->files[$file]); + } + } + + /** + * Move a file or folder in the cache + * + * @param string $source + * @param string $target + */ + public function move($source, $target) { + if ($cache = $this->getSourceCache($source)) { + $targetPath = \OC_Share_Backend_File::getSourcePath(dirname($target)); + if ($targetPath) { + $targetPath .= '/'.basename($target); + $cache->move($this->files[$source], $targetPath); + } + + } + } + + /** + * remove all entries for files that are stored on the storage from the cache + */ + public function clear() { + // Not a valid action for Shared Cache + } + + /** + * @param string $file + * + * @return int, Cache::NOT_FOUND, Cache::PARTIAL, Cache::SHALLOW or Cache::COMPLETE + */ + public function getStatus($file) { + if ($cache = $this->getSourceCache($file)) { + return $cache->getStatus($this->files[$file]); + } + return false; + } + + /** + * search for files matching $pattern + * + * @param string $pattern + * @return array of file data + */ + public function search($pattern) { + // TODO + } + + /** + * search for files by mimetype + * + * @param string $part1 + * @param string $part2 + * @return array + */ + public function searchByMime($mimetype) { + if (strpos($mimetype, '/')) { + $where = '`mimetype` = ?'; + } else { + $where = '`mimepart` = ?'; + } + $ids = $this->getAll(); + $placeholders = join(',', array_fill(0, count($ids), '?')); + $query = \OC_DB::prepare(' + SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted` + FROM `*PREFIX*filecache` WHERE ' . $where . ' AND `fileid` IN = ('.$placeholders.')' + ); + $result = $query->execute(array_merge(array($mimetype), $ids)); + return $result->fetchAll(); + } + + /** + * get the size of a folder and set it in the cache + * + * @param string $path + * @return int + */ + public function calculateFolderSize($path) { + if ($cache = $this->getSourceCache($path)) { + return $cache->calculateFolderSize($this->files[$path]); + } + return 0; + } + + /** + * get all file ids on the files on the storage + * + * @return int[] + */ + public function getAll() { + return OCP\Share::getItemsSharedWith('file', \OC_Share_Backend_File::FORMAT_GET_ALL); + } + +} \ No newline at end of file diff --git a/apps/files_sharing/lib/permissions.php b/apps/files_sharing/lib/permissions.php new file mode 100644 index 0000000000..51ae4cf102 --- /dev/null +++ b/apps/files_sharing/lib/permissions.php @@ -0,0 +1,82 @@ +. +*/ +namespace OC\Files\Cache; + +class Shared_Permissions { + + /** + * get the permissions for a single file + * + * @param int $fileId + * @param string $user + * @return int (-1 if file no permissions set) + */ + static public function get($fileId, $user) { + $source = \OCP\Share::getItemSharedWithBySource('file', $fileId, \OC_Share_Backend_File::FORMAT_SHARED_STORAGE); + if ($source) { + return $source['permissions']; + } else { + return -1; + } + } + + /** + * set the permissions of a file + * + * @param int $fileId + * @param string $user + * @param int $permissions + */ + static public function set($fileId, $user, $permissions) { + // Not a valid action for Shared Permissions + } + + /** + * get the permissions of multiply files + * + * @param int[] $fileIds + * @param string $user + * @return int[] + */ + static public function getMultiple($fileIds, $user) { + if (count($fileIds) === 0) { + return array(); + } + foreach ($fileIds as $fileId) { + $filePermissions[$fileId] = self::get($fileId, $user); + } + return $filePermissions; + } + + /** + * remove the permissions for a file + * + * @param int $fileId + * @param string $user + */ + static public function remove($fileId, $user) { + // Not a valid action for Shared Permissions + } + + static public function removeMultiple($fileIds, $user) { + // Not a valid action for Shared Permissions + } +} diff --git a/apps/files_sharing/lib/scanner.php b/apps/files_sharing/lib/scanner.php new file mode 100644 index 0000000000..d13d2f9cbc --- /dev/null +++ b/apps/files_sharing/lib/scanner.php @@ -0,0 +1,69 @@ +. +*/ + +namespace OC\Files\Cache; + +class Shared_Scanner extends Scanner { + + public function __construct(\OC\Files\Storage\Storage $storage) { + + } + + /** + * get all the metadata of a file or folder + * * + * + * @param string $path + * @return array with metadata of the file + */ + public function getData($path) { + // Not a valid action for Shared Scanner + } + + /** + * scan a single file and store it in the cache + * + * @param string $file + * @return array with metadata of the scanned file + */ + public function scanFile($file) { + // Not a valid action for Shared Scanner + } + + /** + * scan all the files in a folder and store them in the cache + * + * @param string $path + * @param SCAN_RECURSIVE/SCAN_SHALLOW $recursive + * @return int the size of the scanned folder or -1 if the size is unknown at this stage + */ + public function scan($path, $recursive = self::SCAN_RECURSIVE) { + // Not a valid action for Shared Scanner + } + + /** + * walk over any folders that are not fully scanned yet and scan them + */ + public function backgroundScan() { + // Not a valid action for Shared Scanner + } + +} \ No newline at end of file diff --git a/apps/files_sharing/lib/share/file.php b/apps/files_sharing/lib/share/file.php index ac58523683..52220dc5b2 100644 --- a/apps/files_sharing/lib/share/file.php +++ b/apps/files_sharing/lib/share/file.php @@ -22,16 +22,17 @@ class OC_Share_Backend_File implements OCP\Share_Backend_File_Dependent { const FORMAT_SHARED_STORAGE = 0; - const FORMAT_FILE_APP = 1; - const FORMAT_FILE_APP_ROOT = 2; + const FORMAT_GET_FOLDER_CONTENTS = 1; + const FORMAT_GET_ALL = 2; const FORMAT_OPENDIR = 3; private $path; public function isValidSource($itemSource, $uidOwner) { - $path = OC_FileCache::getPath($itemSource, $uidOwner); - if ($path) { - $this->path = $path; + $query = \OC_DB::prepare('SELECT `name` FROM `*PREFIX*filecache` WHERE `fileid` = ?'); + $result = $query->execute(array($itemSource)); + if ($row = $result->fetchRow()) { + $this->path = $row['name']; return true; } return false; @@ -70,50 +71,29 @@ class OC_Share_Backend_File implements OCP\Share_Backend_File_Dependent { public function formatItems($items, $format, $parameters = null) { if ($format == self::FORMAT_SHARED_STORAGE) { // Only 1 item should come through for this format call - return array('path' => $items[key($items)]['path'], 'permissions' => $items[key($items)]['permissions']); - } else if ($format == self::FORMAT_FILE_APP) { - if (isset($parameters['mimetype_filter']) && $parameters['mimetype_filter']) { - $mimetype_filter = $parameters['mimetype_filter']; - } + return array('path' => $items[key($items)]['path'], 'permissions' => $items[key($items)]['permissions'], 'uid_owner' => $items[key($items)]['uid_owner']); + } else if ($format == self::FORMAT_GET_FOLDER_CONTENTS) { $files = array(); foreach ($items as $item) { - if (isset($mimetype_filter) - && strpos($item['mimetype'], $mimetype_filter) !== 0 - && $item['mimetype'] != 'httpd/unix-directory') { - continue; - } $file = array(); - $file['id'] = $item['file_source']; + $file['fileid'] = $item['file_source']; + $file['storage'] = $item['storage']; $file['path'] = $item['file_target']; + $file['parent'] = $item['file_parent']; $file['name'] = basename($item['file_target']); - $file['ctime'] = $item['ctime']; - $file['mtime'] = $item['mtime']; $file['mimetype'] = $item['mimetype']; $file['size'] = $item['size']; + $file['mtime'] = $item['mtime']; $file['encrypted'] = $item['encrypted']; - $file['versioned'] = $item['versioned']; - $file['directory'] = $parameters['folder']; - $file['type'] = ($item['mimetype'] == 'httpd/unix-directory') ? 'dir' : 'file'; - $file['permissions'] = $item['permissions']; - if ($file['type'] == 'file') { - // Remove Create permission if type is file - $file['permissions'] &= ~OCP\PERMISSION_CREATE; - } - // NOTE: Temporary fix to allow unsharing of files in root of Shared directory - $file['permissions'] |= OCP\PERMISSION_DELETE; $files[] = $file; } return $files; - } else if ($format == self::FORMAT_FILE_APP_ROOT) { - $mtime = 0; - $size = 0; + } else if ($format == self::FORMAT_GET_ALL) { + $ids = array(); foreach ($items as $item) { - if ($item['mtime'] > $mtime) { - $mtime = $item['mtime']; - } - $size += $item['size']; + $ids[] = $item['file_source']; } - return array(0 => array('id' => -1, 'name' => 'Shared', 'mtime' => $mtime, 'mimetype' => 'httpd/unix-directory', 'size' => $size, 'writable' => false, 'type' => 'dir', 'directory' => '', 'permissions' => OCP\PERMISSION_READ)); + return $ids; } else if ($format == self::FORMAT_OPENDIR) { $files = array(); foreach ($items as $item) { @@ -124,4 +104,26 @@ class OC_Share_Backend_File implements OCP\Share_Backend_File_Dependent { return array(); } + public static function getSource($target) { + $target = '/'.$target; + $target = rtrim($target, '/'); + $pos = strpos($target, '/', 1); + // Get shared folder name + if ($pos !== false) { + $folder = substr($target, 0, $pos); + $source = \OCP\Share::getItemSharedWith('folder', $folder, \OC_Share_Backend_File::FORMAT_SHARED_STORAGE); + if ($source) { + $source['path'] = $source['path'].substr($target, strlen($folder)); + return $source; + } + } else { + $source = \OCP\Share::getItemSharedWith('file', $target, \OC_Share_Backend_File::FORMAT_SHARED_STORAGE); + if ($source) { + return $source; + } + } + \OCP\Util::writeLog('files_sharing', 'File source not found for: '.$target, \OCP\Util::ERROR); + return false; + } + } diff --git a/apps/files_sharing/lib/share/folder.php b/apps/files_sharing/lib/share/folder.php index d414fcf10f..a1bb843d72 100644 --- a/apps/files_sharing/lib/share/folder.php +++ b/apps/files_sharing/lib/share/folder.php @@ -21,34 +21,6 @@ class OC_Share_Backend_Folder extends OC_Share_Backend_File implements OCP\Share_Backend_Collection { - public function formatItems($items, $format, $parameters = null) { - if ($format == self::FORMAT_SHARED_STORAGE) { - // Only 1 item should come through for this format call - return array('path' => $items[key($items)]['path'], 'permissions' => $items[key($items)]['permissions']); - } else if ($format == self::FORMAT_FILE_APP && isset($parameters['folder'])) { - // Only 1 item should come through for this format call - $folder = $items[key($items)]; - if (isset($parameters['mimetype_filter'])) { - $mimetype_filter = $parameters['mimetype_filter']; - } else { - $mimetype_filter = ''; - } - $path = $folder['path'].substr($parameters['folder'], 7 + strlen($folder['file_target'])); - $files = OC_FileCache::getFolderContent($path, '', $mimetype_filter); - foreach ($files as &$file) { - $file['directory'] = $parameters['folder']; - $file['type'] = ($file['mimetype'] == 'httpd/unix-directory') ? 'dir' : 'file'; - $file['permissions'] = $folder['permissions']; - if ($file['type'] == 'file') { - // Remove Create permission if type is file - $file['permissions'] &= ~OCP\PERMISSION_CREATE; - } - } - return $files; - } - return array(); - } - public function getChildren($itemSource) { $children = array(); $parents = array($itemSource); diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php index 5abdbf29f0..960aa64099 100644 --- a/apps/files_sharing/lib/sharedstorage.php +++ b/apps/files_sharing/lib/sharedstorage.php @@ -34,41 +34,8 @@ class Shared extends \OC\Files\Storage\Common { $this->sharedFolder = $arguments['sharedFolder']; } - /** - * @brief Get the source file path and the permissions granted for a shared file - * @param string Shared target file path - * @return array with the keys path and permissions or false if not found - */ - private function getFile($target) { - $target = '/'.$target; - $target = rtrim($target, '/'); - if (isset($this->files[$target])) { - return $this->files[$target]; - } else { - $pos = strpos($target, '/', 1); - // Get shared folder name - if ($pos !== false) { - $folder = substr($target, 0, $pos); - if (isset($this->files[$folder])) { - $file = $this->files[$folder]; - } else { - $file = \OCP\Share::getItemSharedWith('folder', $folder, \OC_Share_Backend_File::FORMAT_SHARED_STORAGE); - } - if ($file) { - $this->files[$target]['path'] = $file['path'].substr($target, strlen($folder)); - $this->files[$target]['permissions'] = $file['permissions']; - return $this->files[$target]; - } - } else { - $file = \OCP\Share::getItemSharedWith('file', $target, \OC_Share_Backend_File::FORMAT_SHARED_STORAGE); - if ($file) { - $this->files[$target] = $file; - return $this->files[$target]; - } - } - \OCP\Util::writeLog('files_sharing', 'File source not found for: '.$target, \OCP\Util::ERROR); - return false; - } + public function getId(){ + return 'shared::' . $this->sharedFolder; } /** @@ -77,13 +44,13 @@ class Shared extends \OC\Files\Storage\Common { * @return string source file path or false if not found */ private function getSourcePath($target) { - $file = $this->getFile($target); - if (isset($file['path'])) { - $uid = substr($file['path'], 1, strpos($file['path'], '/', 1) - 1); - \OC\Files\Filesystem::mount('\OC\Files\Storage\Local', array('datadir' => \OC_User::getHome($uid)), $uid); - return $file['path']; + if (!isset($this->files[$target])) { + $source = \OC_Share_Backend_File::getSource($target); + $source['path'] = '/'.$source['uid_owner'].'/'.$source['path']; + $this->files[$target] = $source; + \OC\Files\Filesystem::initMountPoints($source['uid_owner']); } - return false; + return $this->files[$target]['path']; } /** @@ -92,26 +59,18 @@ class Shared extends \OC\Files\Storage\Common { * @return int CRUDS permissions granted or false if not found */ public function getPermissions($target) { - $file = $this->getFile($target); - if (isset($file['permissions'])) { - return $file['permissions']; + if (!isset($this->files[$target])) { + $source = \OC_Share_Backend_File::getSource($target); + $this->files[$target] = $source; } - return false; - } - - public function getOwner($target) { - $shared_item = \OCP\Share::getItemSharedWith('folder', $target, \OC_Share_Backend_File::FORMAT_SHARED_STORAGE); - if ($shared_item) { - return $shared_item[0]["uid_owner"]; - } - return null; + return $this->files[$target]['permissions']; } public function mkdir($path) { if ($path == '' || $path == '/' || !$this->isCreatable(dirname($path))) { return false; } else if ($source = $this->getSourcePath($path)) { - list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); return $storage->mkdir($internalPath); } return false; @@ -119,7 +78,7 @@ class Shared extends \OC\Files\Storage\Common { public function rmdir($path) { if (($source = $this->getSourcePath($path)) && $this->isDeletable($path)) { - list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); return $storage->rmdir($internalPath); } return false; @@ -131,7 +90,7 @@ class Shared extends \OC\Files\Storage\Common { \OC_FakeDirStream::$dirs['shared'] = $files; return opendir('fakedir://shared'); } else if ($source = $this->getSourcePath($path)) { - list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); return $storage->opendir($internalPath); } return false; @@ -141,7 +100,7 @@ class Shared extends \OC\Files\Storage\Common { if ($path == '' || $path == '/') { return true; } else if ($source = $this->getSourcePath($path)) { - list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); return $storage->is_dir($internalPath); } return false; @@ -149,7 +108,7 @@ class Shared extends \OC\Files\Storage\Common { public function is_file($path) { if ($source = $this->getSourcePath($path)) { - list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); return $storage->is_file($internalPath); } return false; @@ -161,7 +120,7 @@ class Shared extends \OC\Files\Storage\Common { $stat['mtime'] = $this->filemtime($path); return $stat; } else if ($source = $this->getSourcePath($path)) { - list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); return $storage->stat($internalPath); } return false; @@ -171,7 +130,7 @@ class Shared extends \OC\Files\Storage\Common { if ($path == '' || $path == '/') { return 'dir'; } else if ($source = $this->getSourcePath($path)) { - list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); return $storage->filetype($internalPath); } return false; @@ -181,7 +140,7 @@ class Shared extends \OC\Files\Storage\Common { if ($path == '' || $path == '/' || $this->is_dir($path)) { return 0; } else if ($source = $this->getSourcePath($path)) { - list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); return $storage->filesize($internalPath); } return false; @@ -191,7 +150,7 @@ class Shared extends \OC\Files\Storage\Common { if ($path == '') { return false; } - return ($this->getPermissions($path) & OCP\PERMISSION_CREATE); + return ($this->getPermissions($path) & \OCP\PERMISSION_CREATE); } public function isReadable($path) { @@ -202,28 +161,28 @@ class Shared extends \OC\Files\Storage\Common { if ($path == '') { return false; } - return ($this->getPermissions($path) & OCP\PERMISSION_UPDATE); + return ($this->getPermissions($path) & \OCP\PERMISSION_UPDATE); } public function isDeletable($path) { if ($path == '') { return true; } - return ($this->getPermissions($path) & OCP\PERMISSION_DELETE); + return ($this->getPermissions($path) & \OCP\PERMISSION_DELETE); } public function isSharable($path) { if ($path == '') { return false; } - return ($this->getPermissions($path) & OCP\PERMISSION_SHARE); + return ($this->getPermissions($path) & \OCP\PERMISSION_SHARE); } public function file_exists($path) { if ($path == '' || $path == '/') { return true; } else if ($source = $this->getSourcePath($path)) { - list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); return $storage->file_exists($internalPath); } return false; @@ -244,7 +203,7 @@ class Shared extends \OC\Files\Storage\Common { } else { $source = $this->getSourcePath($path); if ($source) { - list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); return $storage->filemtime($internalPath); } } @@ -258,7 +217,7 @@ class Shared extends \OC\Files\Storage\Common { 'source' => $source, ); \OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_get_contents', $info); - list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); return $storage->file_get_contents($internalPath); } } @@ -274,7 +233,7 @@ class Shared extends \OC\Files\Storage\Common { 'source' => $source, ); \OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_put_contents', $info); - list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); $result = $storage->file_put_contents($internalPath, $data); return $result; } @@ -285,7 +244,7 @@ class Shared extends \OC\Files\Storage\Common { // Delete the file if DELETE permission is granted if ($source = $this->getSourcePath($path)) { if ($this->isDeletable($path)) { - list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); return $storage->unlink($internalPath); } else if (dirname($path) == '/' || dirname($path) == '.') { // Unshare the file from the user if in the root of the Shared folder @@ -309,8 +268,8 @@ class Shared extends \OC\Files\Storage\Common { if (dirname($path1) == dirname($path2)) { // Rename the file if UPDATE permission is granted if ($this->isUpdatable($path1)) { - list($storage, $oldInternalPath)=\OC\Files\Filesystem::resolvePath($oldSource); - list( , $newInternalPath)=\OC\Files\Filesystem::resolvePath($newSource); + list($storage, $oldInternalPath) = \OC\Files\Filesystem::resolvePath($oldSource); + list( , $newInternalPath) = \OC\Files\Filesystem::resolvePath($newSource); return $storage->rename($oldInternalPath, $newInternalPath); } } else { @@ -325,8 +284,8 @@ class Shared extends \OC\Files\Storage\Common { return $this->unlink($path1); } } else { - list($storage, $oldInternalPath)=\OC\Files\Filesystem::resolvePath($oldSource); - list( , $newInternalPath)=\OC\Files\Filesystem::resolvePath($newSource); + list($storage, $oldInternalPath) = \OC\Files\Filesystem::resolvePath($oldSource); + list( , $newInternalPath) = \OC\Files\Filesystem::resolvePath($newSource); return $storage->rename($oldInternalPath, $newInternalPath); } } @@ -372,7 +331,7 @@ class Shared extends \OC\Files\Storage\Common { 'mode' => $mode, ); \OCP\Util::emitHook('\OC\Files\Storage\Shared', 'fopen', $info); - list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); return $storage->fopen($internalPath, $mode); } return false; @@ -383,7 +342,7 @@ class Shared extends \OC\Files\Storage\Common { return 'httpd/unix-directory'; } if ($source = $this->getSourcePath($path)) { - list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); return $storage->getMimeType($internalPath); } return false; @@ -392,21 +351,21 @@ class Shared extends \OC\Files\Storage\Common { public function free_space($path) { $source = $this->getSourcePath($path); if ($source) { - list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); return $storage->free_space($internalPath); } } public function getLocalFile($path) { if ($source = $this->getSourcePath($path)) { - list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); return $storage->getLocalFile($internalPath); } return false; } public function touch($path, $mtime = null) { if ($source = $this->getSourcePath($path)) { - list($storage, $internalPath)=\OC\Files\Filesystem::resolvePath($source); + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); return $storage->touch($internalPath, $mtime); } return false; @@ -417,17 +376,28 @@ class Shared extends \OC\Files\Storage\Common { \OC\Files\Filesystem::mount('\OC\Files\Storage\Shared', array('sharedFolder' => '/Shared'), $user_dir.'/Shared/'); } - /** - * check if a file or folder has been updated since $time - * @param int $time - * @return bool - */ - public function hasUpdated($path, $time) { - //TODO - return false; + public function getCache() { + return new \OC\Files\Cache\Shared_Cache($this); } - public function getId(){ - return 'shared::' . $this->sharedFolder; + public function getScanner(){ + return new \OC\Files\Cache\Shared_Scanner($this); } + + public function getPermissionsCache() { + return new \OC\Files\Cache\Shared_Permissions($this); + } + + public function getOwner($path) { + if (!isset($this->files[$path])) { + $source = \OC_Share_Backend_File::getSource($path); + $this->files[$path] = $source; + } + return $this->files[$path]['uid_owner']; + } + + public function getETag($path) { + + } + } diff --git a/lib/public/share.php b/lib/public/share.php index 9bb64a38c8..8981de1b50 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -552,7 +552,7 @@ class Share { // Get filesystem root to add it to the file target and remove from the file source, match file_source with the file cache if ($itemType == 'file' || $itemType == 'folder') { $root = \OC\Files\Filesystem::getRoot(); - $where = 'INNER JOIN `*PREFIX*fscache` ON `file_source` = `*PREFIX*fscache`.`id`'; + $where = 'INNER JOIN `*PREFIX*filecache` ON `file_source` = `*PREFIX*filecache`.`fileid`'; if (!isset($item)) { $where .= ' WHERE `file_target` IS NOT NULL'; } @@ -569,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` = ?'; @@ -681,8 +681,8 @@ class Share { } } 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`'; + if (($itemType == 'file' || $itemType == 'folder') && $format == \OC_Share_Backend_File::FORMAT_GET_FOLDER_CONTENTS) { + $select = '`*PREFIX*share`.`id`, `item_type`, `*PREFIX*share`.`parent`, `uid_owner`, `share_type`, `share_with`, `file_source`, `path`, `file_target`, `permissions`, `expiration`, `*PREFIX*filecache`.`parent` as `file_parent`, `name`, `mtime`, `mimetype`, `mimepart`, `size`, `encrypted`'; } else { $select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `item_target`, `*PREFIX*share`.`parent`, `share_type`, `share_with`, `uid_owner`, `file_source`, `path`, `file_target`, `permissions`, `stime`, `expiration`, `token`'; } From b4515d874e5259647886d148db902f9753bbeb81 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Wed, 26 Dec 2012 15:36:50 -0500 Subject: [PATCH 120/347] Only folders have Create permission --- lib/files/storage/common.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/files/storage/common.php b/lib/files/storage/common.php index c891d0c3ad..3cf960d05d 100644 --- a/lib/files/storage/common.php +++ b/lib/files/storage/common.php @@ -38,7 +38,10 @@ abstract class Common implements \OC\Files\Storage\Storage { } } public function isCreatable($path) { - return $this->isUpdatable($path); + if ($this->is_dir($path) && $this->isUpdatable($path)) { + return true; + } + return false; } public function isDeletable($path) { return $this->isUpdatable($path); From 1910057900476c5b7509a456a460d70664c01610 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Wed, 26 Dec 2012 16:20:10 -0500 Subject: [PATCH 121/347] Fix shared statuses inside folders --- apps/files_sharing/lib/share/folder.php | 4 ++-- lib/public/share.php | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/files_sharing/lib/share/folder.php b/apps/files_sharing/lib/share/folder.php index a1bb843d72..bbe4c130bd 100644 --- a/apps/files_sharing/lib/share/folder.php +++ b/apps/files_sharing/lib/share/folder.php @@ -26,11 +26,11 @@ class OC_Share_Backend_Folder extends OC_Share_Backend_File implements OCP\Share $parents = array($itemSource); while (!empty($parents)) { $parents = "'".implode("','", $parents)."'"; - $query = OC_DB::prepare('SELECT `id`, `name`, `mimetype` FROM `*PREFIX*fscache` WHERE `parent` IN ('.$parents.')'); + $query = OC_DB::prepare('SELECT `fileid`, `name`, `mimetype` FROM `*PREFIX*filecache` WHERE `parent` IN ('.$parents.')'); $result = $query->execute(); $parents = array(); while ($file = $result->fetchRow()) { - $children[] = array('source' => $file['id'], 'file_path' => $file['name']); + $children[] = array('source' => $file['fileid'], 'file_path' => $file['name']); // If a child folder is found look inside it if ($file['mimetype'] == 'httpd/unix-directory') { $parents[] = $file['id']; diff --git a/lib/public/share.php b/lib/public/share.php index 8981de1b50..2775a07f13 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -739,7 +739,8 @@ class Share { if (isset($row['parent'])) { $row['path'] = '/Shared/'.basename($row['path']); } else { - $row['path'] = substr($row['path'], $root); + // Strip 'files' from path + $row['path'] = substr($row['path'], 5); } } if (isset($row['expiration'])) { From 65f1e521079968a4450468917649b241b0fb6b24 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Thu, 27 Dec 2012 15:49:48 -0500 Subject: [PATCH 122/347] Change old is_readable to isReadable, fixes downloads --- lib/files.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/files.php b/lib/files.php index e12797bd61..15bfbc3fc2 100644 --- a/lib/files.php +++ b/lib/files.php @@ -100,7 +100,7 @@ class OC_Files { $filename = $dir . '/' . $files; } OC_Util::obEnd(); - if($zip or \OC\Files\Filesystem::is_readable($filename)) { + if ($zip or \OC\Files\Filesystem::isReadable($filename)) { if ( preg_match( "/MSIE/", $_SERVER["HTTP_USER_AGENT"] ) ) { header( 'Content-Disposition: attachment; filename="' . rawurlencode( basename($filename) ) . '"' ); } else { From b03562670973fd924a042064644994639a59667d Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Thu, 27 Dec 2012 16:53:32 -0500 Subject: [PATCH 123/347] Retrieve storage correctly, filename is not the mountpoint --- lib/files.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/files.php b/lib/files.php index 15bfbc3fc2..e1a31c6f03 100644 --- a/lib/files.php +++ b/lib/files.php @@ -117,7 +117,7 @@ class OC_Files { }else{ header('Content-Type: '.\OC\Files\Filesystem::getMimeType($filename)); header("Content-Length: ".\OC\Files\Filesystem::filesize($filename)); - $storage = \OC\Files\Filesystem::getStorage($filename); + list($storage) = \OC\Files\Filesystem::resolvePath($filename); if ($storage instanceof \OC\File\Storage\Local) { self::addSendfileHeader(\OC\Files\Filesystem::getLocalFile($filename)); } From 8bdfb040565eafb33bc27305463eb08374f14e32 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Fri, 28 Dec 2012 15:06:12 -0500 Subject: [PATCH 124/347] Fix shared folders --- apps/files_sharing/lib/cache.php | 17 ++++++++++++++--- lib/files/filesystem.php | 1 + lib/util.php | 1 - 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/apps/files_sharing/lib/cache.php b/apps/files_sharing/lib/cache.php index 196e767cf6..d2ac8ccaaa 100644 --- a/apps/files_sharing/lib/cache.php +++ b/apps/files_sharing/lib/cache.php @@ -30,6 +30,10 @@ class Shared_Cache extends Cache { private $files = array(); + public function __construct($storage) { + + } + /** * @brief Get the source cache of a shared file or folder * @param string Shared target file path @@ -41,8 +45,12 @@ class Shared_Cache extends Cache { $source['path'] = '/'.$source['uid_owner'].'/'.$source['path']; \OC\Files\Filesystem::initMountPoints($source['uid_owner']); list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source['path']); - $this->files[$target] = $internalPath; - return $storage->getCache(); + if ($storage) { + $this->files[$target] = $internalPath; + $cache = $storage->getCache(); + $this->numericId = $cache->getNumericStorageId(); + return $cache; + } } return false; } @@ -83,8 +91,11 @@ class Shared_Cache extends Cache { if ($folder == '') { return \OCP\Share::getItemsSharedWith('file', \OC_Share_Backend_File::FORMAT_GET_FOLDER_CONTENTS); } else { - return $this->getSourceCache($folder)->getFolderContents('/'.$this->files[$folder]); + if ($cache = $this->getSourceCache($folder)) { + return $cache->getFolderContents($this->files[$folder]); + } } + return false; } /** diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php index c5b56ba9f0..8183b8ff99 100644 --- a/lib/files/filesystem.php +++ b/lib/files/filesystem.php @@ -276,6 +276,7 @@ class Filesystem { } // Load personal mount points $root = \OC_User::getHome($user); + self::mount('\OC\Files\Storage\Local', array('datadir' => $root), $user); if (is_file($root.'/mount.php')) { $mountConfig = include $root.'/mount.php'; if (isset($mountConfig['user'][$user])) { diff --git a/lib/util.php b/lib/util.php index 4ebc2564d1..c5a495234d 100755 --- a/lib/util.php +++ b/lib/util.php @@ -51,7 +51,6 @@ class OC_Util { mkdir( $userdirectory, 0755, true ); } //jail the user into his "home" directory - \OC\Files\Filesystem::mount('\OC\Files\Storage\Local', array('datadir' => $user_root), $user); \OC\Files\Filesystem::init($user_dir); $quotaProxy=new OC_FileProxy_Quota(); From fb053f8e73056108acfd1574973d7b18581fc833 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Sat, 29 Dec 2012 11:09:57 -0500 Subject: [PATCH 125/347] Fix retrieving of shared source paths --- apps/files_sharing/lib/sharedstorage.php | 41 ++++++++++++++++-------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php index 960aa64099..cb9b36482f 100644 --- a/apps/files_sharing/lib/sharedstorage.php +++ b/apps/files_sharing/lib/sharedstorage.php @@ -38,19 +38,34 @@ class Shared extends \OC\Files\Storage\Common { return 'shared::' . $this->sharedFolder; } + /** + * @brief Get the source file path, permissions, and owner for a shared file + * @param string Shared target file path + * @return Returns array with the keys path, permissions, and owner or false if not found + */ + private function getFile($target) { + if (!isset($this->files[$target])) { + $source = \OC_Share_Backend_File::getSource($target); + if ($source) { + $source['path'] = '/'.$source['uid_owner'].'/'.$source['path']; + } + $this->files[$target] = $source; + } + return $this->files[$target]; + } + /** * @brief Get the source file path for a shared file * @param string Shared target file path * @return string source file path or false if not found */ private function getSourcePath($target) { - if (!isset($this->files[$target])) { - $source = \OC_Share_Backend_File::getSource($target); - $source['path'] = '/'.$source['uid_owner'].'/'.$source['path']; - $this->files[$target] = $source; + $source = $this->getFile($target); + if ($source) { \OC\Files\Filesystem::initMountPoints($source['uid_owner']); + return $source['path']; } - return $this->files[$target]['path']; + return false; } /** @@ -59,11 +74,11 @@ class Shared extends \OC\Files\Storage\Common { * @return int CRUDS permissions granted or false if not found */ public function getPermissions($target) { - if (!isset($this->files[$target])) { - $source = \OC_Share_Backend_File::getSource($target); - $this->files[$target] = $source; + $source = $this->getFile($target); + if ($source) { + return $source['permissions']; } - return $this->files[$target]['permissions']; + return false; } public function mkdir($path) { @@ -389,11 +404,11 @@ class Shared extends \OC\Files\Storage\Common { } public function getOwner($path) { - if (!isset($this->files[$path])) { - $source = \OC_Share_Backend_File::getSource($path); - $this->files[$path] = $source; + $source = $this->getFile($path); + if ($source) { + return $source['uid_owner']; } - return $this->files[$path]['uid_owner']; + return false; } public function getETag($path) { From cfc3526b25f1b96ab7a989f1c89f5b3911bc18fc Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Sat, 29 Dec 2012 11:45:13 -0500 Subject: [PATCH 126/347] Fix data for shared root folder --- apps/files_sharing/lib/cache.php | 4 +++- apps/files_sharing/lib/permissions.php | 3 +++ apps/files_sharing/lib/share/file.php | 26 +++++++++++++++++++------- lib/public/share.php | 2 +- 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/apps/files_sharing/lib/cache.php b/apps/files_sharing/lib/cache.php index d2ac8ccaaa..a22e7af7f5 100644 --- a/apps/files_sharing/lib/cache.php +++ b/apps/files_sharing/lib/cache.php @@ -62,7 +62,9 @@ class Shared_Cache extends Cache { * @return array */ public function get($file) { - if (is_string($file)) { + if ($file == '') { + return \OCP\Share::getItemsSharedWith('file', \OC_Share_Backend_File::FORMAT_FILE_APP_ROOT); + } else if (is_string($file)) { if ($cache = $this->getSourceCache($file)) { return $cache->get($this->files[$file]); } diff --git a/apps/files_sharing/lib/permissions.php b/apps/files_sharing/lib/permissions.php index 51ae4cf102..6eaed34b33 100644 --- a/apps/files_sharing/lib/permissions.php +++ b/apps/files_sharing/lib/permissions.php @@ -30,6 +30,9 @@ class Shared_Permissions { * @return int (-1 if file no permissions set) */ static public function get($fileId, $user) { + if ($fileId == -1) { + return \OCP\PERMISSION_READ; + } $source = \OCP\Share::getItemSharedWithBySource('file', $fileId, \OC_Share_Backend_File::FORMAT_SHARED_STORAGE); if ($source) { return $source['permissions']; diff --git a/apps/files_sharing/lib/share/file.php b/apps/files_sharing/lib/share/file.php index 52220dc5b2..5e98c455d3 100644 --- a/apps/files_sharing/lib/share/file.php +++ b/apps/files_sharing/lib/share/file.php @@ -23,8 +23,9 @@ class OC_Share_Backend_File implements OCP\Share_Backend_File_Dependent { const FORMAT_SHARED_STORAGE = 0; const FORMAT_GET_FOLDER_CONTENTS = 1; - const FORMAT_GET_ALL = 2; + const FORMAT_FILE_APP_ROOT = 2; const FORMAT_OPENDIR = 3; + const FORMAT_GET_ALL = 4; private $path; @@ -82,24 +83,35 @@ class OC_Share_Backend_File implements OCP\Share_Backend_File_Dependent { $file['parent'] = $item['file_parent']; $file['name'] = basename($item['file_target']); $file['mimetype'] = $item['mimetype']; + $file['mimepart'] = $item['mimepart']; $file['size'] = $item['size']; $file['mtime'] = $item['mtime']; $file['encrypted'] = $item['encrypted']; $files[] = $file; } return $files; + } else if ($format == self::FORMAT_FILE_APP_ROOT) { + $mtime = 0; + $size = 0; + foreach ($items as $item) { + if ($item['mtime'] > $mtime) { + $mtime = $item['mtime']; + } + $size += (int)$item['size']; + } + return array('fileid' => -1, 'name' => 'Shared', 'mtime' => $mtime, 'mimetype' => 'httpd/unix-directory', 'size' => $size); + } else if ($format == self::FORMAT_OPENDIR) { + $files = array(); + foreach ($items as $item) { + $files[] = basename($item['file_target']); + } + return $files; } else if ($format == self::FORMAT_GET_ALL) { $ids = array(); foreach ($items as $item) { $ids[] = $item['file_source']; } return $ids; - } else if ($format == self::FORMAT_OPENDIR) { - $files = array(); - foreach ($items as $item) { - $files[] = basename($item['file_target']); - } - return $files; } return array(); } diff --git a/lib/public/share.php b/lib/public/share.php index 2775a07f13..e438386ca3 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -681,7 +681,7 @@ class Share { } } else { if ($fileDependent) { - if (($itemType == 'file' || $itemType == 'folder') && $format == \OC_Share_Backend_File::FORMAT_GET_FOLDER_CONTENTS) { + if (($itemType == 'file' || $itemType == 'folder') && $format == \OC_Share_Backend_File::FORMAT_GET_FOLDER_CONTENTS || $format == \OC_Share_Backend_File::FORMAT_FILE_APP_ROOT) { $select = '`*PREFIX*share`.`id`, `item_type`, `*PREFIX*share`.`parent`, `uid_owner`, `share_type`, `share_with`, `file_source`, `path`, `file_target`, `permissions`, `expiration`, `*PREFIX*filecache`.`parent` as `file_parent`, `name`, `mtime`, `mimetype`, `mimepart`, `size`, `encrypted`'; } else { $select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `item_target`, `*PREFIX*share`.`parent`, `share_type`, `share_with`, `uid_owner`, `file_source`, `path`, `file_target`, `permissions`, `stime`, `expiration`, `token`'; From d275725e233092f21247a62bde3e46a352d5a1b5 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Sat, 29 Dec 2012 13:43:44 -0500 Subject: [PATCH 127/347] No longer need to create folders locally for external storage mount points --- apps/files_external/lib/config.php | 41 ------------------------------ 1 file changed, 41 deletions(-) diff --git a/apps/files_external/lib/config.php b/apps/files_external/lib/config.php index 0e0bc56ad0..323e4060a4 100755 --- a/apps/files_external/lib/config.php +++ b/apps/files_external/lib/config.php @@ -178,22 +178,6 @@ class OC_Mount_Config { return $personal; } - /** - * Add directory for mount point to the filesystem - * @param OC_Fileview instance $view - * @param string path to mount point - */ - private static function addMountPointDirectory($view, $path) { - $dir = ''; - foreach ( explode('/', $path) as $pathPart) { - $dir = $dir.'/'.$pathPart; - if ( !$view->file_exists($dir)) { - $view->mkdir($dir); - } - } - } - - /** * Add a mount point to the filesystem * @param string Mount point @@ -216,33 +200,8 @@ class OC_Mount_Config { if ($applicable != OCP\User::getUser() || $class == '\OC\Files\Storage\Local') { return false; } - $view = new \OC\Files\View('/'.OCP\User::getUser().'/files'); - self::addMountPointDirectory($view, ltrim($mountPoint, '/')); $mountPoint = '/'.$applicable.'/files/'.ltrim($mountPoint, '/'); } else { - $view = new \OC\Files\View('/'); - switch ($mountType) { - case 'user': - if ($applicable == "all") { - $users = OCP\User::getUsers(); - foreach ( $users as $user ) { - $path = $user.'/files/'.ltrim($mountPoint, '/'); - self::addMountPointDirectory($view, $path); - } - } else { - $path = $applicable.'/files/'.ltrim($mountPoint, '/'); - self::addMountPointDirectory($view, $path); - } - break; - case 'group' : - $groupMembers = OC_Group::usersInGroups(array($applicable)); - foreach ( $groupMembers as $user ) { - $path = $user.'/files/'.ltrim($mountPoint, '/'); - self::addMountPointDirectory($view, $path); - } - break; - } - $mountPoint = '/$user/files/'.ltrim($mountPoint, '/'); } $mount = array($applicable => array($mountPoint => array('class' => $class, 'options' => $classOptions))); From 2c23e143d33e231e62dccb450bf1f1b0f3938ccd Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Sun, 30 Dec 2012 16:32:55 -0500 Subject: [PATCH 128/347] Store etags in the file cache --- db_structure.xml | 8 ++++++++ lib/files/cache/cache.php | 10 +++++----- lib/files/cache/scanner.php | 1 + lib/util.php | 2 +- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/db_structure.xml b/db_structure.xml index aa0916264c..7c67ca78f4 100644 --- a/db_structure.xml +++ b/db_structure.xml @@ -189,6 +189,14 @@ 4 + + etag + text + + true + 250 + + storage_path_hash true diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index 3ebae9baa5..d105f865eb 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -76,7 +76,7 @@ class Cache { $params = array($file); } $query = \OC_DB::prepare( - 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted` + 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag` FROM `*PREFIX*filecache` ' . $where); $result = $query->execute($params); $data = $result->fetchRow(); @@ -107,7 +107,7 @@ class Cache { $fileId = $this->getId($folder); if ($fileId > -1) { $query = \OC_DB::prepare( - 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted` + 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag` FROM `*PREFIX*filecache` WHERE parent = ? ORDER BY `name` ASC'); $result = $query->execute(array($fileId)); return $result->fetchAll(); @@ -180,7 +180,7 @@ class Cache { * @return array */ static function buildParts(array $data) { - $fields = array('path', 'parent', 'name', 'mimetype', 'size', 'mtime', 'encrypted'); + $fields = array('path', 'parent', 'name', 'mimetype', 'size', 'mtime', 'encrypted', 'etag'); $params = array(); $queryParts = array(); @@ -333,7 +333,7 @@ class Cache { */ public function search($pattern) { $query = \OC_DB::prepare(' - SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted` + SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag` FROM `*PREFIX*filecache` WHERE `name` LIKE ? AND `storage` = ?' ); $result = $query->execute(array($pattern, $this->numericId)); @@ -357,7 +357,7 @@ class Cache { $where = '`mimepart` = ?'; } $query = \OC_DB::prepare(' - SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted` + SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted`, `etag` FROM `*PREFIX*filecache` WHERE ' . $where . ' AND `storage` = ?' ); $result = $query->execute(array($mimetype, $this->numericId)); diff --git a/lib/files/cache/scanner.php b/lib/files/cache/scanner.php index 4c0ec9617f..e7bfb1898e 100644 --- a/lib/files/cache/scanner.php +++ b/lib/files/cache/scanner.php @@ -58,6 +58,7 @@ class Scanner { $data['size'] = $this->storage->filesize($path); $data['permissions'] = $this->storage->getPermissions($path); } + $data['etag'] = $this->storage->getETag($path); return $data; } diff --git a/lib/util.php b/lib/util.php index c5a495234d..df26a825d1 100755 --- a/lib/util.php +++ b/lib/util.php @@ -74,7 +74,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,04); + return array(4,91,05); } /** From a5cb7363a5031d25d3e4cbd46817930c19893143 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Sun, 30 Dec 2012 19:18:05 -0500 Subject: [PATCH 129/347] Use etags from file cache in SabreDAV connector --- lib/connector/sabre/directory.php | 2 +- lib/connector/sabre/node.php | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/connector/sabre/directory.php b/lib/connector/sabre/directory.php index 8d4dd92a3d..a720157936 100644 --- a/lib/connector/sabre/directory.php +++ b/lib/connector/sabre/directory.php @@ -121,8 +121,8 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa $paths = array(); foreach($folder_content as $info) { $paths[] = $this->path.'/'.$info['name']; + $properties[$this->path.'/'.$info['name']][self::GETETAG_PROPERTYNAME] = $info['etag']; } - $properties = array_fill_keys($paths, array()); if(count($paths)>0) { // // the number of arguments within IN conditions are limited in most databases diff --git a/lib/connector/sabre/node.php b/lib/connector/sabre/node.php index ad08bd434f..d4023dfad7 100644 --- a/lib/connector/sabre/node.php +++ b/lib/connector/sabre/node.php @@ -190,6 +190,7 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr while( $row = $result->fetchRow()) { $this->property_cache[$row['propertyname']] = $row['propertyvalue']; } + $this->property_cache[self::GETETAG_PROPERTYNAME] = $this->getETagPropertyForPath($this->path); } // if the array was empty, we need to return everything @@ -210,14 +211,11 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr * @return string|null Returns null if the ETag can not effectively be determined */ static public function getETagPropertyForPath($path) { - $tag = \OC\Files\Filesystem::getETag($path); - if (empty($tag)) { - return null; + $data = \OC\Files\Filesystem::getFileInfo($path); + if (isset($data['etag'])) { + return $data['etag']; } - $etag = '"'.$tag.'"'; - $query = OC_DB::prepare( 'INSERT INTO `*PREFIX*properties` (`userid`,`propertypath`,`propertyname`,`propertyvalue`) VALUES(?,?,?,?)' ); - $query->execute( array( OC_User::getUser(), $path, self::GETETAG_PROPERTYNAME, $etag )); - return $etag; + return null; } /** From 83064aca51db7d8382282743ade2ab9da2a6e1b0 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Sun, 30 Dec 2012 19:23:31 -0500 Subject: [PATCH 130/347] Remove old etag code --- lib/connector/sabre/node.php | 24 ------------------------ lib/files/filesystem.php | 21 --------------------- lib/files/view.php | 2 -- lib/filesystem.php | 7 ------- 4 files changed, 54 deletions(-) diff --git a/lib/connector/sabre/node.php b/lib/connector/sabre/node.php index d4023dfad7..dd8ae152ff 100644 --- a/lib/connector/sabre/node.php +++ b/lib/connector/sabre/node.php @@ -218,28 +218,4 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr return null; } - /** - * @brief Remove the ETag from the cache. - * @param string $path Path of the file - */ - static public function removeETagPropertyForPath($path) { - // remove tags from this and parent paths - $paths = array(); - while ($path != '/' && $path != '.' && $path != '' && $path != '\\') { - $paths[] = $path; - $path = dirname($path); - } - if (empty($paths)) { - return; - } - $paths[] = $path; - $path_placeholders = join(',', array_fill(0, count($paths), '?')); - $query = OC_DB::prepare( 'DELETE FROM `*PREFIX*properties`' - .' WHERE `userid` = ?' - .' AND `propertyname` = ?' - .' AND `propertypath` IN ('.$path_placeholders.')' - ); - $vals = array( OC_User::getUser(), self::GETETAG_PROPERTYNAME ); - $query->execute(array_merge( $vals, $paths )); - } } diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php index 8183b8ff99..d62b5186cb 100644 --- a/lib/files/filesystem.php +++ b/lib/files/filesystem.php @@ -582,23 +582,6 @@ class Filesystem { return self::$defaultInstance->hasUpdated($path, $time); } - static public function removeETagHook($params, $root = false) { - if (isset($params['path'])) { - $path = $params['path']; - } else { - $path = $params['oldpath']; - } - - if ($root) { // reduce path to the required part of it (no 'username/files') - $fakeRootView = new View($root); - $count = 1; - $path = str_replace(\OC_App::getStorage("files")->getAbsolutePath(''), "", $fakeRootView->getAbsolutePath($path), $count); - } - - $path = self::normalizePath($path); - \OC_Connector_Sabre_Node::removeETagPropertyForPath($path); - } - /** * normalize a path * @@ -682,10 +665,6 @@ class Filesystem { } } -\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\Files\Cache\Updater', 'writeHook'); \OC_Hook::connect('OC_Filesystem', 'post_delete', '\OC\Files\Cache\Updater', 'deleteHook'); \OC_Hook::connect('OC_Filesystem', 'post_rename', '\OC\Files\Cache\Updater', 'renameHook'); diff --git a/lib/files/view.php b/lib/files/view.php index 592c484a21..77146895e6 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -462,8 +462,6 @@ class View { Filesystem::signal_post_write, array(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 - Filesystem::removeETagHook(array("path" => $path2), $this->fakeRoot); } return $result; } else { diff --git a/lib/filesystem.php b/lib/filesystem.php index 20b5ab2790..57cca90230 100644 --- a/lib/filesystem.php +++ b/lib/filesystem.php @@ -398,13 +398,6 @@ class OC_Filesystem { return \OC\Files\Filesystem::hasUpdated($path, $time); } - /** - * @deprecated OC_Filesystem is replaced by \OC\Files\Filesystem - */ - static public function removeETagHook($params, $root = false) { - \OC\Files\Filesystem::removeETagHook($params, $root); - } - /** * normalize a path * From 77f12c526bf0010219e363844b588ffae27f1251 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Sun, 30 Dec 2012 19:54:51 -0500 Subject: [PATCH 131/347] Update etags in parent folders --- lib/files/cache/updater.php | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/lib/files/cache/updater.php b/lib/files/cache/updater.php index fb9783023e..d57e4a1abe 100644 --- a/lib/files/cache/updater.php +++ b/lib/files/cache/updater.php @@ -34,6 +34,7 @@ class Updater { $scanner = new Scanner($storage); $scanner->scan($internalPath, Scanner::SCAN_SHALLOW); $cache->correctFolderSize($internalPath); + self::eTagUpdate($path); } static public function deleteUpdate($path) { @@ -45,6 +46,29 @@ class Updater { $cache = new Cache($storage); $cache->remove($internalPath); $cache->correctFolderSize($internalPath); + self::eTagUpdate($path); + } + + static public function eTagUpdate($path) { + if ($path !== '') { + $parent = dirname($path); + if ($parent === '.') { + $parent = ''; + } + /** + * @var \OC\Files\Storage\Storage $storage + * @var string $internalPath + */ + list($storage, $internalPath) = self::resolvePath($parent); + if ($storage) { + $cache = $storage->getCache(); + $id = $cache->getId($internalPath); + if ($id !== -1) { + $cache->update($id, array('etag' => $storage->getETag($internalPath))); + self::updateFolderETags($parent); + } + } + } } /** From 3ee3323b8766992a0b60bb76b909e49fc1ea76d2 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Sun, 30 Dec 2012 20:27:38 -0500 Subject: [PATCH 132/347] Fix retrieving of cache and scanner in Updater class --- lib/files/cache/updater.php | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/files/cache/updater.php b/lib/files/cache/updater.php index fb9783023e..c8c96a97ee 100644 --- a/lib/files/cache/updater.php +++ b/lib/files/cache/updater.php @@ -30,10 +30,12 @@ class Updater { * @var string $internalPath */ list($storage, $internalPath) = self::resolvePath($path); - $cache = new Cache($storage); - $scanner = new Scanner($storage); - $scanner->scan($internalPath, Scanner::SCAN_SHALLOW); - $cache->correctFolderSize($internalPath); + if ($storage) { + $cache = $storage->getCache(); + $scanner = $storage->getScanner(); + $scanner->scan($internalPath, Scanner::SCAN_SHALLOW); + $cache->correctFolderSize($internalPath); + } } static public function deleteUpdate($path) { @@ -42,9 +44,11 @@ class Updater { * @var string $internalPath */ list($storage, $internalPath) = self::resolvePath($path); - $cache = new Cache($storage); - $cache->remove($internalPath); - $cache->correctFolderSize($internalPath); + if ($storage) { + $cache = $storage->getCache(); + $cache->remove($internalPath); + $cache->correctFolderSize($internalPath); + } } /** From 96e08a1d962b42782d03721009970cbab352eec2 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Sun, 30 Dec 2012 21:23:17 -0500 Subject: [PATCH 133/347] Fix function name --- lib/files/cache/updater.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/files/cache/updater.php b/lib/files/cache/updater.php index d57e4a1abe..7fc9bd382f 100644 --- a/lib/files/cache/updater.php +++ b/lib/files/cache/updater.php @@ -65,7 +65,7 @@ class Updater { $id = $cache->getId($internalPath); if ($id !== -1) { $cache->update($id, array('etag' => $storage->getETag($internalPath))); - self::updateFolderETags($parent); + self::eTagUpdate($parent); } } } From 29b82ccdf32f8a13723e7f49be0c3cbf7e64a404 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Sun, 30 Dec 2012 21:23:54 -0500 Subject: [PATCH 134/347] Change length of etag field to 40 --- db_structure.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db_structure.xml b/db_structure.xml index 7c67ca78f4..527b53040d 100644 --- a/db_structure.xml +++ b/db_structure.xml @@ -194,7 +194,7 @@ text true - 250 + 40 From d0a50fae8317e4b4871027ee4b2940ab5443961f Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Mon, 31 Dec 2012 18:16:44 -0500 Subject: [PATCH 135/347] Fix eTagUpdate and add tests --- lib/files/cache/updater.php | 2 +- tests/lib/files/cache/updater.php | 28 ++++++++++++++++++++++------ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/lib/files/cache/updater.php b/lib/files/cache/updater.php index 2604159009..cfc1ec731e 100644 --- a/lib/files/cache/updater.php +++ b/lib/files/cache/updater.php @@ -54,7 +54,7 @@ class Updater { } static public function eTagUpdate($path) { - if ($path !== '') { + if ($path !== '' && $path !== '/') { $parent = dirname($path); if ($parent === '.') { $parent = ''; diff --git a/tests/lib/files/cache/updater.php b/tests/lib/files/cache/updater.php index d19966c191..cad3d9d46f 100644 --- a/tests/lib/files/cache/updater.php +++ b/tests/lib/files/cache/updater.php @@ -70,14 +70,18 @@ class Updater extends \PHPUnit_Framework_TestCase { public function testWrite() { $textSize = strlen("dummy file data\n"); $imageSize = filesize(\OC::$SERVERROOT . '/core/img/logo.png'); - $cachedData = $this->cache->get(''); - $this->assertEquals(3 * $textSize + $imageSize, $cachedData['size']); + $rootCachedData = $this->cache->get(''); + $this->assertEquals(3 * $textSize + $imageSize, $rootCachedData['size']); + $fooCachedData = $this->cache->get('foo.txt'); Filesystem::file_put_contents('foo.txt', 'asd'); $cachedData = $this->cache->get('foo.txt'); $this->assertEquals(3, $cachedData['size']); + $this->assertNotEquals($fooCachedData['etag'], $cachedData['etag']); $cachedData = $this->cache->get(''); $this->assertEquals(2 * $textSize + $imageSize + 3, $cachedData['size']); + $this->assertNotEquals($rootCachedData['etag'], $cachedData['etag']); + $rootCachedData = $cachedData; $this->assertFalse($this->cache->inCache('bar.txt')); Filesystem::file_put_contents('bar.txt', 'asd'); @@ -86,38 +90,50 @@ class Updater extends \PHPUnit_Framework_TestCase { $this->assertEquals(3, $cachedData['size']); $cachedData = $this->cache->get(''); $this->assertEquals(2 * $textSize + $imageSize + 2 * 3, $cachedData['size']); + $this->assertNotEquals($rootCachedData['etag'], $cachedData['etag']); } public function testDelete() { $textSize = strlen("dummy file data\n"); $imageSize = filesize(\OC::$SERVERROOT . '/core/img/logo.png'); - $cachedData = $this->cache->get(''); - $this->assertEquals(3 * $textSize + $imageSize, $cachedData['size']); + $rootCachedData = $this->cache->get(''); + $this->assertEquals(3 * $textSize + $imageSize, $rootCachedData['size']); $this->assertTrue($this->cache->inCache('foo.txt')); Filesystem::unlink('foo.txt', 'asd'); $this->assertFalse($this->cache->inCache('foo.txt')); $cachedData = $this->cache->get(''); $this->assertEquals(2 * $textSize + $imageSize, $cachedData['size']); + $this->assertNotEquals($rootCachedData['etag'], $cachedData['etag']); + $rootCachedData = $cachedData; Filesystem::mkdir('bar_folder'); $this->assertTrue($this->cache->inCache('bar_folder')); + $cachedData = $this->cache->get(''); + $this->assertNotEquals($rootCachedData['etag'], $cachedData['etag']); + $rootCachedData = $cachedData; Filesystem::rmdir('bar_folder'); $this->assertFalse($this->cache->inCache('bar_folder')); + $cachedData = $this->cache->get(''); + $this->assertNotEquals($rootCachedData['etag'], $cachedData['etag']); } public function testRename() { $textSize = strlen("dummy file data\n"); $imageSize = filesize(\OC::$SERVERROOT . '/core/img/logo.png'); - $cachedData = $this->cache->get(''); - $this->assertEquals(3 * $textSize + $imageSize, $cachedData['size']); + $rootCachedData = $this->cache->get(''); + $this->assertEquals(3 * $textSize + $imageSize, $rootCachedData['size']); $this->assertTrue($this->cache->inCache('foo.txt')); + $fooCachedData = $this->cache->get('foo.txt'); $this->assertFalse($this->cache->inCache('bar.txt')); Filesystem::rename('foo.txt', 'bar.txt'); $this->assertFalse($this->cache->inCache('foo.txt')); $this->assertTrue($this->cache->inCache('bar.txt')); + $cachedData = $this->cache->get('foo.txt'); + $this->assertNotEquals($fooCachedData['etag'], $cachedData['etag']); $cachedData = $this->cache->get(''); $this->assertEquals(3 * $textSize + $imageSize, $cachedData['size']); + $this->assertNotEquals($rootCachedData['etag'], $cachedData['etag']); } } From f2ca7023e1ece60dc3cebc5cd770c7373f53c93a Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Tue, 1 Jan 2013 11:19:33 -0500 Subject: [PATCH 136/347] Fix Shared root problems with Watcher and Quota proxy --- apps/files_sharing/lib/cache.php | 3 +++ apps/files_sharing/lib/sharedstorage.php | 13 +++++++++++++ lib/fileproxy/quota.php | 4 +++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/apps/files_sharing/lib/cache.php b/apps/files_sharing/lib/cache.php index a22e7af7f5..60f29ce5ee 100644 --- a/apps/files_sharing/lib/cache.php +++ b/apps/files_sharing/lib/cache.php @@ -169,6 +169,9 @@ class Shared_Cache extends Cache { * @return int, Cache::NOT_FOUND, Cache::PARTIAL, Cache::SHALLOW or Cache::COMPLETE */ public function getStatus($file) { + if ($file == '') { + return self::COMPLETE; + } if ($cache = $this->getSourceCache($file)) { return $cache->getStatus($this->files[$file]); } diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php index cb9b36482f..3a1d7ef101 100644 --- a/apps/files_sharing/lib/sharedstorage.php +++ b/apps/files_sharing/lib/sharedstorage.php @@ -364,6 +364,9 @@ class Shared extends \OC\Files\Storage\Common { } public function free_space($path) { + if ($path == '') { + return -1; + } $source = $this->getSourcePath($path); if ($source) { list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); @@ -391,6 +394,13 @@ class Shared extends \OC\Files\Storage\Common { \OC\Files\Filesystem::mount('\OC\Files\Storage\Shared', array('sharedFolder' => '/Shared'), $user_dir.'/Shared/'); } + public function hasUpdated($path, $time) { + if ($path == '') { + return false; + } + return $this->filemtime($path) > $time; + } + public function getCache() { return new \OC\Files\Cache\Shared_Cache($this); } @@ -404,6 +414,9 @@ class Shared extends \OC\Files\Storage\Common { } public function getOwner($path) { + if ($path == '') { + return false; + } $source = $this->getFile($path); if ($source) { return $source['uid_owner']; diff --git a/lib/fileproxy/quota.php b/lib/fileproxy/quota.php index 80270728ab..c333efa6cd 100644 --- a/lib/fileproxy/quota.php +++ b/lib/fileproxy/quota.php @@ -63,6 +63,9 @@ class OC_FileProxy_Quota extends OC_FileProxy{ */ list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($path); $owner=$storage->getOwner($internalPath); + if (!$owner) { + return -1; + } $totalSpace=$this->getQuota($owner); if($totalSpace==-1) { @@ -73,7 +76,6 @@ class OC_FileProxy_Quota extends OC_FileProxy{ $rootInfo=$view->getFileInfo('/'); $usedSpace=isset($rootInfo['size'])?$rootInfo['size']:0; - $usedSpace=isset($sharedInfo['size'])?$usedSpace-$sharedInfo['size']:$usedSpace; return $totalSpace-$usedSpace; } From b41189de4420ea8a48adaaf7bb59f9227124b70a Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 1 Jan 2013 18:04:29 +0100 Subject: [PATCH 137/347] Cache: allow storage backends to overwrite Watcher --- lib/files/storage/common.php | 7 +++++++ lib/files/storage/storage.php | 5 +++++ lib/files/view.php | 4 ++-- tests/lib/files/cache/watcher.php | 14 +++++++------- 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/lib/files/storage/common.php b/lib/files/storage/common.php index 3cf960d05d..ab167f2864 100644 --- a/lib/files/storage/common.php +++ b/lib/files/storage/common.php @@ -249,6 +249,13 @@ abstract class Common implements \OC\Files\Storage\Storage { return new \OC\Files\Cache\Permissions($this); } + /** + * @return \OC\Files\Cache\Watcher + */ + public function getWatcher(){ + return new \OC\Files\Cache\Watcher($this); + } + /** * get the owner of a path * @param string $path The path to get the owner diff --git a/lib/files/storage/storage.php b/lib/files/storage/storage.php index 73dcb8fe36..b603381dc9 100644 --- a/lib/files/storage/storage.php +++ b/lib/files/storage/storage.php @@ -69,6 +69,11 @@ interface Storage{ */ public function getPermissionsCache(); + /** + * @return \OC\Files\Cache\Watcher + */ + public function getWatcher(); + /** * get the ETag for a file or folder * diff --git a/lib/files/view.php b/lib/files/view.php index 592c484a21..d3f93d39f5 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -685,7 +685,7 @@ class View { $scanner = $storage->getScanner(); $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW); } else { - $watcher = new \OC\Files\Cache\Watcher($storage); + $watcher = $storage->getWatcher(); $watcher->checkUpdate($internalPath); } @@ -733,7 +733,7 @@ class View { $scanner = $storage->getScanner(); $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW); } else { - $watcher = new \OC\Files\Cache\Watcher($storage); + $watcher = $storage->getWatcher(); $watcher->checkUpdate($internalPath); } diff --git a/tests/lib/files/cache/watcher.php b/tests/lib/files/cache/watcher.php index 07c8ac3640..e8a1689cab 100644 --- a/tests/lib/files/cache/watcher.php +++ b/tests/lib/files/cache/watcher.php @@ -32,7 +32,7 @@ class Watcher extends \PHPUnit_Framework_TestCase { function testWatcher() { $storage = $this->getTestStorage(); $cache = $storage->getCache(); - $updater = new \OC\Files\Cache\Watcher($storage); + $updater = $storage->getWatcher(); //set the mtime to the past so it can detect an mtime change $cache->put('', array('mtime' => 10)); @@ -66,16 +66,16 @@ class Watcher extends \PHPUnit_Framework_TestCase { public function testFileToFolder() { $storage = $this->getTestStorage(); $cache = $storage->getCache(); - $updater = new \OC\Files\Cache\Watcher($storage); + $updater = $storage->getWatcher(); //set the mtime to the past so it can detect an mtime change $cache->put('', array('mtime' => 10)); $storage->unlink('foo.txt'); - $storage->rename('folder','foo.txt'); + $storage->rename('folder', 'foo.txt'); $updater->checkUpdate(''); - $entry= $cache->get('foo.txt'); + $entry = $cache->get('foo.txt'); $this->assertEquals(-1, $entry['size']); $this->assertEquals('httpd/unix-directory', $entry['mimetype']); $this->assertFalse($cache->inCache('folder')); @@ -83,16 +83,16 @@ class Watcher extends \PHPUnit_Framework_TestCase { $storage = $this->getTestStorage(); $cache = $storage->getCache(); - $updater = new \OC\Files\Cache\Watcher($storage); + $updater = $storage->getWatcher(); //set the mtime to the past so it can detect an mtime change $cache->put('foo.txt', array('mtime' => 10)); $storage->unlink('foo.txt'); - $storage->rename('folder','foo.txt'); + $storage->rename('folder', 'foo.txt'); $updater->checkUpdate('foo.txt'); - $entry= $cache->get('foo.txt'); + $entry = $cache->get('foo.txt'); $this->assertEquals('httpd/unix-directory', $entry['mimetype']); $this->assertTrue($cache->inCache('foo.txt/bar.txt')); } From 4b65dd608a70117141c52749f4a06e6c5466ff7b Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 1 Jan 2013 18:07:10 +0100 Subject: [PATCH 138/347] Share: small phpdoc fixes --- apps/files_sharing/lib/cache.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/files_sharing/lib/cache.php b/apps/files_sharing/lib/cache.php index 60f29ce5ee..679e42d94d 100644 --- a/apps/files_sharing/lib/cache.php +++ b/apps/files_sharing/lib/cache.php @@ -36,8 +36,8 @@ class Shared_Cache extends Cache { /** * @brief Get the source cache of a shared file or folder - * @param string Shared target file path - * @return \OC\Files\Storage\Cache + * @param string $target Shared target file path + * @return \OC\Files\Cache\Cache */ private function getSourceCache($target) { $source = \OC_Share_Backend_File::getSource($target); @@ -230,7 +230,7 @@ class Shared_Cache extends Cache { * @return int[] */ public function getAll() { - return OCP\Share::getItemsSharedWith('file', \OC_Share_Backend_File::FORMAT_GET_ALL); + return \OCP\Share::getItemsSharedWith('file', \OC_Share_Backend_File::FORMAT_GET_ALL); } -} \ No newline at end of file +} From 0ac78a64110b628832d94061c78fb8f1b89405cb Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 1 Jan 2013 18:10:38 +0100 Subject: [PATCH 139/347] Share: fix cache put function --- apps/files_sharing/lib/cache.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_sharing/lib/cache.php b/apps/files_sharing/lib/cache.php index 679e42d94d..07c305bb95 100644 --- a/apps/files_sharing/lib/cache.php +++ b/apps/files_sharing/lib/cache.php @@ -110,7 +110,7 @@ class Shared_Cache extends Cache { */ public function put($file, array $data) { if ($cache = $this->getSourceCache($file)) { - return $cache->put($this->files[$file]); + return $cache->put($this->files[$file], $data); } return false; } From f4e4a06826459befc4a7df429fe02081a14348f3 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Tue, 1 Jan 2013 11:26:04 -0500 Subject: [PATCH 140/347] Forgot to select storage from filecache --- lib/public/share.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/public/share.php b/lib/public/share.php index e438386ca3..c74960b94c 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -682,7 +682,7 @@ class Share { } else { if ($fileDependent) { if (($itemType == 'file' || $itemType == 'folder') && $format == \OC_Share_Backend_File::FORMAT_GET_FOLDER_CONTENTS || $format == \OC_Share_Backend_File::FORMAT_FILE_APP_ROOT) { - $select = '`*PREFIX*share`.`id`, `item_type`, `*PREFIX*share`.`parent`, `uid_owner`, `share_type`, `share_with`, `file_source`, `path`, `file_target`, `permissions`, `expiration`, `*PREFIX*filecache`.`parent` as `file_parent`, `name`, `mtime`, `mimetype`, `mimepart`, `size`, `encrypted`'; + $select = '`*PREFIX*share`.`id`, `item_type`, `*PREFIX*share`.`parent`, `uid_owner`, `share_type`, `share_with`, `file_source`, `path`, `file_target`, `permissions`, `expiration`, `storage`, `*PREFIX*filecache`.`parent` as `file_parent`, `name`, `mtime`, `mimetype`, `mimepart`, `size`, `encrypted`'; } else { $select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `item_target`, `*PREFIX*share`.`parent`, `share_type`, `share_with`, `uid_owner`, `file_source`, `path`, `file_target`, `permissions`, `stime`, `expiration`, `token`'; } From 3b67613afc6d0b74c0e49e567f5e22ec020172d3 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Tue, 1 Jan 2013 12:43:38 -0500 Subject: [PATCH 141/347] Remove Shared_Scanner and add Shared_Watcher instead --- apps/files_sharing/appinfo/app.php | 2 +- apps/files_sharing/lib/scanner.php | 69 ------------------------ apps/files_sharing/lib/sharedstorage.php | 8 +-- 3 files changed, 5 insertions(+), 74 deletions(-) delete mode 100644 apps/files_sharing/lib/scanner.php diff --git a/apps/files_sharing/appinfo/app.php b/apps/files_sharing/appinfo/app.php index 189fd20cae..d3e05cc62d 100644 --- a/apps/files_sharing/appinfo/app.php +++ b/apps/files_sharing/appinfo/app.php @@ -5,7 +5,7 @@ OC::$CLASSPATH['OC_Share_Backend_Folder'] = 'apps/files_sharing/lib/share/folder OC::$CLASSPATH['OC\Files\Storage\Shared'] = "apps/files_sharing/lib/sharedstorage.php"; OC::$CLASSPATH['OC\Files\Cache\Shared_Cache'] = 'apps/files_sharing/lib/cache.php'; OC::$CLASSPATH['OC\Files\Cache\Shared_Permissions'] = 'apps/files_sharing/lib/permissions.php'; -OC::$CLASSPATH['OC\Files\Cache\Shared_Scanner'] = 'apps/files_sharing/lib/scanner.php'; +OC::$CLASSPATH['OC\Files\Cache\Shared_Watcher'] = 'apps/files_sharing/lib/watcher.php'; OCP\Util::connectHook('OC_Filesystem', 'setup', '\OC\Files\Storage\Shared', 'setup'); OCP\Share::registerBackend('file', 'OC_Share_Backend_File'); OCP\Share::registerBackend('folder', 'OC_Share_Backend_Folder', 'file'); diff --git a/apps/files_sharing/lib/scanner.php b/apps/files_sharing/lib/scanner.php deleted file mode 100644 index d13d2f9cbc..0000000000 --- a/apps/files_sharing/lib/scanner.php +++ /dev/null @@ -1,69 +0,0 @@ -. -*/ - -namespace OC\Files\Cache; - -class Shared_Scanner extends Scanner { - - public function __construct(\OC\Files\Storage\Storage $storage) { - - } - - /** - * get all the metadata of a file or folder - * * - * - * @param string $path - * @return array with metadata of the file - */ - public function getData($path) { - // Not a valid action for Shared Scanner - } - - /** - * scan a single file and store it in the cache - * - * @param string $file - * @return array with metadata of the scanned file - */ - public function scanFile($file) { - // Not a valid action for Shared Scanner - } - - /** - * scan all the files in a folder and store them in the cache - * - * @param string $path - * @param SCAN_RECURSIVE/SCAN_SHALLOW $recursive - * @return int the size of the scanned folder or -1 if the size is unknown at this stage - */ - public function scan($path, $recursive = self::SCAN_RECURSIVE) { - // Not a valid action for Shared Scanner - } - - /** - * walk over any folders that are not fully scanned yet and scan them - */ - public function backgroundScan() { - // Not a valid action for Shared Scanner - } - -} \ No newline at end of file diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php index 3a1d7ef101..8504a2d894 100644 --- a/apps/files_sharing/lib/sharedstorage.php +++ b/apps/files_sharing/lib/sharedstorage.php @@ -405,14 +405,14 @@ class Shared extends \OC\Files\Storage\Common { return new \OC\Files\Cache\Shared_Cache($this); } - public function getScanner(){ - return new \OC\Files\Cache\Shared_Scanner($this); - } - public function getPermissionsCache() { return new \OC\Files\Cache\Shared_Permissions($this); } + public function getWatcher() { + return new \OC\Files\Cache\Shared_Watcher($this); + } + public function getOwner($path) { if ($path == '') { return false; From 268c7acfc47eb44ab154eb90cfbb4484bd64b296 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Tue, 1 Jan 2013 13:16:42 -0500 Subject: [PATCH 142/347] Actually add Shared_Watcher --- apps/files_sharing/lib/watcher.php | 51 ++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 apps/files_sharing/lib/watcher.php diff --git a/apps/files_sharing/lib/watcher.php b/apps/files_sharing/lib/watcher.php new file mode 100644 index 0000000000..e67d1ee908 --- /dev/null +++ b/apps/files_sharing/lib/watcher.php @@ -0,0 +1,51 @@ +. +*/ + +namespace OC\Files\Cache; + +/** + * check the storage backends for updates and change the cache accordingly + */ +class Shared_Watcher extends Watcher { + + /** + * check $path for updates + * + * @param string $path + */ + public function checkUpdate($path) { + if ($path != '') { + parent::checkUpdate($path); + } + } + + /** + * remove deleted files in $path from the cache + * + * @param string $path + */ + public function cleanFolder($path) { + if ($path != '') { + parent::cleanFolder($path); + } + } + +} \ No newline at end of file From 04f83e3b539c6a20ce819bbe4f66c1996e7169f7 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 1 Jan 2013 20:11:39 +0100 Subject: [PATCH 143/347] Cache: optional path argument for getCache/Scanner/etc --- lib/files/storage/common.php | 11 ++++------- lib/files/storage/storage.php | 12 ++++++++---- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/lib/files/storage/common.php b/lib/files/storage/common.php index ab167f2864..e859d447f3 100644 --- a/lib/files/storage/common.php +++ b/lib/files/storage/common.php @@ -237,22 +237,19 @@ abstract class Common implements \OC\Files\Storage\Storage { return $this->filemtime($path)>$time; } - public function getCache(){ + public function getCache($path=''){ return new \OC\Files\Cache\Cache($this); } - public function getScanner(){ + public function getScanner($path=''){ return new \OC\Files\Cache\Scanner($this); } - public function getPermissionsCache(){ + public function getPermissionsCache($path=''){ return new \OC\Files\Cache\Permissions($this); } - /** - * @return \OC\Files\Cache\Watcher - */ - public function getWatcher(){ + public function getWatcher($path=''){ return new \OC\Files\Cache\Watcher($this); } diff --git a/lib/files/storage/storage.php b/lib/files/storage/storage.php index b603381dc9..2cc835236b 100644 --- a/lib/files/storage/storage.php +++ b/lib/files/storage/storage.php @@ -54,25 +54,29 @@ interface Storage{ public function hasUpdated($path,$time); /** + * @param string $path * @return \OC\Files\Cache\Cache */ - public function getCache(); + public function getCache($path=''); /** + * @param string $path * @return \OC\Files\Cache\Scanner */ - public function getScanner(); + public function getScanner($path=''); public function getOwner($path); /** + * @param string $path * @return \OC\Files\Cache\Permissions */ - public function getPermissionsCache(); + public function getPermissionsCache($path=''); /** + * @param string $path * @return \OC\Files\Cache\Watcher */ - public function getWatcher(); + public function getWatcher($path=''); /** * get the ETag for a file or folder From a164fd160fb0d3da548dfe01ec27df67d76b0b59 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 1 Jan 2013 20:19:53 +0100 Subject: [PATCH 144/347] Cache: provide path hints to getCache/etc where available --- lib/files/cache/updater.php | 6 +++--- lib/files/view.php | 28 ++++++++++++++-------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/lib/files/cache/updater.php b/lib/files/cache/updater.php index c8c96a97ee..c14adba3e5 100644 --- a/lib/files/cache/updater.php +++ b/lib/files/cache/updater.php @@ -31,8 +31,8 @@ class Updater { */ list($storage, $internalPath) = self::resolvePath($path); if ($storage) { - $cache = $storage->getCache(); - $scanner = $storage->getScanner(); + $cache = $storage->getCache($internalPath); + $scanner = $storage->getScanner($internalPath); $scanner->scan($internalPath, Scanner::SCAN_SHALLOW); $cache->correctFolderSize($internalPath); } @@ -45,7 +45,7 @@ class Updater { */ list($storage, $internalPath) = self::resolvePath($path); if ($storage) { - $cache = $storage->getCache(); + $cache = $storage->getCache($internalPath); $cache->remove($internalPath); $cache->correctFolderSize($internalPath); } diff --git a/lib/files/view.php b/lib/files/view.php index d3f93d39f5..8558b03fe1 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -679,13 +679,13 @@ class View { */ list($storage, $internalPath) = Filesystem::resolvePath($path); if ($storage) { - $cache = $storage->getCache(); + $cache = $storage->getCache($internalPath); if (!$cache->inCache($internalPath)) { - $scanner = $storage->getScanner(); + $scanner = $storage->getScanner($internalPath); $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW); } else { - $watcher = $storage->getWatcher(); + $watcher = $storage->getWatcher($internalPath); $watcher->checkUpdate($internalPath); } @@ -698,14 +698,14 @@ class View { foreach ($mountPoints as $mountPoint) { $subStorage = Filesystem::getStorage($mountPoint); if ($subStorage) { - $subCache = $subStorage->getCache(); + $subCache = $subStorage->getCache(''); $rootEntry = $subCache->get(''); $data['size'] += $rootEntry['size']; } } } - $permissionsCache = $storage->getPermissionsCache(); + $permissionsCache = $storage->getPermissionsCache($internalPath); $data['permissions'] = $permissionsCache->get($data['fileid'], \OC_User::getUser()); } } @@ -727,13 +727,13 @@ class View { */ list($storage, $internalPath) = Filesystem::resolvePath($path); if ($storage) { - $cache = $storage->getCache(); + $cache = $storage->getCache($internalPath); if ($cache->getStatus($internalPath) < Cache\Cache::COMPLETE) { - $scanner = $storage->getScanner(); + $scanner = $storage->getScanner($internalPath); $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW); } else { - $watcher = $storage->getWatcher(); + $watcher = $storage->getWatcher($internalPath); $watcher->checkUpdate($internalPath); } @@ -745,7 +745,7 @@ class View { foreach ($mountPoints as $mountPoint) { $subStorage = Filesystem::getStorage($mountPoint); if ($subStorage) { - $subCache = $subStorage->getCache(); + $subCache = $subStorage->getCache(''); $rootEntry = $subCache->get(''); $relativePath = trim(substr($mountPoint, $dirLength), '/'); @@ -769,7 +769,7 @@ class View { $files[$i]['type'] = $file['mimetype'] === 'httpd/unix-directory' ? 'dir' : 'file'; $ids[] = $file['fileid']; } - $permissionsCache = $storage->getPermissionsCache(); + $permissionsCache = $storage->getPermissionsCache($internalPath); $permissions = $permissionsCache->getMultiple($ids, \OC_User::getUser()); foreach ($files as $i => $file) { @@ -812,10 +812,10 @@ class View { */ list($storage, $internalPath) = Filesystem::resolvePath($path); if ($storage) { - $cache = $storage->getCache(); + $cache = $storage->getCache($path); if (!$cache->inCache($internalPath)) { - $scanner = $storage->getScanner(); + $scanner = $storage->getScanner($internalPath); $scanner->scan($internalPath, Cache\Scanner::SCAN_SHALLOW); } @@ -857,7 +857,7 @@ class View { $mountPoint = Filesystem::getMountPoint($this->fakeRoot); $storage = Filesystem::getStorage($mountPoint); if ($storage) { - $cache = $storage->getCache(); + $cache = $storage->getCache(''); $results = $cache->$method($query); foreach ($results as $result) { @@ -871,7 +871,7 @@ class View { foreach ($mountPoints as $mountPoint) { $storage = Filesystem::getStorage($mountPoint); if ($storage) { - $cache = $storage->getCache(); + $cache = $storage->getCache(''); $relativeMountPoint = substr($mountPoint, $rootLength); $results = $cache->$method($query); From fe90130618e4ce9b1829b4ce8e87311a15f53b83 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Tue, 1 Jan 2013 14:13:05 -0500 Subject: [PATCH 145/347] Initialize storageId variable in shared cache --- apps/files_sharing/lib/cache.php | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/files_sharing/lib/cache.php b/apps/files_sharing/lib/cache.php index 07c305bb95..0534d6dd89 100644 --- a/apps/files_sharing/lib/cache.php +++ b/apps/files_sharing/lib/cache.php @@ -48,6 +48,7 @@ class Shared_Cache extends Cache { if ($storage) { $this->files[$target] = $internalPath; $cache = $storage->getCache(); + $this->storageId = $storage->getId(); $this->numericId = $cache->getNumericStorageId(); return $cache; } From a1f7c28e28e221a6939a74eb5ae7b43c02a1d8e6 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Tue, 1 Jan 2013 14:47:25 -0500 Subject: [PATCH 146/347] Use the source Scanner for shared storage when the path is specified --- apps/files_sharing/lib/sharedstorage.php | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php index 8504a2d894..3a5755c01f 100644 --- a/apps/files_sharing/lib/sharedstorage.php +++ b/apps/files_sharing/lib/sharedstorage.php @@ -401,15 +401,25 @@ class Shared extends \OC\Files\Storage\Common { return $this->filemtime($path) > $time; } - public function getCache() { + public function getCache($path = '') { return new \OC\Files\Cache\Shared_Cache($this); } - public function getPermissionsCache() { + public function getScanner($path = '') { + if ($path != '' && ($source = $this->getSourcePath($path))) { + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); + if ($storage) { + return $storage->getScanner($internalPath); + } + } + return new \OC\Files\Cache\Scanner($this); + } + + public function getPermissionsCache($path = '') { return new \OC\Files\Cache\Shared_Permissions($this); } - public function getWatcher() { + public function getWatcher($path = '') { return new \OC\Files\Cache\Shared_Watcher($this); } From a068ddff64bb6071de204b948129c4ca23c16d26 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Wed, 2 Jan 2013 14:40:06 -0500 Subject: [PATCH 147/347] Use the sub storage's permission cache for retrieving the correct permission --- lib/files/view.php | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/lib/files/view.php b/lib/files/view.php index 8558b03fe1..9ba3eea3cf 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -739,6 +739,18 @@ class View { $files = $cache->getFolderContents($internalPath); //TODO: mimetype_filter + $ids = array(); + foreach ($files as $i => $file) { + $files[$i]['type'] = $file['mimetype'] === 'httpd/unix-directory' ? 'dir' : 'file'; + $ids[] = $file['fileid']; + } + + $permissionsCache = $storage->getPermissionsCache($internalPath); + $permissions = $permissionsCache->getMultiple($ids, \OC_User::getUser()); + foreach ($files as $i => $file) { + $files[$i]['permissions'] = $permissions[$file['fileid']]; + } + //add a folder for any mountpoint in this directory and add the sizes of other mountpoints to the folders $mountPoints = Filesystem::getMountPoints($path); $dirLength = strlen($path); @@ -758,24 +770,14 @@ class View { } } else { //mountpoint in this folder, add an entry for it $rootEntry['name'] = $relativePath; + $rootEntry['type'] = $rootEntry['mimetype'] === 'httpd/unix-directory' ? 'dir' : 'file'; + $subPermissionsCache = $subStorage->getPermissionsCache(''); + $rootEntry['permissions'] = $subPermissionsCache->get($rootEntry['fileid'], \OC_User::getUser()); $files[] = $rootEntry; } } } - $ids = array(); - - foreach ($files as $i => $file) { - $files[$i]['type'] = $file['mimetype'] === 'httpd/unix-directory' ? 'dir' : 'file'; - $ids[] = $file['fileid']; - } - $permissionsCache = $storage->getPermissionsCache($internalPath); - - $permissions = $permissionsCache->getMultiple($ids, \OC_User::getUser()); - foreach ($files as $i => $file) { - $files[$i]['permissions'] = $permissions[$file['fileid']]; - } - if ($mimetype_filter) { foreach ($files as $file) { if (strpos($mimetype_filter, '/')) { From 6a6d6756b7a6495d044d44c8d6081505880d96b9 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 3 Jan 2013 00:29:10 +0100 Subject: [PATCH 148/347] Cache: rename index to prevent colissions with old fscache indexes --- db_structure.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/db_structure.xml b/db_structure.xml index aa0916264c..e47cf3c629 100644 --- a/db_structure.xml +++ b/db_structure.xml @@ -190,7 +190,7 @@ - storage_path_hash + fs_storage_path_hash true storage @@ -203,7 +203,7 @@ - parent_name_hash + fs_parent_name_hash parent ascending From f144be8857e3356495acefca787637b5672f73ef Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Wed, 2 Jan 2013 19:20:34 -0500 Subject: [PATCH 149/347] Don't mount shared storage unless there are shared files --- apps/files_sharing/lib/sharedstorage.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php index 3a5755c01f..24096e0c10 100644 --- a/apps/files_sharing/lib/sharedstorage.php +++ b/apps/files_sharing/lib/sharedstorage.php @@ -390,8 +390,10 @@ class Shared extends \OC\Files\Storage\Common { } public static function setup($options) { - $user_dir = $options['user_dir']; - \OC\Files\Filesystem::mount('\OC\Files\Storage\Shared', array('sharedFolder' => '/Shared'), $user_dir.'/Shared/'); + if (\OCP\Share::getItemsSharedWith('file')) { + $user_dir = $options['user_dir']; + \OC\Files\Filesystem::mount('\OC\Files\Storage\Shared', array('sharedFolder' => '/Shared'), $user_dir.'/Shared/'); + } } public function hasUpdated($path, $time) { From 38876fc98a11a917e68780357d7f4b5a146ba89a Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Thu, 3 Jan 2013 12:07:04 -0500 Subject: [PATCH 150/347] Update old storage classes names to the new namespace during mounting --- apps/files_external/lib/config.php | 12 ++++++++++++ lib/files/filesystem.php | 5 ++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/apps/files_external/lib/config.php b/apps/files_external/lib/config.php index 323e4060a4..d7286c52c0 100755 --- a/apps/files_external/lib/config.php +++ b/apps/files_external/lib/config.php @@ -120,6 +120,10 @@ class OC_Mount_Config { if (isset($mountPoints[self::MOUNT_TYPE_GROUP])) { foreach ($mountPoints[self::MOUNT_TYPE_GROUP] as $group => $mounts) { foreach ($mounts as $mountPoint => $mount) { + // Update old classes to new namespace + if (strpos($mount['class'], 'OC_Filestorage_') !== false) { + $mount['class'] = '\OC\Files\Storage\\'.substr($mount['class'], 15, strlen($mount['class']) - 15); + } // Remove '/$user/files/' from mount point $mountPoint = substr($mountPoint, 13); // Merge the mount point into the current mount points @@ -139,6 +143,10 @@ class OC_Mount_Config { if (isset($mountPoints[self::MOUNT_TYPE_USER])) { foreach ($mountPoints[self::MOUNT_TYPE_USER] as $user => $mounts) { foreach ($mounts as $mountPoint => $mount) { + // Update old classes to new namespace + if (strpos($mount['class'], 'OC_Filestorage_') !== false) { + $mount['class'] = '\OC\Files\Storage\\'.substr($mount['class'], 15, strlen($mount['class']) - 15); + } // Remove '/$user/files/' from mount point $mountPoint = substr($mountPoint, 13); // Merge the mount point into the current mount points @@ -169,6 +177,10 @@ class OC_Mount_Config { $personal = array(); if (isset($mountPoints[self::MOUNT_TYPE_USER][$uid])) { foreach ($mountPoints[self::MOUNT_TYPE_USER][$uid] as $mountPoint => $mount) { + // Update old classes to new namespace + if (strpos($mount['class'], 'OC_Filestorage_') !== false) { + $mount['class'] = '\OC\Files\Storage\\'.substr($mount['class'], 15, strlen($mount['class']) - 15); + } // Remove '/uid/files/' from mount point $personal[substr($mountPoint, strlen($uid) + 8)] = array('class' => $mount['class'], 'backend' => $backends[$mount['class']]['backend'], diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php index 8183b8ff99..b9fd6a0376 100644 --- a/lib/files/filesystem.php +++ b/lib/files/filesystem.php @@ -364,7 +364,10 @@ class Filesystem { if (strlen($mountpoint) > 1) { $mountpoint .= '/'; } - + // Update old classes to new namespace + if (strpos($class, 'OC_Filestorage_') !== false) { + $class = '\OC\Files\Storage\\'.substr($class, 15, strlen($class) - 15); + } if ($class instanceof \OC\Files\Storage\Storage) { self::$mounts[$mountpoint] = array('class' => get_class($class), 'arguments' => $arguments); self::$storages[$mountpoint] = $class; From 1137723b2a46c37d61e7f501694c73562b21ef74 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Thu, 3 Jan 2013 12:13:45 -0500 Subject: [PATCH 151/347] Remove unnecessary length parameter from last commit --- apps/files_external/lib/config.php | 6 +++--- lib/files/filesystem.php | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/files_external/lib/config.php b/apps/files_external/lib/config.php index d7286c52c0..3bb512493d 100755 --- a/apps/files_external/lib/config.php +++ b/apps/files_external/lib/config.php @@ -122,7 +122,7 @@ class OC_Mount_Config { foreach ($mounts as $mountPoint => $mount) { // Update old classes to new namespace if (strpos($mount['class'], 'OC_Filestorage_') !== false) { - $mount['class'] = '\OC\Files\Storage\\'.substr($mount['class'], 15, strlen($mount['class']) - 15); + $mount['class'] = '\OC\Files\Storage\\'.substr($mount['class'], 15); } // Remove '/$user/files/' from mount point $mountPoint = substr($mountPoint, 13); @@ -145,7 +145,7 @@ class OC_Mount_Config { foreach ($mounts as $mountPoint => $mount) { // Update old classes to new namespace if (strpos($mount['class'], 'OC_Filestorage_') !== false) { - $mount['class'] = '\OC\Files\Storage\\'.substr($mount['class'], 15, strlen($mount['class']) - 15); + $mount['class'] = '\OC\Files\Storage\\'.substr($mount['class'], 15); } // Remove '/$user/files/' from mount point $mountPoint = substr($mountPoint, 13); @@ -179,7 +179,7 @@ class OC_Mount_Config { foreach ($mountPoints[self::MOUNT_TYPE_USER][$uid] as $mountPoint => $mount) { // Update old classes to new namespace if (strpos($mount['class'], 'OC_Filestorage_') !== false) { - $mount['class'] = '\OC\Files\Storage\\'.substr($mount['class'], 15, strlen($mount['class']) - 15); + $mount['class'] = '\OC\Files\Storage\\'.substr($mount['class'], 15); } // Remove '/uid/files/' from mount point $personal[substr($mountPoint, strlen($uid) + 8)] = array('class' => $mount['class'], diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php index b9fd6a0376..d9487bde80 100644 --- a/lib/files/filesystem.php +++ b/lib/files/filesystem.php @@ -366,7 +366,7 @@ class Filesystem { } // Update old classes to new namespace if (strpos($class, 'OC_Filestorage_') !== false) { - $class = '\OC\Files\Storage\\'.substr($class, 15, strlen($class) - 15); + $class = '\OC\Files\Storage\\'.substr($class, 15); } if ($class instanceof \OC\Files\Storage\Storage) { self::$mounts[$mountpoint] = array('class' => get_class($class), 'arguments' => $arguments); From 0ca5047da56c1b6d0614174b01d42bace85d53ee Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 7 Jan 2013 00:36:01 +0100 Subject: [PATCH 152/347] Autoload namespaced test classes --- lib/base.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/base.php b/lib/base.php index 3d3e7d59f9..80e5c5ed77 100644 --- a/lib/base.php +++ b/lib/base.php @@ -105,6 +105,8 @@ class OC $path = str_replace('\\', '/', $className) . '.php'; } elseif (strpos($className, 'Test_') === 0) { $path = 'tests/lib/' . strtolower(str_replace('_', '/', substr($className, 5)) . '.php'); + } elseif (strpos($className, 'Test\\') === 0) { + $path = 'tests/lib/' . strtolower(str_replace('\\', '/', substr($className, 5)) . '.php'); } else { return false; } From 457dc270f5147863c00b55355542298ba4d41762 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 7 Jan 2013 00:36:39 +0100 Subject: [PATCH 153/347] Fix messed up mounts --- lib/files/filesystem.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/files/filesystem.php b/lib/files/filesystem.php index d9487bde80..b3ba62c3a4 100644 --- a/lib/files/filesystem.php +++ b/lib/files/filesystem.php @@ -364,14 +364,14 @@ class Filesystem { if (strlen($mountpoint) > 1) { $mountpoint .= '/'; } - // Update old classes to new namespace - if (strpos($class, 'OC_Filestorage_') !== false) { - $class = '\OC\Files\Storage\\'.substr($class, 15); - } if ($class instanceof \OC\Files\Storage\Storage) { self::$mounts[$mountpoint] = array('class' => get_class($class), 'arguments' => $arguments); self::$storages[$mountpoint] = $class; } else { + // Update old classes to new namespace + if (strpos($class, 'OC_Filestorage_') !== false) { + $class = '\OC\Files\Storage\\'.substr($class, 15); + } self::$mounts[$mountpoint] = array('class' => $class, 'arguments' => $arguments); } } From 439578288facbae3144f131aca85a7235f622053 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 7 Jan 2013 01:03:11 +0100 Subject: [PATCH 154/347] Cache: split permission cache scanning and cache scanning --- lib/files/cache/scanner.php | 9 --------- lib/files/view.php | 30 ++++++++++++++++++++++-------- tests/lib/files/view.php | 1 + 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/lib/files/cache/scanner.php b/lib/files/cache/scanner.php index 4c0ec9617f..526d4a2aab 100644 --- a/lib/files/cache/scanner.php +++ b/lib/files/cache/scanner.php @@ -24,11 +24,6 @@ class Scanner { */ private $cache; - /** - * @var \OC\Files\Cache\Permissions $permissionsCache - */ - private $permissionsCache; - const SCAN_RECURSIVE = true; const SCAN_SHALLOW = false; @@ -36,7 +31,6 @@ class Scanner { $this->storage = $storage; $this->storageId = $this->storage->getId(); $this->cache = $storage->getCache(); - $this->permissionsCache = $storage->getPermissionsCache(); } /** @@ -53,10 +47,8 @@ class Scanner { $data['mtime'] = $this->storage->filemtime($path); if ($data['mimetype'] == 'httpd/unix-directory') { $data['size'] = -1; //unknown - $data['permissions'] = $this->storage->getPermissions($path . '/'); } else { $data['size'] = $this->storage->filesize($path); - $data['permissions'] = $this->storage->getPermissions($path); } return $data; } @@ -81,7 +73,6 @@ class Scanner { } } $id = $this->cache->put($file, $data); - $this->permissionsCache->set($id, \OC_User::getUser(), $data['permissions']); } return $data; } diff --git a/lib/files/view.php b/lib/files/view.php index 9ba3eea3cf..124345f3c6 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -680,6 +680,8 @@ class View { list($storage, $internalPath) = Filesystem::resolvePath($path); if ($storage) { $cache = $storage->getCache($internalPath); + $permissionsCache = $storage->getPermissionsCache($internalPath); + $user = \OC_User::getUser(); if (!$cache->inCache($internalPath)) { $scanner = $storage->getScanner($internalPath); @@ -705,8 +707,12 @@ class View { } } - $permissionsCache = $storage->getPermissionsCache($internalPath); - $data['permissions'] = $permissionsCache->get($data['fileid'], \OC_User::getUser()); + $permissions = $permissionsCache->get($data['fileid'], $user); + if ($permissions === -1) { + $permissions = $storage->getPermissions($internalPath); + $permissionsCache->set($data['fileid'], $user, $permissions); + } + $data['permissions'] = $permissions; } } return $data; @@ -728,6 +734,8 @@ class View { list($storage, $internalPath) = Filesystem::resolvePath($path); if ($storage) { $cache = $storage->getCache($internalPath); + $permissionsCache = $storage->getPermissionsCache($internalPath); + $user = \OC_User::getUser(); if ($cache->getStatus($internalPath) < Cache\Cache::COMPLETE) { $scanner = $storage->getScanner($internalPath); @@ -743,12 +751,13 @@ class View { foreach ($files as $i => $file) { $files[$i]['type'] = $file['mimetype'] === 'httpd/unix-directory' ? 'dir' : 'file'; $ids[] = $file['fileid']; - } - $permissionsCache = $storage->getPermissionsCache($internalPath); - $permissions = $permissionsCache->getMultiple($ids, \OC_User::getUser()); - foreach ($files as $i => $file) { - $files[$i]['permissions'] = $permissions[$file['fileid']]; + $permissions = $permissionsCache->get($file['fileid'], $user); + if ($permissions === -1) { + $permissions = $storage->getPermissions($file['path']); + $permissionsCache->set($file['fileid'], $user, $permissions); + } + $files[$i]['permissions'] = $permissions; } //add a folder for any mountpoint in this directory and add the sizes of other mountpoints to the folders @@ -772,7 +781,12 @@ class View { $rootEntry['name'] = $relativePath; $rootEntry['type'] = $rootEntry['mimetype'] === 'httpd/unix-directory' ? 'dir' : 'file'; $subPermissionsCache = $subStorage->getPermissionsCache(''); - $rootEntry['permissions'] = $subPermissionsCache->get($rootEntry['fileid'], \OC_User::getUser()); + $permissions = $subPermissionsCache->get($rootEntry['fileid'], $user); + if ($permissions === -1) { + $permissions = $subStorage->getPermissions($rootEntry['path']); + $subPermissionsCache->set($rootEntry['fileid'], $user, $permissions); + } + $rootEntry['permissions'] = $subPermissionsCache; $files[] = $rootEntry; } } diff --git a/tests/lib/files/view.php b/tests/lib/files/view.php index 712166ab32..4b0abc2201 100644 --- a/tests/lib/files/view.php +++ b/tests/lib/files/view.php @@ -43,6 +43,7 @@ class View extends \PHPUnit_Framework_TestCase { $cachedData = $rootView->getFileInfo('/foo.txt'); $this->assertEquals($textSize, $cachedData['size']); $this->assertEquals('text/plain', $cachedData['mimetype']); + $this->assertEquals(\OCP\PERMISSION_ALL ^ \OCP\PERMISSION_CREATE, $cachedData['permissions']); $cachedData = $rootView->getFileInfo('/'); $this->assertEquals($storageSize * 3, $cachedData['size']); From ad3badeabff9dde839827558c281a691c611cf87 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 7 Jan 2013 01:03:11 +0100 Subject: [PATCH 155/347] Cache: split permission cache scanning and cache scanning --- tests/lib/files/view.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/lib/files/view.php b/tests/lib/files/view.php index 4b0abc2201..5327114267 100644 --- a/tests/lib/files/view.php +++ b/tests/lib/files/view.php @@ -43,7 +43,7 @@ class View extends \PHPUnit_Framework_TestCase { $cachedData = $rootView->getFileInfo('/foo.txt'); $this->assertEquals($textSize, $cachedData['size']); $this->assertEquals('text/plain', $cachedData['mimetype']); - $this->assertEquals(\OCP\PERMISSION_ALL ^ \OCP\PERMISSION_CREATE, $cachedData['permissions']); + $this->assertNotEquals(-1, $cachedData['permissions']); $cachedData = $rootView->getFileInfo('/'); $this->assertEquals($storageSize * 3, $cachedData['size']); From d0377b1951a156e218ca0200340e2bcfb51ac0c8 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Mon, 7 Jan 2013 01:40:09 +0100 Subject: [PATCH 156/347] Cache: normalize mimetypes --- db_structure.xml | 44 ++++++++++++++++++++++++++--- lib/files/cache/cache.php | 59 +++++++++++++++++++++++++++++++++++---- lib/files/view.php | 2 +- lib/util.php | 2 +- 4 files changed, 96 insertions(+), 11 deletions(-) diff --git a/db_structure.xml b/db_structure.xml index e47cf3c629..3022983473 100644 --- a/db_structure.xml +++ b/db_structure.xml @@ -94,6 +94,42 @@
+ + + *dbprefix*mimetypes + + + + + id + integer + 0 + true + 1 + 4 + + + + mimetype + text + + true + 64 + + + + mimetype_id_index + true + + mimetype + ascending + + + + + +
+ *dbprefix*filecache @@ -151,18 +187,18 @@ mimetype - text + integer true - 64 + 4 mimepart - text + integer true - 32 + 4 diff --git a/lib/files/cache/cache.php b/lib/files/cache/cache.php index 3ebae9baa5..0001c2752d 100644 --- a/lib/files/cache/cache.php +++ b/lib/files/cache/cache.php @@ -36,6 +36,9 @@ class Cache { */ private $numericId; + private $mimetypeIds = array(); + private $mimetypes = array(); + /** * @param \OC\Files\Storage\Storage|string $storage */ @@ -61,6 +64,41 @@ class Cache { return $this->numericId; } + /** + * normalize mimetypes + * + * @param string $mime + * @return int + */ + public function getMimetypeId($mime) { + if (!isset($this->mimetypeIds[$mime])) { + $query = \OC_DB::prepare('SELECT `id` FROM `*PREFIX*mimetypes` WHERE `mimetype` = ?'); + $result = $query->execute(array($mime)); + if ($row = $result->fetchRow()) { + $this->mimetypeIds[$mime] = $row['id']; + } else { + $query = \OC_DB::prepare('INSERT INTO `*PREFIX*mimetypes`(`mimetype`) VALUES(?)'); + $query->execute(array($mime)); + $this->mimetypeIds[$mime] = \OC_DB::insertid('*PREFIX*mimetypes'); + } + $this->mimetypes[$this->mimetypeIds[$mime]] = $mime; + } + return $this->mimetypeIds[$mime]; + } + + public function getMimetype($id) { + if (!isset($this->mimetypes[$id])) { + $query = \OC_DB::prepare('SELECT `mimetype` FROM `*PREFIX*mimetypes` WHERE `id` = ?'); + $result = $query->execute(array($id)); + if ($row = $result->fetchRow()) { + $this->mimetypes[$id] = $row['mimetype']; + } else { + return null; + } + } + return $this->mimetypes[$id]; + } + /** * get the stored metadata of a file or folder * @@ -92,6 +130,8 @@ class Cache { $data['size'] = (int)$data['size']; $data['mtime'] = (int)$data['mtime']; $data['encrypted'] = (bool)$data['encrypted']; + $data['mimetype'] = $this->getMimetype($data['mimetype']); + $data['mimepart'] = $this->getMimetype($data['mimepart']); } return $data; @@ -110,7 +150,12 @@ class Cache { 'SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted` FROM `*PREFIX*filecache` WHERE parent = ? ORDER BY `name` ASC'); $result = $query->execute(array($fileId)); - return $result->fetchAll(); + $files = $result->fetchAll(); + foreach ($files as &$file) { + $file['mimetype'] = $this->getMimetype($file['mimetype']); + $file['mimepart'] = $this->getMimetype($file['mimepart']); + } + return $files; } else { return array(); } @@ -179,22 +224,23 @@ class Cache { * @param array $data * @return array */ - static function buildParts(array $data) { + function buildParts(array $data) { $fields = array('path', 'parent', 'name', 'mimetype', 'size', 'mtime', 'encrypted'); $params = array(); $queryParts = array(); foreach ($data as $name => $value) { if (array_search($name, $fields) !== false) { - $params[] = $value; - $queryParts[] = '`' . $name . '`'; if ($name === 'path') { $params[] = md5($value); $queryParts[] = '`path_hash`'; } elseif ($name === 'mimetype') { - $params[] = substr($value, 0, strpos($value, '/')); + $params[] = $this->getMimetypeId(substr($value, 0, strpos($value, '/'))); $queryParts[] = '`mimepart`'; + $value = $this->getMimetypeId($value); } + $params[] = $value; + $queryParts[] = '`' . $name . '`'; } } return array($queryParts, $params); @@ -339,6 +385,8 @@ class Cache { $result = $query->execute(array($pattern, $this->numericId)); $files = array(); while ($row = $result->fetchRow()) { + $row['mimetype'] = $this->getMimetype($row['mimetype']); + $row['mimepart'] = $this->getMimetype($row['mimepart']); $files[] = $row; } return $files; @@ -360,6 +408,7 @@ class Cache { SELECT `fileid`, `storage`, `path`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted` FROM `*PREFIX*filecache` WHERE ' . $where . ' AND `storage` = ?' ); + $mimetype = $this->getMimetypeId($mimetype); $result = $query->execute(array($mimetype, $this->numericId)); return $result->fetchAll(); } diff --git a/lib/files/view.php b/lib/files/view.php index 124345f3c6..8303a080bd 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -693,7 +693,7 @@ class View { $data = $cache->get($internalPath); - if ($data) { + if ($data and $data['fileid']) { if ($data['mimetype'] === 'httpd/unix-directory') { //add the sizes of other mountpoints to the folder $mountPoints = Filesystem::getMountPoints($path); diff --git a/lib/util.php b/lib/util.php index 805ef6f18b..93c0d0f26d 100755 --- a/lib/util.php +++ b/lib/util.php @@ -74,7 +74,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,04); + return array(4,91,05); } /** From 5174eda23270463f09c82db77f2f61d3496f752f Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Mon, 7 Jan 2013 15:21:38 -0500 Subject: [PATCH 157/347] Fix permissions for mount point --- lib/files/view.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/files/view.php b/lib/files/view.php index 8303a080bd..94c89603ae 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -786,7 +786,7 @@ class View { $permissions = $subStorage->getPermissions($rootEntry['path']); $subPermissionsCache->set($rootEntry['fileid'], $user, $permissions); } - $rootEntry['permissions'] = $subPermissionsCache; + $rootEntry['permissions'] = $permissions; $files[] = $rootEntry; } } From a7d4d042239236082d7f2c2679249ea7d48e596c Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Mon, 7 Jan 2013 15:27:22 -0500 Subject: [PATCH 158/347] Fix mimetypes in shared cache --- apps/files_sharing/lib/cache.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/files_sharing/lib/cache.php b/apps/files_sharing/lib/cache.php index 0534d6dd89..8b989db3b0 100644 --- a/apps/files_sharing/lib/cache.php +++ b/apps/files_sharing/lib/cache.php @@ -79,6 +79,8 @@ class Shared_Cache extends Cache { $data['size'] = (int)$data['size']; $data['mtime'] = (int)$data['mtime']; $data['encrypted'] = (bool)$data['encrypted']; + $data['mimetype'] = $this->getMimetype($data['mimetype']); + $data['mimepart'] = $this->getMimetype($data['mimepart']); return $data; } return false; @@ -92,7 +94,12 @@ class Shared_Cache extends Cache { */ public function getFolderContents($folder) { if ($folder == '') { - return \OCP\Share::getItemsSharedWith('file', \OC_Share_Backend_File::FORMAT_GET_FOLDER_CONTENTS); + $files = \OCP\Share::getItemsSharedWith('file', \OC_Share_Backend_File::FORMAT_GET_FOLDER_CONTENTS); + foreach ($files as &$file) { + $file['mimetype'] = $this->getMimetype($file['mimetype']); + $file['mimepart'] = $this->getMimetype($file['mimepart']); + } + return $files; } else { if ($cache = $this->getSourceCache($folder)) { return $cache->getFolderContents($this->files[$folder]); From 8f8a5bbfb750b3c9091da810749a43cada2740b2 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Mon, 7 Jan 2013 18:17:14 -0500 Subject: [PATCH 159/347] Maked Shared_Permissions extend Permissions class --- apps/files_sharing/lib/permissions.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/files_sharing/lib/permissions.php b/apps/files_sharing/lib/permissions.php index 6eaed34b33..508c3a384f 100644 --- a/apps/files_sharing/lib/permissions.php +++ b/apps/files_sharing/lib/permissions.php @@ -20,7 +20,7 @@ */ namespace OC\Files\Cache; -class Shared_Permissions { +class Shared_Permissions extends Permissions { /** * get the permissions for a single file @@ -29,7 +29,7 @@ class Shared_Permissions { * @param string $user * @return int (-1 if file no permissions set) */ - static public function get($fileId, $user) { + public function get($fileId, $user) { if ($fileId == -1) { return \OCP\PERMISSION_READ; } @@ -48,7 +48,7 @@ class Shared_Permissions { * @param string $user * @param int $permissions */ - static public function set($fileId, $user, $permissions) { + public function set($fileId, $user, $permissions) { // Not a valid action for Shared Permissions } @@ -59,7 +59,7 @@ class Shared_Permissions { * @param string $user * @return int[] */ - static public function getMultiple($fileIds, $user) { + public function getMultiple($fileIds, $user) { if (count($fileIds) === 0) { return array(); } @@ -75,11 +75,11 @@ class Shared_Permissions { * @param int $fileId * @param string $user */ - static public function remove($fileId, $user) { + public function remove($fileId, $user) { // Not a valid action for Shared Permissions } - static public function removeMultiple($fileIds, $user) { + public function removeMultiple($fileIds, $user) { // Not a valid action for Shared Permissions } } From e8b195bf109d702402735e628b2d239b199088e5 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Mon, 7 Jan 2013 20:52:51 -0500 Subject: [PATCH 160/347] Almost fix Shared scanner... --- apps/files_sharing/lib/cache.php | 13 +++++++++++++ apps/files_sharing/lib/permissions.php | 2 +- apps/files_sharing/lib/share/file.php | 3 +++ apps/files_sharing/lib/share/folder.php | 11 +++++++++-- apps/files_sharing/lib/sharedstorage.php | 6 ------ lib/public/share.php | 5 ++++- 6 files changed, 30 insertions(+), 10 deletions(-) diff --git a/apps/files_sharing/lib/cache.php b/apps/files_sharing/lib/cache.php index 8b989db3b0..d35a5148de 100644 --- a/apps/files_sharing/lib/cache.php +++ b/apps/files_sharing/lib/cache.php @@ -136,6 +136,19 @@ class Shared_Cache extends Cache { return -1; } + /** + * check if a file is available in the cache + * + * @param string $file + * @return bool + */ + public function inCache($file) { + if ($file == '') { + return true; + } + return parent::inCache($file); + } + /** * remove a file or folder from the cache * diff --git a/apps/files_sharing/lib/permissions.php b/apps/files_sharing/lib/permissions.php index 508c3a384f..2b068ff935 100644 --- a/apps/files_sharing/lib/permissions.php +++ b/apps/files_sharing/lib/permissions.php @@ -33,7 +33,7 @@ class Shared_Permissions extends Permissions { if ($fileId == -1) { return \OCP\PERMISSION_READ; } - $source = \OCP\Share::getItemSharedWithBySource('file', $fileId, \OC_Share_Backend_File::FORMAT_SHARED_STORAGE); + $source = \OCP\Share::getItemSharedWithBySource('file', $fileId, \OC_Share_Backend_File::FORMAT_SHARED_STORAGE, null, true); if ($source) { return $source['permissions']; } else { diff --git a/apps/files_sharing/lib/share/file.php b/apps/files_sharing/lib/share/file.php index 5e98c455d3..6d3c55a008 100644 --- a/apps/files_sharing/lib/share/file.php +++ b/apps/files_sharing/lib/share/file.php @@ -117,6 +117,9 @@ class OC_Share_Backend_File implements OCP\Share_Backend_File_Dependent { } public static function getSource($target) { + if ($target == '') { + return false; + } $target = '/'.$target; $target = rtrim($target, '/'); $pos = strpos($target, '/', 1); diff --git a/apps/files_sharing/lib/share/folder.php b/apps/files_sharing/lib/share/folder.php index bbe4c130bd..11c8c6b1e8 100644 --- a/apps/files_sharing/lib/share/folder.php +++ b/apps/files_sharing/lib/share/folder.php @@ -24,6 +24,13 @@ class OC_Share_Backend_Folder extends OC_Share_Backend_File implements OCP\Share public function getChildren($itemSource) { $children = array(); $parents = array($itemSource); + $query = \OC_DB::prepare('SELECT `id` FROM `*PREFIX*mimetypes` WHERE `mimetype` = ?'); + $result = $query->execute(array('httpd/unix-directory')); + if ($row = $result->fetchRow()) { + $mimetype = $row['id']; + } else { + $mimetype = -1; + } while (!empty($parents)) { $parents = "'".implode("','", $parents)."'"; $query = OC_DB::prepare('SELECT `fileid`, `name`, `mimetype` FROM `*PREFIX*filecache` WHERE `parent` IN ('.$parents.')'); @@ -32,8 +39,8 @@ class OC_Share_Backend_Folder extends OC_Share_Backend_File implements OCP\Share while ($file = $result->fetchRow()) { $children[] = array('source' => $file['fileid'], 'file_path' => $file['name']); // If a child folder is found look inside it - if ($file['mimetype'] == 'httpd/unix-directory') { - $parents[] = $file['id']; + if ($file['mimetype'] == $mimetype) { + $parents[] = $file['fileid']; } } } diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php index 24096e0c10..c8756af8ed 100644 --- a/apps/files_sharing/lib/sharedstorage.php +++ b/apps/files_sharing/lib/sharedstorage.php @@ -408,12 +408,6 @@ class Shared extends \OC\Files\Storage\Common { } public function getScanner($path = '') { - if ($path != '' && ($source = $this->getSourcePath($path))) { - list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); - if ($storage) { - return $storage->getScanner($internalPath); - } - } return new \OC\Files\Cache\Scanner($this); } diff --git a/lib/public/share.php b/lib/public/share.php index c74960b94c..7722e0b86c 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -756,7 +756,7 @@ class Share { $collectionItems = array(); foreach ($items as &$row) { // Return only the item instead of a 2-dimensional array - if ($limit == 1 && $row['item_type'] == $itemType && $row[$column] == $item) { + if ($limit == 1 && $row[$column] == $item && ($row['item_type'] == $itemType || $itemType == 'file')) { if ($format == self::FORMAT_NONE) { return $row; } else { @@ -823,6 +823,9 @@ class Share { if (!empty($collectionItems)) { $items = array_merge($items, $collectionItems); } + if (empty($items) && $limit == 1) { + return false; + } if ($format == self::FORMAT_NONE) { return $items; } else if ($format == self::FORMAT_STATUSES) { From 464dafd7d2627d59732c09e01986d705d604ee56 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Wed, 9 Jan 2013 22:17:39 -0500 Subject: [PATCH 161/347] Make Google Drive storage id unique, before it was anonymousanonymous --- apps/files_external/lib/google.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_external/lib/google.php b/apps/files_external/lib/google.php index bbb315c491..4c485773e7 100644 --- a/apps/files_external/lib/google.php +++ b/apps/files_external/lib/google.php @@ -41,7 +41,7 @@ class Google extends \OC\Files\Storage\Common { ) { $consumer_key = isset($params['consumer_key']) ? $params['consumer_key'] : 'anonymous'; $consumer_secret = isset($params['consumer_secret']) ? $params['consumer_secret'] : 'anonymous'; - $this->id = 'google::' . $consumer_key . $consumer_secret; + $this->id = 'google::' . $params['token']; $this->consumer = new \OAuthConsumer($consumer_key, $consumer_secret); $this->oauth_token = new \OAuthToken($params['token'], $params['token_secret']); $this->sig_method = new \OAuthSignatureMethod_HMAC_SHA1(); From 106541361c3857ed8e35c6869c91faffb8ae984d Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Wed, 9 Jan 2013 22:57:42 -0500 Subject: [PATCH 162/347] Change length of mimetypes to 255, the maximum length according to RFC 4288 --- db_structure.xml | 2 +- lib/util.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/db_structure.xml b/db_structure.xml index 3022983473..7b6829aa30 100644 --- a/db_structure.xml +++ b/db_structure.xml @@ -114,7 +114,7 @@ text true - 64 + 255 diff --git a/lib/util.php b/lib/util.php index 93c0d0f26d..e814a3a32d 100755 --- a/lib/util.php +++ b/lib/util.php @@ -74,7 +74,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,05); + return array(4,91,06); } /** From aa15fcf22f4c32026eca5ff8ae5e5df244f2c53e Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Thu, 10 Jan 2013 12:09:55 -0500 Subject: [PATCH 163/347] Scan mount points in root before adding a entry --- lib/files/view.php | 46 ++++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/lib/files/view.php b/lib/files/view.php index 94c89603ae..703cda5123 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -767,27 +767,37 @@ class View { $subStorage = Filesystem::getStorage($mountPoint); if ($subStorage) { $subCache = $subStorage->getCache(''); - $rootEntry = $subCache->get(''); - $relativePath = trim(substr($mountPoint, $dirLength), '/'); - if ($pos = strpos($relativePath, '/')) { //mountpoint inside subfolder add size to the correct folder - $entryName = substr($relativePath, 0, $pos); - foreach ($files as &$entry) { - if ($entry['name'] === $entryName) { - $entry['size'] += $rootEntry['size']; + if ($subCache->getStatus('') < Cache\Cache::COMPLETE) { + $subScanner = $subStorage->getScanner(''); + $subScanner->scan('', Cache\Scanner::SCAN_SHALLOW); + } else { + $subWatcher = $subStorage->getWatcher(''); + $subWatcher->checkUpdate(''); + } + + $rootEntry = $subCache->get(''); + if ($rootEntry) { + $relativePath = trim(substr($mountPoint, $dirLength), '/'); + if ($pos = strpos($relativePath, '/')) { //mountpoint inside subfolder add size to the correct folder + $entryName = substr($relativePath, 0, $pos); + foreach ($files as &$entry) { + if ($entry['name'] === $entryName) { + $entry['size'] += $rootEntry['size']; + } } + } else { //mountpoint in this folder, add an entry for it + $rootEntry['name'] = $relativePath; + $rootEntry['type'] = $rootEntry['mimetype'] === 'httpd/unix-directory' ? 'dir' : 'file'; + $subPermissionsCache = $subStorage->getPermissionsCache(''); + $permissions = $subPermissionsCache->get($rootEntry['fileid'], $user); + if ($permissions === -1) { + $permissions = $subStorage->getPermissions($rootEntry['path']); + $subPermissionsCache->set($rootEntry['fileid'], $user, $permissions); + } + $rootEntry['permissions'] = $permissions; + $files[] = $rootEntry; } - } else { //mountpoint in this folder, add an entry for it - $rootEntry['name'] = $relativePath; - $rootEntry['type'] = $rootEntry['mimetype'] === 'httpd/unix-directory' ? 'dir' : 'file'; - $subPermissionsCache = $subStorage->getPermissionsCache(''); - $permissions = $subPermissionsCache->get($rootEntry['fileid'], $user); - if ($permissions === -1) { - $permissions = $subStorage->getPermissions($rootEntry['path']); - $subPermissionsCache->set($rootEntry['fileid'], $user, $permissions); - } - $rootEntry['permissions'] = $permissions; - $files[] = $rootEntry; } } } From 0784bcb8d74214448e3908e8c05a8c6be38ef457 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Thu, 10 Jan 2013 23:30:26 +0100 Subject: [PATCH 164/347] introduce configPrefix to allow settings for multiple LDAP servers --- apps/user_ldap/ajax/testConfiguration.php | 4 +- apps/user_ldap/appinfo/app.php | 2 +- apps/user_ldap/lib/connection.php | 58 ++++++++++++----------- 3 files changed, 33 insertions(+), 31 deletions(-) diff --git a/apps/user_ldap/ajax/testConfiguration.php b/apps/user_ldap/ajax/testConfiguration.php index a82f7e4c17..fd72485268 100644 --- a/apps/user_ldap/ajax/testConfiguration.php +++ b/apps/user_ldap/ajax/testConfiguration.php @@ -4,7 +4,7 @@ * ownCloud - user_ldap * * @author Arthur Schiwon - * @copyright 2012 Arthur Schiwon blizzz@owncloud.com + * @copyright 2012, 2013 Arthur Schiwon blizzz@owncloud.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE @@ -26,7 +26,7 @@ OCP\JSON::checkAdminUser(); OCP\JSON::checkAppEnabled('user_ldap'); OCP\JSON::callCheck(); -$connection = new \OCA\user_ldap\lib\Connection(null); +$connection = new \OCA\user_ldap\lib\Connection('', null); if($connection->setConfiguration($_POST)) { //Configuration is okay if($connection->bind()) { diff --git a/apps/user_ldap/appinfo/app.php b/apps/user_ldap/appinfo/app.php index ce3079da0b..9e72e388e6 100644 --- a/apps/user_ldap/appinfo/app.php +++ b/apps/user_ldap/appinfo/app.php @@ -23,7 +23,7 @@ OCP\App::registerAdmin('user_ldap', 'settings'); -$connector = new OCA\user_ldap\lib\Connection('user_ldap'); +$connector = new OCA\user_ldap\lib\Connection('', 'user_ldap'); $userBackend = new OCA\user_ldap\USER_LDAP(); $userBackend->setConnector($connector); $groupBackend = new OCA\user_ldap\GROUP_LDAP(); diff --git a/apps/user_ldap/lib/connection.php b/apps/user_ldap/lib/connection.php index 7046cbbfc7..21b2d7560c 100644 --- a/apps/user_ldap/lib/connection.php +++ b/apps/user_ldap/lib/connection.php @@ -4,7 +4,7 @@ * ownCloud – LDAP Access * * @author Arthur Schiwon - * @copyright 2012 Arthur Schiwon blizzz@owncloud.com + * @copyright 2012, 2013 Arthur Schiwon blizzz@owncloud.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE @@ -25,6 +25,7 @@ namespace OCA\user_ldap\lib; class Connection { private $ldapConnectionRes = null; + private $configPrefix; private $configID; private $configured = false; @@ -59,7 +60,8 @@ class Connection { 'hasPagedResultSupport' => false, ); - public function __construct($configID = 'user_ldap') { + public function __construct($configPrefix = '', $configID = 'user_ldap') { + $this->configPrefix = $configPrefix; $this->configID = $configID; $this->cache = \OC_Cache::getGlobalCache(); $this->config['hasPagedResultSupport'] = (function_exists('ldap_control_paged_result') && function_exists('ldap_control_paged_result_response')); @@ -89,7 +91,7 @@ class Connection { \OCP\Util::writeLog('user_ldap', 'Set config ldapUuidAttribute to '.$value, \OCP\Util::DEBUG); $this->config[$name] = $value; if(!empty($this->configID)) { - \OCP\Config::setAppValue($this->configID, 'ldap_uuid_attribute', $value); + \OCP\Config::setAppValue($this->configID, $this->configPrefix.'ldap_uuid_attribute', $value); } $changed = true; } @@ -126,7 +128,7 @@ class Connection { } private function getCacheKey($key) { - $prefix = 'LDAP-'.$this->configID.'-'; + $prefix = 'LDAP-'.$this->configID.'-'.$this->configPrefix.'-'; if(is_null($key)) { return $prefix; } @@ -183,30 +185,30 @@ class Connection { \OCP\Util::writeLog('user_ldap', 'Checking conf state: isConfigured? '.print_r($this->configured, true).' isForce? '.print_r($force, true).' configID? '.print_r($this->configID, true), \OCP\Util::DEBUG); if((!$this->configured || $force) && !is_null($this->configID)) { \OCP\Util::writeLog('user_ldap', 'Reading the configuration', \OCP\Util::DEBUG); - $this->config['ldapHost'] = \OCP\Config::getAppValue($this->configID, 'ldap_host', ''); - $this->config['ldapPort'] = \OCP\Config::getAppValue($this->configID, 'ldap_port', 389); - $this->config['ldapAgentName'] = \OCP\Config::getAppValue($this->configID, 'ldap_dn', ''); - $this->config['ldapAgentPassword'] = base64_decode(\OCP\Config::getAppValue($this->configID, 'ldap_agent_password', '')); - $this->config['ldapBase'] = preg_split('/\r\n|\r|\n/', \OCP\Config::getAppValue($this->configID, 'ldap_base', '')); - $this->config['ldapBaseUsers'] = preg_split('/\r\n|\r|\n/', \OCP\Config::getAppValue($this->configID, 'ldap_base_users', $this->config['ldapBase'])); - $this->config['ldapBaseGroups'] = preg_split('/\r\n|\r|\n/', \OCP\Config::getAppValue($this->configID, 'ldap_base_groups', $this->config['ldapBase'])); - $this->config['ldapTLS'] = \OCP\Config::getAppValue($this->configID, 'ldap_tls', 0); - $this->config['ldapNoCase'] = \OCP\Config::getAppValue($this->configID, 'ldap_nocase', 0); - $this->config['turnOffCertCheck'] = \OCP\Config::getAppValue($this->configID, 'ldap_turn_off_cert_check', 0); - $this->config['ldapUserDisplayName'] = mb_strtolower(\OCP\Config::getAppValue($this->configID, 'ldap_display_name', 'uid'), 'UTF-8'); - $this->config['ldapUserFilter'] = \OCP\Config::getAppValue($this->configID, 'ldap_userlist_filter', 'objectClass=person'); - $this->config['ldapGroupFilter'] = \OCP\Config::getAppValue($this->configID, 'ldap_group_filter', '(objectClass=posixGroup)'); - $this->config['ldapLoginFilter'] = \OCP\Config::getAppValue($this->configID, 'ldap_login_filter', '(uid=%uid)'); - $this->config['ldapGroupDisplayName'] = mb_strtolower(\OCP\Config::getAppValue($this->configID, 'ldap_group_display_name', 'uid'), 'UTF-8'); - $this->config['ldapQuotaAttribute'] = \OCP\Config::getAppValue($this->configID, 'ldap_quota_attr', ''); - $this->config['ldapQuotaDefault'] = \OCP\Config::getAppValue($this->configID, 'ldap_quota_def', ''); - $this->config['ldapEmailAttribute'] = \OCP\Config::getAppValue($this->configID, 'ldap_email_attr', ''); - $this->config['ldapGroupMemberAssocAttr'] = \OCP\Config::getAppValue($this->configID, 'ldap_group_member_assoc_attribute', 'uniqueMember'); + $this->config['ldapHost'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_host', ''); + $this->config['ldapPort'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_port', 389); + $this->config['ldapAgentName'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_dn', ''); + $this->config['ldapAgentPassword'] = base64_decode(\OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_agent_password', '')); + $this->config['ldapBase'] = preg_split('/\r\n|\r|\n/', \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_base', '')); + $this->config['ldapBaseUsers'] = preg_split('/\r\n|\r|\n/', \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_base_users', $this->config['ldapBase'])); + $this->config['ldapBaseGroups'] = preg_split('/\r\n|\r|\n/', \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_base_groups', $this->config['ldapBase'])); + $this->config['ldapTLS'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_tls', 0); + $this->config['ldapNoCase'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_nocase', 0); + $this->config['turnOffCertCheck'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_turn_off_cert_check', 0); + $this->config['ldapUserDisplayName'] = mb_strtolower(\OCP\Config::getAppValue($this->configID, '$this->configPrefix.ldap_display_name', 'uid'), 'UTF-8'); + $this->config['ldapUserFilter'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_userlist_filter', 'objectClass=person'); + $this->config['ldapGroupFilter'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_group_filter', '(objectClass=posixGroup)'); + $this->config['ldapLoginFilter'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_login_filter', '(uid=%uid)'); + $this->config['ldapGroupDisplayName'] = mb_strtolower(\OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_group_display_name', 'uid'), 'UTF-8'); + $this->config['ldapQuotaAttribute'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_quota_attr', ''); + $this->config['ldapQuotaDefault'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_quota_def', ''); + $this->config['ldapEmailAttribute'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_email_attr', ''); + $this->config['ldapGroupMemberAssocAttr'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_group_member_assoc_attribute', 'uniqueMember'); $this->config['ldapIgnoreNamingRules'] = \OCP\Config::getSystemValue('ldapIgnoreNamingRules', false); - $this->config['ldapCacheTTL'] = \OCP\Config::getAppValue($this->configID, 'ldap_cache_ttl', 10*60); - $this->config['ldapUuidAttribute'] = \OCP\Config::getAppValue($this->configID, 'ldap_uuid_attribute', 'auto'); - $this->config['ldapOverrideUuidAttribute'] = \OCP\Config::getAppValue($this->configID, 'ldap_override_uuid_attribute', 0); - $this->config['homeFolderNamingRule'] = \OCP\Config::getAppValue($this->configID, 'home_folder_naming_rule', 'opt:username'); + $this->config['ldapCacheTTL'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_cache_ttl', 10*60); + $this->config['ldapUuidAttribute'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_uuid_attribute', 'auto'); + $this->config['ldapOverrideUuidAttribute'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_override_uuid_attribute', 0); + $this->config['homeFolderNamingRule'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'home_folder_naming_rule', 'opt:username'); $this->configured = $this->validateConfiguration(); } @@ -264,7 +266,7 @@ class Connection { \OCP\Util::writeLog('user_ldap', 'No group filter is specified, LDAP group feature will not be used.', \OCP\Util::INFO); } if(!in_array($this->config['ldapUuidAttribute'], array('auto', 'entryuuid', 'nsuniqueid', 'objectguid')) && (!is_null($this->configID))) { - \OCP\Config::setAppValue($this->configID, 'ldap_uuid_attribute', 'auto'); + \OCP\Config::setAppValue($this->configID, $this->configPrefix.'ldap_uuid_attribute', 'auto'); \OCP\Util::writeLog('user_ldap', 'Illegal value for the UUID Attribute, reset to autodetect.', \OCP\Util::INFO); } From fab5817f67a9e9dde245d522838fee3b928fcbd8 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Thu, 10 Jan 2013 23:34:24 +0100 Subject: [PATCH 165/347] documentation for the Connection constructor --- apps/user_ldap/lib/connection.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/user_ldap/lib/connection.php b/apps/user_ldap/lib/connection.php index 21b2d7560c..803ac34f59 100644 --- a/apps/user_ldap/lib/connection.php +++ b/apps/user_ldap/lib/connection.php @@ -60,6 +60,11 @@ class Connection { 'hasPagedResultSupport' => false, ); + /** + * @brief Constructor + * @param $configPrefix a string with the prefix for the configkey column (appconfig table) + * @param $configID a string with the value for the appid column (appconfig table) or null for on-the-fly connections + */ public function __construct($configPrefix = '', $configID = 'user_ldap') { $this->configPrefix = $configPrefix; $this->configID = $configID; From 4835525c469d5ac75104e92c2dfbbb049d62890c Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Thu, 10 Jan 2013 22:28:50 -0500 Subject: [PATCH 166/347] Switch scan to scanFile for root of mount points --- lib/files/view.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/files/view.php b/lib/files/view.php index 703cda5123..fa031b7478 100644 --- a/lib/files/view.php +++ b/lib/files/view.php @@ -768,9 +768,9 @@ class View { if ($subStorage) { $subCache = $subStorage->getCache(''); - if ($subCache->getStatus('') < Cache\Cache::COMPLETE) { + if ($subCache->getStatus('') === Cache\Cache::NOT_FOUND) { $subScanner = $subStorage->getScanner(''); - $subScanner->scan('', Cache\Scanner::SCAN_SHALLOW); + $subScanner->scanFile(''); } else { $subWatcher = $subStorage->getWatcher(''); $subWatcher->checkUpdate(''); From 36cac7f924ad07738a3cb72fee06f21d07baad42 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Thu, 10 Jan 2013 22:29:47 -0500 Subject: [PATCH 167/347] Return NOT_FOUND in shared cache --- apps/files_sharing/lib/cache.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_sharing/lib/cache.php b/apps/files_sharing/lib/cache.php index d35a5148de..0b187a3c3f 100644 --- a/apps/files_sharing/lib/cache.php +++ b/apps/files_sharing/lib/cache.php @@ -196,7 +196,7 @@ class Shared_Cache extends Cache { if ($cache = $this->getSourceCache($file)) { return $cache->getStatus($this->files[$file]); } - return false; + return self::NOT_FOUND; } /** From 09c54722a877352713d8cefdb6a0a92860633898 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Fri, 11 Jan 2013 18:13:22 +0100 Subject: [PATCH 168/347] add LDAP User and Group proxies to suppoer multiple servers --- apps/user_ldap/group_proxy.php | 178 +++++++++++++++++++++++++++++++++ apps/user_ldap/lib/proxy.php | 104 +++++++++++++++++++ apps/user_ldap/user_proxy.php | 159 +++++++++++++++++++++++++++++ 3 files changed, 441 insertions(+) create mode 100644 apps/user_ldap/group_proxy.php create mode 100644 apps/user_ldap/lib/proxy.php create mode 100644 apps/user_ldap/user_proxy.php diff --git a/apps/user_ldap/group_proxy.php b/apps/user_ldap/group_proxy.php new file mode 100644 index 0000000000..5aa1aef0e0 --- /dev/null +++ b/apps/user_ldap/group_proxy.php @@ -0,0 +1,178 @@ +. + * + */ + +namespace OCA\user_ldap; + +class Group_Proxy extends lib\Proxy implements \OCP\GroupInterface { + private $backends = array(); + private $refBackend = null; + + /** + * @brief Constructor + * @param $serverConfigPrefixes array containing the config Prefixes + */ + public function __construct($serverConfigPrefixes) { + parent::__construct(); + foreach($serverConfigPrefixes as $configPrefix) { + $this->backends[$configPrefix] = new \OCA\user_ldap\GROUP_LDAP(); + $connector = $this->getConnector($configPrefix); + $this->backends[$configPrefix]->setConnector($connector); + if(is_null($this->refBackend)) { + $this->refBackend = &$this->backends[$configPrefix]; + } + } + } + + /** + * @brief Tries the backends one after the other until a positive result is returned from the specified method + * @param $gid string, the gid connected to the request + * @param $method string, the method of the group backend that shall be called + * @param $parameters an array of parameters to be passed + * @return mixed, the result of the method or false + */ + protected function walkBackends($gid, $method, $parameters) { + $cacheKey = $this->getGroupCacheKey($gid); + foreach($this->backends as $configPrefix => $backend) { + if($result = call_user_func_array(array($backend, $method), $parameters)) { + $this->writeToCache($cacheKey, $configPrefix); + return $result; + } + } + return false; + } + + /** + * @brief Asks the backend connected to the server that supposely takes care of the gid from the request. + * @param $gid string, the gid connected to the request + * @param $method string, the method of the group backend that shall be called + * @param $parameters an array of parameters to be passed + * @return mixed, the result of the method or false + */ + protected function callOnLastSeenOn($gid, $method, $parameters) { + $cacheKey = $this->getGroupCacheKey($gid);; + $prefix = $this->getFromCache($cacheKey); + //in case the uid has been found in the past, try this stored connection first + if(!is_null($prefix)) { + if(isset($this->backends[$prefix])) { + $result = call_user_func_array(array($this->backends[$prefix], $method), $parameters); + if(!$result) { + //not found here, reset cache to null + $this->writeToCache($cacheKey, null); + } + return $result; + } + } + return false; + } + + /** + * @brief is user in group? + * @param $uid uid of the user + * @param $gid gid of the group + * @returns true/false + * + * Checks whether the user is member of a group or not. + */ + public function inGroup($uid, $gid) { + return $this->handleRequest($gid, 'inGroup', array($uid, $gid)); + } + + /** + * @brief Get all groups a user belongs to + * @param $uid Name of the user + * @returns array with group names + * + * This function fetches all groups a user belongs to. It does not check + * if the user exists at all. + */ + public function getUserGroups($uid) { + $groups = array(); + + foreach($this->backends as $backend) { + $backendGroups = $backend->getUserGroups($uid); + if (is_array($backendGroups)) { + $groups = array_merge($groups, $backendGroups); + } + } + + return $groups; + } + + /** + * @brief get a list of all users in a group + * @returns array with user ids + */ + public function usersInGroup($gid, $search = '', $limit = -1, $offset = 0) { + $users = array(); + + foreach($this->backends as $backend) { + $backendUsers = $backend->usersInGroup($gid, $search, $limit, $offset); + if (is_array($backendUsers)) { + $users = array_merge($users, $backendUsers); + } + } + + return $users; + } + + /** + * @brief get a list of all groups + * @returns array with group names + * + * Returns a list with all groups + */ + public function getGroups($search = '', $limit = -1, $offset = 0) { + $groups = array(); + + foreach($this->backends as $backend) { + $backendGroups = $backend->getGroups($search, $limit, $offset); + if (is_array($backendGroups)) { + $groups = array_merge($groups, $backendGroups); + } + } + + return $groups; + } + + /** + * check if a group exists + * @param string $gid + * @return bool + */ + public function groupExists($gid) { + return $this->handleRequest($gid, 'groupExists', array($gid)); + } + + /** + * @brief Check if backend implements actions + * @param $actions bitwise-or'ed actions + * @returns boolean + * + * Returns the supported actions as int to be + * compared with OC_USER_BACKEND_CREATE_USER etc. + */ + public function implementsActions($actions) { + //it's the same across all our user backends obviously + return $this->refBackend->implementsActions($actions); + } +} \ No newline at end of file diff --git a/apps/user_ldap/lib/proxy.php b/apps/user_ldap/lib/proxy.php new file mode 100644 index 0000000000..c80e216347 --- /dev/null +++ b/apps/user_ldap/lib/proxy.php @@ -0,0 +1,104 @@ +. + * + */ + +namespace OCA\user_ldap\lib; + +abstract class Proxy { + static private $connectors = array(); + + public function __construct() { + $this->cache = \OC_Cache::getGlobalCache(); + } + + private function addConnector($configPrefix) { + self::$connectors[$configPrefix] = new \OCA\user_ldap\lib\Connection($configPrefix); + } + + protected function getConnector($configPrefix) { + if(!isset(self::$connectors[$configPrefix])) { + $this->addConnector($configPrefix); + } + return self::$connectors[$configPrefix]; + } + + protected function getConnectors() { + return self::$connectors; + } + + protected function getUserCacheKey($uid) { + return 'user-'.$uid.'-lastSeenOn'; + } + + protected function getGroupCacheKey($gid) { + return 'group-'.$gid.'-lastSeenOn'; + } + + abstract protected function callOnLastSeenOn($id, $method, $parameters); + abstract protected function walkBackends($id, $method, $parameters); + + /** + * @brief Takes care of the request to the User backend + * @param $uid string, the uid connected to the request + * @param $method string, the method of the user backend that shall be called + * @param $parameters an array of parameters to be passed + * @return mixed, the result of the specified method + */ + protected function handleRequest($id, $method, $parameters) { + if(!$result = $this->callOnLastSeenOn($id, $method, $parameters)) { + $result = $this->walkBackends($id, $method, $parameters); + } + return $result; + } + + private function getCacheKey($key) { + $prefix = 'LDAP-Proxy-'; + if(is_null($key)) { + return $prefix; + } + return $prefix.md5($key); + } + + public function getFromCache($key) { + if(!$this->isCached($key)) { + return null; + } + $key = $this->getCacheKey($key); + + return unserialize(base64_decode($this->cache->get($key))); + } + + public function isCached($key) { + $key = $this->getCacheKey($key); + return $this->cache->hasKey($key); + } + + public function writeToCache($key, $value) { + $key = $this->getCacheKey($key); + $value = base64_encode(serialize($value)); + $this->cache->set($key, $value, '2592000'); + } + + public function clearCache() { + $this->cache->clear($this->getCacheKey(null)); + } +} \ No newline at end of file diff --git a/apps/user_ldap/user_proxy.php b/apps/user_ldap/user_proxy.php new file mode 100644 index 0000000000..47f901ddb5 --- /dev/null +++ b/apps/user_ldap/user_proxy.php @@ -0,0 +1,159 @@ +. + * + */ + +namespace OCA\user_ldap; + +class User_Proxy extends lib\Proxy implements \OCP\UserInterface { + private $backends = array(); + private $refBackend = null; + + /** + * @brief Constructor + * @param $serverConfigPrefixes array containing the config Prefixes + */ + public function __construct($serverConfigPrefixes) { + parent::__construct(); + foreach($serverConfigPrefixes as $configPrefix) { + $this->backends[$configPrefix] = new \OCA\user_ldap\USER_LDAP(); + $connector = $this->getConnector($configPrefix); + $this->backends[$configPrefix]->setConnector($connector); + if(is_null($this->refBackend)) { + $this->refBackend = &$this->backends[$configPrefix]; + } + } + } + + /** + * @brief Tries the backends one after the other until a positive result is returned from the specified method + * @param $uid string, the uid connected to the request + * @param $method string, the method of the user backend that shall be called + * @param $parameters an array of parameters to be passed + * @return mixed, the result of the method or false + */ + protected function walkBackends($uid, $method, $parameters) { + $cacheKey = $this->getUserCacheKey($uid); + foreach($this->backends as $configPrefix => $backend) { + if($result = call_user_func_array(array($backend, $method), $parameters)) { + $this->writeToCache($cacheKey, $configPrefix); + return $result; + } + } + return false; + } + + /** + * @brief Asks the backend connected to the server that supposely takes care of the uid from the request. + * @param $uid string, the uid connected to the request + * @param $method string, the method of the user backend that shall be called + * @param $parameters an array of parameters to be passed + * @return mixed, the result of the method or false + */ + protected function callOnLastSeenOn($uid, $method, $parameters) { + $cacheKey = $this->getUserCacheKey($uid); + $prefix = $this->getFromCache($cacheKey); + //in case the uid has been found in the past, try this stored connection first + if(!is_null($prefix)) { + if(isset($this->backends[$prefix])) { + $result = call_user_func_array(array($this->backends[$prefix], $method), $parameters); + if(!$result) { + //not found here, reset cache to null + $this->writeToCache($cacheKey, null); + } + return $result; + } + } + return false; + } + + /** + * @brief Check if backend implements actions + * @param $actions bitwise-or'ed actions + * @returns boolean + * + * Returns the supported actions as int to be + * compared with OC_USER_BACKEND_CREATE_USER etc. + */ + public function implementsActions($actions) { + //it's the same across all our user backends obviously + return $this->refBackend->implementsActions($actions); + } + + /** + * @brief Get a list of all users + * @returns array with all uids + * + * Get a list of all users. + */ + public function getUsers($search = '', $limit = 10, $offset = 0) { + //we do it just as the /OC_User implementation: do not play around with limit and offset but ask all backends + $users = array(); + foreach($this->backends as $backend) { + $backendUsers = $backend->getUsers($search, $limit, $offset); + if (is_array($backendUsers)) { + $users = array_merge($users, $backendUsers); + } + } + return $users; + } + + /** + * @brief check if a user exists + * @param string $uid the username + * @return boolean + */ + public function userExists($uid) { + return $this->handleRequest($uid, 'userExists', array($uid)); + } + + /** + * @brief Check if the password is correct + * @param $uid The username + * @param $password The password + * @returns true/false + * + * Check if the password is correct without logging in the user + */ + public function checkPassword($uid, $password) { + return $this->handleRequest($uid, 'checkPassword', array($uid, $password)); + } + + /** + * @brief get the user's home directory + * @param string $uid the username + * @return boolean + */ + public function getHome($uid) { + return $this->handleRequest($uid, 'getHome', array($uid)); + } + + /** + * @brief delete a user + * @param $uid The username of the user to delete + * @returns true/false + * + * Deletes a user + */ + public function deleteUser($uid) { + return false; + } +} \ No newline at end of file From 8a63bcc1e85499335ade1df459f0c9f467161404 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Fri, 11 Jan 2013 20:56:36 -0500 Subject: [PATCH 169/347] Don't use more entropy for etags --- lib/files/storage/common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/files/storage/common.php b/lib/files/storage/common.php index e859d447f3..591803f044 100644 --- a/lib/files/storage/common.php +++ b/lib/files/storage/common.php @@ -274,7 +274,7 @@ abstract class Common implements \OC\Files\Storage\Storage { $hash = call_user_func($ETagFunction, $path); return $hash; }else{ - return uniqid('', true); + return uniqid(); } } } From 9e2f3a53244e353cb75f9927e1c69ef40f589db7 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Fri, 11 Jan 2013 20:59:53 -0500 Subject: [PATCH 170/347] Remove old create etag function --- lib/connector/sabre/file.php | 9 --------- 1 file changed, 9 deletions(-) diff --git a/lib/connector/sabre/file.php b/lib/connector/sabre/file.php index 1770b49128..e0723e1230 100644 --- a/lib/connector/sabre/file.php +++ b/lib/connector/sabre/file.php @@ -101,15 +101,6 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D return $this->getETagPropertyForPath($this->path); } - /** - * 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 \OC\Files\Filesystem::hash('md5', $path); - } - /** * Returns the mime-type for a file * From a00b9e0a03a7cdb1103415d33d2c3f22e86edffb Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Fri, 11 Jan 2013 21:01:28 -0500 Subject: [PATCH 171/347] Bump version --- lib/util.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/util.php b/lib/util.php index e814a3a32d..faae962859 100755 --- a/lib/util.php +++ b/lib/util.php @@ -74,7 +74,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,06); + return array(4,91,07); } /** From b30648cb7dc258208fad4dadb297aa1d792fa7ef Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Fri, 11 Jan 2013 21:09:01 -0500 Subject: [PATCH 172/347] Don't waste time making another call since we know it doesn't exist --- lib/connector/sabre/file.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/connector/sabre/file.php b/lib/connector/sabre/file.php index e0723e1230..1c18a39174 100644 --- a/lib/connector/sabre/file.php +++ b/lib/connector/sabre/file.php @@ -98,7 +98,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D if (isset($properties[self::GETETAG_PROPERTYNAME])) { return $properties[self::GETETAG_PROPERTYNAME]; } - return $this->getETagPropertyForPath($this->path); + return null; } /** From 094a852bff378c03c873b6e8fd94587d2a2c784e Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Fri, 11 Jan 2013 21:09:58 -0500 Subject: [PATCH 173/347] Wrap the etag in double quotes --- lib/connector/sabre/node.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/connector/sabre/node.php b/lib/connector/sabre/node.php index dd8ae152ff..93d8fc477d 100644 --- a/lib/connector/sabre/node.php +++ b/lib/connector/sabre/node.php @@ -213,7 +213,7 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr static public function getETagPropertyForPath($path) { $data = \OC\Files\Filesystem::getFileInfo($path); if (isset($data['etag'])) { - return $data['etag']; + return '"'.$data['etag'].'"'; } return null; } From 94068e5d08cba776e410d925e26037d442b5bc62 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 3 Jan 2013 00:26:13 +0100 Subject: [PATCH 174/347] Cache: show upgrade progress --- apps/files/ajax/upgrade.php | 42 ++++++++ apps/files/appinfo/app.php | 10 -- apps/files/css/files.css | 9 ++ apps/files/index.php | 72 ++++++++------ apps/files/js/upgrade.js | 17 ++++ apps/files/templates/upgrade.php | 4 + lib/files/cache/legacy.php | 73 ++++++++++++++ lib/files/cache/upgrade.php | 161 ++++++++++++++++++++++--------- 8 files changed, 305 insertions(+), 83 deletions(-) create mode 100644 apps/files/ajax/upgrade.php create mode 100644 apps/files/js/upgrade.js create mode 100644 apps/files/templates/upgrade.php create mode 100644 lib/files/cache/legacy.php diff --git a/apps/files/ajax/upgrade.php b/apps/files/ajax/upgrade.php new file mode 100644 index 0000000000..965c0073b8 --- /dev/null +++ b/apps/files/ajax/upgrade.php @@ -0,0 +1,42 @@ +hasItems()) { + OC_Hook::connect('\OC\Files\Cache\Upgrade', 'migrate_path', $listener, 'upgradePath'); + + $upgrade = new \OC\Files\Cache\Upgrade($legacy); + $count = $legacy->getCount(); + $eventSource->send('total', $count); + $upgrade->upgradePath('/' . $user . '/files'); +} +\OC\Files\Cache\Upgrade::upgradeDone($user); +$eventSource->send('done', true); +$eventSource->close(); + +class UpgradeListener { + /** + * @var OC_EventSource $eventSource + */ + private $eventSource; + + private $count = 0; + private $lastSend = 0; + + public function __construct($eventSource) { + $this->eventSource = $eventSource; + } + + public function upgradePath($path) { + $this->count++; + if ($this->count > ($this->lastSend + 5)) { + $this->lastSend = $this->count; + $this->eventSource->send('count', $this->count); + } + } +} diff --git a/apps/files/appinfo/app.php b/apps/files/appinfo/app.php index 643d8ed18a..ab2f3b01a2 100644 --- a/apps/files/appinfo/app.php +++ b/apps/files/appinfo/app.php @@ -10,13 +10,3 @@ OCP\App::addNavigationEntry( array( "id" => "files_index", "name" => $l->t("Files") )); OC_Search::registerProvider('OC_Search_Provider_File'); - -if (OC_User::isLoggedIn()) { - // update OC4.5 filecache to OC5 filecache, can't do this in update.php since it needs to happen for each user individually - $cacheVersion = (int)OCP\Config::getUserValue(OC_User::getUser(), 'files', 'cache_version', 4); - if ($cacheVersion < 5) { - \OC_Log::write('files', 'updating filecache to 5.0 for user ' . OC_User::getUser(), \OC_Log::INFO); - \OC\Files\Cache\Upgrade::upgrade(); - OCP\Config::setUserValue(OC_User::getUser(), 'files', 'cache_version', 5); - } -} diff --git a/apps/files/css/files.css b/apps/files/css/files.css index 36a1e5c954..0c130efe47 100644 --- a/apps/files/css/files.css +++ b/apps/files/css/files.css @@ -122,3 +122,12 @@ a.action>img { max-height:16px; max-width:16px; vertical-align:text-bottom; } #scanning-message{ top:40%; left:40%; position:absolute; display:none; } div.crumb a{ padding:0.9em 0 0.7em 0; } + +#upgrade { + width: 400px; + position: absolute; + top: 200px; + left: 50%; + text-align: center; + margin-left: -200px; +} diff --git a/apps/files/index.php b/apps/files/index.php index 993d8b4dcf..0dce768696 100644 --- a/apps/files/index.php +++ b/apps/files/index.php @@ -28,7 +28,6 @@ OCP\User::checkLoggedIn(); OCP\Util::addStyle('files', 'files'); OCP\Util::addscript('files', 'jquery.iframe-transport'); OCP\Util::addscript('files', 'jquery.fileupload'); -OCP\Util::addscript('files', 'files'); OCP\Util::addscript('files', 'filelist'); OCP\Util::addscript('files', 'fileactions'); OCP\Util::addscript('files', 'keyboardshortcuts'); @@ -37,8 +36,8 @@ OCP\App::setActiveNavigationEntry('files_index'); // Load the files $dir = isset($_GET['dir']) ? stripslashes($_GET['dir']) : ''; // Redirect if directory does not exist -if(!\OC\Files\Filesystem::is_dir($dir . '/')) { - header('Location: '.$_SERVER['SCRIPT_NAME'].''); +if (!\OC\Files\Filesystem::is_dir($dir . '/')) { + header('Location: ' . $_SERVER['SCRIPT_NAME'] . ''); exit(); } @@ -53,16 +52,25 @@ function fileCmp($a, $b) { } $files = array(); -foreach( \OC\Files\Filesystem::getDirectoryContent( $dir ) as $i ) { - $i['date'] = OCP\Util::formatDate($i['mtime'] ); - if($i['type'] == 'file') { +$user = OC_User::getUser(); +if (\OC\Files\Cache\Upgrade::needUpgrade($user)) { //dont load anything if we need to upgrade the cache + $content = array(); + $needUpgrade = true; + $freeSpace = 0; +} else { + $content = \OC\Files\Filesystem::getDirectoryContent($dir); + $freeSpace = \OC\Files\Filesystem::free_space($dir); + $needUpgrade = false; +} +foreach ($content as $i) { + $i['date'] = OCP\Util::formatDate($i['mtime']); + if ($i['type'] == 'file') { $fileinfo = pathinfo($i['name']); $i['basename'] = $fileinfo['filename']; if (!empty($fileinfo['extension'])) { - $i['extension']='.' . $fileinfo['extension']; - } - else { - $i['extension']=''; + $i['extension'] = '.' . $fileinfo['extension']; + } else { + $i['extension'] = ''; } } $i['directory'] = $dir; @@ -74,10 +82,10 @@ usort($files, "fileCmp"); // Make breadcrumb $breadcrumb = array(); $pathtohere = ''; -foreach( explode( '/', $dir ) as $i ) { - if( $i != '' ) { +foreach (explode('/', $dir) as $i) { + if ($i != '') { $pathtohere .= '/' . $i; - $breadcrumb[] = array( 'dir' => $pathtohere, 'name' => $i ); + $breadcrumb[] = array('dir' => $pathtohere, 'name' => $i); } } @@ -94,29 +102,35 @@ $upload_max_filesize = OCP\Util::computerFileSize(ini_get('upload_max_filesize') $post_max_size = OCP\Util::computerFileSize(ini_get('post_max_size')); $maxUploadFilesize = min($upload_max_filesize, $post_max_size); -$freeSpace = \OC\Files\Filesystem::free_space($dir); -$freeSpace = max($freeSpace,0); +$freeSpace = max($freeSpace, 0); $maxUploadFilesize = min($maxUploadFilesize, $freeSpace); $permissions = OCP\PERMISSION_READ; if (\OC\Files\Filesystem::isUpdatable($dir . '/')) { - $permissions |= OCP\PERMISSION_UPDATE; + $permissions |= OCP\PERMISSION_UPDATE; } if (\OC\Files\Filesystem::isDeletable($dir . '/')) { - $permissions |= OCP\PERMISSION_DELETE; + $permissions |= OCP\PERMISSION_DELETE; } if (\OC\Files\Filesystem::isSharable($dir . '/')) { - $permissions |= OCP\PERMISSION_SHARE; + $permissions |= OCP\PERMISSION_SHARE; } -$tmpl = new OCP\Template( 'files', 'index', 'user' ); -$tmpl->assign( 'fileList', $list->fetchPage(), false ); -$tmpl->assign( 'breadcrumb', $breadcrumbNav->fetchPage(), false ); -$tmpl->assign( 'dir', \OC\Files\Filesystem::normalizePath($dir)); -$tmpl->assign( 'isCreatable', \OC\Files\Filesystem::isCreatable($dir . '/')); -$tmpl->assign('permissions', $permissions); -$tmpl->assign('files', $files); -$tmpl->assign('uploadMaxFilesize', $maxUploadFilesize); -$tmpl->assign('uploadMaxHumanFilesize', OCP\Util::humanFileSize($maxUploadFilesize)); -$tmpl->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true))); -$tmpl->printPage(); +if ($needUpgrade) { + OCP\Util::addscript('files', 'upgrade'); + $tmpl = new OCP\Template('files', 'upgrade', 'user'); + $tmpl->printPage(); +} else { + OCP\Util::addscript('files', 'files'); + $tmpl = new OCP\Template('files', 'index', 'user'); + $tmpl->assign('fileList', $list->fetchPage(), false); + $tmpl->assign('breadcrumb', $breadcrumbNav->fetchPage(), false); + $tmpl->assign('dir', \OC\Files\Filesystem::normalizePath($dir)); + $tmpl->assign('isCreatable', \OC\Files\Filesystem::isCreatable($dir . '/')); + $tmpl->assign('permissions', $permissions); + $tmpl->assign('files', $files); + $tmpl->assign('uploadMaxFilesize', $maxUploadFilesize); + $tmpl->assign('uploadMaxHumanFilesize', OCP\Util::humanFileSize($maxUploadFilesize)); + $tmpl->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true))); + $tmpl->printPage(); +} diff --git a/apps/files/js/upgrade.js b/apps/files/js/upgrade.js new file mode 100644 index 0000000000..02d57fc9e6 --- /dev/null +++ b/apps/files/js/upgrade.js @@ -0,0 +1,17 @@ +$(document).ready(function () { + var eventSource, total, bar = $('#progressbar'); + console.log('start'); + bar.progressbar({value: 0}); + eventSource = new OC.EventSource(OC.filePath('files', 'ajax', 'upgrade.php')); + eventSource.listen('total', function (count) { + total = count; + console.log(count + ' files needed to be migrated'); + }); + eventSource.listen('count', function (count) { + bar.progressbar({value: (count / total) * 100}); + console.log(count); + }); + eventSource.listen('done', function () { + document.location.reload(); + }); +}); diff --git a/apps/files/templates/upgrade.php b/apps/files/templates/upgrade.php new file mode 100644 index 0000000000..de6cc71302 --- /dev/null +++ b/apps/files/templates/upgrade.php @@ -0,0 +1,4 @@ +
+ t('Upgrading filesystem cache...');?> +
+
diff --git a/lib/files/cache/legacy.php b/lib/files/cache/legacy.php new file mode 100644 index 0000000000..ee10a1c135 --- /dev/null +++ b/lib/files/cache/legacy.php @@ -0,0 +1,73 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Files\Cache; + +/** + * Provide read only support for the old filecache + */ +class Legacy { + private $user; + + public function __construct($user) { + $this->user = $user; + } + + function getCount() { + $query = \OC_DB::prepare('SELECT COUNT(`id`) AS `count` FROM `*PREFIX*fscache` WHERE `user` = ?'); + $result = $query->execute(array($this->user)); + if ($row = $result->fetchRow()) { + return $row['count']; + } else { + return 0; + } + } + + /** + * check if a legacy cache is present and holds items + * + * @return bool + */ + function hasItems() { + try { + $query = \OC_DB::prepare('SELECT `id` FROM `*PREFIX*fscache` WHERE `user` = ? LIMIT 1'); + } catch (\Exception $e) { + return false; + } + try { + $result = $query->execute(array($this->user)); + } catch (\Exception $e) { + return false; + } + return (bool)$result->fetchRow(); + } + + /** + * @param string|int $path + * @return array + */ + function get($path) { + if (is_numeric($path)) { + $query = \OC_DB::prepare('SELECT * FROM `*PREFIX*fscache` WHERE `id` = ?'); + } else { + $query = \OC_DB::prepare('SELECT * FROM `*PREFIX*fscache` WHERE `path` = ?'); + } + $result = $query->execute(array($path)); + return $result->fetchRow(); + } + + /** + * @param int $id + * @return array + */ + function getChildren($id) { + $query = \OC_DB::prepare('SELECT * FROM `*PREFIX*fscache` WHERE `parent` = ?'); + $result = $query->execute(array($id)); + return $result->fetchAll(); + } +} diff --git a/lib/files/cache/upgrade.php b/lib/files/cache/upgrade.php index 77db4c2339..1032e0a844 100644 --- a/lib/files/cache/upgrade.php +++ b/lib/files/cache/upgrade.php @@ -9,62 +9,102 @@ namespace OC\Files\Cache; class Upgrade { - static $permissionsCaches = array(); + /** + * @var Legacy $legacy + */ + private $legacy; - static $numericIds = array(); + private $permissionsCaches = array(); - static function upgrade() { - $insertQuery = \OC_DB::prepare('INSERT INTO `*PREFIX*filecache`( `fileid`, `storage`, `path`, `path_hash`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted` ) - VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'); + private $numericIds = array(); - try { - $oldEntriesQuery = \OC_DB::prepare('SELECT * FROM `*PREFIX*fscache` ORDER BY `id` ASC'); //sort ascending to ensure the parent gets inserted before a child - } catch (\Exception $e) { - return; - } - try { - $oldEntriesResult = $oldEntriesQuery->execute(); - } catch (\Exception $e) { - return; - } - if (!$oldEntriesResult) { + private $mimeTypeIds = array(); + + /** + * @param Legacy $legacy + */ + public function __construct($legacy) { + $this->legacy = $legacy; + } + + /** + * Preform a shallow upgrade + * + * @param string $path + * @param int $mode + */ + function upgradePath($path, $mode = Scanner::SCAN_RECURSIVE) { + if (!$this->legacy->hasItems()) { return; } + \OC_Hook::emit('\OC\Files\Cache\Upgrade', 'migrate_path', $path); - $checkExistingQuery = \OC_DB::prepare('SELECT `fileid` FROM `*PREFIX*filecache` WHERE `fileid` = ?'); + if ($row = $this->legacy->get($path)) { + $data = $this->getNewData($row); + $this->insert($data); - while ($row = $oldEntriesResult->fetchRow()) { - if ($checkExistingQuery->execute(array($row['id']))->fetchRow()) { - continue; + $children = $this->legacy->getChildren($data['id']); + foreach ($children as $child) { + if ($mode == Scanner::SCAN_SHALLOW) { + $childData = $this->getNewData($child); + \OC_Hook::emit('\OC\Files\Cache\Upgrade', 'migrate_path', $child['path']); + $this->insert($childData); + } else { + $this->upgradePath($child['path']); + } } - - list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($row['path']); - /** - * @var \OC\Files\Storage\Storage $storage - * @var string $internalPath; - */ - $pathHash = md5($internalPath); - $storageId = self::getNumericId($storage); - $parentId = ($internalPath === '') ? -1 : $row['parent']; - - $insertQuery->execute(array($row['id'], $storageId, $internalPath, $pathHash, $parentId, $row['name'], $row['mimetype'], $row['mimepart'], $row['size'], $row['mtime'], $row['encrypted'])); - - $permissions = ($row['writable']) ? \OCP\PERMISSION_ALL : \OCP\PERMISSION_READ; - $permissionsCache = self::getPermissionsCache($storage); - $permissionsCache->set($row['id'], $row['user'], $permissions); } } + /** + * @param array $data the data for the new cache + */ + function insert($data) { + $insertQuery = \OC_DB::prepare('INSERT INTO `*PREFIX*filecache` + ( `fileid`, `storage`, `path`, `path_hash`, `parent`, `name`, `mimetype`, `mimepart`, `size`, `mtime`, `encrypted` ) + VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'); + + $insertQuery->execute(array($data['id'], $data['storage'], $data['path'], $data['path_hash'], $data['parent'], $data['name'], + $data['mimetype'], $data['mimepart'], $data['size'], $data['mtime'], $data['encrypted'])); + + $permissionsCache = $this->getPermissionsCache($data['storage_object']); + $permissionsCache->set($data['id'], $data['user'], $data['permissions']); + } + + /** + * get the new data array from the old one + * + * @param array $data the data from the old cache + * @return array + */ + function getNewData($data) { + $newData = $data; + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($data['path']); + /** + * @var \OC\Files\Storage\Storage $storage + * @var string $internalPath; + */ + $newData['path_hash'] = md5($internalPath); + $newData['path'] = $internalPath; + $newData['storage'] = $this->getNumericId($storage); + $newData['parent'] = ($internalPath === '') ? -1 : $data['parent']; + $newData['permissions'] = ($data['writable']) ? \OCP\PERMISSION_ALL : \OCP\PERMISSION_READ; + $newData['storage_object'] = $storage; + $newData['mimetype'] = $this->getMimetypeId($newData['mimetype'], $storage); + $newData['mimepart'] = $this->getMimetypeId($newData['mimepart'], $storage); + return $newData; + } + /** * @param \OC\Files\Storage\Storage $storage * @return Permissions */ - static function getPermissionsCache($storage) { + function getPermissionsCache($storage) { $storageId = $storage->getId(); - if (!isset(self::$permissionsCaches[$storageId])) { - self::$permissionsCaches[$storageId] = $storage->getPermissionsCache(); + if (!isset($this->permissionsCaches[$storageId])) { + $this->permissionsCaches[$storageId] = $storage->getPermissionsCache(); } - return self::$permissionsCaches[$storageId]; + return $this->permissionsCaches[$storageId]; } /** @@ -73,12 +113,45 @@ class Upgrade { * @param \OC\Files\Storage\Storage $storage * @return int */ - static function getNumericId($storage) { + function getNumericId($storage) { $storageId = $storage->getId(); - if (!isset(self::$numericIds[$storageId])) { - $cache = new Cache($storage); - self::$numericIds[$storageId] = $cache->getNumericStorageId(); + if (!isset($this->numericIds[$storageId])) { + $cache = $storage->getCache(); + $this->numericIds[$storageId] = $cache->getNumericStorageId(); } - return self::$numericIds[$storageId]; + return $this->numericIds[$storageId]; + } + + /** + * @param string $mimetype + * @param \OC\Files\Storage\Storage $storage + * @return int + */ + function getMimetypeId($mimetype, $storage) { + if (!isset($this->mimeTypeIds[$mimetype])) { + $cache = new Cache($storage); + $this->mimeTypeIds[$mimetype] = $cache->getMimetypeId($mimetype); + } + return $this->mimeTypeIds[$mimetype]; + } + + /** + * check if a cache upgrade is required for $user + * + * @param string $user + * @return bool + */ + static function needUpgrade($user) { + $cacheVersion = (int)\OCP\Config::getUserValue($user, 'files', 'cache_version', 4); + return $cacheVersion < 5; + } + + /** + * mark the filecache as upgrade + * + * @param string $user + */ + static function upgradeDone($user) { + \OCP\Config::setUserValue($user, 'files', 'cache_version', 5); } } From 7debfac0dc8f602168d8db480cfd4757b4d612b0 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Tue, 15 Jan 2013 19:11:12 +0100 Subject: [PATCH 175/347] Cache: more efficient upgrading --- apps/files/ajax/upgrade.php | 2 ++ lib/files/cache/legacy.php | 10 +++++++++- lib/files/cache/upgrade.php | 24 +++++++++++++++--------- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/apps/files/ajax/upgrade.php b/apps/files/ajax/upgrade.php index 965c0073b8..7237b02c0b 100644 --- a/apps/files/ajax/upgrade.php +++ b/apps/files/ajax/upgrade.php @@ -10,10 +10,12 @@ $legacy = new \OC\Files\Cache\Legacy($user); if ($legacy->hasItems()) { OC_Hook::connect('\OC\Files\Cache\Upgrade', 'migrate_path', $listener, 'upgradePath'); + OC_DB::beginTransaction(); $upgrade = new \OC\Files\Cache\Upgrade($legacy); $count = $legacy->getCount(); $eventSource->send('total', $count); $upgrade->upgradePath('/' . $user . '/files'); + OC_DB::commit(); } \OC\Files\Cache\Upgrade::upgradeDone($user); $eventSource->send('done', true); diff --git a/lib/files/cache/legacy.php b/lib/files/cache/legacy.php index ee10a1c135..33d4b8e7c9 100644 --- a/lib/files/cache/legacy.php +++ b/lib/files/cache/legacy.php @@ -14,6 +14,8 @@ namespace OC\Files\Cache; class Legacy { private $user; + private $cacheHasItems = null; + public function __construct($user) { $this->user = $user; } @@ -34,17 +36,23 @@ class Legacy { * @return bool */ function hasItems() { + if (!is_null($this->cacheHasItems)) { + return $this->cacheHasItems; + } try { $query = \OC_DB::prepare('SELECT `id` FROM `*PREFIX*fscache` WHERE `user` = ? LIMIT 1'); } catch (\Exception $e) { + $this->cacheHasItems = false; return false; } try { $result = $query->execute(array($this->user)); } catch (\Exception $e) { + $this->cacheHasItems = false; return false; } - return (bool)$result->fetchRow(); + $this->cacheHasItems = (bool)$result->fetchRow(); + return $this->cacheHasItems; } /** diff --git a/lib/files/cache/upgrade.php b/lib/files/cache/upgrade.php index 1032e0a844..cd9a9e91a8 100644 --- a/lib/files/cache/upgrade.php +++ b/lib/files/cache/upgrade.php @@ -43,15 +43,21 @@ class Upgrade { $data = $this->getNewData($row); $this->insert($data); - $children = $this->legacy->getChildren($data['id']); - foreach ($children as $child) { - if ($mode == Scanner::SCAN_SHALLOW) { - $childData = $this->getNewData($child); - \OC_Hook::emit('\OC\Files\Cache\Upgrade', 'migrate_path', $child['path']); - $this->insert($childData); - } else { - $this->upgradePath($child['path']); - } + $this->upgradeChilds($data['id'], $mode); + } + } + + /** + * @param int $id + */ + function upgradeChilds($id, $mode = Scanner::SCAN_RECURSIVE) { + $children = $this->legacy->getChildren($id); + foreach ($children as $child) { + $childData = $this->getNewData($child); + \OC_Hook::emit('\OC\Files\Cache\Upgrade', 'migrate_path', $child['path']); + $this->insert($childData); + if ($mode == Scanner::SCAN_RECURSIVE) { + $this->upgradeChilds($child['id']); } } } From 73d45e79a7066b56581072c732f38ca375a4fc29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Tue, 15 Jan 2013 20:35:15 +0100 Subject: [PATCH 176/347] add trash button to web interface --- apps/files/css/files.css | 2 ++ apps/files/index.php | 1 + apps/files/js/files.js | 5 +++++ apps/files/templates/index.php | 6 +++++- 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/apps/files/css/files.css b/apps/files/css/files.css index 36a1e5c954..6355a8cde1 100644 --- a/apps/files/css/files.css +++ b/apps/files/css/files.css @@ -23,6 +23,8 @@ #new>ul>li>p { cursor:pointer; } #new>ul>li>form>input { padding:0.3em; margin:-0.3em; } +#trash { height:17px; margin:0 0 0 1em; z-index:1010; position:absolute; right:13.5em; } + #upload { height:27px; padding:0; margin-left:0.2em; overflow:hidden; } diff --git a/apps/files/index.php b/apps/files/index.php index b64bde44cc..24f58bbd07 100644 --- a/apps/files/index.php +++ b/apps/files/index.php @@ -105,6 +105,7 @@ $tmpl->assign('dir', OC_Filesystem::normalizePath($dir)); $tmpl->assign('isCreatable', OC_Filesystem::isCreatable($dir . '/')); $tmpl->assign('permissions', $permissions); $tmpl->assign('files', $files); +$tmpl->assign('trash', \OCP\App::isEnabled('files_trashbin')); $tmpl->assign('uploadMaxFilesize', $maxUploadFilesize); $tmpl->assign('uploadMaxHumanFilesize', OCP\Util::humanFileSize($maxUploadFilesize)); $tmpl->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true))); diff --git a/apps/files/js/files.js b/apps/files/js/files.js index bb298431e8..c13d7a5961 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -82,6 +82,11 @@ $(document).ready(function() { $(this).parent().children('#file_upload_start').trigger('click'); return false; }); + + // Show Trash bin + $('#trash a').live('click', function() { + console.log("hello"); + }); var lastChecked; diff --git a/apps/files/templates/index.php b/apps/files/templates/index.php index 2e0772443f..f6b4c29d5a 100644 --- a/apps/files/templates/index.php +++ b/apps/files/templates/index.php @@ -35,6 +35,11 @@
+ + +
-
From ad1113c2cb06f1c35102c50e24d803fa1bd2d367 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Wed, 16 Jan 2013 14:56:57 +0100 Subject: [PATCH 177/347] LDAP: fix parameter passed not as expected --- apps/user_ldap/lib/access.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/user_ldap/lib/access.php b/apps/user_ldap/lib/access.php index 422e43fc00..27c7444697 100644 --- a/apps/user_ldap/lib/access.php +++ b/apps/user_ldap/lib/access.php @@ -912,7 +912,7 @@ abstract class Access { $reOffset = ($offset - $limit) < 0 ? 0 : $offset - $limit; //a bit recursive, $offset of 0 is the exit \OCP\Util::writeLog('user_ldap', 'Looking for cookie L/O '.$limit.'/'.$reOffset, \OCP\Util::INFO); - $this->search($filter, $base, $attr, $limit, $reOffset, true); + $this->search($filter, array($base), $attr, $limit, $reOffset, true); $cookie = $this->getPagedResultCookie($base, $filter, $limit, $offset); //still no cookie? obviously, the server does not like us. Let's skip paging efforts. //TODO: remember this, probably does not change in the next request... From 4699f36e4406a50e3b44a2b69b3ecc37a93c321c Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Wed, 16 Jan 2013 14:58:49 +0100 Subject: [PATCH 178/347] LDAP: fix read configuration, remove unnecessary debug output --- apps/user_ldap/lib/connection.php | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/apps/user_ldap/lib/connection.php b/apps/user_ldap/lib/connection.php index 803ac34f59..1dc1d1510a 100644 --- a/apps/user_ldap/lib/connection.php +++ b/apps/user_ldap/lib/connection.php @@ -70,7 +70,6 @@ class Connection { $this->configID = $configID; $this->cache = \OC_Cache::getGlobalCache(); $this->config['hasPagedResultSupport'] = (function_exists('ldap_control_paged_result') && function_exists('ldap_control_paged_result_response')); - \OCP\Util::writeLog('user_ldap', 'PHP supports paged results? '.print_r($this->config['hasPagedResultSupport'], true), \OCP\Util::INFO); } public function __destruct() { @@ -187,20 +186,20 @@ class Connection { * Caches the general LDAP configuration. */ private function readConfiguration($force = false) { - \OCP\Util::writeLog('user_ldap', 'Checking conf state: isConfigured? '.print_r($this->configured, true).' isForce? '.print_r($force, true).' configID? '.print_r($this->configID, true), \OCP\Util::DEBUG); if((!$this->configured || $force) && !is_null($this->configID)) { - \OCP\Util::writeLog('user_ldap', 'Reading the configuration', \OCP\Util::DEBUG); $this->config['ldapHost'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_host', ''); $this->config['ldapPort'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_port', 389); $this->config['ldapAgentName'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_dn', ''); $this->config['ldapAgentPassword'] = base64_decode(\OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_agent_password', '')); - $this->config['ldapBase'] = preg_split('/\r\n|\r|\n/', \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_base', '')); - $this->config['ldapBaseUsers'] = preg_split('/\r\n|\r|\n/', \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_base_users', $this->config['ldapBase'])); - $this->config['ldapBaseGroups'] = preg_split('/\r\n|\r|\n/', \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_base_groups', $this->config['ldapBase'])); + $rawLdapBase = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_base', ''); + $this->config['ldapBase'] = preg_split('/\r\n|\r|\n/', $rawLdapBase); + $this->config['ldapBaseUsers'] = preg_split('/\r\n|\r|\n/', \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_base_users', $rawLdapBase)); + $this->config['ldapBaseGroups'] = preg_split('/\r\n|\r|\n/', \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_base_groups', $rawLdapBase)); + unset($rawLdapBase); $this->config['ldapTLS'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_tls', 0); $this->config['ldapNoCase'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_nocase', 0); $this->config['turnOffCertCheck'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_turn_off_cert_check', 0); - $this->config['ldapUserDisplayName'] = mb_strtolower(\OCP\Config::getAppValue($this->configID, '$this->configPrefix.ldap_display_name', 'uid'), 'UTF-8'); + $this->config['ldapUserDisplayName'] = mb_strtolower(\OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_display_name', 'uid'), 'UTF-8'); $this->config['ldapUserFilter'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_userlist_filter', 'objectClass=person'); $this->config['ldapGroupFilter'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_group_filter', '(objectClass=posixGroup)'); $this->config['ldapLoginFilter'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_login_filter', '(uid=%uid)'); From 6063ce9c8d3f32a7c9d53a0aa77d2cbfa0798f7b Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Wed, 16 Jan 2013 14:59:41 +0100 Subject: [PATCH 179/347] LDAP: enable support for multiple LDAP/AD servers --- apps/user_ldap/appinfo/app.php | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/apps/user_ldap/appinfo/app.php b/apps/user_ldap/appinfo/app.php index 9e72e388e6..69860ba143 100644 --- a/apps/user_ldap/appinfo/app.php +++ b/apps/user_ldap/appinfo/app.php @@ -23,11 +23,27 @@ OCP\App::registerAdmin('user_ldap', 'settings'); -$connector = new OCA\user_ldap\lib\Connection('', 'user_ldap'); -$userBackend = new OCA\user_ldap\USER_LDAP(); -$userBackend->setConnector($connector); -$groupBackend = new OCA\user_ldap\GROUP_LDAP(); -$groupBackend->setConnector($connector); +$query = \OCP\DB::prepare(' + SELECT DISTINCT `configkey` + FROM `*PREFIX*appconfig` + WHERE `configkey` LIKE ? +'); +$serverConnections = $query->execute(array('%ldap_login_filter'))->fetchAll(); +if(count($serverConnections) == 1) { + $prefix = substr($serverConnections[0]['configkey'], 0, strlen($serverConnections[0]['configkey'])- strlen('ldap_login_filter')); + $connector = new OCA\user_ldap\lib\Connection($prefix); + $userBackend = new OCA\user_ldap\USER_LDAP(); + $userBackend->setConnector($connector); + $groupBackend = new OCA\user_ldap\GROUP_LDAP(); + $groupBackend->setConnector($connector); +} else { + $prefixes = array(); + foreach($serverConnections as $serverConnection) { + $prefixes[] = substr($serverConnection['configkey'], 0, strlen($serverConnection['configkey'])- strlen('ldap_login_filter')); + } + $userBackend = new OCA\user_ldap\User_Proxy($prefixes); + $groupBackend = new OCA\user_ldap\Group_Proxy($prefixes); +} // register user backend OC_User::useBackend($userBackend); From c494eb79ab049d71113c786375b1ee11338e5edc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Wed, 16 Jan 2013 16:01:11 +0100 Subject: [PATCH 180/347] listen to post delete event to allow the trash bin to create a copy of the version first --- apps/files_versions/appinfo/app.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_versions/appinfo/app.php b/apps/files_versions/appinfo/app.php index afc0a67edb..edd0a2f702 100644 --- a/apps/files_versions/appinfo/app.php +++ b/apps/files_versions/appinfo/app.php @@ -12,5 +12,5 @@ OCP\Util::addscript('files_versions', 'versions'); // Listen to write signals OCP\Util::connectHook('OC_Filesystem', 'write', "OCA_Versions\Hooks", "write_hook"); // Listen to delete and rename signals -OCP\Util::connectHook('OC_Filesystem', 'delete', "OCA_Versions\Hooks", "remove_hook"); +OCP\Util::connectHook('OC_Filesystem', 'post-delete', "OCA_Versions\Hooks", "remove_hook"); OCP\Util::connectHook('OC_Filesystem', 'rename', "OCA_Versions\Hooks", "rename_hook"); \ No newline at end of file From 29ec00797948d98ffa5dcb0baa1518630ab3ef56 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 16 Jan 2013 19:11:33 +0100 Subject: [PATCH 181/347] Cache: dont migrate permissions, cache them on demain instead --- lib/files/cache/upgrade.php | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/lib/files/cache/upgrade.php b/lib/files/cache/upgrade.php index cd9a9e91a8..19e3d9ad57 100644 --- a/lib/files/cache/upgrade.php +++ b/lib/files/cache/upgrade.php @@ -14,8 +14,6 @@ class Upgrade { */ private $legacy; - private $permissionsCaches = array(); - private $numericIds = array(); private $mimeTypeIds = array(); @@ -72,9 +70,6 @@ class Upgrade { $insertQuery->execute(array($data['id'], $data['storage'], $data['path'], $data['path_hash'], $data['parent'], $data['name'], $data['mimetype'], $data['mimepart'], $data['size'], $data['mtime'], $data['encrypted'])); - - $permissionsCache = $this->getPermissionsCache($data['storage_object']); - $permissionsCache->set($data['id'], $data['user'], $data['permissions']); } /** @@ -101,18 +96,6 @@ class Upgrade { return $newData; } - /** - * @param \OC\Files\Storage\Storage $storage - * @return Permissions - */ - function getPermissionsCache($storage) { - $storageId = $storage->getId(); - if (!isset($this->permissionsCaches[$storageId])) { - $this->permissionsCaches[$storageId] = $storage->getPermissionsCache(); - } - return $this->permissionsCaches[$storageId]; - } - /** * get the numeric storage id * From f9c42a196f03bb193b07a8f5f8ecf42b911ef4b5 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 16 Jan 2013 21:36:04 +0100 Subject: [PATCH 182/347] Cache: no longer using this file --- lib/files/file.php | 61 ---------------------------------------------- 1 file changed, 61 deletions(-) delete mode 100644 lib/files/file.php diff --git a/lib/files/file.php b/lib/files/file.php deleted file mode 100644 index 0d33cea7ee..0000000000 --- a/lib/files/file.php +++ /dev/null @@ -1,61 +0,0 @@ - - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. - */ - -namespace OC\Files; - -/** - * representation of the location a file or folder is stored - */ - -class File{ - /** - * @var Storage\Storage $storage - */ - private $storage; - /** - * @var string internalPath - */ - private $internalPath; - - public function __construct(Storage\Storage $storage, $internalPath){ - $this->storage = $storage; - $this->internalPath = $internalPath; - } - - public static function resolve($fullPath){ - $storage = null; - $internalPath = ''; - list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($fullPath); - return new File($storage, $internalPath); - } - - /** - * get the internal path of the file inside the filestorage - * @return string - */ - public function getInternalPath(){ - return $this->internalPath; - } - - /** - * get the storage the file is stored in - * @return \OC\Files\Storage\Storage - */ - public function getStorage(){ - return $this->storage; - } - - /** - * get the id of the storage the file is stored in - * @return string - */ - public function getStorageId(){ - return $this->storage->getId(); - } - -} From bb43cf378b5e7c6a18a30d8fbb226b72f1e4eb88 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 16 Jan 2013 21:36:25 +0100 Subject: [PATCH 183/347] Files: make sure keybinds js is loaded after files js --- apps/files/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files/index.php b/apps/files/index.php index 0dce768696..854218eee5 100644 --- a/apps/files/index.php +++ b/apps/files/index.php @@ -30,7 +30,6 @@ OCP\Util::addscript('files', 'jquery.iframe-transport'); OCP\Util::addscript('files', 'jquery.fileupload'); OCP\Util::addscript('files', 'filelist'); OCP\Util::addscript('files', 'fileactions'); -OCP\Util::addscript('files', 'keyboardshortcuts'); OCP\App::setActiveNavigationEntry('files_index'); // Load the files @@ -122,6 +121,7 @@ if ($needUpgrade) { $tmpl->printPage(); } else { OCP\Util::addscript('files', 'files'); + OCP\Util::addscript('files', 'keyboardshortcuts'); $tmpl = new OCP\Template('files', 'index', 'user'); $tmpl->assign('fileList', $list->fetchPage(), false); $tmpl->assign('breadcrumb', $breadcrumbNav->fetchPage(), false); From 6871a150bd1309af0ca22e45487043d9640bb356 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 16 Jan 2013 21:58:17 +0100 Subject: [PATCH 184/347] Cache: use a database transition for scanning each folder gives a massive speed improvement while scanning files --- lib/files/cache/scanner.php | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/lib/files/cache/scanner.php b/lib/files/cache/scanner.php index b62a093cec..bf0ef01d6b 100644 --- a/lib/files/cache/scanner.php +++ b/lib/files/cache/scanner.php @@ -83,14 +83,19 @@ class Scanner { * * @param string $path * @param SCAN_RECURSIVE/SCAN_SHALLOW $recursive + * @param bool $onlyChilds * @return int the size of the scanned folder or -1 if the size is unknown at this stage */ - public function scan($path, $recursive = self::SCAN_RECURSIVE) { + public function scan($path, $recursive = self::SCAN_RECURSIVE, $onlyChilds = false) { \OC_Hook::emit('\OC\Files\Cache\Scanner', 'scan_folder', array('path' => $path, 'storage' => $this->storageId)); - $this->scanFile($path); + $childQueue = array(); + if (!$onlyChilds) { + $this->scanFile($path); + } $size = 0; if ($dh = $this->storage->opendir($path)) { + \OC_DB::beginTransaction(); while ($file = readdir($dh)) { if ($file !== '.' and $file !== '..') { $child = ($path) ? $path . '/' . $file : $file; @@ -98,10 +103,12 @@ class Scanner { if ($data) { if ($data['mimetype'] === 'httpd/unix-directory') { if ($recursive === self::SCAN_RECURSIVE) { - $data['size'] = $this->scan($child, self::SCAN_RECURSIVE); + $childQueue[] = $child; + $data['size'] = 0; } else { $data['size'] = -1; } + } else { } if ($data['size'] === -1) { $size = -1; @@ -111,6 +118,15 @@ class Scanner { } } } + \OC_DB::commit(); + foreach ($childQueue as $child) { + $childSize = $this->scan($child, self::SCAN_RECURSIVE, true); + if ($childSize === -1) { + $size = -1; + } else { + $size += $childSize; + } + } if ($size !== -1) { $this->cache->put($path, array('size' => $size)); } From d5ee4352539f2165eebde5dc983113849b6a1a0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Thu, 17 Jan 2013 13:17:48 +0100 Subject: [PATCH 185/347] rename "publicListView" option to "disableSharing", this is more meaningful also because it is not only useful for the public list view --- apps/files/templates/part.list.php | 6 +++--- apps/files_sharing/js/share.js | 2 +- apps/files_sharing/public.php | 2 +- apps/files_sharing/templates/public.php | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/files/templates/part.list.php b/apps/files/templates/part.list.php index dfac43d1b1..1970a80e1b 100644 --- a/apps/files/templates/part.list.php +++ b/apps/files/templates/part.list.php @@ -1,8 +1,8 @@ diff --git a/apps/files_sharing/js/share.js b/apps/files_sharing/js/share.js index 8a546d6216..59faf82e26 100644 --- a/apps/files_sharing/js/share.js +++ b/apps/files_sharing/js/share.js @@ -1,6 +1,6 @@ $(document).ready(function() { - if (typeof OC.Share !== 'undefined' && typeof FileActions !== 'undefined' && !publicListView) { + if (typeof OC.Share !== 'undefined' && typeof FileActions !== 'undefined' && !disableSharing) { FileActions.register('all', 'Share', OC.PERMISSION_READ, OC.imagePath('core', 'actions/share'), function(filename) { if ($('#dir').val() == '/') { diff --git a/apps/files_sharing/public.php b/apps/files_sharing/public.php index 487b9e7996..7e1959cd95 100644 --- a/apps/files_sharing/public.php +++ b/apps/files_sharing/public.php @@ -257,7 +257,7 @@ if ($linkItem) { $list = new OCP\Template('files', 'part.list', ''); $list->assign('files', $files, false); - $list->assign('publicListView', true); + $list->assign('disableSharing', true); $list->assign('baseURL', OCP\Util::linkToPublic('files').$urlLinkIdentifiers.'&path=', false); $list->assign('downloadURL', OCP\Util::linkToPublic('files').$urlLinkIdentifiers.'&download&path=', false); $breadcrumbNav = new OCP\Template('files', 'part.breadcrumb', '' ); diff --git a/apps/files_sharing/templates/public.php b/apps/files_sharing/templates/public.php index 647e1e08a3..bfcc521e10 100644 --- a/apps/files_sharing/templates/public.php +++ b/apps/files_sharing/templates/public.php @@ -1,8 +1,8 @@ From 3d56cf3a5b29e0c75f98646eafd22ee8cb7749dc Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Thu, 17 Jan 2013 13:31:14 +0100 Subject: [PATCH 186/347] LDAP: add support for backup/replica servers --- apps/user_ldap/lib/connection.php | 42 +++++++++++++++++++++------ apps/user_ldap/settings.php | 2 +- apps/user_ldap/templates/settings.php | 3 ++ 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/apps/user_ldap/lib/connection.php b/apps/user_ldap/lib/connection.php index 1dc1d1510a..a22246c709 100644 --- a/apps/user_ldap/lib/connection.php +++ b/apps/user_ldap/lib/connection.php @@ -36,6 +36,8 @@ class Connection { protected $config = array( 'ldapHost' => null, 'ldapPort' => null, + 'ldapBackupHost' => null, + 'ldapBackupPort' => null, 'ldapBase' => null, 'ldapBaseUsers' => null, 'ldapBaseGroups' => null, @@ -56,6 +58,7 @@ class Connection { 'ldapCacheTTL' => null, 'ldapUuidAttribute' => null, 'ldapOverrideUuidAttribute' => null, + 'ldapOverrideMainServer' => false, 'homeFolderNamingRule' => null, 'hasPagedResultSupport' => false, ); @@ -188,7 +191,10 @@ class Connection { private function readConfiguration($force = false) { if((!$this->configured || $force) && !is_null($this->configID)) { $this->config['ldapHost'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_host', ''); + $this->config['ldapBackupHost'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_backup_host', ''); $this->config['ldapPort'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_port', 389); + $this->config['ldapBackupPort'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_backup_port', $this->config['ldapPort']); + $this->config['ldapOverrideMainServer']= \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_override_main_server', false); $this->config['ldapAgentName'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_dn', ''); $this->config['ldapAgentPassword'] = base64_decode(\OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_agent_password', '')); $rawLdapBase = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_base', ''); @@ -229,7 +235,7 @@ class Connection { return false; } - $params = array('ldap_host'=>'ldapHost', 'ldap_port'=>'ldapPort', 'ldap_dn'=>'ldapAgentName', 'ldap_agent_password'=>'ldapAgentPassword', 'ldap_base'=>'ldapBase', 'ldap_base_users'=>'ldapBaseUsers', 'ldap_base_groups'=>'ldapBaseGroups', 'ldap_userlist_filter'=>'ldapUserFilter', 'ldap_login_filter'=>'ldapLoginFilter', 'ldap_group_filter'=>'ldapGroupFilter', 'ldap_display_name'=>'ldapUserDisplayName', 'ldap_group_display_name'=>'ldapGroupDisplayName', + $params = array('ldap_host'=>'ldapHost', 'ldap_port'=>'ldapPort', 'ldap_backup_host'=>'ldapBackupHost', 'ldap_backup_port'=>'ldapBackupPort', 'ldapOverrideMainServer' => 'ldap_override_main_server', 'ldap_dn'=>'ldapAgentName', 'ldap_agent_password'=>'ldapAgentPassword', 'ldap_base'=>'ldapBase', 'ldap_base_users'=>'ldapBaseUsers', 'ldap_base_groups'=>'ldapBaseGroups', 'ldap_userlist_filter'=>'ldapUserFilter', 'ldap_login_filter'=>'ldapLoginFilter', 'ldap_group_filter'=>'ldapGroupFilter', 'ldap_display_name'=>'ldapUserDisplayName', 'ldap_group_display_name'=>'ldapGroupDisplayName', 'ldap_tls'=>'ldapTLS', 'ldap_nocase'=>'ldapNoCase', 'ldap_quota_def'=>'ldapQuotaDefault', 'ldap_quota_attr'=>'ldapQuotaAttribute', 'ldap_email_attr'=>'ldapEmailAttribute', 'ldap_group_member_assoc_attribute'=>'ldapGroupMemberAssocAttr', 'ldap_cache_ttl'=>'ldapCacheTTL', 'home_folder_naming_rule' => 'homeFolderNamingRule'); @@ -342,16 +348,34 @@ class Connection { \OCP\Util::writeLog('user_ldap', 'Could not turn off SSL certificate validation.', \OCP\Util::WARN); } } - $this->ldapConnectionRes = ldap_connect($this->config['ldapHost'], $this->config['ldapPort']); - if(ldap_set_option($this->ldapConnectionRes, LDAP_OPT_PROTOCOL_VERSION, 3)) { - if(ldap_set_option($this->ldapConnectionRes, LDAP_OPT_REFERRALS, 0)) { - if($this->config['ldapTLS']) { - ldap_start_tls($this->ldapConnectionRes); - } - } + if(!$this->config['ldapOverrideMainServer'] && !$this->getFromCache('overrideMainServer')) { + $this->doConnect($this->config['ldapHost'], $this->config['ldapPort']); + $bindStatus = $this->bind(); } - return $this->bind(); + $error = null; + //if LDAP server is not reachable, try the Backup (Replica!) Server + if((!$bindStatus && ($error = ldap_errno($this->ldapConnectionRes)) == -1) + || $this->config['ldapOverrideMainServer'] + || $this->getFromCache('overrideMainServer')) { + $this->doConnect($this->config['ldapBackupHost'], $this->config['ldapBackupPort']); + $bindStatus = $this->bind(); + if($bindStatus && $error == -1) { + $this->writeToCache('overrideMainServer', true); + } + } + return $bindStatus; + } + } + + private function doConnect($host, $port) { + $this->ldapConnectionRes = ldap_connect($host, $port); + if(ldap_set_option($this->ldapConnectionRes, LDAP_OPT_PROTOCOL_VERSION, 3)) { + if(ldap_set_option($this->ldapConnectionRes, LDAP_OPT_REFERRALS, 0)) { + if($this->config['ldapTLS']) { + ldap_start_tls($this->ldapConnectionRes); + } + } } } diff --git a/apps/user_ldap/settings.php b/apps/user_ldap/settings.php index 58ec8e7f7a..e49f37da2d 100644 --- a/apps/user_ldap/settings.php +++ b/apps/user_ldap/settings.php @@ -23,7 +23,7 @@ OC_Util::checkAdminUser(); -$params = array('ldap_host', 'ldap_port', 'ldap_dn', 'ldap_agent_password', 'ldap_base', 'ldap_base_users', 'ldap_base_groups', 'ldap_userlist_filter', 'ldap_login_filter', 'ldap_group_filter', 'ldap_display_name', 'ldap_group_display_name', 'ldap_tls', 'ldap_turn_off_cert_check', 'ldap_nocase', 'ldap_quota_def', 'ldap_quota_attr', 'ldap_email_attr', 'ldap_group_member_assoc_attribute', 'ldap_cache_ttl', 'home_folder_naming_rule'); +$params = array('ldap_host', 'ldap_port', 'ldap_backup_host', 'ldap_backup_port', 'ldap_override_main_server', 'ldap_dn', 'ldap_agent_password', 'ldap_base', 'ldap_base_users', 'ldap_base_groups', 'ldap_userlist_filter', 'ldap_login_filter', 'ldap_group_filter', 'ldap_display_name', 'ldap_group_display_name', 'ldap_tls', 'ldap_turn_off_cert_check', 'ldap_nocase', 'ldap_quota_def', 'ldap_quota_attr', 'ldap_email_attr', 'ldap_group_member_assoc_attribute', 'ldap_cache_ttl', 'home_folder_naming_rule'); OCP\Util::addscript('user_ldap', 'settings'); OCP\Util::addstyle('user_ldap', 'settings'); diff --git a/apps/user_ldap/templates/settings.php b/apps/user_ldap/templates/settings.php index b24c6e2f02..030fbff4aa 100644 --- a/apps/user_ldap/templates/settings.php +++ b/apps/user_ldap/templates/settings.php @@ -22,6 +22,9 @@

+

+

+

title="t('When switched on, ownCloud will only connect to the replica server.');?>" />

From 59a6068246c4012955e3b2b49e44426eedcc923b Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Thu, 17 Jan 2013 13:46:32 +0100 Subject: [PATCH 187/347] fix undeclared variable --- apps/user_ldap/lib/connection.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/user_ldap/lib/connection.php b/apps/user_ldap/lib/connection.php index a22246c709..9eab692bef 100644 --- a/apps/user_ldap/lib/connection.php +++ b/apps/user_ldap/lib/connection.php @@ -351,6 +351,8 @@ class Connection { if(!$this->config['ldapOverrideMainServer'] && !$this->getFromCache('overrideMainServer')) { $this->doConnect($this->config['ldapHost'], $this->config['ldapPort']); $bindStatus = $this->bind(); + } else { + $bindStatus = false; } $error = null; From d8be83029b107359884f9e23dd5bded71fea8999 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Thu, 17 Jan 2013 13:56:37 +0100 Subject: [PATCH 188/347] make sure port is used as backup port if not specified. documentation. determine connection error earlier. --- apps/user_ldap/lib/connection.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/user_ldap/lib/connection.php b/apps/user_ldap/lib/connection.php index 9eab692bef..55234f4ac0 100644 --- a/apps/user_ldap/lib/connection.php +++ b/apps/user_ldap/lib/connection.php @@ -279,6 +279,10 @@ class Connection { \OCP\Config::setAppValue($this->configID, $this->configPrefix.'ldap_uuid_attribute', 'auto'); \OCP\Util::writeLog('user_ldap', 'Illegal value for the UUID Attribute, reset to autodetect.', \OCP\Util::INFO); } + if(empty($this->config['ldapBackupPort'])) { + //force default + $this->config['ldapBackupPort'] = $this->config['ldapPort']; + } //second step: critical checks. If left empty or filled wrong, set as unconfigured and give a warning. @@ -351,18 +355,22 @@ class Connection { if(!$this->config['ldapOverrideMainServer'] && !$this->getFromCache('overrideMainServer')) { $this->doConnect($this->config['ldapHost'], $this->config['ldapPort']); $bindStatus = $this->bind(); + $error = ldap_errno($this->ldapConnectionRes); } else { $bindStatus = false; + $error = null; } $error = null; //if LDAP server is not reachable, try the Backup (Replica!) Server - if((!$bindStatus && ($error = ldap_errno($this->ldapConnectionRes)) == -1) + if((!$bindStatus && ($error == -1)) || $this->config['ldapOverrideMainServer'] || $this->getFromCache('overrideMainServer')) { $this->doConnect($this->config['ldapBackupHost'], $this->config['ldapBackupPort']); $bindStatus = $this->bind(); if($bindStatus && $error == -1) { + //when bind to backup server succeeded and failed to main server, + //skip contacting him until next cache refresh $this->writeToCache('overrideMainServer', true); } } From a53addf8250ea47a36837463f15122339123aeff Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Fri, 18 Jan 2013 01:23:15 +0100 Subject: [PATCH 189/347] LDAP: first basics for multiserver config ui --- .../ajax/getNewServerConfigPrefix.php | 39 +++++++++++++++++++ apps/user_ldap/js/settings.js | 33 ++++++++++++++++ apps/user_ldap/settings.php | 1 + apps/user_ldap/templates/settings.php | 5 +++ 4 files changed, 78 insertions(+) create mode 100644 apps/user_ldap/ajax/getNewServerConfigPrefix.php diff --git a/apps/user_ldap/ajax/getNewServerConfigPrefix.php b/apps/user_ldap/ajax/getNewServerConfigPrefix.php new file mode 100644 index 0000000000..1a5f78cf21 --- /dev/null +++ b/apps/user_ldap/ajax/getNewServerConfigPrefix.php @@ -0,0 +1,39 @@ +. + * + */ + +// Check user and app status +OCP\JSON::checkAdminUser(); +OCP\JSON::checkAppEnabled('user_ldap'); +OCP\JSON::callCheck(); + +$query = \OCP\DB::prepare(' + SELECT DISTINCT `configkey` + FROM `*PREFIX*appconfig` + WHERE `configkey` LIKE ? +'); +$serverConnections = $query->execute(array('%ldap_login_filter'))->fetchAll(); +sort($serverConnections); +$lk = array_pop($serverConnections); +$ln = intval(str_replace('s', '', $lk)); +$nk = 's'.str_pad($ln+1, 2, '0', STR_PAD_LEFT); +OCP\JSON::success(array('configPrefix' => $nk)); \ No newline at end of file diff --git a/apps/user_ldap/js/settings.js b/apps/user_ldap/js/settings.js index 7063eead96..8cd31301f2 100644 --- a/apps/user_ldap/js/settings.js +++ b/apps/user_ldap/js/settings.js @@ -21,4 +21,37 @@ $(document).ready(function() { } ); }); + + $('#ldap_serverconfig_chooser').change(function(event) { + value = $('#ldap_serverconfig_chooser option:selected:first').attr('value'); + if(value == 'NEW') { + $.post( + OC.filePath('user_ldap','ajax','getNewServerConfigPrefix.php'), + function (result) { + if(result.status == 'success') { + OC.dialogs.confirm( + 'Take over settings from recent server configuration?', + 'Keep settings?', + function(keep) { + if(!keep) { + $('#ldap').find('input[type=text], input[type=password], textarea, select').val(''); + $('#ldap').find('input[type=checkbox]').removeAttr('checked'); + } + } + ); + $('#ldap_serverconfig_chooser option:selected:first').removeAttr('selected'); + var html = ''; + $('#ldap_serverconfig_chooser option:last').before(html); + } else { + OC.dialogs.alert( + result.message, + 'Cannot add server configuration' + ); + } + } + ); + } else { + alert(value); + } + }); }); \ No newline at end of file diff --git a/apps/user_ldap/settings.php b/apps/user_ldap/settings.php index e49f37da2d..35233dc987 100644 --- a/apps/user_ldap/settings.php +++ b/apps/user_ldap/settings.php @@ -76,5 +76,6 @@ $tmpl->assign( 'ldap_cache_ttl', OCP\Config::getAppValue('user_ldap', 'ldap_cach $hfnr = OCP\Config::getAppValue('user_ldap', 'home_folder_naming_rule', 'opt:username'); $hfnr = ($hfnr == 'opt:username') ? '' : substr($hfnr, strlen('attr:')); $tmpl->assign( 'home_folder_naming_rule', $hfnr, ''); +$tmpl->assign('serverConfigurationOptions', '', false); return $tmpl->fetchPage(); diff --git a/apps/user_ldap/templates/settings.php b/apps/user_ldap/templates/settings.php index 030fbff4aa..c3ec20fc84 100644 --- a/apps/user_ldap/templates/settings.php +++ b/apps/user_ldap/templates/settings.php @@ -12,6 +12,11 @@ } ?>
+

From 82d4da0d3d0dc09c22d2cd2220d418372206099e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Fri, 18 Jan 2013 10:23:31 +0100 Subject: [PATCH 190/347] call the trash bin view --- apps/files/js/files.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/files/js/files.js b/apps/files/js/files.js index c13d7a5961..359b92a6fd 100644 --- a/apps/files/js/files.js +++ b/apps/files/js/files.js @@ -83,9 +83,9 @@ $(document).ready(function() { return false; }); - // Show Trash bin + // Show trash bin $('#trash a').live('click', function() { - console.log("hello"); + window.location=OC.filePath('files_trashbin', '', 'index.php'); }); var lastChecked; From 1318450791146e7a075c01d8a39df6d333b619f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Fri, 18 Jan 2013 10:51:13 +0100 Subject: [PATCH 191/347] introduce option to disable download action --- apps/files/js/fileactions.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/apps/files/js/fileactions.js b/apps/files/js/fileactions.js index 80b9c01f83..093b6204c3 100644 --- a/apps/files/js/fileactions.js +++ b/apps/files/js/fileactions.js @@ -147,15 +147,19 @@ $(document).ready(function () { } else { var downloadScope = 'file'; } - FileActions.register(downloadScope, 'Download', OC.PERMISSION_READ, function () { - return OC.imagePath('core', 'actions/download'); - }, function (filename) { - window.location = OC.filePath('files', 'ajax', 'download.php') + '?files=' + encodeURIComponent(filename) + '&dir=' + encodeURIComponent($('#dir').val()); - }); - + + if (typeof disableDownloadActions == 'undefined' || !disableDownloadActions) { + FileActions.register(downloadScope, 'Download', OC.PERMISSION_READ, function () { + return OC.imagePath('core', 'actions/download'); + }, function (filename) { + window.location = OC.filePath('files', 'ajax', 'download.php') + '?files=' + encodeURIComponent(filename) + '&dir=' + encodeURIComponent($('#dir').val()); + }); + } + $('#fileList tr').each(function(){ FileActions.display($(this).children('td.filename')); }); + }); FileActions.register('all', 'Delete', OC.PERMISSION_DELETE, function () { From 1c19e66712958930cd772485bb96c68c0c00c011 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Fri, 18 Jan 2013 11:42:34 +0100 Subject: [PATCH 192/347] coding style --- apps/user_ldap/settings.php | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/apps/user_ldap/settings.php b/apps/user_ldap/settings.php index 35233dc987..73e4f0b6f4 100644 --- a/apps/user_ldap/settings.php +++ b/apps/user_ldap/settings.php @@ -23,12 +23,22 @@ OC_Util::checkAdminUser(); -$params = array('ldap_host', 'ldap_port', 'ldap_backup_host', 'ldap_backup_port', 'ldap_override_main_server', 'ldap_dn', 'ldap_agent_password', 'ldap_base', 'ldap_base_users', 'ldap_base_groups', 'ldap_userlist_filter', 'ldap_login_filter', 'ldap_group_filter', 'ldap_display_name', 'ldap_group_display_name', 'ldap_tls', 'ldap_turn_off_cert_check', 'ldap_nocase', 'ldap_quota_def', 'ldap_quota_attr', 'ldap_email_attr', 'ldap_group_member_assoc_attribute', 'ldap_cache_ttl', 'home_folder_naming_rule'); +$params = array('ldap_host', 'ldap_port', 'ldap_backup_host', + 'ldap_backup_port', 'ldap_override_main_server', 'ldap_dn', + 'ldap_agent_password', 'ldap_base', 'ldap_base_users', + 'ldap_base_groups', 'ldap_userlist_filter', + 'ldap_login_filter', 'ldap_group_filter', 'ldap_display_name', + 'ldap_group_display_name', 'ldap_tls', + 'ldap_turn_off_cert_check', 'ldap_nocase', 'ldap_quota_def', + 'ldap_quota_attr', 'ldap_email_attr', + 'ldap_group_member_assoc_attribute', 'ldap_cache_ttl', + 'home_folder_naming_rule' + ); OCP\Util::addscript('user_ldap', 'settings'); OCP\Util::addstyle('user_ldap', 'settings'); -if ($_POST) { +if($_POST) { $clearCache = false; foreach($params as $param) { if(isset($_POST[$param])) { @@ -60,22 +70,22 @@ if ($_POST) { } // fill template -$tmpl = new OCP\Template( 'user_ldap', 'settings'); +$tmpl = new OCP\Template('user_ldap', 'settings'); foreach($params as $param) { - $value = OCP\Config::getAppValue('user_ldap', $param, ''); - $tmpl->assign($param, $value); + $value = OCP\Config::getAppValue('user_ldap', $param, ''); + $tmpl->assign($param, $value); } // settings with default values -$tmpl->assign( 'ldap_port', OCP\Config::getAppValue('user_ldap', 'ldap_port', '389')); -$tmpl->assign( 'ldap_display_name', OCP\Config::getAppValue('user_ldap', 'ldap_display_name', 'uid')); -$tmpl->assign( 'ldap_group_display_name', OCP\Config::getAppValue('user_ldap', 'ldap_group_display_name', 'cn')); -$tmpl->assign( 'ldap_group_member_assoc_attribute', OCP\Config::getAppValue('user_ldap', 'ldap_group_member_assoc_attribute', 'uniqueMember')); -$tmpl->assign( 'ldap_agent_password', base64_decode(OCP\Config::getAppValue('user_ldap', 'ldap_agent_password'))); -$tmpl->assign( 'ldap_cache_ttl', OCP\Config::getAppValue('user_ldap', 'ldap_cache_ttl', '600')); +$tmpl->assign('ldap_port', OCP\Config::getAppValue('user_ldap', 'ldap_port', '389')); +$tmpl->assign('ldap_display_name', OCP\Config::getAppValue('user_ldap', 'ldap_display_name', 'uid')); +$tmpl->assign('ldap_group_display_name', OCP\Config::getAppValue('user_ldap', 'ldap_group_display_name', 'cn')); +$tmpl->assign('ldap_group_member_assoc_attribute', OCP\Config::getAppValue('user_ldap', 'ldap_group_member_assoc_attribute', 'uniqueMember')); +$tmpl->assign('ldap_agent_password', base64_decode(OCP\Config::getAppValue('user_ldap', 'ldap_agent_password'))); +$tmpl->assign('ldap_cache_ttl', OCP\Config::getAppValue('user_ldap', 'ldap_cache_ttl', '600')); $hfnr = OCP\Config::getAppValue('user_ldap', 'home_folder_naming_rule', 'opt:username'); $hfnr = ($hfnr == 'opt:username') ? '' : substr($hfnr, strlen('attr:')); -$tmpl->assign( 'home_folder_naming_rule', $hfnr, ''); +$tmpl->assign('home_folder_naming_rule', $hfnr, ''); $tmpl->assign('serverConfigurationOptions', '', false); return $tmpl->fetchPage(); From d5151fa61c561544ee64472a2c778cbe4fe086f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Fri, 18 Jan 2013 13:11:29 +0100 Subject: [PATCH 193/347] first version of the trash bin app --- apps/files_trashbin/ajax/undelete.php | 13 ++ apps/files_trashbin/appinfo/app.php | 7 + apps/files_trashbin/appinfo/database.xml | 92 ++++++++++ apps/files_trashbin/appinfo/info.xml | 14 ++ apps/files_trashbin/appinfo/version | 1 + apps/files_trashbin/css/trash.css | 78 ++++++++ apps/files_trashbin/download.php | 52 ++++++ apps/files_trashbin/index.php | 55 ++++++ apps/files_trashbin/js/trash.js | 37 ++++ apps/files_trashbin/lib/hooks.php | 45 +++++ apps/files_trashbin/lib/trash.php | 190 ++++++++++++++++++++ apps/files_trashbin/templates/index.php | 36 ++++ apps/files_trashbin/templates/part.list.php | 70 ++++++++ 13 files changed, 690 insertions(+) create mode 100644 apps/files_trashbin/ajax/undelete.php create mode 100644 apps/files_trashbin/appinfo/app.php create mode 100644 apps/files_trashbin/appinfo/database.xml create mode 100644 apps/files_trashbin/appinfo/info.xml create mode 100644 apps/files_trashbin/appinfo/version create mode 100644 apps/files_trashbin/css/trash.css create mode 100644 apps/files_trashbin/download.php create mode 100644 apps/files_trashbin/index.php create mode 100644 apps/files_trashbin/js/trash.js create mode 100644 apps/files_trashbin/lib/hooks.php create mode 100644 apps/files_trashbin/lib/trash.php create mode 100644 apps/files_trashbin/templates/index.php create mode 100644 apps/files_trashbin/templates/part.list.php diff --git a/apps/files_trashbin/ajax/undelete.php b/apps/files_trashbin/ajax/undelete.php new file mode 100644 index 0000000000..c548034828 --- /dev/null +++ b/apps/files_trashbin/ajax/undelete.php @@ -0,0 +1,13 @@ + array('content'=>'foo', 'id' => 'bar'))); \ No newline at end of file diff --git a/apps/files_trashbin/appinfo/app.php b/apps/files_trashbin/appinfo/app.php new file mode 100644 index 0000000000..3741d42c78 --- /dev/null +++ b/apps/files_trashbin/appinfo/app.php @@ -0,0 +1,7 @@ + + + + *dbname* + true + false + + utf8 + +
+ + *dbprefix*files_trash + + + + + id + text + + true + 50 + + + + user + text + + true + 50 + + + + timestamp + text + + true + 12 + + + + location + text + + true + 200 + + + + type + text + + true + 4 + + + + mime + text + + true + 30 + + + + id_index + + id + ascending + + + + + timestamp_index + + timestamp + ascending + + + + + user_index + + user + ascending + + + + + +
+ + diff --git a/apps/files_trashbin/appinfo/info.xml b/apps/files_trashbin/appinfo/info.xml new file mode 100644 index 0000000000..9b48612636 --- /dev/null +++ b/apps/files_trashbin/appinfo/info.xml @@ -0,0 +1,14 @@ + + + files_trashbin + Trash + Trash bin + AGPL + Bjoern Schiessle + true + 4.9 + + + + + diff --git a/apps/files_trashbin/appinfo/version b/apps/files_trashbin/appinfo/version new file mode 100644 index 0000000000..49d59571fb --- /dev/null +++ b/apps/files_trashbin/appinfo/version @@ -0,0 +1 @@ +0.1 diff --git a/apps/files_trashbin/css/trash.css b/apps/files_trashbin/css/trash.css new file mode 100644 index 0000000000..bd6341c6fb --- /dev/null +++ b/apps/files_trashbin/css/trash.css @@ -0,0 +1,78 @@ +body { + background:#ddd; +} + +#header { + background:#1d2d44; + box-shadow:0 0 10px rgba(0,0,0,.5), inset 0 -2px 10px #222; + height:2.5em; + left:0; + line-height:2.5em; + position:fixed; + right:0; + top:0; + z-index:100; + padding:.5em; +} + +#details { + color:#fff; +} + +#header #download { + font-weight:700; + margin-left:2em; +} + +#header #download img { + padding-left:.1em; + padding-right:.3em; + vertical-align:text-bottom; +} + +#preview { + background:#eee; + border-bottom:1px solid #f8f8f8; + min-height:30em; + padding-top:2em; + text-align:center; + margin:50px auto; +} + +#noPreview { + display:none; + padding-top:5em; +} + +p.info { + color:#777; + text-align:center; + text-shadow:#fff 0 1px 0; + width:22em; + margin:2em auto; +} + +p.info a { + color:#777; + font-weight:700; +} + +#imgframe { + height:75%; + padding-bottom:2em; + width:80%; + margin:0 auto; +} + +#imgframe img { + max-height:100%; + max-width:100%; +} + +table td.filename .name { + display:block; + height:1.5em; + vertical-align:middle; + margin-left:3em; + /*font-weight:bold;*/ +} \ No newline at end of file diff --git a/apps/files_trashbin/download.php b/apps/files_trashbin/download.php new file mode 100644 index 0000000000..a987dd4fd1 --- /dev/null +++ b/apps/files_trashbin/download.php @@ -0,0 +1,52 @@ +. +* +*/ + +// Check if we are a user +OCP\User::checkLoggedIn(); + +$filename = $_GET["file"]; + +$view = new OC_FilesystemView('/'.\OCP\User::getUser().'/files_trashbin'); + +if(!$view->file_exists($filename)) { + error_log("file does not exist... " . $view->getInternalPath($filename)); + header("HTTP/1.0 404 Not Found"); + $tmpl = new OCP\Template( '', '404', 'guest' ); + $tmpl->assign('file', $filename); + $tmpl->printPage(); + exit; +} + +$ftype=$view->getMimeType( $filename ); + +header('Content-Type:'.$ftype);if ( preg_match( "/MSIE/", $_SERVER["HTTP_USER_AGENT"] ) ) { + header( 'Content-Disposition: attachment; filename="' . rawurlencode( basename($filename) ) . '"' ); +} else { + header( 'Content-Disposition: attachment; filename*=UTF-8\'\'' . rawurlencode( basename($filename) ) + . '; filename="' . rawurlencode( basename($filename) ) . '"' ); +} +OCP\Response::disableCaching(); +header('Content-Length: '. $view->filesize($filename)); + +OC_Util::obEnd(); +$view->readfile( $filename ); diff --git a/apps/files_trashbin/index.php b/apps/files_trashbin/index.php new file mode 100644 index 0000000000..28414cc1ce --- /dev/null +++ b/apps/files_trashbin/index.php @@ -0,0 +1,55 @@ +execute(array($user))->fetchAll(); + +$files = array(); +foreach ($result as $r) { + $i = array(); + $i['name'] = $r['id']; + $i['date'] = OCP\Util::formatDate($r['timestamp']); + $i['timestamp'] = $r['timestamp']; + $i['mimetype'] = $r['mime']; + $i['type'] = $r['type']; + if ($i['type'] == 'file') { + $fileinfo = pathinfo($r['id']); + $i['basename'] = $fileinfo['filename']; + $i['extension'] = isset($fileinfo['extension']) ? ('.'.$fileinfo['extension']) : ''; + } + $i['directory'] = $r['location']; + if ($i['directory'] == '/') { + $i['directory'] = ''; + } + $i['permissions'] = OCP\PERMISSION_READ; + $files[] = $i; +} + +$breadcrumbNav = new OCP\Template('files', 'part.breadcrumb', ''); +$breadcrumbNav->assign('breadcrumb', array(array('dir' => '', 'name' => 'Trash')), false); +$breadcrumbNav->assign('baseURL', OCP\Util::linkTo('files_trashbin', 'index.php') . '?dir=', false); + +$list = new OCP\Template('files_trashbin', 'part.list', ''); +$list->assign('files', $files, false); +$list->assign('baseURL', OCP\Util::linkTo('files_trashbin', 'index.php'). '?dir=', false); +$list->assign('downloadURL', OCP\Util::linkTo('files_trashbin', 'download.php') . '?file=', false); +$list->assign('disableSharing', true); +$list->assign('disableDownloadActions', true); +$tmpl->assign('breadcrumb', $breadcrumbNav->fetchPage(), false); +$tmpl->assign('fileList', $list->fetchPage(), false); +$tmpl->assign('dir', OC_Filesystem::normalizePath($view->getAbsolutePath())); + +$tmpl->printPage(); diff --git a/apps/files_trashbin/js/trash.js b/apps/files_trashbin/js/trash.js new file mode 100644 index 0000000000..37e9a4bf10 --- /dev/null +++ b/apps/files_trashbin/js/trash.js @@ -0,0 +1,37 @@ +// Override download path to files_sharing/public.php +function fileDownloadPath(dir, file) { + var url = $('#downloadURL').val(); + if (url.indexOf('&path=') != -1) { + url += '/'+file; + } + return url; +} + +$(document).ready(function() { + + if (typeof FileActions !== 'undefined') { + FileActions.register('all', 'Undelete', OC.PERMISSION_READ, '', function(filename) { + var tr=$('tr').filterAttr('data-file', filename); + console.log("tr: " + tr.attr('data-timestamp') + " name: " + name); + $.post(OC.filePath('files_trashbin','ajax','undelete.php'), + {timestamp:tr.attr('data-timestamp'),filename:tr.attr('data-filename')}, + function(result){ + if (result.status == 'success') { + return; + var date=new Date(); + FileList.addFile(name,0,date,false,hidden); + var tr=$('tr').filterAttr('data-file',name); + tr.data('mime','text/plain').data('id',result.data.id); + tr.attr('data-id', result.data.id); + getMimeIcon('text/plain',function(path){ + tr.find('td.filename').attr('style','background-image:url('+path+')'); + }); + } else { + OC.dialogs.alert(result.data.message, 'Error'); + } + }); + + }); + }; + +}); \ No newline at end of file diff --git a/apps/files_trashbin/lib/hooks.php b/apps/files_trashbin/lib/hooks.php new file mode 100644 index 0000000000..d3bee105b5 --- /dev/null +++ b/apps/files_trashbin/lib/hooks.php @@ -0,0 +1,45 @@ +. + * + */ + +/** + * This class contains all hooks. + */ + +namespace OCA_Trash; + +class Hooks { + + /** + * @brief Copy files to trash bin + * @param array + * + * This function is connected to the delete signal of OC_Filesystem + * to copy the file to the trash bin + */ + public static function remove_hook($params) { + + if ( \OCP\App::isEnabled('files_trashbin') ) { + $path = $params['path']; + Trashbin::move2trash($path); + } + } +} diff --git a/apps/files_trashbin/lib/trash.php b/apps/files_trashbin/lib/trash.php new file mode 100644 index 0000000000..384a865ce0 --- /dev/null +++ b/apps/files_trashbin/lib/trash.php @@ -0,0 +1,190 @@ +. + * + */ + +namespace OCA_Trash; + +class Trashbin { + + /** + * move file to the trash bin + * + * @param $file_path path to the deleted file/directory relative to the files root directory + */ + public static function move2trash($file_path) { + $user = \OCP\User::getUser(); + $view = new \OC_FilesystemView('/'. $user); + if (!$view->is_dir('files_trashbin')) { + $view->mkdir('files_trashbin'); + $view->mkdir("versions_trashbin"); + } + + $path_parts = pathinfo($file_path); + + $deleted = $path_parts['basename']; + $location = $path_parts['dirname']; + $timestamp = time(); + $mime = $view->getMimeType('files'.$file_path); + + if ( $view->is_dir('files'.$file_path) ) { + $type = 'dir'; + } else { + $type = 'file'; + } + + self::copy_recursive($file_path, 'files_trashbin/'.$deleted.'.d'.$timestamp, $view); + + $query = \OC_DB::prepare("INSERT INTO *PREFIX*files_trash (id,timestamp,location,type,mime,user) VALUES (?,?,?,?,?,?)"); + $result = $query->execute(array($deleted, $timestamp, $location, $type, $mime, $user)); + + if ( \OCP\App::isEnabled('files_versions') ) { + if ( $view->is_dir('files_versions'.$file_path) ) { + $view->rename('files_versions'.$file_path, 'versions_trashbin/'. $deleted.'.d'.$timestamp); + } else if ( $versions = \OCA_Versions\Storage::getVersions($file_path) ) { + foreach ($versions as $v) { + $view->rename('files_versions'.$v['path'].'.v'.$v['version'], 'versions_trashbin/'. $deleted.'.v'.$v['version'].'.d'.$timestamp); + } + } + } + + self::expire(); + } + + + /** + * restore files from trash bin + * @param $filename name of the file + * @param $timestamp time when the file was deleted + */ + public static function restore($filename, $timestamp) { + + $user = \OCP\User::getUser(); + $view = new \OC_FilesystemView('/'.$user); + + $query = \OC_DB::prepare('SELECT location,type FROM *PREFIX*files_trash WHERE user=? AND id=? AND timestamp=?'); + $result = $query->execute(array($user,$filename,$timestamp))->fetchAll(); + + if ( count($result) != 1 ) { + \OC_Log::write('files_trashbin', 'trash bin database inconsistent!', OC_Log::ERROR); + return false; + } + + $location = $result[0]['location']; + if ( $result[0]['location'] != '/' && !$view->is_dir('files'.$result[0]['location']) ) { + $location = '/'; + } + + $source = 'files_trashbin/'.$filename.'.d'.$timestamp; + $target = \OC_Filesystem::normalizePath('files/'.$location.'/'.$filename); + + $ext = self::getUniqueExtension($location, $filename, $view); + + $view->rename($source, $target.$ext); + + if ( \OCP\App::isEnabled('files_versions') ) { + if ( $result[0][type] == 'dir' ) { + $view->rename('versions_trashbin/'. $filename.'.d'.$timestamp, 'files_versions/'.$location.'/'.$filename.$ext); + } else if ( $versions = self::getVersionsFromTrash($filename, $timestamp) ) { + foreach ($versions as $v) { + $view->rename('versions_trashbin/'.$filename.'.v'.$v.'.d'.$timestamp, 'files_versions/'.$location.'/'.$filename.$ext.'.v'.$v); + } + } + } + + $query = \OC_DB::prepare('DELETE FROM *PREFIX*files_trash WHERE user=? AND id=? AND timestamp=?'); + $query->execute(array($user,$filename,$timestamp)); + + } + + /** + * clean up the trash bin + */ + private static function expire() { + //TODO: implement expire function + return true; + } + + /** + * recursive copy to copy a whole directory + * + * @param $source source path, relative to the users files directory + * @param $destination destination path relative to the users root directoy + * @param $view file view for the users root directory + * @param $location location of the source files, either "fscache" or "local" + */ + private static function copy_recursive( $source, $destination, $view, $location='fscache' ) { + if ( $view->is_dir( 'files'.$source ) ) { + $view->mkdir( $destination ); + foreach ( \OC_Files::getDirectoryContent($source) as $i ) { + $pathDir = $source.'/'.$i['name']; + if ( $view->is_dir('files'.$pathDir) ) { + self::copy_recursive($pathDir, $destination.'/'.$i['name'], $view); + } else { + $view->copy( 'files'.$pathDir, $destination . '/' . $i['name'] ); + } + } + } else { + $view->copy( 'files'.$source, $destination ); + } + } + + /** + * find all versions which belong to the file we want to restore + * @param $filename name of the file which should be restored + * @param $timestamp timestamp when the file was deleted + */ + private static function getVersionsFromTrash($filename, $timestamp) { + $view = new \OC_FilesystemView('/'.\OCP\User::getUser().'/versions_trashbin'); + $versionsName = \OCP\Config::getSystemValue('datadirectory').$view->getAbsolutePath($filename); + $versions = array(); + + // fetch for old versions + $matches = glob( $versionsName.'.v*.d'.$timestamp ); + + foreach( $matches as $ma ) { + $parts = explode( '.v', substr($ma, 0, -strlen($timestamp)-2) ); + $versions[] = ( end( $parts ) ); + } + return $versions; + } + + /** + * find unique extension for restored file if a file with the same name already exists + * @param $location where the file should be restored + * @param $filename name of the file + * @param $view filesystem view relative to users root directory + * @return string with unique extension + */ + private static function getUniqueExtension($location, $filename, $view) { + $ext = ''; + if ( $view->file_exists('files'.$location.'/'.$filename) ) { + $tmpext = '.restored'; + $ext = $tmpext; + $i = 1; + while ( $view->file_exists('files'.$location.'/'.$filename.$ext) ) { + $ext = $tmpext.$i; + $i++; + } + } + return $ext; + } + +} diff --git a/apps/files_trashbin/templates/index.php b/apps/files_trashbin/templates/index.php new file mode 100644 index 0000000000..a412379d53 --- /dev/null +++ b/apps/files_trashbin/templates/index.php @@ -0,0 +1,36 @@ + +
+ +
+
+
+ + +
t('Nothing in here. Upload something!')?>
+ + + + + + + + + + + + +
+ + t( 'Name' ); ?> + + + + Download" /> + t('Download')?> + + + + + t( 'Deleted' ); ?> +
diff --git a/apps/files_trashbin/templates/part.list.php b/apps/files_trashbin/templates/part.list.php new file mode 100644 index 0000000000..d022854330 --- /dev/null +++ b/apps/files_trashbin/templates/part.list.php @@ -0,0 +1,70 @@ + + +200) $relative_date_color = 200; + $name = str_replace('+', '%20', urlencode($file['name'])); + $name = str_replace('%2F', '/', $name); + $directory = str_replace('+', '%20', urlencode($file['directory'])); + $directory = str_replace('%2F', '/', $directory); ?> + ' + data-permissions=''> + + style="background-image:url()" + + style="background-image:url()" + + > + + + + + + + + + + + + + + + + + + + + + + + + + + Date: Fri, 18 Jan 2013 13:35:40 +0100 Subject: [PATCH 194/347] LDAP: gather defaults in one place, simplify readConfiguration --- apps/user_ldap/lib/connection.php | 119 +++++++++++++++++++++++------- 1 file changed, 91 insertions(+), 28 deletions(-) diff --git a/apps/user_ldap/lib/connection.php b/apps/user_ldap/lib/connection.php index 55234f4ac0..b6ed500cb1 100644 --- a/apps/user_ldap/lib/connection.php +++ b/apps/user_ldap/lib/connection.php @@ -185,40 +185,69 @@ class Connection { $this->cache->clear($this->getCacheKey(null)); } + private function getValue($varname) { + static $defaults; + if(is_null($defaults)){ + $defaults = $this->getDefaults(); + } + return \OCP\Config::getAppValue($this->configID, + $this->configPrefix.$varname, + $defaults[$varname]); + } + /** * Caches the general LDAP configuration. */ private function readConfiguration($force = false) { if((!$this->configured || $force) && !is_null($this->configID)) { - $this->config['ldapHost'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_host', ''); - $this->config['ldapBackupHost'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_backup_host', ''); - $this->config['ldapPort'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_port', 389); - $this->config['ldapBackupPort'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_backup_port', $this->config['ldapPort']); - $this->config['ldapOverrideMainServer']= \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_override_main_server', false); - $this->config['ldapAgentName'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_dn', ''); - $this->config['ldapAgentPassword'] = base64_decode(\OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_agent_password', '')); - $rawLdapBase = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_base', ''); - $this->config['ldapBase'] = preg_split('/\r\n|\r|\n/', $rawLdapBase); - $this->config['ldapBaseUsers'] = preg_split('/\r\n|\r|\n/', \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_base_users', $rawLdapBase)); - $this->config['ldapBaseGroups'] = preg_split('/\r\n|\r|\n/', \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_base_groups', $rawLdapBase)); + $defaults = $this->getDefaults(); + $v = 'getValue'; + $this->config['ldapHost'] = $this->$v('ldap_host'); + $this->config['ldapBackupHost'] = $this->$v('ldap_backup_host'); + $this->config['ldapPort'] = $this->$v('ldap_port'); + $this->config['ldapBackupPort'] = $this->$v('ldapPort'); + $this->config['ldapOverrideMainServer'] + = $this->$v('ldap_override_main_server'); + $this->config['ldapAgentName'] = $this->$v('ldap_dn'); + $this->config['ldapAgentPassword'] + = base64_decode($this->$v('ldap_agent_password')); + $rawLdapBase = $this->$v('ldap_base'); + $this->config['ldapBase'] + = preg_split('/\r\n|\r|\n/', $rawLdapBase); + $this->config['ldapBaseUsers'] + = preg_split('/\r\n|\r|\n/', ($this->$v('ldap_base_users'))); + $this->config['ldapBaseGroups'] + = preg_split('/\r\n|\r|\n/', $this->$v('ldap_base_groups')); unset($rawLdapBase); - $this->config['ldapTLS'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_tls', 0); - $this->config['ldapNoCase'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_nocase', 0); - $this->config['turnOffCertCheck'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_turn_off_cert_check', 0); - $this->config['ldapUserDisplayName'] = mb_strtolower(\OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_display_name', 'uid'), 'UTF-8'); - $this->config['ldapUserFilter'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_userlist_filter', 'objectClass=person'); - $this->config['ldapGroupFilter'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_group_filter', '(objectClass=posixGroup)'); - $this->config['ldapLoginFilter'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_login_filter', '(uid=%uid)'); - $this->config['ldapGroupDisplayName'] = mb_strtolower(\OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_group_display_name', 'uid'), 'UTF-8'); - $this->config['ldapQuotaAttribute'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_quota_attr', ''); - $this->config['ldapQuotaDefault'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_quota_def', ''); - $this->config['ldapEmailAttribute'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_email_attr', ''); - $this->config['ldapGroupMemberAssocAttr'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_group_member_assoc_attribute', 'uniqueMember'); - $this->config['ldapIgnoreNamingRules'] = \OCP\Config::getSystemValue('ldapIgnoreNamingRules', false); - $this->config['ldapCacheTTL'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_cache_ttl', 10*60); - $this->config['ldapUuidAttribute'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_uuid_attribute', 'auto'); - $this->config['ldapOverrideUuidAttribute'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'ldap_override_uuid_attribute', 0); - $this->config['homeFolderNamingRule'] = \OCP\Config::getAppValue($this->configID, $this->configPrefix.'home_folder_naming_rule', 'opt:username'); + $this->config['ldapTLS'] = $this->$v('ldap_tls'); + $this->config['ldapNoCase'] = $this->$v('ldap_nocase'); + $this->config['turnOffCertCheck'] + = $this->$v('ldap_turn_off_cert_check'); + $this->config['ldapUserDisplayName'] + = mb_strtolower($this->$v('ldap_display_name'),'UTF-8'); + $this->config['ldapUserFilter'] + = $this->$v('ldap_userlist_filter'); + $this->config['ldapGroupFilter'] = $this->$v('ldap_group_filter'); + $this->config['ldapLoginFilter'] = $this->$v('ldap_login_filter'); + $this->config['ldapGroupDisplayName'] + = mb_strtolower($this->$v('ldap_group_display_name'), 'UTF-8'); + $this->config['ldapQuotaAttribute'] + = $this->$v('ldap_quota_attr'); + $this->config['ldapQuotaDefault'] + = $this->$v('ldap_quota_def'); + $this->config['ldapEmailAttribute'] + = $this->$v('ldap_email_attr'); + $this->config['ldapGroupMemberAssocAttr'] + = $this->$v('ldap_group_member_assoc_attribute'); + $this->config['ldapIgnoreNamingRules'] + = \OCP\Config::getSystemValue('ldapIgnoreNamingRules', false); + $this->config['ldapCacheTTL'] = $this->$v('ldap_cache_ttl'); + $this->config['ldapUuidAttribute'] + = $this->$v('ldap_uuid_attribute'); + $this->config['ldapOverrideUuidAttribute'] + = $this->$v('ldap_override_uuid_attribute'); + $this->config['homeFolderNamingRule'] + = $this->$v('home_folder_naming_rule'); $this->configured = $this->validateConfiguration(); } @@ -326,6 +355,40 @@ class Connection { return $configurationOK; } + /** + * @returns an associted array with the default values. Keys are correspond + * to configvalue entries in the database table + */ + public function getDefaults() { + return array( + 'ldap_host' => '', + 'ldap_port' => '389', + 'ldap_backup_host' => '', + 'ldap_backup_port' => '', + 'ldap_override_main_server' => '', + 'ldap_dn' => '', + 'ldap_agent_password' => '', + 'ldap_base' => '', + 'ldap_base_users' => '', + 'ldap_base_groups' => '', + 'ldap_userlist_filter' => 'objectClass=person', + 'ldap_login_filter' => 'uid=%uid', + 'ldap_group_filter' => 'objectClass=posixGroup', + 'ldap_display_name' => 'cn', + 'ldap_group_display_name' => 'cn', + 'ldap_tls' => 1, + 'ldap_nocase' => 0, + 'ldap_quota_def' => '', + 'ldap_quota_attr' => '', + 'ldap_email_attr' => '', + 'ldap_group_member_assoc_attribute' => 'uniqueMember', + 'ldap_cache_ttl' => 600, + 'ldap_uuid_attribute' => 'auto', + 'ldap_override_uuid_attribute' => 0, + 'home_folder_naming_rule' => '', + ); + } + /** * Connects and Binds to LDAP */ From 805f900b1980ae1f5d69395fd646a9a4605b7c68 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Fri, 18 Jan 2013 13:45:39 +0100 Subject: [PATCH 195/347] LDAP: pass defaults to settings form, and restore them on creating a new configuration if wanted --- apps/user_ldap/js/settings.js | 12 +++++-- apps/user_ldap/settings.php | 13 +++++++- apps/user_ldap/templates/settings.php | 48 +++++++++++++-------------- 3 files changed, 46 insertions(+), 27 deletions(-) diff --git a/apps/user_ldap/js/settings.js b/apps/user_ldap/js/settings.js index 8cd31301f2..0b8f141dfa 100644 --- a/apps/user_ldap/js/settings.js +++ b/apps/user_ldap/js/settings.js @@ -34,8 +34,16 @@ $(document).ready(function() { 'Keep settings?', function(keep) { if(!keep) { - $('#ldap').find('input[type=text], input[type=password], textarea, select').val(''); - $('#ldap').find('input[type=checkbox]').removeAttr('checked'); + $('#ldap').find('input[type=text], input[type=number], input[type=password], textarea, select').each(function() { + $(this).val($(this).attr('data-default')); + }); + $('#ldap').find('input[type=checkbox]').each(function() { + if($(this).attr('data-default') == 1) { + $(this).attr('checked', 'checked'); + } else { + $(this).removeAttr('checked'); + } + }); } } ); diff --git a/apps/user_ldap/settings.php b/apps/user_ldap/settings.php index 73e4f0b6f4..f3f0826739 100644 --- a/apps/user_ldap/settings.php +++ b/apps/user_ldap/settings.php @@ -64,7 +64,7 @@ if($_POST) { } } if($clearCache) { - $ldap = new \OCA\user_ldap\lib\Connection('user_ldap'); + $ldap = new \OCA\user_ldap\lib\Connection(); $ldap->clearCache(); } } @@ -88,4 +88,15 @@ $hfnr = ($hfnr == 'opt:username') ? '' : substr($hfnr, strlen('attr:')); $tmpl->assign('home_folder_naming_rule', $hfnr, ''); $tmpl->assign('serverConfigurationOptions', '', false); +// assign default values +if(!isset($ldap)) { + $ldap = new \OCA\user_ldap\lib\Connection(); +} +$defaults = $ldap->getDefaults(); +foreach($defaults as $key => $default) { + $tmpl->assign($key.'_default', $default); +} + +// $tmpl->assign(); + return $tmpl->fetchPage(); diff --git a/apps/user_ldap/templates/settings.php b/apps/user_ldap/templates/settings.php index c3ec20fc84..90a46a1733 100644 --- a/apps/user_ldap/templates/settings.php +++ b/apps/user_ldap/templates/settings.php @@ -17,32 +17,32 @@

-

-

-

-

-


t('use %%uid placeholder, e.g. "uid=%%uid"');?>

-


t('without any placeholder, e.g. "objectClass=person".');?>

-


t('without any placeholder, e.g. "objectClass=posixGroup".');?>

+

+

+

+

+


t('use %%uid placeholder, e.g. "uid=%%uid"');?>

+


t('without any placeholder, e.g. "objectClass=person".');?>

+


t('without any placeholder, e.g. "objectClass=posixGroup".');?>

-

-

-

-

title="t('When switched on, ownCloud will only connect to the replica server.');?>" />

-

-

-

-

title="t('Do not use it for SSL connections, it will fail.');?>" />

-

>

-

>
t('Not recommended, use for testing only.');?>

-

-

-

-

-

-

-

+

+

+

+

data-default="" title="t('When switched on, ownCloud will only connect to the replica server.');?>" />

+

+

+

+

data-default="" title="t('Do not use it for SSL connections, it will fail.');?>" />

+

>

+

>
t('Not recommended, use for testing only.');?>

+

+

+

+

+

+

+

t('Help');?> From 229a25f41a5cf1b9eeac8cccedaa7196975328b4 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Fri, 18 Jan 2013 13:53:26 +0100 Subject: [PATCH 196/347] fix mixed key and value --- apps/user_ldap/lib/connection.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/user_ldap/lib/connection.php b/apps/user_ldap/lib/connection.php index b6ed500cb1..926691c2d9 100644 --- a/apps/user_ldap/lib/connection.php +++ b/apps/user_ldap/lib/connection.php @@ -264,7 +264,7 @@ class Connection { return false; } - $params = array('ldap_host'=>'ldapHost', 'ldap_port'=>'ldapPort', 'ldap_backup_host'=>'ldapBackupHost', 'ldap_backup_port'=>'ldapBackupPort', 'ldapOverrideMainServer' => 'ldap_override_main_server', 'ldap_dn'=>'ldapAgentName', 'ldap_agent_password'=>'ldapAgentPassword', 'ldap_base'=>'ldapBase', 'ldap_base_users'=>'ldapBaseUsers', 'ldap_base_groups'=>'ldapBaseGroups', 'ldap_userlist_filter'=>'ldapUserFilter', 'ldap_login_filter'=>'ldapLoginFilter', 'ldap_group_filter'=>'ldapGroupFilter', 'ldap_display_name'=>'ldapUserDisplayName', 'ldap_group_display_name'=>'ldapGroupDisplayName', + $params = array('ldap_host'=>'ldapHost', 'ldap_port'=>'ldapPort', 'ldap_backup_host'=>'ldapBackupHost', 'ldap_backup_port'=>'ldapBackupPort', 'ldap_override_main_server' => 'ldapOverrideMainServer', 'ldap_dn'=>'ldapAgentName', 'ldap_agent_password'=>'ldapAgentPassword', 'ldap_base'=>'ldapBase', 'ldap_base_users'=>'ldapBaseUsers', 'ldap_base_groups'=>'ldapBaseGroups', 'ldap_userlist_filter'=>'ldapUserFilter', 'ldap_login_filter'=>'ldapLoginFilter', 'ldap_group_filter'=>'ldapGroupFilter', 'ldap_display_name'=>'ldapUserDisplayName', 'ldap_group_display_name'=>'ldapGroupDisplayName', 'ldap_tls'=>'ldapTLS', 'ldap_nocase'=>'ldapNoCase', 'ldap_quota_def'=>'ldapQuotaDefault', 'ldap_quota_attr'=>'ldapQuotaAttribute', 'ldap_email_attr'=>'ldapEmailAttribute', 'ldap_group_member_assoc_attribute'=>'ldapGroupMemberAssocAttr', 'ldap_cache_ttl'=>'ldapCacheTTL', 'home_folder_naming_rule' => 'homeFolderNamingRule'); @@ -287,6 +287,14 @@ class Connection { return $this->configured; } + /** + * @brief get the current LDAP configuration + * @return array + */ + public function getConfiguration() { + return $this->config; + } + /** * @brief Validates the user specified configuration * @returns true if configuration seems OK, false otherwise From d16164b0cd90cc52758b2d7c7b847e99fb892247 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Fri, 18 Jan 2013 14:09:22 +0100 Subject: [PATCH 197/347] remove item in the trash bin view after successful undelete --- apps/files_trashbin/ajax/undelete.php | 9 +++--- apps/files_trashbin/js/trash.js | 12 ++----- apps/files_trashbin/lib/trash.php | 35 ++++++++++++--------- apps/files_trashbin/templates/part.list.php | 3 +- 4 files changed, 30 insertions(+), 29 deletions(-) diff --git a/apps/files_trashbin/ajax/undelete.php b/apps/files_trashbin/ajax/undelete.php index c548034828..f55629d695 100644 --- a/apps/files_trashbin/ajax/undelete.php +++ b/apps/files_trashbin/ajax/undelete.php @@ -7,7 +7,8 @@ if(!OC_User::isLoggedIn()) { $timestamp = isset( $_REQUEST['timestamp'] ) ? $_REQUEST['timestamp'] : ''; $filename = isset( $_REQUEST['filename'] ) ? trim($_REQUEST['filename'], '/\\') : ''; -OCA_Trash\Trashbin::restore($filename, $timestamp); - -//TODO: return useful data after succsessful restore operation and remove restored files from the list view -OCP\JSON::success(array("data" => array('content'=>'foo', 'id' => 'bar'))); \ No newline at end of file +if ( OCA_Trash\Trashbin::restore($filename, $timestamp) ) { + OCP\JSON::success(array("data" => array('filename'=>$filename, 'timestamp' => $timestamp))); +} else { + OCP\JSON::error(array("data" => array("message" => "Couldn't restore ".$filename))); +} diff --git a/apps/files_trashbin/js/trash.js b/apps/files_trashbin/js/trash.js index 37e9a4bf10..b9088944fd 100644 --- a/apps/files_trashbin/js/trash.js +++ b/apps/files_trashbin/js/trash.js @@ -12,20 +12,12 @@ $(document).ready(function() { if (typeof FileActions !== 'undefined') { FileActions.register('all', 'Undelete', OC.PERMISSION_READ, '', function(filename) { var tr=$('tr').filterAttr('data-file', filename); - console.log("tr: " + tr.attr('data-timestamp') + " name: " + name); $.post(OC.filePath('files_trashbin','ajax','undelete.php'), {timestamp:tr.attr('data-timestamp'),filename:tr.attr('data-filename')}, function(result){ if (result.status == 'success') { - return; - var date=new Date(); - FileList.addFile(name,0,date,false,hidden); - var tr=$('tr').filterAttr('data-file',name); - tr.data('mime','text/plain').data('id',result.data.id); - tr.attr('data-id', result.data.id); - getMimeIcon('text/plain',function(path){ - tr.find('td.filename').attr('style','background-image:url('+path+')'); - }); + var row = document.getElementById(result.data.filename+'.d'+result.data.timestamp); + row.parentNode.removeChild(row); } else { OC.dialogs.alert(result.data.message, 'Error'); } diff --git a/apps/files_trashbin/lib/trash.php b/apps/files_trashbin/lib/trash.php index 384a865ce0..322f5679b7 100644 --- a/apps/files_trashbin/lib/trash.php +++ b/apps/files_trashbin/lib/trash.php @@ -86,7 +86,8 @@ class Trashbin { \OC_Log::write('files_trashbin', 'trash bin database inconsistent!', OC_Log::ERROR); return false; } - + + // if location no longer exists, restore file in the root directory $location = $result[0]['location']; if ( $result[0]['location'] != '/' && !$view->is_dir('files'.$result[0]['location']) ) { $location = '/'; @@ -95,23 +96,29 @@ class Trashbin { $source = 'files_trashbin/'.$filename.'.d'.$timestamp; $target = \OC_Filesystem::normalizePath('files/'.$location.'/'.$filename); + // we need a extension in case a file/dir with the same name already exists $ext = self::getUniqueExtension($location, $filename, $view); - $view->rename($source, $target.$ext); - - if ( \OCP\App::isEnabled('files_versions') ) { - if ( $result[0][type] == 'dir' ) { - $view->rename('versions_trashbin/'. $filename.'.d'.$timestamp, 'files_versions/'.$location.'/'.$filename.$ext); - } else if ( $versions = self::getVersionsFromTrash($filename, $timestamp) ) { - foreach ($versions as $v) { - $view->rename('versions_trashbin/'.$filename.'.v'.$v.'.d'.$timestamp, 'files_versions/'.$location.'/'.$filename.$ext.'.v'.$v); + if( $view->rename($source, $target.$ext) ) { + + // if versioning app is enabled, copy versions from the trash bin back to the original location + if ( $return && \OCP\App::isEnabled('files_versions') ) { + if ( $result[0][type] == 'dir' ) { + $view->rename('versions_trashbin/'. $filename.'.d'.$timestamp, 'files_versions/'.$location.'/'.$filename.$ext); + } else if ( $versions = self::getVersionsFromTrash($filename, $timestamp) ) { + foreach ($versions as $v) { + $view->rename('versions_trashbin/'.$filename.'.v'.$v.'.d'.$timestamp, 'files_versions/'.$location.'/'.$filename.$ext.'.v'.$v); + } } - } + } + + $query = \OC_DB::prepare('DELETE FROM *PREFIX*files_trash WHERE user=? AND id=? AND timestamp=?'); + $query->execute(array($user,$filename,$timestamp)); + + return true; } - - $query = \OC_DB::prepare('DELETE FROM *PREFIX*files_trash WHERE user=? AND id=? AND timestamp=?'); - $query->execute(array($user,$filename,$timestamp)); - + + return false; } /** diff --git a/apps/files_trashbin/templates/part.list.php b/apps/files_trashbin/templates/part.list.php index d022854330..c9a641a2e2 100644 --- a/apps/files_trashbin/templates/part.list.php +++ b/apps/files_trashbin/templates/part.list.php @@ -24,7 +24,8 @@ $name = str_replace('%2F', '/', $name); $directory = str_replace('+', '%20', urlencode($file['directory'])); $directory = str_replace('%2F', '/', $directory); ?> - Date: Fri, 18 Jan 2013 14:11:55 +0100 Subject: [PATCH 198/347] remove unneeded function --- apps/files_trashbin/js/trash.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/apps/files_trashbin/js/trash.js b/apps/files_trashbin/js/trash.js index b9088944fd..075dc6c315 100644 --- a/apps/files_trashbin/js/trash.js +++ b/apps/files_trashbin/js/trash.js @@ -1,12 +1,3 @@ -// Override download path to files_sharing/public.php -function fileDownloadPath(dir, file) { - var url = $('#downloadURL').val(); - if (url.indexOf('&path=') != -1) { - url += '/'+file; - } - return url; -} - $(document).ready(function() { if (typeof FileActions !== 'undefined') { From 8fdcd72d7f5fa9a0f2f84c63a1bc91211265cb19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Fri, 18 Jan 2013 15:12:38 +0100 Subject: [PATCH 199/347] expire files in trash bin after 30 days --- apps/files_trashbin/lib/trash.php | 32 ++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/apps/files_trashbin/lib/trash.php b/apps/files_trashbin/lib/trash.php index 322f5679b7..1b0b9cef4b 100644 --- a/apps/files_trashbin/lib/trash.php +++ b/apps/files_trashbin/lib/trash.php @@ -23,6 +23,8 @@ namespace OCA_Trash; class Trashbin { + + const DELETEAFTER=30; // how long do we keep files in the trash bin (number of days) /** * move file to the trash bin @@ -124,9 +126,33 @@ class Trashbin { /** * clean up the trash bin */ - private static function expire() { - //TODO: implement expire function - return true; + private static function expire() { + + $view = new \OC_FilesystemView('/'.\OCP\User::getUser()); + $user = \OCP\User::getUser(); + + $query = \OC_DB::prepare('SELECT location,type,id,timestamp FROM *PREFIX*files_trash WHERE user=?'); + $result = $query->execute(array($user))->fetchAll(); + + $limit = time() - (self::DELETEAFTER * 86400); + + foreach ( $result as $r ) { + $timestamp = $r['timestamp']; + $filename = $r['id']; + if ( $r['timestamp'] < $limit ) { + $view->unlink('files_trashbin/'.$filename.'.d'.$timestamp); + if ($r['type'] == 'dir') { + $view->unlink('versions_trashbin/'.$filename.'.d'.$timestamp); + } else if ( $versions = self::getVersionsFromTrash($filename, $timestamp) ) { + foreach ($versions as $v) { + $view->unlink('versions_trashbin/'.$filename.'.v'.$v.'.d'.$timestamp); + } + } + } + } + + $query = \OC_DB::prepare('DELETE FROM *PREFIX*files_trash WHERE user=? AND timestampexecute(array($user,$limit)); } /** From adbc576439faf19515b84d0fe4bb48ba52c4450a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Fri, 18 Jan 2013 17:50:44 +0100 Subject: [PATCH 200/347] handle group restore --- apps/files_trashbin/ajax/undelete.php | 35 ++++-- apps/files_trashbin/css/trash.css | 4 +- apps/files_trashbin/js/trash.js | 135 +++++++++++++++++++++++- apps/files_trashbin/lib/trash.php | 2 +- apps/files_trashbin/templates/index.php | 9 +- 5 files changed, 166 insertions(+), 19 deletions(-) diff --git a/apps/files_trashbin/ajax/undelete.php b/apps/files_trashbin/ajax/undelete.php index f55629d695..05b5e7a5ee 100644 --- a/apps/files_trashbin/ajax/undelete.php +++ b/apps/files_trashbin/ajax/undelete.php @@ -4,11 +4,34 @@ if(!OC_User::isLoggedIn()) { exit; } -$timestamp = isset( $_REQUEST['timestamp'] ) ? $_REQUEST['timestamp'] : ''; -$filename = isset( $_REQUEST['filename'] ) ? trim($_REQUEST['filename'], '/\\') : ''; +$files = $_REQUEST['files']; +$list = explode(';', $files); + +$error = array(); + +$i = 0; +foreach ($list as $file) { + $delimiter = strrpos($file, '.d'); + $filename = substr($file, 0, $delimiter); + $timestamp = substr($file, $delimiter+2); + + if ( !OCA_Trash\Trashbin::restore($filename, $timestamp) ) { + $error[] = $filename; + } else { + $success[$i]['filename'] = $filename; + $success[$i]['timestamp'] = $timestamp; + $i++; + } -if ( OCA_Trash\Trashbin::restore($filename, $timestamp) ) { - OCP\JSON::success(array("data" => array('filename'=>$filename, 'timestamp' => $timestamp))); -} else { - OCP\JSON::error(array("data" => array("message" => "Couldn't restore ".$filename))); } + +if ( $error ) { + $filelist = ''; + foreach ( $error as $e ) { + $filelist .= $e.', '; + } + OCP\JSON::error(array("data" => array("message" => "Couldn't restore ".rtrim($filelist,', '), "success" => $success, "error" => $error))); +} else { + OCP\JSON::success(array("data" => array("success" => $success))); +} + diff --git a/apps/files_trashbin/css/trash.css b/apps/files_trashbin/css/trash.css index bd6341c6fb..e0dd8c6e93 100644 --- a/apps/files_trashbin/css/trash.css +++ b/apps/files_trashbin/css/trash.css @@ -19,12 +19,12 @@ body { color:#fff; } -#header #download { +#header #undelete { font-weight:700; margin-left:2em; } -#header #download img { +#header #undelete img { padding-left:.1em; padding-right:.3em; vertical-align:text-bottom; diff --git a/apps/files_trashbin/js/trash.js b/apps/files_trashbin/js/trash.js index 075dc6c315..8f3786f15e 100644 --- a/apps/files_trashbin/js/trash.js +++ b/apps/files_trashbin/js/trash.js @@ -1,20 +1,145 @@ + $(document).ready(function() { if (typeof FileActions !== 'undefined') { FileActions.register('all', 'Undelete', OC.PERMISSION_READ, '', function(filename) { var tr=$('tr').filterAttr('data-file', filename); $.post(OC.filePath('files_trashbin','ajax','undelete.php'), - {timestamp:tr.attr('data-timestamp'),filename:tr.attr('data-filename')}, + {files:tr.attr('data-filename')+'.d'+tr.attr('data-timestamp')}, function(result){ - if (result.status == 'success') { - var row = document.getElementById(result.data.filename+'.d'+result.data.timestamp); + for (var i = 0; i < result.data.success.length; i++) { + var row = document.getElementById(result.data.success[i].filename+'.d'+result.data.success[i].timestamp); row.parentNode.removeChild(row); - } else { + } + if (result.status != 'success') { OC.dialogs.alert(result.data.message, 'Error'); } }); }); }; + + // Sets the select_all checkbox behaviour : + $('#select_all').click(function() { + if($(this).attr('checked')){ + // Check all + $('td.filename input:checkbox').attr('checked', true); + $('td.filename input:checkbox').parent().parent().addClass('selected'); + }else{ + // Uncheck all + $('td.filename input:checkbox').attr('checked', false); + $('td.filename input:checkbox').parent().parent().removeClass('selected'); + } + procesSelection(); + }); -}); \ No newline at end of file + $('td.filename input:checkbox').live('change',function(event) { + if (event.shiftKey) { + var last = $(lastChecked).parent().parent().prevAll().length; + var first = $(this).parent().parent().prevAll().length; + var start = Math.min(first, last); + var end = Math.max(first, last); + var rows = $(this).parent().parent().parent().children('tr'); + for (var i = start; i < end; i++) { + $(rows).each(function(index) { + if (index == i) { + var checkbox = $(this).children().children('input:checkbox'); + $(checkbox).attr('checked', 'checked'); + $(checkbox).parent().parent().addClass('selected'); + } + }); + } + } + var selectedCount=$('td.filename input:checkbox:checked').length; + $(this).parent().parent().toggleClass('selected'); + if(!$(this).attr('checked')){ + $('#select_all').attr('checked',false); + }else{ + if(selectedCount==$('td.filename input:checkbox').length){ + $('#select_all').attr('checked',true); + } + } + procesSelection(); + }); + + $('.undelete').click('click',function(event) { + var fileslist=getSelectedFiles('file').join(';'); + $.post(OC.filePath('files_trashbin','ajax','undelete.php'), + {files:fileslist}, + function(result){ + for (var i = 0; i < result.data.success.length; i++) { + var row = document.getElementById(result.data.success[i].filename+'.d'+result.data.success[i].timestamp); + row.parentNode.removeChild(row); + } + if (result.status != 'success') { + OC.dialogs.alert(result.data.message, 'Error'); + } + }); + }); + + +}); + +function procesSelection(){ + var selected=getSelectedFiles(); + var selectedFiles=selected.filter(function(el){return el.type=='file'}); + var selectedFolders=selected.filter(function(el){return el.type=='dir'}); + if(selectedFiles.length==0 && selectedFolders.length==0) { + $('#headerName>span.name').text(t('files','Name')); + $('#modified').text(t('files','Deleted')); + $('table').removeClass('multiselect'); + $('.selectedActions').hide(); + } + else { + $('.selectedActions').show(); + var selection=''; + if(selectedFolders.length>0){ + if(selectedFolders.length==1){ + selection+=t('files','1 folder'); + }else{ + selection+=t('files','{count} folders',{count: selectedFolders.length}); + } + if(selectedFiles.length>0){ + selection+=' & '; + } + } + if(selectedFiles.length>0){ + if(selectedFiles.length==1){ + selection+=t('files','1 file'); + }else{ + selection+=t('files','{count} files',{count: selectedFiles.length}); + } + } + $('#headerName>span.name').text(selection); + $('#modified').text(''); + $('table').addClass('multiselect'); + } +} + +/** + * @brief get a list of selected files + * @param string property (option) the property of the file requested + * @return array + * + * possible values for property: name, mime, size and type + * if property is set, an array with that property for each file is returnd + * if it's ommited an array of objects with all properties is returned + */ +function getSelectedFiles(property){ + var elements=$('td.filename input:checkbox:checked').parent().parent(); + var files=[]; + elements.each(function(i,element){ + var file={ + name:$(element).attr('data-filename'), + file:$(element).attr('data-file'), + timestamp:$(element).attr('data-timestamp'), + type:$(element).attr('data-type') + }; + if(property){ + files.push(file[property]); + }else{ + files.push(file); + } + }); + return files; +} \ No newline at end of file diff --git a/apps/files_trashbin/lib/trash.php b/apps/files_trashbin/lib/trash.php index 1b0b9cef4b..abfcf847ac 100644 --- a/apps/files_trashbin/lib/trash.php +++ b/apps/files_trashbin/lib/trash.php @@ -77,7 +77,7 @@ class Trashbin { * @param $timestamp time when the file was deleted */ public static function restore($filename, $timestamp) { - + $user = \OCP\User::getUser(); $view = new \OC_FilesystemView('/'.$user); diff --git a/apps/files_trashbin/templates/index.php b/apps/files_trashbin/templates/index.php index a412379d53..a9cb216b1f 100644 --- a/apps/files_trashbin/templates/index.php +++ b/apps/files_trashbin/templates/index.php @@ -16,13 +16,12 @@ t( 'Name' ); ?> - - - Download + + t('Undelete')?> - From 5df6f9d14d5a05d91d6706b420c8ad9a387a9f6d Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Fri, 18 Jan 2013 23:56:47 -0500 Subject: [PATCH 201/347] Fix merge --- lib/public/share.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/public/share.php b/lib/public/share.php index 9d2a64b459..5f9ad7fc09 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -684,13 +684,13 @@ class Share { } else { if ($fileDependent) { if (($itemType == 'file' || $itemType == 'folder') - && $format == \OC_Share_Backend_File::FORMAT_FILE_APP + && $format == \OC_Share_Backend_File::FORMAT_GET_FOLDER_CONTENTS || $format == \OC_Share_Backend_File::FORMAT_FILE_APP_ROOT ) { $select = '`*PREFIX*share`.`id`, `item_type`, `*PREFIX*share`.`parent`, `uid_owner`, ' - .'`share_type`, `share_with`, `file_source`, `path`, `file_target`, `permissions`, ' - .'`expiration`, `name`, `ctime`, `mtime`, `mimetype`, `size`, `encrypted`, ' - .'`versioned`, `writable`'; + .'`share_type`, `share_with`, `file_source`, `path`, `file_target`, ' + .'`permissions`, `expiration`, `storage`, `*PREFIX*filecache`.`parent` as `file_parent`, ' + .'`name` `mtime`, `mimetype`, `mimepart`, `size`, `encrypted`, `etag`'; } else { $select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `item_target`, `*PREFIX*share`.`parent`, `share_type`, `share_with`, `uid_owner`, `file_source`, `path`, `file_target`, `permissions`, `stime`, `expiration`, `token`'; } From cd8d8360b0bcc07e22c4c9b86252ef1676b123dc Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Fri, 18 Jan 2013 23:57:13 -0500 Subject: [PATCH 202/347] Disable fancy folder sharing for now --- lib/public/share.php | 56 ++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/lib/public/share.php b/lib/public/share.php index 5f9ad7fc09..f65d272ff1 100644 --- a/lib/public/share.php +++ b/lib/public/share.php @@ -300,36 +300,36 @@ class Share { throw new \Exception($message); } // If the item is a folder, scan through the folder looking for equivalent item types - if ($itemType == 'folder') { - $parentFolder = self::put('folder', $itemSource, $shareType, $shareWith, $uidOwner, $permissions, true); - if ($parentFolder && $files = \OC\Files\Filesystem::getDirectoryContent($itemSource)) { - for ($i = 0; $i < count($files); $i++) { - $name = substr($files[$i]['name'], strpos($files[$i]['name'], $itemSource) - strlen($itemSource)); - if ($files[$i]['mimetype'] == 'httpd/unix-directory' - && $children = \OC\Files\Filesystem::getDirectoryContent($name, '/') - ) { - // Continue scanning into child folders - array_push($files, $children); - } else { - // Check file extension for an equivalent item type to convert to - $extension = strtolower(substr($itemSource, strrpos($itemSource, '.') + 1)); - foreach (self::$backends as $type => $backend) { - if (isset($backend->dependsOn) && $backend->dependsOn == 'file' && isset($backend->supportedFileExtensions) && in_array($extension, $backend->supportedFileExtensions)) { - $itemType = $type; - break; - } - } - // Pass on to put() to check if this item should be converted, the item won't be inserted into the database unless it can be converted - self::put($itemType, $name, $shareType, $shareWith, $uidOwner, $permissions, $parentFolder); - } - } - return true; - } - return false; - } else { +// if ($itemType == 'folder') { +// $parentFolder = self::put('folder', $itemSource, $shareType, $shareWith, $uidOwner, $permissions, true); +// if ($parentFolder && $files = \OC\Files\Filesystem::getDirectoryContent($itemSource)) { +// for ($i = 0; $i < count($files); $i++) { +// $name = substr($files[$i]['name'], strpos($files[$i]['name'], $itemSource) - strlen($itemSource)); +// if ($files[$i]['mimetype'] == 'httpd/unix-directory' +// && $children = \OC\Files\Filesystem::getDirectoryContent($name, '/') +// ) { +// // Continue scanning into child folders +// array_push($files, $children); +// } else { +// // Check file extension for an equivalent item type to convert to +// $extension = strtolower(substr($itemSource, strrpos($itemSource, '.') + 1)); +// foreach (self::$backends as $type => $backend) { +// if (isset($backend->dependsOn) && $backend->dependsOn == 'file' && isset($backend->supportedFileExtensions) && in_array($extension, $backend->supportedFileExtensions)) { +// $itemType = $type; +// break; +// } +// } +// // Pass on to put() to check if this item should be converted, the item won't be inserted into the database unless it can be converted +// self::put($itemType, $name, $shareType, $shareWith, $uidOwner, $permissions, $parentFolder); +// } +// } +// return true; +// } +// return false; +// } else { // Put the item into the database return self::put($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions); - } +// } } /** From 8ca30d244c19b33e7e3b0da247b70160a3acc44f Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Sat, 19 Jan 2013 00:02:40 -0500 Subject: [PATCH 203/347] Implement getETag() in shared storage --- apps/files_sharing/lib/sharedstorage.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php index c8756af8ed..b0be6843c5 100644 --- a/apps/files_sharing/lib/sharedstorage.php +++ b/apps/files_sharing/lib/sharedstorage.php @@ -431,7 +431,14 @@ class Shared extends \OC\Files\Storage\Common { } public function getETag($path) { - + if ($path == '') { + return parent::getETag($path); + } + if ($source = $this->getSourcePath($path)) { + list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source); + return $storage->getETag($internalPath); + } + return null; } } From 664f33a29c81701fbf6a7fb18eda81e1c4665ecc Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Sat, 19 Jan 2013 21:04:25 -0500 Subject: [PATCH 204/347] Update mtimes of all parent folders after change inside --- lib/files/cache/updater.php | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/files/cache/updater.php b/lib/files/cache/updater.php index 8b0d383503..d04541c219 100644 --- a/lib/files/cache/updater.php +++ b/lib/files/cache/updater.php @@ -35,7 +35,7 @@ class Updater { $scanner = $storage->getScanner($internalPath); $scanner->scan($internalPath, Scanner::SCAN_SHALLOW); $cache->correctFolderSize($internalPath); - self::eTagUpdate($path); + self::correctFolder($path, $storage->filemtime($internalPath)); } } @@ -49,11 +49,17 @@ class Updater { $cache = $storage->getCache($internalPath); $cache->remove($internalPath); $cache->correctFolderSize($internalPath); - self::eTagUpdate($path); + self::correctFolder($path, time()); } } - static public function eTagUpdate($path) { + /** + * Update the mtime and ETag of all parent folders + * + * @param string $path + * @param string $time + */ + static public function correctFolder($path, $time) { if ($path !== '' && $path !== '/') { $parent = dirname($path); if ($parent === '.') { @@ -68,8 +74,8 @@ class Updater { $cache = $storage->getCache(); $id = $cache->getId($internalPath); if ($id !== -1) { - $cache->update($id, array('etag' => $storage->getETag($internalPath))); - self::eTagUpdate($parent); + $cache->update($id, array('mtime' => $time, 'etag' => $storage->getETag($internalPath))); + self::correctFolder($parent, $time); } } } From 6d84aa93d3ddf4f7d3c8599cba17bb02fd6df9e9 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Sun, 20 Jan 2013 18:02:44 +0100 Subject: [PATCH 205/347] Ajaxifiy Settings Save --- apps/user_ldap/ajax/setConfiguration.php | 33 +++++++++++++++ apps/user_ldap/js/settings.js | 14 +++++++ apps/user_ldap/lib/connection.php | 51 ++++++++++++++++++++++-- apps/user_ldap/templates/settings.php | 2 +- 4 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 apps/user_ldap/ajax/setConfiguration.php diff --git a/apps/user_ldap/ajax/setConfiguration.php b/apps/user_ldap/ajax/setConfiguration.php new file mode 100644 index 0000000000..206487c7e0 --- /dev/null +++ b/apps/user_ldap/ajax/setConfiguration.php @@ -0,0 +1,33 @@ +. + * + */ + +// Check user and app status +OCP\JSON::checkAdminUser(); +OCP\JSON::checkAppEnabled('user_ldap'); +OCP\JSON::callCheck(); + +$prefix = $_POST['ldap_serverconfig_chooser']; +$connection = new \OCA\user_ldap\lib\Connection($prefix); +$connection->setConfiguration($_POST); +$connection->saveConfiguration(); +OCP\JSON::success(); \ No newline at end of file diff --git a/apps/user_ldap/js/settings.js b/apps/user_ldap/js/settings.js index 0b8f141dfa..a07d140cf8 100644 --- a/apps/user_ldap/js/settings.js +++ b/apps/user_ldap/js/settings.js @@ -22,6 +22,20 @@ $(document).ready(function() { ); }); + $('#ldap_submit').click(function(event) { + event.preventDefault(); + $.post( + OC.filePath('user_ldap','ajax','setConfiguration.php'), + $('#ldap').serialize(), + function (result) { + if (result.status == 'success') { + $('#notification').text(t('user_ldap', 'LDAP Configuration Saved')); + $('#notification').fadeIn(); + } + } + ); + }); + $('#ldap_serverconfig_chooser').change(function(event) { value = $('#ldap_serverconfig_chooser option:selected:first').attr('value'); if(value == 'NEW') { diff --git a/apps/user_ldap/lib/connection.php b/apps/user_ldap/lib/connection.php index 926691c2d9..ebc46bf3b9 100644 --- a/apps/user_ldap/lib/connection.php +++ b/apps/user_ldap/lib/connection.php @@ -195,6 +195,12 @@ class Connection { $defaults[$varname]); } + private function setValue($varname, $value) { + \OCP\Config::setAppValue($this->configID, + $this->configPrefix.$varname, + $value); + } + /** * Caches the general LDAP configuration. */ @@ -205,7 +211,7 @@ class Connection { $this->config['ldapHost'] = $this->$v('ldap_host'); $this->config['ldapBackupHost'] = $this->$v('ldap_backup_host'); $this->config['ldapPort'] = $this->$v('ldap_port'); - $this->config['ldapBackupPort'] = $this->$v('ldapPort'); + $this->config['ldapBackupPort'] = $this->$v('ldap_backup_port'); $this->config['ldapOverrideMainServer'] = $this->$v('ldap_override_main_server'); $this->config['ldapAgentName'] = $this->$v('ldap_dn'); @@ -253,6 +259,13 @@ class Connection { } } + private function getConfigTranslationArray() { + static $array = array('ldap_host'=>'ldapHost', 'ldap_port'=>'ldapPort', 'ldap_backup_host'=>'ldapBackupHost', 'ldap_backup_port'=>'ldapBackupPort', 'ldap_override_main_server' => 'ldapOverrideMainServer', 'ldap_dn'=>'ldapAgentName', 'ldap_agent_password'=>'ldapAgentPassword', 'ldap_base'=>'ldapBase', 'ldap_base_users'=>'ldapBaseUsers', 'ldap_base_groups'=>'ldapBaseGroups', 'ldap_userlist_filter'=>'ldapUserFilter', 'ldap_login_filter'=>'ldapLoginFilter', 'ldap_group_filter'=>'ldapGroupFilter', 'ldap_display_name'=>'ldapUserDisplayName', 'ldap_group_display_name'=>'ldapGroupDisplayName', + + 'ldap_tls'=>'ldapTLS', 'ldap_nocase'=>'ldapNoCase', 'ldap_quota_def'=>'ldapQuotaDefault', 'ldap_quota_attr'=>'ldapQuotaAttribute', 'ldap_email_attr'=>'ldapEmailAttribute', 'ldap_group_member_assoc_attribute'=>'ldapGroupMemberAssocAttr', 'ldap_cache_ttl'=>'ldapCacheTTL', 'home_folder_naming_rule' => 'homeFolderNamingRule', 'turn_off_cert_check' => 'turnOffCertCheck'); + return $array; + } + /** * @brief set LDAP configuration with values delivered by an array, not read from configuration * @param $config array that holds the config parameters in an associated array @@ -264,9 +277,7 @@ class Connection { return false; } - $params = array('ldap_host'=>'ldapHost', 'ldap_port'=>'ldapPort', 'ldap_backup_host'=>'ldapBackupHost', 'ldap_backup_port'=>'ldapBackupPort', 'ldap_override_main_server' => 'ldapOverrideMainServer', 'ldap_dn'=>'ldapAgentName', 'ldap_agent_password'=>'ldapAgentPassword', 'ldap_base'=>'ldapBase', 'ldap_base_users'=>'ldapBaseUsers', 'ldap_base_groups'=>'ldapBaseGroups', 'ldap_userlist_filter'=>'ldapUserFilter', 'ldap_login_filter'=>'ldapLoginFilter', 'ldap_group_filter'=>'ldapGroupFilter', 'ldap_display_name'=>'ldapUserDisplayName', 'ldap_group_display_name'=>'ldapGroupDisplayName', - - 'ldap_tls'=>'ldapTLS', 'ldap_nocase'=>'ldapNoCase', 'ldap_quota_def'=>'ldapQuotaDefault', 'ldap_quota_attr'=>'ldapQuotaAttribute', 'ldap_email_attr'=>'ldapEmailAttribute', 'ldap_group_member_assoc_attribute'=>'ldapGroupMemberAssocAttr', 'ldap_cache_ttl'=>'ldapCacheTTL', 'home_folder_naming_rule' => 'homeFolderNamingRule'); + $params = $this->getConfigTranslationArray(); foreach($config as $parameter => $value) { if(isset($this->config[$parameter])) { @@ -287,11 +298,42 @@ class Connection { return $this->configured; } + public function saveConfiguration() { + $trans = array_flip($this->getConfigTranslationArray()); + foreach($this->config as $key => $value) { + \OCP\Util::writeLog('user_ldap', 'LDAP: storing key '.$key.' value '.$value, \OCP\Util::DEBUG); + switch ($key) { + case 'ldap_agent_password': + $value = base64_encode($value); + break; + case 'home_folder_naming_rule': + $value = empty($value) ? 'opt:username' : 'attr:'.$value; + break; + case 'ldapIgnoreNamingRules': + case 'ldapOverrideUuidAttribute': + case 'hasPagedResultSupport': + continue; + default: + if(is_null($value)) { + $value = 0; + } + } + + $this->setValue($trans[$key], $value); + } + } + /** * @brief get the current LDAP configuration * @return array */ public function getConfiguration() { + $trans = $this->getConfigTranslationArray(); + $config = array(); + foreach($trans as $classKey => $dbKey) { + $config[$dbKey] = $this->config[$classKey]; + } + return $this->config; } @@ -394,6 +436,7 @@ class Connection { 'ldap_uuid_attribute' => 'auto', 'ldap_override_uuid_attribute' => 0, 'home_folder_naming_rule' => '', + 'ldap_turn_off_cert_check' => 0, ); } diff --git a/apps/user_ldap/templates/settings.php b/apps/user_ldap/templates/settings.php index 90a46a1733..6b95f8660e 100644 --- a/apps/user_ldap/templates/settings.php +++ b/apps/user_ldap/templates/settings.php @@ -44,7 +44,7 @@

- t('Help');?> + t('Help');?> From 0c3466325b858013acf799fa1cd65acaad48d723 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Sun, 20 Jan 2013 18:27:39 +0100 Subject: [PATCH 206/347] fix continue in switch, add another key to skip --- apps/user_ldap/lib/connection.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/user_ldap/lib/connection.php b/apps/user_ldap/lib/connection.php index ebc46bf3b9..bf36db8223 100644 --- a/apps/user_ldap/lib/connection.php +++ b/apps/user_ldap/lib/connection.php @@ -311,8 +311,9 @@ class Connection { break; case 'ldapIgnoreNamingRules': case 'ldapOverrideUuidAttribute': + case 'ldapUuidAttribute': case 'hasPagedResultSupport': - continue; + continue 2; default: if(is_null($value)) { $value = 0; From 10876aba896be188be2883dbc059b93fea96bbf5 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Sun, 20 Jan 2013 18:30:14 +0100 Subject: [PATCH 207/347] fix more config keys for save settings handling --- apps/user_ldap/lib/connection.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/user_ldap/lib/connection.php b/apps/user_ldap/lib/connection.php index bf36db8223..7d9f82cf83 100644 --- a/apps/user_ldap/lib/connection.php +++ b/apps/user_ldap/lib/connection.php @@ -303,10 +303,10 @@ class Connection { foreach($this->config as $key => $value) { \OCP\Util::writeLog('user_ldap', 'LDAP: storing key '.$key.' value '.$value, \OCP\Util::DEBUG); switch ($key) { - case 'ldap_agent_password': + case 'ldapAgentPassword': $value = base64_encode($value); break; - case 'home_folder_naming_rule': + case 'homeFolderNamingRule': $value = empty($value) ? 'opt:username' : 'attr:'.$value; break; case 'ldapIgnoreNamingRules': From 3fd28632c470e89d7c9334379da3d8fa6faf0de4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Mon, 21 Jan 2013 13:07:43 +0100 Subject: [PATCH 208/347] allow to look into deleted directories --- apps/files/js/fileactions.js | 1 + apps/files_trashbin/index.php | 48 +++++++++++++++++++-- apps/files_trashbin/templates/part.list.php | 13 +++++- 3 files changed, 56 insertions(+), 6 deletions(-) diff --git a/apps/files/js/fileactions.js b/apps/files/js/fileactions.js index 093b6204c3..d20f9e835b 100644 --- a/apps/files/js/fileactions.js +++ b/apps/files/js/fileactions.js @@ -189,6 +189,7 @@ FileActions.register('all', 'Rename', OC.PERMISSION_UPDATE, function () { FileList.rename(filename); }); + FileActions.register('dir', 'Open', OC.PERMISSION_READ, '', function (filename) { window.location = OC.linkTo('files', 'index.php') + '?dir=' + encodeURIComponent($('#dir').val()).replace(/%2F/g, '/') + '/' + encodeURIComponent(filename); }); diff --git a/apps/files_trashbin/index.php b/apps/files_trashbin/index.php index 28414cc1ce..2925223197 100644 --- a/apps/files_trashbin/index.php +++ b/apps/files_trashbin/index.php @@ -14,8 +14,37 @@ $view = new OC_Filesystemview('/'.$user.'/files_trashbin'); OCP\Util::addStyle('files', 'files'); OCP\Util::addScript('files', 'filelist'); -$query = \OC_DB::prepare('SELECT id,location,timestamp,type,mime FROM *PREFIX*files_trash WHERE user=?'); -$result = $query->execute(array($user))->fetchAll(); +$dir = isset($_GET['dir']) ? stripslashes($_GET['dir']) : ''; + +if ($dir) { + $dirlisting = true; + $view = new \OC_FilesystemView('/'.\OCP\User::getUser().'/files_trashbin'); + $fullpath = \OCP\Config::getSystemValue('datadirectory').$view->getAbsolutePath($dir); + $dirContent = opendir($fullpath); + $i = 0; + while($entryName = readdir($dirContent)) { + if ( $entryName != '.' && $entryName != '..' ) { + $pos = strpos($dir.'/', '/', 1); + $tmp = substr($dir, 0, $pos); + $pos = strrpos($tmp, '.d'); + $timestamp = substr($tmp,$pos+2); + error_log("timestamp: $timestamp"); + $result[] = array( + 'id' => $entryName, + 'timestamp' => $timestamp, + 'mime' => $view->getMimeType($dir.'/'.$entryName), + 'type' => $view->is_dir($dir.'/'.$entryName) ? 'dir' : 'file', + 'location' => $dir, + ); + } + } + closedir($fullpath); + +} else { + $dirlisting = false; + $query = \OC_DB::prepare('SELECT id,location,timestamp,type,mime FROM *PREFIX*files_trash WHERE user=?'); + $result = $query->execute(array($user))->fetchAll(); +} $files = array(); foreach ($result as $r) { @@ -38,15 +67,26 @@ foreach ($result as $r) { $files[] = $i; } +// Make breadcrumb +$breadcrumb = array('dir' => '', 'name' => 'Trash'); +$pathtohere = ''; +foreach (explode('/', $dir) as $i) { + if ($i != '') { + $pathtohere .= '/' . $i; + $breadcrumb[] = array('dir' => $pathtohere, 'name' => $i); + } +} + $breadcrumbNav = new OCP\Template('files', 'part.breadcrumb', ''); $breadcrumbNav->assign('breadcrumb', array(array('dir' => '', 'name' => 'Trash')), false); $breadcrumbNav->assign('baseURL', OCP\Util::linkTo('files_trashbin', 'index.php') . '?dir=', false); $list = new OCP\Template('files_trashbin', 'part.list', ''); $list->assign('files', $files, false); -$list->assign('baseURL', OCP\Util::linkTo('files_trashbin', 'index.php'). '?dir=', false); -$list->assign('downloadURL', OCP\Util::linkTo('files_trashbin', 'download.php') . '?file=', false); +$list->assign('baseURL', OCP\Util::linkTo('files_trashbin', 'index.php'). '?dir='.$dir, false); +$list->assign('downloadURL', OCP\Util::linkTo('files_trashbin', 'download.php') . '?file='.$dir, false); $list->assign('disableSharing', true); +$list->assign('dirlisting', $dirlisting); $list->assign('disableDownloadActions', true); $tmpl->assign('breadcrumb', $breadcrumbNav->fetchPage(), false); $tmpl->assign('fileList', $list->fetchPage(), false); diff --git a/apps/files_trashbin/templates/part.list.php b/apps/files_trashbin/templates/part.list.php index c9a641a2e2..72359da299 100644 --- a/apps/files_trashbin/templates/part.list.php +++ b/apps/files_trashbin/templates/part.list.php @@ -40,9 +40,17 @@ > - + + + + + - + + + + + @@ -69,3 +77,4 @@ Date: Mon, 21 Jan 2013 20:40:23 +0100 Subject: [PATCH 209/347] we are getting closer. updating is not working yet. --- lib/app.php | 16 +++++- lib/installer.php | 99 ++++++++++++++++++++++++++++++++++--- lib/ocsclient.php | 2 + settings/ajax/apps/ocs.php | 1 + settings/ajax/updateapp.php | 17 +++++++ settings/apps.php | 5 +- settings/js/apps.js | 30 +++++++++++ settings/routes.php | 2 + settings/templates/apps.php | 4 +- 9 files changed, 167 insertions(+), 9 deletions(-) create mode 100644 settings/ajax/updateapp.php diff --git a/lib/app.php b/lib/app.php index e60bce2a20..13f54d6cf7 100644 --- a/lib/app.php +++ b/lib/app.php @@ -142,6 +142,8 @@ class OC_App{ * check if app is shipped * @param string $appid the id of the app to check * @return bool + * + * Check if an app that is installed is a shipped app or installed from the appstore. */ public static function isShipped($appid){ $info = self::getAppInfo($appid); @@ -197,9 +199,10 @@ class OC_App{ if(!is_numeric($app)) { $app = OC_Installer::installShippedApp($app); }else{ + $appdata=OC_OCSClient::getApplication($app); $download=OC_OCSClient::getApplicationDownload($app, 1); if(isset($download['downloadlink']) and $download['downloadlink']!='') { - $app=OC_Installer::installApp(array('source'=>'http', 'href'=>$download['downloadlink'])); + $app=OC_Installer::installApp(array('source'=>'http', 'href'=>$download['downloadlink'],'appdata'=>$appdata)); } } } @@ -212,6 +215,7 @@ class OC_App{ return false; }else{ OC_Appconfig::setValue( $app, 'enabled', 'yes' ); + if(isset($appdata['id'])) OC_Appconfig::setValue( $app, 'ocsid', $appdata['id'] ); return true; } }else{ @@ -229,6 +233,14 @@ class OC_App{ public static function disable( $app ) { // check if app is a shiped app or not. if not delete OC_Appconfig::setValue( $app, 'enabled', 'no' ); + + // check if app is a shiped app or not. if not delete + if(!OC_App::isShipped( $app )){ +// error_log($app.' not shipped'); + OC_Installer::removeApp( $app ); + }else{ +// error_log($app.' shipped'); + } } /** @@ -609,6 +621,8 @@ class OC_App{ $app1[$i]['author'] = $app['personid']; $app1[$i]['ocs_id'] = $app['id']; $app1[$i]['internal'] = $app1[$i]['active'] = 0; + $app1[$i]['update'] = false; + // rating img if($app['score']>=0 and $app['score']<5) $img=OC_Helper::imagePath( "core", "rating/s1.png" ); diff --git a/lib/installer.php b/lib/installer.php index 7dc8b0cef8..f4094a5d4c 100644 --- a/lib/installer.php +++ b/lib/installer.php @@ -141,6 +141,20 @@ class OC_Installer{ return false; } + // check if shipped tag is set which is only allowed for apps that are shipped with ownCloud + if(isset($info['shipped']) and ($info['shipped']=='true')) { + OC_Log::write('core', 'App can\'t be installed because it contains the true tag which is not allowed for non shipped apps', OC_Log::ERROR); + OC_Helper::rmdirr($extractDir); + return false; + } + + // check if the ocs version is the same as the version in info.xml/version + if(!isset($info['version']) or ($info['version']<>$data['appdata']['version'])) { + OC_Log::write('core', 'App can\'t be installed because the version in info.xml/version is not the same as the version reported from the app store', OC_Log::ERROR); + OC_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); @@ -226,7 +240,6 @@ class OC_Installer{ /** * @brief Update an application * @param $data array with all information - * @returns integer * * This function installs an app. All information needed are passed in the * associative array $data. @@ -250,11 +263,57 @@ class OC_Installer{ * * 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 - return true; + public static function updateApp( $app ) { + error_log('updater!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'); + return(true); + if(OC_Installer::isDownloaded( $name )) { + } } + /** + * @brief Check if an update for the app is available + * @param $name name of the application + * @returns emptry string is no update available or the version number of the update + * + * The function will check if an update for a version is available + */ + public static function isUpdateAvailable( $app ) { + //debug + return('1.1'); + + $ocsid=OC_Appconfig::getValue( $app, 'ocsid', ''); + + if($ocsid<>''){ + + $ocsdata=OC_OCSClient::getApplication($ocsid); + $ocsversion=$ocsdata['version']; + $currentversion=OC_App::getAppVersion($app); + +//error_log('bb'.$app.' '.$ocsversion); + return($ocsversion); + + }else{ + return(''); + } + + } + + /** + * @brief Check if app is already downloaded + * @param $name name of the application to remove + * @returns true/false + * + * The function will check if the app is already downloaded in the apps repository + */ + public static function isDownloaded( $name ) { + + $downloaded=false; + foreach(OC::$APPSROOTS as $dir) { + if(is_dir($dir['path'].'/'.$name)) $downloaded=true; + } + return($downloaded); + } + /** * @brief Removes an app * @param $name name of the application to remove @@ -276,8 +335,36 @@ class OC_Installer{ * this has to be done by the function oc_app_uninstall(). */ public static function removeApp( $name, $options = array()) { - // TODO: write function - return true; + + if(isset($options['keeppreferences']) and $options['keeppreferences']==false ){ + // todo + // remove preferences + } + + if(isset($options['keepappconfig']) and $options['keepappconfig']==false ){ + // todo + // remove app config + } + + if(isset($options['keeptables']) and $options['keeptables']==false ){ + // todo + // remove app database tables + } + + if(isset($options['keepfiles']) and $options['keepfiles']==false ){ + // todo + // remove user files + } + + if(OC_Installer::isDownloaded( $name )) { + $appdir=OC_App::getInstallPath().'/'.$name; + OC_Helper::rmdirr($appdir); + + }else{ + OC_Log::write('core', 'can\'t remove app '.$name.'. It is not installed.', OC_Log::ERROR); + + } + } /** diff --git a/lib/ocsclient.php b/lib/ocsclient.php index 24081425f1..3693078877 100644 --- a/lib/ocsclient.php +++ b/lib/ocsclient.php @@ -123,6 +123,7 @@ class OC_OCSClient{ $app=array(); $app['id']=(string)$tmp[$i]->id; $app['name']=(string)$tmp[$i]->name; + $app['version']=(string)$tmp[$i]->version; $app['type']=(string)$tmp[$i]->typeid; $app['typename']=(string)$tmp[$i]->typename; $app['personid']=(string)$tmp[$i]->personid; @@ -162,6 +163,7 @@ class OC_OCSClient{ $app=array(); $app['id']=$tmp->id; $app['name']=$tmp->name; + $app['version']=$tmp->version; $app['type']=$tmp->typeid; $app['typename']=$tmp->typename; $app['personid']=$tmp->personid; diff --git a/settings/ajax/apps/ocs.php b/settings/ajax/apps/ocs.php index 1ffba26ad1..6e09785d23 100644 --- a/settings/ajax/apps/ocs.php +++ b/settings/ajax/apps/ocs.php @@ -54,6 +54,7 @@ if(is_array($catagoryNames)) { 'preview'=>$pre, 'internal'=>false, 'internallabel'=>'3rd Party App', + 'update'=>false, ); } } diff --git a/settings/ajax/updateapp.php b/settings/ajax/updateapp.php new file mode 100644 index 0000000000..68c2bbf7f0 --- /dev/null +++ b/settings/ajax/updateapp.php @@ -0,0 +1,17 @@ + array('appid' => $appid))); +} else { + $l = OC_L10N::get('settings'); + OC_JSON::error(array("data" => array( "message" => $l->t("Could update app. ") ))); +} + + + diff --git a/settings/apps.php b/settings/apps.php index 99a3094399..a2015801e5 100644 --- a/settings/apps.php +++ b/settings/apps.php @@ -68,13 +68,16 @@ foreach ( $installedApps as $app ) { $info['internal']=true; $info['internallabel']='Internal App'; + + $info['update']=false; }else{ $info['internal']=false; $info['internallabel']='3rd Party App'; - + + $info['update']=OC_Installer::isUpdateAvailable($app); } $info['preview'] = OC_Helper::imagePath('settings', 'trans.png'); diff --git a/settings/js/apps.js b/settings/js/apps.js index c4c36b4bb1..8d214bd114 100644 --- a/settings/js/apps.js +++ b/settings/js/apps.js @@ -24,6 +24,14 @@ OC.Settings.Apps = OC.Settings.Apps || { page.find('span.author').text(app.author); page.find('span.licence').text(app.licence); + if (app.update != false) { + page.find('input.update').show(); + page.find('input.update').data('appid', app.id); + page.find('input.update').attr('value',t('settings', 'Update to ')+app.update); + } else { + page.find('input.update').hide(); + } + page.find('input.enable').show(); page.find('input.enable').val((app.active) ? t('settings', 'Disable') : t('settings', 'Enable')); page.find('input.enable').data('appid', app.id); @@ -44,6 +52,7 @@ OC.Settings.Apps = OC.Settings.Apps || { appData = appitem.data('app'); appData.active = !active; appitem.data('app', appData); + element.val(t('settings','Please wait....')); if(active) { $.post(OC.filePath('settings','ajax','disableapp.php'),{appid:appid},function(result) { if(!result || result.status!='success') { @@ -70,6 +79,20 @@ OC.Settings.Apps = OC.Settings.Apps || { $('#leftcontent li[data-id="'+appid+'"]').addClass('active'); } }, + updateApp:function(appid, element) { + console.log('updateApp:', appid, element); + element.val(t('settings','Updateing....')); + $.post(OC.filePath('settings','ajax','updateapp.php'),{appid:appid},function(result) { + if(!result || result.status!='success') { + OC.dialogs.alert('Error while updating app','Error'); + } + else { + element.val(t('settings','Updated')); + element.hide(); + } + },'json'); + }, + insertApp:function(appdata) { var applist = $('#leftcontent li'); var app = @@ -154,6 +177,13 @@ $(document).ready(function(){ OC.Settings.Apps.enableApp(appid, active, element); } }); + $('#rightcontent input.update').click(function(){ + var element = $(this); + var appid=$(this).data('appid'); + if(appid) { + OC.Settings.Apps.updateApp(appid, element); + } + }); if(appid) { var item = $('#leftcontent li[data-id="'+appid+'"]'); diff --git a/settings/routes.php b/settings/routes.php index 9b5bf80923..fa78f56652 100644 --- a/settings/routes.php +++ b/settings/routes.php @@ -51,6 +51,8 @@ $this->create('settings_ajax_enableapp', '/settings/ajax/enableapp.php') ->actionInclude('settings/ajax/enableapp.php'); $this->create('settings_ajax_disableapp', '/settings/ajax/disableapp.php') ->actionInclude('settings/ajax/disableapp.php'); +$this->create('settings_ajax_updateapp', '/settings/ajax/updateapp.php') + ->actionInclude('settings/ajax/updateapp.php'); $this->create('settings_ajax_navigationdetect', '/settings/ajax/navigationdetect.php') ->actionInclude('settings/ajax/navigationdetect.php'); // admin diff --git a/settings/templates/apps.php b/settings/templates/apps.php index 179ce9c540..8654547ecb 100644 --- a/settings/templates/apps.php +++ b/settings/templates/apps.php @@ -7,7 +7,7 @@ var appid = ''; @@ -31,7 +31,6 @@ - t('Update').' '.$app['update'].'" />'); ?> From 8f388d9df4aad381ed8774971ea1e3ae1c9dcf33 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Wed, 30 Jan 2013 13:48:59 +0100 Subject: [PATCH 295/347] LDAP: update link to online documentation --- apps/user_ldap/templates/settings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/user_ldap/templates/settings.php b/apps/user_ldap/templates/settings.php index e7b9e18dbe..ad8e58e1c2 100644 --- a/apps/user_ldap/templates/settings.php +++ b/apps/user_ldap/templates/settings.php @@ -46,7 +46,7 @@

- t('Help');?> + t('Help');?> From 0bce22966cf6a003ad8273373383300ebc94f52a Mon Sep 17 00:00:00 2001 From: irgsmirx Date: Wed, 30 Jan 2013 14:27:08 +0100 Subject: [PATCH 296/347] Update lib/base.php Correction of typo "locate" -> "locale". --- lib/base.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/base.php b/lib/base.php index f9818d3514..ebaf33814e 100644 --- a/lib/base.php +++ b/lib/base.php @@ -502,7 +502,7 @@ class OC // write error into log if locale can't be set if (OC_Util::issetlocaleworking() == false) { - OC_Log::write('core', 'setting locate to en_US.UTF-8 failed. Support is probably not installed on your system', OC_Log::ERROR); + OC_Log::write('core', 'setting locale to en_US.UTF-8 failed. Support is probably not installed on your system', OC_Log::ERROR); } if (OC_Config::getValue('installed', false)) { if (OC_Appconfig::getValue('core', 'backgroundjobs_mode', 'ajax') == 'ajax') { From 1592764a60263a8ecfe691e25f522514eae5022c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Wed, 30 Jan 2013 14:32:20 +0100 Subject: [PATCH 297/347] show a spinner instead of the delete button while moving files to the trash bin --- apps/files/css/files.css | 1 + apps/files/js/filelist.js | 18 +++++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/apps/files/css/files.css b/apps/files/css/files.css index f9406f5865..f337645845 100644 --- a/apps/files/css/files.css +++ b/apps/files/css/files.css @@ -111,6 +111,7 @@ table td.filename form { font-size:.85em; margin-left:3em; margin-right:3em; } } #fileList .fileactions a.action img { position:relative; top:.2em; } #fileList a.action { display:inline; margin:-.5em 0; padding:1em .5em 1em .5em !important; } +#fileList img.move2trash { display:inline; margin:-.5em 0; padding:1em .5em 1em .5em !important; float:right; } a.action.delete { float:right; } a.action>img { max-height:16px; max-width:16px; vertical-align:text-bottom; } .selectedActions { display:none; float:right; } diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 5cb8849ffe..28230409d2 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -271,13 +271,20 @@ var FileList={ } }, do_delete:function(files){ + if(files.substr){ + files=[files]; + } + for (var i in files) { + var deleteAction = $('tr').filterAttr('data-file',files[i]).children("td.date").children(".action.delete"); + var oldHTML = deleteAction[0].outerHTML; + var newHTML = ''; + deleteAction[0].outerHTML = newHTML; + } // Finish any existing actions if (FileList.lastAction) { FileList.lastAction(); } - if(files.substr){ - files=[files]; - } + var fileNames = JSON.stringify(files); $.post(OC.filePath('files', 'ajax', 'delete.php'), {dir:$('#dir').val(),files:fileNames}, @@ -290,6 +297,11 @@ var FileList={ files.removeClass('selected'); }); procesSelection(); + } else { + $.each(files,function(index,file) { + var deleteAction = $('tr').filterAttr('data-file',file).children("td.date").children(".move2trash"); + deleteAction[0].outerHTML = oldHTML; + }); } }); } From 5e422dea614a90f351aee63405419db1b1ed2d58 Mon Sep 17 00:00:00 2001 From: Frank Karlitschek Date: Wed, 30 Jan 2013 14:52:35 +0100 Subject: [PATCH 298/347] fix typo --- settings/ajax/updateapp.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings/ajax/updateapp.php b/settings/ajax/updateapp.php index 68c2bbf7f0..6d02dba984 100644 --- a/settings/ajax/updateapp.php +++ b/settings/ajax/updateapp.php @@ -10,7 +10,7 @@ if($result !== false) { OC_JSON::success(array('data' => array('appid' => $appid))); } else { $l = OC_L10N::get('settings'); - OC_JSON::error(array("data" => array( "message" => $l->t("Could update app. ") ))); + OC_JSON::error(array("data" => array( "message" => $l->t("Couldn\'t update app. ") ))); } From ea5861ed8c4e09eaaac36eb9e74e6d28d25516d3 Mon Sep 17 00:00:00 2001 From: Frank Karlitschek Date: Wed, 30 Jan 2013 15:27:20 +0100 Subject: [PATCH 299/347] remove leftover code --- settings/templates/apps.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/settings/templates/apps.php b/settings/templates/apps.php index bbd5de1fcb..3f0d2a9d1c 100644 --- a/settings/templates/apps.php +++ b/settings/templates/apps.php @@ -15,9 +15,6 @@
  • data-id="" data-type="" data-installed="1"> - '.$app['internallabel'].'' ?>
  • From c62a38fcb1b1445d107ac4096e89b134d7654920 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Wed, 30 Jan 2013 15:35:24 +0100 Subject: [PATCH 300/347] add spinner for undelete operation for visualisation --- apps/files_trashbin/js/trash.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/apps/files_trashbin/js/trash.js b/apps/files_trashbin/js/trash.js index 31d16436b2..0aa9f8dade 100644 --- a/apps/files_trashbin/js/trash.js +++ b/apps/files_trashbin/js/trash.js @@ -4,6 +4,9 @@ $(document).ready(function() { if (typeof FileActions !== 'undefined') { FileActions.register('all', 'Undelete', OC.PERMISSION_READ, OC.imagePath('core', 'actions/undelete.png'), function(filename) { var tr=$('tr').filterAttr('data-file', filename); + var spinner = ''; + var undeleteAction = $('tr').filterAttr('data-file',filename).children("td.date"); + undeleteAction[0].innerHTML = undeleteAction[0].innerHTML+spinner; $.post(OC.filePath('files_trashbin','ajax','undelete.php'), {files:tr.attr('data-file'), dirlisting:tr.attr('data-dirlisting') }, function(result){ @@ -63,8 +66,16 @@ $(document).ready(function() { }); $('.undelete').click('click',function(event) { - var fileslist=getSelectedFiles('file').join(';'); + var spinner = ''; + var files=getSelectedFiles('file'); + var fileslist=files.join(';'); var dirlisting=getSelectedFiles('dirlisting')[0]; + + for (var i in files) { + var undeleteAction = $('tr').filterAttr('data-file',files[i]).children("td.date"); + undeleteAction[0].innerHTML = undeleteAction[0].innerHTML+spinner; + } + $.post(OC.filePath('files_trashbin','ajax','undelete.php'), {files:fileslist, dirlisting:dirlisting}, function(result){ From 9ca0a93847dfbf9266f7e76e90c018d4dcff7f5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Wed, 30 Jan 2013 16:20:13 +0100 Subject: [PATCH 301/347] make spinner title translatable --- apps/files/js/filelist.js | 2 +- apps/files_trashbin/js/trash.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 28230409d2..d0810f7014 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -277,7 +277,7 @@ var FileList={ for (var i in files) { var deleteAction = $('tr').filterAttr('data-file',files[i]).children("td.date").children(".action.delete"); var oldHTML = deleteAction[0].outerHTML; - var newHTML = ''; + var newHTML = ''; deleteAction[0].outerHTML = newHTML; } // Finish any existing actions diff --git a/apps/files_trashbin/js/trash.js b/apps/files_trashbin/js/trash.js index 0aa9f8dade..8a407b88a0 100644 --- a/apps/files_trashbin/js/trash.js +++ b/apps/files_trashbin/js/trash.js @@ -4,7 +4,7 @@ $(document).ready(function() { if (typeof FileActions !== 'undefined') { FileActions.register('all', 'Undelete', OC.PERMISSION_READ, OC.imagePath('core', 'actions/undelete.png'), function(filename) { var tr=$('tr').filterAttr('data-file', filename); - var spinner = ''; + var spinner = ''; var undeleteAction = $('tr').filterAttr('data-file',filename).children("td.date"); undeleteAction[0].innerHTML = undeleteAction[0].innerHTML+spinner; $.post(OC.filePath('files_trashbin','ajax','undelete.php'), @@ -66,7 +66,7 @@ $(document).ready(function() { }); $('.undelete').click('click',function(event) { - var spinner = ''; + var spinner = ''; var files=getSelectedFiles('file'); var fileslist=files.join(';'); var dirlisting=getSelectedFiles('dirlisting')[0]; From 92921ceefd66f49ecf0915fe87997caefa24c6bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Wed, 30 Jan 2013 16:28:41 +0100 Subject: [PATCH 302/347] make strings translatable --- settings/templates/users.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/settings/templates/users.php b/settings/templates/users.php index f30c21efae..4d7c29678c 100644 --- a/settings/templates/users.php +++ b/settings/templates/users.php @@ -94,11 +94,11 @@ $_['subadmingroups'] = array_flip($items); change display name + alt="t("change display name")?>" title="t("change display name")?>"/> ●●●●●●● set new password + alt="t("set new password")?>" title="t("set new password")?>"/>

    -

    -

    -

    -

    -


    t('use %%uid placeholder, e.g. "uid=%%uid"');?>

    -


    t('without any placeholder, e.g. "objectClass=person".');?>

    -


    t('without any placeholder, e.g. "objectClass=posixGroup".');?>

    +

    +

    +

    +

    +


    t('use %%uid placeholder, e.g. "uid=%%uid"');?>

    +


    t('without any placeholder, e.g. "objectClass=person".');?>

    +


    t('without any placeholder, e.g. "objectClass=posixGroup".');?>

    -

    data-default="" title="t('When unchecked, this configuration will be skipped.');?>" />

    -

    -

    -

    -

    data-default="" title="t('When switched on, ownCloud will only connect to the replica server.');?>" />

    -

    -

    +

    +

    +

    +

    +

    +

    +

    -

    data-default="" title="t('Do not use it for SSL connections, it will fail.');?>" />

    +

    >

    -

    >
    t('Not recommended, use for testing only.');?>

    -

    -

    -

    -

    -

    -

    -

    +


    t('Not recommended, use for testing only.');?>

    +

    +

    +

    +

    +

    +

    +

    t('Help');?> From 1a854454d67f39794b24cc00bfbaadf8a921b7a0 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Thu, 31 Jan 2013 02:00:29 +0100 Subject: [PATCH 311/347] LDAP: avoid attempts to save null as configvalue --- apps/user_ldap/lib/connection.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/apps/user_ldap/lib/connection.php b/apps/user_ldap/lib/connection.php index c5af73857a..8ddc106d0b 100644 --- a/apps/user_ldap/lib/connection.php +++ b/apps/user_ldap/lib/connection.php @@ -341,10 +341,9 @@ ingle parameters case 'ldapUuidAttribute': case 'hasPagedResultSupport': continue 2; - default: - if(is_null($value)) { - $value = 0; - } + } + if(is_null($value)) { + $value = ''; } $this->setValue($trans[$key], $value); From 2f11d7fe126dcf0615cbb4c2d04b5c2f51813104 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Thu, 31 Jan 2013 02:10:13 +0100 Subject: [PATCH 312/347] LDAP: adjust settings interface for custom search attributes --- apps/user_ldap/templates/settings.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/user_ldap/templates/settings.php b/apps/user_ldap/templates/settings.php index af983039d6..e6fa91cc85 100644 --- a/apps/user_ldap/templates/settings.php +++ b/apps/user_ldap/templates/settings.php @@ -33,7 +33,9 @@

    +

    +

    >

    From 170cf20298c6c31a1e9a5258edf6a501845f2c1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Thu, 31 Jan 2013 09:57:16 +0100 Subject: [PATCH 313/347] addapt the css to adjust the change display name filed to the set password field --- settings/css/settings.css | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/settings/css/settings.css b/settings/css/settings.css index 4d0f6efd2c..8fad055f2e 100644 --- a/settings/css/settings.css +++ b/settings/css/settings.css @@ -22,13 +22,13 @@ form { display:inline; } table:not(.nostyle) th { height:2em; color:#999; } table:not(.nostyle) th, table:not(.nostyle) td { border-bottom:1px solid #ddd; padding:0 .5em; padding-left:.8em; text-align:left; font-weight:normal; } td.name, td.password { padding-left:.8em; } -td.password>img, td.remove>a, td.quota>img { visibility:hidden; } -td.password, td.quota { width:12em; cursor:pointer; } -td.password>span, td.quota>span { margin-right: 1.2em; color: #C7C7C7; } +td.password>img,td.displayName>img, td.remove>a, td.quota>img { visibility:hidden; } +td.password, td.quota, td.displayName { width:12em; cursor:pointer; } +td.password>span, td.quota>span, rd.displayName>span { margin-right: 1.2em; color: #C7C7C7; } td.remove { width:1em; padding-right:1em; } -tr:hover>td.password>span { margin:0; cursor:pointer; } -tr:hover>td.remove>a, tr:hover>td.password>img, tr:hover>td.quota>img { visibility:visible; cursor:pointer; } +tr:hover>td.password>span, tr:hover>td.displayName>span { margin:0; cursor:pointer; } +tr:hover>td.remove>a, tr:hover>td.password>img,tr:hover>td.displayName>img, tr:hover>td.quota>img { visibility:visible; cursor:pointer; } tr:hover>td.remove>a { float:right; } li.selected { background-color:#ddd; } #content>table:not(.nostyle) { margin-top:3em; } From 5112dac1023617f0cccb04c2472afb560f757087 Mon Sep 17 00:00:00 2001 From: Frank Karlitschek Date: Thu, 31 Jan 2013 10:00:42 +0100 Subject: [PATCH 314/347] remove spaces --- lib/installer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/installer.php b/lib/installer.php index bf81cbdada..f1b386a3e9 100644 --- a/lib/installer.php +++ b/lib/installer.php @@ -254,7 +254,7 @@ class OC_Installer{ * upgrade.php can determine the current installed version of the app using "OC_Appconfig::getValue($appid, 'installed_version')" */ public static function updateApp( $app ) { - $ocsid=OC_Appconfig::getValue( $app, 'ocsid', ''); + $ocsid=OC_Appconfig::getValue( $app, 'ocsid'); OC_App::disable($app); OC_App::enable($ocsid); } From 2ddd40ed417b09c6eab5a562eae418623417fc16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Thu, 31 Jan 2013 10:06:02 +0100 Subject: [PATCH 315/347] rename 'undelete' to 'restore' --- apps/files_trashbin/js/trash.js | 4 ++-- apps/files_trashbin/templates/index.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/files_trashbin/js/trash.js b/apps/files_trashbin/js/trash.js index 8a407b88a0..3ad0ab04fb 100644 --- a/apps/files_trashbin/js/trash.js +++ b/apps/files_trashbin/js/trash.js @@ -2,9 +2,9 @@ $(document).ready(function() { if (typeof FileActions !== 'undefined') { - FileActions.register('all', 'Undelete', OC.PERMISSION_READ, OC.imagePath('core', 'actions/undelete.png'), function(filename) { + FileActions.register('all', 'Restore', OC.PERMISSION_READ, OC.imagePath('core', 'actions/undelete.png'), function(filename) { var tr=$('tr').filterAttr('data-file', filename); - var spinner = ''; + var spinner = ''; var undeleteAction = $('tr').filterAttr('data-file',filename).children("td.date"); undeleteAction[0].innerHTML = undeleteAction[0].innerHTML+spinner; $.post(OC.filePath('files_trashbin','ajax','undelete.php'), diff --git a/apps/files_trashbin/templates/index.php b/apps/files_trashbin/templates/index.php index 104d93ce49..c3e51b4bec 100644 --- a/apps/files_trashbin/templates/index.php +++ b/apps/files_trashbin/templates/index.php @@ -17,9 +17,9 @@ t( 'Name' ); ?> - Undelete" /> - t('Undelete')?> + t('Restore')?> From 665bb41c1f1dc6ecf48a5c32f34d91533424f085 Mon Sep 17 00:00:00 2001 From: Thomas Mueller Date: Thu, 31 Jan 2013 10:27:02 +0100 Subject: [PATCH 316/347] style fixes --- lib/app.php | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/app.php b/lib/app.php index f851d802dc..2a87ec5950 100644 --- a/lib/app.php +++ b/lib/app.php @@ -215,7 +215,9 @@ class OC_App{ return false; }else{ OC_Appconfig::setValue( $app, 'enabled', 'yes' ); - if(isset($appdata['id'])) OC_Appconfig::setValue( $app, 'ocsid', $appdata['id'] ); + if(isset($appdata['id'])) { + OC_Appconfig::setValue( $app, 'ocsid', $appdata['id'] ); + } return true; } }else{ @@ -231,14 +233,13 @@ class OC_App{ * This function set an app as disabled in appconfig. */ public static function disable( $app ) { - // check if app is a shiped app or not. if not delete + // check if app is a shipped app or not. if not delete OC_Appconfig::setValue( $app, 'enabled', 'no' ); - // check if app is a shiped app or not. if not delete + // check if app is a shipped app or not. if not delete if(!OC_App::isShipped( $app )){ OC_Installer::removeApp( $app ); - }else{ - } + } } /** @@ -647,15 +648,15 @@ class OC_App{ } $remoteApps = OC_App::getAppstoreApps(); if ( $remoteApps ) { - // Remove duplicates + // Remove duplicates foreach ( $appList as $app ) { foreach ( $remoteApps AS $key => $remote ) { if ( $app['name'] == $remote['name'] - // To set duplicate detection to use OCS ID instead of string name, - // enable this code, remove the line of code above, - // and add [ID] to info.xml of each 3rd party app: - // OR $app['ocs_id'] == $remote['ocs_id'] + // To set duplicate detection to use OCS ID instead of string name, + // enable this code, remove the line of code above, + // and add [ID] to info.xml of each 3rd party app: + // OR $app['ocs_id'] == $remote['ocs_id'] ) { unset( $remoteApps[$key]); } From e8b423f6669afda88176181c73c5edde7cc5bf48 Mon Sep 17 00:00:00 2001 From: Thomas Mueller Date: Thu, 31 Jan 2013 10:30:13 +0100 Subject: [PATCH 317/347] style fixes --- lib/installer.php | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/lib/installer.php b/lib/installer.php index f1b386a3e9..9786af45be 100644 --- a/lib/installer.php +++ b/lib/installer.php @@ -259,18 +259,18 @@ class OC_Installer{ OC_App::enable($ocsid); } - /** - * @brief Check if an update for the app is available - * @param $name name of the application - * @returns emptry string is no update available or the version number of the update - * - * The function will check if an update for a version is available - */ - public static function isUpdateAvailable( $app ) { + /** + * @brief Check if an update for the app is available + * @param $name name of the application + * @returns empty string is no update available or the version number of the update + * + * The function will check if an update for a version is available + */ + public static function isUpdateAvailable( $app ) { $ocsid=OC_Appconfig::getValue( $app, 'ocsid', ''); if($ocsid<>''){ - + $ocsdata=OC_OCSClient::getApplication($ocsid); $ocsversion= (string) $ocsdata['version']; $currentversion=OC_App::getAppVersion($app); @@ -285,23 +285,23 @@ class OC_Installer{ return(''); } - } + } - /** - * @brief Check if app is already downloaded - * @param $name name of the application to remove - * @returns true/false - * - * The function will check if the app is already downloaded in the apps repository - */ - public static function isDownloaded( $name ) { + /** + * @brief Check if app is already downloaded + * @param $name name of the application to remove + * @returns true/false + * + * The function will check if the app is already downloaded in the apps repository + */ + public static function isDownloaded( $name ) { $downloaded=false; foreach(OC::$APPSROOTS as $dir) { - if(is_dir($dir['path'].'/'.$name)) $downloaded=true; + if(is_dir($dir['path'].'/'.$name)) $downloaded=true; } return($downloaded); - } + } /** * @brief Removes an app @@ -345,7 +345,7 @@ class OC_Installer{ // remove user files } - if(OC_Installer::isDownloaded( $name )) { + if(OC_Installer::isDownloaded( $name )) { $appdir=OC_App::getInstallPath().'/'.$name; OC_Helper::rmdirr($appdir); From 8a662a6c74e5aa961aba7b317107293e559232e1 Mon Sep 17 00:00:00 2001 From: Thomas Mueller Date: Thu, 31 Jan 2013 10:34:54 +0100 Subject: [PATCH 318/347] Cleanup string - easier for translators --- settings/ajax/updateapp.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings/ajax/updateapp.php b/settings/ajax/updateapp.php index 6d02dba984..77c0bbc3e3 100644 --- a/settings/ajax/updateapp.php +++ b/settings/ajax/updateapp.php @@ -10,7 +10,7 @@ if($result !== false) { OC_JSON::success(array('data' => array('appid' => $appid))); } else { $l = OC_L10N::get('settings'); - OC_JSON::error(array("data" => array( "message" => $l->t("Couldn\'t update app. ") ))); + OC_JSON::error(array("data" => array( "message" => $l->t("Couldn't update app.") ))); } From 3af09f2acf0baba5cb3e2dbed5d4e2b4aa2b365c Mon Sep 17 00:00:00 2001 From: Thomas Mueller Date: Thu, 31 Jan 2013 10:43:59 +0100 Subject: [PATCH 319/347] l10n support for the error dialog added --- settings/js/apps.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings/js/apps.js b/settings/js/apps.js index 8d214bd114..5a52a69774 100644 --- a/settings/js/apps.js +++ b/settings/js/apps.js @@ -84,7 +84,7 @@ OC.Settings.Apps = OC.Settings.Apps || { element.val(t('settings','Updateing....')); $.post(OC.filePath('settings','ajax','updateapp.php'),{appid:appid},function(result) { if(!result || result.status!='success') { - OC.dialogs.alert('Error while updating app','Error'); + OC.dialogs.alert(t('settings','Error while updating app'),t('settings','Error')); } else { element.val(t('settings','Updated')); From 9c83b307f6d49f30c4cc6db7258d7e3851bac0b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Thu, 31 Jan 2013 10:50:02 +0100 Subject: [PATCH 320/347] keep mtime --- apps/files_trashbin/lib/trash.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/files_trashbin/lib/trash.php b/apps/files_trashbin/lib/trash.php index b0c2284d97..6aa0bdffb9 100644 --- a/apps/files_trashbin/lib/trash.php +++ b/apps/files_trashbin/lib/trash.php @@ -119,8 +119,9 @@ class Trashbin { // we need a extension in case a file/dir with the same name already exists $ext = self::getUniqueExtension($location, $filename, $view); - + $mtime = $view->filemtime($source); if( $view->rename($source, $target.$ext) ) { + $view->touch($target.$ext, $mtime); // if versioning app is enabled, copy versions from the trash bin back to the original location if ( \OCP\App::isEnabled('files_versions') ) { if ( $result[0]['type'] == 'dir' ) { @@ -189,21 +190,23 @@ class Trashbin { * @param $source source path, relative to the users files directory * @param $destination destination path relative to the users root directoy * @param $view file view for the users root directory - * @param $location location of the source files, either "fscache" or "local" */ - private static function copy_recursive( $source, $destination, $view, $location='fscache' ) { + private static function copy_recursive( $source, $destination, $view ) { if ( $view->is_dir( 'files'.$source ) ) { $view->mkdir( $destination ); + $view->touch($destination, $view->filemtime('files'.$source)); foreach ( \OC_Files::getDirectoryContent($source) as $i ) { $pathDir = $source.'/'.$i['name']; if ( $view->is_dir('files'.$pathDir) ) { self::copy_recursive($pathDir, $destination.'/'.$i['name'], $view); } else { $view->copy( 'files'.$pathDir, $destination . '/' . $i['name'] ); + $view->touch($destination . '/' . $i['name'], $view->filemtime('files'.$pathDir)); } } } else { $view->copy( 'files'.$source, $destination ); + $view->touch($destination, $view->filemtime('files'.$source)); } } From 9a19c0af4b6a74f1578c8d86d4ef445a6ca132c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Thu, 31 Jan 2013 12:09:42 +0100 Subject: [PATCH 321/347] search for display name and uid (with no display name) since it is possible that not all users have a seperate display name --- lib/user/database.php | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/lib/user/database.php b/lib/user/database.php index 7deeb0c469..a9ec7b1bfe 100644 --- a/lib/user/database.php +++ b/lib/user/database.php @@ -156,12 +156,22 @@ class OC_User_Database extends OC_User_Backend { public function getDisplayNames($search = '', $limit = null, $offset = null) { $displayNames = array(); $query = OC_DB::prepare('SELECT `uid`, `displayname` FROM `*PREFIX*users` WHERE LOWER(`displayname`) LIKE LOWER(?)', $limit, $offset); - $result = $query->execute(array($search.'%')); + $result = $query->execute(array($search.'%')); $users = array(); - while ($row = $result->fetchRow()) { - $displayName = trim($row['displayname'], ' '); - $displayNames[$row['uid']] = empty($displayName) ? $row['uid'] : $displayName; - } + while ($row = $result->fetchRow()) { + $displayNames[$row['uid']] = $row['displayname']; + } + + // let's see if we can also find some users who don't have a display name yet + $query = OC_DB::prepare('SELECT `uid`, `displayname` FROM `*PREFIX*users` WHERE LOWER(`uid`) LIKE LOWER(?)', $limit, $offset); + $result = $query->execute(array($search.'%')); + while ($row = $result->fetchRow()) { + $displayName = trim($row['displayname'], ' '); + if ( empty($displayName) ) + $displayNames[$row['uid']] = $row['uid']; + } + + return $displayNames; } From ab255e8bb6551f97f85b863c47549281103de95d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Thu, 31 Jan 2013 12:12:39 +0100 Subject: [PATCH 322/347] add missing brackets --- lib/user/database.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/user/database.php b/lib/user/database.php index a9ec7b1bfe..8dfd9534a9 100644 --- a/lib/user/database.php +++ b/lib/user/database.php @@ -167,8 +167,9 @@ class OC_User_Database extends OC_User_Backend { $result = $query->execute(array($search.'%')); while ($row = $result->fetchRow()) { $displayName = trim($row['displayname'], ' '); - if ( empty($displayName) ) - $displayNames[$row['uid']] = $row['uid']; + if ( empty($displayName) ) { + $displayNames[$row['uid']] = $row['uid']; + } } From 77765bd9670ef64ad6cc90b4f3d74c959f937e13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Thu, 31 Jan 2013 12:17:23 +0100 Subject: [PATCH 323/347] remove some left over comments --- lib/group/database.php | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/lib/group/database.php b/lib/group/database.php index c5dd402b21..1e2328f4c0 100644 --- a/lib/group/database.php +++ b/lib/group/database.php @@ -219,21 +219,14 @@ class OC_Group_Database extends OC_Group_Backend { */ public function DisplayNamesInGroup($gid, $search = '', $limit = -1, $offset = 0) { $displayNames = ''; - /* - - SELECT Persons.LastName, Persons.FirstName, Orders.OrderNo - FROM Persons - INNER JOIN Orders - ON Persons.P_Id=Orders.P_Id - ORDER BY Persons.LastName - */ + $stmt = OC_DB::prepare('SELECT `*PREFIX*users`.`uid`, `*PREFIX*users`.`displayname` FROM `*PREFIX*users` INNER JOIN `*PREFIX*group_user` ON `*PREFIX*group_user`.`uid` = `*PREFIX*users`.`uid` WHERE `gid` = ? AND `*PREFIX*group_user.uid` LIKE ?', $limit, $offset); $result = $stmt->execute(array($gid, $search.'%')); $users = array(); while ($row = $result->fetchRow()) { $displayName = trim($row['displayname'], ' '); $displayNames[$row['uid']] = empty($displayName) ? $row['uid'] : $displayName; - } + } return $displayNames; } } From f7d281af6797c632cd60a50af766d625438fb2c4 Mon Sep 17 00:00:00 2001 From: Frank Karlitschek Date: Thu, 31 Jan 2013 12:24:10 +0100 Subject: [PATCH 324/347] just return "true" for now --- lib/installer.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/installer.php b/lib/installer.php index 9786af45be..c86f801b5f 100644 --- a/lib/installer.php +++ b/lib/installer.php @@ -257,6 +257,7 @@ class OC_Installer{ $ocsid=OC_Appconfig::getValue( $app, 'ocsid'); OC_App::disable($app); OC_App::enable($ocsid); + return(true); } /** From 300ecc2ed25bf43347df80f2f59e2dfb39e92715 Mon Sep 17 00:00:00 2001 From: Jan-Christoph Borchardt Date: Thu, 31 Jan 2013 12:59:30 +0100 Subject: [PATCH 325/347] change button box-shadow from hard white to slight transparent --- core/css/styles.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/css/styles.css b/core/css/styles.css index b949c71b0a..ff09e4d0c0 100644 --- a/core/css/styles.css +++ b/core/css/styles.css @@ -56,8 +56,8 @@ input[type="checkbox"]:hover+label, input[type="checkbox"]:focus+label { color:# /* BUTTONS */ input[type="submit"], input[type="button"], button, .button, #quota, div.jp-progress, select, .pager li a { width:auto; padding:.4em; - background-color:rgba(240,240,240,.9); font-weight:bold; color:#555; text-shadow:#fff 0 1px 0; border:1px solid rgba(190,190,190,.9); cursor:pointer; - -moz-box-shadow:0 1px 1px #fff, 0 1px 1px #fff inset; -webkit-box-shadow:0 1px 1px #fff, 0 1px 1px #fff inset; box-shadow:0 1px 1px #fff, 0 1px 1px #fff inset; + background-color:rgba(240,240,240,.9); font-weight:bold; color:#555; text-shadow:rgba(255,255,255,.9) 0 1px 0; border:1px solid rgba(190,190,190,.9); cursor:pointer; + -moz-box-shadow:0 1px 1px rgba(255,255,255,.9), 0 1px 1px rgba(255,255,255,.9) inset; -webkit-box-shadow:0 1px 1px rgba(255,255,255,.9), 0 1px 1px rgba(255,255,255,.9) inset; box-shadow:0 1px 1px rgba(255,255,255,.9), 0 1px 1px rgba(255,255,255,.9) inset; -moz-border-radius:.5em; -webkit-border-radius:.5em; border-radius:.5em; } input[type="submit"]:hover, input[type="submit"]:focus, input[type="button"]:hover, select:hover, select:focus, select:active, input[type="button"]:focus, .button:hover { From 85a12970c7a593a99016353fd66bd5270b013498 Mon Sep 17 00:00:00 2001 From: Thomas Mueller Date: Thu, 31 Jan 2013 14:11:31 +0100 Subject: [PATCH 326/347] update on translation string --- settings/js/apps.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings/js/apps.js b/settings/js/apps.js index 5a52a69774..68a3fa54de 100644 --- a/settings/js/apps.js +++ b/settings/js/apps.js @@ -27,7 +27,7 @@ OC.Settings.Apps = OC.Settings.Apps || { if (app.update != false) { page.find('input.update').show(); page.find('input.update').data('appid', app.id); - page.find('input.update').attr('value',t('settings', 'Update to ')+app.update); + page.find('input.update').attr('value',t('settings', 'Update to {appversion}', {appversion:app.update})); } else { page.find('input.update').hide(); } From dff5148f6dec899f095cefb3751a7d1f0cc361fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Thu, 31 Jan 2013 14:48:57 +0100 Subject: [PATCH 327/347] debug output removed --- apps/files_trashbin/download.php | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/files_trashbin/download.php b/apps/files_trashbin/download.php index a987dd4fd1..665697dca5 100644 --- a/apps/files_trashbin/download.php +++ b/apps/files_trashbin/download.php @@ -29,7 +29,6 @@ $filename = $_GET["file"]; $view = new OC_FilesystemView('/'.\OCP\User::getUser().'/files_trashbin'); if(!$view->file_exists($filename)) { - error_log("file does not exist... " . $view->getInternalPath($filename)); header("HTTP/1.0 404 Not Found"); $tmpl = new OCP\Template( '', '404', 'guest' ); $tmpl->assign('file', $filename); From c8a4878b7771f92361cf1c07aa32faef31cfece2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Thu, 31 Jan 2013 14:55:14 +0100 Subject: [PATCH 328/347] is_writable() is now isUpdatable() with the new filesystem --- apps/files_trashbin/lib/trash.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_trashbin/lib/trash.php b/apps/files_trashbin/lib/trash.php index 6aa0bdffb9..a7eff3d44e 100644 --- a/apps/files_trashbin/lib/trash.php +++ b/apps/files_trashbin/lib/trash.php @@ -102,7 +102,7 @@ class Trashbin { $location = $result[0]['location']; if ( $result[0]['location'] != '/' && (!$view->is_dir('files'.$result[0]['location']) || - !$view->is_writable('files'.$result[0]['location'])) ) { + !$view->isUpdatable('files'.$result[0]['location'])) ) { $location = ''; } } else { From 54d46fe43c321706a10444aa55fc493882a8255c Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 31 Jan 2013 15:00:48 +0100 Subject: [PATCH 329/347] remove outdated line --- apps/files_external/lib/webdav.php | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/files_external/lib/webdav.php b/apps/files_external/lib/webdav.php index 571b4d79ae..2a953ac63f 100644 --- a/apps/files_external/lib/webdav.php +++ b/apps/files_external/lib/webdav.php @@ -105,7 +105,6 @@ class DAV extends \OC\Files\Storage\Common{ $response=$this->client->propfind($path, array(), 1); $id=md5('webdav'.$this->root.$path); $content = array(); - \OC_FakeDirStream::$dirs[$id]=array(); $files=array_keys($response); array_shift($files);//the first entry is the current directory foreach ($files as $file) { From f0ca8eeba419391b1a4145cc0d24f47c83cc921b Mon Sep 17 00:00:00 2001 From: Jan-Christoph Borchardt Date: Thu, 31 Jan 2013 15:21:50 +0100 Subject: [PATCH 330/347] no box-shadow for public share download button --- core/css/styles.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/css/styles.css b/core/css/styles.css index ff09e4d0c0..d82bdd2db4 100644 --- a/core/css/styles.css +++ b/core/css/styles.css @@ -64,7 +64,7 @@ input[type="submit"]:hover, input[type="submit"]:focus, input[type="button"]:hov background:rgba(250,250,250,.9); color:#333; } input[type="submit"] img, input[type="button"] img, button img, .button img { cursor:pointer; } -#header .button { border:none; } +#header .button { border:none; -moz-box-shadow:none; -webkit-box-shadow:none; box-shadow:none; } /* Primary action button, use sparingly */ .primary, input[type="submit"].primary, input[type="button"].primary, button.primary, .button.primary { From e22a8866fbf636b57bd8fae97f73c51a8e66504c Mon Sep 17 00:00:00 2001 From: Thomas Mueller Date: Thu, 31 Jan 2013 16:16:28 +0100 Subject: [PATCH 331/347] some web servers by default don't recognize index.php as default page - IIS for example In order to allow easy installation and configuration this index.html has been added with a redirect to index.php --- index.html | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 index.html diff --git a/index.html b/index.html new file mode 100644 index 0000000000..69d42e3a0b --- /dev/null +++ b/index.html @@ -0,0 +1,6 @@ + + + + + + From 4162ba4d41743adec0790ec402895343c56043e7 Mon Sep 17 00:00:00 2001 From: Thomas Mueller Date: Thu, 31 Jan 2013 16:48:41 +0100 Subject: [PATCH 332/347] adding l10n support to files_trashbin --- apps/files_trashbin/l10n/.gitkeep | 0 l10n/.tx/config | 6 ++++++ 2 files changed, 6 insertions(+) create mode 100644 apps/files_trashbin/l10n/.gitkeep diff --git a/apps/files_trashbin/l10n/.gitkeep b/apps/files_trashbin/l10n/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/l10n/.tx/config b/l10n/.tx/config index 2aac0feedc..b6589d8112 100644 --- a/l10n/.tx/config +++ b/l10n/.tx/config @@ -40,6 +40,12 @@ source_file = templates/files_sharing.pot source_lang = en type = PO +[owncloud.files_trashbin] +file_filter = /files_trashbin.po +source_file = templates/files_trashbin.pot +source_lang = en +type = PO + [owncloud.files_versions] file_filter = /files_versions.po source_file = templates/files_versions.pot From 9cd692a6d00623940a4dbf04045793e44d602569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Schie=C3=9Fle?= Date: Thu, 31 Jan 2013 17:00:05 +0100 Subject: [PATCH 333/347] use the same tooltip as for the password field --- core/js/js.js | 1 + 1 file changed, 1 insertion(+) diff --git a/core/js/js.js b/core/js/js.js index 01e47edf26..9c8cf4aa62 100644 --- a/core/js/js.js +++ b/core/js/js.js @@ -672,6 +672,7 @@ $(document).ready(function(){ // all the tipsy stuff needs to be here (in reverse order) to work $('.jp-controls .jp-previous').tipsy({gravity:'nw', fade:true, live:true}); $('.jp-controls .jp-next').tipsy({gravity:'n', fade:true, live:true}); + $('.displayName .action').tipsy({gravity:'se', fade:true, live:true}); $('.password .action').tipsy({gravity:'se', fade:true, live:true}); $('#upload').tipsy({gravity:'w', fade:true}); $('.selectedActions a').tipsy({gravity:'s', fade:true, live:true}); From 209d599ec5b00c5b92a33e902867fc621e725c93 Mon Sep 17 00:00:00 2001 From: Jenkins for ownCloud Date: Thu, 31 Jan 2013 17:05:21 +0100 Subject: [PATCH 334/347] [tx-robot] updated from transifex --- apps/files/l10n/bn_BD.php | 3 +- apps/files/l10n/ca.php | 6 +- apps/files/l10n/cs_CZ.php | 6 +- apps/files/l10n/da.php | 2 - apps/files/l10n/de.php | 3 +- apps/files/l10n/de_DE.php | 3 +- apps/files/l10n/el.php | 3 +- apps/files/l10n/eo.php | 3 +- apps/files/l10n/es.php | 3 +- apps/files/l10n/es_AR.php | 3 +- apps/files/l10n/et_EE.php | 2 - apps/files/l10n/eu.php | 3 +- apps/files/l10n/fa.php | 3 +- apps/files/l10n/fi_FI.php | 1 + apps/files/l10n/fr.php | 3 +- apps/files/l10n/gl.php | 3 +- apps/files/l10n/he.php | 2 - apps/files/l10n/hu_HU.php | 3 +- apps/files/l10n/is.php | 3 +- apps/files/l10n/it.php | 6 +- apps/files/l10n/ja_JP.php | 3 +- apps/files/l10n/ka_GE.php | 2 - apps/files/l10n/ko.php | 13 ++-- apps/files/l10n/lt_LT.php | 2 - apps/files/l10n/mk.php | 2 - apps/files/l10n/nb_NO.php | 1 - apps/files/l10n/nl.php | 3 +- apps/files/l10n/pl.php | 3 +- apps/files/l10n/pt_BR.php | 2 - apps/files/l10n/pt_PT.php | 6 +- apps/files/l10n/ro.php | 3 +- apps/files/l10n/ru.php | 3 +- apps/files/l10n/ru_RU.php | 10 ++- apps/files/l10n/sk_SK.php | 3 +- apps/files/l10n/sl.php | 2 - apps/files/l10n/sr.php | 2 - apps/files/l10n/sv.php | 6 +- apps/files/l10n/ta_LK.php | 2 - apps/files/l10n/th_TH.php | 3 +- apps/files/l10n/tr.php | 3 +- apps/files/l10n/uk.php | 2 - apps/files/l10n/vi.php | 2 - apps/files/l10n/zh_CN.GB2312.php | 2 - apps/files/l10n/zh_CN.php | 3 +- apps/files/l10n/zh_TW.php | 3 +- apps/files_encryption/l10n/ko.php | 11 ++++ apps/files_encryption/l10n/ru_RU.php | 9 +++ apps/files_external/l10n/ko.php | 4 +- apps/user_ldap/l10n/ko.php | 6 +- apps/user_webdavauth/l10n/ko.php | 4 +- core/l10n/it.php | 4 +- core/l10n/ko.php | 13 ++-- l10n/ar/core.po | 4 +- l10n/ar/files.po | 74 +++++++++++----------- l10n/ar/files_trashbin.po | 58 ++++++++++++++++++ l10n/bg_BG/core.po | 4 +- l10n/bg_BG/files.po | 74 +++++++++++----------- l10n/bg_BG/files_trashbin.po | 58 ++++++++++++++++++ l10n/bn_BD/core.po | 4 +- l10n/bn_BD/files.po | 78 ++++++++++++------------ l10n/bn_BD/files_trashbin.po | 58 ++++++++++++++++++ l10n/ca/core.po | 4 +- l10n/ca/files.po | 80 ++++++++++++------------ l10n/ca/files_trashbin.po | 58 ++++++++++++++++++ l10n/ca/settings.po | 10 +-- l10n/cs_CZ/core.po | 4 +- l10n/cs_CZ/files.po | 80 ++++++++++++------------ l10n/cs_CZ/files_trashbin.po | 58 ++++++++++++++++++ l10n/cs_CZ/settings.po | 10 +-- l10n/da/core.po | 4 +- l10n/da/files.po | 76 +++++++++++------------ l10n/da/files_trashbin.po | 58 ++++++++++++++++++ l10n/de/core.po | 4 +- l10n/de/files.po | 78 ++++++++++++------------ l10n/de/files_trashbin.po | 58 ++++++++++++++++++ l10n/de_DE/core.po | 4 +- l10n/de_DE/files.po | 78 ++++++++++++------------ l10n/de_DE/files_trashbin.po | 58 ++++++++++++++++++ l10n/el/core.po | 4 +- l10n/el/files.po | 78 ++++++++++++------------ l10n/el/files_trashbin.po | 58 ++++++++++++++++++ l10n/eo/core.po | 4 +- l10n/eo/files.po | 78 ++++++++++++------------ l10n/eo/files_trashbin.po | 58 ++++++++++++++++++ l10n/es/core.po | 4 +- l10n/es/files.po | 78 ++++++++++++------------ l10n/es/files_trashbin.po | 58 ++++++++++++++++++ l10n/es_AR/core.po | 4 +- l10n/es_AR/files.po | 78 ++++++++++++------------ l10n/es_AR/files_trashbin.po | 58 ++++++++++++++++++ l10n/et_EE/core.po | 4 +- l10n/et_EE/files.po | 76 +++++++++++------------ l10n/et_EE/files_trashbin.po | 58 ++++++++++++++++++ l10n/eu/core.po | 4 +- l10n/eu/files.po | 78 ++++++++++++------------ l10n/eu/files_trashbin.po | 58 ++++++++++++++++++ l10n/fa/core.po | 4 +- l10n/fa/files.po | 78 ++++++++++++------------ l10n/fa/files_trashbin.po | 58 ++++++++++++++++++ l10n/fi_FI/core.po | 4 +- l10n/fi_FI/files.po | 76 +++++++++++------------ l10n/fi_FI/files_trashbin.po | 58 ++++++++++++++++++ l10n/fr/core.po | 4 +- l10n/fr/files.po | 78 ++++++++++++------------ l10n/fr/files_trashbin.po | 58 ++++++++++++++++++ l10n/gl/core.po | 4 +- l10n/gl/files.po | 78 ++++++++++++------------ l10n/gl/files_trashbin.po | 58 ++++++++++++++++++ l10n/he/core.po | 4 +- l10n/he/files.po | 76 +++++++++++------------ l10n/he/files_trashbin.po | 58 ++++++++++++++++++ l10n/hi/files.po | 74 +++++++++++----------- l10n/hi/files_trashbin.po | 58 ++++++++++++++++++ l10n/hr/core.po | 4 +- l10n/hr/files.po | 74 +++++++++++----------- l10n/hr/files_trashbin.po | 58 ++++++++++++++++++ l10n/hu_HU/core.po | 4 +- l10n/hu_HU/files.po | 78 ++++++++++++------------ l10n/hu_HU/files_trashbin.po | 58 ++++++++++++++++++ l10n/ia/core.po | 4 +- l10n/ia/files.po | 74 +++++++++++----------- l10n/ia/files_trashbin.po | 58 ++++++++++++++++++ l10n/id/core.po | 4 +- l10n/id/files.po | 74 +++++++++++----------- l10n/id/files_trashbin.po | 58 ++++++++++++++++++ l10n/is/core.po | 4 +- l10n/is/files.po | 78 ++++++++++++------------ l10n/is/files_trashbin.po | 58 ++++++++++++++++++ l10n/it/core.po | 11 ++-- l10n/it/files.po | 80 ++++++++++++------------ l10n/it/files_trashbin.po | 58 ++++++++++++++++++ l10n/it/settings.po | 10 +-- l10n/ja_JP/core.po | 4 +- l10n/ja_JP/files.po | 78 ++++++++++++------------ l10n/ja_JP/files_trashbin.po | 58 ++++++++++++++++++ l10n/ka_GE/core.po | 4 +- l10n/ka_GE/files.po | 76 +++++++++++------------ l10n/ka_GE/files_trashbin.po | 58 ++++++++++++++++++ l10n/ko/core.po | 23 +++---- l10n/ko/files.po | 91 ++++++++++++++-------------- l10n/ko/files_encryption.po | 30 ++++----- l10n/ko/files_external.po | 21 ++++--- l10n/ko/files_trashbin.po | 58 ++++++++++++++++++ l10n/ko/lib.po | 19 +++--- l10n/ko/settings.po | 30 ++++----- l10n/ko/user_ldap.po | 18 +++--- l10n/ko/user_webdavauth.po | 11 ++-- l10n/ku_IQ/files.po | 74 +++++++++++----------- l10n/ku_IQ/files_trashbin.po | 58 ++++++++++++++++++ l10n/lb/core.po | 4 +- l10n/lb/files.po | 74 +++++++++++----------- l10n/lb/files_trashbin.po | 58 ++++++++++++++++++ l10n/lt_LT/core.po | 4 +- l10n/lt_LT/files.po | 76 +++++++++++------------ l10n/lt_LT/files_trashbin.po | 58 ++++++++++++++++++ l10n/lv/core.po | 4 +- l10n/lv/files.po | 74 +++++++++++----------- l10n/lv/files_trashbin.po | 58 ++++++++++++++++++ l10n/mk/core.po | 4 +- l10n/mk/files.po | 76 +++++++++++------------ l10n/mk/files_trashbin.po | 58 ++++++++++++++++++ l10n/ms_MY/core.po | 4 +- l10n/ms_MY/files.po | 74 +++++++++++----------- l10n/ms_MY/files_trashbin.po | 58 ++++++++++++++++++ l10n/nb_NO/core.po | 4 +- l10n/nb_NO/files.po | 74 +++++++++++----------- l10n/nb_NO/files_trashbin.po | 58 ++++++++++++++++++ l10n/nl/core.po | 4 +- l10n/nl/files.po | 78 ++++++++++++------------ l10n/nl/files_trashbin.po | 58 ++++++++++++++++++ l10n/nn_NO/files.po | 74 +++++++++++----------- l10n/nn_NO/files_trashbin.po | 58 ++++++++++++++++++ l10n/oc/core.po | 4 +- l10n/oc/files.po | 74 +++++++++++----------- l10n/oc/files_trashbin.po | 58 ++++++++++++++++++ l10n/pl/core.po | 4 +- l10n/pl/files.po | 78 ++++++++++++------------ l10n/pl/files_trashbin.po | 58 ++++++++++++++++++ l10n/pl_PL/files.po | 74 +++++++++++----------- l10n/pl_PL/files_trashbin.po | 58 ++++++++++++++++++ l10n/pt_BR/core.po | 4 +- l10n/pt_BR/files.po | 76 +++++++++++------------ l10n/pt_BR/files_trashbin.po | 58 ++++++++++++++++++ l10n/pt_PT/core.po | 4 +- l10n/pt_PT/files.po | 81 +++++++++++++------------ l10n/pt_PT/files_trashbin.po | 58 ++++++++++++++++++ l10n/pt_PT/settings.po | 11 ++-- l10n/ro/core.po | 4 +- l10n/ro/files.po | 78 ++++++++++++------------ l10n/ro/files_trashbin.po | 58 ++++++++++++++++++ l10n/ru/core.po | 4 +- l10n/ru/files.po | 78 ++++++++++++------------ l10n/ru/files_trashbin.po | 58 ++++++++++++++++++ l10n/ru_RU/core.po | 4 +- l10n/ru_RU/files.po | 89 +++++++++++++-------------- l10n/ru_RU/files_encryption.po | 25 ++++---- l10n/ru_RU/files_trashbin.po | 58 ++++++++++++++++++ l10n/ru_RU/settings.po | 8 +-- l10n/si_LK/core.po | 4 +- l10n/si_LK/files.po | 74 +++++++++++----------- l10n/si_LK/files_trashbin.po | 58 ++++++++++++++++++ l10n/sk_SK/core.po | 4 +- l10n/sk_SK/files.po | 78 ++++++++++++------------ l10n/sk_SK/files_trashbin.po | 58 ++++++++++++++++++ l10n/sl/core.po | 4 +- l10n/sl/files.po | 76 +++++++++++------------ l10n/sl/files_trashbin.po | 58 ++++++++++++++++++ l10n/sr/core.po | 4 +- l10n/sr/files.po | 76 +++++++++++------------ l10n/sr/files_trashbin.po | 58 ++++++++++++++++++ l10n/sr@latin/files.po | 74 +++++++++++----------- l10n/sr@latin/files_trashbin.po | 58 ++++++++++++++++++ l10n/sv/core.po | 4 +- l10n/sv/files.po | 80 ++++++++++++------------ l10n/sv/files_trashbin.po | 58 ++++++++++++++++++ l10n/sv/settings.po | 10 +-- l10n/ta_LK/core.po | 4 +- l10n/ta_LK/files.po | 76 +++++++++++------------ l10n/ta_LK/files_trashbin.po | 58 ++++++++++++++++++ l10n/templates/core.pot | 2 +- l10n/templates/files.pot | 72 +++++++++++----------- l10n/templates/files_encryption.pot | 2 +- l10n/templates/files_external.pot | 2 +- l10n/templates/files_sharing.pot | 2 +- l10n/templates/files_trashbin.pot | 58 ++++++++++++++++++ l10n/templates/files_versions.pot | 2 +- l10n/templates/lib.pot | 2 +- l10n/templates/settings.pot | 2 +- l10n/templates/user_ldap.pot | 2 +- l10n/templates/user_webdavauth.pot | 2 +- l10n/th_TH/core.po | 4 +- l10n/th_TH/files.po | 78 ++++++++++++------------ l10n/th_TH/files_trashbin.po | 58 ++++++++++++++++++ l10n/tr/core.po | 4 +- l10n/tr/files.po | 78 ++++++++++++------------ l10n/tr/files_trashbin.po | 58 ++++++++++++++++++ l10n/uk/core.po | 4 +- l10n/uk/files.po | 76 +++++++++++------------ l10n/uk/files_trashbin.po | 58 ++++++++++++++++++ l10n/vi/core.po | 4 +- l10n/vi/files.po | 76 +++++++++++------------ l10n/vi/files_trashbin.po | 58 ++++++++++++++++++ l10n/zh_CN.GB2312/core.po | 4 +- l10n/zh_CN.GB2312/files.po | 76 +++++++++++------------ l10n/zh_CN.GB2312/files_trashbin.po | 58 ++++++++++++++++++ l10n/zh_CN/core.po | 4 +- l10n/zh_CN/files.po | 78 ++++++++++++------------ l10n/zh_CN/files_trashbin.po | 58 ++++++++++++++++++ l10n/zh_HK/files.po | 74 +++++++++++----------- l10n/zh_HK/files_trashbin.po | 58 ++++++++++++++++++ l10n/zh_TW/core.po | 4 +- l10n/zh_TW/files.po | 78 ++++++++++++------------ l10n/zh_TW/files_trashbin.po | 58 ++++++++++++++++++ lib/l10n/ko.php | 1 + settings/l10n/ca.php | 2 + settings/l10n/cs_CZ.php | 2 + settings/l10n/it.php | 2 + settings/l10n/ko.php | 18 +++--- settings/l10n/pt_PT.php | 2 + settings/l10n/ru_RU.php | 1 + settings/l10n/sv.php | 2 + 261 files changed, 6341 insertions(+), 2732 deletions(-) create mode 100644 l10n/ar/files_trashbin.po create mode 100644 l10n/bg_BG/files_trashbin.po create mode 100644 l10n/bn_BD/files_trashbin.po create mode 100644 l10n/ca/files_trashbin.po create mode 100644 l10n/cs_CZ/files_trashbin.po create mode 100644 l10n/da/files_trashbin.po create mode 100644 l10n/de/files_trashbin.po create mode 100644 l10n/de_DE/files_trashbin.po create mode 100644 l10n/el/files_trashbin.po create mode 100644 l10n/eo/files_trashbin.po create mode 100644 l10n/es/files_trashbin.po create mode 100644 l10n/es_AR/files_trashbin.po create mode 100644 l10n/et_EE/files_trashbin.po create mode 100644 l10n/eu/files_trashbin.po create mode 100644 l10n/fa/files_trashbin.po create mode 100644 l10n/fi_FI/files_trashbin.po create mode 100644 l10n/fr/files_trashbin.po create mode 100644 l10n/gl/files_trashbin.po create mode 100644 l10n/he/files_trashbin.po create mode 100644 l10n/hi/files_trashbin.po create mode 100644 l10n/hr/files_trashbin.po create mode 100644 l10n/hu_HU/files_trashbin.po create mode 100644 l10n/ia/files_trashbin.po create mode 100644 l10n/id/files_trashbin.po create mode 100644 l10n/is/files_trashbin.po create mode 100644 l10n/it/files_trashbin.po create mode 100644 l10n/ja_JP/files_trashbin.po create mode 100644 l10n/ka_GE/files_trashbin.po create mode 100644 l10n/ko/files_trashbin.po create mode 100644 l10n/ku_IQ/files_trashbin.po create mode 100644 l10n/lb/files_trashbin.po create mode 100644 l10n/lt_LT/files_trashbin.po create mode 100644 l10n/lv/files_trashbin.po create mode 100644 l10n/mk/files_trashbin.po create mode 100644 l10n/ms_MY/files_trashbin.po create mode 100644 l10n/nb_NO/files_trashbin.po create mode 100644 l10n/nl/files_trashbin.po create mode 100644 l10n/nn_NO/files_trashbin.po create mode 100644 l10n/oc/files_trashbin.po create mode 100644 l10n/pl/files_trashbin.po create mode 100644 l10n/pl_PL/files_trashbin.po create mode 100644 l10n/pt_BR/files_trashbin.po create mode 100644 l10n/pt_PT/files_trashbin.po create mode 100644 l10n/ro/files_trashbin.po create mode 100644 l10n/ru/files_trashbin.po create mode 100644 l10n/ru_RU/files_trashbin.po create mode 100644 l10n/si_LK/files_trashbin.po create mode 100644 l10n/sk_SK/files_trashbin.po create mode 100644 l10n/sl/files_trashbin.po create mode 100644 l10n/sr/files_trashbin.po create mode 100644 l10n/sr@latin/files_trashbin.po create mode 100644 l10n/sv/files_trashbin.po create mode 100644 l10n/ta_LK/files_trashbin.po create mode 100644 l10n/templates/files_trashbin.pot create mode 100644 l10n/th_TH/files_trashbin.po create mode 100644 l10n/tr/files_trashbin.po create mode 100644 l10n/uk/files_trashbin.po create mode 100644 l10n/vi/files_trashbin.po create mode 100644 l10n/zh_CN.GB2312/files_trashbin.po create mode 100644 l10n/zh_CN/files_trashbin.po create mode 100644 l10n/zh_HK/files_trashbin.po create mode 100644 l10n/zh_TW/files_trashbin.po diff --git a/apps/files/l10n/bn_BD.php b/apps/files/l10n/bn_BD.php index 986d92f85f..3d676810c7 100644 --- a/apps/files/l10n/bn_BD.php +++ b/apps/files/l10n/bn_BD.php @@ -7,6 +7,7 @@ "No file was uploaded" => "কোন ফাইল আপলোড করা হয় নি", "Missing a temporary folder" => "অস্থায়ী ফোল্ডার খোয়া গিয়েছে", "Failed to write to disk" => "ডিস্কে লিখতে ব্যর্থ", +"Not enough space available" => "যথেষ্ঠ পরিমাণ স্থান নেই", "Invalid directory." => "ভুল ডিরেক্টরি", "Files" => "ফাইল", "Unshare" => "ভাগাভাগি বাতিল ", @@ -19,8 +20,6 @@ "replaced {new_name}" => "{new_name} প্রতিস্থাপন করা হয়েছে", "undo" => "ক্রিয়া প্রত্যাহার", "replaced {new_name} with {old_name}" => "{new_name} কে {old_name} নামে প্রতিস্থাপন করা হয়েছে", -"unshared {files}" => "{files} ভাগাভাগি বাতিল কর", -"deleted {files}" => "{files} মুছে ফেলা হয়েছে", "'.' is an invalid file name." => "টি একটি অননুমোদিত নাম।", "File name cannot be empty." => "ফাইলের নামটি ফাঁকা রাখা যাবে না।", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "নামটি সঠিক নয়, '\\', '/', '<', '>', ':', '\"', '|', '?' এবং '*' অনুমোদিত নয়।", diff --git a/apps/files/l10n/ca.php b/apps/files/l10n/ca.php index 5c8d5626d1..eb98278bfb 100644 --- a/apps/files/l10n/ca.php +++ b/apps/files/l10n/ca.php @@ -7,6 +7,7 @@ "No file was uploaded" => "El fitxer no s'ha pujat", "Missing a temporary folder" => "S'ha perdut un fitxer temporal", "Failed to write to disk" => "Ha fallat en escriure al disc", +"Not enough space available" => "No hi ha prou espai disponible", "Invalid directory." => "Directori no vàlid.", "Files" => "Fitxers", "Unshare" => "Deixa de compartir", @@ -19,8 +20,6 @@ "replaced {new_name}" => "s'ha substituït {new_name}", "undo" => "desfés", "replaced {new_name} with {old_name}" => "s'ha substituït {old_name} per {new_name}", -"unshared {files}" => "no compartits {files}", -"deleted {files}" => "eliminats {files}", "'.' is an invalid file name." => "'.' és un nom no vàlid per un fitxer.", "File name cannot be empty." => "El nom del fitxer no pot ser buit.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "El nóm no és vàlid, '\\', '/', '<', '>', ':', '\"', '|', '?' i '*' no estan permesos.", @@ -63,5 +62,6 @@ "Upload too large" => "La pujada és massa gran", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Els fitxers que esteu intentant pujar excedeixen la mida màxima de pujada del servidor", "Files are being scanned, please wait." => "S'estan escanejant els fitxers, espereu", -"Current scanning" => "Actualment escanejant" +"Current scanning" => "Actualment escanejant", +"Upgrading filesystem cache..." => "Actualitzant la memòria de cau del sistema de fitxers..." ); diff --git a/apps/files/l10n/cs_CZ.php b/apps/files/l10n/cs_CZ.php index b231e70809..76b3b82d72 100644 --- a/apps/files/l10n/cs_CZ.php +++ b/apps/files/l10n/cs_CZ.php @@ -7,6 +7,7 @@ "No file was uploaded" => "Žádný soubor nebyl odeslán", "Missing a temporary folder" => "Chybí adresář pro dočasné soubory", "Failed to write to disk" => "Zápis na disk selhal", +"Not enough space available" => "Nedostatek dostupného místa", "Invalid directory." => "Neplatný adresář", "Files" => "Soubory", "Unshare" => "Zrušit sdílení", @@ -19,8 +20,6 @@ "replaced {new_name}" => "nahrazeno {new_name}", "undo" => "zpět", "replaced {new_name} with {old_name}" => "nahrazeno {new_name} s {old_name}", -"unshared {files}" => "sdílení zrušeno pro {files}", -"deleted {files}" => "smazáno {files}", "'.' is an invalid file name." => "'.' je neplatným názvem souboru.", "File name cannot be empty." => "Název souboru nemůže být prázdný řetězec.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Neplatný název, znaky '\\', '/', '<', '>', ':', '\"', '|', '?' a '*' nejsou povoleny.", @@ -63,5 +62,6 @@ "Upload too large" => "Odeslaný soubor je příliš velký", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Soubory, které se snažíte odeslat, překračují limit velikosti odesílání na tomto serveru.", "Files are being scanned, please wait." => "Soubory se prohledávají, prosím čekejte.", -"Current scanning" => "Aktuální prohledávání" +"Current scanning" => "Aktuální prohledávání", +"Upgrading filesystem cache..." => "Aktualizuji mezipaměť souborového systému..." ); diff --git a/apps/files/l10n/da.php b/apps/files/l10n/da.php index 051bb40a8e..71a5a56de5 100644 --- a/apps/files/l10n/da.php +++ b/apps/files/l10n/da.php @@ -19,8 +19,6 @@ "replaced {new_name}" => "erstattede {new_name}", "undo" => "fortryd", "replaced {new_name} with {old_name}" => "erstattede {new_name} med {old_name}", -"unshared {files}" => "ikke delte {files}", -"deleted {files}" => "slettede {files}", "'.' is an invalid file name." => "'.' er et ugyldigt filnavn.", "File name cannot be empty." => "Filnavnet kan ikke stå tomt.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Ugyldigt navn, '\\', '/', '<', '>', ':' | '?', '\"', '', og '*' er ikke tilladt.", diff --git a/apps/files/l10n/de.php b/apps/files/l10n/de.php index 072d155ab1..d42410fee3 100644 --- a/apps/files/l10n/de.php +++ b/apps/files/l10n/de.php @@ -7,6 +7,7 @@ "No file was uploaded" => "Es wurde keine Datei hochgeladen.", "Missing a temporary folder" => "Temporärer Ordner fehlt.", "Failed to write to disk" => "Fehler beim Schreiben auf die Festplatte", +"Not enough space available" => "Nicht genug Speicherplatz verfügbar", "Invalid directory." => "Ungültiges Verzeichnis", "Files" => "Dateien", "Unshare" => "Nicht mehr freigeben", @@ -19,8 +20,6 @@ "replaced {new_name}" => "{new_name} wurde ersetzt", "undo" => "rückgängig machen", "replaced {new_name} with {old_name}" => "{old_name} ersetzt durch {new_name}", -"unshared {files}" => "Freigabe von {files} aufgehoben", -"deleted {files}" => "{files} gelöscht", "'.' is an invalid file name." => "'.' ist kein gültiger Dateiname", "File name cannot be empty." => "Der Dateiname darf nicht leer sein", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Ungültiger Name, '\\', '/', '<', '>', ':', '\"', '|', '?' und '*' sind nicht zulässig.", diff --git a/apps/files/l10n/de_DE.php b/apps/files/l10n/de_DE.php index f7275c6e58..0a67cd0fc5 100644 --- a/apps/files/l10n/de_DE.php +++ b/apps/files/l10n/de_DE.php @@ -7,6 +7,7 @@ "No file was uploaded" => "Es wurde keine Datei hochgeladen.", "Missing a temporary folder" => "Der temporäre Ordner fehlt.", "Failed to write to disk" => "Fehler beim Schreiben auf die Festplatte", +"Not enough space available" => "Nicht genügend Speicherplatz verfügbar", "Invalid directory." => "Ungültiges Verzeichnis.", "Files" => "Dateien", "Unshare" => "Nicht mehr freigeben", @@ -19,8 +20,6 @@ "replaced {new_name}" => "{new_name} wurde ersetzt", "undo" => "rückgängig machen", "replaced {new_name} with {old_name}" => "{old_name} wurde ersetzt durch {new_name}", -"unshared {files}" => "Freigabe für {files} beendet", -"deleted {files}" => "{files} gelöscht", "'.' is an invalid file name." => "'.' ist kein gültiger Dateiname.", "File name cannot be empty." => "Der Dateiname darf nicht leer sein.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Ungültiger Name, '\\', '/', '<', '>', ':', '\"', '|', '?' und '*' sind nicht zulässig.", diff --git a/apps/files/l10n/el.php b/apps/files/l10n/el.php index b8bb487203..7b458bf35d 100644 --- a/apps/files/l10n/el.php +++ b/apps/files/l10n/el.php @@ -7,6 +7,7 @@ "No file was uploaded" => "Κανένα αρχείο δεν στάλθηκε", "Missing a temporary folder" => "Λείπει ο προσωρινός φάκελος", "Failed to write to disk" => "Αποτυχία εγγραφής στο δίσκο", +"Not enough space available" => "Δεν υπάρχει αρκετός διαθέσιμος χώρος", "Invalid directory." => "Μη έγκυρος φάκελος.", "Files" => "Αρχεία", "Unshare" => "Διακοπή κοινής χρήσης", @@ -19,8 +20,6 @@ "replaced {new_name}" => "{new_name} αντικαταστάθηκε", "undo" => "αναίρεση", "replaced {new_name} with {old_name}" => "αντικαταστάθηκε το {new_name} με {old_name}", -"unshared {files}" => "μη διαμοιρασμένα {files}", -"deleted {files}" => "διαγραμμένα {files}", "'.' is an invalid file name." => "'.' είναι μη έγκυρο όνομα αρχείου.", "File name cannot be empty." => "Το όνομα αρχείου δεν πρέπει να είναι κενό.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Μη έγκυρο όνομα, '\\', '/', '<', '>', ':', '\"', '|', '?' και '*' δεν επιτρέπονται.", diff --git a/apps/files/l10n/eo.php b/apps/files/l10n/eo.php index f885bef5cd..a510d47ad6 100644 --- a/apps/files/l10n/eo.php +++ b/apps/files/l10n/eo.php @@ -7,6 +7,7 @@ "No file was uploaded" => "Neniu dosiero estas alŝutita", "Missing a temporary folder" => "Mankas tempa dosierujo", "Failed to write to disk" => "Malsukcesis skribo al disko", +"Not enough space available" => "Ne haveblas sufiĉa spaco", "Invalid directory." => "Nevalida dosierujo.", "Files" => "Dosieroj", "Unshare" => "Malkunhavigi", @@ -19,8 +20,6 @@ "replaced {new_name}" => "anstataŭiĝis {new_name}", "undo" => "malfari", "replaced {new_name} with {old_name}" => "anstataŭiĝis {new_name} per {old_name}", -"unshared {files}" => "malkunhaviĝis {files}", -"deleted {files}" => "foriĝis {files}", "'.' is an invalid file name." => "'.' ne estas valida dosiernomo.", "File name cannot be empty." => "Dosiernomo devas ne malpleni.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nevalida nomo: “\\”, “/”, “<”, “>”, “:”, “\"”, “|”, “?” kaj “*” ne permesatas.", diff --git a/apps/files/l10n/es.php b/apps/files/l10n/es.php index 260ecd42e4..bc5046767c 100644 --- a/apps/files/l10n/es.php +++ b/apps/files/l10n/es.php @@ -7,6 +7,7 @@ "No file was uploaded" => "No se ha subido ningún archivo", "Missing a temporary folder" => "Falta un directorio temporal", "Failed to write to disk" => "La escritura en disco ha fallado", +"Not enough space available" => "No hay suficiente espacio disponible", "Invalid directory." => "Directorio invalido.", "Files" => "Archivos", "Unshare" => "Dejar de compartir", @@ -19,8 +20,6 @@ "replaced {new_name}" => "reemplazado {new_name}", "undo" => "deshacer", "replaced {new_name} with {old_name}" => "reemplazado {new_name} con {old_name}", -"unshared {files}" => "{files} descompartidos", -"deleted {files}" => "{files} eliminados", "'.' is an invalid file name." => "'.' es un nombre de archivo inválido.", "File name cannot be empty." => "El nombre de archivo no puede estar vacío.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nombre Invalido, \"\\\", \"/\", \"<\", \">\", \":\", \"\", \"|\" \"?\" y \"*\" no están permitidos ", diff --git a/apps/files/l10n/es_AR.php b/apps/files/l10n/es_AR.php index 32219b4304..ea8352e325 100644 --- a/apps/files/l10n/es_AR.php +++ b/apps/files/l10n/es_AR.php @@ -7,6 +7,7 @@ "No file was uploaded" => "El archivo no fue subido", "Missing a temporary folder" => "Falta un directorio temporal", "Failed to write to disk" => "Error al escribir en el disco", +"Not enough space available" => "No hay suficiente espacio disponible", "Invalid directory." => "Directorio invalido.", "Files" => "Archivos", "Unshare" => "Dejar de compartir", @@ -19,8 +20,6 @@ "replaced {new_name}" => "reemplazado {new_name}", "undo" => "deshacer", "replaced {new_name} with {old_name}" => "reemplazado {new_name} con {old_name}", -"unshared {files}" => "{files} se dejaron de compartir", -"deleted {files}" => "{files} borrados", "'.' is an invalid file name." => "'.' es un nombre de archivo inválido.", "File name cannot be empty." => "El nombre del archivo no puede quedar vacío.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nombre invalido, '\\', '/', '<', '>', ':', '\"', '|', '?' y '*' no están permitidos.", diff --git a/apps/files/l10n/et_EE.php b/apps/files/l10n/et_EE.php index dd183ff935..54dd7cfdc5 100644 --- a/apps/files/l10n/et_EE.php +++ b/apps/files/l10n/et_EE.php @@ -17,8 +17,6 @@ "replaced {new_name}" => "asendatud nimega {new_name}", "undo" => "tagasi", "replaced {new_name} with {old_name}" => "asendas nime {old_name} nimega {new_name}", -"unshared {files}" => "jagamata {files}", -"deleted {files}" => "kustutatud {files}", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Vigane nimi, '\\', '/', '<', '>', ':', '\"', '|', '?' ja '*' pole lubatud.", "Unable to upload your file as it is a directory or has 0 bytes" => "Sinu faili üleslaadimine ebaõnnestus, kuna see on kaust või selle suurus on 0 baiti", "Upload Error" => "Üleslaadimise viga", diff --git a/apps/files/l10n/eu.php b/apps/files/l10n/eu.php index 4227c16543..6f4c55f484 100644 --- a/apps/files/l10n/eu.php +++ b/apps/files/l10n/eu.php @@ -7,6 +7,7 @@ "No file was uploaded" => "Ez da fitxategirik igo", "Missing a temporary folder" => "Aldi baterako karpeta falta da", "Failed to write to disk" => "Errore bat izan da diskoan idazterakoan", +"Not enough space available" => "Ez dago leku nahikorik.", "Invalid directory." => "Baliogabeko karpeta.", "Files" => "Fitxategiak", "Unshare" => "Ez elkarbanatu", @@ -19,8 +20,6 @@ "replaced {new_name}" => "ordezkatua {new_name}", "undo" => "desegin", "replaced {new_name} with {old_name}" => " {new_name}-k {old_name} ordezkatu du", -"unshared {files}" => "elkarbanaketa utzita {files}", -"deleted {files}" => "ezabatuta {files}", "'.' is an invalid file name." => "'.' ez da fitxategi izen baliogarria.", "File name cannot be empty." => "Fitxategi izena ezin da hutsa izan.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "IZen aliogabea, '\\', '/', '<', '>', ':', '\"', '|', '?' eta '*' ez daude baimenduta.", diff --git a/apps/files/l10n/fa.php b/apps/files/l10n/fa.php index 41eab2a60a..a4181c6ff5 100644 --- a/apps/files/l10n/fa.php +++ b/apps/files/l10n/fa.php @@ -7,6 +7,7 @@ "No file was uploaded" => "هیچ فایلی بارگذاری نشده", "Missing a temporary folder" => "یک پوشه موقت گم شده است", "Failed to write to disk" => "نوشتن بر روی دیسک سخت ناموفق بود", +"Not enough space available" => "فضای کافی در دسترس نیست", "Invalid directory." => "فهرست راهنما نامعتبر می باشد.", "Files" => "فایل ها", "Unshare" => "لغو اشتراک", @@ -19,8 +20,6 @@ "replaced {new_name}" => "{نام _جدید} جایگزین شد ", "undo" => "بازگشت", "replaced {new_name} with {old_name}" => "{نام_جدید} با { نام_قدیمی} جایگزین شد.", -"unshared {files}" => "{ فایل های } قسمت نشده", -"deleted {files}" => "{ فایل های } پاک شده", "'.' is an invalid file name." => "'.' یک نام پرونده نامعتبر است.", "File name cannot be empty." => "نام پرونده نمی تواند خالی باشد.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "نام نامعتبر ، '\\', '/', '<', '>', ':', '\"', '|', '?' و '*' مجاز نمی باشند.", diff --git a/apps/files/l10n/fi_FI.php b/apps/files/l10n/fi_FI.php index aa0393af32..8f07adcf6f 100644 --- a/apps/files/l10n/fi_FI.php +++ b/apps/files/l10n/fi_FI.php @@ -6,6 +6,7 @@ "No file was uploaded" => "Yhtäkään tiedostoa ei lähetetty", "Missing a temporary folder" => "Väliaikaiskansiota ei ole olemassa", "Failed to write to disk" => "Levylle kirjoitus epäonnistui", +"Not enough space available" => "Tilaa ei ole riittävästi", "Invalid directory." => "Virheellinen kansio.", "Files" => "Tiedostot", "Unshare" => "Peru jakaminen", diff --git a/apps/files/l10n/fr.php b/apps/files/l10n/fr.php index d0459f644f..42e146f584 100644 --- a/apps/files/l10n/fr.php +++ b/apps/files/l10n/fr.php @@ -7,6 +7,7 @@ "No file was uploaded" => "Aucun fichier n'a été téléversé", "Missing a temporary folder" => "Il manque un répertoire temporaire", "Failed to write to disk" => "Erreur d'écriture sur le disque", +"Not enough space available" => "Espace disponible insuffisant", "Invalid directory." => "Dossier invalide.", "Files" => "Fichiers", "Unshare" => "Ne plus partager", @@ -19,8 +20,6 @@ "replaced {new_name}" => "{new_name} a été remplacé", "undo" => "annuler", "replaced {new_name} with {old_name}" => "{new_name} a été remplacé par {old_name}", -"unshared {files}" => "Fichiers non partagés : {files}", -"deleted {files}" => "Fichiers supprimés : {files}", "'.' is an invalid file name." => "'.' n'est pas un nom de fichier valide.", "File name cannot be empty." => "Le nom de fichier ne peut être vide.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nom invalide, les caractères '\\', '/', '<', '>', ':', '\"', '|', '?' et '*' ne sont pas autorisés.", diff --git a/apps/files/l10n/gl.php b/apps/files/l10n/gl.php index 271945890c..a1c0f0a5dd 100644 --- a/apps/files/l10n/gl.php +++ b/apps/files/l10n/gl.php @@ -7,6 +7,7 @@ "No file was uploaded" => "Non se enviou ningún ficheiro", "Missing a temporary folder" => "Falta un cartafol temporal", "Failed to write to disk" => "Erro ao escribir no disco", +"Not enough space available" => "O espazo dispoñíbel é insuficiente", "Invalid directory." => "O directorio é incorrecto.", "Files" => "Ficheiros", "Unshare" => "Deixar de compartir", @@ -19,8 +20,6 @@ "replaced {new_name}" => "substituír {new_name}", "undo" => "desfacer", "replaced {new_name} with {old_name}" => "substituír {new_name} polo {old_name}", -"unshared {files}" => "{files} sen compartir", -"deleted {files}" => "{files} eliminados", "'.' is an invalid file name." => "'.' é un nonme de ficheiro non válido", "File name cannot be empty." => "O nome de ficheiro non pode estar baldeiro", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nome non válido, '\\', '/', '<', '>', ':', '\"', '|', '?' e '*' non se permiten.", diff --git a/apps/files/l10n/he.php b/apps/files/l10n/he.php index 26090f6d69..94cddca000 100644 --- a/apps/files/l10n/he.php +++ b/apps/files/l10n/he.php @@ -18,8 +18,6 @@ "replaced {new_name}" => "{new_name} הוחלף", "undo" => "ביטול", "replaced {new_name} with {old_name}" => "{new_name} הוחלף ב־{old_name}", -"unshared {files}" => "בוטל שיתופם של {files}", -"deleted {files}" => "{files} נמחקו", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "השם שגוי, אסור להשתמש בתווים '\\', '/', '<', '>', ':', '\"', '|', '?' ו־'*'.", "Unable to upload your file as it is a directory or has 0 bytes" => "לא יכול להעלות את הקובץ מכיוון שזו תקיה או שמשקל הקובץ 0 בתים", "Upload Error" => "שגיאת העלאה", diff --git a/apps/files/l10n/hu_HU.php b/apps/files/l10n/hu_HU.php index 3b74026485..86fc0f223f 100644 --- a/apps/files/l10n/hu_HU.php +++ b/apps/files/l10n/hu_HU.php @@ -7,6 +7,7 @@ "No file was uploaded" => "Nem töltődött fel semmi", "Missing a temporary folder" => "Hiányzik egy ideiglenes mappa", "Failed to write to disk" => "Nem sikerült a lemezre történő írás", +"Not enough space available" => "Nincs elég szabad hely", "Invalid directory." => "Érvénytelen mappa.", "Files" => "Fájlok", "Unshare" => "Megosztás visszavonása", @@ -19,8 +20,6 @@ "replaced {new_name}" => "a(z) {new_name} állományt kicseréltük", "undo" => "visszavonás", "replaced {new_name} with {old_name}" => "{new_name} fájlt kicseréltük ezzel: {old_name}", -"unshared {files}" => "{files} fájl megosztása visszavonva", -"deleted {files}" => "{files} fájl törölve", "'.' is an invalid file name." => "'.' fájlnév érvénytelen.", "File name cannot be empty." => "A fájlnév nem lehet semmi.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Érvénytelen elnevezés. Ezek a karakterek nem használhatók: '\\', '/', '<', '>', ':', '\"', '|', '?' és '*'", diff --git a/apps/files/l10n/is.php b/apps/files/l10n/is.php index 3f379a621b..43c10ef236 100644 --- a/apps/files/l10n/is.php +++ b/apps/files/l10n/is.php @@ -7,6 +7,7 @@ "No file was uploaded" => "Engin skrá skilaði sér", "Missing a temporary folder" => "Vantar bráðabirgðamöppu", "Failed to write to disk" => "Tókst ekki að skrifa á disk", +"Not enough space available" => "Ekki nægt pláss tiltækt", "Invalid directory." => "Ógild mappa.", "Files" => "Skrár", "Unshare" => "Hætta deilingu", @@ -19,8 +20,6 @@ "replaced {new_name}" => "endurskýrði {new_name}", "undo" => "afturkalla", "replaced {new_name} with {old_name}" => "yfirskrifaði {new_name} með {old_name}", -"unshared {files}" => "Hætti við deilingu á {files}", -"deleted {files}" => "eyddi {files}", "'.' is an invalid file name." => "'.' er ekki leyfilegt nafn.", "File name cannot be empty." => "Nafn skráar má ekki vera tómt", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Ógilt nafn, táknin '\\', '/', '<', '>', ':', '\"', '|', '?' og '*' eru ekki leyfð.", diff --git a/apps/files/l10n/it.php b/apps/files/l10n/it.php index 8a9060b310..e6fc1e81a9 100644 --- a/apps/files/l10n/it.php +++ b/apps/files/l10n/it.php @@ -7,6 +7,7 @@ "No file was uploaded" => "Nessun file è stato caricato", "Missing a temporary folder" => "Cartella temporanea mancante", "Failed to write to disk" => "Scrittura su disco non riuscita", +"Not enough space available" => "Spazio disponibile insufficiente", "Invalid directory." => "Cartella non valida.", "Files" => "File", "Unshare" => "Rimuovi condivisione", @@ -19,8 +20,6 @@ "replaced {new_name}" => "sostituito {new_name}", "undo" => "annulla", "replaced {new_name} with {old_name}" => "sostituito {new_name} con {old_name}", -"unshared {files}" => "non condivisi {files}", -"deleted {files}" => "eliminati {files}", "'.' is an invalid file name." => "'.' non è un nome file valido.", "File name cannot be empty." => "Il nome del file non può essere vuoto.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nome non valido, '\\', '/', '<', '>', ':', '\"', '|', '?' e '*' non sono consentiti.", @@ -63,5 +62,6 @@ "Upload too large" => "Il file caricato è troppo grande", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "I file che stai provando a caricare superano la dimensione massima consentita su questo server.", "Files are being scanned, please wait." => "Scansione dei file in corso, attendi", -"Current scanning" => "Scansione corrente" +"Current scanning" => "Scansione corrente", +"Upgrading filesystem cache..." => "Aggiornamento della cache del filesystem in corso..." ); diff --git a/apps/files/l10n/ja_JP.php b/apps/files/l10n/ja_JP.php index ccb4eb04dc..792bf7cbf9 100644 --- a/apps/files/l10n/ja_JP.php +++ b/apps/files/l10n/ja_JP.php @@ -7,6 +7,7 @@ "No file was uploaded" => "ファイルはアップロードされませんでした", "Missing a temporary folder" => "テンポラリフォルダが見つかりません", "Failed to write to disk" => "ディスクへの書き込みに失敗しました", +"Not enough space available" => "利用可能なスペースが十分にありません", "Invalid directory." => "無効なディレクトリです。", "Files" => "ファイル", "Unshare" => "共有しない", @@ -19,8 +20,6 @@ "replaced {new_name}" => "{new_name} を置換", "undo" => "元に戻す", "replaced {new_name} with {old_name}" => "{old_name} を {new_name} に置換", -"unshared {files}" => "未共有 {files}", -"deleted {files}" => "削除 {files}", "'.' is an invalid file name." => "'.' は無効なファイル名です。", "File name cannot be empty." => "ファイル名を空にすることはできません。", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "無効な名前、'\\', '/', '<', '>', ':', '\"', '|', '?', '*' は使用できません。", diff --git a/apps/files/l10n/ka_GE.php b/apps/files/l10n/ka_GE.php index 72051c3ea9..7ab6122c65 100644 --- a/apps/files/l10n/ka_GE.php +++ b/apps/files/l10n/ka_GE.php @@ -16,8 +16,6 @@ "replaced {new_name}" => "{new_name} შეცვლილია", "undo" => "დაბრუნება", "replaced {new_name} with {old_name}" => "{new_name} შეცვლილია {old_name}–ით", -"unshared {files}" => "გაზიარება მოხსნილი {files}", -"deleted {files}" => "წაშლილი {files}", "Unable to upload your file as it is a directory or has 0 bytes" => "თქვენი ფაილის ატვირთვა ვერ მოხერხდა. ის არის საქაღალდე და შეიცავს 0 ბაიტს", "Upload Error" => "შეცდომა ატვირთვისას", "Close" => "დახურვა", diff --git a/apps/files/l10n/ko.php b/apps/files/l10n/ko.php index b9b4ff1a76..7774aeea31 100644 --- a/apps/files/l10n/ko.php +++ b/apps/files/l10n/ko.php @@ -7,7 +7,8 @@ "No file was uploaded" => "업로드된 파일 없음", "Missing a temporary folder" => "임시 폴더가 사라짐", "Failed to write to disk" => "디스크에 쓰지 못했습니다", -"Invalid directory." => "올바르지 않은 디렉토리입니다.", +"Not enough space available" => "여유 공간이 부족합니다", +"Invalid directory." => "올바르지 않은 디렉터리입니다.", "Files" => "파일", "Unshare" => "공유 해제", "Delete" => "삭제", @@ -19,11 +20,12 @@ "replaced {new_name}" => "{new_name}을(를) 대체함", "undo" => "실행 취소", "replaced {new_name} with {old_name}" => "{old_name}이(가) {new_name}(으)로 대체됨", -"unshared {files}" => "{files} 공유 해제됨", -"deleted {files}" => "{files} 삭제됨", "'.' is an invalid file name." => "'.' 는 올바르지 않은 파일 이름 입니다.", -"File name cannot be empty." => "파일이름은 공란이 될 수 없습니다.", +"File name cannot be empty." => "파일 이름이 비어 있을 수 없습니다.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "폴더 이름이 올바르지 않습니다. 이름에 문자 '\\', '/', '<', '>', ':', '\"', '|', '? ', '*'는 사용할 수 없습니다.", +"Your storage is full, files can not be updated or synced anymore!" => "저장 공간이 가득 찼습니다. 파일을 업데이트하거나 동기화할 수 없습니다!", +"Your storage is almost full ({usedSpacePercent}%)" => "저장 공간이 거의 가득 찼습니다 ({usedSpacePercent}%)", +"Your download is being prepared. This might take some time if the files are big." => "다운로드가 준비 중입니다. 파일 크기가 크다면 시간이 오래 걸릴 수도 있습니다.", "Unable to upload your file as it is a directory or has 0 bytes" => "이 파일은 디렉터리이거나 비어 있기 때문에 업로드할 수 없습니다", "Upload Error" => "업로드 오류", "Close" => "닫기", @@ -60,5 +62,6 @@ "Upload too large" => "업로드 용량 초과", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "이 파일이 서버에서 허용하는 최대 업로드 가능 용량보다 큽니다.", "Files are being scanned, please wait." => "파일을 검색하고 있습니다. 기다려 주십시오.", -"Current scanning" => "현재 검색" +"Current scanning" => "현재 검색", +"Upgrading filesystem cache..." => "파일 시스템 캐시 업그레이드 중..." ); diff --git a/apps/files/l10n/lt_LT.php b/apps/files/l10n/lt_LT.php index 5172964658..f4ad655f42 100644 --- a/apps/files/l10n/lt_LT.php +++ b/apps/files/l10n/lt_LT.php @@ -16,8 +16,6 @@ "replaced {new_name}" => "pakeiskite {new_name}", "undo" => "anuliuoti", "replaced {new_name} with {old_name}" => "pakeiskite {new_name} į {old_name}", -"unshared {files}" => "nebesidalinti {files}", -"deleted {files}" => "ištrinti {files}", "Unable to upload your file as it is a directory or has 0 bytes" => "Neįmanoma įkelti failo - jo dydis gali būti 0 bitų arba tai katalogas", "Upload Error" => "Įkėlimo klaida", "Close" => "Užverti", diff --git a/apps/files/l10n/mk.php b/apps/files/l10n/mk.php index 1b828d1be1..2580d1e6a9 100644 --- a/apps/files/l10n/mk.php +++ b/apps/files/l10n/mk.php @@ -18,8 +18,6 @@ "replaced {new_name}" => "земенета {new_name}", "undo" => "врати", "replaced {new_name} with {old_name}" => "заменета {new_name} со {old_name}", -"unshared {files}" => "без споделување {files}", -"deleted {files}" => "избришани {files}", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Неправилно име. , '\\', '/', '<', '>', ':', '\"', '|', '?' и '*' не се дозволени.", "Unable to upload your file as it is a directory or has 0 bytes" => "Не може да се преземе вашата датотека бидејќи фолдерот во кој се наоѓа фајлот има големина од 0 бајти", "Upload Error" => "Грешка при преземање", diff --git a/apps/files/l10n/nb_NO.php b/apps/files/l10n/nb_NO.php index 3a500b4fb3..a6ba6e9c03 100644 --- a/apps/files/l10n/nb_NO.php +++ b/apps/files/l10n/nb_NO.php @@ -17,7 +17,6 @@ "replaced {new_name}" => "erstatt {new_name}", "undo" => "angre", "replaced {new_name} with {old_name}" => "erstatt {new_name} med {old_name}", -"deleted {files}" => "slettet {files}", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Ugyldig navn, '\\', '/', '<', '>', ':', '\"', '|', '?' og '*' er ikke tillatt.", "Unable to upload your file as it is a directory or has 0 bytes" => "Kan ikke laste opp filen din siden det er en mappe eller den har 0 bytes", "Upload Error" => "Opplasting feilet", diff --git a/apps/files/l10n/nl.php b/apps/files/l10n/nl.php index f99cdaa2c1..7f2e8ec2bf 100644 --- a/apps/files/l10n/nl.php +++ b/apps/files/l10n/nl.php @@ -7,6 +7,7 @@ "No file was uploaded" => "Geen bestand geüpload", "Missing a temporary folder" => "Een tijdelijke map mist", "Failed to write to disk" => "Schrijven naar schijf mislukt", +"Not enough space available" => "Niet genoeg ruimte beschikbaar", "Invalid directory." => "Ongeldige directory.", "Files" => "Bestanden", "Unshare" => "Stop delen", @@ -19,8 +20,6 @@ "replaced {new_name}" => "verving {new_name}", "undo" => "ongedaan maken", "replaced {new_name} with {old_name}" => "verving {new_name} met {old_name}", -"unshared {files}" => "delen gestopt {files}", -"deleted {files}" => "verwijderde {files}", "'.' is an invalid file name." => "'.' is een ongeldige bestandsnaam.", "File name cannot be empty." => "Bestandsnaam kan niet leeg zijn.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Onjuiste naam; '\\', '/', '<', '>', ':', '\"', '|', '?' en '*' zijn niet toegestaan.", diff --git a/apps/files/l10n/pl.php b/apps/files/l10n/pl.php index badcacc29d..6855850f0d 100644 --- a/apps/files/l10n/pl.php +++ b/apps/files/l10n/pl.php @@ -7,6 +7,7 @@ "No file was uploaded" => "Nie przesłano żadnego pliku", "Missing a temporary folder" => "Brak katalogu tymczasowego", "Failed to write to disk" => "Błąd zapisu na dysk", +"Not enough space available" => "Za mało miejsca", "Invalid directory." => "Zła ścieżka.", "Files" => "Pliki", "Unshare" => "Nie udostępniaj", @@ -19,8 +20,6 @@ "replaced {new_name}" => "zastąpiony {new_name}", "undo" => "wróć", "replaced {new_name} with {old_name}" => "zastąpiony {new_name} z {old_name}", -"unshared {files}" => "Udostępniane wstrzymane {files}", -"deleted {files}" => "usunięto {files}", "'.' is an invalid file name." => "'.' jest nieprawidłową nazwą pliku.", "File name cannot be empty." => "Nazwa pliku nie może być pusta.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Niepoprawna nazwa, Znaki '\\', '/', '<', '>', ':', '\"', '|', '?' oraz '*'są niedozwolone.", diff --git a/apps/files/l10n/pt_BR.php b/apps/files/l10n/pt_BR.php index dd684db26a..361e81052b 100644 --- a/apps/files/l10n/pt_BR.php +++ b/apps/files/l10n/pt_BR.php @@ -19,8 +19,6 @@ "replaced {new_name}" => "substituído {new_name}", "undo" => "desfazer", "replaced {new_name} with {old_name}" => "Substituído {old_name} por {new_name} ", -"unshared {files}" => "{files} não compartilhados", -"deleted {files}" => "{files} apagados", "'.' is an invalid file name." => "'.' é um nome de arquivo inválido.", "File name cannot be empty." => "O nome do arquivo não pode estar vazio.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nome inválido, '\\', '/', '<', '>', ':', '\"', '|', '?' e '*' não são permitidos.", diff --git a/apps/files/l10n/pt_PT.php b/apps/files/l10n/pt_PT.php index 38f914b960..1415b71e7f 100644 --- a/apps/files/l10n/pt_PT.php +++ b/apps/files/l10n/pt_PT.php @@ -7,6 +7,7 @@ "No file was uploaded" => "Não foi enviado nenhum ficheiro", "Missing a temporary folder" => "Falta uma pasta temporária", "Failed to write to disk" => "Falhou a escrita no disco", +"Not enough space available" => "Espaço em disco insuficiente!", "Invalid directory." => "Directório Inválido", "Files" => "Ficheiros", "Unshare" => "Deixar de partilhar", @@ -19,8 +20,6 @@ "replaced {new_name}" => "{new_name} substituido", "undo" => "desfazer", "replaced {new_name} with {old_name}" => "substituido {new_name} por {old_name}", -"unshared {files}" => "{files} não partilhado(s)", -"deleted {files}" => "{files} eliminado(s)", "'.' is an invalid file name." => "'.' não é um nome de ficheiro válido!", "File name cannot be empty." => "O nome do ficheiro não pode estar vazio.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nome Inválido, os caracteres '\\', '/', '<', '>', ':', '\"', '|', '?' e '*' não são permitidos.", @@ -63,5 +62,6 @@ "Upload too large" => "Envio muito grande", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Os ficheiros que está a tentar enviar excedem o tamanho máximo de envio permitido neste servidor.", "Files are being scanned, please wait." => "Os ficheiros estão a ser analisados, por favor aguarde.", -"Current scanning" => "Análise actual" +"Current scanning" => "Análise actual", +"Upgrading filesystem cache..." => "Atualizar cache do sistema de ficheiros..." ); diff --git a/apps/files/l10n/ro.php b/apps/files/l10n/ro.php index a06a7c1638..7837b1f5b3 100644 --- a/apps/files/l10n/ro.php +++ b/apps/files/l10n/ro.php @@ -7,6 +7,7 @@ "No file was uploaded" => "Niciun fișier încărcat", "Missing a temporary folder" => "Lipsește un dosar temporar", "Failed to write to disk" => "Eroare la scriere pe disc", +"Not enough space available" => "Nu este suficient spațiu disponibil", "Invalid directory." => "Director invalid.", "Files" => "Fișiere", "Unshare" => "Anulează partajarea", @@ -19,8 +20,6 @@ "replaced {new_name}" => "inlocuit {new_name}", "undo" => "Anulează ultima acțiune", "replaced {new_name} with {old_name}" => "{new_name} inlocuit cu {old_name}", -"unshared {files}" => "nedistribuit {files}", -"deleted {files}" => "Sterse {files}", "'.' is an invalid file name." => "'.' este un nume invalid de fișier.", "File name cannot be empty." => "Numele fișierului nu poate rămâne gol.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nume invalid, '\\', '/', '<', '>', ':', '\"', '|', '?' si '*' nu sunt permise.", diff --git a/apps/files/l10n/ru.php b/apps/files/l10n/ru.php index f953d78ad4..716afa5f29 100644 --- a/apps/files/l10n/ru.php +++ b/apps/files/l10n/ru.php @@ -7,6 +7,7 @@ "No file was uploaded" => "Файл не был загружен", "Missing a temporary folder" => "Невозможно найти временную папку", "Failed to write to disk" => "Ошибка записи на диск", +"Not enough space available" => "Недостаточно свободного места", "Invalid directory." => "Неправильный каталог.", "Files" => "Файлы", "Unshare" => "Отменить публикацию", @@ -19,8 +20,6 @@ "replaced {new_name}" => "заменено {new_name}", "undo" => "отмена", "replaced {new_name} with {old_name}" => "заменено {new_name} на {old_name}", -"unshared {files}" => "не опубликованные {files}", -"deleted {files}" => "удаленные {files}", "'.' is an invalid file name." => "'.' - неправильное имя файла.", "File name cannot be empty." => "Имя файла не может быть пустым.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Неправильное имя, '\\', '/', '<', '>', ':', '\"', '|', '?' и '*' недопустимы.", diff --git a/apps/files/l10n/ru_RU.php b/apps/files/l10n/ru_RU.php index be7cf6c4d8..e1952567d3 100644 --- a/apps/files/l10n/ru_RU.php +++ b/apps/files/l10n/ru_RU.php @@ -7,6 +7,8 @@ "No file was uploaded" => "Файл не был загружен", "Missing a temporary folder" => "Отсутствует временная папка", "Failed to write to disk" => "Не удалось записать на диск", +"Not enough space available" => "Не достаточно свободного места", +"Invalid directory." => "Неверный каталог.", "Files" => "Файлы", "Unshare" => "Скрыть", "Delete" => "Удалить", @@ -18,8 +20,8 @@ "replaced {new_name}" => "заменено {новое_имя}", "undo" => "отменить действие", "replaced {new_name} with {old_name}" => "заменено {новое_имя} с {старое_имя}", -"unshared {files}" => "Cовместное использование прекращено {файлы}", -"deleted {files}" => "удалено {файлы}", +"'.' is an invalid file name." => "'.' является неверным именем файла.", +"File name cannot be empty." => "Имя файла не может быть пустым.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Некорректное имя, '\\', '/', '<', '>', ':', '\"', '|', '?' и '*' не допустимы.", "Unable to upload your file as it is a directory or has 0 bytes" => "Невозможно загрузить файл,\n так как он имеет нулевой размер или является директорией", "Upload Error" => "Ошибка загрузки", @@ -30,6 +32,7 @@ "Upload cancelled." => "Загрузка отменена", "File upload is in progress. Leaving the page now will cancel the upload." => "Процесс загрузки файла. Если покинуть страницу сейчас, загрузка будет отменена.", "URL cannot be empty." => "URL не должен быть пустым.", +"Invalid folder name. Usage of 'Shared' is reserved by Owncloud" => "Неверное имя папки. Использование наименования 'Опубликовано' зарезервировано Owncloud", "Name" => "Имя", "Size" => "Размер", "Modified" => "Изменен", @@ -56,5 +59,6 @@ "Upload too large" => "Загрузка слишком велика", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Размер файлов, которые Вы пытаетесь загрузить, превышает максимально допустимый размер для загрузки на данный сервер.", "Files are being scanned, please wait." => "Файлы сканируются, пожалуйста, подождите.", -"Current scanning" => "Текущее сканирование" +"Current scanning" => "Текущее сканирование", +"Upgrading filesystem cache..." => "Обновление кэша файловой системы... " ); diff --git a/apps/files/l10n/sk_SK.php b/apps/files/l10n/sk_SK.php index d9a65a92a6..a94d96f6ae 100644 --- a/apps/files/l10n/sk_SK.php +++ b/apps/files/l10n/sk_SK.php @@ -7,6 +7,7 @@ "No file was uploaded" => "Žiaden súbor nebol nahraný", "Missing a temporary folder" => "Chýbajúci dočasný priečinok", "Failed to write to disk" => "Zápis na disk sa nepodaril", +"Not enough space available" => "Nie je k dispozícii dostatok miesta", "Invalid directory." => "Neplatný adresár", "Files" => "Súbory", "Unshare" => "Nezdielať", @@ -19,8 +20,6 @@ "replaced {new_name}" => "prepísaný {new_name}", "undo" => "vrátiť", "replaced {new_name} with {old_name}" => "prepísaný {new_name} súborom {old_name}", -"unshared {files}" => "zdieľanie zrušené pre {files}", -"deleted {files}" => "zmazané {files}", "'.' is an invalid file name." => "'.' je neplatné meno súboru.", "File name cannot be empty." => "Meno súboru nemôže byť prázdne", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Nesprávne meno, '\\', '/', '<', '>', ':', '\"', '|', '?' a '*' nie sú povolené hodnoty.", diff --git a/apps/files/l10n/sl.php b/apps/files/l10n/sl.php index 4c0345d16d..d55b4207d2 100644 --- a/apps/files/l10n/sl.php +++ b/apps/files/l10n/sl.php @@ -18,8 +18,6 @@ "replaced {new_name}" => "zamenjano je ime {new_name}", "undo" => "razveljavi", "replaced {new_name} with {old_name}" => "zamenjano ime {new_name} z imenom {old_name}", -"unshared {files}" => "odstranjeno iz souporabe {files}", -"deleted {files}" => "izbrisano {files}", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Neveljavno ime, znaki '\\', '/', '<', '>', ':', '\"', '|', '?' in '*' niso dovoljeni.", "Unable to upload your file as it is a directory or has 0 bytes" => "Pošiljanje ni mogoče, saj gre za mapo, ali pa je datoteka velikosti 0 bajtov.", "Upload Error" => "Napaka med nalaganjem", diff --git a/apps/files/l10n/sr.php b/apps/files/l10n/sr.php index 32addaff40..188c8fc0da 100644 --- a/apps/files/l10n/sr.php +++ b/apps/files/l10n/sr.php @@ -17,8 +17,6 @@ "replaced {new_name}" => "замењено {new_name}", "undo" => "опозови", "replaced {new_name} with {old_name}" => "замењено {new_name} са {old_name}", -"unshared {files}" => "укинуто дељење {files}", -"deleted {files}" => "обрисано {files}", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Неисправан назив. Следећи знакови нису дозвољени: \\, /, <, >, :, \", |, ? и *.", "Unable to upload your file as it is a directory or has 0 bytes" => "Не могу да отпремим датотеку као фасциклу или она има 0 бајтова", "Upload Error" => "Грешка при отпремању", diff --git a/apps/files/l10n/sv.php b/apps/files/l10n/sv.php index 42b82628d4..4b4785931f 100644 --- a/apps/files/l10n/sv.php +++ b/apps/files/l10n/sv.php @@ -7,6 +7,7 @@ "No file was uploaded" => "Ingen fil blev uppladdad", "Missing a temporary folder" => "Saknar en tillfällig mapp", "Failed to write to disk" => "Misslyckades spara till disk", +"Not enough space available" => "Inte tillräckligt med utrymme tillgängligt", "Invalid directory." => "Felaktig mapp.", "Files" => "Filer", "Unshare" => "Sluta dela", @@ -19,8 +20,6 @@ "replaced {new_name}" => "ersatt {new_name}", "undo" => "ångra", "replaced {new_name} with {old_name}" => "ersatt {new_name} med {old_name}", -"unshared {files}" => "stoppad delning {files}", -"deleted {files}" => "raderade {files}", "'.' is an invalid file name." => "'.' är ett ogiltigt filnamn.", "File name cannot be empty." => "Filnamn kan inte vara tomt.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Ogiltigt namn, '\\', '/', '<', '>', ':', '\"', '|', '?' och '*' är inte tillåtet.", @@ -63,5 +62,6 @@ "Upload too large" => "För stor uppladdning", "The files you are trying to upload exceed the maximum size for file uploads on this server." => "Filerna du försöker ladda upp överstiger den maximala storleken för filöverföringar på servern.", "Files are being scanned, please wait." => "Filer skannas, var god vänta", -"Current scanning" => "Aktuell skanning" +"Current scanning" => "Aktuell skanning", +"Upgrading filesystem cache..." => "Uppgraderar filsystemets cache..." ); diff --git a/apps/files/l10n/ta_LK.php b/apps/files/l10n/ta_LK.php index 83843b8781..383b4ef6f8 100644 --- a/apps/files/l10n/ta_LK.php +++ b/apps/files/l10n/ta_LK.php @@ -17,8 +17,6 @@ "replaced {new_name}" => "மாற்றப்பட்டது {new_name}", "undo" => "முன் செயல் நீக்கம் ", "replaced {new_name} with {old_name}" => "{new_name} ஆனது {old_name} இனால் மாற்றப்பட்டது", -"unshared {files}" => "பகிரப்படாதது {கோப்புகள்}", -"deleted {files}" => "நீக்கப்பட்டது {கோப்புகள்}", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "செல்லுபடியற்ற பெயர்,'\\', '/', '<', '>', ':', '\"', '|', '?' மற்றும் '*' ஆகியன அனுமதிக்கப்படமாட்டாது.", "Unable to upload your file as it is a directory or has 0 bytes" => "அடைவு அல்லது 0 bytes ஐ கொண்டுள்ளதால் உங்களுடைய கோப்பை பதிவேற்ற முடியவில்லை", "Upload Error" => "பதிவேற்றல் வழு", diff --git a/apps/files/l10n/th_TH.php b/apps/files/l10n/th_TH.php index f31321694b..c141e4f716 100644 --- a/apps/files/l10n/th_TH.php +++ b/apps/files/l10n/th_TH.php @@ -7,6 +7,7 @@ "No file was uploaded" => "ยังไม่มีไฟล์ที่ถูกอัพโหลด", "Missing a temporary folder" => "แฟ้มเอกสารชั่วคราวเกิดการสูญหาย", "Failed to write to disk" => "เขียนข้อมูลลงแผ่นดิสก์ล้มเหลว", +"Not enough space available" => "มีพื้นที่เหลือไม่เพียงพอ", "Invalid directory." => "ไดเร็กทอรี่ไม่ถูกต้อง", "Files" => "ไฟล์", "Unshare" => "ยกเลิกการแชร์ข้อมูล", @@ -19,8 +20,6 @@ "replaced {new_name}" => "แทนที่ {new_name} แล้ว", "undo" => "เลิกทำ", "replaced {new_name} with {old_name}" => "แทนที่ {new_name} ด้วย {old_name} แล้ว", -"unshared {files}" => "ยกเลิกการแชร์แล้ว {files} ไฟล์", -"deleted {files}" => "ลบไฟล์แล้ว {files} ไฟล์", "'.' is an invalid file name." => "'.' เป็นชื่อไฟล์ที่ไม่ถูกต้อง", "File name cannot be empty." => "ชื่อไฟล์ไม่สามารถเว้นว่างได้", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "ชื่อที่ใช้ไม่ถูกต้อง, '\\', '/', '<', '>', ':', '\"', '|', '?' และ '*' ไม่ได้รับอนุญาตให้ใช้งานได้", diff --git a/apps/files/l10n/tr.php b/apps/files/l10n/tr.php index 7552379468..3412d8ad44 100644 --- a/apps/files/l10n/tr.php +++ b/apps/files/l10n/tr.php @@ -7,6 +7,7 @@ "No file was uploaded" => "Hiç dosya yüklenmedi", "Missing a temporary folder" => "Geçici bir klasör eksik", "Failed to write to disk" => "Diske yazılamadı", +"Not enough space available" => "Yeterli disk alanı yok", "Invalid directory." => "Geçersiz dizin.", "Files" => "Dosyalar", "Unshare" => "Paylaşılmayan", @@ -19,8 +20,6 @@ "replaced {new_name}" => "değiştirilen {new_name}", "undo" => "geri al", "replaced {new_name} with {old_name}" => "{new_name} ismi {old_name} ile değiştirildi", -"unshared {files}" => "paylaşılmamış {files}", -"deleted {files}" => "silinen {files}", "'.' is an invalid file name." => "'.' geçersiz dosya adı.", "File name cannot be empty." => "Dosya adı boş olamaz.", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Geçersiz isim, '\\', '/', '<', '>', ':', '\"', '|', '?' ve '*' karakterlerine izin verilmemektedir.", diff --git a/apps/files/l10n/uk.php b/apps/files/l10n/uk.php index 894505e4e9..9831dfe0f8 100644 --- a/apps/files/l10n/uk.php +++ b/apps/files/l10n/uk.php @@ -18,8 +18,6 @@ "replaced {new_name}" => "замінено {new_name}", "undo" => "відмінити", "replaced {new_name} with {old_name}" => "замінено {new_name} на {old_name}", -"unshared {files}" => "неопубліковано {files}", -"deleted {files}" => "видалено {files}", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Невірне ім'я, '\\', '/', '<', '>', ':', '\"', '|', '?' та '*' не дозволені.", "Unable to upload your file as it is a directory or has 0 bytes" => "Неможливо завантажити ваш файл тому, що він тека або файл розміром 0 байт", "Upload Error" => "Помилка завантаження", diff --git a/apps/files/l10n/vi.php b/apps/files/l10n/vi.php index 1d97973469..0daf580a2f 100644 --- a/apps/files/l10n/vi.php +++ b/apps/files/l10n/vi.php @@ -17,8 +17,6 @@ "replaced {new_name}" => "đã thay thế {new_name}", "undo" => "lùi lại", "replaced {new_name} with {old_name}" => "đã thay thế {new_name} bằng {old_name}", -"unshared {files}" => "hủy chia sẽ {files}", -"deleted {files}" => "đã xóa {files}", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "Tên không hợp lệ, '\\', '/', '<', '>', ':', '\"', '|', '?' và '*' thì không được phép dùng.", "Unable to upload your file as it is a directory or has 0 bytes" => "Không thể tải lên tập tin này do nó là một thư mục hoặc kích thước tập tin bằng 0 byte", "Upload Error" => "Tải lên lỗi", diff --git a/apps/files/l10n/zh_CN.GB2312.php b/apps/files/l10n/zh_CN.GB2312.php index 810bce353b..a38e2d3bc6 100644 --- a/apps/files/l10n/zh_CN.GB2312.php +++ b/apps/files/l10n/zh_CN.GB2312.php @@ -17,8 +17,6 @@ "replaced {new_name}" => "已替换 {new_name}", "undo" => "撤销", "replaced {new_name} with {old_name}" => "已用 {old_name} 替换 {new_name}", -"unshared {files}" => "未分享的 {files}", -"deleted {files}" => "已删除的 {files}", "Unable to upload your file as it is a directory or has 0 bytes" => "不能上传你指定的文件,可能因为它是个文件夹或者大小为0", "Upload Error" => "上传错误", "Close" => "关闭", diff --git a/apps/files/l10n/zh_CN.php b/apps/files/l10n/zh_CN.php index 2d7a140f52..2491d64534 100644 --- a/apps/files/l10n/zh_CN.php +++ b/apps/files/l10n/zh_CN.php @@ -7,6 +7,7 @@ "No file was uploaded" => "文件没有上传", "Missing a temporary folder" => "缺少临时目录", "Failed to write to disk" => "写入磁盘失败", +"Not enough space available" => "没有足够可用空间", "Invalid directory." => "无效文件夹。", "Files" => "文件", "Unshare" => "取消分享", @@ -19,8 +20,6 @@ "replaced {new_name}" => "替换 {new_name}", "undo" => "撤销", "replaced {new_name} with {old_name}" => "已将 {old_name}替换成 {new_name}", -"unshared {files}" => "取消了共享 {files}", -"deleted {files}" => "删除了 {files}", "'.' is an invalid file name." => "'.' 是一个无效的文件名。", "File name cannot be empty." => "文件名不能为空。", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "无效名称,'\\', '/', '<', '>', ':', '\"', '|', '?' 和 '*' 不被允许使用。", diff --git a/apps/files/l10n/zh_TW.php b/apps/files/l10n/zh_TW.php index 67516bf015..6d354ac1e9 100644 --- a/apps/files/l10n/zh_TW.php +++ b/apps/files/l10n/zh_TW.php @@ -7,6 +7,7 @@ "No file was uploaded" => "無已上傳檔案", "Missing a temporary folder" => "遺失暫存資料夾", "Failed to write to disk" => "寫入硬碟失敗", +"Not enough space available" => "沒有足夠的可用空間", "Invalid directory." => "無效的資料夾。", "Files" => "檔案", "Unshare" => "取消共享", @@ -19,8 +20,6 @@ "replaced {new_name}" => "已取代 {new_name}", "undo" => "復原", "replaced {new_name} with {old_name}" => "使用 {new_name} 取代 {old_name}", -"unshared {files}" => "已取消分享 {files}", -"deleted {files}" => "已刪除 {files}", "'.' is an invalid file name." => "'.' 是不合法的檔名。", "File name cannot be empty." => "檔名不能為空。", "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." => "檔名不合法,不允許 '\\', '/', '<', '>', ':', '\"', '|', '?' 和 '*' 。", diff --git a/apps/files_encryption/l10n/ko.php b/apps/files_encryption/l10n/ko.php index 68d60c1ae3..901c41e12e 100644 --- a/apps/files_encryption/l10n/ko.php +++ b/apps/files_encryption/l10n/ko.php @@ -1,4 +1,15 @@ "ownCloud로 전환한 다음 암호화에 사용할 암호를 변경하면 변환이 완료됩니다.", +"switched to client side encryption" => "클라이언트 암호화로 변경됨", +"Change encryption password to login password" => "암호화 암호를 로그인 암호로 변경", +"Please check your passwords and try again." => "암호를 확인한 다음 다시 시도하십시오.", +"Could not change your file encryption password to your login password" => "암호화 암호를 로그인 암호로 변경할 수 없습니다", +"Choose encryption mode:" => "암호화 모드 선택:", +"Client side encryption (most secure but makes it impossible to access your data from the web interface)" => "클라이언트 암호화 (안전하지만 웹에서 데이터에 접근할 수 없음)", +"Server side encryption (allows you to access your files from the web interface and the desktop client)" => "서버 암호화 (웹 및 데스크톱 클라이언트에서 데이터에 접근할 수 있음)", +"None (no encryption at all)" => "없음 (암호화하지 않음)", +"Important: Once you selected an encryption mode there is no way to change it back" => "알림: 암호화 모드를 선택하면 다른 것으로 변경할 수 없습니다", +"User specific (let the user decide)" => "사용자 지정 (사용자별 설정)", "Encryption" => "암호화", "Exclude the following file types from encryption" => "다음 파일 형식은 암호화하지 않음", "None" => "없음" diff --git a/apps/files_encryption/l10n/ru_RU.php b/apps/files_encryption/l10n/ru_RU.php index 4321fb8a8a..1149ac64f3 100644 --- a/apps/files_encryption/l10n/ru_RU.php +++ b/apps/files_encryption/l10n/ru_RU.php @@ -1,4 +1,13 @@ "Пожалуйста, переключитесь на ownCloud-клиент и измените Ваш пароль шифрования для завершения конвертации.", +"switched to client side encryption" => "переключено на шифрование на клиентской стороне", +"Please check your passwords and try again." => "Пожалуйста, проверьте Ваш пароль и попробуйте снова", +"Choose encryption mode:" => "Выберите способ шифрования:", +"Client side encryption (most secure but makes it impossible to access your data from the web interface)" => "Шифрование на стороне клиента (наиболее безопасно, но делает невозможным получение доступа к Вашим данным по вэб-интерфейсу)", +"Server side encryption (allows you to access your files from the web interface and the desktop client)" => "Шифрование на стороне сервера (позволяет Вам получить доступ к Вашим файлам по вэб-интерфейсу и десктопному клиенту)", +"None (no encryption at all)" => "Нет (шифрование полностью отсутствует)", +"Important: Once you selected an encryption mode there is no way to change it back" => "Важно: Невозможно будет изменить выбранный способ шифрования", +"User specific (let the user decide)" => "Специфика пользователя (позволено решить пользователю)", "Encryption" => "Шифрование", "Exclude the following file types from encryption" => "Исключите следующие типы файлов из шифрования", "None" => "Ни один" diff --git a/apps/files_external/l10n/ko.php b/apps/files_external/l10n/ko.php index cb691cf5e3..47b75f74b8 100644 --- a/apps/files_external/l10n/ko.php +++ b/apps/files_external/l10n/ko.php @@ -5,8 +5,8 @@ "Fill out all required fields" => "모든 필수 항목을 입력하십시오", "Please provide a valid Dropbox app key and secret." => "올바른 Dropbox 앱 키와 암호를 입력하십시오.", "Error configuring Google Drive storage" => "Google 드라이브 저장소 설정 오류", -"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "경고\"smbclient\"가 설치되지 않았습니다. CIFS/SMB 공유애 연결이 불가능 합니다.. 시스템 관리자에게 요청하여 설치하시기 바랍니다.", -"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "경고PHP용 FTP 지원이 사용 불가능 하거나 설치되지 않았습니다. FTP 공유에 연결이 불가능 합니다. 시스템 관리자에게 요청하여 설치하시기 바랍니다. ", +"Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it." => "경고: \"smbclient\"가 설치되지 않았습니다. CIFS/SMB 공유 자원에 연결할 수 없습니다. 시스템 관리자에게 설치를 요청하십시오.", +"Warning: The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it." => "경고: PHP FTP 지원이 비활성화되어 있거나 설치되지 않았습니다. FTP 공유를 마운트할 수 없습니다. 시스템 관리자에게 설치를 요청하십시오.", "External Storage" => "외부 저장소", "Mount point" => "마운트 지점", "Backend" => "백엔드", diff --git a/apps/user_ldap/l10n/ko.php b/apps/user_ldap/l10n/ko.php index c0d09b5c3c..78745a0e01 100644 --- a/apps/user_ldap/l10n/ko.php +++ b/apps/user_ldap/l10n/ko.php @@ -1,8 +1,10 @@ Warning:
    Apps user_ldap and user_webdavauth are incompatible. You may experience unexpected behaviour. Please ask your system administrator to disable one of them." => "경고user_ldap 앱과 user_webdavauth 앱은 호환되지 않습니다. 오동작을 일으킬 수 있으므로, 시스템 관리자에게 요청하여, 둘 중 하나를 비활성화 하시기 바랍니다.", +"Warning: Apps user_ldap and user_webdavauth are incompatible. You may experience unexpected behaviour. Please ask your system administrator to disable one of them." => "경고: user_ldap 앱과 user_webdavauth 앱은 호환되지 않습니다. 오동작을 일으킬 수 있으므로, 시스템 관리자에게 요청하여 둘 중 하나만 사용하도록 하십시오.", +"Warning: The PHP LDAP module is not installed, the backend will not work. Please ask your system administrator to install it." => "경고: PHP LDAP 모듈이 비활성화되어 있거나 설치되어 있지 않습니다. 백엔드를 사용할 수 없습니다. 시스템 관리자에게 설치를 요청하십시오.", "Host" => "호스트", "You can omit the protocol, except you require SSL. Then start with ldaps://" => "SSL을 사용하는 경우가 아니라면 프로토콜을 입력하지 않아도 됩니다. SSL을 사용하려면 ldaps://를 입력하십시오.", "Base DN" => "기본 DN", +"One Base DN per line" => "기본 DN을 한 줄에 하나씩 입력하십시오", "You can specify Base DN for users and groups in the Advanced tab" => "고급 탭에서 사용자 및 그룹에 대한 기본 DN을 지정할 수 있습니다.", "User DN" => "사용자 DN", "The DN of the client user with which the bind shall be done, e.g. uid=agent,dc=example,dc=com. For anonymous access, leave DN and Password empty." => "바인딩 작업을 수행할 클라이언트 사용자 DN입니다. 예를 들어서 uid=agent,dc=example,dc=com입니다. 익명 접근을 허용하려면 DN과 암호를 비워 두십시오.", @@ -19,7 +21,9 @@ "without any placeholder, e.g. \"objectClass=posixGroup\"." => "자리 비움자를 사용할 수 없습니다. 예제: \"objectClass=posixGroup\"", "Port" => "포트", "Base User Tree" => "기본 사용자 트리", +"One User Base DN per line" => "사용자 DN을 한 줄에 하나씩 입력하십시오", "Base Group Tree" => "기본 그룹 트리", +"One Group Base DN per line" => "그룹 기본 DN을 한 줄에 하나씩 입력하십시오", "Group-Member association" => "그룹-회원 연결", "Use TLS" => "TLS 사용", "Do not use it for SSL connections, it will fail." => "SSL 연결 시 사용하는 경우 연결되지 않습니다.", diff --git a/apps/user_webdavauth/l10n/ko.php b/apps/user_webdavauth/l10n/ko.php index 245a510134..578ff35e72 100644 --- a/apps/user_webdavauth/l10n/ko.php +++ b/apps/user_webdavauth/l10n/ko.php @@ -1,3 +1,5 @@ "URL: http://" +"WebDAV Authentication" => "WebDAV 인증", +"URL: http://" => "URL: http://", +"ownCloud will send the user credentials to this URL. This plugin checks the response and will interpret the HTTP statuscodes 401 and 403 as invalid credentials, and all other responses as valid credentials." => "ownCloud에서 이 URL로 사용자 인증 정보를 보냅니다. 이 플러그인은 응답을 확인하여 HTTP 상태 코드 401이나 403이 돌아온 경우에 잘못된 인증 정보로 간주합니다. 다른 모든 상태 코드는 올바른 인증 정보로 간주합니다." ); diff --git a/core/l10n/it.php b/core/l10n/it.php index 82451e955e..ec094f643a 100644 --- a/core/l10n/it.php +++ b/core/l10n/it.php @@ -124,12 +124,12 @@ "web services under your control" => "servizi web nelle tue mani", "Log out" => "Esci", "Automatic logon rejected!" => "Accesso automatico rifiutato.", -"If you did not change your password recently, your account may be compromised!" => "Se non hai cambiato la password recentemente, il tuo account potrebbe essere stato compromesso.", +"If you did not change your password recently, your account may be compromised!" => "Se non hai cambiato la password recentemente, il tuo account potrebbe essere compromesso.", "Please change your password to secure your account again." => "Cambia la password per rendere nuovamente sicuro il tuo account.", "Lost your password?" => "Hai perso la password?", "remember" => "ricorda", "Log in" => "Accedi", "prev" => "precedente", "next" => "successivo", -"Updating ownCloud to version %s, this may take a while." => "Aggiornamento di ownCloud alla versione %s in corso, potrebbe richiedere del tempo." +"Updating ownCloud to version %s, this may take a while." => "Aggiornamento di ownCloud alla versione %s in corso, ciò potrebbe richiedere del tempo." ); diff --git a/core/l10n/ko.php b/core/l10n/ko.php index cc999d0ac1..91c00c4a57 100644 --- a/core/l10n/ko.php +++ b/core/l10n/ko.php @@ -1,8 +1,8 @@ "User %s 가 당신과 파일을 공유하였습니다.", -"User %s shared a folder with you" => "User %s 가 당신과 폴더를 공유하였습니다.", -"User %s shared the file \"%s\" with you. It is available for download here: %s" => "User %s 가 파일 \"%s\"를 당신과 공유하였습니다. 다운로드는 여기서 %s 할 수 있습니다.", -"User %s shared the folder \"%s\" with you. It is available for download here: %s" => "User %s 가 폴더 \"%s\"를 당신과 공유하였습니다. 다운로드는 여기서 %s 할 수 있습니다.", +"User %s shared a file with you" => "%s 님이 파일을 공유하였습니다", +"User %s shared a folder with you" => "%s 님이 폴더를 공유하였습니다", +"User %s shared the file \"%s\" with you. It is available for download here: %s" => "%s 님이 파일 \"%s\"을(를) 공유하였습니다. 여기에서 다운로드할 수 있습니다: %s", +"User %s shared the folder \"%s\" with you. It is available for download here: %s" => "%s 님이 폴더 \"%s\"을(를) 공유하였습니다. 여기에서 다운로드할 수 있습니다: %s", "Category type not provided." => "분류 형식이 제공되지 않았습니다.", "No category to add?" => "추가할 분류가 없습니까?", "This category already exists: " => "이 분류는 이미 존재합니다:", @@ -54,6 +54,7 @@ "The app name is not specified." => "앱 이름이 지정되지 않았습니다.", "The required file {file} is not installed!" => "필요한 파일 {file}이(가) 설치되지 않았습니다!", "Share" => "공유", +"Shared" => "공유됨", "Error while sharing" => "공유하는 중 오류 발생", "Error while unsharing" => "공유 해제하는 중 오류 발생", "Error while changing permissions" => "권한 변경하는 중 오류 발생", @@ -83,6 +84,8 @@ "Error setting expiration date" => "만료 날짜 설정 오류", "Sending ..." => "전송 중...", "Email sent" => "이메일 발송됨", +"The update was unsuccessful. Please report this issue to the ownCloud community." => "업데이트가 실패하였습니다. 이 문제를 ownCloud 커뮤니티에 보고해 주십시오.", +"The update was successful. Redirecting you to ownCloud now." => "업데이트가 성공하였습니다. ownCloud로 돌아갑니다.", "ownCloud password reset" => "ownCloud 암호 재설정", "Use the following link to reset your password: {link}" => "다음 링크를 사용하여 암호를 재설정할 수 있습니다: {link}", "You will receive a link to reset your password via Email." => "이메일로 암호 재설정 링크를 보냈습니다.", @@ -128,5 +131,5 @@ "Log in" => "로그인", "prev" => "이전", "next" => "다음", -"Updating ownCloud to version %s, this may take a while." => "ownCloud 를 버젼 %s로 업데이트 하는 중, 시간이 소요됩니다." +"Updating ownCloud to version %s, this may take a while." => "ownCloud를 버전 %s(으)로 업데이트합니다. 잠시 기다려 주십시오." ); diff --git a/l10n/ar/core.po b/l10n/ar/core.po index 7d50e0187b..f5850c1adf 100644 --- a/l10n/ar/core.po +++ b/l10n/ar/core.po @@ -9,8 +9,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Arabic (http://www.transifex.com/projects/p/owncloud/language/ar/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/ar/files.po b/l10n/ar/files.po index 0abddeffe1..eaf6d1705c 100644 --- a/l10n/ar/files.po +++ b/l10n/ar/files.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Arabic (http://www.transifex.com/projects/p/owncloud/language/ar/)\n" "MIME-Version: 1.0\n" @@ -65,15 +65,15 @@ msgstr "" msgid "Files" msgstr "الملفات" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "إلغاء مشاركة" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "محذوف" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "" @@ -97,7 +97,7 @@ msgstr "" msgid "replaced {new_name}" msgstr "" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "" @@ -105,12 +105,8 @@ msgstr "" msgid "replaced {new_name} with {old_name}" msgstr "" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "" - -#: js/filelist.js:288 -msgid "deleted {files}" +#: js/filelist.js:280 +msgid "perform delete operation" msgstr "" #: js/files.js:52 @@ -135,78 +131,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "إغلق" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "" -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "" -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "الاسم" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "حجم" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "معدل" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "" @@ -262,33 +258,37 @@ msgstr "مجلد" msgid "From link" msgstr "" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "لا يوجد شيء هنا. إرفع بعض الملفات!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "تحميل" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "حجم الترفيع أعلى من المسموح" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "حجم الملفات التي تريد ترفيعها أعلى من المسموح على الخادم." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "" -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "" diff --git a/l10n/ar/files_trashbin.po b/l10n/ar/files_trashbin.po new file mode 100644 index 0000000000..ee7ad81828 --- /dev/null +++ b/l10n/ar/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Arabic (http://www.transifex.com/projects/p/owncloud/language/ar/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ar\n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/bg_BG/core.po b/l10n/bg_BG/core.po index e4d55a9b58..9a35782ee7 100644 --- a/l10n/bg_BG/core.po +++ b/l10n/bg_BG/core.po @@ -11,8 +11,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:50+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Bulgarian (Bulgaria) (http://www.transifex.com/projects/p/owncloud/language/bg_BG/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/bg_BG/files.po b/l10n/bg_BG/files.po index dc6db939da..f64a199c15 100644 --- a/l10n/bg_BG/files.po +++ b/l10n/bg_BG/files.po @@ -9,8 +9,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" "Last-Translator: I Robot \n" "Language-Team: Bulgarian (Bulgaria) (http://www.transifex.com/projects/p/owncloud/language/bg_BG/)\n" "MIME-Version: 1.0\n" @@ -66,15 +66,15 @@ msgstr "" msgid "Files" msgstr "Файлове" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Изтриване" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Преименуване" @@ -98,7 +98,7 @@ msgstr "отказ" msgid "replaced {new_name}" msgstr "" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "възтановяване" @@ -106,12 +106,8 @@ msgstr "възтановяване" msgid "replaced {new_name} with {old_name}" msgstr "" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "" - -#: js/filelist.js:288 -msgid "deleted {files}" +#: js/filelist.js:280 +msgid "perform delete operation" msgstr "" #: js/files.js:52 @@ -136,78 +132,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Качването е спряно." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "" -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Име" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Размер" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Променено" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "" @@ -263,33 +259,37 @@ msgstr "Папка" msgid "From link" msgstr "" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Няма нищо тук. Качете нещо." -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Изтегляне" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Файлът който сте избрали за качване е прекалено голям" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "" -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "" -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "" diff --git a/l10n/bg_BG/files_trashbin.po b/l10n/bg_BG/files_trashbin.po new file mode 100644 index 0000000000..e0e23f5d09 --- /dev/null +++ b/l10n/bg_BG/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Bulgarian (Bulgaria) (http://www.transifex.com/projects/p/owncloud/language/bg_BG/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bg_BG\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/bn_BD/core.po b/l10n/bn_BD/core.po index 1f57723dad..6c25c59499 100644 --- a/l10n/bn_BD/core.po +++ b/l10n/bn_BD/core.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:50+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Bengali (Bangladesh) (http://www.transifex.com/projects/p/owncloud/language/bn_BD/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/bn_BD/files.po b/l10n/bn_BD/files.po index 2530bf9e73..a7f37ff99c 100644 --- a/l10n/bn_BD/files.po +++ b/l10n/bn_BD/files.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" "Last-Translator: I Robot \n" "Language-Team: Bengali (Bangladesh) (http://www.transifex.com/projects/p/owncloud/language/bn_BD/)\n" "MIME-Version: 1.0\n" @@ -55,7 +55,7 @@ msgstr "ডিস্কে লিখতে ব্যর্থ" #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "যথেষ্ঠ পরিমাণ স্থান নেই" #: ajax/upload.php:82 msgid "Invalid directory." @@ -65,15 +65,15 @@ msgstr "ভুল ডিরেক্টরি" msgid "Files" msgstr "ফাইল" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "ভাগাভাগি বাতিল " -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "মুছে ফেল" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "পূনঃনামকরণ" @@ -97,7 +97,7 @@ msgstr "বাতিল" msgid "replaced {new_name}" msgstr "{new_name} প্রতিস্থাপন করা হয়েছে" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "ক্রিয়া প্রত্যাহার" @@ -105,13 +105,9 @@ msgstr "ক্রিয়া প্রত্যাহার" msgid "replaced {new_name} with {old_name}" msgstr "{new_name} কে {old_name} নামে প্রতিস্থাপন করা হয়েছে" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "{files} ভাগাভাগি বাতিল কর" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "{files} মুছে ফেলা হয়েছে" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -135,78 +131,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "আপনার ফাইলটি আপলোড করা সম্ভব হলো না, কেননা এটি হয় একটি ফোল্ডার কিংবা এর আকার ০ বাইট" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "আপলোড করতে সমস্যা " -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "বন্ধ" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "মুলতুবি" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "১টি ফাইল আপলোড করা হচ্ছে" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} টি ফাইল আপলোড করা হচ্ছে" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "আপলোড বাতিল করা হয়েছে।" -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "ফাইল আপলোড চলমান। এই পৃষ্ঠা পরিত্যাগ করলে আপলোড বাতিল করা হবে।" -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "URL ফাঁকা রাখা যাবে না।" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "ফোল্ডারের নামটি সঠিক নয়। 'ভাগাভাগি করা' শুধুমাত্র Owncloud এর জন্য সংরক্ষিত।" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "নাম" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "আকার" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "পরিবর্তিত" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "১টি ফোল্ডার" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} টি ফোল্ডার" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "১টি ফাইল" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} টি ফাইল" @@ -262,33 +258,37 @@ msgstr "ফোল্ডার" msgid "From link" msgstr " লিংক থেকে" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "আপলোড বাতিল কর" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "এখানে কিছুই নেই। কিছু আপলোড করুন !" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "ডাউনলোড" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "আপলোডের আকারটি অনেক বড়" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "আপনি এই সার্ভারে আপলোড করার জন্য অনুমোদিত ফাইলের সর্বোচ্চ আকারের চেয়ে বৃহদাকার ফাইল আপলোড করার চেষ্টা করছেন " -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "ফাইলগুলো স্ক্যান করা হচ্ছে, দয়া করে অপেক্ষা করুন।" -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "বর্তমান স্ক্যানিং" diff --git a/l10n/bn_BD/files_trashbin.po b/l10n/bn_BD/files_trashbin.po new file mode 100644 index 0000000000..e6d5c91dcb --- /dev/null +++ b/l10n/bn_BD/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Bengali (Bangladesh) (http://www.transifex.com/projects/p/owncloud/language/bn_BD/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: bn_BD\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/ca/core.po b/l10n/ca/core.po index 1e3785c556..6eea0f16d4 100644 --- a/l10n/ca/core.po +++ b/l10n/ca/core.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: rogerc \n" "Language-Team: Catalan (http://www.transifex.com/projects/p/owncloud/language/ca/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/ca/files.po b/l10n/ca/files.po index bffe388f4d..2f36e169c7 100644 --- a/l10n/ca/files.po +++ b/l10n/ca/files.po @@ -14,8 +14,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Catalan (http://www.transifex.com/projects/p/owncloud/language/ca/)\n" "MIME-Version: 1.0\n" @@ -61,7 +61,7 @@ msgstr "Ha fallat en escriure al disc" #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "No hi ha prou espai disponible" #: ajax/upload.php:82 msgid "Invalid directory." @@ -71,15 +71,15 @@ msgstr "Directori no vàlid." msgid "Files" msgstr "Fitxers" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Deixa de compartir" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Suprimeix" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Reanomena" @@ -103,7 +103,7 @@ msgstr "cancel·la" msgid "replaced {new_name}" msgstr "s'ha substituït {new_name}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "desfés" @@ -111,13 +111,9 @@ msgstr "desfés" msgid "replaced {new_name} with {old_name}" msgstr "s'ha substituït {old_name} per {new_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "no compartits {files}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "eliminats {files}" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -141,78 +137,78 @@ msgstr "El vostre espai d'emmagatzemament és ple, els fitxers ja no es poden ac msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "El vostre espai d'emmagatzemament és gairebé ple ({usedSpacePercent}%)" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "S'està preparant la baixada. Pot trigar una estona si els fitxers són grans." -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "No es pot pujar el fitxer perquè és una carpeta o té 0 bytes" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Error en la pujada" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Tanca" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Pendents" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "1 fitxer pujant" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} fitxers en pujada" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "La pujada s'ha cancel·lat." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Hi ha una pujada en curs. Si abandoneu la pàgina la pujada es cancel·larà." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "La URL no pot ser buida" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "Nom de carpeta no vàlid. L'ús de 'Shared' està reservat per Owncloud" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Nom" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Mida" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Modificat" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 carpeta" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} carpetes" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 fitxer" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} fitxers" @@ -268,36 +264,40 @@ msgstr "Carpeta" msgid "From link" msgstr "Des d'enllaç" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Cancel·la la pujada" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Res per aquí. Pugeu alguna cosa!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Baixa" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "La pujada és massa gran" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Els fitxers que esteu intentant pujar excedeixen la mida màxima de pujada del servidor" -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "S'estan escanejant els fitxers, espereu" -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Actualment escanejant" #: templates/upgrade.php:2 msgid "Upgrading filesystem cache..." -msgstr "" +msgstr "Actualitzant la memòria de cau del sistema de fitxers..." diff --git a/l10n/ca/files_trashbin.po b/l10n/ca/files_trashbin.po new file mode 100644 index 0000000000..660728accb --- /dev/null +++ b/l10n/ca/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Catalan (http://www.transifex.com/projects/p/owncloud/language/ca/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ca\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/ca/settings.po b/l10n/ca/settings.po index 7005160e05..18973896d8 100644 --- a/l10n/ca/settings.po +++ b/l10n/ca/settings.po @@ -13,9 +13,9 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" -"Last-Translator: I Robot \n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 08:30+0000\n" +"Last-Translator: rogerc \n" "Language-Team: Catalan (http://www.transifex.com/projects/p/owncloud/language/ca/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -270,11 +270,11 @@ msgstr "Emmagatzemament" #: templates/users.php:97 msgid "change display name" -msgstr "" +msgstr "canvia el nom a mostrar" #: templates/users.php:101 msgid "set new password" -msgstr "" +msgstr "estableix nova contrasenya" #: templates/users.php:137 msgid "Default" diff --git a/l10n/cs_CZ/core.po b/l10n/cs_CZ/core.po index 629665feee..4d163818fd 100644 --- a/l10n/cs_CZ/core.po +++ b/l10n/cs_CZ/core.po @@ -11,8 +11,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: Tomáš Chvátal \n" "Language-Team: Czech (Czech Republic) (http://www.transifex.com/projects/p/owncloud/language/cs_CZ/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/cs_CZ/files.po b/l10n/cs_CZ/files.po index 705061c1f4..29be735c3f 100644 --- a/l10n/cs_CZ/files.po +++ b/l10n/cs_CZ/files.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Czech (Czech Republic) (http://www.transifex.com/projects/p/owncloud/language/cs_CZ/)\n" "MIME-Version: 1.0\n" @@ -57,7 +57,7 @@ msgstr "Zápis na disk selhal" #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "Nedostatek dostupného místa" #: ajax/upload.php:82 msgid "Invalid directory." @@ -67,15 +67,15 @@ msgstr "Neplatný adresář" msgid "Files" msgstr "Soubory" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Zrušit sdílení" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Smazat" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Přejmenovat" @@ -99,7 +99,7 @@ msgstr "zrušit" msgid "replaced {new_name}" msgstr "nahrazeno {new_name}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "zpět" @@ -107,13 +107,9 @@ msgstr "zpět" msgid "replaced {new_name} with {old_name}" msgstr "nahrazeno {new_name} s {old_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "sdílení zrušeno pro {files}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "smazáno {files}" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -137,78 +133,78 @@ msgstr "Vaše úložiště je plné, nelze aktualizovat ani synchronizovat soubo msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "Vaše úložiště je téměř plné ({usedSpacePercent}%)" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "Vaše soubory ke stažení se připravují. Pokud jsou velké může to chvíli trvat." -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Nelze odeslat Váš soubor, protože je to adresář nebo má velikost 0 bajtů" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Chyba odesílání" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Zavřít" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Čekající" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "odesílá se 1 soubor" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "odesílám {count} souborů" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Odesílání zrušeno." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Probíhá odesílání souboru. Opuštění stránky vyústí ve zrušení nahrávání." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "URL nemůže být prázdná" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "Neplatný název složky. Použití 'Shared' je rezervováno pro vnitřní potřeby Owncloud" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Název" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Velikost" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Změněno" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 složka" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} složky" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 soubor" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} soubory" @@ -264,36 +260,40 @@ msgstr "Složka" msgid "From link" msgstr "Z odkazu" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Zrušit odesílání" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Žádný obsah. Nahrajte něco." -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Stáhnout" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Odeslaný soubor je příliš velký" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Soubory, které se snažíte odeslat, překračují limit velikosti odesílání na tomto serveru." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Soubory se prohledávají, prosím čekejte." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Aktuální prohledávání" #: templates/upgrade.php:2 msgid "Upgrading filesystem cache..." -msgstr "" +msgstr "Aktualizuji mezipaměť souborového systému..." diff --git a/l10n/cs_CZ/files_trashbin.po b/l10n/cs_CZ/files_trashbin.po new file mode 100644 index 0000000000..74a1948515 --- /dev/null +++ b/l10n/cs_CZ/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Czech (Czech Republic) (http://www.transifex.com/projects/p/owncloud/language/cs_CZ/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: cs_CZ\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/cs_CZ/settings.po b/l10n/cs_CZ/settings.po index cfe7ffb495..0e0e0a5599 100644 --- a/l10n/cs_CZ/settings.po +++ b/l10n/cs_CZ/settings.po @@ -13,9 +13,9 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" -"Last-Translator: I Robot \n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 07:20+0000\n" +"Last-Translator: Tomáš Chvátal \n" "Language-Team: Czech (Czech Republic) (http://www.transifex.com/projects/p/owncloud/language/cs_CZ/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -270,11 +270,11 @@ msgstr "Úložiště" #: templates/users.php:97 msgid "change display name" -msgstr "" +msgstr "změnit zobrazované jméno" #: templates/users.php:101 msgid "set new password" -msgstr "" +msgstr "nastavit nové heslo" #: templates/users.php:137 msgid "Default" diff --git a/l10n/da/core.po b/l10n/da/core.po index 6bbc9024b4..fa817909c3 100644 --- a/l10n/da/core.po +++ b/l10n/da/core.po @@ -16,8 +16,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Danish (http://www.transifex.com/projects/p/owncloud/language/da/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/da/files.po b/l10n/da/files.po index 8456788fff..a58ad1dfbc 100644 --- a/l10n/da/files.po +++ b/l10n/da/files.po @@ -15,8 +15,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:27+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Danish (http://www.transifex.com/projects/p/owncloud/language/da/)\n" "MIME-Version: 1.0\n" @@ -72,15 +72,15 @@ msgstr "Ugyldig mappe." msgid "Files" msgstr "Filer" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Fjern deling" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Slet" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Omdøb" @@ -104,7 +104,7 @@ msgstr "fortryd" msgid "replaced {new_name}" msgstr "erstattede {new_name}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "fortryd" @@ -112,13 +112,9 @@ msgstr "fortryd" msgid "replaced {new_name} with {old_name}" msgstr "erstattede {new_name} med {old_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "ikke delte {files}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "slettede {files}" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -142,78 +138,78 @@ msgstr "Din opbevaringsplads er fyldt op, filer kan ikke opdateres eller synkron msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "Din opbevaringsplads er næsten fyldt op ({usedSpacePercent}%)" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "Dit download forberedes. Dette kan tage lidt tid ved større filer." -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Kunne ikke uploade din fil, da det enten er en mappe eller er tom" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Fejl ved upload" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Luk" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Afventer" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "1 fil uploades" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} filer uploades" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Upload afbrudt." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Fil upload kører. Hvis du forlader siden nu, vil uploadet blive annuleret." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "URLen kan ikke være tom." -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "Ugyldigt mappenavn. Brug af \"Shared\" er forbeholdt Owncloud" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Navn" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Størrelse" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Ændret" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 mappe" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} mapper" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 fil" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} filer" @@ -269,33 +265,37 @@ msgstr "Mappe" msgid "From link" msgstr "Fra link" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Fortryd upload" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Her er tomt. Upload noget!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Download" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Upload for stor" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Filerne, du prøver at uploade, er større end den maksimale størrelse for fil-upload på denne server." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Filerne bliver indlæst, vent venligst." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Indlæser" diff --git a/l10n/da/files_trashbin.po b/l10n/da/files_trashbin.po new file mode 100644 index 0000000000..f79e0b1579 --- /dev/null +++ b/l10n/da/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Danish (http://www.transifex.com/projects/p/owncloud/language/da/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: da\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/de/core.po b/l10n/de/core.po index 9e08918d71..ef51cc996c 100644 --- a/l10n/de/core.po +++ b/l10n/de/core.po @@ -23,8 +23,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:47+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: German (http://www.transifex.com/projects/p/owncloud/language/de/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/de/files.po b/l10n/de/files.po index 2f2ff6e3ee..93e568ef6e 100644 --- a/l10n/de/files.po +++ b/l10n/de/files.po @@ -27,8 +27,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:27+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: German (http://www.transifex.com/projects/p/owncloud/language/de/)\n" "MIME-Version: 1.0\n" @@ -74,7 +74,7 @@ msgstr "Fehler beim Schreiben auf die Festplatte" #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "Nicht genug Speicherplatz verfügbar" #: ajax/upload.php:82 msgid "Invalid directory." @@ -84,15 +84,15 @@ msgstr "Ungültiges Verzeichnis" msgid "Files" msgstr "Dateien" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Nicht mehr freigeben" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Löschen" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Umbenennen" @@ -116,7 +116,7 @@ msgstr "abbrechen" msgid "replaced {new_name}" msgstr "{new_name} wurde ersetzt" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "rückgängig machen" @@ -124,13 +124,9 @@ msgstr "rückgängig machen" msgid "replaced {new_name} with {old_name}" msgstr "{old_name} ersetzt durch {new_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "Freigabe von {files} aufgehoben" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "{files} gelöscht" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -154,78 +150,78 @@ msgstr "Ihr Speicherplatz ist voll, Dateien können nicht mehr aktualisiert oder msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "Ihr Speicherplatz ist fast aufgebraucht ({usedSpacePercent}%)" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "Dein Download wird vorbereitet. Dies kann bei größeren Dateien etwas dauern." -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Deine Datei kann nicht hochgeladen werden, da sie entweder ein Verzeichnis oder 0 Bytes groß ist." -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Fehler beim Upload" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Schließen" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Ausstehend" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "Eine Datei wird hoch geladen" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} Dateien werden hochgeladen" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Upload abgebrochen." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Dateiupload läuft. Wenn Du die Seite jetzt verlässt, wird der Upload abgebrochen." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "Die URL darf nicht leer sein" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "Ungültiger Verzeichnisname. Die Nutzung von \"Shared\" ist ownCloud vorbehalten." -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Name" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Größe" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Bearbeitet" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 Ordner" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} Ordner" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 Datei" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} Dateien" @@ -281,33 +277,37 @@ msgstr "Ordner" msgid "From link" msgstr "Von einem Link" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Upload abbrechen" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Alles leer. Lade etwas hoch!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Herunterladen" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Upload zu groß" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Die Datei überschreitet die Maximalgröße für Uploads auf diesem Server." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Dateien werden gescannt, bitte warten." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Scanne" diff --git a/l10n/de/files_trashbin.po b/l10n/de/files_trashbin.po new file mode 100644 index 0000000000..0b445ccb0e --- /dev/null +++ b/l10n/de/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: German (http://www.transifex.com/projects/p/owncloud/language/de/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: de\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/de_DE/core.po b/l10n/de_DE/core.po index 274621ffd7..f1b0ea2e3c 100644 --- a/l10n/de_DE/core.po +++ b/l10n/de_DE/core.po @@ -24,8 +24,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:47+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: German (Germany) (http://www.transifex.com/projects/p/owncloud/language/de_DE/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/de_DE/files.po b/l10n/de_DE/files.po index a452edb4ac..dab36be8e0 100644 --- a/l10n/de_DE/files.po +++ b/l10n/de_DE/files.po @@ -28,8 +28,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" "Last-Translator: I Robot \n" "Language-Team: German (Germany) (http://www.transifex.com/projects/p/owncloud/language/de_DE/)\n" "MIME-Version: 1.0\n" @@ -75,7 +75,7 @@ msgstr "Fehler beim Schreiben auf die Festplatte" #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "Nicht genügend Speicherplatz verfügbar" #: ajax/upload.php:82 msgid "Invalid directory." @@ -85,15 +85,15 @@ msgstr "Ungültiges Verzeichnis." msgid "Files" msgstr "Dateien" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Nicht mehr freigeben" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Löschen" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Umbenennen" @@ -117,7 +117,7 @@ msgstr "abbrechen" msgid "replaced {new_name}" msgstr "{new_name} wurde ersetzt" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "rückgängig machen" @@ -125,13 +125,9 @@ msgstr "rückgängig machen" msgid "replaced {new_name} with {old_name}" msgstr "{old_name} wurde ersetzt durch {new_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "Freigabe für {files} beendet" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "{files} gelöscht" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -155,78 +151,78 @@ msgstr "Ihr Speicher ist voll. Daher können keine Dateien mehr aktualisiert ode msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "Ihr Speicher ist fast voll ({usedSpacePercent}%)" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "Ihr Download wird vorbereitet. Dies kann bei größeren Dateien einen Moment dauern." -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Ihre Datei kann nicht hochgeladen werden, da sie entweder ein Verzeichnis oder 0 Bytes groß ist." -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Fehler beim Upload" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Schließen" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Ausstehend" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "1 Datei wird hochgeladen" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} Dateien wurden hochgeladen" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Upload abgebrochen." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Der Dateiupload läuft. Wenn Sie die Seite jetzt verlassen, wird der Upload abgebrochen." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "Die URL darf nicht leer sein." -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "Ungültiger Verzeichnisname. Die Nutzung von \"Shared\" ist ownCloud vorbehalten" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Name" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Größe" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Bearbeitet" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 Ordner" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} Ordner" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 Datei" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} Dateien" @@ -282,33 +278,37 @@ msgstr "Ordner" msgid "From link" msgstr "Von einem Link" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Upload abbrechen" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Alles leer. Bitte laden Sie etwas hoch!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Herunterladen" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Der Upload ist zu groß" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Die Datei überschreitet die Maximalgröße für Uploads auf diesem Server." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Dateien werden gescannt, bitte warten." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Scanne" diff --git a/l10n/de_DE/files_trashbin.po b/l10n/de_DE/files_trashbin.po new file mode 100644 index 0000000000..7cf2c7e39a --- /dev/null +++ b/l10n/de_DE/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: German (Germany) (http://www.transifex.com/projects/p/owncloud/language/de_DE/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: de_DE\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/el/core.po b/l10n/el/core.po index 6bb746ef12..07b4bd3275 100644 --- a/l10n/el/core.po +++ b/l10n/el/core.po @@ -15,8 +15,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Greek (http://www.transifex.com/projects/p/owncloud/language/el/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/el/files.po b/l10n/el/files.po index 23dc33a5a2..5b329a9908 100644 --- a/l10n/el/files.po +++ b/l10n/el/files.po @@ -15,8 +15,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:27+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Greek (http://www.transifex.com/projects/p/owncloud/language/el/)\n" "MIME-Version: 1.0\n" @@ -62,7 +62,7 @@ msgstr "Αποτυχία εγγραφής στο δίσκο" #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "Δεν υπάρχει αρκετός διαθέσιμος χώρος" #: ajax/upload.php:82 msgid "Invalid directory." @@ -72,15 +72,15 @@ msgstr "Μη έγκυρος φάκελος." msgid "Files" msgstr "Αρχεία" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Διακοπή κοινής χρήσης" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Διαγραφή" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Μετονομασία" @@ -104,7 +104,7 @@ msgstr "ακύρωση" msgid "replaced {new_name}" msgstr "{new_name} αντικαταστάθηκε" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "αναίρεση" @@ -112,13 +112,9 @@ msgstr "αναίρεση" msgid "replaced {new_name} with {old_name}" msgstr "αντικαταστάθηκε το {new_name} με {old_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "μη διαμοιρασμένα {files}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "διαγραμμένα {files}" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -142,78 +138,78 @@ msgstr "Ο αποθηκευτικός σας χώρος είναι γεμάτο msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "Ο αποθηκευτικός χώρος είναι σχεδόν γεμάτος ({usedSpacePercent}%)" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "Η λήψη προετοιμάζεται. Αυτό μπορεί να πάρει ώρα εάν τα αρχεία έχουν μεγάλο μέγεθος." -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Αδυναμία στην αποστολή του αρχείου σας αφού είναι φάκελος ή έχει 0 bytes" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Σφάλμα Αποστολής" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Κλείσιμο" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Εκκρεμεί" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "1 αρχείο ανεβαίνει" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} αρχεία ανεβαίνουν" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Η αποστολή ακυρώθηκε." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Η αποστολή του αρχείου βρίσκεται σε εξέλιξη. Το κλείσιμο της σελίδας θα ακυρώσει την αποστολή." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "Η URL δεν πρέπει να είναι κενή." -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "Μη έγκυρο όνομα φακέλου. Η χρήση του 'Κοινόχρηστος' χρησιμοποιείται από ο Owncloud" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Όνομα" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Μέγεθος" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Τροποποιήθηκε" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 φάκελος" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} φάκελοι" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 αρχείο" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} αρχεία" @@ -269,33 +265,37 @@ msgstr "Φάκελος" msgid "From link" msgstr "Από σύνδεσμο" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Ακύρωση αποστολής" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Δεν υπάρχει τίποτα εδώ. Ανέβασε κάτι!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Λήψη" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Πολύ μεγάλο αρχείο προς αποστολή" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Τα αρχεία που προσπαθείτε να ανεβάσετε υπερβαίνουν το μέγιστο μέγεθος αποστολής αρχείων σε αυτόν τον διακομιστή." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Τα αρχεία σαρώνονται, παρακαλώ περιμένετε" -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Τρέχουσα αναζήτηση " diff --git a/l10n/el/files_trashbin.po b/l10n/el/files_trashbin.po new file mode 100644 index 0000000000..af301af1b4 --- /dev/null +++ b/l10n/el/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Greek (http://www.transifex.com/projects/p/owncloud/language/el/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: el\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/eo/core.po b/l10n/eo/core.po index 87f8a4fe77..1347e38ac5 100644 --- a/l10n/eo/core.po +++ b/l10n/eo/core.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Esperanto (http://www.transifex.com/projects/p/owncloud/language/eo/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/eo/files.po b/l10n/eo/files.po index 1feb4c9d82..fd6b90487f 100644 --- a/l10n/eo/files.po +++ b/l10n/eo/files.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Esperanto (http://www.transifex.com/projects/p/owncloud/language/eo/)\n" "MIME-Version: 1.0\n" @@ -57,7 +57,7 @@ msgstr "Malsukcesis skribo al disko" #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "Ne haveblas sufiĉa spaco" #: ajax/upload.php:82 msgid "Invalid directory." @@ -67,15 +67,15 @@ msgstr "Nevalida dosierujo." msgid "Files" msgstr "Dosieroj" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Malkunhavigi" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Forigi" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Alinomigi" @@ -99,7 +99,7 @@ msgstr "nuligi" msgid "replaced {new_name}" msgstr "anstataŭiĝis {new_name}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "malfari" @@ -107,13 +107,9 @@ msgstr "malfari" msgid "replaced {new_name} with {old_name}" msgstr "anstataŭiĝis {new_name} per {old_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "malkunhaviĝis {files}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "foriĝis {files}" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -137,78 +133,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "Via elŝuto pretiĝatas. Ĉi tio povas daŭri iom da tempo se la dosieroj grandas." -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Ne eblis alŝuti vian dosieron ĉar ĝi estas dosierujo aŭ havas 0 duumokojn" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Alŝuta eraro" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Fermi" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Traktotaj" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "1 dosiero estas alŝutata" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} dosieroj alŝutatas" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "La alŝuto nuliĝis." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Dosieralŝuto plenumiĝas. Lasi la paĝon nun nuligus la alŝuton." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "URL ne povas esti malplena." -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "Nevalida dosierujnomo. Uzo de “Shared” rezervatas de Owncloud." -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Nomo" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Grando" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Modifita" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 dosierujo" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} dosierujoj" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 dosiero" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} dosierujoj" @@ -264,33 +260,37 @@ msgstr "Dosierujo" msgid "From link" msgstr "El ligilo" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Nuligi alŝuton" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Nenio estas ĉi tie. Alŝutu ion!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Elŝuti" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Elŝuto tro larĝa" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "La dosieroj, kiujn vi provas alŝuti, transpasas la maksimuman grandon por dosieralŝutoj en ĉi tiu servilo." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Dosieroj estas skanataj, bonvolu atendi." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Nuna skano" diff --git a/l10n/eo/files_trashbin.po b/l10n/eo/files_trashbin.po new file mode 100644 index 0000000000..bddacc0366 --- /dev/null +++ b/l10n/eo/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Esperanto (http://www.transifex.com/projects/p/owncloud/language/eo/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: eo\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/es/core.po b/l10n/es/core.po index a15a24305d..29d6918611 100644 --- a/l10n/es/core.po +++ b/l10n/es/core.po @@ -19,8 +19,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 15:30+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: felix.liberio \n" "Language-Team: Spanish (http://www.transifex.com/projects/p/owncloud/language/es/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/es/files.po b/l10n/es/files.po index e5f52a7217..d927503e75 100644 --- a/l10n/es/files.po +++ b/l10n/es/files.po @@ -16,8 +16,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:27+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Spanish (http://www.transifex.com/projects/p/owncloud/language/es/)\n" "MIME-Version: 1.0\n" @@ -63,7 +63,7 @@ msgstr "La escritura en disco ha fallado" #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "No hay suficiente espacio disponible" #: ajax/upload.php:82 msgid "Invalid directory." @@ -73,15 +73,15 @@ msgstr "Directorio invalido." msgid "Files" msgstr "Archivos" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Dejar de compartir" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Eliminar" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Renombrar" @@ -105,7 +105,7 @@ msgstr "cancelar" msgid "replaced {new_name}" msgstr "reemplazado {new_name}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "deshacer" @@ -113,13 +113,9 @@ msgstr "deshacer" msgid "replaced {new_name} with {old_name}" msgstr "reemplazado {new_name} con {old_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "{files} descompartidos" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "{files} eliminados" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -143,78 +139,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "Tu descarga esta siendo preparada. Esto puede tardar algun tiempo si los archivos son muy grandes." -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "No ha sido posible subir tu archivo porque es un directorio o tiene 0 bytes" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Error al subir el archivo" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "cerrrar" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Pendiente" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "subiendo 1 archivo" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "Subiendo {count} archivos" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Subida cancelada." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "La subida del archivo está en proceso. Salir de la página ahora cancelará la subida." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "La URL no puede estar vacía." -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "Nombre de carpeta invalido. El uso de \"Shared\" esta reservado para Owncloud" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Nombre" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Tamaño" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Modificado" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 carpeta" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} carpetas" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 archivo" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} archivos" @@ -270,33 +266,37 @@ msgstr "Carpeta" msgid "From link" msgstr "Desde el enlace" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Cancelar subida" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Aquí no hay nada. ¡Sube algo!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Descargar" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "El archivo es demasiado grande" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Los archivos que estás intentando subir sobrepasan el tamaño máximo permitido por este servidor." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Se están escaneando los archivos, por favor espere." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Ahora escaneando" diff --git a/l10n/es/files_trashbin.po b/l10n/es/files_trashbin.po new file mode 100644 index 0000000000..2b25413fcc --- /dev/null +++ b/l10n/es/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Spanish (http://www.transifex.com/projects/p/owncloud/language/es/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/es_AR/core.po b/l10n/es_AR/core.po index 3b362910e2..71d928cfc4 100644 --- a/l10n/es_AR/core.po +++ b/l10n/es_AR/core.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 16:00+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: cjtess \n" "Language-Team: Spanish (Argentina) (http://www.transifex.com/projects/p/owncloud/language/es_AR/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/es_AR/files.po b/l10n/es_AR/files.po index b736273d87..dd36d78dc3 100644 --- a/l10n/es_AR/files.po +++ b/l10n/es_AR/files.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Spanish (Argentina) (http://www.transifex.com/projects/p/owncloud/language/es_AR/)\n" "MIME-Version: 1.0\n" @@ -57,7 +57,7 @@ msgstr "Error al escribir en el disco" #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "No hay suficiente espacio disponible" #: ajax/upload.php:82 msgid "Invalid directory." @@ -67,15 +67,15 @@ msgstr "Directorio invalido." msgid "Files" msgstr "Archivos" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Dejar de compartir" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Borrar" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Cambiar nombre" @@ -99,7 +99,7 @@ msgstr "cancelar" msgid "replaced {new_name}" msgstr "reemplazado {new_name}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "deshacer" @@ -107,13 +107,9 @@ msgstr "deshacer" msgid "replaced {new_name} with {old_name}" msgstr "reemplazado {new_name} con {old_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "{files} se dejaron de compartir" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "{files} borrados" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -137,78 +133,78 @@ msgstr "El almacenamiento está lleno, los archivos no se pueden seguir actualiz msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "El almacenamiento está casi lleno ({usedSpacePercent}%)" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "Tu descarga esta siendo preparada. Esto puede tardar algun tiempo si los archivos son muy grandes." -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "No fue posible subir el archivo porque es un directorio o porque su tamaño es 0 bytes" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Error al subir el archivo" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Cerrar" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Pendiente" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "Subiendo 1 archivo" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "Subiendo {count} archivos" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "La subida fue cancelada" -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "La subida del archivo está en proceso. Si salís de la página ahora, la subida se cancelará." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "La URL no puede estar vacía" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "Nombre de carpeta inválido. El uso de 'Shared' está reservado por ownCloud" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Nombre" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Tamaño" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Modificado" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 directorio" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} directorios" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 archivo" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} archivos" @@ -264,33 +260,37 @@ msgstr "Carpeta" msgid "From link" msgstr "Desde enlace" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Cancelar subida" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "No hay nada. ¡Subí contenido!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Descargar" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "El archivo es demasiado grande" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Los archivos que intentás subir sobrepasan el tamaño máximo " -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Se están escaneando los archivos, por favor esperá." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Escaneo actual" diff --git a/l10n/es_AR/files_trashbin.po b/l10n/es_AR/files_trashbin.po new file mode 100644 index 0000000000..d3f144da17 --- /dev/null +++ b/l10n/es_AR/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Spanish (Argentina) (http://www.transifex.com/projects/p/owncloud/language/es_AR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_AR\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/et_EE/core.po b/l10n/et_EE/core.po index 279a9737cd..2e7a0ddd0d 100644 --- a/l10n/et_EE/core.po +++ b/l10n/et_EE/core.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Estonian (Estonia) (http://www.transifex.com/projects/p/owncloud/language/et_EE/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/et_EE/files.po b/l10n/et_EE/files.po index 220476a877..1c693682ee 100644 --- a/l10n/et_EE/files.po +++ b/l10n/et_EE/files.po @@ -9,8 +9,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Estonian (Estonia) (http://www.transifex.com/projects/p/owncloud/language/et_EE/)\n" "MIME-Version: 1.0\n" @@ -66,15 +66,15 @@ msgstr "" msgid "Files" msgstr "Failid" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Lõpeta jagamine" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Kustuta" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "ümber" @@ -98,7 +98,7 @@ msgstr "loobu" msgid "replaced {new_name}" msgstr "asendatud nimega {new_name}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "tagasi" @@ -106,13 +106,9 @@ msgstr "tagasi" msgid "replaced {new_name} with {old_name}" msgstr "asendas nime {old_name} nimega {new_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "jagamata {files}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "kustutatud {files}" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -136,78 +132,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Sinu faili üleslaadimine ebaõnnestus, kuna see on kaust või selle suurus on 0 baiti" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Üleslaadimise viga" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Sulge" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Ootel" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "1 faili üleslaadimisel" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} faili üleslaadimist" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Üleslaadimine tühistati." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Faili üleslaadimine on töös. Lehelt lahkumine katkestab selle üleslaadimise." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "URL ei saa olla tühi." -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Nimi" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Suurus" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Muudetud" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 kaust" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} kausta" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 fail" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} faili" @@ -263,33 +259,37 @@ msgstr "Kaust" msgid "From link" msgstr "Allikast" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Tühista üleslaadimine" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Siin pole midagi. Lae midagi üles!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Lae alla" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Üleslaadimine on liiga suur" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Failid, mida sa proovid üles laadida, ületab serveri poolt üleslaetavatele failidele määratud maksimaalse suuruse." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Faile skannitakse, palun oota" -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Praegune skannimine" diff --git a/l10n/et_EE/files_trashbin.po b/l10n/et_EE/files_trashbin.po new file mode 100644 index 0000000000..f50b6ff074 --- /dev/null +++ b/l10n/et_EE/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Estonian (Estonia) (http://www.transifex.com/projects/p/owncloud/language/et_EE/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: et_EE\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/eu/core.po b/l10n/eu/core.po index 2bbe9c7c6a..e4ffe9890e 100644 --- a/l10n/eu/core.po +++ b/l10n/eu/core.po @@ -11,8 +11,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 22:50+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: asieriko \n" "Language-Team: Basque (http://www.transifex.com/projects/p/owncloud/language/eu/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/eu/files.po b/l10n/eu/files.po index aadd0656f8..e9705b048c 100644 --- a/l10n/eu/files.po +++ b/l10n/eu/files.po @@ -11,8 +11,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Basque (http://www.transifex.com/projects/p/owncloud/language/eu/)\n" "MIME-Version: 1.0\n" @@ -58,7 +58,7 @@ msgstr "Errore bat izan da diskoan idazterakoan" #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "Ez dago leku nahikorik." #: ajax/upload.php:82 msgid "Invalid directory." @@ -68,15 +68,15 @@ msgstr "Baliogabeko karpeta." msgid "Files" msgstr "Fitxategiak" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Ez elkarbanatu" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Ezabatu" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Berrizendatu" @@ -100,7 +100,7 @@ msgstr "ezeztatu" msgid "replaced {new_name}" msgstr "ordezkatua {new_name}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "desegin" @@ -108,13 +108,9 @@ msgstr "desegin" msgid "replaced {new_name} with {old_name}" msgstr " {new_name}-k {old_name} ordezkatu du" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "elkarbanaketa utzita {files}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "ezabatuta {files}" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -138,78 +134,78 @@ msgstr "Zure biltegiratzea beterik dago, ezingo duzu aurrerantzean fitxategirik msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "Zure biltegiratzea nahiko beterik dago (%{usedSpacePercent})" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "Zure deskarga prestatu egin behar da. Denbora bat har lezake fitxategiak handiak badira. " -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Ezin da zure fitxategia igo, karpeta bat da edo 0 byt ditu" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Igotzean errore bat suertatu da" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Itxi" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Zain" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "fitxategi 1 igotzen" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} fitxategi igotzen" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Igoera ezeztatuta" -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Fitxategien igoera martxan da. Orria orain uzteak igoera ezeztatutko du." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "URLa ezin da hutsik egon." -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "Baliogabeako karpeta izena. 'Shared' izena Owncloudek erreserbatzen du" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Izena" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Tamaina" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Aldatuta" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "karpeta bat" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} karpeta" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "fitxategi bat" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} fitxategi" @@ -265,33 +261,37 @@ msgstr "Karpeta" msgid "From link" msgstr "Estekatik" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Ezeztatu igoera" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Ez dago ezer. Igo zerbait!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Deskargatu" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Igotakoa handiegia da" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Igotzen saiatzen ari zaren fitxategiak zerbitzari honek igotzeko onartzen duena baino handiagoak dira." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Fitxategiak eskaneatzen ari da, itxoin mezedez." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Orain eskaneatzen ari da" diff --git a/l10n/eu/files_trashbin.po b/l10n/eu/files_trashbin.po new file mode 100644 index 0000000000..fe82ebdbfc --- /dev/null +++ b/l10n/eu/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Basque (http://www.transifex.com/projects/p/owncloud/language/eu/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: eu\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/fa/core.po b/l10n/fa/core.po index 217e58d5bd..7790d77f9b 100644 --- a/l10n/fa/core.po +++ b/l10n/fa/core.po @@ -9,8 +9,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Persian (http://www.transifex.com/projects/p/owncloud/language/fa/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/fa/files.po b/l10n/fa/files.po index e0b92b3f69..f101ae7637 100644 --- a/l10n/fa/files.po +++ b/l10n/fa/files.po @@ -11,8 +11,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Persian (http://www.transifex.com/projects/p/owncloud/language/fa/)\n" "MIME-Version: 1.0\n" @@ -58,7 +58,7 @@ msgstr "نوشتن بر روی دیسک سخت ناموفق بود" #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "فضای کافی در دسترس نیست" #: ajax/upload.php:82 msgid "Invalid directory." @@ -68,15 +68,15 @@ msgstr "فهرست راهنما نامعتبر می باشد." msgid "Files" msgstr "فایل ها" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "لغو اشتراک" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "پاک کردن" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "تغییرنام" @@ -100,7 +100,7 @@ msgstr "لغو" msgid "replaced {new_name}" msgstr "{نام _جدید} جایگزین شد " -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "بازگشت" @@ -108,13 +108,9 @@ msgstr "بازگشت" msgid "replaced {new_name} with {old_name}" msgstr "{نام_جدید} با { نام_قدیمی} جایگزین شد." -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "{ فایل های } قسمت نشده" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "{ فایل های } پاک شده" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -138,78 +134,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "دانلود شما در حال آماده شدن است. در صورتیکه پرونده ها بزرگ باشند ممکن است مدتی طول بکشد." -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "ناتوان در بارگذاری یا فایل یک پوشه است یا 0بایت دارد" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "خطا در بار گذاری" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "بستن" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "در انتظار" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "1 پرونده آپلود شد." -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{ شمار } فایل های در حال آپلود" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "بار گذاری لغو شد" -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "آپلودکردن پرونده در حال پیشرفت است. در صورت خروج از صفحه آپلود لغو میگردد. " -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "URL نمی تواند خالی باشد." -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "نام پوشه نامعتبر است. استفاده از \" به اشتراک گذاشته شده \" متعلق به سایت Owncloud است." -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "نام" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "اندازه" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "تغییر یافته" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 پوشه" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{ شمار} پوشه ها" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 پرونده" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{ شمار } فایل ها" @@ -265,33 +261,37 @@ msgstr "پوشه" msgid "From link" msgstr "از پیوند" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "متوقف کردن بار گذاری" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "اینجا هیچ چیز نیست." -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "بارگیری" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "حجم بارگذاری بسیار زیاد است" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "فایلها بیش از حد تعیین شده در این سرور هستند\nمترجم:با تغییر فایل php,ini میتوان این محدودیت را برطرف کرد" -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "پرونده ها در حال بازرسی هستند لطفا صبر کنید" -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "بازرسی کنونی" diff --git a/l10n/fa/files_trashbin.po b/l10n/fa/files_trashbin.po new file mode 100644 index 0000000000..99f4a8d73e --- /dev/null +++ b/l10n/fa/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Persian (http://www.transifex.com/projects/p/owncloud/language/fa/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fa\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/fi_FI/core.po b/l10n/fi_FI/core.po index 3ff113a54d..cd1630bfcf 100644 --- a/l10n/fi_FI/core.po +++ b/l10n/fi_FI/core.po @@ -14,8 +14,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 15:30+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: Jiri Grönroos \n" "Language-Team: Finnish (Finland) (http://www.transifex.com/projects/p/owncloud/language/fi_FI/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/fi_FI/files.po b/l10n/fi_FI/files.po index b13a9ab58b..0208f51f42 100644 --- a/l10n/fi_FI/files.po +++ b/l10n/fi_FI/files.po @@ -12,8 +12,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Finnish (Finland) (http://www.transifex.com/projects/p/owncloud/language/fi_FI/)\n" "MIME-Version: 1.0\n" @@ -59,7 +59,7 @@ msgstr "Levylle kirjoitus epäonnistui" #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "Tilaa ei ole riittävästi" #: ajax/upload.php:82 msgid "Invalid directory." @@ -69,15 +69,15 @@ msgstr "Virheellinen kansio." msgid "Files" msgstr "Tiedostot" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Peru jakaminen" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Poista" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Nimeä uudelleen" @@ -101,7 +101,7 @@ msgstr "peru" msgid "replaced {new_name}" msgstr "" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "kumoa" @@ -109,12 +109,8 @@ msgstr "kumoa" msgid "replaced {new_name} with {old_name}" msgstr "" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "" - -#: js/filelist.js:288 -msgid "deleted {files}" +#: js/filelist.js:280 +msgid "perform delete operation" msgstr "" #: js/files.js:52 @@ -139,78 +135,78 @@ msgstr "Tallennustila on loppu, tiedostoja ei voi enää päivittää tai synkro msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "Tallennustila on melkein loppu ({usedSpacePercent}%)" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "Lataustasi valmistellaan. Tämä saattaa kestää hetken, jos tiedostot ovat suuria kooltaan." -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Tiedoston lähetys epäonnistui, koska sen koko on 0 tavua tai kyseessä on kansio" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Lähetysvirhe." -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Sulje" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Odottaa" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Lähetys peruttu." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Tiedoston lähetys on meneillään. Sivulta poistuminen nyt peruu tiedoston lähetyksen." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "Verkko-osoite ei voi olla tyhjä" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Nimi" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Koko" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Muutettu" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 kansio" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} kansiota" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 tiedosto" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} tiedostoa" @@ -266,33 +262,37 @@ msgstr "Kansio" msgid "From link" msgstr "Linkistä" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Peru lähetys" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Täällä ei ole mitään. Lähetä tänne jotakin!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Lataa" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Lähetettävä tiedosto on liian suuri" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Lähetettäväksi valitsemasi tiedostot ylittävät palvelimen salliman tiedostokoon rajan." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Tiedostoja tarkistetaan, odota hetki." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Tämänhetkinen tutkinta" diff --git a/l10n/fi_FI/files_trashbin.po b/l10n/fi_FI/files_trashbin.po new file mode 100644 index 0000000000..6c75aef2cf --- /dev/null +++ b/l10n/fi_FI/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Finnish (Finland) (http://www.transifex.com/projects/p/owncloud/language/fi_FI/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fi_FI\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/fr/core.po b/l10n/fr/core.po index 668258ddc5..81a4e6bd2e 100644 --- a/l10n/fr/core.po +++ b/l10n/fr/core.po @@ -19,8 +19,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: French (http://www.transifex.com/projects/p/owncloud/language/fr/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/fr/files.po b/l10n/fr/files.po index 103a5bd308..de61e4b057 100644 --- a/l10n/fr/files.po +++ b/l10n/fr/files.po @@ -20,8 +20,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:27+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: French (http://www.transifex.com/projects/p/owncloud/language/fr/)\n" "MIME-Version: 1.0\n" @@ -67,7 +67,7 @@ msgstr "Erreur d'écriture sur le disque" #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "Espace disponible insuffisant" #: ajax/upload.php:82 msgid "Invalid directory." @@ -77,15 +77,15 @@ msgstr "Dossier invalide." msgid "Files" msgstr "Fichiers" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Ne plus partager" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Supprimer" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Renommer" @@ -109,7 +109,7 @@ msgstr "annuler" msgid "replaced {new_name}" msgstr "{new_name} a été remplacé" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "annuler" @@ -117,13 +117,9 @@ msgstr "annuler" msgid "replaced {new_name} with {old_name}" msgstr "{new_name} a été remplacé par {old_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "Fichiers non partagés : {files}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "Fichiers supprimés : {files}" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -147,78 +143,78 @@ msgstr "Votre espage de stockage est plein, les fichiers ne peuvent plus être t msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "Votre espace de stockage est presque plein ({usedSpacePercent}%)" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "Votre téléchargement est cours de préparation. Ceci peut nécessiter un certain temps si les fichiers sont volumineux." -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Impossible de charger vos fichiers car il s'agit d'un dossier ou le fichier fait 0 octet." -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Erreur de chargement" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Fermer" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "En cours" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "1 fichier en cours de téléchargement" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} fichiers téléversés" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Chargement annulé." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "L'envoi du fichier est en cours. Quitter cette page maintenant annulera l'envoi du fichier." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "L'URL ne peut-être vide" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "Nom de dossier invalide. L'utilisation du mot 'Shared' est réservée à Owncloud" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Nom" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Taille" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Modifié" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 dossier" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} dossiers" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 fichier" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} fichiers" @@ -274,33 +270,37 @@ msgstr "Dossier" msgid "From link" msgstr "Depuis le lien" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Annuler l'envoi" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Il n'y a rien ici ! Envoyez donc quelque chose :)" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Télécharger" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Fichier trop volumineux" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Les fichiers que vous essayez d'envoyer dépassent la taille maximale permise par ce serveur." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Les fichiers sont en cours d'analyse, veuillez patienter." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Analyse en cours" diff --git a/l10n/fr/files_trashbin.po b/l10n/fr/files_trashbin.po new file mode 100644 index 0000000000..997e15235b --- /dev/null +++ b/l10n/fr/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: French (http://www.transifex.com/projects/p/owncloud/language/fr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/gl/core.po b/l10n/gl/core.po index 3ae2a9276e..9b46998107 100644 --- a/l10n/gl/core.po +++ b/l10n/gl/core.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Galician (http://www.transifex.com/projects/p/owncloud/language/gl/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/gl/files.po b/l10n/gl/files.po index ac9f8a4b62..19fcb367ba 100644 --- a/l10n/gl/files.po +++ b/l10n/gl/files.po @@ -9,8 +9,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Galician (http://www.transifex.com/projects/p/owncloud/language/gl/)\n" "MIME-Version: 1.0\n" @@ -56,7 +56,7 @@ msgstr "Erro ao escribir no disco" #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "O espazo dispoñíbel é insuficiente" #: ajax/upload.php:82 msgid "Invalid directory." @@ -66,15 +66,15 @@ msgstr "O directorio é incorrecto." msgid "Files" msgstr "Ficheiros" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Deixar de compartir" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Eliminar" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Mudar o nome" @@ -98,7 +98,7 @@ msgstr "cancelar" msgid "replaced {new_name}" msgstr "substituír {new_name}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "desfacer" @@ -106,13 +106,9 @@ msgstr "desfacer" msgid "replaced {new_name} with {old_name}" msgstr "substituír {new_name} polo {old_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "{files} sen compartir" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "{files} eliminados" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -136,78 +132,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Non se puido subir o ficheiro pois ou é un directorio ou ten 0 bytes" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Erro na subida" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Pechar" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Pendentes" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "1 ficheiro subíndose" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} ficheiros subíndose" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Subida cancelada." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "A subida do ficheiro está en curso. Saír agora da páxina cancelará a subida." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "URL non pode quedar baleiro." -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "Nome de cartafol non válido. O uso de 'Shared' está reservado por Owncloud" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Nome" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Tamaño" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Modificado" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 cartafol" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} cartafoles" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 ficheiro" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} ficheiros" @@ -263,33 +259,37 @@ msgstr "Cartafol" msgid "From link" msgstr "Dende a ligazón" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Cancelar a subida" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Nada por aquí. Envía algo." -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Descargar" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Envío demasiado grande" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Os ficheiros que trata de subir superan o tamaño máximo permitido neste servidor" -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Estanse analizando os ficheiros. Agarda." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Análise actual" diff --git a/l10n/gl/files_trashbin.po b/l10n/gl/files_trashbin.po new file mode 100644 index 0000000000..7c20517d24 --- /dev/null +++ b/l10n/gl/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Galician (http://www.transifex.com/projects/p/owncloud/language/gl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: gl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/he/core.po b/l10n/he/core.po index 77438c94d3..a8d90561ae 100644 --- a/l10n/he/core.po +++ b/l10n/he/core.po @@ -12,8 +12,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Hebrew (http://www.transifex.com/projects/p/owncloud/language/he/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/he/files.po b/l10n/he/files.po index 9b769f346b..d40c318198 100644 --- a/l10n/he/files.po +++ b/l10n/he/files.po @@ -11,8 +11,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Hebrew (http://www.transifex.com/projects/p/owncloud/language/he/)\n" "MIME-Version: 1.0\n" @@ -68,15 +68,15 @@ msgstr "" msgid "Files" msgstr "קבצים" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "הסר שיתוף" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "מחיקה" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "שינוי שם" @@ -100,7 +100,7 @@ msgstr "ביטול" msgid "replaced {new_name}" msgstr "{new_name} הוחלף" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "ביטול" @@ -108,13 +108,9 @@ msgstr "ביטול" msgid "replaced {new_name} with {old_name}" msgstr "{new_name} הוחלף ב־{old_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "בוטל שיתופם של {files}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "{files} נמחקו" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -138,78 +134,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "לא יכול להעלות את הקובץ מכיוון שזו תקיה או שמשקל הקובץ 0 בתים" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "שגיאת העלאה" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "סגירה" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "ממתין" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "קובץ אחד נשלח" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} קבצים נשלחים" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "ההעלאה בוטלה." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "מתבצעת כעת העלאת קבצים. עזיבה של העמוד תבטל את ההעלאה." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "קישור אינו יכול להיות ריק." -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "שם" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "גודל" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "זמן שינוי" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "תיקייה אחת" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} תיקיות" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "קובץ אחד" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} קבצים" @@ -265,33 +261,37 @@ msgstr "תיקייה" msgid "From link" msgstr "מקישור" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "ביטול ההעלאה" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "אין כאן שום דבר. אולי ברצונך להעלות משהו?" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "הורדה" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "העלאה גדולה מידי" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "הקבצים שניסית להעלות חרגו מהגודל המקסימלי להעלאת קבצים על שרת זה." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "הקבצים נסרקים, נא להמתין." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "הסריקה הנוכחית" diff --git a/l10n/he/files_trashbin.po b/l10n/he/files_trashbin.po new file mode 100644 index 0000000000..ecba90622c --- /dev/null +++ b/l10n/he/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Hebrew (http://www.transifex.com/projects/p/owncloud/language/he/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: he\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/hi/files.po b/l10n/hi/files.po index 699615e59c..c56da3dc54 100644 --- a/l10n/hi/files.po +++ b/l10n/hi/files.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Hindi (http://www.transifex.com/projects/p/owncloud/language/hi/)\n" "MIME-Version: 1.0\n" @@ -64,15 +64,15 @@ msgstr "" msgid "Files" msgstr "" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "" @@ -96,7 +96,7 @@ msgstr "" msgid "replaced {new_name}" msgstr "" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "" @@ -104,12 +104,8 @@ msgstr "" msgid "replaced {new_name} with {old_name}" msgstr "" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "" - -#: js/filelist.js:288 -msgid "deleted {files}" +#: js/filelist.js:280 +msgid "perform delete operation" msgstr "" #: js/files.js:52 @@ -134,78 +130,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "" -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "" -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "" @@ -261,33 +257,37 @@ msgstr "" msgid "From link" msgstr "" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "" -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "" -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "" diff --git a/l10n/hi/files_trashbin.po b/l10n/hi/files_trashbin.po new file mode 100644 index 0000000000..81376782a7 --- /dev/null +++ b/l10n/hi/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Hindi (http://www.transifex.com/projects/p/owncloud/language/hi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hi\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/hr/core.po b/l10n/hr/core.po index 398e7e7728..050cbe3ac7 100644 --- a/l10n/hr/core.po +++ b/l10n/hr/core.po @@ -11,8 +11,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Croatian (http://www.transifex.com/projects/p/owncloud/language/hr/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/hr/files.po b/l10n/hr/files.po index 856858711e..92a63cc100 100644 --- a/l10n/hr/files.po +++ b/l10n/hr/files.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Croatian (http://www.transifex.com/projects/p/owncloud/language/hr/)\n" "MIME-Version: 1.0\n" @@ -67,15 +67,15 @@ msgstr "" msgid "Files" msgstr "Datoteke" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Prekini djeljenje" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Briši" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Promjeni ime" @@ -99,7 +99,7 @@ msgstr "odustani" msgid "replaced {new_name}" msgstr "" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "vrati" @@ -107,12 +107,8 @@ msgstr "vrati" msgid "replaced {new_name} with {old_name}" msgstr "" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "" - -#: js/filelist.js:288 -msgid "deleted {files}" +#: js/filelist.js:280 +msgid "perform delete operation" msgstr "" #: js/files.js:52 @@ -137,78 +133,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Nemoguće poslati datoteku jer je prazna ili je direktorij" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Pogreška pri slanju" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Zatvori" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "U tijeku" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "1 datoteka se učitava" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Slanje poništeno." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Učitavanje datoteke. Napuštanjem stranice će prekinuti učitavanje." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Naziv" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Veličina" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Zadnja promjena" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "" @@ -264,33 +260,37 @@ msgstr "mapa" msgid "From link" msgstr "" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Prekini upload" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Nema ničega u ovoj mapi. Pošalji nešto!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Preuzmi" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Prijenos je preobiman" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Datoteke koje pokušavate prenijeti prelaze maksimalnu veličinu za prijenos datoteka na ovom poslužitelju." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Datoteke se skeniraju, molimo pričekajte." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Trenutno skeniranje" diff --git a/l10n/hr/files_trashbin.po b/l10n/hr/files_trashbin.po new file mode 100644 index 0000000000..8c1029fd3e --- /dev/null +++ b/l10n/hr/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Croatian (http://www.transifex.com/projects/p/owncloud/language/hr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hr\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/hu_HU/core.po b/l10n/hu_HU/core.po index 78c4bb1314..aa5dc24380 100644 --- a/l10n/hu_HU/core.po +++ b/l10n/hu_HU/core.po @@ -12,8 +12,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Hungarian (Hungary) (http://www.transifex.com/projects/p/owncloud/language/hu_HU/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/hu_HU/files.po b/l10n/hu_HU/files.po index 2b869524e8..3fc7f3effb 100644 --- a/l10n/hu_HU/files.po +++ b/l10n/hu_HU/files.po @@ -14,8 +14,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Hungarian (Hungary) (http://www.transifex.com/projects/p/owncloud/language/hu_HU/)\n" "MIME-Version: 1.0\n" @@ -61,7 +61,7 @@ msgstr "Nem sikerült a lemezre történő írás" #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "Nincs elég szabad hely" #: ajax/upload.php:82 msgid "Invalid directory." @@ -71,15 +71,15 @@ msgstr "Érvénytelen mappa." msgid "Files" msgstr "Fájlok" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Megosztás visszavonása" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Törlés" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Átnevezés" @@ -103,7 +103,7 @@ msgstr "mégse" msgid "replaced {new_name}" msgstr "a(z) {new_name} állományt kicseréltük" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "visszavonás" @@ -111,13 +111,9 @@ msgstr "visszavonás" msgid "replaced {new_name} with {old_name}" msgstr "{new_name} fájlt kicseréltük ezzel: {old_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "{files} fájl megosztása visszavonva" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "{files} fájl törölve" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -141,78 +137,78 @@ msgstr "A tároló tele van, a fájlok nem frissíthetőek vagy szinkronizálhat msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "A tároló majdnem tele van ({usedSpacePercent}%)" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "Készül a letöltendő állomány. Ez eltarthat egy ideig, ha nagyok a fájlok." -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Nem tölthető fel, mert mappa volt, vagy 0 byte méretű" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Feltöltési hiba" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Bezárás" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Folyamatban" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "1 fájl töltődik föl" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} fájl töltődik föl" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "A feltöltést megszakítottuk." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Fájlfeltöltés van folyamatban. Az oldal elhagyása megszakítja a feltöltést." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "Az URL nem lehet semmi." -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "Érvénytelen mappanév. A név használata csak a Owncloud számára lehetséges." -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Név" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Méret" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Módosítva" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 mappa" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} mappa" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 fájl" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} fájl" @@ -268,33 +264,37 @@ msgstr "Mappa" msgid "From link" msgstr "Feltöltés linkről" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "A feltöltés megszakítása" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Itt nincs semmi. Töltsön fel valamit!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Letöltés" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "A feltöltés túl nagy" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "A feltöltendő állományok mérete meghaladja a kiszolgálón megengedett maximális méretet." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "A fájllista ellenőrzése zajlik, kis türelmet!" -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Ellenőrzés alatt" diff --git a/l10n/hu_HU/files_trashbin.po b/l10n/hu_HU/files_trashbin.po new file mode 100644 index 0000000000..1dcce92d77 --- /dev/null +++ b/l10n/hu_HU/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Hungarian (Hungary) (http://www.transifex.com/projects/p/owncloud/language/hu_HU/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: hu_HU\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/ia/core.po b/l10n/ia/core.po index 7d3302b48f..6359a737f3 100644 --- a/l10n/ia/core.po +++ b/l10n/ia/core.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Interlingua (http://www.transifex.com/projects/p/owncloud/language/ia/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/ia/files.po b/l10n/ia/files.po index 185bc455a7..bbf335b031 100644 --- a/l10n/ia/files.po +++ b/l10n/ia/files.po @@ -9,8 +9,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Interlingua (http://www.transifex.com/projects/p/owncloud/language/ia/)\n" "MIME-Version: 1.0\n" @@ -66,15 +66,15 @@ msgstr "" msgid "Files" msgstr "Files" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Deler" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "" @@ -98,7 +98,7 @@ msgstr "" msgid "replaced {new_name}" msgstr "" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "" @@ -106,12 +106,8 @@ msgstr "" msgid "replaced {new_name} with {old_name}" msgstr "" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "" - -#: js/filelist.js:288 -msgid "deleted {files}" +#: js/filelist.js:280 +msgid "perform delete operation" msgstr "" #: js/files.js:52 @@ -136,78 +132,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Clauder" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "" -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "" -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Nomine" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Dimension" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Modificate" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "" @@ -263,33 +259,37 @@ msgstr "Dossier" msgid "From link" msgstr "" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Nihil hic. Incarga alcun cosa!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Discargar" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Incargamento troppo longe" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "" -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "" -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "" diff --git a/l10n/ia/files_trashbin.po b/l10n/ia/files_trashbin.po new file mode 100644 index 0000000000..42db681745 --- /dev/null +++ b/l10n/ia/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Interlingua (http://www.transifex.com/projects/p/owncloud/language/ia/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ia\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/id/core.po b/l10n/id/core.po index 9a0840fe9d..adf34a7cb2 100644 --- a/l10n/id/core.po +++ b/l10n/id/core.po @@ -11,8 +11,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Indonesian (http://www.transifex.com/projects/p/owncloud/language/id/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/id/files.po b/l10n/id/files.po index b163ba8eb7..a858466262 100644 --- a/l10n/id/files.po +++ b/l10n/id/files.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Indonesian (http://www.transifex.com/projects/p/owncloud/language/id/)\n" "MIME-Version: 1.0\n" @@ -67,15 +67,15 @@ msgstr "" msgid "Files" msgstr "Berkas" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "batalkan berbagi" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Hapus" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "" @@ -99,7 +99,7 @@ msgstr "batalkan" msgid "replaced {new_name}" msgstr "" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "batal dikerjakan" @@ -107,12 +107,8 @@ msgstr "batal dikerjakan" msgid "replaced {new_name} with {old_name}" msgstr "" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "" - -#: js/filelist.js:288 -msgid "deleted {files}" +#: js/filelist.js:280 +msgid "perform delete operation" msgstr "" #: js/files.js:52 @@ -137,78 +133,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Gagal mengunggah berkas anda karena berupa direktori atau mempunyai ukuran 0 byte" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Terjadi Galat Pengunggahan" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "tutup" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Menunggu" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Pengunggahan dibatalkan." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "" -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "tautan tidak boleh kosong" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Nama" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Ukuran" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Dimodifikasi" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "" @@ -264,33 +260,37 @@ msgstr "Folder" msgid "From link" msgstr "" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Batal mengunggah" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Tidak ada apa-apa di sini. Unggah sesuatu!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Unduh" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Unggahan terlalu besar" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Berkas yang anda coba unggah melebihi ukuran maksimum untuk pengunggahan berkas di server ini." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Berkas sedang dipindai, silahkan tunggu." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Sedang memindai" diff --git a/l10n/id/files_trashbin.po b/l10n/id/files_trashbin.po new file mode 100644 index 0000000000..671c1c77ee --- /dev/null +++ b/l10n/id/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Indonesian (http://www.transifex.com/projects/p/owncloud/language/id/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: id\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/is/core.po b/l10n/is/core.po index beaf3bce1c..fa83addcf9 100644 --- a/l10n/is/core.po +++ b/l10n/is/core.po @@ -9,8 +9,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Icelandic (http://www.transifex.com/projects/p/owncloud/language/is/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/is/files.po b/l10n/is/files.po index 1d7feca142..34313c0d99 100644 --- a/l10n/is/files.po +++ b/l10n/is/files.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Icelandic (http://www.transifex.com/projects/p/owncloud/language/is/)\n" "MIME-Version: 1.0\n" @@ -55,7 +55,7 @@ msgstr "Tókst ekki að skrifa á disk" #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "Ekki nægt pláss tiltækt" #: ajax/upload.php:82 msgid "Invalid directory." @@ -65,15 +65,15 @@ msgstr "Ógild mappa." msgid "Files" msgstr "Skrár" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Hætta deilingu" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Eyða" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Endurskýra" @@ -97,7 +97,7 @@ msgstr "hætta við" msgid "replaced {new_name}" msgstr "endurskýrði {new_name}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "afturkalla" @@ -105,13 +105,9 @@ msgstr "afturkalla" msgid "replaced {new_name} with {old_name}" msgstr "yfirskrifaði {new_name} með {old_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "Hætti við deilingu á {files}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "eyddi {files}" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -135,78 +131,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Innsending á skrá mistókst, hugsanlega sendir þú möppu eða skráin er 0 bæti." -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Villa við innsendingu" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Loka" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Bíður" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "1 skrá innsend" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} skrár innsendar" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Hætt við innsendingu." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Innsending í gangi. Ef þú ferð af þessari síðu mun innsending misheppnast." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "Vefslóð má ekki vera tóm." -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "Óleyfilegt nafn á möppu. Nafnið 'Shared' er frátekið fyrir Owncloud" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Nafn" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Stærð" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Breytt" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 mappa" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} möppur" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 skrá" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} skrár" @@ -262,33 +258,37 @@ msgstr "Mappa" msgid "From link" msgstr "Af tengli" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Hætta við innsendingu" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Ekkert hér. Settu eitthvað inn!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Niðurhal" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Innsend skrá er of stór" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Skrárnar sem þú ert að senda inn eru stærri en hámarks innsendingarstærð á þessum netþjóni." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Verið er að skima skrár, vinsamlegast hinkraðu." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Er að skima" diff --git a/l10n/is/files_trashbin.po b/l10n/is/files_trashbin.po new file mode 100644 index 0000000000..2ff20172cb --- /dev/null +++ b/l10n/is/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Icelandic (http://www.transifex.com/projects/p/owncloud/language/is/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: is\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/it/core.po b/l10n/it/core.po index 9e752cc43e..c1cb41fed8 100644 --- a/l10n/it/core.po +++ b/l10n/it/core.po @@ -6,15 +6,16 @@ # , 2011. # Francesco Apruzzese , 2011, 2012. # , 2011, 2012. +# , 2013. # , 2011. # Vincenzo Reale , 2012-2013. msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" -"Last-Translator: I Robot \n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 07:30+0000\n" +"Last-Translator: pgcloud \n" "Language-Team: Italian (http://www.transifex.com/projects/p/owncloud/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -557,7 +558,7 @@ msgstr "Accesso automatico rifiutato." msgid "" "If you did not change your password recently, your account may be " "compromised!" -msgstr "Se non hai cambiato la password recentemente, il tuo account potrebbe essere stato compromesso." +msgstr "Se non hai cambiato la password recentemente, il tuo account potrebbe essere compromesso." #: templates/login.php:13 msgid "Please change your password to secure your account again." @@ -586,4 +587,4 @@ msgstr "successivo" #: templates/update.php:3 #, php-format msgid "Updating ownCloud to version %s, this may take a while." -msgstr "Aggiornamento di ownCloud alla versione %s in corso, potrebbe richiedere del tempo." +msgstr "Aggiornamento di ownCloud alla versione %s in corso, ciò potrebbe richiedere del tempo." diff --git a/l10n/it/files.po b/l10n/it/files.po index 866f39981d..45e4a1587e 100644 --- a/l10n/it/files.po +++ b/l10n/it/files.po @@ -11,8 +11,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:27+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Italian (http://www.transifex.com/projects/p/owncloud/language/it/)\n" "MIME-Version: 1.0\n" @@ -58,7 +58,7 @@ msgstr "Scrittura su disco non riuscita" #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "Spazio disponibile insufficiente" #: ajax/upload.php:82 msgid "Invalid directory." @@ -68,15 +68,15 @@ msgstr "Cartella non valida." msgid "Files" msgstr "File" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Rimuovi condivisione" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Elimina" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Rinomina" @@ -100,7 +100,7 @@ msgstr "annulla" msgid "replaced {new_name}" msgstr "sostituito {new_name}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "annulla" @@ -108,13 +108,9 @@ msgstr "annulla" msgid "replaced {new_name} with {old_name}" msgstr "sostituito {new_name} con {old_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "non condivisi {files}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "eliminati {files}" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -138,78 +134,78 @@ msgstr "Lo spazio di archiviazione è pieno, i file non possono essere più aggi msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "Lo spazio di archiviazione è quasi pieno ({usedSpacePercent}%)" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "Il tuo scaricamento è in fase di preparazione. Ciò potrebbe richiedere del tempo se i file sono grandi." -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Impossibile inviare il file poiché è una cartella o ha dimensione 0 byte" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Errore di invio" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Chiudi" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "In corso" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "1 file in fase di caricamento" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} file in fase di caricamentoe" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Invio annullato" -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Caricamento del file in corso. La chiusura della pagina annullerà il caricamento." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "L'URL non può essere vuoto." -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "Nome della cartella non valido. L'uso di 'Shared' è riservato da ownCloud" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Nome" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Dimensione" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Modificato" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 cartella" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} cartelle" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 file" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} file" @@ -265,36 +261,40 @@ msgstr "Cartella" msgid "From link" msgstr "Da collegamento" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Annulla invio" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Non c'è niente qui. Carica qualcosa!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Scarica" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Il file caricato è troppo grande" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "I file che stai provando a caricare superano la dimensione massima consentita su questo server." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Scansione dei file in corso, attendi" -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Scansione corrente" #: templates/upgrade.php:2 msgid "Upgrading filesystem cache..." -msgstr "" +msgstr "Aggiornamento della cache del filesystem in corso..." diff --git a/l10n/it/files_trashbin.po b/l10n/it/files_trashbin.po new file mode 100644 index 0000000000..b5021a55f5 --- /dev/null +++ b/l10n/it/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Italian (http://www.transifex.com/projects/p/owncloud/language/it/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: it\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/it/settings.po b/l10n/it/settings.po index 1536b204ae..117e005d4a 100644 --- a/l10n/it/settings.po +++ b/l10n/it/settings.po @@ -14,9 +14,9 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" -"Last-Translator: I Robot \n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 06:40+0000\n" +"Last-Translator: Vincenzo Reale \n" "Language-Team: Italian (http://www.transifex.com/projects/p/owncloud/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -271,11 +271,11 @@ msgstr "Archiviazione" #: templates/users.php:97 msgid "change display name" -msgstr "" +msgstr "cambia il nome visualizzato" #: templates/users.php:101 msgid "set new password" -msgstr "" +msgstr "imposta una nuova password" #: templates/users.php:137 msgid "Default" diff --git a/l10n/ja_JP/core.po b/l10n/ja_JP/core.po index 8a855bf80e..8b2b2d4cb7 100644 --- a/l10n/ja_JP/core.po +++ b/l10n/ja_JP/core.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Japanese (Japan) (http://www.transifex.com/projects/p/owncloud/language/ja_JP/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/ja_JP/files.po b/l10n/ja_JP/files.po index eeb900bd96..9d8e49b325 100644 --- a/l10n/ja_JP/files.po +++ b/l10n/ja_JP/files.po @@ -11,8 +11,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Japanese (Japan) (http://www.transifex.com/projects/p/owncloud/language/ja_JP/)\n" "MIME-Version: 1.0\n" @@ -58,7 +58,7 @@ msgstr "ディスクへの書き込みに失敗しました" #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "利用可能なスペースが十分にありません" #: ajax/upload.php:82 msgid "Invalid directory." @@ -68,15 +68,15 @@ msgstr "無効なディレクトリです。" msgid "Files" msgstr "ファイル" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "共有しない" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "削除" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "名前の変更" @@ -100,7 +100,7 @@ msgstr "キャンセル" msgid "replaced {new_name}" msgstr "{new_name} を置換" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "元に戻す" @@ -108,13 +108,9 @@ msgstr "元に戻す" msgid "replaced {new_name} with {old_name}" msgstr "{old_name} を {new_name} に置換" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "未共有 {files}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "削除 {files}" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -138,78 +134,78 @@ msgstr "あなたのストレージは一杯です。ファイルの更新と同 msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "あなたのストレージはほぼ一杯です({usedSpacePercent}%)" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "ダウンロードの準備中です。ファイルサイズが大きい場合は少し時間がかかるかもしれません。" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "ディレクトリもしくは0バイトのファイルはアップロードできません" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "アップロードエラー" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "閉じる" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "保留" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "ファイルを1つアップロード中" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} ファイルをアップロード中" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "アップロードはキャンセルされました。" -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "ファイル転送を実行中です。今このページから移動するとアップロードが中止されます。" -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "URLは空にできません。" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "無効なフォルダ名です。'Shared' の利用は ownCloud が予約済みです。" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "名前" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "サイズ" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "更新日時" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 フォルダ" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} フォルダ" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 ファイル" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} ファイル" @@ -265,33 +261,37 @@ msgstr "フォルダ" msgid "From link" msgstr "リンク" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "アップロードをキャンセル" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "ここには何もありません。何かアップロードしてください。" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "ダウンロード" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "ファイルサイズが大きすぎます" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "アップロードしようとしているファイルは、サーバで規定された最大サイズを超えています。" -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "ファイルをスキャンしています、しばらくお待ちください。" -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "スキャン中" diff --git a/l10n/ja_JP/files_trashbin.po b/l10n/ja_JP/files_trashbin.po new file mode 100644 index 0000000000..67b3cb9aa1 --- /dev/null +++ b/l10n/ja_JP/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Japanese (Japan) (http://www.transifex.com/projects/p/owncloud/language/ja_JP/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ja_JP\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/ka_GE/core.po b/l10n/ka_GE/core.po index c9cd6befe2..8400725e1d 100644 --- a/l10n/ka_GE/core.po +++ b/l10n/ka_GE/core.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Georgian (Georgia) (http://www.transifex.com/projects/p/owncloud/language/ka_GE/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/ka_GE/files.po b/l10n/ka_GE/files.po index dd92548115..1fad0f39af 100644 --- a/l10n/ka_GE/files.po +++ b/l10n/ka_GE/files.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" "Last-Translator: I Robot \n" "Language-Team: Georgian (Georgia) (http://www.transifex.com/projects/p/owncloud/language/ka_GE/)\n" "MIME-Version: 1.0\n" @@ -65,15 +65,15 @@ msgstr "" msgid "Files" msgstr "ფაილები" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "გაზიარების მოხსნა" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "წაშლა" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "გადარქმევა" @@ -97,7 +97,7 @@ msgstr "უარყოფა" msgid "replaced {new_name}" msgstr "{new_name} შეცვლილია" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "დაბრუნება" @@ -105,13 +105,9 @@ msgstr "დაბრუნება" msgid "replaced {new_name} with {old_name}" msgstr "{new_name} შეცვლილია {old_name}–ით" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "გაზიარება მოხსნილი {files}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "წაშლილი {files}" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -135,78 +131,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "თქვენი ფაილის ატვირთვა ვერ მოხერხდა. ის არის საქაღალდე და შეიცავს 0 ბაიტს" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "შეცდომა ატვირთვისას" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "დახურვა" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "მოცდის რეჟიმში" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "1 ფაილის ატვირთვა" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} ფაილი იტვირთება" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "ატვირთვა შეჩერებულ იქნა." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "მიმდინარეობს ფაილის ატვირთვა. სხვა გვერდზე გადასვლა გამოიწვევს ატვირთვის შეჩერებას" -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "სახელი" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "ზომა" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "შეცვლილია" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 საქაღალდე" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} საქაღალდე" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 ფაილი" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} ფაილი" @@ -262,33 +258,37 @@ msgstr "საქაღალდე" msgid "From link" msgstr "" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "ატვირთვის გაუქმება" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "აქ არაფერი არ არის. ატვირთე რამე!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "ჩამოტვირთვა" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "ასატვირთი ფაილი ძალიან დიდია" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "ფაილის ზომა რომლის ატვირთვასაც თქვენ აპირებთ, აჭარბებს სერვერზე დაშვებულ მაქსიმუმს." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "მიმდინარეობს ფაილების სკანირება, გთხოვთ დაელოდოთ." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "მიმდინარე სკანირება" diff --git a/l10n/ka_GE/files_trashbin.po b/l10n/ka_GE/files_trashbin.po new file mode 100644 index 0000000000..cab751104b --- /dev/null +++ b/l10n/ka_GE/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Georgian (Georgia) (http://www.transifex.com/projects/p/owncloud/language/ka_GE/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ka_GE\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/ko/core.po b/l10n/ko/core.po index 98f2ffca7f..f4e1345570 100644 --- a/l10n/ko/core.po +++ b/l10n/ko/core.po @@ -6,14 +6,15 @@ # , 2013. # 남자사람 , 2012. # , 2012. +# Park Shinjo , 2013. # Shinjo Park , 2012. msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" -"Last-Translator: I Robot \n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 08:10+0000\n" +"Last-Translator: Shinjo Park \n" "Language-Team: Korean (http://www.transifex.com/projects/p/owncloud/language/ko/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -24,26 +25,26 @@ msgstr "" #: ajax/share.php:85 #, php-format msgid "User %s shared a file with you" -msgstr "User %s 가 당신과 파일을 공유하였습니다." +msgstr "%s 님이 파일을 공유하였습니다" #: ajax/share.php:87 #, php-format msgid "User %s shared a folder with you" -msgstr "User %s 가 당신과 폴더를 공유하였습니다." +msgstr "%s 님이 폴더를 공유하였습니다" #: ajax/share.php:89 #, php-format msgid "" "User %s shared the file \"%s\" with you. It is available for download here: " "%s" -msgstr "User %s 가 파일 \"%s\"를 당신과 공유하였습니다. 다운로드는 여기서 %s 할 수 있습니다." +msgstr "%s 님이 파일 \"%s\"을(를) 공유하였습니다. 여기에서 다운로드할 수 있습니다: %s" #: ajax/share.php:91 #, php-format msgid "" "User %s shared the folder \"%s\" with you. It is available for download " "here: %s" -msgstr "User %s 가 폴더 \"%s\"를 당신과 공유하였습니다. 다운로드는 여기서 %s 할 수 있습니다." +msgstr "%s 님이 폴더 \"%s\"을(를) 공유하였습니다. 여기에서 다운로드할 수 있습니다: %s" #: ajax/vcategories/add.php:26 ajax/vcategories/edit.php:25 msgid "Category type not provided." @@ -260,7 +261,7 @@ msgstr "공유" #: js/share.js:29 js/share.js:43 js/share.js:90 js/share.js:93 msgid "Shared" -msgstr "" +msgstr "공유됨" #: js/share.js:141 js/share.js:611 msgid "Error while sharing" @@ -383,11 +384,11 @@ msgid "" "The update was unsuccessful. Please report this issue to the ownCloud " "community." -msgstr "" +msgstr "업데이트가 실패하였습니다. 이 문제를 ownCloud 커뮤니티에 보고해 주십시오." #: js/update.js:18 msgid "The update was successful. Redirecting you to ownCloud now." -msgstr "" +msgstr "업데이트가 성공하였습니다. ownCloud로 돌아갑니다." #: lostpassword/controller.php:47 msgid "ownCloud password reset" @@ -585,4 +586,4 @@ msgstr "다음" #: templates/update.php:3 #, php-format msgid "Updating ownCloud to version %s, this may take a while." -msgstr "ownCloud 를 버젼 %s로 업데이트 하는 중, 시간이 소요됩니다." +msgstr "ownCloud를 버전 %s(으)로 업데이트합니다. 잠시 기다려 주십시오." diff --git a/l10n/ko/files.po b/l10n/ko/files.po index c9998ab40f..cc5153e34c 100644 --- a/l10n/ko/files.po +++ b/l10n/ko/files.po @@ -7,13 +7,14 @@ # 남자사람 , 2012. # Harim Park , 2013. # , 2012. +# Park Shinjo , 2013. # Shinjo Park , 2012. msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Korean (http://www.transifex.com/projects/p/owncloud/language/ko/)\n" "MIME-Version: 1.0\n" @@ -59,25 +60,25 @@ msgstr "디스크에 쓰지 못했습니다" #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "여유 공간이 부족합니다" #: ajax/upload.php:82 msgid "Invalid directory." -msgstr "올바르지 않은 디렉토리입니다." +msgstr "올바르지 않은 디렉터리입니다." #: appinfo/app.php:10 msgid "Files" msgstr "파일" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "공유 해제" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "삭제" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "이름 바꾸기" @@ -101,7 +102,7 @@ msgstr "취소" msgid "replaced {new_name}" msgstr "{new_name}을(를) 대체함" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "실행 취소" @@ -109,13 +110,9 @@ msgstr "실행 취소" msgid "replaced {new_name} with {old_name}" msgstr "{old_name}이(가) {new_name}(으)로 대체됨" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "{files} 공유 해제됨" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "{files} 삭제됨" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -123,7 +120,7 @@ msgstr "'.' 는 올바르지 않은 파일 이름 입니다." #: js/files.js:56 msgid "File name cannot be empty." -msgstr "파일이름은 공란이 될 수 없습니다." +msgstr "파일 이름이 비어 있을 수 없습니다." #: js/files.js:64 msgid "" @@ -133,84 +130,84 @@ msgstr "폴더 이름이 올바르지 않습니다. 이름에 문자 '\\', '/', #: js/files.js:78 msgid "Your storage is full, files can not be updated or synced anymore!" -msgstr "" +msgstr "저장 공간이 가득 찼습니다. 파일을 업데이트하거나 동기화할 수 없습니다!" #: js/files.js:82 msgid "Your storage is almost full ({usedSpacePercent}%)" -msgstr "" +msgstr "저장 공간이 거의 가득 찼습니다 ({usedSpacePercent}%)" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." -msgstr "" +msgstr "다운로드가 준비 중입니다. 파일 크기가 크다면 시간이 오래 걸릴 수도 있습니다." -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "이 파일은 디렉터리이거나 비어 있기 때문에 업로드할 수 없습니다" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "업로드 오류" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "닫기" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "보류 중" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "파일 1개 업로드 중" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "파일 {count}개 업로드 중" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "업로드가 취소되었습니다." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "파일 업로드가 진행 중입니다. 이 페이지를 벗어나면 업로드가 취소됩니다." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "URL을 입력해야 합니다." -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "폴더 이름이 유효하지 않습니다. " -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "이름" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "크기" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "수정됨" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "폴더 1개" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "폴더 {count}개" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "파일 1개" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "파일 {count}개" @@ -266,36 +263,40 @@ msgstr "폴더" msgid "From link" msgstr "링크에서" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "업로드 취소" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "내용이 없습니다. 업로드할 수 있습니다!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "다운로드" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "업로드 용량 초과" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "이 파일이 서버에서 허용하는 최대 업로드 가능 용량보다 큽니다." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "파일을 검색하고 있습니다. 기다려 주십시오." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "현재 검색" #: templates/upgrade.php:2 msgid "Upgrading filesystem cache..." -msgstr "" +msgstr "파일 시스템 캐시 업그레이드 중..." diff --git a/l10n/ko/files_encryption.po b/l10n/ko/files_encryption.po index 441ba8cec4..2988d1f0cf 100644 --- a/l10n/ko/files_encryption.po +++ b/l10n/ko/files_encryption.po @@ -4,14 +4,14 @@ # # Translators: # 남자사람 , 2012. -# Shinjo Park , 2012. +# Shinjo Park , 2012-2013. msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-23 00:05+0100\n" -"PO-Revision-Date: 2013-01-22 23:05+0000\n" -"Last-Translator: I Robot \n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 08:20+0000\n" +"Last-Translator: Shinjo Park \n" "Language-Team: Korean (http://www.transifex.com/projects/p/owncloud/language/ko/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -23,53 +23,53 @@ msgstr "" msgid "" "Please switch to your ownCloud client and change your encryption password to" " complete the conversion." -msgstr "" +msgstr "ownCloud로 전환한 다음 암호화에 사용할 암호를 변경하면 변환이 완료됩니다." #: js/settings-personal.js:17 msgid "switched to client side encryption" -msgstr "" +msgstr "클라이언트 암호화로 변경됨" #: js/settings-personal.js:21 msgid "Change encryption password to login password" -msgstr "" +msgstr "암호화 암호를 로그인 암호로 변경" #: js/settings-personal.js:25 msgid "Please check your passwords and try again." -msgstr "" +msgstr "암호를 확인한 다음 다시 시도하십시오." #: js/settings-personal.js:25 msgid "Could not change your file encryption password to your login password" -msgstr "" +msgstr "암호화 암호를 로그인 암호로 변경할 수 없습니다" #: templates/settings-personal.php:3 templates/settings.php:5 msgid "Choose encryption mode:" -msgstr "" +msgstr "암호화 모드 선택:" #: templates/settings-personal.php:20 templates/settings.php:24 msgid "" "Client side encryption (most secure but makes it impossible to access your " "data from the web interface)" -msgstr "" +msgstr "클라이언트 암호화 (안전하지만 웹에서 데이터에 접근할 수 없음)" #: templates/settings-personal.php:30 templates/settings.php:36 msgid "" "Server side encryption (allows you to access your files from the web " "interface and the desktop client)" -msgstr "" +msgstr "서버 암호화 (웹 및 데스크톱 클라이언트에서 데이터에 접근할 수 있음)" #: templates/settings-personal.php:41 templates/settings.php:60 msgid "None (no encryption at all)" -msgstr "" +msgstr "없음 (암호화하지 않음)" #: templates/settings.php:10 msgid "" "Important: Once you selected an encryption mode there is no way to change it" " back" -msgstr "" +msgstr "알림: 암호화 모드를 선택하면 다른 것으로 변경할 수 없습니다" #: templates/settings.php:48 msgid "User specific (let the user decide)" -msgstr "" +msgstr "사용자 지정 (사용자별 설정)" #: templates/settings.php:65 msgid "Encryption" diff --git a/l10n/ko/files_external.po b/l10n/ko/files_external.po index f43b896377..0c7bf2da32 100644 --- a/l10n/ko/files_external.po +++ b/l10n/ko/files_external.po @@ -5,14 +5,15 @@ # Translators: # , 2013. # 남자사람 , 2012. +# Park Shinjo , 2013. # Shinjo Park , 2012. msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-08 00:30+0100\n" -"PO-Revision-Date: 2013-01-07 10:07+0000\n" -"Last-Translator: aoiob4305 \n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 08:10+0000\n" +"Last-Translator: Shinjo Park \n" "Language-Team: Korean (http://www.transifex.com/projects/p/owncloud/language/ko/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -28,11 +29,11 @@ msgstr "접근 허가됨" msgid "Error configuring Dropbox storage" msgstr "Dropbox 저장소 설정 오류" -#: js/dropbox.js:34 js/dropbox.js:45 js/google.js:31 js/google.js:40 +#: js/dropbox.js:34 js/dropbox.js:45 js/google.js:31 js/google.js:41 msgid "Grant access" msgstr "접근 권한 부여" -#: js/dropbox.js:73 js/google.js:72 +#: js/dropbox.js:73 js/google.js:73 msgid "Fill out all required fields" msgstr "모든 필수 항목을 입력하십시오" @@ -40,22 +41,22 @@ msgstr "모든 필수 항목을 입력하십시오" msgid "Please provide a valid Dropbox app key and secret." msgstr "올바른 Dropbox 앱 키와 암호를 입력하십시오." -#: js/google.js:26 js/google.js:73 js/google.js:78 +#: js/google.js:26 js/google.js:74 js/google.js:79 msgid "Error configuring Google Drive storage" msgstr "Google 드라이브 저장소 설정 오류" -#: lib/config.php:434 +#: lib/config.php:405 msgid "" "Warning: \"smbclient\" is not installed. Mounting of CIFS/SMB shares " "is not possible. Please ask your system administrator to install it." -msgstr "경고\"smbclient\"가 설치되지 않았습니다. CIFS/SMB 공유애 연결이 불가능 합니다.. 시스템 관리자에게 요청하여 설치하시기 바랍니다." +msgstr "경고: \"smbclient\"가 설치되지 않았습니다. CIFS/SMB 공유 자원에 연결할 수 없습니다. 시스템 관리자에게 설치를 요청하십시오." -#: lib/config.php:435 +#: lib/config.php:406 msgid "" "Warning: The FTP support in PHP is not enabled or installed. Mounting" " of FTP shares is not possible. Please ask your system administrator to " "install it." -msgstr "경고PHP용 FTP 지원이 사용 불가능 하거나 설치되지 않았습니다. FTP 공유에 연결이 불가능 합니다. 시스템 관리자에게 요청하여 설치하시기 바랍니다. " +msgstr "경고: PHP FTP 지원이 비활성화되어 있거나 설치되지 않았습니다. FTP 공유를 마운트할 수 없습니다. 시스템 관리자에게 설치를 요청하십시오." #: templates/settings.php:3 msgid "External Storage" diff --git a/l10n/ko/files_trashbin.po b/l10n/ko/files_trashbin.po new file mode 100644 index 0000000000..db8be55cbb --- /dev/null +++ b/l10n/ko/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Korean (http://www.transifex.com/projects/p/owncloud/language/ko/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ko\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/ko/lib.po b/l10n/ko/lib.po index c759d43ece..ffbaa11a4e 100644 --- a/l10n/ko/lib.po +++ b/l10n/ko/lib.po @@ -4,14 +4,15 @@ # # Translators: # 남자사람 , 2012. +# Park Shinjo , 2013. # Shinjo Park , 2012. msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-17 00:26+0100\n" -"PO-Revision-Date: 2013-01-16 23:26+0000\n" -"Last-Translator: I Robot \n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 08:10+0000\n" +"Last-Translator: Shinjo Park \n" "Language-Team: Korean (http://www.transifex.com/projects/p/owncloud/language/ko/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -43,25 +44,25 @@ msgstr "앱" msgid "Admin" msgstr "관리자" -#: files.php:365 +#: files.php:202 msgid "ZIP download is turned off." msgstr "ZIP 다운로드가 비활성화되었습니다." -#: files.php:366 +#: files.php:203 msgid "Files need to be downloaded one by one." msgstr "파일을 개별적으로 다운로드해야 합니다." -#: files.php:366 files.php:391 +#: files.php:203 files.php:228 msgid "Back to Files" msgstr "파일로 돌아가기" -#: files.php:390 +#: files.php:227 msgid "Selected files too large to generate zip file." msgstr "선택한 파일들은 ZIP 파일을 생성하기에 너무 큽니다." -#: helper.php:228 +#: helper.php:226 msgid "couldn't be determined" -msgstr "" +msgstr "결정할 수 없음" #: json.php:28 msgid "Application is not enabled" diff --git a/l10n/ko/settings.po b/l10n/ko/settings.po index b1e3a45522..3ae712d483 100644 --- a/l10n/ko/settings.po +++ b/l10n/ko/settings.po @@ -7,14 +7,14 @@ # 남자사람 , 2012. # Harim Park , 2013. # , 2012. -# Shinjo Park , 2012. +# Shinjo Park , 2012-2013. msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" -"Last-Translator: I Robot \n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 08:10+0000\n" +"Last-Translator: Shinjo Park \n" "Language-Team: Korean (http://www.transifex.com/projects/p/owncloud/language/ko/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -114,11 +114,11 @@ msgstr "apps.owncloud.com에 있는 앱 페이지를 참고하십시오" #: templates/apps.php:29 msgid "-licensed by " -msgstr "-라이선스 보유자 " +msgstr "-라이선스됨: " #: templates/help.php:3 msgid "User Documentation" -msgstr "유저 문서" +msgstr "사용자 문서" #: templates/help.php:4 msgid "Administrator Documentation" @@ -134,7 +134,7 @@ msgstr "포럼" #: templates/help.php:9 msgid "Bugtracker" -msgstr "버그트래커" +msgstr "버그 트래커" #: templates/help.php:11 msgid "Commercial Support" @@ -147,11 +147,11 @@ msgstr "현재 공간 %s/%s을(를) 사용 중 #: templates/personal.php:12 msgid "Clients" -msgstr "고객" +msgstr "클라이언트" #: templates/personal.php:13 msgid "Download Desktop Clients" -msgstr "데스크탑 클라이언트 다운로드" +msgstr "데스크톱 클라이언트 다운로드" #: templates/personal.php:14 msgid "Download Android Client" @@ -215,11 +215,11 @@ msgstr "WebDAV" #: templates/personal.php:54 msgid "Use this address to connect to your ownCloud in your file manager" -msgstr "파일 매니저에서 사용자의 ownCloud에 접속하기 위해 이 주소를 사용하십시요." +msgstr "파일 관리자에서 ownCloud에 접속하려면 이 주소를 사용하십시오." #: templates/personal.php:63 msgid "Version" -msgstr "버젼" +msgstr "버전" #: templates/personal.php:65 msgid "" @@ -233,7 +233,7 @@ msgstr "ownCloud 커 #: templates/users.php:21 templates/users.php:79 msgid "Login Name" -msgstr "" +msgstr "로그인 이름" #: templates/users.php:26 templates/users.php:82 templates/users.php:107 msgid "Groups" @@ -257,7 +257,7 @@ msgstr "기타" #: templates/users.php:80 msgid "Display Name" -msgstr "" +msgstr "표시 이름" #: templates/users.php:84 templates/users.php:121 msgid "Group Admin" @@ -269,11 +269,11 @@ msgstr "저장소" #: templates/users.php:97 msgid "change display name" -msgstr "" +msgstr "표시 이름 변경" #: templates/users.php:101 msgid "set new password" -msgstr "" +msgstr "새 암호 설정" #: templates/users.php:137 msgid "Default" diff --git a/l10n/ko/user_ldap.po b/l10n/ko/user_ldap.po index 53b9f3b081..4afced481e 100644 --- a/l10n/ko/user_ldap.po +++ b/l10n/ko/user_ldap.po @@ -5,14 +5,14 @@ # Translators: # , 2013. # 남자사람 , 2012. -# Shinjo Park , 2012. +# Shinjo Park , 2012-2013. msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-16 00:19+0100\n" -"PO-Revision-Date: 2013-01-15 23:20+0000\n" -"Last-Translator: I Robot \n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 08:10+0000\n" +"Last-Translator: Shinjo Park \n" "Language-Team: Korean (http://www.transifex.com/projects/p/owncloud/language/ko/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -25,13 +25,13 @@ msgid "" "Warning: Apps user_ldap and user_webdavauth are incompatible. You may" " experience unexpected behaviour. Please ask your system administrator to " "disable one of them." -msgstr "경고user_ldap 앱과 user_webdavauth 앱은 호환되지 않습니다. 오동작을 일으킬 수 있으므로, 시스템 관리자에게 요청하여, 둘 중 하나를 비활성화 하시기 바랍니다." +msgstr "경고: user_ldap 앱과 user_webdavauth 앱은 호환되지 않습니다. 오동작을 일으킬 수 있으므로, 시스템 관리자에게 요청하여 둘 중 하나만 사용하도록 하십시오." #: templates/settings.php:11 msgid "" "Warning: The PHP LDAP module is not installed, the backend will not " "work. Please ask your system administrator to install it." -msgstr "" +msgstr "경고: PHP LDAP 모듈이 비활성화되어 있거나 설치되어 있지 않습니다. 백엔드를 사용할 수 없습니다. 시스템 관리자에게 설치를 요청하십시오." #: templates/settings.php:15 msgid "Host" @@ -48,7 +48,7 @@ msgstr "기본 DN" #: templates/settings.php:16 msgid "One Base DN per line" -msgstr "" +msgstr "기본 DN을 한 줄에 하나씩 입력하십시오" #: templates/settings.php:16 msgid "You can specify Base DN for users and groups in the Advanced tab" @@ -123,7 +123,7 @@ msgstr "기본 사용자 트리" #: templates/settings.php:25 msgid "One User Base DN per line" -msgstr "" +msgstr "사용자 DN을 한 줄에 하나씩 입력하십시오" #: templates/settings.php:26 msgid "Base Group Tree" @@ -131,7 +131,7 @@ msgstr "기본 그룹 트리" #: templates/settings.php:26 msgid "One Group Base DN per line" -msgstr "" +msgstr "그룹 기본 DN을 한 줄에 하나씩 입력하십시오" #: templates/settings.php:27 msgid "Group-Member association" diff --git a/l10n/ko/user_webdavauth.po b/l10n/ko/user_webdavauth.po index bd135598c7..f10bd76454 100644 --- a/l10n/ko/user_webdavauth.po +++ b/l10n/ko/user_webdavauth.po @@ -5,13 +5,14 @@ # Translators: # , 2013. # 남자사람 , 2012. +# Park Shinjo , 2013. msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-15 00:03+0100\n" -"PO-Revision-Date: 2013-01-14 23:04+0000\n" -"Last-Translator: I Robot \n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 08:10+0000\n" +"Last-Translator: Shinjo Park \n" "Language-Team: Korean (http://www.transifex.com/projects/p/owncloud/language/ko/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -21,7 +22,7 @@ msgstr "" #: templates/settings.php:3 msgid "WebDAV Authentication" -msgstr "" +msgstr "WebDAV 인증" #: templates/settings.php:4 msgid "URL: http://" @@ -32,4 +33,4 @@ msgid "" "ownCloud will send the user credentials to this URL. This plugin checks the " "response and will interpret the HTTP statuscodes 401 and 403 as invalid " "credentials, and all other responses as valid credentials." -msgstr "" +msgstr "ownCloud에서 이 URL로 사용자 인증 정보를 보냅니다. 이 플러그인은 응답을 확인하여 HTTP 상태 코드 401이나 403이 돌아온 경우에 잘못된 인증 정보로 간주합니다. 다른 모든 상태 코드는 올바른 인증 정보로 간주합니다." diff --git a/l10n/ku_IQ/files.po b/l10n/ku_IQ/files.po index 980d6c02db..6827e786ca 100644 --- a/l10n/ku_IQ/files.po +++ b/l10n/ku_IQ/files.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Kurdish (Iraq) (http://www.transifex.com/projects/p/owncloud/language/ku_IQ/)\n" "MIME-Version: 1.0\n" @@ -64,15 +64,15 @@ msgstr "" msgid "Files" msgstr "" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "" @@ -96,7 +96,7 @@ msgstr "" msgid "replaced {new_name}" msgstr "" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "" @@ -104,12 +104,8 @@ msgstr "" msgid "replaced {new_name} with {old_name}" msgstr "" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "" - -#: js/filelist.js:288 -msgid "deleted {files}" +#: js/filelist.js:280 +msgid "perform delete operation" msgstr "" #: js/files.js:52 @@ -134,78 +130,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "داخستن" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "" -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "" -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "ناونیشانی به‌سته‌ر نابێت به‌تاڵ بێت." -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "ناو" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "" @@ -261,33 +257,37 @@ msgstr "بوخچه" msgid "From link" msgstr "" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "داگرتن" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "" -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "" -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "" diff --git a/l10n/ku_IQ/files_trashbin.po b/l10n/ku_IQ/files_trashbin.po new file mode 100644 index 0000000000..9d51dca2cd --- /dev/null +++ b/l10n/ku_IQ/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Kurdish (Iraq) (http://www.transifex.com/projects/p/owncloud/language/ku_IQ/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ku_IQ\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/lb/core.po b/l10n/lb/core.po index 5af337c2fa..18bf6381db 100644 --- a/l10n/lb/core.po +++ b/l10n/lb/core.po @@ -9,8 +9,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Luxembourgish (http://www.transifex.com/projects/p/owncloud/language/lb/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/lb/files.po b/l10n/lb/files.po index 6e1fda9da7..6c93eac950 100644 --- a/l10n/lb/files.po +++ b/l10n/lb/files.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Luxembourgish (http://www.transifex.com/projects/p/owncloud/language/lb/)\n" "MIME-Version: 1.0\n" @@ -65,15 +65,15 @@ msgstr "" msgid "Files" msgstr "Dateien" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Net méi deelen" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Läschen" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "" @@ -97,7 +97,7 @@ msgstr "ofbriechen" msgid "replaced {new_name}" msgstr "" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "réckgängeg man" @@ -105,12 +105,8 @@ msgstr "réckgängeg man" msgid "replaced {new_name} with {old_name}" msgstr "" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "" - -#: js/filelist.js:288 -msgid "deleted {files}" +#: js/filelist.js:280 +msgid "perform delete operation" msgstr "" #: js/files.js:52 @@ -135,78 +131,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Kann deng Datei net eroplueden well et en Dossier ass oder 0 byte grouss ass." -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Fehler beim eroplueden" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Zoumaachen" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Upload ofgebrach." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "File Upload am gaang. Wann's de des Säit verléiss gëtt den Upload ofgebrach." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Numm" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Gréisst" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Geännert" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "" @@ -262,33 +258,37 @@ msgstr "Dossier" msgid "From link" msgstr "" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Upload ofbriechen" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Hei ass näischt. Lued eppes rop!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Eroflueden" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Upload ze grouss" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Déi Dateien déi Dir probéiert erop ze lueden sinn méi grouss wei déi Maximal Gréisst déi op dësem Server erlaabt ass." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Fichieren gi gescannt, war weg." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Momentane Scan" diff --git a/l10n/lb/files_trashbin.po b/l10n/lb/files_trashbin.po new file mode 100644 index 0000000000..b3405a18ed --- /dev/null +++ b/l10n/lb/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Luxembourgish (http://www.transifex.com/projects/p/owncloud/language/lb/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lb\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/lt_LT/core.po b/l10n/lt_LT/core.po index 5676435c04..8b6ad9ccc6 100644 --- a/l10n/lt_LT/core.po +++ b/l10n/lt_LT/core.po @@ -9,8 +9,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Lithuanian (Lithuania) (http://www.transifex.com/projects/p/owncloud/language/lt_LT/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/lt_LT/files.po b/l10n/lt_LT/files.po index 29ff50d96c..973ce84515 100644 --- a/l10n/lt_LT/files.po +++ b/l10n/lt_LT/files.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Lithuanian (Lithuania) (http://www.transifex.com/projects/p/owncloud/language/lt_LT/)\n" "MIME-Version: 1.0\n" @@ -67,15 +67,15 @@ msgstr "" msgid "Files" msgstr "Failai" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Nebesidalinti" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Ištrinti" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Pervadinti" @@ -99,7 +99,7 @@ msgstr "atšaukti" msgid "replaced {new_name}" msgstr "pakeiskite {new_name}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "anuliuoti" @@ -107,13 +107,9 @@ msgstr "anuliuoti" msgid "replaced {new_name} with {old_name}" msgstr "pakeiskite {new_name} į {old_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "nebesidalinti {files}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "ištrinti {files}" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -137,78 +133,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Neįmanoma įkelti failo - jo dydis gali būti 0 bitų arba tai katalogas" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Įkėlimo klaida" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Užverti" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Laukiantis" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "įkeliamas 1 failas" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} įkeliami failai" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Įkėlimas atšauktas." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Failo įkėlimas pradėtas. Jei paliksite šį puslapį, įkėlimas nutrūks." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Pavadinimas" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Dydis" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Pakeista" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 aplankalas" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} aplankalai" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 failas" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} failai" @@ -264,33 +260,37 @@ msgstr "Katalogas" msgid "From link" msgstr "" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Atšaukti siuntimą" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Čia tuščia. Įkelkite ką nors!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Atsisiųsti" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Įkėlimui failas per didelis" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Bandomų įkelti failų dydis viršija maksimalų leidžiamą šiame serveryje" -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Skenuojami failai, prašome palaukti." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Šiuo metu skenuojama" diff --git a/l10n/lt_LT/files_trashbin.po b/l10n/lt_LT/files_trashbin.po new file mode 100644 index 0000000000..8f201877c0 --- /dev/null +++ b/l10n/lt_LT/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Lithuanian (Lithuania) (http://www.transifex.com/projects/p/owncloud/language/lt_LT/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lt_LT\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/lv/core.po b/l10n/lv/core.po index 1a5b812980..33e4a0ab1a 100644 --- a/l10n/lv/core.po +++ b/l10n/lv/core.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Latvian (http://www.transifex.com/projects/p/owncloud/language/lv/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/lv/files.po b/l10n/lv/files.po index 8d8b7d8884..e1a30aaf30 100644 --- a/l10n/lv/files.po +++ b/l10n/lv/files.po @@ -9,8 +9,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Latvian (http://www.transifex.com/projects/p/owncloud/language/lv/)\n" "MIME-Version: 1.0\n" @@ -66,15 +66,15 @@ msgstr "" msgid "Files" msgstr "Faili" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Pārtraukt līdzdalīšanu" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Izdzēst" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Pārdēvēt" @@ -98,7 +98,7 @@ msgstr "atcelt" msgid "replaced {new_name}" msgstr "" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "vienu soli atpakaļ" @@ -106,12 +106,8 @@ msgstr "vienu soli atpakaļ" msgid "replaced {new_name} with {old_name}" msgstr "" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "" - -#: js/filelist.js:288 -msgid "deleted {files}" +#: js/filelist.js:280 +msgid "perform delete operation" msgstr "" #: js/files.js:52 @@ -136,78 +132,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Nav iespējams augšuplādēt jūsu failu, jo tāds jau eksistē vai arī failam nav izmēra (0 baiti)" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Augšuplādēšanas laikā radās kļūda" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Gaida savu kārtu" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Augšuplāde ir atcelta" -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Notiek augšupielāde. Pametot lapu tagad, tiks atcelta augšupielāde." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Nosaukums" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Izmērs" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Izmainīts" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "" @@ -263,33 +259,37 @@ msgstr "Mape" msgid "From link" msgstr "" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Atcelt augšuplādi" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Te vēl nekas nav. Rīkojies, sāc augšuplādēt" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Lejuplādēt" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Fails ir par lielu lai to augšuplādetu" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Jūsu augšuplādējamie faili pārsniedz servera pieļaujamo failu augšupielādes apjomu" -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Faili šobrīd tiek caurskatīti, nedaudz jāpagaida." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Šobrīd tiek pārbaudīti" diff --git a/l10n/lv/files_trashbin.po b/l10n/lv/files_trashbin.po new file mode 100644 index 0000000000..eaa941cf0f --- /dev/null +++ b/l10n/lv/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Latvian (http://www.transifex.com/projects/p/owncloud/language/lv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: lv\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/mk/core.po b/l10n/mk/core.po index 95679fe31d..99fa224afd 100644 --- a/l10n/mk/core.po +++ b/l10n/mk/core.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Macedonian (http://www.transifex.com/projects/p/owncloud/language/mk/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/mk/files.po b/l10n/mk/files.po index b4dc2e60d8..ff1175a990 100644 --- a/l10n/mk/files.po +++ b/l10n/mk/files.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Macedonian (http://www.transifex.com/projects/p/owncloud/language/mk/)\n" "MIME-Version: 1.0\n" @@ -67,15 +67,15 @@ msgstr "" msgid "Files" msgstr "Датотеки" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Не споделувај" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Избриши" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Преименувај" @@ -99,7 +99,7 @@ msgstr "откажи" msgid "replaced {new_name}" msgstr "земенета {new_name}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "врати" @@ -107,13 +107,9 @@ msgstr "врати" msgid "replaced {new_name} with {old_name}" msgstr "заменета {new_name} со {old_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "без споделување {files}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "избришани {files}" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -137,78 +133,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Не може да се преземе вашата датотека бидејќи фолдерот во кој се наоѓа фајлот има големина од 0 бајти" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Грешка при преземање" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Затвои" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Чека" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "1 датотека се подига" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} датотеки се подигаат" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Преземањето е прекинато." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Подигање на датотека е во тек. Напуштење на страницата ќе го прекине." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "Адресата неможе да биде празна." -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Име" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Големина" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Променето" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 папка" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} папки" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 датотека" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} датотеки" @@ -264,33 +260,37 @@ msgstr "Папка" msgid "From link" msgstr "Од врска" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Откажи прикачување" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Тука нема ништо. Снимете нешто!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Преземи" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Датотеката е премногу голема" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Датотеките кои се обидувате да ги подигнете ја надминуваат максималната големина за подигнување датотеки на овој сервер." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Се скенираат датотеки, ве молам почекајте." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Моментално скенирам" diff --git a/l10n/mk/files_trashbin.po b/l10n/mk/files_trashbin.po new file mode 100644 index 0000000000..e171b9df53 --- /dev/null +++ b/l10n/mk/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Macedonian (http://www.transifex.com/projects/p/owncloud/language/mk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: mk\n" +"Plural-Forms: nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/ms_MY/core.po b/l10n/ms_MY/core.po index 98f3b0afee..e8d31c87c2 100644 --- a/l10n/ms_MY/core.po +++ b/l10n/ms_MY/core.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Malay (Malaysia) (http://www.transifex.com/projects/p/owncloud/language/ms_MY/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/ms_MY/files.po b/l10n/ms_MY/files.po index af05e61894..351ea5b3fd 100644 --- a/l10n/ms_MY/files.po +++ b/l10n/ms_MY/files.po @@ -11,8 +11,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Malay (Malaysia) (http://www.transifex.com/projects/p/owncloud/language/ms_MY/)\n" "MIME-Version: 1.0\n" @@ -68,15 +68,15 @@ msgstr "" msgid "Files" msgstr "fail" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Padam" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "" @@ -100,7 +100,7 @@ msgstr "Batal" msgid "replaced {new_name}" msgstr "" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "" @@ -108,12 +108,8 @@ msgstr "" msgid "replaced {new_name} with {old_name}" msgstr "" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "" - -#: js/filelist.js:288 -msgid "deleted {files}" +#: js/filelist.js:280 +msgid "perform delete operation" msgstr "" #: js/files.js:52 @@ -138,78 +134,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Tidak boleh memuatnaik fail anda kerana mungkin ianya direktori atau saiz fail 0 bytes" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Muat naik ralat" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Tutup" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Dalam proses" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Muatnaik dibatalkan." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "" -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Nama " -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Saiz" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Dimodifikasi" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "" @@ -265,33 +261,37 @@ msgstr "Folder" msgid "From link" msgstr "" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Batal muat naik" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Tiada apa-apa di sini. Muat naik sesuatu!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Muat turun" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Muat naik terlalu besar" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Fail yang cuba dimuat naik melebihi saiz maksimum fail upload server" -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Fail sedang diimbas, harap bersabar." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Imbasan semasa" diff --git a/l10n/ms_MY/files_trashbin.po b/l10n/ms_MY/files_trashbin.po new file mode 100644 index 0000000000..bebd72e8ed --- /dev/null +++ b/l10n/ms_MY/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Malay (Malaysia) (http://www.transifex.com/projects/p/owncloud/language/ms_MY/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ms_MY\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/nb_NO/core.po b/l10n/nb_NO/core.po index 6bb4f89191..fe3666fe40 100644 --- a/l10n/nb_NO/core.po +++ b/l10n/nb_NO/core.po @@ -14,8 +14,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Norwegian Bokmål (Norway) (http://www.transifex.com/projects/p/owncloud/language/nb_NO/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/nb_NO/files.po b/l10n/nb_NO/files.po index 6198f2690c..be448cfd6d 100644 --- a/l10n/nb_NO/files.po +++ b/l10n/nb_NO/files.po @@ -16,8 +16,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Norwegian Bokmål (Norway) (http://www.transifex.com/projects/p/owncloud/language/nb_NO/)\n" "MIME-Version: 1.0\n" @@ -73,15 +73,15 @@ msgstr "" msgid "Files" msgstr "Filer" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Avslutt deling" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Slett" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Omdøp" @@ -105,7 +105,7 @@ msgstr "avbryt" msgid "replaced {new_name}" msgstr "erstatt {new_name}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "angre" @@ -113,14 +113,10 @@ msgstr "angre" msgid "replaced {new_name} with {old_name}" msgstr "erstatt {new_name} med {old_name}" -#: js/filelist.js:286 -msgid "unshared {files}" +#: js/filelist.js:280 +msgid "perform delete operation" msgstr "" -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "slettet {files}" - #: js/files.js:52 msgid "'.' is an invalid file name." msgstr "" @@ -143,78 +139,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Kan ikke laste opp filen din siden det er en mappe eller den har 0 bytes" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Opplasting feilet" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Lukk" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Ventende" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "1 fil lastes opp" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} filer laster opp" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Opplasting avbrutt." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Filopplasting pågår. Forlater du siden nå avbrytes opplastingen." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "URL-en kan ikke være tom." -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Navn" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Størrelse" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Endret" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 mappe" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} mapper" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 fil" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} filer" @@ -270,33 +266,37 @@ msgstr "Mappe" msgid "From link" msgstr "Fra link" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Avbryt opplasting" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Ingenting her. Last opp noe!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Last ned" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Opplasting for stor" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Filene du prøver å laste opp er for store for å laste opp til denne serveren." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Skanner etter filer, vennligst vent." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Pågående skanning" diff --git a/l10n/nb_NO/files_trashbin.po b/l10n/nb_NO/files_trashbin.po new file mode 100644 index 0000000000..e986b6bbf3 --- /dev/null +++ b/l10n/nb_NO/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Norwegian Bokmål (Norway) (http://www.transifex.com/projects/p/owncloud/language/nb_NO/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nb_NO\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/nl/core.po b/l10n/nl/core.po index 0e4ae9cb8b..2631c0b1fd 100644 --- a/l10n/nl/core.po +++ b/l10n/nl/core.po @@ -21,8 +21,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Dutch (http://www.transifex.com/projects/p/owncloud/language/nl/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/nl/files.po b/l10n/nl/files.po index e30647c61a..e89b67b08e 100644 --- a/l10n/nl/files.po +++ b/l10n/nl/files.po @@ -19,8 +19,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Dutch (http://www.transifex.com/projects/p/owncloud/language/nl/)\n" "MIME-Version: 1.0\n" @@ -66,7 +66,7 @@ msgstr "Schrijven naar schijf mislukt" #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "Niet genoeg ruimte beschikbaar" #: ajax/upload.php:82 msgid "Invalid directory." @@ -76,15 +76,15 @@ msgstr "Ongeldige directory." msgid "Files" msgstr "Bestanden" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Stop delen" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Verwijder" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Hernoem" @@ -108,7 +108,7 @@ msgstr "annuleren" msgid "replaced {new_name}" msgstr "verving {new_name}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "ongedaan maken" @@ -116,13 +116,9 @@ msgstr "ongedaan maken" msgid "replaced {new_name} with {old_name}" msgstr "verving {new_name} met {old_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "delen gestopt {files}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "verwijderde {files}" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -146,78 +142,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "Uw download wordt voorbereid. Dit kan enige tijd duren bij grote bestanden." -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "uploaden van de file mislukt, het is of een directory of de bestandsgrootte is 0 bytes" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Upload Fout" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Sluit" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Wachten" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "1 bestand wordt ge-upload" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} bestanden aan het uploaden" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Uploaden geannuleerd." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Bestandsupload is bezig. Wanneer de pagina nu verlaten wordt, stopt de upload." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "URL kan niet leeg zijn." -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "Ongeldige mapnaam. Gebruik van'Gedeeld' is voorbehouden aan Owncloud" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Naam" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Bestandsgrootte" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Laatst aangepast" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 map" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} mappen" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 bestand" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} bestanden" @@ -273,33 +269,37 @@ msgstr "Map" msgid "From link" msgstr "Vanaf link" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Upload afbreken" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Er bevindt zich hier niets. Upload een bestand!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Download" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Bestanden te groot" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "De bestanden die u probeert te uploaden zijn groter dan de maximaal toegestane bestandsgrootte voor deze server." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Bestanden worden gescand, even wachten." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Er wordt gescand" diff --git a/l10n/nl/files_trashbin.po b/l10n/nl/files_trashbin.po new file mode 100644 index 0000000000..79849be829 --- /dev/null +++ b/l10n/nl/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Dutch (http://www.transifex.com/projects/p/owncloud/language/nl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/nn_NO/files.po b/l10n/nn_NO/files.po index 28ffec0234..ccd8d42d8b 100644 --- a/l10n/nn_NO/files.po +++ b/l10n/nn_NO/files.po @@ -9,8 +9,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Norwegian Nynorsk (Norway) (http://www.transifex.com/projects/p/owncloud/language/nn_NO/)\n" "MIME-Version: 1.0\n" @@ -66,15 +66,15 @@ msgstr "" msgid "Files" msgstr "Filer" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Slett" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "" @@ -98,7 +98,7 @@ msgstr "" msgid "replaced {new_name}" msgstr "" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "" @@ -106,12 +106,8 @@ msgstr "" msgid "replaced {new_name} with {old_name}" msgstr "" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "" - -#: js/filelist.js:288 -msgid "deleted {files}" +#: js/filelist.js:280 +msgid "perform delete operation" msgstr "" #: js/files.js:52 @@ -136,78 +132,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Lukk" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "" -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "" -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Namn" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Storleik" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Endra" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "" @@ -263,33 +259,37 @@ msgstr "Mappe" msgid "From link" msgstr "" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Ingenting her. Last noko opp!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Last ned" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "For stor opplasting" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Filene du prøver å laste opp er større enn maksgrensa til denne tenaren." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "" -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "" diff --git a/l10n/nn_NO/files_trashbin.po b/l10n/nn_NO/files_trashbin.po new file mode 100644 index 0000000000..522394a9a8 --- /dev/null +++ b/l10n/nn_NO/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Norwegian Nynorsk (Norway) (http://www.transifex.com/projects/p/owncloud/language/nn_NO/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: nn_NO\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/oc/core.po b/l10n/oc/core.po index 8ad819dd9e..8a0593cf3e 100644 --- a/l10n/oc/core.po +++ b/l10n/oc/core.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Occitan (post 1500) (http://www.transifex.com/projects/p/owncloud/language/oc/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/oc/files.po b/l10n/oc/files.po index ccb0ea9e29..49be6c576e 100644 --- a/l10n/oc/files.po +++ b/l10n/oc/files.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Occitan (post 1500) (http://www.transifex.com/projects/p/owncloud/language/oc/)\n" "MIME-Version: 1.0\n" @@ -65,15 +65,15 @@ msgstr "" msgid "Files" msgstr "Fichièrs" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Non parteja" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Escafa" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Torna nomenar" @@ -97,7 +97,7 @@ msgstr "anulla" msgid "replaced {new_name}" msgstr "" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "defar" @@ -105,12 +105,8 @@ msgstr "defar" msgid "replaced {new_name} with {old_name}" msgstr "" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "" - -#: js/filelist.js:288 -msgid "deleted {files}" +#: js/filelist.js:280 +msgid "perform delete operation" msgstr "" #: js/files.js:52 @@ -135,78 +131,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Impossible d'amontcargar lo teu fichièr qu'es un repertòri o que ten pas que 0 octet." -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Error d'amontcargar" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Al esperar" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "1 fichièr al amontcargar" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Amontcargar anullat." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Un amontcargar es a se far. Daissar aquesta pagina ara tamparà lo cargament. " -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Nom" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Talha" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Modificat" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "" @@ -262,33 +258,37 @@ msgstr "Dorsièr" msgid "From link" msgstr "" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr " Anulla l'amontcargar" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Pas res dedins. Amontcarga qualquaren" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Avalcarga" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Amontcargament tròp gròs" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Los fichièrs que sias a amontcargar son tròp pesucs per la talha maxi pel servidor." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Los fiichièrs son a èsser explorats, " -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Exploracion en cors" diff --git a/l10n/oc/files_trashbin.po b/l10n/oc/files_trashbin.po new file mode 100644 index 0000000000..7d4329b294 --- /dev/null +++ b/l10n/oc/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Occitan (post 1500) (http://www.transifex.com/projects/p/owncloud/language/oc/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: oc\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/pl/core.po b/l10n/pl/core.po index 70a4880051..73e2387f9d 100644 --- a/l10n/pl/core.po +++ b/l10n/pl/core.po @@ -17,8 +17,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Polish (http://www.transifex.com/projects/p/owncloud/language/pl/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/pl/files.po b/l10n/pl/files.po index 8052c7c543..36c7353658 100644 --- a/l10n/pl/files.po +++ b/l10n/pl/files.po @@ -15,8 +15,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Polish (http://www.transifex.com/projects/p/owncloud/language/pl/)\n" "MIME-Version: 1.0\n" @@ -62,7 +62,7 @@ msgstr "Błąd zapisu na dysk" #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "Za mało miejsca" #: ajax/upload.php:82 msgid "Invalid directory." @@ -72,15 +72,15 @@ msgstr "Zła ścieżka." msgid "Files" msgstr "Pliki" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Nie udostępniaj" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Usuwa element" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Zmień nazwę" @@ -104,7 +104,7 @@ msgstr "anuluj" msgid "replaced {new_name}" msgstr "zastąpiony {new_name}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "wróć" @@ -112,13 +112,9 @@ msgstr "wróć" msgid "replaced {new_name} with {old_name}" msgstr "zastąpiony {new_name} z {old_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "Udostępniane wstrzymane {files}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "usunięto {files}" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -142,78 +138,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Nie można wczytać pliku jeśli jest katalogiem lub ma 0 bajtów" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Błąd wczytywania" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Zamknij" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Oczekujące" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "1 plik wczytany" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} przesyłanie plików" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Wczytywanie anulowane." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Wysyłanie pliku jest w toku. Teraz opuszczając stronę wysyłanie zostanie anulowane." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "URL nie może być pusty." -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "Nazwa folderu nieprawidłowa. Wykorzystanie \"Shared\" jest zarezerwowane przez Owncloud" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Nazwa" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Rozmiar" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Czas modyfikacji" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 folder" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} foldery" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 plik" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} pliki" @@ -269,33 +265,37 @@ msgstr "Katalog" msgid "From link" msgstr "Z linku" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Przestań wysyłać" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Brak zawartości. Proszę wysłać pliki!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Pobiera element" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Wysyłany plik ma za duży rozmiar" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Pliki które próbujesz przesłać, przekraczają maksymalną, dopuszczalną wielkość." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Skanowanie plików, proszę czekać." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Aktualnie skanowane" diff --git a/l10n/pl/files_trashbin.po b/l10n/pl/files_trashbin.po new file mode 100644 index 0000000000..1c2572023c --- /dev/null +++ b/l10n/pl/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Polish (http://www.transifex.com/projects/p/owncloud/language/pl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pl\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/pl_PL/files.po b/l10n/pl_PL/files.po index a7f0400709..ab00380cb6 100644 --- a/l10n/pl_PL/files.po +++ b/l10n/pl_PL/files.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Polish (Poland) (http://www.transifex.com/projects/p/owncloud/language/pl_PL/)\n" "MIME-Version: 1.0\n" @@ -64,15 +64,15 @@ msgstr "" msgid "Files" msgstr "" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "" @@ -96,7 +96,7 @@ msgstr "" msgid "replaced {new_name}" msgstr "" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "" @@ -104,12 +104,8 @@ msgstr "" msgid "replaced {new_name} with {old_name}" msgstr "" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "" - -#: js/filelist.js:288 -msgid "deleted {files}" +#: js/filelist.js:280 +msgid "perform delete operation" msgstr "" #: js/files.js:52 @@ -134,78 +130,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "" -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "" -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "" @@ -261,33 +257,37 @@ msgstr "" msgid "From link" msgstr "" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "" -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "" -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "" diff --git a/l10n/pl_PL/files_trashbin.po b/l10n/pl_PL/files_trashbin.po new file mode 100644 index 0000000000..6a27483b43 --- /dev/null +++ b/l10n/pl_PL/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Polish (Poland) (http://www.transifex.com/projects/p/owncloud/language/pl_PL/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pl_PL\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/pt_BR/core.po b/l10n/pt_BR/core.po index d2e12de601..c180eefca1 100644 --- a/l10n/pt_BR/core.po +++ b/l10n/pt_BR/core.po @@ -18,8 +18,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 15:30+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: rodrigost23 \n" "Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/owncloud/language/pt_BR/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/pt_BR/files.po b/l10n/pt_BR/files.po index c36b462544..fdbe76ca2d 100644 --- a/l10n/pt_BR/files.po +++ b/l10n/pt_BR/files.po @@ -16,8 +16,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/owncloud/language/pt_BR/)\n" "MIME-Version: 1.0\n" @@ -73,15 +73,15 @@ msgstr "Diretório inválido." msgid "Files" msgstr "Arquivos" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Descompartilhar" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Excluir" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Renomear" @@ -105,7 +105,7 @@ msgstr "cancelar" msgid "replaced {new_name}" msgstr "substituído {new_name}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "desfazer" @@ -113,13 +113,9 @@ msgstr "desfazer" msgid "replaced {new_name} with {old_name}" msgstr "Substituído {old_name} por {new_name} " -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "{files} não compartilhados" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "{files} apagados" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -143,78 +139,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "Seu download está sendo preparado. Isto pode levar algum tempo se os arquivos forem grandes." -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Impossível enviar seus arquivo como diretório ou ele tem 0 bytes." -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Erro de envio" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Fechar" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Pendente" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "enviando 1 arquivo" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "Enviando {count} arquivos" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Envio cancelado." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Upload em andamento. Sair da página agora resultará no cancelamento do envio." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "URL não pode ficar em branco" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "Nome de pasta inválido. O uso de 'Shared' é reservado para o Owncloud" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Nome" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Tamanho" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Modificado" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 pasta" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} pastas" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 arquivo" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} arquivos" @@ -270,33 +266,37 @@ msgstr "Pasta" msgid "From link" msgstr "Do link" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Cancelar upload" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Nada aqui.Carrege alguma coisa!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Baixar" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Arquivo muito grande" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Os arquivos que você está tentando carregar excedeu o tamanho máximo para arquivos no servidor." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Arquivos sendo escaneados, por favor aguarde." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Scanning atual" diff --git a/l10n/pt_BR/files_trashbin.po b/l10n/pt_BR/files_trashbin.po new file mode 100644 index 0000000000..3511463385 --- /dev/null +++ b/l10n/pt_BR/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/owncloud/language/pt_BR/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pt_BR\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/pt_PT/core.po b/l10n/pt_PT/core.po index e5f09b7f56..de0bb148c4 100644 --- a/l10n/pt_PT/core.po +++ b/l10n/pt_PT/core.po @@ -15,8 +15,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 13:50+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: Duarte Velez Grilo \n" "Language-Team: Portuguese (Portugal) (http://www.transifex.com/projects/p/owncloud/language/pt_PT/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/pt_PT/files.po b/l10n/pt_PT/files.po index ac9f18e9cb..0ffd259156 100644 --- a/l10n/pt_PT/files.po +++ b/l10n/pt_PT/files.po @@ -9,13 +9,14 @@ # Duarte Velez Grilo , 2012. # , 2012. # Helder Meneses , 2012. +# Miguel Sousa , 2013. # , 2012. msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Portuguese (Portugal) (http://www.transifex.com/projects/p/owncloud/language/pt_PT/)\n" "MIME-Version: 1.0\n" @@ -61,7 +62,7 @@ msgstr "Falhou a escrita no disco" #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "Espaço em disco insuficiente!" #: ajax/upload.php:82 msgid "Invalid directory." @@ -71,15 +72,15 @@ msgstr "Directório Inválido" msgid "Files" msgstr "Ficheiros" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Deixar de partilhar" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Apagar" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Renomear" @@ -103,7 +104,7 @@ msgstr "cancelar" msgid "replaced {new_name}" msgstr "{new_name} substituido" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "desfazer" @@ -111,13 +112,9 @@ msgstr "desfazer" msgid "replaced {new_name} with {old_name}" msgstr "substituido {new_name} por {old_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "{files} não partilhado(s)" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "{files} eliminado(s)" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -141,78 +138,78 @@ msgstr "O seu armazenamento está cheio, os ficheiros não podem ser sincronizad msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "O seu espaço de armazenamento está quase cheiro ({usedSpacePercent}%)" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "O seu download está a ser preparado. Este processo pode demorar algum tempo se os ficheiros forem grandes." -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Não é possível fazer o envio do ficheiro devido a ser uma pasta ou ter 0 bytes" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Erro no envio" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Fechar" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Pendente" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "A enviar 1 ficheiro" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "A carregar {count} ficheiros" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Envio cancelado." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Envio de ficheiro em progresso. Irá cancelar o envio se sair da página agora." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "O URL não pode estar vazio." -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "Nome de pasta inválido. O Uso de 'shared' é reservado para o ownCloud" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Nome" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Tamanho" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Modificado" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 pasta" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} pastas" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 ficheiro" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} ficheiros" @@ -268,36 +265,40 @@ msgstr "Pasta" msgid "From link" msgstr "Da ligação" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Cancelar envio" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Vazio. Envie alguma coisa!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Transferir" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Envio muito grande" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Os ficheiros que está a tentar enviar excedem o tamanho máximo de envio permitido neste servidor." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Os ficheiros estão a ser analisados, por favor aguarde." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Análise actual" #: templates/upgrade.php:2 msgid "Upgrading filesystem cache..." -msgstr "" +msgstr "Atualizar cache do sistema de ficheiros..." diff --git a/l10n/pt_PT/files_trashbin.po b/l10n/pt_PT/files_trashbin.po new file mode 100644 index 0000000000..150827a263 --- /dev/null +++ b/l10n/pt_PT/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Portuguese (Portugal) (http://www.transifex.com/projects/p/owncloud/language/pt_PT/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: pt_PT\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/pt_PT/settings.po b/l10n/pt_PT/settings.po index 055deff15c..3849efff6e 100644 --- a/l10n/pt_PT/settings.po +++ b/l10n/pt_PT/settings.po @@ -8,14 +8,15 @@ # Duarte Velez Grilo , 2012-2013. # , 2012. # Helder Meneses , 2012. +# Miguel Sousa , 2013. # , 2012. msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" -"Last-Translator: I Robot \n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 01:00+0000\n" +"Last-Translator: Miguel Sousa \n" "Language-Team: Portuguese (Portugal) (http://www.transifex.com/projects/p/owncloud/language/pt_PT/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -270,11 +271,11 @@ msgstr "Armazenamento" #: templates/users.php:97 msgid "change display name" -msgstr "" +msgstr "modificar nome exibido" #: templates/users.php:101 msgid "set new password" -msgstr "" +msgstr "definir nova palavra-passe" #: templates/users.php:137 msgid "Default" diff --git a/l10n/ro/core.po b/l10n/ro/core.po index 838b859f6f..6d28362461 100644 --- a/l10n/ro/core.po +++ b/l10n/ro/core.po @@ -13,8 +13,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Romanian (http://www.transifex.com/projects/p/owncloud/language/ro/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/ro/files.po b/l10n/ro/files.po index e75ae16fdc..a199844446 100644 --- a/l10n/ro/files.po +++ b/l10n/ro/files.po @@ -13,8 +13,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Romanian (http://www.transifex.com/projects/p/owncloud/language/ro/)\n" "MIME-Version: 1.0\n" @@ -60,7 +60,7 @@ msgstr "Eroare la scriere pe disc" #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "Nu este suficient spațiu disponibil" #: ajax/upload.php:82 msgid "Invalid directory." @@ -70,15 +70,15 @@ msgstr "Director invalid." msgid "Files" msgstr "Fișiere" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Anulează partajarea" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Șterge" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Redenumire" @@ -102,7 +102,7 @@ msgstr "anulare" msgid "replaced {new_name}" msgstr "inlocuit {new_name}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "Anulează ultima acțiune" @@ -110,13 +110,9 @@ msgstr "Anulează ultima acțiune" msgid "replaced {new_name} with {old_name}" msgstr "{new_name} inlocuit cu {old_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "nedistribuit {files}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "Sterse {files}" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -140,78 +136,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "Se pregătește descărcarea. Aceasta poate să dureze ceva timp dacă fișierele sunt mari." -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Nu s-a putut încărca fișierul tău deoarece pare să fie un director sau are 0 bytes." -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Eroare la încărcare" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Închide" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "În așteptare" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "un fișier se încarcă" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} fisiere incarcate" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Încărcare anulată." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Fișierul este în curs de încărcare. Părăsirea paginii va întrerupe încărcarea." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "Adresa URL nu poate fi goală." -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "Invalid folder name. Usage of 'Shared' is reserved by Ownclou" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Nume" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Dimensiune" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Modificat" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 folder" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} foldare" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 fisier" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} fisiere" @@ -267,33 +263,37 @@ msgstr "Dosar" msgid "From link" msgstr "de la adresa" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Anulează încărcarea" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Nimic aici. Încarcă ceva!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Descarcă" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Fișierul încărcat este prea mare" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Fișierul care l-ai încărcat a depășită limita maximă admisă la încărcare pe acest server." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Fișierele sunt scanate, te rog așteptă." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "În curs de scanare" diff --git a/l10n/ro/files_trashbin.po b/l10n/ro/files_trashbin.po new file mode 100644 index 0000000000..68e72348ff --- /dev/null +++ b/l10n/ro/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Romanian (http://www.transifex.com/projects/p/owncloud/language/ro/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ro\n" +"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/ru/core.po b/l10n/ru/core.po index 497f496cfe..6f8d26bc80 100644 --- a/l10n/ru/core.po +++ b/l10n/ru/core.po @@ -17,8 +17,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Russian (http://www.transifex.com/projects/p/owncloud/language/ru/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/ru/files.po b/l10n/ru/files.po index f14a42f81b..ce99f9649d 100644 --- a/l10n/ru/files.po +++ b/l10n/ru/files.po @@ -18,8 +18,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Russian (http://www.transifex.com/projects/p/owncloud/language/ru/)\n" "MIME-Version: 1.0\n" @@ -65,7 +65,7 @@ msgstr "Ошибка записи на диск" #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "Недостаточно свободного места" #: ajax/upload.php:82 msgid "Invalid directory." @@ -75,15 +75,15 @@ msgstr "Неправильный каталог." msgid "Files" msgstr "Файлы" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Отменить публикацию" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Удалить" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Переименовать" @@ -107,7 +107,7 @@ msgstr "отмена" msgid "replaced {new_name}" msgstr "заменено {new_name}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "отмена" @@ -115,13 +115,9 @@ msgstr "отмена" msgid "replaced {new_name} with {old_name}" msgstr "заменено {new_name} на {old_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "не опубликованные {files}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "удаленные {files}" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -145,78 +141,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Не удается загрузить файл размером 0 байт в каталог" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Ошибка загрузки" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Закрыть" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Ожидание" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "загружается 1 файл" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} файлов загружается" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Загрузка отменена." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Файл в процессе загрузки. Покинув страницу вы прервёте загрузку." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "Ссылка не может быть пустой." -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "Неправильное имя каталога. Имя 'Shared' зарезервировано." -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Название" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Размер" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Изменён" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 папка" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} папок" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 файл" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} файлов" @@ -272,33 +268,37 @@ msgstr "Папка" msgid "From link" msgstr "Из ссылки" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Отмена загрузки" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Здесь ничего нет. Загрузите что-нибудь!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Скачать" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Файл слишком большой" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Файлы, которые Вы пытаетесь загрузить, превышают лимит для файлов на этом сервере." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Подождите, файлы сканируются." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Текущее сканирование" diff --git a/l10n/ru/files_trashbin.po b/l10n/ru/files_trashbin.po new file mode 100644 index 0000000000..488b1f95b9 --- /dev/null +++ b/l10n/ru/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Russian (http://www.transifex.com/projects/p/owncloud/language/ru/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ru\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/ru_RU/core.po b/l10n/ru_RU/core.po index ad3125e6d9..6618f278e1 100644 --- a/l10n/ru_RU/core.po +++ b/l10n/ru_RU/core.po @@ -9,8 +9,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Russian (Russia) (http://www.transifex.com/projects/p/owncloud/language/ru_RU/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/ru_RU/files.po b/l10n/ru_RU/files.po index f91c30ed74..5cffe8c9d8 100644 --- a/l10n/ru_RU/files.po +++ b/l10n/ru_RU/files.po @@ -3,14 +3,15 @@ # This file is distributed under the same license as the PACKAGE package. # # Translators: +# , 2013. # , 2012. # , 2012. msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Russian (Russia) (http://www.transifex.com/projects/p/owncloud/language/ru_RU/)\n" "MIME-Version: 1.0\n" @@ -56,25 +57,25 @@ msgstr "Не удалось записать на диск" #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "Не достаточно свободного места" #: ajax/upload.php:82 msgid "Invalid directory." -msgstr "" +msgstr "Неверный каталог." #: appinfo/app.php:10 msgid "Files" msgstr "Файлы" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Скрыть" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Удалить" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Переименовать" @@ -98,7 +99,7 @@ msgstr "отменить" msgid "replaced {new_name}" msgstr "заменено {новое_имя}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "отменить действие" @@ -106,21 +107,17 @@ msgstr "отменить действие" msgid "replaced {new_name} with {old_name}" msgstr "заменено {новое_имя} с {старое_имя}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "Cовместное использование прекращено {файлы}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "удалено {файлы}" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." -msgstr "" +msgstr "'.' является неверным именем файла." #: js/files.js:56 msgid "File name cannot be empty." -msgstr "" +msgstr "Имя файла не может быть пустым." #: js/files.js:64 msgid "" @@ -136,78 +133,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Невозможно загрузить файл,\n так как он имеет нулевой размер или является директорией" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Ошибка загрузки" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Закрыть" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Ожидающий решения" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "загрузка 1 файла" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{количество} загружено файлов" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Загрузка отменена" -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Процесс загрузки файла. Если покинуть страницу сейчас, загрузка будет отменена." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "URL не должен быть пустым." -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" -msgstr "" +msgstr "Неверное имя папки. Использование наименования 'Опубликовано' зарезервировано Owncloud" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Имя" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Размер" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Изменен" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 папка" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{количество} папок" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 файл" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{количество} файлов" @@ -263,36 +260,40 @@ msgstr "Папка" msgid "From link" msgstr "По ссылке" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Отмена загрузки" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Здесь ничего нет. Загрузите что-нибудь!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Загрузить" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Загрузка слишком велика" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Размер файлов, которые Вы пытаетесь загрузить, превышает максимально допустимый размер для загрузки на данный сервер." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Файлы сканируются, пожалуйста, подождите." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Текущее сканирование" #: templates/upgrade.php:2 msgid "Upgrading filesystem cache..." -msgstr "" +msgstr "Обновление кэша файловой системы... " diff --git a/l10n/ru_RU/files_encryption.po b/l10n/ru_RU/files_encryption.po index b27f0a2def..2453fc2cb9 100644 --- a/l10n/ru_RU/files_encryption.po +++ b/l10n/ru_RU/files_encryption.po @@ -3,14 +3,15 @@ # This file is distributed under the same license as the PACKAGE package. # # Translators: +# , 2013. # , 2012. msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-23 00:05+0100\n" -"PO-Revision-Date: 2013-01-22 23:05+0000\n" -"Last-Translator: I Robot \n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 12:11+0000\n" +"Last-Translator: AnnaSch \n" "Language-Team: Russian (Russia) (http://www.transifex.com/projects/p/owncloud/language/ru_RU/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -22,11 +23,11 @@ msgstr "" msgid "" "Please switch to your ownCloud client and change your encryption password to" " complete the conversion." -msgstr "" +msgstr "Пожалуйста, переключитесь на ownCloud-клиент и измените Ваш пароль шифрования для завершения конвертации." #: js/settings-personal.js:17 msgid "switched to client side encryption" -msgstr "" +msgstr "переключено на шифрование на клиентской стороне" #: js/settings-personal.js:21 msgid "Change encryption password to login password" @@ -34,7 +35,7 @@ msgstr "" #: js/settings-personal.js:25 msgid "Please check your passwords and try again." -msgstr "" +msgstr "Пожалуйста, проверьте Ваш пароль и попробуйте снова" #: js/settings-personal.js:25 msgid "Could not change your file encryption password to your login password" @@ -42,33 +43,33 @@ msgstr "" #: templates/settings-personal.php:3 templates/settings.php:5 msgid "Choose encryption mode:" -msgstr "" +msgstr "Выберите способ шифрования:" #: templates/settings-personal.php:20 templates/settings.php:24 msgid "" "Client side encryption (most secure but makes it impossible to access your " "data from the web interface)" -msgstr "" +msgstr "Шифрование на стороне клиента (наиболее безопасно, но делает невозможным получение доступа к Вашим данным по вэб-интерфейсу)" #: templates/settings-personal.php:30 templates/settings.php:36 msgid "" "Server side encryption (allows you to access your files from the web " "interface and the desktop client)" -msgstr "" +msgstr "Шифрование на стороне сервера (позволяет Вам получить доступ к Вашим файлам по вэб-интерфейсу и десктопному клиенту)" #: templates/settings-personal.php:41 templates/settings.php:60 msgid "None (no encryption at all)" -msgstr "" +msgstr "Нет (шифрование полностью отсутствует)" #: templates/settings.php:10 msgid "" "Important: Once you selected an encryption mode there is no way to change it" " back" -msgstr "" +msgstr "Важно: Невозможно будет изменить выбранный способ шифрования" #: templates/settings.php:48 msgid "User specific (let the user decide)" -msgstr "" +msgstr "Специфика пользователя (позволено решить пользователю)" #: templates/settings.php:65 msgid "Encryption" diff --git a/l10n/ru_RU/files_trashbin.po b/l10n/ru_RU/files_trashbin.po new file mode 100644 index 0000000000..de62fb208e --- /dev/null +++ b/l10n/ru_RU/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Russian (Russia) (http://www.transifex.com/projects/p/owncloud/language/ru_RU/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ru_RU\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/ru_RU/settings.po b/l10n/ru_RU/settings.po index 9660ab8456..518e016817 100644 --- a/l10n/ru_RU/settings.po +++ b/l10n/ru_RU/settings.po @@ -9,9 +9,9 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" -"Last-Translator: I Robot \n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 13:40+0000\n" +"Last-Translator: AnnaSch \n" "Language-Team: Russian (Russia) (http://www.transifex.com/projects/p/owncloud/language/ru_RU/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -270,7 +270,7 @@ msgstr "" #: templates/users.php:101 msgid "set new password" -msgstr "" +msgstr "назначить новый пароль" #: templates/users.php:137 msgid "Default" diff --git a/l10n/si_LK/core.po b/l10n/si_LK/core.po index 082545b7a7..c03125867c 100644 --- a/l10n/si_LK/core.po +++ b/l10n/si_LK/core.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Sinhala (Sri Lanka) (http://www.transifex.com/projects/p/owncloud/language/si_LK/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/si_LK/files.po b/l10n/si_LK/files.po index ca38591aa1..51da12e3cb 100644 --- a/l10n/si_LK/files.po +++ b/l10n/si_LK/files.po @@ -9,8 +9,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" "Last-Translator: I Robot \n" "Language-Team: Sinhala (Sri Lanka) (http://www.transifex.com/projects/p/owncloud/language/si_LK/)\n" "MIME-Version: 1.0\n" @@ -66,15 +66,15 @@ msgstr "" msgid "Files" msgstr "ගොනු" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "නොබෙදු" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "මකන්න" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "නැවත නම් කරන්න" @@ -98,7 +98,7 @@ msgstr "අත් හරින්න" msgid "replaced {new_name}" msgstr "" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "නිෂ්ප්‍රභ කරන්න" @@ -106,12 +106,8 @@ msgstr "නිෂ්ප්‍රභ කරන්න" msgid "replaced {new_name} with {old_name}" msgstr "" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "" - -#: js/filelist.js:288 -msgid "deleted {files}" +#: js/filelist.js:280 +msgid "perform delete operation" msgstr "" #: js/files.js:52 @@ -136,78 +132,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "උඩුගත කිරීමේ දෝශයක්" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "වසන්න" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "1 ගොනුවක් උඩගත කෙරේ" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "උඩුගත කිරීම අත් හරින්න ලදී" -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "උඩුගතකිරීමක් සිදුවේ. පිටුව හැර යාමෙන් එය නැවතෙනු ඇත" -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "යොමුව හිස් විය නොහැක" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "නම" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "ප්‍රමාණය" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "වෙනස් කළ" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 ෆොල්ඩරයක්" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 ගොනුවක්" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "" @@ -263,33 +259,37 @@ msgstr "ෆෝල්ඩරය" msgid "From link" msgstr "යොමුවෙන්" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "උඩුගත කිරීම අත් හරින්න" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "මෙහි කිසිවක් නොමැත. යමක් උඩුගත කරන්න" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "බාගත කිරීම" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "උඩුගත කිරීම විශාල වැඩිය" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "ඔබ උඩුගත කිරීමට තැත් කරන ගොනු මෙම සේවාදායකයා උඩුගත කිරීමට ඉඩදී ඇති උපරිම ගොනු විශාලත්වයට වඩා වැඩිය" -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "ගොනු පරික්ෂා කෙරේ. මඳක් රැඳී සිටින්න" -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "වර්තමාන පරික්ෂාව" diff --git a/l10n/si_LK/files_trashbin.po b/l10n/si_LK/files_trashbin.po new file mode 100644 index 0000000000..6b75377015 --- /dev/null +++ b/l10n/si_LK/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Sinhala (Sri Lanka) (http://www.transifex.com/projects/p/owncloud/language/si_LK/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: si_LK\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/sk_SK/core.po b/l10n/sk_SK/core.po index 530ce81b43..8e64ab1aaf 100644 --- a/l10n/sk_SK/core.po +++ b/l10n/sk_SK/core.po @@ -13,8 +13,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Slovak (Slovakia) (http://www.transifex.com/projects/p/owncloud/language/sk_SK/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/sk_SK/files.po b/l10n/sk_SK/files.po index 9b4c68104a..2ca4b67297 100644 --- a/l10n/sk_SK/files.po +++ b/l10n/sk_SK/files.po @@ -12,8 +12,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Slovak (Slovakia) (http://www.transifex.com/projects/p/owncloud/language/sk_SK/)\n" "MIME-Version: 1.0\n" @@ -59,7 +59,7 @@ msgstr "Zápis na disk sa nepodaril" #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "Nie je k dispozícii dostatok miesta" #: ajax/upload.php:82 msgid "Invalid directory." @@ -69,15 +69,15 @@ msgstr "Neplatný adresár" msgid "Files" msgstr "Súbory" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Nezdielať" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Odstrániť" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Premenovať" @@ -101,7 +101,7 @@ msgstr "zrušiť" msgid "replaced {new_name}" msgstr "prepísaný {new_name}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "vrátiť" @@ -109,13 +109,9 @@ msgstr "vrátiť" msgid "replaced {new_name} with {old_name}" msgstr "prepísaný {new_name} súborom {old_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "zdieľanie zrušené pre {files}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "zmazané {files}" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -139,78 +135,78 @@ msgstr "Vaše úložisko je plné. Súbory nemožno aktualizovať ani synchroniz msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "Vaše úložisko je takmer plné ({usedSpacePercent}%)" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "Vaše sťahovanie sa pripravuje. Ak sú sťahované súbory veľké, môže to chvíľu trvať." -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Nemôžem nahrať súbor lebo je to priečinok alebo má 0 bajtov." -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Chyba odosielania" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Zavrieť" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Čaká sa" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "1 súbor sa posiela " -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} súborov odosielaných" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Odosielanie zrušené" -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Opustenie stránky zruší práve prebiehajúce odosielanie súboru." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "URL nemôže byť prázdne" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "Neplatné meno adresára. Používanie mena 'Shared' je vyhradené len pre Owncloud" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Meno" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Veľkosť" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Upravené" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 priečinok" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} priečinkov" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 súbor" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} súborov" @@ -266,33 +262,37 @@ msgstr "Priečinok" msgid "From link" msgstr "Z odkazu" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Zrušiť odosielanie" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Žiadny súbor. Nahrajte niečo!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Stiahnuť" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Odosielaný súbor je príliš veľký" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Súbory, ktoré sa snažíte nahrať, presahujú maximálnu veľkosť pre nahratie súborov na tento server." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Čakajte, súbory sú prehľadávané." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Práve prehliadané" diff --git a/l10n/sk_SK/files_trashbin.po b/l10n/sk_SK/files_trashbin.po new file mode 100644 index 0000000000..8615310fbc --- /dev/null +++ b/l10n/sk_SK/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Slovak (Slovakia) (http://www.transifex.com/projects/p/owncloud/language/sk_SK/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sk_SK\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/sl/core.po b/l10n/sl/core.po index ea692e06ee..c1774ede61 100644 --- a/l10n/sl/core.po +++ b/l10n/sl/core.po @@ -11,8 +11,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Slovenian (http://www.transifex.com/projects/p/owncloud/language/sl/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/sl/files.po b/l10n/sl/files.po index 0aadeafed2..dec7d65690 100644 --- a/l10n/sl/files.po +++ b/l10n/sl/files.po @@ -11,8 +11,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Slovenian (http://www.transifex.com/projects/p/owncloud/language/sl/)\n" "MIME-Version: 1.0\n" @@ -68,15 +68,15 @@ msgstr "" msgid "Files" msgstr "Datoteke" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Odstrani iz souporabe" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Izbriši" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Preimenuj" @@ -100,7 +100,7 @@ msgstr "prekliči" msgid "replaced {new_name}" msgstr "zamenjano je ime {new_name}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "razveljavi" @@ -108,13 +108,9 @@ msgstr "razveljavi" msgid "replaced {new_name} with {old_name}" msgstr "zamenjano ime {new_name} z imenom {old_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "odstranjeno iz souporabe {files}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "izbrisano {files}" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -138,78 +134,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Pošiljanje ni mogoče, saj gre za mapo, ali pa je datoteka velikosti 0 bajtov." -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Napaka med nalaganjem" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Zapri" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "V čakanju ..." -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "Pošiljanje 1 datoteke" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "nalagam {count} datotek" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Pošiljanje je preklicano." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "V teku je pošiljanje datoteke. Če zapustite to stran zdaj, bo pošiljanje preklicano." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "Naslov URL ne sme biti prazen." -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Ime" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Velikost" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Spremenjeno" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 mapa" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} map" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 datoteka" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} datotek" @@ -265,33 +261,37 @@ msgstr "Mapa" msgid "From link" msgstr "Iz povezave" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Prekliči pošiljanje" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Tukaj ni ničesar. Naložite kaj!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Prejmi" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Nalaganje ni mogoče, ker je preveliko" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Datoteke, ki jih želite naložiti, presegajo največjo dovoljeno velikost na tem strežniku." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Poteka preučevanje datotek, počakajte ..." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Trenutno poteka preučevanje" diff --git a/l10n/sl/files_trashbin.po b/l10n/sl/files_trashbin.po new file mode 100644 index 0000000000..102ce0e9eb --- /dev/null +++ b/l10n/sl/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Slovenian (http://www.transifex.com/projects/p/owncloud/language/sl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sl\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/sr/core.po b/l10n/sr/core.po index da0a165ac2..b28eef045f 100644 --- a/l10n/sr/core.po +++ b/l10n/sr/core.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Serbian (http://www.transifex.com/projects/p/owncloud/language/sr/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/sr/files.po b/l10n/sr/files.po index 1548c06289..0d4505ebef 100644 --- a/l10n/sr/files.po +++ b/l10n/sr/files.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Serbian (http://www.transifex.com/projects/p/owncloud/language/sr/)\n" "MIME-Version: 1.0\n" @@ -67,15 +67,15 @@ msgstr "" msgid "Files" msgstr "Датотеке" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Укини дељење" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Обриши" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Преименуј" @@ -99,7 +99,7 @@ msgstr "откажи" msgid "replaced {new_name}" msgstr "замењено {new_name}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "опозови" @@ -107,13 +107,9 @@ msgstr "опозови" msgid "replaced {new_name} with {old_name}" msgstr "замењено {new_name} са {old_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "укинуто дељење {files}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "обрисано {files}" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -137,78 +133,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Не могу да отпремим датотеку као фасциклу или она има 0 бајтова" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Грешка при отпремању" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Затвори" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "На чекању" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "Отпремам 1 датотеку" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "Отпремам {count} датотеке/а" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Отпремање је прекинуто." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Отпремање датотеке је у току. Ако сада напустите страницу, прекинућете отпремање." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Назив" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Величина" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Измењено" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 фасцикла" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} фасцикле/и" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 датотека" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} датотеке/а" @@ -264,33 +260,37 @@ msgstr "фасцикла" msgid "From link" msgstr "Са везе" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Прекини отпремање" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Овде нема ничег. Отпремите нешто!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Преузми" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Датотека је превелика" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Датотеке које желите да отпремите прелазе ограничење у величини." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Скенирам датотеке…" -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Тренутно скенирање" diff --git a/l10n/sr/files_trashbin.po b/l10n/sr/files_trashbin.po new file mode 100644 index 0000000000..4841b50b03 --- /dev/null +++ b/l10n/sr/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Serbian (http://www.transifex.com/projects/p/owncloud/language/sr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sr\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/sr@latin/files.po b/l10n/sr@latin/files.po index 9ff8bb26b8..73873acd21 100644 --- a/l10n/sr@latin/files.po +++ b/l10n/sr@latin/files.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Serbian (Latin) (http://www.transifex.com/projects/p/owncloud/language/sr@latin/)\n" "MIME-Version: 1.0\n" @@ -65,15 +65,15 @@ msgstr "" msgid "Files" msgstr "Fajlovi" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Obriši" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "" @@ -97,7 +97,7 @@ msgstr "" msgid "replaced {new_name}" msgstr "" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "" @@ -105,12 +105,8 @@ msgstr "" msgid "replaced {new_name} with {old_name}" msgstr "" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "" - -#: js/filelist.js:288 -msgid "deleted {files}" +#: js/filelist.js:280 +msgid "perform delete operation" msgstr "" #: js/files.js:52 @@ -135,78 +131,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Zatvori" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "" -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "" -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Ime" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Veličina" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Zadnja izmena" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "" @@ -262,33 +258,37 @@ msgstr "" msgid "From link" msgstr "" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Ovde nema ničeg. Pošaljite nešto!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Preuzmi" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Pošiljka je prevelika" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Fajlovi koje želite da pošaljete prevazilaze ograničenje maksimalne veličine pošiljke na ovom serveru." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "" -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "" diff --git a/l10n/sr@latin/files_trashbin.po b/l10n/sr@latin/files_trashbin.po new file mode 100644 index 0000000000..c7c81a1d61 --- /dev/null +++ b/l10n/sr@latin/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Serbian (Latin) (http://www.transifex.com/projects/p/owncloud/language/sr@latin/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sr@latin\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/sv/core.po b/l10n/sv/core.po index dd6eace5cc..71a6c4faec 100644 --- a/l10n/sv/core.po +++ b/l10n/sv/core.po @@ -14,8 +14,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Swedish (http://www.transifex.com/projects/p/owncloud/language/sv/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/sv/files.po b/l10n/sv/files.po index 6193e2e4af..9d76f3178f 100644 --- a/l10n/sv/files.po +++ b/l10n/sv/files.po @@ -14,8 +14,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Swedish (http://www.transifex.com/projects/p/owncloud/language/sv/)\n" "MIME-Version: 1.0\n" @@ -61,7 +61,7 @@ msgstr "Misslyckades spara till disk" #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "Inte tillräckligt med utrymme tillgängligt" #: ajax/upload.php:82 msgid "Invalid directory." @@ -71,15 +71,15 @@ msgstr "Felaktig mapp." msgid "Files" msgstr "Filer" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Sluta dela" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Radera" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Byt namn" @@ -103,7 +103,7 @@ msgstr "avbryt" msgid "replaced {new_name}" msgstr "ersatt {new_name}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "ångra" @@ -111,13 +111,9 @@ msgstr "ångra" msgid "replaced {new_name} with {old_name}" msgstr "ersatt {new_name} med {old_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "stoppad delning {files}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "raderade {files}" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -141,78 +137,78 @@ msgstr "Ditt lagringsutrymme är fullt, filer kan ej längre laddas upp eller sy msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "Ditt lagringsutrymme är nästan fullt ({usedSpacePercent}%)" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "Din nedladdning förbereds. Det kan ta tid om det är stora filer." -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Kunde inte ladda upp dina filer eftersom det antingen är en mapp eller har 0 bytes." -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Uppladdningsfel" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Stäng" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Väntar" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "1 filuppladdning" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} filer laddas upp" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Uppladdning avbruten." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Filuppladdning pågår. Lämnar du sidan så avbryts uppladdningen." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "URL kan inte vara tom." -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "Ogiltigt mappnamn. Användande av 'Shared' är reserverat av ownCloud" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Namn" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Storlek" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Ändrad" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 mapp" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} mappar" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 fil" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} filer" @@ -268,36 +264,40 @@ msgstr "Mapp" msgid "From link" msgstr "Från länk" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Avbryt uppladdning" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Ingenting här. Ladda upp något!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Ladda ner" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "För stor uppladdning" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Filerna du försöker ladda upp överstiger den maximala storleken för filöverföringar på servern." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Filer skannas, var god vänta" -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Aktuell skanning" #: templates/upgrade.php:2 msgid "Upgrading filesystem cache..." -msgstr "" +msgstr "Uppgraderar filsystemets cache..." diff --git a/l10n/sv/files_trashbin.po b/l10n/sv/files_trashbin.po new file mode 100644 index 0000000000..0e87cb89c0 --- /dev/null +++ b/l10n/sv/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Swedish (http://www.transifex.com/projects/p/owncloud/language/sv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sv\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/sv/settings.po b/l10n/sv/settings.po index f8d3cb191d..eef6b68342 100644 --- a/l10n/sv/settings.po +++ b/l10n/sv/settings.po @@ -16,9 +16,9 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" -"Last-Translator: I Robot \n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 02:00+0000\n" +"Last-Translator: Lokal_Profil \n" "Language-Team: Swedish (http://www.transifex.com/projects/p/owncloud/language/sv/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -273,11 +273,11 @@ msgstr "Lagring" #: templates/users.php:97 msgid "change display name" -msgstr "" +msgstr "ändra visat namn" #: templates/users.php:101 msgid "set new password" -msgstr "" +msgstr "ange nytt lösenord" #: templates/users.php:137 msgid "Default" diff --git a/l10n/ta_LK/core.po b/l10n/ta_LK/core.po index ae45ba61f4..acdbe5f39a 100644 --- a/l10n/ta_LK/core.po +++ b/l10n/ta_LK/core.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Tamil (Sri-Lanka) (http://www.transifex.com/projects/p/owncloud/language/ta_LK/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/ta_LK/files.po b/l10n/ta_LK/files.po index 1da508bc1a..c88cea4b33 100644 --- a/l10n/ta_LK/files.po +++ b/l10n/ta_LK/files.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" "Last-Translator: I Robot \n" "Language-Team: Tamil (Sri-Lanka) (http://www.transifex.com/projects/p/owncloud/language/ta_LK/)\n" "MIME-Version: 1.0\n" @@ -65,15 +65,15 @@ msgstr "" msgid "Files" msgstr "கோப்புகள்" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "பகிரப்படாதது" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "அழிக்க" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "பெயர்மாற்றம்" @@ -97,7 +97,7 @@ msgstr "இரத்து செய்க" msgid "replaced {new_name}" msgstr "மாற்றப்பட்டது {new_name}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "முன் செயல் நீக்கம் " @@ -105,13 +105,9 @@ msgstr "முன் செயல் நீக்கம் " msgid "replaced {new_name} with {old_name}" msgstr "{new_name} ஆனது {old_name} இனால் மாற்றப்பட்டது" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "பகிரப்படாதது {கோப்புகள்}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "நீக்கப்பட்டது {கோப்புகள்}" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -135,78 +131,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "அடைவு அல்லது 0 bytes ஐ கொண்டுள்ளதால் உங்களுடைய கோப்பை பதிவேற்ற முடியவில்லை" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "பதிவேற்றல் வழு" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "மூடுக" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "நிலுவையிலுள்ள" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "1 கோப்பு பதிவேற்றப்படுகிறது" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{எண்ணிக்கை} கோப்புகள் பதிவேற்றப்படுகின்றது" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "பதிவேற்றல் இரத்து செய்யப்பட்டுள்ளது" -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "கோப்பு பதிவேற்றம் செயல்பாட்டில் உள்ளது. இந்தப் பக்கத்திலிருந்து வெறியேறுவதானது பதிவேற்றலை இரத்து செய்யும்." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "URL வெறுமையாக இருக்கமுடியாது." -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "பெயர்" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "அளவு" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "மாற்றப்பட்டது" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 கோப்புறை" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{எண்ணிக்கை} கோப்புறைகள்" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 கோப்பு" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{எண்ணிக்கை} கோப்புகள்" @@ -262,33 +258,37 @@ msgstr "கோப்புறை" msgid "From link" msgstr "இணைப்பிலிருந்து" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "பதிவேற்றலை இரத்து செய்க" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "இங்கு ஒன்றும் இல்லை. ஏதாவது பதிவேற்றுக!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "பதிவிறக்குக" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "பதிவேற்றல் மிகப்பெரியது" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "நீங்கள் பதிவேற்ற முயற்சிக்கும் கோப்புகளானது இந்த சேவையகத்தில் கோப்பு பதிவேற்றக்கூடிய ஆகக்கூடிய அளவிலும் கூடியது." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "கோப்புகள் வருடப்படுகின்றன, தயவுசெய்து காத்திருங்கள்." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "தற்போது வருடப்படுபவை" diff --git a/l10n/ta_LK/files_trashbin.po b/l10n/ta_LK/files_trashbin.po new file mode 100644 index 0000000000..6699d6ca96 --- /dev/null +++ b/l10n/ta_LK/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Tamil (Sri-Lanka) (http://www.transifex.com/projects/p/owncloud/language/ta_LK/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ta_LK\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/templates/core.pot b/l10n/templates/core.pot index d6b1cde875..f045b7f034 100644 --- a/l10n/templates/core.pot +++ b/l10n/templates/core.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/l10n/templates/files.pot b/l10n/templates/files.pot index 2eee327bd1..c85bf1abbe 100644 --- a/l10n/templates/files.pot +++ b/l10n/templates/files.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -64,15 +64,15 @@ msgstr "" msgid "Files" msgstr "" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "" @@ -96,7 +96,7 @@ msgstr "" msgid "replaced {new_name}" msgstr "" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "" @@ -104,12 +104,8 @@ msgstr "" msgid "replaced {new_name} with {old_name}" msgstr "" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "" - -#: js/filelist.js:288 -msgid "deleted {files}" +#: js/filelist.js:280 +msgid "perform delete operation" msgstr "" #: js/files.js:52 @@ -134,78 +130,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "" -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "" -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "" @@ -261,33 +257,37 @@ msgstr "" msgid "From link" msgstr "" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "" -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "" -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "" diff --git a/l10n/templates/files_encryption.pot b/l10n/templates/files_encryption.pot index 212a10d2f1..c417aac972 100644 --- a/l10n/templates/files_encryption.pot +++ b/l10n/templates/files_encryption.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/l10n/templates/files_external.pot b/l10n/templates/files_external.pot index bf7231438f..61d11f8c81 100644 --- a/l10n/templates/files_external.pot +++ b/l10n/templates/files_external.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/l10n/templates/files_sharing.pot b/l10n/templates/files_sharing.pot index 6aff7da3cb..faa73d04bf 100644 --- a/l10n/templates/files_sharing.pot +++ b/l10n/templates/files_sharing.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/l10n/templates/files_trashbin.pot b/l10n/templates/files_trashbin.pot new file mode 100644 index 0000000000..b9480bd03c --- /dev/null +++ b/l10n/templates/files_trashbin.pot @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/templates/files_versions.pot b/l10n/templates/files_versions.pot index 9f2014b394..fde4a367dc 100644 --- a/l10n/templates/files_versions.pot +++ b/l10n/templates/files_versions.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/l10n/templates/lib.pot b/l10n/templates/lib.pot index 5fc7047312..b8c44b6184 100644 --- a/l10n/templates/lib.pot +++ b/l10n/templates/lib.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/l10n/templates/settings.pot b/l10n/templates/settings.pot index 8cea75c2ec..37e3dd004a 100644 --- a/l10n/templates/settings.pot +++ b/l10n/templates/settings.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/l10n/templates/user_ldap.pot b/l10n/templates/user_ldap.pot index 1fe3cbd560..5ad61de25c 100644 --- a/l10n/templates/user_ldap.pot +++ b/l10n/templates/user_ldap.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/l10n/templates/user_webdavauth.pot b/l10n/templates/user_webdavauth.pot index d6d2617293..d6f4d1f018 100644 --- a/l10n/templates/user_webdavauth.pot +++ b/l10n/templates/user_webdavauth.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/l10n/th_TH/core.po b/l10n/th_TH/core.po index 4da07c4afb..15c2ea2291 100644 --- a/l10n/th_TH/core.po +++ b/l10n/th_TH/core.po @@ -9,8 +9,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Thai (Thailand) (http://www.transifex.com/projects/p/owncloud/language/th_TH/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/th_TH/files.po b/l10n/th_TH/files.po index 5ad5720bc3..f6d46e93f2 100644 --- a/l10n/th_TH/files.po +++ b/l10n/th_TH/files.po @@ -9,8 +9,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Thai (Thailand) (http://www.transifex.com/projects/p/owncloud/language/th_TH/)\n" "MIME-Version: 1.0\n" @@ -56,7 +56,7 @@ msgstr "เขียนข้อมูลลงแผ่นดิสก์ล้ #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "มีพื้นที่เหลือไม่เพียงพอ" #: ajax/upload.php:82 msgid "Invalid directory." @@ -66,15 +66,15 @@ msgstr "ไดเร็กทอรี่ไม่ถูกต้อง" msgid "Files" msgstr "ไฟล์" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "ยกเลิกการแชร์ข้อมูล" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "ลบ" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "เปลี่ยนชื่อ" @@ -98,7 +98,7 @@ msgstr "ยกเลิก" msgid "replaced {new_name}" msgstr "แทนที่ {new_name} แล้ว" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "เลิกทำ" @@ -106,13 +106,9 @@ msgstr "เลิกทำ" msgid "replaced {new_name} with {old_name}" msgstr "แทนที่ {new_name} ด้วย {old_name} แล้ว" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "ยกเลิกการแชร์แล้ว {files} ไฟล์" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "ลบไฟล์แล้ว {files} ไฟล์" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -136,78 +132,78 @@ msgstr "พื้นที่จัดเก็บข้อมูลของค msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "พื้นที่จัดเก็บข้อมูลของคุณใกล้เต็มแล้ว ({usedSpacePercent}%)" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "กำลังเตรียมดาวน์โหลดข้อมูล หากไฟล์มีขนาดใหญ่ อาจใช้เวลาสักครู่" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "ไม่สามารถอัพโหลดไฟล์ของคุณได้ เนื่องจากไฟล์ดังกล่าวเป็นไดเร็กทอรี่หรือมีขนาด 0 ไบต์" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "เกิดข้อผิดพลาดในการอัพโหลด" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "ปิด" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "อยู่ระหว่างดำเนินการ" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "กำลังอัพโหลดไฟล์ 1 ไฟล์" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "กำลังอัพโหลด {count} ไฟล์" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "การอัพโหลดถูกยกเลิก" -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "การอัพโหลดไฟล์กำลังอยู่ในระหว่างดำเนินการ การออกจากหน้าเว็บนี้จะทำให้การอัพโหลดถูกยกเลิก" -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "URL ไม่สามารถเว้นว่างได้" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "ชื่อโฟลเดอร์ไม่ถูกต้อง การใช้งาน 'แชร์' สงวนไว้สำหรับ Owncloud เท่านั้น" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "ชื่อ" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "ขนาด" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "ปรับปรุงล่าสุด" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 โฟลเดอร์" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} โฟลเดอร์" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 ไฟล์" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} ไฟล์" @@ -263,33 +259,37 @@ msgstr "แฟ้มเอกสาร" msgid "From link" msgstr "จากลิงก์" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "ยกเลิกการอัพโหลด" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "ยังไม่มีไฟล์ใดๆอยู่ที่นี่ กรุณาอัพโหลดไฟล์!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "ดาวน์โหลด" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "ไฟล์ที่อัพโหลดมีขนาดใหญ่เกินไป" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "ไฟล์ที่คุณพยายามที่จะอัพโหลดมีขนาดเกินกว่าขนาดสูงสุดที่กำหนดไว้ให้อัพโหลดได้สำหรับเซิร์ฟเวอร์นี้" -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "ไฟล์กำลังอยู่ระหว่างการสแกน, กรุณารอสักครู่." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "ไฟล์ที่กำลังสแกนอยู่ขณะนี้" diff --git a/l10n/th_TH/files_trashbin.po b/l10n/th_TH/files_trashbin.po new file mode 100644 index 0000000000..d9dc1b0c7a --- /dev/null +++ b/l10n/th_TH/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Thai (Thailand) (http://www.transifex.com/projects/p/owncloud/language/th_TH/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: th_TH\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/tr/core.po b/l10n/tr/core.po index 04e9beae3d..e6a8df2a9a 100644 --- a/l10n/tr/core.po +++ b/l10n/tr/core.po @@ -12,8 +12,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Turkish (http://www.transifex.com/projects/p/owncloud/language/tr/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/tr/files.po b/l10n/tr/files.po index 118c91724c..773605dbba 100644 --- a/l10n/tr/files.po +++ b/l10n/tr/files.po @@ -13,8 +13,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Turkish (http://www.transifex.com/projects/p/owncloud/language/tr/)\n" "MIME-Version: 1.0\n" @@ -60,7 +60,7 @@ msgstr "Diske yazılamadı" #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "Yeterli disk alanı yok" #: ajax/upload.php:82 msgid "Invalid directory." @@ -70,15 +70,15 @@ msgstr "Geçersiz dizin." msgid "Files" msgstr "Dosyalar" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Paylaşılmayan" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Sil" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "İsim değiştir." @@ -102,7 +102,7 @@ msgstr "iptal" msgid "replaced {new_name}" msgstr "değiştirilen {new_name}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "geri al" @@ -110,13 +110,9 @@ msgstr "geri al" msgid "replaced {new_name} with {old_name}" msgstr "{new_name} ismi {old_name} ile değiştirildi" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "paylaşılmamış {files}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "silinen {files}" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -140,78 +136,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "İndirmeniz hazırlanıyor. Dosya büyük ise biraz zaman alabilir." -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Dosyanızın boyutu 0 byte olduğundan veya bir dizin olduğundan yüklenemedi" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Yükleme hatası" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Kapat" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Bekliyor" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "1 dosya yüklendi" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} dosya yükleniyor" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Yükleme iptal edildi." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Dosya yükleme işlemi sürüyor. Şimdi sayfadan ayrılırsanız işleminiz iptal olur." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "URL boş olamaz." -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "Geçersiz dizin adı. Shared isminin kullanımı Owncloud tarafından rezerver edilmiştir." -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Ad" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Boyut" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Değiştirilme" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 dizin" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} dizin" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 dosya" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} dosya" @@ -267,33 +263,37 @@ msgstr "Klasör" msgid "From link" msgstr "Bağlantıdan" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Yüklemeyi iptal et" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Burada hiçbir şey yok. Birşeyler yükleyin!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "İndir" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Yüklemeniz çok büyük" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Yüklemeye çalıştığınız dosyalar bu sunucudaki maksimum yükleme boyutunu aşıyor." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Dosyalar taranıyor, lütfen bekleyin." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Güncel tarama" diff --git a/l10n/tr/files_trashbin.po b/l10n/tr/files_trashbin.po new file mode 100644 index 0000000000..03eb077131 --- /dev/null +++ b/l10n/tr/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Turkish (http://www.transifex.com/projects/p/owncloud/language/tr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tr\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/uk/core.po b/l10n/uk/core.po index 5574b3859a..03b5844519 100644 --- a/l10n/uk/core.po +++ b/l10n/uk/core.po @@ -12,8 +12,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Ukrainian (http://www.transifex.com/projects/p/owncloud/language/uk/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/uk/files.po b/l10n/uk/files.po index 65eb2a8b8a..7f4b486f21 100644 --- a/l10n/uk/files.po +++ b/l10n/uk/files.po @@ -10,8 +10,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Ukrainian (http://www.transifex.com/projects/p/owncloud/language/uk/)\n" "MIME-Version: 1.0\n" @@ -67,15 +67,15 @@ msgstr "" msgid "Files" msgstr "Файли" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Заборонити доступ" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Видалити" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Перейменувати" @@ -99,7 +99,7 @@ msgstr "відміна" msgid "replaced {new_name}" msgstr "замінено {new_name}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "відмінити" @@ -107,13 +107,9 @@ msgstr "відмінити" msgid "replaced {new_name} with {old_name}" msgstr "замінено {new_name} на {old_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "неопубліковано {files}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "видалено {files}" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -137,78 +133,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Неможливо завантажити ваш файл тому, що він тека або файл розміром 0 байт" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Помилка завантаження" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Закрити" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Очікування" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "1 файл завантажується" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} файлів завантажується" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Завантаження перервано." -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Виконується завантаження файлу. Закриття цієї сторінки приведе до відміни завантаження." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "URL не може бути пустим." -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Ім'я" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Розмір" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Змінено" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 папка" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} папок" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 файл" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} файлів" @@ -264,33 +260,37 @@ msgstr "Папка" msgid "From link" msgstr "З посилання" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Перервати завантаження" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Тут нічого немає. Відвантажте що-небудь!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Завантажити" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Файл занадто великий" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Файли,що ви намагаєтесь відвантажити перевищують максимальний дозволений розмір файлів на цьому сервері." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Файли скануються, зачекайте, будь-ласка." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Поточне сканування" diff --git a/l10n/uk/files_trashbin.po b/l10n/uk/files_trashbin.po new file mode 100644 index 0000000000..3dbbe27d58 --- /dev/null +++ b/l10n/uk/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Ukrainian (http://www.transifex.com/projects/p/owncloud/language/uk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: uk\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/vi/core.po b/l10n/vi/core.po index ecabca5e69..7434016d8e 100644 --- a/l10n/vi/core.po +++ b/l10n/vi/core.po @@ -12,8 +12,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Vietnamese (http://www.transifex.com/projects/p/owncloud/language/vi/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/vi/files.po b/l10n/vi/files.po index 6b5902bb63..c7458d0610 100644 --- a/l10n/vi/files.po +++ b/l10n/vi/files.po @@ -11,8 +11,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Vietnamese (http://www.transifex.com/projects/p/owncloud/language/vi/)\n" "MIME-Version: 1.0\n" @@ -68,15 +68,15 @@ msgstr "" msgid "Files" msgstr "Tập tin" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "Không chia sẽ" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "Xóa" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "Sửa tên" @@ -100,7 +100,7 @@ msgstr "hủy" msgid "replaced {new_name}" msgstr "đã thay thế {new_name}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "lùi lại" @@ -108,13 +108,9 @@ msgstr "lùi lại" msgid "replaced {new_name} with {old_name}" msgstr "đã thay thế {new_name} bằng {old_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "hủy chia sẽ {files}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "đã xóa {files}" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -138,78 +134,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "Không thể tải lên tập tin này do nó là một thư mục hoặc kích thước tập tin bằng 0 byte" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "Tải lên lỗi" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "Đóng" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Chờ" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "1 tệp tin đang được tải lên" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} tập tin đang tải lên" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "Hủy tải lên" -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "Tập tin tải lên đang được xử lý. Nếu bạn rời khỏi trang bây giờ sẽ hủy quá trình này." -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "URL không được để trống." -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "Tên" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "Kích cỡ" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "Thay đổi" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 thư mục" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} thư mục" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 tập tin" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} tập tin" @@ -265,33 +261,37 @@ msgstr "Thư mục" msgid "From link" msgstr "Từ liên kết" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "Hủy upload" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "Không có gì ở đây .Hãy tải lên một cái gì đó !" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "Tải xuống" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "Tập tin tải lên quá lớn" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "Các tập tin bạn đang tải lên vượt quá kích thước tối đa cho phép trên máy chủ ." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "Tập tin đang được quét ,vui lòng chờ." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "Hiện tại đang quét" diff --git a/l10n/vi/files_trashbin.po b/l10n/vi/files_trashbin.po new file mode 100644 index 0000000000..41ce4eb64e --- /dev/null +++ b/l10n/vi/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Vietnamese (http://www.transifex.com/projects/p/owncloud/language/vi/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: vi\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/zh_CN.GB2312/core.po b/l10n/zh_CN.GB2312/core.po index dbfa5828be..089c03e33c 100644 --- a/l10n/zh_CN.GB2312/core.po +++ b/l10n/zh_CN.GB2312/core.po @@ -9,8 +9,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Chinese (China) (GB2312) (http://www.transifex.com/projects/p/owncloud/language/zh_CN.GB2312/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/zh_CN.GB2312/files.po b/l10n/zh_CN.GB2312/files.po index 04c75d2f0c..8ad4ff2a59 100644 --- a/l10n/zh_CN.GB2312/files.po +++ b/l10n/zh_CN.GB2312/files.po @@ -9,8 +9,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Chinese (China) (GB2312) (http://www.transifex.com/projects/p/owncloud/language/zh_CN.GB2312/)\n" "MIME-Version: 1.0\n" @@ -66,15 +66,15 @@ msgstr "" msgid "Files" msgstr "文件" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "取消共享" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "删除" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "重命名" @@ -98,7 +98,7 @@ msgstr "取消" msgid "replaced {new_name}" msgstr "已替换 {new_name}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "撤销" @@ -106,13 +106,9 @@ msgstr "撤销" msgid "replaced {new_name} with {old_name}" msgstr "已用 {old_name} 替换 {new_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "未分享的 {files}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "已删除的 {files}" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -136,78 +132,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "不能上传你指定的文件,可能因为它是个文件夹或者大小为0" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "上传错误" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "关闭" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "Pending" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "1 个文件正在上传" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} 个文件正在上传" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "上传取消了" -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "文件正在上传。关闭页面会取消上传。" -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "网址不能为空。" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "名字" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "大小" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "修改日期" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 个文件夹" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} 个文件夹" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 个文件" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} 个文件" @@ -263,33 +259,37 @@ msgstr "文件夹" msgid "From link" msgstr "来自链接" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "取消上传" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "这里没有东西.上传点什么!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "下载" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "上传的文件太大了" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "你正在试图上传的文件超过了此服务器支持的最大的文件大小." -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "正在扫描文件,请稍候." -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "正在扫描" diff --git a/l10n/zh_CN.GB2312/files_trashbin.po b/l10n/zh_CN.GB2312/files_trashbin.po new file mode 100644 index 0000000000..4da5c5879d --- /dev/null +++ b/l10n/zh_CN.GB2312/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Chinese (China) (GB2312) (http://www.transifex.com/projects/p/owncloud/language/zh_CN.GB2312/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_CN.GB2312\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/zh_CN/core.po b/l10n/zh_CN/core.po index 58bc32e1e4..054c70f7fa 100644 --- a/l10n/zh_CN/core.po +++ b/l10n/zh_CN/core.po @@ -13,8 +13,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Chinese (China) (http://www.transifex.com/projects/p/owncloud/language/zh_CN/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/zh_CN/files.po b/l10n/zh_CN/files.po index 5f9a49f752..3ccaa537b3 100644 --- a/l10n/zh_CN/files.po +++ b/l10n/zh_CN/files.po @@ -14,8 +14,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Chinese (China) (http://www.transifex.com/projects/p/owncloud/language/zh_CN/)\n" "MIME-Version: 1.0\n" @@ -61,7 +61,7 @@ msgstr "写入磁盘失败" #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "没有足够可用空间" #: ajax/upload.php:82 msgid "Invalid directory." @@ -71,15 +71,15 @@ msgstr "无效文件夹。" msgid "Files" msgstr "文件" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "取消分享" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "删除" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "重命名" @@ -103,7 +103,7 @@ msgstr "取消" msgid "replaced {new_name}" msgstr "替换 {new_name}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "撤销" @@ -111,13 +111,9 @@ msgstr "撤销" msgid "replaced {new_name} with {old_name}" msgstr "已将 {old_name}替换成 {new_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "取消了共享 {files}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "删除了 {files}" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -141,78 +137,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "下载正在准备中。如果文件较大可能会花费一些时间。" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "无法上传文件,因为它是一个目录或者大小为 0 字节" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "上传错误" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "关闭" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "操作等待中" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "1个文件上传中" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} 个文件上传中" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "上传已取消" -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "文件正在上传中。现在离开此页会导致上传动作被取消。" -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "URL不能为空" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "无效文件夹名。'共享' 是 Owncloud 预留的文件夹名。" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "名称" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "大小" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "修改日期" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1个文件夹" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} 个文件夹" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 个文件" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} 个文件" @@ -268,33 +264,37 @@ msgstr "文件夹" msgid "From link" msgstr "来自链接" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "取消上传" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "这里还什么都没有。上传些东西吧!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "下载" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "上传文件过大" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "您正尝试上传的文件超过了此服务器可以上传的最大容量限制" -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "文件正在被扫描,请稍候。" -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "当前扫描" diff --git a/l10n/zh_CN/files_trashbin.po b/l10n/zh_CN/files_trashbin.po new file mode 100644 index 0000000000..68de848c4a --- /dev/null +++ b/l10n/zh_CN/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Chinese (China) (http://www.transifex.com/projects/p/owncloud/language/zh_CN/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_CN\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/zh_HK/files.po b/l10n/zh_HK/files.po index 152d04b392..3a61b47c5a 100644 --- a/l10n/zh_HK/files.po +++ b/l10n/zh_HK/files.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Chinese (Hong Kong) (http://www.transifex.com/projects/p/owncloud/language/zh_HK/)\n" "MIME-Version: 1.0\n" @@ -64,15 +64,15 @@ msgstr "" msgid "Files" msgstr "" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "" @@ -96,7 +96,7 @@ msgstr "" msgid "replaced {new_name}" msgstr "" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "" @@ -104,12 +104,8 @@ msgstr "" msgid "replaced {new_name} with {old_name}" msgstr "" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "" - -#: js/filelist.js:288 -msgid "deleted {files}" +#: js/filelist.js:280 +msgid "perform delete operation" msgstr "" #: js/files.js:52 @@ -134,78 +130,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "" -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "" -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "" -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "" @@ -261,33 +257,37 @@ msgstr "" msgid "From link" msgstr "" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "" -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "" -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "" diff --git a/l10n/zh_HK/files_trashbin.po b/l10n/zh_HK/files_trashbin.po new file mode 100644 index 0000000000..d6fa5fa828 --- /dev/null +++ b/l10n/zh_HK/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Chinese (Hong Kong) (http://www.transifex.com/projects/p/owncloud/language/zh_HK/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_HK\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/l10n/zh_TW/core.po b/l10n/zh_TW/core.po index ff36663374..787cdb9d00 100644 --- a/l10n/zh_TW/core.po +++ b/l10n/zh_TW/core.po @@ -11,8 +11,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 12:46+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-30 23:40+0000\n" "Last-Translator: I Robot \n" "Language-Team: Chinese (Taiwan) (http://www.transifex.com/projects/p/owncloud/language/zh_TW/)\n" "MIME-Version: 1.0\n" diff --git a/l10n/zh_TW/files.po b/l10n/zh_TW/files.po index 8e3bf55ca6..5082c3edac 100644 --- a/l10n/zh_TW/files.po +++ b/l10n/zh_TW/files.po @@ -13,8 +13,8 @@ msgid "" msgstr "" "Project-Id-Version: ownCloud\n" "Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" -"POT-Creation-Date: 2013-01-31 00:27+0100\n" -"PO-Revision-Date: 2013-01-30 23:28+0000\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:02+0000\n" "Last-Translator: I Robot \n" "Language-Team: Chinese (Taiwan) (http://www.transifex.com/projects/p/owncloud/language/zh_TW/)\n" "MIME-Version: 1.0\n" @@ -60,7 +60,7 @@ msgstr "寫入硬碟失敗" #: ajax/upload.php:51 msgid "Not enough space available" -msgstr "" +msgstr "沒有足夠的可用空間" #: ajax/upload.php:82 msgid "Invalid directory." @@ -70,15 +70,15 @@ msgstr "無效的資料夾。" msgid "Files" msgstr "檔案" -#: js/fileactions.js:117 templates/index.php:81 templates/index.php:82 +#: js/fileactions.js:117 templates/index.php:85 templates/index.php:86 msgid "Unshare" msgstr "取消共享" -#: js/fileactions.js:119 templates/index.php:87 templates/index.php:88 +#: js/fileactions.js:119 templates/index.php:91 templates/index.php:92 msgid "Delete" msgstr "刪除" -#: js/fileactions.js:181 +#: js/fileactions.js:185 msgid "Rename" msgstr "重新命名" @@ -102,7 +102,7 @@ msgstr "取消" msgid "replaced {new_name}" msgstr "已取代 {new_name}" -#: js/filelist.js:253 js/filelist.js:255 js/filelist.js:286 js/filelist.js:288 +#: js/filelist.js:253 js/filelist.js:255 msgid "undo" msgstr "復原" @@ -110,13 +110,9 @@ msgstr "復原" msgid "replaced {new_name} with {old_name}" msgstr "使用 {new_name} 取代 {old_name}" -#: js/filelist.js:286 -msgid "unshared {files}" -msgstr "已取消分享 {files}" - -#: js/filelist.js:288 -msgid "deleted {files}" -msgstr "已刪除 {files}" +#: js/filelist.js:280 +msgid "perform delete operation" +msgstr "" #: js/files.js:52 msgid "'.' is an invalid file name." @@ -140,78 +136,78 @@ msgstr "" msgid "Your storage is almost full ({usedSpacePercent}%)" msgstr "" -#: js/files.js:219 +#: js/files.js:224 msgid "" "Your download is being prepared. This might take some time if the files are " "big." msgstr "正在準備您的下載,若您的檔案較大,將會需要更多時間。" -#: js/files.js:256 +#: js/files.js:261 msgid "Unable to upload your file as it is a directory or has 0 bytes" msgstr "無法上傳您的檔案因為它可能是一個目錄或檔案大小為0" -#: js/files.js:256 +#: js/files.js:261 msgid "Upload Error" msgstr "上傳發生錯誤" -#: js/files.js:273 +#: js/files.js:278 msgid "Close" msgstr "關閉" -#: js/files.js:292 js/files.js:408 js/files.js:439 +#: js/files.js:297 js/files.js:413 js/files.js:444 msgid "Pending" msgstr "等候中" -#: js/files.js:312 +#: js/files.js:317 msgid "1 file uploading" msgstr "1 個檔案正在上傳" -#: js/files.js:315 js/files.js:370 js/files.js:385 +#: js/files.js:320 js/files.js:375 js/files.js:390 msgid "{count} files uploading" msgstr "{count} 個檔案正在上傳" -#: js/files.js:388 js/files.js:423 +#: js/files.js:393 js/files.js:428 msgid "Upload cancelled." msgstr "上傳取消" -#: js/files.js:497 +#: js/files.js:502 msgid "" "File upload is in progress. Leaving the page now will cancel the upload." msgstr "檔案上傳中。離開此頁面將會取消上傳。" -#: js/files.js:570 +#: js/files.js:575 msgid "URL cannot be empty." msgstr "URL 不能為空白." -#: js/files.js:575 +#: js/files.js:580 msgid "Invalid folder name. Usage of 'Shared' is reserved by Owncloud" msgstr "無效的資料夾名稱,'Shared' 的使用被 Owncloud 保留" -#: js/files.js:944 templates/index.php:63 +#: js/files.js:949 templates/index.php:67 msgid "Name" msgstr "名稱" -#: js/files.js:945 templates/index.php:74 +#: js/files.js:950 templates/index.php:78 msgid "Size" msgstr "大小" -#: js/files.js:946 templates/index.php:76 +#: js/files.js:951 templates/index.php:80 msgid "Modified" msgstr "修改" -#: js/files.js:965 +#: js/files.js:970 msgid "1 folder" msgstr "1 個資料夾" -#: js/files.js:967 +#: js/files.js:972 msgid "{count} folders" msgstr "{count} 個資料夾" -#: js/files.js:975 +#: js/files.js:980 msgid "1 file" msgstr "1 個檔案" -#: js/files.js:977 +#: js/files.js:982 msgid "{count} files" msgstr "{count} 個檔案" @@ -267,33 +263,37 @@ msgstr "資料夾" msgid "From link" msgstr "從連結" -#: templates/index.php:41 +#: templates/index.php:40 +msgid "Trash" +msgstr "" + +#: templates/index.php:46 msgid "Cancel upload" msgstr "取消上傳" -#: templates/index.php:55 +#: templates/index.php:59 msgid "Nothing in here. Upload something!" msgstr "沒有任何東西。請上傳內容!" -#: templates/index.php:69 +#: templates/index.php:73 msgid "Download" msgstr "下載" -#: templates/index.php:101 +#: templates/index.php:105 msgid "Upload too large" msgstr "上傳過大" -#: templates/index.php:103 +#: templates/index.php:107 msgid "" "The files you are trying to upload exceed the maximum size for file uploads " "on this server." msgstr "您試圖上傳的檔案已超過伺服器的最大檔案大小限制。 " -#: templates/index.php:108 +#: templates/index.php:112 msgid "Files are being scanned, please wait." msgstr "正在掃描檔案,請稍等。" -#: templates/index.php:111 +#: templates/index.php:115 msgid "Current scanning" msgstr "目前掃描" diff --git a/l10n/zh_TW/files_trashbin.po b/l10n/zh_TW/files_trashbin.po new file mode 100644 index 0000000000..7a77dadbde --- /dev/null +++ b/l10n/zh_TW/files_trashbin.po @@ -0,0 +1,58 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: ownCloud\n" +"Report-Msgid-Bugs-To: http://bugs.owncloud.org/\n" +"POT-Creation-Date: 2013-01-31 17:02+0100\n" +"PO-Revision-Date: 2013-01-31 16:03+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Chinese (Taiwan) (http://www.transifex.com/projects/p/owncloud/language/zh_TW/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_TW\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: js/trash.js:7 +msgid "perform restore operation" +msgstr "" + +#: js/trash.js:69 +msgid "perform undelete operation" +msgstr "" + +#: js/trash.js:100 templates/index.php:17 +msgid "Name" +msgstr "" + +#: js/trash.js:101 templates/index.php:27 +msgid "Deleted" +msgstr "" + +#: js/trash.js:110 +msgid "1 folder" +msgstr "" + +#: js/trash.js:112 +msgid "{count} folders" +msgstr "" + +#: js/trash.js:120 +msgid "1 file" +msgstr "" + +#: js/trash.js:122 +msgid "{count} files" +msgstr "" + +#: templates/index.php:9 +msgid "Nothing in here. Your trash bin is empty!" +msgstr "" + +#: templates/index.php:20 templates/index.php:22 +msgid "Restore" +msgstr "" diff --git a/lib/l10n/ko.php b/lib/l10n/ko.php index c4716f9f8b..859657f46b 100644 --- a/lib/l10n/ko.php +++ b/lib/l10n/ko.php @@ -9,6 +9,7 @@ "Files need to be downloaded one by one." => "파일을 개별적으로 다운로드해야 합니다.", "Back to Files" => "파일로 돌아가기", "Selected files too large to generate zip file." => "선택한 파일들은 ZIP 파일을 생성하기에 너무 큽니다.", +"couldn't be determined" => "결정할 수 없음", "Application is not enabled" => "앱이 활성화되지 않았습니다", "Authentication error" => "인증 오류", "Token expired. Please reload page." => "토큰이 만료되었습니다. 페이지를 새로 고치십시오.", diff --git a/settings/l10n/ca.php b/settings/l10n/ca.php index 35c0b7a934..2f9bcba4a5 100644 --- a/settings/l10n/ca.php +++ b/settings/l10n/ca.php @@ -58,6 +58,8 @@ "Display Name" => "Nom a mostrar", "Group Admin" => "Grup Admin", "Storage" => "Emmagatzemament", +"change display name" => "canvia el nom a mostrar", +"set new password" => "estableix nova contrasenya", "Default" => "Per defecte", "Delete" => "Suprimeix" ); diff --git a/settings/l10n/cs_CZ.php b/settings/l10n/cs_CZ.php index f9e8f2155d..a2d8e335dc 100644 --- a/settings/l10n/cs_CZ.php +++ b/settings/l10n/cs_CZ.php @@ -58,6 +58,8 @@ "Display Name" => "Zobrazované jméno", "Group Admin" => "Správa skupiny", "Storage" => "Úložiště", +"change display name" => "změnit zobrazované jméno", +"set new password" => "nastavit nové heslo", "Default" => "Výchozí", "Delete" => "Smazat" ); diff --git a/settings/l10n/it.php b/settings/l10n/it.php index 806732933d..c8d8f16ace 100644 --- a/settings/l10n/it.php +++ b/settings/l10n/it.php @@ -58,6 +58,8 @@ "Display Name" => "Nome visualizzato", "Group Admin" => "Gruppi amministrati", "Storage" => "Archiviazione", +"change display name" => "cambia il nome visualizzato", +"set new password" => "imposta una nuova password", "Default" => "Predefinito", "Delete" => "Elimina" ); diff --git a/settings/l10n/ko.php b/settings/l10n/ko.php index 3a794eb3ce..3601d77c9f 100644 --- a/settings/l10n/ko.php +++ b/settings/l10n/ko.php @@ -21,16 +21,16 @@ "More Apps" => "더 많은 앱", "Select an App" => "앱 선택", "See application page at apps.owncloud.com" => "apps.owncloud.com에 있는 앱 페이지를 참고하십시오", -"-licensed by " => "-라이선스 보유자 ", -"User Documentation" => "유저 문서", +"-licensed by " => "-라이선스됨: ", +"User Documentation" => "사용자 문서", "Administrator Documentation" => "관리자 문서", "Online Documentation" => "온라인 문서", "Forum" => "포럼", -"Bugtracker" => "버그트래커", +"Bugtracker" => "버그 트래커", "Commercial Support" => "상업용 지원", "You have used %s of the available %s" => "현재 공간 %s/%s을(를) 사용 중입니다", -"Clients" => "고객", -"Download Desktop Clients" => "데스크탑 클라이언트 다운로드", +"Clients" => "클라이언트", +"Download Desktop Clients" => "데스크톱 클라이언트 다운로드", "Download Android Client" => "안드로이드 클라이언트 다운로드", "Download iOS Client" => "iOS 클라이언트 다운로드", "Password" => "암호", @@ -46,16 +46,20 @@ "Language" => "언어", "Help translate" => "번역 돕기", "WebDAV" => "WebDAV", -"Use this address to connect to your ownCloud in your file manager" => "파일 매니저에서 사용자의 ownCloud에 접속하기 위해 이 주소를 사용하십시요.", -"Version" => "버젼", +"Use this address to connect to your ownCloud in your file manager" => "파일 관리자에서 ownCloud에 접속하려면 이 주소를 사용하십시오.", +"Version" => "버전", "Developed by the ownCloud community, the source code is licensed under the AGPL." => "ownCloud 커뮤니티에 의해서 개발되었습니다. 원본 코드AGPL에 따라 사용이 허가됩니다.", +"Login Name" => "로그인 이름", "Groups" => "그룹", "Create" => "만들기", "Default Storage" => "기본 저장소", "Unlimited" => "무제한", "Other" => "기타", +"Display Name" => "표시 이름", "Group Admin" => "그룹 관리자", "Storage" => "저장소", +"change display name" => "표시 이름 변경", +"set new password" => "새 암호 설정", "Default" => "기본값", "Delete" => "삭제" ); diff --git a/settings/l10n/pt_PT.php b/settings/l10n/pt_PT.php index 86d4c2778c..24bf8c75e5 100644 --- a/settings/l10n/pt_PT.php +++ b/settings/l10n/pt_PT.php @@ -58,6 +58,8 @@ "Display Name" => "Nome público", "Group Admin" => "Grupo Administrador", "Storage" => "Armazenamento", +"change display name" => "modificar nome exibido", +"set new password" => "definir nova palavra-passe", "Default" => "Padrão", "Delete" => "Apagar" ); diff --git a/settings/l10n/ru_RU.php b/settings/l10n/ru_RU.php index 50c3b136c4..642b31ada7 100644 --- a/settings/l10n/ru_RU.php +++ b/settings/l10n/ru_RU.php @@ -56,6 +56,7 @@ "Other" => "Другой", "Group Admin" => "Группа Admin", "Storage" => "Хранилище", +"set new password" => "назначить новый пароль", "Default" => "По умолчанию", "Delete" => "Удалить" ); diff --git a/settings/l10n/sv.php b/settings/l10n/sv.php index 1bf3d22595..29d11d8574 100644 --- a/settings/l10n/sv.php +++ b/settings/l10n/sv.php @@ -58,6 +58,8 @@ "Display Name" => "Visat namn", "Group Admin" => "Gruppadministratör", "Storage" => "Lagring", +"change display name" => "ändra visat namn", +"set new password" => "ange nytt lösenord", "Default" => "Förvald", "Delete" => "Radera" ); From a17a7f5cdbd6db27207e066d6e6baa147ba717aa Mon Sep 17 00:00:00 2001 From: Thomas Mueller Date: Thu, 31 Jan 2013 17:43:24 +0100 Subject: [PATCH 335/347] adding l10n support to user_ldap --- apps/user_ldap/ajax/deleteConfiguration.php | 3 ++- apps/user_ldap/ajax/testConfiguration.php | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/apps/user_ldap/ajax/deleteConfiguration.php b/apps/user_ldap/ajax/deleteConfiguration.php index e91e75bbba..b7d633a049 100644 --- a/apps/user_ldap/ajax/deleteConfiguration.php +++ b/apps/user_ldap/ajax/deleteConfiguration.php @@ -30,5 +30,6 @@ $prefix = $_POST['ldap_serverconfig_chooser']; if(\OCA\user_ldap\lib\Helper::deleteServerConfiguration($prefix)){ OCP\JSON::success(); } else { - OCP\JSON::error(array('message' => 'Failed to delete the server configuration')); + $l=OC_L10N::get('user_ldap'); + OCP\JSON::error(array('message' => $l->t('Failed to delete the server configuration'))); } \ No newline at end of file diff --git a/apps/user_ldap/ajax/testConfiguration.php b/apps/user_ldap/ajax/testConfiguration.php index fd72485268..f8038e3146 100644 --- a/apps/user_ldap/ajax/testConfiguration.php +++ b/apps/user_ldap/ajax/testConfiguration.php @@ -26,14 +26,16 @@ OCP\JSON::checkAdminUser(); OCP\JSON::checkAppEnabled('user_ldap'); OCP\JSON::callCheck(); +$l=OC_L10N::get('user_ldap'); + $connection = new \OCA\user_ldap\lib\Connection('', null); if($connection->setConfiguration($_POST)) { //Configuration is okay if($connection->bind()) { - OCP\JSON::success(array('message' => 'The configuration is valid and the connection could be established!')); + OCP\JSON::success(array('message' => $l->t('The configuration is valid and the connection could be established!'))); } else { - OCP\JSON::error(array('message' => 'The configuration is valid, but the Bind failed. Please check the server settings and credentials.')); + OCP\JSON::error(array('message' => $l->t('The configuration is valid, but the Bind failed. Please check the server settings and credentials.'))); } } else { - OCP\JSON::error(array('message' => 'The configuration is invalid. Please look in the ownCloud log for further details.')); + OCP\JSON::error(array('message' => $l->t('The configuration is invalid. Please look in the ownCloud log for further details.'))); } From 7f2d7cdbe1b822721ecb3b696937835f36564f39 Mon Sep 17 00:00:00 2001 From: Thomas Mueller Date: Thu, 31 Jan 2013 17:44:25 +0100 Subject: [PATCH 336/347] spell check --- apps/user_ldap/appinfo/update.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/user_ldap/appinfo/update.php b/apps/user_ldap/appinfo/update.php index 11e1928991..f9681e38e6 100644 --- a/apps/user_ldap/appinfo/update.php +++ b/apps/user_ldap/appinfo/update.php @@ -5,7 +5,7 @@ //ATTENTION //Upgrade from ownCloud 3 (LDAP backend 0.1) to ownCloud 4.5 (LDAP backend 0.3) is not supported!! //You must do upgrade to ownCloud 4.0 first! -//The upgrade stuff in the section from 0.1 to 0.2 is just to minimize the bad efffects. +//The upgrade stuff in the section from 0.1 to 0.2 is just to minimize the bad effects. //settings $pw = OCP\Config::getAppValue('user_ldap', 'ldap_password'); @@ -85,6 +85,6 @@ function escapeDN($dn) { if(!isset($connector)) { $connector = new \OCA\user_ldap\lib\Connection(); } -//it is required, that connections do habe ldap_configuration_active setting stored in the database +//it is required, that connections do have ldap_configuration_active setting stored in the database $connector->getConfiguration(); $connector->saveConfiguration(); \ No newline at end of file From a224d80f4d3266fa9b046aa13081285c4efd61b8 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 31 Jan 2013 17:49:58 +0100 Subject: [PATCH 337/347] Sort internal apps above 3rdparty apps --- settings/apps.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/settings/apps.php b/settings/apps.php index 4f8eba159c..b9ed2cac93 100644 --- a/settings/apps.php +++ b/settings/apps.php @@ -36,6 +36,10 @@ function app_sort( $a, $b ) { } + if ($a['internal'] != $b['internal']) { + return $b['internal'] - $a['internal']; + } + return strcmp($a['name'], $b['name']); } From 5862f3d140357bd2da91f0034dab0eeb2ae4a1a0 Mon Sep 17 00:00:00 2001 From: Thomas Mueller Date: Thu, 31 Jan 2013 17:51:59 +0100 Subject: [PATCH 338/347] spell check --- apps/user_ldap/lib/connection.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/user_ldap/lib/connection.php b/apps/user_ldap/lib/connection.php index 8ddc106d0b..7a9732b2ce 100644 --- a/apps/user_ldap/lib/connection.php +++ b/apps/user_ldap/lib/connection.php @@ -97,7 +97,7 @@ class Connection { public function __set($name, $value) { $changed = false; - //omly few options are writable + //only few options are writable if($name == 'ldapUuidAttribute') { \OCP\Util::writeLog('user_ldap', 'Set config ldapUuidAttribute to '.$value, \OCP\Util::DEBUG); $this->config[$name] = $value; @@ -455,8 +455,8 @@ ingle parameters } /** - * @returns an associted array with the default values. Keys are correspond - * to configvalue entries in the database table + * @returns an associative array with the default values. Keys are correspond + * to config-value entries in the database table */ public function getDefaults() { return array( From 19714151e218114cbff8439186adb94155344490 Mon Sep 17 00:00:00 2001 From: Thomas Mueller Date: Thu, 31 Jan 2013 17:53:01 +0100 Subject: [PATCH 339/347] spell check --- apps/user_ldap/lib/helper.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/user_ldap/lib/helper.php b/apps/user_ldap/lib/helper.php index 3c4b98af1a..29ce998dae 100644 --- a/apps/user_ldap/lib/helper.php +++ b/apps/user_ldap/lib/helper.php @@ -37,7 +37,7 @@ class Helper { * 'configkey' have a prefix. The prefix for the very first server * configuration is empty. * Configkey Examples: - * Server 1: ldap_login_filtter + * Server 1: ldap_login_filter * Server 2: s1_ldap_login_filter * Server 3: s2_ldap_login_filter * @@ -72,7 +72,7 @@ class Helper { /** * @brief deletes a given saved LDAP/AD server configuration. * @param string the configuration prefix of the config to delete - * @return bool true on success, false otherweise + * @return bool true on success, false otherwise */ static public function deleteServerConfiguration($prefix) { //just to be on the safe side From 5417e44b2a6d03042156e002264525091f66a6ad Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 31 Jan 2013 17:56:44 +0100 Subject: [PATCH 340/347] Files: fix moving files by DnD --- apps/files/ajax/move.php | 4 ++-- apps/files/js/upload.js | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 apps/files/js/upload.js diff --git a/apps/files/ajax/move.php b/apps/files/ajax/move.php index 99e43ed23b..78ed218c13 100644 --- a/apps/files/ajax/move.php +++ b/apps/files/ajax/move.php @@ -17,8 +17,8 @@ if(\OC\Files\Filesystem::file_exists($target . '/' . $file)) { } if ($dir != '' || $file != 'Shared') { - $targetFile = \OC\Files\Filesystem::normalizePath($dir . '/' . $file); - $sourceFile = \OC\Files\Filesystem::normalizePath($target . '/' . $file); + $targetFile = \OC\Files\Filesystem::normalizePath($target . '/' . $file); + $sourceFile = \OC\Files\Filesystem::normalizePath($dir . '/' . $file); if(\OC\Files\Filesystem::rename($sourceFile, $targetFile)) { OCP\JSON::success(array("data" => array( "dir" => $dir, "files" => $file ))); } else { diff --git a/apps/files/js/upload.js b/apps/files/js/upload.js new file mode 100644 index 0000000000..9d9f61f600 --- /dev/null +++ b/apps/files/js/upload.js @@ -0,0 +1,8 @@ +function Upload(fileSelector) { + if ($.support.xhrFileUpload) { + return new XHRUpload(fileSelector.target.files); + } else { + return new FormUpload(fileSelector); + } +} +Upload.target = OC.filePath('files', 'ajax', 'upload.php'); From afacaf8bc2b4c0aca0130b961df2f0e12408e5bc Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Thu, 31 Jan 2013 18:00:07 +0100 Subject: [PATCH 341/347] string fragment was added by accident and does not belong here --- apps/user_ldap/lib/connection.php | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/user_ldap/lib/connection.php b/apps/user_ldap/lib/connection.php index 7a9732b2ce..acc33e047c 100644 --- a/apps/user_ldap/lib/connection.php +++ b/apps/user_ldap/lib/connection.php @@ -314,7 +314,6 @@ class Connection { /** * @brief saves the current Configuration in the database -ingle parameters */ public function saveConfiguration() { $trans = array_flip($this->getConfigTranslationArray()); From ab2b79cda682a697baba2128a21d3a9b5e90853c Mon Sep 17 00:00:00 2001 From: Stefan Herbrechtsmeier Date: Sun, 9 Sep 2012 12:54:47 +0200 Subject: [PATCH 342/347] add multiple domains reverse proxy support Add support for a reverse proxy that handles multiple domains via different web roots (http[s]://proxy.tld/domain.tld/owncloud). As the reverse proxy web root is transparent for the web server the REQUEST_URI and SCRIPT_NAME need manual adjustments. This patch replace the direct use of this _SERVER variables with function calls and extend this functions to overwrite the web root. Additionally it adds a Sabre request backend that extends the Sabre_HTTP_Request to use the same functions. --- apps/files/appinfo/remote.php | 2 ++ apps/files/index.php | 2 +- config/config.sample.php | 3 ++ lib/app.php | 2 +- lib/base.php | 6 ++-- lib/connector/sabre/request.php | 50 +++++++++++++++++++++++++++++++++ lib/public/util.php | 22 +++++++++++++++ lib/request.php | 32 +++++++++++++++++++++ lib/util.php | 2 +- ocs/providers.php | 2 +- 10 files changed, 116 insertions(+), 7 deletions(-) create mode 100644 lib/connector/sabre/request.php diff --git a/apps/files/appinfo/remote.php b/apps/files/appinfo/remote.php index 6a78a1e0d7..6c92cc80b6 100644 --- a/apps/files/appinfo/remote.php +++ b/apps/files/appinfo/remote.php @@ -32,12 +32,14 @@ OC_Util::obEnd(); // Backends $authBackend = new OC_Connector_Sabre_Auth(); $lockBackend = new OC_Connector_Sabre_Locks(); +$requestBackend = new OC_Connector_Sabre_Request(); // Create ownCloud Dir $publicDir = new OC_Connector_Sabre_Directory(''); // Fire up server $server = new Sabre_DAV_Server($publicDir); +$server->httpRequest = $requestBackend; $server->setBaseUri($baseuri); // Load plugins diff --git a/apps/files/index.php b/apps/files/index.php index 7e767cc8a4..104cf1a55d 100644 --- a/apps/files/index.php +++ b/apps/files/index.php @@ -36,7 +36,7 @@ OCP\App::setActiveNavigationEntry('files_index'); $dir = isset($_GET['dir']) ? stripslashes($_GET['dir']) : ''; // Redirect if directory does not exist if (!\OC\Files\Filesystem::is_dir($dir . '/')) { - header('Location: ' . $_SERVER['SCRIPT_NAME'] . ''); + header('Location: ' . OCP\Util::getScriptName() . ''); exit(); } diff --git a/config/config.sample.php b/config/config.sample.php index 05663a09a4..ebe73fbec7 100644 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -38,6 +38,9 @@ $CONFIG = array( /* The automatic protocol detection of ownCloud can fail in certain reverse proxy situations. This option allows to manually override the protocol detection. For example "https" */ "overwriteprotocol" => "", +/* The automatic webroot detection of ownCloud can fail in certain reverse proxy situations. This option allows to manually override the automatic detection. For example "/domain.tld/ownCloud" */ +"overwritewebroot" => "", + /* A proxy to use to connect to the internet. For example "myproxy.org:88" */ "proxy" => "", diff --git a/lib/app.php b/lib/app.php index 7aafeb3629..fa3e14ce4d 100644 --- a/lib/app.php +++ b/lib/app.php @@ -506,7 +506,7 @@ class OC_App{ * @return string */ public static function getCurrentApp() { - $script=substr($_SERVER["SCRIPT_NAME"], strlen(OC::$WEBROOT)+1); + $script=substr(OC_Request::scriptName(), strlen(OC::$WEBROOT)+1); $topFolder=substr($script, 0, strpos($script, '/')); if (empty($topFolder)) { $path_info = OC_Request::getPathInfo(); diff --git a/lib/base.php b/lib/base.php index ea5c939cd8..232350b59e 100644 --- a/lib/base.php +++ b/lib/base.php @@ -129,7 +129,7 @@ class OC // calculate the root directories OC::$SERVERROOT = str_replace("\\", '/', substr(__DIR__, 0, -4)); OC::$SUBURI = str_replace("\\", "/", substr(realpath($_SERVER["SCRIPT_FILENAME"]), strlen(OC::$SERVERROOT))); - $scriptName = $_SERVER["SCRIPT_NAME"]; + $scriptName = OC_Request::scriptName(); if (substr($scriptName, -1) == '/') { $scriptName .= 'index.php'; //make sure suburi follows the same rules as scriptName @@ -230,7 +230,7 @@ class OC header('Strict-Transport-Security: max-age=31536000'); ini_set("session.cookie_secure", "on"); if (OC_Request::serverProtocol() <> 'https' and !OC::$CLI) { - $url = "https://" . OC_Request::serverHost() . $_SERVER['REQUEST_URI']; + $url = "https://" . OC_Request::serverHost() . OC_Request::requestUri(); header("Location: $url"); exit(); } @@ -764,7 +764,7 @@ class OC 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_User::unsetMagicInCookie(); - $_REQUEST['redirect_url'] = (isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : ''); + $_REQUEST['redirect_url'] = OC_Request::requestUri(); OC_Util::redirectToDefaultPage(); } return true; diff --git a/lib/connector/sabre/request.php b/lib/connector/sabre/request.php new file mode 100644 index 0000000000..97a27996bf --- /dev/null +++ b/lib/connector/sabre/request.php @@ -0,0 +1,50 @@ + + * + * 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 . + * + */ + +class OC_Connector_Sabre_Request extends Sabre_HTTP_Request { + /** + * Returns the requested uri + * + * @return string + */ + public function getUri() { + return OC_Request::requestUri(); + } + + /** + * Returns a specific item from the _SERVER array. + * + * Do not rely on this feature, it is for internal use only. + * + * @param string $field + * @return string + */ + public function getRawServerValue($field) { + if($field == 'REQUEST_URI'){ + return $this->getUri(); + } + else{ + return isset($this->_SERVER[$field])?$this->_SERVER[$field]:null; + } + } +} diff --git a/lib/public/util.php b/lib/public/util.php index 413dbcccd2..a78a52f326 100644 --- a/lib/public/util.php +++ b/lib/public/util.php @@ -218,6 +218,28 @@ class Util { return(\OC_Request::serverProtocol()); } + /** + * @brief Returns the request uri + * @returns the request uri + * + * Returns the request uri, even if the website uses one or more + * reverse proxies + */ + public static function getRequestUri() { + return(\OC_Request::requestUri()); + } + + /** + * @brief Returns the script name + * @returns the script name + * + * Returns the script name, even if the website uses one or more + * reverse proxies + */ + public static function getScriptName() { + return(\OC_Request::scriptName()); + } + /** * @brief Creates path to an image * @param string $app app diff --git a/lib/request.php b/lib/request.php index f2f15c2110..4c056ce9b2 100755 --- a/lib/request.php +++ b/lib/request.php @@ -58,6 +58,38 @@ class OC_Request { return $proto; } + /** + * @brief Returns the request uri + * @returns the request uri + * + * Returns the request uri, even if the website uses one or more + * reverse proxies + */ + public static function requestUri() { + $uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : ''; + if (OC_Config::getValue('overwritewebroot', '') <> '') { + $uri = self::scriptName() . substr($uri, strlen($_SERVER['SCRIPT_NAME'])); + } + return $uri; + } + + /** + * @brief Returns the script name + * @returns the script name + * + * Returns the script name, even if the website uses one or more + * reverse proxies + */ + public static function scriptName() { + $name = $_SERVER['SCRIPT_NAME']; + if (OC_Config::getValue('overwritewebroot', '') <> '') { + $serverroot = str_replace("\\", '/', substr(__DIR__, 0, -4)); + $suburi = str_replace("\\", "/", substr(realpath($_SERVER["SCRIPT_FILENAME"]), strlen($serverroot))); + $name = OC_Config::getValue('overwritewebroot', '') . $suburi; + } + return $name; + } + /** * @brief get Path info from request * @returns string Path info or false when not found diff --git a/lib/util.php b/lib/util.php index e8057abe9a..809f6a88be 100755 --- a/lib/util.php +++ b/lib/util.php @@ -312,7 +312,7 @@ class OC_Util { public static function checkLoggedIn() { // Check if we are a user if( !OC_User::isLoggedIn()) { - header( 'Location: '.OC_Helper::linkToAbsolute( '', 'index.php', array('redirect_url' => $_SERVER["REQUEST_URI"]))); + header( 'Location: '.OC_Helper::linkToAbsolute( '', 'index.php', array('redirect_url' => OC_Request::requestUri()))); exit(); } } diff --git a/ocs/providers.php b/ocs/providers.php index 0c7cbaeff0..bf94b85dcf 100644 --- a/ocs/providers.php +++ b/ocs/providers.php @@ -23,7 +23,7 @@ require_once '../lib/base.php'; -$url=OCP\Util::getServerProtocol().'://'.substr(OCP\Util::getServerHost().$_SERVER['REQUEST_URI'], 0, -17).'ocs/v1.php/'; +$url=OCP\Util::getServerProtocol().'://'.substr(OCP\Util::getServerHost().OCP\Util::getRequestUri(), 0, -17).'ocs/v1.php/'; echo(' From 7747f49263bb45674228318a81bb0f2bd214df34 Mon Sep 17 00:00:00 2001 From: herbrechtsmeier Date: Sun, 6 Jan 2013 12:24:40 +0100 Subject: [PATCH 343/347] add SSL proxy support Add support for a reverse proxy that only forwards SSL connections unencrypted to the web server. This patch allows to detect the reverse proxy via regular expression for the remote IP address and conditional overwrite the host name, protocol and web root. --- config/config.sample.php | 3 +++ lib/request.php | 17 +++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/config/config.sample.php b/config/config.sample.php index ebe73fbec7..5264e94820 100644 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -41,6 +41,9 @@ $CONFIG = array( /* The automatic webroot detection of ownCloud can fail in certain reverse proxy situations. This option allows to manually override the automatic detection. For example "/domain.tld/ownCloud" */ "overwritewebroot" => "", +/* The automatic detection of ownCloud can fail in certain reverse proxy situations. This option allows to define a manually override condition as regular expression for the remote ip address. For example "^10\.0\.0\.[1-3]$" */ +"overwritecondaddr" => "", + /* A proxy to use to connect to the internet. For example "myproxy.org:88" */ "proxy" => "", diff --git a/lib/request.php b/lib/request.php index 4c056ce9b2..1661a1406c 100755 --- a/lib/request.php +++ b/lib/request.php @@ -7,6 +7,15 @@ */ class OC_Request { + /** + * @brief Check overwrite condition + * @returns true/false + */ + private static function isOverwriteCondition() { + $regex = '/' . OC_Config::getValue('overwritecondaddr', '') . '/'; + return $regex === '//' or preg_match($regex, $_SERVER['REMOTE_ADDR']) === 1; + } + /** * @brief Returns the server host * @returns the server host @@ -18,7 +27,7 @@ class OC_Request { if(OC::$CLI) { return 'localhost'; } - if(OC_Config::getValue('overwritehost', '')<>'') { + if(OC_Config::getValue('overwritehost', '')<>'' and self::isOverwriteCondition()) { return OC_Config::getValue('overwritehost'); } if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) { @@ -43,7 +52,7 @@ class OC_Request { * Returns the server protocol. It respects reverse proxy servers and load balancers */ public static function serverProtocol() { - if(OC_Config::getValue('overwriteprotocol', '')<>'') { + if(OC_Config::getValue('overwriteprotocol', '')<>'' and self::isOverwriteCondition()) { return OC_Config::getValue('overwriteprotocol'); } if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) { @@ -67,7 +76,7 @@ class OC_Request { */ public static function requestUri() { $uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : ''; - if (OC_Config::getValue('overwritewebroot', '') <> '') { + if (OC_Config::getValue('overwritewebroot', '') <> '' and self::isOverwriteCondition()) { $uri = self::scriptName() . substr($uri, strlen($_SERVER['SCRIPT_NAME'])); } return $uri; @@ -82,7 +91,7 @@ class OC_Request { */ public static function scriptName() { $name = $_SERVER['SCRIPT_NAME']; - if (OC_Config::getValue('overwritewebroot', '') <> '') { + if (OC_Config::getValue('overwritewebroot', '') <> '' and self::isOverwriteCondition()) { $serverroot = str_replace("\\", '/', substr(__DIR__, 0, -4)); $suburi = str_replace("\\", "/", substr(realpath($_SERVER["SCRIPT_FILENAME"]), strlen($serverroot))); $name = OC_Config::getValue('overwritewebroot', '') . $suburi; From 943c0334c147155b99cb43e5ec8e41f8a4bb3a32 Mon Sep 17 00:00:00 2001 From: Jan-Christoph Borchardt Date: Thu, 31 Jan 2013 20:27:39 +0100 Subject: [PATCH 344/347] remove z-index from app labels which caused overlap with top bar --- settings/css/settings.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/settings/css/settings.css b/settings/css/settings.css index 35c7176d45..667539cd68 100644 --- a/settings/css/settings.css +++ b/settings/css/settings.css @@ -55,8 +55,8 @@ small.recommendedapp.list { float: right; } span.version { margin-left:1em; margin-right:1em; color:#555; } .app { position: relative; display: inline-block; padding: 0.2em 0 0.2em 0 !important; text-overflow: hidden; overflow: hidden; white-space: nowrap; /*transition: .2s max-width linear; -o-transition: .2s max-width linear; -moz-transition: .2s max-width linear; -webkit-transition: .2s max-width linear; -ms-transition: .2s max-width linear;*/ } -.app.externalapp { max-width: 12.5em; z-index: 100; } -.app.recommendedapp { max-width: 12.5em; z-index: 100; } +.app.externalapp { max-width: 12.5em; } +.app.recommendedapp { max-width: 12.5em; } /* Transition to complete width! */ .app:hover, .app:active { max-width: inherit; } From a1dc24c9daef6f976adf2101fe104e8c5d7dc4b2 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Thu, 31 Jan 2013 21:19:24 +0100 Subject: [PATCH 345/347] LDAP: implement getDisplayName and getDisplayNames also for UserProxy (multiple server support) --- apps/user_ldap/user_proxy.php | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/apps/user_ldap/user_proxy.php b/apps/user_ldap/user_proxy.php index 47f901ddb5..5609f72ee6 100644 --- a/apps/user_ldap/user_proxy.php +++ b/apps/user_ldap/user_proxy.php @@ -146,6 +146,33 @@ class User_Proxy extends lib\Proxy implements \OCP\UserInterface { return $this->handleRequest($uid, 'getHome', array($uid)); } + /** + * @brief get display name of the user + * @param $uid user ID of the user + * @return display name + */ + public function getDisplayName($uid) { + return $this->handleRequest($uid, 'getDisplayName', array($uid)); + } + + /** + * @brief Get a list of all display names + * @returns array with all displayNames (value) and the correspondig uids (key) + * + * Get a list of all display names and user ids. + */ + public function getDisplayNames($search = '', $limit = null, $offset = null) { + //we do it just as the /OC_User implementation: do not play around with limit and offset but ask all backends + $users = array(); + foreach($this->backends as $backend) { + $backendUsers = $backend->getDisplayNames($search, $limit, $offset); + if (is_array($backendUsers)) { + $users = array_merge($users, $backendUsers); + } + } + return $users; + } + /** * @brief delete a user * @param $uid The username of the user to delete From 17f94de19b5a22c791d4d099ab3a7ad11b254445 Mon Sep 17 00:00:00 2001 From: Brice Maron Date: Thu, 31 Jan 2013 21:55:51 +0100 Subject: [PATCH 346/347] Case insensitive Lang Detection fix #1328 --- lib/l10n.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/l10n.php b/lib/l10n.php index ca53b3cf65..ee87900926 100644 --- a/lib/l10n.php +++ b/lib/l10n.php @@ -287,7 +287,7 @@ class OC_L10N{ } if(isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { - $accepted_languages = preg_split('/,\s*/', $_SERVER['HTTP_ACCEPT_LANGUAGE']); + $accepted_languages = preg_split('/,\s*/', strtolower($_SERVER['HTTP_ACCEPT_LANGUAGE'])); if(is_array($app)) { $available = $app; } From fc585623a5f0f65bc14a3228ff7e305414e61332 Mon Sep 17 00:00:00 2001 From: Thomas Mueller Date: Thu, 31 Jan 2013 22:49:07 +0100 Subject: [PATCH 347/347] spell check :+1: --- apps/user_ldap/user_proxy.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/user_ldap/user_proxy.php b/apps/user_ldap/user_proxy.php index 5609f72ee6..a94be3354f 100644 --- a/apps/user_ldap/user_proxy.php +++ b/apps/user_ldap/user_proxy.php @@ -157,7 +157,7 @@ class User_Proxy extends lib\Proxy implements \OCP\UserInterface { /** * @brief Get a list of all display names - * @returns array with all displayNames (value) and the correspondig uids (key) + * @returns array with all displayNames (value) and the corresponding uids (key) * * Get a list of all display names and user ids. */