picture viewer

This is my own version of a picture archive and view web interface. On the corresponding server the pictures are stored in folders for year, month and day. There is also the possibility to create specific albums with pictures as well as storing pictures in a folder to reprint/copy.

<?php ############# HEAD  ############################
echo "<!DOCTYPE html>\n";
echo "<html>\n<head>\n <meta charset='utf-8'><meta name='viewport' content='width=device-width, initial-scale=1.0'>\n";
############# style sheets ########################
echo "<link rel='stylesheet' type='text/css' href='stylesheet.css'>";
echo "<title>PictureViewer</title>\n</head>\n<body>\n\n";
echo "<header><h1>My Thoughts</h1><h4>sniplets worth to be remebered</h4></header>\n";
############# Configuration ##########################
$PHP_SELF = htmlspecialchars($_SERVER['PHP_SELF']); # use one file only which will be reload with new parameters all the time
$pathes = array("pictures" => "BackupFromMobile",
				"reprint" => "BackupFromMobile/reprint",
				"albums" => "BackupFromMobile/albums");
$thumb_params = array("width" => 300, "height" => 300, "row" => 5, "big" => 500);# thumbnail parameters
$folder_to_hide = array("pictures", "icons", "thumbnails", "bin");# some folders should not be showed normally
$file_extensions = array( "image" => array(".jpg", ".jpeg", ".png", ".gif"),
						  "audio" => array(".mp3", ".ogg", ".wav"),
						  "ebook" => array(".epub", ".pdf", ".rtx"),
						  "video" => array(".avi", ".3gp", ".flv"));# allowed extensions for files
$rotation_select_box="<option selected value='none'>none</option>
		<option value='0'>0&deg;</option>
		<option value='90'>+90&deg;</option>
		<option value='180'>+180&deg;</option>
		<option value='270'>-90&deg;</option>";# select box for image rotation in 90 degree grade
####### clear html variables from malicious code
function clean_html($variable){
	return trim(htmlspecialchars($variable));
}
###### debug output of POSTÃ¥
function debug_output(){
	echo "<pre><br><h1>Hier kommt der schamass!</h1>";
	print_r($_POST);
	echo "</pre>"; return ;
}
############# create thumbnails in subfolder ######
function check_thumbnail($path, $filename){
	global $thumb_params;
	if (!file_exists($path."thumbnails")){#create thumbnail folder
		if (!mkdir($path."thumbnails")) die ("Unable to create folder (".$path."thumbnails)!");
	}
	$thumb = new Imagick(realpath($path."/".$filename));# Imagick needs absolute path for reference
	$orientation = $thumb -> getimageorientation();# check for image orientation
	# check if rotation was selected
	if (!empty($orientation)){
		switch ($orientation){# rotate image to get it upright
			case imagick::ORIENTATION_BOTTOMRIGHT:
				$thumb->rotateimage("#000000", 180);
				break;
			case imagick::ORIENTATION_RIGHTTOP:
				$thumb->rotateimage("#000000", 90);
				break;
			case imagick::ORIENTATION_LEFTBOTTOM:
				$thumb->rotateimage("#000000", -90);
				break;
			case imagick::ORIENTATION_UNDEFINED:
				$thumb->rotateimage("#000000", 90);
				break;
		}
		$thumb->setImageOrientation(imagick::ORIENTATION_TOPLEFT);# set exif data
	}# resize image but keep ratio
	$thumb->setResourceLimit( Imagick::RESOURCETYPE_MEMORY, 2 );
	$thumb->thumbnailImage($thumb_params["width"], $thumb_params["height"], true);
	$thumb->writeImage(realpath($path)."/thumbnails/".$filename);
	return ; }
############# show side navigation #######################
function explore_directories($current_path, $target_path, $expert_mode){
	global $file_extensions, $folder_to_hide;
	echo "<ul class='navigation'>\n";
	foreach (scandir($current_path, 0) as $element){
		if (substr($element, 0, 1) != "." && !in_array($element, $folder_to_hide)){
			if (is_file($current_path."/".$element)){
				echo "<input type='hidden' name='elements[]' value='".$current_path."/".$element."'>";
				foreach ($file_extensions as $key => $value){# extensions are grouped in multidimensional array
					if (in_array(strtolower(strrchr($element, ".")), $file_extensions[$key])){# only some file extensions will be shown
						echo "<li class='actual_entry'><label><img src='icons/file.png'>";
						echo "<input class='hidden' type='submit' name='folder[".$key."]' value='".$current_path."/".$element."'>".$element."</label></li>\n";
					}
				}
			}
			else { #subfolder
				echo "<li class='navigation'><label><img src='icons/dir.png'>";
				echo "<input class='hidden' type='submit' name='folder[folder]' value='".$current_path."/".$element."/test'>".$element."</label></li>\n";
			}
			if (strncmp($current_path."/".$element, $target_path, strlen($current_path."/".$element)) == 0){
				explore_directories($current_path."/".$element, $target_path, $expert_mode);
			}
		} elseif ($element == "reprint" && $expert_mode == "normal"){# show reprint folder contents if in expert mode
			echo "<li class='navigation'><label><img src='icons/dir.png'>";
			echo "<input class='hidden' type='submit' name='folder[folder]' value='".$current_path."/".$element."/test'>".$element."</label></li>\n";
		}
	}
	echo "</ul>\n";
	return ; }
