web scraper

contents

  • logging
  • data base access
  • solr indexing
  • filesystem access
  • web scraping

logging

Data base access

– mysql in python


import mysql.connector
# from mysql.connector import Error

# pip3 install mysql-connector
# https://dev.mysql.com/doc/connector-python/en/connector-python-reference.html

class DB():
    def __init__(self, config):
        self.connection = None
        self.connection = mysql.connector.connect(**config)
        
    def query(self, sql, args):
        cursor = self.connection.cursor()
        cursor.execute(sql, args)
        return cursor

    def insert(self,sql,args):
        cursor = self.query(sql, args)
        id = cursor.lastrowid
        self.connection.commit()
        cursor.close()
        return id

    # https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-executemany.html
    def insertmany(self,sql,args):
        cursor = self.connection.cursor()
        cursor.executemany(sql, args)
        rowcount = cursor.rowcount
        self.connection.commit()
        cursor.close()
        return rowcount

    def update(self,sql,args):
        cursor = self.query(sql, args)
        rowcount = cursor.rowcount
        self.connection.commit()
        cursor.close()
        return rowcount

    def fetch(self, sql, args):
        rows = []
        cursor = self.query(sql, args)
        if cursor.with_rows:
            rows = cursor.fetchall()
        cursor.close()
        return rows

    def fetchone(self, sql, args):
        row = None
        cursor = self.query(sql, args)
        if cursor.with_rows:
            row = cursor.fetchone()
        cursor.close()
        return row

    def __del__(self):
        if self.connection != None:
            self.connection.close()

  # write your function here for CRUD operations

solr indexing

filesystem access

web scraping

Mirror – semi-transparent mirror info panel

I recently started building my own version of a semi-transparent mirror info panel. The server inside is running as a main service station for basically everything.
The server is hosting an external hard disk to serve videos, music and hard disk space via minidlna, nfs, appletalk and samba. Further the server is hosting my mail, imap, icinga, etc services.

A web front end is showing the basic information on an LCD behind the semi-transparent screen and here comes the PHP behind:

<?php ############# HEAD  ############################
$refresh_period = "3600";# refresh once in an hour only
$PHP_SELF = htmlspecialchars($_SERVER['PHP_SELF']); # use one file only which will be reload with new parameters all the time
header("Refresh: $refresh_period; url=$PHP_SELF");
echo "<!DOCTYPE html>\n";
echo "<html>\n<head>\n <meta http-equiv='refresh' content='.".$refresh_period."'><meta charset='utf-8'><meta name='viewport' content='width=device-width, initial-scale=1.0'>\n";
require_once('simpleCalDAV/SimpleCalDAVClient.php');
$client = new SimpleCalDAVClient();
$zeiger = array("Stunde", "Minute", "Sekunde");
############# Configuration ##########################
$numberClocks = array("Shenzen" => 2, "Saarbruecken" => 0);
$calendar_config = array('server' => '<server adress>/remote.php/dav/calendars/olkn/personal/', 
						'login' => '<login>', 
						'password' => '<password>',
						'calendar' => 'personal');
