- FTP Sharing
- New Upload & New Search
- Performance and stuff under the hood
- Desktop Notifications
- Right-Click on photos and albums
- Retina Thumbs
- Improved Interface
pull/4/head 1.1
Tobias Reich 11 years ago
parent b565390419
commit dcc51497c3

@ -1,3 +1,10 @@
/**
* @name animations.css
* @author Philipp Maurer
* @author Tobias Reich
* @copyright 2013 by Philipp Maurer, Tobias Reich
*/
/* bounceInDown ------------------------------------------------*/
@-webkit-keyframes bounceInDown {
0% {
@ -350,21 +357,17 @@
@-ms-keyframes zoomOut {
0% {
opacity: 1;
-ms-transform: scale(1);
}
100% {
opacity: 0;
-ms-transform: scale(.5);
}
}
@-o-keyframes zoomOut {
0% {
opacity: 1;
-o-transform: scale(1);
}
100% {
opacity: 0;
-o-transform: scale(.5);
}
}
@keyframes zoomOut {
@ -400,21 +403,17 @@
@-ms-keyframes zoomIn {
0% {
opacity: 0;
-ms-transform: scale(.5);
}
100% {
opacity: 1;
-ms-transform: scale(1);
}
}
@-o-keyframes zoomIn {
0% {
opacity: 0;
-o-transform: scale(.5);
}
100% {
opacity: 1;
-o-transform: scale(1);
}
}
@keyframes zoomIn {

Before

Width:  |  Height:  |  Size: 127 KiB

After

Width:  |  Height:  |  Size: 127 KiB

@ -1,3 +1,10 @@
/**
* @name style.css
* @author Philipp Maurer
* @author Tobias Reich
* @copyright 2013 by Philipp Maurer, Tobias Reich
*/
/* Reset -------------------------------------------------*/
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video { margin:0; padding:0; border:0; font-size:100%; font:inherit; vertical-align:baseline; }
article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section { display:block; }
@ -7,43 +14,6 @@ blockquote,q { quotes:none; }
blockquote:before,blockquote:after,q:before,q:after { content:''; content:none; }
table { border-collapse:collapse; border-spacing:0; }
/* Screen behavior -------------------------------------------------*/
@media only screen and (max-width: 900px) {
#title span { display: none; }
}
@media only screen and (max-width: 640px) {
#title { display: none; }
#button_move { display: none; }
.center {
top: 0px !important;
left: 0px !important;
}
.message {
position: fixed !important;
width: 100% !important;
height: 100% !important;
margin: 1px 0px 0px 0px !important;
border-radius: 0px !important;
/* Animation */
-webkit-animation-name: moveUp !important;
-webkit-animation-duration: .3s !important;
-moz-animation-name: moveUp !important;
-moz-animation-duration: .3s !important;
-o-animation-name: moveUp !important;
-o-animation-duration: .3s !important;
animation-name: moveUp !important;
animation-duration: .3s !important;
}
}
/* Basics -------------------------------------------------*/
html, body {
min-height: 100%;
@ -106,7 +76,7 @@ body { background-color: #222; background-image: url(../img/background.jpg); fon
.tipsy-e .tipsy-arrow { right: 0; top: 50%; margin-top: -5px; border-left-style: solid; border-right: none; border-top-color: transparent; border-bottom-color: transparent; }
.tipsy-w .tipsy-arrow { left: 0; top: 50%; margin-top: -5px; border-right-style: solid; border-left: none; border-top-color: transparent; border-bottom-color: transparent; }
/* Overlay ------------------------------------------------*/
/* Animations ------------------------------------------------*/
.fadeIn {
-webkit-animation-name: fadeIn;
-webkit-animation-duration: .3s;
@ -344,7 +314,7 @@ header {
background-image: -o-linear-gradient(top, #555 0%, #333 100%);
background: linear-gradient(top, #555 0%, #333 100%);
border: 1px solid #252525;
border: 1px solid #222;
border-radius: 3px;
box-shadow: inset 0 1px 0 rgba(255,255,255,0.1), 0px 1px 0px #444;
cursor: pointer;
@ -462,6 +432,7 @@ header {
position: absolute;
padding: 41px 0px 33px 0px;
width: 100%;
-webkit-overflow-scrolling: touch;
}
/* Photo ------------------------------------------------*/
@ -525,7 +496,7 @@ header {
box-shadow: 0px 1px 5px #111;
border: 3px solid #ccc;
}
.album:hover img {
.album:hover img, .album.active img {
box-shadow: 0px 0px 10px #005ecc;
}
@ -909,6 +880,9 @@ header {
box-shadow: 0px 2px 4px #000;
-webkit-transition: background-color .3s;
}
#image_view.full {
background-color: #111;
}
#image_view #image {
position: absolute;
@ -960,10 +934,16 @@ header {
left: 20px;
-webkit-transition: left .3s;
}
#image_view.full a#previous {
left: -50px;
}
#image_view a#next {
right: 20px;
-webkit-transition: right .3s
}
#image_view.full a#next {
right: -50px;
}
/* InfoBox ------------------------------------------------*/
#infobox_overlay {
@ -1094,6 +1074,7 @@ header {
width: 100%;
height: 35px;
}
#infobox #edit_title,
#infobox #edit_description {
display: inline;
margin-left: 3px;
@ -1289,17 +1270,75 @@ header {
width: 0%;
height: 100%;
box-shadow: 0 1px 0 #000, 1px 0px 2px #000;
background: rgb(255,255,255); /* Old browsers */
background: -moz-linear-gradient(top, rgba(255,255,255,1) 0%, rgba(241,241,241,1) 50%, rgba(225,225,225,1) 51%, rgba(246,246,246,1) 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,1)), color-stop(50%,rgba(241,241,241,1)), color-stop(51%,rgba(225,225,225,1)), color-stop(100%,rgba(246,246,246,1))); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(241,241,241,1) 50%,rgba(225,225,225,1) 51%,rgba(246,246,246,1) 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(241,241,241,1) 50%,rgba(225,225,225,1) 51%,rgba(246,246,246,1) 100%); /* Opera11.10+ */
background: -ms-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(241,241,241,1) 50%,rgba(225,225,225,1) 51%,rgba(246,246,246,1) 100%); /* IE10+ */
background: linear-gradient(top, rgba(255,255,255,1) 0%,rgba(241,241,241,1) 50%,rgba(225,225,225,1) 51%,rgba(246,246,246,1) 100%); /* W3C */
background-color: #f5f2f7;
background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f2f7), to(#c7c6c8));
background-image: -webkit-linear-gradient(top, #f5f2f7, #c7c6c8);
background-image: -moz-linear-gradient(top, #f5f2f7, #c7c6c8);
background-image: -o-linear-gradient(top, #f5f2f7, #c7c6c8);
background-image: -ms-linear-gradient(top, #f5f2f7, #c7c6c8);
background-image: linear-gradient(top, #f5f2f7, #c7c6c8);
border-radius: 5px;
-webkit-transition: width .2s, opacity .5;
-moz-transition: width .2s, opacity .5;
-o-transition: width .2s, opacity .5;
transition: width .2s, opacity .5;
}
/* Screen behavior -------------------------------------------------*/
@media only screen and (max-width: 900px) {
#title {
margin: 11px 30% 0px 20%;
width: 50%;
}
#title.view { margin: 11px 20% 0px 20%; width: 60%; }
#title span { display: none; }
}
@media only screen and (max-width: 640px) {
#title { display: none; }
#title.view { display: block; margin: 11px 20% 0px 15%; width: 65%; }
#button_move { display: none; }
#button_archive { display: none; }
.center {
top: 0px;
left: 0px;
}
.message {
position: fixed;
width: 100%;
height: 100%;
margin: 1px 0px 0px 0px !important;
border-radius: 0px;
/* Animation */
-webkit-animation-name: moveUp;
-webkit-animation-duration: .3s;
-moz-animation-name: moveUp;
-moz-animation-duration: .3s;
-o-animation-name: moveUp;
-o-animation-duration: .3s;
animation-name: moveUp;
animation-duration: .3s;
}
.album {
margin: 40px 0px 0px 50px;
}
.photo {
margin: 40px 0px 0px 50px;
}
.message.add {
margin-top: 0px;
}
.add_album {
margin: 30px 0px -10px 55px;
}
-webkit-transition: width .2s;
-moz-transition: width .2s;
-o-transition: width .2s;
transition: width .2s;
}

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Before

Width:  |  Height:  |  Size: 184 B

After

Width:  |  Height:  |  Size: 184 B

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Before

Width:  |  Height:  |  Size: 113 B

After

Width:  |  Height:  |  Size: 113 B

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

@ -32,7 +32,6 @@
<div id="tools_albums">
<a class="button" id="button_signout">Sign Out</a>
<a class="button icon icon-plus-sign button_add"></a>
<!--<a class="button icon icon-refresh" id="button_sync"></a>-->
<a class="button_divider"></a>
<input id="search" type="text" name="search" placeholder="Search …">
</div>
@ -48,7 +47,7 @@
<a class="button" id="button_back">Back</a>
<div class="tools" id="button_trash" title="Delete"><a class="icon-trash"></a></div>
<div class="tools" id="button_move" title="Move to Album"><a class="icon-folder-open"></a></div>
<div class="tools" id="button_download" title="Download Photo"><a class="icon-download"></a></div>
<div class="tools" id="button_download" title="Full Photo"><a class="icon-resize-full"></a></div>
<a class="button_divider less"></a>
<div class="tools" id="button_info" title="Show Info"><a class="icon-info-sign"></a></div>
<div class="tools" id="button_edit" title="Edit Title"><a class="icon-edit"></a></div>
@ -79,9 +78,20 @@
<!-- JS -->
<script type="text/javascript" src="js/frameworks.js"></script>
<script type="text/javascript" src="js/upload.js"></script>
<script type="text/javascript" src="js/build.js"></script>
<script type="text/javascript" src="js/functions.js"></script>
<!-- Development
<script type="text/javascript" src="js/modules/lychee.js"></script>
<script type="text/javascript" src="js/modules/build.js"></script>
<script type="text/javascript" src="js/modules/albums.js"></script>
<script type="text/javascript" src="js/modules/photos.js"></script>
<script type="text/javascript" src="js/modules/visible.js"></script>
<script type="text/javascript" src="js/modules/loadingBar.js"></script>
<script type="text/javascript" src="js/modules/contextMenu.js"></script>
<script type="text/javascript" src="js/modules/search.js"></script> -->
<!-- Production -->
<script type="text/javascript" src="js/functions.js"></script>
<script type="text/javascript" src="js/main.js"></script>
</body>

@ -1,247 +0,0 @@
/**
* @name build.js
* @author Philipp Maurer
* @author Tobias Reich
* @copyright 2012 by Philipp Maurer, Tobias Reich
*/
/*
Build Functions
This functions are used to generate HTML-Code.
*/
function buildDivider(title) {
return "<div class='divider fadeIn'><h1>" + title + "</h1></div>";
}
function buildAlbum(albumJSON) {
if(!albumJSON) return "";
if(!albumJSON.thumb0) albumJSON.thumb0 = "img/no_images.png";
if(!albumJSON.thumb1) albumJSON.thumb1 = "img/no_images.png";
if(!albumJSON.thumb2) albumJSON.thumb2 = "img/no_images.png";
if(!albumJSON.title) albumJSON.title = "Untitled";
if(albumJSON.title.length>18) albumJSON.title = albumJSON.title.substr(0, 18) + "...";
var album = "";
album += "<div class='album' data-id='" + albumJSON.id + "'>";
album += "<img src='" + albumJSON.thumb2 + "' width='200' height='200' alt='thumb'>";
album += "<img src='" + albumJSON.thumb1 + "' width='200' height='200' alt='thumb'>";
album += "<img src='" + albumJSON.thumb0 + "' width='200' height='200' alt='thumb'>";
album += "<div class='overlay'>";
album += "<h1>" + albumJSON.title + "</h1>";
album += "<a>" + albumJSON.sysdate + "</a>";
album += "</div>";
if(albumJSON.star=="1") album += "<a class='badge red icon-star'></a>";
if(albumJSON.public=="1") album += "<a class='badge red icon-rss'></a>";
if(albumJSON.unsorted=="1") album += "<a class='badge red icon-reorder'></a>";
album += "</div>";
return album;
}
function buildPhoto(photoJSON) {
if(photoJSON=="") return "";
if(!photoJSON.title) photoJSON.title = "";
if(!photoJSON.thumbUrl) photoJSON.thumbUrl = "img/no_image.png";
if(photoJSON.title.length>18) photoJSON.title = photoJSON.title.substr(0, 18) + "...";
var photo = "";
photo += "<div class='photo' data-id='" + photoJSON.id + "'>";
photo += "<img src='" + photoJSON.thumbUrl + "' width='200' height='200' alt='thumb'>";
photo += "<div class='overlay'>";
photo += "<h1>" + photoJSON.title + "</h1>";
photo += "<a>" + photoJSON.sysdate + "</a>";
photo += "</div>";
if(photoJSON.star=="1") photo += "<a class='badge red icon-star'></a>";
if(photoJSON.public=="1") photo += "<a class='badge red icon-rss'></a>";
photo += "</div>";
return photo;
}
function buildModal(title, text, button, func) {
var modal = "";
modal += "<div class='message_overlay fadeIn'>";
modal += "<div class='message center'>";
modal += "<h1>" + title + "</h1>";
modal += "<a class='close icon-remove-sign'></a>";
modal += "<p>" + text + "</p>";
$.each(button, function(index) {
if (index==0) modal += "<a onclick='message_click(" + index + ")' class='button active'>" + this + "</a>";
else modal += "<a onclick='message_click(" + index + ")' class='button'>" + this + "</a>";
});
modal += "</div>";
modal += "<script>";
modal += "function message_click(action) {";
modal += "switch (action) {";
$.each(func, function(index) {
modal += "case " + index + ":";
modal += this.toString();
modal += "break;";
});
modal += "} closeModal(); }";
modal += "</script>";
modal += "</div>";
return modal;
}
function buildAddModal() {
var modal = "";
modal += "<div class='message_overlay fadeIn'>";
modal += "<div class='message center add'>";
modal += "<h1>Add Album or Photo</h1>";
modal += "<a class='close icon-remove-sign'></a>";
modal += "<div id='add_album' class='add_album'>";
modal += "<div class='icon icon-folder-close'></div>";
modal += "<a>Add new Album</a>";
modal += "</div>";
modal += "<div id='add_photo' class='add_album'>";
modal += "<div class='icon icon-picture'></div>";
modal += "<a>Upload new Photo</a>";
modal += "</div>";
modal += "</div>";
modal += "</div>";
return modal;
}
function buildSignInModal() {
var modal = "";
modal += "<div class='message_overlay'>";
modal += "<div class='message center'>";
modal += "<h1><a class='icon-lock'></a> Sign in</h1>";
modal += "<div class='sign_in'>";
modal += "<input id='username' type='text' name='' value='' placeholder='username'>";
modal += "<input id='password' type='password' name='' value='' placeholder='password'>";
modal += "</div>";
modal += "<div id='version'>Version " + version + "</div>";
modal += "<a onclick='login()' class='button active'>Sign in</a>";
modal += "</div>";
modal += "</div>";
return modal;
}
function buildUploadModal() {
var modal = "";
modal += "<div class='upload_overlay fadeIn'>";
modal += "<div class='upload_message center'>";
modal += "<a class='icon-upload'></a>";
modal += "<div class='progressbar'><div></div></div>";
modal += "</div>";
modal += "</div>";
return modal;
}
function buildContextMenu(items) {
var menu = "";
menu += "<div class='contextmenu_bg'></div>";
menu += "<div class='contextmenu'>";
menu += "<table>";
menu += "<tbody>";
$.each(items, function(index) {
if (items[index][1].length!=0) {
menu += "<tr><td onclick='" + items[index][1] + "; closeContextMenu();'>" + items[index][0] + "</td></tr>";
}
});
menu += "</tbody>";
menu += "</table>";
menu += "</div>";
return menu;
}
function buildInfobox(photo) {
var infobox = "";
infobox += "<div class='header'><h1>About</h1><a class='icon-remove-sign'></a></div>";
infobox += "<div class='wrapper'>";
if (photo.public==1) photo.public = "Public"; else photo.public = "Private";
infos = [
["", "Basics"],
["Name", photo.title],
["Uploaded", photo.sysdate],
["Description", photo.description + " <div id='edit_description'><a class='icon-pencil'></a></div>"],
["", "Image"],
["Size", photo.size],
["Format", photo.type],
["Resolution", photo.width + " x " + photo.height],
["", "Camera"],
["Captured", photo.takedate],
["Make", photo.make],
["Type/Model", photo.model],
["Shutter Speed", photo.shutter],
["Aperture", photo.aperture],
["Focal Length", photo.focal],
["ISO", photo.iso],
["", "Share"],
["Privacy", photo.public],
["Short Link", photo.shortlink]
];
$.each(infos, function(index) {
if (infos[index][1]==""||infos[index][1]==undefined||infos[index][1]==null) infos[index][1] = "-";
if (infos[index][0]=="") {
infobox += "</table>";
infobox += "<div class='separater'><h1>" + infos[index][1] + "</h1></div>";
infobox += "<table id='infos'>";
} else {
infobox += "<tr>";
infobox += "<td>" + infos[index][0] + "</td>";
infobox += "<td>" + infos[index][1] + "</td>";
infobox += "</tr>";
}
});
infobox += "</table>";
infobox += "<div class='bumper'></div>";
infobox += "</div>";
return infobox;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -2,17 +2,11 @@
* @name main.js
* @author Philipp Maurer
* @author Tobias Reich
* @copyright 2012 by Philipp Maurer, Tobias Reich
* @copyright 2013 by Philipp Maurer, Tobias Reich
*/
var header = $("header"),
headerTitle = $("#title"),
content = $("#content"),
image_view = $("#image_view"),
loading = $("#loading"),
infobox = $("#infobox"),
api_path = "php/api.php",
version = "1.0.2";
/* Modules */
lychee.init("php/api.php", "");
$(document).ready(function(){
@ -20,100 +14,120 @@ $(document).ready(function(){
if (mobileBrowser()) event_name = "touchend";
else event_name = "click";
/* Login */
$("#password").live("keyup", function() {
if ($(this).val().length>0) $(this).removeClass("error");
});
/* Add Dialog */
$(".button_add").live(event_name, function() { $("body").append(buildAddModal) });
$("#add_album").live(event_name, addAlbum);
$("#add_photo").live(event_name, function() { $("#auswahl").html(""); $("#upload_files").click() });
/* Toolbar Buttons */
$("#button_signout").live(event_name, function() {
modal = buildModal("Sign Out", "Are you sure you want to leave and log out?", ["Sign out", "Stay here"], ["logout();", ""]);
/* Toolbar */
$("#button_signout").on(event_name, function() {
modal = build.modal("Sign Out", "Are you sure you want to leave and log out?", ["Sign out", "Stay here"], ["lychee.logout();", ""]);
$("body").append(modal);
});
$("#button_download").live(event_name, function() {
$("#button_download").on(event_name, function() {
link = $("#image_view #image").css("background-image").replace(/"/g,"").replace(/url\(|\)$/ig, "");
window.open(link,"_newtab");
});
$("#button_move").live(event_name, function(e) {
showContextMenuMove(image_view.attr("data-id"), e.pageX, e.pageY);
$("#button_share").on(event_name, function(e) {
if ($("#button_share a.active").length) contextMenu.share(lychee.image_view.attr("data-id"), e.pageX, e.pageY);
else photos.setPublic(e);
});
$("#button_trash_album").live(event_name, function() {
if (content.attr("data-id")=="0") deleteUnsorted();
else deleteAlbum();
});
$("#button_trash").live(event_name, function() { deletePhoto() });
$("#button_edit_album").live(event_name, function() { renameAlbum() });
$("#button_edit").live(event_name, function() { renamePhoto() });
$("#button_info").live(event_name, function() { showInfobox() });
$("#button_archive").live(event_name, function() { getAlbumArchive() });
$("#button_sync").live(event_name, function() { syncFolder() });
/* Rename Album/Photo via Titlebar */
$("#title.editable").live(event_name, function() {
if (visibleImageview()) renamePhoto(); else renameAlbum();
$("#button_trash_album").on(event_name, function() { albums.deleteDialog(lychee.content.attr("data-id")) });
$("#button_move").on(event_name, function(e) { contextMenu.move(lychee.image_view.attr("data-id"), e.pageX, e.pageY) });
$("#button_trash").on(event_name, function() { photos.deleteDialog() });
$("#button_edit_album").on(event_name, function() { albums.rename() });
$("#button_edit").on(event_name, function() { photos.rename() });
$("#button_info").on(event_name, function() { photos.showInfobox() });
$("#button_archive").on(event_name, function() { albums.getArchive() });
$("#button_star").on(event_name, function() { photos.setStar() });
$(".copylink").on(event_name, function() { $(this).select() });
/* Search */
$("#search").on("keyup click", function() { search.find($(this).val()) });
/* Back Buttons */
$("#button_back_home").on(event_name, function() { lychee.goto("") });
$("#button_back").on(event_name, function() { lychee.goto("a" + lychee.content.attr("data-id")) });
/* Image View */
$("#image_view")
.on(event_name, "a#previous", photos.previous)
.on(event_name, "a#next", photos.next);
/* Infobox */
$("#infobox")
.on(event_name, ".header a", function() { photos.hideInfobox() })
.on(event_name, "#edit_title", function() { photos.rename() })
.on(event_name, "#edit_description", function() { photos.setDescription() });
/* Keyboard */
Mousetrap
.bind('n', function(e) { $("body").append(build.addModal) })
.bind('u', function(e) { $("#auswahl").html(""); $("#upload_files").click() })
.bind('s', function(e) { if (visible.imageview()) $("#button_star").click() })
.bind('f', function(e) { if (visible.imageview()) $("#button_download").click() })
.bind('i', function(e) { if (visible.imageview()) photos.showInfobox() })
.bind('backspace', function(e) { if (visible.imageview()) photos.deleteDialog() })
.bind('left', function(e) { if (visible.imageview()) photos.previous() })
.bind('right', function(e) { if (visible.imageview()) photos.next() });
Mousetrap.bindGlobal('enter', function(e) {
if ($(".message .button.active").length) $(".message .button.active").addClass("pressed").click()
});
/* Context Menu */
$(".photo").live("contextmenu", function(e) {
Mousetrap.bindGlobal('esc', function(e) {
e.preventDefault();
showContextMenuPhoto($(this).attr("data-id"), e.pageX, e.pageY);
if ($(".message").length&&$(".sign_in").length==0) lychee.closeModal();
else if (visible.infobox()) photos.hideInfobox();
else if (visible.imageview()) lychee.goto("a" + lychee.content.attr("data-id"));
else if (visible.albums()&&$("#search").val().length!=0) search.reset();
});
$(".contextmenu_bg").live(event_name, closeContextMenu);
/* Star/Share Photo */
$("#button_star").live(event_name, setPhotoStar);
$("#button_share").live(event_name, function(e) {
if ($("#button_share a.active").length) showContextMenuShare(image_view.attr("data-id"), e.pageX, e.pageY);
else setPhotoPublic(e);
});
$(".copylink").live(event_name, function() { $(this).select() });
/* Document */
$(document)
/* Upload */
$("#upload_files").live("change", function() {
closeModal();
handleFiles(this.files);
$("#upload_button").click();
});
/* Login */
.on("keyup", "#password", function() { if ($(this).val().length>0) $(this).removeClass("error") })
/* Search */
$("#search").live("keyup", function() { search($(this).val()) });
/* Toolbar */
.on(event_name, "#title.editable", function() { if (visible.imageview()) photos.rename(); else albums.rename(); })
/* Nav Forward */
$(".album").live("click", function() { setURL("a" + $(this).attr("data-id")) });
$(".photo").live("click", function() { setURL("a" + content.attr("data-id") + "p" + $(this).attr("data-id")) });
/* Navigation */
.on("click", ".album", function() { lychee.goto("a" + $(this).attr("data-id")) })
.on("click", ".photo", function() {
if (lychee.content.attr("data-id")!="") lychee.goto("a" + lychee.content.attr("data-id") + "p" + $(this).attr("data-id"));
else lychee.goto("a" + $(this).attr("data-album-id") + "p" + $(this).attr("data-id"));
})
/* Nav Back */
$("#button_back_home").live(event_name, function() { setURL("") });
$("#button_back").live(event_name, function() { setURL("a" + content.attr("data-id")) });
/* Modal */
.on(event_name, ".message .close", lychee.closeModal)
/* Close Modal */
$(".message a.close").live(event_name, closeModal);
/* Add Dialog */
.on(event_name, ".button_add", function() { $("body").append(build.addModal) })
.on(event_name, "#add_album", albums.add)
.on(event_name, "#add_photo", function() { $("#auswahl").html(""); $("#upload_files").click() })
/* Image View */
$("#image_view a#previous").live(event_name, loadPreviousPhoto);
$("#image_view a#next").live(event_name, loadNextPhoto);
/* Upload */
.on("change", "#upload_files", function() { lychee.closeModal(); lychee.upload(this.files); })
/* Infobox */
$("#infobox_overlay, #infobox .header a").live(event_name, function() { hideInfobox() });
$("#edit_description").live(event_name, function() { setPhotoDescription() });
/* Context Menu */
.on("contextmenu", ".photo", contextMenu.photo)
.on("contextmenu", ".album", contextMenu.album)
.on(event_name, ".contextmenu_bg", contextMenu.close)
/* Window */
$(window).keydown(key);
$(window).bind("popstate", getURL);
$(window).bind("mouseleave", hideControls);
$(window).bind("mouseenter", showControls);
/* Infobox */
.on(event_name, "#infobox_overlay", function() { photos.hideInfobox() })
/* Init */
if ((BrowserDetect.browser=="Explorer")||(BrowserDetect.browser=="Safari"&&BrowserDetect.version<5)||(BrowserDetect.browser=="Chrome"&&BrowserDetect.version<18)||(BrowserDetect.browser=="Firefox"&&BrowserDetect.version<15)) {
/* Controls */
.bind("mouseenter", lychee.showControls)
.bind("mouseleave", lychee.hideControls);
modal = buildModal("Browser not supported", "You are currently using an outdated or unsupported Browser. This site might not work properly. Please consider to update your Browser!", ["Leave"], ["location.href = 'http://browsehappy.com';"]);
$("body").append(modal);
/* Upload */
document.documentElement.ondrop = function (e) {
e.stopPropagation();
e.preventDefault();
lychee.upload(event.dataTransfer.files);
return true;
}
} else init();
/* Init */
lychee.ready();
});

@ -0,0 +1,254 @@
/**
* @name albums.js
* @author Philipp Maurer
* @author Tobias Reich
* @copyright 2013 by Philipp Maurer, Tobias Reich
*
* Albums Module
* Takes care of every action albums can handle and execute.
*/
albums = {
load: function() {
loadingBar.show();
lychee.animate(".album, .photo", "contentZoomOut");
/* Search */
lychee.content.attr("data-search", "");
lychee.animate(".divider", "fadeOut");
startTime = new Date().getTime();
lychee.api("getAlbums", "json", function(data) {
durationTime = (new Date().getTime() - startTime);
if (durationTime>300) waitTime = 0; else waitTime = 300 - durationTime;
$.timer(waitTime,function(){
$("#tools_album, #tools_photo").hide();
$("#tools_albums").show();
/* Smart Albums */
unsortedAlbum = new Object();
unsortedAlbum.id = 0;
unsortedAlbum.title = "Unsorted";
unsortedAlbum.sysdate = data.unsortNum + " photos";
unsortedAlbum.unsorted = 1;
if (data.unsortThumb0) unsortedAlbum.thumb0 = lychee.upload_path + data.unsortThumb0; else unsortedAlbum.thumb0 = "";
if (data.unsortThumb1) unsortedAlbum.thumb1 = lychee.upload_path + data.unsortThumb1; else unsortedAlbum.thumb1 = "";
if (data.unsortThumb2) unsortedAlbum.thumb2 = lychee.upload_path + data.unsortThumb2; else unsortedAlbum.thumb2 = "";
starredAlbum = new Object();
starredAlbum.id = "f";
starredAlbum.title = "Starred";
starredAlbum.sysdate = data.starredNum + " photos";
starredAlbum.star = 1;
if (data.starredThumb0) starredAlbum.thumb0 = lychee.upload_path + data.starredThumb0; else starredAlbum.thumb0 = "";
if (data.starredThumb1) starredAlbum.thumb1 = lychee.upload_path + data.starredThumb1; else starredAlbum.thumb1 = "";
if (data.starredThumb2) starredAlbum.thumb2 = lychee.upload_path + data.starredThumb2; else starredAlbum.thumb2 = "";
publicAlbum = new Object();
publicAlbum.id = "s";
publicAlbum.title = "Public";
publicAlbum.sysdate = data.publicNum + " photos";
publicAlbum.public = 1;
if (data.publicThumb0) publicAlbum.thumb0 = lychee.upload_path + data.publicThumb0; else publicAlbum.thumb0 = "";
if (data.publicThumb1) publicAlbum.thumb1 = lychee.upload_path + data.publicThumb1; else publicAlbum.thumb1 = "";
if (data.publicThumb2) publicAlbum.thumb2 = lychee.upload_path + data.publicThumb2; else publicAlbum.thumb2 = "";
smartData = build.divider("Smart Albums") + build.album(unsortedAlbum) + build.album(starredAlbum) + build.album(publicAlbum);
/* Albums */
if (data.albums) {
albumsData = build.divider("Albums");
$.each(data.album, function() { albumsData += build.album(this); });
} else albumsData = "";
lychee.content.html(smartData + albumsData);
lychee.animate(".album, .photo", "contentZoomIn");
document.title = "Lychee";
lychee.headerTitle.html("Albums").removeClass("editable");
$("img").retina();
loadingBar.hide();
});
})
},
loadInfo: function(albumID) {
if (albumID=="f"||albumID=="s"||albumID==0) {
lychee.headerTitle.removeClass("editable");
lychee.api("getSmartInfo", "json", function(data) {
switch (albumID) {
case "f":
document.title = "Lychee - Starred";
lychee.headerTitle.html("Starred<span> - " + data.starredNum + " photos</span>");
$("#button_edit_album, #button_trash_album, .button_divider").hide();
break;
case "s":
document.title = "Lychee - Public";
lychee.headerTitle.html("Public<span> - " + data.publicNum + " photos</span>");
$("#button_edit_album, #button_trash_album, .button_divider").hide();
break;
case "0":
document.title = "Lychee - Unsorted";
lychee.headerTitle.html("Unsorted<span> - " + data.unsortNum + " photos</span>");
$("#button_edit_album").hide();
$("#button_trash_album, .button_divider").show();
break;
}
loadingBar.hide();
});
} else {
params = "getAlbumInfo&albumID=" + albumID;
lychee.api(params, "json", function(data) {
$("#button_edit_album, #button_trash_album, .button_divider").show();
if (!data.title) data.title = "Untitled";
document.title = "Lychee - " + data.title;
lychee.headerTitle.html(data.title + "<span> - " + data.num + " photos</span>").addClass("editable");
loadingBar.hide();
});
}
},
add: function() {
title = prompt("Please enter a title for this album:", "Untitled");
lychee.closeModal();
if (title.length>2&&title.length<31) {
loadingBar.show();
params = "addAlbum&title=" + escape(title);
lychee.api(params, "text", function(data) {
if (data) lychee.goto("a" + data);
else loadingBar.show("error");
});
} else if (title.length>0) loadingBar.show("error", "Error", "Title to short or too long. Please try another one!");
},
hide: function(albumID) {
$(".album[data-id='" + albumID + "']").css("opacity", 0).animate({
width: 0,
marginLeft: 0
}, 300, function() {
$(this).remove();
});
},
delete: function(albumID, delAll) {
loadingBar.show();
params = "deleteAlbum&albumID=" + albumID + "&delAll=" + delAll;
lychee.api(params, "text", function(data) {
if (data) {
if (visible.albums()) {
albums.hide(albumID);
loadingBar.hide();
} else lychee.goto("");
} else loadingBar.show("error");
});
},
deleteDialog: function(albumID) {
if (albumID==0) {
f1 = "albums.delete(0, true);";
f2 = "";
modal = build.modal("Clear Unsorted", "Are you sure you want to delete all photos from 'Unsorted'?<br>This action can't be undone!", ["Clear Unsorted", "Keep Photos"], [f1, f2]);
$("body").append(modal);
} else {
if (visible.albums()) albumTitle = $(".album[data-id='" + albumID + "'] .overlay h1").html();
else albumTitle = lychee.title();
f1 = "albums.delete(" + albumID + ", true);";
f2 = "albums.delete(" + albumID + ", false);";
modal = build.modal("Delete Album", "Are you sure you want to delete the album '" + albumTitle + "' and all of the photos it contains? This action can't be undone!", ["Delete Album and Photos", "Keep Photos"], [f1, f2]);
$("body").append(modal);
}
},
rename: function(albumID) {
if (!albumID) oldTitle = lychee.title(); else oldTitle = "";
if (!albumID) albumID = lychee.content.attr("data-id");
newTitle = prompt("Please enter a new title for this album:", oldTitle);
if (albumID!=""&&albumID!=null&&albumID&&newTitle.length>2&&newTitle.length<31) {
loadingBar.show();
params = "setAlbumTitle&albumID=" + albumID + "&title=" + encodeURI(newTitle);
lychee.api(params, "text", function(data) {
if (data) {
if (visible.albums()) $(".album[data-id='" + albumID + "'] .overlay h1").html(newTitle);
else {
lychee.headerTitle.html(newTitle + "<span>" + $("#title span").html() + "</span>");
document.title = "Lychee - " + newTitle;
}
loadingBar.hide();
} else loadingBar.show("error");
});
} else if (newTitle.length>0) loadingBar.show("error", "Error", "New title to short or too long. Please try another one!");
},
getArchive: function() {
albumID = lychee.content.attr("data-id");
if (location.href.indexOf("index.html")>0) link = location.href.replace(location.hash, "").replace("index.html", "php/api.php?function=getAlbumArchive&albumID=" + albumID);
else link = location.href.replace(location.hash, "") + "php/api.php?function=getAlbumArchive&albumID=" + albumID;
location.href = link;
}
}

@ -0,0 +1,251 @@
/**
* @name build.js
* @author Philipp Maurer
* @author Tobias Reich
* @copyright 2013 by Philipp Maurer, Tobias Reich
*
* Build Module
* This module is used to generate HTML-Code.
*/
build = {
divider: function(title) {
return "<div class='divider fadeIn'><h1>" + title + "</h1></div>";
},
album: function(albumJSON) {
if(!albumJSON) return "";
if(!albumJSON.thumb0) albumJSON.thumb0 = "img/no_images.png";
if(!albumJSON.thumb1) albumJSON.thumb1 = "img/no_images.png";
if(!albumJSON.thumb2) albumJSON.thumb2 = "img/no_images.png";
if(!albumJSON.title) albumJSON.title = "Untitled";
if(albumJSON.title.length>18) albumJSON.title = albumJSON.title.substr(0, 18) + "...";
var album = "";
album += "<div class='album' data-id='" + albumJSON.id + "'>";
album += "<img src='" + lychee.upload_path + albumJSON.thumb2 + "' width='200' height='200' alt='thumb'>";
album += "<img src='" + lychee.upload_path + albumJSON.thumb1 + "' width='200' height='200' alt='thumb'>";
album += "<img src='" + lychee.upload_path + albumJSON.thumb0 + "' width='200' height='200' alt='thumb'>";
album += "<div class='overlay'>";
album += "<h1>" + albumJSON.title + "</h1>";
album += "<a>" + albumJSON.sysdate + "</a>";
album += "</div>";
if(albumJSON.star=="1") album += "<a class='badge red icon-star'></a>";
if(albumJSON.public=="1") album += "<a class='badge red icon-rss'></a>";
if(albumJSON.unsorted=="1") album += "<a class='badge red icon-reorder'></a>";
album += "</div>";
return album;
},
photo: function(photoJSON) {
if(photoJSON=="") return "";
if(!photoJSON.title) photoJSON.title = "";
if(!photoJSON.thumbUrl) photoJSON.thumbUrl = "img/no_image.png";
if(photoJSON.title.length>18) photoJSON.title = photoJSON.title.substr(0, 18) + "...";
var photo = "";
photo += "<div class='photo' data-album-id='" + photoJSON.album + "' data-id='" + photoJSON.id + "'>";
photo += "<img src='" + lychee.upload_path + photoJSON.thumbUrl + "' width='200' height='200' alt='thumb'>";
photo += "<div class='overlay'>";
photo += "<h1>" + photoJSON.title + "</h1>";
photo += "<a>" + photoJSON.sysdate + "</a>";
photo += "</div>";
if(photoJSON.star=="1") photo += "<a class='badge red icon-star'></a>";
if(photoJSON.public=="1") photo += "<a class='badge red icon-rss'></a>";
photo += "</div>";
return photo;
},
modal: function(title, text, button, func) {
var modal = "";
modal += "<div class='message_overlay fadeIn'>";
modal += "<div class='message center'>";
modal += "<h1>" + title + "</h1>";
modal += "<a class='close icon-remove-sign'></a>";
modal += "<p>" + text + "</p>";
$.each(button, function(index) {
if (index==0) modal += "<a onclick='message_click(" + index + ")' class='button active'>" + this + "</a>";
else modal += "<a onclick='message_click(" + index + ")' class='button'>" + this + "</a>";
});
modal += "</div>";
modal += "<script>";
modal += "function message_click(action) {";
modal += "switch (action) {";
$.each(func, function(index) {
modal += "case " + index + ":";
modal += this.toString();
modal += "break;";
});
modal += "} lychee.closeModal(); }";
modal += "</script>";
modal += "</div>";
return modal;
},
addModal: function() {
var modal = "";
modal += "<div class='message_overlay fadeIn'>";
modal += "<div class='message center add'>";
modal += "<h1>Add Album or Photo</h1>";
modal += "<a class='close icon-remove-sign'></a>";
modal += "<div id='add_album' class='add_album'>";
modal += "<div class='icon icon-folder-close'></div>";
modal += "<a>Add new Album</a>";
modal += "</div>";
modal += "<div id='add_photo' class='add_album'>";
modal += "<div class='icon icon-picture'></div>";
modal += "<a>Upload new Photo</a>";
modal += "</div>";
modal += "</div>";
modal += "</div>";
return modal;
},
signInModal: function() {
var modal = "";
modal += "<div class='message_overlay'>";
modal += "<div class='message center'>";
modal += "<h1><a class='icon-lock'></a> Sign in</h1>";
modal += "<div class='sign_in'>";
modal += "<input id='username' type='text' name='' value='' placeholder='username'>";
modal += "<input id='password' type='password' name='' value='' placeholder='password'>";
modal += "</div>";
modal += "<div id='version'>Version " + lychee.version + "</div>";
modal += "<a onclick='lychee.login()' class='button active'>Sign in</a>";
modal += "</div>";
modal += "</div>";
return modal;
},
uploadModal: function() {
var modal = "";
modal += "<div class='upload_overlay fadeIn'>";
modal += "<div class='upload_message center'>";
modal += "<a class='icon-upload'></a>";
modal += "<div class='progressbar'><div></div></div>";
modal += "</div>";
modal += "</div>";
return modal;
},
contextMenu: function(items) {
var menu = "";
menu += "<div class='contextmenu_bg'></div>";
menu += "<div class='contextmenu'>";
menu += "<table>";
menu += "<tbody>";
$.each(items, function(index) {
if (items[index][1].length!=0) {
menu += "<tr><td onclick='" + items[index][1] + "; contextMenu.close();'>" + items[index][0] + "</td></tr>";
}
});
menu += "</tbody>";
menu += "</table>";
menu += "</div>";
return menu;
},
infobox: function(photo, forView) {
var infobox = "";
infobox += "<div class='header'><h1>About</h1><a class='icon-remove-sign'></a></div>";
infobox += "<div class='wrapper'>";
if (photo.public==1) photo.public = "Public"; else photo.public = "Private";
if (forView==true) editTitleHTML = ""; else editTitleHTML = " <div id='edit_title'><a class='icon-pencil'></a></div>";
if (forView==true) editDescriptionHTML = ""; else editDescriptionHTML = " <div id='edit_description'><a class='icon-pencil'></a></div>";
infos = [
["", "Basics"],
["Name", photo.title + editTitleHTML],
["Uploaded", photo.sysdate],
["Description", photo.description + editDescriptionHTML],
["", "Image"],
["Size", photo.size],
["Format", photo.type],
["Resolution", photo.width + " x " + photo.height],
["", "Camera"],
["Captured", photo.takedate],
["Make", photo.make],
["Type/Model", photo.model],
["Shutter Speed", photo.shutter],
["Aperture", photo.aperture],
["Focal Length", photo.focal],
["ISO", photo.iso],
["", "Share"],
["Privacy", photo.public],
["Short Link", photo.shortlink]
];
$.each(infos, function(index) {
if (infos[index][1]==""||infos[index][1]==undefined||infos[index][1]==null) infos[index][1] = "-";
if (infos[index][0]=="") {
infobox += "</table>";
infobox += "<div class='separater'><h1>" + infos[index][1] + "</h1></div>";
infobox += "<table id='infos'>";
} else {
infobox += "<tr>";
infobox += "<td>" + infos[index][0] + "</td>";
infobox += "<td class='attr_" + infos[index][0].toLowerCase() + "'>" + infos[index][1] + "</td>";
infobox += "</tr>";
}
});
infobox += "</table>";
infobox += "<div class='bumper'></div>";
infobox += "</div>";
return infobox;
}
}

@ -0,0 +1,140 @@
/**
* @name contextMenu.js
* @author Philipp Maurer
* @author Tobias Reich
* @copyright 2013 by Philipp Maurer, Tobias Reich
*
* ContextMenu Module
* This module is used for the context menu.
*/
contextMenu = {
album: function(e) {
e.preventDefault();
mouse_x = e.pageX;
mouse_y = e.pageY;
albumID = $(this).attr("data-id");
if (albumID=="0"||albumID=="f"||albumID=="s") return false;
mouse_y -= $(document).scrollTop();
items = [
["Rename", "albums.rename(" + albumID + ")"],
["Delete", "albums.deleteDialog(" + albumID + ")"]
];
contextMenu.close();
$("body").css("overflow", "hidden");
$(".album[data-id='" + albumID + "']").addClass("active");
$("body").append(build.contextMenu(items));
$(".contextmenu").css({
"top": mouse_y,
"left": mouse_x
});
},
photo: function(e) {
e.preventDefault();
mouse_x = e.pageX;
mouse_y = e.pageY;
photoID = $(this).attr("data-id");
mouse_y -= $(document).scrollTop();
items = [
["Rename", "photos.rename(" + photoID + ")"],
["Move to Album", "contextMenu.move(" + photoID + ", " + (mouse_x+150) + ", " + (mouse_y+$(document).scrollTop()) + ")"],
["Delete", "photos.deleteDialog(" + photoID + ")"]
];
contextMenu.close();
$("body").css("overflow", "hidden");
$(".photo[data-id='" + photoID + "']").addClass("active");
$("body").append(build.contextMenu(items));
$(".contextmenu").css({
"top": mouse_y,
"left": mouse_x
});
},
move: function(photoID, mouse_x, mouse_y) {
mouse_y -= $(document).scrollTop();
lychee.api("getAlbums", "json", function(data) {
if (lychee.content.attr("data-id")==0) {
items = [];
} else {
items = [
["Unsorted", "photos.move(" + photoID + ", 0)"]
];
}
if (!data.albums) {
items = [
["Create new Album", "albums.add()"]
];
} else {
$.each(data.album, function(index) {
if (this.id!=lychee.content.attr("data-id")) {
if(!this.title) this.title = "Untitled";
items[items.length] = new Array(this.title, "photos.move(" + photoID + ", " + this.id + ")");
} else {
items[items.length] = new Array("", "");
}
});
}
contextMenu.close();
$("body").css("overflow", "hidden");
$(".photo[data-id='" + photoID + "']").addClass("active");
$("body").append(build.contextMenu(items));
$(".contextmenu").css({
"top": mouse_y,
"left": mouse_x-150
});
});
},
share: function(photoID, mouse_x, mouse_y) {
mouse_y -= $(document).scrollTop();
items = [
["<a class='icon-eye-close'></a> Make Private", "photos.setPublic()"],
["<a class='icon-twitter'></a> Twitter", "photos.share(0, " + photoID + ")"],
["<a class='icon-facebook'></a> Facebook", "photos.share(1, " + photoID + ")"],
["<a class='icon-envelope'></a> Mail", "photos.share(2, " + photoID + ")"],
["<a class='icon-link'></a> Copy Link", "photos.share(3, " + photoID + ")"],
["<a class='icon-link'></a> Copy Shortlink", "photos.share(4, " + photoID + ")"]
];
contextMenu.close();
$("body").css("overflow", "hidden");
$(".photo[data-id='" + photoID + "']").addClass("active");
$("body").append(build.contextMenu(items));
$(".contextmenu").css({
"top": mouse_y,
"left": mouse_x
});
},
close: function() {
$(".contextmenu_bg, .contextmenu").remove();
$(".photo.active, .album.active").removeClass("active");
$("body").css("overflow", "scroll");
}
}

@ -0,0 +1,58 @@
/**
* @name loadingBar.js
* @author Philipp Maurer
* @author Tobias Reich
* @copyright 2013 by Philipp Maurer, Tobias Reich
*
* LoadingBar Module
* This module is used to show and hide the loading bar.
*/
loadingBar = {
show: function(status, errorTitle, errorText) {
if (!status) status = "loading";
switch (status) {
case "error":
if (!errorTitle||!errorText) {
errorTitle = "Error";
errorText = "Whoops, it looks like something went wrong. Please reload the site and try again!"
}
lychee.loadingBar
.removeClass("loading uploading error")
.addClass(status)
.html("<h1>" + errorTitle + ": <span>" + errorText + "</span></h1>")
.show()
.css("height", "40px");
lychee.header.css("margin-Top", "40px");
$.timer(3000,function(){ loadingBar.hide() });
break;
case "loading":
clearTimeout(lychee.loadingBar.data("timeout"));
lychee.loadingBar.data("timeout", setTimeout(function () {
lychee.loadingBar
.show()
.removeClass("loading uploading error")
.addClass(status);
if (visible.controls()) lychee.header.css("margin-Top", "3px");
}, 1000));
break;
}
},
hide: function() {
clearTimeout(lychee.loadingBar.data("timeout"));
lychee.loadingBar.html("").css("height", "3px");
if (visible.controls()) lychee.header.css("marginTop", "0px");
$.timer(300,function(){ lychee.loadingBar.hide(); });
}
}

@ -0,0 +1,296 @@
/**
* @name lychee.js
* @author Philipp Maurer
* @author Tobias Reich
* @copyright 2013 by Philipp Maurer, Tobias Reich
*
* Lychee Module
* This module provides the basic functions of Lychee.
*/
lychee = {
init: function(api_path, upload_path) {
this.version = "1.1";
this.api_path = api_path;
this.upload_path = upload_path;
this.loadingBar = $("#loading");
this.header = $("header");
this.headerTitle = $("#title");
this.content = $("#content");
this.image_view = $("#image_view");
this.infobox = $("#infobox");
},
ready: function() {
$("#tools_albums").show();
if (!mobileBrowser()) $(".tools").tipsy({gravity: 'n'});
if (window.webkitNotifications) { window.webkitNotifications.requestPermission() };
lychee.api("loggedIn", "text", function(data) {
if (data!=1) {
$("body").append(build.signInModal());
$("#username").focus();
if (localStorage) {
local_username = localStorage.getItem("username");
if (local_username==null) return false;
if (local_username.length>1) $("#username").val(local_username);
$("#password").focus();
}
} else if (data) {
$(window).bind("popstate", lychee.load);
lychee.load();
}
});
},
api: function(params, type, callback) {
$.ajax({
type: "POST",
url: lychee.api_path,
data: "function=" + params,
dataType: type,
success: callback,
error: lychee.error
});
},
login: function() {
user = $("input#username").val();
password = hex_md5($("input#password").val());
params = "login&user=" + user + "&password=" + password;
lychee.api(params, "text", function(data) {
if (data) {
if (localStorage) { localStorage.setItem("username", user); }
$(window).bind("popstate", lychee.load);
lychee.load();
lychee.closeModal();
} else {
$("#password").val("").addClass("error");
$(".message .button.active").removeClass("pressed");
}
});
},
logout: function() {
lychee.api("logout", "text", function(data) {
window.location.reload();
});
},
upload: function(files) {
pre_progress = 0;
$(".upload_overlay").remove();
$("body").append(build.uploadModal());
var formData = new FormData();
for (var i = 0; i < files.length; i++) formData.append(i, files[i]);
formData.append("function", "upload");
if (lychee.content.attr("data-id")=="") formData.append("albumID", 0);
else formData.append("albumID", lychee.content.attr("data-id"));
var xhr = new XMLHttpRequest();
xhr.open('POST', lychee.api_path);
xhr.onload = function () {
if (xhr.status===200) {
$(".progressbar div").css("width", "100%");
$(".upload_overlay").removeClass("fadeIn").css("opacity", 0);
$.timer(300,function(){ $(".upload_overlay").remove() });
if (window.webkitNotifications&&BrowserDetect.browser=="Safari") {
var popup = window.webkitNotifications.createNotification("", "Upload complete", "You can now manage your new photos.");
popup.show();
}
if (lychee.content.attr("data-id")=="") lychee.goto("a0");
else photos.load(lychee.content.attr("data-id"));
}
};
xhr.upload.onprogress = function (event) {
if (event.lengthComputable) {
var progress = (event.loaded / event.total * 100 | 0);
if (progress>pre_progress) {
$(".progressbar div").css("width", progress + "%");
pre_progress = progress;
}
if (progress>=100) $(".progressbar div").css("opacity", 0.2);
}
};
$("#upload_files").val("");
xhr.send(formData);
},
load: function() {
contextMenu.close();
hash = document.location.hash.replace("#", "");
albumID = "";
photoID = "";
if (hash.indexOf("a")!=-1) albumID = hash.split("p")[0].replace("a", ""); else albumID = "";
if (hash.indexOf("p")!=-1) photoID = hash.split("p")[1]; else photoID = "";
lychee.content.attr("data-id", albumID);
lychee.image_view.attr("data-id", photoID);
if (albumID&&photoID) {
// Show ImageView
if (lychee.content.html()==""||$("#search").val().length!=0) {
lychee.content.hide();
photos.load(albumID, true);
}
photos.loadInfo(photoID);
} else if (albumID) {
// Show Album
if (visible.infobox) photos.hideInfobox();
if (!visible.controls()) lychee.showControls();
if (visible.imageview()) photos.hideView();
else photos.load(albumID, false);
} else {
// Show Albums
if (visible.infobox) photos.hideInfobox();
if (!visible.controls()) lychee.showControls();
if (visible.imageview()) photos.hideView();
albums.load();
}
},
goto: function(url) {
document.location.hash = url;
},
title: function() {
return lychee.headerTitle.html().replace($("#title span").html(), "").replace("<span></span>", "");
},
showControls: function() {
clearTimeout($(window).data("timeout"));
if (visible.imageview()) {
lychee.image_view.removeClass("full");
lychee.loadingBar.css("opacity", 1);
lychee.header.css("margin-Top", "0px");
if ($("#image_view #image.small").length>0) {
$("#image_view #image").css({
marginTop: -1*($("#image_view #image").height()/2)+20
});
} else {
$("#image_view #image").css({
top: 70,
right: 30,
bottom: 30,
left: 30
});
}
}
},
hideControls: function() {
if (visible.imageview()) {
clearTimeout($(window).data("timeout"));
$(window).data("timeout", setTimeout(function() {
lychee.image_view.addClass("full");
lychee.loadingBar.css("opacity", 0);
lychee.header.css("margin-Top", "-45px");
if ($("#image_view #image.small").length>0) {
$("#image_view #image").css({
marginTop: -1*($("#image_view #image").height()/2)
});
} else {
$("#image_view #image").css({
top: 0,
right: 0,
bottom: 0,
left: 0
});
}
}, 500));
}
},
closeModal: function() {
$(".message_overlay").removeClass("fadeIn").css("opacity", 0);
$.timer(300,function(){ $(".message_overlay").remove() });
},
animate: function(obj, animation) {
animations = [
["fadeIn", "fadeOut"],
["contentZoomIn", "contentZoomOut"]
];
if (!obj.jQuery) obj = $(obj);
for (i = 0; i < animations.length; i++) {
for (var x = 0; x < animations[i].length; x++) {
if (animations[i][x]==animation) {
obj.removeClass(animations[i][0] + " " + animations[i][1]).addClass(animation);
return true;
}
}
}
return false;
},
error: function(jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
console.log(textStatus);
console.log(errorThrown);
loadingBar.show("error", textStatus, errorThrown);
}
}

@ -0,0 +1,425 @@
/**
* @name photos.js
* @author Philipp Maurer
* @author Tobias Reich
* @copyright 2013 by Philipp Maurer, Tobias Reich
*
* Photos Module
* Takes care of every action photos can handle and execute.
*/
photos = {
load: function(albumID, refresh) {
// If refresh is true the function will only refresh the content and not change the toolbar buttons either the title
if (!refresh) {
loadingBar.show();
if (visible.imageview()) photos.hideView();
lychee.animate(".album, .photo", "contentZoomOut");
lychee.animate(".divider", "fadeOut");
}
startTime = new Date().getTime();
params = "getPhotos&albumID=" + albumID;
lychee.api(params, "json", function(data) {
durationTime = (new Date().getTime() - startTime);
if (durationTime>300) waitTime = 0; else if (refresh) waitTime = 0; else waitTime = 300 - durationTime;
$.timer(waitTime,function(){
photosData = "";
$.each(data, function() { photosData += build.photo(this); });
lychee.content.html(photosData);
if (!refresh) {
lychee.animate(".album, .photo", "contentZoomIn");
$("#tools_albums, #tools_photo").hide();
$("#tools_album").show();
$("img").retina();
albums.loadInfo(albumID);
}
});
});
},
loadInfo: function(photoID) {
photos.showView();
loadingBar.show();
params = "getPhotoInfo&photoID=" + photoID;
lychee.api(params, "json", function(data) {
if (!data.title) data.title = "Untitled";
document.title = "Lychee - " + data.title;
lychee.headerTitle.html(data.title).addClass("editable");
$("#button_star a").removeClass("icon-star-empty icon-star");
if (data.star=="1") {
$("#button_star a").addClass("icon-star");
$("#button_star").attr("title", "Unstar Photo");
} else {
$("#button_star a").addClass("icon-star-empty");
$("#button_star").attr("title", "Star Photo");
}
if (data.public=="1") {
$("#button_share a").addClass("active");
$("#button_share").attr("title", "Make Photo Private");
} else {
$("#button_share a").removeClass("active");
$("#button_share").attr("title", "Share Photo");
}
data.url = lychee.upload_path + data.url;
if (visible.controls()&&photos.isSmall(data)) lychee.image_view.html("<a id='previous' class='icon-caret-left'></a><a id='next' class='icon-caret-right'></a><div id='image' class='small' style='background-image: url(" + data.url + "); width: " + data.width + "px; height: " + data.height + "px; margin-top: -" + parseInt(data.height/2-20) + "px; margin-left: -" + data.width/2 + "px;'></div>");
else if (visible.controls()) lychee.image_view.html("<a id='previous' class='icon-caret-left'></a><a id='next' class='icon-caret-right'></a><div id='image' style='background-image: url(" + data.url + ")'></div>");
else if (photos.isSmall(data)) lychee.image_view.html("<a id='previous' style='left: -50px' class='icon-caret-left'></a><a id='next' style='right: -50px' class='icon-caret-right'></a><div id='image' class='small' style='background-image: url(" + data.url + "); width: " + data.width + "px; height: " + data.height + "px; margin-top: -" + parseInt(data.height/2) + "px; margin-left: -" + data.width/2 + "px;'></div>");
else lychee.image_view.html("<a id='previous' style='left: -50px' class='icon-caret-left'></a><a id='next' style='right: -50px' class='icon-caret-right'></a><div id='image' style='background-image: url(" + data.url + "); top: 0px; right: 0px; bottom: 0px; left: 0px;'></div>");
lychee.animate(image_view, "fadeIn");
lychee.image_view.show();
if (!visible.controls()) lychee.hideControls();
lychee.infobox.html(build.infobox(data)).show();
$.timer(300,function(){ lychee.content.show(); });
loadingBar.hide();
});
},
isSmall: function(photo) {
size = [
["width", false],
["height", false]
];
if (photo.width<$(window).width()-60) size["width"] = true;
if (photo.height<$(window).height()-100) size["height"] = true;
if (size["width"]&&size["height"]) return true;
else return false;
},
showView: function() {
// Change toolbar-buttons
$("#tools_albums, #tools_album").hide();
$("#tools_photo").show();
// Make body not scrollable
$("body").css("overflow", "hidden");
},
hideView: function() {
// Change toolbar-buttons
$("#tools_photo, #tools_albums").hide();
$("#tools_album").show();
// Make body scrollable
$("body").css("overflow", "scroll");
// Change website title and url by using albums.loadInfo
albums.loadInfo(lychee.content.attr("data-id"));
// Hide ImageViewer
lychee.animate(image_view, "fadeOut");
$.timer(300,function(){ lychee.image_view.hide() });
},
showInfobox: function() {
if (!visible.infobox()) $("body").append("<div id='infobox_overlay'></div>");
lychee.infobox.css("right", "0px");
},
hideInfobox: function() {
$("#infobox_overlay").remove();
lychee.infobox.css("right", "-320px");
},
hide: function(photoID) {
$(".photo[data-id='" + photoID + "']").css("opacity", 0).animate({
width: 0,
marginLeft: 0
}, 300, function() {
$(this).remove();
if (!visible.imageview()) {
imgNum = parseInt($("#title span").html().replace("- ", "").replace(" photos", ""))-1;
$("#title span").html(" - " + imgNum + " photos");
}
});
},
delete: function(photoID) {
loadingBar.show();
params = "deletePhoto&photoID=" + photoID;
lychee.api(params, "text", function(data) {
if (data) {
photos.hide(photoID);
lychee.goto("a" + lychee.content.attr("data-id"));
loadingBar.hide();
} else loadingBar.show("error");
});
},
deleteDialog: function(photoID) {
if (!photoID) photoID = lychee.image_view.attr("data-id");
if (visible.imageview()) photoTitle = lychee.title();
else photoTitle = $(".photo[data-id='" + photoID + "'] .overlay h1").html();
if (photoTitle=="") photoTitle = "Untitled";
f1 = "photos.delete(" + photoID + ");";
f2 = "";
modal = build.modal("Delete Photo", "Are you sure you want to delete the photo '" + photoTitle + "'?<br>This action can't be undone!", ["Delete Photo", "Keep Photo"], [f1, f2]);
$("body").append(modal);
},
rename: function(photoID) {
if (!photoID) oldTitle = lychee.title(); else oldTitle = "";
if (!photoID) photoID = lychee.image_view.attr("data-id");
newTitle = prompt("Please enter a new title for this photo:", oldTitle);
if (photoID!=null&&photoID&&newTitle.length<31) {
loadingBar.show();
if (newTitle=="") newTitle = "Untitled";
params = "setPhotoTitle&photoID=" + photoID + "&title=" + encodeURI(newTitle);
lychee.api(params, "text", function(data) {
if (data) {
if (visible.imageview()) {
$("#infobox .attr_name").html($("#infobox .attr_name").html().replace(lychee.title(), newTitle));
lychee.headerTitle.html(newTitle);
document.title = "Lychee - " + newTitle;
}
$(".photo[data-id='" + photoID + "'] .overlay h1").html(newTitle);
loadingBar.hide();
} else loadingBar.show("error");
});
} else if (newTitle.length>0) loadingBar.show("error", "Error", "New title to short or too long. Please try another one!");
},
move: function(photoID, albumID) {
if (albumID>=0) {
loadingBar.show();
params = "movePhoto&photoID=" + photoID + "&albumID=" + albumID;
lychee.api(params, "text", function(data) {
if (data) {
photos.hide(photoID);
lychee.goto("a" + lychee.content.attr("data-id"));
loadingBar.hide();
} else loadingBar.show("error");
});
}
},
setStar: function() {
loadingBar.show();
photoID = lychee.image_view.attr("data-id");
params = "setPhotoStar&photoID=" + photoID;
lychee.api(params, "text", function(data) {
if (data) {
if ($("#button_star a.icon-star-empty").length) {
$("#button_star a").removeClass("icon-star-empty icon-star").addClass("icon-star");
$("#button_star").attr("title", "Unstar Photo");
} else {
$("#button_star a").removeClass("icon-star-empty icon-star").addClass("icon-star-empty");
$("#button_star").attr("title", "Star Photo");
}
photos.load(lychee.content.attr("data-id"), true);
loadingBar.hide();
} else loadingBar.show("error");
});
},
setPublic: function(e) {
loadingBar.show();
photoID = lychee.image_view.attr("data-id");
params = "setPhotoPublic&photoID=" + photoID + "&url=" + photos.getViewLink(photoID);
lychee.api(params, "text", function(data) {
if (data) {
if ($("#button_share a.active").length) {
$("#button_share a").removeClass("active");
$("#button_share").attr("title", "Make Private");
} else {
$("#button_share a").addClass("active");
$("#button_share").attr("title", "Share Photo");
contextMenu.share(photoID, e.pageX, e.pageY);
}
photos.load(lychee.content.attr("data-id"), true);
loadingBar.hide();
} else loadingBar.show("error");
});
},
setDescription: function() {
description = prompt("Please enter a description for this photo:", "");
photoID = lychee.image_view.attr("data-id");
if (description.length>0&&description.length<160) {
loadingBar.show();
params = "setPhotoDescription&photoID=" + photoID + "&description=" + escape(description);
lychee.api(params, "text", function(data) {
if (data) photos.loadInfo(photoID);
else loadingBar.show("error");
});
} else if (description.length>0) loadingBar.show("error", "Error", "Description to short or too long. Please try another one!");
},
share: function(service, photoID) {
loadingBar.show();
params = "sharePhoto&photoID=" + photoID + "&url=" + photos.getViewLink(photoID);
lychee.api(params, "json", function(data) {
switch (service) {
case 0:
link = data.twitter;
break;
case 1:
link = data.facebook;
break;
case 2:
link = data.mail;
break;
case 3:
link = "copy";
modal = build.modal("Copy Link", "You can use this link to share your image with other people: <input class='copylink' value='" + photos.getViewLink(photoID) + "'>", ["Close"], [""]);
$("body").append(modal);
$(".copylink").focus();
break;
case 4:
link = "copy";
modal = build.modal("Copy Shortlink", "You can use this link to share your image with other people: <input class='copylink' value='" + data.shortlink + "'>", ["Close"], [""]);
$("body").append(modal);
$(".copylink").focus();
break;
default:
link = "";
break;
}
if (link=="copy") loadingBar.hide();
else if (link.length>5) {
location.href = link;
loadingBar.hide();
} else loadingBar.show("error");
});
},
getViewLink: function(photoID) {
if (location.href.indexOf("index.html")>0) return location.href.replace("index.html" + location.hash, "view.php?p=" + photoID);
else return location.href.replace(location.hash, "view.php?p=" + photoID);
},
previous: function() {
albumID = lychee.content.attr("data-id");
photoID = lychee.image_view.attr("data-id");
params = "previousPhoto&photoID=" + photoID + "&albumID=" + albumID;
lychee.api(params, "json", function(data) {
if (data!=false) lychee.goto("a" + albumID + "p" + data.id);
});
},
next: function() {
albumID = lychee.content.attr("data-id");
photoID = lychee.image_view.attr("data-id");
params = "nextPhoto&photoID=" + photoID + "&albumID=" + albumID;
lychee.api(params, "json", function(data) {
if (data) lychee.goto("a" + albumID + "p" + data.id);
});
}
}

@ -0,0 +1,71 @@
/**
* @name photos.js
* @author Philipp Maurer
* @author Tobias Reich
* @copyright 2013 by Philipp Maurer, Tobias Reich
*
* Search Module
* Searches through your photos and albums.
*/
search = {
find: function(term) {
clearTimeout($(window).data("timeout"));
$(window).data("timeout", setTimeout(function() {
if ($("#search").val().length!=0) {
params = "search&term=" + term;
lychee.api(params, "json", function(data) {
albumsData = "";
if (data&&data.albums) $.each(data.albums, function() { albumsData += build.album(this); });
photosData = "";
if (data&&data.photos) $.each(data.photos, function() { photosData += build.photo(this); });
if (albumsData==""&&photosData=="") code = "";
else if (albumsData=="") code = build.divider("Photos")+photosData;
else if (photosData=="") code = build.divider("Albums")+albumsData;
else code = build.divider("Photos")+photosData+build.divider("Albums")+albumsData;
if (lychee.content.attr("data-search")!=code) {
lychee.animate(".album, .photo", "contentZoomOut");
lychee.animate(".divider", "fadeOut");
$.timer(300,function(){
lychee.content.attr("data-search", code);
lychee.content.html(code);
lychee.animate(".album, .photo", "contentZoomIn");
});
}
});
} else search.reset();
}, 250));
},
reset: function() {
$("#search").val("");
if (lychee.content.attr("data-search")!="") {
lychee.content.attr("data-search", "");
lychee.animate(".divider", "fadeOut");
albums.load();
}
}
}

@ -0,0 +1,33 @@
/**
* @name visible.js
* @author Philipp Maurer
* @author Tobias Reich
* @copyright 2013 by Philipp Maurer, Tobias Reich
*
* Visible Module
* This module is used to check if elements are visible or not.
*/
visible = {
albums: function() {
if ($("#tools_albums").css("display")=="block") return true;
else return false;
},
imageview: function() {
if ($("#image_view.fadeIn").length>0) return true;
else return false;
},
infobox: function() {
if (parseInt(lychee.infobox.css("right").replace("px", ""))==-320) return false;
else return true;
},
controls: function() {
if (lychee.loadingBar.css("opacity")>0) return true;
else return false;
}
}

@ -1,102 +0,0 @@
/**
* @name upload.js
* @author Philipp Maurer
* @author Tobias Reich
* @copyright 2012 by Philipp Maurer, Tobias Reich
*/
var global_progress = new Array(),
last_final_progress = 0;
function handleFiles(files) {
var i = 0;
var auswahl_div = document.getElementById('auswahl');
var imageType = /image.*/;
var fileList = files;
for(i = 0; i < fileList.length; i++) {
var img = document.createElement("img");
img.height = 0;
img.file = fileList[i];
img.name = 'pic_'+ i;
img.classList.add("obj");
auswahl_div.appendChild(img);
}
}
function sendFiles(){
imgs = document.querySelectorAll(".obj");
$(".upload_overlay").remove();
$("body").append(buildUploadModal());
global_progress = new Array();
last_final_progress = 0;
for(i = 0; i < imgs.length; i++) {
global_progress[i] = 0;
new FileUpload(i, imgs[i], imgs[i].file);
}
}
function changeProgress(i, progress) {
global_progress[i] = progress;
final_progress = 0;
for(i = 0; i < global_progress.length; i++) {
final_progress += global_progress[i];
}
if (Math.round(final_progress/document.querySelectorAll(".obj").length)%2==0&&Math.round(last_final_progress/document.querySelectorAll(".obj").length)<Math.round(final_progress/document.querySelectorAll(".obj").length)) {
$(".progressbar div").css("width", Math.round(final_progress/document.querySelectorAll(".obj").length) + "%");
}
last_final_progress = final_progress;
if ((final_progress/document.querySelectorAll(".obj").length)>=100) {
$(".progressbar div").css("width", "100%");
$.timer(1000,function(){
$(".upload_overlay").removeClass("fadeIn").css("opacity", 0);
$.timer(300,function(){ $(".upload_overlay").remove() });
if (content.attr("data-id")=="") setURL("a0");
else loadPhotos(content.attr("data-id"));
});
}
}
function FileUpload(i, img, file) {
var old_percent = 0,
xhr = new XMLHttpRequest(),
fd = new FormData,
percent = 0;
this.xhr = xhr;
this.xhr.upload.addEventListener("progress", function(e) {
if (e.lengthComputable) percent = Math.round((e.loaded * 100) / e.total);
changeProgress(i, percent);
}, false);
fd.append("File", file);
fd.append("function", "upload");
if (content.attr("data-id")=="") fd.append("albumID", 0);
else fd.append("albumID", content.attr("data-id"));
xhr.open("POST", "php/api.php", true);
xhr.overrideMimeType('text/plain; charset=x-user-defined-binary');
xhr.send(fd);
}

@ -2,7 +2,7 @@
* @name view.js
* @author Philipp Maurer
* @author Tobias Reich
* @copyright 2012 by Philipp Maurer, Tobias Reich
* @copyright 2013 by Philipp Maurer, Tobias Reich
*/
var header = $("header"),
@ -13,15 +13,20 @@ var header = $("header"),
$(document).ready(function(){
/* Event Name */
if (mobileBrowser()) event_name = "touchend";
else event_name = "click";
/* Window */
$(window).keydown(key);
/* Infobox */
$("#infobox_overlay, #infobox .header a").live("click", function() { hideInfobox() });
$("#button_info").live("click", function() { showInfobox() });
$(document).on(event_name, "#infobox .header a", function() { hideInfobox() });
$(document).on(event_name, "#infobox_overlay", function() { hideInfobox() });
$("#button_info").on(event_name, function() { showInfobox() });
/* Download */
$("#button_download").live("click", function() {
$("#button_download").on(event_name, function() {
link = $("#image_view #image").css("background-image").replace(/"/g,"").replace(/url\(|\)$/ig, "");
window.open(link,"_newtab");
});
@ -83,11 +88,11 @@ function loadPhotoInfo(photoID) {
headerTitle.html(data.title);
image_view.attr("data-id", photoID);
if (isPhotoSmall(data)) image_view.html("").append("<div id='image' class='small' style='background-image: url(" + data.url + "); width: " + data.width + "px; height: " + data.height + "px; margin-top: -" + parseInt((data.height/2)-20) + "px; margin-left: -" + data.width/2 + "px;'></div>");
else image_view.html("").append("<div id='image' style='background-image: url(" + data.url + "); top: 70px; right: 30px; bottom: 30px; left: 30px;'></div>");
if (isPhotoSmall(data)) image_view.html("<div id='image' class='small' style='background-image: url(" + data.url + "); width: " + data.width + "px; height: " + data.height + "px; margin-top: -" + parseInt((data.height/2)-20) + "px; margin-left: -" + data.width/2 + "px;'></div>");
else image_view.html("<div id='image' style='background-image: url(" + data.url + "); top: 70px; right: 30px; bottom: 30px; left: 30px;'></div>");
image_view.removeClass("fadeOut").addClass("fadeIn").show();
infobox.html(buildInfobox(data)).show();
infobox.html(build.infobox(data, true)).show();
}, error: ajaxError });

@ -6,15 +6,14 @@ SET time_zone = "+00:00";
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
CREATE TABLE IF NOT EXISTS `albums` (
CREATE TABLE IF NOT EXISTS `lychee_albums` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(50) NOT NULL,
`sysdate` varchar(10) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `photos` (
CREATE TABLE IF NOT EXISTS `lychee_photos` (
`id` bigint(14) NOT NULL,
`title` varchar(50) NOT NULL,
`description` varchar(160) NOT NULL,
@ -36,8 +35,9 @@ CREATE TABLE IF NOT EXISTS `photos` (
`takedate` varchar(10) NOT NULL,
`taketime` varchar(8) NOT NULL,
`star` tinyint(1) NOT NULL,
`album` varchar(30) NOT NULL DEFAULT '0',
`thumbUrl` varchar(50) NOT NULL,
`album` varchar(30) NOT NULL DEFAULT '0',
`import_name` varchar(100) DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

@ -4,13 +4,18 @@
* @name api.php
* @author Philipp Maurer
* @author Tobias Reich
* @copyright 2012 by Philipp Maurer, Tobias Reich
* @copyright 2013 by Philipp Maurer, Tobias Reich
*/
if(floatval(phpversion())<5.2) die("Please upgrade to PHP 5.2 or higher!");
if((isset($_POST["function"])&&$_POST["function"]!="")||(isset($_GET["function"])&&$_GET["function"]!="")) {
session_start();
define("LYCHEE", true);
include("array2json.php");
include("config.php");
include("functions.php");
// Security
@ -20,7 +25,7 @@ if((isset($_POST["function"])&&$_POST["function"]!="")||(isset($_GET["function"]
if($_SESSION["login"]==true) {
//Connect to DB
dbConnect();
$database = dbConnect();
// Album Functions
if($_POST["function"]=="getAlbums") echo array2json(getAlbums());
@ -54,12 +59,13 @@ if((isset($_POST["function"])&&$_POST["function"]!="")||(isset($_GET["function"]
if($_POST["function"]=="syncFolder") echo syncFolder();
// Session Functions
if($_POST["function"]=="login") echo login($_POST['user'], $_POST['password']);
if($_POST["function"]=="logout") logout();
if($_POST["function"]=="loggedIn") echo true;
} else {
dbConnect();
$database = dbConnect();
// Photo Functions
if($_POST["function"]=="getPhotoInfo"&&isset($_POST["photoID"])&&isPhotoPublic($_POST["photoID"])) echo array2json(getPhotoInfo($_POST["photoID"]));
@ -70,6 +76,11 @@ if((isset($_POST["function"])&&$_POST["function"]!="")||(isset($_GET["function"]
}
} else echo "Error: No permission!";
} else {
header('HTTP/1.1 401 Unauthorized');
die("Error: No permission!");
}
?>

@ -1,43 +1,43 @@
<?php
function array2json($arr) {
<?php
function array2json($arr) {
if(function_exists('json_encode')) return json_encode($arr); //Lastest versions of PHP already has this functionality.
$parts = array();
$is_list = false;
$parts = array();
$is_list = false;
//Find out if the given array is a numerical array
$keys = array_keys($arr);
$max_length = count($arr)-1;
//Find out if the given array is a numerical array
$keys = array_keys($arr);
$max_length = count($arr)-1;
if(($keys[0] == 0) and ($keys[$max_length] == $max_length)) {//See if the first key is 0 and last key is length - 1
$is_list = true;
for($i=0; $i<count($keys); $i++) { //See if each key correspondes to its position
if($i != $keys[$i]) { //A key fails at position check.
$is_list = false; //It is an associative array.
break;
}
}
}
$is_list = true;
for($i=0; $i<count($keys); $i++) { //See if each key correspondes to its position
if($i != $keys[$i]) { //A key fails at position check.
$is_list = false; //It is an associative array.
break;
}
}
}
foreach($arr as $key=>$value) {
if(is_array($value)) { //Custom handling for arrays
if($is_list) $parts[] = array2json($value); /* :RECURSION: */
else $parts[] = '"' . $key . '":' . array2json($value); /* :RECURSION: */
} else {
$str = '';
if(!$is_list) $str = '"' . $key . '":';
foreach($arr as $key=>$value) {
if(is_array($value)) { //Custom handling for arrays
if($is_list) $parts[] = array2json($value); /* :RECURSION: */
else $parts[] = '"' . $key . '":' . array2json($value); /* :RECURSION: */
} else {
$str = '';
if(!$is_list) $str = '"' . $key . '":';
//Custom handling for multiple data types
if(is_numeric($value)) $str .= $value; //Numbers
elseif($value === false) $str .= 'false'; //The booleans
elseif($value === true) $str .= 'true';
else $str .= '"' . addslashes($value) . '"'; //All other things
// :TODO: Is there any more datatype we should be in the lookout for? (Object?)
//Custom handling for multiple data types
if(is_numeric($value)) $str .= $value; //Numbers
elseif($value === false) $str .= 'false'; //The booleans
elseif($value === true) $str .= 'true';
else $str .= '"' . addslashes($value) . '"'; //All other things
// :TODO: Is there any more datatype we should be in the lookout for? (Object?)
$parts[] = $str;
}
}
$json = implode(',',$parts);
if($is_list) return '[' . $json . ']';//Return numerical JSON
return '{' . $json . '}';//Return associative JSON
$parts[] = $str;
}
}
$json = implode(',',$parts);
if($is_list) return '[' . $json . ']';//Return numerical JSON
return '{' . $json . '}';//Return associative JSON
}
?>

@ -0,0 +1,39 @@
<?php
define("LYCHEE", true);
// Declare
$error = "";
// Include
include("config.php");
// PHP Version
if (floatval(phpversion())<5.2) $error .= ("Error 100: Please upgrade to PHP 5.2 or higher!<br>\n");
// Extensions
if (!extension_loaded("exif")) $error .= ("Error 200: PHP exif extension not activated.<br>\n");
if (!extension_loaded("mbstring")) $error .= ("Error 201: PHP mbstring extension not activated.<br>\n");
if (!extension_loaded("gd")) $error .= ("Error 202: PHP gd extension not activated.<br>\n");
if (!extension_loaded("mysqli")) $error .= ("Error 203: PHP mysqli extension not activated.<br>\n");
// Config
if (!$db||$db=="") $error .= ("Error 300: No property for \$db in config.php.<br>\n");
if (!$dbUser||$dbUser=="") $error .= ("Error 301: No property for \$dbUser in config.php.<br>\n");
if (!$dbPassword||$dbPassword=="") $error .= ("Error 302: No property for \$dbPassword in config.php.<br>\n");
if (!$dbHost||$dbHost=="") $error .= ("Error 303: No property for \$dbHost in config.php.<br>\n");
if (!$user||$user=="") $error .= ("Error 304: No property for \$user in config.php.<br>\n");
if (!$password||$password=="") $error .= ("Error 305: No property for \$password in config.php.<br>\n");
// Database
$database = new mysqli($dbHost, $dbUser, $dbPassword, $db);
if (mysqli_connect_errno()!=0) $error .= ("Error 400: " . mysqli_connect_errno() . ": " . mysqli_connect_error() . "<br>\n");
// Permissions
if (substr(sprintf('%o', fileperms("../uploads/big/")), -4) != "0777") $error .= ("Error 500: Wrong permissions for \"/uploads/big\" (777 required).<br>\n");
if (substr(sprintf('%o', fileperms("../uploads/thumb/")), -4) != "0777") $error .= ("Error 501: Wrong permissions for \"/uploads/thumb\" (777 required).<br>\n");
if (substr(sprintf('%o', fileperms("../uploads/import/")), -4) != "0777") $error .= ("Error 502: Wrong permissions for \"/uploads/import\" (777 required).<br>\n");
if ($error == "") echo("Lychee is ready!"); else echo $error;
?>

@ -4,21 +4,23 @@
* @name config.php
* @author Philipp Maurer
* @author Tobias Reich
* @copyright 2012 by Philipp Maurer, Tobias Reich
* @copyright 2013 by Philipp Maurer, Tobias Reich
*/
if(!defined('LYCHEE')) die("Direct access is not allowed!");
//Database configurations
$db = "lychee"; //Database name
$dbUser = "lychee"; //Username of the database
$dbPassword = "lychee_passwd"; //Password of the Database
$dbHost = "localhost"; //Host of the Database
//lychee user configuration
//Lychee user configuration
$user = "lychee"; //lychee username
$password = "1234"; //lychee password
//Additional settings
$thumbQuality = 95; //Quality of the Thumbs (0-100). Default: 95
$bitlyUsername = ""; //Your Bit.ly Username
$bitlyApi = ""; //Your Bit.ly API Key

@ -4,53 +4,53 @@
* @name functions.php
* @author Philipp Maurer
* @author Tobias Reich
* @copyright 2012 by Philipp Maurer, Tobias Reich
* @copyright 2013 by Philipp Maurer, Tobias Reich
*/
include("config.php");
if(!defined('LYCHEE')) die("Direct access is not allowed!");
// Database Functions
function dbConnect() {
global $db, $dbUser, $dbPassword, $dbHost;
$connect = mysql_connect($dbHost, $dbUser, $dbPassword);
if(!$connect) {
echo "No connection: ".mysql_error();
$database = new mysqli($dbHost, $dbUser, $dbPassword);
if (mysqli_connect_errno() != 0) {
echo mysqli_connect_errno().': '.mysqli_connect_error();
return false;
}
$dbSelect = mysql_select_db($db);
if(!$dbSelect) {
if(createDatabase($db)){$dbSelect = mysql_select_db($db);}
else {echo "Can not create Database!"; return false;}
}
$query = "SELECT * FROM photos, albums;";
if(!mysql_query($query)) createTables();
return true;
}
if (!$database->select_db($db)) {
createDatabase($db, $database);
}
$query = "SELECT * FROM lychee_photos, lychee_albums;";
if(!$database->query($query)) createTables($database);
return $database;
}
function dbClose() {
$close = mysql_close();
global $database;
$close = $database->close();
if(!$close) {
echo "Closing the connection failed!";
return false;
}
return true;
}
function createDatabase($db) {
$query = "CREATE DATABASE $db;";
$result = mysql_query($query);
function createDatabase($db, $database) {
$query = "CREATE DATABASE IF NOT EXISTS $db;";
$result = $database->query($query);
$database->select_db($db);
if(!$result) return false;
return true;
}
function createTables() {
$query = "CREATE TABLE IF NOT EXISTS `albums` (
function createTables($database) {
$query = "CREATE TABLE IF NOT EXISTS `lychee_albums` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(50) NOT NULL,
`sysdate` varchar(10) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;";
$result = mysql_query($query);
$result = $database->query($query);
if(!$result) return false;
$query = "CREATE TABLE IF NOT EXISTS `photos` (
$query = "CREATE TABLE `lychee_photos` (
`id` bigint(14) NOT NULL,
`title` varchar(50) NOT NULL,
`description` varchar(160) NOT NULL,
@ -72,65 +72,81 @@ function createTables() {
`takedate` varchar(10) NOT NULL,
`taketime` varchar(8) NOT NULL,
`star` tinyint(1) NOT NULL,
`album` varchar(30) NOT NULL DEFAULT '0',
`thumbUrl` varchar(50) NOT NULL,
`album` varchar(30) NOT NULL DEFAULT '0',
`import_name` varchar(100) DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;";
$result = mysql_query($query);
) ENGINE=MyISAM DEFAULT CHARSET=latin1;";
$result = $database->query($query);
if(!$result) return false;
return true;
}
// Upload Functions
function upload($file, $albumID) {
switch($albumID) {
case 's':
$public = 1;
$star = 0;
$albumID = 0;
break;
case 'f':
$star = 1;
$public = 0;
$albumID = 0;
break;
default:
$star = 0;
$public = 0;
function upload($files, $albumID) {
global $database;
foreach ($files as $file) {
switch($albumID) {
// s for public (share)
case 's':
$public = 1;
$star = 0;
$albumID = 0;
break;
// f for starred (fav)
case 'f':
$star = 1;
$public = 0;
$albumID = 0;
break;
default:
$star = 0;
$public = 0;
}
$id = str_replace('.', '', microtime(true));
while(strlen($id)<14) $id .= 0;
$tmp_name = $file["tmp_name"];
$type = getimagesize($tmp_name);
if(($type[2]!=1)&&($type[2]!=2)&&($type[2]!=3)) return false;
$data = $file["name"];
$data = explode('.',$data);
$data = array_reverse ($data);
$data = $data[0];
if(!is_uploaded_file($file)) {
if (copy($tmp_name, "../uploads/big/$id.$data")) {
unlink($tmp_name);
$import_name = $tmp_name;
}
} else {
move_uploaded_file($tmp_name, "../uploads/big/$id.$data");
$import_name = "";
}
createThumb($id.".".$data);
// Read infos
$info = getCamera($id.".".$data);
$title="";
if(isset($info['type'])){$type=$info['type'];}else{$type="";}
if(isset($info['width'])){$width=$info['width'];}else{$width="";}
if(isset($info['height'])){$height=$info['height'] OR "";}else{$height="";}
if(isset($info['size'])){$size=$info['size'] OR "";}else{$size="";}
if(isset($info['date'])){$sysdate=$info['date'];}else{$sysdate="";}
if(isset($info['time'])){$systime=$info['time'];}else{$systime="";}
if(isset($info['iso'])){$iso=$info['iso'];}else{$iso="";}
if(isset($info['aperture'])){$aperture=$info['aperture'];}else{$aperture="";}
if(isset($info['make'])){$make=$info['make'];}else{$make="";}
if(isset($info['model'])){$model=$info['model'] OR "";}else{$model="";}
if(isset($info['shutter'])){$shutter=$info['shutter'];}else{$shutter="";}
if(isset($info['focal'])){$focal=$info['focal'];}else{$focal="";}
if(isset($info['takeDate'])){$takeDate=$info['takeDate'];}else{$takeDate="";}
if(isset($info['takeTime'])){$takeTime=$info['takeTime'];}else{$takeTime="";}
$query = "INSERT INTO lychee_photos (id, title, url, type, width, height, size, sysdate, systime, iso, aperture, make, model, shutter, focal, takedate, taketime, thumbUrl, album, public, star, import_name)
VALUES ('$id', '$title', 'uploads/big/$id.$data', '$type', '$width', '$height', '$size', '$sysdate', '$systime', '$iso', '$aperture', '$make', '$model', '$shutter', '$focal', '$takeDate', '$takeTime', 'uploads/thumb/$id.$data', '$albumID', '$public', '$star', '$import_name');";
$result = $database->query($query);
}
$id = str_replace('.', '', microtime(true));
while(strlen($id)<14) $id .= 0;
$tmp_name = $file['File']["tmp_name"];
$type = getimagesize($tmp_name);
if(($type[2]!=1)&&($type[2]!=2)&&($type[2]!=3)) return false;
$data = $file['File']["name"];
$data = explode('.',$data);
$data = array_reverse ($data);
$data = $data[0];
move_uploaded_file($tmp_name, "../uploads/big/$id.$data");
createThumb($id.".".$data);
// Read infos
$info = getCamera($id.".".$data);
$title="";
if(isset($info['type'])){$type=$info['type'];}else{$type="";}
if(isset($info['width'])){$width=$info['width'];}else{$width="";}
if(isset($info['height'])){$height=$info['height'] OR "";}else{$height="";}
if(isset($info['size'])){$size=$info['size'] OR "";}else{$size="";}
if(isset($info['date'])){$sysdate=$info['date'];}else{$sysdate="";}
if(isset($info['time'])){$systime=$info['time'];}else{$systime="";}
if(isset($info['iso'])){$iso=$info['iso'];}else{$iso="";}
if(isset($info['aperture'])){$aperture=$info['aperture'];}else{$aperture="";}
if(isset($info['make'])){$make=$info['make'];}else{$make="";}
if(isset($info['model'])){$model=$info['model'] OR "";}else{$model="";}
if(isset($info['shutter'])){$shutter=$info['shutter'];}else{$shutter="";}
if(isset($info['focal'])){$focal=$info['focal'];}else{$focal="";}
if(isset($info['takeDate'])){$takeDate=$info['takeDate'];}else{$takeDate="";}
if(isset($info['takeTime'])){$takeTime=$info['takeTime'];}else{$takeTime="";}
$query = "INSERT INTO photos (id, title, url, type, width, height, size, sysdate, systime, iso, aperture, make, model, shutter, focal, takedate, taketime, thumbUrl, album, public, star)
VALUES ('$id', '$title', 'uploads/big/$id.$data', '$type', '$width', '$height', '$size', '$sysdate', '$systime', '$iso', '$aperture', '$make', '$model', '$shutter', '$focal', '$takeDate', '$takeTime', 'uploads/thumb/$id.$data', '$albumID', '$public', '$star');";
$result = mysql_query($query);
return true;
}
function getCamera($photoID) {
global $database;
$return = array();
$url = "../uploads/big/$photoID";
$type = getimagesize($url);
@ -152,7 +168,7 @@ function getCamera($photoID) {
$return['date'] = date("d.m.Y",filectime($url));
$return['time'] = date("H:i:s",filectime($url));
echo $exif['FileDateTime']."<br/>".$exif['DateTimeOriginal'];
//echo $exif['FileDateTime']."<br/>".$exif['DateTimeOriginal'];
// Camera Information
if(isset($exif['ISOSpeedRatings'])){$return['iso']="ISO-".$exif['ISOSpeedRatings'];}
@ -183,10 +199,12 @@ function getCamera($photoID) {
}
return $return;
}
function createThumb($photoName, $width = 200, $height = 200) {
global $thumbQuality;
function createThumb($photoName, $width = 200, $width2x = 400, $height = 200, $height2x = 400) {
global $database, $thumbQuality;
$photoUrl = "../uploads/big/$photoName";
$newUrl = "../uploads/thumb/$photoName";
$thumbPhotoName = explode(".", $photoName);
$newUrl2x = "../uploads/thumb/".$thumbPhotoName[0]."@2x.".$thumbPhotoName[1];
$oldImg = getimagesize($photoUrl);
$type = $oldImg['mime'];
switch($type) {
@ -196,6 +214,7 @@ function createThumb($photoName, $width = 200, $height = 200) {
default: return false;
}
$thumb = imagecreatetruecolor($width, $height);
$thumb2x = imagecreatetruecolor($width2x, $height2x);
if($oldImg[0]<$oldImg[1]) {
$newSize = $oldImg[0];
$startWidth = 0;
@ -206,10 +225,11 @@ function createThumb($photoName, $width = 200, $height = 200) {
$startHeight = 0;
}
imagecopyresampled($thumb,$sourceImg,0,0,$startWidth,$startHeight,$width,$height,$newSize,$newSize);
imagecopyresampled($thumb2x,$sourceImg,0,0,$startWidth,$startHeight,$width2x,$height2x,$newSize,$newSize);
switch($type) {
case "image/jpeg": imagejpeg($thumb,$newUrl,$thumbQuality); break;
case "image/png": imagepng($thumb,$newUrl); break;
case "image/gif": imagegif($thumb,$newUrl); break;
case "image/jpeg": imagejpeg($thumb,$newUrl,$thumbQuality); imagejpeg($thumb2x,$newUrl2x,$thumbQuality); break;
case "image/png": imagepng($thumb,$newUrl); imagepng($thumb2x,$newUrl2x); break;
case "image/gif": imagegif($thumb,$newUrl); imagegif($thumb2x,$newUrl2x); break;
default: return false;
}
return true;
@ -217,9 +237,13 @@ function createThumb($photoName, $width = 200, $height = 200) {
// Session Functions
function login($loginUser, $loginPassword) {
global $user, $password;
if(($loginUser == $user) && ($loginPassword == $password)){
global $database, $user, $password;
if(($loginUser == $user) && ($loginPassword == md5($password))){
$_SESSION['login'] = true;
ini_set("session.cookie_lifetime","86400");
ini_set("session.gc_maxlifetime", 86400);
ini_set("session.gc_probability",1);
ini_set("session.gc_divisor",1);
return true;
} else {
return false;
@ -232,137 +256,149 @@ function logout() {
// Album Functions
function addAlbum($title) {
$title = mysql_escape_string($title);
global $database;
$title = mysqli_real_escape_string($database, $title);
$sysdate = date("d.m.Y");
$query = "INSERT INTO albums (title, sysdate) VALUES ('$title', '$sysdate');";
$result = mysql_query($query);
$query = "INSERT INTO lychee_albums (title, sysdate) VALUES ('$title', '$sysdate');";
$result = $database->query($query);
if(!$result) return false;
return mysql_insert_id();
return $database->insert_id;
}
function getAlbums() {
$return = array(array());
$query = "SELECT id, title, sysdate FROM albums ORDER BY id DESC;";
$result = mysql_query($query) OR die("Error: $result <br>".mysql_error());
global $database;
$return = array(array(array()));
// Smart Albums
$return = getSmartInfo();
// Albums
$query = "SELECT id, title, sysdate FROM lychee_albums ORDER BY id DESC;";
$result = $database->query($query) OR die("Error: $result <br>".$database->error);
$i=0;
while($row = mysql_fetch_object($result)) {
$return[$i]['id'] = $row->id;
$return[$i]['title'] = $row->title;
$return[$i]['sysdate'] = $row->sysdate;
while($row = $result->fetch_object()) {
$return["album"][$i]['id'] = $row->id;
$return["album"][$i]['title'] = $row->title;
$return["album"][$i]['sysdate'] = $row->sysdate;
$albumID = $row->id;
$query = "SELECT thumbUrl FROM photos WHERE album = '$albumID' ORDER BY id DESC LIMIT 0, 3;";
$result2 = mysql_query($query);
$query = "SELECT thumbUrl FROM lychee_photos WHERE album = '$albumID' ORDER BY id DESC LIMIT 0, 3;";
$result2 = $database->query($query);
$k = 0;
while($row2 = mysql_fetch_object($result2)){
$return[$i]["thumb$k"] = $row2->thumbUrl;
while($row2 = $result2->fetch_object()){
$return["album"][$i]["thumb$k"] = $row2->thumbUrl;
$k++;
}
if(!isset($return[$i]["thumb0"]))$return[$i]["thumb0"]="";
if(!isset($return[$i]["thumb1"]))$return[$i]["thumb1"]="";
if(!isset($return[$i]["thumb2"]))$return[$i]["thumb2"]="";
if(!isset($return["album"][$i]["thumb0"]))$return[$i]["thumb0"]="";
if(!isset($return["album"][$i]["thumb1"]))$return[$i]["thumb1"]="";
if(!isset($return["album"][$i]["thumb2"]))$return[$i]["thumb2"]="";
$i++;
}
if($i==0) return false;
if($i==0) $return["albums"] = false;
else $return["albums"] = true;
return $return;
}
function getSmartInfo() {
$return = array();
$query = "SELECT * FROM photos WHERE album = 0 ORDER BY id DESC;";
$result = mysql_query($query);
global $database;
$return = array(array());
$query = "SELECT * FROM lychee_photos WHERE album = 0 ORDER BY id DESC;";
$result = $database->query($query);
$i = 0;
while($row = mysql_fetch_object($result)) {
while($row = $result->fetch_object()) {
if($i<3) $return["unsortThumb$i"] = $row->thumbUrl;
$i++;
}
$return['unsortNum'] = $i;
$query2 = "SELECT * FROM photos WHERE public = 1 ORDER BY id DESC;";
$result2 = mysql_query($query2);
$query2 = "SELECT * FROM lychee_photos WHERE public = 1 ORDER BY id DESC;";
$result2 = $database->query($query2);
$i = 0;
while($row2 = mysql_fetch_object($result2)) {
while($row2 = $result2->fetch_object()) {
if($i<3) $return["publicThumb$i"] = $row2->thumbUrl;
$i++;
}
$return['publicNum'] = $i;
$query3 = "SELECT * FROM photos WHERE star = 1 ORDER BY id DESC;";
$result3 = mysql_query($query3);
$query3 = "SELECT * FROM lychee_photos WHERE star = 1 ORDER BY id DESC;";
$result3 = $database->query($query3);
$i = 0;
while($row3 = mysql_fetch_object($result3)) {
while($row3 = $result3->fetch_object()) {
if($i<3) $return["starredThumb$i"] = $row3->thumbUrl;
$i++;
}
$return['starredNum'] = $i;
return $return;
}
function getAlbumInfo($albumID) {
global $database;
$return = array();
$query = "SELECT * FROM albums WHERE id = '$albumID';";
$result = mysql_query($query);
$row = mysql_fetch_object($result);
$query = "SELECT * FROM lychee_albums WHERE id = '$albumID';";
$result = $database->query($query);
$row = $result->fetch_object();
$return['title'] = $row->title;
$return['date'] = $row->sysdate;
$return['star'] = $row->star;
$return['public'] = $row->public;
$query = "SELECT COUNT(*) AS num FROM photos WHERE album = '$albumID';";
$result = mysql_query($query);
$row = mysql_fetch_object($result);
$query = "SELECT COUNT(*) AS num FROM lychee_photos WHERE album = '$albumID';";
$result = $database->query($query);
$row = $result->fetch_object();
$return['num'] = $row->num;
return $return;
}
function setAlbumTitle($albumID, $title) {
$title = mysql_real_escape_string(urldecode($title));
global $database;
$title = mysqli_real_escape_string($database, urldecode($title));
if(strlen($title)<3||strlen($title)>30) return false;
$query = "UPDATE albums SET title = '$title' WHERE id = '$albumID';";
$result = mysql_query($query);
$query = "UPDATE lychee_albums SET title = '$title' WHERE id = '$albumID';";
$result = $database->query($query);
if(!$result) return false;
return true;
}
function deleteAlbum($albumID, $delAll) {
global $database;
if($delAll=="true") {
$query = "SELECT id FROM photos WHERE album = '$albumID';";
$result = mysql_query($query);
$query = "SELECT id FROM lychee_photos WHERE album = '$albumID';";
$result = $database->query($query);
$error = false;
while($row = mysql_fetch_object($result)) {
while($row = $result->fetch_object()) {
if(!deletePhoto($row->id)) $error = true;
}
} else {
$query = "UPDATE photos SET album = '0' WHERE album = '$albumID';";
$result = mysql_query($query);
$query = "UPDATE lychee_photos SET album = '0' WHERE album = '$albumID';";
$result = $database->query($query);
if(!$result) return false;
}
if($albumID!=0) {
$query = "DELETE FROM albums WHERE id = '$albumID';";
$result = mysql_query($query);
$query = "DELETE FROM lychee_albums WHERE id = '$albumID';";
$result = $database->query($query);
if(!$result) return false;
}
if($error) return false;
return true;
}
function getAlbumArchive($albumID) {
global $database;
switch($albumID) {
case 's':
$query = "SELECT * FROM photos WHERE public = '1';";
$query = "SELECT * FROM lychee_photos WHERE public = '1';";
$zipTitle = "Public";
break;
case 'f':
$query = "SELECT * FROM photos WHERE star = '1';";
$query = "SELECT * FROM lychee_photos WHERE star = '1';";
$zipTitle = "Starred";
break;
default:
$query = "SELECT * FROM photos WHERE album = '$albumID';";
$query = "SELECT * FROM lychee_photos WHERE album = '$albumID';";
$zipTitle = "Unsorted";
}
$result = mysql_query($query);
$result = $database->query($query);
$files = array();
$i=0;
while($row = mysql_fetch_object($result)) {
while($row = $result->fetch_object()) {
$files[$i] = "../".$row->url;
$i++;
}
$query = "SELECT * FROM albums WHERE id = '$albumID';";
$result = mysql_query($query);
$row = mysql_fetch_object($result);
$query = "SELECT * FROM lychee_albums WHERE id = '$albumID';";
$result = $database->query($query);
$row = $result->fetch_object();
if($albumID!=0&&is_numeric($albumID))$zipTitle = $row->title;
$filename = "./".$zipTitle.".zip";
@ -390,17 +426,18 @@ function getAlbumArchive($albumID) {
// Photo Functions
function getPhotos($albumID) {
global $database;
switch($albumID) {
case "f": $query = "SELECT * FROM photos WHERE star = 1 ORDER BY id DESC;";
case "f": $query = "SELECT * FROM lychee_photos WHERE star = 1 ORDER BY id DESC;";
break;
case "s": $query = "SELECT * FROM photos WHERE public = 1 ORDER BY id DESC;";
case "s": $query = "SELECT * FROM lychee_photos WHERE public = 1 ORDER BY id DESC;";
break;
default: $query = "SELECT * FROM photos WHERE album = '$albumID' ORDER BY id DESC;";
default: $query = "SELECT * FROM lychee_photos WHERE album = '$albumID' ORDER BY id DESC;";
}
$result = mysql_query($query);
$result = $database->query($query);
$return = array(array());
$i = 0;
while($row = mysql_fetch_array($result)) {
while($row = $result->fetch_array()) {
$return[$i] = $row;
$i++;
}
@ -408,15 +445,30 @@ function getPhotos($albumID) {
return $return;
}
function getPhotoInfo($photoID) {
$query = "SELECT * FROM photos WHERE id = '$photoID';";
$result = mysql_query($query);
$return = mysql_fetch_array($result);
global $database;
if(!is_numeric($photoID)) {
$query = "SELECT COUNT(*) AS quantity FROM lychee_photos WHERE import_name = '../uploads/import/$photoID';";
$result = $database->query($query);
$row = $result->fetch_object();
if($row->quantity == 0) {
importPhoto($photoID);
}
if(is_file("../uploads/import/$photoID")) {
importPhoto($photoID);
}
$query = "SELECT * FROM lychee_photos WHERE import_name = '../uploads/import/$photoID' ORDER BY ID DESC;";
} else {
$query = "SELECT * FROM lychee_photos WHERE id = '$photoID';";
}
$result = $database->query($query);
$return = $result->fetch_array();
return $return;
}
function downloadPhoto($photoID) {
$query = "SELECT * FROM photos WHERE id = '$photoID';";
$result = mysql_query($query);
$row = mysql_fetch_object($result);
global $database;
$query = "SELECT * FROM lychee_photos WHERE id = '$photoID';";
$result = $database->query($query);
$row = $result->fetch_object();
$photo = "../".$row->url;
$title = $row->title;
@ -437,20 +489,23 @@ function downloadPhoto($photoID) {
return true;
}
function countPhotos() {
$query = "SELECT COUNT(*) AS num FROM photos;";
$result = mysql_query($query);
$row = mysql_fetch_object($result);
global $database;
$query = "SELECT COUNT(*) AS num FROM lychee_photos;";
$result = $database->query($query);
$row = $result->fetch_object();
return $row->num;
}
function setPhotoPublic($photoID, $url) {
$query = "SELECT public, shortlink FROM photos WHERE id = '$photoID';";
$row = mysql_fetch_object(mysql_query($query));
global $database;
$query = "SELECT public, shortlink FROM lychee_photos WHERE id = '$photoID';";
$result = $database->query($query);
$row = $result->fetch_object();
if($row->public == 0){
$public = 1;
}else{
$public = 0;
}
if(preg_match('/localhost/', $_SERVER['HTTP_REFERER'])) {
if($public==0 || preg_match('/localhost/', $_SERVER['HTTP_REFERER']) || preg_match('\file:\/\/\/', $_SERVER['HTTP_REFERER'])) {
$shortlink = "";
}else{
if($row->shortlink==""){
@ -459,108 +514,132 @@ function setPhotoPublic($photoID, $url) {
$shortlink = $row->shortlink;
}
}
$query = "UPDATE photos SET public = '$public', shortlink = '$shortlink' WHERE id = '$photoID';";
$result = mysql_query($query);
$query = "UPDATE lychee_photos SET public = '$public', shortlink = '$shortlink' WHERE id = '$photoID';";
$result = $database->query($query);
if(!$result) return false;
return true;
}
function setPhotoStar($photoID) {
$query = "SELECT star FROM photos WHERE id = '$photoID';";
$row = mysql_fetch_object(mysql_query($query));
global $database;
$query = "SELECT star FROM lychee_photos WHERE id = '$photoID';";
$result = $database->query($query);
$row = $result->fetch_object();
if($row->star == 0) {
$star = 1;
} else {
$star = 0;
}
$query = "UPDATE photos SET star = '$star' WHERE id = '$photoID';";
$result = mysql_query($query);
$query = "UPDATE lychee_photos SET star = '$star' WHERE id = '$photoID';";
$result = $database->query($query);
return true;
}
function nextPhoto($photoID, $albumID) {
global $database;
switch($albumID) {
case 'f': $query = "SELECT * FROM photos WHERE id < '$photoID' AND star = '1' ORDER BY id DESC LIMIT 0, 1;";
case 'f': $query = "SELECT * FROM lychee_photos WHERE id < '$photoID' AND star = '1' ORDER BY id DESC LIMIT 0, 1;";
break;
case 's': $query = "SELECT * FROM photos WHERE id < '$photoID' AND public = '1' ORDER BY id DESC LIMIT 0, 1;";
case 's': $query = "SELECT * FROM lychee_photos WHERE id < '$photoID' AND public = '1' ORDER BY id DESC LIMIT 0, 1;";
break;
default: $query = "SELECT * FROM photos WHERE id < '$photoID' AND album = '$albumID' ORDER BY id DESC LIMIT 0, 1;";
default: $query = "SELECT * FROM lychee_photos WHERE id < '$photoID' AND album = '$albumID' ORDER BY id DESC LIMIT 0, 1;";
}
$result = mysql_query($query);
$return = mysql_fetch_array($result);
$result = $database->query($query);
$return = $result->fetch_array();
if(!$return || ($return==0)) {
switch($albumID) {
case 'f': $query = "SELECT * FROM photos WHERE star = '1' ORDER BY id DESC LIMIT 0, 1;";
case 'f': $query = "SELECT * FROM lychee_photos WHERE star = '1' ORDER BY id DESC LIMIT 0, 1;";
break;
case 's': $query = "SELECT * FROM photos WHERE public = '1' ORDER BY id DESC LIMIT 0, 1;";
case 's': $query = "SELECT * FROM lychee_photos WHERE public = '1' ORDER BY id DESC LIMIT 0, 1;";
break;
default: $query = "SELECT * FROM photos WHERE album = '$albumID' ORDER BY id DESC LIMIT 0, 1;";
default: $query = "SELECT * FROM lychee_photos WHERE album = '$albumID' ORDER BY id DESC LIMIT 0, 1;";
}
$result = mysql_query($query);
$return = mysql_fetch_array($result);
$result = $database->query($query);
$return = $result->fetch_array();
}
return $return;
}
function previousPhoto($photoID, $albumID) {
global $database;
switch($albumID) {
case 'f': $query = "SELECT * FROM photos WHERE id > '$photoID' AND star = '1' LIMIT 0, 1;";
case 'f': $query = "SELECT * FROM lychee_photos WHERE id > '$photoID' AND star = '1' LIMIT 0, 1;";
break;
case 's': $query = "SELECT * FROM photos WHERE id > '$photoID' AND public = '1' LIMIT 0, 1;";
case 's': $query = "SELECT * FROM lychee_photos WHERE id > '$photoID' AND public = '1' LIMIT 0, 1;";
break;
default: $query = "SELECT * FROM photos WHERE id > '$photoID' AND album = '$albumID' LIMIT 0, 1;";
default: $query = "SELECT * FROM lychee_photos WHERE id > '$photoID' AND album = '$albumID' LIMIT 0, 1;";
}
$result = mysql_query($query);
$return = mysql_fetch_array($result);
$result = $database->query($query);
$return = $result->fetch_array();
if(!$return || ($return==0)) {
switch($albumID) {
case 'f': $query = "SELECT * FROM photos WHERE star = '1' ORDER BY id LIMIT 0, 1;";
case 'f': $query = "SELECT * FROM lychee_photos WHERE star = '1' ORDER BY id LIMIT 0, 1;";
break;
case 's': $query = "SELECT * FROM photos WHERE public = '1' ORDER BY id LIMIT 0, 1;";
case 's': $query = "SELECT * FROM lychee_photos WHERE public = '1' ORDER BY id LIMIT 0, 1;";
break;
default: $query = "SELECT * FROM photos WHERE album = '$albumID' ORDER BY id LIMIT 0, 1;";
default: $query = "SELECT * FROM lychee_photos WHERE album = '$albumID' ORDER BY id LIMIT 0, 1;";
}
$result = mysql_query($query);
$return = mysql_fetch_array($result);
$result = $database->query($query);
$return = $result->fetch_array();
}
return $return;
}
function movePhoto($photoID, $newAlbum) {
$query = "UPDATE photos SET album = '$newAlbum' WHERE id = '$photoID';";
$result = mysql_query($query);
global $database;
$query = "UPDATE lychee_photos SET album = '$newAlbum' WHERE id = '$photoID';";
$result = $database->query($query);
if(!$result) return false;
else return true;
}
function setPhotoTitle($photoID, $title) {
$title = mysql_real_escape_string(urldecode($title));
global $database;
$title = mysqli_real_escape_string($database, urldecode($title));
if(strlen($title)>30) return false;
$query = "UPDATE photos SET title = '$title' WHERE id = '$photoID';";
$result = mysql_query($query);
$query = "UPDATE lychee_photos SET title = '$title' WHERE id = '$photoID';";
$result = $database->query($query);
if(!$result) return false;
else return true;
}
function setPhotoDescription($photoID, $description) {
$description = mysql_real_escape_string(htmlentities($description));
global $database;
$description = mysqli_real_escape_string($database, htmlentities($description));
if(strlen($description)>160) return false;
$query = "UPDATE photos SET description = '$description' WHERE id = '$photoID';";
$result = mysql_query($query);
$query = "UPDATE lychee_photos SET description = '$description' WHERE id = '$photoID';";
$result = $database->query($query);
if(!$result) return false;
return true;
}
function deletePhoto($photoID) {
$query = "SELECT * FROM photos WHERE id = '$photoID';";
$result = mysql_query($query);
global $database;
$query = "SELECT * FROM lychee_photos WHERE id = '$photoID';";
$result = $database->query($query);
if(!$result) return false;
$row = mysql_fetch_object($result);
$row = $result->fetch_object();
$retinaUrl = explode(".", $row->thumbUrl);
$unlink1 = unlink("../".$row->url);
$unlink2 = unlink("../".$row->thumbUrl);
if(!$unlink1 || !$unlink2) return false;
$query = "DELETE FROM photos WHERE id = '$photoID';";
$result = mysql_query($query);
$unlink3 = unlink("../".$retinaUrl[0].'@2x.'.$retinaUrl[1]);
$query = "DELETE FROM lychee_photos WHERE id = '$photoID';";
$result = $database->query($query);
if(!$unlink1 || !$unlink2 || !$unlink3) return false;
if(!$result) return false;
return true;
}
function importPhoto($name) {
global $database;
$tmp_name = "../uploads/import/$name";
$details = getimagesize($tmp_name);
$size = filesize($tmp_name);
$nameFile = array(array());
$nameFile[0]['name'] = $name;
$nameFile[0]['type'] = $details['mime'];
$nameFile[0]['tmp_name'] = $tmp_name;
$nameFile[0]['error'] = 0;
$nameFile[0]['size'] = $size;
if(!upload($nameFile, 's')) return false;
else return true;
}
// Share Functions
function urlShortner($url) {
global $bitlyUsername, $bitlyApi;
global $database, $bitlyUsername, $bitlyApi;
if($bitlyUsername==""||$bitlyApi=="") return false;
$url = urlencode($url);
$bitlyAPI = "http://api.bit.ly/shorten?version=2.0.1&format=xml&longUrl=$url&login=$bitlyUsername&apiKey=$bitlyApi";
@ -572,9 +651,10 @@ function urlShortner($url) {
return $shortlink;
}
function sharePhoto($photoID, $url) {
$query = "SELECT * FROM photos WHERE id = '$photoID'";
$result = mysql_query($query);
$row = mysql_fetch_object($result);
global $database;
$query = "SELECT * FROM lychee_photos WHERE id = '$photoID';";
$result = $database->query($query);
$row = $result->fetch_object();
$thumb = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']."/../../".$row->thumbUrl;
$title = $row->title;
@ -583,8 +663,6 @@ function sharePhoto($photoID, $url) {
$twitterUrl = "https://twitter.com/share?url=".urlencode("$url");
$facebookUrl = "http://www.facebook.com/sharer.php?u=".urlencode("$url")."&t=".urlencode($title);
$tumblrUrl = "http://www.tumblr.com/share/link?url=".urlencode("$url")."&name=". urlencode($title)."&description=".urlencode($description);
$pinterestUrl = "http://pinterest.com/pin/create/button/?url=".urlencode("$url")."&media=".urlencode($thumb);
$mailUrl = "mailto:?subject=".rawurlencode($title)."&body=".rawurlencode("Hey guy! Check this out: $url");
$share = array();
@ -598,11 +676,11 @@ function sharePhoto($photoID, $url) {
return $share;
}
function facebookHeader($photoID) {
$database = dbConnect();
if(!is_numeric($photoID)) return false;
dbConnect();
$query = "SELECT * FROM photos WHERE id = '$photoID';";
$result = mysql_query($query);
$row = mysql_fetch_object($result);
$query = "SELECT * FROM lychee_photos WHERE id = '$photoID';";
$result = $database->query($query);
$row = $result->fetch_object();
$parseUrl = parse_url("http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
$thumb = $parseUrl['scheme']."://".$parseUrl['host'].$parseUrl['path']."/../".$row->thumbUrl;
@ -614,37 +692,47 @@ function facebookHeader($photoID) {
return $return;
}
function isPhotoPublic($photoID) {
$query = "SELECT * FROM photos WHERE id = '$photoID';";
$result = mysql_query($query);
$row = mysql_fetch_object($result);
if($row->public == 1) return true;
return false;
global $database;
$photoID = mysqli_real_escape_string($database, $photoID);
if(is_numeric($photoID)) {
$query = "SELECT * FROM lychee_photos WHERE id = '$photoID';";
} else {
$query = "SELECT * FROM lychee_photos WHERE import_name = '../uploads/import/$photoID';";
}
$result = $database->query($query);
$row = $result->fetch_object();
if (!is_numeric($photoID)&&!$row) return true;
if($row->public == 1) {
return true;
} else {
return false;
}
}
// Search Function
function search($term) {
$term = mysql_real_escape_string($term);
global $database;
$term = mysqli_real_escape_string($database, $term);
$query = "SELECT * FROM photos WHERE title like '%$term%' OR description like '%$term%';";
$result = mysql_query($query);
while($row = mysql_fetch_array($result)) {
$query = "SELECT * FROM lychee_photos WHERE title like '%$term%' OR description like '%$term%';";
$result = $database->query($query);
while($row = $result->fetch_array()) {
$return['photos'][] = $row;
}
$query = "SELECT * FROM albums WHERE title like '%$term%';";
$result = mysql_query($query);
$query = "SELECT * FROM lychee_albums WHERE title like '%$term%';";
$result = $database->query($query);
$i=0;
while($row = mysql_fetch_array($result)) {
while($row = $result->fetch_array()) {
$return['albums'][$i] = $row;
$query = "SELECT thumbUrl FROM photos WHERE album = '".$row['id']."' ORDER BY id DESC LIMIT 0, 3;";
$result2 = mysql_query($query);
$query2 = "SELECT thumbUrl FROM lychee_photos WHERE album = '".$row['id']."' ORDER BY id DESC LIMIT 0, 3;";
$result2 = $database->query($query2);
$k = 0;
while($row2 = mysql_fetch_object($result2)){
while($row2 = $result2->fetch_object()){
$return['albums'][$i]["thumb$k"] = $row2->thumbUrl;
$k++;
}
$i++;
}
return $return;
}

@ -27,7 +27,7 @@ To use Lychee without restrictions, we recommend to increase the values of the f
Change the permissions of `/lychee/uploads` to 777, including all subfolders:
chmod -R 777 /lychee/uploads
chmod -R 777 lychee/uploads/
#### Lychee configuration `lychee/php/config.php`
@ -40,8 +40,8 @@ Your photos are protected by a username and password you need to set:
$user = Your username for Lychee
$password = Your password for Lychee
Optional configuration:
This settings are optional and doesn't need to be changed:
$thumbQuality = Photo thumbs quality
-> Less means a inferiority quality of your thumbs, but faster loading
@ -52,14 +52,41 @@ Optional configuration:
## How to use
After the configuration navigate your browser to the place where Lychee is located. Everything should work now. If not, check the logs and try to fix the error.
After the configuration, navigate your browser to the place where Lychee is located. Everything should work now. If not, try the installation again.
### FTP Upload
You can upload and share photos directly from every FTP client with Lychee. To do so, upload images to `uploads/import/` and navigate your browser to the place where Lychee is located (e.g. `http://example.com/view.php?p=filename.png`). `filename.png` must be replaced by the filename of your uploaded file. [Sample configuration](http://lychee.electerious.com/view.php?p=13657692738813).
### Keyboard Shortcuts
######Everywhere
`n` New album/photo
`u` Upload photo
`esc` Close/Back
######Photoview
`s` Star photo
`i` Show information
`f` Show photo in new tab
`backspace` Delete photo
`left` Previous photo
`right` Next photo
## Browser Support
Lychee supports the latest versions of Google Chrome, Apple Safari and Mozilla Firefox. Photos you share with others can be viewed from every browser.
## About
Lychee is made by [Tobias Reich](http://electerious.com) (HTML, CSS, JS, Design, Website Design and Development) with the help of [Philipp Maurer](http://phinal.net) (PHP, MySQL).
##License
(MIT License)
Copyright (C) 2012 [Tobias Reich](http://electerious.com)
Copyright (C) 2012 [Philipp Maurer](http://phinal.net)
Copyright (C) 2013 [Tobias Reich](http://electerious.com)
Copyright (C) 2013 [Philipp Maurer](http://phinal.net)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

@ -1,4 +1,3 @@
<?php require_once("php/functions.php"); ?>
<!DOCTYPE HTML>
<html>
<head>
@ -19,22 +18,32 @@
<meta name="viewport" content="user-scalable=no, initial-scale=1">
<meta name="apple-mobile-web-app-capable" content="yes">
<?php if(isset($_GET['p'])) echo facebookHeader($_GET['p']); ?>
<?php
if(isset($_GET['p'])) {
define("LYCHEE", true);
include("php/config.php");
include("php/functions.php");
echo facebookHeader($_GET['p']);
}
?>
</head>
<body>
<!-- Loading -->
<div id="loading"></div>
<!-- Header -->
<header>
<!-- Buttons -->
<div class="tools" id="button_download" title="Download Photo"><a class="icon-download"></a></div>
<div class="tools" id="button_download" title="Full Photo"><a class="icon-resize-full"></a></div>
<div class="tools" id="button_info" title="Show Info"><a class="icon-info-sign"></a></div>
<a id="title"></a>
<a id="title" class="view"></a>
</header>
@ -46,7 +55,7 @@
<!-- JS -->
<script type="text/javascript" src="js/frameworks.js"></script>
<script type="text/javascript" src="js/build.js"></script>
<script type="text/javascript" src="js/modules/build.js"></script>
<script type="text/javascript" src="js/view.js"></script>

Loading…
Cancel
Save