12. Administration - login - filesystem

12.1. PHP File: filesystem.php

12.1.1. Source code

<?php
define('IMINFO_VERSION','20170525H2314');
define('DEBUG',true);
define('DEBUG_TEST',false);
define('RPROCFILE','rproc.txt');
define('FPROCFILE','fproc.txt');
define('LOCAL_ADDRESS','127.0.1.1');
define('VISITCNT_PER_EMAIL',50);
define('DS','/');
define('PUBLIC_DIR','Resized');
define('PRIVATE_DIR','Private');
define('MOVE_COPY_VIDEO','COPY');
define('MEDIA_FILES','*.{jpg,JPG,png,PNG,gif,GIF,webm,WEBM,mp4,MP4}');
define('IMAGE_FILES','*.{jpg,JPG,png,PNG,gif,GIF}');
define('VIDEO_FILES','*.{mp4,MP4,webm,WEBM}');
define('GALLERY_IMAGE_FILES','*-small.{jpg,JPG,png,PNG,gif,GIF}');
define('MEDIA_FILES_REGEX','/.*\.(jpg|JPG|png|PNG|gif|GIF|webm|WEBM|mp4|MP4)/');
define('IMAGE_FILES_REGEX','/.*\.(jpg|JPG|png|PNG|gif|GIF)/');
define('VIDEO_FILES_REGEX','/.*\.(mp4|MP4|webm|WEBM)/');
define('GAL_IMFILES_REGEX','/.*-small\.(jpg|JPG|png|PNG|gif|GIF)/');

define('NUMBER_OF_BITS_PER_DIGIT',4);
define('NO_PROCESSED_FILES',                 0x00000);
define('PROCESSED_FILES_ORIGINALS_KEPT',		0x00001);
define('PROCESSED_FILES_ORIGINALS_ADD_REM',	0x00002);//Orginals have been removed, new originals have been added.
define('PROCESSED_FILES_ORIGINALS_REMOVED',	0x00003);
define('LOCATION_DIR_HAS_CHANGED',				0x00004);//Access time of location dir more recent than access time of iminfo.xml file
define('PUBLIC_DIR_HAS_CHANGED',					0x00008);//Access time of Resized dir more recent than access time of iminfo.xml file
define('RESIZE_STAT_MASK',							0x0000F); 
define('RESIZE_STAT_MASK_2',						0x00003);
define('RESIZE_STAT_MASK_TIMECHANGE',			0x0000C);
define('RPROC_FPROC_NOT_EXIST',					0xFF00F);

define('FPROC_STAT_MASK',							0x000F0);
define('FPROC_STAT_EXIST',							0x00010);
define('FPROC_STAT_ALBUM_MEDIA_EXIST',			0x00020);
define('FPROC_STAT_MEDIA_EXIST',					0x00040);
define('FPROC_STAT_PHPDEF_EXIST',				0x00080);

define('RPROC_STAT_MASK', 							0x00F00);
define('RPROC_STAT_EXIST',							0x00100);
define('RPROC_STAT_UPD_WITH_PUBPRIV_COUNT',  0x00200);
define('RPROC_STAT_UPD_WITH_LOC_IMAGE_COUNT',0x00400);
define('RPROC_STAT_UPD_WITH_LOC_VIDEO_COUNT',0x00800);

define('UPD_NOTHING',   							0x00000);
define('UPD_MEDIA_MASK',							0x0F000);// Public and private update status
define('UPD_PUB_IMAGES',							0x01000);
define('UPD_PUB_VIDEOS',							0x02000);
define('UPD_PRV_IMAGES',							0x04000);
define('UPD_PRV_VIDEOS',							0x08000);

//define('PPUPD_IMAGES',0x1000);
//define('PPUPD_VIDEOS',0x2000);
//define('PPUPD_ALL_MEDIA',0x3000);
define('PUBLIC_PRIVATE_CHANGE',  0x04000); // NOT YET USED
define('NO_MEDIA_PROCESSING',    0x00);
define('ALL_MEDIA_PROCESSING',   0x01);
define('UPD_MEDIA_PROCESSING',   0x02);
define('MASK_MEDIA_PROCESSING',  0x0F);
define('RPROC_UPD_PUB_MEDIA',	   0x10000);
define('RPROC_UPD_PRV_MEDIA',		0x20000);
define('RPROC_UPD_MEDIA_MASK',	0xF0000);
define('MEDIA_UPDATE',true);
define('ADMIN_LOGIN_MASK',0xF0E0C);

define('OK',0);
define('REMOVE_RPROC',-1);
define('UPDATE_RPROC',-2);
define('UPDATE_PUBPRIV',-3);
define('BACKGROUND_COLOR_WARNING','#F90'); // ORANGE
define('BACKGROUND_COLOR_NOTIFY', '#FF0'); // YELLOW
define('BACKGROUND_COLOR_ALERT',  '#F00'); // RED
define('BACKGROUND_COLOR_OK',     '#0F0'); // GREEN
define('BACKGROUND_COLOR_NORMAL', '#FFF'); // WHITE
define('ADMINISTRATOR','admin');
define('UPDATE_IMINFO_NOFILE',		0x00);
define('UPDATE_IMINFO_EXISTS_OK',	0x01);
define('UPDATE_IMINFO_MEDIACOUNT',	0x02);
define('UPDATE_IMINFO_VERSION',		0x04);
define('UPDATE_IMINFO_MAXCOUNT', 	0x08);
define('UPDATE_IMINFO_IMAGEINFO',	0x10);
define('UPDATE_IMINFO_VIDEOINFO',	0x20);
define('UPDATE_IMINFO_MODUS_TXT', 001);
define('UPDATE_IMINFO_MODUS_XML', 002);
define('UPDATE_IMINFO_MODUS_KEEP_MODTIME',000);
define('UPDATE_IMINFO_MODUS_CHNG_MODTIME',010);
// NO MEDIA TRANSFER ACTION CODES
define('TRANSFER_NONE',0); // Media must not be transferred to either public or private directory
define('TRANSFER2PUBLIC',1); // Media is transferred to public directory:
define('TRANSFER2PRIVATE',2); // Media is transferred to private directory
// MEDIA TRANSFER ACTION CODES
define('TRANSFER2PUBLIC_AGAIN',-1); // Public media deleted. Original is available --> transfer again
define('TRANSFER2PRIVATE_AGAIN',-2); // Private media deleted. Original is available --> transfer again
define('TRANSFER_FIRST_TIME_SCHEDULED',-100);// Transfer new media
define('_FFMPEG','C:\Dany\Software\MultimediaProcessing\ffmpeg-20151116-git-1fe82ab-win64-static\bin\ffmpeg.exe');
define('CONST_SERVER_TIMEZONE',			'UTC');
define('CONST_SERVER_DATEFORMAT',		'YmdHis');
define('SYSTEM_ERROR_TMP_JSON',			0x0001);
define('SYSTEM_ERROR_TMP_MKDIR',			0x0002);
define('SYSTEM_ERROR_ALBUM_NO_DEF',		0x0010);
define('SYSTEM_ERROR_ALBUM_NO_MEDIA',	0x0020);
define('ECHO_MODE',0);
define('INIT_STAT_DISPLAY_MODE',			00000);
define('STAT_TABLE_MODE',					01000);
define('STAT_DISPLAY_MODE',				01101);
define('NO_STAT_DISPLAY_MODE',			00110);
define('UPD_STAT_DISPLAY_MODE',			01011);
define('JSON_SLEEP',125000);
define('TIME_RANK_PREFIX_LENGTH',4);
define('E_IMINFO_FS_W',-10); // File system write error: no permission, not enough memory,...) iminfo.xml not generated 
define('E_IMINFO_UPD_NOT_MODIFIED',-4); // iminfo.xml not modified
define('E_IMINFO_XML_2',-3); // Empty 'iminfo.xml' file
define('E_IMINFO_XML_1',-2); // No 'iminfo.xml' file
define('E_IMINFO_TXT_1',-1); // iminfo.xml not generated: no 'iminfo.txt' file.
define('E_IMINFO_TXT_2',0);  // iminfo.xml not generated: 'iminfo.txt' file is empty.
define('E_IMINFO_UPD_OK',1); // 'iminfo.xml' file exists and updated, original is renamed with timestamp
define('E_IMINFO_UPD_OK_B',2); // update of 'iminfo.xml' file is written to new file for test purpose
define('E_IMINFO_CRE_OK',3); // 'iminfo.xml' file is created from txt
// end_macro_definition

function f_parse_csv($filename,$longest,$delimiter)
/* Reference: http://stackoverflow.com/questions/96759/how-do-i-sort-a-multidimensional-array-in-php */
{
	if ($file=fopen($filename,"r")){
		$mdarray=array();
		while ($line=fgetcsv($file,$longest,$delimiter)){array_push($mdarray,$line);}
		fclose($file);
 		return $mdarray;
	}
	else return (NULL);
}

function removeDirectory($path){
	$files = glob($path . '/*');
	foreach ($files as $file) is_dir($file) ? removeDirectory($file) : unlink($file);
	rmdir($path);
	return;
}

function is_dir_empty($dir)
{
	$iterator = new FilesystemIterator($dir);
	return (!$iterator->valid());
}

function xml2array($xml)
{
	$arr=array();
	foreach ($xml->children() as $r) {
		$t=array();
		if(count($r->children())==0) {
			$arr[$r->getName()]=strval($r);
		} else {
			$arr[$r->getName()][]=xml2array($r);
		}
	}
	return $arr;
}

function my_empty($var){
// IN PHP A STRING WITH VALUE "0" IS CONSIDERED TO BE EMPTY!
// http://php.net/manual/en/function.empty.php
// IN THIS APPLICATION A STRING WITH VALUE "0" IS CONSIDERED NOT TO BE EMPTY!
	if (is_string($var)){
		if (strlen(trim($var))==0){return (true);}
		else return (false);
	} else return empty($var);
}

function array_key_exist_and_not_empty($key,$arr)
{
	if ((array_key_exists($key,$arr))&&(!my_empty($arr[$key])))
	{return 1;}
	else {return 0;}
}

function rename_with_timestamp($filename,$str='')
{
// OUT1: new name (without trailing directory)
	if (strlen($str)==0){$timeStr=date("Ymd-Hi",time());}
	else {$timeStr=$str;}
	$file_parts=pathinfo($filename);
	$dir=$file_parts['dirname'];
	$name_without_extension=$file_parts['filename'];
	$extension=$file_parts['extension'];
	$newName_noDir=$name_without_extension.'-'.$timeStr.'.'.$extension;
	$newName=$dir.DS.$newName_noDir;
	rename($filename,$newName);
	return $newName_noDir;
}

