Files
overwatch/Ov3rw4tch.class.php

275 lines
8.0 KiB
PHP

<?php
/**
* ../overwatch/Ov3rw4tch.class.php
* Overwatchd
* @package default
*/
define("OVERWATCH_ROOT", dirname(__FILE__));
define("OVERWATCH_LIBRARIES", OVERWATCH_ROOT.DIRECTORY_SEPARATOR."lib");
define("OVERWATCH_MODULES", OVERWATCH_LIBRARIES.DIRECTORY_SEPARATOR."modules".DIRECTORY_SEPARATOR);
// Load in module support and required classes.
require_once "vendor/autoload.php";
require_once OVERWATCH_LIBRARIES.DIRECTORY_SEPARATOR."libModOverwatch.class.php";
require_once OVERWATCH_LIBRARIES.DIRECTORY_SEPARATOR."libOverwatchAPI.class.php";
require_once OVERWATCH_LIBRARIES.DIRECTORY_SEPARATOR."libAPIQL.class.php";
require_once OVERWATCH_ROOT.DIRECTORY_SEPARATOR."sdk".DIRECTORY_SEPARATOR."OverwatchSDK.inc.php";
if(\Overwatch\SDK\Manager::isSDK_Installed("1") == false)
{
die("OverwatchSDK is missing, possibly a bad build, or tree?");
}
use Noodlehaus\Config;
echo PHP_EOL;
#error_reporting(0);
$quit = 0;
$arrOverwatch_Config = array();
$arrOverwatch_SystemConfig = array();
$application_channel = "release";
// Load version information from built-in version file. (used for releases)
if(file_exists(OVERWATCH_ROOT.DIRECTORY_SEPARATOR."build".DIRECTORY_SEPARATOR."version"))
{
$version = file_get_contents(OVERWATCH_ROOT.DIRECTORY_SEPARATOR."build".DIRECTORY_SEPARATOR."version");
}
// Load (or override local) version information using git repository.
if (file_exists(".git")) {
$version = `git describe`;
$application_channel = "dev";
}
// Define engine version so that plugins can check against it.
// We will want to define the local version information (built into the phar if compiled)
// rather than the git version, unless there's a decent way to compare versions provided by git describe.
define("OVERWATCH_VERSION", $version);
// Load the core version from the phar if we're running compiled.
if(file_exists(OVERWATCH_ROOT.DIRECTORY_SEPARATOR."build".DIRECTORY_SEPARATOR."core-version"))
{
$coreversion = file_get_contents(OVERWATCH_ROOT.DIRECTORY_SEPARATOR."build".DIRECTORY_SEPARATOR."core-version");
} else {
$coreversion = $version;
}
// Now we'll define the core version of the software as well.
$coreversion = str_replace(array("\n", "\r"), "", $coreversion);
$version = str_replace(array("\n", "\r"), "", $version);
\Overwatch\SDK\v1\Utility::Log("Overwatchd startup, version: $version (built from: $coreversion), channel: $application_channel", "OVERWATCH");
// We look for a system-wide configuration file for the daemon in /etc. If one is not available,
// we then skip it.
if(file_exists(__FILE__.DIRECTORY_SEPARATOR."overwatchd.conf.dist"))
{
$configFiles = array(__FILE__.DIRECTORY_SEPARATOR."overwatchd.conf.dist");
}
if(file_exists("/etc/overwatchd.conf"))
{
array_push($configFiles,"/etc/overwatchd.conf");
}
if(file_exists(__FILE__.DIRECTORY_SEPARATOR."overwatchd.conf"))
{
array_push($configFiles,__FILE__.DIRECTOR_SEPARATOR."overwatchd.conf");
}
if(isset($configFiles))
{
$arrOverwatch_Config = new Config($configFiles);
}
// We're now looking for a local configuration file for the daemon.
// Allow turning on debug mode from a configuration option.
if(array_key_exists("DEBUG",$arrOverwatch_Config) OR $application_channel == "dev")
{
if(array_key_exists("DEBUG", $arrOverwatch_Config) AND $arrOverwatch_Config['DEBUG'] == "true")
{
define("DEBUG",true);
\Overwatch\SDK\v1\Utility::Log("Enabling debug mode due to configuration flag..", "DEBUG");
} elseif ($application_channel == "dev")
{
define("DEBUG", true);
\Overwatch\SDK\v1\Utility::Log("We're running under the dev channel. Debug Ahoy!", "DEBUG");
}
}
\Overwatch\SDK\v1\Utility::Log("Loading built-in API Modules...", "OVERWATCH");
LoadAPIModules(OVERWATCH_MODULES);
LoadModulesFromConfiguration();
$state = array();
// We're going to register a shutdown command so that we can easily shutdown the system remotely,
// only when we're in debug mode though. We'll also turn on PHP's error messages.
if(defined("DEBUG"))
{
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
apiql::register("!SHUTDOWN[json]", "Shutdown");
$quit == 2;
} else {
error_reporting(0);
}
function is_base64($str) {
if (!preg_match('~[^0-9a-zA-Z+/=]~', $str)) {
$check = str_split(base64_decode($str));
$x = 0;
foreach ($check as $char) if (ord($char) > 126) $x++;
if ($x/count($check)*100 < 30) return true;
}
return false;
}
// Let's set up the event loop
$loop = React\EventLoop\Factory::create();
// Now that the rest is set up, let's start the actual server.
$socket = new React\Socket\Server($loop);
$clients = new SplObjectStorage();
$i = 0;
$socket->on('connection', function($connection) use ($clients, &$i) {
$connection->id = ++$i;
// Socket Listener
$connection->on('data', function($message) use ($clients, $connection) {
$connection->lastAPI = str_replace(array("\n", "\r\n", "\r"), '', $message);
if(strpos($connection->lastAPI, " {") == 0)
{
if (is_base64($connection->lastAPI) == true) {
\Overwatch\SDK\v1\Utility::Log("Raw data from conection: $connection->id, $connection->lastAPI","S2S-COMMS-DEBUG",\Overwatch\SDK\v1\Utility::OVR_UTIL_LOGLEVEL_DEBUG);
$connection->lastAPI = base64_decode($connection->lastAPI);
}
}
$connection->lastAPI = str_replace("'", "\"", $connection->lastAPI);
# Let's pull apart the current request to check for a connection-id item. If it doesn't exist, we'll inject it in.
$command = explode (" {", $connection->lastAPI, 2);
if(isset($command[1]))
{
$commandJSON = json_decode("{".$command[1], true);
}
if(!isset($commandJSON['connection-id']))
{
$commandJSON['connection-id'] = $connection->id;
$commandJSON = json_encode($commandJSON);
$connection->lastAPI = rtrim($command[0]," ")." ".$commandJSON;
}
$connection->lastResult = apicall($connection->lastAPI);
\Overwatch\SDK\v1\Utility::Log("Received query: ".$connection->lastAPI." from ".$connection->id, "SOCKET-API");
foreach ($clients as $client) {
if ($client->id == $connection->id) {
if($connection->lastResult != NULL)
{
$client->write($connection->lastResult."\r\n");
}
} else {
continue;
}
}
});
$clients->attach($connection);
});
if (empty($arrOverwatch_Config['API_PORT'])) {
$API_PORT="1337";
} else {
$API_PORT= $arrOverwatch_Config['API_PORT'];
}
// Start listening on the configured port.
$socket->listen($API_PORT, "0.0.0.0");
\Overwatch\SDK\v1\Utility::Log("Server listening on port: $API_PORT", "OVERWATCH");
// Now we begin the actual event loop.
$loop->run();
/**
*
* @return unknown
*/
function Shutdown($sql) {
global $quit;
global $loop;
$loop->stop();
$quit = 1;
return "Shutting Down.";
exit(0);
}
/**
*
* @param unknown $call
* @param unknown $apiKey (optional)
* @return unknown
*/
function APIcall($call, $apiKey = null) {
#LogEcho("APIcall($call)","S2S-DEBUG");
$APIResponse = apiql::query($call);
if ($APIResponse == NULL) {
$ResponseArray = array('response_type'=>"error",
'response_data'=>array('type'=>'APIcall',
'data'=>$call,
'response'=>$APIResponse),
'response_code'=>'OVW_404');
return "ERROR ".json_encode($ResponseArray);
} else {
if(empty($APIResponse) or $APIResponse == "1")
{
return NULL;
}
if(is_array($APIResponse))
{
$APIResponse = json_encode($APIResponse);
}
return $APIResponse;
}
}
function LoadModulesFromConfiguration()
{
global $arrOverwatch_Config;
if(array_key_exists("MODULES_DIR", $arrOverwatch_Config))
{
\Overwatch\SDK\v1\Utility::Log("External module directory defined, loading external modules...","OVERWATCH");
LoadAPIModules($arrOverwatch_Config['MODULES_DIR']);
}
if(array_key_exists("SYSTEM_MODULES_DIR", $arrOverwatch_Config))
{
\Overwatch\SDK\v1\Utility::Log("Loading modules from system store: ".$arrOverwatch_Config['SYSTEM_MODULES_DIR']);
LoadAPIModules($arrOverwatch_Config['SYSTEM_MODULES_DIR']);
}
}
function is_json($json)
{
json_decode($json);
return (json_last_error() == JSON_ERROR_NONE);
}
?>