aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/files/ajax/list.php2
-rw-r--r--apps/files/index.php3
-rw-r--r--apps/files/js/filelist.js6
-rwxr-xr-xapps/files_encryption/lib/helper.php51
-rw-r--r--apps/files_encryption/lib/proxy.php12
-rw-r--r--apps/files_encryption/lib/stream.php2
-rw-r--r--apps/files_encryption/tests/helper.php15
-rw-r--r--apps/files_external/3rdparty/smb4php/smb.php3
-rw-r--r--apps/files_external/css/settings.css4
-rw-r--r--apps/files_sharing/lib/sharedstorage.php106
-rw-r--r--apps/files_versions/js/versions.js2
-rw-r--r--apps/user_ldap/css/settings.css8
-rw-r--r--apps/user_ldap/js/settings.js27
-rw-r--r--apps/user_ldap/lib/wizard.php59
-rw-r--r--apps/user_ldap/templates/part.wizard-server.php4
-rw-r--r--apps/user_ldap/templates/settings.php3
-rw-r--r--core/css/multiselect.css1
-rw-r--r--core/js/multiselect.js2
-rw-r--r--db_structure.xml30
-rw-r--r--lib/private/api.php63
-rw-r--r--lib/private/db/mdb2schemareader.php7
-rw-r--r--lib/private/files/cache/homecache.php40
-rw-r--r--lib/private/files/filesystem.php34
-rw-r--r--lib/private/files/storage/common.php10
-rw-r--r--lib/private/files/storage/home.php21
-rw-r--r--lib/private/preview/image.php4
-rw-r--r--lib/private/preview/movies.php59
-rw-r--r--lib/private/preview/mp3.php6
-rw-r--r--lib/private/preview/office-cl.php3
-rw-r--r--lib/private/preview/office-fallback.php3
-rw-r--r--lib/public/share.php2
-rw-r--r--settings/css/settings.css5
-rw-r--r--tests/data/db_structure.xml22
-rw-r--r--tests/data/db_structure2.xml22
-rw-r--r--tests/lib/api.php128
-rw-r--r--tests/lib/db/mdb2schemareader.php4
-rw-r--r--tests/lib/files/cache/cache.php55
-rw-r--r--tests/lib/files/cache/homecache.php95
-rw-r--r--tests/lib/files/filesystem.php121
-rw-r--r--tests/lib/files/storage/home.php29
-rw-r--r--version.php4
41 files changed, 870 insertions, 207 deletions
diff --git a/apps/files/ajax/list.php b/apps/files/ajax/list.php
index 350fc7fa5f6..0be38c3b96f 100644
--- a/apps/files/ajax/list.php
+++ b/apps/files/ajax/list.php
@@ -10,7 +10,7 @@ OCP\JSON::checkLoggedIn();
// Load the files
$dir = isset( $_GET['dir'] ) ? $_GET['dir'] : '';
-
+$dir = \OC\Files\Filesystem::normalizePath($dir);
if (!\OC\Files\Filesystem::is_dir($dir . '/')) {
header("HTTP/1.0 404 Not Found");
exit();
diff --git a/apps/files/index.php b/apps/files/index.php
index f0f95b3bac8..9ae378d7a1d 100644
--- a/apps/files/index.php
+++ b/apps/files/index.php
@@ -36,6 +36,7 @@ OCP\Util::addscript('files', 'filelist');
OCP\App::setActiveNavigationEntry('files_index');
// Load the files
$dir = isset($_GET['dir']) ? stripslashes($_GET['dir']) : '';
+$dir = \OC\Files\Filesystem::normalizePath($dir);
// Redirect if directory does not exist
if (!\OC\Files\Filesystem::is_dir($dir . '/')) {
header('Location: ' . OCP\Util::getScriptName() . '');
@@ -128,7 +129,7 @@ if ($needUpgrade) {
$tmpl = new OCP\Template('files', 'index', 'user');
$tmpl->assign('fileList', $list->fetchPage());
$tmpl->assign('breadcrumb', $breadcrumbNav->fetchPage());
- $tmpl->assign('dir', \OC\Files\Filesystem::normalizePath($dir));
+ $tmpl->assign('dir', $dir);
$tmpl->assign('isCreatable', $isCreatable);
$tmpl->assign('permissions', $permissions);
$tmpl->assign('files', $files);
diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js
index 0a94657c2d8..49dd28517be 100644
--- a/apps/files/js/filelist.js
+++ b/apps/files/js/filelist.js
@@ -660,19 +660,19 @@ var FileList={
$('.summary .filesize').html(humanFileSize(fileSummary.totalSize));
// Show only what's necessary (may be hidden)
- if ($dirInfo.html().charAt(0) === "0") {
+ if (fileSummary.totalDirs === 0) {
$dirInfo.hide();
$connector.hide();
} else {
$dirInfo.show();
}
- if ($fileInfo.html().charAt(0) === "0") {
+ if (fileSummary.totalFiles === 0) {
$fileInfo.hide();
$connector.hide();
} else {
$fileInfo.show();
}
- if ($dirInfo.html().charAt(0) !== "0" && $fileInfo.html().charAt(0) !== "0") {
+ if (fileSummary.totalDirs > 0 && fileSummary.totalFiles > 0) {
$connector.show();
}
}
diff --git a/apps/files_encryption/lib/helper.php b/apps/files_encryption/lib/helper.php
index 314ac577b2f..0ac6fcf403a 100755
--- a/apps/files_encryption/lib/helper.php
+++ b/apps/files_encryption/lib/helper.php
@@ -165,7 +165,7 @@ class Helper {
public static function isPartialFilePath($path) {
$extension = pathinfo($path, PATHINFO_EXTENSION);
- if ( $extension === 'part' || $extension === 'etmp') {
+ if ( $extension === 'part') {
return true;
} else {
return false;
@@ -183,7 +183,7 @@ class Helper {
public static function stripPartialFileExtension($path) {
$extension = pathinfo($path, PATHINFO_EXTENSION);
- if ( $extension === 'part' || $extension === 'etmp') {
+ if ( $extension === 'part') {
$newLength = strlen($path) - 5; // 5 = strlen(".part") = strlen(".etmp")
$fPath = substr($path, 0, $newLength);
@@ -256,24 +256,53 @@ class Helper {
}
/**
- * @brief get path to the correspondig file in data/user/files
+ * @brief get path to the correspondig file in data/user/files if path points
+ * to a version or to a file in cache
* @param string $path path to a version or a file in the trash
* @return string path to correspondig file relative to data/user/files
*/
public static function getPathToRealFile($path) {
$trimmed = ltrim($path, '/');
$split = explode('/', $trimmed);
-
- if (count($split) < 3 || $split[1] !== "files_versions") {
- return false;
+ $result = false;
+
+ if (count($split) >= 3 && ($split[1] === "files_versions" || $split[1] === 'cache')) {
+ $sliced = array_slice($split, 2);
+ $result = implode('/', $sliced);
+ if ($split[1] === "files_versions") {
+ // we skip user/files
+ $sliced = array_slice($split, 2);
+ $relPath = implode('/', $sliced);
+ //remove the last .v
+ $result = substr($relPath, 0, strrpos($relPath, '.v'));
+ }
+ if ($split[1] === "cache") {
+ // we skip /user/cache/transactionId
+ $sliced = array_slice($split, 3);
+ $result = implode('/', $sliced);
+ //prepare the folders
+ self::mkdirr($path, new \OC\Files\View('/'));
+ }
}
- $sliced = array_slice($split, 2);
- $realPath = implode('/', $sliced);
- //remove the last .v
- $realPath = substr($realPath, 0, strrpos($realPath, '.v'));
+ return $result;
+ }
- return $realPath;
+ /**
+ * @brief create directory recursively
+ * @param string $path
+ * @param \OC\Files\View $view
+ */
+ public static function mkdirr($path, $view) {
+ $dirname = \OC_Filesystem::normalizePath(dirname($path));
+ $dirParts = explode('/', $dirname);
+ $dir = "";
+ foreach ($dirParts as $part) {
+ $dir = $dir . '/' . $part;
+ if (!$view->file_exists($dir)) {
+ $view->mkdir($dir);
+ }
+ }
}
/**
diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php
index e2bc8f6b163..54c3b9caa15 100644
--- a/apps/files_encryption/lib/proxy.php
+++ b/apps/files_encryption/lib/proxy.php
@@ -90,7 +90,13 @@ class Proxy extends \OC_FileProxy {
return true;
}
- $handle = fopen('crypt://' . $path . '.etmp', 'w');
+ // create random cache folder
+ $cacheFolder = rand();
+ $path_slices = explode('/', \OC_Filesystem::normalizePath($path));
+ $path_slices[2] = "cache/".$cacheFolder;
+ $tmpPath = implode('/', $path_slices);
+
+ $handle = fopen('crypt://' . $tmpPath, 'w');
if (is_resource($handle)) {
// write data to stream
@@ -104,10 +110,10 @@ class Proxy extends \OC_FileProxy {
\OC_FileProxy::$enabled = false;
// get encrypted content
- $data = $view->file_get_contents($path . '.etmp');
+ $data = $view->file_get_contents($tmpPath);
// remove our temp file
- $view->unlink($path . '.etmp');
+ $view->deleteAll('/' . \OCP\User::getUser() . '/cache/' . $cacheFolder);
// re-enable proxy - our work is done
\OC_FileProxy::$enabled = $proxyStatus;
diff --git a/apps/files_encryption/lib/stream.php b/apps/files_encryption/lib/stream.php
index 069d9145a28..fe85b2eac4a 100644
--- a/apps/files_encryption/lib/stream.php
+++ b/apps/files_encryption/lib/stream.php
@@ -109,7 +109,7 @@ class Stream {
}
if($this->relPath === false) {
- \OCP\Util::writeLog('Encryption library', 'failed to open file "' . $this->rawPath . '" expecting a path to user/files or to user/files_versions', \OCP\Util::ERROR);
+ \OCP\Util::writeLog('Encryption library', 'failed to open file "' . $this->rawPath . '" expecting a path to "files", "files_versions" or "cache"', \OCP\Util::ERROR);
return false;
}
diff --git a/apps/files_encryption/tests/helper.php b/apps/files_encryption/tests/helper.php
index 067fc763a95..cd2be70a8fe 100644
--- a/apps/files_encryption/tests/helper.php
+++ b/apps/files_encryption/tests/helper.php
@@ -51,4 +51,17 @@ class Test_Encryption_Helper extends \PHPUnit_Framework_TestCase {
$this->assertEquals('testfile.txt', Encryption\Helper::stripPartialFileExtension($filename));
}
-} \ No newline at end of file
+ function testGetPathToRealFile() {
+
+ // the relative path to /user/files/ that's what we want to get from getPathToRealFile()
+ $relativePath = "foo/bar/test.txt";
+
+ // test paths
+ $versionPath = "/user/files_versions/foo/bar/test.txt.v456756835";
+ $cachePath = "/user/cache/transferid636483/foo/bar/test.txt";
+
+ $this->assertEquals($relativePath, Encryption\Helper::getPathToRealFile($versionPath));
+ $this->assertEquals($relativePath, Encryption\Helper::getPathToRealFile($cachePath));
+ }
+
+}
diff --git a/apps/files_external/3rdparty/smb4php/smb.php b/apps/files_external/3rdparty/smb4php/smb.php
index e91b0a59581..1a6cd05590c 100644
--- a/apps/files_external/3rdparty/smb4php/smb.php
+++ b/apps/files_external/3rdparty/smb4php/smb.php
@@ -460,7 +460,8 @@ class smb_stream_wrapper extends smb {
function stream_tell () { return ftell($this->stream); }
- function stream_seek ($offset, $whence=null) { return fseek($this->stream, $offset, $whence); }
+ // PATCH: the wrapper must return true when fseek succeeded by returning 0.
+ function stream_seek ($offset, $whence=null) { return fseek($this->stream, $offset, $whence) === 0; }
function stream_flush () {
if ($this->mode <> 'r' && $this->need_flush) {
diff --git a/apps/files_external/css/settings.css b/apps/files_external/css/settings.css
index 0ebae9d82be..9858c10ea35 100644
--- a/apps/files_external/css/settings.css
+++ b/apps/files_external/css/settings.css
@@ -18,3 +18,7 @@ tr:hover>td.remove>img { visibility:visible; cursor:pointer; }
#addMountPoint>td { border:none; }
#addMountPoint>td.applicable { visibility:hidden; }
#selectBackend { margin-left:-10px; }
+
+#externalStorage label > input[type="checkbox"] {
+ margin-right: 3px;
+}
diff --git a/apps/files_sharing/lib/sharedstorage.php b/apps/files_sharing/lib/sharedstorage.php
index 6141d832199..3116cd717fb 100644
--- a/apps/files_sharing/lib/sharedstorage.php
+++ b/apps/files_sharing/lib/sharedstorage.php
@@ -34,15 +34,15 @@ class Shared extends \OC\Files\Storage\Common {
$this->sharedFolder = $arguments['sharedFolder'];
}
- public function getId(){
+ public function getId() {
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
- */
+ * @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
+ */
public function getFile($target) {
if (!isset($this->files[$target])) {
// Check for partial files
@@ -62,10 +62,10 @@ class Shared extends \OC\Files\Storage\Common {
}
/**
- * @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
- */
+ * @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
+ */
public function getSourcePath($target) {
$source = $this->getFile($target);
if ($source) {
@@ -73,7 +73,7 @@ class Shared extends \OC\Files\Storage\Common {
\OC\Files\Filesystem::initMountPoints($source['fileOwner']);
$mount = \OC\Files\Filesystem::getMountByNumericId($source['storage']);
if (is_array($mount)) {
- $this->files[$target]['fullPath'] = $mount[key($mount)]->getMountPoint().$source['path'];
+ $this->files[$target]['fullPath'] = $mount[key($mount)]->getMountPoint() . $source['path'];
} else {
$this->files[$target]['fullPath'] = false;
}
@@ -84,10 +84,10 @@ class Shared extends \OC\Files\Storage\Common {
}
/**
- * @brief Get the permissions granted for a shared file
- * @param string Shared target file path
- * @return int CRUDS permissions granted or false if not found
- */
+ * @brief Get the permissions granted for a shared file
+ * @param string Shared target file path
+ * @return int CRUDS permissions granted or false if not found
+ */
public function getPermissions($target) {
$source = $this->getFile($target);
if ($source) {
@@ -222,7 +222,7 @@ class Shared extends \OC\Files\Storage\Common {
if ($path == '' || $path == '/') {
$mtime = 0;
$dh = $this->opendir($path);
- if(is_resource($dh)) {
+ if (is_resource($dh)) {
while (($filename = readdir($dh)) !== false) {
$tempmtime = $this->filemtime($filename);
if ($tempmtime > $mtime) {
@@ -244,7 +244,7 @@ class Shared extends \OC\Files\Storage\Common {
$source = $this->getSourcePath($path);
if ($source) {
$info = array(
- 'target' => $this->sharedFolder.$path,
+ 'target' => $this->sharedFolder . $path,
'source' => $source,
);
\OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_get_contents', $info);
@@ -257,13 +257,14 @@ class Shared extends \OC\Files\Storage\Common {
if ($source = $this->getSourcePath($path)) {
// Check if permission is granted
if (($this->file_exists($path) && !$this->isUpdatable($path))
- || ($this->is_dir($path) && !$this->isCreatable($path))) {
+ || ($this->is_dir($path) && !$this->isCreatable($path))
+ ) {
return false;
}
$info = array(
- 'target' => $this->sharedFolder.$path,
- 'source' => $source,
- );
+ 'target' => $this->sharedFolder . $path,
+ 'source' => $source,
+ );
\OCP\Util::emitHook('\OC\Files\Storage\Shared', 'file_put_contents', $info);
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
$result = $storage->file_put_contents($internalPath, $data);
@@ -304,31 +305,16 @@ class Shared extends \OC\Files\Storage\Common {
$pos1 = strpos($path1, '/', 1);
$pos2 = strpos($path2, '/', 1);
if ($pos1 !== false && $pos2 !== false && ($oldSource = $this->getSourcePath($path1))) {
- $newSource = $this->getSourcePath(dirname($path2)).'/'.basename($path2);
- 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);
- return $storage->rename($oldInternalPath, $newInternalPath);
- }
- } else {
- // Move the file if DELETE and CREATE permissions are granted
- if ($this->isDeletable($path1) && $this->isCreatable(dirname($path2))) {
- // Get the root shared folder
- $folder1 = substr($path1, 0, $pos1);
- $folder2 = substr($path2, 0, $pos2);
- // Copy and unlink the file if it exists in a different shared folder
- if ($folder1 != $folder2) {
- if ($this->copy($path1, $path2)) {
- return $this->unlink($path1);
- }
- } else {
- list($storage, $oldInternalPath) = \OC\Files\Filesystem::resolvePath($oldSource);
- list( , $newInternalPath) = \OC\Files\Filesystem::resolvePath($newSource);
- return $storage->rename($oldInternalPath, $newInternalPath);
- }
- }
+ $newSource = $this->getSourcePath(dirname($path2)) . '/' . basename($path2);
+ // Within the same folder, we only need UPDATE permissions
+ if (dirname($path1) == dirname($path2) and $this->isUpdatable($path1)) {
+ list($storage, $oldInternalPath) = \OC\Files\Filesystem::resolvePath($oldSource);
+ list(, $newInternalPath) = \OC\Files\Filesystem::resolvePath($newSource);
+ return $storage->rename($oldInternalPath, $newInternalPath);
+ // otherwise DELETE and CREATE permissions required
+ } elseif ($this->isDeletable($path1) && $this->isCreatable(dirname($path2))) {
+ $rootView = new \OC\Files\View('');
+ return $rootView->rename($oldSource, $newSource);
}
}
}
@@ -338,10 +324,10 @@ class Shared extends \OC\Files\Storage\Common {
public function copy($path1, $path2) {
// Copy the file if CREATE permission is granted
if ($this->isCreatable(dirname($path2))) {
- $source = $this->fopen($path1, 'r');
- $target = $this->fopen($path2, 'w');
- list ($count, $result) = \OC_Helper::streamCopy($source, $target);
- return $result;
+ $oldSource = $this->getSourcePath($path1);
+ $newSource = $this->getSourcePath(dirname($path2)) . '/' . basename($path2);
+ $rootView = new \OC\Files\View('');
+ return $rootView->copy($oldSource, $newSource);
}
return false;
}
@@ -363,16 +349,16 @@ class Shared extends \OC\Files\Storage\Common {
case 'xb':
case 'a':
case 'ab':
- $exists = $this->file_exists($path);
- if ($exists && !$this->isUpdatable($path)) {
- return false;
- }
- if (!$exists && !$this->isCreatable(dirname($path))) {
- return false;
- }
+ $exists = $this->file_exists($path);
+ if ($exists && !$this->isUpdatable($path)) {
+ return false;
+ }
+ if (!$exists && !$this->isCreatable(dirname($path))) {
+ return false;
+ }
}
$info = array(
- 'target' => $this->sharedFolder.$path,
+ 'target' => $this->sharedFolder . $path,
'source' => $source,
'mode' => $mode,
);
@@ -412,6 +398,7 @@ class Shared extends \OC\Files\Storage\Common {
}
return false;
}
+
public function touch($path, $mtime = null) {
if ($source = $this->getSourcePath($path)) {
list($storage, $internalPath) = \OC\Files\Filesystem::resolvePath($source);
@@ -422,11 +409,12 @@ class Shared extends \OC\Files\Storage\Common {
public static function setup($options) {
if (!\OCP\User::isLoggedIn() || \OCP\User::getUser() != $options['user']
- || \OCP\Share::getItemsSharedWith('file')) {
+ || \OCP\Share::getItemsSharedWith('file')
+ ) {
$user_dir = $options['user_dir'];
\OC\Files\Filesystem::mount('\OC\Files\Storage\Shared',
array('sharedFolder' => '/Shared'),
- $user_dir.'/Shared/');
+ $user_dir . '/Shared/');
}
}
diff --git a/apps/files_versions/js/versions.js b/apps/files_versions/js/versions.js
index d118456d62e..738a7ece6f2 100644
--- a/apps/files_versions/js/versions.js
+++ b/apps/files_versions/js/versions.js
@@ -21,7 +21,7 @@ $(document).ready(function(){
// Action to perform when clicked
if (scanFiles.scanning){return;}//workaround to prevent additional http request block scanning feedback
- var file = $('#dir').val()+'/'+filename;
+ var file = $('#dir').val().replace(/(?!<=\/)$|\/$/, '/' + filename);
var createDropDown = true;
// Check if drop down is already visible for a different file
if (($('#dropdown').length > 0) ) {
diff --git a/apps/user_ldap/css/settings.css b/apps/user_ldap/css/settings.css
index 41578e91b69..be03419c2de 100644
--- a/apps/user_ldap/css/settings.css
+++ b/apps/user_ldap/css/settings.css
@@ -3,13 +3,9 @@
width: 60%;
}
-.tablecell {
- display: table-cell !important;
- white-space: nowrap;
-}
-
.tablerow {
display: table-row;
+ white-space: nowrap;
}
.tablerow input, .tablerow textarea {
@@ -78,6 +74,7 @@
.wizSpinner {
height: 15px;
+ margin: 0.3em;
}
.ldapSettingControls {
@@ -100,7 +97,6 @@
#ldap fieldset input, #ldap fieldset textarea {
width: 60%;
- display: inline-block;
}
#ldap fieldset p input[type=checkbox] {
diff --git a/apps/user_ldap/js/settings.js b/apps/user_ldap/js/settings.js
index 3abec1e232e..dcaeb70b57f 100644
--- a/apps/user_ldap/js/settings.js
+++ b/apps/user_ldap/js/settings.js
@@ -192,19 +192,20 @@ var LdapWizard = {
'&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val();
LdapWizard.showSpinner('#ldap_base');
+ $('#ldap_base').prop('disabled', 'disabled');
LdapWizard.ajax(param,
function(result) {
LdapWizard.applyChanges(result);
LdapWizard.hideSpinner('#ldap_base');
if($('#ldap_base').val()) {
- $('#ldap_base').removeClass('invisible');
LdapWizard.hideInfoBox();
}
+ $('#ldap_base').prop('disabled', false);
},
function (result) {
LdapWizard.hideSpinner('#ldap_base');
- $('#ldap_base').removeClass('invisible');
- LdapWizard.showInfoBox('Please specify a port');
+ LdapWizard.showInfoBox('Please specify a Base DN');
+ $('#ldap_base').prop('disabled', false);
}
);
}
@@ -212,28 +213,28 @@ var LdapWizard = {
checkPort: function() {
host = $('#ldap_host').val();
- user = $('#ldap_dn').val();
- pass = $('#ldap_agent_password').val();
+ port = $('#ldap_port').val();
- if(host && user && pass) {
+ if(host && !port) {
param = 'action=guessPortAndTLS'+
'&ldap_serverconfig_chooser='+$('#ldap_serverconfig_chooser').val();
LdapWizard.showSpinner('#ldap_port');
+ $('#ldap_port').prop('disabled', 'disabled');
LdapWizard.ajax(param,
function(result) {
LdapWizard.applyChanges(result);
LdapWizard.hideSpinner('#ldap_port');
if($('#ldap_port').val()) {
LdapWizard.checkBaseDN();
- $('#ldap_port').removeClass('invisible');
+ $('#ldap_port').prop('disabled', false);
LdapWizard.hideInfoBox();
}
},
function (result) {
LdapWizard.hideSpinner('#ldap_port');
- $('#ldap_port').removeClass('invisible');
- LdapWizard.showInfoBox('Please specify the BaseDN');
+ $('#ldap_port').prop('disabled', false);
+ LdapWizard.showInfoBox('Please specify the Port');
}
);
}
@@ -461,12 +462,6 @@ var LdapWizard = {
},
init: function() {
- if($('#ldap_port').val()) {
- $('#ldap_port').removeClass('invisible');
- }
- if($('#ldap_base').val()) {
- $('#ldap_base').removeClass('invisible');
- }
LdapWizard.basicStatusCheck();
},
@@ -521,6 +516,8 @@ var LdapWizard = {
},
processChanges: function(triggerObj) {
+ LdapWizard.hideInfoBox();
+
if(triggerObj.id == 'ldap_host'
|| triggerObj.id == 'ldap_port'
|| triggerObj.id == 'ldap_dn'
diff --git a/apps/user_ldap/lib/wizard.php b/apps/user_ldap/lib/wizard.php
index 9428a98e29c..fb6aca9e961 100644
--- a/apps/user_ldap/lib/wizard.php
+++ b/apps/user_ldap/lib/wizard.php
@@ -63,8 +63,6 @@ class Wizard extends LDAPUtility {
public function countGroups() {
if(!$this->checkRequirements(array('ldapHost',
'ldapPort',
- 'ldapAgentName',
- 'ldapAgentPassword',
'ldapBase',
))) {
return false;
@@ -98,8 +96,6 @@ class Wizard extends LDAPUtility {
public function countUsers() {
if(!$this->checkRequirements(array('ldapHost',
'ldapPort',
- 'ldapAgentName',
- 'ldapAgentPassword',
'ldapBase',
'ldapUserFilter',
))) {
@@ -130,8 +126,6 @@ class Wizard extends LDAPUtility {
public function determineAttributes() {
if(!$this->checkRequirements(array('ldapHost',
'ldapPort',
- 'ldapAgentName',
- 'ldapAgentPassword',
'ldapBase',
'ldapUserFilter',
))) {
@@ -160,8 +154,6 @@ class Wizard extends LDAPUtility {
private function getUserAttributes() {
if(!$this->checkRequirements(array('ldapHost',
'ldapPort',
- 'ldapAgentName',
- 'ldapAgentPassword',
'ldapBase',
'ldapUserFilter',
))) {
@@ -214,8 +206,6 @@ class Wizard extends LDAPUtility {
private function determineGroups($dbkey, $confkey, $testMemberOf = true) {
if(!$this->checkRequirements(array('ldapHost',
'ldapPort',
- 'ldapAgentName',
- 'ldapAgentPassword',
'ldapBase',
))) {
return false;
@@ -242,8 +232,6 @@ class Wizard extends LDAPUtility {
public function determineGroupMemberAssoc() {
if(!$this->checkRequirements(array('ldapHost',
'ldapPort',
- 'ldapAgentName',
- 'ldapAgentPassword',
'ldapGroupFilter',
))) {
return false;
@@ -266,8 +254,6 @@ class Wizard extends LDAPUtility {
public function determineGroupObjectClasses() {
if(!$this->checkRequirements(array('ldapHost',
'ldapPort',
- 'ldapAgentName',
- 'ldapAgentPassword',
'ldapBase',
))) {
return false;
@@ -294,8 +280,6 @@ class Wizard extends LDAPUtility {
public function determineUserObjectClasses() {
if(!$this->checkRequirements(array('ldapHost',
'ldapPort',
- 'ldapAgentName',
- 'ldapAgentPassword',
'ldapBase',
))) {
return false;
@@ -322,12 +306,17 @@ class Wizard extends LDAPUtility {
public function getGroupFilter() {
if(!$this->checkRequirements(array('ldapHost',
'ldapPort',
- 'ldapAgentName',
- 'ldapAgentPassword',
'ldapBase',
))) {
return false;
}
+ //make sure the use display name is set
+ $displayName = $this->configuration->ldapGroupDisplayName;
+ if(empty($displayName)) {
+ $d = $this->configuration->getDefaults();
+ $this->applyFind('ldap_group_display_name',
+ $d['ldap_group_display_name']);
+ }
$filter = $this->composeLdapFilter(self::LFILTER_GROUP_LIST);
$this->applyFind('ldap_group_filter', $filter);
@@ -337,12 +326,16 @@ class Wizard extends LDAPUtility {
public function getUserListFilter() {
if(!$this->checkRequirements(array('ldapHost',
'ldapPort',
- 'ldapAgentName',
- 'ldapAgentPassword',
'ldapBase',
))) {
return false;
}
+ //make sure the use display name is set
+ $displayName = $this->configuration->ldapUserDisplayName;
+ if(empty($displayName)) {
+ $d = $this->configuration->getDefaults();
+ $this->applyFind('ldap_display_name', $d['ldap_display_name']);
+ }
$filter = $this->composeLdapFilter(self::LFILTER_USER_LIST);
if(!$filter) {
throw new \Exception('Cannot create filter');
@@ -355,13 +348,12 @@ class Wizard extends LDAPUtility {
public function getUserLoginFilter() {
if(!$this->checkRequirements(array('ldapHost',
'ldapPort',
- 'ldapAgentName',
- 'ldapAgentPassword',
'ldapBase',
'ldapUserFilter',
))) {
return false;
}
+
$filter = $this->composeLdapFilter(self::LFILTER_LOGIN);
if(!$filter) {
throw new \Exception('Cannot create filter');
@@ -377,8 +369,6 @@ class Wizard extends LDAPUtility {
*/
public function guessPortAndTLS() {
if(!$this->checkRequirements(array('ldapHost',
- 'ldapAgentName',
- 'ldapAgentPassword'
))) {
return false;
}
@@ -418,8 +408,6 @@ class Wizard extends LDAPUtility {
*/
public function guessBaseDN() {
if(!$this->checkRequirements(array('ldapHost',
- 'ldapAgentName',
- 'ldapAgentPassword',
'ldapPort',
))) {
return false;
@@ -799,7 +787,22 @@ class Wizard extends LDAPUtility {
throw new \Exception($error);
}
+ /**
+ * @brief checks whether a valid combination of agent and password has been
+ * provided (either two values or nothing for anonymous connect)
+ * @return boolean, true if everything is fine, false otherwise
+ *
+ */
+ private function checkAgentRequirements() {
+ $agent = $this->configuration->ldapAgentName;
+ $pwd = $this->configuration->ldapAgentPassword;
+
+ return ( (!empty($agent) && !empty($pwd))
+ || (empty($agent) && empty($pwd)));
+ }
+
private function checkRequirements($reqs) {
+ $this->checkAgentRequirements();
foreach($reqs as $option) {
$value = $this->configuration->$option;
if(empty($value)) {
@@ -1005,9 +1008,9 @@ class Wizard extends LDAPUtility {
//In case the port is already provided, we will check this first
if($port > 0) {
$hostInfo = parse_url($host);
- if(is_array($hostInfo)
+ if(!(is_array($hostInfo)
&& isset($hostInfo['scheme'])
- && stripos($hostInfo['scheme'], 'ldaps') === false) {
+ && stripos($hostInfo['scheme'], 'ldaps') !== false)) {
$portSettings[] = array('port' => $port, 'tls' => true);
}
$portSettings[] =array('port' => $port, 'tls' => false);
diff --git a/apps/user_ldap/templates/part.wizard-server.php b/apps/user_ldap/templates/part.wizard-server.php
index 01dd8d0fcb2..fde7c36cdd1 100644
--- a/apps/user_ldap/templates/part.wizard-server.php
+++ b/apps/user_ldap/templates/part.wizard-server.php
@@ -32,7 +32,7 @@
/>
<span>
<input type="number" id="ldap_port" name="ldap_port"
- class="invisible lwautosave"
+ class="lwautosave"
placeholder="<?php p($l->t('Port'));?>" />
</span>
</div>
@@ -56,7 +56,7 @@
<div class="tablerow">
<textarea id="ldap_base" name="ldap_base"
- class="tablecell invisible lwautosave"
+ class="tablecell lwautosave"
placeholder="<?php p($l->t('One Base DN per line'));?>"
title="<?php p($l->t('You can specify Base DN for users and groups in the Advanced tab'));?>">
</textarea>
diff --git a/apps/user_ldap/templates/settings.php b/apps/user_ldap/templates/settings.php
index 22aab0186f7..feb5ac6385d 100644
--- a/apps/user_ldap/templates/settings.php
+++ b/apps/user_ldap/templates/settings.php
@@ -20,8 +20,7 @@
<h3><?php p($l->t('Connection Settings'));?></h3>
<div>
<p><label for="ldap_configuration_active"><?php p($l->t('Configuration Active'));?></label><input type="checkbox" id="ldap_configuration_active" name="ldap_configuration_active" value="1" data-default="<?php p($_['ldap_configuration_active_default']); ?>" title="<?php p($l->t('When unchecked, this configuration will be skipped.'));?>" /></p>
- <p><label for="ldap_login_filter"><?php p($l->t('User Login Filter'));?></label>
- <input type="text" id="ldap_login_filter" name="ldap_login_filter"
+ <p><label for="ldap_login_filter"><?php p($l->t('User Login Filter'));?></label><input type="text" id="ldap_login_filter" name="ldap_login_filter"
data-default="<?php p($_['ldap_login_filter_default']); ?>"
title="<?php p($l->t('Defines the filter to apply, when login is attempted. %%uid replaces the username in the login action. Example: "uid=%%uid"'));?>" /></p>
<p><label for="ldap_backup_host"><?php p($l->t('Backup (Replica) Host'));?></label><input type="text" id="ldap_backup_host" name="ldap_backup_host" data-default="<?php p($_['ldap_backup_host_default']); ?>" title="<?php p($l->t('Give an optional backup host. It must be a replica of the main LDAP/AD server.'));?>"></p>
diff --git a/core/css/multiselect.css b/core/css/multiselect.css
index c25446808ea..e2a35ac3633 100644
--- a/core/css/multiselect.css
+++ b/core/css/multiselect.css
@@ -52,6 +52,7 @@ div.multiselect {
display: inline-block;
max-width: 400px;
min-width: 150px;
+ min-height: 20px;
padding-right: .6em;
position: relative;
vertical-align: bottom;
diff --git a/core/js/multiselect.js b/core/js/multiselect.js
index 373fd2d41a2..2210df3bc7a 100644
--- a/core/js/multiselect.js
+++ b/core/js/multiselect.js
@@ -156,8 +156,6 @@
var newOuterWidth=Math.max((button.outerWidth()-2),settings.minOuterWidth)+'px';
var newWidth=Math.max(button.width(),settings.minWidth);
var pos=button.position();
- button.css('height',button.height());
- button.css('white-space','nowrap');
button.css('width',oldWidth);
button.animate({'width':newWidth},undefined,undefined,function(){
button.css('width','');
diff --git a/db_structure.xml b/db_structure.xml
index a41892e39e7..377363b7eea 100644
--- a/db_structure.xml
+++ b/db_structure.xml
@@ -853,6 +853,24 @@
</field>
<index>
+ <name>item_share_type_index</name>
+ <field>
+ <name>item_type</name>
+ <sorting>ascending</sorting>
+ </field>
+ <field>
+ <name>share_type</name>
+ <sorting>ascending</sorting>
+ </field>
+ </index>
+ <index>
+ <name>file_source_index</name>
+ <field>
+ <name>file_source</name>
+ <sorting>ascending</sorting>
+ </field>
+ </index>
+ <index>
<name>token_index</name>
<field>
<name>token</name>
@@ -1073,6 +1091,18 @@
</field>
</index>
+ <index>
+ <name>vcategory_objectd_index</name>
+ <field>
+ <name>objid</name>
+ <sorting>ascending</sorting>
+ </field>
+ <field>
+ <name>type</name>
+ <sorting>ascending</sorting>
+ </field>
+ </index>
+
</declaration>
</table>
diff --git a/lib/private/api.php b/lib/private/api.php
index eac4a825e07..03d7b7382a5 100644
--- a/lib/private/api.php
+++ b/lib/private/api.php
@@ -96,6 +96,7 @@ class OC_API {
$responses[] = array(
'app' => $action['app'],
'response' => new OC_OCS_Result(null, OC_API::RESPOND_UNAUTHORISED, 'Unauthorised'),
+ 'shipped' => OC_App::isShipped($action['app']),
);
continue;
}
@@ -103,6 +104,7 @@ class OC_API {
$responses[] = array(
'app' => $action['app'],
'response' => new OC_OCS_Result(null, OC_API::RESPOND_NOT_FOUND, 'Api method not found'),
+ 'shipped' => OC_App::isShipped($action['app']),
);
continue;
}
@@ -110,6 +112,7 @@ class OC_API {
$responses[] = array(
'app' => $action['app'],
'response' => call_user_func($action['action'], $parameters),
+ 'shipped' => OC_App::isShipped($action['app']),
);
}
$response = self::mergeResponses($responses);
@@ -127,7 +130,7 @@ class OC_API {
* merge the returned result objects into one response
* @param array $responses
*/
- private static function mergeResponses($responses) {
+ public static function mergeResponses($responses) {
$response = array();
// Sort into shipped and thirdparty
$shipped = array(
@@ -140,50 +143,76 @@ class OC_API {
);
foreach($responses as $response) {
- if(OC_App::isShipped($response['app']) || ($response['app'] === 'core')) {
+ if($response['shipped'] || ($response['app'] === 'core')) {
if($response['response']->succeeded()) {
- $shipped['succeeded'][$response['app']] = $response['response'];
+ $shipped['succeeded'][$response['app']] = $response;
} else {
- $shipped['failed'][$response['app']] = $response['response'];
+ $shipped['failed'][$response['app']] = $response;
}
} else {
if($response['response']->succeeded()) {
- $thirdparty['succeeded'][$response['app']] = $response['response'];
+ $thirdparty['succeeded'][$response['app']] = $response;
} else {
- $thirdparty['failed'][$response['app']] = $response['response'];
+ $thirdparty['failed'][$response['app']] = $response;
}
}
}
// Remove any error responses if there is one shipped response that succeeded
- if(!empty($shipped['succeeded'])) {
- $responses = array_merge($shipped['succeeded'], $thirdparty['succeeded']);
- } else if(!empty($shipped['failed'])) {
+ if(!empty($shipped['failed'])) {
// Which shipped response do we use if they all failed?
// They may have failed for different reasons (different status codes)
// Which reponse code should we return?
// Maybe any that are not OC_API::RESPOND_SERVER_ERROR
- $response = reset($shipped['failed']);
+ // Merge failed responses if more than one
+ $data = array();
+ $meta = array();
+ foreach($shipped['failed'] as $failure) {
+ $data = array_merge_recursive($data, $failure['response']->getData());
+ }
+ $picked = reset($shipped['failed']);
+ $code = $picked['response']->getStatusCode();
+ $response = new OC_OCS_Result($data, $code);
return $response;
+ } elseif(!empty($shipped['succeeded'])) {
+ $responses = array_merge($shipped['succeeded'], $thirdparty['succeeded']);
} elseif(!empty($thirdparty['failed'])) {
- // Return the third party failure result
- $response = reset($thirdparty['failed']);
+ // Merge failed responses if more than one
+ $data = array();
+ $meta = array();
+ foreach($thirdparty['failed'] as $failure) {
+ $data = array_merge_recursive($data, $failure['response']->getData());
+ }
+ $picked = reset($thirdparty['failed']);
+ $code = $picked['response']->getStatusCode();
+ $response = new OC_OCS_Result($data, $code);
return $response;
} else {
- $responses = array_merge($shipped['succeeded'], $thirdparty['succeeded']);
+ $responses = $thirdparty['succeeded'];
}
// Merge the successful responses
$meta = array();
$data = array();
foreach($responses as $app => $response) {
- if(OC_App::isShipped($app)) {
- $data = array_merge_recursive($response->getData(), $data);
+ if($response['shipped']) {
+ $data = array_merge_recursive($response['response']->getData(), $data);
} else {
- $data = array_merge_recursive($data, $response->getData());
+ $data = array_merge_recursive($data, $response['response']->getData());
}
+ $codes[] = $response['response']->getStatusCode();
}
- $result = new OC_OCS_Result($data, 100);
+
+ // Use any non 100 status codes
+ $statusCode = 100;
+ foreach($codes as $code) {
+ if($code != 100) {
+ $statusCode = $code;
+ break;
+ }
+ }
+
+ $result = new OC_OCS_Result($data, $statusCode);
return $result;
}
diff --git a/lib/private/db/mdb2schemareader.php b/lib/private/db/mdb2schemareader.php
index b7128a2f176..511bd1c90bd 100644
--- a/lib/private/db/mdb2schemareader.php
+++ b/lib/private/db/mdb2schemareader.php
@@ -150,6 +150,9 @@ class MDB2SchemaReader {
case 'timestamp':
$type = 'datetime';
break;
+ case 'numeric':
+ $type = 'decimal';
+ break;
}
break;
case 'length':
@@ -186,14 +189,14 @@ class MDB2SchemaReader {
}
}
if (isset($name) && isset($type)) {
- if (empty($options['default'])) {
+ if (isset($options['default']) && empty($options['default'])) {
if (empty($options['notnull']) || !$options['notnull']) {
unset($options['default']);
$options['notnull'] = false;
} else {
$options['default'] = '';
}
- if ($type == 'integer') {
+ if ($type == 'integer' || $type == 'decimal') {
$options['default'] = 0;
} elseif ($type == 'boolean') {
$options['default'] = false;
diff --git a/lib/private/files/cache/homecache.php b/lib/private/files/cache/homecache.php
new file mode 100644
index 00000000000..4b14bd12190
--- /dev/null
+++ b/lib/private/files/cache/homecache.php
@@ -0,0 +1,40 @@
+<?php
+/**
+ * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\Files\Cache;
+
+class HomeCache extends Cache {
+ /**
+ * get the size of a folder and set it in the cache
+ *
+ * @param string $path
+ * @return int
+ */
+ public function calculateFolderSize($path) {
+ if ($path !== '/' and $path !== '') {
+ return parent::calculateFolderSize($path);
+ }
+
+ $totalSize = 0;
+ $entry = $this->get($path);
+ if ($entry && $entry['mimetype'] === 'httpd/unix-directory') {
+ $id = $entry['fileid'];
+ $sql = 'SELECT SUM(`size`) FROM `*PREFIX*filecache` ' .
+ 'WHERE `parent` = ? AND `storage` = ? AND `size` >= 0';
+ $result = \OC_DB::executeAudited($sql, array($id, $this->getNumericStorageId()));
+ if ($row = $result->fetchRow()) {
+ list($sum) = array_values($row);
+ $totalSize = (int)$sum;
+ if ($entry['size'] !== $totalSize) {
+ $this->update($id, array('size' => $totalSize));
+ }
+ }
+ }
+ return $totalSize;
+ }
+}
diff --git a/lib/private/files/filesystem.php b/lib/private/files/filesystem.php
index e40502bbe64..8500b3c581b 100644
--- a/lib/private/files/filesystem.php
+++ b/lib/private/files/filesystem.php
@@ -307,10 +307,18 @@ class Filesystem {
$root = \OC_User::getHome($user);
$userObject = \OC_User::getManager()->get($user);
- if (\OC\Files\Cache\Storage::exists('local::' . $root . '/') or is_null($userObject)) {
+
+ if (!is_null($userObject)) {
+ // check for legacy home id (<= 5.0.12)
+ if (\OC\Files\Cache\Storage::exists('local::' . $root . '/')) {
+ self::mount('\OC\Files\Storage\Home', array('user' => $userObject, 'legacy' => true), $user);
+ }
+ else {
+ self::mount('\OC\Files\Storage\Home', array('user' => $userObject), $user);
+ }
+ }
+ else {
self::mount('\OC\Files\Storage\Local', array('datadir' => $root), $user);
- } else {
- self::mount('\OC\Files\Storage\Home', array('user' => $userObject), $user);
}
$datadir = \OC_Config::getValue("datadirectory", \OC::$SERVERROOT . "/data");
@@ -681,18 +689,32 @@ class Filesystem {
}
//no windows style slashes
$path = str_replace('\\', '/', $path);
+
//add leading slash
if ($path[0] !== '/') {
$path = '/' . $path;
}
- //remove duplicate slashes
- while (strpos($path, '//') !== false) {
- $path = str_replace('//', '/', $path);
+
+ // remove '/./'
+ // ugly, but str_replace() can't replace them all in one go
+ // as the replacement itself is part of the search string
+ // which will only be found during the next iteration
+ while (strpos($path, '/./') !== false) {
+ $path = str_replace('/./', '/', $path);
}
+ // remove sequences of slashes
+ $path = preg_replace('#/{2,}#', '/', $path);
+
//remove trailing slash
if ($stripTrailingSlash and strlen($path) > 1 and substr($path, -1, 1) === '/') {
$path = substr($path, 0, -1);
}
+
+ // remove trailing '/.'
+ if (substr($path, -2) == '/.') {
+ $path = substr($path, 0, -2);
+ }
+
//normalize unicode if possible
$path = \OC_Util::normalizeUnicode($path);
diff --git a/lib/private/files/storage/common.php b/lib/private/files/storage/common.php
index a5b79f0e967..3943d667c35 100644
--- a/lib/private/files/storage/common.php
+++ b/lib/private/files/storage/common.php
@@ -21,11 +21,11 @@ namespace OC\Files\Storage;
*/
abstract class Common implements \OC\Files\Storage\Storage {
- private $cache;
- private $scanner;
- private $permissioncache;
- private $watcher;
- private $storageCache;
+ protected $cache;
+ protected $scanner;
+ protected $permissioncache;
+ protected $watcher;
+ protected $storageCache;
public function __construct($parameters) {
}
diff --git a/lib/private/files/storage/home.php b/lib/private/files/storage/home.php
index bf1d6017cbf..b4ceb8f4f9b 100644
--- a/lib/private/files/storage/home.php
+++ b/lib/private/files/storage/home.php
@@ -13,6 +13,11 @@ namespace OC\Files\Storage;
*/
class Home extends Local {
/**
+ * @var string
+ */
+ protected $id;
+
+ /**
* @var \OC\User\User $user
*/
protected $user;
@@ -20,11 +25,25 @@ class Home extends Local {
public function __construct($arguments) {
$this->user = $arguments['user'];
$datadir = $this->user->getHome();
+ if (isset($arguments['legacy']) && $arguments['legacy']) {
+ // legacy home id (<= 5.0.12)
+ $this->id = 'local::' . $datadir . '/';
+ }
+ else {
+ $this->id = 'home::' . $this->user->getUID();
+ }
parent::__construct(array('datadir' => $datadir));
}
public function getId() {
- return 'home::' . $this->user->getUID();
+ return $this->id;
+ }
+
+ public function getCache($path = '') {
+ if (!isset($this->cache)) {
+ $this->cache = new \OC\Files\Cache\HomeCache($this);
+ }
+ return $this->cache;
}
}
diff --git a/lib/private/preview/image.php b/lib/private/preview/image.php
index 9aec967282d..84343df2608 100644
--- a/lib/private/preview/image.php
+++ b/lib/private/preview/image.php
@@ -21,11 +21,11 @@ class Image extends Provider {
return false;
}
+ $image = new \OC_Image();
//check if file is encrypted
if($fileInfo['encrypted'] === true) {
- $image = new \OC_Image(stream_get_contents($fileview->fopen($path, 'r')));
+ $image->loadFromData(stream_get_contents($fileview->fopen($path, 'r')));
}else{
- $image = new \OC_Image();
$image->loadFromFile($fileview->getLocalFile($path));
}
diff --git a/lib/private/preview/movies.php b/lib/private/preview/movies.php
index 4d85e23c63c..28f130f7506 100644
--- a/lib/private/preview/movies.php
+++ b/lib/private/preview/movies.php
@@ -8,21 +8,39 @@
*/
namespace OC\Preview;
+function findBinaryPath($program) {
+ exec('which ' . escapeshellarg($program) . ' 2> /dev/null', $output, $returnCode);
+ if ($returnCode === 0 && count($output) > 0) {
+ return escapeshellcmd($output[0]);
+ }
+ return null;
+}
+
// movie preview is currently not supported on Windows
if (!\OC_Util::runningOnWindows()) {
- $isShellExecEnabled = !in_array('shell_exec', explode(', ', ini_get('disable_functions')));
- $whichAVCONV = ($isShellExecEnabled ? shell_exec('which avconv') : '');
- $isAVCONVAvailable = !empty($whichAVCONV);
+ $isExecEnabled = !in_array('exec', explode(', ', ini_get('disable_functions')));
+ $ffmpegBinary = null;
+ $avconvBinary = null;
+
+ if ($isExecEnabled) {
+ $avconvBinary = findBinaryPath('avconv');
+ if (!$avconvBinary) {
+ $ffmpegBinary = findBinaryPath('ffmpeg');
+ }
+ }
- if($isShellExecEnabled && $isAVCONVAvailable) {
+ if($isExecEnabled && ( $avconvBinary || $ffmpegBinary )) {
class Movie extends Provider {
+ public static $avconvBinary;
+ public static $ffmpegBinary;
public function getMimeType() {
return '/video\/.*/';
}
public function getThumbnail($path, $maxX, $maxY, $scalingup, $fileview) {
+ // TODO: use proc_open() and stream the source file ?
$absPath = \OC_Helper::tmpFile();
$tmpPath = \OC_Helper::tmpFile();
@@ -31,20 +49,39 @@ if (!\OC_Util::runningOnWindows()) {
$firstmb = stream_get_contents($handle, 1048576); //1024 * 1024 = 1048576
file_put_contents($absPath, $firstmb);
- //$cmd = 'ffmpeg -y -i ' . escapeshellarg($absPath) . ' -f mjpeg -vframes 1 -ss 1 -s ' . escapeshellarg($maxX) . 'x' . escapeshellarg($maxY) . ' ' . $tmpPath;
- $cmd = 'avconv -an -y -ss 1 -i ' . escapeshellarg($absPath) . ' -f mjpeg -vframes 1 ' . escapeshellarg($tmpPath);
+ if (self::$avconvBinary) {
+ $cmd = self::$avconvBinary . ' -an -y -ss 1'.
+ ' -i ' . escapeshellarg($absPath) .
+ ' -f mjpeg -vframes 1 ' . escapeshellarg($tmpPath) .
+ ' > /dev/null 2>&1';
+ }
+ else {
+ $cmd = self::$ffmpegBinary . ' -y -ss 1' .
+ ' -i ' . escapeshellarg($absPath) .
+ ' -f mjpeg -vframes 1' .
+ ' -s ' . escapeshellarg($maxX) . 'x' . escapeshellarg($maxY) .
+ ' ' . escapeshellarg($tmpPath) .
+ ' > /dev/null 2>&1';
+ }
- shell_exec($cmd);
-
- $image = new \OC_Image($tmpPath);
+ exec($cmd, $output, $returnCode);
unlink($absPath);
- unlink($tmpPath);
- return $image->valid() ? $image : false;
+ if ($returnCode === 0) {
+ $image = new \OC_Image();
+ $image->loadFromFile($tmpPath);
+ unlink($tmpPath);
+ return $image->valid() ? $image : false;
+ }
+ return false;
}
}
+ // a bit hacky but didn't want to use subclasses
+ Movie::$avconvBinary = $avconvBinary;
+ Movie::$ffmpegBinary = $ffmpegBinary;
+
\OC\Preview::registerProvider('OC\Preview\Movie');
}
}
diff --git a/lib/private/preview/mp3.php b/lib/private/preview/mp3.php
index 1eed566315c..3fc0ab0490c 100644
--- a/lib/private/preview/mp3.php
+++ b/lib/private/preview/mp3.php
@@ -25,7 +25,8 @@ class MP3 extends Provider {
if(isset($tags['id3v2']['APIC'][0]['data'])) {
$picture = @$tags['id3v2']['APIC'][0]['data'];
unlink($tmpPath);
- $image = new \OC_Image($picture);
+ $image = new \OC_Image();
+ $image->loadFromData($picture);
return $image->valid() ? $image : $this->getNoCoverThumbnail();
}
@@ -39,7 +40,8 @@ class MP3 extends Provider {
return false;
}
- $image = new \OC_Image($icon);
+ $image = new \OC_Image();
+ $image->loadFromFile($icon);
return $image->valid() ? $image : false;
}
diff --git a/lib/private/preview/office-cl.php b/lib/private/preview/office-cl.php
index 8f2e06c050b..b11fed13ba1 100644
--- a/lib/private/preview/office-cl.php
+++ b/lib/private/preview/office-cl.php
@@ -48,7 +48,8 @@ if (!\OC_Util::runningOnWindows()) {
return false;
}
- $image = new \OC_Image($pdf);
+ $image = new \OC_Image();
+ $image->loadFromData($pdf);
unlink($absPath);
unlink($absPath . '.pdf');
diff --git a/lib/private/preview/office-fallback.php b/lib/private/preview/office-fallback.php
index e69ab0ab8cb..f184b3149d5 100644
--- a/lib/private/preview/office-fallback.php
+++ b/lib/private/preview/office-fallback.php
@@ -80,7 +80,8 @@ class MSOfficeExcel extends Provider {
unlink($absPath);
unlink($tmpPath);
- $image = new \OC_Image($pdf);
+ $image = new \OC_Image();
+ $image->loadFromData($pdf);
return $image->valid() ? $image : false;
}
diff --git a/lib/public/share.php b/lib/public/share.php
index 01bf61a60a5..caa274b8579 100644
--- a/lib/public/share.php
+++ b/lib/public/share.php
@@ -354,7 +354,7 @@ class Share {
\OC_Log::write('OCP\Share', \OC_DB::getErrorMessage($result) . ', token=' . $token, \OC_Log::ERROR);
}
$row = $result->fetchRow();
- if (self::expireItem($row)) {
+ if (is_array($row) and self::expireItem($row)) {
return false;
}
return $row;
diff --git a/settings/css/settings.css b/settings/css/settings.css
index 6eef96c2dc1..2e464c3f110 100644
--- a/settings/css/settings.css
+++ b/settings/css/settings.css
@@ -12,6 +12,11 @@ input#openid, input#webdav { width:20em; }
display: block;
}
+.personalblock input[type="checkbox"] {
+ position: relative;
+ top: 2px;
+}
+
/* Sync clients */
.clientsbox { margin:12px; }
.clientsbox h1 { font-size:40px; font-weight:bold; margin:50px 0 20px; }
diff --git a/tests/data/db_structure.xml b/tests/data/db_structure.xml
index 2e83bbb78c7..5f2edbbc516 100644
--- a/tests/data/db_structure.xml
+++ b/tests/data/db_structure.xml
@@ -199,4 +199,26 @@
</declaration>
</table>
+ <table>
+ <name>*dbprefix*decimal</name>
+ <declaration>
+ <field>
+ <name>id</name>
+ <autoincrement>1</autoincrement>
+ <type>integer</type>
+ <default>0</default>
+ <notnull>true</notnull>
+ <length>4</length>
+ </field>
+
+ <field>
+ <name>decimaltest</name>
+ <type>decimal</type>
+ <default/>
+ <notnull>true</notnull>
+ <length>15</length>
+ </field>
+ </declaration>
+ </table>
+
</database>
diff --git a/tests/data/db_structure2.xml b/tests/data/db_structure2.xml
index bbfb24985cb..6cd071451df 100644
--- a/tests/data/db_structure2.xml
+++ b/tests/data/db_structure2.xml
@@ -96,4 +96,26 @@
</declaration>
</table>
+ <table>
+ <name>*dbprefix*decimal</name>
+ <declaration>
+ <field>
+ <name>id</name>
+ <autoincrement>1</autoincrement>
+ <type>integer</type>
+ <default>0</default>
+ <notnull>true</notnull>
+ <length>4</length>
+ </field>
+
+ <field>
+ <name>decimaltest</name>
+ <type>decimal</type>
+ <default/>
+ <notnull>true</notnull>
+ <length>15</length>
+ </field>
+ </declaration>
+ </table>
+
</database>
diff --git a/tests/lib/api.php b/tests/lib/api.php
new file mode 100644
index 00000000000..95d75f15311
--- /dev/null
+++ b/tests/lib/api.php
@@ -0,0 +1,128 @@
+<?php
+/**
+ * Copyright (c) 2013 Tom Needham <tom@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+class Test_API extends PHPUnit_Framework_TestCase {
+
+ // Helps build a response variable
+ function buildResponse($shipped, $data, $code) {
+ return array(
+ 'shipped' => $shipped,
+ 'response' => new OC_OCS_Result($data, $code),
+ 'app' => uniqid('testapp_', true),
+ );
+ }
+
+ // Validate details of the result
+ function checkResult($result, $success) {
+ // Check response is of correct type
+ $this->assertInstanceOf('OC_OCS_Result', $result);
+ // Check if it succeeded
+ /** @var $result OC_OCS_Result */
+ $this->assertEquals($success, $result->succeeded());
+ }
+
+ function dataProviderTestOneResult() {
+ return array(
+ array(100, true),
+ array(101, true),
+ array(997, false),
+ );
+ }
+
+ /**
+ * @dataProvider dataProviderTestOneResult
+ *
+ * @param $statusCode
+ * @param $succeeded
+ */
+ public function testOneResult($statusCode, $succeeded) {
+ // Setup some data arrays
+ $data1 = array(
+ 'users' => array(
+ 'tom' => array(
+ 'key' => 'value',
+ ),
+ 'frank' => array(
+ 'key' => 'value',
+ ),
+ ));
+
+ // Test merging one success result
+ $response = $this->buildResponse(true, $data1, $statusCode);
+ $result = OC_API::mergeResponses(array($response));
+ $this->assertEquals($response['response'], $result);
+ $this->checkResult($result, $succeeded);
+ }
+
+ function dataProviderTestMergeResponses() {
+ return array(
+ // Two shipped success results
+ array(true, 100, true, 100, true),
+ // Two shipped results, one success and one failure
+ array(true, 100, true, 997, false),
+ // Two shipped results, both failure
+ array(true, 997, true, 997, false),
+ // Two third party success results
+ array(false, 100, false, 100, true),
+ // Two third party results, one success and one failure
+ array(false, 100, false, 997, false),
+ // Two third party results, both failure
+ array(false, 997, false, 997, false),
+ // One of each, both success
+ array(false, 100, true, 100, true),
+ array(true, 100, false, 100, true),
+ // One of each, both failure
+ array(false, 997, true, 997, false),
+ // One of each, shipped success
+ array(false, 997, true, 100, true),
+ // One of each, third party success
+ array(false, 100, true, 997, false),
+ );
+ }
+ /**
+ * @dataProvider dataProviderTestMergeResponses
+ *
+ * Test the merging of multiple responses
+ * @param $statusCode1
+ * @param $statusCode2
+ * @param $succeeded
+ */
+ public function testMultipleMergeResponses($shipped1, $statusCode1, $shipped2, $statusCode2, $succeeded){
+ // Tests that app responses are merged correctly
+ // Setup some data arrays
+ $data1 = array(
+ 'users' => array(
+ 'tom' => array(
+ 'key' => 'value',
+ ),
+ 'frank' => array(
+ 'key' => 'value',
+ ),
+ ));
+
+ $data2 = array(
+ 'users' => array(
+ 'tom' => array(
+ 'key' => 'newvalue',
+ ),
+ 'jan' => array(
+ 'key' => 'value',
+ ),
+ ));
+
+ // Two shipped success results
+ $result = OC_API::mergeResponses(array(
+ $this->buildResponse($shipped1, $data1, $statusCode1),
+ $this->buildResponse($shipped2, $data2, $statusCode2),
+ ));
+ $this->checkResult($result, $succeeded);
+ $resultData = $result->getData();
+ $this->assertArrayHasKey('jan', $resultData['users']);
+ }
+
+}
diff --git a/tests/lib/db/mdb2schemareader.php b/tests/lib/db/mdb2schemareader.php
index b9b241194fd..57cafa7c76b 100644
--- a/tests/lib/db/mdb2schemareader.php
+++ b/tests/lib/db/mdb2schemareader.php
@@ -57,13 +57,13 @@ class MDB2SchemaReader extends \PHPUnit_Framework_TestCase {
$this->assertNull($table->getColumn('clobfield')->getLength());
$this->assertFalse($table->getColumn('clobfield')->getAutoincrement());
- $this->assertSame('', $table->getColumn('clobfield')->getDefault());
+ $this->assertNull($table->getColumn('clobfield')->getDefault());
$this->assertTrue($table->getColumn('clobfield')->getNotnull());
$this->assertInstanceOf('Doctrine\DBAL\Types\TextType', $table->getColumn('clobfield')->getType());
$this->assertNull($table->getColumn('booleanfield')->getLength());
$this->assertFalse($table->getColumn('booleanfield')->getAutoincrement());
- $this->assertFalse($table->getColumn('booleanfield')->getDefault());
+ $this->assertNull($table->getColumn('booleanfield')->getDefault());
$this->assertInstanceOf('Doctrine\DBAL\Types\BooleanType', $table->getColumn('booleanfield')->getType());
$this->assertTrue($table->getColumn('booleanfield_true')->getDefault());
diff --git a/tests/lib/files/cache/cache.php b/tests/lib/files/cache/cache.php
index 247373a5cb9..052d70dd0b4 100644
--- a/tests/lib/files/cache/cache.php
+++ b/tests/lib/files/cache/cache.php
@@ -18,11 +18,11 @@ class LongId extends \OC\Files\Storage\Temporary {
class Cache extends \PHPUnit_Framework_TestCase {
/**
- * @var \OC\Files\Storage\Temporary $storage;
+ * @var \OC\Files\Storage\Temporary $storage ;
*/
private $storage;
/**
- * @var \OC\Files\Storage\Temporary $storage2;
+ * @var \OC\Files\Storage\Temporary $storage2 ;
*/
private $storage2;
@@ -137,6 +137,33 @@ class Cache extends \PHPUnit_Framework_TestCase {
$this->assertFalse($this->cache->inCache('folder/bar'));
}
+ public function testRootFolderSizeForNonHomeStorage() {
+ $dir1 = 'knownsize';
+ $dir2 = 'unknownsize';
+ $fileData = array();
+ $fileData[''] = array('size' => -1, 'mtime' => 20, 'mimetype' => 'httpd/unix-directory');
+ $fileData[$dir1] = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'httpd/unix-directory');
+ $fileData[$dir2] = array('size' => -1, 'mtime' => 25, 'mimetype' => 'httpd/unix-directory');
+
+ $this->cache->put('', $fileData['']);
+ $this->cache->put($dir1, $fileData[$dir1]);
+ $this->cache->put($dir2, $fileData[$dir2]);
+
+ $this->assertTrue($this->cache->inCache($dir1));
+ $this->assertTrue($this->cache->inCache($dir2));
+
+ // check that root size ignored the unknown sizes
+ $this->assertEquals(-1, $this->cache->calculateFolderSize(''));
+
+ // clean up
+ $this->cache->remove('');
+ $this->cache->remove($dir1);
+ $this->cache->remove($dir2);
+
+ $this->assertFalse($this->cache->inCache($dir1));
+ $this->assertFalse($this->cache->inCache($dir2));
+ }
+
function testStatus() {
$this->assertEquals(\OC\Files\Cache\Cache::NOT_FOUND, $this->cache->getStatus('foo'));
$this->cache->put('foo', array('size' => -1));
@@ -247,14 +274,14 @@ class Cache extends \PHPUnit_Framework_TestCase {
$data = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'foo/file');
$this->cache->put('foo', $data);
$cachedData = $this->cache->get('foo');
- $this->assertEquals($data['mtime'], $cachedData['storage_mtime']);//if no storage_mtime is saved, mtime should be used
+ $this->assertEquals($data['mtime'], $cachedData['storage_mtime']); //if no storage_mtime is saved, mtime should be used
- $this->cache->put('foo', array('storage_mtime' => 30));//when setting storage_mtime, mtime is also set
+ $this->cache->put('foo', array('storage_mtime' => 30)); //when setting storage_mtime, mtime is also set
$cachedData = $this->cache->get('foo');
$this->assertEquals(30, $cachedData['storage_mtime']);
$this->assertEquals(30, $cachedData['mtime']);
- $this->cache->put('foo', array('mtime' => 25));//setting mtime does not change storage_mtime
+ $this->cache->put('foo', array('mtime' => 25)); //setting mtime does not change storage_mtime
$cachedData = $this->cache->get('foo');
$this->assertEquals(30, $cachedData['storage_mtime']);
$this->assertEquals(25, $cachedData['mtime']);
@@ -295,18 +322,18 @@ class Cache extends \PHPUnit_Framework_TestCase {
$this->assertGreaterThan(0, $cacheMock->put('folder', $data));
// put un-normalized folder
- $this->assertFalse($cacheMock->get('folder/' .$folderWith0308));
- $this->assertGreaterThan(0, $cacheMock->put('folder/' .$folderWith0308, $data));
+ $this->assertFalse($cacheMock->get('folder/' . $folderWith0308));
+ $this->assertGreaterThan(0, $cacheMock->put('folder/' . $folderWith0308, $data));
// get un-normalized folder by name
- $unNormalizedFolderName = $cacheMock->get('folder/' .$folderWith0308);
+ $unNormalizedFolderName = $cacheMock->get('folder/' . $folderWith0308);
// check if database layer normalized the folder name (this should not happen)
$this->assertEquals($folderWith0308, $unNormalizedFolderName['name']);
// put normalized folder
$this->assertFalse($cacheMock->get('folder/' . $folderWith00F6));
- $this->assertGreaterThan(0, $cacheMock->put('folder/' .$folderWith00F6, $data));
+ $this->assertGreaterThan(0, $cacheMock->put('folder/' . $folderWith00F6, $data));
// this is our bug, we have two different hashes with the same name (Schön)
$this->assertEquals(2, count($cacheMock->getFolderContents('folder')));
@@ -317,7 +344,7 @@ class Cache extends \PHPUnit_Framework_TestCase {
*/
public function testWithNormalizer() {
- if(!class_exists('Patchwork\PHP\Shim\Normalizer')) {
+ if (!class_exists('Patchwork\PHP\Shim\Normalizer')) {
$this->markTestSkipped('The 3rdparty Normalizer extension is not available.');
return;
}
@@ -335,18 +362,18 @@ class Cache extends \PHPUnit_Framework_TestCase {
$this->assertGreaterThan(0, $this->cache->put('folder', $data));
// put un-normalized folder
- $this->assertFalse($this->cache->get('folder/' .$folderWith0308));
- $this->assertGreaterThan(0, $this->cache->put('folder/' .$folderWith0308, $data));
+ $this->assertFalse($this->cache->get('folder/' . $folderWith0308));
+ $this->assertGreaterThan(0, $this->cache->put('folder/' . $folderWith0308, $data));
// get un-normalized folder by name
- $unNormalizedFolderName = $this->cache->get('folder/' .$folderWith0308);
+ $unNormalizedFolderName = $this->cache->get('folder/' . $folderWith0308);
// check if folder name was normalized
$this->assertEquals($folderWith00F6, $unNormalizedFolderName['name']);
// put normalized folder
$this->assertTrue(is_array($this->cache->get('folder/' . $folderWith00F6)));
- $this->assertGreaterThan(0, $this->cache->put('folder/' .$folderWith00F6, $data));
+ $this->assertGreaterThan(0, $this->cache->put('folder/' . $folderWith00F6, $data));
// at this point we should have only one folder named "Schön"
$this->assertEquals(1, count($this->cache->getFolderContents('folder')));
diff --git a/tests/lib/files/cache/homecache.php b/tests/lib/files/cache/homecache.php
new file mode 100644
index 00000000000..ebf2b7270da
--- /dev/null
+++ b/tests/lib/files/cache/homecache.php
@@ -0,0 +1,95 @@
+<?php
+/**
+ * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace Test\Files\Cache;
+
+class DummyUser extends \OC\User\User {
+ /**
+ * @var string $home
+ */
+ private $home;
+
+ /**
+ * @var string $uid
+ */
+ private $uid;
+
+ public function __construct($uid, $home) {
+ $this->home = $home;
+ $this->uid = $uid;
+ }
+
+ /**
+ * @return string
+ */
+ public function getHome() {
+ return $this->home;
+ }
+
+ /**
+ * @return string
+ */
+ public function getUID() {
+ return $this->uid;
+ }
+}
+
+class HomeCache extends \PHPUnit_Framework_TestCase {
+ /**
+ * @var \OC\Files\Storage\Home $storage
+ */
+ private $storage;
+
+ /**
+ * @var \OC\Files\Cache\HomeCache $cache
+ */
+ private $cache;
+
+ /**
+ * @var \OC\User\User $user
+ */
+ private $user;
+
+ public function setUp() {
+ $this->user = new DummyUser('foo', \OC_Helper::tmpFolder());
+ $this->storage = new \OC\Files\Storage\Home(array('user' => $this->user));
+ $this->cache = $this->storage->getCache();
+ }
+
+ /**
+ * Tests that the root folder size calculation ignores the subdirs that have an unknown
+ * size. This makes sure that quota calculation still works as it's based on the root
+ * folder size.
+ */
+ public function testRootFolderSizeIgnoresUnknownUpdate() {
+ $dir1 = 'knownsize';
+ $dir2 = 'unknownsize';
+ $fileData = array();
+ $fileData[''] = array('size' => -1, 'mtime' => 20, 'mimetype' => 'httpd/unix-directory');
+ $fileData[$dir1] = array('size' => 1000, 'mtime' => 20, 'mimetype' => 'httpd/unix-directory');
+ $fileData[$dir2] = array('size' => -1, 'mtime' => 25, 'mimetype' => 'httpd/unix-directory');
+
+ $this->cache->put('', $fileData['']);
+ $this->cache->put($dir1, $fileData[$dir1]);
+ $this->cache->put($dir2, $fileData[$dir2]);
+
+ $this->assertTrue($this->cache->inCache($dir1));
+ $this->assertTrue($this->cache->inCache($dir2));
+
+ // check that root size ignored the unknown sizes
+ $this->assertEquals(1000, $this->cache->calculateFolderSize(''));
+
+ // clean up
+ $this->cache->remove('');
+ $this->cache->remove($dir1);
+ $this->cache->remove($dir2);
+
+ $this->assertFalse($this->cache->inCache($dir1));
+ $this->assertFalse($this->cache->inCache($dir2));
+ }
+}
diff --git a/tests/lib/files/filesystem.php b/tests/lib/files/filesystem.php
index bef70cc725b..7cb57bf95ad 100644
--- a/tests/lib/files/filesystem.php
+++ b/tests/lib/files/filesystem.php
@@ -41,9 +41,12 @@ class Filesystem extends \PHPUnit_Framework_TestCase {
foreach ($this->tmpDirs as $dir) {
\OC_Helper::rmdirr($dir);
}
+ \OC\Files\Filesystem::clearMounts();
+ \OC_User::setUserId('');
}
public function setUp() {
+ \OC_User::setUserId('');
\OC\Files\Filesystem::clearMounts();
}
@@ -66,17 +69,72 @@ class Filesystem extends \PHPUnit_Framework_TestCase {
}
public function testNormalize() {
+ $this->assertEquals('/', \OC\Files\Filesystem::normalizePath(''));
+ $this->assertEquals('/', \OC\Files\Filesystem::normalizePath('/'));
+ $this->assertEquals('/', \OC\Files\Filesystem::normalizePath('/', false));
+ $this->assertEquals('/', \OC\Files\Filesystem::normalizePath('//'));
+ $this->assertEquals('/', \OC\Files\Filesystem::normalizePath('//', false));
$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/', false));
$this->assertEquals('/foo/bar', \OC\Files\Filesystem::normalizePath('/foo////bar'));
+ $this->assertEquals('/foo/bar', \OC\Files\Filesystem::normalizePath('/foo/////bar'));
+ $this->assertEquals('/foo/bar', \OC\Files\Filesystem::normalizePath('/foo/bar/.'));
+ $this->assertEquals('/foo/bar', \OC\Files\Filesystem::normalizePath('/foo/bar/./'));
+ $this->assertEquals('/foo/bar/', \OC\Files\Filesystem::normalizePath('/foo/bar/./', false));
+ $this->assertEquals('/foo/bar', \OC\Files\Filesystem::normalizePath('/foo/bar/./.'));
+ $this->assertEquals('/foo/bar', \OC\Files\Filesystem::normalizePath('/foo/bar/././'));
+ $this->assertEquals('/foo/bar/', \OC\Files\Filesystem::normalizePath('/foo/bar/././', false));
+ $this->assertEquals('/foo/bar', \OC\Files\Filesystem::normalizePath('/foo/./bar/'));
+ $this->assertEquals('/foo/bar/', \OC\Files\Filesystem::normalizePath('/foo/./bar/', false));
+ $this->assertEquals('/foo/.bar', \OC\Files\Filesystem::normalizePath('/foo/.bar/'));
+ $this->assertEquals('/foo/.bar/', \OC\Files\Filesystem::normalizePath('/foo/.bar/', false));
+ $this->assertEquals('/foo/.bar/tee', \OC\Files\Filesystem::normalizePath('/foo/.bar/tee'));
+
+ // normalize does not resolve '..' (by design)
+ $this->assertEquals('/foo/..', \OC\Files\Filesystem::normalizePath('/foo/../'));
+
if (class_exists('Patchwork\PHP\Shim\Normalizer')) {
$this->assertEquals("/foo/bar\xC3\xBC", \OC\Files\Filesystem::normalizePath("/foo/baru\xCC\x88"));
}
}
+ public function testNormalizeWindowsPaths() {
+ $this->assertEquals('/', \OC\Files\Filesystem::normalizePath(''));
+ $this->assertEquals('/', \OC\Files\Filesystem::normalizePath('\\'));
+ $this->assertEquals('/', \OC\Files\Filesystem::normalizePath('\\', false));
+ $this->assertEquals('/', \OC\Files\Filesystem::normalizePath('\\\\'));
+ $this->assertEquals('/', \OC\Files\Filesystem::normalizePath('\\\\', false));
+ $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\\', false));
+ $this->assertEquals('/foo/bar', \OC\Files\Filesystem::normalizePath('\\foo\\\\bar\\'));
+ $this->assertEquals('/foo/bar/', \OC\Files\Filesystem::normalizePath('\\foo\\\\bar\\', false));
+ $this->assertEquals('/foo/bar', \OC\Files\Filesystem::normalizePath('\\foo\\\\\\\\bar'));
+ $this->assertEquals('/foo/bar', \OC\Files\Filesystem::normalizePath('\\foo\\\\\\\\\\bar'));
+ $this->assertEquals('/foo/bar', \OC\Files\Filesystem::normalizePath('\\foo\\bar\\.'));
+ $this->assertEquals('/foo/bar', \OC\Files\Filesystem::normalizePath('\\foo\\bar\\.\\'));
+ $this->assertEquals('/foo/bar/', \OC\Files\Filesystem::normalizePath('\\foo\\bar\\.\\', false));
+ $this->assertEquals('/foo/bar', \OC\Files\Filesystem::normalizePath('\\foo\\bar\\.\\.'));
+ $this->assertEquals('/foo/bar', \OC\Files\Filesystem::normalizePath('\\foo\\bar\\.\\.\\'));
+ $this->assertEquals('/foo/bar/', \OC\Files\Filesystem::normalizePath('\\foo\\bar\\.\\.\\', false));
+ $this->assertEquals('/foo/bar', \OC\Files\Filesystem::normalizePath('\\foo\\.\\bar\\'));
+ $this->assertEquals('/foo/bar/', \OC\Files\Filesystem::normalizePath('\\foo\\.\\bar\\', false));
+ $this->assertEquals('/foo/.bar', \OC\Files\Filesystem::normalizePath('\\foo\\.bar\\'));
+ $this->assertEquals('/foo/.bar/', \OC\Files\Filesystem::normalizePath('\\foo\\.bar\\', false));
+ $this->assertEquals('/foo/.bar/tee', \OC\Files\Filesystem::normalizePath('\\foo\\.bar\\tee'));
+
+ // normalize does not resolve '..' (by design)
+ $this->assertEquals('/foo/..', \OC\Files\Filesystem::normalizePath('\\foo\\..\\'));
+
+ if (class_exists('Patchwork\PHP\Shim\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();
@@ -103,6 +161,67 @@ class Filesystem extends \PHPUnit_Framework_TestCase {
// \OC\Files\Filesystem::file_put_contents('/bar//foo', $fh);
}
+ /**
+ * Tests that a local storage mount is used when passed user
+ * does not exist.
+ */
+ public function testLocalMountWhenUserDoesNotExist() {
+ $datadir = \OC_Config::getValue("datadirectory", \OC::$SERVERROOT . "/data");
+ $userId = uniqid('user_');
+
+ \OC\Files\Filesystem::initMountPoints($userId);
+
+ $homeMount = \OC\Files\Filesystem::getStorage('/' . $userId . '/');
+
+ $this->assertInstanceOf('\OC\Files\Storage\Local', $homeMount);
+ $this->assertEquals('local::' . $datadir . '/' . $userId . '/', $homeMount->getId());
+ }
+
+ /**
+ * Tests that the home storage is used for the user's mount point
+ */
+ public function testHomeMount() {
+ $userId = uniqid('user_');
+
+ \OC_User::createUser($userId, $userId);
+
+ \OC\Files\Filesystem::initMountPoints($userId);
+
+ $homeMount = \OC\Files\Filesystem::getStorage('/' . $userId . '/');
+
+ $this->assertInstanceOf('\OC\Files\Storage\Home', $homeMount);
+ $this->assertEquals('home::' . $userId, $homeMount->getId());
+
+ \OC_User::deleteUser($userId);
+ }
+
+ /**
+ * Tests that the home storage is used in legacy mode
+ * for the user's mount point
+ */
+ public function testLegacyHomeMount() {
+ $datadir = \OC_Config::getValue("datadirectory", \OC::$SERVERROOT . "/data");
+ $userId = uniqid('user_');
+
+ // insert storage into DB by constructing it
+ // to make initMountsPoint find its existence
+ $localStorage = new \OC\Files\Storage\Local(array('datadir' => $datadir . '/' . $userId . '/'));
+ // this will trigger the insert
+ $cache = $localStorage->getCache();
+
+ \OC_User::createUser($userId, $userId);
+ \OC\Files\Filesystem::initMountPoints($userId);
+
+ $homeMount = \OC\Files\Filesystem::getStorage('/' . $userId . '/');
+
+ $this->assertInstanceOf('\OC\Files\Storage\Home', $homeMount);
+ $this->assertEquals('local::' . $datadir. '/' . $userId . '/', $homeMount->getId());
+
+ \OC_User::deleteUser($userId);
+ // delete storage entry
+ $cache->clear();
+ }
+
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/storage/home.php b/tests/lib/files/storage/home.php
index b01e07f7457..885291e4404 100644
--- a/tests/lib/files/storage/home.php
+++ b/tests/lib/files/storage/home.php
@@ -56,8 +56,8 @@ class Home extends Storage {
public function setUp() {
$this->tmpDir = \OC_Helper::tmpFolder();
- $userId = uniqid('user_');
- $this->user = new DummyUser($userId, $this->tmpDir);
+ $this->userId = uniqid('user_');
+ $this->user = new DummyUser($this->userId, $this->tmpDir);
$this->instance = new \OC\Files\Storage\Home(array('user' => $this->user));
}
@@ -65,7 +65,32 @@ class Home extends Storage {
\OC_Helper::rmdirr($this->tmpDir);
}
+ /**
+ * Tests that the root path matches the data dir
+ */
public function testRoot() {
$this->assertEquals($this->tmpDir, $this->instance->getLocalFolder(''));
}
+
+ /**
+ * Tests that the home id is in the format home::user1
+ */
+ public function testId() {
+ $this->assertEquals('home::' . $this->userId, $this->instance->getId());
+ }
+
+ /**
+ * Tests that the legacy home id is in the format local::/path/to/datadir/user1/
+ */
+ public function testLegacyId() {
+ $this->instance = new \OC\Files\Storage\Home(array('user' => $this->user, 'legacy' => true));
+ $this->assertEquals('local::' . $this->tmpDir . '/', $this->instance->getId());
+ }
+
+ /**
+ * Tests that getCache() returns an instance of HomeCache
+ */
+ public function testGetCacheReturnsHomeCache() {
+ $this->assertInstanceOf('\OC\Files\Cache\HomeCache', $this->instance->getCache());
+ }
}
diff --git a/version.php b/version.php
index 567fbe5c923..9b04bd244fb 100644
--- a/version.php
+++ b/version.php
@@ -1,10 +1,10 @@
<?php
// We only can count up. The 4. digit is only for the internal patchlevel to trigger DB upgrades between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel when updating major/minor version number.
-$OC_Version=array(6, 00, 0, 5);
+$OC_Version=array(6, 00, 0, 7);
// The human readable string
-$OC_VersionString='6.0 beta 3';
+$OC_VersionString='6.0 beta 4';
// The ownCloud edition
$OC_Edition='';