$tokens = array('SUMMA', 'DESCR', 'DTSTA', 'LOCAT', 'DTEND');// tokens to check for in calendar entry
############# style sheets ########################
echo "<link rel='stylesheet' type='text/css' href='stylesheet.css'>\n";
echo "<style>\n";
foreach ($numberClocks as $ort => $zeitzone){
	$rotation["Stunde"] = (date("h") + $zeitzone) * 30 + round(date("i")/2);# define hour rotation including timezone and minute part
	$rotation["Minute"] = date("i") * 6;# define minute rotation and
	$rotation["Sekunde"] = date("s") * 6;# second rotation
	foreach ($zeiger as $zeigername){
		$rotstart = $rotation[$zeigername];$rotstop = $rotation[$zeigername]+360;
		$temp = $zeigername.$ort;# CSS class name is StundeShenzen, etc
		echo ".".$temp." { \n\t-moz-animation-name: drehen".$temp.";\n\t-webkit-animation-name: drehen".$temp." ;\n\t";
		echo "-o-animation-name: drehen".$temp.";\n\t-ms-animation-name: drehen".$temp.";\n\tanimation-name: drehen".$temp.";\n\t";
		echo "-moz-animation-iteration-count: infinite;\n\t-webkit-animation-iteration-count: infinite;\n\t";
		echo "-o-animation-iteration-count: infinite;\n\t-ms-animation-iteration-count: infinite;\n\t";
		echo "animation-iteration-count: infinite;\n\t-moz-animation-direction: normal;\n\t-webkit-animation-direction: normal;\n\t";
		echo "-o-animation-direction: normal;\n\t-ms-animation-direction: normal;\n\tanimation-direction: normal;\n\t";
		if ($zeigername == "Sekunde"){# second hand will go in steps rather than continously
			echo "-moz-animation-timing-function: steps(60);\n\t-webkit-animation-timing-function: steps(60);\n\t";
			echo "-o-animation-timing-function: steps(60);\n\t-ms-animation-timing-function: steps(60);\n\tanimation-timing-function: steps(60);\n\t}\n";
		} else {
			echo "-moz-animation-timing-function: linear;\n\t-webkit-animation-timing-function: linear;\n\t";
			echo "-o-animation-timing-function: linear;\n\t-ms-animation-timing-function: linear;\n\tanimation-timing-function: linear;\n\t}\n";
		}
		echo "@-moz-keyframes drehen".$temp." { \n\tfrom { -moz-transform: rotate(".$rotstart."deg); } \n\tto { -moz-transform: rotate(".$rotstop."deg); } \n}\n";
		echo "@-webkit-keyframes drehen".$temp." { \n\tfrom { -moz-transform: rotate(".$rotstart."deg); } \n\tto { -moz-transform: rotate(".$rotstop."deg); } \n}\n";
		echo "@-o-keyframes drehen".$temp." { \n\tfrom { -moz-transform: rotate(".$rotstart."deg); } \n\tto { -moz-transform: rotate(".$rotstop."deg); } \n}\n";
		echo "@-ms-keyframes drehen".$temp." { \n\tfrom { -moz-transform: rotate(".$rotstart."deg); } \n\tto { -moz-transform: rotate(".$rotstop."deg); } \n}\n";
		echo "@keyframes drehen".$temp." { \n\tfrom { -moz-transform: rotate(".$rotstart."deg); } \n\tto { -moz-transform: rotate(".$rotstop."deg); } \n}\n";
	}
}
echo "</style>\n";
echo "<title>Mirror</title>\n</head>\n<body>\n\n";
############################## MAIN ##################################
date_default_timezone_set('Europe/Berlin');# set time zone
############## show weather on top right #############################
echo "<a href='second.php'><div class='header'>\n";
echo "<div id='cont_29118c24cbd1fe3b37edea315a92451d'><span id='h_29118c24cbd1fe3b37edea315a92451d'>";
echo "</span><script type='text/javascript' async src='https://www.daswetter.com/wid_loader/29118c24cbd1fe3b37edea315a92451d'>";
echo "</script></div>";
echo "</div>\n";# header
############### show calender and clock on bottom ####################
echo "<div class='footer'>\n";
echo "<div class='calendar'>\n";
try {
	$client->connect($calendar_config['server'], $calendar_config['login'], $calendar_config['password']);
	$arrayOfCalendars = $client->findCalendars();# get all available calendars
	$client->setCalendar($arrayOfCalendars[$calendar_config['calendar']]);# choose specific calendar
	$events = $client->getEvents(date('Ymd')."T000000Z", date('Ymd')."T240000Z"); # get list of events for today
	echo "<div class='calendar_header'>".date("l d.F Y")."</div>\n";# show current date
	foreach ($events as $event){
		$results = array();
		$event_data = explode("\n", $event->getData());
		foreach ($event_data as $line){
			list($key, $value) = explode(":", $line);
			if ($key == "BEGIN" && $value == "VEVENT") $trigger = true;// only check VEVENT entries
			elseif ($key == "END") $trigger = false;// other entries will be ignored
			if ($trigger){
				$key = substr($key, 0, 5);// DTSTART and END use complexe format, so the beginning of the word is enough
				if (in_array($key, $tokens)){// we found a relevant token, so store it in array for this event
					$results[$key] = $value;
				}
			}//end of triggering
		}//mext line of ICALENDAR Event
		echo "<div class='calendar_contents'>\n";
		if (strstr($results['DTSTA'], 'T') && strstr($results['DTEND'], 'T')){//we have a specific time (no whole day entry)
			echo "<div class='calendar_time'>".str_split(substr($results['DTSTA'], -6), 2)[0].":".str_split(substr($results['DTSTA'], -6), 2)[1];
			echo " - ".str_split(substr($results['DTEND'], -6), 2)[0].":".str_split(substr($results['DTEND'], -6), 2)[1];
			echo "</div>\n";//calendar_time
		}//event time processing
		echo $results['SUMMA']."\n<div class='calendar_entry'>".$results['DESCR']."</div>\n";//calendar_entry
		if (isset($results['LOCAT'])) echo "<div class='calendar_location'>".$results['LOCAT']."</div>\n";//calendar_location
		echo "</div>\n";//calender_contents
	}// next event
}
catch (Exception $e) {
	echo $e->__toString();
	echo "Error during catching calendar entries from Server<br>";
}
echo "</div>\n";# calender
############### show two clocks for worldtime ########################
echo "<div class='clock'>\n";
foreach ($numberClocks as $ort => $zeitzone){
	echo "<div class='clock_inner'>\n";
	echo "\t<div class='uhr'>\n";
	echo "\t<ul class='markierungen'>\n<li id='mark01'><div></div></li><li id='mark02'><div></div></li>\n";
	echo "\t<li id='mark03'><div></div></li><li id='mark04'><div></div></li>\n<li id='mark05'><div></div></li>";
	echo "\t<li id='mark06'><div></div></li>\n<li id='mark07'><div></div></li><li id='mark08'><div></div></li>\n";
	echo "\t<li id='mark09'><div></div></li><li id='mark10'><div></div></li>\n<li id='mark11'><div></div></li>";
	echo "\t<li id='mark12'><div></div></li>\n</ul>\n";
	foreach ($zeiger as $zeigername){
		echo "\t<div class='".$zeigername.$ort."' id='".$zeigername."'></div>";
	}
	echo "\t</div><div class='clock_location'>".$ort."</div>\n";
	echo "</div>\n";# clock_inner
}
echo "</div>\n";# clock
echo "</div>\n</a>";# footer
############### close ####################################################
echo "</body>\n</HTML>\n";
########### END ###################################?>

There is also a second page, which is showing some statistics about the server:

<?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>Mirror</title>\n</head>\n<body>\n\n";
############# Configuration ##########################
$PHP_SELF = htmlspecialchars($_SERVER['PHP_SELF']); # use one file only which will be reload with new parameters all the time
$display_size = array(1024, 768);
###### debug output of POST
function debug_output(){
        echo "<pre><br><h1>Hier kommt der schamass!</h1>";
        print_r($_POST);
        echo "</pre>"; return ;
}
######################################################################
############################## MAIN ##################################
######################################################################
echo "<body><form method='POST' action='$PHP_SELF'>\n";# page header with headline and table headers
echo "<a href='index.php'><section class='contents'>";
############## show weather on top right #############################
echo "<table width='100%' border=1><tr>";
echo "<td><img src='<cacti-server-adress>/graph_image.php?local_graph_id=12&rra_id=1&graph_width=500&graph_height=120&graph_nolegend=true'></td>";
echo "<td><img src='<cacti-server-adress>/graph_image.php?local_graph_id=24&rra_id=1&graph_width=500&graph_height=120&graph_nolegend=true'></td>";
echo "</tr><tr>";
echo "<td><img src='<cacti-server-adress>/graph_image.php?local_graph_id=20&rra_id=1&graph_width=500&graph_height=120&graph_nolegend=true'></td>";
echo "<td><img src='<cacti-server-adress>/graph_image.php?local_graph_id=38&rra_id=1&graph_width=500&graph_height=120&graph_nolegend=true'></td>";
echo "</tr><tr>";
echo "<td><img src='<cacti-server-adress>/graph_image.php?local_graph_id=40&rra_id=1&graph_width=500&graph_height=120&graph_nolegend=true'></td>";
echo "<td><img src='<cacti-server-adress>/graph_image.php?local_graph_id=9&rra_id=1&graph_width=500&graph_height=120&graph_nolegend=true'></td>";
echo "</tr><tr>";
echo "<td><img src='<cacti-server-adress>/graph_image.php?local_graph_id=23&rra_id=1&graph_width=500&graph_height=120&graph_nolegend=true'></td>";
echo "<td><img src='<cacti-server-adress>/graph_image.php?local_graph_id=9&rra_id=1&graph_width=500&graph_height=120&graph_nolegend=true'></td>";
echo "</tr></table>";
echo "Nagios Entries!";
echo "</section>";
############# cleanup and end ########################################
#debug_output();
echo "</form>\n<footer id='footer'>My personal page hosted on my own server &copy; olkn</footer></a></body></HTML>\n";
########### END ###################################?>

