Copy of Nextcloud richdocuments app, but with modifications so all traffic goes over clearnet/CJDNS/Tor/I2P/whatever instead of having a single default hostname.
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.

documentcontroller.php 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643
  1. <?php
  2. /**
  3. * ownCloud - Richdocuments App
  4. *
  5. * @author Victor Dubiniuk
  6. * @copyright 2014 Victor Dubiniuk victor.dubiniuk@gmail.com
  7. *
  8. * This file is licensed under the Affero General Public License version 3 or
  9. * later.
  10. */
  11. namespace OCA\Richdocuments\Controller;
  12. use \OCP\AppFramework\Controller;
  13. use \OCP\IRequest;
  14. use \OCP\IConfig;
  15. use \OCP\IL10N;
  16. use \OCP\AppFramework\Http\ContentSecurityPolicy;
  17. use \OCP\AppFramework\Http\JSONResponse;
  18. use \OCP\AppFramework\Http\TemplateResponse;
  19. use \OCA\Richdocuments\Db;
  20. use \OCA\Richdocuments\Helper;
  21. use \OCA\Richdocuments\Storage;
  22. use \OCA\Richdocuments\Download;
  23. use \OCA\Richdocuments\DownloadResponse;
  24. use \OCA\Richdocuments\File;
  25. use \OCA\Richdocuments\Genesis;
  26. use \OC\Files\View;
  27. use \OCP\ICacheFactory;
  28. use \OCP\ILogger;
  29. class ResponseException extends \Exception {
  30. private $hint;
  31. public function __construct($description, $hint = '') {
  32. parent::__construct($description);
  33. $this->hint = $hint;
  34. }
  35. public function getHint() {
  36. return $this->hint;
  37. }
  38. }
  39. class DocumentController extends Controller {
  40. private $uid;
  41. private $l10n;
  42. private $settings;
  43. private $appConfig;
  44. private $cache;
  45. private $logger;
  46. const ODT_TEMPLATE_PATH = '/assets/odttemplate.odt';
  47. public function __construct($appName, IRequest $request, IConfig $settings, IConfig $appConfig, IL10N $l10n, $uid, ICacheFactory $cache, ILogger $logger){
  48. parent::__construct($appName, $request);
  49. $this->uid = $uid;
  50. $this->l10n = $l10n;
  51. $this->settings = $settings;
  52. $this->appConfig = $appConfig;
  53. $this->cache = $cache->create($appName);
  54. $this->logger = $logger;
  55. }
  56. /**
  57. * @param \SimpleXMLElement $discovery
  58. * @param string $mimetype
  59. * @param string $action
  60. */
  61. private function getWopiSrcUrl($discovery_parsed, $mimetype, $action) {
  62. if(is_null($discovery_parsed) || $discovery_parsed == false) {
  63. return null;
  64. }
  65. $result = $discovery_parsed->xpath(sprintf('/wopi-discovery/net-zone/app[@name=\'%s\']/action[@name=\'%s\']', $mimetype, $action));
  66. if ($result && count($result) > 0) {
  67. return (string)$result[0]['urlsrc'];
  68. }
  69. return null;
  70. }
  71. /**
  72. * Log the user with given $userid.
  73. * This function should only be used from public controller methods where no
  74. * existing session exists, for example, when loolwsd is directly calling a
  75. * public method with its own access token. After validating the access
  76. * token, and retrieving the correct user with help of access token, it can
  77. * be set as current user with help of this method.
  78. *
  79. * @param string $userid
  80. */
  81. private function loginUser($userid) {
  82. $users = \OC::$server->getUserManager()->search($userid, 1, 0);
  83. if (count($users) > 0) {
  84. $user = array_shift($users);
  85. if (strcasecmp($user->getUID(), $userid) === 0) {
  86. // clear the existing sessions, if any
  87. \OC::$server->getSession()->close();
  88. // initialize a dummy memory session
  89. $session = new \OC\Session\Memory('');
  90. // wrap it
  91. $cryptoWrapper = \OC::$server->getSessionCryptoWrapper();
  92. $session = $cryptoWrapper->wrapSession($session);
  93. // set our session
  94. \OC::$server->setSession($session);
  95. \OC::$server->getUserSession()->setUser($user);
  96. }
  97. }
  98. }
  99. private function responseError($message, $hint = ''){
  100. $errors = array('errors' => array(array('error' => $message, 'hint' => $hint)));
  101. $response = new TemplateResponse('', 'error', $errors, 'error');
  102. return $response;
  103. }
  104. /** Return the content of discovery.xml - either from cache, or download it.
  105. */
  106. private function getDiscovery(){
  107. \OC::$server->getLogger()->debug('getDiscovery(): Getting discovery.xml from the cache.');
  108. $wopiRemote = $this->appConfig->getAppValue('wopi_url');
  109. // Provides access to information about the capabilities of a WOPI client
  110. // and the mechanisms for invoking those abilities through URIs.
  111. $wopiDiscovery = $wopiRemote . '/hosting/discovery';
  112. // Read the memcached value (if the memcache is installed)
  113. $discovery = $this->cache->get('discovery.xml');
  114. if (is_null($discovery)) {
  115. $contact_admin = $this->l10n->t('Please contact the "%s" administrator.', array($wopiRemote));
  116. try {
  117. $wopiClient = \OC::$server->getHTTPClientService()->newClient();
  118. $discovery = $wopiClient->get($wopiDiscovery)->getBody();
  119. }
  120. catch (\Exception $e) {
  121. $error_message = $e->getMessage();
  122. if (preg_match('/^cURL error ([0-9]*):/', $error_message, $matches)) {
  123. $admin_check = $this->l10n->t('Please ask your administrator to check the Collabora Online server setting. The exact error message was: ') . $error_message;
  124. $curl_error = $matches[1];
  125. switch ($curl_error) {
  126. case '1':
  127. throw new ResponseException($this->l10n->t('Collabora Online: The protocol specified in "%s" is not allowed.', array($wopiRemote)), $admin_check);
  128. case '3':
  129. throw new ResponseException($this->l10n->t('Collabora Online: Malformed URL "%s".', array($wopiRemote)), $admin_check);
  130. case '6':
  131. throw new ResponseException($this->l10n->t('Collabora Online: Cannot resolve the host "%s".', array($wopiRemote)), $admin_check);
  132. case '7':
  133. throw new ResponseException($this->l10n->t('Collabora Online: Cannot connect to the host "%s".', array($wopiRemote)), $admin_check);
  134. case '60':
  135. throw new ResponseException($this->l10n->t('Collabora Online: SSL certificate is not installed.'), $this->l10n->t('Please ask your administrator to add ca-chain.cert.pem to the ca-bundle.crt, for example "cat /etc/loolwsd/ca-chain.cert.pem >> <server-installation>/resources/config/ca-bundle.crt" . The exact error message was: ') . $error_message);
  136. }
  137. }
  138. throw new ResponseException($this->l10n->t('Collabora Online unknown error: ') . $error_message, $contact_admin);
  139. }
  140. if (!$discovery) {
  141. throw new ResponseException($this->l10n->t('Collabora Online: Unable to read discovery.xml from "%s".', array($wopiRemote)), $contact_admin);
  142. }
  143. \OC::$server->getLogger()->debug('Storing the discovery.xml to the cache.');
  144. $this->cache->set('discovery.xml', $discovery, 3600);
  145. }
  146. return $discovery;
  147. }
  148. /** Prepare document(s) structure
  149. */
  150. private function prepareDocuments($rawDocuments){
  151. $discovery_parsed = null;
  152. try {
  153. $discovery = $this->getDiscovery();
  154. $loadEntities = libxml_disable_entity_loader(true);
  155. $discovery_parsed = simplexml_load_string($discovery);
  156. libxml_disable_entity_loader($loadEntities);
  157. if ($discovery_parsed === false) {
  158. $this->cache->remove('discovery.xml');
  159. $wopiRemote = $this->appConfig->getAppValue('wopi_url');
  160. return array(
  161. 'status' => 'error',
  162. 'message' => $this->l10n->t('Collabora Online: discovery.xml from "%s" is not a well-formed XML string.', array($wopiRemote)),
  163. 'hint' => $this->l10n->t('Please contact the "%s" administrator.', array($wopiRemote))
  164. );
  165. }
  166. }
  167. catch (ResponseException $e) {
  168. return array(
  169. 'status' => 'error',
  170. 'message' => $e->getMessage(),
  171. 'hint' => $e->getHint()
  172. );
  173. }
  174. $fileIds = array();
  175. $documents = array();
  176. $lolang = strtolower(str_replace('_', '-', $this->settings->getUserValue($this->uid, 'core', 'lang', 'en')));
  177. foreach ($rawDocuments as $key=>$document) {
  178. if (is_object($document)){
  179. $documents[] = $document->getData();
  180. } else {
  181. $documents[$key] = $document;
  182. }
  183. $documents[$key]['icon'] = preg_replace('/\.png$/', '.svg', \OCP\Template::mimetype_icon($document['mimetype']));
  184. $documents[$key]['hasPreview'] = \OC::$server->getPreviewManager()->isMimeSupported($document['mimetype']);
  185. $documents[$key]['urlsrc'] = $this->getWopiSrcUrl($discovery_parsed, $document['mimetype'], 'edit');
  186. $documents[$key]['lolang'] = $lolang;
  187. $fileIds[] = $document['fileid'];
  188. }
  189. usort($documents, function($a, $b){
  190. return @$b['mtime']-@$a['mtime'];
  191. });
  192. $session = new Db\Session();
  193. $sessions = $session->getCollectionBy('file_id', $fileIds);
  194. $members = array();
  195. $member = new Db\Member();
  196. foreach ($sessions as $session) {
  197. $members[$session['es_id']] = $member->getActiveCollection($session['es_id']);
  198. }
  199. return array(
  200. 'status' => 'success', 'documents' => $documents,'sessions' => $sessions,'members' => $members
  201. );
  202. }
  203. /**
  204. * @NoAdminRequired
  205. * @NoCSRFRequired
  206. */
  207. public function index(){
  208. $wopiRemote = $this->appConfig->getAppValue('wopi_url');
  209. if (($parts = parse_url($wopiRemote)) && isset($parts['scheme']) && isset($parts['host'])) {
  210. $webSocketProtocol = "ws://";
  211. if ($parts['scheme'] == "https") {
  212. $webSocketProtocol = "wss://";
  213. }
  214. $webSocket = sprintf(
  215. "%s%s%s",
  216. $webSocketProtocol,
  217. $parts['host'],
  218. isset($parts['port']) ? ":" . $parts['port'] : "");
  219. }
  220. else {
  221. return $this->responseError($this->l10n->t('Collabora Online: Invalid URL "%s".', array($wopiRemote)), $this->l10n->t('Please ask your administrator to check the Collabora Online server setting.'));
  222. }
  223. \OC::$server->getNavigationManager()->setActiveEntry( 'richdocuments_index' );
  224. $maxUploadFilesize = \OCP\Util::maxUploadFilesize("/");
  225. $response = new TemplateResponse('richdocuments', 'documents', [
  226. 'enable_previews' => $this->settings->getSystemValue('enable_previews', true),
  227. 'savePath' => $this->settings->getUserValue($this->uid, 'richdocuments', 'save_path', '/'),
  228. 'uploadMaxFilesize' => $maxUploadFilesize,
  229. 'uploadMaxHumanFilesize' => \OCP\Util::humanFileSize($maxUploadFilesize),
  230. 'allowShareWithLink' => $this->settings->getAppValue('core', 'shareapi_allow_links', 'yes'),
  231. 'wopi_url' => $webSocket,
  232. ]);
  233. $policy = new ContentSecurityPolicy();
  234. $policy->addAllowedScriptDomain('\'self\' http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js http://cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.12/jquery.mousewheel.min.js \'unsafe-eval\' ' . $wopiRemote);
  235. /* frame-src is deprecated on Firefox, but Safari wants it! */
  236. $policy->addAllowedFrameDomain('\'self\' http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js http://cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.12/jquery.mousewheel.min.js \'unsafe-eval\' ' . $wopiRemote);
  237. $policy->addAllowedChildSrcDomain('\'self\' http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js http://cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.12/jquery.mousewheel.min.js \'unsafe-eval\' ' . $wopiRemote);
  238. $policy->addAllowedConnectDomain($webSocket);
  239. $policy->addAllowedImageDomain('*');
  240. $policy->allowInlineScript(true);
  241. $policy->addAllowedFontDomain('data:');
  242. $response->setContentSecurityPolicy($policy);
  243. return $response;
  244. }
  245. /**
  246. * @NoAdminRequired
  247. */
  248. public function create(){
  249. $mimetype = $this->request->post['mimetype'];
  250. $filename = $this->request->post['filename'];
  251. $dir = $this->request->post['dir'];
  252. $view = new View('/' . $this->uid . '/files');
  253. if (!$dir){
  254. $dir = $this->settings->getUserValue($this->uid, $this->appName, 'save_path', '/');
  255. if (!$view->is_dir($dir)){
  256. $dir = '/';
  257. }
  258. }
  259. $basename = $this->l10n->t('New Document.odt');
  260. switch ($mimetype) {
  261. case 'application/vnd.oasis.opendocument.spreadsheet':
  262. $basename = $this->l10n->t('New Spreadsheet.ods');
  263. break;
  264. case 'application/vnd.oasis.opendocument.presentation':
  265. $basename = $this->l10n->t('New Presentation.odp');
  266. break;
  267. default:
  268. // to be safe
  269. $mimetype = 'application/vnd.oasis.opendocument.text';
  270. break;
  271. }
  272. if (!$filename){
  273. $path = Helper::getNewFileName($view, $dir . '/' . $basename);
  274. } else {
  275. $path = $dir . '/' . $filename;
  276. }
  277. $content = '';
  278. if (class_exists('\OC\Files\Type\TemplateManager')){
  279. $manager = \OC_Helper::getFileTemplateManager();
  280. $content = $manager->getTemplate($mimetype);
  281. }
  282. if (!$content){
  283. $content = file_get_contents(dirname(__DIR__) . self::ODT_TEMPLATE_PATH);
  284. }
  285. $discovery_parsed = null;
  286. try {
  287. $discovery = $this->getDiscovery();
  288. $loadEntities = libxml_disable_entity_loader(true);
  289. $discovery_parsed = simplexml_load_string($discovery);
  290. libxml_disable_entity_loader($loadEntities);
  291. if ($discovery_parsed === false) {
  292. $this->cache->remove('discovery.xml');
  293. $wopiRemote = $this->appConfig->getAppValue('wopi_url');
  294. return array(
  295. 'status' => 'error',
  296. 'message' => $this->l10n->t('Collabora Online: discovery.xml from "%s" is not a well-formed XML string.', array($wopiRemote)),
  297. 'hint' => $this->l10n->t('Please contact the "%s" administrator.', array($wopiRemote))
  298. );
  299. }
  300. }
  301. catch (ResponseException $e) {
  302. return array(
  303. 'status' => 'error',
  304. 'message' => $e->getMessage(),
  305. 'hint' => $e->getHint()
  306. );
  307. }
  308. if ($content && $view->file_put_contents($path, $content)){
  309. $info = $view->getFileInfo($path);
  310. $response = array(
  311. 'status' => 'success',
  312. 'fileid' => $info['fileid'],
  313. 'urlsrc' => $this->getWopiSrcUrl($discovery_parsed, $mimetype, 'edit'),
  314. 'lolang' => $this->settings->getUserValue($this->uid, 'core', 'lang', 'en'),
  315. 'data' => \OCA\Files\Helper::formatFileInfo($info)
  316. );
  317. } else {
  318. $response = array(
  319. 'status' => 'error',
  320. 'message' => (string) $this->l10n->t('Can\'t create document')
  321. );
  322. }
  323. return $response;
  324. }
  325. /**
  326. * @NoAdminRequired
  327. * Generates and returns an access token for a given fileId.
  328. * Only for authenticated users!
  329. */
  330. public function wopiGetToken($fileId){
  331. $arr = explode('_', $fileId, 2);
  332. $version = '0';
  333. if (count($arr) == 2) {
  334. $fileId = $arr[0];
  335. $version = $arr[1];
  336. }
  337. \OC::$server->getLogger()->debug('Generating WOPI Token for file {fileId}, version {version}.', [ 'app' => $this->appName, 'fileId' => $fileId, 'version' => $version ]);
  338. $row = new Db\Wopi();
  339. $token = $row->generateFileToken($fileId, $version);
  340. // Return the token.
  341. return array(
  342. 'status' => 'success',
  343. 'token' => $token
  344. );
  345. }
  346. /**
  347. * @NoAdminRequired
  348. * @NoCSRFRequired
  349. * @PublicPage
  350. * Returns general info about a file.
  351. */
  352. public function wopiCheckFileInfo($fileId){
  353. $token = $this->request->getParam('access_token');
  354. $arr = explode('_', $fileId, 2);
  355. $version = '0';
  356. if (count($arr) == 2) {
  357. $fileId = $arr[0];
  358. $version = $arr[1];
  359. }
  360. \OC::$server->getLogger()->debug('Getting info about file {fileId}, version {version} by token {token}.', [ 'app' => $this->appName, 'fileId' => $fileId, 'version' => $version, 'token' => $token ]);
  361. $row = new Db\Wopi();
  362. $row->loadBy('token', $token);
  363. $res = $row->getPathForToken($fileId, $version, $token);
  364. if ($res == false || http_response_code() != 200)
  365. {
  366. return false;
  367. }
  368. // Login the user to see his mount locations
  369. $this->loginUser($res['owner']);
  370. $view = new \OC\Files\View('/' . $res['owner'] . '/files');
  371. $info = $view->getFileInfo($res['path']);
  372. // Close the session created for user login
  373. \OC::$server->getSession()->close();
  374. if (!$info) {
  375. http_response_code(404);
  376. return false;
  377. }
  378. \OC::$server->getLogger()->debug('File info: {info}.', [ 'app' => $this->appName, 'info' => $info ]);
  379. return array(
  380. 'BaseFileName' => $info['name'],
  381. 'Size' => $info['size'],
  382. 'Version' => $version
  383. //'DownloadUrl' => '',
  384. //'FileUrl' => '',
  385. );
  386. }
  387. /**
  388. * @NoAdminRequired
  389. * @NoCSRFRequired
  390. * @PublicPage
  391. * Given an access token and a fileId, returns the contents of the file.
  392. * Expects a valid token in access_token parameter.
  393. */
  394. public function wopiGetFile($fileId){
  395. $token = $this->request->getParam('access_token');
  396. $arr = explode('_', $fileId, 2);
  397. $version = '0';
  398. if (count($arr) == 2) {
  399. $fileId = $arr[0];
  400. $version = $arr[1];
  401. }
  402. \OC::$server->getLogger()->debug('Getting contents of file {fileId}, version {version} by token {token}.', [ 'app' => $this->appName, 'fileId' => $fileId, 'version' => $version, 'token' => $token ]);
  403. $row = new Db\Wopi();
  404. $row->loadBy('token', $token);
  405. //TODO: Support X-WOPIMaxExpectedSize header.
  406. $res = $row->getPathForToken($fileId, $version, $token);
  407. $ownerid = $res['owner'];
  408. // Login the user to see his mount locations
  409. $this->loginUser($ownerid);
  410. $filename = '';
  411. // If some previous version is requested, fetch it from Files_Version app
  412. if ($version !== '0') {
  413. \OCP\JSON::checkAppEnabled('files_versions');
  414. // Setup the FS
  415. \OC_Util::tearDownFS();
  416. \OC_Util::setupFS($ownerid, '/' . $ownerid . '/files');
  417. list($ownerid, $filename) = \OCA\Files_Versions\Storage::getUidAndFilename($res['path']);
  418. $filename = '/files_versions/' . $filename . '.v' . $version;
  419. \OC_Util::tearDownFS();
  420. } else {
  421. $filename = '/files' . $res['path'];
  422. }
  423. // Close the session created for user login
  424. \OC::$server->getSession()->close();
  425. return new DownloadResponse($this->request, $ownerid, $filename);
  426. }
  427. /**
  428. * @NoAdminRequired
  429. * @NoCSRFRequired
  430. * @PublicPage
  431. * Given an access token and a fileId, replaces the files with the request body.
  432. * Expects a valid token in access_token parameter.
  433. */
  434. public function wopiPutFile($fileId){
  435. $token = $this->request->getParam('access_token');
  436. $arr = explode('_', $fileId, 2);
  437. $version = '0';
  438. if (count($arr) == 2) {
  439. $fileId = $arr[0];
  440. $version = $arr[1];
  441. }
  442. // Changing a previous version of the file is not possible
  443. // Ignore WOPI put if such a request is encountered
  444. if ($version !== '0') {
  445. return array(
  446. 'status' => 'success'
  447. );
  448. }
  449. \OC::$server->getLogger()->debug('Putting contents of file {fileId}, version {version} by token {token}.', [ 'app' => $this->appName, 'fileId' => $fileId, 'version' => $version, 'token' => $token ]);
  450. $row = new Db\Wopi();
  451. $row->loadBy('token', $token);
  452. $res = $row->getPathForToken($fileId, $version, $token);
  453. // Log-in as the user to regiser the change under her name.
  454. $editorid = $res['editor'];
  455. // This call is made from loolwsd, so we need to initialize the
  456. // session before we can make the user who opened the document
  457. // login. This is necessary to make activity app register the
  458. // change made to this file under this user's (editorid) name.
  459. $this->loginUser($editorid);
  460. // Set up the filesystem view for the owner (where the file actually is).
  461. $userid = $res['owner'];
  462. $root = '/' . $userid . '/files';
  463. $view = new \OC\Files\View($root);
  464. // Read the contents of the file from the POST body and store.
  465. $content = fopen('php://input', 'r');
  466. \OC::$server->getLogger()->debug('Storing file {fileId} by {editor} owned by {owner}.', [ 'app' => $this->appName, 'fileId' => $fileId, 'editor' => $editorid, 'owner' => $userid ]);
  467. // Setup the FS which is needed to emit hooks (versioning).
  468. \OC_Util::tearDownFS();
  469. \OC_Util::setupFS($userid, $root);
  470. $view->file_put_contents($res['path'], $content);
  471. \OC_Util::tearDownFS();
  472. // clear any session created before
  473. \OC::$server->getSession()->close();
  474. return array(
  475. 'status' => 'success'
  476. );
  477. }
  478. /**
  479. * @NoAdminRequired
  480. * @PublicPage
  481. * Process partial/complete file download
  482. */
  483. public function serve($esId){
  484. $session = new Db\Session();
  485. $session->load($esId);
  486. $filename = $session->getGenesisUrl() ? $session->getGenesisUrl() : '';
  487. return new DownloadResponse($this->request, $session->getOwner(), $filename);
  488. }
  489. /**
  490. * @NoAdminRequired
  491. */
  492. public function download($path){
  493. if (!$path){
  494. $response = new JSONResponse();
  495. $response->setStatus(Http::STATUS_BAD_REQUEST);
  496. return $response;
  497. }
  498. $fullPath = '/files' . $path;
  499. $fileInfo = \OC\Files\Filesystem::getFileInfo($path);
  500. if ($fileInfo){
  501. $file = new File($fileInfo->getId());
  502. $genesis = new Genesis($file);
  503. $fullPath = $genesis->getPath();
  504. }
  505. return new DownloadResponse($this->request, $this->uid, $fullPath);
  506. }
  507. /**
  508. * @NoAdminRequired
  509. */
  510. public function rename($fileId){
  511. $name = $this->request->post['name'];
  512. $view = \OC\Files\Filesystem::getView();
  513. $path = $view->getPath($fileId);
  514. if ($name && $view->is_file($path) && $view->isUpdatable($path)) {
  515. $newPath = dirname($path) . '/' . $name;
  516. if ($view->rename($path, $newPath)) {
  517. return array('status' => 'success');
  518. }
  519. }
  520. return array(
  521. 'status' => 'error',
  522. 'message' => (string) $this->l10n->t('You don\'t have permission to rename this document')
  523. );
  524. }
  525. /**
  526. * @NoAdminRequired
  527. * Get file information about single document with fileId
  528. */
  529. public function get($fileId){
  530. $documents = array();
  531. $documents[0] = Storage::getDocumentById($fileId);
  532. return $this->prepareDocuments($documents);
  533. }
  534. /**
  535. * @NoAdminRequired
  536. * lists the documents the user has access to (including shared files, once the code in core has been fixed)
  537. * also adds session and member info for these files
  538. */
  539. public function listAll(){
  540. return $this->prepareDocuments(Storage::getDocuments());
  541. }
  542. }