<?php
/*!
 * \file phpmynetconf.php
 * \brief NETCONF PHP gateway for Apache module of Netopeer
 * \author Tomas Cejka <cejkat@cesnet.cz>
 * \date 2012
 */
/*
 * Copyright (C) 2011-2012 CESNET
 *
 * LICENSE TERMS
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name of the Company nor the names of its contributors
 *    may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * ALTERNATIVELY, provided that this notice is retained in full, this
 * product may be distributed under the terms of the GNU General Public
 * License (GPL) version 2 or later, in which case the provisions
 * of the GPL apply INSTEAD OF those given above.
 *
 * This software is provided ``as is'', and any express or implied
 * warranties, including, but not limited to, the implied warranties of
 * merchantability and fitness for a particular purpose are disclaimed.
 * In no event shall the company or contributors be liable for any
 * direct, indirect, incidental, special, exemplary, or consequential
 * damages (including, but not limited to, procurement of substitute
 * goods or services; loss of use, data, or profits; or business
 * interruption) however caused and on any theory of liability, whether
 * in contract, strict liability, or tort (including negligence or
 * otherwise) arising in any way out of the use of this software, even
 * if advised of the possibility of such damage.
 *
 */

/* Enumeration of Message type (taken from mod_netconf.c) */
class MsgType {
	const REPLY_OK		= 0;
	const REPLY_DATA	= 1;
	const REPLY_ERROR	= 2;
	const REPLY_INFO	= 3;
	const MSG_CONNECT	= 4;
	const MSG_DISCONNECT	= 5;
	const MSG_GET		= 6;
	const MSG_GETCONFIG	= 7;
	const MSG_EDITCONFIG	= 8;
	const MSG_COPYCONFIG	= 9;
	const MSG_DELETECONFIG  = 10;
	const MSG_LOCK		= 11;
	const MSG_UNLOCK	= 12;
	const MSG_KILL		= 13;
	const MSG_INFO		= 14;
	const MSG_GENERIC	= 15;
};

/**
  \brief Read response from socket
  \param[in,out] $sock socket descriptor
  \return trimmed string that was read
 */
function readnetconf(&$sock)
{
	$response = "";
	do {
		$tmp = "";
		$tmp = fread($sock, 4096);
		if ($tmp != "") {
			$response .= $tmp;
		}
		if (strlen($tmp) < 4096) {
			break;
		}
	} while ($tmp != "");
	return trim($response);
}

function printJsonError() {
	switch (json_last_error()) {
		case JSON_ERROR_NONE:
			echo 'No errors';
			break;
		case JSON_ERROR_DEPTH:
			echo 'Maximum stack depth exceeded';
			break;
		case JSON_ERROR_STATE_MISMATCH:
			echo 'Underflow or the modes mismatch';
			break;
		case JSON_ERROR_CTRL_CHAR:
			echo 'Unexpected control character found';
			break;
		case JSON_ERROR_SYNTAX:
			echo 'Syntax error, malformed JSON';
			break;
		case JSON_ERROR_UTF8:
			echo 'Malformed UTF-8 characters, possibly incorrectly encoded';
			break;
		default:
			echo 'Unknown error';
			break;
	}
}

/**
  \brief Prints formatted XML
 */
function printxml($string)
{
	$xmlObj = simplexml_load_string("<rootnode>".str_replace('<?xml version="1.0" encoding="UTF-8"?>', "", $string)."</rootnode>");
	echo("<pre>".htmlspecialchars($xmlObj->asXML())."</pre>");
}

/**
 \param[in,out] $sock socket descriptor
 \return 0 on success
*/
function handle_connect(&$sock)
{
	$connect = json_encode(array("type" => MsgType::MSG_CONNECT,
	"host" => $_REQUEST["host"],
	"port" => 22,
	"user" => $_REQUEST["user"],
	"pass" => $_REQUEST["pass"]
	));
	fwrite($sock, $connect);
	$response = readnetconf($sock);
	$decoded = json_decode($response, true);
	echo "<h2>CONNECT</h2>";
	if ($decoded["type"] == MsgType::REPLY_OK) {
		$sessionkey = $decoded["session"];
		if (!isset($_SESSION["keys"])) {
			$_SESSION["keys"] = array("$sessionkey");
		} else {
			$_SESSION["keys"][] = $sessionkey;
		}
		if (!isset($_SESSION["hosts"])) {
			$_SESSION["hosts"] = array($_REQUEST["host"]);
		} else {
			$_SESSION["hosts"][] = $_REQUEST["host"];
		}
		echo "Successfully connected.";
		return 0;
	} else {
		echo "Could not connect.";
		var_dump($decoded);
		return 1;
	}
}

/**
 \return 0 on success
 */
