Compare commits
240 Commits
returnIfVe
...
v8.0.3RC3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b7ab280d8e | ||
|
|
76eadfa8dc | ||
|
|
273719f620 | ||
|
|
6e041088b8 | ||
|
|
da23ab0dd6 | ||
|
|
d3761e02f5 | ||
|
|
9dac69b21b | ||
|
|
e4f0892831 | ||
|
|
105b285874 | ||
|
|
adfc8c79c4 | ||
|
|
06ab387509 | ||
|
|
7a3b4b464e | ||
|
|
3f6db4c1ab | ||
|
|
628bb3fb3e | ||
|
|
dfd302178a | ||
|
|
351a1ccaad | ||
|
|
3d45d0bd1d | ||
|
|
142694d095 | ||
|
|
8357a253b3 | ||
|
|
ea647ede73 | ||
|
|
e94152b226 | ||
|
|
b1688311c8 | ||
|
|
c1f52508a5 | ||
|
|
03473c51c2 | ||
|
|
ddcb4e1b94 | ||
|
|
5e3203348e | ||
|
|
a538f14b4a | ||
|
|
baa2e4f995 | ||
|
|
ae59df8492 | ||
|
|
a64c3fb3a2 | ||
|
|
5964cd3751 | ||
|
|
893cbc917d | ||
|
|
48ceaa9502 | ||
|
|
944b301837 | ||
|
|
29c56fbfb2 | ||
|
|
3b69354d19 | ||
|
|
5ee843cd59 | ||
|
|
93ae742ad8 | ||
|
|
cd47e72e88 | ||
|
|
b896be821f | ||
|
|
e90ead2a8d | ||
|
|
bc7676089c | ||
|
|
3232dc76d4 | ||
|
|
c0bcaa4980 | ||
|
|
e12c76ed66 | ||
|
|
722faee4c6 | ||
|
|
d04ad4be26 | ||
|
|
ba9446a1b8 | ||
|
|
9bc1f0a67a | ||
|
|
f7f14708a2 | ||
|
|
78c348381d | ||
|
|
4c92aafc19 | ||
|
|
e4d8dc7825 | ||
|
|
6e26b117b9 | ||
|
|
4149fc40c2 | ||
|
|
e2ea175ea2 | ||
|
|
b960fa83ef | ||
|
|
31de51eacc | ||
|
|
bda7b5c446 | ||
|
|
58ad3fac06 | ||
|
|
88a180fadb | ||
|
|
95d81c36ff | ||
|
|
625cbc63a4 | ||
|
|
5720211f70 | ||
|
|
9d0ea7fa11 | ||
|
|
02f00c9980 | ||
|
|
4774d648bd | ||
|
|
3d7ed01135 | ||
|
|
c28356fffc | ||
|
|
3dad31d6df | ||
|
|
c9bafe5c7a | ||
|
|
637503a1ac | ||
|
|
9ad48e0fe9 | ||
|
|
97a65e153d | ||
|
|
5ad226cedb | ||
|
|
6843f1690f | ||
|
|
04809b6037 | ||
|
|
5538c27322 | ||
|
|
35abb4d71e | ||
|
|
bc5ca78816 | ||
|
|
f15d41e185 | ||
|
|
27df0a1735 | ||
|
|
171974e43c | ||
|
|
03ef085a4c | ||
|
|
d9f6971d0b | ||
|
|
b081bb24e5 | ||
|
|
aa63a16f25 | ||
|
|
27990b5360 | ||
|
|
9383856ca5 | ||
|
|
78b2c8b0be | ||
|
|
4cfa4ecc28 | ||
|
|
92a024b2fd | ||
|
|
a1c414c197 | ||
|
|
e8ee079aa7 | ||
|
|
769f666663 | ||
|
|
c6136de551 | ||
|
|
4bf3d2907d | ||
|
|
1f1078120c | ||
|
|
096ccb7a7b | ||
|
|
e416b469de | ||
|
|
228d4087ac | ||
|
|
b95405e09a | ||
|
|
8a5ef62b60 | ||
|
|
f59b286a59 | ||
|
|
7e87cdab4a | ||
|
|
5effc4a53a | ||
|
|
1540d8fad1 | ||
|
|
81ae4b3687 | ||
|
|
79f827cf40 | ||
|
|
8781608ca7 | ||
|
|
5c10c05c1f | ||
|
|
9b573ee8c9 | ||
|
|
5d53314e8f | ||
|
|
625bb3c4d5 | ||
|
|
1374f25a0b | ||
|
|
ed954bd941 | ||
|
|
a03d39b1ad | ||
|
|
2bfd03e483 | ||
|
|
c100d90793 | ||
|
|
8db687a1cd | ||
|
|
5def2c0998 | ||
|
|
10d0f0d9b3 | ||
|
|
c477e24034 | ||
|
|
36bed7c2f6 | ||
|
|
860c59a347 | ||
|
|
f6ceb0b0d5 | ||
|
|
e5aefc8bda | ||
|
|
ba1748bd80 | ||
|
|
6d5e60bd9b | ||
|
|
a7fc0fc07b | ||
|
|
c032b94b77 | ||
|
|
8961967fec | ||
|
|
c0cfd2ddbb | ||
|
|
00d0120e22 | ||
|
|
3672ec39dd | ||
|
|
2f6eaa3832 | ||
|
|
8f23742ca6 | ||
|
|
c0a4affe00 | ||
|
|
efe635f0d5 | ||
|
|
fa64ba356a | ||
|
|
eb2ac86c5d | ||
|
|
598c4fdcae | ||
|
|
fe9e2e9945 | ||
|
|
716e0e6645 | ||
|
|
266a655107 | ||
|
|
2e85c1fb9b | ||
|
|
8c529adf85 | ||
|
|
fb8569499c | ||
|
|
1d9d0f653d | ||
|
|
846fdecbcc | ||
|
|
95cfc4185a | ||
|
|
c78b5453ff | ||
|
|
75cae3b252 | ||
|
|
a796021143 | ||
|
|
83dd98426c | ||
|
|
0ec73a58e9 | ||
|
|
d29234382f | ||
|
|
411cd5b2d5 | ||
|
|
6d8d4ea546 | ||
|
|
9f6a640e73 | ||
|
|
810ac0fca7 | ||
|
|
c77fd2eef6 | ||
|
|
3356abe5c7 | ||
|
|
5faf9f8192 | ||
|
|
c8d61ddad8 | ||
|
|
80e3337bad | ||
|
|
17635053ab | ||
|
|
e82f30caae | ||
|
|
ca7acd8461 | ||
|
|
c0550ed953 | ||
|
|
b0a6a54651 | ||
|
|
b057ae2da1 | ||
|
|
e277a9b3dd | ||
|
|
5c7157e0af | ||
|
|
1188c74fe5 | ||
|
|
06742fe24b | ||
|
|
9e38e2c1a9 | ||
|
|
2e361618a3 | ||
|
|
b63a6a4fc4 | ||
|
|
bc14181563 | ||
|
|
c6c888c8a1 | ||
|
|
ced104c206 | ||
|
|
5fef637f87 | ||
|
|
2ed3c7af27 | ||
|
|
673c8a7531 | ||
|
|
089ad7c242 | ||
|
|
ee83fa673e | ||
|
|
033635c9fb | ||
|
|
3c51f5ff38 | ||
|
|
62029c3541 | ||
|
|
9735fbb0f4 | ||
|
|
c8f55ae5dd | ||
|
|
9e4be2909c | ||
|
|
d8b676f485 | ||
|
|
08e1ae11d5 | ||
|
|
88f62bf4ea | ||
|
|
e1985647d5 | ||
|
|
8e55425c93 | ||
|
|
42c6963acc | ||
|
|
cb3060c940 | ||
|
|
cd75ac2e2c | ||
|
|
968dc81a74 | ||
|
|
fc4bb1ae88 | ||
|
|
f4f5097b00 | ||
|
|
f558ee5802 | ||
|
|
2740bdc1d9 | ||
|
|
1378c17b55 | ||
|
|
033873c6cc | ||
|
|
159d1e4ce7 | ||
|
|
5642f1b97a | ||
|
|
b25bfb2796 | ||
|
|
4b8d1e8dbd | ||
|
|
95aa9a8890 | ||
|
|
05e56711f3 | ||
|
|
5dd63bdd04 | ||
|
|
8bd2f2eb23 | ||
|
|
676c91d4a3 | ||
|
|
a719f022fb | ||
|
|
47ceebbfc5 | ||
|
|
ae89229815 | ||
|
|
2885a84373 | ||
|
|
def1ffad23 | ||
|
|
948ee0e398 | ||
|
|
4e9fd632ea | ||
|
|
cc243e1296 | ||
|
|
d6c7f6f413 | ||
|
|
662ebc6c80 | ||
|
|
4f1f68ead8 | ||
|
|
ab456bed98 | ||
|
|
4825a4ca1e | ||
|
|
36cb41d15f | ||
|
|
61eaf0e832 | ||
|
|
e95d274f17 | ||
|
|
1740fb236e | ||
|
|
de0c16789e | ||
|
|
f99ca64adc | ||
|
|
46186dc896 | ||
|
|
d0fd28c97c | ||
|
|
c5a87c2a18 | ||
|
|
85d695dbe8 |
@@ -1,4 +1,4 @@
|
||||
# Version: 8.0.0
|
||||
# Version: 8.0.3
|
||||
<IfModule mod_fcgid.c>
|
||||
<IfModule mod_setenvif.c>
|
||||
<IfModule mod_headers.c>
|
||||
@@ -13,6 +13,8 @@ php_value post_max_size 513M
|
||||
php_value memory_limit 512M
|
||||
php_value mbstring.func_overload 0
|
||||
php_value always_populate_raw_post_data -1
|
||||
php_value default_charset 'UTF-8'
|
||||
php_value output_buffering off
|
||||
<IfModule mod_env.c>
|
||||
SetEnv htaccessWorking true
|
||||
</IfModule>
|
||||
|
||||
@@ -3,3 +3,5 @@ post_max_size=513M
|
||||
memory_limit=512M
|
||||
mbstring.func_overload=0
|
||||
always_populate_raw_post_data=-1
|
||||
default_charset='UTF-8'
|
||||
output_buffering=off
|
||||
|
||||
2
3rdparty
2
3rdparty
Submodule 3rdparty updated: a32d3924bd...70ed7fe3d5
@@ -102,7 +102,11 @@ class ApiController extends Controller {
|
||||
foreach ($fileInfos as &$fileInfo) {
|
||||
$file = \OCA\Files\Helper::formatFileInfo($fileInfo);
|
||||
$parts = explode('/', dirname($fileInfo->getPath()), 4);
|
||||
$file['path'] = '/' . $parts[3];
|
||||
if(isset($parts[3])) {
|
||||
$file['path'] = '/' . $parts[3];
|
||||
} else {
|
||||
$file['path'] = '/';
|
||||
}
|
||||
$file['tags'] = array($tagName);
|
||||
$files[] = $file;
|
||||
}
|
||||
|
||||
@@ -947,7 +947,7 @@
|
||||
mime: mime,
|
||||
etag: fileData.etag,
|
||||
callback: function(url) {
|
||||
iconDiv.css('background-image', 'url(' + url + ')');
|
||||
iconDiv.css('background-image', 'url("' + url + '")');
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -959,7 +959,7 @@
|
||||
};
|
||||
var previewUrl = this.generatePreviewUrl(urlSpec);
|
||||
previewUrl = previewUrl.replace('(', '%28').replace(')', '%29');
|
||||
iconDiv.css('background-image', 'url(' + previewUrl + ')');
|
||||
iconDiv.css('background-image', 'url("' + previewUrl + '")');
|
||||
}
|
||||
}
|
||||
return tr;
|
||||
|
||||
243
apps/files/tests/controller/apicontrollertest.php
Normal file
243
apps/files/tests/controller/apicontrollertest.php
Normal file
@@ -0,0 +1,243 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) 2015 Lukas Reschke <lukas@owncloud.com>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace OCA\Files\Controller;
|
||||
|
||||
use OC\Files\FileInfo;
|
||||
use OCP\AppFramework\Http;
|
||||
use OC\Preview;
|
||||
use OCP\Files\NotFoundException;
|
||||
use OCP\Files\StorageNotAvailableException;
|
||||
use Test\TestCase;
|
||||
use OCP\IRequest;
|
||||
use OCA\Files\Service\TagService;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
|
||||
/**
|
||||
* Class ApiController
|
||||
*
|
||||
* @package OCA\Files\Controller
|
||||
*/
|
||||
class ApiControllerTest extends TestCase {
|
||||
/** @var string */
|
||||
private $appName = 'files';
|
||||
/** @var IRequest */
|
||||
private $request;
|
||||
/** @var TagService */
|
||||
private $tagService;
|
||||
/** @var ApiController */
|
||||
private $apiController;
|
||||
|
||||
public function setUp() {
|
||||
$this->request = $this->getMockBuilder('\OCP\IRequest')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->tagService = $this->getMockBuilder('\OCA\Files\Service\TagService')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$this->apiController = new ApiController(
|
||||
$this->appName,
|
||||
$this->request,
|
||||
$this->tagService
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetFilesByTagEmpty() {
|
||||
$tagName = 'MyTagName';
|
||||
$this->tagService->expects($this->once())
|
||||
->method('getFilesByTag')
|
||||
->with($this->equalTo([$tagName]))
|
||||
->will($this->returnValue([]));
|
||||
|
||||
$expected = new DataResponse(['files' => []]);
|
||||
$this->assertEquals($expected, $this->apiController->getFilesByTag([$tagName]));
|
||||
}
|
||||
|
||||
public function testGetFilesByTagSingle() {
|
||||
$tagName = 'MyTagName';
|
||||
$fileInfo = new FileInfo(
|
||||
'/root.txt',
|
||||
$this->getMockBuilder('\OC\Files\Storage\Storage')
|
||||
->disableOriginalConstructor()
|
||||
->getMock(),
|
||||
'/var/www/root.txt',
|
||||
[
|
||||
'mtime' => 55,
|
||||
'mimetype' => 'application/pdf',
|
||||
'size' => 1234,
|
||||
'etag' => 'MyEtag',
|
||||
],
|
||||
$this->getMockBuilder('\OCP\Files\Mount\IMountPoint')
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
);
|
||||
$this->tagService->expects($this->once())
|
||||
->method('getFilesByTag')
|
||||
->with($this->equalTo([$tagName]))
|
||||
->will($this->returnValue([$fileInfo]));
|
||||
|
||||
$expected = new DataResponse([
|
||||
'files' => [
|
||||
[
|
||||
'id' => null,
|
||||
'parentId' => null,
|
||||
'date' => \OCP\Util::formatDate(55),
|
||||
'mtime' => 55000,
|
||||
'icon' => \OCA\Files\Helper::determineIcon($fileInfo),
|
||||
'name' => 'root.txt',
|
||||
'permissions' => null,
|
||||
'mimetype' => 'application/pdf',
|
||||
'size' => 1234,
|
||||
'type' => 'file',
|
||||
'etag' => 'MyEtag',
|
||||
'path' => '/',
|
||||
'tags' => [
|
||||
[
|
||||
'MyTagName'
|
||||
]
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
$this->assertEquals($expected, $this->apiController->getFilesByTag([$tagName]));
|
||||
}
|
||||
|
||||
public function testGetFilesByTagMultiple() {
|
||||
$tagName = 'MyTagName';
|
||||
$fileInfo1 = new FileInfo(
|
||||
'/root.txt',
|
||||
$this->getMockBuilder('\OC\Files\Storage\Storage')
|
||||
->disableOriginalConstructor()
|
||||
->getMock(),
|
||||
'/var/www/root.txt',
|
||||
[
|
||||
'mtime' => 55,
|
||||
'mimetype' => 'application/pdf',
|
||||
'size' => 1234,
|
||||
'etag' => 'MyEtag',
|
||||
],
|
||||
$this->getMockBuilder('\OCP\Files\Mount\IMountPoint')
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
);
|
||||
$fileInfo2 = new FileInfo(
|
||||
'/root.txt',
|
||||
$this->getMockBuilder('\OC\Files\Storage\Storage')
|
||||
->disableOriginalConstructor()
|
||||
->getMock(),
|
||||
'/var/www/some/sub.txt',
|
||||
[
|
||||
'mtime' => 999,
|
||||
'mimetype' => 'application/binary',
|
||||
'size' => 9876,
|
||||
'etag' => 'SubEtag',
|
||||
],
|
||||
$this->getMockBuilder('\OCP\Files\Mount\IMountPoint')
|
||||
->disableOriginalConstructor()
|
||||
->getMock()
|
||||
);
|
||||
$this->tagService->expects($this->once())
|
||||
->method('getFilesByTag')
|
||||
->with($this->equalTo([$tagName]))
|
||||
->will($this->returnValue([$fileInfo1, $fileInfo2]));
|
||||
|
||||
$expected = new DataResponse([
|
||||
'files' => [
|
||||
[
|
||||
'id' => null,
|
||||
'parentId' => null,
|
||||
'date' => \OCP\Util::formatDate(55),
|
||||
'mtime' => 55000,
|
||||
'icon' => \OCA\Files\Helper::determineIcon($fileInfo1),
|
||||
'name' => 'root.txt',
|
||||
'permissions' => null,
|
||||
'mimetype' => 'application/pdf',
|
||||
'size' => 1234,
|
||||
'type' => 'file',
|
||||
'etag' => 'MyEtag',
|
||||
'path' => '/',
|
||||
'tags' => [
|
||||
[
|
||||
'MyTagName'
|
||||
]
|
||||
],
|
||||
],
|
||||
[
|
||||
'id' => null,
|
||||
'parentId' => null,
|
||||
'date' => \OCP\Util::formatDate(999),
|
||||
'mtime' => 999000,
|
||||
'icon' => \OCA\Files\Helper::determineIcon($fileInfo2),
|
||||
'name' => 'root.txt',
|
||||
'permissions' => null,
|
||||
'mimetype' => 'application/binary',
|
||||
'size' => 9876,
|
||||
'type' => 'file',
|
||||
'etag' => 'SubEtag',
|
||||
'path' => '/',
|
||||
'tags' => [
|
||||
[
|
||||
'MyTagName'
|
||||
]
|
||||
],
|
||||
]
|
||||
],
|
||||
]);
|
||||
$this->assertEquals($expected, $this->apiController->getFilesByTag([$tagName]));
|
||||
}
|
||||
|
||||
public function testUpdateFileTagsEmpty() {
|
||||
$expected = new DataResponse([]);
|
||||
$this->assertEquals($expected, $this->apiController->updateFileTags('/path.txt'));
|
||||
}
|
||||
|
||||
public function testUpdateFileTagsWorking() {
|
||||
$this->tagService->expects($this->once())
|
||||
->method('updateFileTags')
|
||||
->with('/path.txt', ['Tag1', 'Tag2']);
|
||||
|
||||
$expected = new DataResponse([
|
||||
'tags' => [
|
||||
'Tag1',
|
||||
'Tag2'
|
||||
],
|
||||
]);
|
||||
$this->assertEquals($expected, $this->apiController->updateFileTags('/path.txt', ['Tag1', 'Tag2']));
|
||||
}
|
||||
|
||||
public function testUpdateFileTagsNotFoundException() {
|
||||
$this->tagService->expects($this->once())
|
||||
->method('updateFileTags')
|
||||
->with('/path.txt', ['Tag1', 'Tag2'])
|
||||
->will($this->throwException(new NotFoundException('My error message')));
|
||||
|
||||
$expected = new DataResponse('My error message', Http::STATUS_NOT_FOUND);
|
||||
$this->assertEquals($expected, $this->apiController->updateFileTags('/path.txt', ['Tag1', 'Tag2']));
|
||||
}
|
||||
|
||||
public function testUpdateFileTagsStorageNotAvailableException() {
|
||||
$this->tagService->expects($this->once())
|
||||
->method('updateFileTags')
|
||||
->with('/path.txt', ['Tag1', 'Tag2'])
|
||||
->will($this->throwException(new StorageNotAvailableException('My error message')));
|
||||
|
||||
$expected = new DataResponse('My error message', Http::STATUS_SERVICE_UNAVAILABLE);
|
||||
$this->assertEquals($expected, $this->apiController->updateFileTags('/path.txt', ['Tag1', 'Tag2']));
|
||||
}
|
||||
|
||||
public function testUpdateFileTagsStorageGenericException() {
|
||||
$this->tagService->expects($this->once())
|
||||
->method('updateFileTags')
|
||||
->with('/path.txt', ['Tag1', 'Tag2'])
|
||||
->will($this->throwException(new \Exception('My error message')));
|
||||
|
||||
$expected = new DataResponse('My error message', Http::STATUS_NOT_FOUND);
|
||||
$this->assertEquals($expected, $this->apiController->updateFileTags('/path.txt', ['Tag1', 'Tag2']));
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
<?php
|
||||
$TRANSLATIONS = array(
|
||||
"Saving..." => "Spašavam..."
|
||||
);
|
||||
$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);";
|
||||
@@ -1,5 +0,0 @@
|
||||
<?php
|
||||
$TRANSLATIONS = array(
|
||||
"Saving..." => "Simpan..."
|
||||
);
|
||||
$PLURAL_FORMS = "nplurals=1; plural=0;";
|
||||
@@ -1,5 +0,0 @@
|
||||
<?php
|
||||
$TRANSLATIONS = array(
|
||||
"Saving..." => "Enregistra..."
|
||||
);
|
||||
$PLURAL_FORMS = "nplurals=2; plural=(n > 1);";
|
||||
@@ -1,5 +0,0 @@
|
||||
<?php
|
||||
$TRANSLATIONS = array(
|
||||
"personal settings" => "వ్యక్తిగత అమరికలు"
|
||||
);
|
||||
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
/**
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @copyright (C) 2014 ownCloud, Inc.
|
||||
@@ -35,6 +35,7 @@ class Migration {
|
||||
|
||||
public function __construct() {
|
||||
$this->view = new \OC\Files\View();
|
||||
$this->view->getUpdater()->disable();
|
||||
$this->public_share_key_id = Helper::getPublicShareKeyId();
|
||||
$this->recovery_key_id = Helper::getRecoveryKeyId();
|
||||
}
|
||||
@@ -50,7 +51,7 @@ class Migration {
|
||||
$this->reorganizeFolderStructureForUser($user);
|
||||
}
|
||||
$offset += $limit;
|
||||
} while(count($users) >= $limit);
|
||||
} while (count($users) >= $limit);
|
||||
}
|
||||
|
||||
public function reorganizeSystemFolderStructure() {
|
||||
@@ -74,6 +75,10 @@ class Migration {
|
||||
$this->view->deleteAll('/owncloud_private_key');
|
||||
$this->view->deleteAll('/files_encryption/share-keys');
|
||||
$this->view->deleteAll('/files_encryption/keyfiles');
|
||||
$storage = $this->view->getMount('')->getStorage();
|
||||
$storage->getScanner()->scan('files_encryption');
|
||||
$storage->getCache()->remove('owncloud_private_key');
|
||||
$storage->getCache()->remove('public-keys');
|
||||
}
|
||||
|
||||
|
||||
@@ -96,6 +101,7 @@ class Migration {
|
||||
}
|
||||
// delete old folders
|
||||
$this->deleteOldKeys($user);
|
||||
$this->view->getMount('/' . $user)->getStorage()->getScanner()->scan('files_encryption');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,7 +133,7 @@ class Migration {
|
||||
while (($oldPublicKey = readdir($dh)) !== false) {
|
||||
if (!\OC\Files\Filesystem::isIgnoredDir($oldPublicKey)) {
|
||||
$newPublicKey = substr($oldPublicKey, 0, strlen($oldPublicKey) - strlen('.public.key')) . '.publicKey';
|
||||
$this->view->rename('public-keys/' . $oldPublicKey , 'files_encryption/public_keys/' . $newPublicKey);
|
||||
$this->view->rename('public-keys/' . $oldPublicKey, 'files_encryption/public_keys/' . $newPublicKey);
|
||||
}
|
||||
}
|
||||
closedir($dh);
|
||||
@@ -141,7 +147,7 @@ class Migration {
|
||||
while (($oldPrivateKey = readdir($dh)) !== false) {
|
||||
if (!\OC\Files\Filesystem::isIgnoredDir($oldPrivateKey)) {
|
||||
$newPrivateKey = substr($oldPrivateKey, 0, strlen($oldPrivateKey) - strlen('.private.key')) . '.privateKey';
|
||||
$this->view->rename('owncloud_private_key/' . $oldPrivateKey , 'files_encryption/' . $newPrivateKey);
|
||||
$this->view->rename('owncloud_private_key/' . $oldPrivateKey, 'files_encryption/' . $newPrivateKey);
|
||||
}
|
||||
}
|
||||
closedir($dh);
|
||||
@@ -149,10 +155,10 @@ class Migration {
|
||||
}
|
||||
|
||||
private function renameUsersPrivateKey($user) {
|
||||
$oldPrivateKey = $user . '/files_encryption/' . $user . '.private.key';
|
||||
$newPrivateKey = substr($oldPrivateKey, 0, strlen($oldPrivateKey) - strlen('.private.key')) . '.privateKey';
|
||||
$oldPrivateKey = $user . '/files_encryption/' . $user . '.private.key';
|
||||
$newPrivateKey = substr($oldPrivateKey, 0, strlen($oldPrivateKey) - strlen('.private.key')) . '.privateKey';
|
||||
|
||||
$this->view->rename($oldPrivateKey, $newPrivateKey);
|
||||
$this->view->rename($oldPrivateKey, $newPrivateKey);
|
||||
}
|
||||
|
||||
private function getFileName($file, $trash) {
|
||||
@@ -186,7 +192,7 @@ class Migration {
|
||||
}
|
||||
|
||||
private function getFilePath($path, $user, $trash) {
|
||||
$offset = $trash ? strlen($user . '/files_trashbin/keyfiles') : strlen($user . '/files_encryption/keyfiles');
|
||||
$offset = $trash ? strlen($user . '/files_trashbin/keyfiles') : strlen($user . '/files_encryption/keyfiles');
|
||||
return substr($path, $offset);
|
||||
}
|
||||
|
||||
@@ -215,7 +221,7 @@ class Migration {
|
||||
$extension = $this->getExtension($file, $trash);
|
||||
$targetDir = $this->getTargetDir($user, $filePath, $filename, $extension, $trash);
|
||||
$this->createPathForKeys($targetDir);
|
||||
$this->view->copy($path . '/' . $file, $targetDir . '/fileKey');
|
||||
$this->view->rename($path . '/' . $file, $targetDir . '/fileKey');
|
||||
$this->renameShareKeys($user, $filePath, $filename, $targetDir, $trash);
|
||||
}
|
||||
}
|
||||
@@ -258,10 +264,10 @@ class Migration {
|
||||
if ($this->view->is_dir($oldShareKeyPath . '/' . $file)) {
|
||||
continue;
|
||||
} else {
|
||||
if (substr($file, 0, strlen($filename) +1) === $filename . '.') {
|
||||
if (substr($file, 0, strlen($filename) + 1) === $filename . '.') {
|
||||
|
||||
$uid = $this->getUidFromShareKey($file, $filename, $trash);
|
||||
$this->view->copy($oldShareKeyPath . '/' . $file, $target . '/' . $uid . '.shareKey');
|
||||
$this->view->rename($oldShareKeyPath . '/' . $file, $target . '/' . $uid . '.shareKey');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -100,7 +100,12 @@ class Dropbox extends \OC\Files\Storage\Common {
|
||||
return $contents;
|
||||
} else {
|
||||
try {
|
||||
$response = $this->dropbox->getMetaData($path, 'false');
|
||||
$requestPath = $path;
|
||||
if ($path === '.') {
|
||||
$requestPath = '';
|
||||
}
|
||||
|
||||
$response = $this->dropbox->getMetaData($requestPath, 'false');
|
||||
if (!isset($response['is_deleted']) || !$response['is_deleted']) {
|
||||
$this->metaData[$path] = $response;
|
||||
return $response;
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
<field>
|
||||
<name>remote_id</name>
|
||||
<type>integer</type>
|
||||
<default>-1</default>
|
||||
<notnull>true</notnull>
|
||||
<length>4</length>
|
||||
</field>
|
||||
|
||||
@@ -1 +1 @@
|
||||
0.6.0
|
||||
0.6.1
|
||||
|
||||
@@ -42,7 +42,7 @@ class Application extends App {
|
||||
$server->getAppConfig(),
|
||||
$server->getConfig(),
|
||||
$c->query('URLGenerator'),
|
||||
$server->getUserManager(),
|
||||
$c->query('UserManager'),
|
||||
$server->getLogger(),
|
||||
$server->getActivityManager()
|
||||
);
|
||||
@@ -65,6 +65,9 @@ class Application extends App {
|
||||
$container->registerService('URLGenerator', function(SimpleContainer $c) use ($server){
|
||||
return $server->getUrlGenerator();
|
||||
});
|
||||
$container->registerService('UserManager', function(SimpleContainer $c) use ($server){
|
||||
return $server->getUserManager();
|
||||
});
|
||||
$container->registerService('IsIncomingShareEnabled', function(SimpleContainer $c) {
|
||||
return Helper::isIncomingServer2serverShareEnabled();
|
||||
});
|
||||
|
||||
@@ -23,7 +23,7 @@ OC.L10N.register(
|
||||
"Add remote share" : "Entfernte Freigabe hinzufügen",
|
||||
"No ownCloud installation (7 or higher) found at {remote}" : "Keine OwnCloud-Installation (7 oder höher) auf {remote} gefunden",
|
||||
"Invalid ownCloud url" : "Ungültige OwnCloud-URL",
|
||||
"Share" : "Share",
|
||||
"Share" : "Teilen",
|
||||
"Shared by" : "Geteilt von ",
|
||||
"A file or folder was shared from <strong>another server</strong>" : "Eine Datei oder ein Ordner wurde von <strong>einem anderen Server</strong> geteilt",
|
||||
"A public shared file or folder was <strong>downloaded</strong>" : "Eine öffentliche geteilte Datei oder ein öffentlicher geteilter Ordner wurde <strong>heruntergeladen</strong>",
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
"Add remote share" : "Entfernte Freigabe hinzufügen",
|
||||
"No ownCloud installation (7 or higher) found at {remote}" : "Keine OwnCloud-Installation (7 oder höher) auf {remote} gefunden",
|
||||
"Invalid ownCloud url" : "Ungültige OwnCloud-URL",
|
||||
"Share" : "Share",
|
||||
"Share" : "Teilen",
|
||||
"Shared by" : "Geteilt von ",
|
||||
"A file or folder was shared from <strong>another server</strong>" : "Eine Datei oder ein Ordner wurde von <strong>einem anderen Server</strong> geteilt",
|
||||
"A public shared file or folder was <strong>downloaded</strong>" : "Eine öffentliche geteilte Datei oder ein öffentlicher geteilter Ordner wurde <strong>heruntergeladen</strong>",
|
||||
|
||||
@@ -394,6 +394,28 @@ class Shared_Cache extends Cache {
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* update the folder size and the size of all parent folders
|
||||
*
|
||||
* @param string|boolean $path
|
||||
* @param array $data (optional) meta data of the folder
|
||||
*/
|
||||
public function correctFolderSize($path, $data = null) {
|
||||
$this->calculateFolderSize($path, $data);
|
||||
if ($path !== '') {
|
||||
$parent = dirname($path);
|
||||
if ($parent === '.' or $parent === '/') {
|
||||
$parent = '';
|
||||
}
|
||||
$this->correctFolderSize($parent);
|
||||
} else {
|
||||
// bubble up to source cache
|
||||
$sourceCache = $this->getSourceCache($path);
|
||||
$parent = dirname($this->files[$path]);
|
||||
$sourceCache->correctFolderSize($parent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get the size of a folder and set it in the cache
|
||||
*
|
||||
|
||||
@@ -17,12 +17,12 @@ use OC_Files;
|
||||
use OC_Util;
|
||||
use OCP;
|
||||
use OCP\Template;
|
||||
use OCP\JSON;
|
||||
use OCP\Share;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\IRequest;
|
||||
use OCP\AppFramework\Http\TemplateResponse;
|
||||
use OCP\AppFramework\Http\RedirectResponse;
|
||||
use OCP\AppFramework\Http\NotFoundResponse;
|
||||
use OC\URLGenerator;
|
||||
use OC\AppConfig;
|
||||
use OCP\ILogger;
|
||||
@@ -60,7 +60,7 @@ class ShareController extends Controller {
|
||||
* @param AppConfig $appConfig
|
||||
* @param OCP\IConfig $config
|
||||
* @param URLGenerator $urlGenerator
|
||||
* @param OC\User\Manager $userManager
|
||||
* @param OCP\IUserManager $userManager
|
||||
* @param ILogger $logger
|
||||
* @param OCP\Activity\IManager $activityManager
|
||||
*/
|
||||
@@ -70,7 +70,7 @@ class ShareController extends Controller {
|
||||
AppConfig $appConfig,
|
||||
OCP\IConfig $config,
|
||||
URLGenerator $urlGenerator,
|
||||
OC\User\Manager $userManager,
|
||||
OCP\IUserManager $userManager,
|
||||
ILogger $logger,
|
||||
OCP\Activity\IManager $activityManager) {
|
||||
parent::__construct($appName, $request);
|
||||
@@ -113,7 +113,7 @@ class ShareController extends Controller {
|
||||
public function authenticate($token, $password = '') {
|
||||
$linkItem = Share::getShareByToken($token, false);
|
||||
if($linkItem === false) {
|
||||
return new TemplateResponse('core', '404', array(), 'guest');
|
||||
return new NotFoundResponse();
|
||||
}
|
||||
|
||||
$authenticate = Helper::authenticate($linkItem, $password);
|
||||
@@ -139,18 +139,11 @@ class ShareController extends Controller {
|
||||
// Check whether share exists
|
||||
$linkItem = Share::getShareByToken($token, false);
|
||||
if($linkItem === false) {
|
||||
return new TemplateResponse('core', '404', array(), 'guest');
|
||||
return new NotFoundResponse();
|
||||
}
|
||||
|
||||
$shareOwner = $linkItem['uid_owner'];
|
||||
$originalSharePath = null;
|
||||
$rootLinkItem = OCP\Share::resolveReShare($linkItem);
|
||||
if (isset($rootLinkItem['uid_owner'])) {
|
||||
OCP\JSON::checkUserExists($rootLinkItem['uid_owner']);
|
||||
OC_Util::tearDownFS();
|
||||
OC_Util::setupFS($rootLinkItem['uid_owner']);
|
||||
$originalSharePath = Filesystem::getPath($linkItem['file_source']);
|
||||
}
|
||||
$originalSharePath = $this->getPath($token);
|
||||
|
||||
// Share is password protected - check whether the user is permitted to access the share
|
||||
if (isset($linkItem['share_with']) && !Helper::authenticate($linkItem)) {
|
||||
@@ -161,11 +154,13 @@ class ShareController extends Controller {
|
||||
if (Filesystem::isReadable($originalSharePath . $path)) {
|
||||
$getPath = Filesystem::normalizePath($path);
|
||||
$originalSharePath .= $path;
|
||||
} else {
|
||||
throw new OCP\Files\NotFoundException();
|
||||
}
|
||||
|
||||
$file = basename($originalSharePath);
|
||||
|
||||
$shareTmpl = array();
|
||||
$shareTmpl = [];
|
||||
$shareTmpl['displayName'] = User::getDisplayName($shareOwner);
|
||||
$shareTmpl['filename'] = $file;
|
||||
$shareTmpl['directory_path'] = $linkItem['file_target'];
|
||||
@@ -263,22 +258,29 @@ class ShareController extends Controller {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $token
|
||||
* @return null|string
|
||||
* @param string $token
|
||||
* @return string Resolved file path of the token
|
||||
* @throws \Exception In case share could not get properly resolved
|
||||
*/
|
||||
private function getPath($token) {
|
||||
$linkItem = Share::getShareByToken($token, false);
|
||||
$path = null;
|
||||
if (is_array($linkItem) && isset($linkItem['uid_owner'])) {
|
||||
// seems to be a valid share
|
||||
$rootLinkItem = Share::resolveReShare($linkItem);
|
||||
if (isset($rootLinkItem['uid_owner'])) {
|
||||
JSON::checkUserExists($rootLinkItem['uid_owner']);
|
||||
if(!$this->userManager->userExists($rootLinkItem['uid_owner'])) {
|
||||
throw new \Exception('Owner of the share does not exist anymore');
|
||||
}
|
||||
OC_Util::tearDownFS();
|
||||
OC_Util::setupFS($rootLinkItem['uid_owner']);
|
||||
$path = Filesystem::getPath($linkItem['file_source']);
|
||||
|
||||
if(!empty($path) && Filesystem::isReadable($path)) {
|
||||
return $path;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $path;
|
||||
|
||||
throw new \Exception('No file found belonging to file.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,8 +257,21 @@ class Helper {
|
||||
*/
|
||||
public static function getShareFolder() {
|
||||
$shareFolder = \OC::$server->getConfig()->getSystemValue('share_folder', '/');
|
||||
$shareFolder = \OC\Files\Filesystem::normalizePath($shareFolder);
|
||||
|
||||
if (!\OC\Files\Filesystem::file_exists($shareFolder)) {
|
||||
$dir = '';
|
||||
$subdirs = explode('/', $shareFolder);
|
||||
foreach ($subdirs as $subdir) {
|
||||
$dir = $dir . '/' . $subdir;
|
||||
if (!\OC\Files\Filesystem::is_dir($dir)) {
|
||||
\OC\Files\Filesystem::mkdir($dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $shareFolder;
|
||||
|
||||
return \OC\Files\Filesystem::normalizePath($shareFolder);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
namespace OCA\Files_Sharing\Middleware;
|
||||
|
||||
use OCP\App\IAppManager;
|
||||
use OCP\AppFramework\Http\NotFoundResponse;
|
||||
use OCP\AppFramework\Middleware;
|
||||
use OCP\AppFramework\Http\TemplateResponse;
|
||||
use OCP\IConfig;
|
||||
@@ -59,7 +60,7 @@ class SharingCheckMiddleware extends Middleware {
|
||||
* @return TemplateResponse
|
||||
*/
|
||||
public function afterException($controller, $methodName, \Exception $exception){
|
||||
return new TemplateResponse('core', '404', array(), 'guest');
|
||||
return new NotFoundResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,8 +35,8 @@ class SharedMount extends MountPoint implements MoveableMount {
|
||||
$mountPoint = basename($share['file_target']);
|
||||
$parent = dirname($share['file_target']);
|
||||
|
||||
while (!\OC\Files\Filesystem::is_dir($parent)) {
|
||||
$parent = dirname($parent);
|
||||
if (!\OC\Files\Filesystem::is_dir($parent)) {
|
||||
$parent = Helper::getShareFolder();
|
||||
}
|
||||
|
||||
$newMountPoint = \OCA\Files_Sharing\Helper::generateUniqueTarget(
|
||||
|
||||
@@ -293,26 +293,34 @@ class Shared extends \OC\Files\Storage\Common implements ISharedStorage {
|
||||
// we need the paths relative to data/user/files
|
||||
$relPath1 = $this->getMountPoint() . '/' . $path1;
|
||||
$relPath2 = $this->getMountPoint() . '/' . $path2;
|
||||
$pathinfo = pathinfo($relPath1);
|
||||
|
||||
// check for update permissions on the share
|
||||
if ($this->isUpdatable('')) {
|
||||
|
||||
$pathinfo = pathinfo($relPath1);
|
||||
// for part files we need to ask for the owner and path from the parent directory because
|
||||
// the file cache doesn't return any results for part files
|
||||
if (isset($pathinfo['extension']) && $pathinfo['extension'] === 'part') {
|
||||
list($user1, $path1) = \OCA\Files_Sharing\Helper::getUidAndFilename($pathinfo['dirname']);
|
||||
$path1 = $path1 . '/' . $pathinfo['basename'];
|
||||
} else {
|
||||
list($user1, $path1) = \OCA\Files_Sharing\Helper::getUidAndFilename($relPath1);
|
||||
$isPartFile = (isset($pathinfo['extension']) && $pathinfo['extension'] === 'part');
|
||||
$targetExists = $this->file_exists($path2);
|
||||
$sameFolder = (dirname($relPath1) === dirname($relPath2));
|
||||
if ($targetExists || ($sameFolder && !$isPartFile)) {
|
||||
// note that renaming a share mount point is always allowed
|
||||
if (!$this->isUpdatable('')) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!$this->isCreatable('')) {
|
||||
return false;
|
||||
}
|
||||
$targetFilename = basename($relPath2);
|
||||
list($user2, $path2) = \OCA\Files_Sharing\Helper::getUidAndFilename(dirname($relPath2));
|
||||
$rootView = new \OC\Files\View('');
|
||||
return $rootView->rename('/' . $user1 . '/files/' . $path1, '/' . $user2 . '/files/' . $path2 . '/' . $targetFilename);
|
||||
}
|
||||
|
||||
return false;
|
||||
// for part files we need to ask for the owner and path from the parent directory because
|
||||
// the file cache doesn't return any results for part files
|
||||
if ($isPartFile) {
|
||||
list($user1, $path1) = \OCA\Files_Sharing\Helper::getUidAndFilename($pathinfo['dirname']);
|
||||
$path1 = $path1 . '/' . $pathinfo['basename'];
|
||||
} else {
|
||||
list($user1, $path1) = \OCA\Files_Sharing\Helper::getUidAndFilename($relPath1);
|
||||
}
|
||||
$targetFilename = basename($relPath2);
|
||||
list($user2, $path2) = \OCA\Files_Sharing\Helper::getUidAndFilename(dirname($relPath2));
|
||||
$rootView = new \OC\Files\View('');
|
||||
return $rootView->rename('/' . $user1 . '/files/' . $path1, '/' . $user2 . '/files/' . $path2 . '/' . $targetFilename);
|
||||
}
|
||||
|
||||
public function copy($path1, $path2) {
|
||||
@@ -343,13 +351,25 @@ class Shared extends \OC\Files\Storage\Common implements ISharedStorage {
|
||||
case 'xb':
|
||||
case 'a':
|
||||
case 'ab':
|
||||
$exists = $this->file_exists($path);
|
||||
if ($exists && !$this->isUpdatable($path)) {
|
||||
$creatable = $this->isCreatable($path);
|
||||
$updatable = $this->isUpdatable($path);
|
||||
// if neither permissions given, no need to continue
|
||||
if (!$creatable && !$updatable) {
|
||||
return false;
|
||||
}
|
||||
if (!$exists && !$this->isCreatable(dirname($path))) {
|
||||
|
||||
$exists = $this->file_exists($path);
|
||||
// if a file exists, updatable permissions are required
|
||||
if ($exists && !$updatable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// part file is allowed if !$creatable but the final file is $updatable
|
||||
if (pathinfo($path, PATHINFO_EXTENSION) !== 'part') {
|
||||
if (!$exists && !$creatable) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
$info = array(
|
||||
'target' => $this->getMountPoint() . $path,
|
||||
|
||||
@@ -1008,6 +1008,24 @@ class Test_Files_Sharing_Api extends TestCase {
|
||||
$this->assertTrue(is_array($updatedLinkShare));
|
||||
$this->assertEquals($dateWithinRange->format('Y-m-d') . ' 00:00:00', $updatedLinkShare['expiration']);
|
||||
|
||||
|
||||
// Try to remove expire date
|
||||
$params = array();
|
||||
$params['id'] = $linkShare['id'];
|
||||
$params['_put'] = ['expireDate' => ''];
|
||||
|
||||
$result = \OCA\Files_Sharing\API\Local::updateShare($params);
|
||||
|
||||
$this->assertFalse($result->succeeded());
|
||||
|
||||
$items = \OCP\Share::getItemShared('file', $linkShare['file_source']);
|
||||
|
||||
$updatedLinkShare = reset($items);
|
||||
|
||||
// date shouldn't be changed
|
||||
$this->assertTrue(is_array($updatedLinkShare));
|
||||
$this->assertEquals($dateWithinRange->format('Y-m-d') . ' 00:00:00', $updatedLinkShare['expiration']);
|
||||
|
||||
// cleanup
|
||||
$config->setAppValue('core', 'shareapi_default_expire_date', 'no');
|
||||
$config->setAppValue('core', 'shareapi_enforce_expire_date', 'no');
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace OCA\Files_Sharing\Controllers;
|
||||
|
||||
use OC\Files\Filesystem;
|
||||
use OCA\Files_Sharing\Application;
|
||||
use OCP\AppFramework\Http\NotFoundResponse;
|
||||
use OCP\AppFramework\IAppContainer;
|
||||
use OCP\Files;
|
||||
use OCP\AppFramework\Http\RedirectResponse;
|
||||
@@ -49,6 +50,8 @@ class ShareControllerTest extends \PHPUnit_Framework_TestCase {
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$this->container['URLGenerator'] = $this->getMockBuilder('\OC\URLGenerator')
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$this->container['UserManager'] = $this->getMockBuilder('\OCP\IUserManager')
|
||||
->disableOriginalConstructor()->getMock();
|
||||
$this->urlGenerator = $this->container['URLGenerator'];
|
||||
$this->shareController = $this->container['ShareController'];
|
||||
|
||||
@@ -115,7 +118,7 @@ class ShareControllerTest extends \PHPUnit_Framework_TestCase {
|
||||
public function testAuthenticate() {
|
||||
// Test without a not existing token
|
||||
$response = $this->shareController->authenticate('ThisTokenShouldHopefullyNeverExistSoThatTheUnitTestWillAlwaysPass :)');
|
||||
$expectedResponse = new TemplateResponse('core', '404', array(), 'guest');
|
||||
$expectedResponse = new NotFoundResponse();
|
||||
$this->assertEquals($expectedResponse, $response);
|
||||
|
||||
// Test with a valid password
|
||||
@@ -130,9 +133,14 @@ class ShareControllerTest extends \PHPUnit_Framework_TestCase {
|
||||
}
|
||||
|
||||
public function testShowShare() {
|
||||
$this->container['UserManager']->expects($this->exactly(2))
|
||||
->method('userExists')
|
||||
->with($this->user)
|
||||
->will($this->returnValue(true));
|
||||
|
||||
// Test without a not existing token
|
||||
$response = $this->shareController->showShare('ThisTokenShouldHopefullyNeverExistSoThatTheUnitTestWillAlwaysPass :)');
|
||||
$expectedResponse = new TemplateResponse('core', '404', array(), 'guest');
|
||||
$expectedResponse = new NotFoundResponse();
|
||||
$this->assertEquals($expectedResponse, $response);
|
||||
|
||||
// Test with a password protected share and no authentication
|
||||
@@ -170,4 +178,54 @@ class ShareControllerTest extends \PHPUnit_Framework_TestCase {
|
||||
array('token' => $this->token)));
|
||||
$this->assertEquals($expectedResponse, $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Exception
|
||||
* @expectedExceptionMessage No file found belonging to file.
|
||||
*/
|
||||
public function testShowShareWithDeletedFile() {
|
||||
$this->container['UserManager']->expects($this->once())
|
||||
->method('userExists')
|
||||
->with($this->user)
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$view = new View('/'. $this->user . '/files');
|
||||
$view->unlink('file1.txt');
|
||||
$linkItem = Share::getShareByToken($this->token, false);
|
||||
\OC::$server->getSession()->set('public_link_authenticated', $linkItem['id']);
|
||||
$this->shareController->showShare($this->token);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Exception
|
||||
* @expectedExceptionMessage No file found belonging to file.
|
||||
*/
|
||||
public function testDownloadShareWithDeletedFile() {
|
||||
$this->container['UserManager']->expects($this->once())
|
||||
->method('userExists')
|
||||
->with($this->user)
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$view = new View('/'. $this->user . '/files');
|
||||
$view->unlink('file1.txt');
|
||||
$linkItem = Share::getShareByToken($this->token, false);
|
||||
\OC::$server->getSession()->set('public_link_authenticated', $linkItem['id']);
|
||||
$this->shareController->downloadShare($this->token);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Exception
|
||||
* @expectedExceptionMessage Owner of the share does not exist anymore
|
||||
*/
|
||||
public function testShowShareWithNotExistingUser() {
|
||||
$this->container['UserManager']->expects($this->once())
|
||||
->method('userExists')
|
||||
->with($this->user)
|
||||
->will($this->returnValue(false));
|
||||
|
||||
$linkItem = Share::getShareByToken($this->token, false);
|
||||
\OC::$server->getSession()->set('public_link_authenticated', $linkItem['id']);
|
||||
$this->shareController->showShare($this->token);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,9 +30,11 @@ class Test_Files_Sharing_Helper extends TestCase {
|
||||
function testSetGetShareFolder() {
|
||||
$this->assertSame('/', \OCA\Files_Sharing\Helper::getShareFolder());
|
||||
|
||||
\OCA\Files_Sharing\Helper::setShareFolder('/Shared');
|
||||
\OCA\Files_Sharing\Helper::setShareFolder('/Shared/Folder');
|
||||
|
||||
$this->assertSame('/Shared', \OCA\Files_Sharing\Helper::getShareFolder());
|
||||
$sharedFolder = \OCA\Files_Sharing\Helper::getShareFolder();
|
||||
$this->assertSame('/Shared/Folder', \OCA\Files_Sharing\Helper::getShareFolder());
|
||||
$this->assertTrue(\OC\Files\Filesystem::is_dir($sharedFolder));
|
||||
|
||||
// cleanup
|
||||
\OC::$server->getConfig()->deleteSystemValue('share_folder');
|
||||
|
||||
90
apps/files_sharing/tests/propagation.php
Normal file
90
apps/files_sharing/tests/propagation.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Robin Appelman
|
||||
* @copyright 2015 Robin Appelman <icewind@owncloud.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA\Files_sharing\Tests;
|
||||
|
||||
use OC\Files\View;
|
||||
|
||||
class Propagation extends TestCase {
|
||||
|
||||
public function testSizePropagationWhenOwnerChangesFile() {
|
||||
$this->loginAsUser(self::TEST_FILES_SHARING_API_USER1);
|
||||
$recipientView = new View('/' . self::TEST_FILES_SHARING_API_USER1 . '/files');
|
||||
|
||||
$this->loginAsUser(self::TEST_FILES_SHARING_API_USER2);
|
||||
$ownerView = new View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files');
|
||||
$ownerView->mkdir('/sharedfolder/subfolder');
|
||||
$ownerView->file_put_contents('/sharedfolder/subfolder/foo.txt', 'bar');
|
||||
|
||||
$sharedFolderInfo = $ownerView->getFileInfo('/sharedfolder', false);
|
||||
\OCP\Share::shareItem('folder', $sharedFolderInfo->getId(), \OCP\Share::SHARE_TYPE_USER, self::TEST_FILES_SHARING_API_USER1, 31);
|
||||
$ownerRootInfo = $ownerView->getFileInfo('', false);
|
||||
|
||||
$this->loginAsUser(self::TEST_FILES_SHARING_API_USER1);
|
||||
$this->assertTrue($recipientView->file_exists('/sharedfolder/subfolder/foo.txt'));
|
||||
$recipientRootInfo = $recipientView->getFileInfo('', false);
|
||||
|
||||
// when file changed as owner
|
||||
$this->loginAsUser(self::TEST_FILES_SHARING_API_USER2);
|
||||
$ownerView->file_put_contents('/sharedfolder/subfolder/foo.txt', 'foobar');
|
||||
|
||||
// size of recipient's root stays the same
|
||||
$this->loginAsUser(self::TEST_FILES_SHARING_API_USER1);
|
||||
$newRecipientRootInfo = $recipientView->getFileInfo('', false);
|
||||
$this->assertEquals($recipientRootInfo->getSize(), $newRecipientRootInfo->getSize());
|
||||
|
||||
// size of owner's root increases
|
||||
$this->loginAsUser(self::TEST_FILES_SHARING_API_USER2);
|
||||
$newOwnerRootInfo = $ownerView->getFileInfo('', false);
|
||||
$this->assertEquals($ownerRootInfo->getSize() + 3, $newOwnerRootInfo->getSize());
|
||||
}
|
||||
|
||||
public function testSizePropagationWhenRecipientChangesFile() {
|
||||
$this->loginAsUser(self::TEST_FILES_SHARING_API_USER1);
|
||||
$recipientView = new View('/' . self::TEST_FILES_SHARING_API_USER1 . '/files');
|
||||
|
||||
$this->loginAsUser(self::TEST_FILES_SHARING_API_USER2);
|
||||
$ownerView = new View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files');
|
||||
$ownerView->mkdir('/sharedfolder/subfolder');
|
||||
$ownerView->file_put_contents('/sharedfolder/subfolder/foo.txt', 'bar');
|
||||
|
||||
$sharedFolderInfo = $ownerView->getFileInfo('/sharedfolder', false);
|
||||
\OCP\Share::shareItem('folder', $sharedFolderInfo->getId(), \OCP\Share::SHARE_TYPE_USER, self::TEST_FILES_SHARING_API_USER1, 31);
|
||||
$ownerRootInfo = $ownerView->getFileInfo('', false);
|
||||
|
||||
$this->loginAsUser(self::TEST_FILES_SHARING_API_USER1);
|
||||
$this->assertTrue($recipientView->file_exists('/sharedfolder/subfolder/foo.txt'));
|
||||
$recipientRootInfo = $recipientView->getFileInfo('', false);
|
||||
|
||||
// when file changed as recipient
|
||||
$recipientView->file_put_contents('/sharedfolder/subfolder/foo.txt', 'foobar');
|
||||
|
||||
// size of recipient's root stays the same
|
||||
$newRecipientRootInfo = $recipientView->getFileInfo('', false);
|
||||
$this->assertEquals($recipientRootInfo->getSize(), $newRecipientRootInfo->getSize());
|
||||
|
||||
// size of owner's root increases
|
||||
$this->loginAsUser(self::TEST_FILES_SHARING_API_USER2);
|
||||
$newOwnerRootInfo = $ownerView->getFileInfo('', false);
|
||||
$this->assertEquals($ownerRootInfo->getSize() + 3, $newOwnerRootInfo->getSize());
|
||||
}
|
||||
}
|
||||
@@ -199,6 +199,158 @@ class Test_Files_Sharing_Storage extends OCA\Files_sharing\Tests\TestCase {
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
public function testFopenWithReadOnlyPermission() {
|
||||
$this->view->file_put_contents($this->folder . '/existing.txt', 'foo');
|
||||
$fileinfoFolder = $this->view->getFileInfo($this->folder);
|
||||
$result = \OCP\Share::shareItem('folder', $fileinfoFolder['fileid'], \OCP\Share::SHARE_TYPE_USER,
|
||||
self::TEST_FILES_SHARING_API_USER2, \OCP\Constants::PERMISSION_READ);
|
||||
$this->assertTrue($result);
|
||||
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
|
||||
$user2View = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files');
|
||||
|
||||
// part file should be forbidden
|
||||
$handle = $user2View->fopen($this->folder . '/test.txt.part', 'w');
|
||||
$this->assertFalse($handle);
|
||||
|
||||
// regular file forbidden
|
||||
$handle = $user2View->fopen($this->folder . '/test.txt', 'w');
|
||||
$this->assertFalse($handle);
|
||||
|
||||
// rename forbidden
|
||||
$this->assertFalse($user2View->rename($this->folder . '/existing.txt', $this->folder . '/existing2.txt'));
|
||||
|
||||
// delete forbidden
|
||||
$this->assertFalse($user2View->unlink($this->folder . '/existing.txt'));
|
||||
|
||||
//cleanup
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
|
||||
$result = \OCP\Share::unshare('folder', $fileinfoFolder['fileid'], \OCP\Share::SHARE_TYPE_USER,
|
||||
self::TEST_FILES_SHARING_API_USER2);
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
public function testFopenWithCreateOnlyPermission() {
|
||||
$this->view->file_put_contents($this->folder . '/existing.txt', 'foo');
|
||||
$fileinfoFolder = $this->view->getFileInfo($this->folder);
|
||||
$result = \OCP\Share::shareItem('folder', $fileinfoFolder['fileid'], \OCP\Share::SHARE_TYPE_USER,
|
||||
self::TEST_FILES_SHARING_API_USER2, \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE);
|
||||
$this->assertTrue($result);
|
||||
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
|
||||
$user2View = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files');
|
||||
|
||||
// create part file allowed
|
||||
$handle = $user2View->fopen($this->folder . '/test.txt.part', 'w');
|
||||
$this->assertNotFalse($handle);
|
||||
fclose($handle);
|
||||
|
||||
// create regular file allowed
|
||||
$handle = $user2View->fopen($this->folder . '/test-create.txt', 'w');
|
||||
$this->assertNotFalse($handle);
|
||||
fclose($handle);
|
||||
|
||||
// rename file never allowed
|
||||
$this->assertFalse($user2View->rename($this->folder . '/test-create.txt', $this->folder . '/newtarget.txt'));
|
||||
$this->assertFalse($user2View->file_exists($this->folder . '/newtarget.txt'));
|
||||
|
||||
// rename file not allowed if target exists
|
||||
$this->assertFalse($user2View->rename($this->folder . '/newtarget.txt', $this->folder . '/existing.txt'));
|
||||
|
||||
// overwriting file not allowed
|
||||
$handle = $user2View->fopen($this->folder . '/existing.txt', 'w');
|
||||
$this->assertFalse($handle);
|
||||
|
||||
// overwrite forbidden (no update permission)
|
||||
$this->assertFalse($user2View->rename($this->folder . '/test.txt.part', $this->folder . '/existing.txt'));
|
||||
|
||||
// delete forbidden
|
||||
$this->assertFalse($user2View->unlink($this->folder . '/existing.txt'));
|
||||
|
||||
//cleanup
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
|
||||
$result = \OCP\Share::unshare('folder', $fileinfoFolder['fileid'], \OCP\Share::SHARE_TYPE_USER,
|
||||
self::TEST_FILES_SHARING_API_USER2);
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
public function testFopenWithUpdateOnlyPermission() {
|
||||
$this->view->file_put_contents($this->folder . '/existing.txt', 'foo');
|
||||
$fileinfoFolder = $this->view->getFileInfo($this->folder);
|
||||
|
||||
$result = \OCP\Share::shareItem('folder', $fileinfoFolder['fileid'], \OCP\Share::SHARE_TYPE_USER,
|
||||
self::TEST_FILES_SHARING_API_USER2, \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_UPDATE);
|
||||
$this->assertTrue($result);
|
||||
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
|
||||
$user2View = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files');
|
||||
|
||||
// create part file allowed
|
||||
$handle = $user2View->fopen($this->folder . '/test.txt.part', 'w');
|
||||
$this->assertNotFalse($handle);
|
||||
fclose($handle);
|
||||
|
||||
// create regular file not allowed
|
||||
$handle = $user2View->fopen($this->folder . '/test-create.txt', 'w');
|
||||
$this->assertFalse($handle);
|
||||
|
||||
// rename part file not allowed to non-existing file
|
||||
$this->assertFalse($user2View->rename($this->folder . '/test.txt.part', $this->folder . '/nonexist.txt'));
|
||||
|
||||
// rename part file allowed to target existing file
|
||||
$this->assertTrue($user2View->rename($this->folder . '/test.txt.part', $this->folder . '/existing.txt'));
|
||||
$this->assertTrue($user2View->file_exists($this->folder . '/existing.txt'));
|
||||
|
||||
// rename regular file allowed
|
||||
$this->assertTrue($user2View->rename($this->folder . '/existing.txt', $this->folder . '/existing-renamed.txt'));
|
||||
$this->assertTrue($user2View->file_exists($this->folder . '/existing-renamed.txt'));
|
||||
|
||||
// overwriting file directly is allowed
|
||||
$handle = $user2View->fopen($this->folder . '/existing-renamed.txt', 'w');
|
||||
$this->assertNotFalse($handle);
|
||||
fclose($handle);
|
||||
|
||||
// delete forbidden
|
||||
$this->assertFalse($user2View->unlink($this->folder . '/existing-renamed.txt'));
|
||||
|
||||
//cleanup
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
|
||||
$result = \OCP\Share::unshare('folder', $fileinfoFolder['fileid'], \OCP\Share::SHARE_TYPE_USER,
|
||||
self::TEST_FILES_SHARING_API_USER2);
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
public function testFopenWithDeleteOnlyPermission() {
|
||||
$this->view->file_put_contents($this->folder . '/existing.txt', 'foo');
|
||||
$fileinfoFolder = $this->view->getFileInfo($this->folder);
|
||||
$result = \OCP\Share::shareItem('folder', $fileinfoFolder['fileid'], \OCP\Share::SHARE_TYPE_USER,
|
||||
self::TEST_FILES_SHARING_API_USER2, \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_DELETE);
|
||||
$this->assertTrue($result);
|
||||
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER2);
|
||||
$user2View = new \OC\Files\View('/' . self::TEST_FILES_SHARING_API_USER2 . '/files');
|
||||
|
||||
// part file should be forbidden
|
||||
$handle = $user2View->fopen($this->folder . '/test.txt.part', 'w');
|
||||
$this->assertFalse($handle);
|
||||
|
||||
// regular file forbidden
|
||||
$handle = $user2View->fopen($this->folder . '/test.txt', 'w');
|
||||
$this->assertFalse($handle);
|
||||
|
||||
// rename forbidden
|
||||
$this->assertFalse($user2View->rename($this->folder . '/existing.txt', $this->folder . '/existing2.txt'));
|
||||
|
||||
// delete allowed
|
||||
$this->assertTrue($user2View->unlink($this->folder . '/existing.txt'));
|
||||
|
||||
//cleanup
|
||||
self::loginHelper(self::TEST_FILES_SHARING_API_USER1);
|
||||
$result = \OCP\Share::unshare('folder', $fileinfoFolder['fileid'], \OCP\Share::SHARE_TYPE_USER,
|
||||
self::TEST_FILES_SHARING_API_USER2);
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
function testMountSharesOtherUser() {
|
||||
$folderInfo = $this->view->getFileInfo($this->folder);
|
||||
$fileInfo = $this->view->getFileInfo($this->filename);
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
<?php
|
||||
$TRANSLATIONS = array(
|
||||
"_%n folder_::_%n folders_" => array("",""),
|
||||
"_%n file_::_%n files_" => array("","")
|
||||
);
|
||||
$PLURAL_FORMS = "nplurals=2; plural=(n > 1);";
|
||||
@@ -1,6 +0,0 @@
|
||||
<?php
|
||||
$TRANSLATIONS = array(
|
||||
"_%n folder_::_%n folders_" => array("",""),
|
||||
"_%n file_::_%n files_" => array("","")
|
||||
);
|
||||
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
|
||||
@@ -1,6 +0,0 @@
|
||||
<?php
|
||||
$TRANSLATIONS = array(
|
||||
"_%n folder_::_%n folders_" => array("",""),
|
||||
"_%n file_::_%n files_" => array("","")
|
||||
);
|
||||
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
|
||||
@@ -1,6 +0,0 @@
|
||||
<?php
|
||||
$TRANSLATIONS = array(
|
||||
"_%n folder_::_%n folders_" => array("",""),
|
||||
"_%n file_::_%n files_" => array("","")
|
||||
);
|
||||
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
|
||||
@@ -1,6 +0,0 @@
|
||||
<?php
|
||||
$TRANSLATIONS = array(
|
||||
"_%n folder_::_%n folders_" => array(""),
|
||||
"_%n file_::_%n files_" => array("")
|
||||
);
|
||||
$PLURAL_FORMS = "nplurals=1; plural=0;";
|
||||
@@ -1,6 +0,0 @@
|
||||
<?php
|
||||
$TRANSLATIONS = array(
|
||||
"_%n folder_::_%n folders_" => array("",""),
|
||||
"_%n file_::_%n files_" => array("","")
|
||||
);
|
||||
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
|
||||
@@ -1,6 +0,0 @@
|
||||
<?php
|
||||
$TRANSLATIONS = array(
|
||||
"_%n folder_::_%n folders_" => array(""),
|
||||
"_%n file_::_%n files_" => array("")
|
||||
);
|
||||
$PLURAL_FORMS = "nplurals=1; plural=0;";
|
||||
@@ -1,6 +0,0 @@
|
||||
<?php
|
||||
$TRANSLATIONS = array(
|
||||
"_%n folder_::_%n folders_" => array("",""),
|
||||
"_%n file_::_%n files_" => array("","")
|
||||
);
|
||||
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
|
||||
@@ -1,6 +0,0 @@
|
||||
<?php
|
||||
$TRANSLATIONS = array(
|
||||
"_%n folder_::_%n folders_" => array(""),
|
||||
"_%n file_::_%n files_" => array("")
|
||||
);
|
||||
$PLURAL_FORMS = "nplurals=1; plural=0;";
|
||||
@@ -1,6 +0,0 @@
|
||||
<?php
|
||||
$TRANSLATIONS = array(
|
||||
"_%n folder_::_%n folders_" => array("",""),
|
||||
"_%n file_::_%n files_" => array("","")
|
||||
);
|
||||
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
|
||||
@@ -61,6 +61,22 @@ class Storage extends Wrapper {
|
||||
self::$disableTrash = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename path1 to path2 by calling the wrapped storage.
|
||||
*
|
||||
* @param string $path1 first path
|
||||
* @param string $path2 second path
|
||||
*/
|
||||
public function rename($path1, $path2) {
|
||||
$result = $this->storage->rename($path1, $path2);
|
||||
if ($result === false) {
|
||||
// when rename failed, the post_rename hook isn't triggered,
|
||||
// but we still want to reenable the trash logic
|
||||
self::$disableTrash = false;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the given file by moving it into the trashbin.
|
||||
*
|
||||
|
||||
@@ -32,6 +32,13 @@ class Trashbin {
|
||||
// unit: percentage; 50% of available disk space/quota
|
||||
const DEFAULTMAXSIZE = 50;
|
||||
|
||||
/**
|
||||
* Whether versions have already be rescanned during this PHP request
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private static $scannedVersions = false;
|
||||
|
||||
public static function getUidAndFilename($filename) {
|
||||
$uid = \OC\Files\Filesystem::getOwner($filename);
|
||||
\OC\Files\Filesystem::initMountPoints($uid);
|
||||
@@ -825,9 +832,12 @@ class Trashbin {
|
||||
$versions = array();
|
||||
|
||||
//force rescan of versions, local storage may not have updated the cache
|
||||
/** @var \OC\Files\Storage\Storage $storage */
|
||||
list($storage, ) = $view->resolvePath('/');
|
||||
$storage->getScanner()->scan('files_trashbin');
|
||||
if (!self::$scannedVersions) {
|
||||
/** @var \OC\Files\Storage\Storage $storage */
|
||||
list($storage, ) = $view->resolvePath('/');
|
||||
$storage->getScanner()->scan('files_trashbin/versions');
|
||||
self::$scannedVersions = true;
|
||||
}
|
||||
|
||||
if ($timestamp) {
|
||||
// fetch for old versions
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
<?php $TRANSLATIONS = array(
|
||||
"History" => "Historique",
|
||||
"Files Versioning" => "Fichier's Versionéierung ",
|
||||
"Enable" => "Aschalten"
|
||||
);
|
||||
@@ -85,7 +85,7 @@ switch($action) {
|
||||
exit;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
\OCP\JSON::error(array('message' => $e->getMessage()));
|
||||
\OCP\JSON::error(array('message' => $e->getMessage(), 'code' => $e->getCode()));
|
||||
exit;
|
||||
}
|
||||
\OCP\JSON::error();
|
||||
|
||||
@@ -630,7 +630,7 @@ class GROUP_LDAP extends BackendUtility implements \OCP\GroupInterface {
|
||||
}
|
||||
$maxGroups = 100000; // limit max results (just for safety reasons)
|
||||
if ($limit > -1) {
|
||||
$overallLimit = min($limit, $maxGroups);
|
||||
$overallLimit = min($limit + $offset, $maxGroups);
|
||||
} else {
|
||||
$overallLimit = $maxGroups;
|
||||
}
|
||||
|
||||
@@ -351,7 +351,7 @@ var LdapWizard = {
|
||||
encodeURIComponent($('#ldap_serverconfig_chooser').val());
|
||||
|
||||
LdapWizard.showSpinner(spinnerID);
|
||||
var request = LdapWizard.ajax(param,
|
||||
LdapWizard.ajax(param,
|
||||
function(result) {
|
||||
LdapWizard.applyChanges(result);
|
||||
LdapWizard.hideSpinner(spinnerID);
|
||||
@@ -360,7 +360,7 @@ var LdapWizard = {
|
||||
}
|
||||
},
|
||||
function (result) {
|
||||
OC.Notification.show('Counting the entries failed with, ' + result.message);
|
||||
OC.Notification.showTemporary('Counting the entries failed with: ' + result.message);
|
||||
LdapWizard.hideSpinner(spinnerID);
|
||||
if(!_.isUndefined(doneCallback)) {
|
||||
doneCallback(method);
|
||||
@@ -371,11 +371,17 @@ var LdapWizard = {
|
||||
},
|
||||
|
||||
countGroups: function(doneCallback) {
|
||||
LdapWizard._countThings('countGroups', '#ldap_group_count', doneCallback);
|
||||
var groupFilter = $('#ldap_group_filter').val();
|
||||
if(!_.isEmpty(groupFilter)) {
|
||||
LdapWizard._countThings('countGroups', '#ldap_group_count', doneCallback);
|
||||
}
|
||||
},
|
||||
|
||||
countUsers: function(doneCallback) {
|
||||
LdapWizard._countThings('countUsers', '#ldap_user_count', doneCallback);
|
||||
var userFilter = $('#ldap_userlist_filter').val();
|
||||
if(!_.isEmpty(userFilter)) {
|
||||
LdapWizard._countThings('countUsers', '#ldap_user_count', doneCallback);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
<?php
|
||||
$TRANSLATIONS = array(
|
||||
"_%s group found_::_%s groups found_" => array("",""),
|
||||
"_%s user found_::_%s users found_" => array("","")
|
||||
);
|
||||
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
|
||||
@@ -1372,7 +1372,8 @@ class Access extends LDAPUtility implements user\IUserTools {
|
||||
* @return void
|
||||
*/
|
||||
private function setPagedResultCookie($base, $filter, $limit, $offset, $cookie) {
|
||||
if(!empty($cookie)) {
|
||||
// allow '0' for 389ds
|
||||
if(!empty($cookie) || $cookie === '0') {
|
||||
$cacheKey = 'lc' . crc32($base) . '-' . crc32($filter) . '-' .intval($limit) . '-' . intval($offset);
|
||||
$this->cookies[$cacheKey] = $cookie;
|
||||
$this->lastCookie = $cookie;
|
||||
@@ -1410,11 +1411,12 @@ class Access extends LDAPUtility implements user\IUserTools {
|
||||
foreach($bases as $base) {
|
||||
|
||||
$cookie = $this->getPagedResultCookie($base, $filter, $limit, $offset);
|
||||
if(empty($cookie) && ($offset > 0)) {
|
||||
if(empty($cookie) && $cookie !== "0" && ($offset > 0)) {
|
||||
// no cookie known, although the offset is not 0. Maybe cache run out. We need
|
||||
// to start all over *sigh* (btw, Dear Reader, did you know LDAP paged
|
||||
// searching was designed by MSFT?)
|
||||
// Lukas: No, but thanks to reading that source I finally know!
|
||||
// '0' is valid, because 389ds
|
||||
$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);
|
||||
@@ -1422,7 +1424,8 @@ class Access extends LDAPUtility implements user\IUserTools {
|
||||
$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...
|
||||
if(empty($cookie)) {
|
||||
if(empty($cookie) && $cookie !== '0') {
|
||||
// '0' is valid, because 389ds
|
||||
$cookie = null;
|
||||
}
|
||||
}
|
||||
@@ -1443,6 +1446,17 @@ class Access extends LDAPUtility implements user\IUserTools {
|
||||
}
|
||||
|
||||
}
|
||||
} else if($this->connection->hasPagedResultSupport && $limit === 0) {
|
||||
// a search without limit was requested. However, if we do use
|
||||
// Paged Search once, we always must do it. This requires us to
|
||||
// initialize it with the configured page size.
|
||||
$this->abandonPagedSearch();
|
||||
// in case someone set it to 0 … use 500, otherwise no results will
|
||||
// be returned.
|
||||
$pageSize = intval($this->connection->ldapPagingSize) > 0 ? intval($this->connection->ldapPagingSize) : 500;
|
||||
$pagedSearchOK = $this->ldap->controlPagedResult(
|
||||
$this->connection->getConnectionResource(), $pageSize, false, ''
|
||||
);
|
||||
}
|
||||
|
||||
return $pagedSearchOK;
|
||||
|
||||
@@ -293,4 +293,18 @@ class Test_Group_Ldap extends \Test\TestCase {
|
||||
$groupBackend->inGroup($uid, $gid);
|
||||
}
|
||||
|
||||
public function testGetGroupsWithOffset() {
|
||||
$access = $this->getAccessMock();
|
||||
$this->enableGroups($access);
|
||||
|
||||
$access->expects($this->once())
|
||||
->method('ownCloudGroupNames')
|
||||
->will($this->returnValue(array('group1', 'group2')));
|
||||
|
||||
$groupBackend = new GroupLDAP($access);
|
||||
$groups = $groupBackend->getGroups('', 2, 2);
|
||||
|
||||
$this->assertSame(2, count($groups));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -229,9 +229,9 @@ $CONFIG = array(
|
||||
'skeletondirectory' => '',
|
||||
|
||||
/**
|
||||
* The ``user_backends`` app allows you to configure alternate authentication
|
||||
* backends. Supported backends are IMAP (OC_User_IMAP), SMB (OC_User_SMB), and
|
||||
* FTP (OC_User_FTP).
|
||||
* The ``user_backends`` app (which needs to be enabled first) allows you to
|
||||
* configure alternate authentication backends. Supported backends are:
|
||||
* IMAP (OC_User_IMAP), SMB (OC_User_SMB), and FTP (OC_User_FTP).
|
||||
*/
|
||||
'user_backends' => array(
|
||||
array(
|
||||
@@ -420,8 +420,9 @@ $CONFIG = array(
|
||||
*/
|
||||
|
||||
/**
|
||||
* Check 3rd party apps to make sure they are using the private API and not the
|
||||
* public API. If the app uses the private API it cannot be installed.
|
||||
* Checks an app before install whether it uses private APIs instead of the
|
||||
* proper public APIs. If this is set to true it will only allow to install or
|
||||
* enable apps that pass this check.
|
||||
*/
|
||||
'appcodechecker' => true,
|
||||
|
||||
@@ -669,6 +670,10 @@ $CONFIG = array(
|
||||
* - OC\Preview\StarOffice
|
||||
* - OC\Preview\SVG
|
||||
* - OC\Preview\TIFF
|
||||
*
|
||||
* .. note:: Troubleshooting steps for the MS Word previews are available
|
||||
* at the :doc:`../configuration_files/collaborative_documents_configuration`
|
||||
* section of the Administrators Manual.
|
||||
*
|
||||
* The following providers are not available in Microsoft Windows:
|
||||
*
|
||||
|
||||
@@ -11,6 +11,9 @@ use Symfony\Component\Console\Application;
|
||||
try {
|
||||
require_once 'lib/base.php';
|
||||
|
||||
// set to run indefinitely if needed
|
||||
set_time_limit(0);
|
||||
|
||||
// Don't do anything if ownCloud has not been installed yet
|
||||
if (!\OC::$server->getConfig()->getSystemValue('installed', false)) {
|
||||
echo "Console can only be used once ownCloud has been installed" . PHP_EOL;
|
||||
|
||||
@@ -105,7 +105,7 @@ if (isset($_POST['action']) && isset($_POST['itemType']) && isset($_POST['itemSo
|
||||
// don't send a mail to the user who shared the file
|
||||
$recipientList = array_diff($recipientList, array(\OCP\User::getUser()));
|
||||
|
||||
$mailNotification = new OC\Share\MailNotifications();
|
||||
$mailNotification = new OC\Share\MailNotifications(\OCP\User::getUser());
|
||||
$result = $mailNotification->sendInternalShareMail($recipientList, $itemSource, $itemType);
|
||||
|
||||
\OCP\Share::setSendMailStatus($itemType, $itemSource, $shareType, $recipient, true);
|
||||
@@ -137,7 +137,7 @@ if (isset($_POST['action']) && isset($_POST['itemType']) && isset($_POST['itemSo
|
||||
$file = $_POST['file'];
|
||||
$to_address = $_POST['toaddress'];
|
||||
|
||||
$mailNotification = new \OC\Share\MailNotifications();
|
||||
$mailNotification = new \OC\Share\MailNotifications(\OCP\User::getUser());
|
||||
|
||||
$expiration = null;
|
||||
if (isset($_POST['expiration']) && $_POST['expiration'] !== '') {
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
set_time_limit(0);
|
||||
require_once '../../lib/base.php';
|
||||
|
||||
\OCP\JSON::callCheck();
|
||||
|
||||
if (OC::checkUpgrade(false)) {
|
||||
// if a user is currently logged in, their session must be ignored to
|
||||
// avoid side effects
|
||||
@@ -11,9 +13,12 @@ if (OC::checkUpgrade(false)) {
|
||||
$eventSource = \OC::$server->createEventSource();
|
||||
$updater = new \OC\Updater(
|
||||
\OC::$server->getHTTPHelper(),
|
||||
\OC::$server->getAppConfig(),
|
||||
\OC::$server->getConfig(),
|
||||
\OC_Log::$object
|
||||
);
|
||||
$incompatibleApps = [];
|
||||
$disabledThirdPartyApps = [];
|
||||
|
||||
$updater->listen('\OC\Updater', 'maintenanceStart', function () use ($eventSource, $l) {
|
||||
$eventSource->send('success', (string)$l->t('Turned on maintenance mode'));
|
||||
});
|
||||
@@ -32,13 +37,17 @@ if (OC::checkUpgrade(false)) {
|
||||
$updater->listen('\OC\Updater', 'appUpgrade', function ($app, $version) use ($eventSource, $l) {
|
||||
$eventSource->send('success', (string)$l->t('Updated "%s" to %s', array($app, $version)));
|
||||
});
|
||||
$updater->listen('\OC\Updater', 'disabledApps', function ($appList) use ($eventSource, $l) {
|
||||
$list = array();
|
||||
foreach ($appList as $appId) {
|
||||
$info = OC_App::getAppInfo($appId);
|
||||
$list[] = $info['name'] . ' (' . $info['id'] . ')';
|
||||
}
|
||||
$eventSource->send('success', (string)$l->t('Disabled incompatible apps: %s', implode(', ', $list)));
|
||||
$updater->listen('\OC\Updater', 'repairWarning', function ($description) use ($eventSource, $l) {
|
||||
$eventSource->send('notice', (string)$l->t('Repair warning: ') . $description);
|
||||
});
|
||||
$updater->listen('\OC\Updater', 'repairError', function ($description) use ($eventSource, $l) {
|
||||
$eventSource->send('notice', (string)$l->t('Repair error: ') . $description);
|
||||
});
|
||||
$updater->listen('\OC\Updater', 'incompatibleAppDisabled', function ($app) use (&$incompatibleApps) {
|
||||
$incompatibleApps[]= $app;
|
||||
});
|
||||
$updater->listen('\OC\Updater', 'thirdPartyAppDisabled', function ($app) use (&$disabledThirdPartyApps) {
|
||||
$disabledThirdPartyApps[]= $app;
|
||||
});
|
||||
$updater->listen('\OC\Updater', 'failure', function ($message) use ($eventSource) {
|
||||
$eventSource->send('failure', $message);
|
||||
@@ -48,6 +57,15 @@ if (OC::checkUpgrade(false)) {
|
||||
|
||||
$updater->upgrade();
|
||||
|
||||
if (!empty($incompatibleApps)) {
|
||||
$eventSource->send('notice',
|
||||
(string)$l->t('Following incompatible apps have been disabled: %s', implode(', ', $incompatibleApps)));
|
||||
}
|
||||
if (!empty($disabledThirdPartyApps)) {
|
||||
$eventSource->send('notice',
|
||||
(string)$l->t('Following 3rd party apps have been disabled: %s', implode(', ', $disabledThirdPartyApps)));
|
||||
}
|
||||
|
||||
$eventSource->send('done', '');
|
||||
$eventSource->close();
|
||||
}
|
||||
|
||||
@@ -46,6 +46,9 @@ class Repair extends Command {
|
||||
$this->repair->listen('\OC\Repair', 'info', function ($description) use ($output) {
|
||||
$output->writeln(' - ' . $description);
|
||||
});
|
||||
$this->repair->listen('\OC\Repair', 'warning', function ($description) use ($output) {
|
||||
$output->writeln(' - WARNING: ' . $description);
|
||||
});
|
||||
$this->repair->listen('\OC\Repair', 'error', function ($description) use ($output) {
|
||||
$output->writeln(' - ERROR: ' . $description);
|
||||
});
|
||||
|
||||
@@ -84,7 +84,8 @@ class Upgrade extends Command {
|
||||
|
||||
if(\OC::checkUpgrade(false)) {
|
||||
$self = $this;
|
||||
$updater = new Updater(\OC::$server->getHTTPHelper(), \OC::$server->getAppConfig());
|
||||
$updater = new Updater(\OC::$server->getHTTPHelper(),
|
||||
\OC::$server->getConfig());
|
||||
|
||||
$updater->setSimulateStepEnabled($simulateStepEnabled);
|
||||
$updater->setUpdateStepEnabled($updateStepEnabled);
|
||||
@@ -106,8 +107,23 @@ class Upgrade extends Command {
|
||||
$updater->listen('\OC\Updater', 'dbSimulateUpgrade', function () use($output) {
|
||||
$output->writeln('<info>Checked database schema update</info>');
|
||||
});
|
||||
$updater->listen('\OC\Updater', 'disabledApps', function ($appList) use($output) {
|
||||
$output->writeln('<info>Disabled incompatible apps: ' . implode(', ', $appList) . '</info>');
|
||||
$updater->listen('\OC\Updater', 'incompatibleAppDisabled', function ($app) use($output) {
|
||||
$output->writeln('<info>Disabled incompatible app: ' . $app . '</info>');
|
||||
});
|
||||
$updater->listen('\OC\Updater', 'thirdPartyAppDisabled', function ($app) use($output) {
|
||||
$output->writeln('<info>Disabled 3rd-party app: ' . $app . '</info>');
|
||||
});
|
||||
$updater->listen('\OC\Updater', 'repairWarning', function ($app) use($output) {
|
||||
$output->writeln('<error>Repair warning: ' . $app . '</error>');
|
||||
});
|
||||
$updater->listen('\OC\Updater', 'repairError', function ($app) use($output) {
|
||||
$output->writeln('<error>Repair error: ' . $app . '</error>');
|
||||
});
|
||||
$updater->listen('\OC\Updater', 'appUpgradeCheck', function () use ($output) {
|
||||
$output->writeln('<info>Checked database schema update for apps</info>');
|
||||
});
|
||||
$updater->listen('\OC\Updater', 'appUpgrade', function ($app, $version) use ($output) {
|
||||
$output->writeln("<info>Updated <$app> to $version</info>");
|
||||
});
|
||||
|
||||
$updater->listen('\OC\Updater', 'failure', function ($message) use($output, $self) {
|
||||
|
||||
@@ -74,6 +74,7 @@
|
||||
display: block;
|
||||
width: 100%;
|
||||
line-height: 44px;
|
||||
min-height: 44px;
|
||||
padding: 0 12px;
|
||||
overflow: hidden;
|
||||
-moz-box-sizing: border-box; box-sizing: border-box;
|
||||
|
||||
@@ -54,6 +54,11 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* do not show update notification on mobile */
|
||||
#update-notification {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* position share dropdown */
|
||||
#dropdown {
|
||||
margin-right: 10% !important;
|
||||
|
||||
@@ -1213,7 +1213,7 @@ $.fn.filterAttr = function(attr_name, attr_value) {
|
||||
function humanFileSize(size, skipSmallSizes) {
|
||||
var humanList = ['B', 'kB', 'MB', 'GB', 'TB'];
|
||||
// Calculate Log with base 1024: size = 1024 ** order
|
||||
var order = size?Math.floor(Math.log(size) / Math.log(1024)):0;
|
||||
var order = size > 0 ? Math.floor(Math.log(size) / Math.log(1024)) : 0;
|
||||
// Stay in range of the byte sizes that are defined
|
||||
order = Math.min(humanList.length - 1, order);
|
||||
var readableFormat = humanList[order];
|
||||
|
||||
@@ -59,6 +59,11 @@
|
||||
t('core', 'Your data directory and your files are probably accessible from the internet. The .htaccess file is not working. We strongly suggest that you configure your webserver in a way that the data directory is no longer accessible or you move the data directory outside the webserver document root.')
|
||||
);
|
||||
}
|
||||
if(!data.hasCurlInstalled) {
|
||||
messages.push(
|
||||
t('core', 'cURL is not installed, some functionality might not work. Please install the PHP cURL extension. Future versions will require installed cURL.')
|
||||
);
|
||||
}
|
||||
} else {
|
||||
messages.push(t('core', 'Error occurred while checking server setup'));
|
||||
}
|
||||
|
||||
@@ -465,6 +465,8 @@ describe('Core base tests', function() {
|
||||
it('renders file sizes with the correct unit', function() {
|
||||
var data = [
|
||||
[0, '0 B'],
|
||||
["0", '0 B'],
|
||||
["A", 'NaN B'],
|
||||
[125, '125 B'],
|
||||
[128000, '125 kB'],
|
||||
[128000000, '122.1 MB'],
|
||||
|
||||
@@ -38,6 +38,9 @@
|
||||
updateEventSource.listen('success', function(message) {
|
||||
$('<span>').append(message).append('<br />').appendTo($el);
|
||||
});
|
||||
updateEventSource.listen('notice', function(message) {
|
||||
$('<span>').addClass('error').append(message).append('<br />').appendTo($el);
|
||||
});
|
||||
updateEventSource.listen('error', function(message) {
|
||||
$('<span>').addClass('error').append(message).append('<br />').appendTo($el);
|
||||
message = t('core', 'Please reload the page.');
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
$TRANSLATIONS = array(
|
||||
"_%n minute ago_::_%n minutes ago_" => array("",""),
|
||||
"_%n hour ago_::_%n hours ago_" => array("",""),
|
||||
"_%n day ago_::_%n days ago_" => array("",""),
|
||||
"_%n month ago_::_%n months ago_" => array("",""),
|
||||
"_{count} file conflict_::_{count} file conflicts_" => array("","")
|
||||
);
|
||||
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
|
||||
@@ -337,7 +337,7 @@
|
||||
var $row = $(this);
|
||||
var item = $row.data('result');
|
||||
if(self.hasHandler(item.type)){
|
||||
var result = self.getHandler(item.type)($row, result, event);
|
||||
var result = self.getHandler(item.type)($row, item, event);
|
||||
$searchBox.val('');
|
||||
if(self.hasFilter(getCurrentApp())) {
|
||||
self.getFilter(getCurrentApp())('');
|
||||
@@ -360,10 +360,17 @@
|
||||
})();
|
||||
|
||||
$(document).ready(function() {
|
||||
var $searchResults = $('<div id="searchresults" class="hidden"/>');
|
||||
$('#app-content')
|
||||
.append($searchResults)
|
||||
.find('.viewcontainer').css('min-height', 'initial');
|
||||
var $searchResults = $('#searchresults');
|
||||
if ($searchResults.length) {
|
||||
$searchResults.addClass('hidden');
|
||||
$('#app-content')
|
||||
.find('.viewcontainer').css('min-height', 'initial');
|
||||
} else {
|
||||
$searchResults = $('<div id="searchresults" class="hidden"/>');
|
||||
$('#app-content')
|
||||
.append($searchResults)
|
||||
.find('.viewcontainer').css('min-height', 'initial');
|
||||
}
|
||||
$searchResults.load(OC.webroot + '/core/search/templates/part.results.html', function () {
|
||||
OC.Search = new OCA.Search($('#searchbox'), $('#searchresults'));
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<ul>
|
||||
<li class='update'>
|
||||
<?php p($l->t('This %s instance is currently being updated, which may take a while.', array($theme->getName()))) ?><br/><br/>
|
||||
<?php p($l->t('This %s instance is currently in maintenance mode, which may take a while.', array($theme->getName()))) ?><br/><br/>
|
||||
<?php p($l->t('This page will refresh itself when the %s instance is available again.', array($theme->getName()))) ?><br/><br/>
|
||||
<?php p($l->t('Contact your system administrator if this message persists or appeared unexpectedly.')) ?><br/><br/>
|
||||
<?php p($l->t('Thank you for your patience.')); ?><br/><br/>
|
||||
|
||||
6
cron.php
6
cron.php
@@ -50,7 +50,11 @@ try {
|
||||
|
||||
if (\OCP\Util::needUpgrade()) {
|
||||
\OCP\Util::writeLog('cron', 'Update required, skipping cron', \OCP\Util::DEBUG);
|
||||
exit();
|
||||
exit;
|
||||
}
|
||||
if (\OC::$server->getSystemConfig()->getValue('maintenance', false)) {
|
||||
\OCP\Util::writeLog('cron', 'We are in maintenance mode, skipping cron', \OCP\Util::DEBUG);
|
||||
exit;
|
||||
}
|
||||
|
||||
// load all apps to get all api routes properly setup
|
||||
|
||||
29
lib/base.php
29
lib/base.php
@@ -478,7 +478,10 @@ class OC {
|
||||
require_once $vendorAutoLoad;
|
||||
} else {
|
||||
OC_Response::setStatus(OC_Response::STATUS_SERVICE_UNAVAILABLE);
|
||||
OC_Template::printErrorPage('Composer autoloader not found, unable to continue.');
|
||||
// we can't use the template error page here, because this needs the
|
||||
// DI container which isn't available yet
|
||||
print('Composer autoloader not found, unable to continue. Check the folder "3rdparty".');
|
||||
exit();
|
||||
}
|
||||
|
||||
// setup the basic server
|
||||
@@ -550,15 +553,30 @@ class OC {
|
||||
$errors = OC_Util::checkServer(\OC::$server->getConfig());
|
||||
if (count($errors) > 0) {
|
||||
if (self::$CLI) {
|
||||
// Convert l10n string into regular string for usage in database
|
||||
$staticErrors = [];
|
||||
foreach ($errors as $error) {
|
||||
echo $error['error'] . "\n";
|
||||
echo $error['hint'] . "\n\n";
|
||||
$staticErrors[] = [
|
||||
'error' => (string) $error['error'],
|
||||
'hint' => (string) $error['hint'],
|
||||
];
|
||||
}
|
||||
|
||||
try {
|
||||
\OC::$server->getConfig()->setAppValue('core', 'cronErrors', json_encode($staticErrors));
|
||||
} catch(\Exception $e) {
|
||||
echo('Writing to database failed');
|
||||
}
|
||||
exit();
|
||||
} else {
|
||||
OC_Response::setStatus(OC_Response::STATUS_SERVICE_UNAVAILABLE);
|
||||
OC_Template::printGuestPage('', 'error', array('errors' => $errors));
|
||||
exit;
|
||||
}
|
||||
exit;
|
||||
} elseif(self::$CLI && \OC::$server->getConfig()->getSystemValue('installed', false)) {
|
||||
\OC::$server->getConfig()->deleteAppValue('core', 'cronErrors');
|
||||
}
|
||||
|
||||
//try to set the session lifetime
|
||||
@@ -736,6 +754,9 @@ class OC {
|
||||
self::checkUpgrade();
|
||||
}
|
||||
|
||||
// Always load authentication apps
|
||||
OC_App::loadApps(['authentication']);
|
||||
|
||||
// Load minimum set of apps
|
||||
if (!self::checkUpgrade(false)
|
||||
&& !$systemConfig->getValue('maintenance', false)
|
||||
@@ -744,8 +765,7 @@ class OC {
|
||||
if(OC_User::isLoggedIn()) {
|
||||
OC_App::loadApps();
|
||||
} else {
|
||||
// For guests: Load only authentication, filesystem and logging
|
||||
OC_App::loadApps(array('authentication'));
|
||||
// For guests: Load only filesystem and logging
|
||||
OC_App::loadApps(array('filesystem', 'logging'));
|
||||
\OC_User::tryBasicAuthLogin();
|
||||
}
|
||||
@@ -754,7 +774,6 @@ class OC {
|
||||
if (!self::$CLI and (!isset($_GET["logout"]) or ($_GET["logout"] !== 'true'))) {
|
||||
try {
|
||||
if (!$systemConfig->getValue('maintenance', false) && !\OCP\Util::needUpgrade()) {
|
||||
OC_App::loadApps(array('authentication'));
|
||||
OC_App::loadApps(array('filesystem', 'logging'));
|
||||
OC_App::loadApps();
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
$TRANSLATIONS = array(
|
||||
"_%n minute ago_::_%n minutes ago_" => array("",""),
|
||||
"_%n hour ago_::_%n hours ago_" => array("",""),
|
||||
"_%n day go_::_%n days ago_" => array("",""),
|
||||
"_%n month ago_::_%n months ago_" => array("","")
|
||||
);
|
||||
$PLURAL_FORMS = "nplurals=2; plural=(n != 1);";
|
||||
@@ -161,7 +161,6 @@ class AllConfig implements \OCP\IConfig {
|
||||
\OC::$server->getAppConfig()->deleteApp($appName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set a user defined value
|
||||
*
|
||||
@@ -189,11 +188,18 @@ class AllConfig implements \OCP\IConfig {
|
||||
return;
|
||||
}
|
||||
|
||||
$data = array($value, $userId, $appName, $key);
|
||||
$affectedRows = 0;
|
||||
if (!$exists && $preCondition === null) {
|
||||
$sql = 'INSERT INTO `*PREFIX*preferences` (`configvalue`, `userid`, `appid`, `configkey`)'.
|
||||
'VALUES (?, ?, ?, ?)';
|
||||
$this->connection->insertIfNotExist('*PREFIX*preferences', [
|
||||
'configvalue' => $value,
|
||||
'userid' => $userId,
|
||||
'appid' => $appName,
|
||||
'configkey' => $key,
|
||||
], ['configkey', 'userid', 'appid']);
|
||||
$affectedRows = 1;
|
||||
} elseif ($exists) {
|
||||
$data = array($value, $userId, $appName, $key);
|
||||
|
||||
$sql = 'UPDATE `*PREFIX*preferences` SET `configvalue` = ? '.
|
||||
'WHERE `userid` = ? AND `appid` = ? AND `configkey` = ? ';
|
||||
|
||||
@@ -206,8 +212,8 @@ class AllConfig implements \OCP\IConfig {
|
||||
}
|
||||
$data[] = $preCondition;
|
||||
}
|
||||
$affectedRows = $this->connection->executeUpdate($sql, $data);
|
||||
}
|
||||
$affectedRows = $this->connection->executeUpdate($sql, $data);
|
||||
|
||||
// only add to the cache if we already loaded data for the user
|
||||
if ($affectedRows > 0 && isset($this->userCache[$userId])) {
|
||||
|
||||
@@ -277,6 +277,7 @@ class OC_App {
|
||||
*/
|
||||
public static function enable($app, $groups = null) {
|
||||
self::$enabledAppsCache = array(); // flush
|
||||
|
||||
if (!OC_Installer::isInstalled($app)) {
|
||||
$app = self::installApp($app);
|
||||
}
|
||||
@@ -327,6 +328,12 @@ class OC_App {
|
||||
self::$enabledAppsCache = array(); // flush
|
||||
// check if app is a shipped app or not. if not delete
|
||||
\OC_Hook::emit('OC_App', 'pre_disable', array('app' => $app));
|
||||
|
||||
// Convert OCS ID to regular application identifier
|
||||
if(self::getInternalAppIdByOcs($app) !== false) {
|
||||
$app = self::getInternalAppIdByOcs($app);
|
||||
}
|
||||
|
||||
OC_Appconfig::setValue($app, 'enabled', 'no' );
|
||||
}
|
||||
|
||||
@@ -896,6 +903,21 @@ class OC_App {
|
||||
return $combinedApps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the internal app ID or false
|
||||
* @param string $ocsID
|
||||
* @return string|false
|
||||
*/
|
||||
protected static function getInternalAppIdByOcs($ocsID) {
|
||||
if(is_numeric($ocsID)) {
|
||||
$idArray = \OC::$server->getAppConfig()->getValues(false, 'ocsid');
|
||||
if(array_search($ocsID, $idArray)) {
|
||||
return array_search($ocsID, $idArray);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* get a list of all apps on apps.owncloud.com
|
||||
* @return array, multi-dimensional array of apps.
|
||||
@@ -921,11 +943,13 @@ class OC_App {
|
||||
$i = 0;
|
||||
$l = \OC::$server->getL10N('core');
|
||||
foreach ($remoteApps as $app) {
|
||||
$potentialCleanId = self::getInternalAppIdByOcs($app['id']);
|
||||
// enhance app info (for example the description)
|
||||
$app1[$i] = OC_App::parseAppInfo($app);
|
||||
$app1[$i]['author'] = $app['personid'];
|
||||
$app1[$i]['ocs_id'] = $app['id'];
|
||||
$app1[$i]['internal'] = $app1[$i]['active'] = 0;
|
||||
$app1[$i]['internal'] = 0;
|
||||
$app1[$i]['active'] = ($potentialCleanId !== false) ? self::isEnabled($potentialCleanId) : false;
|
||||
$app1[$i]['update'] = false;
|
||||
$app1[$i]['groups'] = false;
|
||||
$app1[$i]['score'] = $app['score'];
|
||||
@@ -957,39 +981,6 @@ class OC_App {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if the current enabled apps are compatible with the current
|
||||
* ownCloud version. disable them if not.
|
||||
* This is important if you upgrade ownCloud and have non ported 3rd
|
||||
* party apps installed.
|
||||
*
|
||||
* @param array $apps optional app id list to check, uses all enabled apps
|
||||
* when not specified
|
||||
*
|
||||
* @return array containing the list of ids of the disabled apps
|
||||
*/
|
||||
public static function checkAppsRequirements($apps = array()) {
|
||||
$disabledApps = array();
|
||||
if (empty($apps)) {
|
||||
$apps = OC_App::getEnabledApps();
|
||||
}
|
||||
$version = OC_Util::getVersion();
|
||||
foreach ($apps as $app) {
|
||||
// check if the app is compatible with this version of ownCloud
|
||||
$info = OC_App::getAppInfo($app);
|
||||
if(!self::isAppCompatible($version, $info)) {
|
||||
OC_Log::write('core',
|
||||
'App "' . $info['name'] . '" (' . $app . ') can\'t be used because it is'
|
||||
. ' not compatible with this version of ownCloud',
|
||||
OC_Log::ERROR);
|
||||
OC_App::disable($app);
|
||||
OC_Hook::emit('update', 'success', 'Disabled ' . $info['name'] . ' app because it is not compatible');
|
||||
$disabledApps[] = $app;
|
||||
}
|
||||
}
|
||||
return $disabledApps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust the number of version parts of $version1 to match
|
||||
* the number of version parts of $version2.
|
||||
@@ -1088,7 +1079,6 @@ class OC_App {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param mixed $app
|
||||
* @return bool
|
||||
@@ -1108,8 +1098,21 @@ class OC_App {
|
||||
} else {
|
||||
$app = OC_Installer::installShippedApp($app);
|
||||
}
|
||||
}else{
|
||||
$app = self::downloadApp($app);
|
||||
} else {
|
||||
// Maybe the app is already installed - compare the version in this
|
||||
// case and use the local already installed one.
|
||||
// FIXME: This is a horrible hack. I feel sad. The god of code cleanness may forgive me.
|
||||
$internalAppId = self::getInternalAppIdByOcs($app);
|
||||
if($internalAppId !== false) {
|
||||
if($appData && version_compare(\OC_App::getAppVersion($internalAppId), $appData['version'], '<')) {
|
||||
$app = self::downloadApp($app);
|
||||
} else {
|
||||
self::enable($internalAppId);
|
||||
$app = $internalAppId;
|
||||
}
|
||||
} else {
|
||||
$app = self::downloadApp($app);
|
||||
}
|
||||
}
|
||||
|
||||
if($app!==false) {
|
||||
|
||||
@@ -50,17 +50,77 @@ class DependencyAnalyzer {
|
||||
$this->analyzeOC($dependencies, $app));
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncates both verions to the lowest common version, e.g.
|
||||
* 5.1.2.3 and 5.1 will be turned into 5.1 and 5.1,
|
||||
* 5.2.6.5 and 5.1 will be turned into 5.2 and 5.1
|
||||
* @param string $first
|
||||
* @param string $second
|
||||
* @return array first element is the first version, second element is the
|
||||
* second version
|
||||
*/
|
||||
private function normalizeVersions($first, $second) {
|
||||
$first = explode('.', $first);
|
||||
$second = explode('.', $second);
|
||||
|
||||
// get both arrays to the same minimum size
|
||||
$length = min(count($second), count($first));
|
||||
$first = array_slice($first, 0, $length);
|
||||
$second = array_slice($second, 0, $length);
|
||||
|
||||
return [implode('.', $first), implode('.', $second)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameters will be normalized and then passed into version_compare
|
||||
* in the same order they are specified in the method header
|
||||
* @param string $first
|
||||
* @param string $second
|
||||
* @param string $operator
|
||||
* @return bool result similar to version_compare
|
||||
*/
|
||||
private function compare($first, $second, $operator) {
|
||||
// we cant normalize versions if one of the given parameters is not a
|
||||
// version string but null. In case one parameter is null normalization
|
||||
// will therefore be skipped
|
||||
if ($first !== null && $second !== null) {
|
||||
list($first, $second) = $this->normalizeVersions($first, $second);
|
||||
}
|
||||
|
||||
return version_compare($first, $second, $operator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a version is bigger than another version
|
||||
* @param string $first
|
||||
* @param string $second
|
||||
* @return bool true if the first version is bigger than the second
|
||||
*/
|
||||
private function compareBigger($first, $second) {
|
||||
return $this->compare($first, $second, '>');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a version is smaller than another version
|
||||
* @param string $first
|
||||
* @param string $second
|
||||
* @return bool true if the first version is smaller than the second
|
||||
*/
|
||||
private function compareSmaller($first, $second) {
|
||||
return $this->compare($first, $second, '<');
|
||||
}
|
||||
|
||||
private function analyzePhpVersion($dependencies) {
|
||||
$missing = [];
|
||||
if (isset($dependencies['php']['@attributes']['min-version'])) {
|
||||
$minVersion = $dependencies['php']['@attributes']['min-version'];
|
||||
if (version_compare($this->platform->getPhpVersion(), $minVersion, '<')) {
|
||||
if ($this->compareSmaller($this->platform->getPhpVersion(), $minVersion)) {
|
||||
$missing[] = (string)$this->l->t('PHP %s or higher is required.', $minVersion);
|
||||
}
|
||||
}
|
||||
if (isset($dependencies['php']['@attributes']['max-version'])) {
|
||||
$maxVersion = $dependencies['php']['@attributes']['max-version'];
|
||||
if (version_compare($this->platform->getPhpVersion(), $maxVersion, '>')) {
|
||||
if ($this->compareBigger($this->platform->getPhpVersion(), $maxVersion)) {
|
||||
$missing[] = (string)$this->l->t('PHP with a version lower than %s is required.', $maxVersion);
|
||||
}
|
||||
}
|
||||
@@ -134,14 +194,14 @@ class DependencyAnalyzer {
|
||||
if (is_array($lib)) {
|
||||
if (isset($lib['@attributes']['min-version'])) {
|
||||
$minVersion = $lib['@attributes']['min-version'];
|
||||
if (version_compare($libVersion, $minVersion, '<')) {
|
||||
if ($this->compareSmaller($libVersion, $minVersion)) {
|
||||
$missing[] = (string)$this->l->t('Library %s with a version higher than %s is required - available version %s.',
|
||||
array($libName, $minVersion, $libVersion));
|
||||
}
|
||||
}
|
||||
if (isset($lib['@attributes']['max-version'])) {
|
||||
$maxVersion = $lib['@attributes']['max-version'];
|
||||
if (version_compare($libVersion, $maxVersion, '>')) {
|
||||
if ($this->compareBigger($libVersion, $maxVersion)) {
|
||||
$missing[] = (string)$this->l->t('Library %s with a version lower than %s is required - available version %s.',
|
||||
array($libName, $maxVersion, $libVersion));
|
||||
}
|
||||
@@ -193,12 +253,12 @@ class DependencyAnalyzer {
|
||||
}
|
||||
|
||||
if (!is_null($minVersion)) {
|
||||
if (version_compare($this->platform->getOcVersion(), $minVersion, '<')) {
|
||||
if ($this->compareSmaller($this->platform->getOcVersion(), $minVersion)) {
|
||||
$missing[] = (string)$this->l->t('ownCloud %s or higher is required.', $minVersion);
|
||||
}
|
||||
}
|
||||
if (!is_null($maxVersion)) {
|
||||
if (version_compare($this->platform->getOcVersion(), $maxVersion, '>')) {
|
||||
if ($this->compareBigger($this->platform->getOcVersion(), $maxVersion)) {
|
||||
$missing[] = (string)$this->l->t('ownCloud with a version lower than %s is required.', $maxVersion);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
|
||||
'method',
|
||||
'requesttoken',
|
||||
);
|
||||
protected $streamReadInitialized = false;
|
||||
|
||||
/**
|
||||
* @param array $vars An associative array with the following optional values:
|
||||
@@ -86,16 +87,6 @@ class Request implements \ArrayAccess, \Countable, IRequest {
|
||||
$this->items['post'] = $params;
|
||||
}
|
||||
}
|
||||
// Handle application/x-www-form-urlencoded for methods other than GET
|
||||
// or post correctly
|
||||
} elseif($vars['method'] !== 'GET'
|
||||
&& $vars['method'] !== 'POST'
|
||||
&& strpos($this->getHeader('Content-Type'), 'application/x-www-form-urlencoded') !== false) {
|
||||
|
||||
parse_str(file_get_contents($this->inputStream), $params);
|
||||
if(is_array($params)) {
|
||||
$this->items['params'] = $params;
|
||||
}
|
||||
}
|
||||
|
||||
$this->items['parameters'] = array_merge(
|
||||
@@ -276,6 +267,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
|
||||
* @return mixed the content of the array
|
||||
*/
|
||||
public function getParam($key, $default = null) {
|
||||
$this->initializeStreamParams();
|
||||
return isset($this->parameters[$key])
|
||||
? $this->parameters[$key]
|
||||
: $default;
|
||||
@@ -287,9 +279,35 @@ class Request implements \ArrayAccess, \Countable, IRequest {
|
||||
* @return array the array with all parameters
|
||||
*/
|
||||
public function getParams() {
|
||||
$this->initializeStreamParams();
|
||||
return $this->parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Workaround for ownCloud 8 to only read the stream-input when parameters
|
||||
* are requested. For the next master release this is removed and implemented
|
||||
* using a different approach.
|
||||
*/
|
||||
protected function initializeStreamParams() {
|
||||
if(
|
||||
$this->streamReadInitialized === false &&
|
||||
$this->getMethod() !== 'GET' &&
|
||||
$this->getMethod() !== 'POST' &&
|
||||
strpos($this->getHeader('Content-Type'), 'application/x-www-form-urlencoded') !== false
|
||||
) {
|
||||
$params = [];
|
||||
parse_str(file_get_contents($this->inputStream), $params);
|
||||
if(!empty($params)) {
|
||||
$this->items['params'] = $params;
|
||||
$this->items['parameters'] = array_merge(
|
||||
$this->items['parameters'],
|
||||
$this->items['params']
|
||||
);
|
||||
}
|
||||
}
|
||||
$this->streamReadInitialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the method of the request
|
||||
* @return string the method of the request (POST, GET, etc)
|
||||
@@ -337,6 +355,7 @@ class Request implements \ArrayAccess, \Countable, IRequest {
|
||||
* @throws \LogicException
|
||||
*/
|
||||
protected function getContent() {
|
||||
$this->initializeStreamParams();
|
||||
// If the content can't be parsed into an array then return a stream resource.
|
||||
if ($this->method === 'PUT'
|
||||
&& strpos($this->getHeader('Content-Type'), 'application/x-www-form-urlencoded') === false
|
||||
|
||||
2
lib/private/cache/file.php
vendored
2
lib/private/cache/file.php
vendored
@@ -83,7 +83,7 @@ class File {
|
||||
|
||||
public function hasKey($key) {
|
||||
$storage = $this->getStorage();
|
||||
if ($storage && $storage->is_file($key)) {
|
||||
if ($storage && $storage->is_file($key) && $storage->isReadable($key)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
27
lib/private/cache/fileglobal.php
vendored
27
lib/private/cache/fileglobal.php
vendored
@@ -52,7 +52,7 @@ class FileGlobal {
|
||||
public function hasKey($key) {
|
||||
$key = $this->fixKey($key);
|
||||
$cache_dir = self::getCacheDir();
|
||||
if ($cache_dir && is_file($cache_dir.$key)) {
|
||||
if ($cache_dir && is_file($cache_dir.$key) && is_readable($cache_dir.$key)) {
|
||||
$mtime = filemtime($cache_dir.$key);
|
||||
if ($mtime < time()) {
|
||||
unlink($cache_dir.$key);
|
||||
@@ -86,29 +86,4 @@ class FileGlobal {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static public function gc() {
|
||||
$appConfig = \OC::$server->getAppConfig();
|
||||
$last_run = $appConfig->getValue('core', 'global_cache_gc_lastrun', 0);
|
||||
$now = time();
|
||||
if (($now - $last_run) < 300) {
|
||||
// only do cleanup every 5 minutes
|
||||
return;
|
||||
}
|
||||
$appConfig->setValue('core', 'global_cache_gc_lastrun', $now);
|
||||
$cache_dir = self::getCacheDir();
|
||||
if($cache_dir and is_dir($cache_dir)) {
|
||||
$dh=opendir($cache_dir);
|
||||
if(is_resource($dh)) {
|
||||
while (($file = readdir($dh)) !== false) {
|
||||
if($file!='.' and $file!='..') {
|
||||
$mtime = filemtime($cache_dir.$file);
|
||||
if ($mtime < $now) {
|
||||
unlink($cache_dir.$file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
54
lib/private/cache/fileglobalgc.php
vendored
54
lib/private/cache/fileglobalgc.php
vendored
@@ -2,8 +2,56 @@
|
||||
|
||||
namespace OC\Cache;
|
||||
|
||||
class FileGlobalGC extends \OC\BackgroundJob\Job{
|
||||
public function run($argument){
|
||||
FileGlobal::gc();
|
||||
use OC\BackgroundJob\Job;
|
||||
use OCP\IConfig;
|
||||
|
||||
class FileGlobalGC extends Job {
|
||||
// only do cleanup every 5 minutes
|
||||
const CLEANUP_TTL_SEC = 300;
|
||||
|
||||
public function run($argument) {
|
||||
$this->gc(\OC::$server->getConfig(), $this->getCacheDir());
|
||||
}
|
||||
|
||||
protected function getCacheDir() {
|
||||
return get_temp_dir() . '/owncloud-' . \OC_Util::getInstanceId() . '/';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $cacheDir
|
||||
* @param int $now
|
||||
* @return string[]
|
||||
*/
|
||||
public function getExpiredPaths($cacheDir, $now) {
|
||||
$files = scandir($cacheDir);
|
||||
$files = array_filter($files, function ($file) {
|
||||
return $file != '.' and $file != '..';
|
||||
});
|
||||
$paths = array_map(function ($file) use ($cacheDir) {
|
||||
return $cacheDir . $file;
|
||||
}, $files);
|
||||
return array_values(array_filter($paths, function ($path) use ($now) {
|
||||
return is_file($path) and (filemtime($path) < $now);
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \OCP\IConfig $config
|
||||
* @param string $cacheDir
|
||||
*/
|
||||
public function gc(IConfig $config, $cacheDir) {
|
||||
$lastRun = $config->getAppValue('core', 'global_cache_gc_lastrun', 0);
|
||||
$now = time();
|
||||
if (($now - $lastRun) < self::CLEANUP_TTL_SEC) {
|
||||
return;
|
||||
}
|
||||
$config->setAppValue('core', 'global_cache_gc_lastrun', $now);
|
||||
if (!is_dir($cacheDir)) {
|
||||
return;
|
||||
}
|
||||
$paths = $this->getExpiredPaths($cacheDir, $now);
|
||||
array_walk($paths, function($file) {
|
||||
unlink($file);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ class OC_Connector_Sabre_Auth extends \Sabre\DAV\Auth\Backend\AbstractBasic {
|
||||
*/
|
||||
protected function validateUserPass($username, $password) {
|
||||
if (OC_User::isLoggedIn() &&
|
||||
$this->isDavAuthenticated($username)
|
||||
$this->isDavAuthenticated(OC_User::getUser())
|
||||
) {
|
||||
OC_Util::setupFS(OC_User::getUser());
|
||||
\OC::$server->getSession()->close();
|
||||
@@ -60,8 +60,11 @@ class OC_Connector_Sabre_Auth extends \Sabre\DAV\Auth\Backend\AbstractBasic {
|
||||
} else {
|
||||
OC_Util::setUpFS(); //login hooks may need early access to the filesystem
|
||||
if(OC_User::login($username, $password)) {
|
||||
OC_Util::setUpFS(OC_User::getUser());
|
||||
\OC::$server->getSession()->set(self::DAV_AUTHENTICATED, $username);
|
||||
// make sure we use owncloud's internal username here
|
||||
// and not the HTTP auth supplied one, see issue #14048
|
||||
$ocUser = OC_User::getUser();
|
||||
OC_Util::setUpFS($ocUser);
|
||||
\OC::$server->getSession()->set(self::DAV_AUTHENTICATED, $ocUser);
|
||||
\OC::$server->getSession()->close();
|
||||
return true;
|
||||
} else {
|
||||
|
||||
@@ -126,8 +126,9 @@ class ObjectTree extends \Sabre\DAV\ObjectTree {
|
||||
throw new \Sabre\DAV\Exception\ServiceUnavailable('filesystem not setup');
|
||||
}
|
||||
|
||||
$targetNodeExists = $this->nodeExists($destinationPath);
|
||||
$sourceNode = $this->getNodeForPath($sourcePath);
|
||||
if ($sourceNode instanceof \Sabre\DAV\ICollection and $this->nodeExists($destinationPath)) {
|
||||
if ($sourceNode instanceof \Sabre\DAV\ICollection && $targetNodeExists) {
|
||||
throw new \Sabre\DAV\Exception\Forbidden('Could not copy directory ' . $sourceNode . ', target exists');
|
||||
}
|
||||
list($sourceDir,) = \Sabre\DAV\URLUtil::splitPath($sourcePath);
|
||||
@@ -141,14 +142,22 @@ class ObjectTree extends \Sabre\DAV\ObjectTree {
|
||||
}
|
||||
|
||||
try {
|
||||
// check update privileges
|
||||
if (!$this->fileView->isUpdatable($sourcePath) && !$isMovableMount) {
|
||||
throw new \Sabre\DAV\Exception\Forbidden();
|
||||
}
|
||||
if ($sourceDir !== $destinationDir) {
|
||||
$sameFolder = ($sourceDir === $destinationDir);
|
||||
// if we're overwriting or same folder
|
||||
if ($targetNodeExists || $sameFolder) {
|
||||
// note that renaming a share mount point is always allowed
|
||||
if (!$this->fileView->isUpdatable($destinationDir) && !$isMovableMount) {
|
||||
throw new \Sabre\DAV\Exception\Forbidden();
|
||||
}
|
||||
} else {
|
||||
if (!$this->fileView->isCreatable($destinationDir)) {
|
||||
throw new \Sabre\DAV\Exception\Forbidden();
|
||||
}
|
||||
}
|
||||
|
||||
if (!$sameFolder) {
|
||||
// moving to a different folder, source will be gone, like a deletion
|
||||
// note that moving a share mount point is always allowed
|
||||
if (!$this->fileView->isDeletable($sourcePath) && !$isMovableMount) {
|
||||
throw new \Sabre\DAV\Exception\Forbidden();
|
||||
}
|
||||
|
||||
@@ -38,25 +38,80 @@ class DateTimeZone implements IDateTimeZone {
|
||||
/**
|
||||
* Get the timezone of the current user, based on his session information and config data
|
||||
*
|
||||
* @param bool|int $timestamp
|
||||
* @return \DateTimeZone
|
||||
*/
|
||||
public function getTimeZone() {
|
||||
public function getTimeZone($timestamp = false) {
|
||||
$timeZone = $this->config->getUserValue($this->session->get('user_id'), 'core', 'timezone', null);
|
||||
if ($timeZone === null) {
|
||||
if ($this->session->exists('timezone')) {
|
||||
$offsetHours = $this->session->get('timezone');
|
||||
// Note: the timeZone name is the inverse to the offset,
|
||||
// so a positive offset means negative timeZone
|
||||
// and the other way around.
|
||||
if ($offsetHours > 0) {
|
||||
return new \DateTimeZone('Etc/GMT-' . $offsetHours);
|
||||
} else {
|
||||
return new \DateTimeZone('Etc/GMT+' . abs($offsetHours));
|
||||
}
|
||||
} else {
|
||||
return new \DateTimeZone('UTC');
|
||||
return $this->guessTimeZoneFromOffset($this->session->get('timezone'), $timestamp);
|
||||
}
|
||||
$timeZone = $this->getDefaultTimeZone();
|
||||
}
|
||||
return new \DateTimeZone($timeZone);
|
||||
|
||||
try {
|
||||
return new \DateTimeZone($timeZone);
|
||||
} catch (\Exception $e) {
|
||||
\OCP\Util::writeLog('datetimezone', 'Failed to created DateTimeZone "' . $timeZone . "'", \OCP\Util::DEBUG);
|
||||
return new \DateTimeZone($this->getDefaultTimeZone());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Guess the DateTimeZone for a given offset
|
||||
*
|
||||
* We first try to find a Etc/GMT* timezone, if that does not exist,
|
||||
* we try to find it manually, before falling back to UTC.
|
||||
*
|
||||
* @param mixed $offset
|
||||
* @param bool|int $timestamp
|
||||
* @return \DateTimeZone
|
||||
*/
|
||||
protected function guessTimeZoneFromOffset($offset, $timestamp) {
|
||||
try {
|
||||
// Note: the timeZone name is the inverse to the offset,
|
||||
// so a positive offset means negative timeZone
|
||||
// and the other way around.
|
||||
if ($offset > 0) {
|
||||
$timeZone = 'Etc/GMT-' . $offset;
|
||||
} else {
|
||||
$timeZone = 'Etc/GMT+' . abs($offset);
|
||||
}
|
||||
|
||||
return new \DateTimeZone($timeZone);
|
||||
} catch (\Exception $e) {
|
||||
// If the offset has no Etc/GMT* timezone,
|
||||
// we try to guess one timezone that has the same offset
|
||||
foreach (\DateTimeZone::listIdentifiers() as $timeZone) {
|
||||
$dtz = new \DateTimeZone($timeZone);
|
||||
$dateTime = new \DateTime();
|
||||
|
||||
if ($timestamp !== false) {
|
||||
$dateTime->setTimestamp($timestamp);
|
||||
}
|
||||
|
||||
$dtOffset = $dtz->getOffset($dateTime);
|
||||
if ($dtOffset == 3600 * $offset) {
|
||||
return $dtz;
|
||||
}
|
||||
}
|
||||
|
||||
// No timezone found, fallback to UTC
|
||||
\OCP\Util::writeLog('datetimezone', 'Failed to find DateTimeZone for offset "' . $offset . "'", \OCP\Util::DEBUG);
|
||||
return new \DateTimeZone($this->getDefaultTimeZone());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default timezone of the server
|
||||
*
|
||||
* Falls back to UTC if it is not yet set.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getDefaultTimeZone() {
|
||||
$serverTimeZone = date_default_timezone_get();
|
||||
return $serverTimeZone ?: 'UTC';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
define('MDB2_SCHEMA_DUMP_STRUCTURE', '1');
|
||||
|
||||
/**
|
||||
* This class manages the access to the database. It basically is a wrapper for
|
||||
* Doctrine with some adaptions.
|
||||
@@ -40,8 +38,7 @@ class OC_DB {
|
||||
*
|
||||
* @return \OC\DB\MDB2SchemaManager
|
||||
*/
|
||||
private static function getMDB2SchemaManager()
|
||||
{
|
||||
private static function getMDB2SchemaManager() {
|
||||
return new \OC\DB\MDB2SchemaManager(\OC::$server->getDatabaseConnection());
|
||||
}
|
||||
|
||||
@@ -166,16 +163,6 @@ class OC_DB {
|
||||
return \OC::$server->getDatabaseConnection()->lastInsertId($table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a row if a matching row doesn't exists.
|
||||
* @param string $table The table to insert into in the form '*PREFIX*tableName'
|
||||
* @param array $input An array of fieldname/value pairs
|
||||
* @return boolean number of updated rows
|
||||
*/
|
||||
public static function insertIfNotExist($table, $input) {
|
||||
return \OC::$server->getDatabaseConnection()->insertIfNotExist($table, $input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a transaction
|
||||
*/
|
||||
@@ -205,7 +192,7 @@ class OC_DB {
|
||||
*
|
||||
* TODO: write more documentation
|
||||
*/
|
||||
public static function getDbStructure( $file, $mode = 0) {
|
||||
public static function getDbStructure($file) {
|
||||
$schemaManager = self::getMDB2SchemaManager();
|
||||
return $schemaManager->getDbStructure($file);
|
||||
}
|
||||
|
||||
@@ -40,44 +40,38 @@ class Adapter {
|
||||
}
|
||||
|
||||
/**
|
||||
* insert the @input values when they do not exist yet
|
||||
* @param string $table name
|
||||
* @param array $input key->value pair, key has to be sanitized properly
|
||||
* @throws \OC\HintException
|
||||
* @return int count of inserted rows
|
||||
* Insert a row if the matching row does not exists.
|
||||
*
|
||||
* @param string $table The table name (will replace *PREFIX* with the actual prefix)
|
||||
* @param array $input data that should be inserted into the table (column name => value)
|
||||
* @param array|null $compare List of values that should be checked for "if not exists"
|
||||
* If this is null or an empty array, all keys of $input will be compared
|
||||
* Please note: text fields (clob) must not be used in the compare array
|
||||
* @return int number of inserted rows
|
||||
* @throws \Doctrine\DBAL\DBALException
|
||||
*/
|
||||
public function insertIfNotExist($table, $input) {
|
||||
public function insertIfNotExist($table, $input, array $compare = null) {
|
||||
if (empty($compare)) {
|
||||
$compare = array_keys($input);
|
||||
}
|
||||
$query = 'INSERT INTO `' .$table . '` (`'
|
||||
. implode('`,`', array_keys($input)) . '`) SELECT '
|
||||
. str_repeat('?,', count($input)-1).'? ' // Is there a prettier alternative?
|
||||
. 'FROM `' . $table . '` WHERE ';
|
||||
|
||||
$inserts = array_values($input);
|
||||
foreach($input as $key => $value) {
|
||||
foreach($compare as $key) {
|
||||
$query .= '`' . $key . '`';
|
||||
if (is_null($value)) {
|
||||
if (is_null($input[$key])) {
|
||||
$query .= ' IS NULL AND ';
|
||||
} else {
|
||||
$inserts[] = $value;
|
||||
$inserts[] = $input[$key];
|
||||
$query .= ' = ? AND ';
|
||||
}
|
||||
}
|
||||
$query = substr($query, 0, strlen($query) - 5);
|
||||
$query .= ' HAVING COUNT(*) = 0';
|
||||
|
||||
try {
|
||||
return $this->conn->executeUpdate($query, $inserts);
|
||||
} catch(\Doctrine\DBAL\DBALException $e) {
|
||||
$entry = 'DB Error: "'.$e->getMessage() . '"<br />';
|
||||
$entry .= 'Offending command was: ' . $query.'<br />';
|
||||
\OC_Log::write('core', $entry, \OC_Log::FATAL);
|
||||
$l = \OC::$server->getL10N('lib');
|
||||
throw new \OC\HintException(
|
||||
$l->t('Database Error'),
|
||||
$l->t('Please contact your system administrator.'),
|
||||
0,
|
||||
$e
|
||||
);
|
||||
}
|
||||
return $this->conn->executeUpdate($query, $inserts);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,62 +18,39 @@ class AdapterSqlite extends Adapter {
|
||||
return $statement;
|
||||
}
|
||||
|
||||
public function insertIfNotExist($table, $input) {
|
||||
// NOTE: For SQLite we have to use this clumsy approach
|
||||
// otherwise all fieldnames used must have a unique key.
|
||||
$query = 'SELECT COUNT(*) FROM `' . $table . '` WHERE ';
|
||||
$inserts = array();
|
||||
foreach ($input as $key => $value) {
|
||||
/**
|
||||
* Insert a row if the matching row does not exists.
|
||||
*
|
||||
* @param string $table The table name (will replace *PREFIX* with the actual prefix)
|
||||
* @param array $input data that should be inserted into the table (column name => value)
|
||||
* @param array|null $compare List of values that should be checked for "if not exists"
|
||||
* If this is null or an empty array, all keys of $input will be compared
|
||||
* Please note: text fields (clob) must not be used in the compare array
|
||||
* @return int number of inserted rows
|
||||
* @throws \Doctrine\DBAL\DBALException
|
||||
*/
|
||||
public function insertIfNotExist($table, $input, array $compare = null) {
|
||||
if (empty($compare)) {
|
||||
$compare = array_keys($input);
|
||||
}
|
||||
$fieldList = '`' . implode('`,`', array_keys($input)) . '`';
|
||||
$query = "INSERT INTO `$table` ($fieldList) SELECT "
|
||||
. str_repeat('?,', count($input)-1).'? '
|
||||
. " WHERE NOT EXISTS (SELECT 1 FROM `$table` WHERE ";
|
||||
|
||||
$inserts = array_values($input);
|
||||
foreach($compare as $key) {
|
||||
$query .= '`' . $key . '`';
|
||||
if (is_null($value)) {
|
||||
if (is_null($input[$key])) {
|
||||
$query .= ' IS NULL AND ';
|
||||
} else {
|
||||
$inserts[] = $value;
|
||||
$inserts[] = $input[$key];
|
||||
$query .= ' = ? AND ';
|
||||
}
|
||||
}
|
||||
$query = substr($query, 0, strlen($query) - 5);
|
||||
$query .= ')';
|
||||
|
||||
try {
|
||||
$stmt = $this->conn->prepare($query);
|
||||
$result = $stmt->execute($inserts);
|
||||
} catch(\Doctrine\DBAL\DBALException $e) {
|
||||
$entry = 'DB Error: "'.$e->getMessage() . '"<br />';
|
||||
$entry .= 'Offending command was: ' . $query . '<br />';
|
||||
\OC_Log::write('core', $entry, \OC_Log::FATAL);
|
||||
$l = \OC::$server->getL10N('lib');
|
||||
throw new \OC\HintException(
|
||||
$l->t('Database Error'),
|
||||
$l->t('Please contact your system administrator.'),
|
||||
0,
|
||||
$e
|
||||
);
|
||||
}
|
||||
|
||||
if ($stmt->fetchColumn() === '0') {
|
||||
$query = 'INSERT INTO `' . $table . '` (`'
|
||||
. implode('`,`', array_keys($input)) . '`) VALUES('
|
||||
. str_repeat('?,', count($input)-1).'? ' . ')';
|
||||
} else {
|
||||
return 0; //no rows updated
|
||||
}
|
||||
|
||||
try {
|
||||
$statement = $this->conn->prepare($query);
|
||||
$result = $statement->execute(array_values($input));
|
||||
} catch(\Doctrine\DBAL\DBALException $e) {
|
||||
$entry = 'DB Error: "'.$e->getMessage() . '"<br />';
|
||||
$entry .= 'Offending command was: ' . $query.'<br />';
|
||||
\OC_Log::write('core', $entry, \OC_Log::FATAL);
|
||||
$l = \OC::$server->getL10N('lib');
|
||||
throw new \OC\HintException(
|
||||
$l->t('Database Error'),
|
||||
$l->t('Please contact your system administrator.'),
|
||||
0,
|
||||
$e
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
return $this->conn->executeUpdate($query, $inserts);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,8 @@ class Connection extends \Doctrine\DBAL\Connection implements IDBConnection {
|
||||
parent::__construct($params, $driver, $config, $eventManager);
|
||||
$this->adapter = new $params['adapter']($this);
|
||||
$this->tablePrefix = $params['tablePrefix'];
|
||||
|
||||
parent::setTransactionIsolation(parent::TRANSACTION_READ_COMMITTED);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,20 +152,23 @@ class Connection extends \Doctrine\DBAL\Connection implements IDBConnection {
|
||||
}
|
||||
|
||||
// internal use
|
||||
public function realLastInsertId($seqName = null)
|
||||
{
|
||||
public function realLastInsertId($seqName = null) {
|
||||
return parent::lastInsertId($seqName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a row if a matching row doesn't exists.
|
||||
* @param string $table. The table to insert into in the form '*PREFIX*tableName'
|
||||
* @param array $input. An array of fieldname/value pairs
|
||||
* @throws \OC\HintException
|
||||
* @return bool The return value from execute()
|
||||
* Insert a row if the matching row does not exists.
|
||||
*
|
||||
* @param string $table The table name (will replace *PREFIX* with the actual prefix)
|
||||
* @param array $input data that should be inserted into the table (column name => value)
|
||||
* @param array|null $compare List of values that should be checked for "if not exists"
|
||||
* If this is null or an empty array, all keys of $input will be compared
|
||||
* Please note: text fields (clob) must not be used in the compare array
|
||||
* @return int number of inserted rows
|
||||
* @throws \Doctrine\DBAL\DBALException
|
||||
*/
|
||||
public function insertIfNotExist($table, $input) {
|
||||
return $this->adapter->insertIfNotExist($table, $input);
|
||||
public function insertIfNotExist($table, $input, array $compare = null) {
|
||||
return $this->adapter->insertIfNotExist($table, $input, $compare);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -96,6 +96,7 @@ class ConnectionFactory {
|
||||
break;
|
||||
case 'sqlite3':
|
||||
$journalMode = $additionalConnectionParams['sqlite.journal_mode'];
|
||||
$additionalConnectionParams['platform'] = new OCSqlitePlatform();
|
||||
$eventManager->addEventSubscriber(new SQLiteSessionInit(true, $journalMode));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ class MDB2SchemaManager {
|
||||
*
|
||||
* TODO: write more documentation
|
||||
*/
|
||||
public function getDbStructure($file, $mode = MDB2_SCHEMA_DUMP_STRUCTURE) {
|
||||
public function getDbStructure($file) {
|
||||
return \OC_DB_MDB2SchemaWriter::saveSchemaToFile($file, $this->conn);
|
||||
}
|
||||
|
||||
|
||||
@@ -293,6 +293,9 @@ class MDB2SchemaReader {
|
||||
}
|
||||
if (!empty($fields)) {
|
||||
if (isset($primary) && $primary) {
|
||||
if ($table->hasPrimaryKey()) {
|
||||
return;
|
||||
}
|
||||
$table->setPrimaryKey($fields, $name);
|
||||
} else {
|
||||
if (isset($unique) && $unique) {
|
||||
|
||||
35
lib/private/db/ocsqliteplatform.php
Normal file
35
lib/private/db/ocsqliteplatform.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) 2015 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\DB;
|
||||
|
||||
class OCSqlitePlatform extends \Doctrine\DBAL\Platforms\SqlitePlatform {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getColumnDeclarationSQL($name, array $field) {
|
||||
$def = parent::getColumnDeclarationSQL($name, $field);
|
||||
if (!empty($field['autoincrement'])) {
|
||||
$def .= ' PRIMARY KEY AUTOINCREMENT';
|
||||
}
|
||||
return $def;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function _getCreateTableSQL($name, array $columns, array $options = array()){
|
||||
// if auto increment is set the column is already defined as primary key
|
||||
foreach ($columns as $column) {
|
||||
if (!empty($column['autoincrement'])) {
|
||||
$options['primary'] = null;
|
||||
}
|
||||
}
|
||||
return parent::_getCreateTableSQL($name, $columns, $options);
|
||||
}
|
||||
}
|
||||
@@ -58,6 +58,7 @@ class SQLiteMigrator extends Migrator {
|
||||
$platform = $connection->getDatabasePlatform();
|
||||
$platform->registerDoctrineTypeMapping('tinyint unsigned', 'integer');
|
||||
$platform->registerDoctrineTypeMapping('smallint unsigned', 'integer');
|
||||
$platform->registerDoctrineTypeMapping('varchar ', 'string');
|
||||
|
||||
return parent::getDiff($targetSchema, $connection);
|
||||
}
|
||||
|
||||
@@ -51,15 +51,6 @@ class OC_DB_StatementWrapper {
|
||||
}
|
||||
$this->lastArguments = $input;
|
||||
if (count($input) > 0) {
|
||||
|
||||
if (!isset($type)) {
|
||||
$type = OC_Config::getValue( "dbtype", "sqlite" );
|
||||
}
|
||||
|
||||
if ($type == 'mssql') {
|
||||
$input = $this->tryFixSubstringLastArgumentDataForMSSQL($input);
|
||||
}
|
||||
|
||||
$result = $this->statement->execute($input);
|
||||
} else {
|
||||
$result = $this->statement->execute();
|
||||
@@ -75,99 +66,6 @@ class OC_DB_StatementWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
private function tryFixSubstringLastArgumentDataForMSSQL($input) {
|
||||
$query = $this->statement->getWrappedStatement()->queryString;
|
||||
$pos = stripos ($query, 'SUBSTRING');
|
||||
|
||||
if ( $pos === false) {
|
||||
return $input;
|
||||
}
|
||||
|
||||
try {
|
||||
$newQuery = '';
|
||||
|
||||
$cArg = 0;
|
||||
|
||||
$inSubstring = false;
|
||||
$queryLength = strlen($query);
|
||||
|
||||
// Create new query
|
||||
for ($i = 0; $i < $queryLength; $i++) {
|
||||
if ($inSubstring == false) {
|
||||
// Defines when we should start inserting values
|
||||
if (substr ($query, $i, 9) == 'SUBSTRING') {
|
||||
$inSubstring = true;
|
||||
}
|
||||
} else {
|
||||
// Defines when we should stop inserting values
|
||||
if (substr ($query, $i, 1) == ')') {
|
||||
$inSubstring = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (substr ($query, $i, 1) == '?') {
|
||||
// We found a question mark
|
||||
if ($inSubstring) {
|
||||
$newQuery .= $input[$cArg];
|
||||
|
||||
//
|
||||
// Remove from input array
|
||||
//
|
||||
array_splice ($input, $cArg, 1);
|
||||
} else {
|
||||
$newQuery .= substr ($query, $i, 1);
|
||||
$cArg++;
|
||||
}
|
||||
} else {
|
||||
$newQuery .= substr ($query, $i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// The global data we need
|
||||
$name = OC_Config::getValue( "dbname", "owncloud" );
|
||||
$host = OC_Config::getValue( "dbhost", "" );
|
||||
$user = OC_Config::getValue( "dbuser", "" );
|
||||
$pass = OC_Config::getValue( "dbpassword", "" );
|
||||
if (strpos($host, ':')) {
|
||||
list($host, $port) = explode(':', $host, 2);
|
||||
} else {
|
||||
$port = false;
|
||||
}
|
||||
$opts = array();
|
||||
|
||||
if ($port) {
|
||||
$dsn = 'sqlsrv:Server='.$host.','.$port.';Database='.$name;
|
||||
} else {
|
||||
$dsn = 'sqlsrv:Server='.$host.';Database='.$name;
|
||||
}
|
||||
|
||||
$PDO = new PDO($dsn, $user, $pass, $opts);
|
||||
$PDO->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
|
||||
$PDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
$this->statement = $PDO->prepare($newQuery);
|
||||
|
||||
$this->lastArguments = $input;
|
||||
|
||||
return $input;
|
||||
} catch (PDOException $e){
|
||||
$entry = 'PDO DB Error: "'.$e->getMessage().'"<br />';
|
||||
$entry .= 'Offending command was: '.$this->statement->queryString .'<br />';
|
||||
$entry .= 'Input parameters: ' .print_r($input, true).'<br />';
|
||||
$entry .= 'Stack trace: ' .$e->getTraceAsString().'<br />';
|
||||
OC_Log::write('core', $entry, OC_Log::FATAL);
|
||||
OC_User::setUserId(null);
|
||||
|
||||
$l = \OC::$server->getL10N('lib');
|
||||
throw new \OC\HintException(
|
||||
$l->t('Database Error'),
|
||||
$l->t('Please contact your system administrator.'),
|
||||
0,
|
||||
$e
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* provide an alias for fetch
|
||||
*
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
<?php
|
||||
|
||||
if (file_exists(OC::$SERVERROOT . '/themes/' . OC_Util::getTheme() . '/defaults.php')) {
|
||||
require_once 'themes/' . OC_Util::getTheme() . '/defaults.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Default strings and values which differ between the enterprise and the
|
||||
* community edition. Use the get methods to always get the right strings.
|
||||
@@ -45,7 +41,11 @@ class OC_Defaults {
|
||||
$this->defaultLogoClaim = '';
|
||||
$this->defaultMailHeaderColor = '#1d2d44'; /* header color of mail notifications */
|
||||
|
||||
if (class_exists('OC_Theme')) {
|
||||
if (file_exists(OC::$SERVERROOT . '/themes/' . OC_Util::getTheme() . '/defaults.php')) {
|
||||
// prevent defaults.php from printing output
|
||||
ob_start();
|
||||
require_once 'themes/' . OC_Util::getTheme() . '/defaults.php';
|
||||
ob_end_clean();
|
||||
$this->theme = new OC_Theme();
|
||||
}
|
||||
}
|
||||
|
||||
36
lib/private/files/cache/cache.php
vendored
36
lib/private/files/cache/cache.php
vendored
@@ -74,9 +74,11 @@ class Cache {
|
||||
|
||||
if (!isset(self::$mimetypeIds[$mime])) {
|
||||
try {
|
||||
$result = \OC_DB::executeAudited('INSERT INTO `*PREFIX*mimetypes`(`mimetype`) VALUES(?)', array($mime));
|
||||
self::$mimetypeIds[$mime] = \OC_DB::insertid('*PREFIX*mimetypes');
|
||||
self::$mimetypes[self::$mimetypeIds[$mime]] = $mime;
|
||||
$connection = \OC_DB::getConnection();
|
||||
$connection->insertIfNotExist('*PREFIX*mimetypes', [
|
||||
'mimetype' => $mime,
|
||||
]);
|
||||
$this->loadMimetypes();
|
||||
} catch (\Doctrine\DBAL\DBALException $e) {
|
||||
\OC_Log::write('core', 'Exception during mimetype insertion: ' . $e->getmessage(), \OC_Log::DEBUG);
|
||||
return -1;
|
||||
@@ -95,6 +97,8 @@ class Cache {
|
||||
}
|
||||
|
||||
public function loadMimetypes() {
|
||||
self::$mimetypeIds = self::$mimetypes = array();
|
||||
|
||||
$result = \OC_DB::executeAudited('SELECT `id`, `mimetype` FROM `*PREFIX*mimetypes`', array());
|
||||
if ($result) {
|
||||
while ($row = $result->fetchRow()) {
|
||||
@@ -207,6 +211,7 @@ class Cache {
|
||||
* @param array $data
|
||||
*
|
||||
* @return int file id
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function put($file, array $data) {
|
||||
if (($id = $this->getId($file)) > -1) {
|
||||
@@ -236,13 +241,28 @@ class Cache {
|
||||
list($queryParts, $params) = $this->buildParts($data);
|
||||
$queryParts[] = '`storage`';
|
||||
$params[] = $this->getNumericStorageId();
|
||||
$valuesPlaceholder = array_fill(0, count($queryParts), '?');
|
||||
|
||||
$sql = 'INSERT INTO `*PREFIX*filecache` (' . implode(', ', $queryParts) . ')'
|
||||
. ' VALUES (' . implode(', ', $valuesPlaceholder) . ')';
|
||||
\OC_DB::executeAudited($sql, $params);
|
||||
$params = array_map(function($item) {
|
||||
return trim($item, "`");
|
||||
}, $params);
|
||||
$queryParts = array_map(function($item) {
|
||||
return trim($item, "`");
|
||||
}, $queryParts);
|
||||
$values = array_combine($queryParts, $params);
|
||||
if (\OC::$server->getDatabaseConnection()->insertIfNotExist('*PREFIX*filecache', $values, [
|
||||
'storage',
|
||||
'path_hash',
|
||||
])) {
|
||||
return (int)\OC_DB::insertid('*PREFIX*filecache');
|
||||
}
|
||||
|
||||
return (int)\OC_DB::insertid('*PREFIX*filecache');
|
||||
// The file was created in the mean time
|
||||
if (($id = $this->getId($file)) > -1) {
|
||||
$this->update($id, $data);
|
||||
return $id;
|
||||
} else {
|
||||
throw new \RuntimeException('File entry could not be inserted with insertIfNotExist() but could also not be selected with getId() in order to perform an update. Please try again.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
15
lib/private/files/cache/storage.php
vendored
15
lib/private/files/cache/storage.php
vendored
@@ -21,6 +21,7 @@ class Storage {
|
||||
|
||||
/**
|
||||
* @param \OC\Files\Storage\Storage|string $storage
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function __construct($storage) {
|
||||
if ($storage instanceof \OC\Files\Storage\Storage) {
|
||||
@@ -35,9 +36,17 @@ class Storage {
|
||||
if ($row = $result->fetchRow()) {
|
||||
$this->numericId = $row['numeric_id'];
|
||||
} else {
|
||||
$sql = 'INSERT INTO `*PREFIX*storages` (`id`) VALUES(?)';
|
||||
\OC_DB::executeAudited($sql, array($this->storageId));
|
||||
$this->numericId = \OC_DB::insertid('*PREFIX*storages');
|
||||
$connection = \OC_DB::getConnection();
|
||||
if ($connection->insertIfNotExist('*PREFIX*storages', ['id' => $this->storageId])) {
|
||||
$this->numericId = \OC_DB::insertid('*PREFIX*storages');
|
||||
} else {
|
||||
$result = \OC_DB::executeAudited($sql, array($this->storageId));
|
||||
if ($row = $result->fetchRow()) {
|
||||
$this->numericId = $row['numeric_id'];
|
||||
} else {
|
||||
throw new \RuntimeException('Storage could neither be inserted nor be selected from the database');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
25
lib/private/files/cache/updater.php
vendored
25
lib/private/files/cache/updater.php
vendored
@@ -12,6 +12,11 @@ namespace OC\Files\Cache;
|
||||
* Update the cache and propagate changes
|
||||
*/
|
||||
class Updater {
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $enabled = true;
|
||||
|
||||
/**
|
||||
* @var \OC\Files\View
|
||||
*/
|
||||
@@ -30,6 +35,14 @@ class Updater {
|
||||
$this->propagator = new ChangePropagator($view);
|
||||
}
|
||||
|
||||
public function disable() {
|
||||
$this->enabled = false;
|
||||
}
|
||||
|
||||
public function enable() {
|
||||
$this->enabled = true;
|
||||
}
|
||||
|
||||
public function propagate($path, $time = null) {
|
||||
$this->propagator->addChange($path);
|
||||
$this->propagator->propagateChanges($time);
|
||||
@@ -42,6 +55,9 @@ class Updater {
|
||||
* @param int $time
|
||||
*/
|
||||
public function update($path, $time = null) {
|
||||
if (!$this->enabled or Scanner::isPartialFile($path)) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* @var \OC\Files\Storage\Storage $storage
|
||||
* @var string $internalPath
|
||||
@@ -64,6 +80,9 @@ class Updater {
|
||||
* @param string $path
|
||||
*/
|
||||
public function remove($path) {
|
||||
if (!$this->enabled) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* @var \OC\Files\Storage\Storage $storage
|
||||
* @var string $internalPath
|
||||
@@ -88,6 +107,9 @@ class Updater {
|
||||
* @param string $target
|
||||
*/
|
||||
public function rename($source, $target) {
|
||||
if (!$this->enabled) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* @var \OC\Files\Storage\Storage $sourceStorage
|
||||
* @var \OC\Files\Storage\Storage $targetStorage
|
||||
@@ -104,6 +126,9 @@ class Updater {
|
||||
if ($sourceStorage && $targetStorage) {
|
||||
if ($sourceStorage === $targetStorage) {
|
||||
$cache = $sourceStorage->getCache($sourceInternalPath);
|
||||
if ($cache->inCache($targetInternalPath)) {
|
||||
$cache->remove($targetInternalPath);
|
||||
}
|
||||
$cache->move($sourceInternalPath, $targetInternalPath);
|
||||
|
||||
if (pathinfo($sourceInternalPath, PATHINFO_EXTENSION) !== pathinfo($targetInternalPath, PATHINFO_EXTENSION)) {
|
||||
|
||||
@@ -389,4 +389,16 @@ class Folder extends Node implements \OCP\Files\Folder {
|
||||
throw new NotPermittedException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a suffix to the name in case the file exists
|
||||
*
|
||||
* @param string $name
|
||||
* @return string
|
||||
* @throws NotPermittedException
|
||||
*/
|
||||
public function getNonExistingName($name) {
|
||||
$uniqueName = \OC_Helper::buildNotExistingFileNameForView($this->getPath(), $name, $this->view);
|
||||
return trim($this->getRelativePath($uniqueName), '/');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
|
||||
namespace OC\Files\Node;
|
||||
|
||||
use OC\Files\Filesystem;
|
||||
use OCP\Files\FileInfo;
|
||||
use OCP\Files\InvalidPathException;
|
||||
use OCP\Files\NotFoundException;
|
||||
use OCP\Files\NotPermittedException;
|
||||
|
||||
class Node implements \OCP\Files\Node {
|
||||
@@ -45,11 +49,21 @@ class Node implements \OCP\Files\Node {
|
||||
/**
|
||||
* Returns the matching file info
|
||||
*
|
||||
* @return \OCP\Files\FileInfo
|
||||
* @return FileInfo
|
||||
* @throws InvalidPathException
|
||||
* @throws NotFoundException
|
||||
*/
|
||||
public function getFileInfo() {
|
||||
if (!Filesystem::isValidPath($this->path)) {
|
||||
throw new InvalidPathException();
|
||||
}
|
||||
if (!$this->fileInfo) {
|
||||
$this->fileInfo = $this->view->getFileInfo($this->path);
|
||||
$fileInfo = $this->view->getFileInfo($this->path);
|
||||
if ($fileInfo instanceof FileInfo) {
|
||||
$this->fileInfo = $fileInfo;
|
||||
} else {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
}
|
||||
return $this->fileInfo;
|
||||
}
|
||||
@@ -138,6 +152,8 @@ class Node implements \OCP\Files\Node {
|
||||
|
||||
/**
|
||||
* @return int
|
||||
* @throws InvalidPathException
|
||||
* @throws NotFoundException
|
||||
*/
|
||||
public function getId() {
|
||||
return $this->getFileInfo()->getId();
|
||||
@@ -152,6 +168,8 @@ class Node implements \OCP\Files\Node {
|
||||
|
||||
/**
|
||||
* @return int
|
||||
* @throws InvalidPathException
|
||||
* @throws NotFoundException
|
||||
*/
|
||||
public function getMTime() {
|
||||
return $this->getFileInfo()->getMTime();
|
||||
@@ -159,6 +177,8 @@ class Node implements \OCP\Files\Node {
|
||||
|
||||
/**
|
||||
* @return int
|
||||
* @throws InvalidPathException
|
||||
* @throws NotFoundException
|
||||
*/
|
||||
public function getSize() {
|
||||
return $this->getFileInfo()->getSize();
|
||||
@@ -166,6 +186,8 @@ class Node implements \OCP\Files\Node {
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws InvalidPathException
|
||||
* @throws NotFoundException
|
||||
*/
|
||||
public function getEtag() {
|
||||
return $this->getFileInfo()->getEtag();
|
||||
@@ -173,6 +195,8 @@ class Node implements \OCP\Files\Node {
|
||||
|
||||
/**
|
||||
* @return int
|
||||
* @throws InvalidPathException
|
||||
* @throws NotFoundException
|
||||
*/
|
||||
public function getPermissions() {
|
||||
return $this->getFileInfo()->getPermissions();
|
||||
@@ -180,6 +204,8 @@ class Node implements \OCP\Files\Node {
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws InvalidPathException
|
||||
* @throws NotFoundException
|
||||
*/
|
||||
public function isReadable() {
|
||||
return $this->getFileInfo()->isReadable();
|
||||
@@ -187,6 +213,8 @@ class Node implements \OCP\Files\Node {
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws InvalidPathException
|
||||
* @throws NotFoundException
|
||||
*/
|
||||
public function isUpdateable() {
|
||||
return $this->getFileInfo()->isUpdateable();
|
||||
@@ -194,6 +222,8 @@ class Node implements \OCP\Files\Node {
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws InvalidPathException
|
||||
* @throws NotFoundException
|
||||
*/
|
||||
public function isDeletable() {
|
||||
return $this->getFileInfo()->isDeletable();
|
||||
@@ -201,11 +231,18 @@ class Node implements \OCP\Files\Node {
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws InvalidPathException
|
||||
* @throws NotFoundException
|
||||
*/
|
||||
public function isShareable() {
|
||||
return $this->getFileInfo()->isShareable();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws InvalidPathException
|
||||
* @throws NotFoundException
|
||||
*/
|
||||
public function isCreatable() {
|
||||
return $this->getFileInfo()->isCreatable();
|
||||
}
|
||||
|
||||
@@ -33,10 +33,9 @@ class NoopScanner extends Scanner {
|
||||
*
|
||||
* @param string $file
|
||||
* @param int $reuseExisting
|
||||
* @param bool $parentExistsInCache
|
||||
* @return array with metadata of the scanned file
|
||||
* @return array an array of metadata of the scanned file
|
||||
*/
|
||||
public function scanFile($file, $reuseExisting = 0, $parentExistsInCache = false) {
|
||||
public function scanFile($file, $reuseExisting = 0) {
|
||||
return array();
|
||||
}
|
||||
|
||||
@@ -60,9 +59,8 @@ class NoopScanner extends Scanner {
|
||||
* @param int $reuse
|
||||
* @return int the size of the scanned folder or -1 if the size is unknown at this stage
|
||||
*/
|
||||
public function scanChildren($path, $recursive = Storage::SCAN_RECURSIVE, $reuse = -1) {
|
||||
$size = 0;
|
||||
return $size;
|
||||
public function scanChildren($path, $recursive = self::SCAN_RECURSIVE, $reuse = -1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -451,8 +451,11 @@ class View {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path1
|
||||
* @param string $path2
|
||||
* Rename/move a file or folder from the source path to target path.
|
||||
*
|
||||
* @param string $path1 source path
|
||||
* @param string $path2 target path
|
||||
*
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function rename($path1, $path2) {
|
||||
@@ -494,7 +497,7 @@ class View {
|
||||
$mount = $manager->find($absolutePath1 . $postFix1);
|
||||
$storage1 = $mount->getStorage();
|
||||
$internalPath1 = $mount->getInternalPath($absolutePath1 . $postFix1);
|
||||
list(, $internalPath2) = Filesystem::resolvePath($absolutePath2 . $postFix2);
|
||||
list($storage2, $internalPath2) = Filesystem::resolvePath($absolutePath2 . $postFix2);
|
||||
if ($internalPath1 === '' and $mount instanceof MoveableMount) {
|
||||
if ($this->isTargetAllowed($absolutePath2)) {
|
||||
/**
|
||||
@@ -523,8 +526,10 @@ class View {
|
||||
} else {
|
||||
$source = $this->fopen($path1 . $postFix1, 'r');
|
||||
$target = $this->fopen($path2 . $postFix2, 'w');
|
||||
list($count, $result) = \OC_Helper::streamCopy($source, $target);
|
||||
$this->touch($path2, $this->filemtime($path1));
|
||||
list(, $result) = \OC_Helper::streamCopy($source, $target);
|
||||
if ($result !== false) {
|
||||
$this->touch($path2, $this->filemtime($path1));
|
||||
}
|
||||
|
||||
// close open handle - especially $source is necessary because unlink below will
|
||||
// throw an exception on windows because the file is locked
|
||||
@@ -533,6 +538,11 @@ class View {
|
||||
|
||||
if ($result !== false) {
|
||||
$result &= $storage1->unlink($internalPath1);
|
||||
} else {
|
||||
// delete partially written target file
|
||||
$storage2->unlink($internalPath2);
|
||||
// delete cache entry that was created by fopen
|
||||
$storage2->getCache()->remove($internalPath2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -564,6 +574,15 @@ class View {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a file/folder from the source path to target path
|
||||
*
|
||||
* @param string $path1 source path
|
||||
* @param string $path2 target path
|
||||
* @param bool $preserveMtime whether to preserve mtime on the copy
|
||||
*
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function copy($path1, $path2, $preserveMtime = false) {
|
||||
$postFix1 = (substr($path1, -1, 1) === '/') ? '/' : '';
|
||||
$postFix2 = (substr($path2, -1, 1) === '/') ? '/' : '';
|
||||
@@ -603,6 +622,11 @@ class View {
|
||||
list(, $internalPath2) = Filesystem::resolvePath($absolutePath2 . $postFix2);
|
||||
if ($storage) {
|
||||
$result = $storage->copy($internalPath1, $internalPath2);
|
||||
if (!$result) {
|
||||
// delete partially written target file
|
||||
$storage->unlink($internalPath2);
|
||||
$storage->getCache()->remove($internalPath2);
|
||||
}
|
||||
} else {
|
||||
$result = false;
|
||||
}
|
||||
@@ -615,19 +639,27 @@ class View {
|
||||
if (is_resource($dh)) {
|
||||
while (($file = readdir($dh)) !== false) {
|
||||
if (!Filesystem::isIgnoredDir($file)) {
|
||||
$result = $this->copy($path1 . '/' . $file, $path2 . '/' . $file, $preserveMtime);
|
||||
if (!$this->copy($path1 . '/' . $file, $path2 . '/' . $file, $preserveMtime)) {
|
||||
$result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
list($storage2, $internalPath2) = Filesystem::resolvePath($absolutePath2 . $postFix2);
|
||||
$source = $this->fopen($path1 . $postFix1, 'r');
|
||||
$target = $this->fopen($path2 . $postFix2, 'w');
|
||||
list($count, $result) = \OC_Helper::streamCopy($source, $target);
|
||||
if($preserveMtime) {
|
||||
list(, $result) = \OC_Helper::streamCopy($source, $target);
|
||||
if($result && $preserveMtime) {
|
||||
$this->touch($path2, $this->filemtime($path1));
|
||||
}
|
||||
fclose($source);
|
||||
fclose($target);
|
||||
if (!$result) {
|
||||
// delete partially written target file
|
||||
$storage2->unlink($internalPath2);
|
||||
$storage2->getCache()->remove($internalPath2);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->updater->update($path2);
|
||||
@@ -1378,4 +1410,11 @@ class View {
|
||||
$mount
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Updater
|
||||
*/
|
||||
public function getUpdater(){
|
||||
return $this->updater;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -578,13 +578,23 @@ class OC_Helper {
|
||||
if (!$source or !$target) {
|
||||
return array(0, false);
|
||||
}
|
||||
$bufSize = 8192;
|
||||
$result = true;
|
||||
$count = 0;
|
||||
while (!feof($source)) {
|
||||
if (($c = fwrite($target, fread($source, 8192))) === false) {
|
||||
$buf = fread($source, $bufSize);
|
||||
$bytesWritten = fwrite($target, $buf);
|
||||
if ($bytesWritten !== false) {
|
||||
$count += $bytesWritten;
|
||||
}
|
||||
// note: strlen is expensive so only use it when necessary,
|
||||
// on the last block
|
||||
if ($bytesWritten === false
|
||||
|| ($bytesWritten < $bufSize && $bytesWritten < strlen($buf))
|
||||
) {
|
||||
// write error, could be disk full ?
|
||||
$result = false;
|
||||
} else {
|
||||
$count += $c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return array($count, $result);
|
||||
|
||||
@@ -214,7 +214,8 @@ class HTTPHelper {
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_POST, count($fields));
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $fieldsString);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, (string)$fieldsString);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
|
||||
if (is_readable($certBundle)) {
|
||||
curl_setopt($ch, CURLOPT_CAINFO, $certBundle);
|
||||
}
|
||||
|
||||
@@ -283,9 +283,12 @@ class OC_Image {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string Returns the raw image data.
|
||||
* @return null|string Returns the raw image data.
|
||||
*/
|
||||
function data() {
|
||||
if (!$this->valid()) {
|
||||
return null;
|
||||
}
|
||||
ob_start();
|
||||
switch ($this->mimeType) {
|
||||
case "image/png":
|
||||
@@ -391,7 +394,7 @@ class OC_Image {
|
||||
$rotate = 90;
|
||||
break;
|
||||
}
|
||||
if($flip) {
|
||||
if($flip && function_exists('imageflip')) {
|
||||
imageflip($this->resource, IMG_FLIP_HORIZONTAL);
|
||||
}
|
||||
if ($rotate) {
|
||||
|
||||
@@ -241,7 +241,7 @@ class OC_Installer{
|
||||
if(!isset($data['href'])) {
|
||||
throw new \Exception($l->t("No href specified when installing app from http"));
|
||||
}
|
||||
copy($data['href'], $path);
|
||||
file_put_contents($path, \OC_Util::getUrlContent($data['href']));
|
||||
}else{
|
||||
if(!isset($data['path'])) {
|
||||
throw new \Exception($l->t("No path specified when installing app from local file"));
|
||||
|
||||
@@ -28,10 +28,11 @@ class OC_Mail {
|
||||
* @param string $ccaddress
|
||||
* @param string $ccname
|
||||
* @param string $bcc
|
||||
* @param string $replyTo
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function send($toaddress, $toname, $subject, $mailtext, $fromaddress, $fromname,
|
||||
$html=0, $altbody='', $ccaddress='', $ccname='', $bcc='') {
|
||||
$html=0, $altbody='', $ccaddress='', $ccname='', $bcc='', $replyTo='') {
|
||||
|
||||
$SMTPMODE = OC_Config::getValue( 'mail_smtpmode', 'sendmail' );
|
||||
$SMTPHOST = OC_Config::getValue( 'mail_smtphost', '127.0.0.1' );
|
||||
@@ -79,7 +80,9 @@ class OC_Mail {
|
||||
if($ccaddress != '') $mailo->AddCC($ccaddress, $ccname);
|
||||
if($bcc != '') $mailo->AddBCC($bcc);
|
||||
|
||||
$mailo->AddReplyTo($fromaddress, $fromname);
|
||||
if($replyTo !== '') {
|
||||
$mailo->addReplyTo($replyTo);
|
||||
}
|
||||
|
||||
$mailo->WordWrap = 78;
|
||||
$mailo->IsHTML($html == 1);
|
||||
|
||||
@@ -12,8 +12,12 @@ class APCu extends APC {
|
||||
static public function isAvailable() {
|
||||
if (!extension_loaded('apcu')) {
|
||||
return false;
|
||||
} elseif (!ini_get('apc.enabled')) {
|
||||
return false;
|
||||
} elseif (!ini_get('apc.enable_cli') && \OC::$CLI) {
|
||||
return false;
|
||||
} elseif (version_compare(phpversion('apc'), '4.0.6') === -1) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
namespace OC;
|
||||
|
||||
use OC\Preview\Provider;
|
||||
use OCP\Files\FileInfo;
|
||||
use OCP\Files\NotFoundException;
|
||||
|
||||
class Preview {
|
||||
@@ -327,21 +328,21 @@ class Preview {
|
||||
* deletes all previews of a file
|
||||
*/
|
||||
public function deleteAllPreviews() {
|
||||
$file = $this->getFile();
|
||||
|
||||
$fileInfo = $this->getFileInfo($file);
|
||||
|
||||
$toDelete = $this->getChildren();
|
||||
$toDelete[] = $fileInfo;
|
||||
$toDelete[] = $this->getFileInfo();
|
||||
|
||||
foreach ($toDelete as $delete) {
|
||||
if ($delete !== null && $delete !== false) {
|
||||
if ($delete instanceof FileInfo) {
|
||||
/** @var \OCP\Files\FileInfo $delete */
|
||||
$fileId = $delete->getId();
|
||||
|
||||
$previewPath = $this->getPreviewPath($fileId);
|
||||
$this->userView->deleteAll($previewPath);
|
||||
$this->userView->rmdir($previewPath);
|
||||
// getId() might return null, e.g. when the file is a
|
||||
// .ocTransferId*.part file from chunked file upload.
|
||||
if (!empty($fileId)) {
|
||||
$previewPath = $this->getPreviewPath($fileId);
|
||||
$this->userView->deleteAll($previewPath);
|
||||
$this->userView->rmdir($previewPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user