diff options
-rw-r--r-- | controller/servicecontroller.php | 76 | ||||
-rw-r--r-- | css/gallerybutton.css | 2 | ||||
-rw-r--r-- | css/styles.css | 13 | ||||
-rw-r--r-- | environment/environment.php | 3 | ||||
-rw-r--r-- | js/gallery.js | 38 | ||||
-rw-r--r-- | service/infoservice.php | 160 |
6 files changed, 194 insertions, 98 deletions
diff --git a/controller/servicecontroller.php b/controller/servicecontroller.php index 70848ea3..6243cfbd 100644 --- a/controller/servicecontroller.php +++ b/controller/servicecontroller.php @@ -17,14 +17,11 @@ namespace OCA\GalleryPlus\Controller; use OCP\IEventSource; use OCP\IURLGenerator; use OCP\IRequest; -use OCP\Files\Folder; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; use OCP\AppFramework\Http\JSONResponse; -use Symfony\Component\Yaml\Yaml; - use OCA\GalleryPlus\Environment\Environment; use OCA\GalleryPlus\Environment\EnvironmentException; use OCA\GalleryPlus\Http\ImageResponse; @@ -135,17 +132,18 @@ class ServiceController extends Controller { public function getFiles($location) { try { $imagesFolder = $this->environment->getResourceFromPath($location); + $fromRootToFolder = $this->environment->getFromRootToFolder(); + list($albumInfo, $privateAlbum) = + $this->infoService->getAlbumInfo($imagesFolder, $fromRootToFolder); - if (is_null($imagesFolder) || $this->isFolderPrivate($imagesFolder)) { - return new JSONResponse(['message' => 'Oh Nooooes!', 'success' => false], 500); + if ($privateAlbum) { + return new JSONResponse(['message' => 'Album is private', 'success' => false], 403); } - $fromRootToFolder = $this->environment->getFromRootToFolder(); $folderData = [ 'imagesFolder' => $imagesFolder, 'fromRootToFolder' => $fromRootToFolder, ]; $files = $this->infoService->getImages($folderData); - $albumInfo = $this->getAlbumInfo($imagesFolder, $fromRootToFolder); return ['files' => $files, 'albuminfo' => $albumInfo]; } catch (EnvironmentException $exception) { @@ -229,70 +227,6 @@ class ServiceController extends Controller { } /** - * Checks if we're authorised to look for pictures in this folder - * - * @param Folder $folder - * - * @return bool - */ - private function isFolderPrivate($folder) { - if ($folder->nodeExists('.nomedia')) { - return true; - } else { - $path = $folder->getPath(); - if ($path !== '' && $path !== '/') { - $folder = $folder->getParent(); - - return $this->isFolderPrivate($folder); - } - } - - return false; - } - - /** - * Returns information about the currently selected folders - * - * @param Folder $folderNode - * @param string $folderPathFromRoot - * - * @return array<string,string|int> - */ - private function getAlbumInfo($folderNode, $folderPathFromRoot) { - $path = str_replace($folderPathFromRoot, '', $folderNode->getPath()); - if (rtrim($folderPathFromRoot, '/') === $folderNode->getPath()) { - $path = ''; - } - $albumInfo = [ - 'path' => $path, - 'fileid' => $folderNode->getID(), - 'permissions' => $folderNode->getPermissions() - ]; - $albumInfo = array_merge($albumInfo, $this->hasAlbumConfig($folderNode)); - - return $albumInfo; - } - - /** - * Returns an album configuration array - * - * @param Folder $folder - * - * @return array<null|string,string> - */ - private function hasAlbumConfig($folder) { - $configName = 'gallery.cnf'; - $config = []; - if ($folder->nodeExists($configName)) { - /** @type \OCP\Files\File $configFile */ - $configFile = $folder->get($configName); - $config = Yaml::parse($configFile->getContent()); - } - - return $config; - } - - /** * Retrieves the thumbnail to send back to the browser * * The thumbnail is either a resized preview of the file or the original file diff --git a/css/gallerybutton.css b/css/gallerybutton.css index 1227a514..2219fda2 100644 --- a/css/gallerybutton.css +++ b/css/gallerybutton.css @@ -1,7 +1,7 @@ /* toggle for opening shared picture view as file list */ #openAsFileListButton { float: left; - margin-top: 4px; + margin-top: 5px; margin-right: 0; font-weight: normal; } diff --git a/css/styles.css b/css/styles.css index 2b0f8306..8b605fbe 100644 --- a/css/styles.css +++ b/css/styles.css @@ -8,23 +8,22 @@ overflow: hidden; } -button.share { - display: none; - margin-top: 4px; +#controls .button { + margin-top: 5px; } -#album-info-button { - margin-top: 4px; +button.share { + margin-top: 5px; } .album-info-content { background-color: #eee; border-bottom-left-radius: 5px; box-shadow: 0 1px 1px #777; - display:none; + display: none; z-index: 600; width: 420px; - min-height: 60px; + min-height: 100px; max-height: 600px; position: absolute; top: 43px; diff --git a/environment/environment.php b/environment/environment.php index f09b5474..776114da 100644 --- a/environment/environment.php +++ b/environment/environment.php @@ -19,6 +19,7 @@ use OCP\IUserManager; use OCP\Share; use OCP\Files\Folder; use OCP\Files\Node; +use OCP\Files\File; use OCP\Files\NotFoundException; use OCA\GalleryPlus\Utility\SmarterLogger; @@ -143,7 +144,7 @@ class Environment { * * @param string $subPath * - * @return Node + * @return File|Folder */ public function getResourceFromPath($subPath) { $path = $this->getImagePathFromFolder($subPath); diff --git a/js/gallery.js b/js/gallery.js index 016020d0..99aae2a4 100644 --- a/js/gallery.js +++ b/js/gallery.js @@ -8,6 +8,7 @@ Gallery.albumMap = {}; Gallery.imageMap = {}; Gallery.appName = 'galleryplus'; Gallery.token = undefined; +Gallery.currentSort = {}; Gallery.getAlbum = function (path) { if (!Gallery.albumMap[path]) { @@ -81,16 +82,21 @@ Gallery.fillAlbums = function () { var sortType = 'name'; var sortOrder = 'asc'; var albumSortOrder = 'asc'; - if (albumInfo.sorting !== null) { + if (!$.isEmptyObject(albumInfo.sorting)) { sortType = albumInfo.sorting; } - if (albumInfo.sort_order !== null) { + if (!$.isEmptyObject(albumInfo.sort_order)) { sortOrder = albumInfo.sort_order; if (sortType === 'name') { albumSortOrder = sortOrder; } } + Gallery.currentSort = { + type: sortType, + order: sortOrder + }; + for (var j = 0, keys = Object.keys(Gallery.albumMap); j < keys.length; j++) { Gallery.albumMap[keys[j]].images.sort(Gallery.sortBy(sortType, sortOrder)); Gallery.albumMap[keys[j]].subAlbums.sort(Gallery.sortBy('name', albumSortOrder)); @@ -196,19 +202,18 @@ Gallery.download = function (event) { }; Gallery.showInfo = function (event) { - //event.preventDefault(); event.stopPropagation(); var infoContentElement = $('.album-info-content'); if (infoContentElement.is(':visible')) { infoContentElement.slideUp(); } else { + // Fixme At this stage, the old content is still loaded infoContentElement.slideDown(); - var albumInfo = Gallery.albumsInfo[Gallery.currentAlbum]; if (!albumInfo.infoLoaded) { + infoContentElement.empty(); if (!$.isEmptyObject(albumInfo.description)) { - infoContentElement.empty(); var params = { file: Gallery.currentAlbum + '/' + albumInfo.description }; @@ -217,14 +222,13 @@ Gallery.showInfo = function (event) { $.get(descriptionUrl).done(function (data) { infoContentElement.append(marked(data)); infoContentElement.find('a').attr("target", "_blank"); - Gallery.showCopyright(albumInfo, infoContentElement); } ).fail(function () { infoContentElement.append('<p>' + t('gallery', 'Could not load the description') + '</p>'); + Gallery.showCopyright(albumInfo, infoContentElement); }); - infoContentElement.removeClass('icon-loading'); } else { Gallery.showCopyright(albumInfo, infoContentElement); @@ -240,13 +244,11 @@ Gallery.showCopyright = function (albumInfo, infoContentElement) { var copyrightTitle = $('<h4/>'); copyrightTitle.append(t('gallery', 'Copyright')); infoContentElement.append(copyrightTitle); - var p = $('<p/>'); - infoContentElement.append(p); if (!$.isEmptyObject(albumInfo.copyright)) { - copyright = albumInfo.copyright; + copyright = marked(albumInfo.copyright); } else { - copyright = t('gallery', 'Copyright notice'); + copyright = '<p>' + t('gallery', 'Copyright notice') + '</p>'; } if (!$.isEmptyObject(albumInfo.copyrightLink)) { @@ -263,14 +265,14 @@ Gallery.showCopyright = function (albumInfo, infoContentElement) { } var copyrightUrl = OC.generateUrl(subUrl, params); var copyrightLink = $('<a>', { - text: copyright, + html: copyright, title: copyright, href: copyrightUrl, target: "_blank" }); - p.append(copyrightLink); + infoContentElement.append(copyrightLink); } else { - p.append(copyright); + infoContentElement.append(copyright); } } }; @@ -319,11 +321,11 @@ Gallery.view.viewAlbum = function (albumPath) { Gallery.view.clear(); if (albumPath !== Gallery.currentAlbum) { Gallery.view.loadVisibleRows.loading = false; + Gallery.currentAlbum = albumPath; + Gallery.view.shareButtonSetup(albumPath); + Gallery.view.infoButtonSetup(); + Gallery.view.buildBreadCrumb(albumPath); } - Gallery.currentAlbum = albumPath; - Gallery.view.shareButtonSetup(albumPath); - Gallery.view.infoButtonSetup(); - Gallery.view.buildBreadCrumb(albumPath); Gallery.albumMap[albumPath].viewedItems = 0; setTimeout(function () { diff --git a/service/infoservice.php b/service/infoservice.php index c07b101d..cbc23fa8 100644 --- a/service/infoservice.php +++ b/service/infoservice.php @@ -12,6 +12,8 @@ namespace OCA\GalleryPlus\Service; +use Symfony\Component\Yaml\Yaml; + use OCP\Files\Folder; use OCP\Files\File; use OCP\Files\Node; @@ -120,6 +122,42 @@ class InfoService extends Service { } /** + * Returns information about the currently selected folder + * + * * privacy setting + * * special configuration + * * permissions + * * ID + * + * @param Folder $folderNode + * @param string $folderPathFromRoot + * + * @return array<string,string|int> + */ + public function getAlbumInfo($folderNode, $folderPathFromRoot) { + $configName = 'gallery.cnf'; + $privacyChecker = '.nomedia'; + $albumInfo = []; + list ($albumConfig, $privateAlbum) = + $this->getAlbumConfig($folderNode, $privacyChecker, $configName); + + if (!$privateAlbum) { + $path = str_replace($folderPathFromRoot, '', $folderNode->getPath()); + if (rtrim($folderPathFromRoot, '/') === $folderNode->getPath()) { + $path = ''; + } + $albumInfo = [ + 'path' => $path, + 'fileid' => $folderNode->getID(), + 'permissions' => $folderNode->getPermissions() + ]; + $albumInfo = array_merge($albumInfo, $albumConfig); + } + + return [$albumInfo, $privateAlbum]; + } + + /** * This returns the list of all images which can be shown starting from the given folder * * If the starting URL is one of a fullscreen preview, we'll return the images of the @@ -145,6 +183,128 @@ class InfoService extends Service { } /** + * Returns an album configuration array + * + * @param Folder $folder + * @param string $privacyChecker + * @param string $configName + * @param int $level + * @param array $configArray + * @param bool $configComplete + * + * @return array <null|string,string> + */ + private function getAlbumConfig( + $folder, $privacyChecker, $configName, $level = 0, $configArray = [], + $configComplete = false + ) { + if ($folder->nodeExists($privacyChecker)) { + // Cancel as soon as we find out that the folder is private + return [null, true]; + } + list($configArray, $configComplete) = + $this->parseConfig($folder, $configName, $configArray, $configComplete, $level); + $parentFolder = $folder->getParent(); + $path = $parentFolder->getPath(); + if ($path !== '' && $path !== '/') { + $level++; + + return $this->getAlbumConfig( + $parentFolder, $privacyChecker, $configName, $level, $configArray, $configComplete + ); + } + + // We have reached the root folder + return [$configArray, false]; + } + + /** + * Returns a parsed configuration if one was found in the current folder + * + * @param Folder $folder + * @param string $configName + * @param array $currentConfigArray + * @param bool $configComplete + * @param int $level + * + * @return bool + */ + private function parseConfig( + $folder, $configName, $currentConfigArray, $configComplete, $level + ) { + $configArray = $currentConfigArray; + // Let's try to find the missing information in the configuration located in this folder + if (!$configComplete && $folder->nodeExists($configName)) { + /** @type File $configFile */ + $configFile = $folder->get($configName); + try { + $rawConfig = $configFile->getContent(); + $saneConfig = $this->bomFixer($rawConfig); + $parsedConfigArray = Yaml::parse($saneConfig); + list($configArray, $configComplete) = + $this->validateConfig($currentConfigArray, $parsedConfigArray, $level); + } catch (\Exception $exception) { + $this->logger->debug( + "Problem while parsing the configuration file : {path}", + ['path' => $folder->getPath() . '/' . $configFile->getPath()] + ); + } + } + + return [$configArray, $configComplete]; + } + + /** + * Removes the BOM from a file + * + * http://us.php.net/manual/en/function.pack.php#104151 + * + * @param string $file + * + * @return string + */ + private function bomFixer($file) { + $bom = pack("CCC", 0xef, 0xbb, 0xbf); + if (strncmp($file, $bom, 3) === 0) { + $file = substr($file, 3); + } + + return $file; + } + + /** + * Returns either the local config or one merged with a config containing sorting information + * + * @param array $currentConfigArray + * @param array $parsedConfigArray + * @param int $level + * + * @return array + */ + private function validateConfig($currentConfigArray, $parsedConfigArray, $level) { + $configComplete = false; + $sorting = $parsedConfigArray['sorting']; + $sortOrder = $parsedConfigArray['sort_order']; + $configArray = $parsedConfigArray; + if ($sorting) { + $configComplete = true; + if ($level > 0) { + // We only need the sorting information + $currentConfigArray['sorting'] = $sorting; + $currentConfigArray['sort_order'] = $sortOrder; + $configArray = $currentConfigArray; + } + } else { + if ($level > 0) { + // Reset the array to what we had earlier since we didn't find any sorting information + $configArray = $currentConfigArray; + } + } + + return [$configArray, $configComplete]; + } + + /** * Look for media files and folders in the given folder * * @param Folder $folder |