summaryrefslogtreecommitdiffstats
path: root/apps/files_sharing
diff options
context:
space:
mode:
authorLukas Reschke <lukas@statuscode.ch>2016-06-10 18:29:09 +0200
committerGitHub <noreply@github.com>2016-06-10 18:29:09 +0200
commit842cc2a7889d1ff8004fddd2546aec1232e0eaed (patch)
treee309a759b4ebee9ab9fa32d839d8ebb819c145f6 /apps/files_sharing
parent74580daa23016fab370b2f6c14d82401032733cb (diff)
parent54e2ac57130666add0ad5d3c583c6f29527b4ebc (diff)
downloadnextcloud-server-842cc2a7889d1ff8004fddd2546aec1232e0eaed.tar.gz
nextcloud-server-842cc2a7889d1ff8004fddd2546aec1232e0eaed.zip
Merge pull request #19 from nextcloud/files-drop
add "hide file list" option
Diffstat (limited to 'apps/files_sharing')
-rw-r--r--apps/files_sharing/ajax/publicpreview.php7
-rw-r--r--apps/files_sharing/ajax/shareinfo.php5
-rw-r--r--apps/files_sharing/css/public.css59
-rw-r--r--apps/files_sharing/js/files_drop.js81
-rw-r--r--apps/files_sharing/js/public.js4
-rw-r--r--apps/files_sharing/lib/API/Share20OCS.php1
-rw-r--r--apps/files_sharing/lib/Controllers/ShareController.php14
-rw-r--r--apps/files_sharing/templates/public.php72
-rw-r--r--apps/files_sharing/tests/Controllers/ShareControllerTest.php28
9 files changed, 249 insertions, 22 deletions
diff --git a/apps/files_sharing/ajax/publicpreview.php b/apps/files_sharing/ajax/publicpreview.php
index 5999740af31..c02d475a769 100644
--- a/apps/files_sharing/ajax/publicpreview.php
+++ b/apps/files_sharing/ajax/publicpreview.php
@@ -42,6 +42,13 @@ if($token === ''){
}
$linkedItem = \OCP\Share::getShareByToken($token);
+$shareManager = \OC::$server->getShareManager();
+$share = $shareManager->getShareByToken($token);
+if(!($share->getPermissions() & \OCP\Constants::PERMISSION_READ)) {
+ OCP\JSON::error(array('data' => 'Share is not readable.'));
+ exit();
+}
+
if($linkedItem === false || ($linkedItem['item_type'] !== 'file' && $linkedItem['item_type'] !== 'folder')) {
\OC_Response::setStatus(\OC_Response::STATUS_NOT_FOUND);
\OCP\Util::writeLog('core-preview', 'Passed token parameter is not valid', \OCP\Util::DEBUG);
diff --git a/apps/files_sharing/ajax/shareinfo.php b/apps/files_sharing/ajax/shareinfo.php
index acf58a2431a..002d7ab275e 100644
--- a/apps/files_sharing/ajax/shareinfo.php
+++ b/apps/files_sharing/ajax/shareinfo.php
@@ -71,6 +71,11 @@ $shareManager = \OC::$server->getShareManager();
$share = $shareManager->getShareByToken($token);
$sharePermissions= (int)$share->getPermissions();
+if(!($share->getPermissions() & \OCP\Constants::PERMISSION_READ)) {
+ OCP\JSON::error(array('data' => 'Share is not readable.'));
+ exit();
+}
+
/**
* @param \OCP\Files\FileInfo $dir
* @param \OC\Files\View $view
diff --git a/apps/files_sharing/css/public.css b/apps/files_sharing/css/public.css
index d09947dab26..c998501dad6 100644
--- a/apps/files_sharing/css/public.css
+++ b/apps/files_sharing/css/public.css
@@ -158,3 +158,62 @@ thead {
opacity: 1;
cursor: pointer;
}
+
+#public-upload .avatardiv {
+ margin: 0 auto;
+}
+
+#public-upload #emptycontent h2 {
+ margin: 10px 0 5px 0;
+}
+
+#public-upload #emptycontent h2+p {
+ margin-bottom: 30px;
+}
+
+#public-upload #emptycontent .icon-folder {
+ height: 16px;
+ width: 16px;
+ background-size: 16px;
+ display: inline-block;
+ vertical-align: text-top;
+ margin-bottom: 0;
+ margin-right: 5px;
+ opacity: 1;
+}
+
+#public-upload #emptycontent .button {
+ background-size: 16px;
+ height: 16px;
+ width: 16px;
+ background-position: 16px;
+ opacity: .7;
+ font-size: 20px;
+ margin: 20px;
+ padding: 10px 20px;
+ padding-left: 42px;
+ font-weight: normal;
+}
+
+#public-upload #emptycontent ul {
+ width: 160px;
+ margin: 5px auto;
+ text-align: left;
+}
+
+#public-upload #emptycontent li {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ padding: 7px 0;
+}
+
+#public-upload #emptycontent li img {
+ vertical-align: text-bottom;
+ margin-right: 5px;
+}
+
+#public-upload li span.icon-loading-small {
+ padding-left: 18px;
+ margin-right: 7px;
+}
diff --git a/apps/files_sharing/js/files_drop.js b/apps/files_sharing/js/files_drop.js
new file mode 100644
index 00000000000..0a6a1c7567f
--- /dev/null
+++ b/apps/files_sharing/js/files_drop.js
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2016 Lukas Reschke <lukas@statuscode.ch>
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+(function ($) {
+ var Drop = {
+ initialize: function () {
+ $(document).bind('drop dragover', function (e) {
+ // Prevent the default browser drop action:
+ e.preventDefault();
+ });
+ $('#public-upload').fileupload({
+ url: OC.linkTo('files', 'ajax/upload.php'),
+ dataType: 'json',
+ dropZone: $('#public-upload'),
+ formData: {
+ dirToken: $('#sharingToken').val()
+ },
+ add: function(e, data) {
+ var errors = [];
+ if(data.files[0]['size'] && data.files[0]['size'] > $('#maxFilesizeUpload').val()) {
+ errors.push('File is too big');
+ }
+
+ $('#drop-upload-done-indicator').addClass('hidden');
+ $('#drop-upload-progress-indicator').removeClass('hidden');
+ _.each(data['files'], function(file) {
+ if(errors.length === 0) {
+ $('#public-upload ul').append('<li data-toggle="tooltip" title="'+escapeHTML(file.name)+'" data-name="'+escapeHTML(file.name)+'"><span class="icon-loading-small"></span> '+escapeHTML(file.name)+'</li>');
+ $('[data-toggle="tooltip"]').tooltip();
+ data.submit();
+ } else {
+ OC.Notification.showTemporary(OC.L10N.translate('files_sharing', 'Could not upload "{filename}"', {filename: file.name}));
+ $('#public-upload ul').append('<li data-toggle="tooltip" title="'+escapeHTML(file.name)+'" data-name="'+escapeHTML(file.name)+'"><img src="'+OC.imagePath('core', 'actions/error.svg')+'"/> '+escapeHTML(file.name)+'</li>');
+ $('[data-toggle="tooltip"]').tooltip();
+ }
+ });
+ },
+ success: function (response) {
+ if(response.status !== 'error') {
+ var mimeTypeUrl = OC.MimeType.getIconUrl(response['mimetype']);
+ $('#public-upload ul li[data-name="' + escapeHTML(response['filename']) + '"]').html('<img src="' + escapeHTML(mimeTypeUrl) + '"/> ' + escapeHTML(response['filename']));
+ $('[data-toggle="tooltip"]').tooltip();
+ }
+ },
+ progressall: function (e, data) {
+ var progress = parseInt(data.loaded / data.total * 100, 10);
+ if(progress === 100) {
+ $('#drop-upload-done-indicator').removeClass('hidden');
+ $('#drop-upload-progress-indicator').addClass('hidden');
+ } else {
+ $('#drop-upload-done-indicator').addClass('hidden');
+ $('#drop-upload-progress-indicator').removeClass('hidden');
+ }
+ }
+ });
+ $('#public-upload .button.icon-upload').click(function(e) {
+ e.preventDefault();
+ $('#public-upload #emptycontent input').focus().trigger('click');
+ });
+ }
+ };
+
+ $(document).ready(function() {
+ if($('#upload-only-interface').val() === "1") {
+ $('.avatardiv').avatar($('#sharingUserId').val(), 128, true);
+ }
+
+ OCA.Files_Sharing_Drop = Drop;
+ OCA.Files_Sharing_Drop.initialize();
+ });
+
+
+})(jQuery);
+
diff --git a/apps/files_sharing/js/public.js b/apps/files_sharing/js/public.js
index 572ccc47b71..f207eff7909 100644
--- a/apps/files_sharing/js/public.js
+++ b/apps/files_sharing/js/public.js
@@ -302,7 +302,7 @@ OCA.Sharing.PublicApp = {
$('#save-button-confirm')
.removeClass("icon-loading-small")
.addClass("icon-confirm");
-
+
}
else {
$('#save-button-confirm')
@@ -314,7 +314,7 @@ OCA.Sharing.PublicApp = {
toggleLoading();
var location = window.location.protocol + '//' + window.location.host + OC.webroot;
-
+
if(remote.substr(-1) !== '/') {
remote += '/'
};
diff --git a/apps/files_sharing/lib/API/Share20OCS.php b/apps/files_sharing/lib/API/Share20OCS.php
index 90e1f19130c..b10c51ce2c9 100644
--- a/apps/files_sharing/lib/API/Share20OCS.php
+++ b/apps/files_sharing/lib/API/Share20OCS.php
@@ -602,6 +602,7 @@ class Share20OCS {
if ($newPermissions !== null &&
$newPermissions !== \OCP\Constants::PERMISSION_READ &&
+ $newPermissions !== (\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE) &&
$newPermissions !== (\OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_UPDATE)) {
$share->getNode()->unlock(ILockingProvider::LOCK_SHARED);
return new \OC_OCS_Result(null, 400, $this->l->t('Can\'t change permissions for public share links'));
diff --git a/apps/files_sharing/lib/Controllers/ShareController.php b/apps/files_sharing/lib/Controllers/ShareController.php
index 96c0a0ca556..56f94b91c80 100644
--- a/apps/files_sharing/lib/Controllers/ShareController.php
+++ b/apps/files_sharing/lib/Controllers/ShareController.php
@@ -49,7 +49,6 @@ use OCP\ILogger;
use OCP\IUserManager;
use OCP\ISession;
use OCP\IPreview;
-use OCA\Files_Sharing\Helper;
use OCP\Util;
use OCA\Files_Sharing\Activity;
use \OCP\Files\NotFoundException;
@@ -253,6 +252,7 @@ class ShareController extends Controller {
* @param string $path
* @return TemplateResponse|RedirectResponse
* @throws NotFoundException
+ * @throws \Exception
*/
public function showShare($token, $path = '') {
\OC_User::setIncognitoMode(true);
@@ -314,6 +314,7 @@ class ShareController extends Controller {
$shareTmpl['fileSize'] = \OCP\Util::humanFileSize($share->getNode()->getSize());
// Show file list
+ $hideFileList = false;
if ($share->getNode() instanceof \OCP\Files\Folder) {
$shareTmpl['dir'] = $rootFolder->getRelativePath($path->getPath());
@@ -329,12 +330,14 @@ class ShareController extends Controller {
$uploadLimit = Util::uploadLimit();
$maxUploadFilesize = min($freeSpace, $uploadLimit);
+ $hideFileList = $share->getPermissions() & \OCP\Constants::PERMISSION_READ ? false : true;
$folder = new Template('files', 'list', '');
$folder->assign('dir', $rootFolder->getRelativePath($path->getPath()));
$folder->assign('dirToken', $token);
$folder->assign('permissions', \OCP\Constants::PERMISSION_READ);
$folder->assign('isPublic', true);
+ $folder->assign('hideFileList', $hideFileList);
$folder->assign('publicUploadEnabled', 'no');
$folder->assign('uploadMaxFilesize', $maxUploadFilesize);
$folder->assign('uploadMaxHumanFilesize', OCP\Util::humanFileSize($maxUploadFilesize));
@@ -345,6 +348,8 @@ class ShareController extends Controller {
$shareTmpl['folder'] = $folder->fetchPage();
}
+ $shareTmpl['hideFileList'] = $hideFileList;
+ $shareTmpl['shareOwner'] = $this->userManager->get($share->getShareOwner())->getDisplayName();
$shareTmpl['downloadURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.downloadShare', array('token' => $token));
$shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
$shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
@@ -369,13 +374,18 @@ class ShareController extends Controller {
* @param string $files
* @param string $path
* @param string $downloadStartSecret
- * @return void|RedirectResponse
+ * @return void|OCP\AppFramework\Http\Response
+ * @throws NotFoundException
*/
public function downloadShare($token, $files = null, $path = '', $downloadStartSecret = '') {
\OC_User::setIncognitoMode(true);
$share = $this->shareManager->getShareByToken($token);
+ if(!($share->getPermissions() & \OCP\Constants::PERMISSION_READ)) {
+ return new OCP\AppFramework\Http\DataResponse('Share is read-only');
+ }
+
// Share is password protected - check whether the user is permitted to access the share
if ($share->getPassword() !== null && !$this->linkShareAuth($share)) {
return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.authenticate',
diff --git a/apps/files_sharing/templates/public.php b/apps/files_sharing/templates/public.php
index e39d1b08076..c15001ad24b 100644
--- a/apps/files_sharing/templates/public.php
+++ b/apps/files_sharing/templates/public.php
@@ -9,6 +9,7 @@ OCP\Util::addScript('files_sharing', 'public');
OCP\Util::addScript('files', 'fileactions');
OCP\Util::addScript('files', 'fileactionsmenu');
OCP\Util::addScript('files', 'jquery.fileupload');
+OCP\Util::addScript('files_sharing', 'files_drop');
// JS required for folders
OCP\Util::addStyle('files', 'files');
@@ -30,6 +31,7 @@ OCP\Util::addscript('files', 'keyboardshortcuts');
<div id="notification" style="display: none;"></div>
</div>
+<input type="hidden" id="sharingUserId" value="<?php p($_['owner']) ?>">
<input type="hidden" id="filesApp" name="filesApp" value="1">
<input type="hidden" id="isPublic" name="isPublic" value="1">
<input type="hidden" name="dir" value="<?php p($_['dir']) ?>" id="dir">
@@ -39,7 +41,16 @@ OCP\Util::addscript('files', 'keyboardshortcuts');
<input type="hidden" name="mimetype" value="<?php p($_['mimetype']) ?>" id="mimetype">
<input type="hidden" name="previewSupported" value="<?php p($_['previewSupported'] ? 'true' : 'false'); ?>" id="previewSupported">
<input type="hidden" name="mimetypeIcon" value="<?php p(\OC::$server->getMimeTypeDetector()->mimeTypeIcon($_['mimetype'])); ?>" id="mimetypeIcon">
-<input type="hidden" name="filesize" value="<?php p($_['nonHumanFileSize']); ?>" id="filesize">
+<?php
+$upload_max_filesize = OC::$server->getIniWrapper()->getBytes('upload_max_filesize');
+$post_max_size = OC::$server->getIniWrapper()->getBytes('post_max_size');
+$maxUploadFilesize = min($upload_max_filesize, $post_max_size);
+?>
+<input type="hidden" name="maxFilesizeUpload" value="<?php p($maxUploadFilesize); ?>" id="maxFilesizeUpload">
+
+<?php if (!isset($_['hideFileList']) || (isset($_['hideFileList']) && $_['hideFileList'] === false)): ?>
+ <input type="hidden" name="filesize" value="<?php p($_['nonHumanFileSize']); ?>" id="filesize">
+<?php endif; ?>
<input type="hidden" name="maxSizeAnimateGif" value="<?php p($_['maxSizeAnimateGif']); ?>" id="maxSizeAnimateGif">
@@ -66,27 +77,30 @@ OCP\Util::addscript('files', 'keyboardshortcuts');
<div class="header-right">
<span id="details">
<?php
- if ($_['server2serversharing']) {
- ?>
- <span id="save" data-protected="<?php p($_['protected']) ?>"
- data-owner-display-name="<?php p($_['displayName']) ?>" data-owner="<?php p($_['owner']) ?>" data-name="<?php p($_['filename']) ?>">
- <button id="save-button"><?php p($l->t('Add to your ownCloud')) ?></button>
- <form class="save-form hidden" action="#">
- <input type="text" id="remote_address" placeholder="example.com/owncloud"/>
- <button id="save-button-confirm" class="icon-confirm svg" disabled></button>
- </form>
- </span>
+ if (!isset($_['hideFileList']) || (isset($_['hideFileList']) && $_['hideFileList'] === false)) {
+ if ($_['server2serversharing']) {
+ ?>
+ <span id="save" data-protected="<?php p($_['protected']) ?>"
+ data-owner-display-name="<?php p($_['displayName']) ?>" data-owner="<?php p($_['owner']) ?>" data-name="<?php p($_['filename']) ?>">
+ <button id="save-button"><?php p($l->t('Add to your ownCloud')) ?></button>
+ <form class="save-form hidden" action="#">
+ <input type="text" id="remote_address" placeholder="example.com/owncloud"/>
+ <button id="save-button-confirm" class="icon-confirm svg" disabled></button>
+ </form>
+ </span>
+ <?php } ?>
+ <a href="<?php p($_['downloadURL']); ?>" id="download" class="button">
+ <img class="svg" alt="" src="<?php print_unescaped(image_path("core", "actions/download.svg")); ?>"/>
+ <span id="download-text"><?php p($l->t('Download'))?></span>
+ </a>
<?php } ?>
- <a href="<?php p($_['downloadURL']); ?>" id="download" class="button">
- <img class="svg" alt="" src="<?php print_unescaped(image_path("core", "actions/download.svg")); ?>"/>
- <span id="download-text"><?php p($l->t('Download'))?></span>
- </a>
</span>
</div>
-</div></header>
+ </div></header>
<div id="content-wrapper">
+ <?php if (!isset($_['hideFileList']) || (isset($_['hideFileList']) && $_['hideFileList'] === false)) { ?>
<div id="content">
- <div id="preview">
+ <div id="preview">
<?php if (isset($_['folder'])): ?>
<?php print_unescaped($_['folder']); ?>
<?php else: ?>
@@ -112,7 +126,31 @@ OCP\Util::addscript('files', 'keyboardshortcuts');
</div>
<?php endif; ?>
</div>
+ <?php } else { ?>
+ <input type="hidden" id="upload-only-interface" value="1"/>
+ <div id="public-upload">
+ <div id="emptycontent" class="">
+ <div id="displayavatar"><div class="avatardiv"></div></div>
+ <h2><?php p($l->t('Upload files to %s', [$_['shareOwner']])) ?></h2>
+ <p><span class="icon-folder"></span> <?php p($_['filename']) ?></p>
+ <input type="file" name="files[]" class="hidden" multiple>
+
+ <a href="#" class="button icon-upload"><?php p($l->t('Select or drop files')) ?></a>
+ <div id="drop-upload-progress-indicator" style="padding-top: 25px;" class="hidden"><?php p($l->t('Uploading files…')) ?></div>
+ <div id="drop-upload-done-indicator" style="padding-top: 25px;" class="hidden"><?php p($l->t('Uploaded files:')) ?></div>
+ <ul>
+ </ul>
+ </div>
+ </div>
+ <?php } ?>
+</div>
+<?php if (!isset($_['hideFileList']) || (isset($_['hideFileList']) && $_['hideFileList'] !== true)): ?>
+ <input type="hidden" name="dir" id="dir" value="" />
+ <div class="hiddenuploadfield">
+ <input type="file" id="file_upload_start" class="hiddenuploadfield" name="files[]"
+ data-url="<?php print_unescaped(OCP\Util::linkTo('files', 'ajax/upload.php')); ?>" />
</div>
+ <?php endif; ?>
<footer>
<p class="info">
<?php print_unescaped($theme->getLongFooter()); ?>
diff --git a/apps/files_sharing/tests/Controllers/ShareControllerTest.php b/apps/files_sharing/tests/Controllers/ShareControllerTest.php
index d97b3a14928..0c35449fb1a 100644
--- a/apps/files_sharing/tests/Controllers/ShareControllerTest.php
+++ b/apps/files_sharing/tests/Controllers/ShareControllerTest.php
@@ -32,6 +32,7 @@ namespace OCA\Files_Sharing\Tests\Controllers;
use OC\Files\Filesystem;
use OCA\FederatedFileSharing\FederatedShareProvider;
use OCA\Files_Sharing\Controllers\ShareController;
+use OCP\AppFramework\Http\DataResponse;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\AppFramework\Http\NotFoundResponse;
use OCP\AppFramework\Http\RedirectResponse;
@@ -372,6 +373,8 @@ class ShareControllerTest extends \Test\TestCase {
'previewEnabled' => true,
'previewMaxX' => 1024,
'previewMaxY' => 1024,
+ 'hideFileList' => false,
+ 'shareOwner' => 'ownerDisplay'
);
$csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
@@ -430,10 +433,13 @@ class ShareControllerTest extends \Test\TestCase {
$this->shareController->showShare('token');
}
-
public function testDownloadShare() {
$share = $this->getMock('\OCP\Share\IShare');
$share->method('getPassword')->willReturn('password');
+ $share
+ ->expects($this->once())
+ ->method('getPermissions')
+ ->willReturn(\OCP\Constants::PERMISSION_READ);
$this->shareManager
->expects($this->once())
@@ -452,4 +458,24 @@ class ShareControllerTest extends \Test\TestCase {
$this->assertEquals($expectedResponse, $response);
}
+ public function testDownloadShareWithCreateOnlyShare() {
+ $share = $this->getMock('\OCP\Share\IShare');
+ $share->method('getPassword')->willReturn('password');
+ $share
+ ->expects($this->once())
+ ->method('getPermissions')
+ ->willReturn(\OCP\Constants::PERMISSION_CREATE);
+
+ $this->shareManager
+ ->expects($this->once())
+ ->method('getShareByToken')
+ ->with('validtoken')
+ ->willReturn($share);
+
+ // Test with a password protected share and no authentication
+ $response = $this->shareController->downloadShare('validtoken');
+ $expectedResponse = new DataResponse('Share is read-only');
+ $this->assertEquals($expectedResponse, $response);
+ }
+
}