WebFrontEnd for rsnapshot based backup system

As already discussed in: rsnapshot backup solution I am using rsnapshot as my main backup solutions for a variety of servers.
But I am lazy and often forget about the correct settings, commands, etc. For this reason I started building up some web front ends for several common daily tasks. Just to remember what to do and how and of course to have some fun with programming.
And here is another part of this series: The Rsnapshot Web Front End:

The complete webpage is enclosed into one file – this was my first internal order, because I wanted something that may be installed very easily. There is also a file structure as follows:
main folder:

  • default – the base for new config files
  • pid – the process id file
  • logs – the folder with log files
  • rsnapshot – the folder holding the config files
  • backup.php – the web front end

The default file is cloned to get the base for an new config file and as such is the master. All files in folder rsnapshot are shown in a matrix to access the action.

The web page itself is self explanatory and allows to:

  • view the config and logfiles,
  • create and delete a config file/server entry
  •  start a backup process and
  • edit the config file

Any new entry made in the config file is checked against a regular expression already within the backup.php file to avoid misconfigurations. The editing is further devided into normal and expert mode whereas normal mode is only showing the most important options and expert mode is showing all options.

The styling/design of the page is very poor and might be improved later on. Also the security of the page is lacking some attention and might change.

But now to the code:

<?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 "<title>Backup Admin Page</title>\n</head>\n<body>\n\n";
echo "<header><h1>Backup Admin - Main Page</h1>";
echo "<h4>created to configure my own backup system based on rsnapshot</h4></header>\n";
echo "<style>.red { color: red;} .blue {color: blue;} .hide {display: none;} .comment { width: 100%;}</style>";
############# Configuration ##########################
$config['configfile'] = "rsnapshot/";# folder for config files
$config['logfile'] = "log/";# folder for logfiles
$config['command'] = "ls -l";# command to be executed to start backup
##################################### no editing below here ###########################
$PHP_SELF = htmlspecialchars($_SERVER['PHP_SELF']); # use one file only which will be reload with new parameters all the time
$general_menu = array( "Cancel", "NewHost");# general menue options not associated with host/server
$menue_items = array("ShowConfigfile", "StartBackup", "ShowLogfile", "EditConfigfile", "Delete");# menue items for each host/server
$config['columns'] = count($menue_items);# the number of columns in total
$config['values'] = array("snapshot_root", "interval", "backup", "no_create_root", "cmd_cp", "cmd_rm",
		"cmd_rsync", "cmd_ssh", "cmd_logger", "cmd_du", "verbose", "loglevel", "rsync_long_args", "ssh_args", 
		"du_args", "logfile", "lockfile", "config_version");
