From 33a685bc41628e1236015bd79cc8f82b9cb6cabf Mon Sep 17 00:00:00 2001
From: Bjoern Schiessle <bjoern@schiessle.org>
Date: Tue, 12 Jul 2016 14:03:29 +0200
Subject: [PATCH] continue to accept the URL of the remote server instead of
 the federated cloud id

---
 .../Controller/SaveToOwnCloudController.php   |  40 ++++--
 .../SaveToOwnCloudControllerTest.php          |  16 ++-
 apps/files_sharing/ajax/external.php          | 119 ++++--------------
 apps/files_sharing/js/external.js             |   6 +-
 apps/files_sharing/js/public.js               |  86 ++++++++++---
 5 files changed, 138 insertions(+), 129 deletions(-)

diff --git a/apps/federatedfilesharing/lib/Controller/SaveToOwnCloudController.php b/apps/federatedfilesharing/lib/Controller/SaveToOwnCloudController.php
index a20806e6abb..2318d21afb5 100644
--- a/apps/federatedfilesharing/lib/Controller/SaveToOwnCloudController.php
+++ b/apps/federatedfilesharing/lib/Controller/SaveToOwnCloudController.php
@@ -29,6 +29,7 @@ use OCP\AppFramework\Controller;
 use OCP\AppFramework\Http;
 use OCP\AppFramework\Http\JSONResponse;
 use OCP\IRequest;