function delete_fotoproc_file(){unlink(FPROCFILE);}

function array_keys_exist($needles,$haystack)
// https://www.reddit.com/r/PHP/comments/2jitxn/best_way_to_check_an_array_for_existence_of/
{
	foreach ($needles as $needle)	{
		if (!isset($haystack[$needle])) return false;
	}
	return true;
}

function now($str_user_timezone,$str_server_timezone=CONST_SERVER_TIMEZONE,$str_server_dateformat=CONST_SERVER_DATEFORMAT)
// http://www.pontikis.net/tip/?id=18
{
	// set timezone to user timezone
	date_default_timezone_set($str_user_timezone);
	$date=new DateTime('now');
	$date->setTimezone(new DateTimeZone($str_server_timezone));
	$str_server_now=$date->format($str_server_dateformat);
	// return timezone to server default
	date_default_timezone_set($str_server_timezone);
	return $str_server_now;
}

function json_send_string($arr,$sleep)
{
	echo json_encode($arr);
	flush();
	usleep($sleep);
}

function my_echo($mode,$str,$script=false){
	if ($mode==0){
		echo $str;
	}
	else if (($mode==00010)&&(!$script)){
		json_send_string(array('status'=>3,'html'=>$str),100000);
	}
}

function _or($a,$b) {return $a|$b;}
function _has_value_1($a,$b) {return ($a==1)||$b;}

function create_testfile($fname,$dir,$value)
{
	$myfile=fopen($_SERVER['DOCUMENT_ROOT']."/".$dir."/".$fname,"w");
	fwrite($myfile,$value);
	fclose($myfile);
}

function globalstat2binstr($globStat,$type=1)
{
	$binCode=decbin($globStat);
	$nrBits=5*NUMBER_OF_BITS_PER_DIGIT;// 20 characters (XFFFFF = 5*4, i.e. 5 hexadecimal numbers represented as bits)
	$binCode_rep=str_repeat("0",$nrBits);// 0000-0000-0000-0000-0000
	$binCode_rep=substr_replace($binCode_rep,$binCode,$nrBits-strlen($binCode));
	if ($type==0) {
		$binCode_rep=substr_replace($binCode_rep,"xxxx",4,4);
		$binCode_rep=substr_replace($binCode_rep,"xxxx",12,4);
	}
	$binCode_rep=substr_replace($binCode_rep,"-",4,0);  // Insert - char after position 4 starting from left
	$binCode_rep=substr_replace($binCode_rep,"-",9,0);  // Insert - char after position 9 starting from left
	$binCode_rep=substr_replace($binCode_rep,"-",-4,0); // Insert - char after position 4 starting from right
	$binCode_rep=substr_replace($binCode_rep,"-",-9,0); // Insert - char after position 9 starting from right
	return $binCode_rep;
}

function _globalStat2Binstr($globStat)
{
	$hexCode_StrRep=array_fill_keys(array('all_parts',1,2,3,4,5),'');
	$binCode=decbin($globStat&RESIZE_STAT_MASK);
	$hexCode_StrRep[1]=substr_replace("0000",$binCode,NUMBER_OF_BITS_PER_DIGIT-strlen($binCode));
	$binCode=decbin(($globStat&FPROC_STAT_MASK)>>(NUMBER_OF_BITS_PER_DIGIT));
	$hexCode_StrRep[2]=substr_replace("0000",$binCode,NUMBER_OF_BITS_PER_DIGIT-strlen($binCode));
	$binCode=decbin(($globStat&RPROC_STAT_MASK)>>(2*NUMBER_OF_BITS_PER_DIGIT));
	$hexCode_StrRep[3]=substr_replace("0000",$binCode,NUMBER_OF_BITS_PER_DIGIT-strlen($binCode));
	$binCode=decbin(($globStat&UPD_MEDIA_MASK)>>(3*NUMBER_OF_BITS_PER_DIGIT));
	$hexCode_StrRep[4]=substr_replace("0000",$binCode,NUMBER_OF_BITS_PER_DIGIT-strlen($binCode));
	$binCode=decbin(($globStat&RPROC_UPD_MEDIA_MASK)>>(4*NUMBER_OF_BITS_PER_DIGIT));
	$hexCode_StrRep[5]=substr_replace("0000",$binCode,NUMBER_OF_BITS_PER_DIGIT-strlen($binCode));
	$hexCode_StrRep['all_parts']=$hexCode_StrRep[5].'-'.$hexCode_StrRep[4].'-'.$hexCode_StrRep[3].'-'.$hexCode_StrRep[2].'-'.$hexCode_StrRep[1];
	return $hexCode_StrRep;
}

function globalstat_1pos_2binstr($globStat,$pos)
{
	switch($pos){
		case 1:$binCode=decbin($globStat&RESIZE_STAT_MASK);
		break;
		case 2:$binCode=decbin(($globStat&FPROC_STAT_MASK)>>(NUMBER_OF_BITS_PER_DIGIT));
		break;
		case 3:$binCode=decbin(($globStat&RPROC_STAT_MASK)>>(2*NUMBER_OF_BITS_PER_DIGIT));
		break;
		case 4:$binCode=decbin(($globStat&UPD_MEDIA_MASK)>>(3*NUMBER_OF_BITS_PER_DIGIT));
		break;
		case 5:$binCode=decbin(($globStat&RPROC_UPD_MEDIA_MASK)>>(4*NUMBER_OF_BITS_PER_DIGIT));
		break;
	}
	return (substr_replace("0000",$binCode,NUMBER_OF_BITS_PER_DIGIT-strlen($binCode)));
}

// http://www.geekality.net/2011/05/28/php-tail-tackling-large-files/
function tail($filename,$lines=10,$buffer=4096)
{
	$f=fopen($filename,"rb");
	// Jump to last character
	fseek($f,-1,SEEK_END);
// Read it and adjust line number if necessary
// (Otherwise the result would be wrong if file doesn't end with a blank line)
	if(fread($f,1)!="\n") $lines-=1;
// Start reading
	$output='';
	$chunk='';
	// While we would like more
	while(ftell($f) > 0 && $lines >= 0)
	{
		// Figure out how far back we should jump
		$seek=min(ftell($f),$buffer);
		// Do the jump (backwards, relative to where we are)
		fseek($f,-$seek,SEEK_CUR);
		// Read a chunk and prepend it to our output
		$output=($chunk=fread($f,$seek)).$output;
		// Jump back to where we started reading
		fseek($f,-mb_strlen($chunk,'8bit'),SEEK_CUR);
		// Decrease our line counter
		$lines-=substr_count($chunk,"\n");
	}
// While we have too many lines (because of buffer size we might have read too many)
	while($lines++ < 0)
	{
		// Find first newline and remove all text before that
		$output=substr($output,strpos($output,"\n") + 1);
	}
	fclose($f); 
	return $output;
}

function filesize_r($folder){
// https://bytes.com/topic/php/answers/593461-how-check-folder-size
	if(!file_exists($folder)) return 0;
	if(is_file($folder)) return filesize($folder);
	$ret=0;
	foreach(glob($folder."/*") as $fn) $ret+=filesize_r($fn);
	return $ret;
}

function rfile_count($folder,$fname,$depth=-1) {
// Count number of files recursively.
// https://stackoverflow.com/questions/17160696/php-glob-scan-in-subfolders-for-a-file
	$dir=new RecursiveDirectoryIterator($folder);
	$ite=new RecursiveIteratorIterator($dir);
	$ite->setMaxDepth($depth);
	$files=new RegexIterator($ite,$fname,RegexIterator::GET_MATCH);
	$cnt=0;
	foreach($files as $file) {
		$cnt++;
	}
   return $cnt;
}

function rfile_list($folder,$fname,$depth=-1) {
// https://stackoverflow.com/questions/17160696/php-glob-scan-in-subfolders-for-a-file
	$dir=new RecursiveDirectoryIterator($folder);
	$ite=new RecursiveIteratorIterator($dir);
	$ite->setMaxDepth($depth);
	$files=new RegexIterator($ite,$fname,RegexIterator::GET_MATCH);
	$fileList=array();
	foreach($files as $file) {
		$fileList=array_merge($fileList,$file);
	}
   return $cnt;
}

12.1.2. Function f_parse_csv($filename, $longest, $delimiter)

f_parse_csv($filename, $longest, $delimiter)
Parameters:
  • $filename (String) –
  • $longest (String) –
  • $delimiter (Char) –
Returns:

Array

12.1.3. Function removeDirectory($path)

removeDirectory($path)
Parameters:
  • $path (String) –

12.1.4. Function xml2array($xml)

xml2array($xml)
Parameters:
  • $xml (XML-Object) –

12.1.5. Function json_send_string($arr, $sleep)

json_send_string($arr, $sleep)
Parameters:
  • $arr (Array) –
  • $sleep (Integer) – time in microseconds

12.2. PHP File: mysql_create_insert.php

12.2.1. Source code

<?php

function create_database($servername,$username,$password,$database){
// Create connection
	$conn = mysqli_connect($servername,$username,$password);
	if (!$conn){
		die("Connection failed: ".mysqli_connect_error());
		return FALSE;
	}
// CREATE DATABASE
//	$sql="CREATE DATABASE IF NOT EXISTS ".$database;
	$status=FALSE;
	if (!mysqli_select_db($conn,$database)) {
		$sql = "CREATE DATABASE ".$database;
		if (mysqli_query($conn, $sql)){
			echo "Database created successfully.<br>";
			$status = TRUE;
		}
		else echo "Error creating database: ".mysqli_error($conn);
//	mysqli_select_db($conn,$database);
	}
	else {
		echo "Database already exists.<br>";
	}
	mysqli_close($conn);
	return $status;
}

// CREATE DATABASE TABLES
function create_tables_members_log($servername,$username,$password,$database,$selector){
	$conn=mysqli_connect($servername,$username,$password,$database);
	if ($conn){
		echo "Connect succesfull<br>";
		if ($selector==0 || $selector==1){
			$tbl_members="CREATE TABLE IF NOT EXISTS members(
				id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
				username VARCHAR(30) NOT NULL,
				password CHAR(128) NOT NULL,
				email VARCHAR(50) NOT NULL,
				email_password CHAR(128) NOT NULL,
				salt CHAR(128) NOT NULL,
				Group ENUM('familie','veronique') NOT 'familie',
				Timelimit TINYINT(1) NOT 0,
				BeginTime DATE NOT NULL,
				EndTime DATE NOT NULL)";
			$sql=mysqli_query($conn,$tbl_members);
			if ($sql)echo "MEMBERS TABLE CREATED SUCCESSFULLY. <br>";
			else "ERROR: MEMBERS TABLE NOT CREATED. <br>";
		}
		if ($selector==0 || $selector==2){
			$tbl_log="CREATE TABLE IF NOT EXISTS log(
				id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
				user_id INT(11) NOT NULL,
				username VARCHAR(30) NOT NULL,
				email VARCHAR(50) NOT NULL,
				message_code INT(4) NOT NULL,
				ip VARCHAR(128) NOT NULL,
				login_attempt DATETIME NOT NULL,
				message VARCHAR(128) NOT NULL)";
			$sql=mysqli_query($conn,$tbl_log);
			if ($sql) echo "LOG TABLE CREATED SUCCESSFULLY. <br>";
			else "ERROR: LOG TABLE NOT CREATED. <br>";
		}
		mysqli_close($conn);
	}
}