$config["inputtype"]["interval"] = array("weekly","hourly","daily","monthly");
$config["inputtype"]["verbose"] = array("1","2","3","4","5");
$config["inputtype"]["loglevel"] = array("1","2","3","4","5");
##################################### function definitions ########################################
####### 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 ;
}
###### parse contents of configfile and store everything in two arrays
function parse_file_contents($filename){
	global $inputvalues; # one matrix for all values already filled with defaults
	if ($data = file_get_contents($filename)){
		$contents = explode("\n", $data);$comment = "";
		foreach ($contents as $line) { # parse each line of the input file seperately
			$line = trim($line); $value = ""; # and override default values with config file values
			if (strlen($line) && substr($line, 0, 1) == '#') # a comment line
				$comment .= "\n".$line; 
			elseif (strlen($line)){ # non empty line found
				$key = trim(strtok($line, " \t")); # name of the specific option is first parameter
				while ($inputpart = strtok(" \t")) $value = $value.trim($inputpart)."\t"; # rest of the line is combined as value
				if ($key == "exclude") # special treatement for excluded directories
					$inputvalues["exclude"][] = trim($value);
				else # normal value will override default values in array
					$inputvalues["values"][$key] = trim($value);
				if ($comment != "") {# non enpty comment will be stored
					$inputvalues['comment'][$key] = $comment; 
					$comment = "";
				}
			}
		}
		$return = "File: ".$filename." successfully paresed!";
	}
	else # could not get file contents via function so die
		$return = "Could not open file: ".$filename;
	return $return;
}
####### save config file
function save_conf_file($inputvalues, $filename){
	global $config;
	$output = "";
	foreach ($config['values'] as $key){# iterate over all config file parameters
		if (isset($inputvalues['comment'][$key])) $output .= $inputvalues['comment'][$key]."\n";
		if (isset($inputvalues['values'][$key]))  $output .= $key."\t".$inputvalues['values'][$key]."\n";
	}
	if (isset($inputvalues['comment']['exclude'])) $output .= $inputvalues['comment']['exclude']."\n";
	foreach ($inputvalues['exclude'] as $key => $value)
		if ($inputvalues['exclude'][$key] != "") $output .= "exclude"."\t".$value."\n";
	
	/*
	if ($handle = fopen($filename, "w")){ # open configfile for write
		fwrite($handle, $output);
		fclose($handle);
	}
	
	else 
		$return = "Could not open file: ".$filename;
		*/
	return "<pre>".$output."</pre>";
#	return $return;
}
####### edit values using defaults or values from config file
function edit_conf_file($inputvalues, $config, $mode){
	$class = "show";
	$return = "<table border='1' width='100%'>\n<tr><td colspan='4' align='right'>";
	$return .= "<input type='submit' name='action[Expert]' value='".$mode."'></td></tr>\n";
	foreach ($config['values'] as $key){
		if ($key == "no_create_root" && $mode == "Normal") $class = "hide";# show other entries only in expert mnode
		if (isset($inputvalues['comment'][$key])){# any comments for the forthcoming option?
			$rows = substr_count($inputvalues['comment'][$key], "\n") + 2;
			$return .= "<tr class='".$class."'><td colspan='3'><textarea cols='100%' rows='".$rows;
			$return .= "' name='inputvalues[comment][".$key."]'> ".$inputvalues['comment'][$key];
			$return .= " </textarea></td></tr>\n";
		}# and now the entry
		$return .= "<tr class='".$class."'><td>".$key."</td>";
		if (isset($config['inputtype'][$key])) {# no simple input field but a select box
			$return .= "<td><select name='inputvalues[values][".$key."]' size='1'>";
			foreach ($config['inputtype'][$key] as $value){
				$return .= "<option";
				if(isset($inputvalues['values'][$key]) && strtok($inputvalues['values'][$key], " ") == $value ) $return .= " selected ";
				$return .= ">".$value."</option>\n";
			}
			$return .= "</select></td>";
		} else {# simple input field
			$return .= "<td><input type='input' name='inputvalues[values][".$key."]' value='";
			if (isset($inputvalues['values'][$key])) $return .= $inputvalues['values'][$key]; 
			$return .= "'></td>";
		}
		$return .= "<td></td></tr>\n";
	}################# Exclude directories ##################
	$return .= "<tr class='show'><td colspan='4'>Exclude Directories:</td></tr>\n";
	if (isset($inputvalues['comment']['exclude'])){
		$rows = substr_count($inputvalues['comment']['exclude'], "\n") + 2;
		$return .= "<tr class='show'><td colspan='3'><textarea cols='100%' rows='".$rows;
		$return .= "' name='inputvalues[comment][exclude]'> ".$inputvalues['comment']['exclude'];
		$return .= " </textarea></td></tr>\n";
	}
	if (isset($inputvalues['exclude'])){
		foreach ($inputvalues['exclude'] as $subkey => $value){# show excludes as checkbox list
			if ($value != "") {# only if there is an entry and not en empty line
				$return .= "<tr class='show'><td colspan='2'>".$value."</td><td><input type='checkbox' name='inputvalues[exclude]";
				$return .= "[".$subkey."]' value='".$value."' checked></td></tr>\n";
			}
		}
	} 
	for ($i=0; $i < 5; $i++)# add 5 extra rows for exclude input
		$return .= "<tr class='show'><td>Add exclude folder</td><td colspan='2'><input type='input' value='' name='inputvalues[exclude][]'></td></tr>\n";
	$return .= "<tr class='show'><td align='center' colspan='2'><input type='submit' value='SaveConfigfile' ";
	$return .= "name='action[SaveConfigfile]'></td><td align='center' colspan='2'>";
	$return .= "<input type='submit' name='action[Cancel]' value='Cancel'></td></tr>\n</table>\n";
	return $return;
}
####### function generate menu
function generate_menue($menue_items, $configfile){
	$return = "<tr><thead align='center'>";
	foreach ($menue_items as $key) # table headers
			$return .= "<th>".$key."</th>";
	$return .= "</thead>\n<tbody align='center'>\n";
	foreach (scandir($configfile) as $file){# iterate over complete directory contents
		if (substr($file, 0, 1) != ".") { # dotfiles are ignored
			$file = htmlspecialchars($file);$return .= "<tr>";
			foreach ($menue_items as $key) {
				$return .= "<td><input type='submit' value='  ".$file."  ' name='action[".$key."]'></td>";
			}
			$return .= "</tr>\n";
		}
	}
	return $return;}
