raspap-webgui/includes/webconsole.php

852 lines
194 KiB
PHP
Raw Normal View History

<?php
require_once 'config.php';
require_once RASPI_CONFIG.'/raspap.php';
session_start();
header('X-Frame-Options: SAMEORIGIN');
header("Content-Security-Policy: default-src 'none'; frame-src 'self'; connect-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'");
require_once 'authenticate.php';
// Web Console v0.9.7 (2016-11-05)
//
// Author: Nickolay Kovalev (http://nickola.ru)
// GitHub: https://github.com/nickola/web-console
// URL: http://web-console.org
// Disable login (don't ask for credentials, be careful)
// Example: $NO_LOGIN = true;
$NO_LOGIN = true;
// Single-user credentials
// Example: $USER = 'user'; $PASSWORD = 'password';
$USER = '';
$PASSWORD = '';
// Multi-user credentials
// Example: $ACCOUNTS = array('user1' => 'password1', 'user2' => 'password2');
$ACCOUNTS = array();
// Password hash algorithm (password must be hashed)
// Example: $PASSWORD_HASH_ALGORITHM = 'md5';
// $PASSWORD_HASH_ALGORITHM = 'sha256';
$PASSWORD_HASH_ALGORITHM = '';
// Home directory (multi-user mode supported)
// Example: $HOME_DIRECTORY = '/tmp';
// $HOME_DIRECTORY = array('user1' => '/home/user1', 'user2' => '/home/user2');
$HOME_DIRECTORY = '';
// Code below is automatically generated from different components
// For more information see: https://github.com/nickola/web-console
//
// Used components:
// - jQuery JavaScript Library: https://github.com/jquery/jquery
// - jQuery Terminal Emulator: https://github.com/jcubic/jquery.terminal
// - jQuery Mouse Wheel Plugin: https://github.com/brandonaaron/jquery-mousewheel
// - PHP JSON-RPC 2.0 Server/Client Implementation: https://github.com/sergeyfast/eazy-jsonrpc
// - Normalize.css: https://github.com/necolas/normalize.css
?>
<?php
/**
* JSON RPC Server for Eaze
*
* Reads $_GET['rawRequest'] or php://input for Request Data
* @link http://www.jsonrpc.org/specification
* @link http://dojotoolkit.org/reference-guide/1.8/dojox/rpc/smd.html
* @package Eaze
* @subpackage Model
* @author Sergeyfast
*/
class BaseJsonRpcServer {
const ParseError = -32700,
InvalidRequest = -32600,
MethodNotFound = -32601,
InvalidParams = -32602,
InternalError = -32603;
/**
* Exposed Instances
* @var object[] namespace => method
*/
protected $instances = array();
/**
* Decoded Json Request
* @var object|array
*/
protected $request;
/**
* Array of Received Calls
* @var array
*/
protected $calls = array();
/**
* Array of Responses for Calls
* @var array
*/
protected $response = array();
/**
* Has Calls Flag (not notifications)
* @var bool
*/
protected $hasCalls = false;
/**
* Is Batch Call in using
* @var bool
*/
private $isBatchCall = false;
/**
* Hidden Methods
* @var array
*/
protected $hiddenMethods = array(
'execute', '__construct', 'registerinstance'
);
/**
* Content Type
* @var string
*/
public $ContentType = 'application/json';
/**
* Allow Cross-Domain Requests
* @var bool
*/
public $IsXDR = true;
/**
* Max Batch Calls
* @var int
*/
public $MaxBatchCalls = 10;
/**
* Error Messages
* @var array
*/
protected $errorMessages = array(
self::ParseError => 'Parse error',
self::InvalidRequest => 'Invalid Request',
self::MethodNotFound => 'Method not found',
self::InvalidParams => 'Invalid params',
self::InternalError => 'Internal error',
);
/**
* Cached Reflection Methods
* @var ReflectionMethod[]
*/
private $reflectionMethods = array();
/**
* Validate Request
* @return int error
*/
private function getRequest() {
$error = null;
do {
if ( array_key_exists( 'REQUEST_METHOD', $_SERVER ) && $_SERVER['REQUEST_METHOD'] != 'POST' ) {
$error = self::InvalidRequest;
break;
};
$request = !empty( $_GET['rawRequest'] ) ? $_GET['rawRequest'] : file_get_contents( 'php://input' );
$this->request = json_decode( $request, false );
if ( $this->request === null ) {
$error = self::ParseError;
break;
}
if ( $this->request === array() ) {
$error = self::InvalidRequest;
break;
}
// check for batch call
if ( is_array( $this->request ) ) {
if( count( $this->request ) > $this->MaxBatchCalls ) {
$error = self::InvalidRequest;
break;
}
$this->calls = $this->request;
$this->isBatchCall = true;
} else {
$this->calls[] = $this->request;
}
} while ( false );
return $error;
}
/**
* Get Error Response
* @param int $code
* @param mixed $id
* @param null $data
* @return array
*/
private function getError( $code, $id = null, $data = null ) {
return array(
'jsonrpc' => '2.0',
'id' => $id,
'error' => array(
'code' => $code,
'message' => isset( $this->errorMessages[$code] ) ? $this->errorMessages[$code] : $this->errorMessages[self::InternalError],
'data' => $data,
),
);
}
/**
* Check for jsonrpc version and correct method
* @param object $call
* @return array|null
*/
private function validateCall( $call ) {
$result = null;
$error = null;
$data = null;
$id = is_object( $call ) && property_exists( $call, 'id' ) ? $call->id : null;
do {
if ( !is_object( $call ) ) {
$error = self::InvalidRequest;
break;
}
// hack for inputEx smd tester
if ( property_exists( $call, 'version' ) ) {
if ( $call->version == 'json-rpc-2.0' ) {
$call->jsonrpc = '2.0';
}
}
if ( !property_exists( $call, 'jsonrpc' ) || $call->jsonrpc != '2.0' ) {
$error = self::InvalidRequest;
break;
}
$fullMethod = property_exists( $call, 'method' ) ? $call->method : '';
$methodInfo = explode( '.', $fullMethod, 2 );
$namespace = array_key_exists( 1, $methodInfo ) ? $methodInfo[0] : '';
$method = $namespace ? $methodInfo[1] : $fullMethod;
if ( !$method || !array_key_exists( $namespace, $this->instances ) || !method_exists( $this->instances[$namespace], $method ) || in_array( strtolower( $method ), $this->hiddenMethods ) ) {
$error = self::MethodNotFound;
break;
}
if ( !array_key_exists( $fullMethod, $this->reflectionMethods ) ) {
$this->reflectionMethods[$fullMethod] = new ReflectionMethod( $this->instances[$namespace], $method );
}
/** @var $params array */
$params = property_exists( $call, 'params' ) ? $call->params : null;
$paramsType = gettype( $params );
if ( $params !== null && $paramsType != 'array' && $paramsType != 'object' ) {
$error = self::InvalidParams;
break;
}
// check parameters
switch ( $paramsType ) {
case 'array':
$totalRequired = 0;
// doesn't hold required, null, required sequence of params
foreach ( $this->reflectionMethods[$fullMethod]->getParameters() as $param ) {
if ( !$param->isDefaultValueAvailable() ) {
$totalRequired++;
}
}
if ( count( $params ) < $totalRequired ) {
$error = self::InvalidParams;
$data = sprintf( 'Check numbers of required params (got %d, expected %d)', count( $params ), $totalRequired );
}
break;
case 'object':
foreach ( $this->reflectionMethods[$fullMethod]->getParameters() as $param ) {
if ( !$param->isDefaultValueAvailable() && !array_key_exists( $param->getName(), $params ) ) {
$error = self::InvalidParams;
$data = $param->getName() . ' not found';
break 3;
}
}
break;
case 'NULL':
if ( $this->reflectionMethods[$fullMethod]->getNumberOfRequiredParameters() > 0 ) {
$error = self::InvalidParams;
$data = 'Empty required params';
break 2;
}
break;
}
} while ( false );
if ( $error ) {
$result = array( $error, $id, $data );
}
return $result;
}
/**
* Process Call
* @param $call
* @return array|null
*/
private function processCall( $call ) {
$id = property_exists( $call, 'id' ) ? $call->id : null;
$params = property_exists( $call, 'params' ) ? $call->params : array();
$result = null;
$namespace = substr( $call->method, 0, strpos( $call->method, '.' ) );
try {
// set named parameters
if ( is_object( $params ) ) {
$newParams = array();
foreach ( $this->reflectionMethods[$call->method]->getParameters() as $param ) {
$paramName = $param->getName();
$defaultValue = $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null;
$newParams[] = property_exists( $params, $paramName ) ? $params->$paramName : $defaultValue;
}
$params = $newParams;
}
// invoke
$result = $this->reflectionMethods[$call->method]->invokeArgs( $this->instances[$namespace], $params );
} catch ( Exception $e ) {
return $this->getError( $e->getCode(), $id, $e->getMessage() );
}
if ( !$id && $id !== 0 ) {
return null;
}
return array(
'jsonrpc' => '2.0',
'result' => $result,
'id' => $id,
);
}
/**
* Create new Instance
* @param object $instance
*/
public function __construct( $instance = null ) {
if ( get_parent_class( $this ) ) {
$this->RegisterInstance( $this, '' );
} else if ( $instance ) {
$this->RegisterInstance( $instance, '' );
}
}
/**
* Register Instance
* @param object $instance
* @param string $namespace default is empty string
* @return $this
*/
public function RegisterInstance( $instance, $namespace = '' ) {
$this->instances[$namespace] = $instance;
$this->instances[$namespace]->errorMessages = $this->errorMessages;
return $this;
}
/**
* Handle Requests
*/
public function Execute() {
do {
// check for SMD Discovery request
if ( array_key_exists( 'smd', $_GET ) ) {
$this->response[] = $this->getServiceMap();
$this->hasCalls = true;
break;
}
$error = $this->getRequest();
if ( $error ) {
$this->response[] = $this->getError( $error );
$this->hasCalls = true;
break;
}
foreach ( $this->calls as $call ) {
$error = $this->validateCall( $call );
if ( $error ) {
$this->response[] = $this->getError( $error[0], $error[1], $error[2] );
$this->hasCalls = true;
} else {
$result = $this->processCall( $call );
if ( $result ) {
$this->response[] = $result;
$this->hasCalls = true;
}
}
}
} while ( false );
// flush response
if ( $this->hasCalls ) {
if ( !$this->isBatchCall ) {
$this->response = reset( $this->response );
}
if ( !headers_sent() ) {
// Set Content Type
if ( $this->ContentType ) {
header( 'Content-Type: ' . $this->ContentType );
}
// Allow Cross Domain Requests
if ( $this->IsXDR ) {
header( 'Access-Control-Allow-Origin: *' );
header( 'Access-Control-Allow-Headers: x-requested-with, content-type' );
}
}
echo json_encode( $this->response );
$this->resetVars();
}
}
/**
* Get Doc Comment
* @param $comment
* @return string|null
*/
private function getDocDescription( $comment ) {
$result = null;
if ( preg_match( '/\*\s+([^@]*)\s+/s', $comment, $matches ) ) {
$result = str_replace( '*', "\n", trim( trim( $matches[1], '*' ) ) );
}
return $result;
}
/**
* Get Service Map
* Maybe not so good realization of auto-discover via doc blocks
* @return array
*/
private function getServiceMap() {
$result = array(
'transport' => 'POST',
'envelope' => 'JSON-RPC-2.0',
'SMDVersion' => '2.0',
'contentType' => 'application/json',
'target' => !empty( $_SERVER['REQUEST_URI'] ) ? substr( $_SERVER['REQUEST_URI'], 0, strpos( $_SERVER['REQUEST_URI'], '?' ) ) : '',
'services' => array(),
'description' => '',
);
foreach( $this->instances as $namespace => $instance ) {
$rc = new ReflectionClass( $instance);
// Get Class Description
if ( $rcDocComment = $this->getDocDescription( $rc->getDocComment() ) ) {
$result['description'] .= $rcDocComment . PHP_EOL;
}
foreach ( $rc->getMethods() as $method ) {
/** @var ReflectionMethod $method */
if ( !$method->isPublic() || in_array( strtolower( $method->getName() ), $this->hiddenMethods ) ) {
continue;
}
$methodName = ( $namespace ? $namespace . '.' : '' ) . $method->getName();
$docComment = $method->getDocComment();
$result['services'][$methodName] = array( 'parameters' => array() );
// set description
if ( $rmDocComment = $this->getDocDescription( $docComment ) ) {
$result['services'][$methodName]['description'] = $rmDocComment;
}
// @param\s+([^\s]*)\s+([^\s]*)\s*([^\s\*]*)
$parsedParams = array();
if ( preg_match_all( '/@param\s+([^\s]*)\s+([^\s]*)\s*([^\n\*]*)/', $docComment, $matches ) ) {
foreach ( $matches[2] as $number => $name ) {
$type = $matches[1][$number];
$desc = $matches[3][$number];
$name = trim( $name, '$' );
$param = array( 'type' => $type, 'description' => $desc );
$parsedParams[$name] = array_filter( $param );
}
};
// process params
foreach ( $method->getParameters() as $parameter ) {
$name = $parameter->getName();
$param = array( 'name' => $name, 'optional' => $parameter->isDefaultValueAvailable() );
if ( array_key_exists( $name, $parsedParams ) ) {
$param += $parsedParams[$name];
}
if ( $param['optional'] ) {
$param['default'] = $parameter->getDefaultValue();
}
$result['services'][$methodName]['parameters'][] = $param;
}
// set return type
if ( preg_match( '/@return\s+([^\s]+)\s*([^\n\*]+)/', $docComment, $matches ) ) {
$returns = array( 'type' => $matches[1], 'description' => trim( $matches[2] ) );
$result['services'][$methodName]['returns'] = array_filter( $returns );
}
}
}
return $result;
}
/**
* Reset Local Class Vars after Execute
*/
private function resetVars() {
$this->response = $this->calls = array();
$this->hasCalls = $this->isBatchCall = false;
}
}
?>
<?php
// Initializing
if (!isset($NO_LOGIN)) $NO_LOGIN = false;
if (!isset($ACCOUNTS)) $ACCOUNTS = array();
if (isset($USER) && isset($PASSWORD) && $USER && $PASSWORD) $ACCOUNTS[$USER] = $PASSWORD;
if (!isset($PASSWORD_HASH_ALGORITHM)) $PASSWORD_HASH_ALGORITHM = '';
if (!isset($HOME_DIRECTORY)) $HOME_DIRECTORY = '';
$IS_CONFIGURED = ($NO_LOGIN || count($ACCOUNTS) >= 1) ? true : false;
// Utilities
function is_empty_string($string) {
return strlen($string) <= 0;
}
function is_equal_strings($string1, $string2) {
return strcmp($string1, $string2) == 0;
}
function get_hash($algorithm, $string) {
return hash($algorithm, trim((string) $string));
}
// Command execution
function execute_command($command) {
$descriptors = array(
0 => array('pipe', 'r'), // STDIN
1 => array('pipe', 'w'), // STDOUT
2 => array('pipe', 'w') // STDERR
);
$process = proc_open($command . ' 2>&1', $descriptors, $pipes);
if (!is_resource($process)) die("Can't execute command.");
// Nothing to push to STDIN
fclose($pipes[0]);
$output = stream_get_contents($pipes[1]);
fclose($pipes[1]);
$error = stream_get_contents($pipes[2]);
fclose($pipes[2]);
// All pipes must be closed before "proc_close"
$code = proc_close($process);
return $output;
}
// Command parsing
function parse_command($command) {
$value = ltrim((string) $command);
if (!is_empty_string($value)) {
$values = explode(' ', $value);
$values_total = count($values);
if ($values_total > 1) {
$value = $values[$values_total - 1];
for ($index = $values_total - 2; $index >= 0; $index--) {
$value_item = $values[$index];
if (substr($value_item, -1) == '\\') $value = $value_item . ' ' . $value;
else break;
}
}
}
return $value;
}
// RPC Server
class WebConsoleRPCServer extends BaseJsonRpcServer {
protected $home_directory = '';
private function error($message) {
throw new Exception($message);
}
// Authentication
private function authenticate_user($user, $password) {
$user = trim((string) $user);
$password = trim((string) $password);
if ($user && $password) {
global $ACCOUNTS, $PASSWORD_HASH_ALGORITHM;
if (isset($ACCOUNTS[$user]) && !is_empty_string($ACCOUNTS[$user])) {
if ($PASSWORD_HASH_ALGORITHM) $password = get_hash($PASSWORD_HASH_ALGORITHM, $password);
if (is_equal_strings($password, $ACCOUNTS[$user]))
return $user . ':' . get_hash('sha256', $password);
}
}
throw new Exception("Incorrect user or password");
}
private function authenticate_token($token) {
global $NO_LOGIN;
if ($NO_LOGIN) return true;
$token = trim((string) $token);
$token_parts = explode(':', $token, 2);
if (count($token_parts) == 2) {
$user = trim((string) $token_parts[0]);
$password_hash = trim((string) $token_parts[1]);
if ($user && $password_hash) {
global $ACCOUNTS;
if (isset($ACCOUNTS[$user]) && !is_empty_string($ACCOUNTS[$user])) {
$real_password_hash = get_hash('sha256', $ACCOUNTS[$user]);
if (is_equal_strings($password_hash, $real_password_hash)) return $user;
}
}
}
throw new Exception("Incorrect user or password");
}
private function get_home_directory($user) {
global $HOME_DIRECTORY;
if (is_string($HOME_DIRECTORY)) {
if (!is_empty_string($HOME_DIRECTORY)) return $HOME_DIRECTORY;
}
else if (is_string($user) && !is_empty_string($user) && isset($HOME_DIRECTORY[$user]) && !is_empty_string($HOME_DIRECTORY[$user]))
return $HOME_DIRECTORY[$user];
return getcwd();
}
// Environment
private function get_environment() {
$hostname = function_exists('gethostname') ? gethostname() : null;
return array('path' => getcwd(), 'hostname' => $hostname);
}
private function set_environment($environment) {
$environment = !empty($environment) ? (array) $environment : array();
$path = (isset($environment['path']) && !is_empty_string($environment['path'])) ? $environment['path'] : $this->home_directory;
if (!is_empty_string($path)) {
if (is_dir($path)) {
if (!@chdir($path)) return array('output' => "Unable to change directory to current working directory, updating current directory",
'environment' => $this->get_environment());
}
else return array('output' => "Current working directory not found, updating current directory",
'environment' => $this->get_environment());
}
}
// Initialization
private function initialize($token, $environment) {
$user = $this->authenticate_token($token);
$this->home_directory = $this->get_home_directory($user);
$result = $this->set_environment($environment);
if ($result) return $result;
}
// Methods
public function login($user, $password) {
$result = array('token' => $this->authenticate_user($user, $password),
'environment' => $this->get_environment());
$home_directory = $this->get_home_directory($user);
if (!is_empty_string($home_directory)) {
if (is_dir($home_directory)) $result['environment']['path'] = $home_directory;
else $result['output'] = "Home directory not found: ". $home_directory;
}
return $result;
}
public function cd($token, $environment, $path) {
$result = $this->initialize($token, $environment);
if ($result) return $result;
$path = trim((string) $path);
if (is_empty_string($path)) $path = $this->home_directory;
if (!is_empty_string($path)) {
if (is_dir($path)) {
if (!@chdir($path)) return array('output' => "cd: ". $path . ": Unable to change directory");
}
else return array('output' => "cd: ". $path . ": No such directory");
}
return array('environment' => $this->get_environment());
}
public function completion($token, $environment, $pattern, $command) {
$result = $this->initialize($token, $environment);
if ($result) return $result;
$scan_path = '';
$completion_prefix = '';
$completion = array();
if (!empty($pattern)) {
if (!is_dir($pattern)) {
$pattern = dirname($pattern);
if ($pattern == '.') $pattern = '';
}
if (!empty($pattern)) {
if (is_dir($pattern)) {
$scan_path = $completion_prefix = $pattern;
if (substr($completion_prefix, -1) != '/') $completion_prefix .= '/';
}
}
else $scan_path = getcwd();
}
else $scan_path = getcwd();
if (!empty($scan_path)) {
// Loading directory listing
$completion = array_values(array_diff(scandir($scan_path), array('..', '.')));
natsort($completion);
// Prefix
if (!empty($completion_prefix) && !empty($completion)) {
foreach ($completion as &$value) $value = $completion_prefix . $value;
}
// Pattern
if (!empty($pattern) && !empty($completion)) {
// For PHP version that does not support anonymous functions (available since PHP 5.3.0)
function filter_pattern($value) {
global $pattern;
return !strncmp($pattern, $value, strlen($pattern));
}
$completion = array_values(array_filter($completion, 'filter_pattern'));
}
}
return array('completion' => $completion);
}
public function run($token, $environment, $command) {
$result = $this->initialize($token, $environment);
if ($result) return $result;
$output = ($command && !is_empty_string($command)) ? execute_command($command) : '';
if ($output && substr($output, -1) == "\n") $output = substr($output, 0, -1);
return array('output' => $output);
}
}
// Processing request
if (array_key_exists('REQUEST_METHOD', $_SERVER) && $_SERVER['REQUEST_METHOD'] == 'POST') {
$rpc_server = new WebConsoleRPCServer();
$rpc_server->Execute();
}
else if (!$IS_CONFIGURED) {
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Web Console</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="Web Console (http://www.web-console.org)" />
<meta name="author" content="Nickolay Kovalev (http://resume.nickola.ru)" />
<meta name="robots" content="none" />
<style type="text/css">html{font-family:sans-serif;line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,footer,header,nav,section{display:block}h1{font-size:2em;margin:.67em 0}figcaption,figure,main{display:block}figure{margin:1em 40px}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent;-webkit-text-decoration-skip:objects}a:active,a:hover{outline-width:0}abbr[title]{border-bottom:0;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}dfn{font-style:italic}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}img{border-style:none}svg:not(:root){overflow:hidden}button,input,optgroup,select,textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{display:inline-block;vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details,menu{display:block}summary{display:list-item}canvas{display:inline-block}[hidden],template{display:none}.cmd .format,.cmd .prompt,.cmd .prompt div,.terminal .terminal-output .format,.terminal .terminal-output div div{display:inline-block}.cmd,.terminal h1,.terminal h2,.terminal h3,.terminal h4,.terminal h5,.terminal h6,.terminal pre{margin:0}.terminal h1,.terminal h2,.terminal h3,.terminal h4,.terminal h5,.terminal h6{line-height:1.2em}.cmd .clipboard{position:absolute;left:-16px;top:0;width:10px;height:16px;background:0 0;border:0;color:transparent;outline:0;padding:0;resize:none;z-index:0;overflow:hidden}.terminal .error{color:red}.terminal{padding:10px;position:relative;overflow:auto}.cmd{padding:0;height:1.3em;position:relative}.cmd .cursor.blink,.cmd .inverted,.terminal .inverted{background-color:#aaa;color:#000}.cmd .cursor.blink{-webkit-animation:terminal-blink 1s infinite steps(1,start);-moz-animation:terminal-blink 1s infinite steps(1,start);-ms-animation:terminal-blink 1s infinite steps(1,start);animation:terminal-blink 1s infinite steps(1,start)}@-webkit-keyframes terminal-blink{0%,100%{background-color:#000;color:#aaa}50%{background-color:#bbb;color:#000}}@-ms-keyframes terminal-blink{0%,100%{background-color:#000;color:#aaa}50%{background-color:#bbb;color:#000}}@-moz-keyframes terminal-blink{0%,100%{background-color:#000;color:#aaa}50%{background-color:#bbb;color:#000}}@keyframes terminal-blink{0%,100%{background-color:#000;color:#aaa}50%{background-color:#bbb;color:#000}}.cmd .prompt,.terminal .terminal-output div div{display:block;line-height:14px;height:auto}.cmd .prompt{float:left}.cmd,.terminal{background-color:#000}.terminal-output>div{min-height:14px}.terminal-output>div>div *{word-wrap:break-word}.terminal .terminal-output div span{display:inline-block}.cmd span{float:left}.cmd div,.cmd span,.terminal h1,.terminal h2,.terminal h3,.terminal h4,.terminal h5,.terminal h
</head>
<body>
<div class="configure">
<p>Web Console must be configured before use:</p>
<ul>
<li>Open Web Console PHP file in your favorite text editor.</li>
<li>At the beginning of the file enter your <span class="variable">$USER</span> and <span class="variable">$PASSWORD</span> credentials, edit any other settings that you like (see description in the comments).</li>
<li>Upload changed file to the web server and open it in the browser.</li>
</ul>
<p>For more information visit Web Console website: <a href="http://web-console.org">http://web-console.org</a></p>
</div>
</body>
</html>
<?php
}
else { ?>
<!DOCTYPE html>
<html class="no-js">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Web Console</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="Web Console (http://www.web-console.org)" />
<meta name="author" content="Nickolay Kovalev (http://resume.nickola.ru)" />
<meta name="robots" content="none" />
<style type="text/css">html{font-family:sans-serif;line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,footer,header,nav,section{display:block}h1{font-size:2em;margin:.67em 0}figcaption,figure,main{display:block}figure{margin:1em 40px}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent;-webkit-text-decoration-skip:objects}a:active,a:hover{outline-width:0}abbr[title]{border-bottom:0;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}dfn{font-style:italic}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}img{border-style:none}svg:not(:root){overflow:hidden}button,input,optgroup,select,textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{display:inline-block;vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details,menu{display:block}summary{display:list-item}canvas{display:inline-block}[hidden],template{display:none}.cmd .format,.cmd .prompt,.cmd .prompt div,.terminal .terminal-output .format,.terminal .terminal-output div div{display:inline-block}.cmd,.terminal h1,.terminal h2,.terminal h3,.terminal h4,.terminal h5,.terminal h6,.terminal pre{margin:0}.terminal h1,.terminal h2,.terminal h3,.terminal h4,.terminal h5,.terminal h6{line-height:1.2em}.cmd .clipboard{position:absolute;left:-16px;top:0;width:10px;height:16px;background:0 0;border:0;color:transparent;outline:0;padding:0;resize:none;z-index:0;overflow:hidden}.terminal .error{color:red}.terminal{padding:10px;position:relative;overflow:auto}.cmd{padding:0;height:1.3em;position:relative}.cmd .cursor.blink,.cmd .inverted,.terminal .inverted{background-color:#aaa;color:#000}.cmd .cursor.blink{-webkit-animation:terminal-blink 1s infinite steps(1,start);-moz-animation:terminal-blink 1s infinite steps(1,start);-ms-animation:terminal-blink 1s infinite steps(1,start);animation:terminal-blink 1s infinite steps(1,start)}@-webkit-keyframes terminal-blink{0%,100%{background-color:#000;color:#aaa}50%{background-color:#bbb;color:#000}}@-ms-keyframes terminal-blink{0%,100%{background-color:#000;color:#aaa}50%{background-color:#bbb;color:#000}}@-moz-keyframes terminal-blink{0%,100%{background-color:#000;color:#aaa}50%{background-color:#bbb;color:#000}}@keyframes terminal-blink{0%,100%{background-color:#000;color:#aaa}50%{background-color:#bbb;color:#000}}.cmd .prompt,.terminal .terminal-output div div{display:block;line-height:14px;height:auto}.cmd .prompt{float:left}.cmd,.terminal{background-color:#000}.terminal-output>div{min-height:14px}.terminal-output>div>div *{word-wrap:break-word}.terminal .terminal-output div span{display:inline-block}.cmd span{float:left}.cmd div,.cmd span,.terminal h1,.terminal h2,.terminal h3,.terminal h4,.terminal h5,.terminal h
<script type="text/javascript">!function(a,b){function c(a){return K.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}function d(a){if(!tb[a]){var b=H.body,c=K("<"+a+">").appendTo(b),d=c.css("display");c.remove(),("none"===d||""===d)&&(pb||(pb=H.createElement("iframe"),pb.frameBorder=pb.width=pb.height=0),b.appendChild(pb),qb&&pb.createElement||(qb=(pb.contentWindow||pb.contentDocument).document,qb.write(("CSS1Compat"===H.compatMode?"<!doctype html>":"")+"<html><body>"),qb.close()),c=qb.createElement(a),qb.body.appendChild(c),d=K.css(c,"display"),b.removeChild(pb)),tb[a]=d}return tb[a]}function e(a,b){var c={};return K.each(wb.concat.apply([],wb.slice(0,b)),function(){c[this]=a}),c}function f(){sb=b}function g(){return setTimeout(f,0),sb=K.now()}function h(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function i(){try{return new a.XMLHttpRequest}catch(b){}}function j(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d,e,f,g,h,i,j,k,l=a.dataTypes,m={},n=l.length,o=l[0];for(d=1;n>d;d++){if(1===d)for(e in a.converters)"string"==typeof e&&(m[e.toLowerCase()]=a.converters[e]);if(g=o,o=l[d],"*"===o)o=g;else if("*"!==g&&g!==o){if(h=g+" "+o,i=m[h]||m["* "+o],!i){k=b;for(j in m)if(f=j.split(" "),(f[0]===g||"*"===f[0])&&(k=m[f[1]+" "+o])){j=m[j],j===!0?i=k:k===!0&&(i=j);break}}!i&&!k&&K.error("No conversion from "+h.replace(" "," to ")),i!==!0&&(c=i?i(c):k(j(c)))}}return c}function k(a,c,d){var e,f,g,h,i=a.contents,j=a.dataTypes,k=a.responseFields;for(f in k)f in d&&(c[k[f]]=d[f]);for(;"*"===j[0];)j.shift(),e===b&&(e=a.mimeType||c.getResponseHeader("content-type"));if(e)for(f in i)if(i[f]&&i[f].test(e)){j.unshift(f);break}if(j[0]in d)g=j[0];else{for(f in d){if(!j[0]||a.converters[f+" "+j[0]]){g=f;break}h||(h=f)}g=g||h}return g?(g!==j[0]&&j.unshift(g),d[g]):void 0}function l(a,b,c,d){if(K.isArray(b))K.each(b,function(b,e){c||Ta.test(a)?d(a,e):l(a+"["+("object"==typeof e||K.isArray(e)?b:"")+"]",e,c,d)});else if(c||null==b||"object"!=typeof b)d(a,b);else for(var e in b)l(a+"["+e+"]",b[e],c,d)}function m(a,c){var d,e,f=K.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((f[d]?a:e||(e={}))[d]=c[d]);e&&K.extend(!0,a,e)}function n(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;for(var h,i=a[f],j=0,k=i?i.length:0,l=a===gb;k>j&&(l||!h);j++)h=i[j](c,d,e),"string"==typeof h&&(!l||g[h]?h=b:(c.dataTypes.unshift(h),h=n(a,c,d,e,h,g)));return(l||!h)&&!g["*"]&&(h=n(a,c,d,e,"*",g)),h}function o(a){return function(b,c){if("string"!=typeof b&&(c=b,b="*"),K.isFunction(c))for(var d,e,f,g=b.toLowerCase().split(cb),h=0,i=g.length;i>h;h++)d=g[h],f=/^\+/.test(d),f&&(d=d.substr(1)||"*"),e=a[d]=a[d]||[],e[f?"unshift":"push"](c)}}function p(a,b,c){var d="width"===b?a.offsetWidth:a.offsetHeight,e="width"===b?Oa:Pa,f=0,g=e.length;if(d>0){if("border"!==c)for(;g>f;f++)c||(d-=parseFloat(K.css(a,"padding"+e[f]))||0),"margin"===c?d+=parseFloat(K.css(a,c+e[f]))||0:d-=parseFloat(K.css(a,"border"+e[f]+"Width"))||0;return d+"px"}if(d=Ea(a,b,b),(0>d||null==d)&&(d=a.style[b]||0),d=parseFloat(d)||0,c)for(;g>f;f++)d+=parseFloat(K.css(a,"padding"+e[f]))||0,"padding"!==c&&(d+=parseFloat(K.css(a,"border"+e[f]+"Width"))||0),"margin"===c&&(d+=parseFloat(K.css(a,c+e[f]))||0);return d+"px"}function q(a,b){b.src?K.ajax({url:b.src,async:!1,dataType:"script"}):K.globalEval((b.text||b.textContent||b.innerHTML||"").replace(Ba,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function r(a){var b=H.createElement("div");return Da.appendChild(b),b.innerHTML=a.outerHTML,b.firstChild}function s(a){var b=(a.nodeName||"").toLowerCase();"input"===b?t(a):"script"!==b&&"undefined"!=typeof a.getElementsByTagName&&K.grep(a.getElementsByTagName("input"),t)}function t(a){("checkbox"===a.type||"radio"===a.type)&&(a.defaultChecked=a.checked)}function u(a){return"undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName("*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll("*"):[]}function v(a,b){var c;1===b.nodeType&&(b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),"object"===c?b
},ha=function(a){return K.event.special.hover?a:a.replace(aa,"mouseenter$1 mouseleave$1")};K.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,p,q;if(3!==a.nodeType&&8!==a.nodeType&&c&&d&&(g=K._data(a))){for(d.handler&&(o=d,d=o.handler),d.guid||(d.guid=K.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return"undefined"==typeof K||a&&K.event.triggered===a.type?b:K.event.dispatch.apply(h.elem,arguments)},h.elem=a),c=K.trim(ha(c)).split(" "),j=0;j<c.length;j++)k=_.exec(c[j])||[],l=k[1],m=(k[2]||"").split(".").sort(),q=K.event.special[l]||{},l=(f?q.delegateType:q.bindType)||l,q=K.event.special[l]||{},n=K.extend({type:l,origType:k[1],data:e,handler:d,guid:d.guid,selector:f,quick:fa(f),namespace:m.join(".")},o),p=i[l],p||(p=i[l]=[],p.delegateCount=0,q.setup&&q.setup.call(a,e,m,h)!==!1||(a.addEventListener?a.addEventListener(l,h,!1):a.attachEvent&&a.attachEvent("on"+l,h))),q.add&&(q.add.call(a,n),n.handler.guid||(n.handler.guid=d.guid)),f?p.splice(p.delegateCount++,0,n):p.push(n),K.event.global[l]=!0;a=null}},global:{},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q,r=K.hasData(a)&&K._data(a);if(r&&(m=r.events)){for(b=K.trim(ha(b||"")).split(" "),f=0;f<b.length;f++)if(g=_.exec(b[f])||[],h=i=g[1],j=g[2],h){for(n=K.event.special[h]||{},h=(d?n.delegateType:n.bindType)||h,p=m[h]||[],k=p.length,j=j?new RegExp("(^|\\.)"+j.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null,l=0;l<p.length;l++)q=p[l],(e||i===q.origType)&&(!c||c.guid===q.guid)&&(!j||j.test(q.namespace))&&(!d||d===q.selector||"**"===d&&q.selector)&&(p.splice(l--,1),q.selector&&p.delegateCount--,n.remove&&n.remove.call(a,q));0===p.length&&k!==p.length&&((!n.teardown||n.teardown.call(a,j)===!1)&&K.removeEvent(a,h,r.handle),delete m[h])}else for(h in m)K.event.remove(a,h+b[f],c,d,!0);K.isEmptyObject(m)&&(o=r.handle,o&&(o.elem=null),K.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,f){if(!e||3!==e.nodeType&&8!==e.nodeType){var g,h,i,j,k,l,m,n,o,p,q=c.type||c,r=[];if(da.test(q+K.event.triggered))return;if(q.indexOf("!")>=0&&(q=q.slice(0,-1),h=!0),q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),(!e||K.event.customEvent[q])&&!K.event.global[q])return;if(c="object"==typeof c?c[K.expando]?c:new K.Event(q,c):new K.Event(q),c.type=q,c.isTrigger=!0,c.exclusive=h,c.namespace=r.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,l=q.indexOf(":")<0?"on"+q:"",!e){g=K.cache;for(i in g)g[i].events&&g[i].events[q]&&K.event.trigger(c,d,g[i].handle.elem,!0);return}if(c.result=b,c.target||(c.target=e),d=null!=d?K.makeArray(d):[],d.unshift(c),m=K.event.special[q]||{},m.trigger&&m.trigger.apply(e,d)===!1)return;if(o=[[e,m.bindType||q]],!f&&!m.noBubble&&!K.isWindow(e)){for(p=m.delegateType||q,j=da.test(p+q)?e:e.parentNode,k=null;j;j=j.parentNode)o.push([j,p]),k=j;k&&k===e.ownerDocument&&o.push([k.defaultView||k.parentWindow||a,p])}for(i=0;i<o.length&&!c.isPropagationStopped();i++)j=o[i][0],c.type=o[i][1],n=(K._data(j,"events")||{})[c.type]&&K._data(j,"handle"),n&&n.apply(j,d),n=l&&j[l],n&&K.acceptData(j)&&n.apply(j,d)===!1&&c.preventDefault();return c.type=q,!f&&!c.isDefaultPrevented()&&(!m._default||m._default.apply(e.ownerDocument,d)===!1)&&("click"!==q||!K.nodeName(e,"a"))&&K.acceptData(e)&&l&&e[q]&&("focus"!==q&&"blur"!==q||0!==c.target.offsetWidth)&&!K.isWindow(e)&&(k=e[l],k&&(e[l]=null),K.event.triggered=q,e[q](),K.event.triggered=b,k&&(e[l]=k)),c.result}},dispatch:function(c){c=K.event.fix(c||a.event);var d,e,f,g,h,i,j,k,l,m,n=(K._data(this,"events")||{})[c.type]||[],o=n.delegateCount,p=[].slice.call(arguments,0),q=!c.exclusive&&!c.namespace,r=[];if(p[0]=c,c.delegateTarget=this,o&&!c.target.disabled&&(!c.button||"click"!==c.type))for(g=K(this),g.context=this.ownerDocument||this,f=c.target;f!=this;f=f.parentNode||this){for(i={},k=[],g[0]=f,d=0;o>d;d++)l=n[d],m=l.selector,i[m]===b&&(i[m]=l.quick?ga(f,l.quick):g.is(m)),i[m]&&k.push(l);k.length&&r.push({elem:f,matches:k})}for(n.length>o&&r.push
if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=K.clean(arguments);return a.push.apply(a,this.toArray()),this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);return a.push.apply(a,K.clean(arguments)),a}},remove:function(a,b){for(var c,d=0;null!=(c=this[d]);d++)(!a||K.filter(a,[c]).length)&&(!b&&1===c.nodeType&&(K.cleanData(c.getElementsByTagName("*")),K.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)for(1===a.nodeType&&K.cleanData(a.getElementsByTagName("*"));a.firstChild;)a.removeChild(a.firstChild);return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return K.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&1===this[0].nodeType?this[0].innerHTML.replace(qa,""):null;if("string"!=typeof a||wa.test(a)||!K.support.leadingWhitespace&&ra.test(a)||Ca[(ta.exec(a)||["",""])[1].toLowerCase()])K.isFunction(a)?this.each(function(b){var c=K(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);else{a=a.replace(sa,"<$1></$2>");try{for(var c=0,d=this.length;d>c;c++)1===this[c].nodeType&&(K.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}return this},replaceWith:function(a){return this[0]&&this[0].parentNode?K.isFunction(a)?this.each(function(b){var c=K(this),d=c.html();c.replaceWith(a.call(this,b,d))}):("string"!=typeof a&&(a=K(a).detach()),this.each(function(){var b=this.nextSibling,c=this.parentNode;K(this).remove(),b?K(b).before(a):K(c).append(a)})):this.length?this.pushStack(K(K.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,f,g,h,i=a[0],j=[];if(!K.support.checkClone&&3===arguments.length&&"string"==typeof i&&za.test(i))return this.each(function(){K(this).domManip(a,c,d,!0)});if(K.isFunction(i))return this.each(function(e){var f=K(this);a[0]=i.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){if(h=i&&i.parentNode,e=K.support.parentNode&&h&&11===h.nodeType&&h.childNodes.length===this.length?{fragment:h}:K.buildFragment(a,this,j),g=e.fragment,f=1===g.childNodes.length?g=g.firstChild:g.firstChild,f){c=c&&K.nodeName(f,"tr");for(var k=0,l=this.length,m=l-1;l>k;k++)d.call(c?x(this[k],f):this[k],e.cacheable||l>1&&m>k?K.clone(g,!0,!0):g)}j.length&&K.each(j,q)}return this}}),K.buildFragment=function(a,b,c){var d,e,f,g,h=a[0];return b&&b[0]&&(g=b[0].ownerDocument||b[0]),g.createDocumentFragment||(g=H),1===a.length&&"string"==typeof h&&h.length<512&&g===H&&"<"===h.charAt(0)&&!xa.test(h)&&(K.support.checkClone||!za.test(h))&&(K.support.html5Clone||!ya.test(h))&&(e=!0,f=K.fragments[h],f&&1!==f&&(d=f)),d||(d=g.createDocumentFragment(),K.clean(a,g,d,c)),e&&(K.fragments[h]=f?d:1),{fragment:d,cacheable:e}},K.fragments={},K.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){K.fn[a]=function(c){var d=[],e=K(c),f=1===this.length&&this[0].parentNode;if(f&&11===f.nodeType&&1===f.childNodes.length&&1===e.length)return e[b](this[0]),this;for(var g=0,h=e.length;h>g;g++){var i=(g>0?this.clone(!0):this).get();K(e[g])[b](i),d=d.concat(i)}return this.pushStack(d,a,e.selector)}}),K.extend({clone:function(a,b,c){var d,e,f,g=K.support.html5Clone||!ya.test("<"+a.nodeName)?a.cloneNode(!0):r(a);if(!(K.support.noCloneEvent&&K.support.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||K.isXMLDoc(a)))for(v(a,g),d=u(a),e=u(g),f=0;d[f];++f)e[f]&&v(d[f],e[f]);if(b&&(w(a,g),c))for(d=u(a),e=u(g),f=0;d[f];++f)w(d[f],e[f]);return d=e=null,g},clean:function(a,b,c,d){var e;b=b||H,"undefined"==typeof b.createElement&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||H);for(var f,g,h=[],i=0;null!=(g=a[i]);i++)if("number"==
f.push(h[1])}c[2]=f}else e|=2;if(3===e)throw"[sprintf] mixing positional and named placeholders is not (yet) supported";d.push(c)}b=b.substring(c[0].length)}return d};var e=function(a,b,c){return c=b.slice(0),c.splice(0,0,a),d.apply(null,c)};a.sprintf=d,a.vsprintf=e}("undefined"!=typeof global?global:window),function(a,b){"use strict";function c(a,b){var c;if("string"==typeof a&&"string"==typeof b)return localStorage[a]=b,!0;if("object"==typeof a&&"undefined"==typeof b){for(c in a)a.hasOwnProperty(c)&&(localStorage[c]=a[c]);return!0}return!1}function d(a,b){var c,d,e;if(c=new Date,c.setTime(c.getTime()+31536e6),d="; expires="+c.toGMTString(),"string"==typeof a&&"string"==typeof b)return document.cookie=a+"="+b+d+"; path=/",!0;if("object"==typeof a&&"undefined"==typeof b){for(e in a)a.hasOwnProperty(e)&&(document.cookie=e+"="+a[e]+d+"; path=/");return!0}return!1}function e(a){return localStorage[a]}function f(a){var b,c,d,e;for(b=a+"=",c=document.cookie.split(";"),d=0;d<c.length;d++){for(e=c[d];" "===e.charAt(0);)e=e.substring(1,e.length);if(0===e.indexOf(b))return e.substring(b.length,e.length)}return null}function g(a){return delete localStorage[a]}function h(a){return d(a,"",-1)}function i(a,b){var c=[],d=a.length;if(b>d)return[a];if(0>b)throw new Error("str_parts: length can't be negative");for(var e=0;d>e;e+=b)c.push(a.substring(e,e+b));return c}function j(b){var c=b?[b]:[],d=0;a.extend(this,{get:function(){return c},rotate:function(){return c.filter(Boolean).length?1===c.length?c[0]:(d===c.length-1?d=0:++d,c[d]?c[d]:this.rotate()):void 0},length:function(){return c.length},remove:function(a){delete c[a]},set:function(a){for(var b=c.length;b--;)if(c[b]===a)return void(d=b);this.append(a)},front:function(){if(c.length){for(var a=d,b=!1;!c[a];)if(a++,a>c.length){if(b)break;a=0,b=!0}return c[a]}},append:function(a){c.push(a)}})}function k(b){var c=b instanceof Array?b:b?[b]:[];a.extend(this,{data:function(){return c},map:function(b){return a.map(c,b)},size:function(){return c.length},pop:function(){if(0===c.length)return null;var a=c[c.length-1];return c=c.slice(0,c.length-1),a},push:function(a){return c=c.concat([a]),a},top:function(){return c.length>0?c[c.length-1]:null},clone:function(){return new k(c.slice(0))}})}function l(b,c){var d=!0,e="";"string"==typeof b&&""!==b&&(e=b+"_"),e+="commands";var f=a.Storage.get(e);f=f?a.parseJSON(f):[];var g=f.length-1;a.extend(this,{append:function(b){d&&f[f.length-1]!==b&&(f.push(b),c&&f.length>c&&(f=f.slice(-c)),g=f.length-1,a.Storage.set(e,a.json_stringify(f)))},data:function(){return f},reset:function(){g=f.length-1},last:function(){return f[f.length-1]},end:function(){return g===f.length-1},position:function(){return g},current:function(){return f[g]},next:function(){return g<f.length-1&&++g,-1!==g?f[g]:void 0},previous:function(){var a=g;return g>0&&--g,-1!==a?f[g]:void 0},clear:function(){f=[],this.purge()},enabled:function(){return d},enable:function(){d=!0},purge:function(){a.Storage.remove(e)},disable:function(){d=!1}})}function m(b){return a("<div>"+a.terminal.strip(b)+"</div>").text().length}function n(b,c){var d=c(b);if(d.length){var e=d.shift(),f=new RegExp("^"+a.terminal.escape_regex(e)),g=b.replace(f,"").trim();return{command:b,name:e,args:d,rest:g}}return{command:b,name:"",args:[],rest:""}}function o(){var b=a('<div class="terminal temp"><div class="cmd"><span class="cursor">&nbsp;</span></div></div>').appendTo("body"),c=b.find("span"),d={width:c.width(),height:c.outerHeight()};return b.remove(),d}function p(b){var c=a('<div class="terminal wrap"><span class="cursor">&nbsp;</span></div>').appendTo("body").css("padding",0),d=c.find("span"),e=d[0].getBoundingClientRect().width,f=Math.floor(b.width()/e);if(c.remove(),s(b)){var g=20,h=b.innerWidth()-b.width();f-=Math.ceil((g-h/2)/(e-1))}return f}function q(a){return Math.floor(a.height()/o().height)}function r(){if(window.getSelection||document.getSelection){var a=(window.getSelection||document.getSelection)();return a.text?a.text:a.toString()}return document.selection?document
var g=b.token();g?d(a.name,[g].concat(a.args)):b.error("&#91;AUTH&#93; "+ya.noTokenError)}else d(a.name,a.args)}}}function j(c,d,f,g){return function(h,i){if(""!==h){var k;try{k=e(h)}catch(l){return void ha.error(l.toString())}var m=c[k.name],n=a.type(m);if("function"===n){if(!d||m.length===k.args.length)return m.apply(ha,k.args);ha.error("&#91;Arity&#93; "+sprintf(ya.wrongArity,k.name,m.length,k.args.length))}else if("object"===n||"string"===n){var o=[];"object"===n&&(o=Object.keys(m),m=j(m,d,f)),i.push(m,{prompt:k.name+"> ",name:k.name,completion:"object"===n?o:b})}else a.isFunction(g)?g(h,ha):a.isFunction(xa.onCommandNotFound)?xa.onCommandNotFound(h,ha):i.error(sprintf(ya.commandNotFound,k.name))}}}function l(b,c,d){ha.resume(),a.isFunction(xa.onAjaxError)?xa.onAjaxError.call(ha,b,c,d):"abort"!==c&&ha.error("&#91;AJAX&#93; "+c+" - "+ya.serverResponse+": \n"+a.terminal.escape_brackets(b.responseText))}function m(b,c,d){a.jrpc(b,"system.describe",[],function(e){if(e.procs){var g={};a.each(e.procs,function(d,e){g[e.name]=function(){var d=c&&"help"!=e.name,g=Array.prototype.slice.call(arguments),i=g.length+(d?1:0);if(xa.checkArity&&e.params&&e.params.length!==i)ha.error("&#91;Arity&#93; "+sprintf(ya.wrongArity,e.name,e.params.length,i));else{if(ha.pause(),d){var j=ha.token(!0);j?g=[j].concat(g):ha.error("&#91;AUTH&#93; "+ya.noTokenError)}a.jrpc(b,e.name,g,function(b){b.error?h(b.error):a.isFunction(xa.processRPCResponse)?xa.processRPCResponse.call(ha,b.result,ha):f(b.result),ha.resume()},l)}}}),g.help=g.help||function(b){if("undefined"==typeof b)ha.echo("Available commands: "+e.procs.map(function(a){return a.name}).join(", ")+", help");else{var c=!1;if(a.each(e.procs,function(a,d){if(d.name==b){c=!0;var e="";return e+="[[bu;#fff;]"+d.name+"]",d.params&&(e+=" "+d.params.join(" ")),d.help&&(e+="\n"+d.help),ha.echo(e),!1}}),!c)if("help"==b)ha.echo("[[bu;#fff;]help] [method]\ndisplay help for the method or list of methods if not specified");else{var d="Method `"+b.toString()+"' not found ";ha.error(d)}}},d(g)}else d(null)},function(){d(null)})}function o(b,c,d){d=d||a.noop;var e,f,g=a.type(b),h={},k=0;if("array"===g)e={},function l(b,d){if(b.length){var g=b[0],h=b.slice(1),j=a.type(g);"string"===j?(k++,ha.pause(),xa.ignoreSystemDescribe?(1===k?f=i(g,c):ha.error(ya.oneRPCWithIgnore),l(h,d)):m(g,c,function(b){b&&a.extend(e,b),ha.resume(),l(h,d)})):"function"===j?(f?ha.error(ya.oneInterpreterFunction):f=g,l(h,d)):"object"===j&&(a.extend(e,g),l(h,d))}else d()}(b,function(){d({interpreter:j(e,!1,c,f),completion:Object.keys(e)})});else if("string"===g)xa.ignoreSystemDescribe?(e={interpreter:i(b,c)},a.isArray(xa.completion)&&(e.completion=xa.completion),d(e)):(ha.pause(),m(b,c,function(a){a?(h.interpreter=j(a,!1,c),h.completion=Object.keys(a)):h.interpreter=i(b,c),d(h),ha.resume()}));else if("object"===g)d({interpreter:j(b,xa.checkArity),completion:Object.keys(b)});else{if("undefined"===g)b=a.noop;else if("function"!==g)throw g+" is invalid interpreter value";d({interpreter:b,completion:xa.completion})}}function t(b,c){var d="boolean"===a.type(c)?"login":c;return function(c,e,f,g){ha.pause(),a.jrpc(b,d,[c,e],function(a){f(!a.error&&a.result?a.result:null),ha.resume()},l)}}function v(a){return"string"==typeof a?a:"string"==typeof a.fileName?a.fileName+": "+a.message:a.message}function w(b,c){a.isFunction(xa.exceptionHandler)?xa.exceptionHandler.call(ha,b):ha.exception(b,c)}function x(){var a;a=ia.prop?ia.prop("scrollHeight"):ia.attr("scrollHeight"),ia.scrollTop(a)}function y(b,c){try{if(a.isFunction(c))c(function(){});else if("string"!=typeof c){var d=b+" must be string or function";throw d}}catch(e){return w(e,b.toUpperCase()),!1}return!0}function z(b,c){xa.convertLinks&&(b=b.replace(K,"[[!;;]$1]").replace(J,"[[!;;]$1]"));var d,e,f=a.terminal.defaults.formatters;if(!c.raw){for(d=0;d<f.length;++d)try{if("function"==typeof f[d]){var g=f[d](b);"string"==typeof g&&(b=g)}}catch(h){alert("formatting error at formatters["+d+"]\n"+(h.stack?h.stack:h))}b=a.terminal.encode(b)}if(da.push(ea),!c.raw&&(b.l
</head>
<body></body>
</html>
<?php } ?>