/** * Get the template for a specific activity-event in the activities * * @param array $activity An array with all the activity data in it * @return string */ public function show($activity) { $tmpl = new Template('activity', 'stream.item'); $tmpl->assign('formattedDate', $this->dateTimeFormatter->formatDateTime($activity['timestamp'])); $tmpl->assign('formattedTimestamp', Template::relative_modified_date($activity['timestamp'])); if (strpos($activity['subjectformatted']['markup']['trimmed'], '<a ') !== false) { // We do not link the subject as we create links for the parameters instead $activity['link'] = ''; } $tmpl->assign('event', $activity); if ($activity['file']) { $this->view->chroot('/' . $activity['affecteduser'] . '/files'); $exist = $this->view->file_exists($activity['file']); $is_dir = $this->view->is_dir($activity['file']); $tmpl->assign('previewLink', $this->getPreviewLink($activity['file'], $is_dir)); // show a preview image if the file still exists $mimeType = Files::getMimeType($activity['file']); if ($mimeType && !$is_dir && $this->preview->isMimeSupported($mimeType) && $exist) { $tmpl->assign('previewImageLink', $this->urlGenerator->linkToRoute('core_ajax_preview', array('file' => $activity['file'], 'x' => 150, 'y' => 150))); } else { $mimeTypeIcon = Template::mimetype_icon($is_dir ? 'dir' : $mimeType); $mimeTypeIcon = substr($mimeTypeIcon, -4) === '.png' ? substr($mimeTypeIcon, 0, -4) . '.svg' : $mimeTypeIcon; $tmpl->assign('previewImageLink', $mimeTypeIcon); $tmpl->assign('previewLinkIsDir', true); } } return $tmpl->fetchPage(); }
/** * Add notifications for the owners whose files have been reshared * * @param string $currentOwner * @param string $subject * @param string $shareWith * @param int $fileSource * @param string $itemType */ protected function shareNotificationForOriginalOwners($currentOwner, $subject, $shareWith, $fileSource, $itemType) { // Get the full path of the current user $this->view->chroot('/' . $currentOwner . '/files'); try { $path = $this->view->getPath($fileSource); } catch (NotFoundException $e) { return; } /** * Get the original owner and his path */ $owner = $this->view->getOwner($path); if ($owner !== $currentOwner) { $this->reshareNotificationForSharer($owner, $subject, $shareWith, $fileSource, $itemType); } /** * Get the sharee who shared the item with the currentUser */ $this->view->chroot('/' . $currentOwner . '/files'); $mount = $this->view->getMount($path); if (!$mount instanceof IMountPoint) { return; } $storage = $mount->getStorage(); if (!$storage->instanceOfStorage('OC\\Files\\Storage\\Shared')) { return; } /** @var \OC\Files\Storage\Shared $storage */ $shareOwner = $storage->getSharedFrom(); if ($shareOwner === '' || $shareOwner === null || $shareOwner === $owner || $shareOwner === $currentOwner) { return; } $this->reshareNotificationForSharer($shareOwner, $subject, $shareWith, $fileSource, $itemType); }
/** * @param string $user * @param int $fileId * @param string $filePath * @return array */ protected function findInfoById($user, $fileId, $filePath) { $this->view->chroot('/' . $user . '/files'); $cache = ['path' => $filePath, 'exists' => false, 'is_dir' => false, 'view' => '']; $notFound = false; try { $path = $this->view->getPath($fileId); $cache['path'] = $path; $cache['is_dir'] = $this->view->is_dir($path); $cache['exists'] = true; } catch (NotFoundException $e) { // The file was not found in the normal view, maybe it is in // the trashbin? $this->view->chroot('/' . $user . '/files_trashbin'); try { $path = $this->view->getPath($fileId); $cache = ['path' => substr($path, strlen('/files')), 'exists' => true, 'is_dir' => $this->view->is_dir($path), 'view' => 'trashbin']; } catch (NotFoundException $e) { $notFound = true; } } $this->cacheId[$user][$fileId] = $cache; if ($notFound) { $this->cacheId[$user][$fileId]['path'] = null; } return $cache; }
/** * @param string $owner * @param int $fileId * @param string $filePath * @return array */ protected function getPreview($owner, $fileId, $filePath) { $info = $this->infoCache->getInfoById($owner, $fileId, $filePath); if (!$info['exists'] || $info['view'] !== '') { return $this->getPreviewFromPath($filePath, $info); } $preview = ['link' => $this->getPreviewLink($info['path'], $info['is_dir'], $info['view']), 'source' => '', 'isMimeTypeIcon' => true]; // show a preview image if the file still exists if ($info['is_dir']) { $preview['source'] = $this->getPreviewPathFromMimeType('dir'); } else { $this->view->chroot('/' . $owner . '/files'); $fileInfo = $this->view->getFileInfo($info['path']); if (!$fileInfo instanceof FileInfo) { $pathPreview = $this->getPreviewFromPath($filePath, $info); $preview['source'] = $pathPreview['source']; } else { if ($this->preview->isAvailable($fileInfo)) { $preview['isMimeTypeIcon'] = false; $preview['source'] = $this->urlGenerator->linkToRoute('core_ajax_preview', ['file' => $info['path'], 'c' => $this->view->getETag($info['path']), 'x' => 150, 'y' => 150]); } else { $preview['source'] = $this->getPreviewPathFromMimeType($fileInfo->getMimetype()); } } } return $preview; }
/** * Encrypt all files in a directory * @param string $dirPath the directory whose files will be encrypted * @return bool * @note Encryption is recursive */ public function encryptAll($dirPath) { $result = true; $found = $this->findEncFiles($dirPath); // Disable proxy to prevent file being encrypted twice \OC_FileProxy::$enabled = false; $versionStatus = \OCP\App::isEnabled('files_versions'); \OC_App::disable('files_versions'); $encryptedFiles = array(); // Encrypt unencrypted files foreach ($found['plain'] as $plainFile) { //get file info $fileInfo = \OC\Files\Filesystem::getFileInfo($plainFile['path']); //relative to data/<user>/file $relPath = $plainFile['path']; //relative to /data $rawPath = '/' . $this->userId . '/files/' . $plainFile['path']; // keep timestamp $timestamp = $fileInfo['mtime']; // Open plain file handle for binary reading $plainHandle = $this->view->fopen($rawPath, 'rb'); // Open enc file handle for binary writing, with same filename as original plain file $encHandle = fopen('crypt://' . $rawPath . '.part', 'wb'); if (is_resource($encHandle) && is_resource($plainHandle)) { // Move plain file to a temporary location $size = stream_copy_to_stream($plainHandle, $encHandle); fclose($encHandle); fclose($plainHandle); $fakeRoot = $this->view->getRoot(); $this->view->chroot('/' . $this->userId . '/files'); $this->view->rename($relPath . '.part', $relPath); // set timestamp $this->view->touch($relPath, $timestamp); $encSize = $this->view->filesize($relPath); $this->view->chroot($fakeRoot); // Add the file to the cache \OC\Files\Filesystem::putFileInfo($relPath, array('encrypted' => true, 'size' => $encSize, 'unencrypted_size' => $size, 'etag' => $fileInfo['etag'])); $encryptedFiles[] = $relPath; } else { \OCP\Util::writeLog('files_encryption', 'initial encryption: could not encrypt ' . $rawPath, \OCP\Util::FATAL); $result = false; } } \OC_FileProxy::$enabled = true; if ($versionStatus) { \OC_App::enable('files_versions'); } $result = $result && $this->encryptVersions($encryptedFiles); return $result; }
/** * @medium */ function testFailShareFile() { // login as admin self::loginHelper(self::TEST_ENCRYPTION_SHARE_USER1); // save file with content $cryptedFile = file_put_contents('crypt:///' . self::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename, $this->dataShort); // test that data was successfully written $this->assertInternalType('int', $cryptedFile); // disable encryption proxy to prevent recursive calls $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; // get the file info from previous created file $fileInfo = $this->view->getFileInfo('/' . self::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename); // check if we have a valid file info $this->assertInstanceOf('\\OC\\Files\\FileInfo', $fileInfo); // check if the unencrypted file size is stored $this->assertGreaterThan(0, $fileInfo['unencrypted_size']); // break users public key $this->view->rename(\OCA\Files_Encryption\Keymanager::getPublicKeyPath() . '/' . self::TEST_ENCRYPTION_SHARE_USER3 . '.publicKey', \OCA\Files_Encryption\Keymanager::getPublicKeyPath() . '/' . self::TEST_ENCRYPTION_SHARE_USER3 . '.publicKey_backup'); // re-enable the file proxy \OC_FileProxy::$enabled = $proxyStatus; // share the file try { \OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_GROUP, self::TEST_ENCRYPTION_SHARE_GROUP1, \OCP\Constants::PERMISSION_ALL); } catch (\Exception $e) { $this->assertEquals(0, strpos($e->getMessage(), "Following users are not set up for encryption")); } // login as admin self::loginHelper(self::TEST_ENCRYPTION_SHARE_USER1); // check if share key for user1 not exists $this->assertFalse($this->view->file_exists('/' . self::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/keys/' . $this->filename . '/' . self::TEST_ENCRYPTION_SHARE_USER3 . '.shareKey')); // disable encryption proxy to prevent recursive calls $proxyStatus = \OC_FileProxy::$enabled; \OC_FileProxy::$enabled = false; // break user1 public key $this->view->rename(\OCA\Files_Encryption\Keymanager::getPublicKeyPath() . '/' . self::TEST_ENCRYPTION_SHARE_USER3 . '.publicKey_backup', \OCA\Files_Encryption\Keymanager::getPublicKeyPath() . '/' . self::TEST_ENCRYPTION_SHARE_USER3 . '.publicKey'); // remove share file $this->view->unlink('/' . self::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/keys/' . $this->filename . '/' . self::TEST_ENCRYPTION_SHARE_USER3 . '.shareKey'); // re-enable the file proxy \OC_FileProxy::$enabled = $proxyStatus; // unshare the file with user1 \OCP\Share::unshare('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_GROUP, self::TEST_ENCRYPTION_SHARE_GROUP1); // check if share key not exists $this->assertFalse($this->view->file_exists('/' . self::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/keys/' . $this->filename . '/' . self::TEST_ENCRYPTION_SHARE_USER3 . '.shareKey')); // cleanup $this->view->chroot('/' . self::TEST_ENCRYPTION_SHARE_USER1 . '/files/'); $this->view->unlink($this->filename); $this->view->chroot('/'); }
/** * test rename operation */ function doTestRenameHook($filename) { // check if keys exists $this->assertTrue($this->rootView->file_exists( '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/' . $filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey')); $this->assertTrue($this->rootView->file_exists( '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' . $filename . '.key')); // make subfolder and sub-subfolder $this->rootView->mkdir('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder); $this->rootView->mkdir('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder . '/' . $this->folder); $this->assertTrue($this->rootView->is_dir('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder . '/' . $this->folder)); // move the file to the sub-subfolder $root = $this->rootView->getRoot(); $this->rootView->chroot('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/'); $this->rootView->rename($filename, '/' . $this->folder . '/' . $this->folder . '/' . $filename); $this->rootView->chroot($root); $this->assertFalse($this->rootView->file_exists('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $filename)); $this->assertTrue($this->rootView->file_exists('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder . '/' . $this->folder . '/' . $filename)); // keys should be renamed too $this->assertFalse($this->rootView->file_exists( '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/' . $filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey')); $this->assertFalse($this->rootView->file_exists( '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' . $filename . '.key')); $this->assertTrue($this->rootView->file_exists( '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/' . $this->folder . '/' . $this->folder . '/' . $filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey')); $this->assertTrue($this->rootView->file_exists( '/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' . $this->folder . '/' . $this->folder . '/' . $filename . '.key')); // cleanup $this->rootView->unlink('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder); }
/** * @param string $owner * @param int $fileId * @param string $filePath * @return array */ protected function getPreview($owner, $fileId, $filePath) { $this->view->chroot('/' . $owner . '/files'); $path = $this->view->getPath($fileId); if ($path === null || $path === '' || !$this->view->file_exists($path)) { return $this->getPreviewFromPath($filePath); } $is_dir = $this->view->is_dir($path); $preview = ['link' => $this->getPreviewLink($path, $is_dir), 'source' => '', 'isMimeTypeIcon' => true]; // show a preview image if the file still exists if ($is_dir) { $preview['source'] = $this->getPreviewPathFromMimeType('dir'); } else { $fileInfo = $this->view->getFileInfo($path); if ($this->preview->isAvailable($fileInfo)) { $preview['isMimeTypeIcon'] = false; $preview['source'] = $this->urlGenerator->linkToRoute('core_ajax_preview', ['file' => $path, 'c' => $this->view->getETag($path), 'x' => 150, 'y' => 150]); } else { $preview['source'] = $this->getPreviewPathFromMimeType($fileInfo->getMimetype()); } } return $preview; }