############ show thumbnails #############################
function show_thumbnails($path, $number_of_rows, $expert_mode){
	global $file_extensions,$rotation_select_box, $pathes;
	$i=0;
	foreach (scandir($path) as $file){# iterate over complete directory contents
		if (substr($file,0,1) != "." && in_array(strtolower(strrchr($file, ".")), $file_extensions["image"])){# only allowed extension will be shown
			$file = htmlspecialchars($file); $i++;# clean filename
			if (!file_exists($path."/thumbnails/".$file)){
				check_thumbnail($path."/", $file);
			}
			echo "<div class='gallery'><label><input class='hidden' type='submit' name='folder[image]' value='".$path."/".$file."'>";
			echo "<img src='".$path."/thumbnails/".$file."' alt='".$file."'></label>\n";
			if ($expert_mode == "normal"){# show checkbox for reprint
				if (strncmp($path, $pathes['reprint'], strlen($pathes['reprint'])) == 0 ) {
					echo "<p class='delete'><input type='checkbox' name='delete".$i."' value='".$path."/".$file."'> delete from reprint list </p>\n";
				}
				else {
					echo "<p class='reprint'><input type='checkbox' name='reprint".$i."' value='".$path."/".$file."'> reprint <span> rotate <select name='rotate".$i."'>";
					echo $rotation_select_box."</select></span><input type='hidden' name='rotation".$i."' value='".$path."/".$file."'></p>\n";# we need the filename beside the rotation value
					if (strncmp($path, $pathes['albums'], strlen($pathes['albums'])) == 0)
						echo "<p class='delete'><input type='checkbox' name='delete".$i."' value='".$path."/".$file."'> delete from album </p>\n";
					else
						echo "<p class='album'><input type='checkbox' name='album".$i."' value='".$path."/".$file."'> add to album choosen above</p>\n";
				}
			}
			echo "</div>\n";
		}
	}
	return ;}
############# rotate pictures from list in given direction ##############
function rotatepictures($rotation, $files){
	global $thumb_params; $i=0;
	$path = dirname($files[0]);
	foreach ($files as $value) {
		$thumb = new Imagick(realpath($value));# Imagick needs absolute path for reference
		switch ($rotation[$i]){# rotate image to get it upright
			case "0";
				$thumb->rotateimage("#000000", 0);
				break;
			case "90";
				$thumb->rotateimage("#000000", 90);
				break;
			case "180":
				$thumb->rotateimage("#000000", 180);
				break;
			case "270":
				$thumb->rotateimage("#000000", -90);
				break;
		}
		$thumb->setImageOrientation(imagick::ORIENTATION_TOPLEFT);# set exif data
		$thumb->setResourceLimit( Imagick::RESOURCETYPE_MEMORY, 2 );# resize image but keep ratio
		$thumb->thumbnailImage($thumb_params["width"], $thumb_params["height"], true);
		$thumb->writeImage(realpath($path)."/thumbnails/".basename($value));
		$i++; # take a counter with us to get desired orientation
	}
	return "done";}
############# copy pics for reprint ###################
function copypictures($files, $folder){
	if (!file_exists($folder)){
		if (!mkdir($folder)) die("Could not create folder:".$folder);
	}
	foreach ($files as $value) {
		if (!copy($value, $folder."/".basename($value) ))
				die("Could not copy file".$value." to ".$folder."/".basename($value));
		}
	return "done";}
############# delete pictures from album ##############
function delpictures($files){
	foreach ($files as $value) {
		if (!unlink($value))
			die("Could not delete file".$value);
	}
	return "done";}
