#!/usr/bin/php
<?php
//version 20200118
if (isset($argv[1])) $TPFpath = $argv[1];
else
	$TPFpath = getenv("HOME")."/.local/share/Steam/steamapps/common/Transport Fever 2/";  //set TPF default path here
if (isset($argv[2])) $WSpath = $argv[2];
else
	$WSpath = getenv("HOME")."/.local/share/Steam/steamapps/workshop/content/1066780/";  //set TPF default path here


$wd = pathinfo($_SERVER["SCRIPT_FILENAME"], PATHINFO_DIRNAME);




if(empty($TPFpath) || !is_dir($TPFpath) || !is_dir($TPFpath."/mods")){
	fwrite(STDERR,"Path to TPF installation not given or wrong.".PHP_EOL);
	fwrite(STDERR,"You can pass it as only argument or".PHP_EOL);
	fwrite(STDERR,"or set it in the script file ".$_SERVER["SCRIPT_FILENAME"].PHP_EOL);
	die(1);
}

$returnCode = 1;

$cmds = array("tar"=>"","unzip"=>"","ls"=>"","mv"=>"","mktemp"=>"","unrar"=>"","mkdir"=>"","find"=>"","7z"=>"","rm"=>"","cp"=>"","rsync"=>"","wc"=>"","tr"=>"","grep"=>"","cut"=>"");

foreach($cmds as $cmd=>&$where){
	$where = trim(exec("which ".$cmd,$rettext,$returnCode));
	if ($returnCode !== 0) {
		fwrite(STDERR,"could not find '".$cmd."'".PHP_EOL);
		die(1);
	}
}

$dirs = array(	"installfiles" => $wd."/2install",
				"installtmp" => $wd."/installing",
				"backup" => $wd."/backup",
				"installed" => $wd."/installed",
				"tpfmods" => $TPFpath."/mods",
			);
			
foreach ($dirs as $testdir){
	if (!is_dir($testdir)){
		fwrite(STDERR,"directory ".$testdir." doesn't exist, please create".PHP_EOL);
		die(1);
	}
}

$logfile = $wd."/installer.log";

