diff --git a/docs/Plugins.md b/docs/Plugins.md index 046c2f4..03d506d 100644 --- a/docs/Plugins.md +++ b/docs/Plugins.md @@ -120,8 +120,8 @@ These hooks are called from `php/modules/Photo.php`. | Photo::get:after | | | Photo::getInfo:before | Lychee reads the metadata of an image | | Photo::getInfo:after | | -| Photo::getArchive:before | User downloads photo | -| Photo::getArchive:after | | +| Photo::getPhoto:before | User downloads photo | +| Photo::getPhoto:after | | | Photo::setTitle:before | User renames photo | | Photo::setTitle:after | | | Photo::setDescription:before | User sets description | diff --git a/php/Access/Admin.php b/php/Access/Admin.php index df622f6..30fde25 100644 --- a/php/Access/Admin.php +++ b/php/Access/Admin.php @@ -62,6 +62,7 @@ final class Admin extends Access { // $_GET functions case 'Album::getArchive': self::getAlbumArchiveAction(); break; case 'Photo::getArchive': self::getPhotoArchiveAction(); break; + case 'Photo::getPhoto': self::getPhotoFileAction(); break; } @@ -334,19 +335,28 @@ final class Admin extends Access { private static function getAlbumArchiveAction() { - Validator::required(isset($_GET['albumID']), __METHOD__); + Validator::required(isset($_GET['albumIDs']), __METHOD__); - $album = new Album($_GET['albumID']); + $album = new Album($_GET['albumIDs']); $album->getArchive(); } private static function getPhotoArchiveAction() { + Validator::required(isset($_GET['photoIDs']), __METHOD__); + + $photo = new Photo($_GET['photoIDs']); + $photo->getArchive(); + + } + + private static function getPhotoFileAction() { + Validator::required(isset($_GET['photoID']), __METHOD__); $photo = new Photo($_GET['photoID']); - $photo->getArchive(); + $photo->getPhoto(); } diff --git a/php/Access/Guest.php b/php/Access/Guest.php index 7b988a2..d5c1390 100644 --- a/php/Access/Guest.php +++ b/php/Access/Guest.php @@ -33,6 +33,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; } @@ -140,9 +141,9 @@ final class Guest extends Access { private static function getAlbumArchiveAction() { - Validator::required(isset($_GET['albumID'], $_GET['password']), __METHOD__); + Validator::required(isset($_GET['albumIDs'], $_GET['password']), __METHOD__); - $album = new Album($_GET['albumID']); + $album = new Album($_GET['albumIDs']); if ($album->getPublic()&&$album->getDownloadable()) { @@ -161,24 +162,27 @@ final class Guest extends Access { private static function getPhotoArchiveAction() { - Validator::required(isset($_GET['photoID'], $_GET['password']), __METHOD__); + Validator::required(isset($_GET['photoIDs']), $_GET['password'], __METHOD__); - $photo = new Photo($_GET['photoID']); + $photo = new Photo($_GET['photoIDs']); $pgP = $photo->getPublic($_GET['password']); - // Photo Download - if ($pgP===2) { + if ($pgP===2) $photo->getArchive(); + else Response::warning('Photo private or password incorrect!'); - // Photo Public - $photo->getArchive(); + } - } else { + private static function getPhotoFileAction() { + + Validator::required(isset($_GET['photoID'], $_GET['password']), __METHOD__); - // Photo Private - Response::warning('Photo private or password incorrect!'); + $photo = new Photo($_GET['photoID']); - } + $pgP = $photo->getPublic($_GET['password']); + + if ($pgP===2) $photo->getPhoto(); + else Response::warning('Photo private or password incorrect!'); } diff --git a/php/Modules/Album.php b/php/Modules/Album.php index 143ac64..be0cd4d 100644 --- a/php/Modules/Album.php +++ b/php/Modules/Album.php @@ -2,8 +2,6 @@ namespace Lychee\Modules; -use ZipArchive; - final class Album { private $albumIDs = null; @@ -184,7 +182,7 @@ final class Album { } /** - * Starts a download of an album. + * Starts a download of albums. * @return resource|boolean Sends a ZIP-file or returns false on failure. */ public function getArchive() { @@ -209,68 +207,40 @@ final class Album { $photos = Database::prepare(Database::get(), 'SELECT title, url FROM ? WHERE LEFT(id, 10) >= unix_timestamp(DATE_SUB(NOW(), INTERVAL 1 DAY)) GROUP BY checksum', array(LYCHEE_TABLE_PHOTOS)); $zipTitle = 'Recent'; break; - default: + case 0: + $photos = Database::prepare(Database::get(), 'SELECT title, url FROM ? WHERE album = 0', array(LYCHEE_TABLE_PHOTOS)); $zipTitle = 'Unsorted'; - - // Get title from database when album is not a SmartAlbum - if ($this->albumIDs!=0 && is_numeric($this->albumIDs)) { - - $query = Database::prepare(Database::get(), "SELECT title FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); - $album = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - - if ($album===false) return false; - - // Get album object - $album = $album->fetch_object(); - - // Album not found? - if ($album===null) { - Log::error(Database::get(), __METHOD__, __LINE__, 'Could not find specified album'); - return false; - } - - // Set title - $zipTitle = $album->title; - - } + break; + default: + $zipTitle = 'Albums'; break; } - // Escape title - $zipTitle = $this->cleanZipName($zipTitle); - - $filename = LYCHEE_DATA . $zipTitle . '.zip'; - - // Create zip - $zip = new ZipArchive(); - if ($zip->open($filename, ZIPARCHIVE::CREATE)!==TRUE) { - Log::error(Database::get(), __METHOD__, __LINE__, 'Could not create ZipArchive'); - return false; - } + $archive = new Archive($zipTitle); - // Add photos to zip switch($this->albumIDs) { case 's': case 'f': case 'r': - $this->addPhotosToZip($zip, $zipTitle, $photos); - break; + case 0: + if (!$archive->addPhotos($zipTitle, $photos)) return false; + break; + default: - $this->addAlbumToZip($zip, $zipTitle, $this->albumIDs); - break; - } + // load titles from DB + $query = Database::prepare(Database::get(), "SELECT id, title FROM ? WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs)); + $albums = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - // Finish zip - $zip->close(); + if ($albums===false) return false; - // Send zip - header("Content-Type: application/zip"); - header("Content-Disposition: attachment; filename=\"$zipTitle.zip\""); - header("Content-Length: " . filesize($filename)); - readfile($filename); + // add these albums to zip + while ($album = $albums->fetch_object()) { + if (!$archive->addAlbum($album->title, $album->id)) return false; + } + break; + } - // Delete zip - unlink($filename); + $archive->send(); // Call plugins Plugins::get()->activate(__METHOD__, 1, func_get_args()); @@ -279,84 +249,6 @@ final class Album { } - private function cleanZipName($name) { - - // Illicit chars - $badChars = array_merge( - array_map('chr', range(0,31)), - array("<", ">", ":", '"', "/", "\\", "|", "?", "*") - ); - - return str_replace($badChars, '', $name); - - } - - private function addAlbumToZip($zip, $path, $albumID) { - - // Fetch album title - $photos = Database::prepare(Database::get(), "SELECT title, url FROM ? WHERE album = '?'", array(LYCHEE_TABLE_PHOTOS, $albumID)); - - $this->addPhotosToZip($zip, $path, $photos); - - // Fetch subalbums - $query = Database::prepare(Database::get(), "SELECT id, title FROM ? WHERE parent = '?'", array(LYCHEE_TABLE_ALBUMS, $albumID)); - $albums = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - - // Add them recursively - while($album = $albums->fetch_assoc()) { - $this->addAlbumToZip($zip, $path . '/' . $this->cleanZipName($album['title']), $album['id']); - } - - } - - private function addPhotosToZip($zip, $path, $query) { - - // Execute query - $photos = Database::execute(Database::get(), $query, __METHOD__, __LINE__); - - // Parse each path - $files = array(); - while ($photo = $photos->fetch_object()) { - - // Parse url - $photo->url = LYCHEE_UPLOADS_BIG . $photo->url; - - // Parse title - $photo->title = $this->cleanZipName($photo->title); - if (!isset($photo->title)||$photo->title==='') $photo->title = 'Untitled'; - - // Check if readable - if (!@is_readable($photo->url)) continue; - - // Get extension of image - $extension = getExtension($photo->url, false); - - // Set title for photo - $zipFileName = $path . '/' . $photo->title . $extension; - - // Check for duplicates - if (!empty($files)) { - $i = 1; - while (in_array($zipFileName, $files)) { - - // Set new title for photo - $zipFileName = $path . '/' . $photo->title . '-' . $i . $extension; - - $i++; - - } - } - - // Add to array - $files[] = $zipFileName; - - // Add photo to zip - $zip->addFile($photo->url, $zipFileName); - - } - - } - /** * @return boolean Returns true when successful. */ diff --git a/php/Modules/Archive.php b/php/Modules/Archive.php new file mode 100644 index 0000000..e29e880 --- /dev/null +++ b/php/Modules/Archive.php @@ -0,0 +1,167 @@ +title = $this->cleanZipName($title); + + $this->filename = LYCHEE_DATA . $this->title . '.zip'; + + // Create zip + $this->zip = new ZipArchive(); + if ($this->zip->open($this->filename, ZIPARCHIVE::CREATE)!==TRUE) { + Log::error(Database::get(), __METHOD__, __LINE__, 'Could not create ZipArchive'); + $this->zip = null; + } + + } + + public function __destruct() { + + if ($this->zip!==null) $this->zip->close(); + + unlink($this->filename); + + } + + /** + * Closes the zip file and sends it to the browser. + */ + public function send() { + + // Finish zip + $this->zip->close(); + $this->zip = null; + + // Send zip + header("Content-Type: application/zip"); + header("Content-Disposition: attachment; filename=\"" . $this->title . ".zip\""); + header("Content-Length: " . filesize($this->filename)); + readfile($this->filename); + + } + + /** + * Adds the given album including subalbums at given path to the zip archive. + * + * @param string $path the path in the zip archive + * @param int $albumID the id of the album + * @return true on success + */ + public function addAlbum($path, $albumID) { + + // Fetch photos + $query = Database::prepare(Database::get(), "SELECT title, url FROM ? WHERE album = '?'", array(LYCHEE_TABLE_PHOTOS, $albumID)); + + if (!$this->addPhotos($path, $query)) return false; + + // Fetch subalbums + $query = Database::prepare(Database::get(), "SELECT id, title FROM ? WHERE parent = '?'", array(LYCHEE_TABLE_ALBUMS, $albumID)); + $albums = Database::execute(Database::get(), $query, __METHOD__, __LINE__); + + if ($albums===false) return false; + + // Add them recursively + while($album = $albums->fetch_assoc()) { + if (!$this->addAlbum($path . '/' . $this->cleanZipName($album['title']), $album['id'])) return false; + } + + return true; + + } + + /** + * Adds the photos that are selected by the given query at given path to the zip archive. + * + * @param string $path the path in the zip archive + * @param mysqli_stmt $query the SQL query to execute + * @return true on success + */ + public function addPhotos($path, $query) { + + if ($this->zip===null) return false; + + $photos = Database::execute(Database::get(), $query, __METHOD__, __LINE__); + + if (!$photos) return false; + + // Parse each path + $files = array(); + while ($photo = $photos->fetch_object()) { + + // Parse url + $photo->url = LYCHEE_UPLOADS_BIG . $photo->url; + + // Parse title + $photo->title = $this->cleanZipName($photo->title); + if (!isset($photo->title)||$photo->title==='') $photo->title = 'Untitled'; + + // Check if readable + if (!@is_readable($photo->url)) continue; + + // Get extension of image + $extension = getExtension($photo->url, false); + + // Set title for photo + $zipFileName = $path . '/' . $photo->title . $extension; + + // Check for duplicates + if (!empty($files)) { + $i = 1; + while (in_array($zipFileName, $files)) { + + // Set new title for photo + $zipFileName = $path . '/' . $photo->title . '-' . $i . $extension; + + $i++; + + } + } + + // Add to array + $files[] = $zipFileName; + + // Add photo to zip + $this->zip->addFile($photo->url, $zipFileName); + + } + + return true; + + } + + private function cleanZipName($name) { + + // Illicit chars + $badChars = array_merge( + array_map('chr', range(0,31)), + array("<", ">", ":", '"', "/", "\\", "|", "?", "*") + ); + + return str_replace($badChars, '', $name); + + } + +} + +?> \ No newline at end of file diff --git a/php/Modules/Photo.php b/php/Modules/Photo.php index 59beb77..2f49acd 100755 --- a/php/Modules/Photo.php +++ b/php/Modules/Photo.php @@ -2,7 +2,6 @@ namespace Lychee\Modules; -use ZipArchive; use Imagick; use ImagickPixel; @@ -890,9 +889,9 @@ final class Photo { /** * Starts a download of a photo. - * @return resource|boolean Sends a ZIP-file or returns false on failure. + * @return resource|boolean Sends the photo or returns false on failure. */ - public function getArchive() { + public function getPhoto() { // Check dependencies Validator::required(isset($this->photoIDs), __METHOD__); @@ -949,6 +948,33 @@ final class Photo { } + /** + * Starts a download of photos. + * @return resource|boolean Sends a ZIP-file or returns false on failure. + */ + public function getArchive() { + + // Check dependencies + Validator::required(isset($this->photoIDs), __METHOD__); + + // Call plugins + Plugins::get()->activate(__METHOD__, 0, func_get_args()); + + $archive = new Archive('Photos'); + + $query = Database::prepare(Database::get(), 'SELECT title, url FROM ? WHERE id IN (?)', array(LYCHEE_TABLE_PHOTOS, $this->photoIDs)); + + if (!$archive->addPhotos('', $query)) return false; + + $archive->send(); + + // Call plugins + Plugins::get()->activate(__METHOD__, 1, func_get_args()); + + return true; + + } + /** * Sets the title of a photo. * @return boolean Returns true when successful. @@ -1041,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) { @@ -1055,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') { - - // Photo public - return 2; - - } else { + while ($photo = $photos->fetch_object()) { - // Check if album public - $album = new Album($photo->album); - $agP = $album->getPublic(); - $acP = $album->checkPassword($password); + // Check if public + if ($photo->photo_public==='1') continue; - // Album public and password correct - if ($agP===true&&$acP===true) return 2; + // Album private + if ($photo->album_public==='0') return 0; - // 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/album.js b/src/scripts/album.js index e84aac9..c12110f 100644 --- a/src/scripts/album.js +++ b/src/scripts/album.js @@ -625,17 +625,14 @@ album.share = function(service) { } -album.getArchive = function(albumID) { +album.getArchive = function(albumIDs) { - let link = '' - let url = `${ api.path }?function=Album::getArchive&albumID=${ albumID }` + let path = `${ api.path }?function=Album::getArchive&albumIDs=${ albumIDs.join(',') }` + let url = lychee.getURL(path) - if (location.href.indexOf('index.html')>0) link = location.href.replace(location.hash, '').replace('index.html', url) - else link = location.href.replace(location.hash, '') + url + if (lychee.publicMode===true) url += `&password=${ encodeURIComponent(password.value) }` - if (lychee.publicMode===true) link += `&password=${ encodeURIComponent(password.value) }` - - location.href = link + location.href = url } diff --git a/src/scripts/contextMenu.js b/src/scripts/contextMenu.js index 7aa67e6..bea0005 100644 --- a/src/scripts/contextMenu.js +++ b/src/scripts/contextMenu.js @@ -115,10 +115,11 @@ contextMenu.album = function(albumID, e) { if (album.isSmartID(albumID)) return false let items = [ - { 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('cloud-download') + 'Download', fn: () => album.getArchive([ 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 + '"]') @@ -136,11 +137,12 @@ contextMenu.albumMulti = function(albumIDs, e) { let autoMerge = (albumIDs.length>1 ? true : false) let items = [ - { 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('cloud-download') + 'Download All', fn: () => album.getArchive(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() @@ -242,15 +244,21 @@ contextMenu.photo = function(photoID, e) { // in order to keep the selection let items = [ - { 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) @@ -266,15 +274,21 @@ contextMenu.photoMulti = function(photoIDs, e) { // in order to keep the selection and multiselect let items = [ - { 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) } @@ -308,7 +322,7 @@ contextMenu.photoMore = function(photoID, e) { let items = [ { title: build.iconic('fullscreen-enter') + 'Full Photo', fn: () => window.open(photo.getDirectLink()) }, - { title: build.iconic('cloud-download') + 'Download', visible: showDownload, fn: () => photo.getArchive(photoID) } + { title: build.iconic('cloud-download') + 'Download', visible: showDownload, fn: () => photo.getPhoto(photoID) } ] basicContext.show(items, e.originalEvent) diff --git a/src/scripts/header.js b/src/scripts/header.js index 891813a..153080d 100644 --- a/src/scripts/header.js +++ b/src/scripts/header.js @@ -49,7 +49,7 @@ header.bind = function() { header.dom('.header__hostedwith') .on(eventName, function() { window.open(lychee.website) }) header.dom('#button_trash_album') .on(eventName, function() { album.delete([ album.getID() ]) }) header.dom('#button_trash') .on(eventName, function() { photo.delete([ photo.getID() ]) }) - header.dom('#button_archive') .on(eventName, function() { album.getArchive(album.getID()) }) + header.dom('#button_archive') .on(eventName, function() { album.getArchive([ album.getID() ]) }) header.dom('#button_star') .on(eventName, function() { photo.setStar([ photo.getID() ]) }) header.dom('#button_back_home') .on(eventName, function() { lychee.goto(album.getParent()) }) header.dom('#button_back') .on(eventName, function() { lychee.goto(album.getID()) }) diff --git a/src/scripts/lychee.js b/src/scripts/lychee.js index 5c5de87..1a47c85 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 @@ -419,6 +417,18 @@ lychee.html = function(literalSections, ...substs) { } +lychee.getURL = function(path) { + + let pos = location.href.indexOf('#') + let url = pos!=-1 ? location.href.substring(0, pos) : location.href + + if (location.href.indexOf('index.html')>0) url = url.replace('index.html', path) + else url += path + + return url + +} + lychee.error = function(errorThrown, params, data) { console.error({ 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 diff --git a/src/scripts/photo.js b/src/scripts/photo.js index e0b2586..75d9cad 100644 --- a/src/scripts/photo.js +++ b/src/scripts/photo.js @@ -633,17 +633,25 @@ photo.share = function(photoID, service) { } -photo.getArchive = function(photoID) { +photo.getPhoto = function(photoID) { - let link - let url = `${ api.path }?function=Photo::getArchive&photoID=${ photoID }` + let path = `${ api.path }?function=Photo::getPhoto&photoID=${ photoID }` + let url = lychee.getURL(path) - if (location.href.indexOf('index.html')>0) link = location.href.replace(location.hash, '').replace('index.html', url) - else link = location.href.replace(location.hash, '') + url + if (lychee.publicMode===true) url += `&password=${ encodeURIComponent(password.value) }` - if (lychee.publicMode===true) link += `&password=${ encodeURIComponent(password.value) }` + location.href = url - location.href = link +} + +photo.getArchive = function(photoIDs) { + + let path = `${ api.path }?function=Photo::getArchive&photoIDs=${ photoIDs.join(',') }` + let url = lychee.getURL(path) + + if (lychee.publicMode===true) url += `&password=${ encodeURIComponent(password.value) }` + + location.href = url } @@ -659,9 +667,8 @@ photo.getDirectLink = function() { photo.getViewLink = function(photoID) { - let url = 'view.php?p=' + photoID + let path = 'view.php?p=' + photoID - if (location.href.indexOf('index.html')>0) return location.href.replace('index.html' + location.hash, url) - else return location.href.replace(location.hash, url) + return lychee.getURL(path) } \ No newline at end of file