function create_tables_webserver($servername,$username,$password,$database){
	$conn=mysqli_connect($servername,$username,$password,$database);
	if ($conn){
		$tbl_members="CREATE TABLE IF NOT EXISTS webserver(
			 id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
			 hostname VARCHAR(128) NOT NULL,
			 hostadmin VARCHAR(128) NOT NULL,
			 hostadmin_password VARCHAR(128) NOT NULL,
			 hostadmin_email VARCHAR(128) NOT NULL,
			 hostadmin_alias VARCHAR(128) NOT NULL,
			 iv CHAR(128) NOT NULL,
			 SMTPSecure VARCHAR(32) NOT NULL,
			 port INT(11) NOT NULL,
			 contact_email VARCHAR(128) NOT NULL,
			 contact_alias  VARCHAR(128) NOT NULL)";
		$sql=mysqli_query($conn,$tbl_members);
		if ($sql)echo "MEMBERS TABLE CREATED SUCCESSFULLY. <br>";
		else "ERROR: MEMBERS TABLE NOT CREATED. <br>";
		mysqli_close($conn);
	}
}

function create_database_isp($servername,$username,$password){
	if (create_database($servername,$username,$password,'isp')){
		create_tables_webserver($servername,$username,$password,'isp');
		return TRUE;
	}
	return FALSE;
}
?>

12.2.2. Function create_database_isp($server, $admin, $password)

create_database_isp($server, $admin, $passwprd)
Parameters:
  • $server (String) –
  • $admin (String) –
  • $password (String) –
Returns:

12.2.3. Function create_database($server,$admin,$password,‘login’)

create_database($server, $admin, $password, ‘login’)
Parameters:
  • $server (String) –
  • $admin (String) –
  • $password (String) –
  • optional argument (String) –

12.2.4. Function create_tables_members_log()

create_tables_members_log()

12.3. PHP file: login.min.php

PHP script is called by an AJAX script and returns a JSON string, converted from the object

$d=array_fill_keys(array("ConnectMySQLServer","SqlServerStat","login","SID"),array("code"=>0,"private_url"=>"","message"=>""));

If [“SqlServerStat”][“code”] is 0 then the connection to the MySL server is succesful.

12.3.1. Source code

<?php
/* Script is called by 41184.dwt template by an AJAX call (in function login_dialogbox() in dlgboxes_public.js)
 * The AJAX call is given 3 arguments with the POST method. The POST keys are: password (string), username (string), and sitepage (integer).
 * The sitepage corresponds to the row number of the matrix data in the file pages.txt.
 * Return code's (in JSON string for AJAX):
 * -100: See connect_2_mysqli_server_error()
 * -5: Cannot create PHP mailer object
 * -4: Database does not exist,
 * -3: Database connection error,
 * -2: Wachtwoord is niet juist:			Geverifieerd,
 * -1: Onbekende gebruiker:				Geverifieerd,
 * 1: Inloggen gelukt: NOT admin user:	Geverifieerd,
 * 2: Inloggen gelukt: Admin user:		Geverifieerd
 */
require_once($_SERVER['DOCUMENT_ROOT'].'/login/loginFunctions.php');
require_once($_SERVER['DOCUMENT_ROOT'].'/php/mailer/e-mail.php');
ob_start();
sec_session_start();
$password='12345';
$username='guest';
$page='';
if (isset($_POST['password']))$password=$_POST['password'];
if (isset($_POST['username']))$username=$_POST['username'];
if (isset($_POST['page']))$page=$_POST['page'];
// PHP VERSION >= 5.5.0
$d=array();
$SafeUsername=$username;
$invalidUsername=False;
if ($username!=trim($username)){
	// Server side validation of $username: $username may not contain spaces.
	// If it does -> $username is not allowed.
	$invalidUsername=True;
	// Use a non-existent username for database querry
	$SafeUsername="Zoempie";
}
$query="SELECT id, username, password, email, salt, `Group` FROM members WHERE username = '$SafeUsername';";
$SqlConnObj=connect_2_mysqli_server(MYSQL_SERVER);
$conn=$SqlConnObj->conn;
$d=array_fill_keys(array("ConnectMySQLServer","SqlServerStat","login","SID"),array("code"=>0,"private_url"=>"","message"=>""));
if ($conn){
	$emContent=new emailContent($username);
	$kk=new RemoteAddress;
	$ip=$kk->getIpAddress();
	$username=$conn->real_escape_string($username);
	$result=$conn->query($query);
	if($result->num_rows==0) // User not found.
	{
		$str="Failed login: **'$username'** unregistered username.";
		if ($invalidUsername){
			$str.=" Valid username may not contain spaces.";
		}
		$emContent->subj=$str;
		$emContent->code=UNREGISTERED_USER;
		$emContent->codeStr="UNREGISTERED_USER";
		$emContent->mainMsg="Failed login attempt from: '$ip' <br>";
		$emContent->address="E-mail address unknown";
		$d['login']=array('code'=>UNREGISTERED_USER,'message'=>$emContent->subj);
		$emContent->msgList=array_merge($d,$SqlConnObj->msg_arr,updateLogfile(0,$emContent,$SqlConnObj));
		$sendEmail=true;
	} else { // User found in database
		$userData=$result->fetch_array(MYSQLI_ASSOC);
		$hash=hash('sha256',$userData['salt'].hash('sha256',$password));
		if($hash!=$userData['password']){
			$emContent->code=KNOWN_USER_WRONG_PASSWORD;
			$emContent->subj='Failed login: wrong credentials.';
			$emContent->codeStr="KNOWN_USER_WRONG_PASSWORD";
			$emContent->mainMsg="Failed login attempt from: '$ip' <br>";
			$emContent->address=$userData['email'];
			$d['login']=array('code'=>KNOWN_USER_WRONG_PASSWORD,'message'=>$emContent->subj);
			$emContent->msgList=array_merge($d,$SqlConnObj->msg_arr,updateLogfile($userData['id'],$emContent,$SqlConnObj));
			$sendEmail=true;
		} else {//Successful login: send e-mail notification when user is admin, else no e-mail notification
		  //	session_regenerate_id();
			$sid=session_id();
			$time_str=date('l, d-M-Y H:i:s T');
			$_SESSION['sess_id']=$sid;
			$_SESSION['sess_user_id']=$userData['id'];
			$_SESSION['sess_username']=$userData['username'];
			$_SESSION['sess_group']=$userData['Group'];
			$_SESSION['loggedin_time']=$time_str;
			$filename='../pages.txt';
			$url_arguments='';
			if ($file=fopen($filename,"r")){
				$pages=array();
				while ($line=fgetcsv($file,1000,',')){array_push($pages,$line);}
				fclose($file);
				$str=str_replace('-private','',trim($pages[$page-1][3]));
				if (trim($pages[$page-1][2])==$str){ // PRIVATE VERSION OF SAME PAGE
					$parts=parse_url($_SERVER['HTTP_REFERER']);
					if (array_key_exists('query',$parts)) $url_arguments='?'.$parts['query'];
				} 
				$private=$pages[$page-1][3];
				unset($pages);
			}
			else $private='index-private.php'; //FALLBACK
			$params=session_get_cookie_params();
			$cookieLogFile=$_SERVER["DOCUMENT_ROOT"].DS."log".DS."cookie_param_login.txt";
			$message=date("Y-m-d H:i:s")." ".json_encode($params)." ".PHP_EOL;
			file_put_contents($cookieLogFile,$message,FILE_APPEND);
			$emContent->address=$userData['email'];
			$emContent->codeStr="NONE";
			$emContent->mainMsg="";
			$emContent->subj="User $username is logged on from $ip at time $time_str: switch to private version";
			if ($userData["username"]=="admin"){
				$d['login']=array("code"=>ADMIN_LOGGED_ON,"private_url"=>$private.$url_arguments,"message"=>$emContent->subj);
				$emContent->code=ADMIN_LOGGED_ON;
				$sendEmail=true;
				$_SESSION['sess_user_permission']=ADMIN_PERMISSION_LEVEL;
			}
			else { //user != admin
				$d['login']=array("code"=>USER_LOGGED_ON,"private_url"=>$private.$url_arguments,"message"=>$emContent->subj);
				$emContent->code=USER_LOGGED_ON;
				$sendEmail=false;
				$_SESSION['sess_user_permission']=REG_USER_PERMISSION_LEVEL;
				if ($_SESSION['sess_group']=="familie") $_SESSION['sess_user_permission']+=FAMILY_PERMISSION_LEVEL;
			}
			$d['SID']=array("code"=>$sid,"message"=>"Generated by session_id()");
			$emContent->msgList=array_merge($d,$SqlConnObj->msg_arr,updateLogfile($userData['id'],$emContent,$SqlConnObj));
//			setcookie(session_name(),$sid,0);
		}
	}
	if ($sendEmail) $d=array_merge($d,loginNotificationEmail($emContent,$SqlConnObj,__FILE__));
	$result->free();
	json_send_string($d,1000);
	unset($d);
	$conn->close();
}
else {// No connection to MYSQL server
	$sqlFail=new sqlConnectFail("login",$SqlConnObj->status,$SqlConnObj->msg_arr);
	connect_2_mysqli_server_error($sqlFail);
}
session_write_close();
?>

12.4. PHP file: changepassword.php

<?php
// Script is called by 41184-private.dwt template by an AJAX call in dlgboxes_private.js.
include_once 'loginFunctions.php';
require_once($_SERVER['DOCUMENT_ROOT'].'/php/filesystem.php');