function check_logged_keys()
{
	if (!isset($_SESSION["keys"])) {
		echo "Not logged in.";
		return 1;
	}
	if (!isset($_REQUEST["key"])) {
		echo "No Index of key.";
		return 1;
	}
	if (!isset($_SESSION["keys"][$_REQUEST["key"]])) {
		echo "Bad Index of key.";
		return 1;
	}
	return 0;
}

/**
 \param[in,out] $sock socket descriptor
 \param[in] $params array of values for mod_netconf (type, params...)
 \return array - response from mod_netconf
*/
function execute_operation(&$sock, $params)
{
	$operation = json_encode($params);
	fwrite($sock, $operation);
	$response = readnetconf($sock);
	return json_decode($response, true);
}

/**
 \param[in,out] $sock socket descriptor
 \return 0 on success
*/
function handle_get(&$sock)
{
	if (check_logged_keys() != 0) {
		return 1;
	}
	$sessionkey = $_SESSION["keys"][$_REQUEST["key"]];

	$params = array("type" => MsgType::MSG_GET,
			"session" => $sessionkey,
			"source" => "running");
	if (isset($_REQUEST["filter"]) && $_REQUEST["filter"] != "") {
		$params["filter"] = $_REQUEST["filter"];
	}
	$decoded = execute_operation($sock, $params);

	echo "<h2>GET-CONFIG</h2>";
	printxml($decoded["data"]);
}

/**
 \param[in,out] $sock socket descriptor
 \return 0 on success
*/
function handle_getconfig(&$sock)
{
	if (check_logged_keys() != 0) {
		return 1;
	}
	$sessionkey = $_SESSION["keys"][$_REQUEST["key"]];
	$params = array("type" => MsgType::MSG_GETCONFIG,
			"session" => $sessionkey,
			"source" => (isset($_REQUEST["source"])?$_REQUEST["source"]:"running"));
	if (isset($_REQUEST["filter"]) && $_REQUEST["filter"] != "") {
		$params["filter"] = $_REQUEST["filter"];
	}
	$decoded = execute_operation($sock, $params);

	echo "<h2>GET-CONFIG</h2>";
	printxml($decoded["data"]);
	return 0;
}

/**
 \param[in,out] $sock socket descriptor
 \return 0 on success
*/
function handle_editconfig(&$sock)
{
	if (check_logged_keys() != 0) {
		return 1;
	}
	$sessionkey = $_SESSION["keys"][$_REQUEST["key"]];
	/* execute get-config */
	$decoded = execute_operation($sock,
		array("type" => MsgType::MSG_GETCONFIG,
		"session" => $sessionkey,
		"source" => "running"));

	/* apply changes */
	$oldtree = $decoded["data"];
	var_dump($oldtree);
	echo "<br><br><br>";
	$newtree = simplexml_load_string("<rootnode>".str_replace('<?xml version="1.0" encoding="UTF-8"?>', "", $oldtree)."</rootnode>");
	echo "<br><br><br>";
	var_dump($newtree->{'comet-testers'}->{'comet-tester'}->statistics->enabled);
	//return 0;
	$newtree->{'comet-testers'}->{'comet-tester'}->statistics->enabled = "false";
	var_dump($newtree->{'comet-testers'}->{'comet-tester'}->statistics->enabled);
	$config = "";
	foreach ($newtree as $ch) {
		$config .= $ch->asXML();
	}
	/* copy-config to store new values */
	$params = array("type" => MsgType::MSG_EDITCONFIG,
			"session" => $sessionkey,
			"target" => "running",
			"config" => $config);
	print_r($params);
	$decoded = execute_operation($sock, $params);

	echo "<h2>EDIT-CONFIG</h2>";
	var_dump($decoded);
	return 0;
}

function handle_copyconfig(&$sock)
{
	$sessionkey = $_SESSION["keys"][$_REQUEST["key"]];
	if (isset($_REQUEST["config"]) && $_REQUEST["config"] != '') {
		$config = $_REQUEST["config"];
		var_dump($config);
		$params = array("type" => MsgType::MSG_COPYCONFIG,
			"session" => $sessionkey,
			"target" => "running",
			"config" => $config);
		$decoded = execute_operation($sock, $params);
		var_dump($decoded);
	} else {
		echo "No config was sent";
	}
}