//phpinfo();
$d = dir($dirs["installfiles"]);
while (false !== ($entry = $d->read())) {
	if ($entry === "." | $entry === "..") continue;
	$extension = strtolower(substr(strrchr($entry,'.'),1));
	$dextension = strrpos($entry,'tar',-7);
	echo "Processing: ".$entry.PHP_EOL;
	$rettext = array();
	exec($cmds["mktemp"]." -dp ".$dirs["installtmp"],$rettext,$returnCode);
	if ($returnCode !== 0 || count($rettext) !== 1) {
		fwrite(STDERR,"FATAL: failed to create temporary dir, mktemp returned ".$returnCode.PHP_EOL);
		die(1);
	}
	$tmpfolder = $rettext[0];
	echo "Start extraction".PHP_EOL;
	if ($extension === "zip"){
		system($cmds["unzip"]." -od ".escapeshellarg($tmpfolder)." ".escapeshellarg($dirs["installfiles"]."/".$entry)." >> ".escapeshellarg($logfile),$returnCode);
		if ($returnCode !== 0){
			$allsuccess = FALSE;
			fwrite(STDERR,"Failure installing ".$entry.":".PHP_EOL);
			fwrite(STDERR,$cmds["unzip"]." returned ".$returnCode.PHP_EOL);
			continue;
		}
	}elseif($extension === "rar"){
		system($cmds["unrar"]." x ".escapeshellarg($dirs["installfiles"]."/".$entry)." ".escapeshellarg($tmpfolder)." >> ".escapeshellarg($logfile),$returnCode);
		if ($returnCode !== 0){
			$allsuccess = FALSE;
			fwrite(STDERR,"Failure installing ".$entry.":".PHP_EOL);
			fwrite(STDERR,$cmds["unzip"]." returned ".$returnCode.PHP_EOL);
			continue;
		}
	}elseif($extension === "7z"){
		system($cmds["7z"]." x -o".escapeshellarg($tmpfolder)." ".escapeshellarg($dirs["installfiles"]."/".$entry)." >> ".escapeshellarg($logfile) ,$returnCode);
		if ($returnCode !== 0){
			$allsuccess = FALSE;
			fwrite(STDERR,"Failure installing ".$entry.":".PHP_EOL);
			fwrite(STDERR,$cmds["unzip"]." returned ".$returnCode.PHP_EOL);
			continue;
		}
	}elseif($extension === "bz2" && $dextension !== false && strlen($entry)-$dextension = 7){
		system($cmds["tar"]." -C ".escapeshellarg($tmpfolder)." -xvjf ".escapeshellarg($dirs["installfiles"]."/".$entry)." >> ".escapeshellarg($logfile) ,$returnCode);
		if ($returnCode !== 0){
			$allsuccess = FALSE;
			fwrite(STDERR,"Failure installing ".$entry.":".PHP_EOL);
			fwrite(STDERR,$cmds["tar"]." returned ".$returnCode.PHP_EOL);
			continue;
		}
	}elseif($extension === "gz" && $dextension !== false && strlen($entry)-$dextension = 6){
		system($cmds["tar"]." -C ".escapeshellarg($tmpfolder)." -xvzf ".escapeshellarg($dirs["installfiles"]."/".$entry)." >> ".escapeshellarg($logfile) ,$returnCode);
		if ($returnCode !== 0){
			$allsuccess = FALSE;
			fwrite(STDERR,"Failure installing ".$entry.":".PHP_EOL);
			fwrite(STDERR,$cmds["tar"]." returned ".$returnCode.PHP_EOL);
			continue;
		}
	}else{
		fwrite(STDERR,"don't know how to handle ".$entry.PHP_EOL);
		continue;
	}
	echo "Extraction finished".PHP_EOL;
	
	$subdirs = array();
	exec($cmds["ls"]." -1 ".escapeshellarg($tmpfolder), $subdirs,$returnCode);
	if ($returnCode !== 0) {
		fwrite(STDERR,"FATAL: ".$cmds["ls"]." failed with ".$returnCode.PHP_EOL);
		die(1);
	}
	if (count($subdirs) === 0){
		fwrite(STDERR,"FATAL: directory ".$tmpfolder." empty".PHP_EOL);
		die(1);
	}elseif(count($subdirs) > 1 && is_file($tmpfolder."/mod.lua")){
		$path_parts = pathinfo($_SERVER["SCRIPT_FILENAME"]);
		$modName = pathinfo($entry, PATHINFO_FILENAME);
		exec($cmds["mkdir"]." ".escapeshellcmd($tmpfolder."/".$modName)."/", $rettext,$returnCode);
		if ($returnCode !== 0) {
			fwrite(STDERR,"FATAL: ".$cmds["mkdir"]." failed creating new subfolder with ".$returnCode.PHP_EOL);
			die(1);
		}
		//echo $cmds["mv"]." ".escapeshellcmd($tmpfolder)."/!(".escapeshellcmd($modName).") ".escapeshellarg($tmpfolder."/".$modName);
		//system($cmds["mv"]." ".escapeshellcmd($tmpfolder)."/!(".escapeshellcmd($modName).") ".escapeshellarg($tmpfolder."/".$modName), $returnCode);
		//echo $cmds["find"]." ".escapeshellarg($tmpfolder)." -maxdepth 0 -! -name ".escapeshellarg($modName)." -exec ".$cmds["mv"]." -rv {} ".escapeshellarg($tmpfolder."/".$modName."/")." \\;";
		exec($cmds["find"]." ".escapeshellarg($tmpfolder)." -mindepth 1 -maxdepth 1 -! -name ".escapeshellarg($modName)." -exec ".$cmds["mv"]." -v {} ".escapeshellarg($tmpfolder."/".$modName."/")." \\;." >> ".escapeshellarg($logfile)");
		if ($returnCode !== 0) {
			fwrite(STDERR,"FATAL: ".$cmds["mv"]." failed moving files into new subfolder with ".$returnCode.PHP_EOL);
			die(1);
		}
	}elseif(count($subdirs) === 1){
		$modName = trim($subdirs[0]);
	}else{
		fwrite(STDERR,"FATAL: arbitrary files in directory ".$tmpfolder.PHP_EOL);
		die(1);
	}
	echo "Mod folder structure created for ".$modName.PHP_EOL;
	
	$installdirTMP = $tmpfolder."/".$modName;
	$success = doInstall($modName,$installdirTMP,FALSE);
	system($cmds["mv"]." -v --backup ".$dirs["installfiles"]."/".escapeshellarg($entry)." ".escapeshellarg($dirs["installed"]."/")." | tee -a ".escapeshellarg($logfile),$returnCode);
	if($success) echo $entry." / ".$modName." successfully installed".PHP_EOL;
	else echo "Install didn't succeed?".PHP_EOL;
	echo "###".PHP_EOL;
	
//	sleep(5);
}
echo "cleaning up installingfolder".PHP_EOL;
echo "---".PHP_EOL;