ob_start();
sec_session_start();
$password='';
$newpassword='';
if(count($_POST)==0) return;
//	$vex=NULL;
//	if (isset($_POST['vex']))$vex=$_POST['vex'];
if (isset($_POST['old_password']))$password=$_POST['old_password'];
if (isset($_POST['password']))$newpassword=$_POST['password'];
$username=$_SESSION['sess_username'];
$SqlConnObj=connect_2_mysqli_server(MYSQL_SERVER);
$sqlconn=$SqlConnObj->conn;
if ($sqlconn){
	$username=$sqlconn->real_escape_string($username);
	$emContent=new emailContent($username);
	$query="SELECT id, username, password, email, salt
			FROM members
			WHERE username = '$username';";
	$result=$sqlconn->query($query);
	$d=array();
	if(!$result){ // Zou niet mogen kunnen omdat de gebruiker ingelogd moet zijn om hier te komen!!
		$emContent->code=UNREGISTERED_USER;
		$emContent->subj='Procedure for resetting password failed: Unregistered username';
		$emContent->codeStr="UNREGISTERED_USER";
		$emContent->mainMsg="The username $username you entered is not registered. Failed to change password.<br>";
		$emContent->address="a@b.c";
		$d['changepassword']=array('code'=>UNREGISTERED_USER,'message'=>$emContent->subj);
		$emContent->msgList=array_merge($d,$SqlConnObj->msg_arr,updateLogfile(111111111,$emContent,$SqlConnObj));
		$sendEmail=false;
	}
	else{
		$row=$result->fetch_array(MYSQLI_ASSOC);
//encrypted password in MY_SQL database
		$dbpassword=$row["password"];
		$salt=$row['salt'];
// For password comparison the given password must first be encrypted with the same key.
		$hash=hash('sha256',$salt.hash('sha256',$password));
		if($hash!=$dbpassword){
			$emContent->code=KNOWN_USER_WRONG_PASSWORD;
			$emContent->subj='Procedure for resetting password failed: Wrong current password.';
			$emContent->codeStr="KNOWN USER PASSWORD NOT MODIFIED";
			$emContent->mainMsg='Incorrect current password. Password will not be changed.<br>';
			$emContent->address=$row['email'];
			$d['changepassword']=array('code'=>KNOWN_USER_WRONG_PASSWORD,'message'=>$emContent->subj);
			$emContent->msgList=array_merge($d,$SqlConnObj->msg_arr,updateLogfile($row['id'],$emContent,$SqlConnObj));
			$sendEmail=true;
		}
		else{
			$hash=hash('sha256',$salt.hash('sha256',$newpassword));
			$sqlconn->query("UPDATE members set password='$hash' WHERE username='$username'");
			$emContent->code=USER_PASSWORD_CHANGED;
			$emContent->subj="Password changed";
			$emContent->codeStr="PASSWORD CHANGED";
			$emContent->mainMsg="Password of user '$username' has been modified.<br>";
			$emContent->address=$row['email'];
			$d['changepassword']=array('code'=>USER_PASSWORD_CHANGED,'message'=>$emContent->subj);
			$emContent->msgList=array_merge($d,$SqlConnObj->msg_arr,updateLogfile($row['id'],$emContent,$SqlConnObj));
			$sendEmail=true;
		}
	}
	if ($sendEmail) $d=array_merge($d,loginNotificationEmail($emContent,$SqlConnObj,__FILE__));
	$result->free();
	json_send_string($d,1000);
	unset($d);
	$sqlconn->close();
}
else {
	$sqlFail=new sqlConnectFail("changepassword",$SqlConnObj->status,$SqlConnObj->msg_arr);
	connect_2_mysqli_server_error($sqlFail);
}
session_write_close();
?>

12.5. PHP file: wachtwoordvergeten.min.php

<?php
/* Script is called by AJAX javascript wachtwoord_vergeten() implemented in dlgboxes_public.js
 * Return code's:
 * -3: Naar admin wordt geen nieuw wachtwoord gestuurd --> wachtwoord niet veranderd.
 * -2: Onbekende gebruiker.
 * -1: Opgegeven e-mail adres niet bekend.
 * 0: Gekende gebruiker, e-mail bekend, verzenden nieuw wachtwoord niet gelukt --> wachtwoord niet veranderd.
 * 1: Gekende gebruiker, e-mail bekend, verzenden nieuw wachtwoord gelukt --> wachtwoord is veranderd.
 */
require_once($_SERVER['DOCUMENT_ROOT'].'/login/database_info.php');
require_once($_SERVER['DOCUMENT_ROOT'].'/login/loginFunctions.php');
require_once($_SERVER['DOCUMENT_ROOT'].'/php/mailer/e-mail.php');

function generate_password($length=8,$complex=3) {
// http://99webtools.com/blog/php-strong-random-password-generator/
	$min="abcdefghijklmnopqrstuvwxyz";
	$num="0123456789";
	$maj="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
	$symb="!@#$%^&*()_-=+;:,.?";
	$chars=$min;
	if ($complex>=2) {$chars.=$num;}
	if ($complex>=3) {$chars.=$maj;}
	if ($complex>=4) {$chars.=$symb;}
	$password=substr(str_shuffle($chars),0,$length);
	return $password;
}

ob_start();
sec_session_start();
$email='';
$username='';
if (isset($_POST['username']))$username=$_POST['username'];
if (isset($_POST['email']))$email=$_POST['email'];
$d=array();
$SqlConnObj=connect_2_mysqli_server(MYSQL_SERVER);
$sqlconn=$SqlConnObj->conn;
if ($sqlconn){
   $username=$sqlconn->real_escape_string($username);
   $emContent=new emailContent($username);
   $query="SELECT id, username, password, email, salt FROM members WHERE username = '$username';";
   $result=$sqlconn->query($query);
   if($result->num_rows==0){// User not found.
      $emContent->code=UNREGISTERED_USER;
      $emContent->subj='Username not registered';
      $emContent->codeStr="UNREGISTERED_USER";
      $emContent->mainMsg="$username not registered. <br>";
      $emContent->address="E-mail address unknown";
      $d['ForgotPassword']=array('code'=>UNREGISTERED_USER,'message'=>$emContent->subj);
      $emContent->msgList=array_merge($d,$SqlConnObj->msg_arr,updateLogfile(0,$emContent,$SqlConnObj));
      $sendEmail=true;
   } 
   else {// User found
      $userData=$result->fetch_array(MYSQLI_ASSOC);
      if ($username==='admin'){
         $emContent->code=ADMIN_USER_NO_RESET_PASSWD;
         $emContent->subj='User admin does not forget password';
         $emContent->codeStr="ADMIN_USER_NO_RESET_PASSWD";
         $emContent->mainMsg="User admin does not forget password. <br>";
         $emContent->address=$userData['email'];
         $d['ForgotPassword']=array('code'=>ADMIN_USER_NO_RESET_PASSWD,'message'=>$emContent->subj);
         $emContent->msgList=array_merge($d,$SqlConnObj->msg_arr,updateLogfile($userData['id'],$emContent,$SqlConnObj));
         $sendEmail=true;
      }
      else {
         if($email!=$userData['email']){//Username is known, e-mail, wrong e-mail address.
            $emContent->code=KNOWN_USER_WRONG_EMAIL;
            $emContent->subj="Username is registered. Unknown e-mail address ($email): password cannot be reset.";
            $emContent->codeStr="KNOWN_USER_WRONG_EMAIL";
            $emContent->mainMsg="Username $username is registered.<br> Unknown e-mail address: password cannot be reset.<br>";
            $emContent->address="Given e-mail address not registered.";
            $d['ForgotPassword']=array('code'=>KNOWN_USER_WRONG_EMAIL,'message'=>$emContent->subj);
            $emContent->msgList=array_merge($d,$SqlConnObj->msg_arr,updateLogfile($userData['id'],$emContent,$SqlConnObj));
            $sendEmail=true;
         }
         else {// Username and e-mail are known
            $newpassword=generate_password(8);
            $hash=hash('sha256',$userData['salt'].hash('sha256',$newpassword));
            $sqlconn->query("UPDATE members set password='$hash' WHERE username='$username'");
            $emContent->subj="Password reset";
            $emContent->codeStr="NONE";
            $emContent->mainMsg="Your new password is: $newpassword<br>";
            $emContent->address=$userData['email'];
            $d['ForgotPassword']=array('code'=>1,'message'=>'New password is sent to '.$email);
            $emContent->msgList=array_merge($d,$SqlConnObj->msg_arr,updateLogfile($userData['id'],$emContent,$SqlConnObj));   
            $sendEmail=true;
         }
      }
   }
   $d=array_merge($d,$SqlConnObj->msg_arr);
   if ($sendEmail) $d=array_merge($d,loginNotificationEmail($emContent,$SqlConnObj,__FILE__));
   $result->free();
   json_send_string($d,1000);
   unset($d);
   $sqlconn->close();
}
else {
   $sqlFail=new sqlConnectFail("ForgotPassword",$SqlConnObj->status,$SqlConnObj->msg_arr);
   connect_2_mysqli_server_error($sqlFail);
}
session_write_close();
?>

12.6. PHP file: register2a.php

12.6.1. Source code

<?php
require_once($_SERVER['DOCUMENT_ROOT'].'/login/loginFunctions.php');

function createSalt(){
   $text=md5(uniqid(rand(),true));
   return substr($text,0,3);
}
$username=$_POST['username'];
$password1=$_POST['password'];
$password2=$_POST['confirm_password'];
$email=$_POST['email'];
$vex=NULL;
if (isset($_POST['vex']))$vex=$_POST['vex'];
if($password1!=$password2){
	$d['register_new_user']=array('code'=>E_NEW_USER_PASSWD_MISMATCH,'message'=>'Passwords do not match.');
}
else if (strlen($username)>30){
	$d['register_new_user']=array('code'=>E_NEW_USER_NAME_TOO_LONG,'message'=>'Username too long (max 30char).');
}
else {/* HASH is PHP - FUNCTION*/
	$hash=hash('sha256',$password1);    
	$salt=createSalt();
	$password=hash('sha256',$salt.$hash);
	$SqlConnObj=connect_2_mysqli_server(MYSQL_SERVER);
	$conn=$SqlConnObj->conn;
	if ($conn){
		$username=$conn->real_escape_string($username);
		$query="INSERT INTO members (username,password,email,salt) VALUES ('$username','$password','$email','$salt')";
		if (!$conn->query($query)){
			$message="Error description: " .$conn->error;
			$d['register_new_user']=array('code'=>E_NEW_USER_NOT_ADDED,'message'=>$message);
		}else{
			$message="Nieuwe gebruiker geregistreerd.";
			$d['register_new_user']=array('code'=>USER_NEW_REGISTERED,'message'=>$message);
	//            if ($vex!= NULL) echo json_encode(array('code'=>1,'message'=>$message));
	//            else header('Location: /index.html');            
		}
		json_send_string($d,1000);
		unset($d);
		$conn->close();
	}
	else {
		$sqlFail=new sqlConnectFail("register_new_user",$SqlConnObj->status,$SqlConnObj->msg_arr);
		connect_2_mysqli_server_error($sqlFail);
   }
}
?>