######################################################################
############################## MAIN ##################################
######################################################################
echo "<body><form method='POST' action='".$PHP_SELF."'>\n";# page header with headline and table headers
echo "<table border=1 cellspacing='10'>\n";# everything will be bound to one table
echo generate_menue($menue_items, $config['configfile']);
$cols = round($config['columns'] / 2);$cols_remain = $config['columns'] - $cols;
echo "<tr><td colspan='".$cols."'><input type='submit' name='action[Cancel]' value='Cancel'></td>";
echo "<td colspan='".$cols_remain."'><input type='submit' name='action[NewHost]' value='NewHost'></td></tr>";
######################### Main Menue #####################################
if (isset($_POST['expertMode']) && $_POST['expertMode'] == "Expert") $mode = "Expert";
else $mode = "Normal";
if (isset($_POST['action'])) {
	$menue_entry = array_keys($_POST['action'])[0];# action[<menue_entry>] -> <host>/<menue_entry>
	$host = clean_html($_POST['action'][$menue_entry]);
	switch ($menue_entry){
		case "EditConfigfile":###########################################
			if (file_exists($config['configfile'].$host)) {
				$return = "<h3>Edit (".$host.")</h3>";# show headline
				$return .= parse_file_contents($config['configfile'].$host);
				$return .= "<input type='hidden' name='hostname' value='".$host."'>";			
				$return .= "<pre class='blue'>".edit_conf_file($inputvalues, $config, $mode)."</pre>";
			} else {
				$return = "<h3>Error (".$host.")</h3>";# show headline
				$return .= "<pre class='red'>File: ".$config['configfile'].$host." does not exist!</pre>\n";# show error message
			}
			break;
		case "Expert":###################################################
			if (isset($_POST['hostname'])){
				$return = "<h3>Edit (".$_POST['hostname'].")</h3>";# show headline
				if ($host == "Expert") $mode = "Normal";
				else $mode = "Expert";
				$return .= "<input type='hidden' name='hostname' value='".$_POST['hostname']."'>";			
				$return .= "<pre class='blue'>".edit_conf_file($_POST['inputvalues'], $config, $mode)."</pre>";
			} else {
				$return = "<h3>Error (".$host.")</h3>";# show headline
				$return .= "<pre class='red'>Error! No host defined!</pre>\n";# show error message
			}
			break;
		case "SaveConfigfile":############################################
			if (isset($_POST['inputvalues'])){
				$return = "<h3>Save Configfile (".$host.")</h3>";# show headline
				$return .= "<pre class='blue'>".save_conf_file($_POST['inputvalues'], $config['configfile'].$host)."</pre>";# write file contents
			} else {
				$return = "<h3>Error (".$host.")</h3>";# show headline
				$return .= "<pre class='red'>Error! No host defined!</pre>\n";# show error message
			}
			break;
		case "ShowConfigfile":############################################
			if (file_exists($config['configfile'].$host)){# check if file exists in folder
				$return = "<h3>Show Configfile (".$host.")</h3>";# show headline
				$return .= "<pre class='blue'>".file_get_contents($config['configfile'].$host)."</pre>";# get file contents
			} else { 
				$return = "<h3>Error (".$host.")</h3>";# show headline
				$return .= "<pre class='red'>File: ".$config['configfile'].$host." does not exist!</pre>";# show error
			}
			break;
		case "StartBackup":###############################################
			$befehl = $config['command']." ".$config['configfile'].$host." 2>&1";# create backup command
			if (file_exists($config['configfile'].$host)){# check if file exists
				$return = "<h3>Start Backup (".$host.")</h3>";
				$return .= "<pre class='blue'>Execute Command: (".$befehl.")</pre>";
				$return .= exec($befehl, $output, $return_val);# execute backup command
#				$return .= $output." ".$return_val;
			} else {
				$return = "<h3>Error (".$host.")</h3>";# show headline
				$return .= "<pre class='red'>File: ".$config['configfile'].$host." does not exist!</pre>";# show error message
			}
			break;
		case "ShowLogfile":##############################################
			if (file_exists($config['logfile'].$host)){ # check if file exists
				$return = "<h3>Show Logfile (".$host.")</h3>";# show headline
				$return .= "<pre class='blue'>".file_get_contents($config['logfile'].$host)."</pre>";# get file contents
			} else { 
				$return = "<h3>Error (".$host.")</h3>";# show headline
				$return .= "<pre class='red'>File: ".$config['logfile'].$host." does not exist!</pre>";# show error message
			}
			break;
		case "Delete":###################################################
			$return = "<h3>Delete (".$host.")</h3>";# show headline
			$return .= "<div class='red'>You really want to delete:"; 
			$return .= "<input type='submit' name='action[ReallyDelete]' value='".$host."'></div>";
			break;
		case "ReallyDelete":#############################################
			$return = "<h3>Delete (".$host.")</h3>";# show headline
			if (file_exists($config['configfile'].$host)){
				if (unlink($config['configfile'].$host)){
						unlink($config['configfile'].$host);
						$return .= "<pre class='blue'>Host: ".$host." successfully deleted!</pre>";
				}
				else 
					$return .= "<pre class='red'>An error occured while deleting Host: ".$host."</pre>";
			}
			else 
				$return .= "<pre class='red'>File: ".$config['configfile'].$host." does not exist!</pre>\n";# show error message
			break;
		case "NewHost":##################################################
			$return = "<h3>Create (New Host)</h3>";# show headline
			$return .= "<div class='blue'>Please name new host entry:";
			$return .= "<input type='input' name='hostname' value='New Host'>";
			$return .= "<input type='submit' name='action[ReallyNewHost]' value='Create'></div>";
			break;
		case "ReallyNewHost":############################################
			$return = "<h3>Create (".$_POST['hostname'].")</h3>";# show headline
			if (file_exists($config['configfile'].$_POST['hostname'])) 
				$return .= "<pre class='red'>Host: <em>".$_POST['hostname']."</em> already exists!</pre>";
			else{
				if (copy('default', $config['configfile'].$_POST['hostname'])) {
					$return .= "<pre class='red'>New Host: <em>".$_POST['hostname']."</em> created!</pre>";
					$return .= parse_file_contents($config['configfile'].$_POST['hostname']);
					$return .= "<input type='hidden' name='hostname' value='".$_POST['hostname']."'>";
					$return .= "<pre class='blue'>".edit_conf_file($inputvalues, $config, $mode)."</pre>";
				}
				else 
					$return .= "<pre class='red'>Error while copying!</pre>";
			}
			break;
		default:#########################################################
			$return = "<h3>Error (".$menue_entry.")</h3>";# show headline
			$return .= "<pre class='red'>Please choose one of the options above!</pre>";
			break;
	}
}
elseif (isset($_POST['Comment'])){# comment button pressed
	$menue_entry = clean_html(array_keys($_POST['Comment'])[0]);# Comment[<config file option>][<line no>] -> <+/->
	$line = clean_html(array_keys($_POST['Comment'][$menue_entry])[0]);
		if (isset($_POST['hostname'])){
			$return = "<h3>Edit (".$_POST['hostname'].")</h3>";# show headline
			$return .= "<input type='hidden' name='hostname' value='".$_POST['hostname']."'>";
			$inputvalues = $_POST['inputvalues']; unset($inputvalues['comment'][$menue_entry][$line]);# delete specific line from variable			
			$return .= "<pre class='blue'>".edit_conf_file($inputvalues, $config, $mode)."</pre>";
		}
		else 
			$return = "<pre class='red'>Error! No host defined!</pre>\n";# show error message
}
else $return = "";
$return .= "<input type='hidden' name='expertMode' value='".$mode."'>";
################# Main Menue End ########################################
echo "<tr><td colspan='".$config['columns']."' align='left'>".$return."</td></tr>";
echo "</tr>\n</tbody></table>\n";
echo "<pre>";print_r($config);echo "</pre>";
echo "<pre> ";print_r($inputvalues);echo "</pre>";
debug_output();
############################# END #################################################################
echo "<br><br>";
echo "</form>\n<footer id='footer'>My personal page hosted on my own server &copy; olkn</footer></body></HTML>\n";
########### END ###################################?>

