Imports code from RippingCluster project
Imports all generic classes from the RippingCluster project, with any ripping-specific code stripped out. Tested against a dummy project for errors.
This commit is contained in:
5
.buildpath
Normal file
5
.buildpath
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<buildpath>
|
||||||
|
<buildpathentry kind="src" path="source"/>
|
||||||
|
<buildpathentry kind="con" path="org.eclipse.php.core.LANGUAGE"/>
|
||||||
|
</buildpath>
|
||||||
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# Eclipse metadata
|
||||||
|
/.buildpath
|
||||||
|
/.project
|
||||||
|
/.settings/
|
||||||
|
|
||||||
22
.project
Normal file
22
.project
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>sihnon-php-lib</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.wst.validation.validationbuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.dltk.core.scriptbuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.php.core.PHPNature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
||||||
7
.settings/org.eclipse.php.core.prefs
Normal file
7
.settings/org.eclipse.php.core.prefs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#Sun Oct 10 10:59:03 BST 2010
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
include_path=0;/sihnon-php-lib/source
|
||||||
|
org.eclipse.php.core.phpForamtterIndentationSize=4
|
||||||
|
org.eclipse.php.core.phpForamtterUseTabs=false
|
||||||
|
phpVersion=php5.3
|
||||||
|
use_asp_tags_as_php=false
|
||||||
3
.settings/org.eclipse.php.ui.prefs
Normal file
3
.settings/org.eclipse.php.ui.prefs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#Sun Oct 10 10:59:06 BST 2010
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.php.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates/>
|
||||||
32
private/config.php.dist
Normal file
32
private/config.php.dist
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sihnon Library path
|
||||||
|
*
|
||||||
|
* Specifies the absolute or relative path to the Sihnon library directory, relative to the webui root directory.
|
||||||
|
* Path must end with a trailing slash.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
define('Sihnon_Lib', '../lib/');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sihnon Database Configuration
|
||||||
|
*
|
||||||
|
* Specifies the absolute or relative path to the Sihnon database configuration file.
|
||||||
|
* This is a standard ini type file, containing the config required to connect to the database.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
define('Sihnon_DBConfig', '../dbconfig.conf');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sihnon Log Table
|
||||||
|
*
|
||||||
|
* Specifies the name of the database table used to store log entries for this application.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
define('Sihnon_Log_Table', 'logs');
|
||||||
|
|
||||||
|
?>
|
||||||
5
private/dbconfig.conf.dist
Normal file
5
private/dbconfig.conf.dist
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
hostname = localhost
|
||||||
|
username = username
|
||||||
|
password = password
|
||||||
|
dbname = database
|
||||||
|
|
||||||
17
source/lib/Sihnon/BackgroundTask.class.php
Normal file
17
source/lib/Sihnon/BackgroundTask.class.php
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class Sihnon_BackgroundTask {
|
||||||
|
|
||||||
|
protected function __construct() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function run($command) {
|
||||||
|
$pipes = array();
|
||||||
|
$pid = proc_open($command . ' &', array(), $pipes);
|
||||||
|
proc_close($pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
?>
|
||||||
62
source/lib/Sihnon/Cache.class.php
Normal file
62
source/lib/Sihnon/Cache.class.php
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class Sihnon_Cache {
|
||||||
|
|
||||||
|
protected $config;
|
||||||
|
protected $cache_dir;
|
||||||
|
|
||||||
|
public function __construct(Sihnon_Config $config) {
|
||||||
|
$this->config = $config;
|
||||||
|
$this->cache_dir = $config->get('cache.base_dir');
|
||||||
|
|
||||||
|
if (is_dir($this->cache_dir)) {
|
||||||
|
if ( ! is_writeable($this->cache_dir)) {
|
||||||
|
throw new Sihnon_Exception_InvalidCacheDir();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ( ! Sihnon_Main::mkdir_recursive($this->cache_dir)) {
|
||||||
|
throw new Sihnon_Exception_InvalidCacheDir();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function cacheFilename($source_filename) {
|
||||||
|
return $this->cache_dir . sha1($source_filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function exists($source_filename, $ttl = 3600) {
|
||||||
|
$cache_filename = $this->cacheFilename($source_filename);
|
||||||
|
|
||||||
|
// Check to see if the file is cached
|
||||||
|
if (!file_exists($cache_filename)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check to see if the cache has expired
|
||||||
|
if (filemtime($cache_filename) + $ttl < time()) {
|
||||||
|
// Delete the cached item
|
||||||
|
unlink($cache_filename);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store($source_filename, $content) {
|
||||||
|
$cache_filename = $this->cacheFilename($source_filename);
|
||||||
|
return file_put_contents($cache_filename, $content);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fetch($source_filename, $ttl = 3600) {
|
||||||
|
$cache_filename = $this->cacheFilename($source_filename);
|
||||||
|
|
||||||
|
if (!$this->exists($source_filename)) {
|
||||||
|
throw new Sihnon_Exception_CacheObjectNotFound($source_filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
return file_get_contents($cache_filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
?>
|
||||||
145
source/lib/Sihnon/Config.class.php
Normal file
145
source/lib/Sihnon/Config.class.php
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class Sihnon_Config {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Boolean value type
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
const TYPE_BOOL = 'bool';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integer value type
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
const TYPE_INT = 'int';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Float value type
|
||||||
|
* @var float
|
||||||
|
*/
|
||||||
|
const TYPE_FLOAT = 'float';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String value type
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const TYPE_STRING = 'string';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String List value type; list of newline separated strings
|
||||||
|
* @var array(string)
|
||||||
|
*/
|
||||||
|
const TYPE_STRING_LIST = 'array(string)';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contents of the dbconfig file
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $dbconfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Database object created for the lifetime of this script
|
||||||
|
* @var Sihnon_Database
|
||||||
|
*/
|
||||||
|
private $database;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Associative array of connection parameters for the database configuration
|
||||||
|
* @var array(string=>string)
|
||||||
|
*/
|
||||||
|
private $databaseConfig = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Associative array of settings loaded from the database
|
||||||
|
* @var array(string=>array(string=>string))
|
||||||
|
*/
|
||||||
|
private $settings = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new instance of the Config class
|
||||||
|
*
|
||||||
|
* @param string $dbconfig Database configuration file contents
|
||||||
|
* @return Sihnon_Config
|
||||||
|
*/
|
||||||
|
public function __construct($dbconfig) {
|
||||||
|
$this->dbconfig = $dbconfig;
|
||||||
|
|
||||||
|
$this->parseDatabaseConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the contents of the database configuration file so that individual settings can be retrieved.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function parseDatabaseConfig() {
|
||||||
|
$this->databaseConfig = parse_ini_file($this->dbconfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of the named item from the database configuration file
|
||||||
|
*
|
||||||
|
* @param string $key Name of the setting to retrieve
|
||||||
|
*/
|
||||||
|
public function getDatabase($key) {
|
||||||
|
if (!isset($this->databaseConfig[$key])) {
|
||||||
|
throw new Sihnon_Exception_DatabaseConfigMissing($key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->databaseConfig[$key];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the database instance used by this object
|
||||||
|
*
|
||||||
|
* @param Sihnon_Database $database Database instance
|
||||||
|
*/
|
||||||
|
public function setDatabase(Sihnon_Database $database) {
|
||||||
|
$this->database = $database;
|
||||||
|
$this->preload();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the entire list of settings from the database
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private function preload() {
|
||||||
|
if (!$this->database) {
|
||||||
|
throw new Sihnon_Exception_NoDatabaseConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->settings = $this->database->selectAssoc('SELECT name,type,value FROM settings', 'name', array('name', 'value', 'type'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifies whether the named setting exists
|
||||||
|
*
|
||||||
|
* @param string $key Name of the setting
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function exists($key) {
|
||||||
|
return isset($this->settings[$key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the value of the named setting
|
||||||
|
*
|
||||||
|
* @param string $key Name of the setting
|
||||||
|
*/
|
||||||
|
public function get($key) {
|
||||||
|
if (!isset($this->settings[$key])) {
|
||||||
|
throw new Sihnon_Exception_UnknownSetting($key);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($this->settings[$key]['type']) {
|
||||||
|
case self::TYPE_STRING_LIST:
|
||||||
|
return array_map('trim', explode("\n", $this->settings[$key]['value']));
|
||||||
|
|
||||||
|
default:
|
||||||
|
return $this->settings[$key]['value'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
?>
|
||||||
141
source/lib/Sihnon/Database.class.php
Normal file
141
source/lib/Sihnon/Database.class.php
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class Sihnon_Database {
|
||||||
|
|
||||||
|
private $config;
|
||||||
|
private $dbh;
|
||||||
|
|
||||||
|
private $hostname;
|
||||||
|
private $username;
|
||||||
|
private $password;
|
||||||
|
private $dbname;
|
||||||
|
|
||||||
|
private $prepared_statements = array();
|
||||||
|
|
||||||
|
public function __construct(Sihnon_Config $config) {
|
||||||
|
$this->config = $config;
|
||||||
|
|
||||||
|
$this->hostname = $this->config->getDatabase('hostname');
|
||||||
|
$this->username = $this->config->getDatabase('username');
|
||||||
|
$this->password = $this->config->getDatabase('password');
|
||||||
|
$this->dbname = $this->config->getDatabase('dbname');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->dbh = new PDO("mysql:host={$this->hostname};dbname={$this->dbname}", $this->username, $this->password);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
throw new Sihnon_Exception_DatabaseConnectFailed($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __destruct() {
|
||||||
|
$this->dbh = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function selectAssoc($sql, $key_col, $value_cols) {
|
||||||
|
$results = array();
|
||||||
|
|
||||||
|
foreach ($this->dbh->query($sql) as $row) {
|
||||||
|
if (is_array($value_cols)) {
|
||||||
|
$values = array();
|
||||||
|
foreach ($value_cols as $value_col) {
|
||||||
|
$values[$value_col] = $row[$value_col];
|
||||||
|
}
|
||||||
|
|
||||||
|
$results[$row[$key_col]] = $values;
|
||||||
|
} else {
|
||||||
|
$results[$row[$key_col]] = $row[$value_col];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function selectList($sql, $bind_params = null) {
|
||||||
|
if ($bind_params) {
|
||||||
|
$stmt = $this->dbh->prepare($sql);
|
||||||
|
|
||||||
|
foreach ($bind_params as $param) {
|
||||||
|
$stmt->bindValue(':'.$param['name'], $param['value'], $param['type']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = $stmt->execute();
|
||||||
|
if (!$result) {
|
||||||
|
list($dummy, $code, $message) = $stmt->errorInfo();
|
||||||
|
throw new Sihnon_Exception_DatabaseQueryFailed($message, $code);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $stmt->fetchAll();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$results = array();
|
||||||
|
|
||||||
|
$result = $this->dbh->query($sql);
|
||||||
|
foreach ($result as $row) {
|
||||||
|
$results[] = $row;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function selectOne($sql, $bind_params = null) {
|
||||||
|
$rows = $this->selectList($sql, $bind_params);
|
||||||
|
if (count($rows) != 1) {
|
||||||
|
throw new Sihnon_Exception_ResultCountMismatch(count($rows));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $rows[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function insert($sql, $bind_params = null) {
|
||||||
|
$stmt = $this->dbh->prepare($sql);
|
||||||
|
|
||||||
|
if ($bind_params) {
|
||||||
|
foreach ($bind_params as $param) {
|
||||||
|
if (isset($param['type'])) {
|
||||||
|
$stmt->bindValue(':'.$param['name'], $param['value'], $param['type']);
|
||||||
|
} else {
|
||||||
|
$stmt->bindValue(':'.$param['name'], $param['value']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = $stmt->execute();
|
||||||
|
if (!$result) {
|
||||||
|
list($code, $dummy, $message) = $stmt->errorInfo();
|
||||||
|
throw new Sihnon_Exception_DatabaseQueryFailed($message, $code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update($sql, $bind_params = null) {
|
||||||
|
$stmt = $this->dbh->prepare($sql);
|
||||||
|
|
||||||
|
if ($bind_params) {
|
||||||
|
foreach ($bind_params as $param) {
|
||||||
|
if (isset($param['type'])) {
|
||||||
|
$stmt->bindValue(':'.$param['name'], $param['value'], $param['type']);
|
||||||
|
} else {
|
||||||
|
$stmt->bindValue(':'.$param['name'], $param['value']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = $stmt->execute();
|
||||||
|
if (!$result) {
|
||||||
|
list($code, $dummy, $message) = $stmt->errorInfo();
|
||||||
|
throw new Sihnon_Exception_DatabaseQueryFailed($message, $code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function errorInfo() {
|
||||||
|
return $this->dbh->errorInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function lastInsertId() {
|
||||||
|
return $this->dbh->lastInsertId();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
21
source/lib/Sihnon/Exceptions.class.php
Normal file
21
source/lib/Sihnon/Exceptions.class.php
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class Sihnon_Exception extends Exception {};
|
||||||
|
|
||||||
|
class Sihnon_Exception_DatabaseException extends Sihnon_Exception {};
|
||||||
|
class Sihnon_Exception_DatabaseConfigMissing extends Sihnon_Exception_DatabaseException {};
|
||||||
|
class Sihnon_Exception_DatabaseConnectFailed extends Sihnon_Exception_DatabaseException {};
|
||||||
|
class Sihnon_Exception_NoDatabaseConnection extends Sihnon_Exception_DatabaseException {};
|
||||||
|
class Sihnon_Exception_DatabaseQueryFailed extends Sihnon_Exception_DatabaseException {};
|
||||||
|
class Sihnon_Exception_ResultCountMismatch extends Sihnon_Exception_DatabaseException {};
|
||||||
|
|
||||||
|
class Sihnon_Exception_ConfigException extends Sihnon_Exception {};
|
||||||
|
class Sihnon_Exception_UnknownSetting extends Sihnon_Exception_ConfigException {};
|
||||||
|
|
||||||
|
class Sihnon_Exception_CacheException extends Sihnon_Exception {};
|
||||||
|
class Sihnon_Exception_InvalidCacheDir extends Sihnon_Exception_CacheException {};
|
||||||
|
class Sihnon_Exception_CacheObjectNotFound extends Sihnon_Exception_CacheException {};
|
||||||
|
|
||||||
|
class Sihnon_Exception_InvalidPluginName extends Sihnon_Exception {};
|
||||||
|
|
||||||
|
?>
|
||||||
113
source/lib/Sihnon/ForegroundTask.class.php
Normal file
113
source/lib/Sihnon/ForegroundTask.class.php
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class Sihnon_ForegroundTask {
|
||||||
|
|
||||||
|
const PIPE_STDIN = 0;
|
||||||
|
const PIPE_STDOUT = 1;
|
||||||
|
const PIPE_STDERR = 2;
|
||||||
|
|
||||||
|
private function __construct() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Code largely taken from user submitted comment on http://php.sihnon.net/manual/en/function.proc-open.php
|
||||||
|
* @param unknown_type $command
|
||||||
|
* @param unknown_type $cwd
|
||||||
|
* @param unknown_type $env
|
||||||
|
* @param unknown_type $stdin
|
||||||
|
* @param unknown_type $callback_stdout
|
||||||
|
* @param unknown_type $callback_stderr
|
||||||
|
*/
|
||||||
|
public static function execute($command, $cwd = null, $env = null, $stdin = null, $callback_stdout = null, $callback_stderr = null, $identifier = null) {
|
||||||
|
$txOff = 0;
|
||||||
|
$txLen = strlen($stdin);
|
||||||
|
$stdout = '';
|
||||||
|
$stdoutDone = FALSE;
|
||||||
|
$stderr = '';
|
||||||
|
$stderrDone = FALSE;
|
||||||
|
|
||||||
|
$descriptors = array(
|
||||||
|
self::PIPE_STDIN => array('pipe', 'r'),
|
||||||
|
self::PIPE_STDOUT => array('pipe', 'w'),
|
||||||
|
self::PIPE_STDERR => array('pipe', 'w'),
|
||||||
|
);
|
||||||
|
|
||||||
|
$pipes = array();
|
||||||
|
$process = proc_open($command, $descriptors, $pipes);
|
||||||
|
|
||||||
|
stream_set_blocking($pipes[self::PIPE_STDIN], 0); // Make stdin/stdout/stderr non-blocking
|
||||||
|
stream_set_blocking($pipes[self::PIPE_STDOUT], 0);
|
||||||
|
stream_set_blocking($pipes[self::PIPE_STDERR], 0);
|
||||||
|
|
||||||
|
if ($txLen == 0) {
|
||||||
|
fclose($pipes[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
$rx = array(); // The program's stdout/stderr
|
||||||
|
if (!$stdoutDone) {
|
||||||
|
$rx[] = $pipes[self::PIPE_STDOUT];
|
||||||
|
}
|
||||||
|
if (!$stderrDone) {
|
||||||
|
$rx[] = $pipes[self::PIPE_STDERR];
|
||||||
|
}
|
||||||
|
|
||||||
|
$tx = array(); // The program's stdin
|
||||||
|
if ($txOff < $txLen) {
|
||||||
|
$tx[] = $pipes[self::PIPE_STDIN];
|
||||||
|
}
|
||||||
|
|
||||||
|
$ex = array();
|
||||||
|
|
||||||
|
stream_select($rx, $tx, $ex, null, null); // Block til r/w possible
|
||||||
|
if (!empty($tx)) {
|
||||||
|
$txRet = fwrite($pipes[self::PIPE_STDIN], substr($stdin, $txOff, 8192));
|
||||||
|
if ($txRet !== false) {
|
||||||
|
$txOff += $txRet;
|
||||||
|
}
|
||||||
|
if ($txOff >= $txLen) {
|
||||||
|
fclose($pipes[self::PIPE_STDIN]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($rx as $r) {
|
||||||
|
if ($r == $pipes[self::PIPE_STDOUT]) {
|
||||||
|
$chunk = fread($pipes[self::PIPE_STDOUT], 8192);
|
||||||
|
if (feof($pipes[self::PIPE_STDOUT])) {
|
||||||
|
fclose($pipes[self::PIPE_STDOUT]); $stdoutDone = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($callback_stdout) {
|
||||||
|
call_user_func($callback_stdout, $identifier, $chunk);
|
||||||
|
} else {
|
||||||
|
$stdout .= $chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if ($r == $pipes[self::PIPE_STDERR]) {
|
||||||
|
$chunk = fread($pipes[self::PIPE_STDERR], 8192);
|
||||||
|
if (feof($pipes[self::PIPE_STDERR])) {
|
||||||
|
fclose($pipes[self::PIPE_STDERR]); $stderrDone = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($callback_stderr) {
|
||||||
|
call_user_func($callback_stderr, $identifier, $chunk);
|
||||||
|
} else {
|
||||||
|
$stderr .= $chunk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_resource($process))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if ($txOff >= $txLen && $stdoutDone && $stderrDone)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return array(proc_close($process), $stdout, $stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
11
source/lib/Sihnon/IPlugin.class.php
Normal file
11
source/lib/Sihnon/IPlugin.class.php
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
interface Sihnon_IPlugin {
|
||||||
|
|
||||||
|
public static function init();
|
||||||
|
|
||||||
|
public static function name();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
9
source/lib/Sihnon/IPluginFactory.class.php
Normal file
9
source/lib/Sihnon/IPluginFactory.class.php
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
interface Sihnon_IPluginFactory {
|
||||||
|
|
||||||
|
public static function init();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
61
source/lib/Sihnon/Log.class.php
Normal file
61
source/lib/Sihnon/Log.class.php
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class Sihnon_Log {
|
||||||
|
|
||||||
|
const LEVEL_DEBUG = 'DEBUG';
|
||||||
|
const LEVEL_INFO = 'INFO';
|
||||||
|
const LEVEL_WARNING = 'WARNING';
|
||||||
|
const LEVEL_ERROR = 'ERROR';
|
||||||
|
|
||||||
|
private static $hostname = '';
|
||||||
|
|
||||||
|
private $database;
|
||||||
|
private $config;
|
||||||
|
private $table;
|
||||||
|
|
||||||
|
public function __construct(Sihnon_Database $database, Sihnon_Config $config, $table) {
|
||||||
|
$this->database = $database;
|
||||||
|
$this->config = $config;
|
||||||
|
$this->table = $table;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function log($severity, $message) {
|
||||||
|
$this->database->insert("INSERT INTO {$this->table} (level,ctime,pid,hostname,progname,line,message) VALUES(:level, :ctime, :pid, :hostname, :progname, :line, :message)",
|
||||||
|
array(
|
||||||
|
array('name' => 'level', 'value' => $severity, 'type' => PDO::PARAM_STR),
|
||||||
|
array('name' => 'ctime', 'value' => time(), 'type' => PDO::PARAM_INT),
|
||||||
|
array('name' => 'pid', 'value' => 0, 'type' => PDO::PARAM_INT),
|
||||||
|
array('name' => 'hostname', 'value' => self::$hostname, 'type' => PDO::PARAM_STR),
|
||||||
|
array('name' => 'progname', 'value' => 'webui', 'type' => PDO::PARAM_STR),
|
||||||
|
array('name' => 'line', 'value' => 0, 'type' => PDO::PARAM_INT),
|
||||||
|
array('name' => 'message', 'value' => $message, 'type' => PDO::PARAM_STR)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function debug($message) {
|
||||||
|
return $this->log(self::LEVEL_DEBUG, $message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function info($message) {
|
||||||
|
return $this->log(self::LEVEL_INFO, $message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function warning($message) {
|
||||||
|
return $this->log(self::LEVEL_WARNING, $message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function error($message) {
|
||||||
|
return $this->log(self::LEVEL_ERROR, $message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function initialise() {
|
||||||
|
self::$hostname = trim(`hostname`);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Sihnon_Log::initialise();
|
||||||
|
|
||||||
|
?>
|
||||||
97
source/lib/Sihnon/LogEntry.class.php
Normal file
97
source/lib/Sihnon/LogEntry.class.php
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
abstract class Sihnon_LogEntry {
|
||||||
|
|
||||||
|
protected static $table_name = "";
|
||||||
|
|
||||||
|
protected $id;
|
||||||
|
protected $level;
|
||||||
|
protected $ctime;
|
||||||
|
protected $pid;
|
||||||
|
protected $hostname;
|
||||||
|
protected $progname;
|
||||||
|
protected $line;
|
||||||
|
protected $message;
|
||||||
|
|
||||||
|
protected function __construct($id, $level, $ctime, $pid, $hostname, $progname, $line, $message) {
|
||||||
|
$this->id = $id;
|
||||||
|
$this->level = $level;
|
||||||
|
$this->ctime = $ctime;
|
||||||
|
$this->pid = $pid;
|
||||||
|
$this->hostname = $hostname;
|
||||||
|
$this->progname = $progname;
|
||||||
|
$this->line = $line;
|
||||||
|
$this->message = $message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function fromDatabaseRow($row) {
|
||||||
|
return new Sihnon_ClientLogEntry(
|
||||||
|
$row['id'],
|
||||||
|
$row['level'],
|
||||||
|
$row['ctime'],
|
||||||
|
$row['pid'],
|
||||||
|
$row['hostname'],
|
||||||
|
$row['progname'],
|
||||||
|
$row['line'],
|
||||||
|
$row['message']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function fromId($id) {
|
||||||
|
$database = Sihnon_Main::instance()->database();
|
||||||
|
return Sihnon_ClientLogEntry::fromDatabaseRow(
|
||||||
|
$database->selectOne('SELECT * FROM '.self::$table_name.' WHERE id=:id', array(
|
||||||
|
array('name' => 'id', 'value' => $id, 'type' => PDO::PARAM_INT)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function recent($limit = 100) {
|
||||||
|
$entries = array();
|
||||||
|
|
||||||
|
$database = Sihnon_Main::instance()->database();
|
||||||
|
foreach ($database->selectList('SELECT * FROM '.self::$table_name.' ORDER BY ctime DESC LIMIT :limit', array(
|
||||||
|
array('name' => 'limit', 'value' => $limit, 'type' => PDO::PARAM_INT)
|
||||||
|
)) as $row) {
|
||||||
|
$entries[] = self::fromDatabaseRow($row);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function id() {
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function level() {
|
||||||
|
return $this->level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function ctime() {
|
||||||
|
return $this->ctime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function pid() {
|
||||||
|
return $this->pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hostname() {
|
||||||
|
return $this->hostname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function progname() {
|
||||||
|
return $this->progname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function line() {
|
||||||
|
return $this->line;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function message() {
|
||||||
|
return $this->message;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
?>
|
||||||
172
source/lib/Sihnon/Main.class.php
Normal file
172
source/lib/Sihnon/Main.class.php
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class Sihnon_Main {
|
||||||
|
|
||||||
|
private static $instance;
|
||||||
|
|
||||||
|
private $config;
|
||||||
|
private $database;
|
||||||
|
private $log;
|
||||||
|
private $cache;
|
||||||
|
|
||||||
|
private $base_uri;
|
||||||
|
|
||||||
|
private function __construct() {
|
||||||
|
$this->config = new Sihnon_Config(Sihnon_DBConfig);
|
||||||
|
$this->database = new Sihnon_Database($this->config);
|
||||||
|
$this->config->setDatabase($this->database);
|
||||||
|
|
||||||
|
$this->log = new Sihnon_Log($this->database, $this->config, Sihnon_Log_Table);
|
||||||
|
$this->cache = new Sihnon_Cache($this->config);
|
||||||
|
|
||||||
|
$this->base_uri = dirname($_SERVER['SCRIPT_NAME']) . '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return Sihnon_Main
|
||||||
|
*/
|
||||||
|
public static function instance() {
|
||||||
|
if (!self::$instance) {
|
||||||
|
self::$instance = new Sihnon_Main();
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return Sihnon_Config
|
||||||
|
*/
|
||||||
|
public function config() {
|
||||||
|
return $this->config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return Sihnon_Database
|
||||||
|
*/
|
||||||
|
public function database() {
|
||||||
|
return $this->database;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return Sihnon_Log
|
||||||
|
*/
|
||||||
|
public function log() {
|
||||||
|
return $this->log;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return Sihnon_Cache
|
||||||
|
*/
|
||||||
|
public function cache() {
|
||||||
|
return $this->cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function baseUri() {
|
||||||
|
return $this->base_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function absoluteUrl($relative_url) {
|
||||||
|
$secure = isset($_SERVER['secure']);
|
||||||
|
$port = $_SERVER['SERVER_PORT'];
|
||||||
|
return 'http' . ($secure ? 's' : '') . '://'
|
||||||
|
. $_SERVER['HTTP_HOST'] . (($port == 80 || ($secure && $port == 443)) ? '' : ':' . $port)
|
||||||
|
. '/' . $this->base_uri . $relative_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function initialise() {
|
||||||
|
spl_autoload_register(array('Sihnon_Main','autoload'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function autoload($classname) {
|
||||||
|
// Ensure the classname contains only valid class name characters
|
||||||
|
if (!preg_match('/^[A-Z][a-zA-Z0-9_]*$/', $classname)) {
|
||||||
|
throw new Exception('Illegal characters in classname'); // TODO Subclass this exception
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure the class to load begins with our prefix
|
||||||
|
if (!preg_match('/^Sihnon_/', $classname)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special case: All exceptions are stored in the same file
|
||||||
|
if (preg_match('/^Sihnon_Exception/', $classname)) {
|
||||||
|
require_once(Sihnon_Lib . 'Sihnon/Exceptions.class.php');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace any underscores with directory separators
|
||||||
|
$filename = Sihnon_Lib . preg_replace('/_/', '/', $classname);
|
||||||
|
|
||||||
|
// Tack on the class file suffix
|
||||||
|
$filename .= '.class.php';
|
||||||
|
|
||||||
|
// If this file exists, load it
|
||||||
|
if (file_exists($filename)) {
|
||||||
|
require_once $filename;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function mkdir_recursive($directory, $permissions=0777) {
|
||||||
|
$parts = explode('/', $directory);
|
||||||
|
$path = '';
|
||||||
|
for ($i=1,$l=count($parts); $i<=$l; $i++) {
|
||||||
|
$iPath = $parts;
|
||||||
|
$path = join('/', array_slice($iPath, 0, $i));
|
||||||
|
if (empty($path)) continue;
|
||||||
|
if (!file_exists($path)) {
|
||||||
|
if (!mkdir($path)) return false;
|
||||||
|
if (!chmod($path, $permissions)) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function issetelse($var, $default = null) {
|
||||||
|
if (isset($var)) {
|
||||||
|
return $var;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_string($default) && preg_match('/^Sihnon_Exception/', $default) && class_exists($default) && is_subclass_of($default, Sihnon_Exception)) {
|
||||||
|
throw new $default();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function formatDuration($time) {
|
||||||
|
if (is_null($time)) {
|
||||||
|
return 'unknown';
|
||||||
|
}
|
||||||
|
|
||||||
|
$labels = array('seconds', 'minutes', 'hours', 'days', 'weeks', 'months', 'years');
|
||||||
|
$limits = array(1, 60, 3600, 86400, 604800, 2592000, 31556926, PHP_INT_MAX);
|
||||||
|
|
||||||
|
$working_time = $time;
|
||||||
|
|
||||||
|
$result = "";
|
||||||
|
$ptr = count($labels) - 1;
|
||||||
|
|
||||||
|
while ($ptr >= 0 && $working_time < $limits[$ptr]) {
|
||||||
|
--$ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ($ptr >= 0) {
|
||||||
|
$unit_time = floor($working_time / $limits[$ptr]);
|
||||||
|
$working_time -= $unit_time * $limits[$ptr];
|
||||||
|
$result = $result . ' ' . $unit_time . ' ' . $labels[$ptr];
|
||||||
|
--$ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Sihnon_Main::initialise();
|
||||||
|
|
||||||
|
?>
|
||||||
30
source/lib/Sihnon/PluginBase.class.php
Normal file
30
source/lib/Sihnon/PluginBase.class.php
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for all plugins, providing default implementations for
|
||||||
|
* standard plugin methods.
|
||||||
|
*
|
||||||
|
* @class Sihnon_PluginBase
|
||||||
|
*/
|
||||||
|
class Sihnon_PluginBase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a basic initialisation function that does nothing.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static function init() {
|
||||||
|
// Nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of this plugin
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function name() {
|
||||||
|
return static::PLUGIN_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
67
source/lib/Sihnon/PluginFactory.class.php
Normal file
67
source/lib/Sihnon/PluginFactory.class.php
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
abstract class Sihnon_PluginFactory implements Sihnon_IPluginFactory {
|
||||||
|
|
||||||
|
static private $validPlugins = array();
|
||||||
|
|
||||||
|
protected static function ensureScanned() {
|
||||||
|
if (! isset(self::$validPlugins[get_called_class()])) {
|
||||||
|
static::scan();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static function isValidPlugin($plugin) {
|
||||||
|
return isset(self::$validPlugins[get_called_class()][$plugin]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getValidPlugins() {
|
||||||
|
static::ensureScanned();
|
||||||
|
return array_keys(self::$validPlugins[get_called_class()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static function findPlugins($directory) {
|
||||||
|
$plugins = array();
|
||||||
|
|
||||||
|
$iterator = new Sihnon_Utility_ClassFilesIterator(new Sihnon_Utility_VisibleFilesIterator(new DirectoryIterator(Sihnon_Lib . $directory)));
|
||||||
|
|
||||||
|
foreach ($iterator as /** @var SplFileInfo */ $file) {
|
||||||
|
$plugin = preg_replace('/.class.php$/', '', $file->getFilename());
|
||||||
|
$plugins[] = $plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $plugins;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static function loadPlugins($plugins, $prefix, $interface) {
|
||||||
|
self::$validPlugins[get_called_class()] = array();
|
||||||
|
|
||||||
|
foreach ($plugins as $plugin) {
|
||||||
|
$fullClassname = $prefix . $plugin;
|
||||||
|
if ( ! class_exists($fullClassname, true)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! in_array($interface, class_implements($fullClassname))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialise the plugin
|
||||||
|
call_user_func(array($fullClassname, 'init'));
|
||||||
|
|
||||||
|
self::$validPlugins[get_called_class()][$plugin] = $fullClassname;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function classname($plugin) {
|
||||||
|
static::ensureScanned();
|
||||||
|
|
||||||
|
if ( ! self::isValidPlugin($plugin)) {
|
||||||
|
throw new Sihnon_Exception_InvalidPluginName($plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$validPlugins[get_called_class()][$plugin];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
9
source/lib/Sihnon/Utility/ClassFilesIterator.class.php
Normal file
9
source/lib/Sihnon/Utility/ClassFilesIterator.class.php
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class Sihnon_Utility_ClassFilesIterator extends FilterIterator {
|
||||||
|
public function accept() {
|
||||||
|
return preg_match('/.class.php$/i', $this->current()->getFilename());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
9
source/lib/Sihnon/Utility/VisibleFilesIterator.class.php
Normal file
9
source/lib/Sihnon/Utility/VisibleFilesIterator.class.php
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class Sihnon_Utility_VisibleFilesIterator extends FilterIterator {
|
||||||
|
public function accept() {
|
||||||
|
return !(substr($this->current()->getFilename(), 0, 1) == '.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class Sihnon_Utility_VisibleFilesRecursiveIterator extends RecursiveFilterIterator {
|
||||||
|
public function accept() {
|
||||||
|
return !(substr($this->current()->getFilename(), 0, 1) == '.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
Reference in New Issue
Block a user