12.7. PHP File: remoteaddress.php

12.7.1. Source code

<?php
/**
 * Functionality for determining client IP address.
 */
class RemoteAddress
{
  protected $useProxy=false;
  protected $trustedProxies=array();
  protected $proxyHeader='HTTP_X_FORWARDED_FOR';
  public function setUseProxy($useProxy=true)
  {
	  $this->useProxy=$useProxy;
	  return $this;
  }
  public function getUseProxy(){return $this->useProxy;}
  public function setTrustedProxies(array $trustedProxies)
  {
	  $this->trustedProxies=$trustedProxies;
	  return $this;
  }
  public function setProxyHeader($header='X-Forwarded-For')
  {
	  $this->proxyHeader=$this->normalizeProxyHeader($header);
	  return $this;
  }
  public function getIpAddress()
  {
	  $ip = $this->getIpAddressFromProxy();
	  if ($ip) {return $ip;}
	  if (isset($_SERVER['REMOTE_ADDR'])) {return $_SERVER['REMOTE_ADDR'];}
	  return '';
  }
  protected function getIpAddressFromProxy()
  {
	  if (!$this->useProxy || (isset($_SERVER['REMOTE_ADDR']) && !in_array($_SERVER['REMOTE_ADDR'],$this->trustedProxies))){
		  return false;
	  }
	  $header=$this->proxyHeader;
	  if (!isset($_SERVER[$header]) || empty($_SERVER[$header])) {return false;}
	  $ips=explode(',',$_SERVER[$header]);
	  $ips=array_map('trim',$ips);
	  $ips=array_diff($ips,$this->trustedProxies);
	  if (empty($ips)) {return false;}
	  $ip=array_pop($ips);
	  return $ip;
  }
  protected function normalizeProxyHeader($header)
  {
	  $header=strtoupper($header);
	  $header=str_replace('-','_', $header);
	  if (0 !== strpos($header,'HTTP_')) {$header='HTTP_'.$header;}
	  return $header;
  }
}

12.8. PHP file: loginFunctions.php

12.8.1. Source code

<?php 
//namespace Zend\Http\PhpEnvironment;
include_once($_SERVER['DOCUMENT_ROOT'].'/login/database_info.php');
require_once($_SERVER['DOCUMENT_ROOT'].'/login/remoteaddress.php');
require_once($_SERVER['DOCUMENT_ROOT'].'/php/mailer/e-mail.php');
require_once($_SERVER['DOCUMENT_ROOT'].'/php/filesystem.php');

//define('MYSQL_SERVER','LOCAL');
define('MYSQL_SERVER', HOST_ISP);
define("WEBMASTER", "dany");
define("WEBSITE_VISITOR", "site_visitor");
define("VISITOR_GROUP", "no_group");
define("ADMIN_PERMISSION_LEVEL", 31);//0b11111
define("FAMILY_PERMISSION_LEVEL", 8); //0b01000
define("REG_USER_PERMISSION_LEVEL", 4); //0b00100
define("GUEST_PERMISSION_LEVEL", 2); // 0b00010
define("VISITOR_PERMISSION_LEVEL", 1); // 0b00001
define('ALBUM_UPDATE_PERMISSION_LEVEL',ADMIN_PERMISSION_LEVEL); /* Alternative: 'REG_USER_PERMISSION_LEVEL' */
define("PUBLIC",1);
define("PRIVATE",0);
define("SECURE",FALSE);// FOR DEVELOPMENT ONLY!!!!

define("USER_LOGGED_ON",1);
define("ADMIN_LOGGED_ON",2);
define("USER_PASSWORD_CHANGED",3);
define("USER_PASSWORD_RESET",4);
define("USER_NEW_REGISTERED",5);

define("UNREGISTERED_USER",-1); // NOT KNOWN IN MEMBERS TABLE
define("KNOWN_USER_WRONG_PASSWORD",-2);
define("KNOWN_USER_WRONG_EMAIL",-3);
define("ADMIN_USER_NO_RESET_PASSWD",-4);

define("E_MYSQL_CONFIG_NOT_FOUND",-5);
define("E_MYSQL_SERVER_UNKOWN",-6);
define("E_MYSQL_NOT_CONNECTED",-7);
define("E_NEW_USER_NOT_ADDED",-8);
define("E_NEW_USER_PASSWD_MISMATCH",-9);
define("E_NEW_USER_NAME_TOO_LONG",-10);
define("E_PHPMAILER_OBJECT",-11);
define("E_PHPMAILER_CANNOT_SEND",-12);
define("E_MAIL_CONT_WEBSERVER_NF",-13); // E-MAIL CONTAINER ERROR: ENTRY "WEBSERVER" not found in table "MEMBERS"
define("E_WEBSERVER_TABLE_NF",-14);
define("E_ISP_HOSTNAME_NF",-15); // ISP HOSTNAME NOT FOUND IN WEBSERVER TABLE

define("UNKNOWN_USER_CHANGE_PASSWORD",2);// NOT USED ANYMORE: 20210411

define("KNOWN_USER_PASSWORD_NOT_MODIFIED",4);// NOT USED ANYMORE: 20210411
define("ADMIN_USER_DOESNT_ASK_PASSWORD",5);// NOT USED ANYMORE: 20210411

class codeMessage
{
	public $code;
	public $message;
}

class emailContent
{
	public $subj;
   public $code;
   public $codeStr;
   public $msgList;
   public $mainMsg;
   public $uname;
   public $address;
   public function __construct($uname)
   {
      $this->uname=$uname;
   }
}

class sqlConnectFail
{
   public $debug=DEBUG;
   public $keyName;
   public $sql_server_stat;
   public $sql_msg_arr;
   public function __construct($key,$sql_server_stat,$sql_msg_arr)
   {
      $this->keyName=$key;
      $this->sql_server_stat=$sql_server_stat;
      $this->ConnectMySQLServer=$sql_msg_arr;
   }
}

// sec_session_start_Begin
function sec_session_start(){
// Reference: https://www.wikihow.com/Create-a-Secure-Login-Script-in-PHP-and-MySQL
//if (!isset($_SESSION)){
		$session_name='sec_session_id';
		$secure=SECURE;
		$httponly=true;
		if (ini_set('session.use_only_cookies',1)===FALSE){
			header("Location: ../error.php?err=Could not initiate a safe session (ini_set)");
			exit();
		}
		$cookieParams = session_get_cookie_params();
		session_set_cookie_params($cookieParams["lifetime"],$cookieParams["path"],$cookieParams["domain"],$secure,$httponly);
		session_name($session_name);
		if (version_compare(phpversion(),'5.4.0','<')){
			if(session_id()==''){$state=session_start();}
		}
		else if (session_status()==PHP_SESSION_NONE){$state=session_start();}
// Regenerating the session_id makes the session management rather cumbersome.
// Therefore it is easier not to regenerate the session_id.
		session_regenerate_id(true);
//	} else $state='true';
}
// sec_session_start_End

// connect_2_mysqli_server_Begin
function connect_2_mysqli_server($mysql_server){
	// Inform mysqli to throw exceptions
	mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
	static $sqlconn;
	static $mysql_msg_arr;
	static $status;
	$status=0;
	if (!isset($sqlconn)){
		try {
			if (($mysql_server==='LOCAL')&&($_SERVER['SERVER_ADDR']==='127.0.0.1')){
				$sqlconn=new mysqli(HOST_LOCAL,DB_ADMIN_LOCAL,DB_ADMIN_PWD_LOCAL,DB_USERS_LOCAL);
				$connID="LOCAL MYSQL, LOCAL WEBSERVER";
				$mysql_msg_arr['ConnectMySQLServer']=array('code'=>0,'message'=>$connID);
			}
			else {
				$isp_db_info=DB_ADMIN_PWD_ISP();
				if ($isp_db_info){
					$hn=$isp_db_info['hostname'];
					if (($mysql_server===$isp_db_info['host_ip'])&&($_SERVER['SERVER_ADDR']==='127.0.0.1')){
						$sqlconn=new mysqli($isp_db_info['host_ip'],$isp_db_info['username'],$isp_db_info['password'],$isp_db_info['users_db']);
						$connID="MYSQL @ ISP($hn), LOCAL WEBSERVER";
						$mysql_msg_arr['ConnectMySQLServer']=array('code'=>0,'message'=>$connID); // Succesful connection to MYSQL Server.
					}
					else if (($mysql_server===$isp_db_info['host_ip'])&&($_SERVER['SERVER_ADDR']===$isp_db_info['host_ip'])){ // MYSQL Server AT ISP, ISP WEBSERVER
						$sqlconn=new mysqli($isp_db_info['host_ip'],$isp_db_info['username'],$isp_db_info['password'],$isp_db_info['users_db']);
						$connID="MYSQL @ ISP($hn), ISP WEBSERVER";
						$mysql_msg_arr['ConnectMySQLServer']=array('code'=>0,'message'=>$connID); // Succesful connection to MYSQL Server.
					}
					else {
						$sqlconn=false;
						$status=E_MYSQL_SERVER_UNKOWN;
						$connID="Unknown remote MYSQL-server selected by constant MYSQL_SERVER.";
						$mysql_msg_arr['ConnectMySQLServer']=array('code'=>E_MYSQL_SERVER_UNKOWN,'message'=>$connID);
					}
				}
				else {
					$sqlconn=false;
					$status=E_MYSQL_CONFIG_NOT_FOUND;
					$mysql_msg_arr['ConnectMySQLServer']=array('code'=>E_MYSQL_CONFIG_NOT_FOUND,'message'=>'File mysql_config.ini not found.');
				}
			}
		}
		catch(\mysqli_sql_exception $e) {// Ensure the use of functions defined in global name space
			$sqlconn=false;
			$status=E_MYSQL_NOT_CONNECTED;
			$mysql_msg_arr['ConnectMySQLServer']=array('code'=>mysqli_connect_errno(),'message'=>mysqli_connect_error());
		}
	}
	$SqlConnObj = new stdClass;
	$SqlConnObj->conn=$sqlconn;
	$SqlConnObj->status=$status; // Can have the following values: 0, E_MYSQL_CONFIG_NOT_FOUND, E_MYSQL_SERVER_UNKOWN, E_MYSQL_NOT_CONNECTED
	$SqlConnObj->msg_arr=$mysql_msg_arr;
	return $SqlConnObj;
}
// connect_2_mysqli_server_End

