From 95c99948d72e345088048aec6a6af7f1c9e87ec6 Mon Sep 17 00:00:00 2001 From: Nils Asmussen Date: Sun, 21 Aug 2016 14:54:31 +0200 Subject: [PATCH] Allow guests to download multiple items, too. For this, the album/photo contextmenus and multiselect is now enabled for guests, but limited to the download items. Additionally, Photo::getPublic has been extended to support multiple photos and also optimized to use just one DB query. --- php/Access/Guest.php | 28 ++++++++++-------- php/Modules/Photo.php | 46 +++++++++++------------------ src/scripts/contextMenu.js | 60 ++++++++++++++++++++++---------------- src/scripts/lychee.js | 2 -- src/scripts/multiselect.js | 1 - 5 files changed, 68 insertions(+), 69 deletions(-) diff --git a/php/Access/Guest.php b/php/Access/Guest.php index 8f0f72b..d5c1390 100644 --- a/php/Access/Guest.php +++ b/php/Access/Guest.php @@ -32,6 +32,7 @@ final class Guest extends Access { // $_GET functions case 'Album::getArchive': self::getAlbumArchiveAction(); break; + case 'Photo::getArchive': self::getPhotoArchiveAction(); break; case 'Photo::getPhoto': self::getPhotoFileAction(); break; } @@ -159,6 +160,19 @@ final class Guest extends Access { } + private static function getPhotoArchiveAction() { + + Validator::required(isset($_GET['photoIDs']), $_GET['password'], __METHOD__); + + $photo = new Photo($_GET['photoIDs']); + + $pgP = $photo->getPublic($_GET['password']); + + if ($pgP===2) $photo->getArchive(); + else Response::warning('Photo private or password incorrect!'); + + } + private static function getPhotoFileAction() { Validator::required(isset($_GET['photoID'], $_GET['password']), __METHOD__); @@ -167,18 +181,8 @@ final class Guest extends Access { $pgP = $photo->getPublic($_GET['password']); - // Photo Download - if ($pgP===2) { - - // Photo Public - $photo->getPhoto(); - - } else { - - // Photo Private - Response::warning('Photo private or password incorrect!'); - - } + if ($pgP===2) $photo->getPhoto(); + else Response::warning('Photo private or password incorrect!'); } diff --git a/php/Modules/Photo.php b/php/Modules/Photo.php index 006baec..2f49acd 100755 --- a/php/Modules/Photo.php +++ b/php/Modules/Photo.php @@ -1067,10 +1067,10 @@ final class Photo { } /** - * Checks if photo or parent album is public. - * @return integer 0 = Photo private and parent album private - * 1 = Album public, but password incorrect - * 2 = Photo public or album public and password correct + * Checks if all photos or their parent albums are public. + * @return integer 0 = At least one photo private and parent album private + * 1 = At least one album public, but password incorrect + * 2 = All photos public or album public and password correct */ public function getPublic($password) { @@ -1081,46 +1081,34 @@ final class Photo { Plugins::get()->activate(__METHOD__, 0, func_get_args()); // Get photo - $query = Database::prepare(Database::get(), "SELECT public, album FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); + $query = Database::prepare(Database::get(), "SELECT p.public AS photo_public, a.public AS album_public, password FROM ? AS p JOIN ? AS a ON a.id = p.album WHERE p.id IN (?)", array(LYCHEE_TABLE_PHOTOS, LYCHEE_TABLE_ALBUMS, $this->photoIDs)); $photos = Database::execute(Database::get(), $query, __METHOD__, __LINE__); if ($photos===false) return 0; - // Get photo object - $photo = $photos->fetch_object(); - - // Photo not found? - if ($photo===null) { - Log::error(Database::get(), __METHOD__, __LINE__, 'Could not find specified photo'); - return false; + // Not all photos found? + if ($photos->num_rows != count(explode(',', $this->photoIDs))) { + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not find specified photos'); + return 0; } - // Check if public - if ($photo->public==='1') { + while ($photo = $photos->fetch_object()) { - // Photo public - return 2; + // Check if public + if ($photo->photo_public==='1') continue; - } else { + // Album private + if ($photo->album_public==='0') return 0; - // Check if album public - $album = new Album($photo->album); - $agP = $album->getPublic(); - $acP = $album->checkPassword($password); - - // Album public and password correct - if ($agP===true&&$acP===true) return 2; - - // Album public, but password incorrect - if ($agP===true&&$acP===false) return 1; + // Check if password is correct + if ($photo->password!='' && $photo->password!==crypt($password, $photo->password)) return 1; } // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); - // Photo private - return 0; + return 2; } diff --git a/src/scripts/contextMenu.js b/src/scripts/contextMenu.js index e5af8cc..bea0005 100644 --- a/src/scripts/contextMenu.js +++ b/src/scripts/contextMenu.js @@ -116,10 +116,10 @@ contextMenu.album = function(albumID, e) { let items = [ { title: build.iconic('cloud-download') + 'Download', fn: () => album.getArchive([ albumID ]) }, - { title: build.iconic('pencil') + 'Rename', fn: () => album.setTitle([ albumID ]) }, - { title: build.iconic('collapse-left') + 'Merge', fn: () => { basicContext.close(); contextMenu.mergeAlbum(albumID, e) } }, - { title: build.iconic('folder') + 'Move', fn: () => { basicContext.close(); contextMenu.moveAlbum([ albumID ], e) } }, - { title: build.iconic('trash') + 'Delete', fn: () => album.delete([ albumID ]) } + { title: build.iconic('pencil') + 'Rename', visible: !lychee.publicMode, fn: () => album.setTitle([ albumID ]) }, + { title: build.iconic('collapse-left') + 'Merge', visible: !lychee.publicMode, fn: () => { basicContext.close(); contextMenu.mergeAlbum(albumID, e) } }, + { title: build.iconic('folder') + 'Move', visible: !lychee.publicMode, fn: () => { basicContext.close(); contextMenu.moveAlbum([ albumID ], e) } }, + { title: build.iconic('trash') + 'Delete', visible: !lychee.publicMode, fn: () => album.delete([ albumID ]) } ] multiselect.select('.album[data-id="' + albumID + '"]') @@ -138,11 +138,11 @@ contextMenu.albumMulti = function(albumIDs, e) { let items = [ { title: build.iconic('cloud-download') + 'Download All', fn: () => album.getArchive(albumIDs) }, - { title: build.iconic('pencil') + 'Rename All', fn: () => album.setTitle(albumIDs) }, - { title: build.iconic('collapse-left') + 'Merge All', visible: autoMerge, fn: () => album.merge(albumIDs) }, - { title: build.iconic('collapse-left') + 'Merge', visible: !autoMerge, fn: () => { basicContext.close(); contextMenu.mergeAlbum(albumIDs[0], e) } }, - { title: build.iconic('folder') + 'Move All', fn: () => { basicContext.close(); contextMenu.moveAlbum(albumIDs, e) } }, - { title: build.iconic('trash') + 'Delete All', fn: () => album.delete(albumIDs) } + { title: build.iconic('pencil') + 'Rename All', visible: !lychee.publicMode, fn: () => album.setTitle(albumIDs) }, + { title: build.iconic('collapse-left') + 'Merge All', visible: !lychee.publicMode && autoMerge, fn: () => album.merge(albumIDs) }, + { title: build.iconic('collapse-left') + 'Merge', visible: !lychee.publicMode && !autoMerge, fn: () => { basicContext.close(); contextMenu.mergeAlbum(albumIDs[0], e) } }, + { title: build.iconic('folder') + 'Move All', visible: !lychee.publicMode, fn: () => { basicContext.close(); contextMenu.moveAlbum(albumIDs, e) } }, + { title: build.iconic('trash') + 'Delete All', visible: !lychee.publicMode, fn: () => album.delete(albumIDs) } ] items.push() @@ -244,16 +244,21 @@ contextMenu.photo = function(photoID, e) { // in order to keep the selection let items = [ - { title: build.iconic('cloud-download') + 'Download', fn: () => photo.getPhoto(photoID) }, - { title: build.iconic('star') + 'Star', fn: () => photo.setStar([ photoID ]) }, - { title: build.iconic('tag') + 'Tags', fn: () => photo.editTags([ photoID ]) }, - { }, - { title: build.iconic('pencil') + 'Rename', fn: () => photo.setTitle([ photoID ]) }, - { title: build.iconic('layers') + 'Duplicate', fn: () => photo.duplicate([ photoID ]) }, - { title: build.iconic('folder') + 'Move', fn: () => { basicContext.close(); contextMenu.move([ photoID ], e) } }, - { title: build.iconic('trash') + 'Delete', fn: () => photo.delete([ photoID ]) } + { title: build.iconic('cloud-download') + 'Download', fn: () => photo.getPhoto(photoID) } ] + if (!lychee.publicMode) { + items = items.concat([ + { title: build.iconic('star') + 'Star', fn: () => photo.setStar([ photoID ]) }, + { title: build.iconic('tag') + 'Tags', fn: () => photo.editTags([ photoID ]) }, + { }, + { title: build.iconic('pencil') + 'Rename', fn: () => photo.setTitle([ photoID ]) }, + { title: build.iconic('layers') + 'Duplicate', fn: () => photo.duplicate([ photoID ]) }, + { title: build.iconic('folder') + 'Move', fn: () => { basicContext.close(); contextMenu.move([ photoID ], e) } }, + { title: build.iconic('trash') + 'Delete', fn: () => photo.delete([ photoID ]) } + ]) + } + multiselect.select('.photo[data-id="' + photoID + '"]') basicContext.show(items, e.originalEvent, contextMenu.close) @@ -269,16 +274,21 @@ contextMenu.photoMulti = function(photoIDs, e) { // in order to keep the selection and multiselect let items = [ - { title: build.iconic('cloud-download') + 'Download All', fn: () => photo.getArchive(photoIDs) }, - { title: build.iconic('star') + 'Star All', fn: () => photo.setStar(photoIDs) }, - { title: build.iconic('tag') + 'Tag All', fn: () => photo.editTags(photoIDs) }, - { }, - { title: build.iconic('pencil') + 'Rename All', fn: () => photo.setTitle(photoIDs) }, - { title: build.iconic('layers') + 'Duplicate All', fn: () => photo.duplicate(photoIDs) }, - { title: build.iconic('folder') + 'Move All', fn: () => { basicContext.close(); contextMenu.move(photoIDs, e) } }, - { title: build.iconic('trash') + 'Delete All', fn: () => photo.delete(photoIDs) } + { title: build.iconic('cloud-download') + 'Download All', fn: () => photo.getArchive(photoIDs) } ] + if (!lychee.publicMode) { + items = items.concat([ + { title: build.iconic('star') + 'Star All', fn: () => photo.setStar(photoIDs) }, + { title: build.iconic('tag') + 'Tag All', fn: () => photo.editTags(photoIDs) }, + { }, + { title: build.iconic('pencil') + 'Rename All', fn: () => photo.setTitle(photoIDs) }, + { title: build.iconic('layers') + 'Duplicate All', fn: () => photo.duplicate(photoIDs) }, + { title: build.iconic('folder') + 'Move All', fn: () => { basicContext.close(); contextMenu.move(photoIDs, e) } }, + { title: build.iconic('trash') + 'Delete All', fn: () => photo.delete(photoIDs) } + ]) + } + basicContext.show(items, e.originalEvent, contextMenu.close) } diff --git a/src/scripts/lychee.js b/src/scripts/lychee.js index 5c5de87..81be85b 100644 --- a/src/scripts/lychee.js +++ b/src/scripts/lychee.js @@ -251,8 +251,6 @@ lychee.setMode = function(mode) { $(document) .off('click', '.header__title--editable') .off('touchend', '.header__title--editable') - .off('contextmenu', '.photo') - .off('contextmenu', '.album') .off('drop') Mousetrap diff --git a/src/scripts/multiselect.js b/src/scripts/multiselect.js index 1b7b2db..38a75f7 100644 --- a/src/scripts/multiselect.js +++ b/src/scripts/multiselect.js @@ -150,7 +150,6 @@ multiselect.clearSelection = function(deselect = true) { multiselect.show = function(e) { - if (lychee.publicMode) return false if (!visible.albums() && !visible.album()) return false if ($('.album:hover, .photo:hover').length!==0) return false if (visible.search()) return false