Merge pull request #169 from electerious/v2.5
v2.5 - `New` Swipe gestures on mobile devices - `New` Plugin-System - `New` Rewritten Back-End - `New` Support for ImageMagick (thanks @bb-Ricardo) - `New` Logging-System - `New` Blowfish hash instead of MD5 for all new passwords (thanks @bb-Ricardo) - `New` Compile Lychee using Grunt (with npm and bower) - `New` Open full photo without making the photo public - `Improved` Shortcuts - `Improved` Album share dialog - `Improved` Database update mechanism - `Improved` Download photos with correct title (thanks @bb-Ricardo) - `Improved` EXIF parsing - `Improved` URL and Server import (thanks @djdallmann) - `Improved` Check permissions on upload - `Fixed` Wrong capture date in Infobox - `Fixed` Sorting by takedate
This commit is contained in:
commit
b0d4054d13
3
.gitignore
vendored
3
.gitignore
vendored
@ -8,8 +8,9 @@ uploads/import/*
|
||||
uploads/big/*
|
||||
uploads/thumb/*
|
||||
plugins/*
|
||||
etc/*
|
||||
|
||||
!uploads/import/index.html
|
||||
!uploads/big/index.html
|
||||
!uploads/thumb/index.html
|
||||
!plugins/check.php
|
||||
!plugins/check/
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -116,7 +116,7 @@
|
||||
background: -ms-linear-gradient(top, rgba(0,0,0,0) 0%,rgba(0,0,0,0) 20%,rgba(0,0,0,0.9) 100%); /* IE10+ */
|
||||
background: linear-gradient(top, rgba(0,0,0,0) 0%,rgba(0,0,0,0) 20%,rgba(0,0,0,0.9) 100%); /* W3C */
|
||||
}
|
||||
.photo .overlay {
|
||||
.photo .overlay {
|
||||
background: -moz-linear-gradient(top, rgba(0,0,0,0) 0%, rgba(0,0,0,0) 60%, rgba(0,0,0,0.5) 80%, rgba(0,0,0,0.9) 100%); /* FF3.6+ */
|
||||
background: -webkit-linear-gradient(top, rgba(0,0,0,0) 0%, rgba(0,0,0,0) 60%, rgba(0,0,0,0.5) 80%, rgba(0,0,0,0.9) 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -ms-linear-gradient(top, rgba(0,0,0,0) 0%, rgba(0,0,0,0) 60%, rgba(0,0,0,0.5) 80%, rgba(0,0,0,0.9) 100%); /* IE10+ */
|
||||
@ -130,7 +130,7 @@
|
||||
.album .overlay h1,
|
||||
.photo .overlay h1 {
|
||||
min-height: 19px;
|
||||
width: 190px;
|
||||
width: 185px;
|
||||
margin: 153px 0px 3px 15px;
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
@ -156,13 +156,13 @@
|
||||
margin-top: -1px;
|
||||
margin-left: 12px;
|
||||
padding: 12px 7px 3px 7px;
|
||||
box-shadow: 0px 0px 3px #000;
|
||||
box-shadow: 0px 0px 3px rgba(0, 0, 0, .8);
|
||||
border-radius: 0px 0px 3px 3px;
|
||||
border: 1px solid #fff;
|
||||
border-top: none;
|
||||
color: #fff;
|
||||
font-size: 24px;
|
||||
text-shadow: 0px 1px 0px #000;
|
||||
text-shadow: 0px 1px 0px rgba(0, 0, 0, .4);
|
||||
opacity: .9;
|
||||
}
|
||||
.album .badge.icon-star,
|
||||
@ -236,7 +236,7 @@
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
text-shadow: 0px -1px 0px #000;
|
||||
text-shadow: 0px -1px 0px rgba(0, 0, 0, .8);
|
||||
}
|
||||
|
||||
/* No Content ------------------------------------------------*/
|
||||
|
@ -15,15 +15,15 @@
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
padding: 5px 0px 6px 0px;
|
||||
background-color: #393939;
|
||||
background-image: -webkit-linear-gradient(top, #444, #2d2d2d);
|
||||
background-image: -moz-linear-gradient(top, #393939, #2d2d2d);
|
||||
background-image: -ms-linear-gradient(top, #393939, #2d2d2d);
|
||||
background-image: linear-gradient(top, #393939, #2d2d2d);
|
||||
border: 1px solid rgba(0,0,0,0.7);
|
||||
border-bottom: 1px solid rgba(0,0,0,.9);
|
||||
background-color: #444;
|
||||
background-image: -webkit-linear-gradient(top, #444, #2f2f2f);
|
||||
background-image: -moz-linear-gradient(top, #444, #2f2f2f);
|
||||
background-image: -ms-linear-gradient(top, #444, #2f2f2f);
|
||||
background-image: linear-gradient(top, #444, #2f2f2f);
|
||||
border: 1px solid rgba(0,0,0,0.5);
|
||||
border-bottom: 1px solid rgba(0,0,0,.7);
|
||||
border-radius: 5px;
|
||||
box-shadow: 0px 4px 5px rgba(0,0,0,0.3), inset 0px 1px 0px rgba(255,255,255,0.15), inset 1px 0px 0px rgba(255,255,255,0.05), inset -1px 0px 0px rgba(255,255,255,0.05);
|
||||
box-shadow: 0px 3px 4px rgba(0,0,0,0.25), inset 0px 1px 0px rgba(255,255,255, .1);
|
||||
opacity: 0;
|
||||
z-index: 1001;
|
||||
|
||||
@ -36,15 +36,15 @@
|
||||
.contextmenu tr {
|
||||
font-size: 14px;
|
||||
color: #eee;
|
||||
text-shadow: 0px -1px 0px rgba(0,0,0,.6);
|
||||
text-shadow: 0px -1px 0px rgba(0,0,0,.2);
|
||||
cursor: pointer;
|
||||
}
|
||||
.contextmenu tr:hover {
|
||||
background-color: #6a84f2;
|
||||
background-image: -webkit-linear-gradient(top, #6a84f2, #3959ef);
|
||||
background-image: -moz-linear-gradient(top, #6a84f2, #3959ef);
|
||||
background-image: -ms-linear-gradient(top, #6a84f2, #3959ef);
|
||||
background-image: linear-gradient(top, #6a84f2, #3959ef);
|
||||
background-image: -webkit-linear-gradient(top, #6a84f2, #4967F0);
|
||||
background-image: -moz-linear-gradient(top, #6a84f2, #4967F0);
|
||||
background-image: -ms-linear-gradient(top, #6a84f2, #4967F0);
|
||||
background-image: linear-gradient(top, #6a84f2, #4967F0);
|
||||
}
|
||||
.contextmenu tr.no_hover:hover {
|
||||
cursor: inherit;
|
||||
@ -55,8 +55,8 @@
|
||||
float: left;
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
background-color: #1c1c1c;
|
||||
border-bottom: 1px solid #4a4a4a;
|
||||
background-color: #1f1f1f;
|
||||
border-bottom: 1px solid #4c4c4c;
|
||||
margin: 5px 0px;
|
||||
cursor: inherit;
|
||||
}
|
||||
@ -74,7 +74,7 @@
|
||||
.contextmenu tr:hover td {
|
||||
color: #fff;
|
||||
box-shadow: inset 0px 1px 0px rgba(255,255,255,.05);
|
||||
text-shadow: 0px -1px 0px rgba(0,0,0,.4);
|
||||
text-shadow: 0px -1px 0px rgba(0,0,0,.2);
|
||||
}
|
||||
.contextmenu tr.no_hover:hover td {
|
||||
box-shadow: none;
|
||||
@ -90,13 +90,13 @@
|
||||
.contextmenu #link {
|
||||
float: right;
|
||||
width: 140px;
|
||||
margin: 0px -17px -1px 0px;
|
||||
padding: 4px 6px 5px 6px;
|
||||
margin: -1px -18px -2px -1px;
|
||||
padding: 5px 7px 6px 7px;
|
||||
background-color: #444;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border: 1px solid #111;
|
||||
box-shadow: 0px 1px 0px rgba(255,255,255,.1);
|
||||
border: 1px solid rgba(0, 0, 0, .5);
|
||||
box-shadow: 0px 1px 0px rgba(255,255,255,.08);
|
||||
outline: none;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
display: none;
|
||||
width: 100%;
|
||||
min-height: 100%;
|
||||
background-color: rgba(10,10,10,.99);
|
||||
background-color: rgba(10,10,10,.98);
|
||||
|
||||
-webkit-transition: background-color .3s;
|
||||
}
|
||||
@ -19,7 +19,7 @@
|
||||
background-color: inherit;
|
||||
}
|
||||
#imageview.full {
|
||||
background-color: #040404;
|
||||
background-color: rgba(0,0,0,1);
|
||||
}
|
||||
|
||||
/* ImageView ------------------------------------------------*/
|
||||
@ -33,7 +33,9 @@
|
||||
background-position: 50% 50%;
|
||||
background-size: contain;
|
||||
|
||||
-webkit-transition: top .3s, bottom .3s, margin-top .3s;
|
||||
-webkit-transition: top .3s, right .3s, bottom .3s, left .3s, margin-top .3s, opacity .2s, -webkit-transform .3s cubic-bezier(0.51,.92,.24,1.15);
|
||||
-moz-transition: top .3s, right .3s, bottom .3s, left .3s, margin-top .3s, opacity .2s, -moz-transform .3s cubic-bezier(0.51,.92,.24,1.15);
|
||||
transition: top .3s, right .3s, bottom .3s, left .3s, margin-top .3s, opacity .2s, transform .3s cubic-bezier(0.51,.92,.24,1.15);
|
||||
|
||||
-webkit-animation-name: zoomIn;
|
||||
-webkit-animation-duration: .3s;
|
||||
@ -45,12 +47,18 @@
|
||||
animation-duration: .3s;
|
||||
animation-timing-function: cubic-bezier(0.51,.92,.24,1.15);
|
||||
}
|
||||
#imageview #image.small {
|
||||
top: 50%;
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
left: 50%;
|
||||
}
|
||||
#imageview #image.small {
|
||||
top: 50%;
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
left: 50%;
|
||||
}
|
||||
#imageview #image.full {
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
}
|
||||
|
||||
/* Previous/Next Buttons ------------------------------------------------*/
|
||||
#imageview .arrow_wrapper {
|
||||
|
@ -11,7 +11,7 @@
|
||||
height: 100%;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
background-color: rgba(0,0,0,.85);
|
||||
background-color: rgba(0,0,0,.8);
|
||||
}
|
||||
#infobox {
|
||||
z-index: 4;
|
||||
@ -77,7 +77,7 @@
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
text-shadow: 0px -1px 0px #000;
|
||||
text-shadow: 0px -1px 0px rgba(0, 0, 0, .8);
|
||||
}
|
||||
#infobox .header a {
|
||||
float: right;
|
||||
@ -85,7 +85,7 @@
|
||||
color: #fff;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
text-shadow: 0px -1px 0px #000;
|
||||
text-shadow: 0px -1px 0px rgba(0, 0, 0, .8);
|
||||
opacity: .5;
|
||||
cursor: pointer;
|
||||
}
|
||||
@ -105,7 +105,7 @@
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
text-shadow: 0px -1px 0px #000;
|
||||
text-shadow: 0px -1px 0px rgba(0, 0, 0, .8);
|
||||
}
|
||||
|
||||
/* Table ------------------------------------------------*/
|
||||
|
@ -45,7 +45,7 @@
|
||||
|
||||
/* Content ------------------------------------------------*/
|
||||
#loading h1 {
|
||||
margin: 13px;
|
||||
margin: 13px 13px 0px 13px;
|
||||
color: #ddd;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
|
@ -45,6 +45,10 @@
|
||||
margin: 40px 0px 0px 50px !important;
|
||||
}
|
||||
|
||||
#imageview .arrow_wrapper {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.message {
|
||||
position: fixed !important;
|
||||
width: 100% !important;
|
||||
@ -57,7 +61,7 @@
|
||||
-moz-animation: moveUp .3s !important;
|
||||
animation: moveUp .3s !important;
|
||||
}
|
||||
|
||||
|
||||
.upload_message {
|
||||
top: 50% !important;
|
||||
left: 50% !important;
|
||||
|
@ -25,7 +25,7 @@
|
||||
background-image: -ms-linear-gradient(top, rgb(75, 75, 75), rgb(45, 45, 45));
|
||||
background-image: linear-gradient(top, rgb(75, 75, 75), rgb(45, 45, 45));
|
||||
border-radius: 5px;
|
||||
box-shadow: 0px 0px 5px #000, inset 0px 1px 0px rgba(255,255,255,.08), inset 1px 0px 0px rgba(255,255,255,.03), inset -1px 0px 0px rgba(255,255,255,.03);
|
||||
box-shadow: 0px 0px 5px #000, inset 0px 1px 0px rgba(255,255,255,.08);
|
||||
|
||||
/* Animation */
|
||||
-webkit-animation-name: moveUp;
|
||||
@ -47,7 +47,7 @@
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
text-shadow: 0px -1px 0px #222;
|
||||
text-shadow: 0px -1px 0px rgba(0, 0, 0, .3);
|
||||
text-align: center;
|
||||
}
|
||||
.message .close {
|
||||
@ -57,7 +57,7 @@
|
||||
padding: 12px 14px 6px 7px;
|
||||
color: #aaa;
|
||||
font-size: 20px;
|
||||
text-shadow: 0px -1px 0px #222;
|
||||
text-shadow: 0px -1px 0px rgba(0, 0, 0, .3);
|
||||
cursor: pointer;
|
||||
}
|
||||
.message .close:hover {
|
||||
@ -72,7 +72,7 @@
|
||||
padding: 12px 5% 15px 5%;
|
||||
color: #eee;
|
||||
font-size: 14px;
|
||||
text-shadow: 0px -1px 0px #222;
|
||||
text-shadow: 0px -1px 0px rgba(0, 0, 0, .3);
|
||||
line-height: 20px;
|
||||
}
|
||||
.message p b {
|
||||
@ -88,20 +88,15 @@
|
||||
.message .button {
|
||||
float: right;
|
||||
margin: 15px 15px 15px 0px;
|
||||
padding: 6px 10px 8px 10px;
|
||||
background-color: #4e4e4e;
|
||||
background-image: -webkit-linear-gradient(top, rgb(60, 60, 60), rgb(45, 45, 45));
|
||||
background-image: -moz-linear-gradient(top, rgb(60, 60, 60), rgb(45, 45, 45));
|
||||
background-image: -ms-linear-gradient(top, rgb(60, 60, 60), rgb(45, 45, 45));
|
||||
background-image: linear-gradient(top, rgb(60, 60, 60), rgb(45, 45, 45));
|
||||
padding: 7px 10px 8px 10px;
|
||||
color: #ccc;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
text-shadow: 0px -1px 0px #222;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #191919;
|
||||
box-shadow: inset 0px 1px 0px rgba(255,255,255,.1), 0px 1px 0px rgba(255,255,255,.1);
|
||||
border: 1px solid rgba(0,0,0,.4);
|
||||
box-shadow: inset 0px 1px 0px rgba(255,255,255,.08), 0px 1px 0px rgba(255,255,255,.05);
|
||||
cursor: pointer;
|
||||
}
|
||||
.message .button:first-of-type {
|
||||
@ -109,22 +104,22 @@
|
||||
}
|
||||
.message .button.active {
|
||||
color: #fff;
|
||||
box-shadow: inset 0px 1px 0px rgba(255,255,255,.1), 0px 1px 0px rgba(255,255,255,.1), 0px 0px 4px #005ecc;
|
||||
box-shadow: inset 0px 1px 0px rgba(255,255,255,.08), 0px 1px 0px rgba(255,255,255,.1), 0px 0px 4px #005ecc;
|
||||
}
|
||||
.message .button:hover {
|
||||
background-color: #565757;
|
||||
background-image: -webkit-linear-gradient(top, rgb(80, 80, 80), rgb(57, 57, 57));
|
||||
background-image: -moz-linear-gradient(top, rgb(80, 80, 80), rgb(57, 57, 57));
|
||||
background-image: -ms-linear-gradient(top, rgb(80, 80, 80), rgb(57, 57, 57));
|
||||
background-image: linear-gradient(top, rgb(80, 80, 80), rgb(57, 57, 57));
|
||||
background-image: -webkit-linear-gradient(top, rgb(60, 60, 60), rgb(57, 57, 57));
|
||||
background-image: -moz-linear-gradient(top, rgb(60, 60, 60), rgb(57, 57, 57));
|
||||
background-image: -ms-linear-gradient(top, rgb(60, 60, 60), rgb(57, 57, 57));
|
||||
background-image: linear-gradient(top, rgb(60, 60, 60), rgb(57, 57, 57));
|
||||
}
|
||||
.message .button:active,
|
||||
.message .button.pressed {
|
||||
background-color: #393939;
|
||||
background-image: -webkit-linear-gradient(top, rgb(57, 57, 57), rgb(70, 70, 70));
|
||||
background-image: -moz-linear-gradient(top, rgb(57, 57, 57), rgb(70, 70, 70));
|
||||
background-image: -ms-linear-gradient(top, rgb(57, 57, 57), rgb(70, 70, 70));
|
||||
background-image: linear-gradient(top, rgb(57, 57, 57), rgb(70, 70, 70));
|
||||
background-image: -webkit-linear-gradient(top, rgb(57, 57, 57), rgb(60, 60, 60));
|
||||
background-image: -moz-linear-gradient(top, rgb(57, 57, 57), rgb(60, 60, 60));
|
||||
background-image: -ms-linear-gradient(top, rgb(57, 57, 57), rgb(60, 60, 60));
|
||||
background-image: linear-gradient(top, rgb(57, 57, 57), rgb(60, 60, 60));
|
||||
}
|
||||
|
||||
/* Sign in ------------------------------------------------*/
|
||||
@ -195,4 +190,35 @@
|
||||
}
|
||||
.message .copylink {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Radio Buttons ------------------------------------------------*/
|
||||
.message .choice {
|
||||
float: left;
|
||||
padding: 12px 5% 15px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.message .choice input {
|
||||
float: left;
|
||||
}
|
||||
.message .choice h2 {
|
||||
float: left;
|
||||
margin: 1px 0px 0px 8px;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, .3);
|
||||
}
|
||||
.message .choice p {
|
||||
margin-top: 2px;
|
||||
padding: 0px 5% 0px 25px;
|
||||
color: #aaa;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.message .choice p input {
|
||||
width: 100%;
|
||||
padding: 10px 1px 9px;
|
||||
margin-top: 10px;
|
||||
}
|
File diff suppressed because one or more lines are too long
108
assets/js/_swipe.jquery.js
Normal file
108
assets/js/_swipe.jquery.js
Normal file
@ -0,0 +1,108 @@
|
||||
(function($) {
|
||||
var Swipe = function(el) {
|
||||
var self = this;
|
||||
|
||||
this.el = $(el);
|
||||
this.pos = { start: { x: 0, y: 0 }, end: { x: 0, y: 0 } };
|
||||
this.startTime;
|
||||
|
||||
el.on('touchstart', function(e) { self.touchStart(e); });
|
||||
el.on('touchmove', function(e) { self.touchMove(e); });
|
||||
el.on('touchend', function(e) { self.swipeEnd(); });
|
||||
el.on('mousedown', function(e) { self.mouseDown(e); });
|
||||
};
|
||||
|
||||
Swipe.prototype = {
|
||||
touchStart: function(e) {
|
||||
var touch = e.originalEvent.touches[0];
|
||||
|
||||
this.swipeStart(e, touch.pageX, touch.pageY);
|
||||
},
|
||||
|
||||
touchMove: function(e) {
|
||||
var touch = e.originalEvent.touches[0];
|
||||
|
||||
this.swipeMove(e, touch.pageX, touch.pageY);
|
||||
},
|
||||
|
||||
mouseDown: function(e) {
|
||||
var self = this;
|
||||
|
||||
this.swipeStart(e, e.pageX, e.pageY);
|
||||
|
||||
this.el.on('mousemove', function(e) { self.mouseMove(e); });
|
||||
this.el.on('mouseup', function() { self.mouseUp(); });
|
||||
},
|
||||
|
||||
mouseMove: function(e) {
|
||||
this.swipeMove(e, e.pageX, e.pageY);
|
||||
},
|
||||
|
||||
mouseUp: function(e) {
|
||||
this.swipeEnd(e);
|
||||
|
||||
this.el.off('mousemove');
|
||||
this.el.off('mouseup');
|
||||
},
|
||||
|
||||
swipeStart: function(e, x, y) {
|
||||
this.pos.start.x = x;
|
||||
this.pos.start.y = y;
|
||||
this.pos.end.x = x;
|
||||
this.pos.end.y = y;
|
||||
|
||||
this.startTime = new Date().getTime();
|
||||
|
||||
this.trigger('swipeStart', e);
|
||||
},
|
||||
|
||||
swipeMove: function(e, x, y) {
|
||||
this.pos.end.x = x;
|
||||
this.pos.end.y = y;
|
||||
|
||||
this.trigger('swipeMove', e);
|
||||
},
|
||||
|
||||
swipeEnd: function(e) {
|
||||
this.trigger('swipeEnd', e);
|
||||
},
|
||||
|
||||
trigger: function(e, originalEvent) {
|
||||
var self = this;
|
||||
|
||||
var
|
||||
event = $.Event(e),
|
||||
x = self.pos.start.x - self.pos.end.x,
|
||||
y = self.pos.end.y - self.pos.start.y,
|
||||
radians = Math.atan2(y, x),
|
||||
direction = 'up',
|
||||
distance = Math.round(Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2))),
|
||||
angle = Math.round(radians * 180 / Math.PI),
|
||||
speed = Math.round(distance / ( new Date().getTime() - self.startTime ) * 1000);
|
||||
|
||||
if ( angle < 0 ) {
|
||||
angle = 360 - Math.abs(angle);
|
||||
}
|
||||
|
||||
if ( ( angle <= 45 && angle >= 0 ) || ( angle <= 360 && angle >= 315 ) ) {
|
||||
direction = 'left';
|
||||
} else if ( angle >= 135 && angle <= 225 ) {
|
||||
direction = 'right';
|
||||
} else if ( angle > 45 && angle < 135 ) {
|
||||
direction = 'down';
|
||||
}
|
||||
|
||||
event.originalEvent = originalEvent;
|
||||
|
||||
event.swipe = { x: x, y: y, direction: direction, distance: distance, angle: angle, speed: speed };
|
||||
|
||||
$(self.el).trigger(event);
|
||||
}
|
||||
};
|
||||
|
||||
$.fn.swipe = function() {
|
||||
var swipe = new Swipe(this);
|
||||
|
||||
return this;
|
||||
};
|
||||
})(jQuery);
|
@ -96,7 +96,8 @@ album = {
|
||||
|
||||
var title,
|
||||
params,
|
||||
buttons;
|
||||
buttons,
|
||||
isNumber = function(n) { return !isNaN(parseFloat(n)) && isFinite(n) };
|
||||
|
||||
buttons = [
|
||||
["Create Album", function() {
|
||||
@ -110,10 +111,10 @@ album = {
|
||||
params = "addAlbum&title=" + escape(encodeURI(title));
|
||||
lychee.api(params, function(data) {
|
||||
|
||||
if (data!==false) {
|
||||
if (data===true) data = 1; // Avoid first album to be true
|
||||
lychee.goto(data);
|
||||
} else lychee.error(null, params, data);
|
||||
if (data===true) data = 1; // Avoid first album to be true
|
||||
|
||||
if (data!==false&&isNumber(data)) lychee.goto(data);
|
||||
else lychee.error(null, params, data);
|
||||
|
||||
});
|
||||
|
||||
@ -206,7 +207,14 @@ album = {
|
||||
buttons = [
|
||||
["Set Title", function() {
|
||||
|
||||
newTitle = ($(".message input.text").val()==="") ? "Untitled" : $(".message input.text").val();
|
||||
// Get input
|
||||
newTitle = $(".message input.text").val();
|
||||
|
||||
// Remove html from input
|
||||
newTitle = lychee.removeHTML(newTitle);
|
||||
|
||||
// Set to Untitled when empty
|
||||
newTitle = (newTitle==="") ? "Untitled" : newTitle;
|
||||
|
||||
if (visible.album()) {
|
||||
|
||||
@ -248,14 +256,18 @@ album = {
|
||||
buttons = [
|
||||
["Set Description", function() {
|
||||
|
||||
// Get input
|
||||
description = $(".message input.text").val();
|
||||
|
||||
// Remove html from input
|
||||
description = lychee.removeHTML(description);
|
||||
|
||||
if (visible.album()) {
|
||||
album.json.description = description;
|
||||
view.album.description();
|
||||
}
|
||||
|
||||
params = "setAlbumDescription&albumID=" + photoID + "&description=" + escape(description);
|
||||
params = "setAlbumDescription&albumID=" + photoID + "&description=" + escape(encodeURI(description));
|
||||
lychee.api(params, function(data) {
|
||||
|
||||
if (data!==true) lychee.error(null, params, data);
|
||||
@ -274,14 +286,29 @@ album = {
|
||||
|
||||
var params;
|
||||
|
||||
if ($(".message input.text").length>0&&$(".message input.text").val().length>0) {
|
||||
if (!visible.message()&&album.json.public==0) {
|
||||
|
||||
params = "setAlbumPublic&albumID=" + albumID + "&password=" + hex_md5($(".message input.text").val());
|
||||
modal.show("Share Album", "This album will be shared with one of the following properties:</p><form><div class='choice'><input type='radio' value='public' name='choice' checked><h2>Public</h2><p>Visible and accessible for everyone.</p></div><div class='choice'><input type='radio' value='password' name='choice'><h2>Password protected</h2><p>Not visible to visitors and only accessible with a valid password.<input class='text' type='password' placeholder='password' value='' style='display: none;'></p></div></form><p style='display: none;'>", [["Share Album", function() { album.setPublic(album.getID(), e) }], ["Cancel", function() {}]], -160);
|
||||
|
||||
$(".message .choice input:radio").on("change", function() {
|
||||
|
||||
if ($(this).val()==="password") $(".message .choice input.text").show();
|
||||
else $(".message .choice input.text").hide();
|
||||
|
||||
});
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
if (visible.message()&&$(".message .choice input:checked").val()==="password") {
|
||||
|
||||
params = "setAlbumPublic&albumID=" + albumID + "&password=" + md5($(".message input.text").val());
|
||||
album.json.password = true;
|
||||
|
||||
} else {
|
||||
|
||||
params = "setAlbumPublic&albumID=" + albumID;
|
||||
params = "setAlbumPublic&albumID=" + albumID + "&password=";
|
||||
album.json.password = false;
|
||||
|
||||
}
|
||||
@ -316,7 +343,7 @@ album = {
|
||||
link = "http://www.facebook.com/sharer.php?u=" + encodeURI(url) + "&t=" + encodeURI(album.json.title);
|
||||
break;
|
||||
case 2:
|
||||
link = "mailto:?subject=" + encodeURI(album.json.title) + "&body=" + encodeURI("Hi! Check this out: " + url);
|
||||
link = "mailto:?subject=" + encodeURI(album.json.title) + "&body=" + encodeURI(url);
|
||||
break;
|
||||
default:
|
||||
link = "";
|
||||
|
@ -114,7 +114,7 @@ build = {
|
||||
if (visibleControls)
|
||||
view += "<div id='image' style='background-image: url(" + photoJSON.url + ")'></div>";
|
||||
else
|
||||
view += "<div id='image' style='background-image: url(" + photoJSON.url + "); top: 0px; right: 0px; bottom: 0px; left: 0px;'></div>";
|
||||
view += "<div id='image' style='background-image: url(" + photoJSON.url + ");' class='full'></div>";
|
||||
|
||||
}
|
||||
|
||||
@ -302,7 +302,7 @@ build = {
|
||||
|
||||
infos = [
|
||||
["", "Basics"],
|
||||
["Name", photoJSON.title + editTitleHTML],
|
||||
["Title", photoJSON.title + editTitleHTML],
|
||||
["Uploaded", photoJSON.sysdate],
|
||||
["Description", photoJSON.description + editDescriptionHTML],
|
||||
["", "Image"],
|
||||
@ -312,7 +312,7 @@ build = {
|
||||
["Tags", build.tags(photoJSON.tags, forView)]
|
||||
];
|
||||
|
||||
if ((photoJSON.takedate+photoJSON.make+photoJSON.model+photoJSON.shutter+photoJSON.aperture+photoJSON.focal+photoJSON.iso)!="") {
|
||||
if ((photoJSON.takestamp+photoJSON.make+photoJSON.model+photoJSON.shutter+photoJSON.aperture+photoJSON.focal+photoJSON.iso)!=="null") {
|
||||
|
||||
infos = infos.concat([
|
||||
["", "Camera"],
|
||||
@ -414,7 +414,7 @@ build = {
|
||||
|
||||
infos = [
|
||||
["", "Basics"],
|
||||
["Name", albumJSON.title + editTitleHTML],
|
||||
["Title", albumJSON.title + editTitleHTML],
|
||||
["Description", albumJSON.description + editDescriptionHTML],
|
||||
["", "Album"],
|
||||
["Created", albumJSON.sysdate],
|
||||
|
@ -86,8 +86,9 @@ contextMenu = {
|
||||
function() { settings.setLogin() },
|
||||
function() { settings.setSorting() },
|
||||
function() { settings.setDropboxKey() },
|
||||
function() { window.open(lychee.website, "_newtab"); },
|
||||
function() { window.open("plugins/check.php", "_newtab"); },
|
||||
function() { window.open(lychee.website); },
|
||||
function() { window.open("plugins/check/"); },
|
||||
function() { window.open("plugins/displaylog/"); },
|
||||
function() { lychee.logout() }
|
||||
];
|
||||
|
||||
@ -98,8 +99,9 @@ contextMenu = {
|
||||
["separator", -1],
|
||||
["<a class='icon-info-sign'></a> About Lychee", 3],
|
||||
["<a class='icon-dashboard'></a> Diagnostics", 4],
|
||||
["<a class='icon-list'></a> Show Log", 5],
|
||||
["separator", -1],
|
||||
["<a class='icon-signout'></a> Sign Out", 5]
|
||||
["<a class='icon-signout'></a> Sign Out", 6]
|
||||
];
|
||||
|
||||
contextMenu.show(items, mouse_x, mouse_y, "right");
|
||||
@ -210,6 +212,26 @@ contextMenu = {
|
||||
|
||||
},
|
||||
|
||||
photoMore: function(photoID, e) {
|
||||
|
||||
var mouse_x = e.pageX,
|
||||
mouse_y = e.pageY - $(document).scrollTop(),
|
||||
items;
|
||||
|
||||
contextMenu.fns = [
|
||||
function() { window.open(photo.getDirectLink()) },
|
||||
function() { photo.getArchive(photoID) }
|
||||
];
|
||||
|
||||
items = [
|
||||
["<a class='icon-resize-full'></a> Full Photo", 0],
|
||||
["<a class='icon-circle-arrow-down'></a> Download", 1]
|
||||
];
|
||||
|
||||
contextMenu.show(items, mouse_x, mouse_y, "right");
|
||||
|
||||
},
|
||||
|
||||
move: function(photoIDs, e, orientation) {
|
||||
|
||||
var mouse_x = e.pageX,
|
||||
@ -256,7 +278,7 @@ contextMenu = {
|
||||
function() { photo.share(photoID, 1) },
|
||||
function() { photo.share(photoID, 2) },
|
||||
function() { photo.share(photoID, 3) },
|
||||
function() { window.open(photo.getDirectLink(),"_newtab") }
|
||||
function() { window.open(photo.getDirectLink()) }
|
||||
];
|
||||
|
||||
link = photo.getViewLink(photoID);
|
||||
|
@ -20,18 +20,18 @@ $(document).ready(function(){
|
||||
$(document).on("mouseup", multiselect.getSelection);
|
||||
|
||||
/* Header */
|
||||
$("#hostedwith").on(event_name, function() { window.open(lychee.website,"_newtab") });
|
||||
$("#hostedwith").on(event_name, function() { window.open(lychee.website) });
|
||||
$("#button_signin").on(event_name, lychee.loginDialog);
|
||||
$("#button_settings").on(event_name, contextMenu.settings);
|
||||
$("#button_settings").on("click", contextMenu.settings);
|
||||
$("#button_share").on(event_name, function(e) {
|
||||
if (photo.json.public==1||photo.json.public==2) contextMenu.sharePhoto(photo.getID(), e);
|
||||
else photo.setPublic(photo.getID(), e);
|
||||
});
|
||||
$("#button_share_album").on(event_name, function(e) {
|
||||
if (album.json.public==1) contextMenu.shareAlbum(album.getID(), e);
|
||||
else modal.show("Share Album", "All photos inside this album will be public and visible for everyone. Existing public photos will have the same sharing permission as this album. Are your sure you want to share this album? <input class='text' type='password' placeholder='password (optional)' value=''>", [["Share Album", function() { album.setPublic(album.getID(), e) }], ["Cancel", function() {}]]);
|
||||
else album.setPublic(album.getID(), e);
|
||||
});
|
||||
$("#button_download").on(event_name, function() { photo.getArchive(photo.getID()) });
|
||||
$("#button_more").on(event_name, function(e) { contextMenu.photoMore(photo.getID(), e) });
|
||||
$("#button_trash_album").on(event_name, function() { album.delete([album.getID()]) });
|
||||
$("#button_move").on(event_name, function(e) { contextMenu.move([photo.getID()], e) });
|
||||
$("#button_trash").on(event_name, function() { photo.delete([photo.getID()]) });
|
||||
@ -55,12 +55,8 @@ $(document).ready(function(){
|
||||
|
||||
/* Image View */
|
||||
lychee.imageview
|
||||
.on(event_name, ".arrow_wrapper.previous", function() {
|
||||
if (album.json&&album.json.content[photo.getID()]&&album.json.content[photo.getID()].previousPhoto!=="") lychee.goto(album.getID() + "/" + album.json.content[photo.getID()].previousPhoto)
|
||||
})
|
||||
.on(event_name, ".arrow_wrapper.next", function() {
|
||||
if (album.json&&album.json.content[photo.getID()]&&album.json.content[photo.getID()].nextPhoto!=="") lychee.goto(album.getID() + "/" + album.json.content[photo.getID()].nextPhoto)
|
||||
});
|
||||
.on(event_name, ".arrow_wrapper.previous", photo.previous)
|
||||
.on(event_name, ".arrow_wrapper.next", photo.next);
|
||||
|
||||
/* Infobox */
|
||||
$("#infobox")
|
||||
@ -74,17 +70,40 @@ $(document).ready(function(){
|
||||
|
||||
/* Keyboard */
|
||||
Mousetrap
|
||||
.bind('u', function() { $("#upload_files").click() })
|
||||
.bind('s', function() { if (visible.photo()) $("#button_star").click() })
|
||||
.bind('left', function() { if (visible.photo()) $("#imageview a#previous").click() })
|
||||
.bind('right', function() { if (visible.photo()) $("#imageview a#next").click() })
|
||||
.bind('command+backspace', function() {
|
||||
.bind(['u', 'ctrl+u'], function() { $("#upload_files").click() })
|
||||
.bind(['s', 'ctrl+s', 'f', 'ctrl+f'], function(e) {
|
||||
if (visible.photo()) {
|
||||
$("#button_star").click();
|
||||
} else if (visible.albums()) {
|
||||
e.preventDefault();
|
||||
$("#search").focus();
|
||||
}
|
||||
})
|
||||
.bind(['r', 'ctrl+r'], function(e) {
|
||||
e.preventDefault();
|
||||
if (visible.album()) album.setTitle(album.getID());
|
||||
else if (visible.photo()) photo.setTitle([photo.getID()]);
|
||||
})
|
||||
.bind(['d', 'ctrl+d'], function(e) {
|
||||
e.preventDefault();
|
||||
if (visible.photo()) photo.setDescription(photo.getID());
|
||||
else if (visible.album()) album.setDescription(album.getID());
|
||||
})
|
||||
.bind(['t', 'ctrl+t'], function(e) {
|
||||
if (visible.photo()) {
|
||||
e.preventDefault();
|
||||
photo.editTags([photo.getID()]);
|
||||
}
|
||||
})
|
||||
.bind(['i', 'ctrl+i'], function() {
|
||||
if (visible.infobox()) view.infobox.hide();
|
||||
else if (visible.infoboxbutton()) view.infobox.show();
|
||||
})
|
||||
.bind(['command+backspace', 'ctrl+backspace'], function() {
|
||||
if (visible.photo()&&!visible.message()) photo.delete([photo.getID()]);
|
||||
else if (visible.album()&&!visible.message()) album.delete([album.getID()]);
|
||||
})
|
||||
.bind('i', function() {
|
||||
if (visible.infobox()) view.infobox.hide();
|
||||
else if (!visible.albums()) view.infobox.show();
|
||||
});
|
||||
|
||||
Mousetrap.bindGlobal('enter', function() {
|
||||
@ -101,6 +120,26 @@ $(document).ready(function(){
|
||||
else if (visible.albums()&&$("#search").val().length!==0) search.reset();
|
||||
});
|
||||
|
||||
|
||||
if (mobileBrowser()) {
|
||||
|
||||
$(document)
|
||||
|
||||
/* Fullscreen on mobile */
|
||||
.on('touchend', '#image', function(e) {
|
||||
if (swipe.obj===null||(swipe.offset>=-5&&swipe.offset<=5)) {
|
||||
if (visible.controls()) view.header.hide(e, 0);
|
||||
else view.header.show();
|
||||
}
|
||||
})
|
||||
|
||||
/* Swipe on mobile */
|
||||
.swipe().on('swipeStart', function() { if (visible.photo()) swipe.start($("#image")) })
|
||||
.swipe().on('swipeMove', function(e) { if (visible.photo()) swipe.move(e.swipe) })
|
||||
.swipe().on('swipeEnd', function(e) { if (visible.photo()) swipe.stop(e.swipe, photo.previous, photo.next) });
|
||||
|
||||
}
|
||||
|
||||
/* Document */
|
||||
$(document)
|
||||
|
||||
|
@ -11,48 +11,77 @@ loadingBar = {
|
||||
|
||||
show: function(status, errorText) {
|
||||
|
||||
if (status==="error") {
|
||||
if (status==='error') {
|
||||
|
||||
loadingBar.status = "error";
|
||||
// Set status
|
||||
loadingBar.status = 'error';
|
||||
|
||||
if (!errorText) errorText = "Whoops, it looks like something went wrong. Please reload the site and try again!";
|
||||
// Parse text
|
||||
if (errorText) errorText = errorText.replace('<br>', '');
|
||||
if (!errorText) errorText = 'Whoops, it looks like something went wrong. Please reload the site and try again!';
|
||||
|
||||
// Move header down
|
||||
if (visible.controls()) lychee.header.addClass('error');
|
||||
|
||||
// Modify loading
|
||||
lychee.loadingBar
|
||||
.removeClass("loading uploading error")
|
||||
.removeClass('loading uploading error')
|
||||
.addClass(status)
|
||||
.html("<h1>Error: <span>" + errorText + "</span></h1>")
|
||||
.html('<h1>Error: <span>' + errorText + '</span></h1>')
|
||||
.show()
|
||||
.css("height", "40px");
|
||||
if (visible.controls()) lychee.header.addClass("error");
|
||||
.css('height', '40px');
|
||||
|
||||
clearTimeout(lychee.loadingBar.data("timeout"));
|
||||
lychee.loadingBar.data("timeout", setTimeout(function() { loadingBar.hide(true) }, 3000));
|
||||
// Set timeout
|
||||
clearTimeout(lychee.loadingBar.data('timeout'));
|
||||
lychee.loadingBar.data('timeout', setTimeout(function() { loadingBar.hide(true) }, 3000));
|
||||
|
||||
} else if (loadingBar.status===null) {
|
||||
return true;
|
||||
|
||||
loadingBar.status = "loading";
|
||||
}
|
||||
|
||||
clearTimeout(lychee.loadingBar.data("timeout"));
|
||||
lychee.loadingBar.data("timeout", setTimeout(function() {
|
||||
if (loadingBar.status===null) {
|
||||
|
||||
// Set status
|
||||
loadingBar.status = 'loading';
|
||||
|
||||
// Set timeout
|
||||
clearTimeout(lychee.loadingBar.data('timeout'));
|
||||
lychee.loadingBar.data('timeout', setTimeout(function() {
|
||||
|
||||
// Move header down
|
||||
if (visible.controls()) lychee.header.addClass('loading');
|
||||
|
||||
// Modify loading
|
||||
lychee.loadingBar
|
||||
.show()
|
||||
.removeClass("loading uploading error")
|
||||
.addClass("loading");
|
||||
if (visible.controls()) lychee.header.addClass("loading");
|
||||
.removeClass('loading uploading error')
|
||||
.addClass('loading')
|
||||
.show();
|
||||
|
||||
}, 1000));
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
hide: function(force_hide) {
|
||||
hide: function(force) {
|
||||
|
||||
if ((loadingBar.status!=="error"&&loadingBar.status!==null)||force_hide) {
|
||||
if ((loadingBar.status!=='error'&&loadingBar.status!==null)||force) {
|
||||
|
||||
// Remove status
|
||||
loadingBar.status = null;
|
||||
clearTimeout(lychee.loadingBar.data("timeout"));
|
||||
lychee.loadingBar.html("").css("height", "3px");
|
||||
if (visible.controls()) lychee.header.removeClass("error loading");
|
||||
|
||||
// Move header up
|
||||
if (visible.controls()) lychee.header.removeClass('error loading');
|
||||
|
||||
// Modify loading
|
||||
lychee.loadingBar
|
||||
.html('')
|
||||
.css('height', '3px');
|
||||
|
||||
// Set timeout
|
||||
clearTimeout(lychee.loadingBar.data('timeout'));
|
||||
setTimeout(function() { lychee.loadingBar.hide() }, 300);
|
||||
|
||||
}
|
||||
|
@ -7,7 +7,9 @@
|
||||
|
||||
var lychee = {
|
||||
|
||||
version: "2.1.1",
|
||||
title: "",
|
||||
version: "2.5 rc1",
|
||||
version_code: "020500",
|
||||
|
||||
api_path: "php/api.php",
|
||||
update_path: "http://lychee.electerious.com/version/index.php",
|
||||
@ -38,7 +40,7 @@ var lychee = {
|
||||
|
||||
var params;
|
||||
|
||||
params = "init&version=" + escape(lychee.version);
|
||||
params = "init&version=" + lychee.version_code;
|
||||
lychee.api(params, function(data) {
|
||||
|
||||
if (data.loggedIn!==true) {
|
||||
@ -86,6 +88,7 @@ var lychee = {
|
||||
|
||||
if (typeof data==="string"&&data.substring(0, 7)==="Error: ") {
|
||||
lychee.error(data.substring(7, data.length), params, data);
|
||||
upload.close(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -112,13 +115,13 @@ var lychee = {
|
||||
login: function() {
|
||||
|
||||
var user = $("input#username").val(),
|
||||
password = hex_md5($("input#password").val()),
|
||||
password = md5($("input#password").val()),
|
||||
params;
|
||||
|
||||
params = "login&user=" + user + "&password=" + password;
|
||||
lychee.api(params, function(data) {
|
||||
if (data===true) {
|
||||
localStorage.setItem("username", user);
|
||||
localStorage.setItem("lychee_username", user);
|
||||
window.location.reload();
|
||||
} else {
|
||||
$("#password").val("").addClass("error").focus();
|
||||
@ -135,7 +138,7 @@ var lychee = {
|
||||
$("body").append(build.signInModal());
|
||||
$("#username").focus();
|
||||
if (localStorage) {
|
||||
local_username = localStorage.getItem("username");
|
||||
local_username = localStorage.getItem("lychee_username");
|
||||
if (local_username!==null) {
|
||||
if (local_username.length>0) $("#username").val(local_username);
|
||||
$("#password").focus();
|
||||
@ -166,6 +169,7 @@ var lychee = {
|
||||
photoID = "",
|
||||
hash = document.location.hash.replace("#", "").split("/");
|
||||
|
||||
$(".no_content").remove();
|
||||
contextMenu.close();
|
||||
multiselect.close();
|
||||
|
||||
@ -224,8 +228,10 @@ var lychee = {
|
||||
|
||||
setTitle: function(title, editable) {
|
||||
|
||||
if (title==="Albums") document.title = "Lychee";
|
||||
else document.title = "Lychee - " + title;
|
||||
if (lychee.title==="") lychee.title = document.title;
|
||||
|
||||
if (title==="Albums") document.title = lychee.title;
|
||||
else document.title = lychee.title + " - " + title;
|
||||
|
||||
if (editable) $("#title").addClass("editable");
|
||||
else $("#title").removeClass("editable");
|
||||
@ -248,10 +254,12 @@ var lychee = {
|
||||
.off("drop");
|
||||
|
||||
Mousetrap
|
||||
.unbind('n')
|
||||
.unbind('u')
|
||||
.unbind('s')
|
||||
.unbind('backspace');
|
||||
.unbind(['u', 'ctrl+u'])
|
||||
.unbind(['s', 'ctrl+s'])
|
||||
.unbind(['r', 'ctrl+r'])
|
||||
.unbind(['d', 'ctrl+d'])
|
||||
.unbind(['t', 'ctrl+t'])
|
||||
.unbind(['command+backspace', 'ctrl+backspace']);
|
||||
|
||||
if (mode==="public") {
|
||||
|
||||
@ -328,6 +336,14 @@ var lychee = {
|
||||
|
||||
},
|
||||
|
||||
removeHTML: function(html) {
|
||||
|
||||
var tmp = document.createElement("DIV");
|
||||
tmp.innerHTML = html;
|
||||
return tmp.textContent || tmp.innerText;
|
||||
|
||||
},
|
||||
|
||||
error: function(errorThrown, params, data) {
|
||||
|
||||
console.log("Error Description: " + errorThrown);
|
||||
|
@ -22,7 +22,7 @@ password = {
|
||||
view.album.password();
|
||||
}
|
||||
|
||||
params = "setAlbumPassword&albumID=" + albumID + "&password=" + hex_md5($(".message input.text").val());
|
||||
params = "setAlbumPassword&albumID=" + albumID + "&password=" + md5($(".message input.text").val());
|
||||
lychee.api(params, function(data) {
|
||||
|
||||
if (data!==true) lychee.error(null, params, data);
|
||||
@ -58,11 +58,11 @@ password = {
|
||||
} else {
|
||||
|
||||
// Check password
|
||||
params = "checkAlbumAccess&albumID=" + albumID + "&password=" + hex_md5(passwd);
|
||||
params = "checkAlbumAccess&albumID=" + albumID + "&password=" + md5(passwd);
|
||||
lychee.api(params, function(data) {
|
||||
|
||||
if (data===true) {
|
||||
password.value = hex_md5(passwd);
|
||||
password.value = md5(passwd);
|
||||
callback();
|
||||
} else {
|
||||
lychee.goto("");
|
||||
|
@ -56,6 +56,68 @@ photo = {
|
||||
|
||||
},
|
||||
|
||||
previous: function(animate) {
|
||||
|
||||
var delay = 0;
|
||||
|
||||
if (photo.getID()!==false&&
|
||||
album.json&&
|
||||
album.json.content[photo.getID()]&&
|
||||
album.json.content[photo.getID()].previousPhoto!=="") {
|
||||
|
||||
if (animate===true) {
|
||||
|
||||
delay = 200;
|
||||
|
||||
$("#image").css({
|
||||
WebkitTransform: 'translateX(100%)',
|
||||
MozTransform: 'translateX(100%)',
|
||||
transform: 'translateX(100%)',
|
||||
opacity: 0
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
setTimeout(function() {
|
||||
if (photo.getID()===false) return false;
|
||||
lychee.goto(album.getID() + "/" + album.json.content[photo.getID()].previousPhoto)
|
||||
}, delay);
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
next: function(animate) {
|
||||
|
||||
var delay = 0;
|
||||
|
||||
if (photo.getID()!==false&&
|
||||
album.json&&
|
||||
album.json.content[photo.getID()]&&
|
||||
album.json.content[photo.getID()].nextPhoto!=="") {
|
||||
|
||||
if (animate===true) {
|
||||
|
||||
delay = 200;
|
||||
|
||||
$("#image").css({
|
||||
WebkitTransform: 'translateX(-100%)',
|
||||
MozTransform: 'translateX(-100%)',
|
||||
transform: 'translateX(-100%)',
|
||||
opacity: 0
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
setTimeout(function() {
|
||||
if (photo.getID()===false) return false;
|
||||
lychee.goto(album.getID() + "/" + album.json.content[photo.getID()].nextPhoto);
|
||||
}, delay);
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
delete: function(photoIDs) {
|
||||
|
||||
var params,
|
||||
@ -145,8 +207,12 @@ photo = {
|
||||
buttons = [
|
||||
["Set Title", function() {
|
||||
|
||||
// Get input
|
||||
newTitle = $(".message input.text").val();
|
||||
|
||||
// Remove html from input
|
||||
newTitle = lychee.removeHTML(newTitle);
|
||||
|
||||
if (visible.photo()) {
|
||||
photo.json.title = (newTitle==="") ? "Untitled" : newTitle;
|
||||
view.photo.title();
|
||||
@ -256,7 +322,7 @@ photo = {
|
||||
album.json.content[photoID].public = (album.json.content[photoID].public==0) ? 1 : 0;
|
||||
view.album.content.public(photoID);
|
||||
|
||||
params = "setPhotoPublic&photoID=" + photoID + "&url=" + photo.getViewLink(photoID);
|
||||
params = "setPhotoPublic&photoID=" + photoID;
|
||||
lychee.api(params, function(data) {
|
||||
|
||||
if (data!==true) lychee.error(null, params, data);
|
||||
@ -275,14 +341,18 @@ photo = {
|
||||
buttons = [
|
||||
["Set Description", function() {
|
||||
|
||||
// Get input
|
||||
description = $(".message input.text").val();
|
||||
|
||||
// Remove html from input
|
||||
description = lychee.removeHTML(description);
|
||||
|
||||
if (visible.photo()) {
|
||||
photo.json.description = description;
|
||||
view.photo.description();
|
||||
}
|
||||
|
||||
params = "setPhotoDescription&photoID=" + photoID + "&description=" + escape(description);
|
||||
params = "setPhotoDescription&photoID=" + photoID + "&description=" + escape(encodeURI(description));
|
||||
lychee.api(params, function(data) {
|
||||
|
||||
if (data!==true) lychee.error(null, params, data);
|
||||
@ -300,7 +370,8 @@ photo = {
|
||||
editTags: function(photoIDs) {
|
||||
|
||||
var oldTags = "",
|
||||
tags = "";
|
||||
tags = "",
|
||||
buttons;
|
||||
|
||||
if (!photoIDs) return false;
|
||||
if (photoIDs instanceof Array===false) photoIDs = [photoIDs];
|
||||
@ -345,7 +416,10 @@ photo = {
|
||||
|
||||
// Parse tags
|
||||
tags = tags.replace(/(\ ,\ )|(\ ,)|(,\ )|(,{1,}\ {0,})|(,$|^,)/g, ',');
|
||||
tags = tags.replace(/,$|^,/g, '');
|
||||
tags = tags.replace(/,$|^,|(\ ){0,}$/g, '');
|
||||
|
||||
// Remove html from input
|
||||
tags = lychee.removeHTML(tags);
|
||||
|
||||
if (visible.photo()) {
|
||||
photo.json.tags = tags;
|
||||
|
@ -45,14 +45,14 @@ search = {
|
||||
else if (photosData==="") code = build.divider("Albums")+albumsData;
|
||||
else code = build.divider("Photos")+photosData+build.divider("Albums")+albumsData;
|
||||
|
||||
if (search.code!==hex_md5(code)) {
|
||||
if (search.code!==md5(code)) {
|
||||
|
||||
$(".no_content").remove();
|
||||
|
||||
lychee.animate(".album, .photo", "contentZoomOut");
|
||||
lychee.animate(".divider", "fadeOut");
|
||||
|
||||
search.code = hex_md5(code);
|
||||
search.code = md5(code);
|
||||
|
||||
setTimeout(function() {
|
||||
|
||||
|
@ -13,7 +13,8 @@ var settings = {
|
||||
dbUser,
|
||||
dbPassword,
|
||||
dbHost,
|
||||
buttons;
|
||||
buttons,
|
||||
params;
|
||||
|
||||
buttons = [
|
||||
["Connect", function() {
|
||||
@ -26,7 +27,7 @@ var settings = {
|
||||
if (dbHost.length<1) dbHost = "localhost";
|
||||
if (dbName.length<1) dbName = "lychee";
|
||||
|
||||
params = "dbCreateConfig&dbName=" + escape(dbName) + "&dbUser=" + escape(dbUser) + "&dbPassword=" + escape(dbPassword) + "&dbHost=" + escape(dbHost) + "&version=" + escape(lychee.version);
|
||||
params = "dbCreateConfig&dbName=" + escape(dbName) + "&dbUser=" + escape(dbUser) + "&dbPassword=" + escape(dbPassword) + "&dbHost=" + escape(dbHost);
|
||||
lychee.api(params, function(data) {
|
||||
|
||||
if (data!==true) {
|
||||
@ -113,7 +114,7 @@ var settings = {
|
||||
|
||||
} else {
|
||||
|
||||
params = "setLogin&username=" + escape(username) + "&password=" + hex_md5(password);
|
||||
params = "setLogin&username=" + escape(username) + "&password=" + md5(password);
|
||||
lychee.api(params, function(data) {
|
||||
|
||||
if (data!==true) {
|
||||
@ -173,7 +174,7 @@ var settings = {
|
||||
return false;
|
||||
}
|
||||
|
||||
params = "setLogin&oldPassword=" + hex_md5(old_password) + "&username=" + escape(username) + "&password=" + hex_md5(password);
|
||||
params = "setLogin&oldPassword=" + md5(old_password) + "&username=" + escape(username) + "&password=" + md5(password);
|
||||
lychee.api(params, function(data) {
|
||||
|
||||
if (data!==true) lychee.error(null, params, data);
|
||||
@ -191,7 +192,8 @@ var settings = {
|
||||
setSorting: function() {
|
||||
|
||||
var buttons,
|
||||
sorting;
|
||||
sorting,
|
||||
params;
|
||||
|
||||
buttons = [
|
||||
["Change Sorting", function() {
|
||||
@ -216,7 +218,7 @@ var settings = {
|
||||
"Sort photos by \
|
||||
<select id='settings_type'> \
|
||||
<option value='id'>Upload Time</option> \
|
||||
<option value='take'>Take Date</option> \
|
||||
<option value='takestamp'>Take Date</option> \
|
||||
<option value='title'>Title</option> \
|
||||
<option value='description'>Description</option> \
|
||||
<option value='public'>Public</option> \
|
||||
@ -232,13 +234,12 @@ var settings = {
|
||||
", buttons);
|
||||
|
||||
if (lychee.sorting!=="") {
|
||||
sorting = lychee.sorting.replace("ORDER BY ", "").split(" ");
|
||||
|
||||
// Special parsing
|
||||
if (sorting[0]==='UNIX_TIMESTAMP(STR_TO_DATE(CONCAT(takedate,"-",taketime),"%d.%m.%Y-%H:%i:%S"))') sorting[0] = "take";
|
||||
sorting = lychee.sorting.replace("ORDER BY ", "").split(" ");
|
||||
|
||||
$("select#settings_type").val(sorting[0]);
|
||||
$("select#settings_order").val(sorting[1]);
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
54
assets/js/swipe.js
Normal file
54
assets/js/swipe.js
Normal file
@ -0,0 +1,54 @@
|
||||
/**
|
||||
* @name Swipe Module
|
||||
* @description Swipes and moves an object.
|
||||
* @author Tobias Reich
|
||||
* @copyright 2014 by Tobias Reich
|
||||
*/
|
||||
|
||||
swipe = {
|
||||
|
||||
obj: null,
|
||||
tolerance: 150,
|
||||
offset: 0,
|
||||
|
||||
start: function(obj, tolerance) {
|
||||
|
||||
if (obj) swipe.obj = obj;
|
||||
if (tolerance) swipe.tolerance = tolerance;
|
||||
|
||||
return true;
|
||||
|
||||
},
|
||||
|
||||
move: function(e) {
|
||||
|
||||
if (swipe.obj===null) return false;
|
||||
|
||||
swipe.offset = -1 * e.x;
|
||||
|
||||
swipe.obj.css({
|
||||
WebkitTransform: 'translateX(' + swipe.offset + 'px)',
|
||||
MozTransform: 'translateX(' + swipe.offset + 'px)',
|
||||
transform: 'translateX(' + swipe.offset + 'px)'
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
stop: function(e, left, right) {
|
||||
|
||||
if (e.x<=-swipe.tolerance) left(true);
|
||||
else if (e.x>=swipe.tolerance) right(true);
|
||||
else if (swipe.obj!==null) {
|
||||
swipe.obj.css({
|
||||
WebkitTransform: 'translateX(0px)',
|
||||
MozTransform: 'translateX(0px)',
|
||||
transform: 'translateX(0px)'
|
||||
});
|
||||
}
|
||||
|
||||
swipe.obj = null;
|
||||
swipe.offset = 0;
|
||||
|
||||
}
|
||||
|
||||
};
|
@ -63,7 +63,7 @@ upload = {
|
||||
progress;
|
||||
|
||||
if (files.length<=0) return false;
|
||||
if (albumID===false) albumID = 0;
|
||||
if (albumID===false||visible.albums()===true) albumID = 0;
|
||||
|
||||
formData.append("function", "upload");
|
||||
formData.append("albumID", albumID);
|
||||
@ -132,7 +132,8 @@ upload = {
|
||||
var albumID = album.getID(),
|
||||
params,
|
||||
extension,
|
||||
buttons;
|
||||
buttons,
|
||||
link;
|
||||
|
||||
if (albumID===false) albumID = 0;
|
||||
|
||||
|
@ -11,49 +11,40 @@ view = {
|
||||
|
||||
show: function() {
|
||||
|
||||
var newMargin = -1*($("#imageview #image").height()/2)+20;
|
||||
|
||||
clearTimeout($(window).data("timeout"));
|
||||
|
||||
if (visible.photo()) {
|
||||
lychee.imageview.removeClass("full");
|
||||
lychee.loadingBar.css("opacity", 1);
|
||||
lychee.header.removeClass("hidden");
|
||||
if ($("#imageview #image.small").length>0) {
|
||||
$("#imageview #image").css({
|
||||
marginTop: -1*($("#imageview #image").height()/2)+20
|
||||
});
|
||||
} else {
|
||||
$("#imageview #image").css({
|
||||
top: 60,
|
||||
right: 30,
|
||||
bottom: 30,
|
||||
left: 30
|
||||
});
|
||||
}
|
||||
}
|
||||
lychee.imageview.removeClass("full");
|
||||
lychee.header.removeClass("hidden");
|
||||
lychee.loadingBar.css("opacity", 1);
|
||||
|
||||
if ($("#imageview #image.small").length>0) $("#imageview #image").css('margin-top', newMargin);
|
||||
else $("#imageview #image").removeClass('full');
|
||||
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
hide: function(e, delay) {
|
||||
|
||||
var newMargin = -1*($("#imageview #image").height()/2);
|
||||
|
||||
if (delay===undefined) delay = 500;
|
||||
|
||||
if (visible.photo()&&!visible.infobox()&&!visible.contextMenu()&&!visible.message()) {
|
||||
|
||||
clearTimeout($(window).data("timeout"));
|
||||
|
||||
$(window).data("timeout", setTimeout(function() {
|
||||
|
||||
lychee.imageview.addClass("full");
|
||||
lychee.loadingBar.css("opacity", 0);
|
||||
lychee.header.addClass("hidden");
|
||||
if ($("#imageview #image.small").length>0) {
|
||||
$("#imageview #image").css({
|
||||
marginTop: -1*($("#imageview #image").height()/2)
|
||||
});
|
||||
} else {
|
||||
$("#imageview #image").css({
|
||||
top: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
left: 0
|
||||
});
|
||||
}
|
||||
}, 500));
|
||||
lychee.loadingBar.css("opacity", 0);
|
||||
|
||||
if ($("#imageview #image.small").length>0) $("#imageview #image").css('margin-top', newMargin);
|
||||
else $("#imageview #image").addClass('full');
|
||||
|
||||
}, delay));
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
@ -229,7 +220,7 @@ view = {
|
||||
lychee.setTitle("Unsorted", false);
|
||||
break;
|
||||
default:
|
||||
if (album.json.init) $("#infobox .attr_name").html(album.json.title + " " + build.editIcon("edit_title_album"));
|
||||
if (album.json.init) $("#infobox .attr_title").html(album.json.title + " " + build.editIcon("edit_title_album"));
|
||||
lychee.setTitle(album.json.title, true);
|
||||
break;
|
||||
}
|
||||
@ -381,7 +372,7 @@ view = {
|
||||
|
||||
hide: function() {
|
||||
|
||||
if (!visible.controls()) view.header.show();
|
||||
view.header.show();
|
||||
if (visible.infobox) view.infobox.hide();
|
||||
|
||||
lychee.content.removeClass("view");
|
||||
@ -406,7 +397,7 @@ view = {
|
||||
|
||||
title: function() {
|
||||
|
||||
if (photo.json.init) $("#infobox .attr_name").html(photo.json.title + " " + build.editIcon("edit_title"));
|
||||
if (photo.json.init) $("#infobox .attr_title").html(photo.json.title + " " + build.editIcon("edit_title"));
|
||||
lychee.setTitle(photo.json.title, true);
|
||||
|
||||
},
|
||||
|
@ -32,6 +32,13 @@ visible = {
|
||||
else return false;
|
||||
},
|
||||
|
||||
infoboxbutton: function() {
|
||||
if (visible.albums()) return false;
|
||||
if (visible.photo()) return true;
|
||||
if (visible.album()&&$('#button_info_album:visible').length>0) return true;
|
||||
else return false;
|
||||
},
|
||||
|
||||
controls: function() {
|
||||
if (lychee.loadingBar.css('opacity')<1) return false;
|
||||
else return true;
|
||||
|
2
assets/min/main.css
Normal file
2
assets/min/main.css
Normal file
File diff suppressed because one or more lines are too long
7
assets/min/main.js
Normal file
7
assets/min/main.js
Normal file
File diff suppressed because one or more lines are too long
5
assets/min/view.js
Normal file
5
assets/min/view.js
Normal file
File diff suppressed because one or more lines are too long
108
build/Gruntfile.coffee
Normal file
108
build/Gruntfile.coffee
Normal file
@ -0,0 +1,108 @@
|
||||
module.exports = (grunt) ->
|
||||
|
||||
grunt.initConfig
|
||||
|
||||
pkg: grunt.file.readJSON 'package.json'
|
||||
|
||||
concat:
|
||||
|
||||
view:
|
||||
|
||||
options:
|
||||
separator: "\n"
|
||||
src: [
|
||||
'bower_components/jQuery/dist/jquery.min.js'
|
||||
'bower_components/js-md5/js/md5.min.js'
|
||||
'bower_components/mousetrap/mousetrap.min.js'
|
||||
'bower_components/mousetrap/plugins/global-bind/mousetrap-global-bind.min.js'
|
||||
'../assets/js/_frameworks.js'
|
||||
'../assets/js/build.js'
|
||||
'../assets/js/view/main.js'
|
||||
]
|
||||
dest: '../assets/min/view.js'
|
||||
|
||||
js:
|
||||
options:
|
||||
separator: "\n"
|
||||
src: [
|
||||
'bower_components/jQuery/dist/jquery.min.js'
|
||||
'bower_components/js-md5/js/md5.min.js'
|
||||
'bower_components/mousetrap/mousetrap.min.js'
|
||||
'bower_components/mousetrap/plugins/global-bind/mousetrap-global-bind.min.js'
|
||||
'../assets/js/*.js'
|
||||
]
|
||||
dest: '../assets/min/main.js'
|
||||
|
||||
css:
|
||||
options:
|
||||
separator: "\n"
|
||||
src: [
|
||||
'../assets/css/*.css'
|
||||
]
|
||||
dest: '../assets/min/main.css'
|
||||
|
||||
uglify:
|
||||
|
||||
view:
|
||||
options:
|
||||
banner: '/*! <%= pkg.name %> <%= pkg.version %> */\n'
|
||||
files:
|
||||
'../assets/min/view.js': '../assets/min/view.js'
|
||||
|
||||
assets:
|
||||
options:
|
||||
banner: '/*! <%= pkg.name %> <%= pkg.version %> */\n'
|
||||
files:
|
||||
'../assets/min/main.js': '../assets/min/main.js'
|
||||
|
||||
cssmin:
|
||||
|
||||
assets:
|
||||
options:
|
||||
banner: '/*! <%= pkg.name %> <%= pkg.version %> */'
|
||||
files:
|
||||
'../assets/min/main.css': '../assets/min/main.css'
|
||||
|
||||
watch:
|
||||
|
||||
js:
|
||||
files: [
|
||||
'../assets/js/*.js'
|
||||
]
|
||||
tasks: ['js']
|
||||
options:
|
||||
spawn: false
|
||||
interrupt: true
|
||||
|
||||
css:
|
||||
files: [
|
||||
'../assets/css/*.css'
|
||||
]
|
||||
tasks: ['css']
|
||||
options:
|
||||
spawn: false
|
||||
interrupt: true
|
||||
|
||||
require('load-grunt-tasks')(grunt)
|
||||
|
||||
grunt.registerTask 'default', ->
|
||||
grunt.task.run [
|
||||
'view'
|
||||
'js'
|
||||
'css'
|
||||
]
|
||||
|
||||
grunt.registerTask 'view', [
|
||||
'concat:view'
|
||||
'uglify:view'
|
||||
]
|
||||
|
||||
grunt.registerTask 'js', [
|
||||
'concat:js'
|
||||
'uglify:assets'
|
||||
]
|
||||
|
||||
grunt.registerTask 'css', [
|
||||
'concat:css'
|
||||
'cssmin:assets'
|
||||
]
|
8
build/bower.json
Normal file
8
build/bower.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "Lychee",
|
||||
"dependencies": {
|
||||
"jQuery": "~2.1.0",
|
||||
"js-md5": "~1.1.0",
|
||||
"mousetrap": "~1.4.6"
|
||||
}
|
||||
}
|
22
build/package.json
Normal file
22
build/package.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "Lychee",
|
||||
"version": "2.5.0",
|
||||
"description": "Self-hosted photo-management done right.",
|
||||
"authors": "Tobias Reich <tobias.reich.ich@gmail.com>",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/electerious/Lychee.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"grunt": "~0.4.2",
|
||||
"grunt-contrib-clean": "~0.5.0",
|
||||
"grunt-contrib-coffee": "~0.10.1",
|
||||
"grunt-contrib-concat": "~0.3.0",
|
||||
"grunt-contrib-cssmin": "~0.9.0",
|
||||
"grunt-contrib-uglify": "~0.4.0",
|
||||
"grunt-contrib-watch": "~0.6.0",
|
||||
"grunt-notify": "^0.3.0",
|
||||
"load-grunt-tasks": "~0.4.0"
|
||||
}
|
||||
}
|
@ -2,19 +2,25 @@
|
||||
|
||||
First you have to install the following dependencies:
|
||||
|
||||
- [CSS Optimizer](https://github.com/css/csso) `csso`
|
||||
- [UglifyJS](https://github.com/mishoo/UglifyJS2) `uglifyjs`
|
||||
- `node` [Node.js](http://nodejs.org) v0.10 or later
|
||||
- `npm` [Node Packaged Modules](https://www.npmjs.org)
|
||||
- `bower` [Bower](http://bower.io)
|
||||
- `grunt` [Grunt](http://gruntjs.com)
|
||||
|
||||
These dependencies can be installed using `npm`:
|
||||
After [installing Node.js](http://nodejs.org) you can use the included `npm` package manager to install the global requirements and Lychee-dependencies with the following command:
|
||||
|
||||
npm install csso uglify-js -g;
|
||||
npm install -g bower grunt-cli;
|
||||
npm install && bower install;
|
||||
|
||||
|
||||
### Build
|
||||
|
||||
The Makefile is located in `etc/` and can be easily executed, using the following command. Make sure your run this from the root of Lychee:
|
||||
|
||||
make -f etc/Makefile
|
||||
The Gruntfile is located in `build/` and can be easily executed using the `grunt` command.
|
||||
|
||||
### Use uncompressed files
|
||||
### Watch for changes
|
||||
|
||||
While developing, you might want to use the uncompressed files. This is possible by editing the `index.html`. Simply change the linked CSS and JS files. There are already out-commented link-tags for development and production.
|
||||
While developing, you might want to use the following command to watch for changes in `assets/js/` and `assets/css/`:
|
||||
|
||||
grunt watch
|
||||
|
||||
`grunt` will automatically build Lychee, everytime you save a file.
|
||||
|
@ -1,3 +1,25 @@
|
||||
## v2.5
|
||||
|
||||
Released -
|
||||
|
||||
- `New` Swipe gestures on mobile devices
|
||||
- `New` Plugin-System
|
||||
- `New` Rewritten Back-End
|
||||
- `New` Support for ImageMagick (thanks @bb-Ricardo)
|
||||
- `New` Logging-System
|
||||
- `New` Blowfish hash instead of MD5 for all new passwords (thanks @bb-Ricardo)
|
||||
- `New` Compile Lychee using Grunt (with npm and bower)
|
||||
- `New` Open full photo without making the photo public
|
||||
- `Improved` Shortcuts
|
||||
- `Improved` Album share dialog
|
||||
- `Improved` Database update mechanism
|
||||
- `Improved` Download photos with correct title (thanks @bb-Ricardo)
|
||||
- `Improved` EXIF parsing
|
||||
- `Improved` URL and Server import (thanks @djdallmann)
|
||||
- `Improved` Check permissions on upload
|
||||
- `Fixed` Wrong capture date in Infobox
|
||||
- `Fixed` Sorting by takedate
|
||||
|
||||
## v2.1.1
|
||||
|
||||
Released March 20, 2014
|
||||
|
@ -1,5 +1,5 @@
|
||||
#### Lychee is not working
|
||||
If Lychee is not working properly, try to open `plugins/check.php`. This script will display all errors it can find.
|
||||
If Lychee is not working properly, try to open `plugins/check/index.php`. This script will display all errors it can find.
|
||||
|
||||
#### What do I need to run Lychee on my server?
|
||||
To run Lychee, everything you need is a web-server with PHP 5.3 or later and a MySQL-Database.
|
||||
@ -13,6 +13,7 @@ If possible, change these settings directly in your `php.ini`. We recommend to i
|
||||
upload_max_size = 200M
|
||||
upload_max_filesize = 20M
|
||||
max_file_uploads = 100
|
||||
memory_limit = 256M
|
||||
|
||||
#### Which browsers are supported?
|
||||
Lychee supports the latest versions of Google Chrome, Apple Safari, Mozilla Firefox and Opera. Photos you share with others can be viewed from every browser.
|
||||
@ -34,6 +35,12 @@ To backup your Lychee installation you need to do the following steps:
|
||||
- INSERT INTO lychee_photos_backup SELECT * FROM lychee_photos;
|
||||
- CREATE TABLE lychee_settings_backup LIKE lychee_settings;
|
||||
- INSERT INTO lychee_settings_backup SELECT * FROM lychee_settings;
|
||||
|
||||
#### Can I use my existing folder-structure?
|
||||
No. Lychee has it's own folder-structure and database. Please upload or import all your photos to use them.
|
||||
|
||||
#### Can I upload videos?
|
||||
No. Video support is not planned.
|
||||
|
||||
#### What's the advantage of buying Lychee?
|
||||
Lychee is completely free to use for personal usage. However, if you like Lychee or want to use in commercially, you need to buy Lychee from [our site](http://lychee.electerious.com). I hope you appreciate my work and support further development by buying a license.
|
@ -12,6 +12,7 @@ To use Lychee without restrictions, we recommend to increase the values of the f
|
||||
upload_max_size = 200M
|
||||
upload_max_filesize = 20M
|
||||
max_file_uploads = 100
|
||||
memory_limit = 256M
|
||||
|
||||
You might also take a look at [Issue #106](https://github.com/electerious/Lychee/issues/106) if you are using nginx or in the [FAQ](https://github.com/electerious/Lychee/blob/master/docs/FAQ.md#i-cant-upload-multiple-photos-at-once) if you are using CGI or FastCGI.
|
||||
|
||||
|
@ -1,22 +1,37 @@
|
||||
### About
|
||||
|
||||
The following keys and shortcuts can be used in Lychee. Single char-shortcuts are also working, when using them with together the `ctrl`-key.
|
||||
|
||||
### Everywhere
|
||||
| Key | Action |
|
||||
|:-----------|:------------|
|
||||
| `enter` | Confirm Dialog |
|
||||
| `u` | Upload photo |
|
||||
| `esc` | Close/Back |
|
||||
| `cmd`+`up` | Close/Back |
|
||||
| `enter` | Confirm Dialog |
|
||||
| `esc` or `cmd`+`up` | Close/Back |
|
||||
|
||||
### Albums
|
||||
| Key | Action |
|
||||
|:-----------|:------------|
|
||||
| `s` or `f` | Search |
|
||||
|
||||
### Album
|
||||
| Key | Action |
|
||||
|:-----------|:------------|
|
||||
| `r` | Set title |
|
||||
| `d` | Set description |
|
||||
| `i` | Show information |
|
||||
| `cmd`+`backspace` | Delete album |
|
||||
| `ctrl`+`backspace` | Delete album |
|
||||
|
||||
### Photo
|
||||
| Key | Action |
|
||||
|:-----------|:------------|
|
||||
| `s` | Star photo |
|
||||
| `i` | Show information |
|
||||
| `cmd`+`backspace` | Delete photo |
|
||||
| `r` | Set title |
|
||||
| `t` | Set tags |
|
||||
| `d` | Set description |
|
||||
| `s` or `f` | Star photo |
|
||||
| `i` | Show information |
|
||||
| `left` | Previous photo |
|
||||
| `right` | Next photo |
|
||||
| `cmd`+`backspace` | Delete photo |
|
||||
| `ctrl`+`backspace` | Delete photo |
|
35
etc/Makefile
35
etc/Makefile
@ -1,35 +0,0 @@
|
||||
NO_COLOR=\x1b[0m
|
||||
OK_COLOR=\x1b[32;01m
|
||||
ERROR_COLOR=\x1b[31;01m
|
||||
WARN_COLOR=\x1b[33;01m
|
||||
|
||||
OK_STRING=$(OK_COLOR)[OK]$(NO_COLOR)
|
||||
ERROR_STRING=$(ERROR_COLOR)[ERRORS]$(NO_COLOR)
|
||||
RUN_STRING=$(WARN_COLOR)[RUN]$(NO_COLOR)
|
||||
|
||||
ROOT = .
|
||||
CSS = '$(ROOT)/assets/css'
|
||||
JS = '$(ROOT)/assets/js'
|
||||
BUILD = '$(ROOT)/assets/build'
|
||||
|
||||
all: clean create css js
|
||||
|
||||
clean:
|
||||
rm -f -R $(BUILD)
|
||||
@echo "$(OK_STRING) Clean build"
|
||||
|
||||
create: clean
|
||||
mkdir $(BUILD)
|
||||
@echo "$(OK_STRING) Create build"
|
||||
|
||||
css: create
|
||||
@echo "$(RUN_STRING) Compiling CSS"
|
||||
awk 'FNR==1{print ""}1' $(CSS)/*.css > $(BUILD)/main.css
|
||||
csso $(BUILD)/main.css $(BUILD)/main.css
|
||||
@echo "$(OK_STRING) CSS compiled"
|
||||
|
||||
js: create
|
||||
@echo "$(RUN_STRING) Compiling JS"
|
||||
awk 'FNR==1{print ""}1' $(JS)/*.js > $(BUILD)/main.js
|
||||
uglifyjs $(BUILD)/main.js -o $(BUILD)/main.js
|
||||
@echo "$(OK_STRING) JS compiled"
|
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 2.0 KiB |
Binary file not shown.
Before Width: | Height: | Size: 79 KiB |
@ -1 +0,0 @@
|
||||
Entypo
|
@ -1,14 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>app</key>
|
||||
<string>com.bohemiancoding.sketch</string>
|
||||
<key>build</key>
|
||||
<integer>5302</integer>
|
||||
<key>commit</key>
|
||||
<string>9460a4bc62af5e9ba50dd4143578fd9401710ce5</string>
|
||||
<key>version</key>
|
||||
<integer>18</integer>
|
||||
</dict>
|
||||
</plist>
|
@ -1 +0,0 @@
|
||||
18
|
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 5.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 9.4 KiB |
@ -1,14 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>app</key>
|
||||
<string>com.bohemiancoding.sketch</string>
|
||||
<key>build</key>
|
||||
<integer>5302</integer>
|
||||
<key>commit</key>
|
||||
<string>9460a4bc62af5e9ba50dd4143578fd9401710ce5</string>
|
||||
<key>version</key>
|
||||
<integer>18</integer>
|
||||
</dict>
|
||||
</plist>
|
@ -1 +0,0 @@
|
||||
18
|
50
index.html
50
index.html
@ -9,25 +9,8 @@
|
||||
<meta name="keywords" content="">
|
||||
<meta name="description" content="">
|
||||
|
||||
<!-- Development
|
||||
<link type="text/css" rel="stylesheet" href="assets/css/_reset.css">
|
||||
<link type="text/css" rel="stylesheet" href="assets/css/upload.css">
|
||||
<link type="text/css" rel="stylesheet" href="assets/css/tooltip.css">
|
||||
<link type="text/css" rel="stylesheet" href="assets/css/misc.css">
|
||||
<link type="text/css" rel="stylesheet" href="assets/css/message.css">
|
||||
<link type="text/css" rel="stylesheet" href="assets/css/mediaquery.css">
|
||||
<link type="text/css" rel="stylesheet" href="assets/css/loading.css">
|
||||
<link type="text/css" rel="stylesheet" href="assets/css/infobox.css">
|
||||
<link type="text/css" rel="stylesheet" href="assets/css/imageview.css">
|
||||
<link type="text/css" rel="stylesheet" href="assets/css/header.css">
|
||||
<link type="text/css" rel="stylesheet" href="assets/css/font.css">
|
||||
<link type="text/css" rel="stylesheet" href="assets/css/contextmenu.css">
|
||||
<link type="text/css" rel="stylesheet" href="assets/css/content.css">
|
||||
<link type="text/css" rel="stylesheet" href="assets/css/animations.css">
|
||||
<link type="text/css" rel="stylesheet" href="assets/css/multiselect.css"> -->
|
||||
|
||||
<!-- Production -->
|
||||
<link type="text/css" rel="stylesheet" href="assets/build/main.css">
|
||||
<!-- CSS -->
|
||||
<link type="text/css" rel="stylesheet" href="assets/min/main.css">
|
||||
|
||||
<link rel="shortcut icon" href="favicon.ico">
|
||||
<link rel="apple-touch-icon" href="assets/img/apple-touch-icon-iphone.png" sizes="120x120">
|
||||
@ -61,16 +44,16 @@
|
||||
<a class="button right icon icon-plus button_add"></a>
|
||||
<a class="button_divider"></a>
|
||||
<div class="tools" id="button_trash_album" title="Delete Album"><a class="icon-trash"></a></div>
|
||||
<div class="tools" id="button_archive" title="Download Album"><a class="icon-circle-arrow-down"></a></div>
|
||||
<div class="tools" id="button_info_album" title="Show Info"><a class="icon-info-sign"></a></div>
|
||||
<div class="tools" id="button_archive" title="Download Album"><a class="icon-circle-arrow-down"></a></div>
|
||||
<div class="tools" id="button_share_album" title="Share Album"><a class="icon-share"></a></div>
|
||||
</div>
|
||||
<div id="tools_photo">
|
||||
<a class="button left icon-arrow-left" id="button_back"></a>
|
||||
<div class="tools" id="button_more" title="More"><a class="icon-caret-down"></a></div>
|
||||
<a class="button_divider"></a>
|
||||
<div class="tools" id="button_trash" title="Delete"><a class="icon-trash"></a></div>
|
||||
<div class="tools" id="button_move" title="Move"><a class="icon-folder-open"></a></div>
|
||||
<a class="button_divider"></a>
|
||||
<div class="tools" id="button_download" title="Download"><a class="icon-circle-arrow-down"></a></div>
|
||||
<div class="tools" id="button_info" title="Show Info"><a class="icon-info-sign"></a></div>
|
||||
<a class="button_divider"></a>
|
||||
<div class="tools" id="button_share" title="Share Photo"><a class="icon-share"></a></div>
|
||||
@ -95,27 +78,8 @@
|
||||
<input id="upload_files" type="file" name="fileElem[]" multiple accept="image/*">
|
||||
</div>
|
||||
|
||||
<!-- Development
|
||||
<script defer type="text/javascript" src="assets/js/_frameworks.js"></script>
|
||||
<script defer type="text/javascript" src="assets/js/init.js"></script>
|
||||
<script defer type="text/javascript" src="assets/js/lychee.js"></script>
|
||||
<script defer type="text/javascript" src="assets/js/build.js"></script>
|
||||
<script defer type="text/javascript" src="assets/js/settings.js"></script>
|
||||
<script defer type="text/javascript" src="assets/js/upload.js"></script>
|
||||
<script defer type="text/javascript" src="assets/js/view.js"></script>
|
||||
<script defer type="text/javascript" src="assets/js/password.js"></script>
|
||||
<script defer type="text/javascript" src="assets/js/modal.js"></script>
|
||||
<script defer type="text/javascript" src="assets/js/album.js"></script>
|
||||
<script defer type="text/javascript" src="assets/js/albums.js"></script>
|
||||
<script defer type="text/javascript" src="assets/js/photo.js"></script>
|
||||
<script defer type="text/javascript" src="assets/js/visible.js"></script>
|
||||
<script defer type="text/javascript" src="assets/js/loadingBar.js"></script>
|
||||
<script defer type="text/javascript" src="assets/js/contextMenu.js"></script>
|
||||
<script defer type="text/javascript" src="assets/js/search.js"></script>
|
||||
<script defer type="text/javascript" src="assets/js/multiselect.js"></script> -->
|
||||
|
||||
<!-- Production -->
|
||||
<script async type="text/javascript" src="assets/build/main.js"></script>
|
||||
<!-- JS -->
|
||||
<script async type="text/javascript" src="assets/min/main.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
30
php/access/Access.php
Normal file
30
php/access/Access.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
###
|
||||
# @name Access
|
||||
# @author Tobias Reich
|
||||
# @copyright 2014 by Tobias Reich
|
||||
###
|
||||
|
||||
if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
|
||||
|
||||
class Access {
|
||||
|
||||
protected $database = null;
|
||||
protected $plugins = null;
|
||||
protected $settings = null;
|
||||
|
||||
public function __construct($database, $plugins, $settings) {
|
||||
|
||||
# Init vars
|
||||
$this->database = $database;
|
||||
$this->plugins = $plugins;
|
||||
$this->settings = $settings;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
306
php/access/Admin.php
Normal file
306
php/access/Admin.php
Normal file
@ -0,0 +1,306 @@
|
||||
<?php
|
||||
|
||||
###
|
||||
# @name Admin Access
|
||||
# @author Tobias Reich
|
||||
# @copyright 2014 by Tobias Reich
|
||||
###
|
||||
|
||||
if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
|
||||
if (!defined('LYCHEE_ACCESS_ADMIN')) exit('Error: You are not allowed to access this area!');
|
||||
|
||||
class Admin extends Access {
|
||||
|
||||
public function check($fn) {
|
||||
|
||||
switch ($fn) {
|
||||
|
||||
# Album functions
|
||||
case 'getAlbums': $this->getAlbums(); break;
|
||||
case 'getAlbum': $this->getAlbum(); break;
|
||||
case 'addAlbum': $this->addAlbum(); break;
|
||||
case 'setAlbumTitle': $this->setAlbumTitle(); break;
|
||||
case 'setAlbumDescription': $this->setAlbumDescription(); break;
|
||||
case 'setAlbumPublic': $this->setAlbumPublic(); break;
|
||||
case 'setAlbumPassword': $this->setAlbumPassword(); break;
|
||||
case 'deleteAlbum': $this->deleteAlbum(); break;
|
||||
|
||||
# Photo functions
|
||||
case 'getPhoto': $this->getPhoto(); break;
|
||||
case 'setPhotoTitle': $this->setPhotoTitle(); break;
|
||||
case 'setPhotoDescription': $this->setPhotoDescription(); break;
|
||||
case 'setPhotoStar': $this->setPhotoStar(); break;
|
||||
case 'setPhotoPublic': $this->setPhotoPublic(); break;
|
||||
case 'setPhotoAlbum': $this->setPhotoAlbum(); break;
|
||||
case 'setPhotoTags': $this->setPhotoTags(); break;
|
||||
case 'deletePhoto': $this->deletePhoto(); break;
|
||||
|
||||
# Add functions
|
||||
case 'upload': $this->upload(); break;
|
||||
case 'importUrl': $this->importUrl(); break;
|
||||
case 'importServer': $this->importServer(); break;
|
||||
|
||||
# Search functions
|
||||
case 'search': $this->search(); break;
|
||||
|
||||
# Session functions
|
||||
case 'init': $this->init(); break;
|
||||
case 'login': $this->login(); break;
|
||||
case 'logout': $this->logout(); break;
|
||||
|
||||
# Settings functions
|
||||
case 'setLogin': $this->setLogin(); break;
|
||||
case 'setSorting': $this->setSorting(); break;
|
||||
case 'setDropboxKey': $this->setDropboxKey(); break;
|
||||
|
||||
# $_GET functions
|
||||
case 'getAlbumArchive': $this->getAlbumArchive(); break;
|
||||
case 'getPhotoArchive': $this->getPhotoArchive(); break;
|
||||
|
||||
# Error
|
||||
default: exit('Error: Function not found! Please check the spelling of the called function.');
|
||||
return false; break;
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
# Album functions
|
||||
|
||||
private function getAlbums() {
|
||||
|
||||
$album = new Album($this->database, $this->plugins, $this->settings, null);
|
||||
echo json_encode($album->getAll(false));
|
||||
|
||||
}
|
||||
|
||||
private function getAlbum() {
|
||||
|
||||
Module::dependencies(isset($_POST['albumID']));
|
||||
$album = new Album($this->database, $this->plugins, $this->settings, $_POST['albumID']);
|
||||
echo json_encode($album->get());
|
||||
|
||||
}
|
||||
|
||||
private function addAlbum() {
|
||||
|
||||
Module::dependencies(isset($_POST['title']));
|
||||
$album = new Album($this->database, $this->plugins, $this->settings, null);
|
||||
echo $album->add($_POST['title']);
|
||||
|
||||
}
|
||||
|
||||
private function setAlbumTitle() {
|
||||
|
||||
Module::dependencies(isset($_POST['albumIDs'], $_POST['title']));
|
||||
$album = new Album($this->database, $this->plugins, $this->settings, $_POST['albumIDs']);
|
||||
echo $album->setTitle($_POST['title']);
|
||||
|
||||
}
|
||||
|
||||
private function setAlbumDescription() {
|
||||
|
||||
Module::dependencies(isset($_POST['albumID'], $_POST['description']));
|
||||
$album = new Album($this->database, $this->plugins, $this->settings, $_POST['albumID']);
|
||||
echo $album->setDescription($_POST['description']);
|
||||
|
||||
}
|
||||
|
||||
private function setAlbumPublic() {
|
||||
|
||||
Module::dependencies(isset($_POST['albumID'], $_POST['password']));
|
||||
$album = new Album($this->database, $this->plugins, $this->settings, $_POST['albumID']);
|
||||
echo $album->setPublic($_POST['password']);
|
||||
|
||||
}
|
||||
|
||||
private function setAlbumPassword() {
|
||||
|
||||
Module::dependencies(isset($_POST['albumID'], $_POST['password']));
|
||||
$album = new Album($this->database, $this->plugins, $this->settings, $_POST['albumID']);
|
||||
echo $album->setPassword($_POST['password']);
|
||||
|
||||
}
|
||||
|
||||
private function deleteAlbum() {
|
||||
|
||||
Module::dependencies(isset($_POST['albumIDs']));
|
||||
$album = new Album($this->database, $this->plugins, $this->settings, $_POST['albumIDs']);
|
||||
echo $album->delete($_POST['albumIDs']);
|
||||
|
||||
}
|
||||
|
||||
# Photo functions
|
||||
|
||||
private function getPhoto() {
|
||||
|
||||
Module::dependencies(isset($_POST['photoID'], $_POST['albumID']));
|
||||
$photo = new Photo($this->database, $this->plugins, null, $_POST['photoID']);
|
||||
echo json_encode($photo->get($_POST['albumID']));
|
||||
|
||||
}
|
||||
|
||||
private function setPhotoTitle() {
|
||||
|
||||
Module::dependencies(isset($_POST['photoIDs'], $_POST['title']));
|
||||
$photo = new Photo($this->database, $this->plugins, null, $_POST['photoIDs']);
|
||||
echo $photo->setTitle($_POST['title']);
|
||||
|
||||
}
|
||||
|
||||
private function setPhotoDescription() {
|
||||
|
||||
Module::dependencies(isset($_POST['photoID'], $_POST['description']));
|
||||
$photo = new Photo($this->database, $this->plugins, null, $_POST['photoID']);
|
||||
echo $photo->setDescription($_POST['description']);
|
||||
|
||||
}
|
||||
|
||||
private function setPhotoStar() {
|
||||
|
||||
Module::dependencies(isset($_POST['photoIDs']));
|
||||
$photo = new Photo($this->database, $this->plugins, null, $_POST['photoIDs']);
|
||||
echo $photo->setStar();
|
||||
|
||||
}
|
||||
|
||||
private function setPhotoPublic() {
|
||||
|
||||
Module::dependencies(isset($_POST['photoID']));
|
||||
$photo = new Photo($this->database, $this->plugins, null, $_POST['photoID']);
|
||||
echo $photo->setPublic();
|
||||
|
||||
}
|
||||
|
||||
private function setPhotoAlbum() {
|
||||
|
||||
Module::dependencies(isset($_POST['photoIDs'], $_POST['albumID']));
|
||||
$photo = new Photo($this->database, $this->plugins, null, $_POST['photoIDs']);
|
||||
echo $photo->setAlbum($_POST['albumID']);
|
||||
|
||||
}
|
||||
|
||||
private function setPhotoTags() {
|
||||
|
||||
Module::dependencies(isset($_POST['photoIDs'], $_POST['tags']));
|
||||
$photo = new Photo($this->database, $this->plugins, null, $_POST['photoIDs']);
|
||||
echo $photo->setTags($_POST['tags']);
|
||||
|
||||
}
|
||||
|
||||
private function deletePhoto() {
|
||||
|
||||
Module::dependencies(isset($_POST['photoIDs']));
|
||||
$photo = new Photo($this->database, $this->plugins, null, $_POST['photoIDs']);
|
||||
echo $photo->delete();
|
||||
|
||||
}
|
||||
|
||||
# Add functions
|
||||
|
||||
private function upload() {
|
||||
|
||||
Module::dependencies(isset($_FILES, $_POST['albumID']));
|
||||
$photo = new Photo($this->database, $this->plugins, $this->settings, null);
|
||||
echo $photo->add($_FILES, $_POST['albumID']);
|
||||
|
||||
}
|
||||
|
||||
private function importUrl() {
|
||||
|
||||
Module::dependencies(isset($_POST['url'], $_POST['albumID']));
|
||||
echo Import::url($_POST['url'], $_POST['albumID']);
|
||||
|
||||
}
|
||||
|
||||
private function importServer() {
|
||||
|
||||
Module::dependencies(isset($_POST['albumID']));
|
||||
echo Import::server($_POST['albumID'], null);
|
||||
|
||||
}
|
||||
|
||||
# Search function
|
||||
|
||||
private function search() {
|
||||
|
||||
Module::dependencies(isset($_POST['term']));
|
||||
echo json_encode(search($this->database, $this->settings, $_POST['term']));
|
||||
|
||||
}
|
||||
|
||||
# Session functions
|
||||
|
||||
private function init() {
|
||||
|
||||
global $dbName;
|
||||
|
||||
Module::dependencies(isset($_POST['version']));
|
||||
$session = new Session($this->plugins, $this->settings);
|
||||
echo json_encode($session->init($this->database, $dbName, false, $_POST['version']));
|
||||
|
||||
}
|
||||
|
||||
private function login() {
|
||||
|
||||
Module::dependencies(isset($_POST['user'], $_POST['password']));
|
||||
$session = new Session($this->plugins, $this->settings);
|
||||
echo $session->login($_POST['user'], $_POST['password']);
|
||||
|
||||
}
|
||||
|
||||
private function logout() {
|
||||
|
||||
$session = new Session($this->plugins, $this->settings);
|
||||
echo $session->logout();
|
||||
|
||||
}
|
||||
|
||||
# Settings functions
|
||||
|
||||
private function setLogin() {
|
||||
|
||||
Module::dependencies(isset($_POST['username'], $_POST['password']));
|
||||
if (!isset($_POST['oldPassword'])) $_POST['oldPassword'] = '';
|
||||
$this->settings = new Settings($this->database);
|
||||
echo $this->settings->setLogin($_POST['oldPassword'], $_POST['username'], $_POST['password']);
|
||||
|
||||
}
|
||||
|
||||
private function setSorting() {
|
||||
|
||||
Module::dependencies(isset($_POST['type'], $_POST['order']));
|
||||
$this->settings = new Settings($this->database);
|
||||
echo $this->settings->setSorting($_POST['type'], $_POST['order']);
|
||||
|
||||
}
|
||||
|
||||
private function setDropboxKey() {
|
||||
|
||||
Module::dependencies(isset($_POST['key']));
|
||||
$this->settings = new Settings($this->database);
|
||||
echo $this->settings->setDropboxKey($_POST['key']);
|
||||
|
||||
}
|
||||
|
||||
# Get functions
|
||||
|
||||
private function getAlbumArchive() {
|
||||
|
||||
Module::dependencies(isset($_GET['albumID']));
|
||||
$album = new Album($this->database, $this->plugins, $this->settings, $_GET['albumID']);
|
||||
$album->getArchive();
|
||||
|
||||
}
|
||||
|
||||
private function getPhotoArchive() {
|
||||
|
||||
Module::dependencies(isset($_GET['photoID']));
|
||||
$photo = new Photo($this->database, $this->plugins, null, $_GET['photoID']);
|
||||
$photo->getArchive();
|
||||
|
||||
}
|
||||
|
||||
}
|
176
php/access/Guest.php
Normal file
176
php/access/Guest.php
Normal file
@ -0,0 +1,176 @@
|
||||
<?php
|
||||
|
||||
###
|
||||
# @name Guest Access (Public Mode)
|
||||
# @author Tobias Reich
|
||||
# @copyright 2014 by Tobias Reich
|
||||
###
|
||||
|
||||
if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
|
||||
if (!defined('LYCHEE_ACCESS_GUEST')) exit('Error: You are not allowed to access this area!');
|
||||
|
||||
class Guest extends Access {
|
||||
|
||||
public function check($fn) {
|
||||
|
||||
switch ($fn) {
|
||||
|
||||
# Album functions
|
||||
case 'getAlbums': $this->getAlbums(); break;
|
||||
case 'getAlbum': $this->getAlbum(); break;
|
||||
case 'checkAlbumAccess': $this->checkAlbumAccess(); break;
|
||||
|
||||
# Photo functions
|
||||
case 'getPhoto': $this->getPhoto(); break;
|
||||
|
||||
# Session functions
|
||||
case 'init': $this->init(); break;
|
||||
case 'login': $this->login(); break;
|
||||
case 'logout': $this->logout(); break;
|
||||
|
||||
# $_GET functions
|
||||
case 'getAlbumArchive': $this->getAlbumArchive(); break;
|
||||
case 'getPhotoArchive': $this->getPhotoArchive(); break;
|
||||
|
||||
# Error
|
||||
default: exit('Error: Function not found! Please check the spelling of the called function.');
|
||||
return false; break;
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
# Album functions
|
||||
|
||||
private function getAlbums() {
|
||||
|
||||
$album = new Album($this->database, $this->plugins, $this->settings, null);
|
||||
echo json_encode($album->getAll(true));
|
||||
|
||||
}
|
||||
|
||||
private function getAlbum() {
|
||||
|
||||
Module::dependencies(isset($_POST['albumID'], $_POST['password']));
|
||||
$album = new Album($this->database, $this->plugins, $this->settings, $_POST['albumID']);
|
||||
|
||||
if ($album->getPublic()) {
|
||||
|
||||
# Album public
|
||||
if ($album->checkPassword($_POST['password'])) echo json_encode($album->get());
|
||||
else echo 'Warning: Wrong password!';
|
||||
|
||||
} else {
|
||||
|
||||
# Album private
|
||||
echo 'Warning: Album private!';
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private function checkAlbumAccess() {
|
||||
|
||||
Module::dependencies(isset($_POST['albumID'], $_POST['password']));
|
||||
$album = new Album($this->database, $this->plugins, $this->settings, $_POST['albumID']);
|
||||
|
||||
if ($album->getPublic()) {
|
||||
|
||||
# Album public
|
||||
if ($album->checkPassword($_POST['password'])) echo true;
|
||||
else echo false;
|
||||
|
||||
} else {
|
||||
|
||||
# Album private
|
||||
echo false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Photo functions
|
||||
|
||||
private function getPhoto() {
|
||||
|
||||
Module::dependencies(isset($_POST['photoID'], $_POST['albumID'], $_POST['password']));
|
||||
$photo = new Photo($this->database, $this->plugins, null, $_POST['photoID']);
|
||||
|
||||
if ($photo->getPublic($_POST['password'])) echo json_encode($photo->get($_POST['albumID']));
|
||||
else echo 'Warning: Wrong password!';
|
||||
|
||||
}
|
||||
|
||||
# Session functions
|
||||
|
||||
private function init() {
|
||||
|
||||
global $dbName;
|
||||
|
||||
$session = new Session($this->plugins, $this->settings);
|
||||
echo json_encode($session->init($this->database, $dbName, true, $_POST['version']));
|
||||
|
||||
}
|
||||
|
||||
private function login() {
|
||||
|
||||
Module::dependencies(isset($_POST['user'], $_POST['password']));
|
||||
$session = new Session($this->plugins, $this->settings);
|
||||
echo $session->login($_POST['user'], $_POST['password']);
|
||||
|
||||
}
|
||||
|
||||
private function logout() {
|
||||
|
||||
$session = new Session($this->plugins, $this->settings);
|
||||
echo $session->logout();
|
||||
|
||||
}
|
||||
|
||||
# $_GET functions
|
||||
|
||||
private function getAlbumArchive() {
|
||||
|
||||
Module::dependencies(isset($_GET['albumID'], $_GET['password']));
|
||||
$album = new Album($this->database, $this->plugins, $this->settings, $_GET['albumID']);
|
||||
|
||||
if ($album->getPublic()) {
|
||||
|
||||
# Album Public
|
||||
if ($album->checkPassword($_GET['password'])) $album->getArchive();
|
||||
else exit('Warning: Wrong password!');
|
||||
|
||||
} else {
|
||||
|
||||
# Album Private
|
||||
exit('Warning: Album private or not downloadable!');
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private function getPhotoArchive() {
|
||||
|
||||
Module::dependencies(isset($_GET['photoID'], $_GET['password']));
|
||||
$photo = new Photo($this->database, $this->plugins, null, $_GET['photoID']);
|
||||
|
||||
# Photo Download
|
||||
if ($photo->getPublic($_GET['password'])) {
|
||||
|
||||
# Photo Public
|
||||
$photo->getArchive();
|
||||
|
||||
} else {
|
||||
|
||||
# Photo Private
|
||||
exit('Warning: Photo private or not downloadable!');
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
39
php/access/Installation.php
Normal file
39
php/access/Installation.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
###
|
||||
# @name Installation Access
|
||||
# @author Tobias Reich
|
||||
# @copyright 2014 by Tobias Reich
|
||||
###
|
||||
|
||||
if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
|
||||
if (!defined('LYCHEE_ACCESS_INSTALLATION')) exit('Error: You are not allowed to access this area!');
|
||||
|
||||
class Installation extends Access {
|
||||
|
||||
public function check($fn) {
|
||||
|
||||
switch ($fn) {
|
||||
|
||||
case 'dbCreateConfig': $this->dbCreateConfig(); break;
|
||||
|
||||
# Error
|
||||
default: exit('Warning: No configuration!');
|
||||
return false; break;
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
private function dbCreateConfig() {
|
||||
|
||||
Module::dependencies(isset($_POST['dbHost'], $_POST['dbUser'], $_POST['dbPassword'], $_POST['dbName']));
|
||||
echo Database::createConfig($_POST['dbHost'], $_POST['dbUser'], $_POST['dbPassword'], $_POST['dbName']);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
@ -1,157 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @name Admin Access
|
||||
* @author Tobias Reich
|
||||
* @copyright 2014 by Tobias Reich
|
||||
*/
|
||||
|
||||
if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
|
||||
if (!defined('LYCHEE_ACCESS_ADMIN')) exit('Error: You are not allowed to access this area!');
|
||||
|
||||
switch ($_POST['function']) {
|
||||
|
||||
// Album Functions
|
||||
|
||||
case 'getAlbums': echo json_encode(getAlbums(false));
|
||||
break;
|
||||
|
||||
case 'getAlbum': if (isset($_POST['albumID']))
|
||||
echo json_encode(getAlbum($_POST['albumID']));
|
||||
break;
|
||||
|
||||
case 'addAlbum': if (isset($_POST['title']))
|
||||
echo addAlbum($_POST['title']);
|
||||
break;
|
||||
|
||||
case 'setAlbumTitle': if (isset($_POST['albumIDs'], $_POST['title']))
|
||||
echo setAlbumTitle($_POST['albumIDs'], $_POST['title']);
|
||||
break;
|
||||
|
||||
case 'setAlbumDescription': if (isset($_POST['albumID'], $_POST['description']))
|
||||
echo setAlbumDescription($_POST['albumID'], $_POST['description']);
|
||||
break;
|
||||
|
||||
case 'setAlbumPublic': if (isset($_POST['albumID']))
|
||||
if (!isset($_POST['password'])) $_POST['password'] = '';
|
||||
echo setAlbumPublic($_POST['albumID'], $_POST['password']);
|
||||
break;
|
||||
|
||||
case 'setAlbumPassword': if (isset($_POST['albumID'], $_POST['password']))
|
||||
echo setAlbumPassword($_POST['albumID'], $_POST['password']);
|
||||
break;
|
||||
|
||||
case 'deleteAlbum': if (isset($_POST['albumIDs']))
|
||||
echo deleteAlbum($_POST['albumIDs']);
|
||||
break;
|
||||
|
||||
// Photo Functions
|
||||
|
||||
case 'getPhoto': if (isset($_POST['photoID'], $_POST['albumID']))
|
||||
echo json_encode(getPhoto($_POST['photoID'], $_POST['albumID']));
|
||||
break;
|
||||
|
||||
case 'deletePhoto': if (isset($_POST['photoIDs']))
|
||||
echo deletePhoto($_POST['photoIDs']);
|
||||
break;
|
||||
|
||||
case 'setPhotoAlbum': if (isset($_POST['photoIDs'], $_POST['albumID']))
|
||||
echo setPhotoAlbum($_POST['photoIDs'], $_POST['albumID']);
|
||||
break;
|
||||
|
||||
case 'setPhotoTitle': if (isset($_POST['photoIDs'], $_POST['title']))
|
||||
echo setPhotoTitle($_POST['photoIDs'], $_POST['title']);
|
||||
break;
|
||||
|
||||
case 'setPhotoStar': if (isset($_POST['photoIDs']))
|
||||
echo setPhotoStar($_POST['photoIDs']);
|
||||
break;
|
||||
|
||||
case 'setPhotoPublic': if (isset($_POST['photoID'], $_POST['url']))
|
||||
echo setPhotoPublic($_POST['photoID'], $_POST['url']);
|
||||
break;
|
||||
|
||||
case 'setPhotoDescription': if (isset($_POST['photoID'], $_POST['description']))
|
||||
echo setPhotoDescription($_POST['photoID'], $_POST['description']);
|
||||
break;
|
||||
|
||||
case 'setPhotoTags': if (isset($_POST['photoIDs'], $_POST['tags']))
|
||||
echo setPhotoTags($_POST['photoIDs'], $_POST['tags']);
|
||||
break;
|
||||
|
||||
// Add Functions
|
||||
|
||||
case 'upload': if (isset($_FILES, $_POST['albumID']))
|
||||
echo upload($_FILES, $_POST['albumID']);
|
||||
break;
|
||||
|
||||
case 'importUrl': if (isset($_POST['url'], $_POST['albumID']))
|
||||
echo importUrl($_POST['url'], $_POST['albumID']);
|
||||
break;
|
||||
|
||||
case 'importServer': if (isset($_POST['albumID']))
|
||||
echo importServer($_POST['albumID']);
|
||||
break;
|
||||
|
||||
// Search Function
|
||||
|
||||
case 'search': if (isset($_POST['term']))
|
||||
echo json_encode(search($_POST['term']));
|
||||
break;
|
||||
|
||||
// Session Function
|
||||
|
||||
case 'init': echo json_encode(init('admin', $_POST['version']));
|
||||
break;
|
||||
|
||||
case 'login': if (isset($_POST['user'], $_POST['password']))
|
||||
echo login($_POST['user'], $_POST['password']);
|
||||
break;
|
||||
|
||||
case 'logout': logout();
|
||||
break;
|
||||
|
||||
// Settings
|
||||
|
||||
case 'setLogin': if (isset($_POST['username'], $_POST['password']))
|
||||
if (!isset($_POST['oldPassword'])) $_POST['oldPassword'] = '';
|
||||
echo setLogin($_POST['oldPassword'], $_POST['username'], $_POST['password']);
|
||||
break;
|
||||
|
||||
case 'setSorting': if (isset($_POST['type'], $_POST['order']))
|
||||
echo setSorting($_POST['type'], $_POST['order']);
|
||||
break;
|
||||
|
||||
case 'setDropboxKey': if (isset($_POST['key']))
|
||||
echo setDropboxKey($_POST['key']);
|
||||
break;
|
||||
|
||||
// Miscellaneous
|
||||
|
||||
default: switch ($_GET['function']) {
|
||||
|
||||
case 'getFeed': if (isset($_GET['albumID']))
|
||||
echo getFeed($_GET['albumID']);
|
||||
break;
|
||||
|
||||
case 'getAlbumArchive': if (isset($_GET['albumID']))
|
||||
getAlbumArchive($_GET['albumID']);
|
||||
break;
|
||||
|
||||
case 'getPhotoArchive': if (isset($_GET['photoID']))
|
||||
getPhotoArchive($_GET['photoID']);
|
||||
break;
|
||||
|
||||
case 'update': echo update();
|
||||
break;
|
||||
|
||||
default: exit('Error: Function not found! Please check the spelling of the called function.');
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
?>
|
@ -1,126 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @name Guest Access (Public Mode)
|
||||
* @author Tobias Reich
|
||||
* @copyright 2014 by Tobias Reich
|
||||
*/
|
||||
|
||||
if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
|
||||
if (!defined('LYCHEE_ACCESS_GUEST')) exit('Error: You are not allowed to access this area!');
|
||||
|
||||
switch ($_POST['function']) {
|
||||
|
||||
// Album Functions
|
||||
|
||||
case 'getAlbums': echo json_encode(getAlbums(true));
|
||||
break;
|
||||
|
||||
case 'getAlbum': if (isset($_POST['albumID'], $_POST['password'])) {
|
||||
if (isAlbumPublic($_POST['albumID'])) {
|
||||
// Album Public
|
||||
if (checkAlbumPassword($_POST['albumID'], $_POST['password']))
|
||||
echo json_encode(getAlbum($_POST['albumID']));
|
||||
else
|
||||
echo 'Warning: Wrong password!';
|
||||
} else {
|
||||
// Album Private
|
||||
echo 'Warning: Album private!';
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'checkAlbumAccess':if (isset($_POST['albumID'], $_POST['password'])) {
|
||||
if (isAlbumPublic($_POST['albumID'])) {
|
||||
// Album Public
|
||||
if (checkAlbumPassword($_POST['albumID'], $_POST['password']))
|
||||
echo true;
|
||||
else
|
||||
echo false;
|
||||
} else {
|
||||
// Album Private
|
||||
echo false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// Photo Functions
|
||||
|
||||
case 'getPhoto': if (isset($_POST['photoID'], $_POST['albumID'], $_POST['password'])) {
|
||||
if (isPhotoPublic($_POST['photoID'], $_POST['password']))
|
||||
echo json_encode(getPhoto($_POST['photoID'], $_POST['albumID']));
|
||||
else
|
||||
echo 'Warning: Wrong password!';
|
||||
}
|
||||
break;
|
||||
|
||||
// Session Functions
|
||||
|
||||
case 'init': echo json_encode(init('public', $_POST['version']));
|
||||
break;
|
||||
|
||||
case 'login': if (isset($_POST['user'], $_POST['password']))
|
||||
echo login($_POST['user'], $_POST['password']);
|
||||
break;
|
||||
|
||||
// Miscellaneous
|
||||
|
||||
default: switch ($_GET['function']) {
|
||||
|
||||
case 'getFeed': if (isset($_GET['albumID'], $_GET['password'])) {
|
||||
|
||||
// Album Feed
|
||||
if (isAlbumPublic($_GET['albumID'])) {
|
||||
// Album Public
|
||||
if (checkAlbumPassword($_GET['albumID'], $_GET['password']))
|
||||
echo getFeed($_GET['albumID']);
|
||||
else
|
||||
exit('Warning: Wrong password!');
|
||||
} else {
|
||||
// Album Private
|
||||
exit('Warning: Album private!');
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case 'getAlbumArchive': if (isset($_GET['albumID'], $_GET['password'])) {
|
||||
|
||||
// Album Download
|
||||
if (isAlbumPublic($_GET['albumID'])) {
|
||||
// Album Public
|
||||
if (checkAlbumPassword($_GET['albumID'], $_GET['password']))
|
||||
getAlbumArchive($_GET['albumID']);
|
||||
else
|
||||
exit('Warning: Wrong password!');
|
||||
} else {
|
||||
// Album Private
|
||||
exit('Warning: Album private or not downloadable!');
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case 'getPhotoArchive': if (isset($_GET['photoID'], $_GET['password'])) {
|
||||
|
||||
// Photo Download
|
||||
if (isPhotoPublic($_GET['photoID'], $_GET['password']))
|
||||
// Photo Public
|
||||
getPhotoArchive($_GET['photoID']);
|
||||
else
|
||||
// Photo Private
|
||||
exit('Warning: Photo private or not downloadable!');
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
default: exit('Error: Function not found! Please check the spelling of the called function.');
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
?>
|
@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @name Installation Access
|
||||
* @author Tobias Reich
|
||||
* @copyright 2014 by Tobias Reich
|
||||
*/
|
||||
|
||||
if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
|
||||
if (!defined('LYCHEE_ACCESS_INSTALLATION')) exit('Error: You are not allowed to access this area!');
|
||||
|
||||
switch ($_POST['function']) {
|
||||
|
||||
case 'dbCreateConfig': if (isset($_POST['dbHost'], $_POST['dbUser'], $_POST['dbPassword'], $_POST['dbName'], $_POST['version']))
|
||||
echo dbCreateConfig($_POST['dbHost'], $_POST['dbUser'], $_POST['dbPassword'], $_POST['dbName'], $_POST['version']);
|
||||
break;
|
||||
|
||||
default: echo 'Warning: No configuration!';
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
?>
|
91
php/api.php
91
php/api.php
@ -1,10 +1,10 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @name API
|
||||
* @author Tobias Reich
|
||||
* @copyright 2014 by Tobias Reich
|
||||
*/
|
||||
###
|
||||
# @name API
|
||||
# @author Tobias Reich
|
||||
# @copyright 2014 by Tobias Reich
|
||||
###
|
||||
|
||||
@ini_set('max_execution_time', '200');
|
||||
@ini_set('post_max_size', '200M');
|
||||
@ -15,75 +15,88 @@
|
||||
if (!empty($_POST['function'])||!empty($_GET['function'])) {
|
||||
|
||||
session_start();
|
||||
define('LYCHEE', true);
|
||||
date_default_timezone_set('UTC');
|
||||
|
||||
// Load modules
|
||||
require('modules/album.php');
|
||||
require('modules/db.php');
|
||||
require('modules/misc.php');
|
||||
require('modules/photo.php');
|
||||
require('modules/session.php');
|
||||
require('modules/settings.php');
|
||||
require('modules/upload.php');
|
||||
# Define globals
|
||||
require(__DIR__ . '/define.php');
|
||||
|
||||
if (file_exists('../data/config.php')) require('../data/config.php');
|
||||
# Load autoload
|
||||
require(__DIR__ . '/autoload.php');
|
||||
|
||||
# Load modules
|
||||
require(__DIR__ . '/modules/misc.php');
|
||||
|
||||
if (file_exists(LYCHEE_CONFIG_FILE)) require(LYCHEE_CONFIG_FILE);
|
||||
else {
|
||||
|
||||
/**
|
||||
* Installation Access
|
||||
* Limited access to configure Lychee. Only available when the config.php file is missing.
|
||||
*/
|
||||
###
|
||||
# Installation Access
|
||||
# Limited access to configure Lychee. Only available when the config.php file is missing.
|
||||
###
|
||||
|
||||
define('LYCHEE_ACCESS_INSTALLATION', true);
|
||||
require('access/installation.php');
|
||||
|
||||
$installation = new Installation(null, null, null);
|
||||
$installation->check($_POST['function']);
|
||||
|
||||
exit();
|
||||
|
||||
}
|
||||
|
||||
// Connect and get settings
|
||||
$database = dbConnect();
|
||||
$settings = getSettings();
|
||||
# Connect to database
|
||||
$database = Database::connect($dbHost, $dbUser, $dbPassword, $dbName);
|
||||
|
||||
// Escape
|
||||
# Load settings
|
||||
$settings = new Settings($database);
|
||||
$settings = $settings->get();
|
||||
|
||||
# Init plugins
|
||||
$plugins = explode(';', $settings['plugins']);
|
||||
$plugins = new Plugins($plugins, $database, $settings);
|
||||
|
||||
# Escape
|
||||
foreach(array_keys($_POST) as $key) $_POST[$key] = mysqli_real_escape_string($database, urldecode($_POST[$key]));
|
||||
foreach(array_keys($_GET) as $key) $_GET[$key] = mysqli_real_escape_string($database, urldecode($_GET[$key]));
|
||||
|
||||
// Validate parameters
|
||||
# Validate parameters
|
||||
if (isset($_POST['albumIDs'])&&preg_match('/^[0-9\,]{1,}$/', $_POST['albumIDs'])!==1) exit('Error: Wrong parameter type for albumIDs!');
|
||||
if (isset($_POST['photoIDs'])&&preg_match('/^[0-9\,]{1,}$/', $_POST['photoIDs'])!==1) exit('Error: Wrong parameter type for photoIDs!');
|
||||
if (isset($_POST['albumID'])&&preg_match('/^[0-9sf]{1,}$/', $_POST['albumID'])!==1) exit('Error: Wrong parameter type for albumID!');
|
||||
if (isset($_POST['photoID'])&&preg_match('/^[0-9]{14}$/', $_POST['photoID'])!==1) exit('Error: Wrong parameter type for photoID!');
|
||||
|
||||
// Fallback for switch statement
|
||||
if (!isset($_POST['function'])) $_POST['function'] = '';
|
||||
if (!isset($_GET['function'])) $_GET['function'] = '';
|
||||
# Function for switch statement
|
||||
if (isset($_POST['function'])) $fn = $_POST['function'];
|
||||
else $fn = $_GET['function'];
|
||||
|
||||
if (isset($_SESSION['login'])&&$_SESSION['login']==true) {
|
||||
|
||||
/**
|
||||
* Admin Access
|
||||
* Full access to Lychee. Only with correct password/session.
|
||||
*/
|
||||
###
|
||||
# Admin Access
|
||||
# Full access to Lychee. Only with correct password/session.
|
||||
###
|
||||
|
||||
define('LYCHEE_ACCESS_ADMIN', true);
|
||||
require('access/admin.php');
|
||||
|
||||
$admin = new Admin($database, $plugins, $settings);
|
||||
$admin->check($fn);
|
||||
|
||||
} else {
|
||||
|
||||
/**
|
||||
* Guest Access
|
||||
* Access to view all public folders and photos in Lychee.
|
||||
*/
|
||||
###
|
||||
# Guest Access
|
||||
# Access to view all public folders and photos in Lychee.
|
||||
###
|
||||
|
||||
define('LYCHEE_ACCESS_GUEST', true);
|
||||
require('access/guest.php');
|
||||
|
||||
$guest = new Guest($database, $plugins, $settings);
|
||||
$guest->check($fn);
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
exit('Error: No permission!');
|
||||
exit('Error: Called function not found!');
|
||||
|
||||
}
|
||||
|
||||
|
28
php/autoload.php
Normal file
28
php/autoload.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
###
|
||||
# @name Autoload
|
||||
# @author Tobias Reich
|
||||
# @copyright 2014 by Tobias Reich
|
||||
###
|
||||
|
||||
if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
|
||||
|
||||
function lycheeAutoloaderModules($class_name) {
|
||||
|
||||
$file = LYCHEE . 'php/modules/' . $class_name . '.php';
|
||||
if (file_exists($file)!==false) require $file;
|
||||
|
||||
}
|
||||
|
||||
function lycheeAutoloaderAccess($class_name) {
|
||||
|
||||
$file = LYCHEE . 'php/access/' . $class_name . '.php';
|
||||
if (file_exists($file)!==false) require $file;
|
||||
|
||||
}
|
||||
|
||||
spl_autoload_register('lycheeAutoloaderModules');
|
||||
spl_autoload_register('lycheeAutoloaderAccess');
|
||||
|
||||
?>
|
14
php/database/albums_table.sql
Normal file
14
php/database/albums_table.sql
Normal file
@ -0,0 +1,14 @@
|
||||
# Dump of table lychee_albums
|
||||
# Version 2.5
|
||||
# ------------------------------------------------------------
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `lychee_albums` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(50) NOT NULL,
|
||||
`description` varchar(1000) DEFAULT '',
|
||||
`sysstamp` int(11) NOT NULL,
|
||||
`public` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`visible` tinyint(1) NOT NULL DEFAULT '1',
|
||||
`password` varchar(100) DEFAULT '',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
|
13
php/database/log_table.sql
Normal file
13
php/database/log_table.sql
Normal file
@ -0,0 +1,13 @@
|
||||
# Dump of table lychee_log
|
||||
# Version 2.5
|
||||
# ------------------------------------------------------------
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `lychee_log` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`time` int(11) NOT NULL,
|
||||
`type` varchar(11) NOT NULL,
|
||||
`function` varchar(100) NOT NULL,
|
||||
`line` int(11) NOT NULL,
|
||||
`text` TEXT,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
|
27
php/database/photos_table.sql
Normal file
27
php/database/photos_table.sql
Normal file
@ -0,0 +1,27 @@
|
||||
# Dump of table lychee_photos
|
||||
# Version 2.5
|
||||
# ------------------------------------------------------------
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `lychee_photos` (
|
||||
`id` bigint(14) NOT NULL,
|
||||
`title` varchar(50) NOT NULL,
|
||||
`description` varchar(1000) DEFAULT '',
|
||||
`url` varchar(100) NOT NULL,
|
||||
`tags` varchar(1000) NOT NULL DEFAULT '',
|
||||
`public` tinyint(1) NOT NULL,
|
||||
`type` varchar(10) NOT NULL,
|
||||
`width` int(11) NOT NULL,
|
||||
`height` int(11) NOT NULL,
|
||||
`size` varchar(20) NOT NULL,
|
||||
`iso` varchar(15) NOT NULL,
|
||||
`aperture` varchar(20) NOT NULL,
|
||||
`make` varchar(50) NOT NULL,
|
||||
`model` varchar(50) NOT NULL,
|
||||
`shutter` varchar(30) NOT NULL,
|
||||
`focal` varchar(20) NOT NULL,
|
||||
`takestamp` int(11) DEFAULT NULL,
|
||||
`star` tinyint(1) NOT NULL,
|
||||
`thumbUrl` varchar(50) NOT NULL,
|
||||
`album` varchar(30) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
|
14
php/database/settings_content.sql
Normal file
14
php/database/settings_content.sql
Normal file
@ -0,0 +1,14 @@
|
||||
# Content of table lychee_settings
|
||||
# Version 2.5
|
||||
# ------------------------------------------------------------
|
||||
|
||||
INSERT INTO `lychee_settings` (`key`, `value`)
|
||||
VALUES
|
||||
('version',''),
|
||||
('username',''),
|
||||
('password',''),
|
||||
('thumbQuality','90'),
|
||||
('checkForUpdates','1'),
|
||||
('sorting','ORDER BY id DESC'),
|
||||
('dropboxKey',''),
|
||||
('plugins','');
|
8
php/database/settings_table.sql
Normal file
8
php/database/settings_table.sql
Normal file
@ -0,0 +1,8 @@
|
||||
# Dump of table lychee_settings
|
||||
# Version 2.5
|
||||
# ------------------------------------------------------------
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `lychee_settings` (
|
||||
`key` varchar(50) NOT NULL DEFAULT '',
|
||||
`value` varchar(200) DEFAULT ''
|
||||
) ENGINE=MyISAM DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
|
41
php/database/update_020100.php
Normal file
41
php/database/update_020100.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
###
|
||||
# @name Update to version 2.1
|
||||
# @author Tobias Reich
|
||||
# @copyright 2014 by Tobias Reich
|
||||
###
|
||||
|
||||
if(!$database->query("SELECT `tags` FROM `lychee_photos` LIMIT 1;")) {
|
||||
$result = $database->query("ALTER TABLE `lychee_photos` ADD `tags` VARCHAR( 1000 ) NULL DEFAULT ''");
|
||||
if (!$result) {
|
||||
Log::error($database, 'update_020100', __LINE__, 'Could not update database (' . $database->error . ')');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$result = $database->query("SELECT `key` FROM `lychee_settings` WHERE `key` = 'dropboxKey' LIMIT 1;");
|
||||
if ($result->num_rows===0) {
|
||||
$result = $database->query("INSERT INTO `lychee_settings` (`key`, `value`) VALUES ('dropboxKey', '')");
|
||||
if (!$result) {
|
||||
Log::error($database, 'update_020100', __LINE__, 'Could not update database (' . $database->error . ')');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$result = $database->query("SELECT `key` FROM `lychee_settings` WHERE `key` = 'version' LIMIT 1;");
|
||||
if ($result->num_rows===0) {
|
||||
$result = $database->query("INSERT INTO `lychee_settings` (`key`, `value`) VALUES ('version', '020100')");
|
||||
if (!$result) {
|
||||
Log::error($database, 'update_020100', __LINE__, 'Could not update database (' . $database->error . ')');
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$result = $database->query("UPDATE lychee_settings SET value = '020100' WHERE `key` = 'version';");
|
||||
if (!$result) {
|
||||
Log::error($database, 'update_020100', __LINE__, 'Could not update database (' . $database->error . ')');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
21
php/database/update_020101.php
Normal file
21
php/database/update_020101.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
###
|
||||
# @name Update to version 2.1.1
|
||||
# @author Tobias Reich
|
||||
# @copyright 2014 by Tobias Reich
|
||||
###
|
||||
|
||||
$result = $database->query("ALTER TABLE `lychee_settings` CHANGE `value` `value` VARCHAR( 200 ) NULL DEFAULT ''");
|
||||
if (!$result) {
|
||||
Log::error($database, 'update_020101', __LINE__, 'Could not update database (' . $database->error . ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = $database->query("UPDATE lychee_settings SET value = '020101' WHERE `key` = 'version';");
|
||||
if (!$result) {
|
||||
Log::error($database, 'update_020101', __LINE__, 'Could not update database (' . $database->error . ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
?>
|
23
php/database/update_020200.php
Normal file
23
php/database/update_020200.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
###
|
||||
# @name Update to version 2.2
|
||||
# @author Tobias Reich
|
||||
# @copyright 2014 by Tobias Reich
|
||||
###
|
||||
|
||||
if (!$database->query("SELECT `visible` FROM `lychee_albums` LIMIT 1;")) {
|
||||
$result = $database->query("ALTER TABLE `lychee_albums` ADD `visible` TINYINT(1) NOT NULL DEFAULT 1");
|
||||
if (!$result) {
|
||||
Log::error($database, 'update_020200', __LINE__, 'Could not update database (' . $database->error . ')');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$result = $database->query("UPDATE lychee_settings SET value = '020200' WHERE `key` = 'version';");
|
||||
if (!$result) {
|
||||
Log::error($database, 'update_020200', __LINE__, 'Could not update database (' . $database->error . ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
?>
|
133
php/database/update_020500.php
Normal file
133
php/database/update_020500.php
Normal file
@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
###
|
||||
# @name Update to version 2.5
|
||||
# @author Tobias Reich
|
||||
# @copyright 2014 by Tobias Reich
|
||||
###
|
||||
|
||||
# Add `plugins`
|
||||
$result = $database->query("SELECT `key` FROM `lychee_settings` WHERE `key` = 'plugins' LIMIT 1;");
|
||||
if ($result->num_rows===0) {
|
||||
$result = $database->query("INSERT INTO `lychee_settings` (`key`, `value`) VALUES ('plugins', '')");
|
||||
if (!$result) {
|
||||
Log::error($database, 'update_020500', __LINE__, 'Could not update database (' . $database->error . ')');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
# Add `takestamp`
|
||||
if (!$database->query("SELECT `takestamp` FROM `lychee_photos` LIMIT 1;")) {
|
||||
$result = $database->query("ALTER TABLE `lychee_photos` ADD `takestamp` INT(11) DEFAULT NULL");
|
||||
if (!$result) {
|
||||
Log::error($database, 'update_020500', __LINE__, 'Could not update database (' . $database->error . ')');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
# Convert to `takestamp`
|
||||
if ($database->query("SELECT `takedate`, `taketime` FROM `lychee_photos` LIMIT 1;")) {
|
||||
$result = $database->query("SELECT `id`, `takedate`, `taketime` FROM `lychee_photos` WHERE `takedate` <> '' AND `taketime` <> '';");
|
||||
if (!$result) {
|
||||
Log::error($database, 'update_020500', __LINE__, 'Could not update database (' . $database->error . ')');
|
||||
return false;
|
||||
}
|
||||
while ($photo = $result->fetch_object()) {
|
||||
$takestamp = strtotime($photo->takedate . $photo->taketime);
|
||||
$database->query("UPDATE `lychee_photos` SET `takestamp` = '$takestamp' WHERE `id` = '$photo->id';");
|
||||
}
|
||||
$result = $database->query("ALTER TABLE `lychee_photos` DROP COLUMN `takedate`;");
|
||||
$result = $database->query("ALTER TABLE `lychee_photos` DROP COLUMN `taketime`;");
|
||||
}
|
||||
|
||||
# Remove `import_name`
|
||||
if ($database->query("SELECT `import_name` FROM `lychee_photos` LIMIT 1;")) {
|
||||
$result = $database->query("ALTER TABLE `lychee_photos` DROP COLUMN `import_name`;");
|
||||
}
|
||||
|
||||
# Remove `sysdate` and `systime`
|
||||
if ($database->query("SELECT `sysdate`, `systime` FROM `lychee_photos` LIMIT 1;")) {
|
||||
$result = $database->query("ALTER TABLE `lychee_photos` DROP COLUMN `sysdate`;");
|
||||
$result = $database->query("ALTER TABLE `lychee_photos` DROP COLUMN `systime`;");
|
||||
}
|
||||
|
||||
# Add `sysstamp`
|
||||
if (!$database->query("SELECT `sysstamp` FROM `lychee_albums` LIMIT 1;")) {
|
||||
$result = $database->query("ALTER TABLE `lychee_albums` ADD `sysstamp` INT(11) DEFAULT NULL");
|
||||
if (!$result) {
|
||||
Log::error($database, 'update_020500', __LINE__, 'Could not update database (' . $database->error . ')');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
# Convert to `sysstamp`
|
||||
if ($database->query("SELECT `sysdate` FROM `lychee_albums` LIMIT 1;")) {
|
||||
$result = $database->query("SELECT `id`, `sysdate` FROM `lychee_albums`;");
|
||||
if (!$result) {
|
||||
Log::error($database, 'update_020500', __LINE__, 'Could not update database (' . $database->error . ')');
|
||||
return false;
|
||||
}
|
||||
while ($album = $result->fetch_object()) {
|
||||
$sysstamp = strtotime($album->sysdate);
|
||||
$database->query("UPDATE `lychee_albums` SET `sysstamp` = '$sysstamp' WHERE `id` = '$album->id';");
|
||||
}
|
||||
$result = $database->query("ALTER TABLE `lychee_albums` DROP COLUMN `sysdate`;");
|
||||
}
|
||||
|
||||
# Set character of database
|
||||
$result = $database->query("ALTER DATABASE $dbName CHARACTER SET utf8 COLLATE utf8_general_ci;");
|
||||
if (!$result) {
|
||||
Log::error($database, 'update_020500', __LINE__, 'Could not update database (' . $database->error . ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
# Set character
|
||||
$result = $database->query("ALTER TABLE `lychee_albums` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;");
|
||||
if (!$result) {
|
||||
Log::error($database, 'update_020500', __LINE__, 'Could not update database (' . $database->error . ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
# Set character
|
||||
$result = $database->query("ALTER TABLE `lychee_photos` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;");
|
||||
if (!$result) {
|
||||
Log::error($database, 'update_020500', __LINE__, 'Could not update database (' . $database->error . ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
# Set character
|
||||
$result = $database->query("ALTER TABLE `lychee_settings` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;");
|
||||
if (!$result) {
|
||||
Log::error($database, 'update_020500', __LINE__, 'Could not update database (' . $database->error . ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
# Set album password length to 100 (for longer hashes)
|
||||
$result = $database->query("ALTER TABLE `lychee_albums` CHANGE `password` `password` VARCHAR(100);");
|
||||
if (!$result) {
|
||||
Log::error($database, 'update_020500', __LINE__, 'Could not update database (' . $database->error . ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
# Set make length to 50
|
||||
$result = $database->query("ALTER TABLE `lychee_photos` CHANGE `make` `make` VARCHAR(50);");
|
||||
if (!$result) {
|
||||
Log::error($database, 'update_020500', __LINE__, 'Could not update database (' . $database->error . ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
# Reset sorting
|
||||
$result = $database->query("UPDATE lychee_settings SET value = 'ORDER BY takestamp DESC' WHERE `key` = 'sorting' AND `value` LIKE '%UNIX_TIMESTAMP%';");
|
||||
if (!$result) {
|
||||
Log::error($database, 'update_020500', __LINE__, 'Could not update database (' . $database->error . ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
# Set version
|
||||
$result = $database->query("UPDATE lychee_settings SET value = '020500' WHERE `key` = 'version';");
|
||||
if (!$result) {
|
||||
Log::error($database, 'update_020500', __LINE__, 'Could not update database (' . $database->error . ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
?>
|
24
php/define.php
Normal file
24
php/define.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
###
|
||||
# @name Define
|
||||
# @author Tobias Reich
|
||||
# @copyright 2014 by Tobias Reich
|
||||
###
|
||||
|
||||
# Define root
|
||||
define('LYCHEE', substr(__DIR__, 0, -3));
|
||||
|
||||
# Define dirs
|
||||
define('LYCHEE_DATA', LYCHEE . 'data/');
|
||||
define('LYCHEE_UPLOADS', LYCHEE . 'uploads/');
|
||||
define('LYCHEE_UPLOADS_BIG', LYCHEE_UPLOADS . 'big/');
|
||||
define('LYCHEE_UPLOADS_MEDIUM', LYCHEE_UPLOADS . 'medium/');
|
||||
define('LYCHEE_UPLOADS_THUMB', LYCHEE_UPLOADS . 'thumb/');
|
||||
define('LYCHEE_UPLOADS_IMPORT', LYCHEE_UPLOADS . 'import/');
|
||||
define('LYCHEE_PLUGINS', LYCHEE . 'plugins/');
|
||||
|
||||
# Define files
|
||||
define('LYCHEE_CONFIG_FILE', LYCHEE_DATA . 'config.php');
|
||||
|
||||
?>
|
557
php/modules/Album.php
Normal file
557
php/modules/Album.php
Normal file
@ -0,0 +1,557 @@
|
||||
<?php
|
||||
|
||||
###
|
||||
# @name Album Module
|
||||
# @author Tobias Reich
|
||||
# @copyright 2014 by Tobias Reich
|
||||
###
|
||||
|
||||
if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
|
||||
|
||||
class Album extends Module {
|
||||
|
||||
private $database = null;
|
||||
private $settings = null;
|
||||
private $albumIDs = null;
|
||||
|
||||
public function __construct($database, $plugins, $settings, $albumIDs) {
|
||||
|
||||
# Init vars
|
||||
$this->database = $database;
|
||||
$this->plugins = $plugins;
|
||||
$this->settings = $settings;
|
||||
$this->albumIDs = $albumIDs;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public function add($title = 'Untitled', $public = 0, $visible = 1) {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database));
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 0, func_get_args());
|
||||
|
||||
# Parse
|
||||
if (strlen($title)>50) $title = substr($title, 0, 50);
|
||||
|
||||
# Database
|
||||
$sysstamp = time();
|
||||
$result = $this->database->query("INSERT INTO lychee_albums (title, sysstamp, public, visible) VALUES ('$title', '$sysstamp', '$public', '$visible');");
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 1, func_get_args());
|
||||
|
||||
if (!$result) {
|
||||
Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
|
||||
return false;
|
||||
}
|
||||
return $this->database->insert_id;
|
||||
|
||||
}
|
||||
|
||||
public function get() {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database, $this->settings, $this->albumIDs));
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 0, func_get_args());
|
||||
|
||||
# Get album information
|
||||
switch ($this->albumIDs) {
|
||||
|
||||
case 'f': $return['public'] = false;
|
||||
$query = "SELECT id, title, tags, public, star, album, thumbUrl FROM lychee_photos WHERE star = 1 " . $this->settings['sorting'];
|
||||
break;
|
||||
|
||||
case 's': $return['public'] = false;
|
||||
$query = "SELECT id, title, tags, public, star, album, thumbUrl FROM lychee_photos WHERE public = 1 " . $this->settings['sorting'];
|
||||
break;
|
||||
|
||||
case '0': $return['public'] = false;
|
||||
$query = "SELECT id, title, tags, public, star, album, thumbUrl FROM lychee_photos WHERE album = 0 " . $this->settings['sorting'];
|
||||
break;
|
||||
|
||||
default: $albums = $this->database->query("SELECT * FROM lychee_albums WHERE id = '$this->albumIDs' LIMIT 1;");
|
||||
$return = $albums->fetch_assoc();
|
||||
$return['sysdate'] = date('d M. Y', $return['sysstamp']);
|
||||
$return['password'] = ($return['password']=='' ? false : true);
|
||||
$query = "SELECT id, title, tags, public, star, album, thumbUrl FROM lychee_photos WHERE album = '$this->albumIDs' " . $this->settings['sorting'];
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
# Get photos
|
||||
$photos = $this->database->query($query);
|
||||
$previousPhotoID = '';
|
||||
while ($photo = $photos->fetch_assoc()) {
|
||||
|
||||
# Parse
|
||||
$photo['sysdate'] = date('d F Y', substr($photo['id'], 0, -4));
|
||||
$photo['previousPhoto'] = $previousPhotoID;
|
||||
$photo['nextPhoto'] = '';
|
||||
|
||||
if ($previousPhotoID!=='') $return['content'][$previousPhotoID]['nextPhoto'] = $photo['id'];
|
||||
$previousPhotoID = $photo['id'];
|
||||
|
||||
# Add to return
|
||||
$return['content'][$photo['id']] = $photo;
|
||||
|
||||
}
|
||||
|
||||
if ($photos->num_rows===0) {
|
||||
|
||||
# Album empty
|
||||
$return['content'] = false;
|
||||
|
||||
} else {
|
||||
|
||||
# Enable next and previous for the first and last photo
|
||||
$lastElement = end($return['content']);
|
||||
$lastElementId = $lastElement['id'];
|
||||
$firstElement = reset($return['content']);
|
||||
$firstElementId = $firstElement['id'];
|
||||
|
||||
if ($lastElementId!==$firstElementId) {
|
||||
$return['content'][$lastElementId]['nextPhoto'] = $firstElementId;
|
||||
$return['content'][$firstElementId]['previousPhoto'] = $lastElementId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$return['id'] = $this->albumIDs;
|
||||
$return['num'] = $photos->num_rows;
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 1, func_get_args());
|
||||
|
||||
return $return;
|
||||
|
||||
}
|
||||
|
||||
public function getAll($public) {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database, $this->settings, $public));
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 0, func_get_args());
|
||||
|
||||
# Get SmartAlbums
|
||||
if ($public===false) $return = $this->getSmartInfo();
|
||||
|
||||
# Albums query
|
||||
$query = 'SELECT id, title, public, sysstamp, password FROM lychee_albums WHERE public = 1 AND visible <> 0';
|
||||
if ($public===false) $query = 'SELECT id, title, public, sysstamp, password FROM lychee_albums';
|
||||
|
||||
# Execute query
|
||||
$albums = $this->database->query($query) OR exit('Error: ' . $this->database->error);
|
||||
|
||||
# For each album
|
||||
while ($album = $albums->fetch_assoc()) {
|
||||
|
||||
# Parse info
|
||||
$album['sysdate'] = date('F Y', $album['sysstamp']);
|
||||
$album['password'] = ($album['password'] != '');
|
||||
|
||||
# Thumbs
|
||||
if (($public===true&&$album['password']===false)||($public===false)) {
|
||||
|
||||
# Execute query
|
||||
$thumbs = $this->database->query("SELECT thumbUrl FROM lychee_photos WHERE album = '" . $album['id'] . "' ORDER BY star DESC, " . substr($this->settings['sorting'], 9) . " LIMIT 3");
|
||||
|
||||
# For each thumb
|
||||
$k = 0;
|
||||
while ($thumb = $thumbs->fetch_object()) {
|
||||
$album["thumb$k"] = $thumb->thumbUrl;
|
||||
$k++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Add to return
|
||||
$return['content'][$album['id']] = $album;
|
||||
|
||||
}
|
||||
|
||||
# Num of albums
|
||||
$return['num'] = $albums->num_rows;
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 1, func_get_args());
|
||||
|
||||
return $return;
|
||||
|
||||
}
|
||||
|
||||
private function getSmartInfo() {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database, $this->settings));
|
||||
|
||||
# Unsorted
|
||||
$unsorted = $this->database->query("SELECT thumbUrl FROM lychee_photos WHERE album = 0 " . $this->settings['sorting']);
|
||||
$i = 0;
|
||||
while($row = $unsorted->fetch_object()) {
|
||||
if ($i<3) {
|
||||
$return["unsortedThumb$i"] = $row->thumbUrl;
|
||||
$i++;
|
||||
} else break;
|
||||
}
|
||||
$return['unsortedNum'] = $unsorted->num_rows;
|
||||
|
||||
# Public
|
||||
$public = $this->database->query("SELECT thumbUrl FROM lychee_photos WHERE public = 1 " . $this->settings['sorting']);
|
||||
$i = 0;
|
||||
while($row2 = $public->fetch_object()) {
|
||||
if ($i<3) {
|
||||
$return["publicThumb$i"] = $row2->thumbUrl;
|
||||
$i++;
|
||||
} else break;
|
||||
}
|
||||
$return['publicNum'] = $public->num_rows;
|
||||
|
||||
# Starred
|
||||
$starred = $this->database->query("SELECT thumbUrl FROM lychee_photos WHERE star = 1 " . $this->settings['sorting']);
|
||||
$i = 0;
|
||||
while($row3 = $starred->fetch_object()) {
|
||||
if ($i<3) {
|
||||
$return["starredThumb$i"] = $row3->thumbUrl;
|
||||
$i++;
|
||||
} else break;
|
||||
}
|
||||
$return['starredNum'] = $starred->num_rows;
|
||||
|
||||
return $return;
|
||||
|
||||
}
|
||||
|
||||
public function getArchive() {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database, $this->albumIDs));
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 0, func_get_args());
|
||||
|
||||
# Illicit chars
|
||||
$badChars = array_merge(
|
||||
array_map('chr', range(0,31)),
|
||||
array("<", ">", ":", '"', "/", "\\", "|", "?", "*")
|
||||
);
|
||||
|
||||
# Photos query
|
||||
switch($this->albumIDs) {
|
||||
case 's':
|
||||
$photos = "SELECT title, url FROM lychee_photos WHERE public = '1';";
|
||||
$zipTitle = 'Public';
|
||||
break;
|
||||
case 'f':
|
||||
$photos = "SELECT title, url FROM lychee_photos WHERE star = '1';";
|
||||
$zipTitle = 'Starred';
|
||||
break;
|
||||
default:
|
||||
$photos = "SELECT title, url FROM lychee_photos WHERE album = '$this->albumIDs';";
|
||||
$zipTitle = 'Unsorted';
|
||||
}
|
||||
|
||||
# Set title
|
||||
$album = $this->database->query("SELECT title FROM lychee_albums WHERE id = '$this->albumIDs' LIMIT 1;");
|
||||
if ($this->albumIDs!=0&&is_numeric($this->albumIDs)) $zipTitle = $album->fetch_object()->title;
|
||||
|
||||
# Parse title
|
||||
$zipTitle = str_replace($badChars, '', $zipTitle);
|
||||
|
||||
$filename = LYCHEE_DATA . $zipTitle . '.zip';
|
||||
|
||||
# Create zip
|
||||
$zip = new ZipArchive();
|
||||
if ($zip->open($filename, ZIPARCHIVE::CREATE)!==TRUE) {
|
||||
Log::error($this->database, __METHOD__, __LINE__, 'Could not create ZipArchive');
|
||||
return false;
|
||||
}
|
||||
|
||||
# Execute query
|
||||
$photos = $this->database->query($photos);
|
||||
|
||||
# Check if album empty
|
||||
if ($photos->num_rows==0) {
|
||||
Log::error($this->database, __METHOD__, __LINE__, 'Could not create ZipArchive without images');
|
||||
return false;
|
||||
}
|
||||
|
||||
# Parse each path
|
||||
$files = array();
|
||||
while ($photo = $photos->fetch_object()) {
|
||||
|
||||
# Parse url
|
||||
$photo->url = LYCHEE_UPLOADS_BIG . $photo->url;
|
||||
|
||||
# Parse title
|
||||
$photo->title = str_replace($badChars, '', $photo->title);
|
||||
if (!isset($photo->title)||$photo->title==='') $photo->title = 'Untitled';
|
||||
|
||||
# Check if readable
|
||||
if (!@is_readable($photo->url)) continue;
|
||||
|
||||
# Get extension of image
|
||||
$extension = getExtension($photo->url);
|
||||
|
||||
# Set title for photo
|
||||
$zipFileName = $zipTitle . '/' . $photo->title . $extension;
|
||||
|
||||
# Check for duplicates
|
||||
if (!empty($files)) {
|
||||
$i = 1;
|
||||
while (in_array($zipFileName, $files)) {
|
||||
|
||||
# Set new title for photo
|
||||
$zipFileName = $zipTitle . '/' . $photo->title . '-' . $i . $extension;
|
||||
|
||||
$i++;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
# Add to array
|
||||
$files[] = $zipFileName;
|
||||
|
||||
# Add photo to zip
|
||||
$zip->addFile($photo->url, $zipFileName);
|
||||
|
||||
}
|
||||
|
||||
# Finish zip
|
||||
$zip->close();
|
||||
|
||||
# Send zip
|
||||
header("Content-Type: application/zip");
|
||||
header("Content-Disposition: attachment; filename=\"$zipTitle.zip\"");
|
||||
header("Content-Length: " . filesize($filename));
|
||||
readfile($filename);
|
||||
|
||||
# Delete zip
|
||||
unlink($filename);
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 1, func_get_args());
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public function setTitle($title = 'Untitled') {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database, $this->albumIDs));
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 0, func_get_args());
|
||||
|
||||
# Parse
|
||||
if (strlen($title)>50) $title = substr($title, 0, 50);
|
||||
|
||||
# Execute query
|
||||
$result = $this->database->query("UPDATE lychee_albums SET title = '$title' WHERE id IN ($this->albumIDs);");
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 1, func_get_args());
|
||||
|
||||
if (!$result) {
|
||||
Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public function setDescription($description = '') {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database, $this->albumIDs));
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 0, func_get_args());
|
||||
|
||||
# Parse
|
||||
$description = htmlentities($description);
|
||||
if (strlen($description)>1000) $description = substr($description, 0, 1000);
|
||||
|
||||
# Execute query
|
||||
$result = $this->database->query("UPDATE lychee_albums SET description = '$description' WHERE id IN ($this->albumIDs);");
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 1, func_get_args());
|
||||
|
||||
if (!$result) {
|
||||
Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public function getPublic() {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database, $this->albumIDs));
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 0, func_get_args());
|
||||
|
||||
if ($this->albumIDs==='0'||$this->albumIDs==='s'||$this->albumIDs==='f') return false;
|
||||
|
||||
# Execute query
|
||||
$albums = $this->database->query("SELECT public FROM lychee_albums WHERE id = '$this->albumIDs' LIMIT 1;");
|
||||
$album = $albums->fetch_object();
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 1, func_get_args());
|
||||
|
||||
if ($album->public==1) return true;
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
public function setPublic($password) {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database, $this->albumIDs));
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 0, func_get_args());
|
||||
|
||||
# Get public
|
||||
$albums = $this->database->query("SELECT id, public FROM lychee_albums WHERE id IN ('$this->albumIDs');");
|
||||
|
||||
while ($album = $albums->fetch_object()) {
|
||||
|
||||
# Invert public
|
||||
$public = ($album->public=='0' ? 1 : 0);
|
||||
|
||||
# Set public
|
||||
$result = $this->database->query("UPDATE lychee_albums SET public = '$public', visible = 1, password = NULL WHERE id = '$album->id';");
|
||||
if (!$result) {
|
||||
Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
|
||||
return false;
|
||||
}
|
||||
|
||||
# Reset permissions for photos
|
||||
if ($public===1) {
|
||||
$result = $this->database->query("UPDATE lychee_photos SET public = 0 WHERE album = '$album->id';");
|
||||
if (!$result) {
|
||||
Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 1, func_get_args());
|
||||
|
||||
# Set password
|
||||
if (isset($password)&&strlen($password)>0) return $this->setPassword($password);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public function setPassword($password) {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database, $this->albumIDs));
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 0, func_get_args());
|
||||
|
||||
if (strlen($password)>0) {
|
||||
|
||||
# Get hashed password
|
||||
$password = get_hashed_password($password);
|
||||
|
||||
# Set hashed password
|
||||
$result = $this->database->query("UPDATE lychee_albums SET visible = 0, password = '$password' WHERE id IN ('$this->albumIDs');");
|
||||
|
||||
} else {
|
||||
|
||||
# Unset password
|
||||
$result = $this->database->query("UPDATE lychee_albums SET visible = 1, password = NULL WHERE id IN ('$this->albumIDs');");
|
||||
|
||||
}
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 1, func_get_args());
|
||||
|
||||
if (!$result) {
|
||||
Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public function checkPassword($password) {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database, $this->albumIDs));
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 0, func_get_args());
|
||||
|
||||
# Execute query
|
||||
$albums = $this->database->query("SELECT password FROM lychee_albums WHERE id = '$this->albumIDs' LIMIT 1;");
|
||||
$album = $albums->fetch_object();
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 1, func_get_args());
|
||||
|
||||
if ($album->password=='') return true;
|
||||
else if ($album->password===$password||$album->password===crypt($password, $album->password)) return true;
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
public function delete($albumIDs) {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database, $this->albumIDs));
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 0, func_get_args());
|
||||
|
||||
# Init vars
|
||||
$error = false;
|
||||
|
||||
# Execute query
|
||||
$photos = $this->database->query("SELECT id FROM lychee_photos WHERE album IN ($albumIDs);");
|
||||
|
||||
# For each album delete photo
|
||||
while ($row = $photos->fetch_object()) {
|
||||
|
||||
$photo = new Photo($this->database, $this->plugins, null, $row->id);
|
||||
if (!$photo->delete($row->id)) $error = true;
|
||||
|
||||
}
|
||||
|
||||
# Delete albums
|
||||
$result = $this->database->query("DELETE FROM lychee_albums WHERE id IN ($albumIDs);");
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 1, func_get_args());
|
||||
|
||||
if ($error) return false;
|
||||
if (!$result) {
|
||||
Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
212
php/modules/Database.php
Executable file
212
php/modules/Database.php
Executable file
@ -0,0 +1,212 @@
|
||||
<?php
|
||||
|
||||
###
|
||||
# @name Database Module
|
||||
# @author Tobias Reich
|
||||
# @copyright 2014 by Tobias Reich
|
||||
###
|
||||
|
||||
if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
|
||||
|
||||
class Database extends Module {
|
||||
|
||||
static function connect($host = 'localhost', $user, $password, $name = 'lychee') {
|
||||
|
||||
# Check dependencies
|
||||
Module::dependencies(isset($host, $user, $password, $name));
|
||||
|
||||
$database = new mysqli($host, $user, $password);
|
||||
|
||||
# Check connection
|
||||
if ($database->connect_errno) exit('Error: ' . $database->connect_error);
|
||||
|
||||
# Avoid sql injection on older MySQL versions by using GBK
|
||||
if ($database->server_version<50500) $database->set_charset('GBK');
|
||||
else $database->set_charset("utf8");
|
||||
|
||||
# Check database
|
||||
if (!$database->select_db($name))
|
||||
if (!Database::createDatabase($database, $name)) exit('Error: Could not create database!');
|
||||
|
||||
# Check tables
|
||||
if (!$database->query('SELECT * FROM lychee_photos, lychee_albums, lychee_settings, lychee_log LIMIT 0;'))
|
||||
if (!Database::createTables($database)) exit('Error: Could not create tables!');
|
||||
|
||||
return $database;
|
||||
|
||||
}
|
||||
|
||||
static function update($database, $dbName, $version = 0) {
|
||||
|
||||
# Check dependencies
|
||||
Module::dependencies(isset($database, $dbName));
|
||||
|
||||
# List of updates
|
||||
$updates = array(
|
||||
'020100', #2.1
|
||||
'020101', #2.1.1
|
||||
'020200', #2.2
|
||||
'020500' #2.5
|
||||
);
|
||||
|
||||
# For each update
|
||||
foreach ($updates as $update) {
|
||||
|
||||
if (isset($version)&&$update<=$version) continue;
|
||||
|
||||
# Load update
|
||||
include(__DIR__ . '/../database/update_' . $update . '.php');
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
static function createConfig($host = 'localhost', $user, $password, $name = 'lychee') {
|
||||
|
||||
# Check dependencies
|
||||
Module::dependencies(isset($host, $user, $password, $name));
|
||||
|
||||
$database = new mysqli($host, $user, $password);
|
||||
|
||||
if ($database->connect_errno) return 'Warning: Connection failed!';
|
||||
else {
|
||||
|
||||
$config = "<?php
|
||||
|
||||
###
|
||||
# @name Configuration
|
||||
# @author Tobias Reich
|
||||
# @copyright 2014 Tobias Reich
|
||||
###
|
||||
|
||||
if(!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
|
||||
|
||||
# Database configuration
|
||||
\$dbHost = '$host'; # Host of the database
|
||||
\$dbUser = '$user'; # Username of the database
|
||||
\$dbPassword = '$password'; # Password of the database
|
||||
\$dbName = '$name'; # Database name
|
||||
|
||||
?>";
|
||||
|
||||
# Save file
|
||||
if (file_put_contents(LYCHEE_CONFIG_FILE, $config)===false) return 'Warning: Could not create file!';
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static function createDatabase($database, $name = 'lychee') {
|
||||
|
||||
# Check dependencies
|
||||
Module::dependencies(isset($database, $name));
|
||||
|
||||
# Create database
|
||||
$result = $database->query("CREATE DATABASE IF NOT EXISTS $name;");
|
||||
$database->select_db($name);
|
||||
|
||||
if (!$database->select_db($name)||!$result) return false;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
static function createTables($database) {
|
||||
|
||||
# Check dependencies
|
||||
Module::dependencies(isset($database));
|
||||
|
||||
# Create log
|
||||
if (!$database->query('SELECT * FROM lychee_log LIMIT 0;')) {
|
||||
|
||||
# Read file
|
||||
$file = __DIR__ . '/../database/log_table.sql';
|
||||
$query = @file_get_contents($file);
|
||||
|
||||
# Create table
|
||||
if (!isset($query)||$query===false) return false;
|
||||
if (!$database->query($query)) return false;
|
||||
|
||||
}
|
||||
|
||||
# Create settings
|
||||
if (!$database->query('SELECT * FROM lychee_settings LIMIT 0;')) {
|
||||
|
||||
# Read file
|
||||
$file = __DIR__ . '/../database/settings_table.sql';
|
||||
$query = @file_get_contents($file);
|
||||
|
||||
# Create table
|
||||
if (!isset($query)||$query===false) {
|
||||
Log::error($database, __METHOD__, __LINE__, 'Could not load query for lychee_settings');
|
||||
return false;
|
||||
}
|
||||
if (!$database->query($query)) {
|
||||
Log::error($database, __METHOD__, __LINE__, $database->error);
|
||||
return false;
|
||||
}
|
||||
|
||||
# Read file
|
||||
$file = __DIR__ . '/../database/settings_content.sql';
|
||||
$query = @file_get_contents($file);
|
||||
|
||||
# Add content
|
||||
if (!isset($query)||$query===false) {
|
||||
Log::error($database, __METHOD__, __LINE__, 'Could not load content-query for lychee_settings');
|
||||
return false;
|
||||
}
|
||||
if (!$database->query($query)) {
|
||||
Log::error($database, __METHOD__, __LINE__, $database->error);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Create albums
|
||||
if (!$database->query('SELECT * FROM lychee_albums LIMIT 0;')) {
|
||||
|
||||
# Read file
|
||||
$file = __DIR__ . '/../database/albums_table.sql';
|
||||
$query = @file_get_contents($file);
|
||||
|
||||
# Create table
|
||||
if (!isset($query)||$query===false) {
|
||||
Log::error($database, __METHOD__, __LINE__, 'Could not load query for lychee_albums');
|
||||
return false;
|
||||
}
|
||||
if (!$database->query($query)) {
|
||||
Log::error($database, __METHOD__, __LINE__, $database->error);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Create photos
|
||||
if (!$database->query('SELECT * FROM lychee_photos LIMIT 0;')) {
|
||||
|
||||
# Read file
|
||||
$file = __DIR__ . '/../database/photos_table.sql';
|
||||
$query = @file_get_contents($file);
|
||||
|
||||
# Create table
|
||||
if (!isset($query)||$query===false) {
|
||||
Log::error($database, __METHOD__, __LINE__, 'Could not load query for lychee_photos');
|
||||
return false;
|
||||
}
|
||||
if (!$database->query($query)) {
|
||||
Log::error($database, __METHOD__, __LINE__, $database->error);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
197
php/modules/Import.php
Normal file
197
php/modules/Import.php
Normal file
@ -0,0 +1,197 @@
|
||||
<?php
|
||||
|
||||
###
|
||||
# @name Upload Module
|
||||
# @author Tobias Reich
|
||||
# @copyright 2014 by Tobias Reich
|
||||
###
|
||||
|
||||
if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
|
||||
|
||||
class Import extends Module {
|
||||
|
||||
static function photo($database, $plugins, $settings, $path, $albumID = 0, $description = '', $tags = '') {
|
||||
|
||||
$info = getimagesize($path);
|
||||
$size = filesize($path);
|
||||
$photo = new Photo($database, $plugins, $settings, null);
|
||||
|
||||
$nameFile = array(array());
|
||||
$nameFile[0]['name'] = $path;
|
||||
$nameFile[0]['type'] = $info['mime'];
|
||||
$nameFile[0]['tmp_name'] = $path;
|
||||
$nameFile[0]['error'] = 0;
|
||||
$nameFile[0]['size'] = $size;
|
||||
|
||||
if (!$photo->add($nameFile, $albumID, $description, $tags)) return false;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
static function url($urls, $albumID = 0) {
|
||||
|
||||
$error = false;
|
||||
|
||||
# Parse
|
||||
$urls = str_replace(' ', '%20', $urls);
|
||||
$urls = explode(',', $urls);
|
||||
|
||||
foreach ($urls as &$url) {
|
||||
|
||||
if (@exif_imagetype($url)===false) {
|
||||
$error = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
$pathinfo = pathinfo($url);
|
||||
$filename = $pathinfo['filename'] . '.' . $pathinfo['extension'];
|
||||
$tmp_name = LYCHEE_DATA . $filename;
|
||||
|
||||
if (@copy($url, $tmp_name)===false) $error = true;
|
||||
|
||||
}
|
||||
|
||||
$import = Import::server($albumID, LYCHEE_DATA);
|
||||
|
||||
if ($error===false&&$import===true) return true;
|
||||
else return false;
|
||||
|
||||
}
|
||||
|
||||
static function move($database, $path) {
|
||||
|
||||
# Determine OS type and set move cmd (Windows untested!)
|
||||
$myos = substr(PHP_OS,0,3);
|
||||
$myos = strtoupper($myos);
|
||||
|
||||
if ($myos==='WIN') $osmv = 'MOVE';
|
||||
else $osmv = 'mv';
|
||||
|
||||
# Generate tmp dir name by hashing epoch time & random number
|
||||
$tmpdirname = md5(time() . rand());
|
||||
|
||||
# Make temporary directory
|
||||
if (@mkdir(LYCHEE_DATA . $tmpdirname)===false) {
|
||||
Log::error($database, __METHOD__, __LINE__, 'Failed to create temporary directory');
|
||||
return false;
|
||||
}
|
||||
|
||||
# Get list of files and move them to tmpdir
|
||||
$files = glob($path . '*');
|
||||
if (isset($files)) {
|
||||
|
||||
foreach ($files as $file) {
|
||||
|
||||
# Prevent unsupported files from being moved
|
||||
if (is_dir($file)===false&&@exif_imagetype($file)===false) continue;
|
||||
|
||||
$out = '';
|
||||
$ret = '';
|
||||
$file = escapeshellarg($file);
|
||||
$cmd = $osmv . " $file " . LYCHEE_DATA . $tmpdirname;
|
||||
|
||||
@exec($cmd, $out, $ret);
|
||||
|
||||
if (isset($ret)&&($ret>0)) Log::error($database, __METHOD__, __LINE__, "Failed to move directory or file ($ret):" . $file);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# If no files could be copied to the temp dir, remove
|
||||
$files = glob(LYCHEE_DATA . $tmpdirname . '/*');
|
||||
if (count($files)===0) {
|
||||
rmdir(LYCHEE_DATA . $tmpdirname);
|
||||
Log::error($database, __METHOD__, __LINE__, 'Import failed, because files could not be temporary moved to ' . LYCHEE_DATA);
|
||||
return false;
|
||||
}
|
||||
|
||||
# Set new path
|
||||
$path = LYCHEE_DATA . $tmpdirname;
|
||||
|
||||
return $path;
|
||||
|
||||
}
|
||||
|
||||
static function server($albumID = 0, $path, $useTemp = false) {
|
||||
|
||||
global $database, $plugins, $settings;
|
||||
|
||||
if (!isset($path)) $path = LYCHEE_UPLOADS_IMPORT;
|
||||
|
||||
if ($useTemp===true) {
|
||||
$path = Import::move($database, $path);
|
||||
if ($path===false) {
|
||||
Log::error($database, __METHOD__, __LINE__, 'Failed to move import to temporary directory');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$error = false;
|
||||
$contains['photos'] = false;
|
||||
$contains['albums'] = false;
|
||||
|
||||
# Get all files
|
||||
$files = glob($path . '/*');
|
||||
|
||||
foreach ($files as $file) {
|
||||
|
||||
# It is possible to move a file because of directory permissions but
|
||||
# the file may still be unreadable by the user
|
||||
if (!is_readable($file)) {
|
||||
$error = true;
|
||||
Log::error($database, __METHOD__, __LINE__, 'Could not read file or directory: ' . $file);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (@exif_imagetype($file)!==false) {
|
||||
|
||||
# Photo
|
||||
|
||||
if (!Import::photo($database, $plugins, $settings, $file, $albumID)) {
|
||||
$error = true;
|
||||
Log::error($database, __METHOD__, __LINE__, 'Could not import file: ' . $file);
|
||||
continue;
|
||||
}
|
||||
$contains['photos'] = true;
|
||||
|
||||
} else if (is_dir($file)) {
|
||||
|
||||
# Folder
|
||||
|
||||
$name = mysqli_real_escape_string($database, basename($file));
|
||||
$album = new Album($database, null, null, null);
|
||||
$newAlbumID = $album->add('[Import] ' . $name);
|
||||
|
||||
if ($newAlbumID===false) {
|
||||
$error = true;
|
||||
Log::error($database, __METHOD__, __LINE__, 'Could not create album in Lychee (' . $newAlbumID . ')');
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Import::server($newAlbumID, $file . '/', false)==='Warning: Folder empty or no readable files to process!') {
|
||||
$error = true;
|
||||
Log::error($database, __METHOD__, __LINE__, 'Could not import folder. Function returned error');
|
||||
continue;
|
||||
}
|
||||
|
||||
$contains['albums'] = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Delete tmpdir if import was successful
|
||||
if ($error===false&&$useTemp===true&&file_exists(LYCHEE_DATA . $tmpdirname)) {
|
||||
if (@rmdir(LYCHEE_DATA . $tmpdirname)===false) Log::error($database, __METHOD__, __LINE__, 'Could not delete temp-folder (' . LYCHEE_DATA . $tmpdirname . ') after successful import');
|
||||
}
|
||||
|
||||
if ($contains['photos']===false&&$contains['albums']===false) return 'Warning: Folder empty or no readable files to process!';
|
||||
if ($contains['photos']===false&&$contains['albums']===true) return 'Notice: Import only contains albums!';
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
56
php/modules/Log.php
Normal file
56
php/modules/Log.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
###
|
||||
# @name Log Module
|
||||
# @author Tobias Reich
|
||||
# @copyright 2014 by Tobias Reich
|
||||
###
|
||||
|
||||
if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
|
||||
|
||||
class Log extends Module {
|
||||
|
||||
public static function notice($database, $function, $line, $text = '') {
|
||||
|
||||
return Log::text($database, 'notice', $function, $line, $text);
|
||||
|
||||
}
|
||||
|
||||
public static function warning($database, $function, $line, $text = '') {
|
||||
|
||||
return Log::text($database, 'warning', $function, $line, $text);
|
||||
|
||||
}
|
||||
|
||||
public static function error($database, $function, $line, $text = '') {
|
||||
|
||||
return Log::text($database, 'error', $function, $line, $text);
|
||||
|
||||
}
|
||||
|
||||
public static function text($database, $type, $function, $line, $text = '') {
|
||||
|
||||
# Check dependencies
|
||||
Module::dependencies(isset($database, $type, $function, $line, $text));
|
||||
|
||||
# Get time
|
||||
$sysstamp = time();
|
||||
|
||||
# Escape
|
||||
$type = mysqli_real_escape_string($database, $type);
|
||||
$function = mysqli_real_escape_string($database, $function);
|
||||
$line = mysqli_real_escape_string($database, $line);
|
||||
$text = mysqli_real_escape_string($database, $text);
|
||||
|
||||
# Save in database
|
||||
$query = "INSERT INTO lychee_log (time, type, function, line, text) VALUES ('$sysstamp', '$type', '$function', '$line', '$text');";
|
||||
$result = $database->query($query);
|
||||
|
||||
if (!$result) return false;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
37
php/modules/Module.php
Normal file
37
php/modules/Module.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
###
|
||||
# @name Module
|
||||
# @author Tobias Reich
|
||||
# @copyright 2014 by Tobias Reich
|
||||
###
|
||||
|
||||
if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
|
||||
|
||||
class Module {
|
||||
|
||||
protected $plugins = null;
|
||||
|
||||
protected function plugins($name, $location, $args) {
|
||||
|
||||
if (!isset($this->plugins, $name, $location, $args)) return false;
|
||||
|
||||
# Parse
|
||||
$location = ($location===0 ? 'before' : 'after');
|
||||
|
||||
# Call plugins
|
||||
$this->plugins->activate($name . ":" . $location, $args);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public function dependencies($available = false) {
|
||||
|
||||
if ($available===false) exit('Error: Can not execute function. Missing parameters or variables.');
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
796
php/modules/Photo.php
Executable file
796
php/modules/Photo.php
Executable file
@ -0,0 +1,796 @@
|
||||
<?php
|
||||
|
||||
###
|
||||
# @name Photo Module
|
||||
# @author Tobias Reich
|
||||
# @copyright 2014 by Tobias Reich
|
||||
###
|
||||
|
||||
if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
|
||||
|
||||
class Photo extends Module {
|
||||
|
||||
private $database = null;
|
||||
private $settings = null;
|
||||
private $photoIDs = null;
|
||||
|
||||
private $allowedTypes = array(
|
||||
IMAGETYPE_JPEG,
|
||||
IMAGETYPE_GIF,
|
||||
IMAGETYPE_PNG
|
||||
);
|
||||
private $validExtensions = array(
|
||||
'.jpg',
|
||||
'.jpeg',
|
||||
'.png',
|
||||
'.gif'
|
||||
);
|
||||
|
||||
public function __construct($database, $plugins, $settings, $photoIDs) {
|
||||
|
||||
# Init vars
|
||||
$this->database = $database;
|
||||
$this->plugins = $plugins;
|
||||
$this->settings = $settings;
|
||||
$this->photoIDs = $photoIDs;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public function add($files, $albumID, $description = '', $tags = '') {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database));
|
||||
|
||||
# Check permissions
|
||||
if (hasPermissions(LYCHEE_UPLOADS_BIG)===false||hasPermissions(LYCHEE_UPLOADS_THUMB)===false) {
|
||||
Log::error($this->database, __METHOD__, __LINE__, 'Wrong permissions in uploads/');
|
||||
exit('Error: Wrong permissions in uploads-folder!');
|
||||
}
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 0, func_get_args());
|
||||
|
||||
switch($albumID) {
|
||||
|
||||
case 's':
|
||||
# s for public (share)
|
||||
$public = 1;
|
||||
$star = 0;
|
||||
$albumID = 0;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
# f for starred (fav)
|
||||
$star = 1;
|
||||
$public = 0;
|
||||
$albumID = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
$star = 0;
|
||||
$public = 0;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
foreach ($files as $file) {
|
||||
|
||||
# Verify extension
|
||||
$extension = getExtension($file['name']);
|
||||
if (!in_array(strtolower($extension), $this->validExtensions, true)) continue;
|
||||
|
||||
# Verify image
|
||||
$type = @exif_imagetype($file['tmp_name']);
|
||||
if (!in_array($type, $this->allowedTypes, true)) continue;
|
||||
|
||||
# Generate id
|
||||
$id = str_replace('.', '', microtime(true));
|
||||
while(strlen($id)<14) $id .= 0;
|
||||
|
||||
$tmp_name = $file['tmp_name'];
|
||||
$photo_name = md5($id) . $extension;
|
||||
$path = LYCHEE_UPLOADS_BIG . $photo_name;
|
||||
|
||||
# Import if not uploaded via web
|
||||
if (!is_uploaded_file($tmp_name)) {
|
||||
if (!@copy($tmp_name, $path)) {
|
||||
Log::error($this->database, __METHOD__, __LINE__, 'Could not copy photo to uploads');
|
||||
exit('Error: Could not copy photo to uploads!');
|
||||
} else @unlink($tmp_name);
|
||||
} else {
|
||||
if (!@move_uploaded_file($tmp_name, $path)) {
|
||||
Log::error($this->database, __METHOD__, __LINE__, 'Could not move photo to uploads');
|
||||
exit('Error: Could not move photo to uploads!');
|
||||
}
|
||||
}
|
||||
|
||||
# Read infos
|
||||
$info = $this->getInfo($path);
|
||||
|
||||
# Use title of file if IPTC title missing
|
||||
if ($info['title']==='') $info['title'] = mysqli_real_escape_string($this->database, substr(basename($file['name'], $extension), 0, 30));
|
||||
|
||||
# Use description parameter if set
|
||||
if ($description==='') $description = $info['description'];
|
||||
|
||||
# Set orientation based on EXIF data
|
||||
if ($file['type']==='image/jpeg'&&isset($info['orientation'])&&$info['orientation']!==''&&isset($info['width'])&&isset($info['height'])) {
|
||||
if (!$this->adjustFile($path, $info)) Log::notice($this->database, __METHOD__, __LINE__, 'Could not adjust photo (' . $info['title'] . ')');
|
||||
}
|
||||
|
||||
# Set original date
|
||||
if ($info['takestamp']!=='') @touch($path, $info['takestamp']);
|
||||
|
||||
# Create Thumb
|
||||
if (!$this->createThumb($path, $photo_name)) {
|
||||
Log::error($this->database, __METHOD__, __LINE__, 'Could not create thumbnail for photo');
|
||||
exit('Error: Could not create thumbnail for photo!');
|
||||
}
|
||||
|
||||
# Save to DB
|
||||
$query = "INSERT INTO lychee_photos (id, title, url, description, tags, type, width, height, size, iso, aperture, make, model, shutter, focal, takestamp, thumbUrl, album, public, star)
|
||||
VALUES (
|
||||
'" . $id . "',
|
||||
'" . $info['title'] . "',
|
||||
'" . $photo_name . "',
|
||||
'" . $description . "',
|
||||
'" . $tags . "',
|
||||
'" . $info['type'] . "',
|
||||
'" . $info['width'] . "',
|
||||
'" . $info['height'] . "',
|
||||
'" . $info['size'] . "',
|
||||
'" . $info['iso'] . "',
|
||||
'" . $info['aperture'] . "',
|
||||
'" . $info['make'] . "',
|
||||
'" . $info['model'] . "',
|
||||
'" . $info['shutter'] . "',
|
||||
'" . $info['focal'] . "',
|
||||
'" . $info['takestamp'] . "',
|
||||
'" . md5($id) . ".jpeg',
|
||||
'" . $albumID . "',
|
||||
'" . $public . "',
|
||||
'" . $star . "');";
|
||||
$result = $this->database->query($query);
|
||||
|
||||
if (!$result) {
|
||||
Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
|
||||
exit('Error: Could not save photo in database!');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 1, func_get_args());
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
private function createThumb($url, $filename, $width = 200, $height = 200) {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database, $this->settings, $url, $filename));
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 0, func_get_args());
|
||||
|
||||
$info = getimagesize($url);
|
||||
$photoName = explode(".", $filename);
|
||||
$newUrl = LYCHEE_UPLOADS_THUMB . $photoName[0] . '.jpeg';
|
||||
$newUrl2x = LYCHEE_UPLOADS_THUMB . $photoName[0] . '@2x.jpeg';
|
||||
|
||||
# create thumbnails with Imagick
|
||||
if(extension_loaded('imagick')) {
|
||||
|
||||
# Read image
|
||||
$thumb = new Imagick();
|
||||
$thumb->readImage($url);
|
||||
$thumb->setImageCompressionQuality($this->settings['thumbQuality']);
|
||||
$thumb->setImageFormat('jpeg');
|
||||
|
||||
# Copy image for 2nd thumb version
|
||||
$thumb2x = clone $thumb;
|
||||
|
||||
# Create 1st version
|
||||
$thumb->cropThumbnailImage($width, $height);
|
||||
$thumb->writeImage($newUrl);
|
||||
$thumb->clear();
|
||||
$thumb->destroy();
|
||||
|
||||
# Create 2nd version
|
||||
$thumb2x->cropThumbnailImage($width*2, $height*2);
|
||||
$thumb2x->writeImage($newUrl2x);
|
||||
$thumb2x->clear();
|
||||
$thumb2x->destroy();
|
||||
|
||||
} else {
|
||||
|
||||
# Set position and size
|
||||
$thumb = imagecreatetruecolor($width, $height);
|
||||
$thumb2x = imagecreatetruecolor($width*2, $height*2);
|
||||
if ($info[0]<$info[1]) {
|
||||
$newSize = $info[0];
|
||||
$startWidth = 0;
|
||||
$startHeight = $info[1]/2 - $info[0]/2;
|
||||
} else {
|
||||
$newSize = $info[1];
|
||||
$startWidth = $info[0]/2 - $info[1]/2;
|
||||
$startHeight = 0;
|
||||
}
|
||||
|
||||
# Create new image
|
||||
switch($info['mime']) {
|
||||
case 'image/jpeg': $sourceImg = imagecreatefromjpeg($url); break;
|
||||
case 'image/png': $sourceImg = imagecreatefrompng($url); break;
|
||||
case 'image/gif': $sourceImg = imagecreatefromgif($url); break;
|
||||
default: Log::error($this->database, __METHOD__, __LINE__, 'Type of photo is not supported');
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
# Create thumb
|
||||
fastimagecopyresampled($thumb, $sourceImg, 0, 0, $startWidth, $startHeight, $width, $height, $newSize, $newSize);
|
||||
imagejpeg($thumb, $newUrl, $this->settings['thumbQuality']);
|
||||
imagedestroy($thumb);
|
||||
|
||||
# Create retina thumb
|
||||
fastimagecopyresampled($thumb2x, $sourceImg, 0, 0, $startWidth, $startHeight, $width*2, $height*2, $newSize, $newSize);
|
||||
imagejpeg($thumb2x, $newUrl2x, $this->settings['thumbQuality']);
|
||||
imagedestroy($thumb2x);
|
||||
|
||||
# Free memory
|
||||
imagedestroy($sourceImg);
|
||||
|
||||
}
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 1, func_get_args());
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
private function adjustFile($path, $info) {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($path, $info));
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 0, func_get_args());
|
||||
|
||||
if (extension_loaded('imagick')) {
|
||||
|
||||
$rotateImage = 0;
|
||||
|
||||
switch ($info['orientation']) {
|
||||
|
||||
case 3:
|
||||
$rotateImage = 180;
|
||||
$imageOrientation = 1;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
$rotateImage = 90;
|
||||
$imageOrientation = 1;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
$rotateImage = 270;
|
||||
$imageOrientation = 1;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if ($rotateImage!==0) {
|
||||
$image = new Imagick();
|
||||
$image->readImage($path);
|
||||
$image->rotateImage(new ImagickPixel(), $rotateImage);
|
||||
$image->setImageOrientation($imageOrientation);
|
||||
$image->writeImage($path);
|
||||
$image->clear();
|
||||
$image->destroy();
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
$newWidth = $info['width'];
|
||||
$newHeight = $info['height'];
|
||||
$process = false;
|
||||
$sourceImg = imagecreatefromjpeg($path);
|
||||
|
||||
switch ($info['orientation']) {
|
||||
|
||||
case 2:
|
||||
# mirror
|
||||
# not yet implemented
|
||||
break;
|
||||
|
||||
case 3:
|
||||
$process = true;
|
||||
$sourceImg = imagerotate($sourceImg, -180, 0);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
# rotate 180 and mirror
|
||||
# not yet implemented
|
||||
break;
|
||||
|
||||
case 5:
|
||||
# rotate 90 and mirror
|
||||
# not yet implemented
|
||||
break;
|
||||
|
||||
case 6:
|
||||
$process = true;
|
||||
$sourceImg = imagerotate($sourceImg, -90, 0);
|
||||
$newWidth = $info['height'];
|
||||
$newHeight = $info['width'];
|
||||
break;
|
||||
|
||||
case 7:
|
||||
# rotate -90 and mirror
|
||||
# not yet implemented
|
||||
break;
|
||||
|
||||
case 8:
|
||||
$process = true;
|
||||
$sourceImg = imagerotate($sourceImg, 90, 0);
|
||||
$newWidth = $info['height'];
|
||||
$newHeight = $info['width'];
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
# Need to adjust photo?
|
||||
if ($process===true) {
|
||||
|
||||
# Recreate photo
|
||||
$newSourceImg = imagecreatetruecolor($newWidth, $newHeight);
|
||||
imagecopyresampled($newSourceImg, $sourceImg, 0, 0, 0, 0, $newWidth, $newHeight, $newWidth, $newHeight);
|
||||
imagejpeg($newSourceImg, $path, 100);
|
||||
|
||||
# Free memory
|
||||
imagedestroy($sourceImg);
|
||||
imagedestroy($newSourceImg);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 1, func_get_args());
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public function get($albumID) {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database, $this->photoIDs));
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 0, func_get_args());
|
||||
|
||||
# Get photo
|
||||
$photos = $this->database->query("SELECT * FROM lychee_photos WHERE id = '$this->photoIDs' LIMIT 1;");
|
||||
$photo = $photos->fetch_assoc();
|
||||
|
||||
# Parse photo
|
||||
$photo['sysdate'] = date('d M. Y', substr($photo['id'], 0, -4));
|
||||
if (strlen($photo['takestamp'])>1) $photo['takedate'] = date('d M. Y', $photo['takestamp']);
|
||||
|
||||
if ($albumID!='false') {
|
||||
|
||||
if ($photo['album']!=0) {
|
||||
|
||||
# Get album
|
||||
$albums = $this->database->query("SELECT public FROM lychee_albums WHERE id = '" . $photo['album'] . " LIMIT 1';");
|
||||
$album = $albums->fetch_assoc();
|
||||
|
||||
# Parse album
|
||||
$photo['public'] = ($album['public']=='1' ? '2' : $photo['public']);
|
||||
|
||||
}
|
||||
|
||||
$photo['original_album'] = $photo['album'];
|
||||
$photo['album'] = $albumID;
|
||||
|
||||
}
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 1, func_get_args());
|
||||
|
||||
return $photo;
|
||||
|
||||
}
|
||||
|
||||
private function getInfo($url) {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database, $url));
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 0, func_get_args());
|
||||
|
||||
$iptcArray = array();
|
||||
$info = getimagesize($url, $iptcArray);
|
||||
|
||||
# General information
|
||||
$return['type'] = $info['mime'];
|
||||
$return['width'] = $info[0];
|
||||
$return['height'] = $info[1];
|
||||
|
||||
# Size
|
||||
$size = filesize($url)/1024;
|
||||
if ($size>=1024) $return['size'] = round($size/1024, 1) . ' MB';
|
||||
else $return['size'] = round($size, 1) . ' KB';
|
||||
|
||||
# IPTC Metadata Fallback
|
||||
$return['title'] = '';
|
||||
$return['description'] = '';
|
||||
|
||||
# IPTC Metadata
|
||||
if(isset($iptcArray['APP13'])) {
|
||||
|
||||
$iptcInfo = iptcparse($iptcArray['APP13']);
|
||||
if (is_array($iptcInfo)) {
|
||||
|
||||
$temp = @$iptcInfo['2#105'][0];
|
||||
if (isset($temp)&&strlen($temp)>0) $return['title'] = $temp;
|
||||
|
||||
$temp = @$iptcInfo['2#120'][0];
|
||||
if (isset($temp)&&strlen($temp)>0) $return['description'] = $temp;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# EXIF Metadata Fallback
|
||||
$return['orientation'] = '';
|
||||
$return['iso'] = '';
|
||||
$return['aperture'] = '';
|
||||
$return['make'] = '';
|
||||
$return['model'] = '';
|
||||
$return['shutter'] = '';
|
||||
$return['focal'] = '';
|
||||
$return['takestamp'] = 0;
|
||||
|
||||
# Read EXIF
|
||||
if ($info['mime']=='image/jpeg') $exif = @exif_read_data($url, 'EXIF', 0);
|
||||
else $exif = false;
|
||||
|
||||
# EXIF Metadata
|
||||
if ($exif!==false) {
|
||||
|
||||
if (isset($exif['Orientation'])) $return['orientation'] = $exif['Orientation'];
|
||||
else if (isset($exif['IFD0']['Orientation'])) $return['orientation'] = $exif['IFD0']['Orientation'];
|
||||
|
||||
$temp = @$exif['ISOSpeedRatings'];
|
||||
if (isset($temp)) $return['iso'] = $temp;
|
||||
|
||||
$temp = @$exif['COMPUTED']['ApertureFNumber'];
|
||||
if (isset($temp)) $return['aperture'] = $temp;
|
||||
|
||||
$temp = @$exif['Make'];
|
||||
if (isset($temp)) $return['make'] = trim($temp);
|
||||
|
||||
$temp = @$exif['Model'];
|
||||
if (isset($temp)) $return['model'] = trim($temp);
|
||||
|
||||
$temp = @$exif['ExposureTime'];
|
||||
if (isset($temp)) $return['shutter'] = $exif['ExposureTime'] . ' Sec.';
|
||||
|
||||
$temp = @$exif['FocalLength'];
|
||||
if (isset($temp)) $return['focal'] = ($temp/1) . ' mm';
|
||||
|
||||
$temp = @$exif['DateTimeOriginal'];
|
||||
if (isset($temp)) $return['takestamp'] = strtotime($temp);
|
||||
|
||||
}
|
||||
|
||||
# Security
|
||||
foreach(array_keys($return) as $key) $return[$key] = mysqli_real_escape_string($this->database, $return[$key]);
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 1, func_get_args());
|
||||
|
||||
return $return;
|
||||
|
||||
}
|
||||
|
||||
public function getArchive() {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database, $this->photoIDs));
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 0, func_get_args());
|
||||
|
||||
# Get photo
|
||||
$photos = $this->database->query("SELECT title, url FROM lychee_photos WHERE id = '$this->photoIDs' LIMIT 1;");
|
||||
$photo = $photos->fetch_object();
|
||||
|
||||
# Get extension
|
||||
$extension = getExtension($photo->url);
|
||||
if ($extension===false) {
|
||||
Log::error($this->database, __METHOD__, __LINE__, 'Invalid photo extension');
|
||||
return false;
|
||||
}
|
||||
|
||||
# Parse title
|
||||
if ($photo->title=='') $photo->title = 'Untitled';
|
||||
|
||||
# Set headers
|
||||
header("Content-Type: application/octet-stream");
|
||||
header("Content-Disposition: attachment; filename=\"" . $photo->title . $extension . "\"");
|
||||
header("Content-Length: " . filesize(LYCHEE_UPLOADS_BIG . $photo->url));
|
||||
|
||||
# Send file
|
||||
readfile(LYCHEE_UPLOADS_BIG . $photo->url);
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 1, func_get_args());
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public function setTitle($title) {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database, $this->photoIDs));
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 0, func_get_args());
|
||||
|
||||
# Parse
|
||||
if (strlen($title)>50) $title = substr($title, 0, 50);
|
||||
|
||||
# Set title
|
||||
$result = $this->database->query("UPDATE lychee_photos SET title = '$title' WHERE id IN ($this->photoIDs);");
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 1, func_get_args());
|
||||
|
||||
if (!$result) {
|
||||
Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public function setDescription($description) {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database, $this->photoIDs));
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 0, func_get_args());
|
||||
|
||||
# Parse
|
||||
$description = htmlentities($description);
|
||||
if (strlen($description)>1000) $description = substr($description, 0, 1000);
|
||||
|
||||
# Set description
|
||||
$result = $this->database->query("UPDATE lychee_photos SET description = '$description' WHERE id IN ('$this->photoIDs');");
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 1, func_get_args());
|
||||
|
||||
if (!$result) {
|
||||
Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public function setStar() {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database, $this->photoIDs));
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 0, func_get_args());
|
||||
|
||||
# Init vars
|
||||
$error = false;
|
||||
|
||||
# Get photos
|
||||
$photos = $this->database->query("SELECT id, star FROM lychee_photos WHERE id IN ($this->photoIDs);");
|
||||
|
||||
# For each photo
|
||||
while ($photo = $photos->fetch_object()) {
|
||||
|
||||
# Invert star
|
||||
$star = ($photo->star==0 ? 1 : 0);
|
||||
|
||||
# Set star
|
||||
$star = $this->database->query("UPDATE lychee_photos SET star = '$star' WHERE id = '$photo->id';");
|
||||
if (!$star) $error = true;
|
||||
|
||||
}
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 1, func_get_args());
|
||||
|
||||
if ($error===true) {
|
||||
Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public function getPublic($password) {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database, $this->photoIDs));
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 0, func_get_args());
|
||||
|
||||
# Get photo
|
||||
$photos = $this->database->query("SELECT public, album FROM lychee_photos WHERE id = '$this->photoIDs' LIMIT 1;");
|
||||
$photo = $photos->fetch_object();
|
||||
|
||||
# Check if public
|
||||
if ($photo->public==1) return true;
|
||||
else {
|
||||
$album = new Album($this->database, null, null, $photo->album);
|
||||
$acP = $album->checkPassword($password);
|
||||
$agP = $album->getPublic();
|
||||
if ($acP===true&&$agP===true) return true;
|
||||
}
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 1, func_get_args());
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
public function setPublic() {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database, $this->photoIDs));
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 0, func_get_args());
|
||||
|
||||
# Get public
|
||||
$photos = $this->database->query("SELECT public FROM lychee_photos WHERE id = '$this->photoIDs' LIMIT 1;");
|
||||
$photo = $photos->fetch_object();
|
||||
|
||||
# Invert public
|
||||
$public = ($photo->public==0 ? 1 : 0);
|
||||
|
||||
# Set public
|
||||
$result = $this->database->query("UPDATE lychee_photos SET public = '$public' WHERE id = '$this->photoIDs';");
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 1, func_get_args());
|
||||
|
||||
if (!$result) {
|
||||
Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
function setAlbum($albumID) {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database, $this->photoIDs));
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 0, func_get_args());
|
||||
|
||||
# Set album
|
||||
$result = $this->database->query("UPDATE lychee_photos SET album = '$albumID' WHERE id IN ($this->photoIDs);");
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 1, func_get_args());
|
||||
|
||||
if (!$result) {
|
||||
Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public function setTags($tags) {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database, $this->photoIDs));
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 0, func_get_args());
|
||||
|
||||
# Parse tags
|
||||
$tags = preg_replace('/(\ ,\ )|(\ ,)|(,\ )|(,{1,}\ {0,})|(,$|^,)/', ',', $tags);
|
||||
$tags = preg_replace('/,$|^,|(\ ){0,}$/', '', $tags);
|
||||
if (strlen($tags)>1000) {
|
||||
Log::notice($this->database, __METHOD__, __LINE__, 'Length of tags higher than 1000');
|
||||
return false;
|
||||
}
|
||||
|
||||
# Set tags
|
||||
$result = $this->database->query("UPDATE lychee_photos SET tags = '$tags' WHERE id IN ($this->photoIDs);");
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 1, func_get_args());
|
||||
|
||||
if (!$result) {
|
||||
Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public function delete() {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database, $this->photoIDs));
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 0, func_get_args());
|
||||
|
||||
# Get photos
|
||||
$photos = $this->database->query("SELECT id, url, thumbUrl FROM lychee_photos WHERE id IN ($this->photoIDs);");
|
||||
if (!$photos) {
|
||||
Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
|
||||
return false;
|
||||
}
|
||||
|
||||
# For each photo
|
||||
while ($photo = $photos->fetch_object()) {
|
||||
|
||||
# Get retina thumb url
|
||||
$thumbUrl2x = explode(".", $photo->thumbUrl);
|
||||
$thumbUrl2x = $thumbUrl2x[0] . '@2x.' . $thumbUrl2x[1];
|
||||
|
||||
# Delete big
|
||||
if (file_exists(LYCHEE_UPLOADS_BIG . $photo->url)&&!unlink(LYCHEE_UPLOADS_BIG . $photo->url)) {
|
||||
Log::error($this->database, __METHOD__, __LINE__, 'Could not delete photo in uploads/big/');
|
||||
return false;
|
||||
}
|
||||
|
||||
# Delete thumb
|
||||
if (file_exists(LYCHEE_UPLOADS_THUMB . $photo->thumbUrl)&&!unlink(LYCHEE_UPLOADS_THUMB . $photo->thumbUrl)) {
|
||||
Log::error($this->database, __METHOD__, __LINE__, 'Could not delete photo in uploads/thumb/');
|
||||
return false;
|
||||
}
|
||||
|
||||
# Delete thumb@2x
|
||||
if (file_exists(LYCHEE_UPLOADS_THUMB . $thumbUrl2x)&&!unlink(LYCHEE_UPLOADS_THUMB . $thumbUrl2x)) {
|
||||
Log::error($this->database, __METHOD__, __LINE__, 'Could not delete high-res photo in uploads/thumb/');
|
||||
return false;
|
||||
}
|
||||
|
||||
# Delete db entry
|
||||
$delete = $this->database->query("DELETE FROM lychee_photos WHERE id = '$photo->id';");
|
||||
if (!$delete) {
|
||||
Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 1, func_get_args());
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
96
php/modules/Plugins.php
Normal file
96
php/modules/Plugins.php
Normal file
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
###
|
||||
# @name Plugins Module
|
||||
# @author Tobias Reich
|
||||
# @copyright 2014 by Tobias Reich
|
||||
###
|
||||
|
||||
if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
|
||||
|
||||
class Plugins implements \SplSubject {
|
||||
|
||||
private $files = array();
|
||||
private $observers = array();
|
||||
|
||||
public $action = null;
|
||||
public $args = null;
|
||||
|
||||
public function __construct($files, $database, $settings) {
|
||||
|
||||
if (!isset($files)) return false;
|
||||
|
||||
# Init vars
|
||||
$plugins = $this;
|
||||
$this->files = $files;
|
||||
|
||||
# Load plugins
|
||||
foreach ($this->files as $file) {
|
||||
|
||||
if ($file==='') continue;
|
||||
|
||||
$file = LYCHEE_PLUGINS . $file;
|
||||
|
||||
if (file_exists($file)===false) {
|
||||
Log::warning($database, __METHOD__, __LINE__, 'Could not include plugin. File does not exist (' . $file . ').');
|
||||
continue;
|
||||
}
|
||||
|
||||
include($file);
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public function attach(\SplObserver $observer) {
|
||||
|
||||
if (!isset($observer)) return false;
|
||||
|
||||
# Add observer
|
||||
$this->observers[] = $observer;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public function detach(\SplObserver $observer) {
|
||||
|
||||
if (!isset($observer)) return false;
|
||||
|
||||
# Remove observer
|
||||
$key = array_search($observer, $this->observers, true);
|
||||
if ($key) unset($this->observers[$key]);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public function notify() {
|
||||
|
||||
# Notify each observer
|
||||
foreach ($this->observers as $value) $value->update($this);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public function activate($action, $args) {
|
||||
|
||||
if (!isset($action, $args)) return false;
|
||||
|
||||
# Save vars
|
||||
$this->action = $action;
|
||||
$this->args = $args;
|
||||
|
||||
# Notify observers
|
||||
$this->notify();
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
124
php/modules/Session.php
Executable file
124
php/modules/Session.php
Executable file
@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
###
|
||||
# @name Session Module
|
||||
# @author Tobias Reich
|
||||
# @copyright 2014 by Tobias Reich
|
||||
###
|
||||
|
||||
if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
|
||||
|
||||
class Session extends Module {
|
||||
|
||||
private $settings = null;
|
||||
|
||||
public function __construct($plugins, $settings) {
|
||||
|
||||
# Init vars
|
||||
$this->plugins = $plugins;
|
||||
$this->settings = $settings;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public function init($database, $dbName, $public, $version) {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->settings, $public, $version));
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 0, func_get_args());
|
||||
|
||||
# Update
|
||||
if (!isset($this->settings['version'])||$this->settings['version']!==$version) {
|
||||
if (!Database::update($database, $dbName, @$this->settings['version'])) {
|
||||
Log::error($database, __METHOD__, __LINE__, 'Updating the database failed');
|
||||
exit('Error: Updating the database failed!');
|
||||
}
|
||||
}
|
||||
|
||||
# Return settings
|
||||
$return['config'] = $this->settings;
|
||||
unset($return['config']['password']);
|
||||
|
||||
# No login
|
||||
if ($this->settings['username']===''&&$this->settings['password']==='') $return['config']['login'] = false;
|
||||
else $return['config']['login'] = true;
|
||||
|
||||
if ($public===false) {
|
||||
|
||||
# Logged in
|
||||
$return['loggedIn'] = true;
|
||||
|
||||
} else {
|
||||
|
||||
# Unset unused vars
|
||||
unset($return['config']['username']);
|
||||
unset($return['config']['thumbQuality']);
|
||||
unset($return['config']['sorting']);
|
||||
unset($return['config']['dropboxKey']);
|
||||
unset($return['config']['login']);
|
||||
|
||||
# Logged out
|
||||
$return['loggedIn'] = false;
|
||||
|
||||
}
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 1, func_get_args());
|
||||
|
||||
return $return;
|
||||
|
||||
}
|
||||
|
||||
public function login($username, $password) {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->settings, $username, $password));
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 0, func_get_args());
|
||||
|
||||
# Check login with MD5 hash
|
||||
if ($username===$this->settings['username']&&$password===$this->settings['password']) {
|
||||
$_SESSION['login'] = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
# Check login with crypted hash
|
||||
if ($username===$this->settings['username']&&$this->settings['password']===crypt($password, $this->settings['password'])) {
|
||||
$_SESSION['login'] = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
# No login
|
||||
if ($this->settings['username']===''&&$this->settings['password']==='') {
|
||||
$_SESSION['login'] = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 1, func_get_args());
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
public function logout() {
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 0, func_get_args());
|
||||
|
||||
session_destroy();
|
||||
|
||||
# Call plugins
|
||||
$this->plugins(__METHOD__, 1, func_get_args());
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
191
php/modules/Settings.php
Executable file
191
php/modules/Settings.php
Executable file
@ -0,0 +1,191 @@
|
||||
<?php
|
||||
|
||||
###
|
||||
# @name Settings Module
|
||||
# @author Tobias Reich
|
||||
# @copyright 2014 by Tobias Reich
|
||||
###
|
||||
|
||||
if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
|
||||
|
||||
class Settings extends Module {
|
||||
|
||||
private $database = null;
|
||||
|
||||
public function __construct($database) {
|
||||
|
||||
# Init vars
|
||||
$this->database = $database;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public function get() {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database));
|
||||
|
||||
# Execute query
|
||||
$settings = $this->database->query('SELECT * FROM lychee_settings;');
|
||||
|
||||
# Add each to return
|
||||
while ($setting = $settings->fetch_object()) $return[$setting->key] = $setting->value;
|
||||
|
||||
# Fallback for versions below v2.5
|
||||
if (!isset($return['plugins'])) $return['plugins'] = '';
|
||||
|
||||
return $return;
|
||||
|
||||
}
|
||||
|
||||
public function setLogin($oldPassword = '', $username, $password) {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database));
|
||||
|
||||
# Load settings
|
||||
$settings = $this->get();
|
||||
|
||||
if ($oldPassword===$settings['password']||$settings['password']===crypt($oldPassword, $settings['password'])) {
|
||||
|
||||
# Save username
|
||||
if (!$this->setUsername($username)) exit('Error: Updating username failed!');
|
||||
|
||||
# Save password
|
||||
if (!$this->setPassword($password)) exit('Error: Updating password failed!');
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
exit('Error: Current password entered incorrectly!');
|
||||
|
||||
}
|
||||
|
||||
private function setUsername($username) {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database));
|
||||
|
||||
# Parse
|
||||
$username = htmlentities($username);
|
||||
if (strlen($username)>50) {
|
||||
Log::notice($this->database, __METHOD__, __LINE__, 'Username is longer than 50 chars');
|
||||
return false;
|
||||
}
|
||||
|
||||
# Execute query
|
||||
$result = $this->database->query("UPDATE lychee_settings SET value = '$username' WHERE `key` = 'username';");
|
||||
|
||||
if (!$result) {
|
||||
Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
private function setPassword($password) {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database));
|
||||
|
||||
$password = get_hashed_password($password);
|
||||
|
||||
# Execute query
|
||||
$result = $this->database->query("UPDATE lychee_settings SET value = '$password' WHERE `key` = 'password';");
|
||||
|
||||
if (!$result) {
|
||||
Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public function setDropboxKey($key) {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database, $key));
|
||||
|
||||
if (strlen($key)<1||strlen($key)>50) {
|
||||
Log::notice($this->database, __METHOD__, __LINE__, 'Dropbox key is either too short or too long');
|
||||
return false;
|
||||
}
|
||||
|
||||
# Execute query
|
||||
$result = $this->database->query("UPDATE lychee_settings SET value = '$key' WHERE `key` = 'dropboxKey';");
|
||||
|
||||
if (!$result) {
|
||||
Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public function setSorting($type, $order) {
|
||||
|
||||
# Check dependencies
|
||||
$this->dependencies(isset($this->database, $type, $order));
|
||||
|
||||
$sorting = 'ORDER BY ';
|
||||
|
||||
# Set row
|
||||
switch ($type) {
|
||||
|
||||
case 'id': $sorting .= 'id';
|
||||
break;
|
||||
|
||||
case 'title': $sorting .= 'title';
|
||||
break;
|
||||
|
||||
case 'description': $sorting .= 'description';
|
||||
break;
|
||||
|
||||
case 'public': $sorting .= 'public';
|
||||
break;
|
||||
|
||||
case 'type': $sorting .= 'type';
|
||||
break;
|
||||
|
||||
case 'star': $sorting .= 'star';
|
||||
break;
|
||||
|
||||
case 'takestamp': $sorting .= 'takestamp';
|
||||
break;
|
||||
|
||||
default: exit('Error: Unknown type for sorting!');
|
||||
|
||||
}
|
||||
|
||||
$sorting .= ' ';
|
||||
|
||||
# Set order
|
||||
switch ($order) {
|
||||
|
||||
case 'ASC': $sorting .= 'ASC';
|
||||
break;
|
||||
|
||||
case 'DESC': $sorting .= 'DESC';
|
||||
break;
|
||||
|
||||
default: exit('Error: Unknown order for sorting!');
|
||||
|
||||
}
|
||||
|
||||
# Execute query
|
||||
$result = $this->database->query("UPDATE lychee_settings SET value = '$sorting' WHERE `key` = 'sorting';");
|
||||
|
||||
if (!$result) {
|
||||
Log::error($this->database, __METHOD__, __LINE__, $this->database->error);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
@ -1,353 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @name Album Module
|
||||
* @author Philipp Maurer
|
||||
* @author Tobias Reich
|
||||
* @copyright 2014 by Philipp Maurer, Tobias Reich
|
||||
*/
|
||||
|
||||
if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
|
||||
|
||||
function addAlbum($title, $public = 0) {
|
||||
|
||||
global $database;
|
||||
|
||||
if (strlen($title)<1||strlen($title)>50) return false;
|
||||
|
||||
$sysdate = date("d.m.Y");
|
||||
$result = $database->query("INSERT INTO lychee_albums (title, sysdate, public) VALUES ('$title', '$sysdate', '$public');");
|
||||
|
||||
if (!$result) return false;
|
||||
return $database->insert_id;
|
||||
|
||||
}
|
||||
|
||||
function getAlbums($public) {
|
||||
|
||||
global $database, $settings;
|
||||
|
||||
// Smart Albums
|
||||
if (!$public) $return = getSmartInfo();
|
||||
|
||||
// Albums
|
||||
if ($public) $query = "SELECT id, title, public, sysdate, password FROM lychee_albums WHERE public = 1";
|
||||
else $query = "SELECT id, title, public, sysdate, password FROM lychee_albums";
|
||||
|
||||
$result = $database->query($query) OR exit("Error: $result <br>".$database->error);
|
||||
$i = 0;
|
||||
|
||||
while($row = $result->fetch_object()) {
|
||||
|
||||
// Info
|
||||
$return["content"][$row->id]['id'] = $row->id;
|
||||
$return["content"][$row->id]['title'] = $row->title;
|
||||
$return["content"][$row->id]['public'] = $row->public;
|
||||
$return["content"][$row->id]['sysdate'] = date('F Y', strtotime($row->sysdate));
|
||||
|
||||
// Password
|
||||
if ($row->password=="") $return["content"][$row->id]['password'] = false;
|
||||
else $return["content"][$row->id]['password'] = true;
|
||||
|
||||
// Thumbs
|
||||
if (($public&&$row->password=="")||(!$public)) {
|
||||
|
||||
$albumID = $row->id;
|
||||
$result2 = $database->query("SELECT thumbUrl FROM lychee_photos WHERE album = '$albumID' ORDER BY star DESC, " . substr($settings['sorting'], 9) . " LIMIT 0, 3");
|
||||
$k = 0;
|
||||
while($row2 = $result2->fetch_object()){
|
||||
$return["content"][$row->id]["thumb$k"] = $row2->thumbUrl;
|
||||
$k++;
|
||||
}
|
||||
if (!isset($return["content"][$row->id]["thumb0"])) $return["content"][$row->id]["thumb0"] = "";
|
||||
if (!isset($return["content"][$row->id]["thumb1"])) $return["content"][$row->id]["thumb1"] = "";
|
||||
if (!isset($return["content"][$row->id]["thumb2"])) $return["content"][$row->id]["thumb2"] = "";
|
||||
|
||||
}
|
||||
|
||||
// Album count
|
||||
$i++;
|
||||
|
||||
}
|
||||
|
||||
$return["num"] = $i;
|
||||
|
||||
return $return;
|
||||
|
||||
}
|
||||
|
||||
function getSmartInfo() {
|
||||
|
||||
global $database, $settings;
|
||||
|
||||
// Unsorted
|
||||
$result = $database->query("SELECT thumbUrl FROM lychee_photos WHERE album = 0 " . $settings['sorting']);
|
||||
$i = 0;
|
||||
while($row = $result->fetch_object()) {
|
||||
if ($i<3) $return["unsortedThumb$i"] = $row->thumbUrl;
|
||||
$i++;
|
||||
}
|
||||
$return['unsortedNum'] = $i;
|
||||
|
||||
// Public
|
||||
$result2 = $database->query("SELECT thumbUrl FROM lychee_photos WHERE public = 1 " . $settings['sorting']);
|
||||
$i = 0;
|
||||
while($row2 = $result2->fetch_object()) {
|
||||
if ($i<3) $return["publicThumb$i"] = $row2->thumbUrl;
|
||||
$i++;
|
||||
}
|
||||
$return['publicNum'] = $i;
|
||||
|
||||
// Starred
|
||||
$result3 = $database->query("SELECT thumbUrl FROM lychee_photos WHERE star = 1 " . $settings['sorting']);
|
||||
$i = 0;
|
||||
while($row3 = $result3->fetch_object()) {
|
||||
if ($i<3) $return["starredThumb$i"] = $row3->thumbUrl;
|
||||
$i++;
|
||||
}
|
||||
$return['starredNum'] = $i;
|
||||
|
||||
return $return;
|
||||
|
||||
}
|
||||
|
||||
function getAlbum($albumID) {
|
||||
|
||||
global $database, $settings;
|
||||
|
||||
// Get album information
|
||||
switch($albumID) {
|
||||
|
||||
case "f": $return['public'] = false;
|
||||
$query = "SELECT id, title, tags, sysdate, public, star, album, thumbUrl FROM lychee_photos WHERE star = 1 " . $settings['sorting'];
|
||||
break;
|
||||
|
||||
case "s": $return['public'] = false;
|
||||
$query = "SELECT id, title, tags, sysdate, public, star, album, thumbUrl FROM lychee_photos WHERE public = 1 " . $settings['sorting'];
|
||||
break;
|
||||
|
||||
case "0": $return['public'] = false;
|
||||
$query = "SELECT id, title, tags, sysdate, public, star, album, thumbUrl FROM lychee_photos WHERE album = 0 " . $settings['sorting'];
|
||||
break;
|
||||
|
||||
default: $result = $database->query("SELECT * FROM lychee_albums WHERE id = '$albumID';");
|
||||
$row = $result->fetch_object();
|
||||
$return['title'] = $row->title;
|
||||
$return['description'] = $row->description;
|
||||
$return['sysdate'] = date('d M. Y', strtotime($row->sysdate));
|
||||
$return['public'] = $row->public;
|
||||
$return['password'] = ($row->password=="" ? false : true);
|
||||
$query = "SELECT id, title, tags, sysdate, public, star, album, thumbUrl FROM lychee_photos WHERE album = '$albumID' " . $settings['sorting'];
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// Get photos
|
||||
$result = $database->query($query);
|
||||
$previousPhotoID = "";
|
||||
$i = 0;
|
||||
while($row = $result->fetch_assoc()) {
|
||||
|
||||
$return['content'][$row['id']]['id'] = $row['id'];
|
||||
$return['content'][$row['id']]['title'] = $row['title'];
|
||||
$return['content'][$row['id']]['sysdate'] = date('d F Y', strtotime($row['sysdate']));
|
||||
$return['content'][$row['id']]['public'] = $row['public'];
|
||||
$return['content'][$row['id']]['star'] = $row['star'];
|
||||
$return['content'][$row['id']]['tags'] = $row['tags'];
|
||||
$return['content'][$row['id']]['album'] = $row['album'];
|
||||
$return['content'][$row['id']]['thumbUrl'] = $row['thumbUrl'];
|
||||
|
||||
$return['content'][$row['id']]['previousPhoto'] = $previousPhotoID;
|
||||
$return['content'][$row['id']]['nextPhoto'] = "";
|
||||
if ($previousPhotoID!="") $return['content'][$previousPhotoID]['nextPhoto'] = $row['id'];
|
||||
|
||||
$previousPhotoID = $row['id'];
|
||||
$i++;
|
||||
|
||||
}
|
||||
|
||||
if ($i==0) {
|
||||
|
||||
// Empty album
|
||||
$return['content'] = false;
|
||||
|
||||
} else {
|
||||
|
||||
// Enable next and previous for the first and last photo
|
||||
$lastElement = end($return['content']);
|
||||
$lastElementId = $lastElement['id'];
|
||||
$firstElement = reset($return['content']);
|
||||
$firstElementId = $firstElement['id'];
|
||||
|
||||
if ($lastElementId!==$firstElementId) {
|
||||
$return['content'][$lastElementId]['nextPhoto'] = $firstElementId;
|
||||
$return['content'][$firstElementId]['previousPhoto'] = $lastElementId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$return['id'] = $albumID;
|
||||
$return['num'] = $i;
|
||||
|
||||
return $return;
|
||||
|
||||
}
|
||||
|
||||
function setAlbumTitle($albumIDs, $title) {
|
||||
|
||||
global $database;
|
||||
|
||||
if (strlen($title)<1||strlen($title)>50) return false;
|
||||
$result = $database->query("UPDATE lychee_albums SET title = '$title' WHERE id IN ($albumIDs);");
|
||||
|
||||
if (!$result) return false;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
function setAlbumDescription($albumID, $description) {
|
||||
|
||||
global $database;
|
||||
|
||||
$description = htmlentities($description);
|
||||
if (strlen($description)>1000) return false;
|
||||
$result = $database->query("UPDATE lychee_albums SET description = '$description' WHERE id = '$albumID';");
|
||||
|
||||
if (!$result) return false;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
function deleteAlbum($albumIDs) {
|
||||
|
||||
global $database;
|
||||
|
||||
$error = false;
|
||||
$result = $database->query("SELECT id FROM lychee_photos WHERE album IN ($albumIDs);");
|
||||
|
||||
// Delete photos
|
||||
while ($row = $result->fetch_object())
|
||||
if (!deletePhoto($row->id)) $error = true;
|
||||
|
||||
// Delete album
|
||||
$result = $database->query("DELETE FROM lychee_albums WHERE id IN ($albumIDs);");
|
||||
|
||||
if ($error||!$result) return false;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
function getAlbumArchive($albumID) {
|
||||
|
||||
global $database;
|
||||
|
||||
switch($albumID) {
|
||||
case 's':
|
||||
$query = "SELECT url FROM lychee_photos WHERE public = '1';";
|
||||
$zipTitle = "Public";
|
||||
break;
|
||||
case 'f':
|
||||
$query = "SELECT url FROM lychee_photos WHERE star = '1';";
|
||||
$zipTitle = "Starred";
|
||||
break;
|
||||
default:
|
||||
$query = "SELECT url FROM lychee_photos WHERE album = '$albumID';";
|
||||
$zipTitle = "Unsorted";
|
||||
}
|
||||
|
||||
$zip = new ZipArchive();
|
||||
$result = $database->query($query);
|
||||
$files = array();
|
||||
$i = 0;
|
||||
|
||||
while($row = $result->fetch_object()) {
|
||||
$files[$i] = "../uploads/big/".$row->url;
|
||||
$i++;
|
||||
}
|
||||
|
||||
$result = $database->query("SELECT title FROM lychee_albums WHERE id = '$albumID' LIMIT 1;");
|
||||
$row = $result->fetch_object();
|
||||
if ($albumID!=0&&is_numeric($albumID)) $zipTitle = $row->title;
|
||||
$filename = "../data/$zipTitle.zip";
|
||||
|
||||
if ($zip->open($filename, ZIPARCHIVE::CREATE)!==TRUE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach($files AS $zipFile) {
|
||||
$newFile = explode("/",$zipFile);
|
||||
$newFile = array_reverse($newFile);
|
||||
$zip->addFile($zipFile, $zipTitle."/".$newFile[0]);
|
||||
}
|
||||
|
||||
$zip->close();
|
||||
|
||||
header("Content-Type: application/zip");
|
||||
header("Content-Disposition: attachment; filename=\"$zipTitle.zip\"");
|
||||
header("Content-Length: ".filesize($filename));
|
||||
readfile($filename);
|
||||
unlink($filename);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
function setAlbumPublic($albumID, $password) {
|
||||
|
||||
global $database;
|
||||
|
||||
$result = $database->query("SELECT public FROM lychee_albums WHERE id = '$albumID';");
|
||||
$row = $result->fetch_object();
|
||||
$public = ($row->public=='0' ? 1 : 0);
|
||||
|
||||
$result = $database->query("UPDATE lychee_albums SET public = '$public', password = NULL WHERE id = '$albumID';");
|
||||
if (!$result) return false;
|
||||
|
||||
if ($public==1) {
|
||||
$result = $database->query("UPDATE lychee_photos SET public = 0 WHERE album = '$albumID';");
|
||||
if (!$result) return false;
|
||||
}
|
||||
|
||||
if (strlen($password)>0) return setAlbumPassword($albumID, $password);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
function setAlbumPassword($albumID, $password) {
|
||||
|
||||
global $database;
|
||||
|
||||
$result = $database->query("UPDATE lychee_albums SET password = '$password' WHERE id = '$albumID';");
|
||||
|
||||
if (!$result) return false;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
function checkAlbumPassword($albumID, $password) {
|
||||
|
||||
global $database;
|
||||
|
||||
$result = $database->query("SELECT password FROM lychee_albums WHERE id = '$albumID';");
|
||||
$row = $result->fetch_object();
|
||||
|
||||
if ($row->password=="") return true;
|
||||
else if ($row->password==$password) return true;
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
function isAlbumPublic($albumID) {
|
||||
|
||||
global $database;
|
||||
|
||||
$result = $database->query("SELECT public FROM lychee_albums WHERE id = '$albumID';");
|
||||
$row = $result->fetch_object();
|
||||
|
||||
if ($albumID==='0'||$albumID==='s'||$albumID==='f') return false;
|
||||
if ($row->public==1) return true;
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
?>
|
@ -1,185 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @name DB Module
|
||||
* @author Philipp Maurer
|
||||
* @author Tobias Reich
|
||||
* @copyright 2014 by Philipp Maurer, Tobias Reich
|
||||
*/
|
||||
|
||||
if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
|
||||
|
||||
function dbConnect() {
|
||||
|
||||
global $dbUser, $dbPassword, $dbHost, $dbName;
|
||||
|
||||
$database = new mysqli($dbHost, $dbUser, $dbPassword);
|
||||
|
||||
if ($database->connect_errno) exit('Error: ' . $database->connect_error);
|
||||
|
||||
// Avoid sql injection on older MySQL versions
|
||||
if ($database->server_version<50500) $database->set_charset('GBK');
|
||||
|
||||
if (!$database->select_db($dbName))
|
||||
if (!dbCreate($dbName, $database)) exit('Error: Could not create database!');
|
||||
|
||||
if (!$database->query('SELECT * FROM lychee_photos, lychee_albums, lychee_settings LIMIT 0;'))
|
||||
if (!dbCreateTables($database)) exit('Error: Could not create tables!');
|
||||
|
||||
return $database;
|
||||
|
||||
}
|
||||
|
||||
function dbCreateConfig($dbHost = 'localhost', $dbUser, $dbPassword, $dbName = 'lychee', $version) {
|
||||
|
||||
$dbPassword = urldecode($dbPassword);
|
||||
$database = new mysqli($dbHost, $dbUser, $dbPassword);
|
||||
|
||||
if ($database->connect_errno) return 'Warning: Connection failed!';
|
||||
else {
|
||||
|
||||
$config = "<?php
|
||||
|
||||
/**
|
||||
* @name Config
|
||||
* @author Tobias Reich
|
||||
* @copyright 2014 Tobias Reich
|
||||
*/
|
||||
|
||||
if(!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
|
||||
|
||||
// Config version
|
||||
\$configVersion = '';
|
||||
|
||||
// Database configuration
|
||||
\$dbHost = '$dbHost'; //Host of the Database
|
||||
\$dbUser = '$dbUser'; //Username of the database
|
||||
\$dbPassword = '$dbPassword'; //Password of the Database
|
||||
\$dbName = '$dbName'; //Database name
|
||||
|
||||
?>";
|
||||
|
||||
if (file_put_contents('../data/config.php', $config)===false) return 'Warning: Could not create file!';
|
||||
|
||||
$_SESSION['login'] = true;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function dbCreate($dbName, $database) {
|
||||
|
||||
$result = $database->query("CREATE DATABASE IF NOT EXISTS $dbName;");
|
||||
$database->select_db($dbName);
|
||||
|
||||
if (!$database->select_db($dbName)||!$result) return false;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
function dbCreateTables($database) {
|
||||
|
||||
if (!$database->query('SELECT * FROM lychee_settings LIMIT 0;')) {
|
||||
|
||||
$query = "
|
||||
|
||||
CREATE TABLE `lychee_settings` (
|
||||
`key` varchar(50) NOT NULL DEFAULT '',
|
||||
`value` varchar(50) DEFAULT ''
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
";
|
||||
|
||||
if (!$database->query($query)) return false;
|
||||
|
||||
$query = "
|
||||
|
||||
INSERT INTO `lychee_settings` (`key`, `value`)
|
||||
VALUES
|
||||
('username',''),
|
||||
('password',''),
|
||||
('thumbQuality','90'),
|
||||
('checkForUpdates','1'),
|
||||
('sorting','ORDER BY id DESC'),
|
||||
('dropboxKey','');
|
||||
|
||||
";
|
||||
|
||||
if (!$database->query($query)) return false;
|
||||
|
||||
}
|
||||
|
||||
if (!$database->query('SELECT * FROM lychee_albums LIMIT 0;')) {
|
||||
|
||||
$query = "
|
||||
|
||||
CREATE TABLE `lychee_albums` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(50) NOT NULL,
|
||||
`description` varchar(1000) DEFAULT '',
|
||||
`sysdate` varchar(10) NOT NULL,
|
||||
`public` tinyint(1) DEFAULT '0',
|
||||
`password` varchar(100) DEFAULT '',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
|
||||
|
||||
";
|
||||
|
||||
if (!$database->query($query)) return false;
|
||||
|
||||
}
|
||||
|
||||
if (!$database->query('SELECT * FROM lychee_photos LIMIT 0;')) {
|
||||
|
||||
$query = "
|
||||
|
||||
CREATE TABLE `lychee_photos` (
|
||||
`id` bigint(14) NOT NULL,
|
||||
`title` varchar(50) NOT NULL,
|
||||
`description` varchar(1000) NOT NULL DEFAULT '',
|
||||
`url` varchar(100) NOT NULL,
|
||||
`tags` varchar(1000) NOT NULL DEFAULT '',
|
||||
`public` tinyint(1) NOT NULL,
|
||||
`type` varchar(10) NOT NULL,
|
||||
`width` int(11) NOT NULL,
|
||||
`height` int(11) NOT NULL,
|
||||
`size` varchar(20) NOT NULL,
|
||||
`sysdate` varchar(10) NOT NULL,
|
||||
`systime` varchar(8) NOT NULL,
|
||||
`iso` varchar(15) NOT NULL,
|
||||
`aperture` varchar(20) NOT NULL,
|
||||
`make` varchar(20) NOT NULL,
|
||||
`model` varchar(50) NOT NULL,
|
||||
`shutter` varchar(30) NOT NULL,
|
||||
`focal` varchar(20) NOT NULL,
|
||||
`takedate` varchar(20) NOT NULL,
|
||||
`taketime` varchar(8) NOT NULL,
|
||||
`star` tinyint(1) NOT NULL,
|
||||
`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;
|
||||
|
||||
";
|
||||
|
||||
if (!$database->query($query)) return false;
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
function dbClose() {
|
||||
|
||||
global $database;
|
||||
|
||||
if (!$database->close()) exit('Error: Closing the connection failed!');
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
?>
|
@ -9,9 +9,50 @@
|
||||
|
||||
if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
|
||||
|
||||
function openGraphHeader($photoID) {
|
||||
function search($database, $settings, $term) {
|
||||
|
||||
global $database;
|
||||
if (!isset($database, $settings, $term)) return false;
|
||||
|
||||
$return['albums'] = '';
|
||||
|
||||
// Photos
|
||||
$result = $database->query("SELECT id, title, tags, public, star, album, thumbUrl FROM lychee_photos WHERE title like '%$term%' OR description like '%$term%' OR tags like '%$term%';");
|
||||
while($row = $result->fetch_assoc()) {
|
||||
$return['photos'][$row['id']] = $row;
|
||||
$return['photos'][$row['id']]['sysdate'] = date('d M. Y', substr($row['id'], 0, -4));
|
||||
}
|
||||
|
||||
// Albums
|
||||
$result = $database->query("SELECT id, title, public, sysstamp, password FROM lychee_albums WHERE title like '%$term%' OR description like '%$term%';");
|
||||
$i = 0;
|
||||
while($row = $result->fetch_object()) {
|
||||
|
||||
// Info
|
||||
$return['albums'][$row->id]['id'] = $row->id;
|
||||
$return['albums'][$row->id]['title'] = $row->title;
|
||||
$return['albums'][$row->id]['public'] = $row->public;
|
||||
$return['albums'][$row->id]['sysdate'] = date('F Y', $row->sysstamp);
|
||||
$return['albums'][$row->id]['password'] = ($row->password=='' ? false : true);
|
||||
|
||||
// Thumbs
|
||||
$result2 = $database->query("SELECT thumbUrl FROM lychee_photos WHERE album = '" . $row->id . "' " . $settings['sorting'] . " LIMIT 0, 3;");
|
||||
$k = 0;
|
||||
while($row2 = $result2->fetch_object()){
|
||||
$return['albums'][$row->id]["thumb$k"] = $row2->thumbUrl;
|
||||
$k++;
|
||||
}
|
||||
|
||||
$i++;
|
||||
|
||||
}
|
||||
|
||||
return $return;
|
||||
|
||||
}
|
||||
|
||||
function getGraphHeader($database, $photoID) {
|
||||
|
||||
if (!isset($database, $photoID)) return false;
|
||||
|
||||
$photoID = mysqli_real_escape_string($database, $photoID);
|
||||
|
||||
@ -39,74 +80,81 @@ function openGraphHeader($photoID) {
|
||||
|
||||
}
|
||||
|
||||
function search($term) {
|
||||
function getExtension($filename) {
|
||||
|
||||
global $database, $settings;
|
||||
$extension = strpos($filename, '.') !== false
|
||||
? strrchr($filename, '.')
|
||||
: '';
|
||||
|
||||
$return['albums'] = '';
|
||||
|
||||
// Photos
|
||||
$result = $database->query("SELECT id, title, tags, sysdate, public, star, album, thumbUrl FROM lychee_photos WHERE title like '%$term%' OR description like '%$term%' OR tags like '%$term%';");
|
||||
while($row = $result->fetch_assoc()) {
|
||||
$return['photos'][$row['id']] = $row;
|
||||
$return['photos'][$row['id']]['sysdate'] = date('d F Y', strtotime($row['sysdate']));
|
||||
}
|
||||
|
||||
// Albums
|
||||
$result = $database->query("SELECT id, title, public, sysdate, password FROM lychee_albums WHERE title like '%$term%' OR description like '%$term%';");
|
||||
$i = 0;
|
||||
while($row = $result->fetch_object()) {
|
||||
|
||||
// Info
|
||||
$return['albums'][$row->id]['id'] = $row->id;
|
||||
$return['albums'][$row->id]['title'] = $row->title;
|
||||
$return['albums'][$row->id]['public'] = $row->public;
|
||||
$return['albums'][$row->id]['sysdate'] = date('F Y', strtotime($row->sysdate));
|
||||
$return['albums'][$row->id]['password'] = ($row->password=='' ? false : true);
|
||||
|
||||
// Thumbs
|
||||
$result2 = $database->query("SELECT thumbUrl FROM lychee_photos WHERE album = '" . $row->id . "' " . $settings['sorting'] . " LIMIT 0, 3;");
|
||||
$k = 0;
|
||||
while($row2 = $result2->fetch_object()){
|
||||
$return['albums'][$row->id]["thumb$k"] = $row2->thumbUrl;
|
||||
$k++;
|
||||
}
|
||||
|
||||
$i++;
|
||||
|
||||
}
|
||||
|
||||
return $return;
|
||||
return $extension;
|
||||
|
||||
}
|
||||
|
||||
function update($version = '') {
|
||||
function get_hashed_password($password) {
|
||||
|
||||
global $database, $configVersion;
|
||||
# Inspired by http://alias.io/2010/01/store-passwords-safely-with-php-and-mysql/
|
||||
|
||||
// Albums
|
||||
if(!$database->query("SELECT `description` FROM `lychee_albums` LIMIT 1;")) $database->query("ALTER TABLE `lychee_albums` ADD `description` VARCHAR( 1000 ) NULL DEFAULT ''"); // v2.0
|
||||
if($database->query("SELECT `password` FROM `lychee_albums` LIMIT 1;")) $database->query("ALTER TABLE `lychee_albums` CHANGE `password` `password` VARCHAR( 100 ) NULL DEFAULT ''"); // v2.0
|
||||
# A higher $cost is more secure but consumes more processing power
|
||||
$cost = 10;
|
||||
|
||||
// Photos
|
||||
if($database->query("SELECT `description` FROM `lychee_photos` LIMIT 1;")) $database->query("ALTER TABLE `lychee_photos` CHANGE `description` `description` VARCHAR( 1000 ) NULL DEFAULT ''"); // v2.0
|
||||
if(!$database->query("SELECT `tags` FROM `lychee_photos` LIMIT 1;")) $database->query("ALTER TABLE `lychee_photos` ADD `tags` VARCHAR( 1000 ) NULL DEFAULT ''"); // v2.1
|
||||
$database->query("UPDATE `lychee_photos` SET url = replace(url, 'uploads/big/', ''), thumbUrl = replace(thumbUrl, 'uploads/thumb/', '')");
|
||||
|
||||
// Settings
|
||||
$database->query("ALTER TABLE `lychee_settings` CHANGE `value` `value` VARCHAR( 200 ) NULL DEFAULT ''"); // v2.1.1
|
||||
$result = $database->query("SELECT `key` FROM `lychee_settings` WHERE `key` = 'dropboxKey' LIMIT 1;");
|
||||
if ($result->num_rows===0) $database->query("INSERT INTO `lychee_settings` (`key`, `value`) VALUES ('dropboxKey', '')"); // v2.1
|
||||
|
||||
// Config
|
||||
if ($version!==''&&$configVersion!==$version) {
|
||||
$data = file_get_contents('../data/config.php');
|
||||
$data = preg_replace('/\$configVersion = \'[\w. ]*\';/', "\$configVersion = '$version';", $data);
|
||||
if (file_put_contents('../data/config.php', $data)===false) return 'Error: Could not save updated config!';
|
||||
# Create a random salt
|
||||
if (extension_loaded('openssl')) {
|
||||
$salt = strtr(substr(base64_encode(openssl_random_pseudo_bytes(17)),0,22), '+', '.');
|
||||
} elseif (extension_loaded('mcrypt')) {
|
||||
$salt = strtr(substr(base64_encode(mcrypt_create_iv(17, MCRYPT_DEV_URANDOM)),0,22), '+', '.');
|
||||
} else {
|
||||
$salt = "";
|
||||
for ($i = 0; $i < 22; $i++) {
|
||||
$salt .= substr("./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", mt_rand(0, 63), 1);
|
||||
}
|
||||
}
|
||||
|
||||
# Prefix information about the hash so PHP knows how to verify it later.
|
||||
# "$2a$" Means we're using the Blowfish algorithm. The following two digits are the cost parameter.
|
||||
$salt = sprintf("$2a$%02d$", $cost) . $salt;
|
||||
|
||||
# Hash the password with the salt
|
||||
return crypt($password, $salt);
|
||||
|
||||
}
|
||||
|
||||
function hasPermissions($path, $permissions = '0777') {
|
||||
|
||||
if (substr(sprintf('%o', @fileperms($path)), -4)!=$permissions) return false;
|
||||
else return true;
|
||||
|
||||
}
|
||||
|
||||
function fastimagecopyresampled(&$dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h, $quality = 4) {
|
||||
|
||||
###
|
||||
# Plug-and-Play fastimagecopyresampled function replaces much slower imagecopyresampled.
|
||||
# Just include this function and change all "imagecopyresampled" references to "fastimagecopyresampled".
|
||||
# Typically from 30 to 60 times faster when reducing high resolution images down to thumbnail size using the default quality setting.
|
||||
# Author: Tim Eckel - Date: 09/07/07 - Version: 1.1 - Project: FreeRingers.net - Freely distributable - These comments must remain.
|
||||
#
|
||||
# Optional "quality" parameter (defaults is 3). Fractional values are allowed, for example 1.5. Must be greater than zero.
|
||||
# Between 0 and 1 = Fast, but mosaic results, closer to 0 increases the mosaic effect.
|
||||
# 1 = Up to 350 times faster. Poor results, looks very similar to imagecopyresized.
|
||||
# 2 = Up to 95 times faster. Images appear a little sharp, some prefer this over a quality of 3.
|
||||
# 3 = Up to 60 times faster. Will give high quality smooth results very close to imagecopyresampled, just faster.
|
||||
# 4 = Up to 25 times faster. Almost identical to imagecopyresampled for most images.
|
||||
# 5 = No speedup. Just uses imagecopyresampled, no advantage over imagecopyresampled.
|
||||
###
|
||||
|
||||
if (empty($src_image) || empty($dst_image) || $quality <= 0) { return false; }
|
||||
|
||||
if ($quality < 5 && (($dst_w * $quality) < $src_w || ($dst_h * $quality) < $src_h)) {
|
||||
|
||||
$temp = imagecreatetruecolor($dst_w * $quality + 1, $dst_h * $quality + 1);
|
||||
imagecopyresized($temp, $src_image, 0, 0, $src_x, $src_y, $dst_w * $quality + 1, $dst_h * $quality + 1, $src_w, $src_h);
|
||||
imagecopyresampled($dst_image, $temp, $dst_x, $dst_y, 0, 0, $dst_w, $dst_h, $dst_w * $quality, $dst_h * $quality);
|
||||
imagedestroy($temp);
|
||||
|
||||
} else imagecopyresampled($dst_image, $src_image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
?>
|
@ -1,199 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @name Photo Module
|
||||
* @author Philipp Maurer
|
||||
* @author Tobias Reich
|
||||
* @copyright 2014 by Philipp Maurer, Tobias Reich
|
||||
*/
|
||||
|
||||
if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
|
||||
|
||||
function getPhoto($photoID, $albumID) {
|
||||
|
||||
global $database;
|
||||
|
||||
$query = "SELECT * FROM lychee_photos WHERE id = '$photoID' LIMIT 1;";
|
||||
$result = $database->query($query);
|
||||
$return = $result->fetch_assoc();
|
||||
|
||||
if ($albumID!='false') {
|
||||
|
||||
if ($return['album']!=0) {
|
||||
|
||||
$result = $database->query("SELECT public FROM lychee_albums WHERE id = '" . $return['album'] . "';");
|
||||
$return_album = $result->fetch_assoc();
|
||||
if ($return_album['public']=="1") $return['public'] = "2";
|
||||
|
||||
}
|
||||
|
||||
$return['original_album'] = $return['album'];
|
||||
$return['album'] = $albumID;
|
||||
$return['sysdate'] = date('d M. Y', strtotime($return['sysdate']));
|
||||
if (strlen($return['takedate'])>0) $return['takedate'] = date('d M. Y', strtotime($return['takedate']));
|
||||
|
||||
}
|
||||
|
||||
unset($return['album_public']);
|
||||
|
||||
return $return;
|
||||
|
||||
}
|
||||
|
||||
function setPhotoPublic($photoID, $url) {
|
||||
|
||||
global $database;
|
||||
|
||||
$result = $database->query("SELECT public FROM lychee_photos WHERE id = '$photoID';");
|
||||
$row = $result->fetch_object();
|
||||
$public = ($row->public==0 ? 1 : 0);
|
||||
$result = $database->query("UPDATE lychee_photos SET public = '$public' WHERE id = '$photoID';");
|
||||
|
||||
if (!$result) return false;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
function setPhotoStar($photoIDs) {
|
||||
|
||||
global $database;
|
||||
|
||||
$error = false;
|
||||
$result = $database->query("SELECT id, star FROM lychee_photos WHERE id IN ($photoIDs);");
|
||||
|
||||
while ($row = $result->fetch_object()) {
|
||||
|
||||
$star = ($row->star==0 ? 1 : 0);
|
||||
$star = $database->query("UPDATE lychee_photos SET star = '$star' WHERE id = '$row->id';");
|
||||
if (!$star) $error = true;
|
||||
|
||||
}
|
||||
|
||||
if ($error) return false;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
function setPhotoAlbum($photoIDs, $albumID) {
|
||||
|
||||
global $database;
|
||||
|
||||
$result = $database->query("UPDATE lychee_photos SET album = '$albumID' WHERE id IN ($photoIDs);");
|
||||
|
||||
if (!$result) return false;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
function setPhotoTitle($photoIDs, $title) {
|
||||
|
||||
global $database;
|
||||
|
||||
if (strlen($title)>50) return false;
|
||||
$result = $database->query("UPDATE lychee_photos SET title = '$title' WHERE id IN ($photoIDs);");
|
||||
|
||||
if (!$result) return false;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
function setPhotoDescription($photoID, $description) {
|
||||
|
||||
global $database;
|
||||
|
||||
$description = htmlentities($description);
|
||||
if (strlen($description)>1000) return false;
|
||||
|
||||
$result = $database->query("UPDATE lychee_photos SET description = '$description' WHERE id = '$photoID';");
|
||||
|
||||
if (!$result) return false;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
function setPhotoTags($photoIDs, $tags) {
|
||||
|
||||
global $database;
|
||||
|
||||
// Parse tags
|
||||
$tags = preg_replace('/(\ ,\ )|(\ ,)|(,\ )|(,{1,}\ {0,})|(,$|^,)/', ',', $tags);
|
||||
$tags = preg_replace('/,$|^,/', ',', $tags);
|
||||
|
||||
if (strlen($tags)>1000) return false;
|
||||
|
||||
$result = $database->query("UPDATE lychee_photos SET tags = '$tags' WHERE id IN ($photoIDs);");
|
||||
|
||||
if (!$result) return false;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
function deletePhoto($photoIDs) {
|
||||
|
||||
global $database;
|
||||
|
||||
$result = $database->query("SELECT id, url, thumbUrl FROM lychee_photos WHERE id IN ($photoIDs);");
|
||||
|
||||
while ($row = $result->fetch_object()) {
|
||||
|
||||
// Get retina thumb url
|
||||
$thumbUrl2x = explode(".", $row->thumbUrl);
|
||||
$thumbUrl2x = $thumbUrl2x[0] . '@2x.' . $thumbUrl2x[1];
|
||||
|
||||
// Delete files
|
||||
if (!unlink('../uploads/big/' . $row->url)) return false;
|
||||
if (!unlink('../uploads/thumb/' . $row->thumbUrl)) return false;
|
||||
if (!unlink('../uploads/thumb/' . $thumbUrl2x)) return false;
|
||||
|
||||
// Delete db entry
|
||||
$delete = $database->query("DELETE FROM lychee_photos WHERE id = $row->id;");
|
||||
if (!$delete) return false;
|
||||
|
||||
}
|
||||
|
||||
if (!$result) return false;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
function isPhotoPublic($photoID, $password) {
|
||||
|
||||
global $database;
|
||||
|
||||
$query = "SELECT public, album FROM lychee_photos WHERE id = '$photoID';";
|
||||
|
||||
$result = $database->query($query);
|
||||
$row = $result->fetch_object();
|
||||
|
||||
if ($row->public==1) return true;
|
||||
else {
|
||||
$cAP = checkAlbumPassword($row->album, $password);
|
||||
$iAP = isAlbumPublic($row->album);
|
||||
if ($iAP&&$cAP) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function getPhotoArchive($photoID) {
|
||||
|
||||
global $database;
|
||||
|
||||
$result = $database->query("SELECT title, url FROM lychee_photos WHERE id = '$photoID';");
|
||||
$row = $result->fetch_object();
|
||||
|
||||
$extension = array_reverse(explode('.', $row->url));
|
||||
|
||||
if ($row->title=='') $row->title = 'Untitled';
|
||||
|
||||
header("Content-Type: application/octet-stream");
|
||||
header("Content-Disposition: attachment; filename=\"$row->title.$extension[0]\"");
|
||||
header("Content-Length: " . filesize("../uploads/big/$row->url"));
|
||||
|
||||
readfile("../uploads/big/$row->url");
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
?>
|
@ -1,69 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @name Session Module
|
||||
* @author Philipp Maurer
|
||||
* @author Tobias Reich
|
||||
* @copyright 2014 by Philipp Maurer, Tobias Reich
|
||||
*/
|
||||
|
||||
if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
|
||||
|
||||
function init($mode, $version) {
|
||||
|
||||
global $settings, $configVersion;
|
||||
|
||||
// Update
|
||||
if ($configVersion!==$version)
|
||||
if (!update($version)) exit('Error: Updating the database failed!');
|
||||
|
||||
$return['config'] = $settings;
|
||||
unset($return['config']['password']);
|
||||
|
||||
// No login
|
||||
if ($settings['username']===''&&$settings['password']==='') $return['config']['login'] = false;
|
||||
else $return['config']['login'] = true;
|
||||
|
||||
if ($mode==='admin') {
|
||||
$return['loggedIn'] = true;
|
||||
} else {
|
||||
unset($return['config']['username']);
|
||||
unset($return['config']['thumbQuality']);
|
||||
unset($return['config']['sorting']);
|
||||
unset($return['config']['dropboxKey']);
|
||||
unset($return['config']['login']);
|
||||
$return['loggedIn'] = false;
|
||||
}
|
||||
|
||||
return $return;
|
||||
|
||||
}
|
||||
|
||||
function login($username, $password) {
|
||||
|
||||
global $database, $settings;
|
||||
|
||||
// Check login
|
||||
if ($username===$settings['username']&&$password===$settings['password']) {
|
||||
$_SESSION['login'] = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// No login
|
||||
if ($settings['username']===''&&$settings['password']==='') {
|
||||
$_SESSION['login'] = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
function logout() {
|
||||
|
||||
session_destroy();
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
?>
|
@ -1,136 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @name Settings Module
|
||||
* @author Tobias Reich
|
||||
* @copyright 2014 by Tobias Reich
|
||||
*/
|
||||
|
||||
if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
|
||||
|
||||
function getSettings() {
|
||||
|
||||
global $database;
|
||||
|
||||
$result = $database->query('SELECT * FROM lychee_settings;');
|
||||
|
||||
while($row = $result->fetch_object()) {
|
||||
$return[$row->key] = $row->value;
|
||||
}
|
||||
|
||||
return $return;
|
||||
|
||||
}
|
||||
|
||||
function setLogin($oldPassword = '', $username, $password) {
|
||||
|
||||
global $settings;
|
||||
|
||||
if ($oldPassword==$settings['password']) {
|
||||
|
||||
if (!setUsername($username)) exit('Error: Updating username failed!');
|
||||
if (!setPassword($password)) exit('Error: Updating password failed!');
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
exit('Error: Current password entered incorrectly!');
|
||||
|
||||
}
|
||||
|
||||
function setUsername($username) {
|
||||
|
||||
global $database;
|
||||
|
||||
$username = htmlentities($username);
|
||||
if (strlen($username)>50) return false;
|
||||
|
||||
$result = $database->query("UPDATE lychee_settings SET value = '$username' WHERE `key` = 'username';");
|
||||
|
||||
if (!$result) return false;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
function setPassword($password) {
|
||||
|
||||
global $database;
|
||||
|
||||
if (strlen($password)<1||strlen($password)>50) return false;
|
||||
|
||||
$result = $database->query("UPDATE lychee_settings SET value = '$password' WHERE `key` = 'password';");
|
||||
|
||||
if (!$result) return false;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
function setDropboxKey($key) {
|
||||
|
||||
global $database;
|
||||
|
||||
if (strlen($key)<1||strlen($key)>50) return false;
|
||||
|
||||
$result = $database->query("UPDATE lychee_settings SET value = '$key' WHERE `key` = 'dropboxKey';");
|
||||
|
||||
if (!$result) return false;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
function setSorting($type, $order) {
|
||||
|
||||
global $database;
|
||||
|
||||
$sorting = 'ORDER BY ';
|
||||
|
||||
switch ($type) {
|
||||
|
||||
case 'id': $sorting .= 'id';
|
||||
break;
|
||||
|
||||
case 'title': $sorting .= 'title';
|
||||
break;
|
||||
|
||||
case 'description': $sorting .= 'description';
|
||||
break;
|
||||
|
||||
case 'public': $sorting .= 'public';
|
||||
break;
|
||||
|
||||
case 'type': $sorting .= 'type';
|
||||
break;
|
||||
|
||||
case 'star': $sorting .= 'star';
|
||||
break;
|
||||
|
||||
case 'take': $sorting .= 'UNIX_TIMESTAMP(STR_TO_DATE(CONCAT(takedate,"-",taketime),"%d.%m.%Y-%H:%i:%S"))';
|
||||
break;
|
||||
|
||||
default: exit('Error: Unknown type for sorting!');
|
||||
|
||||
}
|
||||
|
||||
$sorting .= ' ';
|
||||
|
||||
switch ($order) {
|
||||
|
||||
case 'ASC': $sorting .= 'ASC';
|
||||
break;
|
||||
|
||||
case 'DESC': $sorting .= 'DESC';
|
||||
break;
|
||||
|
||||
default: exit('Error: Unknown order for sorting!');
|
||||
|
||||
}
|
||||
|
||||
$result = $database->query("UPDATE lychee_settings SET value = '$sorting' WHERE `key` = 'sorting';");
|
||||
|
||||
if (!$result) return false;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
?>
|
@ -1,407 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @name Upload Module
|
||||
* @author Philipp Maurer
|
||||
* @author Tobias Reich
|
||||
* @copyright 2014 by Philipp Maurer, Tobias Reich
|
||||
*/
|
||||
|
||||
if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
|
||||
|
||||
function upload($files, $albumID) {
|
||||
|
||||
global $database, $settings;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
foreach ($files as $file) {
|
||||
|
||||
if ($file['type']!=='image/jpeg'&&
|
||||
$file['type']!=='image/png'&&
|
||||
$file['type']!=='image/gif')
|
||||
return false;
|
||||
|
||||
$id = str_replace('.', '', microtime(true));
|
||||
while(strlen($id)<14) $id .= 0;
|
||||
|
||||
$tmp_name = $file['tmp_name'];
|
||||
$extension = array_reverse(explode('.', $file['name']));
|
||||
$extension = $extension[0];
|
||||
$photo_name = md5($id) . ".$extension";
|
||||
|
||||
// Import if not uploaded via web
|
||||
if (!is_uploaded_file($tmp_name)) {
|
||||
if (copy($tmp_name, '../uploads/big/' . $photo_name)) {
|
||||
@unlink($tmp_name);
|
||||
$import_name = $tmp_name;
|
||||
}
|
||||
} else {
|
||||
move_uploaded_file($tmp_name, '../uploads/big/' . $photo_name);
|
||||
$import_name = '';
|
||||
}
|
||||
|
||||
// Read infos
|
||||
$info = getInfo($photo_name);
|
||||
|
||||
// Use title of file if IPTC title missing
|
||||
if ($info['title']==='')
|
||||
$info['title'] = mysqli_real_escape_string($database, substr(basename($file['name'], ".$extension"), 0, 30));
|
||||
|
||||
// Set orientation based on EXIF data
|
||||
if ($file['type']==='image/jpeg'&&isset($info['orientation'])&&isset($info['width'])&&isset($info['height'])) {
|
||||
|
||||
if ($info['orientation']==3||$info['orientation']==6||$info['orientation']==8) {
|
||||
|
||||
$newWidth = $info['width'];
|
||||
$newHeight = $info['height'];
|
||||
|
||||
$sourceImg = imagecreatefromjpeg("../uploads/big/$photo_name");
|
||||
|
||||
switch($info['orientation']){
|
||||
|
||||
case 2:
|
||||
// mirror
|
||||
// not yet implemented
|
||||
break;
|
||||
|
||||
case 3:
|
||||
$sourceImg = imagerotate($sourceImg, -180, 0);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
// rotate 180 and mirror
|
||||
// not yet implemented
|
||||
break;
|
||||
|
||||
case 5:
|
||||
// rotate 90 and mirror
|
||||
// not yet implemented
|
||||
break;
|
||||
|
||||
case 6:
|
||||
$sourceImg = imagerotate($sourceImg, -90, 0);
|
||||
$newWidth = $info['height'];
|
||||
$newHeight = $info['width'];
|
||||
break;
|
||||
|
||||
case 7:
|
||||
// rotate -90 and mirror
|
||||
// not yet implemented
|
||||
break;
|
||||
|
||||
case 8:
|
||||
$sourceImg = imagerotate($sourceImg, 90, 0);
|
||||
$newWidth = $info['height'];
|
||||
$newHeight = $info['width'];
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
$newSourceImg = imagecreatetruecolor($newWidth, $newHeight);
|
||||
|
||||
imagecopyresampled($newSourceImg, $sourceImg, 0, 0, 0, 0, $newWidth, $newHeight, $newWidth, $newHeight);
|
||||
imagejpeg($newSourceImg, "../uploads/big/$photo_name", 100);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Create Thumb
|
||||
if (!createThumb($photo_name)) return false;
|
||||
|
||||
// Save to DB
|
||||
$query = "INSERT INTO lychee_photos (id, title, url, description, type, width, height, size, sysdate, systime, iso, aperture, make, model, shutter, focal, takedate, taketime, thumbUrl, album, public, star, import_name)
|
||||
VALUES (
|
||||
'" . $id . "',
|
||||
'" . $info['title'] . "',
|
||||
'" . $photo_name . "',
|
||||
'" . $info['description'] . "',
|
||||
'" . $info['type'] . "',
|
||||
'" . $info['width'] . "',
|
||||
'" . $info['height'] . "',
|
||||
'" . $info['size'] . "',
|
||||
'" . $info['date'] . "',
|
||||
'" . $info['time'] . "',
|
||||
'" . $info['iso'] . "',
|
||||
'" . $info['aperture'] . "',
|
||||
'" . $info['make'] . "',
|
||||
'" . $info['model'] . "',
|
||||
'" . $info['shutter'] . "',
|
||||
'" . $info['focal'] . "',
|
||||
'" . $info['takeDate'] . "',
|
||||
'" . $info['takeTime'] . "',
|
||||
'" . md5($id) . ".jpeg',
|
||||
'" . $albumID . "',
|
||||
'" . $public . "',
|
||||
'" . $star . "',
|
||||
'" . $import_name . "');";
|
||||
$result = $database->query($query);
|
||||
|
||||
if (!$result) return false;
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
function getInfo($filename) {
|
||||
|
||||
global $database;
|
||||
|
||||
$url = '../uploads/big/' . $filename;
|
||||
$iptcArray = array();
|
||||
$info = getimagesize($url, $iptcArray);
|
||||
|
||||
// General information
|
||||
$return['type'] = $info['mime'];
|
||||
$return['width'] = $info[0];
|
||||
$return['height'] = $info[1];
|
||||
$return['date'] = date('d.m.Y', filectime($url));
|
||||
$return['time'] = date('H:i:s', filectime($url));
|
||||
|
||||
// Size
|
||||
$size = filesize($url)/1024;
|
||||
if ($size>=1024) $return['size'] = round($size/1024, 1) . ' MB';
|
||||
else $return['size'] = round($size, 1) . ' KB';
|
||||
|
||||
// IPTC Metadata Fallback
|
||||
$return['title'] = '';
|
||||
$return['description'] = '';
|
||||
|
||||
// IPTC Metadata
|
||||
if(isset($iptcArray['APP13'])) {
|
||||
|
||||
$iptcInfo = iptcparse($iptcArray['APP13']);
|
||||
if (is_array($iptcInfo)) {
|
||||
|
||||
$temp = @$iptcInfo['2#105'][0];
|
||||
if (isset($temp)&&strlen($temp)>0) $return['title'] = $temp;
|
||||
|
||||
$temp = @$iptcInfo['2#120'][0];
|
||||
if (isset($temp)&&strlen($temp)>0) $return['description'] = $temp;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// EXIF Metadata Fallback
|
||||
$return['orientation'] = '';
|
||||
$return['iso'] = '';
|
||||
$return['aperture'] = '';
|
||||
$return['make'] = '';
|
||||
$return['model'] = '';
|
||||
$return['shutter'] = '';
|
||||
$return['focal'] = '';
|
||||
$return['takeDate'] = '';
|
||||
$return['takeTime'] = '';
|
||||
|
||||
// Read EXIF
|
||||
if ($info['mime']=='image/jpeg') $exif = @exif_read_data($url, 'EXIF', 0);
|
||||
else $exif = false;
|
||||
|
||||
// EXIF Metadata
|
||||
if ($exif!==false) {
|
||||
|
||||
$temp = @$exif['Orientation'];
|
||||
if (isset($temp)) $return['orientation'] = $temp;
|
||||
|
||||
$temp = @$exif['ISOSpeedRatings'];
|
||||
if (isset($temp)) $return['iso'] = $temp;
|
||||
|
||||
$temp = @$exif['COMPUTED']['ApertureFNumber'];
|
||||
if (isset($temp)) $return['aperture'] = $temp;
|
||||
|
||||
$temp = @$exif['Make'];
|
||||
if (isset($temp)) $return['make'] = $exif['Make'];
|
||||
|
||||
$temp = @$exif['Model'];
|
||||
if (isset($temp)) $return['model'] = $temp;
|
||||
|
||||
$temp = @$exif['ExposureTime'];
|
||||
if (isset($temp)) $return['shutter'] = $exif['ExposureTime'] . ' Sec.';
|
||||
|
||||
$temp = @$exif['FocalLength'];
|
||||
if (isset($temp)) $return['focal'] = ($temp/1) . ' mm';
|
||||
|
||||
$temp = @$exif['DateTimeOriginal'];
|
||||
if (isset($temp)) {
|
||||
$exifDate = explode(' ', $temp);
|
||||
$date = explode(':', $exifDate[0]);
|
||||
$return['takeDate'] = $date[2].'.'.$date[1].'.'.$date[0];
|
||||
$return['takeTime'] = $exifDate[1];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Security
|
||||
foreach(array_keys($return) as $key) $return[$key] = mysqli_real_escape_string($database, $return[$key]);
|
||||
|
||||
return $return;
|
||||
|
||||
}
|
||||
|
||||
function createThumb($filename, $width = 200, $height = 200) {
|
||||
|
||||
global $settings;
|
||||
|
||||
$url = "../uploads/big/$filename";
|
||||
$info = getimagesize($url);
|
||||
|
||||
$photoName = explode(".", $filename);
|
||||
$newUrl = "../uploads/thumb/$photoName[0].jpeg";
|
||||
$newUrl2x = "../uploads/thumb/$photoName[0]@2x.jpeg";
|
||||
|
||||
// Set position and size
|
||||
$thumb = imagecreatetruecolor($width, $height);
|
||||
$thumb2x = imagecreatetruecolor($width*2, $height*2);
|
||||
if ($info[0]<$info[1]) {
|
||||
$newSize = $info[0];
|
||||
$startWidth = 0;
|
||||
$startHeight = $info[1]/2 - $info[0]/2;
|
||||
} else {
|
||||
$newSize = $info[1];
|
||||
$startWidth = $info[0]/2 - $info[1]/2;
|
||||
$startHeight = 0;
|
||||
}
|
||||
|
||||
// Fallback for older version
|
||||
if ($info['mime']==='image/webp'&&floatval(phpversion())<5.5) return false;
|
||||
|
||||
// Create new image
|
||||
switch($info['mime']) {
|
||||
case 'image/jpeg': $sourceImg = imagecreatefromjpeg($url); break;
|
||||
case 'image/png': $sourceImg = imagecreatefrompng($url); break;
|
||||
case 'image/gif': $sourceImg = imagecreatefromgif($url); break;
|
||||
case 'image/webp': $sourceImg = imagecreatefromwebp($url); break;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
imagecopyresampled($thumb,$sourceImg,0,0,$startWidth,$startHeight,$width,$height,$newSize,$newSize);
|
||||
imagecopyresampled($thumb2x,$sourceImg,0,0,$startWidth,$startHeight,$width*2,$height*2,$newSize,$newSize);
|
||||
|
||||
imagejpeg($thumb,$newUrl,$settings['thumbQuality']);
|
||||
imagejpeg($thumb2x,$newUrl2x,$settings['thumbQuality']);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
function importPhoto($path, $albumID = 0) {
|
||||
|
||||
$info = getimagesize($path);
|
||||
$size = filesize($path);
|
||||
|
||||
$nameFile = array(array());
|
||||
$nameFile[0]['name'] = $path;
|
||||
$nameFile[0]['type'] = $info['mime'];
|
||||
$nameFile[0]['tmp_name'] = $path;
|
||||
$nameFile[0]['error'] = 0;
|
||||
$nameFile[0]['size'] = $size;
|
||||
|
||||
return upload($nameFile, $albumID);
|
||||
|
||||
}
|
||||
|
||||
function importUrl($url, $albumID = 0) {
|
||||
|
||||
if (strpos($url, ',')!==false) {
|
||||
|
||||
// Multiple photos
|
||||
|
||||
$url = explode(',', $url);
|
||||
|
||||
foreach ($url as &$key) {
|
||||
|
||||
$key = str_replace(' ', '%20', $key);
|
||||
|
||||
if (@getimagesize($key)) {
|
||||
|
||||
$pathinfo = pathinfo($key);
|
||||
$filename = $pathinfo['filename'].".".$pathinfo['extension'];
|
||||
$tmp_name = "../uploads/import/$filename";
|
||||
|
||||
copy($key, $tmp_name);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return importServer($albumID);
|
||||
|
||||
} else {
|
||||
|
||||
// One photo
|
||||
|
||||
$url = str_replace(' ', '%20', $url);
|
||||
|
||||
if (@getimagesize($url)) {
|
||||
|
||||
$pathinfo = pathinfo($url);
|
||||
$filename = $pathinfo['filename'].".".$pathinfo['extension'];
|
||||
$tmp_name = "../uploads/import/$filename";
|
||||
|
||||
copy($url, $tmp_name);
|
||||
|
||||
return importPhoto($tmp_name, $albumID);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
function importServer($albumID = 0, $path = '../uploads/import/') {
|
||||
|
||||
global $database;
|
||||
|
||||
$files = glob($path . '*');
|
||||
$contains['photos'] = false;
|
||||
$contains['albums'] = false;
|
||||
|
||||
foreach ($files as $file) {
|
||||
|
||||
if (@getimagesize($file)) {
|
||||
|
||||
// Photo
|
||||
if (!importPhoto($file, $albumID)) return false;
|
||||
$contains['photos'] = true;
|
||||
|
||||
} else if (is_dir($file)) {
|
||||
|
||||
$name = mysqli_real_escape_string($database, basename($file));
|
||||
$newAlbumID = addAlbum('[Import] ' . $name);
|
||||
|
||||
if ($newAlbumID!==false) importServer($newAlbumID, $file . '/');
|
||||
$contains['albums'] = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($contains['photos']===false&&$contains['albums']===false) return "Warning: Folder empty!";
|
||||
if ($contains['photos']===false&&$contains['albums']===true) return "Notice: Import only contains albums!";
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
?>
|
@ -1,70 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @name check.php
|
||||
* @author Tobias Reich
|
||||
* @copyright 2014 by Tobias Reich
|
||||
* @description This file takes a look at your Lychee-configuration and displays all errors it can find.
|
||||
*/
|
||||
|
||||
define('LYCHEE', true);
|
||||
header('content-type: text/plain');
|
||||
|
||||
// Declare
|
||||
$error = '';
|
||||
|
||||
// Include
|
||||
if (!file_exists('../data/config.php')) exit('Error 001: Configuration not found. Please install Lychee first.');
|
||||
require('../data/config.php');
|
||||
require('../php/modules/settings.php');
|
||||
|
||||
// Database
|
||||
$database = new mysqli($dbHost, $dbUser, $dbPassword, $dbName);
|
||||
if (mysqli_connect_errno()!=0) $error .= ('Error 100: ' . mysqli_connect_errno() . ': ' . mysqli_connect_error() . '' . PHP_EOL);
|
||||
|
||||
// Get Settings
|
||||
$settings = getSettings();
|
||||
|
||||
// PHP Version
|
||||
if (floatval(phpversion())<5.2) $error .= ('Error 200: Please upgrade to PHP 5.2 or higher!' . PHP_EOL);
|
||||
|
||||
// Extensions
|
||||
if (!extension_loaded('exif')) $error .= ('Error 300: PHP exif extension not activated' . PHP_EOL);
|
||||
if (!extension_loaded('mbstring')) $error .= ('Error 301: PHP mbstring extension not activated' . PHP_EOL);
|
||||
if (!extension_loaded('gd')) $error .= ('Error 302: PHP gd extension not activated' . PHP_EOL);
|
||||
if (!extension_loaded('mysqli')) $error .= ('Error 303: PHP mysqli extension not activated' . PHP_EOL);
|
||||
if (!extension_loaded('json')) $error .= ('Error 304: PHP json extension not activated' . PHP_EOL);
|
||||
if (!extension_loaded('zip')) $error .= ('Error 305: PHP zip extension not activated' . PHP_EOL);
|
||||
|
||||
// Config
|
||||
if (!isset($dbName)||$dbName=='') $error .= ('Error 400: No property for $dbName in config.php' . PHP_EOL);
|
||||
if (!isset($dbUser)||$dbUser=='') $error .= ('Error 401: No property for $dbUser in config.php' . PHP_EOL);
|
||||
if (!isset($dbPassword)) $error .= ('Error 402: No property for $dbPassword in config.php' . PHP_EOL);
|
||||
if (!isset($dbHost)||$dbHost=='') $error .= ('Error 403: No property for $dbHost in config.php' . PHP_EOL);
|
||||
|
||||
// Database Config
|
||||
if (!$settings['username']||$settings['username']=='') $error .= ('Error 404: Username empty or not set' . PHP_EOL);
|
||||
if (!$settings['password']||$settings['password']=='') $error .= ('Error 405: Password empty or not set' . PHP_EOL);
|
||||
if (!$settings['thumbQuality']||$settings['thumbQuality']=='') $error .= ('Error 406: No or wrong property for thumbQuality' . PHP_EOL);
|
||||
if (!$settings['sorting']||$settings['sorting']=='') $error .= ('Error 407: Wrong property for sorting' . PHP_EOL);
|
||||
if (!$settings['checkForUpdates']||($settings['checkForUpdates']!='0'&&$settings['checkForUpdates']!='1')) $error .= ('Error 408: No or wrong property for checkForUpdates' . PHP_EOL);
|
||||
|
||||
// Permissions
|
||||
if (substr(sprintf('%o', @fileperms('../uploads/big/')), -4)!='0777') $error .= ('Error 500: Wrong permissions for \'uploads/big\' (777 required)' . PHP_EOL);
|
||||
if (substr(sprintf('%o', @fileperms('../uploads/thumb/')), -4)!='0777') $error .= ('Error 501: Wrong permissions for \'uploads/thumb\' (777 required)' . PHP_EOL);
|
||||
if (substr(sprintf('%o', @fileperms('../uploads/import/')), -4)!='0777')$error .= ('Error 502: Wrong permissions for \'uploads/import\' (777 required)' . PHP_EOL);
|
||||
if (substr(sprintf('%o', @fileperms('../uploads/')), -4)!='0777') $error .= ('Error 503: Wrong permissions for \'uploads/\' (777 required)' . PHP_EOL);
|
||||
if (substr(sprintf('%o', @fileperms('../data/')), -4)!='0777') $error .= ('Error 504: Wrong permissions for \'data/\' (777 required)' . PHP_EOL);
|
||||
|
||||
if ($error=='') echo('Everything is fine. Lychee should work without problems!' . PHP_EOL . PHP_EOL); else echo $error;
|
||||
|
||||
// Check dropboxKey
|
||||
if (!$settings['dropboxKey']) echo('Warning: Dropbox import not working. No property for dropboxKey.' . PHP_EOL);
|
||||
|
||||
// Check php.ini Settings
|
||||
if (ini_get('max_execution_time')<200&&ini_set('upload_max_filesize', '20M')===false) echo('Warning: You may experience problems when uploading a large amount of photos. Take a look in the FAQ for details.' . PHP_EOL);
|
||||
|
||||
// Check mysql version
|
||||
if ($database->server_version<50500) echo('Warning: Lychee uses the GBK charset to avoid sql injections on your MySQL version. Please update to MySQL 5.5 or higher to enable UTF-8 support.' . PHP_EOL);
|
||||
|
||||
?>
|
81
plugins/check/index.php
Normal file
81
plugins/check/index.php
Normal file
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
###
|
||||
# @name Check Plugin
|
||||
# @author Tobias Reich
|
||||
# @copyright 2014 by Tobias Reich
|
||||
# @description This file takes a look at your Lychee-configuration and displays all errors it can find.
|
||||
###
|
||||
|
||||
# Location
|
||||
$lychee = __DIR__ . '/../../';
|
||||
|
||||
# Load requirements
|
||||
require($lychee . 'php/define.php');
|
||||
require($lychee . 'php/autoload.php');
|
||||
require($lychee . 'php/modules/misc.php');
|
||||
|
||||
# Set content
|
||||
header('content-type: text/plain');
|
||||
|
||||
# Declare
|
||||
$error = '';
|
||||
|
||||
# Load config
|
||||
if (!file_exists(LYCHEE_CONFIG_FILE)) exit('Error 001: Configuration not found. Please install Lychee first.');
|
||||
require(LYCHEE_CONFIG_FILE);
|
||||
|
||||
# Database
|
||||
$database = new mysqli($dbHost, $dbUser, $dbPassword, $dbName);
|
||||
if (mysqli_connect_errno()!=0) $error .= ('Error 100: ' . mysqli_connect_errno() . ': ' . mysqli_connect_error() . '' . PHP_EOL);
|
||||
|
||||
# Load settings
|
||||
$settings = new Settings($database);
|
||||
$settings = $settings->get();
|
||||
|
||||
# PHP Version
|
||||
if (floatval(phpversion())<5.2) $error .= ('Error 200: Please upgrade to PHP 5.2 or higher!' . PHP_EOL);
|
||||
|
||||
# Extensions
|
||||
if (!extension_loaded('exif')) $error .= ('Error 300: PHP exif extension not activated' . PHP_EOL);
|
||||
if (!extension_loaded('mbstring')) $error .= ('Error 301: PHP mbstring extension not activated' . PHP_EOL);
|
||||
if (!extension_loaded('gd')) $error .= ('Error 302: PHP gd extension not activated' . PHP_EOL);
|
||||
if (!extension_loaded('mysqli')) $error .= ('Error 303: PHP mysqli extension not activated' . PHP_EOL);
|
||||
if (!extension_loaded('json')) $error .= ('Error 304: PHP json extension not activated' . PHP_EOL);
|
||||
if (!extension_loaded('zip')) $error .= ('Error 305: PHP zip extension not activated' . PHP_EOL);
|
||||
|
||||
# Config
|
||||
if (!isset($dbName)||$dbName==='') $error .= ('Error 400: No property for $dbName in config.php' . PHP_EOL);
|
||||
if (!isset($dbUser)||$dbUser==='') $error .= ('Error 401: No property for $dbUser in config.php' . PHP_EOL);
|
||||
if (!isset($dbPassword)) $error .= ('Error 402: No property for $dbPassword in config.php' . PHP_EOL);
|
||||
if (!isset($dbHost)||$dbHost==='') $error .= ('Error 403: No property for $dbHost in config.php' . PHP_EOL);
|
||||
|
||||
# Settings
|
||||
if (!isset($settings['username'])||$settings['username']=='') $error .= ('Error 404: Username empty or not set in database' . PHP_EOL);
|
||||
if (!isset($settings['password'])||$settings['password']=='') $error .= ('Error 405: Password empty or not set in database' . PHP_EOL);
|
||||
if (!isset($settings['thumbQuality'])||$settings['thumbQuality']=='') $error .= ('Error 406: No or wrong property for thumbQuality in database' . PHP_EOL);
|
||||
if (!isset($settings['sorting'])||$settings['sorting']=='') $error .= ('Error 407: Wrong property for sorting in database' . PHP_EOL);
|
||||
if (!isset($settings['plugins'])) $error .= ('Error 408: No property for plugins in database' . PHP_EOL);
|
||||
if (!isset($settings['checkForUpdates'])||($settings['checkForUpdates']!='0'&&$settings['checkForUpdates']!='1')) $error .= ('Error 409: No or wrong property for checkForUpdates in database' . PHP_EOL);
|
||||
|
||||
# Permissions
|
||||
if (hasPermissions(LYCHEE_UPLOADS_BIG)===false) $error .= ('Error 500: Wrong permissions for \'uploads/big\' (777 required)' . PHP_EOL);
|
||||
if (hasPermissions(LYCHEE_UPLOADS_THUMB)===false) $error .= ('Error 501: Wrong permissions for \'uploads/thumb\' (777 required)' . PHP_EOL);
|
||||
if (hasPermissions(LYCHEE_UPLOADS_IMPORT)===false) $error .= ('Error 502: Wrong permissions for \'uploads/import\' (777 required)' . PHP_EOL);
|
||||
if (hasPermissions(LYCHEE_UPLOADS)===false) $error .= ('Error 503: Wrong permissions for \'uploads/\' (777 required)' . PHP_EOL);
|
||||
if (hasPermissions(LYCHEE_DATA)===false) $error .= ('Error 504: Wrong permissions for \'data/\' (777 required)' . PHP_EOL);
|
||||
|
||||
# Output
|
||||
if ($error=='') echo('Everything is fine. Lychee should work without problems!' . PHP_EOL . PHP_EOL);
|
||||
else echo $error;
|
||||
|
||||
# Check dropboxKey
|
||||
if (!$settings['dropboxKey']) echo('Warning: Dropbox import not working. No property for dropboxKey.' . PHP_EOL);
|
||||
|
||||
# Check php.ini Settings
|
||||
if (ini_get('max_execution_time')<200&&ini_set('upload_max_filesize', '20M')===false) echo('Warning: You may experience problems when uploading a large amount of photos. Take a look in the FAQ for details.' . PHP_EOL);
|
||||
|
||||
# Check mysql version
|
||||
if ($database->server_version<50500) echo('Warning: Lychee uses the GBK charset to avoid sql injections on your MySQL version. Please update to MySQL 5.5 or higher to enable UTF-8 support.' . PHP_EOL);
|
||||
|
||||
?>
|
54
plugins/displaylog/index.php
Normal file
54
plugins/displaylog/index.php
Normal file
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
###
|
||||
# @name Display Log Plugin
|
||||
# @author Tobias Reich
|
||||
# @copyright 2014 by Tobias Reich
|
||||
# @description This file queries the database for log messages and displays them if present.
|
||||
###
|
||||
|
||||
# Location
|
||||
$lychee = __DIR__ . '/../../';
|
||||
|
||||
# Load requirements
|
||||
require($lychee . 'php/define.php');
|
||||
require($lychee . 'php/autoload.php');
|
||||
require($lychee . 'php/modules/misc.php');
|
||||
|
||||
# Set content
|
||||
header('content-type: text/plain');
|
||||
|
||||
# Load config
|
||||
if (!file_exists(LYCHEE_CONFIG_FILE)) exit('Error 001: Configuration not found. Please install Lychee first.');
|
||||
require(LYCHEE_CONFIG_FILE);
|
||||
|
||||
# Declare
|
||||
$result = '';
|
||||
|
||||
# Database
|
||||
$database = new mysqli($dbHost, $dbUser, $dbPassword, $dbName);
|
||||
|
||||
if (mysqli_connect_errno()!=0) {
|
||||
echo 'Error 100: ' . mysqli_connect_errno() . ': ' . mysqli_connect_error() . '' . PHP_EOL;
|
||||
exit();
|
||||
}
|
||||
|
||||
# Result
|
||||
$result = $database->query('SELECT FROM_UNIXTIME(time), type, function, line, text FROM lychee_log;');
|
||||
|
||||
# Output
|
||||
if ($result === FALSE) {
|
||||
echo('Everything looks fine, Lychee has not reported any problems!' . PHP_EOL . PHP_EOL);
|
||||
} else {
|
||||
while ( $row = $result->fetch_row() ) {
|
||||
|
||||
# Encode result before printing
|
||||
$row = array_map("htmlentities", $row);
|
||||
|
||||
# Format: time TZ - type - function(line) - text
|
||||
printf ("%s %s - %s - %s (%s) \t- %s\n", $row[0], date_default_timezone_get(), $row[1], $row[2], $row[3], $row[4]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
12
readme.md
12
readme.md
@ -39,11 +39,13 @@ In order to use the Dropbox import from your server, you need a valid drop-ins a
|
||||
|
||||
Lychee supports [Twitter Cards](https://dev.twitter.com/docs/cards) and [Open Graph](http://opengraphprotocol.org) for shared images (not albums). In order to use Twitter Cards you need to request an approval for your domain. Simply share an image with Lychee, copy its link and paste it in [Twitters Card Validator](https://dev.twitter.com/docs/cards/validation/validator).
|
||||
|
||||
## Troubleshooting
|
||||
### Plugins and Extensions
|
||||
|
||||
Take a look at the [FAQ](docs/FAQ.md) if you have problems. Discovered a bug? Please create an issue here on GitHub!
|
||||
The plugin-system of Lychee allows you to execute scripts, when a certain action fires. Plugins are hooks, which are injected directly into Lychee. [Plugin documentation »](docs/)
|
||||
|
||||
## Extensions
|
||||
It's also possible to build extensions upon Lychee. The way to do so isn't documented and can change every time. We recommend to use the plugin-system, when possible.
|
||||
|
||||
Here's a list of all available Plugins and Extensions:
|
||||
|
||||
| Name | Description | |
|
||||
|:-----------|:------------|:------------|
|
||||
@ -51,6 +53,10 @@ Take a look at the [FAQ](docs/FAQ.md) if you have problems. Discovered a bug? Pl
|
||||
| Jekyll | Liquid tag for Jekyll sites that allows embedding Lychee albums | [More »](https://gist.github.com/tobru/9171700) |
|
||||
| lychee-redirect | Redirect from an album-name to a Lychee-album | [More »](https://github.com/electerious/lychee-redirect) |
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
Take a look at the [FAQ](docs/FAQ.md) if you have problems. Discovered a bug? Please create an issue here on GitHub!
|
||||
|
||||
## Developer
|
||||
| Version | Name |
|
||||
|:-----------|:------------|
|
||||
|
0
etc/assets/thumbs.sketch/fonts → uploads/medium/index.html
Normal file → Executable file
0
etc/assets/thumbs.sketch/fonts → uploads/medium/index.html
Normal file → Executable file
32
view.php
32
view.php
@ -3,33 +3,35 @@
|
||||
<head>
|
||||
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
|
||||
<title></title>
|
||||
<title>Lychee</title>
|
||||
|
||||
<meta name="author" content="Tobias Reich, Philipp Maurer">
|
||||
<meta name="author" content="Tobias Reich">
|
||||
<meta name="keywords" content="">
|
||||
<meta name="description" content="">
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="assets/build/main.css">
|
||||
<!-- CSS -->
|
||||
<link type="text/css" rel="stylesheet" href="assets/min/main.css">
|
||||
|
||||
<link rel="shortcut icon" href="favicon.ico">
|
||||
<link rel="apple-touch-icon" href="assets/img/apple-touch-icon-iphone.png" sizes="120x120">
|
||||
<link rel="apple-touch-icon" href="assets/img/apple-touch-icon-ipad.png" sizes="152x152">
|
||||
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black" >
|
||||
<meta name="viewport" content="user-scalable=no, initial-scale=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1.0, maximum-scale=1.0">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
|
||||
<?php
|
||||
|
||||
if(isset($_GET['p'])) {
|
||||
if (isset($_GET['p'])&&$_GET['p']>0) {
|
||||
|
||||
define("LYCHEE", true);
|
||||
require(__DIR__ . "/php/define.php");
|
||||
require(LYCHEE_CONFIG_FILE);
|
||||
require(LYCHEE . "php/autoload.php");
|
||||
require(LYCHEE . "php/modules/misc.php");
|
||||
|
||||
require("data/config.php");
|
||||
require("php/modules/db.php");
|
||||
require("php/modules/misc.php");
|
||||
$database = Database::connect($dbHost, $dbUser, $dbPassword, $dbName);
|
||||
|
||||
$database = dbConnect();
|
||||
|
||||
echo openGraphHeader($_GET['p']);
|
||||
echo getGraphHeader($database, $_GET['p']);
|
||||
|
||||
}
|
||||
|
||||
@ -56,9 +58,7 @@
|
||||
<div id="infobox"></div>
|
||||
|
||||
<!-- JS -->
|
||||
<script type="text/javascript" src="assets/js/_frameworks.js"></script>
|
||||
<script type="text/javascript" src="assets/js/build.js"></script>
|
||||
<script type="text/javascript" src="assets/js/view/main.js"></script>
|
||||
<script type="text/javascript" src="assets/min/view.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user