// updateLogDatabaseTable_Begin
function updateLogDatabaseTable($id,$em_C,$ip,$SqlConnObj){
    // Only called in this file by function updateLogfile
	$nu=date("Y-m-d H:i:s");
   $sqlconn=$SqlConnObj->conn;
	$query="INSERT INTO `".DB_LOG_TABLE."` (user_id,username,email,ip,message_code,login_attempt,message) VALUES
    ('$id','$em_C->uname','$em_C->address','$ip','$em_C->code','$nu','$em_C->subj')";
	if ($sqlconn->query($query)) return array('code'=>0,'message'=>'New entry in Log database table');
	else return array('code'=>$sqlconn->errno,'message'=>$sqlconn->error);
}
// updateLogDatabaseTable_End

// updateLogfile_Begin
function updateLogfile($id,$em_C,$SqlConnObj){
	$kk=new RemoteAddress;
	$ip=$kk->getIpAddress();
	$file=fopen("../log/warnings.log","a");
	$today=date("Y-m-d H:i:s");
	$str=$today.', '.$ip.', Error code:'.$em_C->code.', '.$em_C->uname.', '.$em_C->address.', '.$em_C->subj.PHP_EOL;
	fwrite($file,$str);
	fclose($file);
	$updateLogFile_err_msg=array();
	$updateLogFile_err_msg['LogDbTable']=updateLogDatabaseTable($id,$em_C,$ip,$SqlConnObj);
	return $updateLogFile_err_msg;
}
// updateLogfile_End

function my_simple_encrypt($string,$key,$iv){
// Reference: https://nazmulahsan.me/simple-two-way-function-encrypt-string/
	$output=FALSE;
	$encrypt_method="AES-256-CBC";
	$key=hash('sha256',$key);
	$iv=substr(hash('sha256',$iv),0,16);
	$output=base64_encode(openssl_encrypt($string,$encrypt_method,$key,0,$iv));
	return $output;
}

function my_simple_decrypt($string,$key,$iv){
// Reference: https://nazmulahsan.me/simple-two-way-function-decrypt-string/
	$output=FALSE;
	$encrypt_method="AES-256-CBC";
	$key=hash('sha256',$key);
	$iv=substr(hash('sha256',$iv),0,16);
	$output=openssl_decrypt(base64_decode($string),$encrypt_method,$key,0,$iv);
	return $output;
}

function array2String($array){
   $str="";
   foreach ($array as $key => $obj){
      $str2="";
      foreach ($obj as $skey => $m) $str2.="&#9;".$skey." = ".$m.",<br>";
      $str.=$key." - key:<br>".$str2;
   }
   return $str;
}

// loginNotificationEmail_Begin
function loginNotificationEmail($emContent,$SqlConnObj,$fileName){
   $mail=CreateEmailContainer(WEBMASTER,$SqlConnObj);
   $msg=$mail->sql_msg_arr;
   $fname=basename($fileName);
   if ($mail->obj_stat==1){
      $mail->Subject.=$emContent->subj;
      $emailBody=$emContent->mainMsg;
      $emailBody.="Function: ".__FUNCTION__."()<br>";
      $emailBody.="Error code: ".$emContent->codeStr."<br>";
      $emailBody.="Username: ".$emContent->uname."<br>";
      $emailBody.=array2String($emContent->msgList);
      $mail->Body =$emailBody;
      if(!$mail->send()) $d['email']=array("code"=>E_PHPMAILER_CANNOT_SEND,"message"=>"Sending mail error in \"$fname\". ".$mail->ErrorInfo);//$mail->ErrorInfo
      else $d['email']=array("code"=>0,"message"=>"Mail send from \"$fname\".");
   } else{
      $d['email']=array('code'=>E_PHPMAILER_OBJECT,'message'=>"Mail error: cannot create PHPMailer object in \"$fname\".");
      $d=array_merge($d,$msg);
   }
   return $d;
}
// loginNotificationEmail_End

function connect_2_mysqli_server_error($sqlConnectFail){
   if (!$sqlConnectFail->debug) {
      $msg_1="";
      $msg_2='Cannot connect to MYSQL server.';
   }
   else {
      $msg_1="<a href='/manual/Sphinx/build/html/admin_login_system.html#module-login.min.php'>See Manual</a>";
      $msg_2="<a href='/manual/Sphinx/build/html/process_flow.html#id36'>Failed login: cannot connect to MYSQL server.</a>";
   }
   $d['SqlServerStat']=array('code'=>$sqlConnectFail->sql_server_stat,'message'=>$msg_1);
   $d[$sqlConnectFail->keyName]=array('code'=>$sqlConnectFail->sql_server_stat,'message'=>$msg_2);
   $d=array_merge($d,(array)$sqlConnectFail->ConnectMySQLServer);
   json_send_string($d,1000);
   unset($d);
}
?>

12.8.2. Function connect_2_mysqli_server()

See also section Section 4.5, and Table 4.28.

12.8.2.1. Interface definition

connect_2_mysqli_server($mysql_server)
Parameters:
  • $mysql_server (String) – MYSQL Server IP4 address (in general this is given by the macro value MYSQL_SERVER). (See also Listing 1.1).
Returns:

  1. $SqlConnObj ( Object ) - new stdClass object see also Section 1.4, and has the following members:

    • conn ( Object ) - When connection to MYSQL Server is succesful mysqli object (status =0). Otherwise FALSE (status = E_MYSQL_CONFIG_NOT_FOUND, E_MYSQL_SERVER_UNKOWN, E_MYSQL_SERVER_UNKOWN).

    • msg_arr ( Object ) - Is array with 1 key “ConnectMySQLServer”. The array element is an object (See Table 4.31).

    • status ( Integer ) - Possible values:

      • E_MYSQL_NOT_CONNECTED: (-7) Failed to connect to MQSQL server. Reason for a failed connection to the MQSQL server is given in the second output argument $mysql_arr.

      • E_MYSQL_SERVER_UNKOWN: (-6) Input parameter $mysql_server points to unknown MYSQL Server.

        • [“ConnectMySQLServer”][“code”] = E_MYSQL_SERVER_UNKOWN
      • E_MYSQL_CONFIG_NOT_FOUND: (-5) File mysql_config.ini not found 🡺 MYSQL Server data missing for making a connection.

        • [“ConnectMySQLServer”][“code”] = E_MYSQL_CONFIG_NOT_FOUND
      • 0: Succesful connection to MYSQL Server.

12.8.2.2. Source code

<?php
function connect_2_mysqli_server($mysql_server){
	// Inform mysqli to throw exceptions
	mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
	static $sqlconn;
	static $mysql_msg_arr;
	static $status;
	$status=0;
	if (!isset($sqlconn)){
		try {
			if (($mysql_server==='LOCAL')&&($_SERVER['SERVER_ADDR']==='127.0.0.1')){
				$sqlconn=new mysqli(HOST_LOCAL,DB_ADMIN_LOCAL,DB_ADMIN_PWD_LOCAL,DB_USERS_LOCAL);
				$connID="LOCAL MYSQL, LOCAL WEBSERVER";
				$mysql_msg_arr['ConnectMySQLServer']=array('code'=>0,'message'=>$connID);
			}
			else {
				$isp_db_info=DB_ADMIN_PWD_ISP();
				if ($isp_db_info){
					$hn=$isp_db_info['hostname'];
					if (($mysql_server===$isp_db_info['host_ip'])&&($_SERVER['SERVER_ADDR']==='127.0.0.1')){
						$sqlconn=new mysqli($isp_db_info['host_ip'],$isp_db_info['username'],$isp_db_info['password'],$isp_db_info['users_db']);
						$connID="MYSQL @ ISP($hn), LOCAL WEBSERVER";
						$mysql_msg_arr['ConnectMySQLServer']=array('code'=>0,'message'=>$connID); // Succesful connection to MYSQL Server.
					}
					else if (($mysql_server===$isp_db_info['host_ip'])&&($_SERVER['SERVER_ADDR']===$isp_db_info['host_ip'])){ // MYSQL Server AT ISP, ISP WEBSERVER
						$sqlconn=new mysqli($isp_db_info['host_ip'],$isp_db_info['username'],$isp_db_info['password'],$isp_db_info['users_db']);
						$connID="MYSQL @ ISP($hn), ISP WEBSERVER";
						$mysql_msg_arr['ConnectMySQLServer']=array('code'=>0,'message'=>$connID); // Succesful connection to MYSQL Server.
					}
					else {
						$sqlconn=false;
						$status=E_MYSQL_SERVER_UNKOWN;
						$connID="Unknown remote MYSQL-server selected by constant MYSQL_SERVER.";
						$mysql_msg_arr['ConnectMySQLServer']=array('code'=>E_MYSQL_SERVER_UNKOWN,'message'=>$connID);
					}
				}
				else {
					$sqlconn=false;
					$status=E_MYSQL_CONFIG_NOT_FOUND;
					$mysql_msg_arr['ConnectMySQLServer']=array('code'=>E_MYSQL_CONFIG_NOT_FOUND,'message'=>'File mysql_config.ini not found.');
				}
			}
		}
		catch(\mysqli_sql_exception $e) {// Ensure the use of functions defined in global name space
			$sqlconn=false;
			$status=E_MYSQL_NOT_CONNECTED;
			$mysql_msg_arr['ConnectMySQLServer']=array('code'=>mysqli_connect_errno(),'message'=>mysqli_connect_error());
		}
	}
	$SqlConnObj = new stdClass;
	$SqlConnObj->conn=$sqlconn;
	$SqlConnObj->status=$status; // Can have the following values: 0, E_MYSQL_CONFIG_NOT_FOUND, E_MYSQL_SERVER_UNKOWN, E_MYSQL_NOT_CONNECTED
	$SqlConnObj->msg_arr=$mysql_msg_arr;
	return $SqlConnObj;
}

12.8.3. Function loginNotificationEmail()

loginNotificationEmail($emContent, $SqlConnObj, $fileName)
Parameters:
  • $emContent (Object) – emailContent Object,
  • $SqlConnObj (Object) – Object returned by connect_2_mysqli_server()
  • $filename (String) –
Returns:

  1. Array

12.8.3.1. Source code

