/* * Copyright (c) 2014 * @copyright Copyright (c) 2016, Björn Schießle * * This file is licensed under the Affero General Public License version 3 * or later. * * See the COPYING-README file. * */ /* global FileActions, Files, FileList */ /* global dragOptions, folderDropOptions */ if (!OCA.Sharing) { OCA.Sharing = {}; } if (!OCA.Files) { OCA.Files = {}; } /** * @namespace */ OCA.Sharing.PublicApp = { _initialized: false, /** * Initializes the public share app. * * @param $el container */ initialize: function ($el) { var self = this; var fileActions; if (this._initialized) { return; } fileActions = new OCA.Files.FileActions(); // default actions fileActions.registerDefaultActions(); // legacy actions fileActions.merge(window.FileActions); // regular actions fileActions.merge(OCA.Files.fileActions); // in case apps would decide to register file actions later, // replace the global object with this one OCA.Files.fileActions = fileActions; this._initialized = true; this.initialDir = $('#dir').val(); var token = $('#sharingToken').val(); // file list mode ? if ($el.find('#filestable').length) { var filesClient = new OC.Files.Client({ host: OC.getHost(), port: OC.getPort(), userName: token, // note: password not be required, the endpoint // will recognize previous validation from the session root: OC.getRootPath() + '/public.php/webdav', useHTTPS: OC.getProtocol() === 'https' }); this.fileList = new OCA.Files.FileList( $el, { id: 'files.public', scrollContainer: $('#content-wrapper'), dragOptions: dragOptions, folderDropOptions: folderDropOptions, fileActions: fileActions, detailsViewEnabled: false, filesClient: filesClient, enableUpload: true } ); this.files = OCA.Files.Files; this.files.initialize(); // TODO: move to PublicFileList.initialize() once // the code was split into a separate class OC.Plugins.attach('OCA.Sharing.PublicFileList', this.fileList); } var mimetype = $('#mimetype').val(); var mimetypeIcon = $('#mimetypeIcon').val(); mimetypeIcon = mimetypeIcon.substring(0, mimetypeIcon.length - 3); mimetypeIcon = mimetypeIcon + 'svg'; var previewSupported = $('#previewSupported').val(); if (typeof FileActions !== 'undefined') { // Show file preview if previewer is available, images are already handled by the template if (mimetype.substr(0, mimetype.indexOf('/')) !== 'image' && $('.publicpreview').length === 0) { // Trigger default action if not download TODO var action = FileActions.getDefault(mimetype, 'file', OC.PERMISSION_READ); if (typeof action !== 'undefined') { action($('#filename').val()); } } } // dynamically load image previews var bottomMargin = 350; var previewWidth = $(window).width(); var previewHeight = $(window).height() - bottomMargin; previewHeight = Math.max(200, previewHeight); var params = { x: Math.ceil(previewWidth * window.devicePixelRatio), y: Math.ceil(previewHeight * window.devicePixelRatio), a: 'true', file: encodeURIComponent(this.initialDir + $('#filename').val()), t: token, scalingup: 0 }; var img = $(''); img.css({ 'max-width': previewWidth, 'max-height': previewHeight }); var fileSize = parseInt($('#filesize').val(), 10); var maxGifSize = parseInt($('#maxSizeAnimateGif').val(), 10); if (mimetype === 'image/gif' && (maxGifSize === -1 || fileSize <= (maxGifSize * 1024 * 1024))) { img.attr('src', $('#downloadURL').val()); img.appendTo('#imgframe'); } else if (mimetype.substr(0, mimetype.indexOf('/')) === 'text' && window.btoa) { // Undocumented Url to public WebDAV endpoint var url = parent.location.protocol + '//' + location.host + OC.linkTo('', 'public.php/webdav'); $.ajax({ url: url, headers: { Authorization: 'Basic ' + btoa(token + ':'), Range: 'bytes=0-1000' } }).then(function (data) { self._showTextPreview(data, previewHeight); }); } else if ((previewSupported === 'true' && mimetype.substr(0, mimetype.indexOf('/')) !== 'video') || mimetype.substr(0, mimetype.indexOf('/')) === 'image' && mimetype !== 'image/svg+xml') { img.attr('src', OC.filePath('files_sharing', 'ajax', 'publicpreview.php') + '?' + OC.buildQueryString(params)); img.appendTo('#imgframe'); } else if (mimetype.substr(0, mimetype.indexOf('/')) !== 'video') { img.attr('src', OC.Util.replaceSVGIcon(mimetypeIcon)); img.attr('width', 128); img.appendTo('#imgframe'); } else if (previewSupported === 'true') { $('#imgframe > video').attr('poster', OC.filePath('files_sharing', 'ajax', 'publicpreview.php') + '?' + OC.buildQueryString(params)); } if (this.fileList) { // TODO: move this to a separate PublicFileList class that extends OCA.Files.FileList (+ unit tests) this.fileList.getDownloadUrl = function (filename, dir, isDir) { var path = dir || this.getCurrentDirectory(); if (_.isArray(filename)) { filename = JSON.stringify(filename); } var params = { path: path }; if (filename) { params.files = filename; } return OC.generateUrl('/s/' + token + '/download') + '?' + OC.buildQueryString(params); }; this.fileList.getUploadUrl = function(fileName, dir) { if (_.isUndefined(dir)) { dir = this.getCurrentDirectory(); } var pathSections = dir.split('/'); if (!_.isUndefined(fileName)) { pathSections.push(fileName); } var encodedPath = ''; _.each(pathSections, function(section) { if (section !== '') { encodedPath += '/' + encodeURIComponent(section); } }); var base = ''; if (!this._uploader.isXHRUpload()) { // also add auth in URL due to POST workaround base = OC.getProtocol() + '://' + token + '@' + OC.getHost() + (OC.getPort() ? ':' + OC.getPort() : ''); } return base + OC.getRootPath() + '/public.php/webdav' + encodedPath; }; this.fileList.getAjaxUrl = function (action, params) { params = params || {}; params.t = token; return OC.filePath('files_sharing', 'ajax', action + '.php') + '?' + OC.buildQueryString(params); }; this.fileList.linkTo = function (dir) { return OC.generateUrl('/s/' + token + '', {dir: dir}); }; this.fileList.generatePreviewUrl = function (urlSpec) { urlSpec = urlSpec || {}; if (!urlSpec.x) { urlSpec.x = 32; } if (!urlSpec.y) { urlSpec.y = 32; } urlSpec.x *= window.devicePixelRatio; urlSpec.y *= window.devicePixelRatio; urlSpec.x = Math.ceil(urlSpec.x); urlSpec.y = Math.ceil(urlSpec.y); urlSpec.t = $('#dirToken').val(); return OC.generateUrl('/apps/files_sharing/ajax/publicpreview.php?') + $.param(urlSpec); }; this.fileList.updateEmptyContent = function() { this.$el.find('#emptycontent .uploadmessage').text( t('files_sharing', 'You can upload into this folder') ); OCA.Files.FileList.prototype.updateEmptyContent.apply(this, arguments); }; this.fileList._uploader.on('fileuploadadd', function(e, data) { if (!data.headers) { data.headers = {}; } data.headers.Authorization = 'Basic ' + btoa(token + ':'); }); // do not allow sharing from the public page delete this.fileList.fileActions.actions.all.Share; this.fileList.changeDirectory(this.initialDir || '/', false, true); // URL history handling this.fileList.$el.on('changeDirectory', _.bind(this._onDirectoryChanged, this)); OC.Util.History.addOnPopStateHandler(_.bind(this._onUrlChanged, this)); $('#download').click(function (e) { e.preventDefault(); OC.redirect(FileList.getDownloadUrl()); }); } $(document).on('click', '#directLink', function () { $(this).focus(); $(this).select(); }); $('.save-form').submit(function (event) { event.preventDefault(); var remote = $(this).find('input[type="email"]').val(); var token = $('#sharingToken').val(); var owner = $('#save').data('owner'); var ownerDisplayName = $('#save').data('owner-display-name'); var name = $('#save').data('name'); var isProtected = $('#save').data('protected') ? 1 : 0; OCA.Sharing.PublicApp._createFederatedShare(remote, token, owner, ownerDisplayName, name, isProtected); }); $('#remote_address').on("keyup paste", function() { if ($(this).val() === '') { $('#save-button-confirm').prop('disabled', true); } else { $('#save-button-confirm').prop('disabled', false); } }); $('#save #save-button').click(function () { $(this).hide(); $('.save-form').css('display', 'inline'); $('#remote_address').focus(); }); // legacy window.FileList = this.fileList; }, _showTextPreview: function (data, previewHeight) { var textDiv = $('
').addClass('text-preview'); textDiv.text(data); textDiv.appendTo('#imgframe'); var divHeight = textDiv.height(); if (data.length > 999) { var ellipsis = $('
').addClass('ellipsis'); ellipsis.html('(…)'); ellipsis.appendTo('#imgframe'); } if (divHeight > previewHeight) { textDiv.height(previewHeight); } }, _onDirectoryChanged: function (e) { OC.Util.History.pushState({ // arghhhh, why is this not called "dir" !? path: e.dir }); }, _onUrlChanged: function (params) { this.fileList.changeDirectory(params.path || params.dir, false, true); }, /** * fall back to old behaviour where we redirect the user to his server to mount * the public link instead of creating a dedicated federated share * * @param remote * @param token * @param owner * @param ownerDisplayName * @param name * @param isProtected * @private */ _legacyCreateFederatedShare: function (remote, token, owner, ownerDisplayName, name, isProtected) { var location = window.location.protocol + '//' + window.location.host + OC.webroot; if(remote.substr(-1) !== '/') { remote += '/' } var url = remote + 'index.php/apps/files#' + 'remote=' + encodeURIComponent(location) // our location is the remote for the other server + "&token=" + encodeURIComponent(token) + "&owner=" + encodeURIComponent(owner) +"&ownerDisplayName=" + encodeURIComponent(ownerDisplayName) + "&name=" + encodeURIComponent(name) + "&protected=" + isProtected; if (remote.indexOf('://') > 0) { OC.redirect(url); } else { // if no protocol is specified, we automatically detect it by testing https and http // this check needs to happen on the server due to the Content Security Policy directive $.get(OC.generateUrl('apps/files_sharing/testremote'), {remote: remote}).then(function (protocol) { if (protocol !== 'http' && protocol !== 'https') { OC.dialogs.alert(t('files_sharing', 'No compatible server found at {remote}', {remote: remote}), t('files_sharing', 'Invalid server URL')); } else { OC.redirect(protocol + '://' + url); } }); } }, _createFederatedShare: function (remote, token, owner, ownerDisplayName, name, isProtected) { var toggleLoading = function() { var iconClass = $('#save-button-confirm').attr('class'); var loading = iconClass.indexOf('icon-loading-small') !== -1; if(loading) { $('#save-button-confirm') .removeClass("icon-loading-small") .addClass("icon-confirm"); } else { $('#save-button-confirm') .removeClass("icon-confirm") .addClass("icon-loading-small"); } }; toggleLoading(); if (remote.indexOf('@') === -1) { this._legacyCreateFederatedShare(remote, token, owner, ownerDisplayName, name, isProtected); toggleLoading(); return; } $.post( OC.generateUrl('/apps/federatedfilesharing/createFederatedShare'), { 'shareWith': remote, 'token': token } ).done( function (data) { var url = data.remoteUrl; if (url.indexOf('://') > 0) { OC.redirect(url); } else { OC.redirect('http://' + url); } } ).fail( function (jqXHR) { OC.dialogs.alert(JSON.parse(jqXHR.responseText).message, t('files_sharing', 'Failed to add the public link to your Nextcloud')); toggleLoading(); } ); } }; $(document).ready(function () { // FIXME: replace with OC.Plugins.register() if (window.TESTING) { return; } var App = OCA.Sharing.PublicApp; // defer app init, to give a chance to plugins to register file actions _.defer(function () { App.initialize($('#preview')); }); if (window.Files) { // HACK: for oc-dialogs previews that depends on Files: Files.generatePreviewUrl = function (urlSpec) { return App.fileList.generatePreviewUrl(urlSpec); }; } }); tion value='automated/noid/stable24-update-code-signing-crl'>automated/noid/stable24-update-code-signing-crl Nextcloud server, a safe home for all your data: https://github.com/nextcloud/serverwww-data
aboutsummaryrefslogtreecommitdiffstats
blob: 60b95c7cd133f64305e053612b8a2a3491d928d5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
<?php
/**
 * @author Björn Schießle <bjoern@schiessle.org>
 * @author Clark Tomlinson <fallen013@gmail.com>
 * @author Lukas Reschke <lukas@statuscode.ch>
 *
 * @copyright Copyright (c) 2016, ownCloud, Inc.
 * @license AGPL-3.0
 *
 * This code is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License, version 3,
 * as published by the Free Software Foundation.
 *
 * This program 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, version 3,
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 *
 */

namespace OCA\Encryption\Controller;


use OCA\Encryption\Recovery;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
use OCP\IConfig;
use OCP\IL10N;
use OCP\IRequest;
use OCP\AppFramework\Http\DataResponse;

class RecoveryController extends Controller {
	/**
	 * @var IConfig
	 */
	private $config;
	/**
	 * @var IL10N
	 */
	private $l;
	/**
	 * @var Recovery
	 */
	private $recovery;

	/**
	 * @param string $AppName
	 * @param IRequest $request
	 * @param IConfig $config
	 * @param IL10N $l10n
	 * @param Recovery $recovery
	 */
	public function __construct($AppName,
								IRequest $request,
								IConfig $config,
								IL10N $l10n,
								Recovery $recovery) {
		parent::__construct($AppName, $request);
		$this->config = $config;
		$this->l = $l10n;
		$this->recovery = $recovery;
	}

	/**
	 * @param string $recoveryPassword
	 * @param string $confirmPassword
	 * @param string $adminEnableRecovery
	 * @return DataResponse
	 */
	public function adminRecovery($recoveryPassword, $confirmPassword, $adminEnableRecovery) {
		// Check if both passwords are the same
		if (empty($recoveryPassword)) {
			$errorMessage = (string)$this->l->t('Missing recovery key password');
			return new DataResponse(['data' => ['message' => $errorMessage]],
				Http::STATUS_BAD_REQUEST);
		}

		if (empty($confirmPassword)) {
			$errorMessage = (string)$this->l->t('Please repeat the recovery key password');
			return new DataResponse(['data' => ['message' => $errorMessage]],
				Http::STATUS_BAD_REQUEST);
		}

		if ($recoveryPassword !== $confirmPassword) {
			$errorMessage = (string)$this->l->t('Repeated recovery key password does not match the provided recovery key password');
			return new DataResponse(['data' => ['message' => $errorMessage]],
				Http::STATUS_BAD_REQUEST);
		}

		if (isset($adminEnableRecovery) && $adminEnableRecovery === '1') {
			if ($this->recovery->enableAdminRecovery($recoveryPassword)) {
				return new DataResponse(['data' => ['message' => (string)$this->l->t('Recovery key successfully enabled')]]);
			}
			return new DataResponse(['data' => ['message' => (string)$this->l->t('Could not enable recovery key. Please check your recovery key password!')]], Http::STATUS_BAD_REQUEST);
		} elseif (isset($adminEnableRecovery) && $adminEnableRecovery === '0') {
			if ($this->recovery->disableAdminRecovery($recoveryPassword)) {
				return new DataResponse(['data' => ['message' => (string)$this->l->t('Recovery key successfully disabled')]]);
			}
			return new DataResponse(['data' => ['message' => (string)$this->l->t('Could not disable recovery key. Please check your recovery key password!')]], Http::STATUS_BAD_REQUEST);
		}
		// this response should never be sent but just in case.
		return new DataResponse(['data' => ['message' => (string)$this->l->t('Missing parameters')]], Http::STATUS_BAD_REQUEST);
	}

	/**
	 * @param string $newPassword
	 * @param string $oldPassword
	 * @param string $confirmPassword
	 * @return DataResponse
	 */
	public function changeRecoveryPassword($newPassword, $oldPassword, $confirmPassword) {
		//check if both passwords are the same
		if (empty($oldPassword)) {
			$errorMessage = (string)$this->l->t('Please provide the old recovery password');
			return new DataResponse(['data' => ['message' => $errorMessage]], Http::STATUS_BAD_REQUEST);
		}

		if (empty($newPassword)) {
			$errorMessage = (string)$this->l->t('Please provide a new recovery password');
			return new DataResponse (['data' => ['message' => $errorMessage]], Http::STATUS_BAD_REQUEST);
		}

		if (empty($confirmPassword)) {
			$errorMessage = (string)$this->l->t('Please repeat the new recovery password');
			return new DataResponse(['data' => ['message' => $errorMessage]], Http::STATUS_BAD_REQUEST);
		}

		if ($newPassword !== $confirmPassword) {
			$errorMessage = (string)$this->l->t('Repeated recovery key password does not match the provided recovery key password');
			return new DataResponse(['data' => ['message' => $errorMessage]], Http::STATUS_BAD_REQUEST);
		}

		$result = $this->recovery->changeRecoveryKeyPassword($newPassword,
			$oldPassword);

		if ($result) {
			return new DataResponse(
				[
					'data' => [
						'message' => (string)$this->l->t('Password successfully changed.')]
				]
			);
		}
		return new DataResponse(
			[
				'data' => [
					'message' => (string)$this->l->t('Could not change the password. Maybe the old password was not correct.')
				]
			], Http::STATUS_BAD_REQUEST);
	}

	/**
	 * @NoAdminRequired
	 *
	 * @param string $userEnableRecovery
	 * @return DataResponse
	 */
	public function userSetRecovery($userEnableRecovery) {
		if ($userEnableRecovery === '0' || $userEnableRecovery === '1') {

			$result = $this->recovery->setRecoveryForUser($userEnableRecovery);

			if ($result) {
				if ($userEnableRecovery === '0') {
					return new DataResponse(
						[
							'data' => [
								'message' => (string)$this->l->t('Recovery Key disabled')]
						]
					);
				}
				return new DataResponse(
					[
						'data' => [
							'message' => (string)$this->l->t('Recovery Key enabled')]
					]
				);
			}

		}
		return new DataResponse(
			[
				'data' => [
					'message' => (string)$this->l->t('Could not enable the recovery key, please try again or contact your administrator')
				]
			], Http::STATUS_BAD_REQUEST);
	}

}