/**
 \param[in,out] $sock socket descriptor
 \return 0 on success
*/
function handle_disconnect(&$sock)
{
	if (check_logged_keys() != 0) {
		return 1;
	}
	$sessionkey = $_SESSION["keys"][$_REQUEST["key"]];
	$decoded = execute_operation($sock,
		array(	"type" => MsgType::MSG_DISCONNECT,
			"session" => $sessionkey));
	echo "<h2>Disconnect</h2>";
	if ($decoded["type"] == MsgType::REPLY_OK) {
		echo "Successfully disconnected.";
	} else {
		echo "Error occured.";
		var_dump($decoded);
	}
	unset($_SESSION["keys"][$_REQUEST["key"]]);
	unset($_SESSION["hosts"][$_REQUEST["key"]]);
	$_SESSION["keys"] = array_values($_SESSION["keys"]);
	$_SESSION["hosts"] = array_values($_SESSION["hosts"]);
}

/* main part of script */
session_start();

/* create connection with socket */
if (isset($_REQUEST["getconfig"]) || (isset($_REQUEST["command"]))) {
	$errno = 0;
	$errstr = "";
	$sock = fsockopen('unix:///tmp/mod_netconf.sock', NULL, $errno, $errstr);
	if ($errno != 0) {
		echo "Could not connect to socket.";
		echo "$errstr";
		return 1;
	}
	stream_set_timeout($sock, 1, 100);
}

/* pseudo-AJAX response of get-config running */
if (isset($_REQUEST["getconfig"])) {
	if (check_logged_keys() != 0) {
		return 1;
	}
	$sessionkey = $_SESSION["keys"][$_REQUEST["key"]];
	$params = array("type" => MsgType::MSG_GETCONFIG,
			"session" => $sessionkey,
			"source" => "running");
	$decoded = execute_operation($sock, $params);
	echo $decoded["data"];
	/* end script return only data */
	exit(0);
}


/* print mainpage */
if (!isset($_REQUEST["command"])) {
	echo "<h2>Connect to new NETCONF server</h2>
	<form action='?' method='POST'>
	<input type='hidden' name='command' value='connect'>
	<label for='host'>Hostname:</label><input type='text' name='host'><br>
	<label for='user'>Username:</label><input type='text' name='user'><br>
	<label for='pass'>Password:</label><input type='password' name='pass'><br>
	<input type='submit' value='Login'>
	</form>";
	if (isset($_SESSION["keys"])) {
		echo "<h2>Already connected nodes</h2>";
		$keys = $_SESSION["keys"];
		$i = 0;
		foreach ($keys as $k) {
			echo "$i ".$_SESSION["hosts"][$i]."
<form action='?' method='GET'>
<input type='hidden' name='command' value='get'>
<input type='hidden' name='key' value='$i'>
<label for='get-filter'>Filter:</label><input type='text' name='filter'>
<input type='submit' value='Execute Get'></form>
<form action='?' method='GET'>
<input type='hidden' name='command' value='getconfig'>
<input type='hidden' name='key' value='$i'>
<label for='get-filter'>Filter:</label><input type='text' name='filter'>
<select name='source'><option value='running'>Running</option>
<option value='startup'>Start-up</option>
<option value='candidate'>Candidate</option></select>
<input type='submit' value='Execute Get-config'></form>
<!--<form action='?' method='GET'>
<input type='hidden' name='command' value='editconfig'>
<input type='hidden' name='key' value='$i'>
<label for='edit-element'>Element name:</label><input type='text' name='element'>
<label for='edit-value'>Value:</label><input type='text' name='newval'>
<input type='submit' value='Execute Edit-config'>
</form>-->
<form action='?' method='POST'>
<input type='hidden' name='command' value='copyconfig'>
<input type='hidden' name='key' value='$i'>
<textarea name='config' id='configdata$i' cols=40 rows=10></textarea>
<input type='submit' value='Rewrite running config'> (copy-config)
</form>
<a href='?command=disconnect&amp;key=$i'><button>disconnect</button></a><br>
<script type='text/javascript'>
xmlHttp = new XMLHttpRequest();
xmlHttp.open( 'GET', '?key=$i&getconfig', false );
xmlHttp.send( null );
document.getElementById('configdata$i').value=xmlHttp.responseText;
</script>";
			$i++;
		}
	}
	exit(0);
}

/* handle commands */
if (isset($_REQUEST["command"])) {
	echo "<a href='?'>Back</a>";

	if ($_REQUEST["command"] === "connect") {
		handle_connect($sock);
	} else if ($_REQUEST["command"] === "copyconfig") {
		handle_copyconfig($sock);
	} else if ($_REQUEST["command"] === "editconfig") {
		handle_editconfig($sock);
	} else if ($_REQUEST["command"] === "get") {
		handle_get($sock);
	} else if ($_REQUEST["command"] === "getconfig") {
		handle_getconfig($sock);
	} else if ($_REQUEST["command"] === "disconnect") {
		handle_disconnect($sock);
	} else {
		printf("Not implemented yet. (%s)", $_REQUEST["command"]);
	}
	fclose($sock);
	exit(0);
}