if(empty($WSpath) || !is_dir($WSpath)){
	fwrite(STDERR,"Path to Workshop not given or wrong.".PHP_EOL);
	fwrite(STDERR,"You can pass it as 2nd argument or".PHP_EOL);
	fwrite(STDERR,"set it in the script file ".$_SERVER["SCRIPT_FILENAME"].PHP_EOL);
	die(1);
}


//get modified workshop-folders
echo "looking for changed workshop files/folders".PHP_EOL;


$cmd = $cmds["find"]." ".escapeshellarg($WSpath)." -maxdepth 1 -mindepth 1 -type d -execdir sh -c '".$cmds["rsync"]." -ratbHAXun --info=NAME --exclude settings.lua {}/ ".str_replace("'","\"",escapeshellarg($dirs["tpfmods"]))."/{}_1 | ".$cmds["wc"]." -l | tr \"\\n\" \" \"; echo {}' \\; | ".$cmds["grep"]." -E '^[^0]' | cut -d \" \" -f 2";

//die($cmd);
$rettext = array();
exec($cmd, $rettext,$returnCode);

foreach($rettext as $folder){
	$wsid = (int) basename($folder);
	echo "Workshop mod updated: ".$wsid.PHP_EOL;
	echo "Workshop title: ".getworkshoptitle($wsid).PHP_EOL;
	if(doInstall($wsid."_1",$WSpath."/".$folder,TRUE)) echo $wsid." successfully installed".PHP_EOL;
	else echo "Install didn't succeed?".PHP_EOL;
	echo "###".PHP_EOL;
}


system($cmds["rm"]." -rf ".escapeshellarg($dirs["installtmp"])."/*",$returnCode);
if ($returnCode !== 0) {
		fwrite(STDERR,$cmds["rm"]." failed during clean up".PHP_EOL);
		die(1);
}


