Share your image gallery from a server's directory without need for a database thanks to strong encryption. Users can be authenticated via authentication module, e.g. implementing LDAP.
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
367 lines
17 KiB
367 lines
17 KiB
<?php |
|
mb_internal_encoding("utf8"); |
|
$subpath=""; |
|
$file=""; |
|
function error_die($reason, $status='500 Internal Server Error') { |
|
header("Expires: Tue, 01 Jan 2000 00:00:00 GMT"); |
|
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); |
|
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0"); |
|
header("Cache-Control: post-check=0, pre-check=0", false); |
|
header("Pragma: no-cache"); |
|
header('HTTP/1.0 '.$status); |
|
die('<html><body><h1>Error: '.$status.'</h1><p>'.$reason.'</p>'); |
|
} |
|
function alt(&$p1 = NULL, &$p2 = NULL, &$p3 = NULL) { |
|
if (isset($p1)) return $p1; |
|
if (isset($p2)) return $p2; |
|
return $p2; |
|
} |
|
function computeUnsignedChecksum($bytestring) { |
|
$unsigned_chksum = 0; |
|
for($i=0; $i<512; $i++) |
|
$unsigned_chksum += ord($bytestring[$i]); |
|
for($i=0; $i<8; $i++) |
|
$unsigned_chksum -= ord($bytestring[148 + $i]); |
|
$unsigned_chksum += ord(" ") * 8; |
|
return $unsigned_chksum; |
|
} |
|
function tarHeader($Name, $Size, $information=NULL) { |
|
if (strlen($Name)>99) { |
|
$ext = preg_replace('/.*\./', '', $Name); |
|
$Name = substr($Name, 0, 98-strlen($ext)).'.'.$ext; |
|
} |
|
$header = str_pad($Name,100,chr(0)); |
|
$header .= str_pad("777",7,"0",STR_PAD_LEFT) . chr(0); |
|
$header .= str_pad(decoct($information["user_id"]),7,"0",STR_PAD_LEFT) . chr(0); |
|
$header .= str_pad(decoct($information["group_id"]),7,"0",STR_PAD_LEFT) . chr(0); |
|
$header .= str_pad(decoct($Size),11,"0",STR_PAD_LEFT) . chr(0); |
|
$header .= str_pad(decoct(time(0)),11,"0",STR_PAD_LEFT) . chr(0); |
|
$header .= str_repeat(" ",8); |
|
$header .= "0"; |
|
$header .= str_repeat(chr(0),100); |
|
$header .= str_pad("ustar",6,chr(32)); |
|
$header .= chr(32) . chr(0); |
|
$header .= str_pad($information["user_name"],32,chr(0)); |
|
$header .= str_pad($information["group_name"],32,chr(0)); |
|
$header .= str_repeat(chr(0),8); |
|
$header .= str_repeat(chr(0),8); |
|
$header .= str_repeat(chr(0),155); |
|
$header .= str_repeat(chr(0),12); |
|
$checksum = str_pad(decoct(computeUnsignedChecksum($header)),6,"0",STR_PAD_LEFT); |
|
for($i=0; $i<6; $i++) { |
|
$header[(148 + $i)] = substr($checksum,$i,1); |
|
} |
|
$header[154] = chr(0); |
|
$header[155] = chr(32); |
|
return $header; |
|
} |
|
function checkPath($pathToCheck) { |
|
global $path, $subpath; |
|
if (ereg('^[-_a-zA-Z0-9äöüÄÖÜ/]*$', $pathToCheck) && is_dir($path.'/'.$pathToCheck)) { |
|
$subpath=$pathToCheck; |
|
$path .= '/'.$pathToCheck; |
|
} else { |
|
error_die('path not allowed: '.htmlentities($pathToCheck)); |
|
} |
|
} |
|
function checkFile($fileToCheck, $thumb = false) { |
|
global $path, $file, $subpath, $thumbs, $imgfile; |
|
if (!ereg('/', $fileToCheck) && is_file($path.'/'.$fileToCheck)) { |
|
$imgfile = $fileToCheck; |
|
} else { |
|
error_die('file not found', '404 Not Found'); |
|
} |
|
if ($thumb) { // image from thumbnail path |
|
$file = $thumbs.'/'.$subpath.'/'.$fileToCheck; |
|
if (!is_dir($thumbs.'/'.$subpath)) mkdir($thumbs.'/'.$subpath, 0777, true); |
|
if (!is_file($file)) { // create thumbnail |
|
$image = new Imagick(); |
|
$image->readImage($path.'/'.$fileToCheck); |
|
$image->thumbnailImage(200, 200, true); |
|
$image->writeImage($file); |
|
} |
|
} else { |
|
$file = $path.'/'.$fileToCheck; |
|
} |
|
} |
|
function returnFile($file) { |
|
$ext=strtolower(preg_replace('/.*\./', '', $file)); |
|
switch ($ext) { |
|
case 'jpg': case 'jpeg': $type="image/jpeg"; break; |
|
case 'tif': case 'tiff': $type="image/tiff"; break; |
|
case 'gif': $type="image/gif"; break; |
|
case 'png': $type="image/png"; break; |
|
case 'bmp': $type="image/bmp"; break; |
|
} |
|
if (!is_file($file)) { |
|
error_die('file does not exist', '404 Not Found'); |
|
} |
|
if (!isset($_REQUEST['view'])) { |
|
header('Content-type: '.$type); |
|
header('Content-Length: '.filesize($file)); |
|
header('Content-Transfer-Encoding: binary'); |
|
flush(); |
|
readfile($file); |
|
exit; |
|
} |
|
} |
|
function extractDir($path) { |
|
$res['dirs'] = array(); |
|
$res['files'] = array(); |
|
if ($d=opendir($path)) { |
|
while (false!==($f=readdir($d))) |
|
if (!ereg('^\.', $f) && is_dir($path.'/'.$f)) |
|
$res['dirs'][] = $f; |
|
elseif (!ereg('^\.', $f) && is_file($path.'/'.$f)) |
|
switch (strtolower(preg_replace('/.*\./', '', $f))) { |
|
case "jpg": case "jpeg": case "png": |
|
$res['files'][] = $f; |
|
} |
|
} |
|
closedir($d); |
|
asort($res['dirs']); |
|
asort($res['dirs']); |
|
return $res; |
|
} |
|
/*function encrypt2($text) { |
|
global $_REQUEST, $server_password; |
|
return bin2hex(mcrypt_encrypt(MCRYPT_BLOWFISH, $_REQUEST['password']+$server_password, bzcompress(serialize($text)), MCRYPT_MODE_ECB)); |
|
} |
|
function decrypt2($text) { |
|
global $_REQUEST, $server_password; |
|
return unserialize(bzdecompress(mcrypt_decrypt(MCRYPT_BLOWFISH, $_REQUEST['password']+$server_password, hex2bin($text), MCRYPT_MODE_ECB))); |
|
}*/ |
|
function encrypt($text, $password = NULL) { |
|
global $_REQUEST, $server_password; |
|
if (!$password) $password = $_REQUEST['password']; |
|
return base64_encode(mcrypt_encrypt(MCRYPT_BLOWFISH, $password+$server_password, bzcompress(serialize($text)), MCRYPT_MODE_ECB)); |
|
} |
|
function decrypt($text) { |
|
global $_REQUEST, $server_password; |
|
$res = @unserialize(bzdecompress(mcrypt_decrypt(MCRYPT_BLOWFISH, $_REQUEST['password']+$server_password, base64_decode($text), MCRYPT_MODE_ECB))); |
|
if (!$res) $res = @unserialize(bzdecompress(mcrypt_decrypt(MCRYPT_BLOWFISH, $_REQUEST['password']+$server_password, hex2bin($text), MCRYPT_MODE_ECB))); |
|
return $res; |
|
} |
|
function makelink($link, $img, $filename, $style="") { |
|
echo '<a href="'.$link.'"><img src="'.$img.'" alt="'.htmlentities($filename).'" '.$style.'/></a>'; |
|
} |
|
function linkorselect($link, $img, $filename) { |
|
if (isset($_REQUEST['select'])) { |
|
echo '<input type="checkbox" id="'.htmlentities($filename).'" name="elements[]" value="'.htmlentities($filename).'" />'; |
|
echo '<label for="'.htmlentities($filename).'"><img src="'.$img.'" alt="'.htmlentities($filename).'"/></label>'; |
|
} else { |
|
makelink($link, $img, $filename); |
|
} |
|
} |
|
$server_password=file_get_contents('/etc/gallery/password'); |
|
require('/etc/gallery/settings.php'); |
|
if (!$server_password) $server_password=str_shuffle(sha1(rand().time()."ashu87as")); |
|
$username=""; |
|
if (!isset($_REQUEST['secret'])) { |
|
require('/etc/gallery/authentication.php'); |
|
require('/etc/gallery/usersettings.php'); |
|
if ($username=="") error_die('not authorized', '403 Forbidden'); |
|
if (isset($_REQUEST['path'])) checkPath($_REQUEST['path']); |
|
if (isset($_REQUEST['folder']) && !ereg('/', $_REQUEST['folder'])) { |
|
$file = $thumbs.'/folders/'.$subpath.'/'.$_REQUEST['folder'].'.png'; |
|
$type="image/png"; |
|
if (!is_dir($thumbs.'/folders/'.$subpath)) mkdir($thumbs.'/folders/'.$subpath, 0777, true); |
|
if (!is_file($file)) { // create folder image |
|
$txt = wordwrap(preg_replace('/ +/', ' ', preg_replace('/-/', ' - ', preg_replace('/_/', " ", $_REQUEST['folder']))), 16, "\n", true); |
|
$image = new Imagick(); |
|
$image->readImage('folder.png'); // read local template file |
|
$draw = new ImagickDraw(); |
|
$draw->setFillColor('black'); |
|
$draw->setFont('arial'); |
|
if (mb_strlen($txt)<2) { |
|
$draw->setFontSize(60); |
|
$x = 75; |
|
} else { |
|
$draw->setFontSize(15); |
|
$x = 50; |
|
} |
|
$image->annotateImage($draw, 10, $x, 0, $txt); |
|
$image->writeImage($file); |
|
} |
|
} elseif (isset($_REQUEST['file'])) checkFile($_REQUEST['file'], isset($_REQUEST['thumb'])); |
|
if ($file!="") returnFile($file); |
|
} else { |
|
if (isset($_REQUEST['password'])) { |
|
$secret = decrypt($_REQUEST['secret']) or error_die('bad password', '403 Forbidden'); |
|
if (!isset($secret['valid-until'])) error_die('missing validation date'); |
|
if (!isset($max_validity_days)) error_die('maximum validity days not set'); |
|
if (strtotime($secret['valid-until'])>time()+$max_validity_days*86400) error_die('validity limitation not respected'); |
|
if (strtotime($secret['valid-until'])<time()) error_die('sharing request timed out', '410 Gone'); |
|
checkPath($secret['path']); |
|
if (isset($secret['file'])) { |
|
checkFile($secret['file'], true); |
|
if ($file!="") returnFile($file); |
|
} |
|
foreach ($secret['elements'] as $f) checkFile($f); |
|
if (isset($_REQUEST['download'])) { |
|
$secret = decrypt($_REQUEST['secret']) or error_die('bad password', '403 Forbidden'); |
|
if (!isset($secret['valid-until'])) error_die('missing validation date'); |
|
if (strtotime($secret['valid-until'])<time()) error_die('sharing request timed out', '410 Gone'); |
|
if (isset($secret['elements'])) { |
|
$size = 0; |
|
foreach ($secret['elements'] as $f) { |
|
checkFile($f); |
|
$size += 512 + ceil(filesize($file)/512)*512; |
|
$files[] = $file; |
|
} |
|
header('Content-Description: File Transfer'); |
|
header('Content-Type: application/x-tar'); |
|
header('Content-Length: '.$size); |
|
header('Content-Disposition: attachment; filename=shared-images.tar'); |
|
foreach($files as $f) { |
|
print tarHeader('shared-images/'.basename($f), filesize($f)); |
|
readfile($f); |
|
print str_repeat(chr(0), ceil(filesize($f)/512)*512-filesize($f)); |
|
} |
|
exit; |
|
} |
|
} |
|
} |
|
} |
|
?><!DOCTYPE html> |
|
<html> |
|
<header> |
|
<meta charset="utf-8"> |
|
</header> |
|
<body> |
|
<?php |
|
if ($username=="") { |
|
if (isset($_REQUEST['password'])) { |
|
?> |
|
<h1>Shared Files</h1> |
|
<p>Download shared files as a <a href="http://de.wikipedia.org/wiki/Tar">Tape-ARchive</a> (tar) file.</p> |
|
<p><form method="POST"> |
|
<input type="hidden" name="secret" value="<?php echo htmlentities($_REQUEST['secret']) ?>"/> |
|
<input type="hidden" name="password" value="<?php echo htmlentities($_REQUEST['password']) ?>"/> |
|
<input type="hidden" name="download"/> |
|
<input type="submit" value="download"/> |
|
</form></p> |
|
<?php |
|
foreach ($secret['elements'] as $f) { |
|
$secret['path'] = $subpath; |
|
$secret['file'] = $f; |
|
$secret['valid-until'] = date('c', time()+30); |
|
$password=str_shuffle(sha1(rand().time()."Js83aéa")); |
|
echo '<img src="?secret='.urlencode(encrypt($secret, $password)).'&password='.urlencode($password).'" alt="'.htmlentities($f).'"/>'; |
|
} |
|
} else { |
|
?> |
|
<h1>Password Required</h2> |
|
<p>Enter password to start download of images as a Tape-ARchive (tar) file.</p> |
|
<form method="POST"> |
|
<input type="hidden" name="secret" value="<?php echo htmlentities($_REQUEST['secret']) ?>"/> |
|
<input type="password" name="password"/> |
|
<input type="submit" value="show"/> |
|
</form> |
|
<?php |
|
} |
|
} else { |
|
?> |
|
<h1>Gallery: <?php echo htmlentities($username).' @ '.htmlentities($subpath) ?></h1> |
|
<?php |
|
if (isset($_REQUEST['share'])) { |
|
echo '<a href="?path='.urlencode($subpath).'"><img src="?folder=←" alt="←"/></a><br/>'; |
|
$key = $_REQUEST; |
|
unset($key['password']); |
|
unset($key['share']); |
|
unset($key['select']); |
|
$secret=urlencode(encrypt($key)); |
|
$default_mailto = ""; |
|
if (isset($_REQUEST['mailto'])) { |
|
$message = preg_replace('/PASSWORD/', $_REQUEST['password'], $_REQUEST['mailtext']); |
|
$link = (isset($_SERVER['HTTPS'])?'https://':'http://').$_SERVER['HTTP_HOST'].explode('?', $_SERVER['REQUEST_URI'])[0].'?secret='.$secret; |
|
if (ereg('LINK', $message)) $message = preg_replace('/LINK/', $link, $message); |
|
else $message .= "\n\n".$link; |
|
if (mail($_REQUEST['mailto'], $_REQUEST['subject'], $message, 'From: '.$_REQUEST['replyto']."\r\n".'Reply-To: '.$_REQUEST['replyto'])) { |
|
echo '<h2>Mail Successfully Sent</h2>'; |
|
echo '<p>Mail sent to '.$_REQUEST['mailto'].'.</p>'; |
|
echo '<p>You can send more mails, if you want ...</p>'; |
|
} else { |
|
echo '<h2>Send Mail <strong>Failed</strong></h2>'; |
|
echo '<p>Try again ...</p>'; |
|
} |
|
} |
|
echo '<h2>Share Files</h2>'; |
|
echo '<p>Share files: Tell your friend the password on a separate channel and send this: <a href="?secret |
|
='.$secret.'">Link to Share</a></p>'; |
|
?> |
|
<p>or Send Link in E-Mail:</p> |
|
<form method="POST"> |
|
<table style="width: 100%"><tr> |
|
<td><label for="replyto">From:</label></td><td><input name="replyto" type="text" value="<?php echo alt($_REQUEST['replyto'], $email, $fallback_mail_replyto) ?>" style="width: 99%"/></td> |
|
</tr><tr> |
|
<td><label for="mailto">To:</label></td><td><input name="mailto" type="text" value="<?php echo alt($_REQUEST['mailto'], $default_mailto) ?>" style="width: 99%"/></td> |
|
</tr><tr> |
|
<td><label for="subject">Subject:</label></td><td><input name="subject" type="text" value="<?php echo alt($_REQUEST['subject'], $default_mail_subject) ?>" style="width: 99%"/></td> |
|
</tr><tr> |
|
<td colspan="2"><textarea name="mailtext" style="width: 99%; height: 15em"><?php echo alt($_REQUEST['mailtext'], $default_mail_text) ?></textarea></td> |
|
</tr><tr> |
|
<td colspan="2"><input type="submit" value="send email"/></td> |
|
</tr></table> |
|
<?php |
|
foreach ($_POST as $k => $v) |
|
switch ($k) { |
|
case 'replyto': case 'mailto': case 'subject': case 'mailtext': break; |
|
default: |
|
if (is_array($v)) foreach ($v as $e) echo '<input type="hidden" name="'.$k.'[]" value="'.$e.'"/>'; |
|
else echo '<input type="hidden" name="'.$k.'" value="'.$v.'"/>'; |
|
} |
|
?> |
|
</form> |
|
<?php |
|
foreach ($key['elements'] as $f) |
|
makelink('?path='.urlencode($subpath).'&file='.urlencode($f).'&view', '?path='.urlencode($subpath).'&file='.urlencode($f).'&thumb', $f); |
|
} else { |
|
if (isset($_REQUEST['view'])) { // view single image |
|
$objects = extractDir($path); |
|
$pos = array_search($imgfile, $objects['files']); |
|
if ($pos>0) |
|
echo '<a href="?path='.urlencode($subpath).'&file='.urlencode($objects['files'][$pos-1]).'&view"><img src="?folder=←" alt="previous"/></a>'; |
|
echo '<a href="?path='.urlencode($subpath).'"><img src="?folder=↑" alt="↑"/></a>'; |
|
if ($pos<count($objects['files'])-1) |
|
echo '<a href="?path='.urlencode($subpath).'&file='.urlencode($objects['files'][$pos+1]).'&view"><img src="?folder=→" alt="next"/></a>'; |
|
echo '<div class="image"><img style="width: 100%" src="?path='.urlencode($subpath).'&file='.urlencode($imgfile).'" alt="'.urlencode($imgfile).'"/></div>'; |
|
if ($pos!==NULL) { |
|
$lower = max(0, $pos-floor($preview_num/2)); |
|
$higher = min(count($objects['files']), $lower+$preview_num); |
|
for ($i=$lower; $i<$higher; ++$i) |
|
makelink('?path='.urlencode($subpath).'&file='.urlencode($objects['files'][$i]).'&view', '?path='.urlencode($subpath).'&file='.urlencode($objects['files'][$i]).'&thumb', $objects['files'][$i], 'style="width: '.round(100/($higher-$lower), 3).'%"'); |
|
} |
|
} else { // gallery view |
|
if (isset($_REQUEST['select'])) { |
|
echo '<a href="?path='.urlencode($subpath).'">Normal-Modus</a>'; |
|
echo '<form method="POST">'; |
|
echo '<input type="hidden" name="path" value="'.htmlentities($subpath).'">'; |
|
echo '<label for="password">Passwort:</label>'; |
|
echo '<input type="text" size="5" name="password" value="'.substr(str_shuffle(strtolower(sha1(rand().time()."SeAG6"))),0,4).'">'; |
|
echo '<label for="valid-until">Gültig bis:</label>'; |
|
echo '<input type="date" size="10" name="valid-until" max="'.date('Y-m-d', time()+$max_validity_days*86400).'" value="'.date('Y-m-d', time()+14*86400).'"/>'; |
|
echo '<input type="submit" name="share" value="Teilen"/>'; |
|
} else { |
|
echo '<a href="?path='.urlencode($subpath).'&select">Auswahl-Modus</a>'; |
|
} |
|
echo '<div class="dirs">'; |
|
if (ereg('/', $subpath)) { |
|
echo '<a href="?path='.urlencode(preg_replace('/\/[^\/]+$/', '', $subpath)).'"><img src="?folder=↑" alt="↑"/></a>'; |
|
} elseif ($subpath!="") { |
|
echo '<a href="?"><img src="?folder=↑" alt="↑"/></a>'; |
|
} |
|
$objects = extractDir($path); |
|
foreach ($objects['dirs'] as $f) |
|
makelink('?path='.urlencode($subpath.($subpath!=""?'/':'').$f), '?path='.urlencode($subpath).'&folder='.urlencode($f), $f); |
|
echo '</div><div class="images">'; |
|
foreach ($objects['files'] as $f) |
|
linkorselect('?path='.urlencode($subpath).'&file='.urlencode($f).'&view', '?path='.urlencode($subpath).'&file='.urlencode($f).'&thumb', $f); |
|
echo '</div>'; |
|
if (isset($_REQUEST['select'])) echo '</form>'; |
|
} |
|
} |
|
} |
|
?> |
|
</body> |
|
</html>
|
|
|