You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

284 lines
9.5 KiB

  1. <?php
  2. /**
  3. * @author Clark Tomlinson <clark@owncloud.com>
  4. * @author Lukas Reschke <lukas@owncloud.com>
  5. * @copyright 2014 Clark Tomlinson & Lukas Reschke
  6. *
  7. * This file is licensed under the Affero General Public License version 3 or
  8. * later.
  9. * See the COPYING-README file.
  10. */
  11. namespace OCA\Files_Sharing\Controllers;
  12. use OC;
  13. use OC\Files\Filesystem;
  14. use OC_Files;
  15. use OC_Util;
  16. use OCP;
  17. use OCP\Template;
  18. use OCP\JSON;
  19. use OCP\Share;
  20. use OCP\AppFramework\Controller;
  21. use OCP\IRequest;
  22. use OCP\AppFramework\Http\TemplateResponse;
  23. use OCP\AppFramework\Http\RedirectResponse;
  24. use OC\URLGenerator;
  25. use OC\AppConfig;
  26. use OCP\ILogger;
  27. use OCA\Files_Sharing\Helper;
  28. use OCP\User;
  29. use OCP\Util;
  30. use OCA\Files_Sharing\Activity;
  31. /**
  32. * Class ShareController
  33. *
  34. * @package OCA\Files_Sharing\Controllers
  35. */
  36. class ShareController extends Controller {
  37. /** @var \OC\User\Session */
  38. protected $userSession;
  39. /** @var \OC\AppConfig */
  40. protected $appConfig;
  41. /** @var \OCP\IConfig */
  42. protected $config;
  43. /** @var \OC\URLGenerator */
  44. protected $urlGenerator;
  45. /** @var \OC\User\Manager */
  46. protected $userManager;
  47. /** @var \OCP\ILogger */
  48. protected $logger;
  49. /** @var OCP\Activity\IManager */
  50. protected $activityManager;
  51. /**
  52. * @param string $appName
  53. * @param IRequest $request
  54. * @param OC\User\Session $userSession
  55. * @param AppConfig $appConfig
  56. * @param OCP\IConfig $config
  57. * @param URLGenerator $urlGenerator
  58. * @param OC\User\Manager $userManager
  59. * @param ILogger $logger
  60. * @param OCP\Activity\IManager $activityManager
  61. */
  62. public function __construct($appName,
  63. IRequest $request,
  64. OC\User\Session $userSession,
  65. AppConfig $appConfig,
  66. OCP\IConfig $config,
  67. URLGenerator $urlGenerator,
  68. OC\User\Manager $userManager,
  69. ILogger $logger,
  70. OCP\Activity\IManager $activityManager) {
  71. parent::__construct($appName, $request);
  72. $this->userSession = $userSession;
  73. $this->appConfig = $appConfig;
  74. $this->config = $config;
  75. $this->urlGenerator = $urlGenerator;
  76. $this->userManager = $userManager;
  77. $this->logger = $logger;
  78. $this->activityManager = $activityManager;
  79. }
  80. /**
  81. * @PublicPage
  82. * @NoCSRFRequired
  83. *
  84. * @param string $token
  85. * @return TemplateResponse|RedirectResponse
  86. */
  87. public function showAuthenticate($token) {
  88. $linkItem = Share::getShareByToken($token, false);
  89. if(Helper::authenticate($linkItem)) {
  90. return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.showShare', array('token' => $token)));
  91. }
  92. return new TemplateResponse($this->appName, 'authenticate', array(), 'guest');
  93. }
  94. /**
  95. * @PublicPage
  96. * @UseSession
  97. *
  98. * Authenticates against password-protected shares
  99. * @param $token
  100. * @param string $password
  101. * @return RedirectResponse|TemplateResponse
  102. */
  103. public function authenticate($token, $password = '') {
  104. $linkItem = Share::getShareByToken($token, false);
  105. if($linkItem === false) {
  106. return new TemplateResponse('core', '404', array(), 'guest');
  107. }
  108. $authenticate = Helper::authenticate($linkItem, $password);
  109. if($authenticate === true) {
  110. return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.showShare', array('token' => $token)));
  111. }
  112. return new TemplateResponse($this->appName, 'authenticate', array('wrongpw' => true), 'guest');
  113. }
  114. /**
  115. * @PublicPage
  116. * @NoCSRFRequired
  117. *
  118. * @param string $token
  119. * @param string $path
  120. * @return TemplateResponse|RedirectResponse
  121. */
  122. public function showShare($token, $path = '') {
  123. \OC_User::setIncognitoMode(true);
  124. // Check whether share exists
  125. $linkItem = Share::getShareByToken($token, false);
  126. if($linkItem === false) {
  127. return new TemplateResponse('core', '404', array(), 'guest');
  128. }
  129. $shareOwner = $linkItem['uid_owner'];
  130. $originalSharePath = null;
  131. $rootLinkItem = OCP\Share::resolveReShare($linkItem);
  132. if (isset($rootLinkItem['uid_owner'])) {
  133. OCP\JSON::checkUserExists($rootLinkItem['uid_owner']);
  134. OC_Util::tearDownFS();
  135. OC_Util::setupFS($rootLinkItem['uid_owner']);
  136. $originalSharePath = Filesystem::getPath($linkItem['file_source']);
  137. }
  138. // Share is password protected - check whether the user is permitted to access the share
  139. if (isset($linkItem['share_with']) && !Helper::authenticate($linkItem)) {
  140. return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.authenticate',
  141. array('token' => $token)));
  142. }
  143. if (Filesystem::isReadable($originalSharePath . $path)) {
  144. $getPath = Filesystem::normalizePath($path);
  145. $originalSharePath .= $path;
  146. }
  147. $file = basename($originalSharePath);
  148. $shareTmpl = array();
  149. $shareTmpl['displayName'] = User::getDisplayName($shareOwner);
  150. $shareTmpl['filename'] = $file;
  151. $shareTmpl['directory_path'] = $linkItem['file_target'];
  152. $shareTmpl['mimetype'] = Filesystem::getMimeType($originalSharePath);
  153. $shareTmpl['dirToken'] = $linkItem['token'];
  154. $shareTmpl['sharingToken'] = $token;
  155. $shareTmpl['server2serversharing'] = Helper::isOutgoingServer2serverShareEnabled();
  156. $shareTmpl['protected'] = isset($linkItem['share_with']) ? 'true' : 'false';
  157. $shareTmpl['dir'] = '';
  158. $nonHumanFileSize = \OC\Files\Filesystem::filesize($originalSharePath);
  159. $shareTmpl['nonHumanFileSize'] = $nonHumanFileSize;
  160. $shareTmpl['fileSize'] = \OCP\Util::humanFileSize($nonHumanFileSize);
  161. // Show file list
  162. if (Filesystem::is_dir($originalSharePath)) {
  163. $shareTmpl['dir'] = $getPath;
  164. $files = array();
  165. $maxUploadFilesize = Util::maxUploadFilesize($originalSharePath);
  166. $freeSpace = Util::freeSpace($originalSharePath);
  167. $uploadLimit = Util::uploadLimit();
  168. $folder = new Template('files', 'list', '');
  169. $folder->assign('dir', $getPath);
  170. $folder->assign('dirToken', $linkItem['token']);
  171. $folder->assign('permissions', \OCP\Constants::PERMISSION_READ);
  172. $folder->assign('isPublic', true);
  173. $folder->assign('publicUploadEnabled', 'no');
  174. $folder->assign('files', $files);
  175. $folder->assign('uploadMaxFilesize', $maxUploadFilesize);
  176. $folder->assign('uploadMaxHumanFilesize', OCP\Util::humanFileSize($maxUploadFilesize));
  177. $folder->assign('freeSpace', $freeSpace);
  178. $folder->assign('uploadLimit', $uploadLimit); // PHP upload limit
  179. $folder->assign('usedSpacePercent', 0);
  180. $folder->assign('trash', false);
  181. $shareTmpl['folder'] = $folder->fetchPage();
  182. }
  183. $shareTmpl['downloadURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.downloadShare', array('token' => $token));
  184. $shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
  185. return new TemplateResponse($this->appName, 'public', $shareTmpl, 'base');
  186. }
  187. /**
  188. * @PublicPage
  189. * @NoCSRFRequired
  190. *
  191. * @param string $token
  192. * @param string $files
  193. * @param string $path
  194. * @return void|RedirectResponse
  195. */
  196. public function downloadShare($token, $files = null, $path = '') {
  197. \OC_User::setIncognitoMode(true);
  198. $linkItem = OCP\Share::getShareByToken($token, false);
  199. // Share is password protected - check whether the user is permitted to access the share
  200. if (isset($linkItem['share_with'])) {
  201. if(!Helper::authenticate($linkItem)) {
  202. return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.authenticate',
  203. array('token' => $token)));
  204. }
  205. }
  206. $originalSharePath = self::getPath($token);
  207. if (isset($originalSharePath) && Filesystem::isReadable($originalSharePath . $path)) {
  208. $originalSharePath = Filesystem::normalizePath($originalSharePath . $path);
  209. $type = \OC\Files\Filesystem::is_dir($originalSharePath) ? 'folder' : 'file';
  210. $args = $type === 'folder' ? array('dir' => $originalSharePath) : array('dir' => dirname($originalSharePath), 'scrollto' => basename($originalSharePath));
  211. $linkToFile = \OCP\Util::linkToAbsolute('files', 'index.php', $args);
  212. $subject = $type === 'folder' ? Activity::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED : Activity::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED;
  213. $this->activityManager->publishActivity(
  214. 'files_sharing', $subject, array($originalSharePath), '', array(), $originalSharePath,
  215. $linkToFile, $linkItem['uid_owner'], Activity::TYPE_PUBLIC_LINKS, Activity::PRIORITY_MEDIUM);
  216. }
  217. if (!is_null($files)) { // download selected files
  218. $files_list = json_decode($files);
  219. // in case we get only a single file
  220. if ($files_list === NULL) {
  221. $files_list = array($files);
  222. }
  223. // FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
  224. // after dispatching the request which results in a "Cannot modify header information" notice.
  225. OC_Files::get($originalSharePath, $files_list, $_SERVER['REQUEST_METHOD'] == 'HEAD');
  226. exit();
  227. } else {
  228. // FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
  229. // after dispatching the request which results in a "Cannot modify header information" notice.
  230. OC_Files::get(dirname($originalSharePath), basename($originalSharePath), $_SERVER['REQUEST_METHOD'] == 'HEAD');
  231. exit();
  232. }
  233. }
  234. /**
  235. * @param $token
  236. * @return null|string
  237. */
  238. private function getPath($token) {
  239. $linkItem = Share::getShareByToken($token, false);
  240. $path = null;
  241. if (is_array($linkItem) && isset($linkItem['uid_owner'])) {
  242. // seems to be a valid share
  243. $rootLinkItem = Share::resolveReShare($linkItem);
  244. if (isset($rootLinkItem['uid_owner'])) {
  245. JSON::checkUserExists($rootLinkItem['uid_owner']);
  246. OC_Util::tearDownFS();
  247. OC_Util::setupFS($rootLinkItem['uid_owner']);
  248. $path = Filesystem::getPath($linkItem['file_source']);
  249. }
  250. }
  251. return $path;
  252. }
  253. }