wake on lan and terminal management page

This code was written to get a management interface for my own servers. But as I switched to another option the code was never in productive state.

<?php ############# HEAD  ############################
echo "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n";
echo "<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n";
############# docu ################################
/* create user account on target machine for shutdown (shutdownuser)
 * enable shutdown command for user on target machine (sudoers)
 * copy public key file for HTTP Server account to target machines .ssh/authorized_keys
 */
############# style sheets ########################
echo "<title>Terminal Server</title>\n<link rel='stylesheet' type='text/css' href='terminal.css'></head>\n<body>\n\n";
############# Configuration ##########################
/*
 * start server via relais
 * link zu shell in box fuer direkten connect
 */
$mac_adress_file = "terminal-list";# path where mac adresses are listed, must be accessible on webserver machine with webserver user rights
$server_port_to_check=22;# port to check for availability
$domain = ".steppenwolf.de";# domain all server reside in
$table_headers = array("Check", "Server (Terminal)", "Start", "Stop", "Comment");
$redirect_header = "/bananas";# if we were redirected we append level to URI
$shutdown_command = "ls ";
$shutdown_user = "shutdownuser";# user for shutdown command
$shutdown_public_keyfile = "id_rsa.pub"; # public_keyfile, must be accessible on webserver machine with webserver user rights
$Shutdown_private_keyfile = "id_rsa"; # private_keyfile, must be accessible on webserver machine with webserver user rights
###### links to shell in a box #################################
/*
 * shellinaboxd -t -s /:LOGIN -s /who:nobody:nogroup:/:w
 * In addition to the login shell at http://localhost:4200, show a list of currently logged in users when accessing http://localhost:4200/who. This command must be run as root in order to be able to change to nobody:nogroup as requested by the service description
 * shellinaboxd -t -s '/:root:root:/:wy60 -c /bin/login'
 * Instead of the standard ANSI/VT100 terminal, publish a Wyse 60 terminal. Again, this command should be run as root.
 * shellinaboxd -s /:SSH:example.org

    The terminal connects to a ssh session on example.org. 

shellinaboxd -t -s /:AUTH:HOME:/bin/bash

    Interactively request the user's name and password prior to launching a Bourne shell. This command can be run by unprivileged users. But if doing so, it only allows this particular user to log in. 
    
    oder spezieller Nutzer mit PRG als shell
*/		
###### parse contents of configfile and store everything in two arrays
function parse_file_contents($filename){
	global $inputvalues;
	$return = true;
	if ($data = file_get_contents($filename)){
		$contents = explode("\n", $data);
		foreach ($contents as $line) { # parse each line of the input file seperately
			$line = trim($line); $value = ""; # and override default values with config file values
			if (strlen($line) && substr($line, 0, 1) != '#') { # no comment lines and only lines with contents are parsed
				$key = trim(strtok($line, " \t")); # name of the specific option is first parameter
				$inputvalues["values"][$key] = trim(strtok(" \t")); # second entry is value for option
				while ($inputpart = strtok(" \t")) $value = $value.trim($inputpart)."\t"; # rest of the line is combined as comment
					$inputvalues["comment"][$key] = trim($value);
			} # comment lines and empty lines are ignored
		}# parsing of all lines done
	}# could not get file contents via function so die
	else {
		$return = false;
	}
	return $return;
}
###### check availability of server
function check_vitality($server, $timeout = 2){# ICMP ping packet with a pre-calculated checksum
return "1 OK toki";
	global $server_port_to_check;
	$contents = "";
	$fp = fsockopen($server, $server_port_to_check, $errno, $errstr, $timeout);
	if (!$fp) {
		$return = "0"."$errstr ($errno)";
	} else {
		stream_set_timeout($fp, $timeout);
	    $contents = $contents.fgets($fp, 128);
	    fclose($fp);
	    $return = "1".$contents;
	}
	return $return;
}
###### start server via GPIO
function start_server($server){
	$return = "Alles gut";
	return $return;
}
###### shutdown server
function shutdown_server($server){
	global $shutdown_command, $shutdown_user, $shutdown_public_keyfile, $Shutdown_private_keyfile;
	$connection = ssh2_connect($server, 22, array('hostkey', 'ssh-rsa'));
	if (ssh2_auth_pubkey_file($connection, $shutdown_user,$shutdown_public_keyfile, $Shutdown_private_keyfile)) {
		$return = "Public Key Authentication Successful\n<br>Shutting down server<br>\n";
		$stream = ssh2_exec($connection, $shutdown_command);
		$return = $return."<br>done ...<br>\n";
		fclose($stream);
	} else {
		$return = "Public Key Authentication Failed";
	}
	return $return;
}
###### edit terminal list
function edit_conf_file() {
	global $inputvalues;
	echo "<table border=1 width=700>\n"; # main table with all server names listed
	echo "<tr>\n<td colspan=3 class=header-style><br> Edit terminal list <br>&nbsp</td></tr>\n";
	echo "<tr>\n<td class=subheader-style> Server </td><td class=subheader-style> Terminal </td><td class=subheader-style> Comment </td></tr>\n";
	$counter = 0;
	foreach ($inputvalues["values"] as $key => $value){
		$counter ++;
		echo "<tr><td><input type='input' value='".$key."' name='server".$counter."'></td>";
		echo "<td><input type='input' value='".$value."' name='tty".$counter."'></td>";
		echo "<td  class=Comment-style><input class=Comment-style type='input' size=50 value='".$inputvalues['comment'][$key]."' name='comment".$counter."'></td></tr> ";
	}
	echo "<tr>\n<td colspan=2 align=center><input type='submit' name='CANCEL' value='CANCEL'></td><td align=center><input class=attention-style type='submit' name='SAVE' value='SAVE'></td></tr>\n";
	echo "<input type='hidden' name='counter' value='".$counter."'>\n";
	return;
}
###### save values to file
function save_conf_file($filename){
	$ergebnis = false;
	$output = "";
	for ($i=1;$i <= $_GET['counter']; $i++){# number of entries is stored in variable
		$output = $output.$_GET['server'.$i]."\t".$_GET['tty'.$i]."\t".$_GET['comment'.$i]."\n";
	}
	if ($handle = fopen($filename, "w")){ # open configfile for write
		fwrite($handle, $output);
		fclose($handle);
		$ergebnis = true;
	}
	else { # can not open output file
		$ergebnis = false;
	}
	return $ergebnis;
}
###### debug output of POST
function debug_output(){
	echo "<pre><br><h1>Hier kommt der schamass!</h1>";
	print_r($_GET);
	echo "</pre>"; return ;
}
############################## MAIN ##################################
if (isset($_SERVER['HTTP_X_FORWARDED_SERVER'])){ # if redirected, we use a different URI
	$action_script = $redirect_header.htmlspecialchars($_SERVER['PHP_SELF']);
}else {
	$action_script = htmlspecialchars($_SERVER['PHP_SELF']);
}
echo "<form method='get' action='".$action_script."'>\n";# page header with headline and table headers
if ( !parse_file_contents($mac_adress_file)) { # get contents of external file
	echo "<h1>Error reading config file!!</h1>";
} else {
	echo "<table border=1 width=700>\n"; # main table with all server names listed
	echo "<tr><td colspan=4 class=header-style><br> mini Server Admin Page <br>&nbsp</td><td align='center'><input class=attention-style type='submit' name='EDIT' value='EDIT'></td></tr>\n";
	echo "<tr>";
	foreach ($table_headers as $header)
		echo "<th class='".$header."-style' > ".$header."</th>";
	echo "</tr>\n";
	foreach ($inputvalues["values"] as $key => $value){# iterate over complete list of items 
		$title_text = check_vitality($key); # text to display on mouseover for button
		if (substr($title_text, 0, 1) == "1") 
			$text_color = "green";
		else 	
			$text_color = "red";
		echo "<tr><td align='center'><input type='submit' title='".substr($title_text, 1)."' name='CHECK' value='".$key."'></td>";
		echo "<td align='left' bgcolor='".$text_color."'> <a href='".$inputvalues['values'][$key]."' > ".$key.$domain." </td>";# link to terminal
		echo "<td class=Start-style><input type='submit' name='START' value='".$key."'></td>";# start server
		echo "<td align='center' class=Stop-style><input type='submit' name='STOP' value='".$key."'></td>";# stop server
		echo "<td class=Comment-style> ".$inputvalues['comment'][$key]." </td></tr>\n";# add comments field
	}
	echo "<tr><td colspan=5></td></tr>\n";
	echo "<tr><td colspan=5 align='center'><input type='submit' value='REFRESH' name='REFRESH'></td></tr>\n</table>\n";# just refresh the screen
	if (isset($_GET['STOP']) && array_key_exists($_GET['STOP'], $inputvalues['values'])){############ shutdown system ########################
		$server = $_GET['STOP'];
		echo "<h2>Stop Server: ".$server." </h2>\n<br><br>\n";
		echo shutdown_server($server);
	}
	elseif (isset($_GET['START']) && array_key_exists($_GET['START'], $inputvalues['values'])){############ wake up system ###################
		$server = $_GET['START'];
		echo "<h2>Wake Up System: ".$server."</h2>\n<br><br>\n";
		echo start_server($server);
	}
	elseif (isset($_GET['CHECK']) && array_key_exists($_GET['CHECK'], $inputvalues['values'])){############ get response on connectiontrial ###################
		$server = $_GET['CHECK'];
		echo "<h2>System returns: </h2>\n<br><br>".substr(check_vitality($server), 1)."\n<br><br>\n";
	}
	elseif (isset($_GET['EDIT'])) { ########### edit list of terminals #######################
		echo "<h2>Edit Terminallist</h2>\n";
		edit_conf_file();
	}
	elseif (isset($_GET['SAVE'])) { ########### save new entries to conf file ################
		echo "<h2>Save values to conf</h2>";
		if (save_conf_file($mac_adress_file)) echo "Updating Conf File successful (Choose REFRESH to see changes)!";
		else echo "Error during updating!";
	}
	elseif (!isset($_GET['REFRESH']) && !empty($_GET) && !isset($_GET['CANCEL'])) echo "<h1>Wrong Server choosen</h1>";############ user tries to cheat ################
	}
