- Share > Direct Link
- Download individual images (Issue #43)
- ContextMenu stays within the window (Issue #41)
- Prevent default ContextMenu (Issue #45)
- Small ContextMenu improvements
- Small security improvements
This commit is contained in:
Tobias Reich 2014-01-24 13:49:01 +01:00
parent f9f4afe7db
commit 79607485fb
20 changed files with 139 additions and 63 deletions

File diff suppressed because one or more lines are too long

View File

@ -12,8 +12,8 @@
} }
.contextmenu { .contextmenu {
position: fixed; position: fixed;
top: 110%; top: 0px;
left: 110%; left: 0px;
padding: 5px 0px 6px 0px; padding: 5px 0px 6px 0px;
background-color: #393939; background-color: #393939;
background-image: -webkit-linear-gradient(top, #444, #2d2d2d); background-image: -webkit-linear-gradient(top, #444, #2d2d2d);
@ -24,8 +24,12 @@
border-bottom: 1px solid rgba(0,0,0,.9); border-bottom: 1px solid rgba(0,0,0,.9);
border-radius: 5px; border-radius: 5px;
box-shadow: 0px 4px 5px rgba(0,0,0,0.3), inset 0px 1px 0px rgba(255,255,255,0.15), inset 1px 0px 0px rgba(255,255,255,0.05), inset -1px 0px 0px rgba(255,255,255,0.05); box-shadow: 0px 4px 5px rgba(0,0,0,0.3), inset 0px 1px 0px rgba(255,255,255,0.15), inset 1px 0px 0px rgba(255,255,255,0.05), inset -1px 0px 0px rgba(255,255,255,0.05);
opacity: .98; opacity: 0;
z-index: 1001; z-index: 1001;
-webkit-transition: none;
-moz-transition: none;
transition: none;
} }
/* Items ------------------------------------------------*/ /* Items ------------------------------------------------*/

File diff suppressed because one or more lines are too long

View File

@ -128,7 +128,7 @@ album = {
buttons = [ buttons = [
["Delete Album and Photos", function() { ["Delete Album and Photos", function() {
params = "deleteAlbum&albumID=" + albumID + "&delAll=true"; params = "deleteAlbum&albumID=" + albumID;
lychee.api(params, function(data) { lychee.api(params, function(data) {
if (visible.albums()) { if (visible.albums()) {

View File

@ -197,12 +197,12 @@ build = {
}, },
contextMenu: function(items, orientation) { contextMenu: function(items) {
var menu = ""; var menu = "";
menu += "<div class='contextmenu_bg'></div>"; menu += "<div class='contextmenu_bg'></div>";
menu += "<div class='contextmenu " + orientation + "'>"; menu += "<div class='contextmenu'>";
menu += "<table>"; menu += "<table>";
menu += "<tbody>"; menu += "<tbody>";

View File

@ -11,11 +11,14 @@ contextMenu = {
show: function(items, mouse_x, mouse_y, orientation) { show: function(items, mouse_x, mouse_y, orientation) {
contextMenu.close(); if (visible.contextMenu()) contextMenu.close();
$("body") $("body")
.css("overflow", "hidden") .css("overflow", "hidden")
.append(build.contextMenu(items, orientation)); .append(build.contextMenu(items));
if ((mouse_x+$(".contextmenu").outerWidth(true))>$("html").width()) orientation = "left";
if ((mouse_y+$(".contextmenu").outerHeight(true))>$("html").height()) mouse_y -= (mouse_y+$(".contextmenu").outerHeight(true)-$("html").height())
if (orientation==="left") mouse_x -= $(".contextmenu").outerWidth(true); if (orientation==="left") mouse_x -= $(".contextmenu").outerWidth(true);
@ -26,7 +29,8 @@ contextMenu = {
$(".contextmenu").css({ $(".contextmenu").css({
"top": mouse_y, "top": mouse_y,
"left": mouse_x "left": mouse_x,
"opacity": .98
}); });
}, },
@ -90,7 +94,6 @@ contextMenu = {
album: function(albumID, e) { album: function(albumID, e) {
e.preventDefault();
var mouse_x = e.pageX, var mouse_x = e.pageX,
mouse_y = e.pageY, mouse_y = e.pageY,
items; items;
@ -117,7 +120,6 @@ contextMenu = {
photo: function(photoID, e) { photo: function(photoID, e) {
e.preventDefault();
var mouse_x = e.pageX, var mouse_x = e.pageX,
mouse_y = e.pageY, mouse_y = e.pageY,
items; items;
@ -152,14 +154,6 @@ contextMenu = {
items = []; items = [];
contextMenu.fns = []; contextMenu.fns = [];
mouse_y -= $(document).scrollTop();
if (orientation===undefined) orientation = "left";
if (!mouse_x||!mouse_y) {
mouse_x = "10px";
mouse_y = "10px";
}
if (album.getID()!=="0") { if (album.getID()!=="0") {
items = [ items = [
@ -179,15 +173,11 @@ contextMenu = {
} }
contextMenu.close(); contextMenu.close();
$(".photo[data-id='" + photoID + "']").addClass("active"); $(".photo[data-id='" + photoID + "']").addClass("active");
$("body")
.css("overflow", "hidden") if (!visible.photo()) contextMenu.show(items, mouse_x, mouse_y, "right");
.append(build.contextMenu(items, orientation)); else contextMenu.show(items, mouse_x, mouse_y, "left");
if (!visible.photo()) mouse_x += $(".contextmenu").width();
$(".contextmenu").css({
"top": mouse_y,
"left": mouse_x-$(".contextmenu").width()
});
}); });
@ -206,18 +196,23 @@ contextMenu = {
function() { photo.share(photoID, 0) }, function() { photo.share(photoID, 0) },
function() { photo.share(photoID, 1) }, function() { photo.share(photoID, 1) },
function() { photo.share(photoID, 2) }, function() { photo.share(photoID, 2) },
function() { photo.share(photoID, 3) } function() { photo.share(photoID, 3) },
function() { window.open(photo.getDirectLink(),"_newtab") }
]; ];
link = photo.getViewLink(photoID);
if (photo.json.public==="2") link = location.href;
items = [ items = [
["<input readonly id='link' value='" + photo.getViewLink(photoID) + "'>", -1], ["<input readonly id='link' value='" + link + "'>", -1],
["separator", -1], ["separator", -1],
["<a class='icon-eye-close'></a> Make Private", 0], ["<a class='icon-eye-close'></a> Make Private", 0],
["separator", -1], ["separator", -1],
["<a class='icon-twitter'></a> Twitter", 1], ["<a class='icon-twitter'></a> Twitter", 1],
["<a class='icon-facebook'></a> Facebook", 2], ["<a class='icon-facebook'></a> Facebook", 2],
["<a class='icon-envelope'></a> Mail", 3], ["<a class='icon-envelope'></a> Mail", 3],
["<a class='icon-hdd'></a> Dropbox", 4] ["<a class='icon-hdd'></a> Dropbox", 4],
["<a class='icon-link'></a> Direct Link", 5]
]; ];
contextMenu.show(items, mouse_x, mouse_y, "left"); contextMenu.show(items, mouse_x, mouse_y, "left");

View File

@ -11,6 +11,9 @@ $(document).ready(function(){
/* Notifications */ /* Notifications */
if (window.webkitNotifications) window.webkitNotifications.requestPermission(); if (window.webkitNotifications) window.webkitNotifications.requestPermission();
/* Disable ContextMenu */
$(document).bind("contextmenu", function(e) { e.preventDefault() });
/* Tooltips */ /* Tooltips */
if (!mobileBrowser()) $(".tools").tipsy({gravity: 'n', fade: false, delayIn: 0, opacity: 1}); if (!mobileBrowser()) $(".tools").tipsy({gravity: 'n', fade: false, delayIn: 0, opacity: 1});
@ -27,7 +30,7 @@ $(document).ready(function(){
if (album.json.public==1) contextMenu.shareAlbum(album.getID(), e); if (album.json.public==1) contextMenu.shareAlbum(album.getID(), e);
else modal.show("Share Album", "All photos inside this album will be public and visible for everyone. Existing public photos will have the same sharing permission as this album. Are your sure you want to share this album? <input class='text' type='password' placeholder='password (optional)' value=''>", [["Share Album", function() { album.setPublic(album.getID(), e) }], ["Cancel", function() {}]]); else modal.show("Share Album", "All photos inside this album will be public and visible for everyone. Existing public photos will have the same sharing permission as this album. Are your sure you want to share this album? <input class='text' type='password' placeholder='password (optional)' value=''>", [["Share Album", function() { album.setPublic(album.getID(), e) }], ["Cancel", function() {}]]);
}); });
$("#button_download").on(event_name, function() { window.open(photo.getDirectLink(),"_newtab") }); $("#button_download").on(event_name, function() { photo.getArchive(photo.getID()) });
$("#button_trash_album").on(event_name, function() { album.delete(album.getID()) }); $("#button_trash_album").on(event_name, function() { album.delete(album.getID()) });
$("#button_move").on(event_name, function(e) { contextMenu.move(photo.getID(), e) }); $("#button_move").on(event_name, function(e) { contextMenu.move(photo.getID(), e) });
$("#button_trash").on(event_name, function() { photo.delete(photo.getID()) }); $("#button_trash").on(event_name, function() { photo.delete(photo.getID()) });
@ -64,7 +67,6 @@ $(document).ready(function(){
Mousetrap Mousetrap
.bind('u', function() { $("#upload_files").click() }) .bind('u', function() { $("#upload_files").click() })
.bind('s', function() { if (visible.photo()) $("#button_star").click() }) .bind('s', function() { if (visible.photo()) $("#button_star").click() })
.bind('f', function() { if (visible.photo()) $("#button_download").click() })
.bind('command+backspace', function() { if (visible.photo()&&!visible.message()) photo.delete(photo.getID()) }) .bind('command+backspace', function() { if (visible.photo()&&!visible.message()) photo.delete(photo.getID()) })
.bind('left', function() { if (visible.photo()) $("#imageview a#previous").click() }) .bind('left', function() { if (visible.photo()) $("#imageview a#previous").click() })
.bind('right', function() { if (visible.photo()) $("#imageview a#next").click() }) .bind('right', function() { if (visible.photo()) $("#imageview a#next").click() })
@ -118,6 +120,7 @@ $(document).ready(function(){
.on("contextmenu", ".photo", function(e) { contextMenu.photo(photo.getID(), e) }) .on("contextmenu", ".photo", function(e) { contextMenu.photo(photo.getID(), e) })
.on("contextmenu", ".album", function(e) { contextMenu.album(album.getID(), e) }) .on("contextmenu", ".album", function(e) { contextMenu.album(album.getID(), e) })
.on(event_name, ".contextmenu_bg", contextMenu.close) .on(event_name, ".contextmenu_bg", contextMenu.close)
.on("contextmenu", ".contextmenu_bg", contextMenu.close)
/* Infobox */ /* Infobox */
.on(event_name, "#infobox_overlay", view.infobox.hide) .on(event_name, "#infobox_overlay", view.infobox.hide)

View File

@ -7,7 +7,7 @@
var lychee = { var lychee = {
version: "2.0", version: "2.0.1",
api_path: "php/api.php", api_path: "php/api.php",
update_path: "http://lychee.electerious.com/version/index.php", update_path: "http://lychee.electerious.com/version/index.php",

View File

@ -310,6 +310,19 @@ photo = {
}, },
getArchive: function(photoID) {
var link;
if (location.href.indexOf("index.html")>0) link = location.href.replace(location.hash, "").replace("index.html", "php/api.php?function=getPhotoArchive&photoID=" + photoID);
else link = location.href.replace(location.hash, "") + "php/api.php?function=getPhotoArchive&photoID=" + photoID;
if (lychee.publicMode) link += "&password=" + password.value;
location.href = link;
},
getDirectLink: function() { getDirectLink: function() {
return $("#imageview #image").css("background-image").replace(/"/g,"").replace(/url\(|\)$/ig, ""); return $("#imageview #image").css("background-image").replace(/"/g,"").replace(/url\(|\)$/ig, "");

View File

@ -35,7 +35,7 @@ view = {
hide: function() { hide: function() {
if (visible.photo()&&!visible.infobox()) { if (visible.photo()&&!visible.infobox()&&!visible.contextMenu()&&!visible.message()) {
clearTimeout($(window).data("timeout")); clearTimeout($(window).data("timeout"));
$(window).data("timeout", setTimeout(function() { $(window).data("timeout", setTimeout(function() {
lychee.imageview.addClass("full"); lychee.imageview.addClass("full");

View File

@ -25,10 +25,12 @@ $(document).ready(function(){
$(document).on(event_name, "#infobox_overlay", function() { hideInfobox() }); $(document).on(event_name, "#infobox_overlay", function() { hideInfobox() });
$("#button_info").on(event_name, function() { showInfobox() }); $("#button_info").on(event_name, function() { showInfobox() });
/* Download */ /* Direct Link */
$("#button_download").on(event_name, function() { $("#button_direct").on(event_name, function() {
link = $("#imageview #image").css("background-image").replace(/"/g,"").replace(/url\(|\)$/ig, ""); link = $("#imageview #image").css("background-image").replace(/"/g,"").replace(/url\(|\)$/ig, "");
window.open(link,"_newtab"); window.open(link,"_newtab");
}); });
loadPhotoInfo(gup("p")); loadPhotoInfo(gup("p"));

View File

@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
VERSION='1.3.2' VERSION='2.0'
echo 'Press ENTER to continue or any other key to abort' echo 'Press ENTER to continue or any other key to abort'
read -s -n 1 key read -s -n 1 key

View File

@ -1,11 +1,25 @@
### v2.0 ## v2.0.1
Released January 24, 2014
- Share > Direct Link
- Download individual images (Issue #43)
- ContextMenu stays within the window (Issue #41)
- Prevent default ContextMenu (Issue #45)
- Small ContextMenu improvements
- Small security improvements
## v2.0
Released January 22, 2014
- All new redefined interface - All new redefined interface
- Faster animations and transitions - Faster animations and transitions
- Import from Dropbox - Import from Dropbox
- Import from Server - Import from Server
- Download public albums - Download public albums
- Several sorting options - Several sorting options
- Installation assistent - Installation assistant
- Infobox and description for albums - Infobox and description for albums
- Faster loading and improved performance - Faster loading and improved performance
- Better file handling and upload - Better file handling and upload

View File

@ -18,7 +18,7 @@ If possible, change these settings directly in your `php.ini`. We recommend to i
Lychee supports the latest versions of Google Chrome, Apple Safari, Mozilla Firefox and Opera. Photos you share with others can be viewed from every browser. Lychee supports the latest versions of Google Chrome, Apple Safari, Mozilla Firefox and Opera. Photos you share with others can be viewed from every browser.
#### How can I set thumbnails for my albums? #### How can I set thumbnails for my albums?
Thumbnails are choosen automatically by the photos you have starred and in the order you uploaded them. Star a photo inside a album to set it as an thumbnail. Thumbnails are chosen automatically by the photos you have starred and in the order you uploaded them. Star a photo inside a album to set it as an thumbnail.
#### What is new? #### What is new?
Take a look at the [Changelog](Changelog.md) to see whats new. Take a look at the [Changelog](Changelog.md) to see whats new.

View File

@ -11,7 +11,6 @@
|:-----------|:------------| |:-----------|:------------|
| `s` | Star photo | | `s` | Star photo |
| `i` | Show information | | `i` | Show information |
| `f` | Show photo in new tab
| `cmd`+`backspace` | Delete photo | `cmd`+`backspace` | Delete photo
| `left` | Previous photo | `left` | Previous photo
| `right` | Next photo | `right` | Next photo

View File

@ -70,7 +70,7 @@
<div class="tools" id="button_trash" title="Delete"><a class="icon-trash"></a></div> <div class="tools" id="button_trash" title="Delete"><a class="icon-trash"></a></div>
<div class="tools" id="button_move" title="Move"><a class="icon-folder-open"></a></div> <div class="tools" id="button_move" title="Move"><a class="icon-folder-open"></a></div>
<a class="button_divider"></a> <a class="button_divider"></a>
<div class="tools" id="button_download" title="Full Photo"><a class="icon-resize-full"></a></div> <div class="tools" id="button_download" title="Download"><a class="icon-circle-arrow-down"></a></div>
<div class="tools" id="button_info" title="Show Info"><a class="icon-info-sign"></a></div> <div class="tools" id="button_info" title="Show Info"><a class="icon-info-sign"></a></div>
<a class="button_divider"></a> <a class="button_divider"></a>
<div class="tools" id="button_share" title="Share Photo"><a class="icon-share"></a></div> <div class="tools" id="button_share" title="Share Photo"><a class="icon-share"></a></div>
@ -92,7 +92,7 @@
<!-- Upload --> <!-- Upload -->
<div id="upload"> <div id="upload">
<input id="upload_files" type="file" name="fileElem[]" multiple="true" accept="image/*"> <input id="upload_files" type="file" name="fileElem[]" multiple accept="image/*">
</div> </div>
<!-- JS --> <!-- JS -->

View File

@ -56,9 +56,10 @@ if (!empty($_POST['function'])||!empty($_GET['function'])) {
$settings = getSettings(); $settings = getSettings();
// Security // Security
if (isset($_POST['albumID'])&&($_POST['albumID']==''||$_POST['albumID']<0)) exit('Error: Wrong parameter type for albumID!'); if (isset($_POST['albumID'])&&($_POST['albumID']==''||$_POST['albumID']<0||$_POST['albumID']>10000)) exit('Error: Wrong parameter type for albumID!');
if (isset($_POST['photoID'])&&$_POST['photoID']=='') exit('Error: Wrong parameter type for photoID!'); if (isset($_POST['photoID'])&&$_POST['photoID']=='') exit('Error: Wrong parameter type for photoID!');
foreach(array_keys($_POST) as $key) $_POST[$key] = mysqli_real_escape_string($database, urldecode($_POST[$key])); foreach(array_keys($_POST) as $key) $_POST[$key] = mysqli_real_escape_string($database, urldecode($_POST[$key]));
foreach(array_keys($_GET) as $key) $_GET[$key] = mysqli_real_escape_string($database, urldecode($_GET[$key]));
if (isset($_SESSION['login'])&&$_SESSION['login']==true) { if (isset($_SESSION['login'])&&$_SESSION['login']==true) {
@ -98,8 +99,8 @@ if (!empty($_POST['function'])||!empty($_GET['function'])) {
echo setAlbumPassword($_POST['albumID'], $_POST['password']); echo setAlbumPassword($_POST['albumID'], $_POST['password']);
break; break;
case 'deleteAlbum': if (isset($_POST['albumID'])&&isset($_POST['delAll'])) case 'deleteAlbum': if (isset($_POST['albumID']))
echo deleteAlbum($_POST['albumID'], $_POST['delAll']); echo deleteAlbum($_POST['albumID']);
break; break;
// Photo Functions // Photo Functions
@ -179,13 +180,25 @@ if (!empty($_POST['function'])||!empty($_GET['function'])) {
case 'update': echo update(); case 'update': echo update();
default: if (isset($_GET['function'])&&$_GET['function']=='getAlbumArchive'&&isset($_GET['albumID'])) default: if (isset($_GET['function'])&&$_GET['function']=='getAlbumArchive'&&isset($_GET['albumID']))
// Album Archive
// Album Download
getAlbumArchive($_GET['albumID']); getAlbumArchive($_GET['albumID']);
else if (isset($_GET['function'])&&$_GET['function']=='getPhotoArchive'&&isset($_GET['photoID']))
// Photo Download
getPhotoArchive($_GET['photoID']);
else if (isset($_GET['function'])&&$_GET['function']=='update') else if (isset($_GET['function'])&&$_GET['function']=='update')
// Update Lychee // Update Lychee
echo update(); echo update();
else else
// Function unknown
exit('Error: Function not found! Please check the spelling of the called function.'); exit('Error: Function not found! Please check the spelling of the called function.');
break; break;
} }
@ -254,18 +267,34 @@ if (!empty($_POST['function'])||!empty($_GET['function'])) {
// Miscellaneous // Miscellaneous
default: if (isset($_GET['function'])&&$_GET['function']=='getAlbumArchive'&&isset($_GET['albumID'])&&isset($_GET['password'])) { default: if (isset($_GET['function'])&&$_GET['function']=='getAlbumArchive'&&isset($_GET['albumID'])&&isset($_GET['password'])) {
// Album Download
if (isAlbumPublic($_GET['albumID'])) { if (isAlbumPublic($_GET['albumID'])) {
// Album Public // Album Public
if (checkAlbumPassword($_GET['albumID'], $_GET['password'])) if (checkAlbumPassword($_GET['albumID'], $_GET['password']))
getAlbumArchive($_GET['albumID']); getAlbumArchive($_GET['albumID']);
else else
echo 'Warning: Wrong password!'; exit('Warning: Wrong password!');
} else { } else {
// Album Private // Album Private
echo 'Warning: Album private or not downloadable!'; exit('Warning: Album private or not downloadable!');
} }
} else if (isset($_GET['function'])&&$_GET['function']=='getPhotoArchive'&&isset($_GET['photoID'])&&isset($_GET['password'])) {
// Photo Download
if (isPhotoPublic($_GET['photoID'], $_GET['password']))
// Photo Public
getPhotoArchive($_GET['photoID']);
else
// Photo Private
exit('Warning: Photo private or not downloadable!');
} else { } else {
// Function unknown
exit('Error: Function not found! Please check the spelling of the called function.'); exit('Error: Function not found! Please check the spelling of the called function.');
} }
break; break;

16
php/modules/album.php Executable file → Normal file
View File

@ -213,19 +213,15 @@ function setAlbumDescription($albumID, $description) {
} }
function deleteAlbum($albumID, $delAll) { function deleteAlbum($albumID) {
global $database; global $database;
if ($delAll=="true") { $error = false;
$result = $database->query("SELECT id FROM lychee_photos WHERE album = '$albumID';");
$error = false; $result = $database->query("SELECT id FROM lychee_photos WHERE album = '$albumID';");
while($row = $result->fetch_object()) { while($row = $result->fetch_object()) {
if (!deletePhoto($row->id)) $error = true; if (!deletePhoto($row->id)) $error = true;
}
} else {
$result = $database->query("UPDATE lychee_photos SET album = '0' WHERE album = '$albumID';");
if (!$result) return false;
} }
if ($albumID!=0) { if ($albumID!=0) {

21
php/modules/photo.php Executable file → Normal file
View File

@ -164,4 +164,25 @@ function isPhotoPublic($photoID, $password) {
} }
function getPhotoArchive($photoID) {
global $database;
$result = $database->query("SELECT * FROM lychee_photos WHERE id = '$photoID';");
$row = $result->fetch_object();
$extension = array_reverse(explode('.', $row->url));
if ($row->title=='') $row->title = 'Untitled';
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"$row->title.$extension[0]\"");
header("Content-Length: " . filesize("../uploads/big/$row->url"));
readfile("../uploads/big/$row->url");
return true;
}
?> ?>

View File

@ -43,7 +43,7 @@
<header class="view"> <header class="view">
<!-- Buttons --> <!-- Buttons -->
<div class="tools" id="button_download" title="Full Photo"><a class="icon-resize-full"></a></div> <div class="tools" id="button_direct" title="Direct Link"><a class="icon-link"></a></div>
<div class="tools" id="button_info" title="Show Info"><a class="icon-info-sign"></a></div> <div class="tools" id="button_info" title="Show Info"><a class="icon-info-sign"></a></div>
<a id="title" class="view"></a> <a id="title" class="view"></a>