######################################################################
############################## MAIN ##################################
######################################################################
echo "<body><form method='POST' action='$PHP_SELF'>\n";# page header with headline and table headers
$filelist=array(); $albumlist=array();$dellist=array();$rotatelist=array();$rotationnamelist=array();# list of files for reprint
foreach (array_diff_key($_POST, array("change" => "", "action" => "", "folder" => "", "album" => "")) as $key => $value){
	if (substr($key, 0, 7) == "reprint")# files for reprint are numbered as reprint1..9
		array_push($filelist, $value);# generate array list of files to reprint
	elseif (substr($key, 0, 5) == "album")# files for album are numbered as album1..9
		array_push($albumlist, $value);# generate array list of files for actual album
	elseif (substr($key, 0, 6) == "delete")# files to delete from album
		array_push($dellist, $value);
	elseif (substr($key, 0, 6) == "rotate" && $_POST[$key] != "none"){# files to rotate
		array_push($rotatelist, $value);# store value for rotation
		$index_for_rotation="rotation".substr($key, 6);
		array_push($rotationnamelist, $_POST[$index_for_rotation]);# get image name to rotate
	}
}
# get default values for action, target folder and expert view mode
# $key = last action choosen, e.g. play video, show pictures
# $target_folder = the last folder that was opened
# $expert_mode = status of expert view
if (isset($_POST['actual_action']) && $_POST['actual_action'] != "")
	$key = clean_html($_POST['actual_action']);
else 
	$key = "folder";# default action is showing pictures in folder
if (isset($_POST['folder']) && $_POST['folder'] != ""){
	foreach ($_POST[folder] as $key => $value)# generate target folder variable from POST
		$target_path = clean_html(dirname($value));# if a new folder icon was clicked update target folder
	$key = clean_html(array_keys($_POST['folder'])[0]);$value = clean_html($_POST['folder'][$key]);
}elseif (isset($_POST['actual_folder']) && $_POST['actual_folder'] != ""){
	$target_path = clean_html($_POST['actual_folder']);$value = clean_html($_POST['actual_contents']);
} else 
	$target_path = $pathes['pictures'];
# check the actual status of expert view and toggle if requested by user button press
if (isset($_POST['change']) && $_POST['change'] == "expert")# button is pressed, so we need to toggle
	$expert_mode = "normal";# change value as user triggered the button to change
elseif (isset($_POST['change']) && $_POST['change'] == "normal")
	$expert_mode = "expert";# keep the old stage if set
elseif (isset($_POST['expert_mode']) && $_POST['expert_mode'] == "normal")
	$expert_mode = "normal";
else 
	$expert_mode = "expert";