#print_r($inputvalues);
#debug_output();
echo "</form>\n</Body></HTML>\n";
########### END ###################################?>
@CHARSET "ISO-8859-1";
barbox_a {
  position: absolute;
  top: 330px;
  left: 250px;
  margin: 0px 0px 0px -160px;
  width: 304px;
  height: 24px;
  background-color: black;
}
.per {
  position: absolute;
  top: 330px;
  font-size: 18px;
  left: 250px;
  margin: 1px 0px 0px 150px;
  background-color: #FFFFFF;
}

.bar {
  position: absolute;
  top: 332px;
  left: 250px;
  margin: 0px 0px 0px -158px;
  width: 0px;
  height: 20px;
  background-color: #777777;
  border-style: solid;
  border-width: 1px;
}

.blank {
  background-color: white;
  width: 300px;
  border-style: solid;
  border-width: 1px;
}
.Stop-style {
	color: lightgray;
	background-color: firebrick;
	
}
.header-style {
	font-size: 20px;
}
.Start-style {
	text-align: center;
	background-color: blue;
	color: white;
}
.Comment-style {
	color: gray;
	background-color: lightgray;
}
a {
	color: lightgray;
}
.attention-style {
	background-color: red;
	color: white;
}
.subheader-style {
	color: white;
	background-color: dimgray;
}

Here is an example of the external file which lists the servers and its interfaces.


backup ttyUSB0 Backup Server
bananas ttyUSB1 Nas Server on Banana Pi
toradex ttyUSB2 Certification Authority on Toradex
raspberrypi ttyUSB3 Raspberry Pi for trials
cubietruck ttyUSB4 Cubie Main Server

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;
}

print documents via web interface

This simple php code will allow to choose one or more documents and prints them using the local cups printer. There is also a possibility to select one of the locally installed printers.

