<?php
/*
    slbackup-php, an administration tool for slbackup
    Copyright (C) 2007 Finn-Arne Johansen <faj@bzz.no> BzzWare AS, Norway

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/


function checkkeysandversions ($passwd, $config) {
global $backuphost, $backupuser, $ssh_options, $ssh_askpass ;

    $out = array () ; 
    $desc[0] = array ("pipe", "r") ; 
    $desc[1] = array ("pipe", "w") ; 
    $desc[2] = array ("file", "/tmp/error.log", "a") ; 

    $env = array ('SSH_ASKPASS' => $ssh_askpass, 
		  'DISPLAY' => ':nowhere') ; 

    $cmd = sprintf ("ssh %s %s@%s 'rdiff-backup --version'",
   		     $ssh_options, $backupuser, 
		     $backuphost) ; 

    $proc = proc_open ($cmd, $desc, $pipes, '/tmp', $env) ; 
    if (is_resource ($proc)) {
	fprintf ($pipes[0], "%s\n", $passwd) ; 
	fclose ($pipes[0]) ; 
	while ($line = fgets ($pipes[1], 1024)) {
	    $out["version"] =  trim($line) ; 
	    }
	fclose ($pipes[1]) ; 
	proc_close ($proc) ; 
    }
    foreach ($config["clients"] as $key => $value) {
        if ($key["type"] <> "local") {
	    $out["clients"][$key]["ssh"] = "failed" ; 
	    $cmd = sprintf ("ssh %s %s@%s 'ssh %s echo ssh ok \; rdiff-backup --version'",
			     $ssh_options, $backupuser, 
			     $backuphost, $value["address"]) ; 

	    $proc = proc_open ($cmd, $desc, $pipes, '/tmp', $env) ; 
	    if (is_resource ($proc)) {
		fprintf ($pipes[0], "%s\n", $passwd) ; 
		fclose ($pipes[0]) ; 
		while ($line = fgets ($pipes[1], 1024)) {
		    list ($test, $result) = explode (" ", trim($line)) ; 
		    $out["clients"][$key][$test] = $result ; 
		    }
		fclose ($pipes[1]) ; 
		proc_close ($proc) ; 
	    }
	}

    }
    return ($out) ; 
}

function removesnapshots ($passwd, $clientdir, $snapshot) {
global $backuphost, $backupuser, $ssh_options, $ssh_askpass ;

    $cmd = sprintf ("ssh %s %s@%s 'rdiff-backup --force --remove-older-than %s \"%s\"'",
   		     $ssh_options, $backupuser, 
		     $backuphost, $snapshot, $clientdir) ; 

    $snapshots = array () ; 
    $desc[0] = array ("pipe", "r") ; 
    $desc[1] = array ("pipe", "w") ; 
    $desc[2] = array ("file", "/tmp/error.log", "a") ; 

    $env = array ('SSH_ASKPASS' => $ssh_askpass, 
		  'DISPLAY' => ':nowhere') ; 
    $proc = proc_open ($cmd, $desc, $pipes, '/tmp', $env) ; 
    if (is_resource ($proc)) {
	fprintf ($pipes[0], "%s\n", $passwd) ; 
	fclose ($pipes[0]) ; 
	while ($line = fgets ($pipes[1], 1024)) {
	    $snapshots[] = $line ; 
	    }
	fclose ($pipes[1]) ; 
	proc_close ($proc) ; 
    }
    return $snapshots ; 
}

function listsnapshots ($passwd, $clientdir) {
global $backuphost, $backupuser, $ssh_options, $ssh_askpass ;

    $cmd = sprintf ("ssh %s %s@%s 'find \"%s/rdiff-backup-data\" -maxdepth 1 -name \"increments.*\" -printf %s | sort '", 
   		     $ssh_options, $backupuser, 
		     $backuphost, $clientdir, '"%P\n"') ; 

    $snapshots = array () ; 
    $desc[0] = array ("pipe", "r") ; 
    $desc[1] = array ("pipe", "w") ; 
    $desc[2] = array ("file", "/tmp/error.log", "a") ; 

    $env = array ('SSH_ASKPASS' => $ssh_askpass, 
		  'DISPLAY' => ':nowhere') ; 
    $proc = proc_open ($cmd, $desc, $pipes, '/tmp', $env) ; 
    if (is_resource ($proc)) {
	fprintf ($pipes[0], "%s\n", $passwd) ; 
	fclose ($pipes[0]) ; 
	while ($line = fgets ($pipes[1], 1024)) {
	    $snapshots[] = substr ($line, 11, 25) ; 
	    }
	fclose ($pipes[1]) ; 
	proc_close ($proc) ; 
    }
    return $snapshots ; 
}


function fetchfile ($passwd, $clientdir, $location, $file) {
global $backuphost, $backupuser, $ssh_options, $ssh_askpass ;

    $cmd = sprintf ("ssh %s %s@%s 'cat \"%s%s/%s\"'",
   		     $ssh_options, $backupuser, 
		     $backuphost, $clientdir, $location, $file ) ; 

    $desc[0] = array ("pipe", "r") ; 
    $desc[1] = array ("pipe", "w") ; 
    $desc[2] = array ("file", "/tmp/error.log", "a") ; 

    $env = array ('SSH_ASKPASS' => $ssh_askpass, 
		  'DISPLAY' => ':nowhere') ; 
    $proc = proc_open ($cmd, $desc, $pipes, '/tmp', $env) ; 
    if (is_resource ($proc)) {
	fprintf ($pipes[0], "%s\n", $passwd) ; 
	fclose ($pipes[0]) ; 
	$out = stream_get_contents($pipes[1]) ; 
	fclose ($pipes[1]) ; 
	proc_close ($proc) ; 
    } else unset ($out) ; 
    return $out ; 
}
function fetchsnapshot ($passwd, $clientdir, $location, $file) {
global $backuphost, $backupuser, $ssh_options, $ssh_askpass ;

    $desc[0] = array ("pipe", "r") ; 
    $desc[1] = array ("pipe", "w") ; 
    $desc[2] = array ("file", "/tmp/error.log", "a") ; 

    $env = array ('SSH_ASKPASS' => $ssh_askpass, 
		  'DISPLAY' => ':nowhere') ; 
    $cmd = sprintf ("ssh %s %s@%s 'mktemp'", 
   		     $ssh_options, $backupuser, 
		     $backuphost) ;

    $proc = proc_open ($cmd, $desc, $pipes, '/tmp', $env) ; 
    if (is_resource ($proc)) {
	fprintf ($pipes[0], "%s\n", $passwd) ; 
	fclose ($pipes[0]) ; 
	$tempfile = stream_get_contents($pipes[1]) ; 
	fclose ($pipes[1]) ; 
	proc_close ($proc) ; 
    } else unset ($tempfile) ; 
    if (empty($tempfile))
        return ; 
    $cmd = sprintf ("ssh %s %s@%s 'rdiff-backup --force \"%s/rdiff-backup-data/increments%s/%s %s\"'",
   		     $ssh_options, $backupuser, 
		     $backuphost, $clientdir, $location, $file, $tempfile ) ; 

    $proc = proc_open ($cmd, $desc, $pipes, '/tmp', $env) ; 
    if (is_resource ($proc)) {
	fprintf ($pipes[0], "%s\n", $passwd) ; 
	fclose ($pipes[0]) ; 
	fclose ($pipes[1]) ; 
	proc_close ($proc) ; 
    } 
    $cmd = sprintf ("ssh %s %s@%s 'cat \"%s\" && rm \"%s\"'",
   		     $ssh_options, $backupuser, 
		     $backuphost, $tempfile, $tempfile) ; 
    $proc = proc_open ($cmd, $desc, $pipes, '/tmp', $env) ; 
    if (is_resource ($proc)) {
	fprintf ($pipes[0], "%s\n", $passwd) ; 
	fclose ($pipes[0]) ; 
	$out = stream_get_contents($pipes[1]) ; 
	fclose ($pipes[1]) ; 
	proc_close ($proc) ; 
    } else unset ($out) ; 
    return $out ; 
}

function listfile ($passwd, $clientdir, $location, $file) {
global $backuphost, $backupuser, $ssh_options, $ssh_askpass ;

    $out = array() ; 
    $parent = dirname ($file) ;
    $base = basename ($file) ; 
    if (empty($file)) 
        return $out ; 
    if ($parent == ".") $parent="" ; 
    $out[] = array ('type' => 'parent', 
		    'name' => "Parent directory", 
		    'sub' => trim ($parent)) ; 

    $desc[0] = array ("pipe", "r") ; 
    $desc[1] = array ("pipe", "w") ; 
    $desc[2] = array ("file", "/tmp/error.log", "a") ; 

    $env = array ('SSH_ASKPASS' => $ssh_askpass, 
		  'DISPLAY' => ':nowhere') ; 
    $cmd = sprintf ("ssh %s %s@%s 'find \"%s%s/%s\" -maxdepth 1 -mindepth 1 -type f -name \"%s\"'",
   		     $ssh_options, $backupuser, 
		     $backuphost, $clientdir, $location, $parent, $base ) ; 
    $proc = proc_open ($cmd, $desc, $pipes, '/tmp', $env) ; 
    if (is_resource ($proc)) {
	fprintf ($pipes[0], "%s\n", $passwd) ; 
	fclose ($pipes[0]) ; 
	while ($line = fgets ($pipes[1], 1024)) {
	    $out[] = array ('type' => 'currentfile', 
	                    'name' => basename (trim($line)), 
	                    'sub' => substr (trim ($line), strlen ($clientdir) + strlen ($location) + 1)) ; 

	    }
	fclose ($pipes[1]) ; 
	proc_close ($proc) ; 
    }
    $baselen= strlen ($base) ; 
    $cmd = sprintf ("ssh %s %s@%s 'find \"%s/rdiff-backup-data/increments%s/%s\" -maxdepth 1 -mindepth 1 -type f -name \"%s*.gz\"'",
   		     $ssh_options, $backupuser, 
		     $backuphost, $clientdir, $location, $parent, $base ) ; 

    $proc = proc_open ($cmd, $desc, $pipes, '/tmp', $env) ; 
    if (is_resource ($proc)) {
	fprintf ($pipes[0], "%s\n", $passwd) ; 
	fclose ($pipes[0]) ; 
	while ($line = fgets ($pipes[1], 1024)) {
	    $gzbase = basename (trim($line)) ; 
	    $type = substr ($gzbase, $baselen + 27) ; 
	    $ts = substr($gzbase, $baselen + 1, 25) ;
	    $revision = $gzbase ; 
	    while (($pos = strpos ($revision, '+')) !== false)
	        $revision = substr ($revision, 0,$pos) . '%2B' . substr ($revision, $pos + 1 ) ;
	    switch ($type) {
	        case "snapshot.gz":
	        case "diff.gz":
	        default:
		    $out[] = array ('type' => $type, 
				    'ts' => $ts, 
				    'name' => $base, 
				    'revision' => $revision,
				    'parent' => sprintf ("%s/%s", $sub, $parent)) ; 
		    break ;
	    }
        }
	fclose ($pipes[1]) ; 
	proc_close ($proc) ; 
    }

    return $out ; 
}

function listloc ($passwd, $clientdir, $location, $sub = "") {
global $backuphost, $backupuser, $ssh_options, $ssh_askpass ;

    $loc = array() ; 
    $parent = dirname ($sub) ;
    if (!empty($sub)) {
        if ($parent == ".") $parent="" ; 
	    $loc[] = array ('type' => 'parent', 
	                    'name' => "Parent directory", 
	                    'sub' => trim ($parent)) ; 
    }


    $desc[0] = array ("pipe", "r") ; 
    $desc[1] = array ("pipe", "w") ; 
    $desc[2] = array ("file", "/tmp/error.log", "a") ; 

    $env = array ('SSH_ASKPASS' => $ssh_askpass, 
		  'DISPLAY' => ':nowhere') ; 
    $cmd = sprintf ("ssh %s %s@%s 'find \"%s%s/%s\" -maxdepth 1 -mindepth 1 -type d'",
   		     $ssh_options, $backupuser, 
		     $backuphost, $clientdir, $location, $sub ) ; 
    $proc = proc_open ($cmd, $desc, $pipes, '/tmp', $env) ; 
    if (is_resource ($proc)) {
	fprintf ($pipes[0], "%s\n", $passwd) ; 
	fclose ($pipes[0]) ; 
	while ($line = fgets ($pipes[1], 1024)) {
	    $loc[] = array ('type' => 'dir', 
	                    'name' => basename (trim($line)), 
	                    'sub' => substr (trim ($line), strlen ($clientdir) + strlen ($location) + 1)) ; 

	    }
	fclose ($pipes[1]) ; 
	proc_close ($proc) ; 
    }
    $cmd = sprintf ("ssh %s %s@%s 'find \"%s/rdiff-backup-data/increments%s/%s\" -maxdepth 1 -mindepth 1 -type d'",
   		     $ssh_options, $backupuser, 
		     $backuphost, $clientdir, $location, $sub ) ; 
    $proc = proc_open ($cmd, $desc, $pipes, '/tmp', $env) ; 
    if (is_resource ($proc)) {
	fprintf ($pipes[0], "%s\n", $passwd) ; 
	fclose ($pipes[0]) ; 
	while ($line = fgets ($pipes[1], 1024)) {
	    $found=false ; 
	    foreach ($loc as $key => $value)
		if ($value["type"] == "dir" and 
		    $value["name"] == basename(trim ($line)))
		    $found = true ; 

	    if (!$found)    
		$loc[] = array ('type' => 'deldir', 
				'name' => basename (trim($line)), 
				'sub' => substr (trim ($line), strlen ($clientdir) + strlen ($location) + 30)) ; 

	    }
	fclose ($pipes[1]) ; 
	proc_close ($proc) ; 
    }
    $cmd = sprintf ("ssh %s %s@%s 'find \"%s%s/%s\" -maxdepth 1 -mindepth 1 -type f'",
   		     $ssh_options, $backupuser, 
		     $backuphost, $clientdir, $location, $sub ) ; 

    $proc = proc_open ($cmd, $desc, $pipes, '/tmp', $env) ; 
    if (is_resource ($proc)) {
	fprintf ($pipes[0], "%s\n", $passwd) ; 
	fclose ($pipes[0]) ; 
	while ($line = fgets ($pipes[1], 1024)) {
	    $base = basename (trim($line)) ; 
	    $loc[] = array ('type' => 'file', 
	                    'name' => $base, 
	                    'sub' => sprintf ("%s/%s", $sub, $base)) ; 
        }
	fclose ($pipes[1]) ; 
	proc_close ($proc) ; 
    }
    $cmd = sprintf ("ssh %s %s@%s 'find \"%s/rdiff-backup-data/increments%s/%s\" -maxdepth 1 -mindepth 1 -type f -name \"*.snapshot.gz\"'",
   		     $ssh_options, $backupuser, 
		     $backuphost, $clientdir, $location, $sub ) ; 
    $proc = proc_open ($cmd, $desc, $pipes, '/tmp', $env) ; 
    if (is_resource ($proc)) {
	fprintf ($pipes[0], "%s\n", $passwd) ; 
	fclose ($pipes[0]) ; 
	while ($line = fgets ($pipes[1], 1024)) {
	    $found=false ; 
	    $base = basename (trim($line)) ; 
	    $base = substr($base, 0, strlen($base) - 38) ; 
	    foreach ($loc as $key => $value)
		if ($value["type"] == "file" and 
		    $value["name"] == $base)
		    $found = true ; 

	    if (!$found)    
		$loc[] = array ('type' => 'delfile', 
				'name' => $base, 
				'sub' => sprintf ("%s/%s", $sub, $base)) ; 
	    }
	fclose ($pipes[1]) ; 
	proc_close ($proc) ; 
    }

    return $loc ; 
}

function readcron ($passwd) {
global $backuphost, $backupuser, $backupcron, $ssh_options, $ssh_askpass ;

    $cron = array() ; 
    $cmd = sprintf ("ssh %s %s@%s cat %s", 
   		     $ssh_options, $backupuser, 
		     $backuphost, $backupcron) ; 

    $desc[0] = array ("pipe", "r") ; 
    $desc[1] = array ("pipe", "w") ; 
    $desc[2] = array ("file", "/tmp/error.log", "a") ; 

    $env = array ('SSH_ASKPASS' => $ssh_askpass, 
		  'DISPLAY' => ':nowhere') ; 
    $proc = proc_open ($cmd, $desc, $pipes, '/tmp', $env) ; 
    if (is_resource ($proc)) {
	fprintf ($pipes[0], "%s\n", $passwd) ; 
	fclose ($pipes[0]) ; 
	while ($line = fgets ($pipes[1], 1024))
	    $cron[] = trim ($line) ; 
	fclose ($pipes[1]) ; 
	proc_close ($proc) ; 
    }
    return $cron ; 
}

function writecron ($passwd, $cron) {
global $backuphost, $backupuser, $backupcron, $ssh_options, $ssh_askpass ;

    $cmd = sprintf ("ssh %s %s@%s 'cat > %s'", 
   		     $ssh_options, $backupuser, 
		     $backuphost, $backupcron) ; 

    $desc[0] = array ("pipe", "r") ; 
    $desc[1] = array ("pipe", "w") ; 
    $desc[2] = array ("file", "/tmp/error.log", "a") ; 

    $env = array ('SSH_ASKPASS' => $ssh_askpass, 
		  'DISPLAY' => ':nowhere') ; 

    // cat crontab file on remote backup server
    $proc = proc_open ($cmd, $desc, $pipes, '/tmp', $env) ; 
    if (is_resource ($proc)) {
	fprintf ($pipes[0], "%s\n", $passwd) ; 
	fprintf ($pipes[0], "%s", $cron) ; 
	fclose ($pipes[1]) ; 
	fclose ($pipes[0]) ; 
	proc_close ($proc) ; 
	}

    // chmod on the remote backup job file
    $cmd = sprintf ("ssh %s %s@%s 'chmod 0644 %s'",
		     $ssh_options, $backupuser,
		     $backuphost, $backupcron) ;
    $proc = proc_open ($cmd, $desc, $pipes, '/tmp', $env) ;
    if (is_resource ($proc)) {
	fprintf ($pipes[0], "%s\n", $passwd) ;
	fclose ($pipes[1]) ;
	fclose ($pipes[0]) ;
	proc_close ($proc) ;
	}

}


function writeconf ($passwd, $config) {
global $backuphost, $backupuser, $backupconf, $ssh_options, $ssh_askpass ;

    $out = sprintf ("<client>\n") ;
    foreach ($config["clients"] as $key => $value) {
	$out .= sprintf ("    <%s>\n", $key) ; 
	$out .= sprintf ("        address %s\n", $value["address"]) ; 
	$out .= sprintf ("        keep    %s\n", $value["keep"]) ; 
	foreach ($value["location"] as $loc)
	    $out .= sprintf ("        location %s\n", $loc) ; 
	$out .= sprintf ("        type    %s\n", $value["type"]) ; 
	$out .= sprintf ("        user    %s\n", $value["user"]) ; 
	$out .= sprintf ("    </%s>\n", $key) ; 
    }
    $out .= sprintf ("</client>\n") ;
    $out .= sprintf ("server_address %s\n", $config["server_address"]) ; 
    $out .= sprintf ("server_destdir %s\n", $config["server_destdir"]) ; 
    $out .= sprintf ("server_type    %s\n", $config["server_type"]) ; 
    $out .= sprintf ("server_user    %s\n", $config["server_user"]) ; 

    $cmd = sprintf ("ssh %s %s@%s 'cat > %s'", 
   		     $ssh_options, $backupuser, 
		     $backuphost, $backupconf) ; 

    $desc[0] = array ("pipe", "r") ; 
    $desc[1] = array ("pipe", "w") ; 
    $desc[2] = array ("file", "/tmp/error.log", "a") ; 

    $env = array ('SSH_ASKPASS' => $ssh_askpass, 
		  'DISPLAY' => ':nowhere') ; 
    $proc = proc_open ($cmd, $desc, $pipes, '/tmp', $env) ; 
    if (is_resource ($proc)) {
	fprintf ($pipes[0], "%s\n", $passwd) ; 
	fprintf ($pipes[0], "%s\n", $out) ; 
	fclose ($pipes[1]) ; 
	fclose ($pipes[0]) ; 
	proc_close ($proc) ; 
	}
}

function readconf ($passwd) {
global $backuphost, $backupuser, $backupconf, $ssh_options, $ssh_askpass ;

    $cmd = sprintf ("ssh %s %s@%s cat %s", 
   		     $ssh_options, $backupuser, 
		     $backuphost, $backupconf) ; 

    $desc[0] = array ("pipe", "r") ; 
    $desc[1] = array ("pipe", "w") ; 
    $desc[2] = array ("file", "/tmp/error.log", "a") ; 

    $env = array ('SSH_ASKPASS' => $ssh_askpass, 
		  'DISPLAY' => ':nowhere') ; 
    $proc = proc_open ($cmd, $desc, $pipes, '/tmp', $env) ; 
    if (is_resource ($proc)) {
	fprintf ($pipes[0], "%s\n", $passwd) ; 
	fclose ($pipes[0]) ; 
	while (fscanf ($pipes[1], "\t%s\t%s", $key, $value)) {
	    if (isset ($value)) {
		switch (strtolower($key)) {
		    case "address": 
		    case "keep": 
		    case "type": 
		    case "user": 
			$clientconf[$key] = $value ; 
			break ; 
		    case "location": 
			$clientconf[$key][] = $value ; 
			break ; 
		    case "server_address": 
		    case "server_destdir": 
		    case "server_type": 
		    case "server_user": 
			$config[$key] = $value ; 
			break ; 
		}
	    } else {
		switch ($key) {
		    case "<client>": 
			$readclient = true ; 
			break ; 
		    case "</client>": 
			$readclient = false ; 
			break ; 
		    default:
			if ($readclient && empty ($newclient)) {
			    $newclient = trim ($key, "<>") ; 
			    $clientconf = array () ; 
			    $clientconf["location"] = array () ; 
			} elseif ($readclient && $key == "</" . $newclient . ">") {
			    $config["clients"][$newclient] = $clientconf ; 
			    unset ($newclient) ; 
			    unset ($clientconf) ; 
			}
			break ; 
		}
	    }
	    unset ($value) ; 
	    unset ($key) ; 
	}
	fclose ($pipes[1]) ; 
	proc_close ($proc) ; 
    }
    return $config ; 
}

function readlog ($passwd, $log) {
global $backuphost, $backupuser, $logfile, $ssh_options, $ssh_askpass ;

    $cmd = sprintf ("ssh %s %s@%s cat %s", 
   		     $ssh_options, $backupuser, 
		     $backuphost, $logfile) ; 

    $desc[0] = array ("pipe", "r") ; 
    $desc[1] = array ("pipe", "w") ; 
    $desc[2] = array ("file", "/tmp/error.log", "a") ; 

    $env = array ('SSH_ASKPASS' => $ssh_askpass, 
		  'DISPLAY' => ':nowhere') ; 
    $proc = proc_open ($cmd, $desc, $pipes, '/tmp', $env) ; 
    if (is_resource ($proc)) {
	fprintf ($pipes[0], "%s\n", $passwd) ; 
	fclose ($pipes[0]) ; 
	while ($line = fgets ($pipes[1], 1024)) {
	    list ($timestamp, $info) = explode (" - ", trim($line)) ; 
	    if ($info == "Starting slbackup:") 
	        $log["start"] = strtotime($timestamp) ; 
	    elseif ($info == "Finished slbackup.")
	        $log["end"] = strtotime($timestamp) ; 
	    elseif (strpos ($line, "Starting backup of client ") !== false) {
	        sscanf ($info, "Starting backup of client %s", $client) ; 
	        if (!empty ($client))
	            $log["clients"][$client]["start"] = strtotime($timestamp) ; 
	    } elseif (strpos ($line, "Failed backing up client ") !== false) {
	        sscanf ($info, "Failed backing up client %s", $client) ; 
	        if (!empty ($client))
	            $log["clients"][$client]["failed"] = strtotime($timestamp) ; 
	    } elseif (strpos ($line, "Successfully finished backing up client ") !== false) {
	        sscanf ($info, "Successfully finished backing up client %s", $client) ; 
	        if (!empty ($client))
	            $log["clients"][$client]["ok"] = strtotime($timestamp) ; 
	    }
        }
	fclose ($pipes[1]) ; 
	proc_close ($proc) ; 
    }
    return $log ; 
}

require_once ('functions.php') ; 
loadConfig () ;
require('/usr/share/php/smarty3/Smarty.class.php') ; 
session_start() ;
loadLocale () ; 
ob_start ();

$smarty = new Smarty();
$smarty->template_dir = $smarty_templ ; 
$smarty->compile_dir = $smarty_compile ; 
unset ($_COOKIE['smarty_templ']);
unset ($_COOKIE['smarty_compile']);

# fetch script to use whith passing the ssh-password
$ssh_askpass = sprintf ("%s/script/mypass.sh", 
                        dirname (dirname ($_SERVER["SCRIPT_FILENAME"])));

$arguments = $_REQUEST;

# merge _COOKIE and _REQUEST
$allowed_cookie_keys = array('nonhttps', 'xorstring', 'PHPSESSID', 'locale',);
foreach ($_COOKIE as $key => $value) {
    if ((! array_key_exists($key, $arguments)) && (in_array($key, $allowed_cookie_keys))) {
	if (is_string($key) && is_string($value)) {
	    $arguments[$key] = $value;
	}
    }
}

# Fetch arguments passed as the script is executed
foreach ($arguments as $key => $value) {
    switch ($key) {
        case "smarty_templ": 
        case "smarty_compile": 
        case "locale": 
        case "PHPSESSID": 
            break ;
        case "nonhttps":
            $nonhttps = $value ;
            break ;
        case "Passwd": 
            $passwd = $value ; 
            $submit = "status" ; 
            break ; 
        case "xorstring": 
            if (empty($passwd))
		$xorstring = base64_decode($value) ; 
            else break ; 
            if (empty ($value))
                break ; 
            $encrypt = $_SESSION["encrypt"] ; 
            $passwd = xorstring ($encrypt, $xorstring) ; 
            break ; 
        case "status":
        case "config":
        case "addclient":
        case "server":
        case "chooseclient":
        case "delclient":
        case "clientconfig":
        case "delloc":
        case "addloc":
        case "scheduler":
        case "restore":
        case "restoreclient":
        case "restorelocation":
        case "restorefile":
        case "maint":
        case "removesnapshot":
        case "logout":
            $submit=$key ; 
            break ;
        case "selected":
            $selected=$value ; 
            break ;
        case "snapshot":
            $snapshot=$value ; 
            break ;
        case "client":
            $client=htmlspecialchars(trim($value)) ; 
            break ;
        case "revision":
            $revision=htmlspecialchars(trim($value)) ; 
            break ;
        default:
            $newconf[$key] = htmlspecialchars(trim($value)) ; 
            break ;
    }
}

unset ($arguments);

if ($submit == "logout") {
    unset ($passwd) ; 
    unset ($xorstring) ; 
    $_SESSION['encrypt'] = "" ; 
    setcookie ('xorstring', '') ; 
}

if (isset ($passwd))
    $config = readconf ($passwd) ;

if (empty ($config)) {
    if (empty ($_SERVER["HTTPS"])) {
	$smarty->assign ('nonhttps', $nonhttps) ; 
	if ($nonhttps != $_COOKIE['nonhttps']) setcookie ('nonhttps', $nonhttps);
    }
    $smarty->assign ('backupuser', $backupuser) ; 
    $smarty->assign ('backuphost', $backuphost) ; 
    $smarty->display ('login.tpl') ; 
    return ; 
}

if (empty($encrypt) || empty ($xorstring)) {
    $encrypt = crypt(strrev(sprintf (gettimeofday (true)))) ;
    $_SESSION['encrypt'] = $encrypt ; 
    $xorstring = xorstring ($encrypt, $passwd) ; 
}

setcookie ('xorstring', base64_encode($xorstring)) ; 

$scheduler = readcron ($passwd) ; 

foreach ($scheduler as $line) {
    if ($line[0] == "#") 
        continue ; 
    if (strpos ($line, "slbackup-cron") === false)
        continue ; 
    $config["active"] = true ; 
    $array = explode (" ", $line) ; 
    sscanf ($array[0], "%s", $config["minutes"]) ;
    sscanf ($array[1], "%s", $config["hours"]) ;
}
unset ($revisions) ; 

switch ($submit) {
    case "scheduler": 
        $newsched = "" ; 
        foreach ($scheduler as $line) {
	    if ($line[0] == "#") 
		$newsched .= sprintf ("%s\n", $line) ; 
	    elseif (strpos ($line, "slbackup-cron") === false)
		$newsched .= sprintf ("%s\n", $line) ; 
	    elseif (empty ($newconf["active"])) {
		$newsched .= sprintf ("#%s\n", $line) ; 
                $changed = true ; 
                $config["active"] = false ; 
	    } else {
	        if ($config["minutes"] <> $newconf ["minutes"])
	            $changed = true ; 
	        if ($config["hours"] <> $newconf ["hours"])
	            $changed = true ; 
	        if ($changed) {
	            $config["active"] = true ; 
	            $config["minutes"] = $newconf ["minutes"] ; 
		    $config["hours"] = $newconf ["hours"] ; 
		    $newsched .= sprintf ("%02d %02d * * * root if [ -x /usr/share/slbackup/slbackup-cron -a -f /etc/slbackup/slbackup.conf ]; then /usr/share/slbackup/slbackup-cron ; fi\n", $newconf["minutes"], $newconf["hours"]) ; 
		} else 
		    $newsched .= sprintf ("%s\n", $line) ; 
            }
        }
        if (!$changed and empty($config["active"]) and 
             $newconf["active"] == "on") {
	    $config["active"] = true ; 
	    $config["minutes"] = $newconf ["minutes"] ; 
	    $config["hours"] = $newconf ["hours"] ; 
	    $newsched .= sprintf ("%02d %02d * * * root if [ -x /usr/share/slbackup/slbackup-cron -a -f /etc/slbackup/slbackup.conf ]; then /usr/share/slbackup/slbackup-cron ; fi\n", $newconf["minutes"], $newconf["hours"]) ; 
	    $changed = true ; 
	}
        if ($changed) {
	    writecron ($passwd, $newsched);
	}
        break ;
    case "server":
        foreach (array ("server_address", "server_destdir", "server_user", "server_type") as $key) {
            if ($newconf[$key] <> $config[$key]) {
                $changed = true ; 
                $config[$key] = $newconf[$key] ;
            }
        }
	if ($changed)
	    writeconf ($passwd, $config) ; 
	break ; 
    case "delclient": 
	if (empty ($client)) {
	    printf (_("No client specified :(") . "<BR>\n") ; 
	    break ; 
	}
	$pos = array_search($client, array_keys ($config["clients"])) ;
        if ($pos === false)
	    printf (_("Unable to find %s in the list of clients.") . "<BR>\n", 
	 	    $client) ; 
	else {
	    array_splice ($config["clients"],
	                  $pos,1) ; 
	    writeconf ($passwd, $config) ; 
	}
	unset ($client) ; 
	break ;
    case "addclient":
        $client="<new>" ; 
        $config["clients"][$client]["keep"]="185" ; 
        $config["clients"][$client]["user"]="root" ; 
        break ;
    case "clientconfig":
        if ($client == "&lt;new&gt;") {
	    $client = $newconf["client_address"] ; 
	    $config["clients"][$client]["location"] = array () ;
        }
        foreach (array ("address", "keep", "user", "type") as $key) {
            if ($newconf["client_".$key] <> $config["clients"][$client][$key]) {
                $changed = true ; 
                $config["clients"][$client][$key] = $newconf["client_" . $key] ;
            }
        }
	if ($changed)
	    writeconf ($passwd, $config) ; 
	break ; 
    case "delloc": 
	if (empty ($newconf["location"]))
	    break ; 
	$pos = array_search ($newconf["location"], 
		         $config["clients"][$client]["location"]) ;
        if ($pos === false)
	    printf (_("Unable to find %s in the locations of %s.") . "<BR>\n", 
	 	    $newconf["location"], $client) ; 
	else
	    array_splice ($config["clients"][$client]["location"],
	                  $pos,1) ; 
	writeconf ($passwd, $config) ; 
	break ;
    case "addloc": 
	if (empty ($newconf["newloc"]))
	    break ; 
	if (in_array ($newconf["newloc"], 
		      $config["clients"][$client]["location"]))
	    break ;
	$config["clients"][$client]["location"][] = $newconf["newloc"] ; 
	writeconf ($passwd, $config) ; 
	break ;
    case "restorefile": 
        if (empty($client) || empty ($newconf["location"]))
            break ; 
         switch ($revision) {
             case "current": 
		 $out = fetchfile ($passwd, 
				   sprintf ("%s/%s", 
				            $config["server_destdir"], 
				            $client), 
				   $newconf["location"], $newconf["file"]) ; 
		header ('Content-Type: binary/raw') ; 
		header ('Content-Length: ' . strlen ($out)) ; 
		header (sprintf ("Content-Disposition: attachment; filename=\"%s\"", basename ($newconf["file"]))) ; 
		echo $out ; 
		exit  ; 
            default:
                if (empty($revision))
		    $revisions = listfile ($passwd,
					   sprintf ("%s/%s", 
						    $config["server_destdir"], 
						    $client), 
					   $newconf["location"], $newconf["sub"]) ; 
                else {
		 $out = fetchsnapshot ($passwd, 
				   sprintf ("%s/%s", 
				            $config["server_destdir"], 
				            $client), 
				   $newconf["location"], sprintf ("%s/%s", $newconf["parent"], $revision)) ; 
		header ('Content-Type: binary/raw') ; 
		header ('Content-Length: ' . strlen ($out)) ; 
		header (sprintf ("Content-Disposition: attachment; filename=\"%s\"", $newconf["name"])) ; 
		echo $out ; 
		exit  ; 
//		    debug (array ('client' => $client, 'serverdir' => $config['server_destdir'], 'revision' => $revision , 'newconf' => $newconf)) ; 
               }
               break ;
        }
        break ; 
    case "restorelocation": 
        if (empty($client) || empty ($newconf["location"]))
            break ; 
        if (empty($newconf["sub"]))
	    $loc = listloc ($passwd, 
			    sprintf ("%s/%s", $config["server_destdir"], $client), 
			    $newconf["location"]) ; 
	else 
	    $loc = listloc ($passwd, 
			    sprintf ("%s/%s", $config["server_destdir"], $client), 
			    $newconf["location"], $newconf["sub"]) ; 

	break ; 
    case "removesnapshot":
        if (!empty ($snapshot) and ($selected == $client))
	    $smarty->assign ('removed', removesnapshots ($passwd, sprintf ("%s/%s", $config["server_destdir"], $client), $snapshot)) ; 
    case "maint":
        if (!empty($client)) {
            $smarty->assign ('snapshots', listsnapshots ($passwd, sprintf ("%s/%s", $config["server_destdir"], $client))) ; 
        }
        break ; 
    case "config":
        break ; 
    default:
        $log = array ('start' => '', 'end' => '') ; 
        foreach ($config["clients"] as $key => $value) 
            $log["clients"][$key] = 
                array ('start' => '', 'failed' => '', 'ok' => '') ; 
        $log = readlog ($passwd, $log) ; 
        $smarty->assign ('checkkeysandversions', 
                         checkkeysandversions ($passwd, $config)) ; 
        break ; 
}

switch ($submit) {
    case "restorefile":
        if (empty($revisions))
            $revisions=array() ; 
        $smarty->assign ('revisions', $revisions) ; 
    case "restorelocation":
	$smarty->assign ('loc', $loc) ; 
	$smarty->assign ('location', $newconf["location"]) ; 
	$smarty->assign ('sub', $newconf["sub"]) ; 
    case "restoreclient":
    case "restore":
	$clients = array_keys($config["clients"]) ; 
	$smarty->assign ('clients', $clients) ; 
	if (empty($client))
	    $client = $clients[0] ; 
	$smarty->assign ('client', $client) ; 
	$smarty->assign ('locations', $config["clients"][$client]["location"]) ; 
	$smarty->display ('restore.tpl') ; 
        break ; 
    case "removesnapshot":
    case "maint":
	$clients = array_keys($config["clients"]) ; 
	$smarty->assign ('clients', $clients) ; 
	$smarty->assign ('client', $client) ; 
	$smarty->display ('maint.tpl') ; 
        break ; 
    case "config":
    case "addclient":
    case "server":
    case "chooseclient":
    case "delclient":
    case "clientconfig":
    case "delloc":
    case "addloc":
    case "scheduler":
	if ($config["active"]) 
	    $smarty->assign ('active', "checked") ; 
	for ($i = 0 ; $i < 60 ; $i += 5)
	    $amin[] = sprintf ("%02d", $i) ;
	$smarty->assign ('a_minutes', $amin); 
	$smarty->assign ('minutes', $config["minutes"]) ; 
	for ($i = 0 ; $i < 24 ; $i++) 
	    $ahour[] = sprintf ("%02d", $i) ;
	$smarty->assign ('a_hours', $ahour); 
	$smarty->assign ('hours', $config["hours"]) ; 
	$smarty->assign ('server_address', $config["server_address"]) ; 
	$smarty->assign ('server_destdir', $config["server_destdir"]) ; 
	$smarty->assign ('server_type', $config["server_type"]) ; 
	$smarty->assign ('server_user', $config["server_user"]) ; 
	$smarty->assign ('types', array ('local', 'remote')) ; 
	$clients = array_keys($config["clients"]) ; 
	$smarty->assign ('clients', $clients) ; 
	if (empty($client))
	    $client = $clients[0] ; 
	$smarty->assign ('client', $client) ; 
	$smarty->assign ('clientaddress', $config["clients"][$client]["address"]) ; 
	$smarty->assign ('clientkeep', $config["clients"][$client]["keep"]) ; 
	$smarty->assign ('client_type', $config["clients"][$client]["type"]) ; 
	$smarty->assign ('clientuser', $config["clients"][$client]["user"]) ; 
	if ($submit == "addclient")
	    $smarty->assign ('clientsubmit', _("Add")) ; 
	else
	    $smarty->assign ('clientsubmit', _("Update")) ; 
	$smarty->assign ('locations', $config["clients"][$client]["location"]) ; 
	$smarty->display ('config.tpl') ; 
	break ; 
    default:
        $smarty->assign ('log', $log) ; 
        $smarty->display ('status.tpl') ; 
        break ; 
}
?>