<?php
function loginNotificationEmail($emContent,$SqlConnObj,$fileName){
   $mail=CreateEmailContainer(WEBMASTER,$SqlConnObj);
   $msg=$mail->sql_msg_arr;
   $fname=basename($fileName);
   if ($mail->obj_stat==1){
      $mail->Subject.=$emContent->subj;
      $emailBody=$emContent->mainMsg;
      $emailBody.="Function: ".__FUNCTION__."()<br>";
      $emailBody.="Error code: ".$emContent->codeStr."<br>";
      $emailBody.="Username: ".$emContent->uname."<br>";
      $emailBody.=array2String($emContent->msgList);
      $mail->Body =$emailBody;
      if(!$mail->send()) $d['email']=array("code"=>E_PHPMAILER_CANNOT_SEND,"message"=>"Sending mail error in \"$fname\". ".$mail->ErrorInfo);//$mail->ErrorInfo
      else $d['email']=array("code"=>0,"message"=>"Mail send from \"$fname\".");
   } else{
      $d['email']=array('code'=>E_PHPMAILER_OBJECT,'message'=>"Mail error: cannot create PHPMailer object in \"$fname\".");
      $d=array_merge($d,$msg);
   }
   return $d;
}

12.8.4. Function sec_session_start()

Reference: https://www.wikihow.com/Create-a-Secure-Login-Script-in-PHP-and-MySQL

sec_session_start()

12.8.4.1. Source code

<?php
function sec_session_start(){
// Reference: https://www.wikihow.com/Create-a-Secure-Login-Script-in-PHP-and-MySQL
//if (!isset($_SESSION)){
		$session_name='sec_session_id';
		$secure=SECURE;
		$httponly=true;
		if (ini_set('session.use_only_cookies',1)===FALSE){
			header("Location: ../error.php?err=Could not initiate a safe session (ini_set)");
			exit();
		}
		$cookieParams = session_get_cookie_params();
		session_set_cookie_params($cookieParams["lifetime"],$cookieParams["path"],$cookieParams["domain"],$secure,$httponly);
		session_name($session_name);
		if (version_compare(phpversion(),'5.4.0','<')){
			if(session_id()==''){$state=session_start();}
		}
		else if (session_status()==PHP_SESSION_NONE){$state=session_start();}
// Regenerating the session_id makes the session management rather cumbersome.
// Therefore it is easier not to regenerate the session_id.
		session_regenerate_id(true);
//	} else $state='true';
}

12.8.5. Function updateLogfile()

updateLogfile($username, $email, $statusmessage, $foutcode, $sendnotification)
Parameters:
  • $username (String) – Username
  • $email (String) – e-mail address used by username
  • $statusmessage – Message
  • $foutcode (Integer) – See Table 12.1
  • $sendnotification (Integer) – 0: send no e-mail notification to administrator, 1: send e-mail notification to administrator.
Table 12.1 Error codes
-1 Successful login, or password change,
0 Unknown user tries to login (e-mail notification) [Getest: OK]
1 Registered user but wrong password (e-mail notification) [Getest: OK]
2 Unknown user tries to reset password (e-mail notification) [Getest: OK]
3 Registered user asks for new password, but fails to give current e-mail address (e-mail notification) [Getest: OK]
4 Registered user tries to change password, but fails to give current password (e-mail notification) [Getest: OK]

12.8.5.1. Source code

<?php
function updateLogfile($id,$em_C,$SqlConnObj){
	$kk=new RemoteAddress;
	$ip=$kk->getIpAddress();
	$file=fopen("../log/warnings.log","a");
	$today=date("Y-m-d H:i:s");
	$str=$today.', '.$ip.', Error code:'.$em_C->code.', '.$em_C->uname.', '.$em_C->address.', '.$em_C->subj.PHP_EOL;
	fwrite($file,$str);
	fclose($file);
	$updateLogFile_err_msg=array();
	$updateLogFile_err_msg['LogDbTable']=updateLogDatabaseTable($id,$em_C,$ip,$SqlConnObj);
	return $updateLogFile_err_msg;
}

12.8.6. Function updateLogDatabaseTable()

updateLogDatabaseTable($id, $em_C, $ip, $SqlConnObj)
Parameters:
  • $id (Integer) –
  • $em_C (Object) – e-mail container Object
  • $ip (String) –
  • $SqlConnObj (Object) –
Return array(‘code’,’message’):
 

12.8.6.1. Source code

<?php
function updateLogDatabaseTable($id,$em_C,$ip,$SqlConnObj){
    // Only called in this file by function updateLogfile
	$nu=date("Y-m-d H:i:s");
   $sqlconn=$SqlConnObj->conn;
	$query="INSERT INTO `".DB_LOG_TABLE."` (user_id,username,email,ip,message_code,login_attempt,message) VALUES
    ('$id','$em_C->uname','$em_C->address','$ip','$em_C->code','$nu','$em_C->subj')";
	if ($sqlconn->query($query)) return array('code'=>0,'message'=>'New entry in Log database table');
	else return array('code'=>$sqlconn->errno,'message'=>$sqlconn->error);
}

12.9. PHP functions: e-mail.php

12.9.1. Source code

<?php
include_once($_SERVER['DOCUMENT_ROOT'].'/login/loginFunctions.php');
include_once($_SERVER['DOCUMENT_ROOT'].'/login/remoteaddress.php');
require_once($_SERVER['DOCUMENT_ROOT'].'/php/mailer/PHPMailerAutoload.php');
require_once($_SERVER['DOCUMENT_ROOT'].'/php/mysql/encryption_decryption.php');

class MyPHPMailer extends PHPMailer{
   public $obj_stat=0;
   public $sql_stat;
   public $sql_msg_arr;
// If Child constructor/destructor is defined--> Parent constructor/destructor must be called explicitly (https://www.tutorialspoint.com/how-to-call-parent-constructor-in-child-class-in-php)
   public function __construct($sql_stat,$sql_msg_arr) 
   {
      if ($sql_stat==0) parent::__construct();
      $this->sql_stat=$sql_stat;
      $this->sql_msg_arr=$sql_msg_arr;
   }
}

// CreateEmailContainer_Begin
function CreateEmailContainer($user,$SqlConnObj,$ip=NULL){
// Input argument 1: $user not yet used
// Input argument 2: optional. If the caller does not know the IP address, then the second argument is not used. The IP address must be determined in this function.
// Output argument 1: email container object or NULL,
// Output argument 2: message object, or NULL.
// Called in login.min.php, loginFunctions.php, iminfo.php, media-update-progress.php
// At the first call $userData=NULL. --> A MYSQLI object is tried to be created. 
// If succesful static $userData is filled with e-mail server data. Next time $userData is not NULL 
// If not succesful $userData remains NULL
	if ($ip==NULL){$kk=new RemoteAddress;$ip=$kk->getIpAddress();}
	STATIC $userData=NULL;

	if ($userData==NULL){
		$hostname=HOSTNAME_ISP;
		if (!$SqlConnObj) {
         $SqlConnObj=connect_2_mysqli_server(MYSQL_SERVER);
//			if (!$conn)	return array(NULL,$SQL_msg_arr);
         if ($SqlConnObj->status!=0){
            // $SqlConnObj->status != 0 --> Parent constructor MyPHPMailer (i.e. PHPMailer) not called.
            $mail=new MyPHPMailer($SqlConnObj->status,$SqlConnObj->msg_arr);
            return $mail;
         }
		}
      $conn=$SqlConnObj->conn;
      $result=$conn->query("SELECT id,username, salt FROM members WHERE username = 'webserver';");
      if($result->num_rows==0){
         $d['CreateEmail']=array('code'=>E_MAIL_CONT_WEBSERVER_NF,'message'=>'USERNAME webserver IN MEMBERS TABLE NOT FOUND.');
         $userData=NULL;
         $result->free();
      } else {
         $userData=$result->fetch_array(MYSQLI_ASSOC);
         $key=$userData['salt'];// Key for decrypting
         $result->free();
         if ((($conn->query("SHOW TABLES LIKE 'webserver'"))->num_rows)>0){//webserver table exists
            $query="SELECT id,hostname,hostadmin,hostadmin_password,hostadmin_email,hostadmin_alias,iv,SMTPSecure,port,contact_email,contact_alias
                    FROM webserver WHERE hostname = '$hostname';";
            $result=$conn->query($query);
            if($result->num_rows==0){
               $d['CreateEmail']=array('code'=>E_ISP_HOSTNAME_NF,'message'=>'ISP '.HOSTNAME_ISP.' NOT FOUND');
               $userData=NULL;
            } else {
               $userData=$result->fetch_array(MYSQLI_ASSOC);
               $iv=$userData['iv'];
               $userData['hostadmin_password']=my_simple_decrypt($userData['hostadmin_password'],$key,$iv);
               $userData['sql_stat']=$SqlConnObj->status;
               $userData['sql_msg_arr']=$SqlConnObj->msg_arr;
            }
            $result->free();
         } else {
            $d['CreateEmail']=array('code'=>E_WEBSERVER_TABLE_NF,'message'=>'webserver TABLE NOT KNOWN.');
            $userData=NULL;
         }
      }
	}
   try {
      if ($userData!= NULL){// --> $SqlConnObj was properly configured.
         $mail=new MyPHPMailer($userData['sql_stat'],$userData['sql_msg_arr']); // Use of $userData if function was called FALSE second argument
         $mail->isSMTP();
// HTTPS://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting: PHP 5.6 certificate verification failure
// PHP 5.6 verifies certificates on SSL connections
// BEGIN: Serverdata retrieved from database
         $mail->Host=$userData['hostname'];
   	  	$mail->Username=$userData['hostadmin'];
   	  	$mail->Password=$userData['hostadmin_password'];
   	  	$mail->SMTPSecure=$userData['SMTPSecure'];
   	  	$mail->Port=$userData['port'];
// END: Serverdata retrieved from database
   		$mail->SMTPOptions = array('ssl'=>array('verify_peer'=>false,'verify_peer_name'=>false,'allow_self_signed'=>true));
   		$mail->setFrom($userData['hostadmin_email'],$userData['hostadmin_alias']);
   		$mail->addAddress($userData['contact_email'],$userData['contact_alias']);
   		$mail->Subject=$_SERVER['SERVER_NAME'].' (IP='.$ip.'): ';
   		$mail->SMTPAuth=true;
   		$mail->isHTML(true);
         $mail->obj_stat=1;
//		return array($mail,NULL);
         return $mail;
      }
      else {
         $mail = new stdClass;
         $mail->obj_stat = -1;
         $mail->sql_stat = $SqlConnObj->status;
         $mail->sql_msg_arr = array_merge($d,$SqlConnObj->msg_arr);
         return $mail;
      }
   }
   catch (phpmailerException $e){
      $mail = new stdClass;
      $mail->obj_stat = -1;
      $mail->sql_stat = $SqlConnObj->status;
      $mail->sql_msg_arr = array_merge($d,$SqlConnObj->msg_arr,$e);
      return $mail;
   }
}
// CreateEmailContainer_End

12.9.2. Function CreateEmailContainer()