There are some prerequesites as follows:

  • install unoconv and openoffice/libreoffice (import filters are required)
  • install calc, writer, impress, draw as required (import formats)
  • local lpr printing programm and lpstat for list of installed printers are required
  • upload is putting any non-pdf document in a local folder on the webserver for conversion this folder must be writable by PHP/apache
  • copy this file to location accessible by apache
<?php ############# HEAD  ############################
echo "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n";
echo "<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n";
/* Short Introduction
 * 
 * - install unoconv and openoffice/libreoffice (import filters are required)
 * - install calc, writer, impress, draw as required (import formats)
 * - local lpr printing programm and lpstat for list of installed printers are required
 * - upload is putting any non-pdf document in a local folder on the webserver for conversion
 *   this folder must be writable by PHP/apache
 * - copy this file to location accessible by apache
 */
############# Configuration ##########################
$print_command = "/usr/bin/lpr -P ";# local print command
$conv_command = "unoconv -f pdf ";# conversion command
$upload_directory ="/var/www/PDF/";# dir where all the magic takes place
$filesize = 100000;# file size limit in kB
$printer_default = "PDF";# default printer for first start
### no changes should be necessary beneathe this line
$reg_printer = "/^device for (.*): .*$/im";# examination of lpstat to get list of installed printers
$PHP_SELF = htmlspecialchars($_SERVER['PHP_SELF']); 
$uploadcounter = 1;#default value for number of upload buttons
echo "<title>Print File</title>\n</head>\n<body>\n\n";
###### debug output of POST
# debugging function to show HTML variables
#
function debug_output(){
	echo "<pre><br><h1>Show internal variables</h1>";
	print_r($_POST);echo "<br>";
	print_r($_FILES);
	echo "</pre>"; return ;
}
###### get local printerrs #############
# function will examine lpstat to get list of
# locally installed printers
#
function get_local_printer($printer_default){
	global $reg_printer;
	$output = shell_exec("/usr/bin/lpstat -s");
	if (preg_match_all($reg_printer, $output, $printer)) {
		echo "<SELECT name='printer' size='1'>\n";
		foreach ($printer[1] as $key => $value){
		echo "<OPTION";if ($printer_default == $value) echo " selected";echo "> ".$value." </OPTION>\n";
		}
		echo "</SELECT>";
	}
	return;
}
###### file upload box with comment text
# show file upload box with in-/decrease button
#
function fileupload_box($text, $count=1){
	global $filesize;
	if ($text != "") echo "<h2>".$text."</h2>\n";# show status information on top
	echo '<input type="hidden" name="MAX_FILE_SIZE" value="'.$filesize.'" >';
	echo "<table border='0'>";# Table for formatting
	for ($i=0; $i < $count; $i++){
		echo "<tr><td><input type='submit' name='addcounter' value='+'></td>";
		echo "<td><input type='submit' name='delcounter' value='-'></td>";
		echo "<td>File to print Nr. ".$i." :</td><td><INPUT TYPE='file' NAME='print_file[]' size='50'></td></tr>\n";
	}
	echo "<tr><td colspan='4'>&nbsp; </td></tr>";
	echo "<tr><td colspan='4' align='center'><INPUT TYPE='SUBMIT' NAME='UPLOAD' value=' PRINT '></td></tr>\n</table>\n";
}
############################## MAIN ##################################
echo "<form method='post' action='$PHP_SELF' enctype='multipart/form-data'>\n";# form for file upload
if (isset($_POST['uploadcounter'])) $uploadcounter = $_POST['uploadcounter'];
if (isset($_POST['addcounter'])) $uploadcounter = $uploadcounter+1;# additional upload button please
if (isset($_POST['delcounter'])) $uploadcounter = $uploadcounter-1;# delete one upload button please
if (isset($_POST['printer'])) $printer_default = $_POST['printer'];# keep choosen printer
if ($uploadcounter < 1) $uploadcounter=1;# at least one entry must remain
echo "<table width='100%'><tr><td><h1>Print selected Files</h1></td>\n";$text = "";
echo "<td>Choose Printer:</td><td>";get_local_printer($printer_default);
echo "</td></tr></table>\n";
if (isset($_POST['UPLOAD'])) {# upload button pressed;the magic begins
	for ($i=0; $i < $uploadcounter; $i++){# iterate over list of files
		$file = $_FILES['print_file']['tmp_name'][$i];# temporary file name
		$filename = $upload_directory.basename($file);# final doc name incl folder
		if ($file == "" || $_FILES['print_file']['size'][$i] == 0 || !is_file($file)) { # no file selected 
			$text = "Please choose files to print!";
		}
		else {
			if (is_uploaded_file($file)) { # check for upload errors
				if(!move_uploaded_file($file, $filename))# copy files to dir
					echo "<h2>Moving file".$file." to destination ".$upload_directory." failed!</h2>";
				else{
					if (strripos(mime_content_type($filename), "pdf") === false){# check if file mime type is pdf
						shell_exec( $conv_command." ".$filename." -o ".$filename.".pdf > /dev/null");# unoconv -f pdf file
						shell_exec( $print_command.$printer_default." ".$filename.".pdf > /dev/null");# execute print command
						echo "<p style='color:#aaaaaa, font-size:50%'> (".$print_command.$printer_default." ".$filename.".pdf) </p>";
					}
					else # file is pdf, so print directly
						shell_exec( $print_command.$printer_default." ".$file." > /dev/null");# execute print command
					echo "<br>Printouts may be found in your local printer\n";# be polite ;-)
				}
			}
			else { # file upload went wrong
				$text = "File Upload error";
			}
		}
	}
	$uploadcounter=1;# reset counter
}
echo "<input type='hidden' name='uploadcounter' value='".$uploadcounter."'>";# take hidden counter for number of upload buttons
fileupload_box($text, $uploadcounter);# generate upload boxes
#debug_output();# show debug information
echo "</form>\n</Body></HTML>\n";# The End!
########### END ###################################?>

Tine 2.0 Setup

To enable SMTP and IMAP support in Tine 2.0 the following points must be followed:

  • enable system account in the setup (Systemkonto verwenden)
  • the login name and password must be identical in Tine as well as on the email server

The setup of Tine 2.0 itself is straight forward and following the general installation guide.