+use OCP\ISession;
 use OCP\Share\IManager;
 
 class SaveToOwnCloudController extends Controller {
@@ -42,16 +43,32 @@ class SaveToOwnCloudController extends Controller {
 	/** @var IManager  */
 	private $shareManager;
 
+	/** @var  ISession */
+	private $session;
+
+	/**
+	 * SaveToOwnCloudController constructor.
+	 *
+	 * @param string $appName
+	 * @param IRequest $request
+	 * @param FederatedShareProvider $federatedShareProvider
+	 * @param IManager $shareManager
+	 * @param AddressHandler $addressHandler
+	 * @param ISession $session
+	 */
 	public function __construct($appName,
-								IRequest $request,
-								FederatedShareProvider $federatedShareProvider,
-								IManager $shareManager,
-								AddressHandler $addressHandler) {
+								   IRequest $request,
+								   FederatedShareProvider $federatedShareProvider,
+								   IManager $shareManager,
+								   AddressHandler $addressHandler,
+								   ISession $session
+	) {
 		parent::__construct($appName, $request);
 
 		$this->federatedShareProvider = $federatedShareProvider;
 		$this->shareManager = $shareManager;
 		$this->addressHandler = $addressHandler;
+		$this->session = $session;
 	}
 
 	/**
@@ -63,9 +80,10 @@ class SaveToOwnCloudController extends Controller {
 	 *
 	 * @param string $shareWith
 	 * @param string $token
+	 * @param string $password
 	 * @return JSONResponse
 	 */
-	public function saveToOwnCloud($shareWith, $token) {
+	public function saveToOwnCloud($shareWith, $token, $password = '') {
 
 		try {
 			list(, $server) = $this->addressHandler->splitUserRemote($shareWith);
@@ -74,6 +92,14 @@ class SaveToOwnCloudController extends Controller {
 			return new JSONResponse(['message' => $e->getHint()], Http::STATUS_BAD_REQUEST);
 		}
 
+		// make sure that user is authenticated in case of a password protected link
+		$storedPassword = $share->getPassword();
+		$authenticated = $this->session->get('public_link_authenticated') === $share->getId() ||
+			$this->shareManager->checkPassword($share, $password);
+		if (!empty($storedPassword) && !$authenticated ) {
+			return new JSONResponse(['message' => 'No permission to access the share'], Http::STATUS_BAD_REQUEST);
+		}
+
 		$share->setSharedWith($shareWith);
 
 		try {
@@ -81,8 +107,8 @@ class SaveToOwnCloudController extends Controller {
 		} catch (\Exception $e) {
 			return new JSONResponse(['message' => $e->getMessage()], Http::STATUS_BAD_REQUEST);
 		}
-		
+
 		return new JSONResponse(['remoteUrl' => $server]);
 	}
-	
+
 }
diff --git a/apps/federatedfilesharing/tests/Controller/SaveToOwnCloudControllerTest.php b/apps/federatedfilesharing/tests/Controller/SaveToOwnCloudControllerTest.php
index 24bc18d5644..9189ac76601 100644
--- a/apps/federatedfilesharing/tests/Controller/SaveToOwnCloudControllerTest.php
+++ b/apps/federatedfilesharing/tests/Controller/SaveToOwnCloudControllerTest.php
@@ -28,6 +28,7 @@ use OCA\FederatedFileSharing\Controller\SaveToOwnCloudController;
 use OCA\FederatedFileSharing\FederatedShareProvider;
 use OCP\AppFramework\Http;
 use OCP\Files\IRootFolder;
+use OCP\ISession;
 use OCP\IUserManager;
 use OCP\Share;
 use OCP\Share\IManager;
@@ -56,6 +57,9 @@ class SaveToOwnCloudControllerTest extends \Test\TestCase {
 	/** @var  IUserManager | \PHPUnit_Framework_MockObject_MockObject */
 	private $userManager;
 
+	/** @var  ISession | \PHPUnit_Framework_MockObject_MockObject */
+	private $session;
+
 	/** @var  IShare */
 	private $share;
 
@@ -71,12 +75,14 @@ class SaveToOwnCloudControllerTest extends \Test\TestCase {
 		$this->rootFolder = $this->getMock('OCP\Files\IRootFolder');
 		$this->userManager = $this->getMock('OCP\IUserManager');
 		$this->share = new \OC\Share20\Share($this->rootFolder, $this->userManager);
+		$this->session = $this->getMock('OCP\ISession');
 
 		$this->controller = new SaveToOwnCloudController(
 			'federatedfilesharing', $this->request,
 			$this->federatedShareProvider,
 			$this->shareManager,
-			$this->addressHandler
+			$this->addressHandler,
+			$this->session
 		);
 	}
 
@@ -101,9 +107,9 @@ class SaveToOwnCloudControllerTest extends \Test\TestCase {
 					throw new HintException($expectedReturnData, $expectedReturnData);
 				}
 			);
-		
+
 		$share = $this->share;
-		
+
 		$this->shareManager->expects($this->any())->method('getShareByToken')
 			->with($token)
 			->willReturnCallback(
@@ -114,7 +120,7 @@ class SaveToOwnCloudControllerTest extends \Test\TestCase {
 					throw new HintException($expectedReturnData, $expectedReturnData);
 				}
 			);
-		
+
 		$this->federatedShareProvider->expects($this->any())->method('create')
 			->with($share)
 			->willReturnCallback(
@@ -141,7 +147,7 @@ class SaveToOwnCloudControllerTest extends \Test\TestCase {
 			$this->assertSame($expectedReturnData, $result->getData()['remoteUrl']);
 
 		}
-		
+
 	}
 
 	public function dataTestSaveToOwnCloud() {
diff --git a/apps/files_sharing/ajax/external.php b/apps/files_sharing/ajax/external.php
index 4a7a6096c91..d57d333c7ee 100644
--- a/apps/files_sharing/ajax/external.php
+++ b/apps/files_sharing/ajax/external.php
@@ -42,112 +42,35 @@ if ($federatedShareProvider->isIncomingServer2serverShareEnabled() === false) {
 
 $token = $_POST['token'];
 $remote = $_POST['remote'];
-$owner = $_POST['owner'];
-$ownerDisplayName = $_POST['ownerDisplayName'];
-$name = $_POST['name'];
-$password = $_POST['password'];
+$password = isset($_POST['password']) ? $_POST['password'] : '';
 
-// Check for invalid name
-if(!\OCP\Util::isValidFileName($name)) {
-	\OCP\JSON::error(array('data' => array('message' => $l->t('The mountpoint name contains invalid characters.'))));
-	exit();
-}
-
-$currentUser = \OC::$server->getUserSession()->getUser()->getUID();
-$currentServer = \OC::$server->getURLGenerator()->getAbsoluteURL('/');
-if (\OC\Share\Helper::isSameUserOnSameServer($owner, $remote, $currentUser, $currentServer )) {
-	\OCP\JSON::error(array('data' => array('message' => $l->t('Not allowed to create a federated share with the same user server'))));
-	exit();
-}
+$urlGenerator = \OC::$server->getURLGenerator();
 
-$discoveryManager = new \OCA\FederatedFileSharing\DiscoveryManager(
-	\OC::$server->getMemCacheFactory(),
-	\OC::$server->getHTTPClientService()
-);
-$externalManager = new \OCA\Files_Sharing\External\Manager(
-		\OC::$server->getDatabaseConnection(),
-		\OC\Files\Filesystem::getMountManager(),
-		\OC\Files\Filesystem::getLoader(),
-		\OC::$server->getHTTPHelper(),
-		\OC::$server->getNotificationManager(),
-		$discoveryManager,
-		\OC::$server->getUserSession()->getUser()->getUID()
-);
+$shareWith = \OCP\User::getUser() . '@' . $urlGenerator->getAbsoluteURL('/');
 
-// check for ssl cert
-if (substr($remote, 0, 5) === 'https') {
-	try {
-		\OC::$server->getHTTPClientService()->newClient()->get($remote, [
-			'timeout' => 10,
-			'connect_timeout' => 10,
-		])->getBody();
-	} catch (\Exception $e) {
-		\OCP\JSON::error(array('data' => array('message' => $l->t('Invalid or untrusted SSL certificate'))));
-		exit;
-	}
-}
+$httpClient = \OC::$server->getHTTPClientService()->newClient();
 
-$mount = $externalManager->addShare($remote, $token, $password, $name, $ownerDisplayName, true);
+error_log("do th post");
 
-/**
- * @var \OCA\Files_Sharing\External\Storage $storage
- */
-$storage = $mount->getStorage();
 try {
-	// check if storage exists
-	$storage->checkStorageAvailability();
-} catch (\OCP\Files\StorageInvalidException $e) {
-	// note: checkStorageAvailability will already remove the invalid share
-	\OCP\Util::writeLog(
-		'files_sharing',
-		'Invalid remote storage: ' . get_class($e) . ': ' . $e->getMessage(),
-		\OCP\Util::DEBUG
-	);
-	\OCP\JSON::error(
-		array(
-			'data' => array(
-				'message' => $l->t('Could not authenticate to remote share, password might be wrong')
-			)
-		)
+	$response = $httpClient->post($remote . '/index.php/apps/federatedfilesharing/saveToOwnCloud',
+		[
+			'body' =>
+				[
+					'token' => $token,
+					'shareWith' => rtrim($shareWith, '/'),
+					'password' => $password
+				]
+		]
 	);
-	exit();
 } catch (\Exception $e) {
-	\OCP\Util::writeLog(
-		'files_sharing',
-		'Invalid remote storage: ' . get_class($e) . ': ' . $e->getMessage(),
-		\OCP\Util::DEBUG
-	);
-	$externalManager->removeShare($mount->getMountPoint());
-	\OCP\JSON::error(array('data' => array('message' => $l->t('Storage not valid'))));
-	exit();
-}
-$result = $storage->file_exists('');
-if ($result) {
-	try {
-		$storage->getScanner()->scanAll();
-		\OCP\JSON::success();
-	} catch (\OCP\Files\StorageInvalidException $e) {
-		\OCP\Util::writeLog(
-			'files_sharing',
-			'Invalid remote storage: ' . get_class($e) . ': ' . $e->getMessage(),
-			\OCP\Util::DEBUG
-		);
-		\OCP\JSON::error(array('data' => array('message' => $l->t('Storage not valid'))));
-	} catch (\Exception $e) {
-		\OCP\Util::writeLog(
-			'files_sharing',
-			'Invalid remote storage: ' . get_class($e) . ': ' . $e->getMessage(),
-			\OCP\Util::DEBUG
-		);
-		\OCP\JSON::error(array('data' => array('message' => $l->t('Couldn\'t add remote share'))));
+	if (empty($password)) {
+		$message = $l->t("Couldn't establish a federated share.");
+	} else {
+		$message = $l->t("Couldn't establish a federated share, maybe the password was wrong.");
 	}
-} else {
-	$externalManager->removeShare($mount->getMountPoint());
-	\OCP\Util::writeLog(
-		'files_sharing',
-		'Couldn\'t add remote share',
-		\OCP\Util::DEBUG
-	);
-	\OCP\JSON::error(array('data' => array('message' => $l->t('Couldn\'t add remote share'))));
+	\OCP\JSON::error(array('data' => array('message' => $message)));
+	exit();
 }
 
+\OCP\JSON::success(array('data' => array('message' => $l->t('Federated Share request was successful, you will receive a invitation. Check your notifications.'))));
diff --git a/apps/files_sharing/js/external.js b/apps/files_sharing/js/external.js
index 0ca8213168e..be384818c3c 100644
--- a/apps/files_sharing/js/external.js
+++ b/apps/files_sharing/js/external.js
@@ -107,11 +107,7 @@
 							ownerDisplayName: share.ownerDisplayName || share.owner,
 							name: share.name,
 							password: password}, function(result) {
-							if (result.status === 'error') {
-								OC.Notification.showTemporary(result.data.message);
-							} else {
-								fileList.reload();
-							}
+							OC.Notification.showTemporary(result.data.message);
 						});
 					}
 				};
diff --git a/apps/files_sharing/js/public.js b/apps/files_sharing/js/public.js
index d4f3bd36a63..4293c7b310b 100644
--- a/apps/files_sharing/js/public.js
+++ b/apps/files_sharing/js/public.js
@@ -244,8 +244,10 @@ OCA.Sharing.PublicApp = {
 			var remote = $(this).find('input[type="text"]').val();
 			var token = $('#sharingToken').val();
 			var owner = $('#save').data('owner');
+			var ownerDisplayName = $('#save').data('owner-display-name');
 			var name = $('#save').data('name');
-			OCA.Sharing.PublicApp._saveToOwnCloud(remote, token);
+			var isProtected = $('#save').data('protected') ? 1 : 0;
+			OCA.Sharing.PublicApp._saveToOwnCloud(remote, token, owner, ownerDisplayName, name, isProtected);
 		});
 
 		$('#remote_address').on("keyup paste", function() {
@@ -293,7 +295,72 @@ OCA.Sharing.PublicApp = {
 	},
 
 
-	_saveToOwnCloud: function (remote, token) {
+	/**
+	 * 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
+	 */
+	_legacySaveToOwnCloud: 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);
+				}
+			});
+		}
+	},
+
+	_saveToOwnCloud: 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._legacySaveToOwnCloud(remote, token, owner, ownerDisplayName, name, isProtected);
+			toggleLoading();
+			return;
+		}
 
 		$.post(
 			OC.generateUrl('/apps/federatedfilesharing/saveToOwnCloud'),
@@ -308,17 +375,7 @@ OCA.Sharing.PublicApp = {
 				if (url.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') {
-							toggleLoading();
-							OC.dialogs.alert(t('files_sharing', 'No Nextcloud installation (7 or higher) found at {remote}', {remote: remote}),
-								t('files_sharing', 'Invalid ownCloud url'));
-						} else {
-							OC.redirect(protocol + '://' + url);
-						}
-					});
+					OC.redirect('http://' + url);
 				}
 			}
 		).fail(
@@ -326,7 +383,8 @@ OCA.Sharing.PublicApp = {
 				console.log("ERROR!");
 				console.log(jqXHR);
 				OC.dialogs.alert(JSON.parse(jqXHR.responseText).message,
-					t('files_sharing', 'Failed to add the public link to your ownCloud'));
+					t('files_sharing', 'Failed to add the public link to your Nextcloud'));
+				toggleLoading();
 			}
 		);
 	}
-- 
GitLab