CreateEmailContainer($user, $SqlConnObj, $ip=NULL)
Parameters:
  • $user (String) –
  • $SqlConnObj (Object) –
  • $ip (String) –
Return Object $mail:
 

Either MyPHPMailer or stdClass object.

12.9.2.1. Source code

<?php
function CreateEmailContainer($user,$SqlConnObj,$ip=NULL){
// Input argument 1: $user not yet used
// Input argument 2: optional. If the caller does not know the IP address, then the second argument is not used. The IP address must be determined in this function.
// Output argument 1: email container object or NULL,
// Output argument 2: message object, or NULL.
// Called in login.min.php, loginFunctions.php, iminfo.php, media-update-progress.php
// At the first call $userData=NULL. --> A MYSQLI object is tried to be created. 
// If succesful static $userData is filled with e-mail server data. Next time $userData is not NULL 
// If not succesful $userData remains NULL
	if ($ip==NULL){$kk=new RemoteAddress;$ip=$kk->getIpAddress();}
	STATIC $userData=NULL;

	if ($userData==NULL){
		$hostname=HOSTNAME_ISP;
		if (!$SqlConnObj) {
         $SqlConnObj=connect_2_mysqli_server(MYSQL_SERVER);
//			if (!$conn)	return array(NULL,$SQL_msg_arr);
         if ($SqlConnObj->status!=0){
            // $SqlConnObj->status != 0 --> Parent constructor MyPHPMailer (i.e. PHPMailer) not called.
            $mail=new MyPHPMailer($SqlConnObj->status,$SqlConnObj->msg_arr);
            return $mail;
         }
		}
      $conn=$SqlConnObj->conn;
      $result=$conn->query("SELECT id,username, salt FROM members WHERE username = 'webserver';");
      if($result->num_rows==0){
         $d['CreateEmail']=array('code'=>E_MAIL_CONT_WEBSERVER_NF,'message'=>'USERNAME webserver IN MEMBERS TABLE NOT FOUND.');
         $userData=NULL;
         $result->free();
      } else {
         $userData=$result->fetch_array(MYSQLI_ASSOC);
         $key=$userData['salt'];// Key for decrypting
         $result->free();
         if ((($conn->query("SHOW TABLES LIKE 'webserver'"))->num_rows)>0){//webserver table exists
            $query="SELECT id,hostname,hostadmin,hostadmin_password,hostadmin_email,hostadmin_alias,iv,SMTPSecure,port,contact_email,contact_alias
                    FROM webserver WHERE hostname = '$hostname';";
            $result=$conn->query($query);
            if($result->num_rows==0){
               $d['CreateEmail']=array('code'=>E_ISP_HOSTNAME_NF,'message'=>'ISP '.HOSTNAME_ISP.' NOT FOUND');
               $userData=NULL;
            } else {
               $userData=$result->fetch_array(MYSQLI_ASSOC);
               $iv=$userData['iv'];
               $userData['hostadmin_password']=my_simple_decrypt($userData['hostadmin_password'],$key,$iv);
               $userData['sql_stat']=$SqlConnObj->status;
               $userData['sql_msg_arr']=$SqlConnObj->msg_arr;
            }
            $result->free();
         } else {
            $d['CreateEmail']=array('code'=>E_WEBSERVER_TABLE_NF,'message'=>'webserver TABLE NOT KNOWN.');
            $userData=NULL;
         }
      }
	}
   try {
      if ($userData!= NULL){// --> $SqlConnObj was properly configured.
         $mail=new MyPHPMailer($userData['sql_stat'],$userData['sql_msg_arr']); // Use of $userData if function was called FALSE second argument
         $mail->isSMTP();
// HTTPS://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting: PHP 5.6 certificate verification failure
// PHP 5.6 verifies certificates on SSL connections
// BEGIN: Serverdata retrieved from database
         $mail->Host=$userData['hostname'];
   	  	$mail->Username=$userData['hostadmin'];
   	  	$mail->Password=$userData['hostadmin_password'];
   	  	$mail->SMTPSecure=$userData['SMTPSecure'];
   	  	$mail->Port=$userData['port'];
// END: Serverdata retrieved from database
   		$mail->SMTPOptions = array('ssl'=>array('verify_peer'=>false,'verify_peer_name'=>false,'allow_self_signed'=>true));
   		$mail->setFrom($userData['hostadmin_email'],$userData['hostadmin_alias']);
   		$mail->addAddress($userData['contact_email'],$userData['contact_alias']);
   		$mail->Subject=$_SERVER['SERVER_NAME'].' (IP='.$ip.'): ';
   		$mail->SMTPAuth=true;
   		$mail->isHTML(true);
         $mail->obj_stat=1;
//		return array($mail,NULL);
         return $mail;
      }
      else {
         $mail = new stdClass;
         $mail->obj_stat = -1;
         $mail->sql_stat = $SqlConnObj->status;
         $mail->sql_msg_arr = array_merge($d,$SqlConnObj->msg_arr);
         return $mail;
      }
   }
   catch (phpmailerException $e){
      $mail = new stdClass;
      $mail->obj_stat = -1;
      $mail->sql_stat = $SqlConnObj->status;
      $mail->sql_msg_arr = array_merge($d,$SqlConnObj->msg_arr,$e);
      return $mail;
   }
}

12.10. Action/status codes

Action/status codes are represented by a 4 hexadecimal digit number: 0Xabcde, where a, b, c, and d represent a hexadecimal digit (0 🡺 F). Each hexadecimal digit consists of 4 bits

  1. Hexadecimal bit 1 (e): Resize and video thumbnail processing status in public and private directories:
    1. First 2 bits describe the status of the media file counts in the location and public/private directories (0x00000 🡺 0x00003). The third bit represent the date stamp status of the location directory. If the time stamp of the location directory is more recent (i.e. larger) than the timestamp of any of the iminfo.xml files in the public directories, then this bit is set (🡺 LOCATION_DIR_HAS_CHANGED = 0x00004).
    2. The fourth bit represent the date stamp status of the public directory (“Resized”). If the time stamp of any of the public directory is more recent (i.e. larger) than the timestamp of it corresponding iminfo.xml files in the public directories, then this bit is set (🡺 PUBLIC_DIR_HAS_CHANGED = 0x00008). The value of the first hexadecimal byte is the binary or operation of the 4 bits.
  2. Hexadecimal bit 2 (d): status of file fproc.txt (there is only 1 per album). Only one bit is used.
  3. Hexadecimal bit 3 (c): status of file rproc.txt (there is only 1 per album), or update method if the one of the numbers of media in rproc.txt (see Table 5.5) is smaller than the corresponding numbers in iminfo.xml.
  4. Hexadecimal bit 4 (b): action status as dictated by IMINFO. Since each location directory has its iminfo.xml file a global action status is derived from all IMINFO files: all action status of each IMINFO file are bitwise or-ed.
  5. Hexadecimal bit 5 (a):

The first output argument of the function rf_proc_stat($rstat,$fstat,$resize_stat) returns the status of first 3 hexadecimal bits (d, c, and b).

12.11. Session variables

12.11.1. XAMPP test environment

With the script phpinfo() the location of the $_SESSION variable can be determined. The phpinfo() script is invoked by calling the script file phpinfo.php in the document root directory (C:DanyPrivateWWWDreamweaverBenoy-2).

In the current XAMPP environment this location is C:xampptmp (directive session.save_path).

12.11.2. Session id

A Session ID is an identification number that is generated on the server side to assign user requests to a session. This session ID is stored locally with the user and transferred in the form of cookies or as a URI attribute (Uniform Resource Identifier). More information can be found in the following link . Each webpage of the site (both public and private) calls the function sec_session_start() so that the session id will be different each time a different webpage of the site is visited.

12.11.3. Session file

  • A session is started when the function sec_session_start() is called. An empty session file on the webserver is then created with name e.g. sess_4d1pn96h7kb0tmeumqm9mh8c6g, where the strange string is nothing but the session id. The name of the empty session file will change each time a different page visited.

  • When logging in, a session is started, and session variables are defined (see file login/login.php and login/login.min.php). The following session variables are defined:

    • $_SESSION[‘sess_id’]: this session id is linked to a registered user, and is different from the session id used to create the session file. When a registered user changes to a different webpage of the site, the user linked session id does not change but the session file changes name while its content does not change. Data is transferred (by AJAX / JSON object) to client side and stored in window.sessionStorage

    • $_SESSION[‘sess_user_id’]: info from MYSQL database,

    • $_SESSION[‘sess_username’]: info from MYSQL database,

    • $_SESSION[‘sess_group’]: info from MYSQL database. Group to which the user belongs (see Section 1.7.5.4)

    • $_SESSION[‘sess_user_permission’]: possible values are:

      • ADMIN_PERMISSION_LEVEL (binary 11111 = 31),

      • FAMILY_PERMISSION_LEVEL (binary 01000 = 8),

      • REG_USER_PERMISSION_LEVEL (binary 00100 = 4),

      • GUEST_PERMISSION_LEVEL (binary 00010 = 2),

      • VISITOR_PERMISSION_LEVEL (binary 00001 = 1),

        Values can be combined: e.g. FAMILY_PERMISSION_LEVEL + REG_USER_PERMISSION_LEVEL means that a registered user has also permission to modify an album in the family pages of the site.

    • $_SESSION[‘loggedin_time’].

    The value assignment to the session variables is implemented in login.min.php. These session variables are stored in this session file. In the XAMPP test environment the location of the session file is in the xampp\tmp directory. On other webservers the location of session files can be retrieved with the phpinfo.php scriptfile.

    The value of the session variables $_SESSION[‘sess_id’], $_SESSION[‘sess_user_id’], $_SESSION[‘sess_username’] and $_SESSION[‘sess_group’] can be viewed when logged on as admin user: button ACCOUNT 🡺 ADMIN TOOLS 🡺 SESSION INFO.

  • When logging off, all session variables are cleared, and the session file deleted. The system knows which session to delete (it keeps track of session id, even after a call to session_regenerate_id()).

  • The public file template has a PHP header part in which a call to sec_session_start() takes place. When the public file has a PHP extension, then the PHP header is executed. If the user is not logged on, an empty session file will be created.

    • Can the creation of an empty session file be avoided? Not if each web page calls sec_session_start().
    • Or can the empty session file be deleted when the webpage or browser is closed?
  • When creating an album directory overview the existence of the session variable $_SESSION[“show_infowindow”] is checked. If it is not defined, then the process dialog window is shown when needed (if admin user is logged on and when an album update is needed). If the session variable is defined the process dialog window is not shown (e.g. because of page reload, page back from child, …). The session variable $_SESSION[“show_infowindow”] is not needed anymore.