echo "<input type='hidden' name='expert_mode' value='".$expert_mode."'><input type='hidden' name='actual_folder' value='".$target_path."'>";
echo "<input type='hidden' name='actual_action' value='".$key."'><input type='hidden' name='actual_contents' value='".$value."'>";
############## show navigation on top ###########################################
echo "<div class='navi'><input type='submit' name='change' value='".$expert_mode."'>";
# manage access to albums in special folder
if ($expert_mode == "normal"){# select album from list if in expert mode
	echo "<select name='album'>\n<option value='new'>create new entry</option>\n";
	foreach ( glob($pathes['albums']."/*", GLOB_ONLYDIR) as $directory){
		echo "<option ";
		if (isset($_POST['album']) && $_POST['album'] == $directory)
			echo " selected ";
			echo "value='".$directory."'>".basename($directory)."</option>\n";
	}
	echo "</select>\n<input type='submit' name='action' value='action'>\n";
}
if (isset($_POST['action'])){# action button pressed
	echo "<span class='response'>";
	if (isset($_POST['new_album']) && !empty($_POST['new_album'])){
		if (!file_exists($pathes['albums']."/".$_POST['new_album']))
			if (!mkdir($pathes['albums']."/".$_POST['new_album'])) die("Could not create folder:".$_POST['new_album']);
	}
	else {
		if (isset($_POST['album']) && $_POST['album'] == "new"){
			echo "Create new album: <input type='text' size='20' name='new_album'>\n";
		}
		elseif (!empty($albumlist))# copy pictures to album
			echo copypictures($albumlist, $_POST['album']);
		if (!empty($filelist)) # copy pictures for reprint
			echo copypictures($filelist, $pathes['reprint']);
		if (!empty($dellist)) # delete entries from album
			echo delpictures($dellist);
		if (!empty($rotatelist))# rotate pictures in given direction
			echo rotatepictures($rotatelist, $rotationnamelist);
}
	echo "</span>\n";
}
explore_directories($pathes['pictures'], $target_path, $expert_mode);# show the navigation menue
echo "</div>\n";
############### page content to the right ##################################
echo "<section class='contents'>";
switch ($key){
	case "audio":
		echo "<".$key." controls height='240' width='320'>\n<source src='".$value."' type='".$key."/".strtolower(substr(strrchr($value, "."),1))."'>\n";
		echo "No support for file: ".$value." in your Browser!</".$key.">\n";
		break;
	case "video":
		echo "<".$key." controls height='240' width='320'>\n<source src='".$value."' type='".$key."/".strtolower(substr(strrchr($value, "."),1))."'>\n";
		echo "No support for file: ".$value." in your Browser!</".$key.">\n";
		break;
	case "ebook":
		echo "<br>Read ebook: ".$value."<br>";
		break;
	case "image":
		echo "<div class='gallery'>\n";
		if (isset($_POST['elements']) && $_POST['elements'] != "") {
			$number_of_pictures = count($_POST['elements'])-1;# index is running from 0 up
			for ($i=0; $i<=$number_of_pictures; $i++){# iterate over complete image list
				if ($_POST['elements'][$i] == $value){ # find the number of the current image in list
					if ($i == 0) $last = $_POST['elements'][$number_of_pictures];# we are at position 0 already
					else $last = $_POST['elements'][$i-1];
					if ($i == $number_of_pictures) $next = $_POST['elements'][0];# we are at the end already
					else $next = $_POST['elements'][$i+1];
					echo "<div class='arrow-left'><button type='submit' name='folder[image]' value='".$last."'>";
					echo "<img src='icons/transparent.png' style='border:none;'></button></div>";
					echo "<a href='".$value."'> <img src='".$value."' width='".$thumb_params["big"]."' alt='".$value."'></a>";
					echo "<div class='arrow-right'><button type='submit' name='folder[image]' value='".$next."'>";
					echo "<img src='icons/transparent.png' style='border:none;'></button></div>";
					break;
				}
			}
		}
		if ($expert_mode == "normal"){# show checkbox for reprint
			if (explode("/", $value)[0] == $pathes['reprint']) {
				echo "<p class='delete'><input type='checkbox' name='delete".$i."' value='".$value."'> delete from reprint list </p>\n";
			}
			else {
				echo "<p class='reprint'><input type='checkbox' name='reprint".$i."' value='".$value."'> reprint <span> rotate <select name='rotate".$i."'>";
				echo $rotation_select_box."</select></span><input type='hidden' name='rotation".$i."' value='".$value."'></p>\n";# we need the filename beside the rotation value
				if (explode("/", $value)[0] == $pathes['albums'])
					echo "<p class='delete'><input type='checkbox' name='delete".$i."' value='".$value."'> delete from album </p>\n";
				else
					echo "<p class='album'><input type='checkbox' name='album".$i."' value='".$value."'> add to album choosen above</p>\n";
			}
		}
		echo "</div>";
		break;
	case "folder":
		show_thumbnails($target_path, $thumb_params['row'], $expert_mode);# show thumbs
		break;
	default:
		echo "<br>File type not supported!<br>";
		break;
}
echo "</section>\n";
############# cleanup and end ########################################		
debug_output();
echo "</form>\n<footer id='footer'>My personal page hosted on my own server &copy; olkn</footer></body></HTML>\n";
########### END ###################################?>
@CHARSET "ISO-8859-1";
body {
    background-color: #2C2C29;
   	font-family:"Times New Roman", Times, serif;
    font-size: 13px;
    color: white;
}
.arrow-right {
    position: absolute;
	width: 20%;
    height: 100%;
    right: -50px;
    top: 0;
}
.arrow-left {
    position: absolute;
	width: 20%;
    height: 100%;
    left: -50px;
    top: 0;
}
.arrow-left:hover {
	background: transparent url(icons/arrow-left.png) no-repeat left center;
}
.arrow-right:hover {
	background: transparent url(icons/arrow-right.png) no-repeat right center;
}
.hidden {
	display: none;
}
.response {
	padding: 0 0 0 50px;
}
.navigation {/* navigation divs are nested on the left */
	padding: 0px 0px 0px 12px;
	text-shadow: 4px 3px 0 #444444;
}
ul {
    list-style-type: none;
    padding: 0px 20px 0px 0px;
}
li {
	padding: 0px 0px 0px 12px;
}
.navi { /* show text shadow */
	float: left;
	text-shadow: 4px 3px 0 #444444;
}
a { /* some stylings for links */
	text-decoration:none;
}
a:link {
    color: dimgray;
}
a:visited {
    color: darkgray;
}
a:hover {
    color: royalblue;
}
a:active {
    color: silver;
}
p.reprint { /* caption for reprint */
	background: teal;
	margin: 5px;
	text-align: left;
}
p.reprint span { 
	float:right;
	padding: 0 5px 0 0;
}
p.album { /* caption for add to album */
	background: royalblue;
	margin: 5px;
	text-align: left;
}
p.delete { /* caption for pic delete */
	background: darkred;
	margin: 5px;
	text-align: left;
}
.gallery { /* show nice white border for pics */
	position: relative;
	display: inline-block;
	padding: 5px 5px 20px 5px;
	margin: 20px;
	background: white;
}
.gallery img {
	margin:2px;
	border:1px solid #000000;
  	height:auto;
}
.gallery img:hover { /* blurr image when mouse is over */
	opacity:0.7;
	filter:alpha(opacity=70); 
}
img.arrow {
	border: none;
	margin: 100% 0;
}
button {
	height: 100%;
	width: 130px;
	background: transparent;
	border: none;
}
footer { /* footer in new line */
	clear: left;
}

Leave a Reply