function doInstall($modName,$installdirTMP,$keepsource=TRUE){
	global $cmds,$dirs,$logfile;

	
	$installdirTarget = $dirs["tpfmods"]."/".$modName;
	if (!is_dir($installdirTMP)){
		fwrite(STDERR,"FATAL: this should never happen Script ".$installdirTMP." line: ".__LINE__.PHP_EOL);
		die(1);
	}
	$tempconf = FALSE;
	$tempmodluabak = FALSE;
	$tempconfiglua = FALSE;
	if (is_dir($installdirTarget)){
		$backupfilename = "/";
		$count = 0;
		echo "Creating backup of old Version of ".$modName.PHP_EOL;
		while (file_exists($backupfilename)){
			$backupfilename = $dirs["backup"]."/backup-".$modName."-".date("Ymd").($count++ ?: "").".tar.gz";
		}
		$rettext = array();
		$cmd = $cmds["tar"]." -C ".escapeshellarg($dirs["tpfmods"])." -cvzf ".escapeshellarg($backupfilename)." ".escapeshellarg($installdirTarget."/")." >> ".escapeshellarg($logfile);
		system($cmd,$returnCode);
		
		if ($returnCode !== 0){
			fwrite(STDERR,"FATAL: ".$cmds["tar"]." failed with ".$returnCode.PHP_EOL);
			die();
		}
		
		echo "Successfully made a backup: ".$backupfilename.PHP_EOL;
		if(is_file($installdirTarget."/settings.lua")) {
			$tempconf = file_get_contents($installdirTarget."/settings.lua");
			echo "old settings.lua found and cached".PHP_EOL;
		}
		if(is_file($installdirTarget."/mod.lua.bak")) {
			$tempmodluabak = file_get_contents($installdirTarget."/mod.lua.bak");
			echo "old mod.lua.bak found and cached".PHP_EOL;
		}
		if(is_file($installdirTarget."/config/config.lua")) {
			$tempconfiglua = file_get_contents($installdirTarget."/config/config.lua");
			echo "old config/config.lua found and cached".PHP_EOL;
		}
		system($cmds["rm"]." -rvf ".escapeshellarg($installdirTarget)." >> ".escapeshellarg($logfile),$returnCode);
		if ($returnCode !== 0){
			fwrite(STDERR,"FATAL: failed to delete ".$installdirTarget.PHP_EOL);
			die(1);	
		}
	}
	echo "copying new mod from ".$installdirTMP." to ".$installdirTarget.PHP_EOL;
	if ($keepsource === FALSE) {
		system($cmds["mv"]." -v ".escapeshellarg($installdirTMP)." ".escapeshellarg($installdirTarget)." >> ".escapeshellarg($logfile),$returnCode);
		if ($returnCode !== 0) {
			fwrite(STDERR,"FATAL: ".$cmds["mv"]." failed with ".$returnCode.PHP_EOL);
			die(1);
		}
	}else{
		system($cmds["cp"]." -rav ".escapeshellarg($installdirTMP)." ".escapeshellarg($installdirTarget)." >> ".escapeshellarg($logfile),$returnCode);
		if ($returnCode !== 0) {
			fwrite(STDERR,"FATAL: ".$cmds["cp"]." failed with ".$returnCode.PHP_EOL);
			die(1);
		}
	}
	
	if ($tempconf !== FALSE){
		if (is_file($installdirTarget."/settings.lua")) {
			system($cmds["cp"]." -av ".escapeshellarg($installdirTarget."/settings.lua")." ".escapeshellarg($installdirTarget."/settings.lua.new")." >> ".escapeshellarg($logfile),$returnCode);
			if ($returnCode !== 0) {
				fwrite(STDERR,$cmds["cp"]." failed with ".$returnCode." while copying new settings.lua to settings.lua.new".PHP_EOL);
			}
		}
		file_put_contents($installdirTarget."/settings.lua",$tempconf);
		echo "Copied old config and created new/unused settings.lua as settings.lua.new".PHP_EOL;
		unset($tempconf);
	}
	if ($tempmodluabak !== FALSE){
		file_put_contents($installdirTarget."/mod.lua.bak",$tempmodluabak);
		echo "old mod.lua.bak restored".PHP_EOL;
		unset($tempmodluabak);
	}
	if ($tempconfiglua !== FALSE){
		if (is_file($installdirTarget."/config/config.lua")) {
			system($cmds["cp"]." -av ".escapeshellarg($installdirTarget."/config/config.lua")." ".escapeshellarg($installdirTarget."/config/config.lua.new")." >> ".escapeshellarg($logfile),$returnCode);
			if ($returnCode !== 0) {
				fwrite(STDERR,$cmds["cp"]." failed with ".$returnCode." while copying new config/config.lua to config/config.lua.new".PHP_EOL);
			}
		}
		file_put_contents($installdirTarget."config/config.lua",$tempconfiglua);
		echo "Copied old config and created new/unused cconfig/config.lua as config/config.lua.new".PHP_EOL;
		
		unset($tempconfiglua);
		
	}
	
	echo "###".PHP_EOL;
	return TRUE;
}


function getworkshoptitle($id){
	$url = 'https://steamcommunity.com/sharedfiles/filedetails/?id='.$id;
		 $fp = fopen($url, 'r', FALSE, // do not use_include_path
	    stream_context_create([
	    'http' => [
	      'header'  => [ // header array does not need '\r\n'
//	        'Content-type: application/x-www-form-urlencoded',
//	        'Content-Length: ' . strlen($query_content),
		'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0',
		'Upgrade-Insecure-Requests: 1'
	      ],
	      'method'  => 'GET'
  //    	'content' => $query_content
	    ]
	  ]));
   if ($fp === FALSE) return "ERR1";
     $result = stream_get_contents($fp); // no maxlength/offset
     $explode = explode("<title>Steam Workshop :: ",$result,2);
     if (count($explode) !== 2) return "ERR2";
     $explode2 = explode("</title>",$explode[1],2);
     return $explode2[0];
}
