forked from kevinowino869/mitrobill
PHPMixBill v5.0 - First Upload
This commit is contained in:
243
system/autoload/PEAR2/Autoload.php
Normal file
243
system/autoload/PEAR2/Autoload.php
Normal file
@ -0,0 +1,243 @@
|
||||
<?php
|
||||
namespace PEAR2;
|
||||
if (!class_exists('\PEAR2\Autoload', false)) {
|
||||
class Autoload
|
||||
{
|
||||
/**
|
||||
* Whether the autoload class has been spl_autoload_register-ed
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected static $registered = false;
|
||||
|
||||
/**
|
||||
* Array of PEAR2 autoload paths registered
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $paths = array();
|
||||
|
||||
/**
|
||||
* Array of classname-to-file mapping
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $map = array();
|
||||
|
||||
/**
|
||||
* Array of class maps loaded
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $maps = array();
|
||||
|
||||
/**
|
||||
* Last classmap specified
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $mapfile = null;
|
||||
|
||||
/**
|
||||
* Array of classes loaded automatically not in the map
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $unmapped = array();
|
||||
|
||||
/**
|
||||
* Initialize the PEAR2 autoloader
|
||||
*
|
||||
* @param string $path Directory path to register
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
static function initialize($path, $mapfile = null)
|
||||
{
|
||||
self::register();
|
||||
self::addPath($path);
|
||||
self::addMap($mapfile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the PEAR2 autoload class with spl_autoload_register
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function register()
|
||||
{
|
||||
if (!self::$registered) {
|
||||
// set up __autoload
|
||||
$autoload = spl_autoload_functions();
|
||||
spl_autoload_register('PEAR2\Autoload::load');
|
||||
if (function_exists('__autoload') && ($autoload === false)) {
|
||||
// __autoload() was being used, but now would be ignored, add
|
||||
// it to the autoload stack
|
||||
spl_autoload_register('__autoload');
|
||||
}
|
||||
}
|
||||
self::$registered = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a path
|
||||
*
|
||||
* @param string $path The directory to add to the set of PEAR2 paths
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function addPath($path)
|
||||
{
|
||||
if (!in_array($path, self::$paths)) {
|
||||
self::$paths[] = $path;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a classname-to-file map
|
||||
*
|
||||
* @param string $mapfile The filename of the classmap
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function addMap($mapfile)
|
||||
{
|
||||
if (! in_array($mapfile, self::$maps)) {
|
||||
|
||||
// keep track of specific map file loaded in this
|
||||
// instance so we can update it if necessary
|
||||
self::$mapfile = $mapfile;
|
||||
|
||||
if (file_exists($mapfile)) {
|
||||
$map = include $mapfile;
|
||||
if (is_array($map)) {
|
||||
// mapfile contains a valid map, so we'll keep it
|
||||
self::$maps[] = $mapfile;
|
||||
self::$map = array_merge(self::$map, $map);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the class is already defined in a classmap
|
||||
*
|
||||
* @param string $class The class to look for
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected static function isMapped($class)
|
||||
{
|
||||
if (isset(self::$map[$class])) {
|
||||
return true;
|
||||
}
|
||||
if (isset(self::$mapfile) && ! isset(self::$map[$class])) {
|
||||
self::$unmapped[] = $class;
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a PEAR2 class
|
||||
*
|
||||
* @param string $class The class to load
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
static function load($class)
|
||||
{
|
||||
// need to check if there's a current map file specified ALSO.
|
||||
// this could be the first time writing it.
|
||||
$mapped = self::isMapped($class);
|
||||
if ($mapped) {
|
||||
require self::$map[$class];
|
||||
if (!self::loadSuccessful($class)) {
|
||||
// record this failure & keep going, we may still find it
|
||||
self::$unmapped[] = $class;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
$file = str_replace(array('_', '\\'), DIRECTORY_SEPARATOR, $class) . '.php';
|
||||
foreach (self::$paths as $path) {
|
||||
if (file_exists($path . DIRECTORY_SEPARATOR . $file)) {
|
||||
require $path . DIRECTORY_SEPARATOR . $file;
|
||||
if (!self::loadSuccessful($class)) {
|
||||
throw new \Exception('Class ' . $class . ' was not present in ' .
|
||||
$path . DIRECTORY_SEPARATOR . $file .
|
||||
'") [PEAR2_Autoload-0.2.4]');
|
||||
}
|
||||
|
||||
if (in_array($class, self::$unmapped)) {
|
||||
self::updateMap($class, $path . DIRECTORY_SEPARATOR . $file);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
$e = new \Exception('Class ' . $class . ' could not be loaded from ' .
|
||||
$file . ', file does not exist (registered paths="' .
|
||||
implode(PATH_SEPARATOR, self::$paths) .
|
||||
'") [PEAR2_Autoload-0.2.4]');
|
||||
$trace = $e->getTrace();
|
||||
if (isset($trace[2]) && isset($trace[2]['function']) &&
|
||||
in_array($trace[2]['function'], array('class_exists', 'interface_exists'))) {
|
||||
return false;
|
||||
}
|
||||
if (isset($trace[1]) && isset($trace[1]['function']) &&
|
||||
in_array($trace[1]['function'], array('class_exists', 'interface_exists'))) {
|
||||
return false;
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the requested class was loaded from the specified path
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected static function loadSuccessful($class)
|
||||
{
|
||||
if (!class_exists($class, false) && !interface_exists($class, false)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* If possible, update the classmap file with newly-discovered
|
||||
* mapping.
|
||||
*
|
||||
* @param string $class Class name discovered
|
||||
*
|
||||
* @param string $origin File where class was found
|
||||
*
|
||||
*/
|
||||
protected static function updateMap($class, $origin)
|
||||
{
|
||||
if (is_writable(self::$mapfile) || is_writable(dirname(self::$mapfile))) {
|
||||
self::$map[$class] = $origin;
|
||||
file_put_contents(self::$mapfile,
|
||||
'<'."?php\n"
|
||||
. "// PEAR2\Autoload auto-generated classmap\n"
|
||||
. "return " . var_export(self::$map, true) . ';',
|
||||
LOCK_EX
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* return the array of paths PEAR2 autoload has registered
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
static function getPaths()
|
||||
{
|
||||
return self::$paths;
|
||||
}
|
||||
}
|
||||
}
|
||||
Autoload::initialize(dirname(__DIR__));
|
371
system/autoload/PEAR2/Cache/SHM.php
Normal file
371
system/autoload/PEAR2/Cache/SHM.php
Normal file
@ -0,0 +1,371 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* ~~summary~~
|
||||
*
|
||||
* ~~description~~
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Caching
|
||||
* @package PEAR2_Cache_SHM
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Vasil Rangelov
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 0.1.3
|
||||
* @link http://pear2.php.net/PEAR2_Cache_SHM
|
||||
*/
|
||||
|
||||
/**
|
||||
* The namespace declaration.
|
||||
*/
|
||||
namespace PEAR2\Cache;
|
||||
|
||||
/**
|
||||
* Used as a catch-all for adapter initialization.
|
||||
*/
|
||||
use Exception as E;
|
||||
|
||||
/**
|
||||
* Implements this class.
|
||||
*/
|
||||
use IteratorAggregate;
|
||||
|
||||
/**
|
||||
* Used on failures by this class.
|
||||
*/
|
||||
use PEAR2\Cache\SHM\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Main class for this package.
|
||||
*
|
||||
* Automatically chooses an adapter based on the available extensions.
|
||||
*
|
||||
* @category Caching
|
||||
* @package PEAR2_Cache_SHM
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Cache_SHM
|
||||
*/
|
||||
abstract class SHM implements IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* @var array An array of adapter names that meet their requirements.
|
||||
*/
|
||||
private static $_adapters = array();
|
||||
|
||||
/**
|
||||
* Creates a new shared memory storage.
|
||||
*
|
||||
* Estabilishes a separate persistent storage. Adapter is automatically
|
||||
* chosen based on the available extensions.
|
||||
*
|
||||
* @param string $persistentId The ID for the storage.
|
||||
*
|
||||
* @return static|SHM A new instance of an SHM adapter (child of this
|
||||
* class).
|
||||
*/
|
||||
final public static function factory($persistentId)
|
||||
{
|
||||
foreach (self::$_adapters as $adapter) {
|
||||
try {
|
||||
return new $adapter($persistentId);
|
||||
} catch (E $e) {
|
||||
//In case of a runtime error, try to fallback to other adapters.
|
||||
}
|
||||
}
|
||||
throw new InvalidArgumentException(
|
||||
'No appropriate adapter available',
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the adapter meets its requirements.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public static function isMeetingRequirements()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an adapter.
|
||||
*
|
||||
* Registers an SHM adapter, allowing you to call it with {@link factory()}.
|
||||
*
|
||||
* @param string $adapter FQCN of adapter. A valid adapter is one that
|
||||
* extends this class. The class will be autoloaded if not already
|
||||
* present.
|
||||
* @param bool $prepend Whether to prepend this adapter into the list of
|
||||
* possible adapters, instead of appending to it.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
final public static function registerAdapter($adapter, $prepend = false)
|
||||
{
|
||||
if (class_exists($adapter, true)
|
||||
&& is_subclass_of($adapter, '\\' . __CLASS__)
|
||||
&& $adapter::isMeetingRequirements()
|
||||
) {
|
||||
if ($prepend) {
|
||||
self::$_adapters = array_merge(
|
||||
array($adapter),
|
||||
self::$_adapters
|
||||
);
|
||||
} else {
|
||||
self::$_adapters[] = $adapter;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a value to the shared memory storage.
|
||||
*
|
||||
* Adds a value to the storage if it doesn't exist, or fails if it does.
|
||||
*
|
||||
* @param string $key Name of key to associate the value with.
|
||||
* @param mixed $value Value for the specified key.
|
||||
* @param int $ttl Seconds to store the value. If set to 0 indicates no
|
||||
* time limit.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function __invoke($key, $value, $ttl = 0)
|
||||
{
|
||||
return $this->add($key, $value, $ttl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value from the shared memory storage.
|
||||
*
|
||||
* This is a magic method, thanks to which any property you attempt to get
|
||||
* the value of will be fetched from the adapter, treating the property name
|
||||
* as the key of the value to get.
|
||||
*
|
||||
* @param string $key Name of key to get.
|
||||
*
|
||||
* @return mixed The current value of the specified key.
|
||||
*/
|
||||
public function __get($key)
|
||||
{
|
||||
return $this->get($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a value in the shared memory storage.
|
||||
*
|
||||
* This is a magic method, thanks to which any property you attempt to set
|
||||
* the value of will be set by the adapter, treating the property name as
|
||||
* the key of the value to set. The value is set without a TTL.
|
||||
*
|
||||
* @param string $key Name of key to associate the value with.
|
||||
* @param mixed $value Value for the specified key.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function __set($key, $value)
|
||||
{
|
||||
return $this->set($key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a specified key is in the storage.
|
||||
*
|
||||
* This is a magic method, thanks to which any property you call isset() on
|
||||
* will be checked by the adapter, treating the property name as the key
|
||||
* of the value to check.
|
||||
*
|
||||
* @param string $key Name of key to check.
|
||||
*
|
||||
* @return bool TRUE if the key is in the storage, FALSE otherwise.
|
||||
*/
|
||||
public function __isset($key)
|
||||
{
|
||||
return $this->exists($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a value from the shared memory storage.
|
||||
*
|
||||
* This is a magic method, thanks to which any property you attempt to unset
|
||||
* the value of will be unset by the adapter, treating the property name as
|
||||
* the key of the value to delete.
|
||||
*
|
||||
* @param string $key Name of key to delete.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function __unset($key)
|
||||
{
|
||||
return $this->delete($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new shared memory storage.
|
||||
*
|
||||
* Estabilishes a separate persistent storage.
|
||||
*
|
||||
* @param string $persistentId The ID for the storage. The storage will be
|
||||
* reused if it exists, or created if it doesn't exist. Data and locks
|
||||
* are namespaced by this ID.
|
||||
*/
|
||||
abstract public function __construct($persistentId);
|
||||
|
||||
/**
|
||||
* Obtains a named lock.
|
||||
*
|
||||
* @param string $key Name of the key to obtain. Note that $key may
|
||||
* repeat for each distinct $persistentId.
|
||||
* @param double $timeout If the lock can't be immediatly obtained, the
|
||||
* script will block for at most the specified amount of seconds.
|
||||
* Setting this to 0 makes lock obtaining non blocking, and setting it
|
||||
* to NULL makes it block without a time limit.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
abstract public function lock($key, $timeout = null);
|
||||
|
||||
/**
|
||||
* Releases a named lock.
|
||||
*
|
||||
* @param string $key Name of the key to release. Note that $key may
|
||||
* repeat for each distinct $persistentId.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
abstract public function unlock($key);
|
||||
|
||||
/**
|
||||
* Checks if a specified key is in the storage.
|
||||
*
|
||||
* @param string $key Name of key to check.
|
||||
*
|
||||
* @return bool TRUE if the key is in the storage, FALSE otherwise.
|
||||
*/
|
||||
abstract public function exists($key);
|
||||
|
||||
/**
|
||||
* Adds a value to the shared memory storage.
|
||||
*
|
||||
* Adds a value to the storage if it doesn't exist, or fails if it does.
|
||||
*
|
||||
* @param string $key Name of key to associate the value with.
|
||||
* @param mixed $value Value for the specified key.
|
||||
* @param int $ttl Seconds to store the value. If set to 0 indicates no
|
||||
* time limit.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
abstract public function add($key, $value, $ttl = 0);
|
||||
|
||||
/**
|
||||
* Sets a value in the shared memory storage.
|
||||
*
|
||||
* Adds a value to the storage if it doesn't exist, overwrites it otherwise.
|
||||
*
|
||||
* @param string $key Name of key to associate the value with.
|
||||
* @param mixed $value Value for the specified key.
|
||||
* @param int $ttl Seconds to store the value. If set to 0 indicates no
|
||||
* time limit.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
abstract public function set($key, $value, $ttl = 0);
|
||||
|
||||
/**
|
||||
* Gets a value from the shared memory storage.
|
||||
*
|
||||
* Gets the current value, or throws an exception if it's not stored.
|
||||
*
|
||||
* @param string $key Name of key to get the value of.
|
||||
*
|
||||
* @return mixed The current value of the specified key.
|
||||
*/
|
||||
abstract public function get($key);
|
||||
|
||||
/**
|
||||
* Deletes a value from the shared memory storage.
|
||||
*
|
||||
* @param string $key Name of key to delete.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
abstract public function delete($key);
|
||||
|
||||
/**
|
||||
* Increases a value from the shared memory storage.
|
||||
*
|
||||
* Increases a value from the shared memory storage. Unlike a plain
|
||||
* set($key, get($key)+$step) combination, this function also implicitly
|
||||
* performs locking.
|
||||
*
|
||||
* @param string $key Name of key to increase.
|
||||
* @param int $step Value to increase the key by.
|
||||
*
|
||||
* @return int The new value.
|
||||
*/
|
||||
abstract public function inc($key, $step = 1);
|
||||
|
||||
/**
|
||||
* Decreases a value from the shared memory storage.
|
||||
*
|
||||
* Decreases a value from the shared memory storage. Unlike a plain
|
||||
* set($key, get($key)-$step) combination, this function also implicitly
|
||||
* performs locking.
|
||||
*
|
||||
* @param string $key Name of key to decrease.
|
||||
* @param int $step Value to decrease the key by.
|
||||
*
|
||||
* @return int The new value.
|
||||
*/
|
||||
abstract public function dec($key, $step = 1);
|
||||
|
||||
/**
|
||||
* Sets a new value if a key has a certain value.
|
||||
*
|
||||
* Sets a new value if a key has a certain value. This function only works
|
||||
* when $old and $new are longs.
|
||||
*
|
||||
* @param string $key Key of the value to compare and set.
|
||||
* @param int $old The value to compare the key against.
|
||||
* @param int $new The value to set the key to.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
abstract public function cas($key, $old, $new);
|
||||
|
||||
/**
|
||||
* Clears the persistent storage.
|
||||
*
|
||||
* Clears the persistent storage, i.e. removes all keys. Locks are left
|
||||
* intact.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
abstract public function clear();
|
||||
|
||||
/**
|
||||
* Retrieve an external iterator
|
||||
*
|
||||
* Returns an external iterator.
|
||||
*
|
||||
* @param string|null $filter A PCRE regular expression.
|
||||
* Only matching keys will be iterated over.
|
||||
* Setting this to NULL matches all keys of this instance.
|
||||
* @param bool $keysOnly Whether to return only the keys,
|
||||
* or return both the keys and values.
|
||||
*
|
||||
* @return \Traversable An array with all matching keys as array keys,
|
||||
* and values as array values. If $keysOnly is TRUE, the array keys are
|
||||
* numeric, and the array values are key names.
|
||||
*/
|
||||
abstract public function getIterator($filter = null, $keysOnly = false);
|
||||
}
|
||||
|
||||
SHM::registerAdapter('\\' . __NAMESPACE__ . '\SHM\Adapter\Placebo');
|
||||
SHM::registerAdapter('\\' . __NAMESPACE__ . '\SHM\Adapter\Wincache');
|
||||
SHM::registerAdapter('\\' . __NAMESPACE__ . '\SHM\Adapter\APC');
|
406
system/autoload/PEAR2/Cache/SHM/Adapter/APC.php
Normal file
406
system/autoload/PEAR2/Cache/SHM/Adapter/APC.php
Normal file
@ -0,0 +1,406 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* ~~summary~~
|
||||
*
|
||||
* ~~description~~
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Caching
|
||||
* @package PEAR2_Cache_SHM
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Vasil Rangelov
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 0.1.3
|
||||
* @link http://pear2.php.net/PEAR2_Cache_SHM
|
||||
*/
|
||||
/**
|
||||
* The namespace declaration.
|
||||
*/
|
||||
namespace PEAR2\Cache\SHM\Adapter;
|
||||
|
||||
/**
|
||||
* Throws exceptions from this namespace, and extends from this class.
|
||||
*/
|
||||
use PEAR2\Cache\SHM;
|
||||
|
||||
/**
|
||||
* {@link APC::getIterator()} returns this object.
|
||||
*/
|
||||
use ArrayObject;
|
||||
|
||||
/**
|
||||
* Shared memory adapter for the APC extension.
|
||||
*
|
||||
* @category Caching
|
||||
* @package PEAR2_Cache_SHM
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Cache_SHM
|
||||
*/
|
||||
class APC extends SHM
|
||||
{
|
||||
/**
|
||||
* @var string ID of the current storage.
|
||||
*/
|
||||
protected $persistentId;
|
||||
|
||||
/**
|
||||
* List of persistent IDs.
|
||||
*
|
||||
* A list of persistent IDs within the current request (as keys) with an int
|
||||
* (as a value) specifying the number of instances in the current request.
|
||||
* Used as an attempt to ensure implicit lock releases even on errors in the
|
||||
* critical sections, since APC doesn't have an actual locking function.
|
||||
* @var array
|
||||
*/
|
||||
protected static $requestInstances = array();
|
||||
|
||||
/**
|
||||
* @var array Array of lock names (as values) for each persistent ID (as
|
||||
* key) obtained during the current request.
|
||||
*/
|
||||
protected static $locksBackup = array();
|
||||
|
||||
/**
|
||||
* Creates a new shared memory storage.
|
||||
*
|
||||
* Estabilishes a separate persistent storage.
|
||||
*
|
||||
* @param string $persistentId The ID for the storage. The storage will be
|
||||
* reused if it exists, or created if it doesn't exist. Data and locks
|
||||
* are namespaced by this ID.
|
||||
*/
|
||||
public function __construct($persistentId)
|
||||
{
|
||||
$this->persistentId = __CLASS__ . ' ' . $persistentId;
|
||||
if (isset(static::$requestInstances[$this->persistentId])) {
|
||||
static::$requestInstances[$this->persistentId]++;
|
||||
} else {
|
||||
static::$requestInstances[$this->persistentId] = 1;
|
||||
static::$locksBackup[$this->persistentId] = array();
|
||||
}
|
||||
register_shutdown_function(
|
||||
get_called_class() . '::releaseLocks',
|
||||
$this->persistentId,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the adapter meets its requirements.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public static function isMeetingRequirements()
|
||||
{
|
||||
return extension_loaded('apc')
|
||||
&& version_compare(phpversion('apc'), '3.0.13', '>=')
|
||||
&& ini_get('apc.enabled')
|
||||
&& ('cli' !== PHP_SAPI || ini_get('apc.enable_cli'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases all locks in a storage.
|
||||
*
|
||||
* This function is not meant to be used directly. It is implicitly called
|
||||
* by the the destructor and as a shutdown function when the request ends.
|
||||
* One of these calls ends up releasing any unreleased locks obtained
|
||||
* during the request. A lock is also implicitly released as soon as there
|
||||
* are no objects left in the current request using the same persistent ID.
|
||||
*
|
||||
* @param string $internalPersistentId The internal persistent ID, the locks
|
||||
* of which are being released.
|
||||
* @param bool $isAtShutdown Whether the function was executed at
|
||||
* shutdown.
|
||||
*
|
||||
* @return void
|
||||
* @internal
|
||||
*/
|
||||
public static function releaseLocks($internalPersistentId, $isAtShutdown)
|
||||
{
|
||||
$hasInstances = 0 !== static::$requestInstances[$internalPersistentId];
|
||||
if ($isAtShutdown === $hasInstances) {
|
||||
foreach (static::$locksBackup[$internalPersistentId] as $key) {
|
||||
apc_delete($internalPersistentId . 'l ' . $key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases any locks obtained by this instance as soon as there are no more
|
||||
* references to the object's persistent ID.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
static::$requestInstances[$this->persistentId]--;
|
||||
static::releaseLocks($this->persistentId, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtains a named lock.
|
||||
*
|
||||
* @param string $key Name of the key to obtain. Note that $key may
|
||||
* repeat for each distinct $persistentId.
|
||||
* @param double $timeout If the lock can't be immediatly obtained, the
|
||||
* script will block for at most the specified amount of seconds.
|
||||
* Setting this to 0 makes lock obtaining non blocking, and setting it
|
||||
* to NULL makes it block without a time limit.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function lock($key, $timeout = null)
|
||||
{
|
||||
$lock = $this->persistentId . 'l ' . $key;
|
||||
$hasTimeout = $timeout !== null;
|
||||
$start = microtime(true);
|
||||
while (!apc_add($lock, 1)) {
|
||||
if ($hasTimeout && (microtime(true) - $start) > $timeout) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
static::$locksBackup[$this->persistentId] = $key;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases a named lock.
|
||||
*
|
||||
* @param string $key Name of the key to release. Note that $key may
|
||||
* repeat for each distinct $persistentId.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function unlock($key)
|
||||
{
|
||||
$lock = $this->persistentId . 'l ' . $key;
|
||||
$success = apc_delete($lock);
|
||||
if ($success) {
|
||||
unset(static::$locksBackup[$this->persistentId][array_search(
|
||||
$key,
|
||||
static::$locksBackup[$this->persistentId],
|
||||
true
|
||||
)]);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a specified key is in the storage.
|
||||
*
|
||||
* @param string $key Name of key to check.
|
||||
*
|
||||
* @return bool TRUE if the key is in the storage, FALSE otherwise.
|
||||
*/
|
||||
public function exists($key)
|
||||
{
|
||||
return apc_exists($this->persistentId . 'd ' . $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a value to the shared memory storage.
|
||||
*
|
||||
* Adds a value to the storage if it doesn't exist, or fails if it does.
|
||||
*
|
||||
* @param string $key Name of key to associate the value with.
|
||||
* @param mixed $value Value for the specified key.
|
||||
* @param int $ttl Seconds to store the value. If set to 0 indicates no
|
||||
* time limit.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function add($key, $value, $ttl = 0)
|
||||
{
|
||||
return apc_add($this->persistentId . 'd ' . $key, $value, $ttl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a value in the shared memory storage.
|
||||
*
|
||||
* Adds a value to the storage if it doesn't exist, overwrites it otherwise.
|
||||
*
|
||||
* @param string $key Name of key to associate the value with.
|
||||
* @param mixed $value Value for the specified key.
|
||||
* @param int $ttl Seconds to store the value. If set to 0 indicates no
|
||||
* time limit.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function set($key, $value, $ttl = 0)
|
||||
{
|
||||
return apc_store($this->persistentId . 'd ' . $key, $value, $ttl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value from the shared memory storage.
|
||||
*
|
||||
* Gets the current value, or throws an exception if it's not stored.
|
||||
*
|
||||
* @param string $key Name of key to get the value of.
|
||||
*
|
||||
* @return mixed The current value of the specified key.
|
||||
*/
|
||||
public function get($key)
|
||||
{
|
||||
$fullKey = $this->persistentId . 'd ' . $key;
|
||||
if (apc_exists($fullKey)) {
|
||||
$value = apc_fetch($fullKey, $success);
|
||||
if (!$success) {
|
||||
throw new SHM\InvalidArgumentException(
|
||||
'Unable to fetch key. ' .
|
||||
'Key has either just now expired or (if no TTL was set) ' .
|
||||
'is possibly in a race condition with another request.',
|
||||
100
|
||||
);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
throw new SHM\InvalidArgumentException('No such key in cache', 101);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a value from the shared memory storage.
|
||||
*
|
||||
* @param string $key Name of key to delete.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function delete($key)
|
||||
{
|
||||
return apc_delete($this->persistentId . 'd ' . $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increases a value from the shared memory storage.
|
||||
*
|
||||
* Increases a value from the shared memory storage. Unlike a plain
|
||||
* set($key, get($key)+$step) combination, this function also implicitly
|
||||
* performs locking.
|
||||
*
|
||||
* @param string $key Name of key to increase.
|
||||
* @param int $step Value to increase the key by.
|
||||
*
|
||||
* @return int The new value.
|
||||
*/
|
||||
public function inc($key, $step = 1)
|
||||
{
|
||||
$newValue = apc_inc(
|
||||
$this->persistentId . 'd ' . $key,
|
||||
(int) $step,
|
||||
$success
|
||||
);
|
||||
if (!$success) {
|
||||
throw new SHM\InvalidArgumentException(
|
||||
'Unable to increase the value. Are you sure the value is int?',
|
||||
102
|
||||
);
|
||||
}
|
||||
return $newValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decreases a value from the shared memory storage.
|
||||
*
|
||||
* Decreases a value from the shared memory storage. Unlike a plain
|
||||
* set($key, get($key)-$step) combination, this function also implicitly
|
||||
* performs locking.
|
||||
*
|
||||
* @param string $key Name of key to decrease.
|
||||
* @param int $step Value to decrease the key by.
|
||||
*
|
||||
* @return int The new value.
|
||||
*/
|
||||
public function dec($key, $step = 1)
|
||||
{
|
||||
$newValue = apc_dec(
|
||||
$this->persistentId . 'd ' . $key,
|
||||
(int) $step,
|
||||
$success
|
||||
);
|
||||
if (!$success) {
|
||||
throw new SHM\InvalidArgumentException(
|
||||
'Unable to decrease the value. Are you sure the value is int?',
|
||||
103
|
||||
);
|
||||
}
|
||||
return $newValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new value if a key has a certain value.
|
||||
*
|
||||
* Sets a new value if a key has a certain value. This function only works
|
||||
* when $old and $new are longs.
|
||||
*
|
||||
* @param string $key Key of the value to compare and set.
|
||||
* @param int $old The value to compare the key against.
|
||||
* @param int $new The value to set the key to.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function cas($key, $old, $new)
|
||||
{
|
||||
return apc_cas($this->persistentId . 'd ' . $key, $old, $new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the persistent storage.
|
||||
*
|
||||
* Clears the persistent storage, i.e. removes all keys. Locks are left
|
||||
* intact.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
foreach (new APCIterator(
|
||||
'user',
|
||||
'/^' . preg_quote($this->persistentId, '/') . 'd /',
|
||||
APC_ITER_KEY,
|
||||
100,
|
||||
APC_LIST_ACTIVE
|
||||
) as $key) {
|
||||
apc_delete($key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an external iterator
|
||||
*
|
||||
* Returns an external iterator.
|
||||
*
|
||||
* @param string|null $filter A PCRE regular expression.
|
||||
* Only matching keys will be iterated over.
|
||||
* Setting this to NULL matches all keys of this instance.
|
||||
* @param bool $keysOnly Whether to return only the keys,
|
||||
* or return both the keys and values.
|
||||
*
|
||||
* @return ArrayObject An array with all matching keys as array keys,
|
||||
* and values as array values. If $keysOnly is TRUE, the array keys are
|
||||
* numeric, and the array values are key names.
|
||||
*/
|
||||
public function getIterator($filter = null, $keysOnly = false)
|
||||
{
|
||||
$result = array();
|
||||
foreach (new APCIterator(
|
||||
'user',
|
||||
'/^' . preg_quote($this->persistentId, '/') . 'd /',
|
||||
APC_ITER_KEY,
|
||||
100,
|
||||
APC_LIST_ACTIVE
|
||||
) as $key) {
|
||||
$localKey = strstr($key, $this->persistentId . 'd ');
|
||||
if (null === $filter || preg_match($filter, $localKey)) {
|
||||
if ($keysOnly) {
|
||||
$result[] = $localKey;
|
||||
} else {
|
||||
$result[$localKey] = apc_fetch($key);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new ArrayObject($result);
|
||||
}
|
||||
}
|
358
system/autoload/PEAR2/Cache/SHM/Adapter/Placebo.php
Normal file
358
system/autoload/PEAR2/Cache/SHM/Adapter/Placebo.php
Normal file
@ -0,0 +1,358 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* ~~summary~~
|
||||
*
|
||||
* ~~description~~
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Caching
|
||||
* @package PEAR2_Cache_SHM
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Vasil Rangelov
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 0.1.3
|
||||
* @link http://pear2.php.net/PEAR2_Cache_SHM
|
||||
*/
|
||||
/**
|
||||
* The namespace declaration.
|
||||
*/
|
||||
namespace PEAR2\Cache\SHM\Adapter;
|
||||
|
||||
/**
|
||||
* Throws exceptions from this namespace, and extends from this class.
|
||||
*/
|
||||
use PEAR2\Cache\SHM;
|
||||
|
||||
/**
|
||||
* {@link Placebo::getIterator()} returns this object.
|
||||
*/
|
||||
use ArrayObject;
|
||||
|
||||
/**
|
||||
* This adapter is not truly persistent. It is intended to emulate persistency
|
||||
* in non persistent environments, so that upper level applications can use a
|
||||
* single code path for persistent and non persistent code.
|
||||
*
|
||||
* @category Caching
|
||||
* @package PEAR2_Cache_SHM
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Cache_SHM
|
||||
*/
|
||||
class Placebo extends SHM
|
||||
{
|
||||
/**
|
||||
* @var string ID of the current storage.
|
||||
*/
|
||||
protected $persistentId;
|
||||
|
||||
/**
|
||||
* List of persistent IDs.
|
||||
*
|
||||
* A list of persistent IDs within the current request (as keys) with an int
|
||||
* (as a value) specifying the number of instances in the current request.
|
||||
* Used as an attempt to ensure implicit lock releases on destruction.
|
||||
* @var array
|
||||
*/
|
||||
protected static $requestInstances = array();
|
||||
|
||||
/**
|
||||
* @var array Array of lock names (as values) for each persistent ID (as
|
||||
* key) obtained during the current request.
|
||||
*/
|
||||
protected static $locksBackup = array();
|
||||
|
||||
/**
|
||||
* The data storage.
|
||||
*
|
||||
* Each persistent ID is a key, and the value is an array.
|
||||
* Each such array has data keys as its keys, and an array as a value.
|
||||
* Each such array has as its elements the value, the timeout and the time
|
||||
* the data was set.
|
||||
* @var array
|
||||
*/
|
||||
protected static $data = array();
|
||||
|
||||
/**
|
||||
* Creates a new shared memory storage.
|
||||
*
|
||||
* Estabilishes a separate persistent storage.
|
||||
*
|
||||
* @param string $persistentId The ID for the storage. The storage will be
|
||||
* reused if it exists, or created if it doesn't exist. Data and locks
|
||||
* are namespaced by this ID.
|
||||
*/
|
||||
public function __construct($persistentId)
|
||||
{
|
||||
if (isset(static::$requestInstances[$persistentId])) {
|
||||
++static::$requestInstances[$persistentId];
|
||||
} else {
|
||||
static::$requestInstances[$persistentId] = 1;
|
||||
static::$locksBackup[$persistentId] = array();
|
||||
static::$data[$persistentId] = array();
|
||||
}
|
||||
$this->persistentId = $persistentId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases any unreleased locks.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if (0 === --static::$requestInstances[$this->persistentId]) {
|
||||
static::$locksBackup[$this->persistentId] = array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the adapter meets its requirements.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public static function isMeetingRequirements()
|
||||
{
|
||||
return 'cli' === PHP_SAPI;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pretends to obtain a lock.
|
||||
*
|
||||
* @param string $key Ignored.
|
||||
* @param double $timeout Ignored.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function lock($key, $timeout = null)
|
||||
{
|
||||
$key = (string) $key;
|
||||
if (in_array($key, static::$locksBackup[$this->persistentId], true)) {
|
||||
return false;
|
||||
}
|
||||
static::$locksBackup[$this->persistentId][] = $key;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pretends to release a lock.
|
||||
*
|
||||
* @param string $key Ignored
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function unlock($key)
|
||||
{
|
||||
$key = (string) $key;
|
||||
if (!in_array($key, static::$locksBackup[$this->persistentId], true)) {
|
||||
return false;
|
||||
}
|
||||
unset(static::$locksBackup[$this->persistentId][array_search(
|
||||
$key,
|
||||
static::$locksBackup[$this->persistentId],
|
||||
true
|
||||
)]);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a specified key is in the storage.
|
||||
*
|
||||
* @param string $key Name of key to check.
|
||||
*
|
||||
* @return bool TRUE if the key is in the storage, FALSE otherwise.
|
||||
*/
|
||||
public function exists($key)
|
||||
{
|
||||
return array_key_exists($key, static::$data[$this->persistentId]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a value to the shared memory storage.
|
||||
*
|
||||
* Adds a value to the storage if it doesn't exist, or fails if it does.
|
||||
*
|
||||
* @param string $key Name of key to associate the value with.
|
||||
* @param mixed $value Value for the specified key.
|
||||
* @param int $ttl Because "true" adapters purge the cache at the next
|
||||
* request, this setting is ignored.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function add($key, $value, $ttl = 0)
|
||||
{
|
||||
if ($this->exists($key)) {
|
||||
return false;
|
||||
}
|
||||
return $this->set($key, $value, $ttl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a value in the shared memory storage.
|
||||
*
|
||||
* Adds a value to the storage if it doesn't exist, overwrites it otherwise.
|
||||
*
|
||||
* @param string $key Name of key to associate the value with.
|
||||
* @param mixed $value Value for the specified key.
|
||||
* @param int $ttl Because "true" adapters purge the cache at the next
|
||||
* request, this setting is ignored.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function set($key, $value, $ttl = 0)
|
||||
{
|
||||
static::$data[$this->persistentId][$key] = $value;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value from the shared memory storage.
|
||||
*
|
||||
* Gets the current value, or throws an exception if it's not stored.
|
||||
*
|
||||
* @param string $key Name of key to get the value of.
|
||||
*
|
||||
* @return mixed The current value of the specified key.
|
||||
*/
|
||||
public function get($key)
|
||||
{
|
||||
if ($this->exists($key)) {
|
||||
return static::$data[$this->persistentId][$key];
|
||||
}
|
||||
throw new SHM\InvalidArgumentException(
|
||||
'Unable to fetch key. No such key.',
|
||||
200
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a value from the shared memory storage.
|
||||
*
|
||||
* @param string $key Name of key to delete.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function delete($key)
|
||||
{
|
||||
if ($this->exists($key)) {
|
||||
unset(static::$data[$this->persistentId][$key]);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increases a value from the shared memory storage.
|
||||
*
|
||||
* Increases a value from the shared memory storage. Unlike a plain
|
||||
* set($key, get($key)+$step) combination, this function also implicitly
|
||||
* performs locking.
|
||||
*
|
||||
* @param string $key Name of key to increase.
|
||||
* @param int $step Value to increase the key by.
|
||||
*
|
||||
* @return int The new value.
|
||||
*/
|
||||
public function inc($key, $step = 1)
|
||||
{
|
||||
if (!$this->exists($key) || !is_int($value = $this->get($key))
|
||||
|| !$this->set($key, $value + (int) $step)
|
||||
) {
|
||||
throw new SHM\InvalidArgumentException(
|
||||
'Unable to increase the value. Are you sure the value is int?',
|
||||
201
|
||||
);
|
||||
}
|
||||
return $this->get($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decreases a value from the shared memory storage.
|
||||
*
|
||||
* Decreases a value from the shared memory storage. Unlike a plain
|
||||
* set($key, get($key)-$step) combination, this function also implicitly
|
||||
* performs locking.
|
||||
*
|
||||
* @param string $key Name of key to decrease.
|
||||
* @param int $step Value to decrease the key by.
|
||||
*
|
||||
* @return int The new value.
|
||||
*/
|
||||
public function dec($key, $step = 1)
|
||||
{
|
||||
if (!$this->exists($key) || !is_int($value = $this->get($key))
|
||||
|| !$this->set($key, $value - (int) $step)
|
||||
) {
|
||||
throw new SHM\InvalidArgumentException(
|
||||
'Unable to increase the value. Are you sure the value is int?',
|
||||
202
|
||||
);
|
||||
}
|
||||
return $this->get($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new value if a key has a certain value.
|
||||
*
|
||||
* Sets a new value if a key has a certain value. This function only works
|
||||
* when $old and $new are longs.
|
||||
*
|
||||
* @param string $key Key of the value to compare and set.
|
||||
* @param int $old The value to compare the key against.
|
||||
* @param int $new The value to set the key to.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function cas($key, $old, $new)
|
||||
{
|
||||
return $this->exists($key) && ($this->get($key) === $old)
|
||||
&& is_int($new) && $this->set($key, $new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the persistent storage.
|
||||
*
|
||||
* Clears the persistent storage, i.e. removes all keys. Locks are left
|
||||
* intact.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
static::$data[$this->persistentId] = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an external iterator
|
||||
*
|
||||
* Returns an external iterator.
|
||||
*
|
||||
* @param string|null $filter A PCRE regular expression.
|
||||
* Only matching keys will be iterated over.
|
||||
* Setting this to NULL matches all keys of this instance.
|
||||
* @param bool $keysOnly Whether to return only the keys,
|
||||
* or return both the keys and values.
|
||||
*
|
||||
* @return ArrayObject An array with all matching keys as array keys,
|
||||
* and values as array values. If $keysOnly is TRUE, the array keys are
|
||||
* numeric, and the array values are key names.
|
||||
*/
|
||||
public function getIterator($filter = null, $keysOnly = false)
|
||||
{
|
||||
if (null === $filter) {
|
||||
return new ArrayObject(
|
||||
$keysOnly
|
||||
? array_keys(static::$data[$this->persistentId])
|
||||
: static::$data[$this->persistentId]
|
||||
);
|
||||
}
|
||||
|
||||
$result = array();
|
||||
foreach (static::$data[$this->persistentId] as $key => $value) {
|
||||
if (preg_match($filter, $key)) {
|
||||
$result[$key] = $value;
|
||||
}
|
||||
}
|
||||
return new ArrayObject($keysOnly ? array_keys($result) : $result);
|
||||
}
|
||||
}
|
383
system/autoload/PEAR2/Cache/SHM/Adapter/Wincache.php
Normal file
383
system/autoload/PEAR2/Cache/SHM/Adapter/Wincache.php
Normal file
@ -0,0 +1,383 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* ~~summary~~
|
||||
*
|
||||
* ~~description~~
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Caching
|
||||
* @package PEAR2_Cache_SHM
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Vasil Rangelov
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 0.1.3
|
||||
* @link http://pear2.php.net/PEAR2_Cache_SHM
|
||||
*/
|
||||
/**
|
||||
* The namespace declaration.
|
||||
*/
|
||||
namespace PEAR2\Cache\SHM\Adapter;
|
||||
|
||||
/**
|
||||
* Throws exceptions from this namespace, and extends from this class.
|
||||
*/
|
||||
use PEAR2\Cache\SHM;
|
||||
|
||||
/**
|
||||
* {@link Wincache::getIterator()} returns this object.
|
||||
*/
|
||||
use ArrayObject;
|
||||
|
||||
/**
|
||||
* Shared memory adapter for the WinCache extension.
|
||||
*
|
||||
* @category Caching
|
||||
* @package PEAR2_Cache_SHM
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Cache_SHM
|
||||
*/
|
||||
class Wincache extends SHM
|
||||
{
|
||||
/**
|
||||
* @var string ID of the current storage.
|
||||
*/
|
||||
protected $persistentId;
|
||||
|
||||
/**
|
||||
* List of persistent IDs.
|
||||
*
|
||||
* A list of persistent IDs within the current request (as keys) with an int
|
||||
* (as a value) specifying the number of instances in the current request.
|
||||
* Used as an attempt to ensure implicit lock releases on destruction.
|
||||
* @var array
|
||||
*/
|
||||
protected static $requestInstances = array();
|
||||
|
||||
/**
|
||||
* @var array Array of lock names obtained during the current request.
|
||||
*/
|
||||
protected static $locksBackup = array();
|
||||
|
||||
/**
|
||||
* Creates a new shared memory storage.
|
||||
*
|
||||
* Estabilishes a separate persistent storage.
|
||||
*
|
||||
* @param string $persistentId The ID for the storage. The storage will be
|
||||
* reused if it exists, or created if it doesn't exist. Data and locks
|
||||
* are namespaced by this ID.
|
||||
*/
|
||||
public function __construct($persistentId)
|
||||
{
|
||||
$this->persistentId
|
||||
= static::encodeLockName(__CLASS__ . ' ' . $persistentId) . ' ';
|
||||
if (isset(static::$requestInstances[$this->persistentId])) {
|
||||
static::$requestInstances[$this->persistentId]++;
|
||||
} else {
|
||||
static::$requestInstances[$this->persistentId] = 1;
|
||||
static::$locksBackup[$this->persistentId] = array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a lock name
|
||||
*
|
||||
* Encodes a lock name, so that it can be properly obtained. The scheme used
|
||||
* is a subset of URL encoding, with only the "%" and "\" characters being
|
||||
* escaped. The encoding itself is necessary, since lock names can't contain
|
||||
* the "\" character.
|
||||
*
|
||||
* @param string $name The lock name to encode.
|
||||
*
|
||||
* @return string The encoded name.
|
||||
* @link http://msdn.microsoft.com/en-us/library/ms682411(VS.85).aspx
|
||||
*/
|
||||
protected static function encodeLockName($name)
|
||||
{
|
||||
return str_replace(array('%', '\\'), array('%25', '%5C'), $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the adapter meets its requirements.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public static function isMeetingRequirements()
|
||||
{
|
||||
return extension_loaded('wincache')
|
||||
&& version_compare(phpversion('wincache'), '1.1.0', '>=')
|
||||
&& ini_get('wincache.ucenabled')
|
||||
&& ('cli' !== PHP_SAPI || ini_get('wincache.enablecli'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases any locks obtained by this instance as soon as there are no more
|
||||
* references to the object's persistent ID.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if (0 === --static::$requestInstances[$this->persistentId]) {
|
||||
foreach (static::$locksBackup[$this->persistentId] as $key) {
|
||||
wincache_unlock(
|
||||
$this->persistentId . static::encodeLockName($key)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtains a named lock.
|
||||
*
|
||||
* @param string $key Name of the key to obtain. Note that $key may
|
||||
* repeat for each distinct $persistentId.
|
||||
* @param double $timeout Ignored with WinCache. Script will always block if
|
||||
* the lock can't be immediatly obtained.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function lock($key, $timeout = null)
|
||||
{
|
||||
$result = wincache_lock(
|
||||
$this->persistentId . static::encodeLockName($key)
|
||||
);
|
||||
if ($result) {
|
||||
static::$locksBackup[$this->persistentId] = $key;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases a named lock.
|
||||
*
|
||||
* @param string $key Name of the key to release. Note that $key may
|
||||
* repeat for each distinct $persistentId.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function unlock($key)
|
||||
{
|
||||
$result = wincache_unlock(
|
||||
$this->persistentId . static::encodeLockName($key)
|
||||
);
|
||||
if ($result) {
|
||||
unset(static::$locksBackup[$this->persistentId][array_search(
|
||||
$key,
|
||||
static::$locksBackup[$this->persistentId],
|
||||
true
|
||||
)]);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a specified key is in the storage.
|
||||
*
|
||||
* @param string $key Name of key to check.
|
||||
*
|
||||
* @return bool TRUE if the key is in the storage, FALSE otherwise.
|
||||
*/
|
||||
public function exists($key)
|
||||
{
|
||||
return wincache_ucache_exists($this->persistentId . $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a value to the shared memory storage.
|
||||
*
|
||||
* Sets a value to the storage if it doesn't exist, or fails if it does.
|
||||
*
|
||||
* @param string $key Name of key to associate the value with.
|
||||
* @param mixed $value Value for the specified key.
|
||||
* @param int $ttl Seconds to store the value. If set to 0 indicates no
|
||||
* time limit.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function add($key, $value, $ttl = 0)
|
||||
{
|
||||
return wincache_ucache_add($this->persistentId . $key, $value, $ttl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a value in the shared memory storage.
|
||||
*
|
||||
* Adds a value to the storage if it doesn't exist, overwrites it otherwise.
|
||||
*
|
||||
* @param string $key Name of key to associate the value with.
|
||||
* @param mixed $value Value for the specified key.
|
||||
* @param int $ttl Seconds to store the value. If set to 0 indicates no
|
||||
* time limit.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function set($key, $value, $ttl = 0)
|
||||
{
|
||||
return wincache_ucache_set($this->persistentId . $key, $value, $ttl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value from the shared memory storage.
|
||||
*
|
||||
* Gets the current value, or throws an exception if it's not stored.
|
||||
*
|
||||
* @param string $key Name of key to get the value of.
|
||||
*
|
||||
* @return mixed The current value of the specified key.
|
||||
*/
|
||||
public function get($key)
|
||||
{
|
||||
$value = wincache_ucache_get($this->persistentId . $key, $success);
|
||||
if (!$success) {
|
||||
throw new SHM\InvalidArgumentException(
|
||||
'Unable to fetch key. No such key, or key has expired.',
|
||||
300
|
||||
);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a value from the shared memory storage.
|
||||
*
|
||||
* @param string $key Name of key to delete.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function delete($key)
|
||||
{
|
||||
return wincache_ucache_delete($this->persistentId . $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increases a value from the shared memory storage.
|
||||
*
|
||||
* Increases a value from the shared memory storage. Unlike a plain
|
||||
* set($key, get($key)+$step) combination, this function also implicitly
|
||||
* performs locking.
|
||||
*
|
||||
* @param string $key Name of key to increase.
|
||||
* @param int $step Value to increase the key by.
|
||||
*
|
||||
* @return int The new value.
|
||||
*/
|
||||
public function inc($key, $step = 1)
|
||||
{
|
||||
$newValue = wincache_ucache_inc(
|
||||
$this->persistentId . $key,
|
||||
(int) $step,
|
||||
$success
|
||||
);
|
||||
if (!$success) {
|
||||
throw new SHM\InvalidArgumentException(
|
||||
'Unable to increase the value. Are you sure the value is int?',
|
||||
301
|
||||
);
|
||||
}
|
||||
return $newValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decreases a value from the shared memory storage.
|
||||
*
|
||||
* Decreases a value from the shared memory storage. Unlike a plain
|
||||
* set($key, get($key)-$step) combination, this function also implicitly
|
||||
* performs locking.
|
||||
*
|
||||
* @param string $key Name of key to decrease.
|
||||
* @param int $step Value to decrease the key by.
|
||||
*
|
||||
* @return int The new value.
|
||||
*/
|
||||
public function dec($key, $step = 1)
|
||||
{
|
||||
$newValue = wincache_ucache_dec(
|
||||
$this->persistentId . $key,
|
||||
(int) $step,
|
||||
$success
|
||||
);
|
||||
if (!$success) {
|
||||
throw new SHM\InvalidArgumentException(
|
||||
'Unable to decrease the value. Are you sure the value is int?',
|
||||
302
|
||||
);
|
||||
}
|
||||
return $newValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new value if a key has a certain value.
|
||||
*
|
||||
* Sets a new value if a key has a certain value. This function only works
|
||||
* when $old and $new are longs.
|
||||
*
|
||||
* @param string $key Key of the value to compare and set.
|
||||
* @param int $old The value to compare the key against.
|
||||
* @param int $new The value to set the key to.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function cas($key, $old, $new)
|
||||
{
|
||||
return wincache_ucache_cas($this->persistentId . $key, $old, $new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the persistent storage.
|
||||
*
|
||||
* Clears the persistent storage, i.e. removes all keys. Locks are left
|
||||
* intact.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$info = wincache_ucache_info();
|
||||
foreach ($info['ucache_entries'] as $entry) {
|
||||
if (!$entry['is_session']
|
||||
&& 0 === strpos($entry['key_name'], $this->persistentId)
|
||||
) {
|
||||
wincache_ucache_delete($entry['key_name']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an external iterator
|
||||
*
|
||||
* Returns an external iterator.
|
||||
*
|
||||
* @param string|null $filter A PCRE regular expression.
|
||||
* Only matching keys will be iterated over.
|
||||
* Setting this to NULL matches all keys of this instance.
|
||||
* @param bool $keysOnly Whether to return only the keys,
|
||||
* or return both the keys and values.
|
||||
*
|
||||
* @return ArrayObject An array with all matching keys as array keys,
|
||||
* and values as array values. If $keysOnly is TRUE, the array keys are
|
||||
* numeric, and the array values are key names.
|
||||
*/
|
||||
public function getIterator($filter = null, $keysOnly = false)
|
||||
{
|
||||
$info = wincache_ucache_info();
|
||||
$result = array();
|
||||
foreach ($info['ucache_entries'] as $entry) {
|
||||
if (!$entry['is_session']
|
||||
&& 0 === strpos($entry['key_name'], $this->persistentId)
|
||||
) {
|
||||
$localKey = strstr($entry['key_name'], $this->persistentId);
|
||||
if (null === $filter || preg_match($filter, $localKey)) {
|
||||
if ($keysOnly) {
|
||||
$result[] = $localKey;
|
||||
} else {
|
||||
$result[$localKey] = apc_fetch($localKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return new ArrayObject($result);
|
||||
}
|
||||
}
|
34
system/autoload/PEAR2/Cache/SHM/Exception.php
Normal file
34
system/autoload/PEAR2/Cache/SHM/Exception.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* ~~summary~~
|
||||
*
|
||||
* ~~description~~
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Caching
|
||||
* @package PEAR2_Cache_SHM
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Vasil Rangelov
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 0.1.3
|
||||
* @link http://pear2.php.net/PEAR2_Cache_SHM
|
||||
*/
|
||||
/**
|
||||
* The namespace declaration.
|
||||
*/
|
||||
namespace PEAR2\Cache\SHM;
|
||||
|
||||
/**
|
||||
* Generic exception class of this package.
|
||||
*
|
||||
* @category Caching
|
||||
* @package PEAR2_Cache_SHM
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Cache_SHM
|
||||
*/
|
||||
interface Exception
|
||||
{
|
||||
}
|
35
system/autoload/PEAR2/Cache/SHM/InvalidArgumentException.php
Normal file
35
system/autoload/PEAR2/Cache/SHM/InvalidArgumentException.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* ~~summary~~
|
||||
*
|
||||
* ~~description~~
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Caching
|
||||
* @package PEAR2_Cache_SHM
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Vasil Rangelov
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 0.1.3
|
||||
* @link http://pear2.php.net/PEAR2_Cache_SHM
|
||||
*/
|
||||
/**
|
||||
* The namespace declaration.
|
||||
*/
|
||||
namespace PEAR2\Cache\SHM;
|
||||
|
||||
/**
|
||||
* Exception thrown when there's something wrong with an argument.
|
||||
*
|
||||
* @category Caching
|
||||
* @package PEAR2_Cache_SHM
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Cache_SHM
|
||||
*/
|
||||
class InvalidArgumentException extends \InvalidArgumentException
|
||||
implements Exception
|
||||
{
|
||||
}
|
369
system/autoload/PEAR2/Console/Color.php
Normal file
369
system/autoload/PEAR2/Console/Color.php
Normal file
@ -0,0 +1,369 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Main class for Console_Color
|
||||
*
|
||||
* PHP version 5.3
|
||||
*
|
||||
* @category Console
|
||||
* @package Console_Color
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @author Ivo Nascimento <ivo@o8o.com.br>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0
|
||||
* @link http://pear.php.net/package/Console_Color
|
||||
*/
|
||||
namespace PEAR2\Console;
|
||||
|
||||
use PEAR2\Console\Color\Backgrounds;
|
||||
use PEAR2\Console\Color\Flags;
|
||||
use PEAR2\Console\Color\Fonts;
|
||||
use PEAR2\Console\Color\Styles;
|
||||
use PEAR2\Console\Color\UnexpectedValueException;
|
||||
use ReflectionClass;
|
||||
|
||||
/**
|
||||
* Main class for Console_Color.
|
||||
*
|
||||
* @category Console
|
||||
* @package Console_Color
|
||||
* @author Ivo Nascimento <ivo@o8o.com.br>
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_Color
|
||||
*/
|
||||
class Color
|
||||
{
|
||||
/**
|
||||
* @var array List of valid font colors.
|
||||
* Filled by {@link fillValidators()}.
|
||||
*/
|
||||
protected static $validFonts = array();
|
||||
|
||||
/**
|
||||
* @var array List of valid background colors.
|
||||
* Filled by {@link fillValidators()}.
|
||||
*/
|
||||
protected static $validBackgorunds = array();
|
||||
|
||||
/**
|
||||
* @var string Name of a class that is used to resolve flags to codes.
|
||||
*/
|
||||
protected static $flagsResolver = '';
|
||||
|
||||
/**
|
||||
* @var string Name of a class that is used to resolve styles to codes.
|
||||
*/
|
||||
protected static $stylesResolver = '';
|
||||
|
||||
/**
|
||||
* @var int Flags to set.
|
||||
*/
|
||||
protected $flags = 0;
|
||||
|
||||
/**
|
||||
* @var int|null The code for the currently specified font color.
|
||||
*/
|
||||
protected $font = null;
|
||||
|
||||
/**
|
||||
* @var int|null The code for the currently specified background color.
|
||||
*/
|
||||
protected $backgorund = null;
|
||||
|
||||
/**
|
||||
* @var bool[] Array with the status of each style.
|
||||
*/
|
||||
protected $styles = array();
|
||||
|
||||
/**
|
||||
* @var string|null The string to write to console to get the specified
|
||||
* styling. NULL when the string needs to be regenerated.
|
||||
*/
|
||||
protected $sequence = null;
|
||||
|
||||
/**
|
||||
* Fills the list of valid fonts and backgrounds.
|
||||
*
|
||||
* Classes extending this one that wish to add additional valid colors,
|
||||
* flags or styles should call this method in their own constructor BEFORE
|
||||
* calling the parent constructor.
|
||||
*
|
||||
* @param string $fonts Name of class, the constants of which are
|
||||
* valid font colors.
|
||||
* @param string $backgrounds Name of class, the constants of which are
|
||||
* valid background colors.
|
||||
* @param string $flags Name of class that resolves flags to codes.
|
||||
* Must inheirt from {@link Flags}. Constants of this
|
||||
* class are considered the valid flags, and the coresponding codes must
|
||||
* be overriden at the static $flagCodes property.
|
||||
* @param string $styles Name of class that resolves styles to codes.
|
||||
* Must inherit from {@link Styles}. Constants of this class are
|
||||
* considered the valid styles, and the corresponding off/on codes must
|
||||
* be overriden at the static $styleCodes property.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function fillVlidators(
|
||||
$fonts,
|
||||
$backgrounds,
|
||||
$flags,
|
||||
$styles
|
||||
) {
|
||||
if (empty(static::$validFonts)) {
|
||||
$fonts = new ReflectionClass($fonts);
|
||||
static::$validFonts = array_values(
|
||||
array_unique($fonts->getConstants(), SORT_REGULAR)
|
||||
);
|
||||
}
|
||||
|
||||
if (empty(static::$validBackgorunds)) {
|
||||
$bgs = new ReflectionClass($backgrounds);
|
||||
static::$validBackgorunds = array_values(
|
||||
array_unique($bgs->getConstants(), SORT_REGULAR)
|
||||
);
|
||||
}
|
||||
|
||||
if ('' === static::$flagsResolver) {
|
||||
$base = __CLASS__ . '\Flags';
|
||||
if ($base === $flags || is_subclass_of($flags, $base)) {
|
||||
static::$flagsResolver = $flags;
|
||||
}
|
||||
}
|
||||
|
||||
if ('' === static::$stylesResolver) {
|
||||
$base = __CLASS__ . '\Styles';
|
||||
if ($base === $styles || is_subclass_of($styles, $base)) {
|
||||
static::$stylesResolver = $styles;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new color.
|
||||
*
|
||||
* Note that leaving all arguments with their default values (and not
|
||||
* applying styles) would result in a sequence that resets all settings to
|
||||
* the console's defaults.
|
||||
*
|
||||
* @param int|null $font Initial font color.
|
||||
* @param int|null $background Initial backgorund color.
|
||||
* @param int $flags Initial flags.
|
||||
*
|
||||
* @see setFlags()
|
||||
* @see setStyles()
|
||||
* @see __toString()
|
||||
*/
|
||||
public function __construct(
|
||||
$font = Fonts::KEEP,
|
||||
$background = Backgrounds::KEEP,
|
||||
$flags = Flags::NONE
|
||||
) {
|
||||
static::fillVlidators(
|
||||
__CLASS__ . '\Fonts',
|
||||
__CLASS__ . '\Backgrounds',
|
||||
__CLASS__ . '\Flags',
|
||||
__CLASS__ . '\Styles'
|
||||
);
|
||||
$this->setFont($font);
|
||||
$this->setBackground($background);
|
||||
$this->setFlags($flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the font color.
|
||||
*
|
||||
* @return int|null $color The font color.
|
||||
*/
|
||||
public function getFont()
|
||||
{
|
||||
return $this->font;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the font color.
|
||||
*
|
||||
* @param int|null $color The font color.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setFont($color)
|
||||
{
|
||||
if (!in_array($color, static::$validFonts, true)) {
|
||||
throw new UnexpectedValueException(
|
||||
'Invalid font supplied.',
|
||||
UnexpectedValueException::CODE_FONT
|
||||
);
|
||||
}
|
||||
$this->font = $color;
|
||||
|
||||
$this->sequence = null;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the background color.
|
||||
*
|
||||
* @return int|null $color The background color.
|
||||
*/
|
||||
public function getBackground()
|
||||
{
|
||||
return $this->backgorund;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the background color.
|
||||
*
|
||||
* @param int|null $color The background color.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setBackground($color)
|
||||
{
|
||||
if (!in_array($color, static::$validBackgorunds, true)) {
|
||||
throw new UnexpectedValueException(
|
||||
'Invalid background supplied.',
|
||||
UnexpectedValueException::CODE_BACKGROUND
|
||||
);
|
||||
}
|
||||
$this->backgorund = $color;
|
||||
|
||||
$this->sequence = null;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the flags.
|
||||
*
|
||||
* @return int The currently set flags.
|
||||
*/
|
||||
public function getFlags()
|
||||
{
|
||||
return $this->flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the flags.
|
||||
*
|
||||
* Sets the flags to apply in the sequence. Note that flags are applied
|
||||
* before all other settings, in ascending order of the constant values.
|
||||
*
|
||||
* @param int $flags The new flags to set. Unknown flags will be ignored
|
||||
* when forming the sequence, but will be visible with
|
||||
* {@link getFlags()} non the less.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setFlags($flags)
|
||||
{
|
||||
$this->flags = (int)$flags;
|
||||
|
||||
$this->sequence = null;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets styles.
|
||||
*
|
||||
* @param int|null $style A single style to get the status of,
|
||||
* or {@link Styles::ALL} to get all styles in an array.
|
||||
*
|
||||
* @return bool|null|bool[] A single style status, or
|
||||
* an array of status if $style is {@link Styles::ALL}.
|
||||
*/
|
||||
public function getStyles($style = Styles::ALL)
|
||||
{
|
||||
if (Styles::ALL === $style) {
|
||||
return $this->styles;
|
||||
}
|
||||
return isset($this->styles[$style]) ? $this->styles[$style] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets styles.
|
||||
*
|
||||
* Sets styles matched to a specified state.
|
||||
*
|
||||
* @param int|null $styles Bitmask of styles to set. You can also use the
|
||||
* constant {@link Styles::ALL} (only) to set all known styles.
|
||||
* Unknown styles will be ignored.
|
||||
* @param bool|null $state The state to set the matched styles in.
|
||||
* TRUE to enable them,
|
||||
* FLASE to disable them,
|
||||
* NULL to remove the setting for them (in effect using whatever the
|
||||
* console had before the sequence was applied).
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setStyles($styles, $state)
|
||||
{
|
||||
$matchingStyles = call_user_func(
|
||||
array(static::$stylesResolver, 'match'),
|
||||
$styles
|
||||
);
|
||||
if (null === $state) {
|
||||
foreach ($matchingStyles as $style) {
|
||||
unset($this->styles[$style]);
|
||||
}
|
||||
} else {
|
||||
$state = (bool)$state;
|
||||
foreach ($matchingStyles as $style) {
|
||||
$this->styles[$style] = $state;
|
||||
}
|
||||
ksort($this->styles);
|
||||
}
|
||||
|
||||
$this->sequence = null;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the console escaping sequence.
|
||||
*
|
||||
* This is a magic PHP method that will be called when you use the object in
|
||||
* a string context or otherwise explicitly cast it to a string.
|
||||
*
|
||||
* It generates the escape sequence and returns it.
|
||||
* For the sake of performance, the escape sequence is cached, and is only
|
||||
* regenerated when a setter has been previously called.
|
||||
*
|
||||
* @return string The string to write to console to get the specified
|
||||
* styling.
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
if (null === $this->sequence) {
|
||||
$seq = "\033[";
|
||||
|
||||
$flags = implode(
|
||||
';',
|
||||
call_user_func(
|
||||
array(static::$flagsResolver, 'getCodes'),
|
||||
$this->flags
|
||||
)
|
||||
);
|
||||
if ('' !== $flags) {
|
||||
$seq .= $flags . ';';
|
||||
}
|
||||
|
||||
if (Fonts::KEEP !== $this->font) {
|
||||
$seq .= "{$this->font};";
|
||||
}
|
||||
if (Backgrounds::KEEP !== $this->backgorund) {
|
||||
$seq .= "{$this->backgorund};";
|
||||
}
|
||||
|
||||
foreach ($this->styles as $style => $state) {
|
||||
$seq .= call_user_func(
|
||||
array(static::$stylesResolver, 'getCode'),
|
||||
$style,
|
||||
$state
|
||||
) . ';';
|
||||
}
|
||||
|
||||
$this->sequence = rtrim($seq, ';') . 'm';
|
||||
}
|
||||
|
||||
return $this->sequence;
|
||||
}
|
||||
}
|
136
system/autoload/PEAR2/Console/Color/Backgrounds.php
Normal file
136
system/autoload/PEAR2/Console/Color/Backgrounds.php
Normal file
@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Backgrounds class for PEAR2_Console_Color.
|
||||
*
|
||||
* PHP version 5.3
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2_Console_Color
|
||||
* @author Ivo Nascimento <ivo@o8o.com.br>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0
|
||||
* @link http://pear2.php.net/PEAR2_Console_Color
|
||||
*/
|
||||
namespace PEAR2\Console\Color;
|
||||
|
||||
/**
|
||||
* This class has the possibles values to a Background Color.
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2_Console_Color
|
||||
* @author Ivo Nascimento <ivo@o8o.com.br>
|
||||
* @copyright 2011 Ivo Nascimento
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_Color
|
||||
*/
|
||||
abstract class Backgrounds
|
||||
{
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setBackground()} to specify that
|
||||
* the background color already in effect should be kept.
|
||||
*/
|
||||
const KEEP = null;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setBackground()} to set the
|
||||
* background color to black/grey (implmementation defined).
|
||||
*/
|
||||
const BLACK = 40;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setBackground()} to set the
|
||||
* background color to black/grey (implementation defined).
|
||||
*/
|
||||
const GREY = 40;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setBackground()} to set the
|
||||
* background color to maroon/red (implementation defined).
|
||||
*/
|
||||
const MAROON = 41;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setBackground()} to set the
|
||||
* background color to maroon/red (implementation defined).
|
||||
*/
|
||||
const RED = 41;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setBackground()} to set the
|
||||
* background color to green/lime (implementation defined).
|
||||
*/
|
||||
const GREEN = 42;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setBackground()} to set the
|
||||
* background color to green/lime (implementation defined).
|
||||
*/
|
||||
const LIME = 42;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setBackground()} to set the
|
||||
* background color to brown/yellow (implementation defined).
|
||||
*/
|
||||
const BROWN = 43;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setBackground()} to set the
|
||||
* background color to brown/yellow (implementation defined).
|
||||
*/
|
||||
const YELLOW = 43;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setBackground()} to set the
|
||||
* background color to navy/blue (implementation defined).
|
||||
*/
|
||||
const NAVY = 44;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setBackground()} to set the
|
||||
* background color to navy/blue (implementation defined).
|
||||
*/
|
||||
const BLUE = 44;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setBackground()} to set the
|
||||
* background color to purple/magenta (implementation defined).
|
||||
*/
|
||||
const PURPLE = 45;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setBackground()} to set the
|
||||
* background color to purple/magenta (implementation defined).
|
||||
*/
|
||||
const MAGENTA = 45;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setBackground()} to set the
|
||||
* background color to teal/cyan (implementation defined).
|
||||
*/
|
||||
const TEAL = 46;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setBackground()} to set the
|
||||
* background color to teal/cyan (implementation defined).
|
||||
*/
|
||||
const CYAN = 46;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setBackground()} to set the
|
||||
* background color to silver/white (implementation defined).
|
||||
*/
|
||||
const SILVER = 47;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setBackground()} to set the
|
||||
* background color to silver/white (implementation defined).
|
||||
*/
|
||||
const WHITE = 47;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setBackground()} to set the
|
||||
* background color to whatever the default one is.
|
||||
*/
|
||||
const RESET = 49;
|
||||
}
|
28
system/autoload/PEAR2/Console/Color/Exception.php
Normal file
28
system/autoload/PEAR2/Console/Color/Exception.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Exception class for PEAR2_Console_Color.
|
||||
*
|
||||
* PHP version 5.3
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2_Console_Color
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0
|
||||
* @link http://pear2.php.net/PEAR2_Console_Color
|
||||
*/
|
||||
namespace PEAR2\Console\Color;
|
||||
|
||||
/**
|
||||
* Exception class for PEAR2_Console_Color.
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2_Console_Color
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_Color
|
||||
*/
|
||||
interface Exception
|
||||
{
|
||||
}
|
88
system/autoload/PEAR2/Console/Color/Flags.php
Normal file
88
system/autoload/PEAR2/Console/Color/Flags.php
Normal file
@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Flags class for PEAR2_Console_Color
|
||||
* Mappping the names of Font Style to your values.
|
||||
*
|
||||
* PHP version 5.3
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2_Console_Color
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0
|
||||
* @link http://pear2.php.net/PEAR2_Console_Color
|
||||
*/
|
||||
namespace PEAR2\Console\Color;
|
||||
|
||||
use ReflectionClass;
|
||||
|
||||
/**
|
||||
* This class has the possibles flags to a color setting.
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2_Console_Color
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_Color
|
||||
*/
|
||||
abstract class Flags
|
||||
{
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setFlags()} to specify that no
|
||||
* flags should be applied.
|
||||
*/
|
||||
const NONE = 0;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setFlags()} as part of a bitmask.
|
||||
* If specified, resets all color and style information before applying
|
||||
* everything else.
|
||||
*/
|
||||
const RESET = 1;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setFlags()} as part of a bitmask.
|
||||
* If specified, inverses the font and background colors, before letting
|
||||
* the remaining settings further modify things.
|
||||
* If specified together with {@link self::RESET}, takes effect AFTER the
|
||||
* reset.
|
||||
*/
|
||||
const INVERSE = 2;
|
||||
|
||||
/**
|
||||
* @var int[] Array with the flag as a key, and the corresponding code as a
|
||||
* value.
|
||||
*/
|
||||
protected static $flagCodes = array(
|
||||
self::RESET => 0,
|
||||
self::INVERSE => 7
|
||||
);
|
||||
|
||||
/**
|
||||
* Gets the codes for a flag set.
|
||||
*
|
||||
* @param int $flags The flags to get the codes for.
|
||||
*
|
||||
* @return int[] The codes for the flags specified, in ascending order,
|
||||
* based on the flag constants' values.
|
||||
*/
|
||||
final public static function getCodes($flags)
|
||||
{
|
||||
if (self::NONE === $flags) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$result = array();
|
||||
$flagsClass = new ReflectionClass(get_called_class());
|
||||
$validFlags = array_values(
|
||||
array_unique($flagsClass->getConstants(), SORT_NUMERIC)
|
||||
);
|
||||
foreach ($validFlags as $flag) {
|
||||
if ($flags & $flag) {
|
||||
$result[] = static::$flagCodes[$flag];
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
136
system/autoload/PEAR2/Console/Color/Fonts.php
Normal file
136
system/autoload/PEAR2/Console/Color/Fonts.php
Normal file
@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Font class for PEAR2_Console_Color
|
||||
*
|
||||
* PHP version 5.3
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2_Console_Color
|
||||
* @author Ivo Nascimento <ivo@o8o.com.br>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0
|
||||
* @link http://pear2.php.net/PEAR2_Console_Color
|
||||
*/
|
||||
namespace PEAR2\Console\Color;
|
||||
|
||||
/**
|
||||
* This class has the possibles values to a Font Color.
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2_Console_Color
|
||||
* @author Ivo Nascimento <ivo@o8o.com.br>
|
||||
* @copyright 2011 Ivo Nascimento
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_Color
|
||||
*/
|
||||
abstract class Fonts
|
||||
{
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setFont()} to specify that
|
||||
* the font color already in effect should be kept.
|
||||
*/
|
||||
const KEEP = null;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setFont()} to set the
|
||||
* font color to black/grey (implementation defined).
|
||||
*/
|
||||
const BLACK = 30;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setFont()} to set the
|
||||
* font color to black/grey (implementation defined).
|
||||
*/
|
||||
const GREY = 30;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setFont()} to set the
|
||||
* font color to maroon/red (implementation defined).
|
||||
*/
|
||||
const MAROON = 31;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setFont()} to set the
|
||||
* font color to maroon/red (implementation defined).
|
||||
*/
|
||||
const RED = 31;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setFont()} to set the
|
||||
* font color to green/lime (implementation defined).
|
||||
*/
|
||||
const LIME = 32;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setFont()} to set the
|
||||
* font color to green/lime (implementation defined).
|
||||
*/
|
||||
const GREEN = 32;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setFont()} to set the
|
||||
* font color to brown/yellow (implementation defined).
|
||||
*/
|
||||
const BROWN = 33;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setFont()} to set the
|
||||
* font color to brown/yellow (implementation defined).
|
||||
*/
|
||||
const YELLOW = 33;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setFont()} to set the
|
||||
* font color to navy/blue (implementation defined).
|
||||
*/
|
||||
const NAVY = 34;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setFont()} to set the
|
||||
* font color to navy/blue (implementation defined).
|
||||
*/
|
||||
const BLUE = 34;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setFont()} to set the
|
||||
* font color to purple/magenta (implementation defined).
|
||||
*/
|
||||
const PURPLE = 35;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setFont()} to set the
|
||||
* font color to purple/magenta (implementation defined).
|
||||
*/
|
||||
const MAGENTA = 35;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setFont()} to set the
|
||||
* font color to teal/cyan (implementation defined).
|
||||
*/
|
||||
const TEAL = 36;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setFont()} to set the
|
||||
* font color to teal/cyan (implementation defined).
|
||||
*/
|
||||
const CYAN = 36;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setFont()} to set the
|
||||
* font color to silver/white (implementation defined).
|
||||
*/
|
||||
const SILVER = 37;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setFont()} to set the
|
||||
* font color to silver/white (implementation defined).
|
||||
*/
|
||||
const WHITE = 37;
|
||||
|
||||
/**
|
||||
* Used at {@link \PEAR2\Console\Color::setFont()} to set the
|
||||
* font color to whatever the default one is.
|
||||
*/
|
||||
const RESET = 39;
|
||||
}
|
130
system/autoload/PEAR2/Console/Color/Styles.php
Normal file
130
system/autoload/PEAR2/Console/Color/Styles.php
Normal file
@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Styles class for PEAR2_Console_Color.
|
||||
*
|
||||
* PHP version 5.3
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2_Console_Color
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0
|
||||
* @link http://pear2.php.net/PEAR2_Console_Color
|
||||
*/
|
||||
namespace PEAR2\Console\Color;
|
||||
|
||||
use ReflectionClass;
|
||||
|
||||
/**
|
||||
* This class has the possibles values to a Font Style.
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2_Console_Color
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_Color
|
||||
*/
|
||||
abstract class Styles
|
||||
{
|
||||
/**
|
||||
* Used in {@link \PEAR2\Console\Color::setStyles()} to match all styles.
|
||||
*/
|
||||
const ALL = null;
|
||||
|
||||
/**
|
||||
* Used in {@link \PEAR2\Console\Color::setStyles()} as part of a bitmask.
|
||||
* If specified, matches the bold style.
|
||||
* When this style is enabled, the font is bolder.
|
||||
* With ANSICON, the font color becomes more intense (but not bolder).
|
||||
*/
|
||||
const BOLD = 1;
|
||||
|
||||
/**
|
||||
* Used in {@link \PEAR2\Console\Color::setStyles()} as part of a bitmask.
|
||||
* If specified, matches the underline style.
|
||||
* When this style is enabled, the font is underlined.
|
||||
* With ANSICON, the background color becomes more intense
|
||||
* (and the font is not underlined), same as {@link self::BLINK}.
|
||||
*/
|
||||
const UNDERLINE = 2;
|
||||
|
||||
/**
|
||||
* Used in {@link \PEAR2\Console\Color::setStyles()} as part of a bitmask.
|
||||
* If specified, matches the blink style.
|
||||
* When this style is enabled, the font color switches between its regular
|
||||
* color and the background color at regular (implementation defined)
|
||||
* intervals, creating the illusion of a blinking text.
|
||||
* With ANSICON, the background color becomes more intense
|
||||
* (and the font is not blinking), same as with {@link self::UNDERLINE}.
|
||||
*/
|
||||
const BLINK = 4;
|
||||
|
||||
/**
|
||||
* Used in {@link \PEAR2\Console\Color::setStyles()} as part of a bitmask.
|
||||
* If specified, matches the concealed style.
|
||||
* When this style is enabled, the font color becomes the background color,
|
||||
* rendering the text invisible. This style is particularly useful for
|
||||
* implementations where simply setting the same color and background color
|
||||
* would not necesarily provide a fully invisibile text (e.g. ANSICON).
|
||||
*/
|
||||
const CONCEALED = 8;
|
||||
|
||||
/**
|
||||
* @var (int[])[] An array describing the codes for the styles.
|
||||
* Each array key is the style's constant, and each value is an array
|
||||
* where the first member is the disable code, and the second is the
|
||||
* enable code.
|
||||
*/
|
||||
protected static $styleCodes = array(
|
||||
self::BOLD => array(22, 1),
|
||||
self::UNDERLINE => array(24, 4),
|
||||
self::BLINK => array(25, 5),
|
||||
self::CONCEALED => array(28, 8)
|
||||
);
|
||||
|
||||
/**
|
||||
* Get style constants.
|
||||
*
|
||||
* @param int|null $styles Bitmask of styles to match.
|
||||
* You can also use {@link self::ALL} (only) to get all styles.
|
||||
*
|
||||
* @return int[] Matching style constants.
|
||||
*/
|
||||
final public static function match($styles)
|
||||
{
|
||||
$flagsClass = new ReflectionClass(get_called_class());
|
||||
$validStyles = array_values(
|
||||
array_unique($flagsClass->getConstants(), SORT_NUMERIC)
|
||||
);
|
||||
unset($validStyles[array_search(self::ALL, $validStyles, true)]);
|
||||
|
||||
if (self::ALL === $styles) {
|
||||
return $validStyles;
|
||||
}
|
||||
$styles = (int)$styles;
|
||||
|
||||
$result = array();
|
||||
foreach ($validStyles as $flag) {
|
||||
if ($styles & $flag) {
|
||||
$result[] = $flag;
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the code for a style.
|
||||
*
|
||||
* @param int $style The style to get the code for.
|
||||
* @param bool $state The state to get code for.
|
||||
* TRUE for the enabled state codes,
|
||||
* FALSE for the disabled state codes.
|
||||
*
|
||||
* @return int The code for the flag specified.
|
||||
*/
|
||||
final public static function getCode($style, $state)
|
||||
{
|
||||
return static::$styleCodes[$style][(int)(bool)$state];
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Exception class for PEAR2_Console_Color.
|
||||
*
|
||||
* PHP version 5.3
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2_Console_Color
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0
|
||||
* @link http://pear2.php.net/PEAR2_Console_Color
|
||||
*/
|
||||
namespace PEAR2\Console\Color;
|
||||
|
||||
use UnexpectedValueException as U;
|
||||
|
||||
/**
|
||||
* Exception class for PEAR2_Console_Color.
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2_Console_Color
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Ivo Nascimento
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_Color
|
||||
*/
|
||||
class UnexpectedValueException extends U implements Exception
|
||||
{
|
||||
/**
|
||||
* Used when an unexpected font value is supplied.
|
||||
*/
|
||||
const CODE_FONT = 1;
|
||||
|
||||
/**
|
||||
* Used when an unexpected background value is supplied.
|
||||
*/
|
||||
const CODE_BACKGROUND = 2;
|
||||
}
|
1289
system/autoload/PEAR2/Console/CommandLine.php
Normal file
1289
system/autoload/PEAR2/Console/CommandLine.php
Normal file
File diff suppressed because it is too large
Load Diff
142
system/autoload/PEAR2/Console/CommandLine/Action.php
Normal file
142
system/autoload/PEAR2/Console/CommandLine/Action.php
Normal file
@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* This file is part of the PEAR2\Console\CommandLine package.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE: This source file is subject to the MIT license that is available
|
||||
* through the world-wide-web at the following URI:
|
||||
* http://opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @version 0.2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since File available since release 0.1.0
|
||||
* @filesource
|
||||
*/
|
||||
namespace PEAR2\Console\CommandLine;
|
||||
|
||||
/**
|
||||
* Class that represent an option action.
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since Class available since release 0.1.0
|
||||
*/
|
||||
abstract class Action
|
||||
{
|
||||
// Properties {{{
|
||||
|
||||
/**
|
||||
* A reference to the result instance.
|
||||
*
|
||||
* @var PEAR2\Console\CommandLine_Result $result The result instance
|
||||
*/
|
||||
protected $result;
|
||||
|
||||
/**
|
||||
* A reference to the option instance.
|
||||
*
|
||||
* @var PEAR2\Console\CommandLine_Option $option The action option
|
||||
*/
|
||||
protected $option;
|
||||
|
||||
/**
|
||||
* A reference to the parser instance.
|
||||
*
|
||||
* @var PEAR2\Console\CommandLine $parser The parser
|
||||
*/
|
||||
protected $parser;
|
||||
|
||||
// }}}
|
||||
// __construct() {{{
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param PEAR2\Console\CommandLine_Result $result The result instance
|
||||
* @param PEAR2\Console\CommandLine_Option $option The action option
|
||||
* @param PEAR2\Console\CommandLine $parser The current parser
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($result, $option, $parser)
|
||||
{
|
||||
$this->result = $result;
|
||||
$this->option = $option;
|
||||
$this->parser = $parser;
|
||||
}
|
||||
|
||||
// }}}
|
||||
// getResult() {{{
|
||||
|
||||
/**
|
||||
* Convenience method to retrieve the value of result->options[name].
|
||||
*
|
||||
* @return mixed The result value or null
|
||||
*/
|
||||
public function getResult()
|
||||
{
|
||||
if (isset($this->result->options[$this->option->name])) {
|
||||
return $this->result->options[$this->option->name];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// }}}
|
||||
// format() {{{
|
||||
|
||||
/**
|
||||
* Allow a value to be pre-formatted prior to being used in a choices test.
|
||||
* Setting $value to the new format will keep the formatting.
|
||||
*
|
||||
* @param mixed &$value The value to format
|
||||
*
|
||||
* @return mixed The formatted value
|
||||
*/
|
||||
public function format(&$value)
|
||||
{
|
||||
return $value;
|
||||
}
|
||||
|
||||
// }}}
|
||||
// setResult() {{{
|
||||
|
||||
/**
|
||||
* Convenience method to assign the result->options[name] value.
|
||||
*
|
||||
* @param mixed $result The result value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setResult($result)
|
||||
{
|
||||
$this->result->options[$this->option->name] = $result;
|
||||
}
|
||||
|
||||
// }}}
|
||||
// execute() {{{
|
||||
|
||||
/**
|
||||
* Executes the action with the value entered by the user.
|
||||
* All children actions must implement this method.
|
||||
*
|
||||
* @param mixed $value The option value
|
||||
* @param array $params An optional array of parameters
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function execute($value = false, $params = array());
|
||||
// }}}
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* This file is part of the PEAR2\Console\CommandLine package.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE: This source file is subject to the MIT license that is available
|
||||
* through the world-wide-web at the following URI:
|
||||
* http://opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @version 0.2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since File available since release 0.1.0
|
||||
* @filesource
|
||||
*/
|
||||
namespace PEAR2\Console\CommandLine\Action;
|
||||
|
||||
use PEAR2\Console\CommandLine;
|
||||
|
||||
|
||||
/**
|
||||
* Class that represent the Callback action.
|
||||
*
|
||||
* The result option array entry value is set to the return value of the
|
||||
* callback defined in the option.
|
||||
*
|
||||
* There are two steps to defining a callback option:
|
||||
* - define the option itself using the callback action
|
||||
* - write the callback; this is a function (or method) that takes five
|
||||
* arguments, as described below.
|
||||
*
|
||||
* All callbacks are called as follows:
|
||||
* <code>
|
||||
* callable_func(
|
||||
* $value, // the value of the option
|
||||
* $option_instance, // the option instance
|
||||
* $result_instance, // the result instance
|
||||
* $parser_instance, // the parser instance
|
||||
* $params // an array of params as specified in the option
|
||||
* );
|
||||
* </code>
|
||||
* and *must* return the option value.
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since Class available since release 0.1.0
|
||||
*/
|
||||
class Callback extends CommandLine\Action
|
||||
{
|
||||
// execute() {{{
|
||||
|
||||
/**
|
||||
* Executes the action with the value entered by the user.
|
||||
*
|
||||
* @param mixed $value The value of the option
|
||||
* @param array $params An optional array of parameters
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function execute($value = false, $params = array())
|
||||
{
|
||||
$this->setResult(
|
||||
call_user_func(
|
||||
$this->option->callback,
|
||||
$value,
|
||||
$this->option,
|
||||
$this->result,
|
||||
$this->parser,
|
||||
$params
|
||||
)
|
||||
);
|
||||
}
|
||||
// }}}
|
||||
}
|
84
system/autoload/PEAR2/Console/CommandLine/Action/Counter.php
Normal file
84
system/autoload/PEAR2/Console/CommandLine/Action/Counter.php
Normal file
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* This file is part of the PEAR2\Console\CommandLine package.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE: This source file is subject to the MIT license that is available
|
||||
* through the world-wide-web at the following URI:
|
||||
* http://opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @version 0.2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since File available since release 0.1.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace PEAR2\Console\CommandLine\Action;
|
||||
|
||||
use PEAR2\Console\CommandLine;
|
||||
|
||||
/**
|
||||
* Class that represent the Version action.
|
||||
*
|
||||
* The execute methode add 1 to the value of the result option array entry.
|
||||
* The value is incremented each time the option is found, for example
|
||||
* with an option defined like that:
|
||||
*
|
||||
* <code>
|
||||
* $parser->addOption(
|
||||
* 'verbose',
|
||||
* array(
|
||||
* 'short_name' => '-v',
|
||||
* 'action' => 'Counter'
|
||||
* )
|
||||
* );
|
||||
* </code>
|
||||
* If the user type:
|
||||
* <code>
|
||||
* $ script.php -v -v -v
|
||||
* </code>
|
||||
* or:
|
||||
* <code>
|
||||
* $ script.php -vvv
|
||||
* </code>
|
||||
* the verbose variable will be set to to 3.
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since Class available since release 0.1.0
|
||||
*/
|
||||
class Counter extends CommandLine\Action
|
||||
{
|
||||
// execute() {{{
|
||||
|
||||
/**
|
||||
* Executes the action with the value entered by the user.
|
||||
*
|
||||
* @param mixed $value The option value
|
||||
* @param array $params An optional array of parameters
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function execute($value = false, $params = array())
|
||||
{
|
||||
$result = $this->getResult();
|
||||
if ($result === null) {
|
||||
$result = 0;
|
||||
}
|
||||
$this->setResult(++$result);
|
||||
}
|
||||
// }}}
|
||||
}
|
58
system/autoload/PEAR2/Console/CommandLine/Action/Help.php
Normal file
58
system/autoload/PEAR2/Console/CommandLine/Action/Help.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* This file is part of the PEAR2\Console\CommandLine package.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE: This source file is subject to the MIT license that is available
|
||||
* through the world-wide-web at the following URI:
|
||||
* http://opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @version 0.2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since File available since release 0.1.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace PEAR2\Console\CommandLine\Action;
|
||||
|
||||
use PEAR2\Console\CommandLine;
|
||||
|
||||
/**
|
||||
* Class that represent the Help action, a special action that displays the
|
||||
* help message, telling the user how to use the program.
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since Class available since release 0.1.0
|
||||
*/
|
||||
class Help extends CommandLine\Action
|
||||
{
|
||||
// execute() {{{
|
||||
|
||||
/**
|
||||
* Executes the action with the value entered by the user.
|
||||
*
|
||||
* @param mixed $value The option value
|
||||
* @param array $params An optional array of parameters
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function execute($value = false, $params = array())
|
||||
{
|
||||
return $this->parser->displayUsage();
|
||||
}
|
||||
// }}}
|
||||
}
|
69
system/autoload/PEAR2/Console/CommandLine/Action/List.php
Normal file
69
system/autoload/PEAR2/Console/CommandLine/Action/List.php
Normal file
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* This file is part of the PEAR2\Console\CommandLine package.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE: This source file is subject to the MIT license that is available
|
||||
* through the world-wide-web at the following URI:
|
||||
* http://opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @version CVS: $Id: List.php,v 1.2 2009/02/27 08:03:17 izi Exp $
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since File available since release 0.1.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace PEAR2\Console\CommandLine;
|
||||
|
||||
/**
|
||||
* Class that represent the List action, a special action that simply output an
|
||||
* array as a list.
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since Class available since release 0.1.0
|
||||
*/
|
||||
class Action_List extends Action
|
||||
{
|
||||
// execute() {{{
|
||||
|
||||
/**
|
||||
* Executes the action with the value entered by the user.
|
||||
* Possible parameters are:
|
||||
* - message: an alternative message to display instead of the default
|
||||
* message,
|
||||
* - delimiter: an alternative delimiter instead of the comma,
|
||||
* - post: a string to append after the message (default is the new line
|
||||
* char).
|
||||
*
|
||||
* @param mixed $value The option value
|
||||
* @param array $params An optional array of parameters
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function execute($value = false, $params = array())
|
||||
{
|
||||
$list = isset($params['list']) ? $params['list'] : array();
|
||||
$msg = isset($params['message'])
|
||||
? $params['message']
|
||||
: $this->parser->message_provider->get('LIST_DISPLAYED_MESSAGE');
|
||||
$del = isset($params['delimiter']) ? $params['delimiter'] : ', ';
|
||||
$post = isset($params['post']) ? $params['post'] : "\n";
|
||||
$this->parser->outputter->stdout($msg . implode($del, $list) . $post);
|
||||
exit(0);
|
||||
}
|
||||
// }}}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* This file is part of the PEAR2\Console\CommandLine package.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE: This source file is subject to the MIT license that is available
|
||||
* through the world-wide-web at the following URI:
|
||||
* http://opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @version 0.2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since File available since release 0.1.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace PEAR2\Console\CommandLine\Action;
|
||||
|
||||
use PEAR2\Console\CommandLine;
|
||||
|
||||
/**
|
||||
* Class that represent the Password action, a special action that allow the
|
||||
* user to specify the password on the commandline or to be prompted for
|
||||
* entering it.
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since Class available since release 0.1.0
|
||||
*/
|
||||
class Password extends CommandLine\Action
|
||||
{
|
||||
// execute() {{{
|
||||
|
||||
/**
|
||||
* Executes the action with the value entered by the user.
|
||||
*
|
||||
* @param mixed $value The option value
|
||||
* @param array $params An array of optional parameters
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function execute($value = false, $params = array())
|
||||
{
|
||||
$this->setResult(empty($value) ? $this->_promptPassword() : $value);
|
||||
}
|
||||
// }}}
|
||||
// _promptPassword() {{{
|
||||
|
||||
/**
|
||||
* Prompts the password to the user without echoing it.
|
||||
*
|
||||
* @return string
|
||||
* @todo not echo-ing the password does not work on windows is there a way
|
||||
* to make this work ?
|
||||
*/
|
||||
private function _promptPassword()
|
||||
{
|
||||
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
|
||||
fwrite(
|
||||
STDOUT,
|
||||
$this->parser->message_provider->get('PASSWORD_PROMPT_ECHO')
|
||||
);
|
||||
@flock(STDIN, LOCK_EX);
|
||||
$passwd = fgets(STDIN);
|
||||
@flock(STDIN, LOCK_UN);
|
||||
} else {
|
||||
fwrite(STDOUT, $this->parser->message_provider->get('PASSWORD_PROMPT'));
|
||||
// disable echoing
|
||||
system('stty -echo');
|
||||
@flock(STDIN, LOCK_EX);
|
||||
$passwd = fgets(STDIN);
|
||||
@flock(STDIN, LOCK_UN);
|
||||
system('stty echo');
|
||||
}
|
||||
return trim($passwd);
|
||||
}
|
||||
// }}}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* This file is part of the PEAR2\Console\CommandLine package.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE: This source file is subject to the MIT license that is available
|
||||
* through the world-wide-web at the following URI:
|
||||
* http://opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @version 0.2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since File available since release 0.1.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace PEAR2\Console\CommandLine\Action;
|
||||
|
||||
use PEAR2\Console\CommandLine;
|
||||
|
||||
/**
|
||||
* Class that represent the StoreArray action.
|
||||
*
|
||||
* The execute method appends the value of the option entered by the user to
|
||||
* the result option array entry.
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since Class available since release 0.1.0
|
||||
*/
|
||||
class StoreArray extends CommandLine\Action
|
||||
{
|
||||
// Protected properties {{{
|
||||
|
||||
/**
|
||||
* Force a clean result when first called, overriding any defaults assigned.
|
||||
*
|
||||
* @var object $firstPass First time this action has been called.
|
||||
*/
|
||||
protected $firstPass = true;
|
||||
|
||||
// }}}
|
||||
// execute() {{{
|
||||
|
||||
/**
|
||||
* Executes the action with the value entered by the user.
|
||||
*
|
||||
* @param mixed $value The option value
|
||||
* @param array $params An optional array of parameters
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function execute($value = false, $params = array())
|
||||
{
|
||||
$result = $this->getResult();
|
||||
if (null === $result || $this->firstPass) {
|
||||
$result = array();
|
||||
$this->firstPass = false;
|
||||
}
|
||||
$result[] = $value;
|
||||
$this->setResult($result);
|
||||
}
|
||||
// }}}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* This file is part of the PEAR2\Console\CommandLine package.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE: This source file is subject to the MIT license that is available
|
||||
* through the world-wide-web at the following URI:
|
||||
* http://opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @version 0.2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since File available since release 0.1.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace PEAR2\Console\CommandLine\Action;
|
||||
|
||||
use PEAR2\Console\CommandLine;
|
||||
|
||||
/**
|
||||
* Class that represent the StoreFalse action.
|
||||
*
|
||||
* The execute method store the boolean 'false' in the corrsponding result
|
||||
* option array entry (the value is true if the option is not present in the
|
||||
* command line entered by the user).
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since Class available since release 0.1.0
|
||||
*/
|
||||
class StoreFalse extends CommandLine\Action
|
||||
{
|
||||
// execute() {{{
|
||||
|
||||
/**
|
||||
* Executes the action with the value entered by the user.
|
||||
*
|
||||
* @param mixed $value The option value
|
||||
* @param array $params An array of optional parameters
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function execute($value = false, $params = array())
|
||||
{
|
||||
$this->setResult(false);
|
||||
}
|
||||
|
||||
// }}}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* This file is part of the PEAR2\Console\CommandLine package.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE: This source file is subject to the MIT license that is available
|
||||
* through the world-wide-web at the following URI:
|
||||
* http://opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @version 0.2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since File available since release 0.1.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace PEAR2\Console\CommandLine\Action;
|
||||
|
||||
use PEAR2\Console\CommandLine;
|
||||
|
||||
/**
|
||||
* Class that represent the StoreFloat action.
|
||||
*
|
||||
* The execute method store the value of the option entered by the user as a
|
||||
* float in the result option array entry, if the value passed is not a float
|
||||
* an Exception is raised.
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since Class available since release 0.1.0
|
||||
*/
|
||||
class StoreFloat extends CommandLine\Action
|
||||
{
|
||||
// execute() {{{
|
||||
|
||||
/**
|
||||
* Executes the action with the value entered by the user.
|
||||
*
|
||||
* @param mixed $value The option value
|
||||
* @param array $params An array of optional parameters
|
||||
*
|
||||
* @return string
|
||||
* @throws PEAR2\Console\CommandLine\Exception
|
||||
*/
|
||||
public function execute($value = false, $params = array())
|
||||
{
|
||||
if (!is_numeric($value)) {
|
||||
throw CommandLine\Exception::factory(
|
||||
'OPTION_VALUE_TYPE_ERROR',
|
||||
array(
|
||||
'name' => $this->option->name,
|
||||
'type' => 'float',
|
||||
'value' => $value
|
||||
),
|
||||
$this->parser
|
||||
);
|
||||
}
|
||||
$this->setResult((float)$value);
|
||||
}
|
||||
// }}}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* This file is part of the PEAR2\Console\CommandLine package.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE: This source file is subject to the MIT license that is available
|
||||
* through the world-wide-web at the following URI:
|
||||
* http://opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @version 0.2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since File available since release 0.1.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace PEAR2\Console\CommandLine\Action;
|
||||
|
||||
use PEAR2\Console\CommandLine;
|
||||
|
||||
/**
|
||||
* Class that represent the StoreInt action.
|
||||
*
|
||||
* The execute method store the value of the option entered by the user as an
|
||||
* integer in the result option array entry, if the value passed is not an
|
||||
* integer an Exception is raised.
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since Class available since release 0.1.0
|
||||
*/
|
||||
class StoreInt extends CommandLine\Action
|
||||
{
|
||||
// execute() {{{
|
||||
|
||||
/**
|
||||
* Executes the action with the value entered by the user.
|
||||
*
|
||||
* @param mixed $value The option value
|
||||
* @param array $params An array of optional parameters
|
||||
*
|
||||
* @return string
|
||||
* @throws PEAR2\Console\CommandLine\Exception
|
||||
*/
|
||||
public function execute($value = false, $params = array())
|
||||
{
|
||||
if (!is_numeric($value)) {
|
||||
throw CommandLine\Exception::factory(
|
||||
'OPTION_VALUE_TYPE_ERROR',
|
||||
array(
|
||||
'name' => $this->option->name,
|
||||
'type' => 'int',
|
||||
'value' => $value
|
||||
),
|
||||
$this->parser
|
||||
);
|
||||
}
|
||||
$this->setResult((int)$value);
|
||||
}
|
||||
// }}}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* This file is part of the PEAR2\Console\CommandLine package.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE: This source file is subject to the MIT license that is available
|
||||
* through the world-wide-web at the following URI:
|
||||
* http://opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @version 0.2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since File available since release 0.1.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace PEAR2\Console\CommandLine\Action;
|
||||
|
||||
use PEAR2\Console\CommandLine;
|
||||
|
||||
/**
|
||||
* Class that represent the StoreString action.
|
||||
*
|
||||
* The execute method store the value of the option entered by the user as a
|
||||
* string in the result option array entry.
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since Class available since release 0.1.0
|
||||
*/
|
||||
class StoreString extends CommandLine\Action
|
||||
{
|
||||
// execute() {{{
|
||||
|
||||
/**
|
||||
* Executes the action with the value entered by the user.
|
||||
*
|
||||
* @param mixed $value The option value
|
||||
* @param array $params An array of optional parameters
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function execute($value = false, $params = array())
|
||||
{
|
||||
$this->setResult((string)$value);
|
||||
}
|
||||
// }}}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* This file is part of the PEAR2\Console\CommandLine package.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE: This source file is subject to the MIT license that is available
|
||||
* through the world-wide-web at the following URI:
|
||||
* http://opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @version 0.2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since File available since release 0.1.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace PEAR2\Console\CommandLine\Action;
|
||||
|
||||
use PEAR2\Console\CommandLine;
|
||||
|
||||
/**
|
||||
* Class that represent the StoreTrue action.
|
||||
*
|
||||
* The execute method store the boolean 'true' in the corrsponding result
|
||||
* option array entry (the value is false if the option is not present in the
|
||||
* command line entered by the user).
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since Class available since release 0.1.0
|
||||
*/
|
||||
class StoreTrue extends CommandLine\Action
|
||||
{
|
||||
// execute() {{{
|
||||
|
||||
/**
|
||||
* Executes the action with the value entered by the user.
|
||||
*
|
||||
* @param mixed $value The option value
|
||||
* @param array $params An array of optional parameters
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function execute($value = false, $params = array())
|
||||
{
|
||||
$this->setResult(true);
|
||||
}
|
||||
// }}}
|
||||
}
|
58
system/autoload/PEAR2/Console/CommandLine/Action/Version.php
Normal file
58
system/autoload/PEAR2/Console/CommandLine/Action/Version.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* This file is part of the PEAR2\Console\CommandLine package.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE: This source file is subject to the MIT license that is available
|
||||
* through the world-wide-web at the following URI:
|
||||
* http://opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @version 0.2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since File available since release 0.1.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace PEAR2\Console\CommandLine\Action;
|
||||
|
||||
use PEAR2\Console\CommandLine;
|
||||
|
||||
/**
|
||||
* Class that represent the Version action, a special action that displays the
|
||||
* version string of the program.
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since Class available since release 0.1.0
|
||||
*/
|
||||
class Version extends CommandLine\Action
|
||||
{
|
||||
// execute() {{{
|
||||
|
||||
/**
|
||||
* Executes the action with the value entered by the user.
|
||||
*
|
||||
* @param mixed $value The option value
|
||||
* @param array $params An array of optional parameters
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function execute($value = false, $params = array())
|
||||
{
|
||||
return $this->parser->displayVersion();
|
||||
}
|
||||
// }}}
|
||||
}
|
94
system/autoload/PEAR2/Console/CommandLine/Argument.php
Normal file
94
system/autoload/PEAR2/Console/CommandLine/Argument.php
Normal file
@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* This file is part of the PEAR2\Console\CommandLine package.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE: This source file is subject to the MIT license that is available
|
||||
* through the world-wide-web at the following URI:
|
||||
* http://opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @version 0.2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since File available since release 0.1.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace PEAR2\Console\CommandLine;
|
||||
|
||||
/**
|
||||
* Class that represent a command line argument.
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since Class available since release 0.1.0
|
||||
*/
|
||||
class Argument extends Element
|
||||
{
|
||||
// Public properties {{{
|
||||
|
||||
/**
|
||||
* Setting this to true will tell the parser that the argument expects more
|
||||
* than one argument and that argument values should be stored in an array.
|
||||
*
|
||||
* @var boolean $multiple Whether the argument expects multiple values
|
||||
*/
|
||||
public $multiple = false;
|
||||
|
||||
/**
|
||||
* Setting this to true will tell the parser that the argument is optional
|
||||
* and can be ommited.
|
||||
* Note that it is not a good practice to make arguments optional, it is
|
||||
* the role of the options to be optional, by essence.
|
||||
*
|
||||
* @var boolean $optional Whether the argument is optional or not.
|
||||
*/
|
||||
public $optional = false;
|
||||
|
||||
// }}}
|
||||
// validate() {{{
|
||||
|
||||
/**
|
||||
* Validates the argument instance.
|
||||
*
|
||||
* @return void
|
||||
* @throws PEAR2\Console\CommandLine\Exception
|
||||
* @todo use exceptions
|
||||
*/
|
||||
public function validate()
|
||||
{
|
||||
// check if the argument name is valid
|
||||
if (!preg_match(
|
||||
'/^[a-zA-Z_\x7f-\xff]+[a-zA-Z0-9_\x7f-\xff]*$/',
|
||||
$this->name
|
||||
)
|
||||
) {
|
||||
\PEAR2\Console\CommandLine::triggerError(
|
||||
'argument_bad_name',
|
||||
E_USER_ERROR,
|
||||
array('{$name}' => $this->name)
|
||||
);
|
||||
}
|
||||
if (!$this->optional && $this->default !== null) {
|
||||
\PEAR2\Console\CommandLine::triggerError(
|
||||
'argument_no_default',
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
parent::validate();
|
||||
}
|
||||
|
||||
// }}}
|
||||
}
|
72
system/autoload/PEAR2/Console/CommandLine/Command.php
Normal file
72
system/autoload/PEAR2/Console/CommandLine/Command.php
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* This file is part of the PEAR2\Console\CommandLine package.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE: This source file is subject to the MIT license that is available
|
||||
* through the world-wide-web at the following URI:
|
||||
* http://opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @version 0.2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since File available since release 0.1.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace PEAR2\Console\CommandLine;
|
||||
|
||||
/**
|
||||
* Class that represent a command with option and arguments.
|
||||
*
|
||||
* This class exist just to clarify the interface but at the moment it is
|
||||
* strictly identical to PEAR2\Console\CommandLine class, it could change in the
|
||||
* future though.
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since Class available since release 0.1.0
|
||||
*/
|
||||
class Command extends \PEAR2\Console\CommandLine
|
||||
{
|
||||
// Public properties {{{
|
||||
|
||||
/**
|
||||
* An array of aliases for the subcommand.
|
||||
*
|
||||
* @var array $aliases Aliases for the subcommand.
|
||||
*/
|
||||
public $aliases = array();
|
||||
|
||||
// }}}
|
||||
// __construct() {{{
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $params An optional array of parameters
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($params = array())
|
||||
{
|
||||
if (isset($params['aliases'])) {
|
||||
$this->aliases = $params['aliases'];
|
||||
}
|
||||
parent::__construct($params);
|
||||
}
|
||||
|
||||
// }}}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* This file is part of the PEAR2\Console\CommandLine package.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE: This source file is subject to the MIT license that is available
|
||||
* through the world-wide-web at the following URI:
|
||||
* http://opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @author Michael Gauthier <mike@silverorange.com>
|
||||
* @copyright 2007 David JEAN LOUIS, 2009 silverorange
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @version CVS: $Id: CustomMessageProvider.php 282427 2009-06-19 10:22:48Z izi $
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since File available since release 1.1.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace PEAR2\Console\CommandLine;
|
||||
|
||||
/**
|
||||
* Common interfacefor message providers that allow overriding with custom
|
||||
* messages
|
||||
*
|
||||
* Message providers may optionally implement this interface.
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @author Michael Gauthier <mike@silverorange.com>
|
||||
* @copyright 2007 David JEAN LOUIS, 2009 silverorange
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since Interface available since release 1.1.0
|
||||
*/
|
||||
interface CustomMessageProvider
|
||||
{
|
||||
// getWithCustomMesssages() {{{
|
||||
|
||||
/**
|
||||
* Retrieves the given string identifier corresponding message.
|
||||
*
|
||||
* For a list of identifiers please see the provided default message
|
||||
* provider.
|
||||
*
|
||||
* @param string $code The string identifier of the message
|
||||
* @param array $vars An array of template variables
|
||||
* @param array $messages An optional array of messages to use. Array
|
||||
* indexes are message codes.
|
||||
*
|
||||
* @return string
|
||||
* @see PEAR2\Console\CommandLine_MessageProvider
|
||||
* @see PEAR2\Console\CommandLine_MessageProvider_Default
|
||||
*/
|
||||
public function getWithCustomMessages(
|
||||
$code, $vars = array(), $messages = array()
|
||||
);
|
||||
|
||||
// }}}
|
||||
}
|
151
system/autoload/PEAR2/Console/CommandLine/Element.php
Normal file
151
system/autoload/PEAR2/Console/CommandLine/Element.php
Normal file
@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* This file is part of the PEAR2\Console\CommandLine package.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE: This source file is subject to the MIT license that is available
|
||||
* through the world-wide-web at the following URI:
|
||||
* http://opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @version 0.2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since File available since release 0.1.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace PEAR2\Console\CommandLine;
|
||||
|
||||
/**
|
||||
* Class that represent a command line element (an option, or an argument).
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since Class available since release 0.1.0
|
||||
*/
|
||||
abstract class Element
|
||||
{
|
||||
// Public properties {{{
|
||||
|
||||
/**
|
||||
* The element name.
|
||||
*
|
||||
* @var string $name Element name
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* The name of variable displayed in the usage message, if no set it
|
||||
* defaults to the "name" property.
|
||||
*
|
||||
* @var string $help_name Element "help" variable name
|
||||
*/
|
||||
public $help_name;
|
||||
|
||||
/**
|
||||
* The element description.
|
||||
*
|
||||
* @var string $description Element description
|
||||
*/
|
||||
public $description;
|
||||
/**
|
||||
* The default value of the element if not provided on the command line.
|
||||
*
|
||||
* @var mixed $default Default value of the option.
|
||||
*/
|
||||
public $default;
|
||||
|
||||
/**
|
||||
* Custom errors messages for this element
|
||||
*
|
||||
* This array is of the form:
|
||||
* <code>
|
||||
* <?php
|
||||
* array(
|
||||
* $messageName => $messageText,
|
||||
* $messageName => $messageText,
|
||||
* ...
|
||||
* );
|
||||
* ?>
|
||||
* </code>
|
||||
*
|
||||
* If specified, these messages override the messages provided by the
|
||||
* default message provider. For example:
|
||||
* <code>
|
||||
* <?php
|
||||
* $messages = array(
|
||||
* 'ARGUMENT_REQUIRED' => 'The argument foo is required.',
|
||||
* );
|
||||
* ?>
|
||||
* </code>
|
||||
*
|
||||
* @var array
|
||||
* @see PEAR2\Console\CommandLine_MessageProvider_Default
|
||||
*/
|
||||
public $messages = array();
|
||||
|
||||
// }}}
|
||||
// __construct() {{{
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $name The name of the element
|
||||
* @param array $params An optional array of parameters
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($name = null, $params = array())
|
||||
{
|
||||
$this->name = $name;
|
||||
foreach ($params as $attr => $value) {
|
||||
if (property_exists($this, $attr)) {
|
||||
$this->$attr = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// }}}
|
||||
// toString() {{{
|
||||
|
||||
/**
|
||||
* Returns the string representation of the element.
|
||||
*
|
||||
* @return string The string representation of the element
|
||||
* @todo use __toString() instead
|
||||
*/
|
||||
public function toString()
|
||||
{
|
||||
return $this->help_name;
|
||||
}
|
||||
// }}}
|
||||
// validate() {{{
|
||||
|
||||
/**
|
||||
* Validates the element instance and set it's default values.
|
||||
*
|
||||
* @return void
|
||||
* @throws PEAR2\Console\CommandLine\Exception
|
||||
*/
|
||||
public function validate()
|
||||
{
|
||||
// if no help_name passed, default to name
|
||||
if ($this->help_name == null) {
|
||||
$this->help_name = $this->name;
|
||||
}
|
||||
}
|
||||
|
||||
// }}}
|
||||
}
|
90
system/autoload/PEAR2/Console/CommandLine/Exception.php
Normal file
90
system/autoload/PEAR2/Console/CommandLine/Exception.php
Normal file
@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* This file is part of the PEAR2\Console\CommandLine package.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE: This source file is subject to the MIT license that is available
|
||||
* through the world-wide-web at the following URI:
|
||||
* http://opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @version 0.2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since File available since release 0.1.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace PEAR2\Console\CommandLine;
|
||||
|
||||
use Exception as E;
|
||||
|
||||
/**
|
||||
* Class for exceptions raised by the PEAR2\Console\CommandLine package.
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since Class available since release 0.1.0
|
||||
*/
|
||||
class Exception extends E
|
||||
{
|
||||
// Codes constants {{{
|
||||
|
||||
/**#@+
|
||||
* Exception code constants.
|
||||
*/
|
||||
const OPTION_VALUE_REQUIRED = 1;
|
||||
const OPTION_VALUE_UNEXPECTED = 2;
|
||||
const OPTION_VALUE_TYPE_ERROR = 3;
|
||||
const OPTION_UNKNOWN = 4;
|
||||
const ARGUMENT_REQUIRED = 5;
|
||||
const INVALID_SUBCOMMAND = 6;
|
||||
/**#@-*/
|
||||
|
||||
// }}}
|
||||
// factory() {{{
|
||||
|
||||
/**
|
||||
* Convenience method that builds the exception with the array of params by
|
||||
* calling the message provider class.
|
||||
*
|
||||
* @param string $code The string identifier of the
|
||||
* exception.
|
||||
* @param array $params Array of template vars/values
|
||||
* @param PEAR2\Console\CommandLine $parser An instance of the parser
|
||||
* @param array $messages An optional array of messages
|
||||
* passed to the message provider.
|
||||
*
|
||||
* @return PEAR2\Console\CommandLine\Exception The exception instance
|
||||
*/
|
||||
public static function factory(
|
||||
$code, $params, $parser, array $messages = array()
|
||||
) {
|
||||
$provider = $parser->message_provider;
|
||||
if ($provider instanceof CommandLine\CustomMessageProvider) {
|
||||
$msg = $provider->getWithCustomMessages(
|
||||
$code,
|
||||
$params,
|
||||
$messages
|
||||
);
|
||||
} else {
|
||||
$msg = $provider->get($code, $params);
|
||||
}
|
||||
$const = '\PEAR2\Console\CommandLine\Exception::' . $code;
|
||||
$code = defined($const) ? constant($const) : 0;
|
||||
return new static($msg, $code);
|
||||
}
|
||||
|
||||
// }}}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* This file is part of the PEAR2\Console\CommandLine package.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE: This source file is subject to the MIT license that is available
|
||||
* through the world-wide-web at the following URI:
|
||||
* http://opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @version 0.2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since File available since release 0.1.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace PEAR2\Console\CommandLine;
|
||||
|
||||
/**
|
||||
* Message providers common interface, all message providers must implement
|
||||
* this interface.
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since Class available since release 0.1.0
|
||||
*/
|
||||
interface MessageProvider
|
||||
{
|
||||
// get() {{{
|
||||
|
||||
/**
|
||||
* Retrieves the given string identifier corresponding message.
|
||||
* For a list of identifiers please see the provided default message
|
||||
* provider.
|
||||
*
|
||||
* @param string $code The string identifier of the message
|
||||
* @param array $vars An array of template variables
|
||||
*
|
||||
* @return string
|
||||
* @see PEAR2\Console\CommandLine_MessageProvider_Default
|
||||
*/
|
||||
public function get($code, $vars=array());
|
||||
|
||||
// }}}
|
||||
}
|
@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* This file is part of the PEAR2\Console\CommandLine package.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE: This source file is subject to the MIT license that is available
|
||||
* through the world-wide-web at the following URI:
|
||||
* http://opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @version 0.2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since File available since release 0.1.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace PEAR2\Console\CommandLine;
|
||||
|
||||
/**
|
||||
* Lightweight class that manages messages used by PEAR2\Console\CommandLine package,
|
||||
* allowing the developper to customize these messages, for example to
|
||||
* internationalize a command line frontend.
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since Class available since release 0.1.0
|
||||
*/
|
||||
class MessageProvider_Default
|
||||
implements MessageProvider,
|
||||
CustomMessageProvider
|
||||
{
|
||||
// Properties {{{
|
||||
|
||||
/**
|
||||
* Associative array of messages
|
||||
*
|
||||
* @var array $messages
|
||||
*/
|
||||
protected $messages = array(
|
||||
'OPTION_VALUE_REQUIRED' => 'Option "{$name}" requires a value.',
|
||||
'OPTION_VALUE_UNEXPECTED' => 'Option "{$name}" does not expect a value (got "{$value}").',
|
||||
'OPTION_VALUE_NOT_VALID' => 'Option "{$name}" must be one of the following: "{$choices}" (got "{$value}").',
|
||||
'OPTION_VALUE_TYPE_ERROR' => 'Option "{$name}" requires a value of type {$type} (got "{$value}").',
|
||||
'OPTION_AMBIGUOUS' => 'Ambiguous option "{$name}", can be one of the following: {$matches}.',
|
||||
'OPTION_UNKNOWN' => 'Unknown option "{$name}".',
|
||||
'ARGUMENT_REQUIRED' => 'You must provide at least {$argnum} argument{$plural}.',
|
||||
'PROG_HELP_LINE' => 'Type "{$progname} --help" to get help.',
|
||||
'PROG_VERSION_LINE' => '{$progname} version {$version}.',
|
||||
'COMMAND_HELP_LINE' => 'Type "{$progname} <command> --help" to get help on specific command.',
|
||||
'USAGE_WORD' => 'Usage',
|
||||
'OPTION_WORD' => 'Options',
|
||||
'ARGUMENT_WORD' => 'Arguments',
|
||||
'COMMAND_WORD' => 'Commands',
|
||||
'PASSWORD_PROMPT' => 'Password: ',
|
||||
'PASSWORD_PROMPT_ECHO' => 'Password (warning: will echo): ',
|
||||
'INVALID_CUSTOM_INSTANCE' => 'Instance does not implement the required interface',
|
||||
'LIST_OPTION_MESSAGE' => 'lists valid choices for option {$name}',
|
||||
'LIST_DISPLAYED_MESSAGE' => 'Valid choices are: ',
|
||||
'INVALID_SUBCOMMAND' => 'Command "{$command}" is not valid.',
|
||||
'SUBCOMMAND_REQUIRED' => 'Please enter one of the following command: {$commands}.',
|
||||
);
|
||||
|
||||
// }}}
|
||||
// get() {{{
|
||||
|
||||
/**
|
||||
* Retrieve the given string identifier corresponding message.
|
||||
*
|
||||
* @param string $code The string identifier of the message
|
||||
* @param array $vars An array of template variables
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get($code, $vars = array())
|
||||
{
|
||||
if (!isset($this->messages[$code])) {
|
||||
return 'UNKNOWN';
|
||||
}
|
||||
return $this->replaceTemplateVars($this->messages[$code], $vars);
|
||||
}
|
||||
|
||||
// }}}
|
||||
// getWithCustomMessages() {{{
|
||||
|
||||
/**
|
||||
* Retrieve the given string identifier corresponding message.
|
||||
*
|
||||
* @param string $code The string identifier of the message
|
||||
* @param array $vars An array of template variables
|
||||
* @param array $messages An optional array of messages to use. Array
|
||||
* indexes are message codes.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getWithCustomMessages(
|
||||
$code, $vars = array(), $messages = array()
|
||||
) {
|
||||
// get message
|
||||
if (isset($messages[$code])) {
|
||||
$message = $messages[$code];
|
||||
} elseif (isset($this->messages[$code])) {
|
||||
$message = $this->messages[$code];
|
||||
} else {
|
||||
$message = 'UNKNOWN';
|
||||
}
|
||||
return $this->replaceTemplateVars($message, $vars);
|
||||
}
|
||||
|
||||
// }}}
|
||||
// replaceTemplateVars() {{{
|
||||
|
||||
/**
|
||||
* Replaces template vars in a message
|
||||
*
|
||||
* @param string $message The message
|
||||
* @param array $vars An array of template variables
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function replaceTemplateVars($message, $vars = array())
|
||||
{
|
||||
$tmpkeys = array_keys($vars);
|
||||
$keys = array();
|
||||
foreach ($tmpkeys as $key) {
|
||||
$keys[] = '{$' . $key . '}';
|
||||
}
|
||||
return str_replace($keys, array_values($vars), $message);
|
||||
}
|
||||
|
||||
// }}}
|
||||
}
|
393
system/autoload/PEAR2/Console/CommandLine/Option.php
Normal file
393
system/autoload/PEAR2/Console/CommandLine/Option.php
Normal file
@ -0,0 +1,393 @@
|
||||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* This file is part of the PEAR2\Console\CommandLine package.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE: This source file is subject to the MIT license that is available
|
||||
* through the world-wide-web at the following URI:
|
||||
* http://opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @version 0.2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since File available since release 0.1.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace PEAR2\Console\CommandLine;
|
||||
|
||||
use PEAR2\Console;
|
||||
|
||||
/**
|
||||
* Class that represent a commandline option.
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since Class available since release 0.1.0
|
||||
*/
|
||||
class Option extends Element
|
||||
{
|
||||
// Public properties {{{
|
||||
|
||||
/**
|
||||
* The option short name (ex: -v).
|
||||
*
|
||||
* @var string $short_name Short name of the option
|
||||
*/
|
||||
public $short_name;
|
||||
|
||||
/**
|
||||
* The option long name (ex: --verbose).
|
||||
*
|
||||
* @var string $long_name Long name of the option
|
||||
*/
|
||||
public $long_name;
|
||||
|
||||
/**
|
||||
* The option action, defaults to "StoreString".
|
||||
*
|
||||
* @var string $action Option action
|
||||
*/
|
||||
public $action = 'StoreString';
|
||||
|
||||
/**
|
||||
* An array of possible values for the option. If this array is not empty
|
||||
* and the value passed is not in the array an exception is raised.
|
||||
* This only make sense for actions that accept values of course.
|
||||
*
|
||||
* @var array $choices Valid choices for the option
|
||||
*/
|
||||
public $choices = array();
|
||||
|
||||
/**
|
||||
* The callback function (or method) to call for an action of type
|
||||
* Callback, this can be any callable supported by the php function
|
||||
* call_user_func.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* <code>
|
||||
* $parser->addOption('myoption', array(
|
||||
* 'short_name' => '-m',
|
||||
* 'long_name' => '--myoption',
|
||||
* 'action' => 'Callback',
|
||||
* 'callback' => 'myCallbackFunction'
|
||||
* ));
|
||||
* </code>
|
||||
*
|
||||
* @var callable $callback The option callback
|
||||
*/
|
||||
public $callback;
|
||||
|
||||
/**
|
||||
* An associative array of additional params to pass to the class
|
||||
* corresponding to the action, this array will also be passed to the
|
||||
* callback defined for an action of type Callback, Example:
|
||||
*
|
||||
* <code>
|
||||
* // for a custom action
|
||||
* $parser->addOption('myoption', array(
|
||||
* 'short_name' => '-m',
|
||||
* 'long_name' => '--myoption',
|
||||
* 'action' => 'MyCustomAction',
|
||||
* 'action_params' => array('foo'=>true, 'bar'=>false)
|
||||
* ));
|
||||
*
|
||||
* // if the user type:
|
||||
* // $ <yourprogram> -m spam
|
||||
* // in your MyCustomAction class the execute() method will be called
|
||||
* // with the value 'spam' as first parameter and
|
||||
* // array('foo'=>true, 'bar'=>false) as second parameter
|
||||
* </code>
|
||||
*
|
||||
* @var array $action_params Additional parameters to pass to the action
|
||||
*/
|
||||
public $action_params = array();
|
||||
|
||||
/**
|
||||
* For options that expect an argument, this property tells the parser if
|
||||
* the option argument is optional and can be ommited.
|
||||
*
|
||||
* @var bool $argumentOptional Whether the option arg is optional or not
|
||||
*/
|
||||
public $argument_optional = false;
|
||||
|
||||
/**
|
||||
* For options that uses the "choice" property only.
|
||||
* Adds a --list-<choice> option to the parser that displays the list of
|
||||
* choices for the option.
|
||||
*
|
||||
* @var bool $add_list_option Whether to add a list option or not
|
||||
*/
|
||||
public $add_list_option = false;
|
||||
|
||||
// }}}
|
||||
// Private properties {{{
|
||||
|
||||
/**
|
||||
* When an action is called remember it to allow for multiple calls.
|
||||
*
|
||||
* @var object $action_instance Placeholder for action
|
||||
*/
|
||||
private $_action_instance = null;
|
||||
|
||||
// }}}
|
||||
// __construct() {{{
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $name The name of the option
|
||||
* @param array $params An optional array of parameters
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($name = null, $params = array())
|
||||
{
|
||||
parent::__construct($name, $params);
|
||||
if ($this->action == 'Password') {
|
||||
// special case for Password action, password can be passed to the
|
||||
// commandline or prompted by the parser
|
||||
$this->argument_optional = true;
|
||||
}
|
||||
}
|
||||
|
||||
// }}}
|
||||
// toString() {{{
|
||||
|
||||
/**
|
||||
* Returns the string representation of the option.
|
||||
*
|
||||
* @param string $delim Delimiter to use between short and long option
|
||||
*
|
||||
* @return string The string representation of the option
|
||||
* @todo use __toString() instead
|
||||
*/
|
||||
public function toString($delim = ", ")
|
||||
{
|
||||
$ret = '';
|
||||
$padding = '';
|
||||
if ($this->short_name != null) {
|
||||
$ret .= $this->short_name;
|
||||
if ($this->expectsArgument()) {
|
||||
$ret .= ' ' . $this->help_name;
|
||||
}
|
||||
$padding = $delim;
|
||||
}
|
||||
if ($this->long_name != null) {
|
||||
$ret .= $padding . $this->long_name;
|
||||
if ($this->expectsArgument()) {
|
||||
$ret .= '=' . $this->help_name;
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
// }}}
|
||||
// expectsArgument() {{{
|
||||
|
||||
/**
|
||||
* Returns true if the option requires one or more argument and false
|
||||
* otherwise.
|
||||
*
|
||||
* @return bool Whether the option expects an argument or not
|
||||
*/
|
||||
public function expectsArgument()
|
||||
{
|
||||
if ($this->action == 'StoreTrue'
|
||||
|| $this->action == 'StoreFalse'
|
||||
|| $this->action == 'Help'
|
||||
|| $this->action == 'Version'
|
||||
|| $this->action == 'Counter'
|
||||
|| $this->action == 'List'
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// }}}
|
||||
// dispatchAction() {{{
|
||||
|
||||
/**
|
||||
* Formats the value $value according to the action of the option and
|
||||
* updates the passed PEAR2\Console\CommandLine_Result object.
|
||||
*
|
||||
* @param mixed $value The value to format
|
||||
* @param PEAR2\Console\CommandLine_Result $result The result instance
|
||||
* @param PEAR2\Console\CommandLine $parser The parser instance
|
||||
*
|
||||
* @return void
|
||||
* @throws PEAR2\Console\CommandLine\Exception
|
||||
*/
|
||||
public function dispatchAction($value, $result, $parser)
|
||||
{
|
||||
$actionInfo = Console\CommandLine::$actions[$this->action];
|
||||
$clsname = $actionInfo[0];
|
||||
if ($this->_action_instance === null) {
|
||||
$this->_action_instance = new $clsname($result, $this, $parser);
|
||||
}
|
||||
|
||||
// check value is in option choices
|
||||
if (!empty($this->choices)
|
||||
&& !in_array(
|
||||
$this->_action_instance->format($value),
|
||||
$this->choices
|
||||
)
|
||||
) {
|
||||
throw Console\CommandLine\Exception::factory(
|
||||
'OPTION_VALUE_NOT_VALID',
|
||||
array(
|
||||
'name' => $this->name,
|
||||
'choices' => implode('", "', $this->choices),
|
||||
'value' => $value,
|
||||
),
|
||||
$parser,
|
||||
$this->messages
|
||||
);
|
||||
}
|
||||
$this->_action_instance->execute($value, $this->action_params);
|
||||
}
|
||||
|
||||
// }}}
|
||||
// validate() {{{
|
||||
|
||||
/**
|
||||
* Validates the option instance.
|
||||
*
|
||||
* @return void
|
||||
* @throws PEAR2\Console\CommandLine\Exception
|
||||
* @todo use exceptions instead
|
||||
*/
|
||||
public function validate()
|
||||
{
|
||||
// check if the option name is valid
|
||||
if (!preg_match(
|
||||
'/^[a-zA-Z_\x7f-\xff]+[a-zA-Z0-9_\x7f-\xff]*$/',
|
||||
$this->name
|
||||
)
|
||||
) {
|
||||
Console\CommandLine::triggerError(
|
||||
'option_bad_name',
|
||||
E_USER_ERROR,
|
||||
array('{$name}' => $this->name)
|
||||
);
|
||||
}
|
||||
// call the parent validate method
|
||||
parent::validate();
|
||||
// a short_name or a long_name must be provided
|
||||
if ($this->short_name == null && $this->long_name == null) {
|
||||
Console\CommandLine::triggerError(
|
||||
'option_long_and_short_name_missing',
|
||||
E_USER_ERROR,
|
||||
array('{$name}' => $this->name)
|
||||
);
|
||||
}
|
||||
// check if the option short_name is valid
|
||||
if ($this->short_name != null
|
||||
&& !(preg_match('/^\-[a-zA-Z]{1}$/', $this->short_name))
|
||||
) {
|
||||
Console\CommandLine::triggerError(
|
||||
'option_bad_short_name',
|
||||
E_USER_ERROR,
|
||||
array(
|
||||
'{$name}' => $this->name,
|
||||
'{$short_name}' => $this->short_name
|
||||
)
|
||||
);
|
||||
}
|
||||
// check if the option long_name is valid
|
||||
if ($this->long_name != null
|
||||
&& !preg_match('/^\-\-[a-zA-Z]+[a-zA-Z0-9_\-]*$/', $this->long_name)
|
||||
) {
|
||||
Console\CommandLine::triggerError(
|
||||
'option_bad_long_name',
|
||||
E_USER_ERROR,
|
||||
array(
|
||||
'{$name}' => $this->name,
|
||||
'{$long_name}' => $this->long_name
|
||||
)
|
||||
);
|
||||
}
|
||||
// check if we have a valid action
|
||||
if (!is_string($this->action)) {
|
||||
Console\CommandLine::triggerError(
|
||||
'option_bad_action',
|
||||
E_USER_ERROR,
|
||||
array('{$name}' => $this->name)
|
||||
);
|
||||
}
|
||||
if (!isset(Console\CommandLine::$actions[$this->action])) {
|
||||
Console\CommandLine::triggerError(
|
||||
'option_unregistered_action',
|
||||
E_USER_ERROR,
|
||||
array(
|
||||
'{$action}' => $this->action,
|
||||
'{$name}' => $this->name
|
||||
)
|
||||
);
|
||||
}
|
||||
// if the action is a callback, check that we have a valid callback
|
||||
if ($this->action == 'Callback' && !is_callable($this->callback)) {
|
||||
Console\CommandLine::triggerError(
|
||||
'option_invalid_callback',
|
||||
E_USER_ERROR,
|
||||
array('{$name}' => $this->name)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// }}}
|
||||
// setDefaults() {{{
|
||||
|
||||
/**
|
||||
* Set the default value according to the configured action.
|
||||
*
|
||||
* Note that for backward compatibility issues this method is only called
|
||||
* when the 'force_options_defaults' is set to true, it will become the
|
||||
* default behaviour in the next major release of PEAR2\Console\CommandLine.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setDefaults()
|
||||
{
|
||||
if ($this->default !== null) {
|
||||
// already set
|
||||
return;
|
||||
}
|
||||
switch ($this->action) {
|
||||
case 'Counter':
|
||||
case 'StoreInt':
|
||||
$this->default = 0;
|
||||
break;
|
||||
case 'StoreFloat':
|
||||
$this->default = 0.0;
|
||||
break;
|
||||
case 'StoreArray':
|
||||
$this->default = array();
|
||||
break;
|
||||
case 'StoreTrue':
|
||||
$this->default = false;
|
||||
break;
|
||||
case 'StoreFalse':
|
||||
$this->default = true;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// }}}
|
||||
}
|
64
system/autoload/PEAR2/Console/CommandLine/Outputter.php
Normal file
64
system/autoload/PEAR2/Console/CommandLine/Outputter.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* This file is part of the PEAR2\Console\CommandLine package.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE: This source file is subject to the MIT license that is available
|
||||
* through the world-wide-web at the following URI:
|
||||
* http://opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @version 0.2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since File available since release 0.1.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace PEAR2\Console\CommandLine;
|
||||
|
||||
/**
|
||||
* Outputters common interface, all outputters must implement this interface.
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since Class available since release 0.1.0
|
||||
*/
|
||||
interface Outputter
|
||||
{
|
||||
// stdout() {{{
|
||||
|
||||
/**
|
||||
* Processes the output for a message that should be displayed on STDOUT.
|
||||
*
|
||||
* @param string $msg The message to output
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function stdout($msg);
|
||||
|
||||
// }}}
|
||||
// stderr() {{{
|
||||
|
||||
/**
|
||||
* Processes the output for a message that should be displayed on STDERR.
|
||||
*
|
||||
* @param string $msg The message to output
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function stderr($msg);
|
||||
|
||||
// }}}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* This file is part of the PEAR2\Console\CommandLine package.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE: This source file is subject to the MIT license that is available
|
||||
* through the world-wide-web at the following URI:
|
||||
* http://opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @version 0.2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since File available since release 0.1.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace PEAR2\Console\CommandLine;
|
||||
|
||||
/**
|
||||
* PEAR2\Console\CommandLine default Outputter.
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since Class available since release 0.1.0
|
||||
*/
|
||||
class Outputter_Default implements Outputter
|
||||
{
|
||||
// stdout() {{{
|
||||
|
||||
/**
|
||||
* Writes the message $msg to STDOUT.
|
||||
*
|
||||
* @param string $msg The message to output
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function stdout($msg)
|
||||
{
|
||||
if (defined('STDOUT')) {
|
||||
fwrite(STDOUT, $msg);
|
||||
} else {
|
||||
echo $msg;
|
||||
}
|
||||
}
|
||||
|
||||
// }}}
|
||||
// stderr() {{{
|
||||
|
||||
/**
|
||||
* Writes the message $msg to STDERR.
|
||||
*
|
||||
* @param string $msg The message to output
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function stderr($msg)
|
||||
{
|
||||
if (defined('STDERR')) {
|
||||
fwrite(STDERR, $msg);
|
||||
} else {
|
||||
echo $msg;
|
||||
}
|
||||
}
|
||||
|
||||
// }}}
|
||||
}
|
72
system/autoload/PEAR2/Console/CommandLine/Renderer.php
Normal file
72
system/autoload/PEAR2/Console/CommandLine/Renderer.php
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* This file is part of the PEAR2\Console\CommandLine package.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE: This source file is subject to the MIT license that is available
|
||||
* through the world-wide-web at the following URI:
|
||||
* http://opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @version 0.2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since File available since release 0.1.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace PEAR2\Console\CommandLine;
|
||||
|
||||
/**
|
||||
* Renderers common interface, all renderers must implement this interface.
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since Class available since release 0.1.0
|
||||
*/
|
||||
interface Renderer
|
||||
{
|
||||
// usage() {{{
|
||||
|
||||
/**
|
||||
* Returns the full usage message.
|
||||
*
|
||||
* @return string The usage message
|
||||
*/
|
||||
public function usage();
|
||||
|
||||
// }}}
|
||||
// error() {{{
|
||||
|
||||
/**
|
||||
* Returns a formatted error message.
|
||||
*
|
||||
* @param string $error The error message to format
|
||||
*
|
||||
* @return string The error string
|
||||
*/
|
||||
public function error($error);
|
||||
|
||||
// }}}
|
||||
// version() {{{
|
||||
|
||||
/**
|
||||
* Returns the program version string.
|
||||
*
|
||||
* @return string The version string
|
||||
*/
|
||||
public function version();
|
||||
|
||||
// }}}
|
||||
}
|
441
system/autoload/PEAR2/Console/CommandLine/Renderer/Default.php
Normal file
441
system/autoload/PEAR2/Console/CommandLine/Renderer/Default.php
Normal file
@ -0,0 +1,441 @@
|
||||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* This file is part of the PEAR2\Console\CommandLine package.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE: This source file is subject to the MIT license that is available
|
||||
* through the world-wide-web at the following URI:
|
||||
* http://opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @version 0.2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since File available since release 0.1.0
|
||||
*/
|
||||
|
||||
namespace PEAR2\Console\CommandLine;
|
||||
|
||||
/**
|
||||
* PEAR2\Console\CommandLine default renderer.
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since Class available since release 0.1.0
|
||||
*/
|
||||
class Renderer_Default implements Renderer
|
||||
{
|
||||
// Properties {{{
|
||||
|
||||
/**
|
||||
* Integer that define the max width of the help text.
|
||||
*
|
||||
* @var integer $line_width Line width
|
||||
*/
|
||||
public $line_width = 75;
|
||||
|
||||
/**
|
||||
* Integer that define the max width of the help text.
|
||||
*
|
||||
* @var integer $line_width Line width
|
||||
*/
|
||||
public $options_on_different_lines = false;
|
||||
|
||||
/**
|
||||
* An instance of PEAR2\Console\CommandLine.
|
||||
*
|
||||
* @var PEAR2\Console\CommandLine $parser The parser
|
||||
*/
|
||||
public $parser = false;
|
||||
|
||||
// }}}
|
||||
// __construct() {{{
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param object $parser A PEAR2\Console\CommandLine instance
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($parser = false)
|
||||
{
|
||||
$this->parser = $parser;
|
||||
}
|
||||
|
||||
// }}}
|
||||
// usage() {{{
|
||||
|
||||
/**
|
||||
* Returns the full usage message.
|
||||
*
|
||||
* @return string The usage message
|
||||
*/
|
||||
public function usage()
|
||||
{
|
||||
$ret = '';
|
||||
if (!empty($this->parser->description)) {
|
||||
$ret .= $this->description() . "\n\n";
|
||||
}
|
||||
$ret .= $this->usageLine() . "\n";
|
||||
if (count($this->parser->commands) > 0) {
|
||||
$ret .= $this->commandUsageLine() . "\n";
|
||||
}
|
||||
if (count($this->parser->options) > 0) {
|
||||
$ret .= "\n" . $this->optionList() . "\n";
|
||||
}
|
||||
if (count($this->parser->args) > 0) {
|
||||
$ret .= "\n" . $this->argumentList() . "\n";
|
||||
}
|
||||
if (count($this->parser->commands) > 0) {
|
||||
$ret .= "\n" . $this->commandList() . "\n";
|
||||
}
|
||||
$ret .= "\n";
|
||||
return $ret;
|
||||
}
|
||||
// }}}
|
||||
// error() {{{
|
||||
|
||||
/**
|
||||
* Returns a formatted error message.
|
||||
*
|
||||
* @param string $error The error message to format
|
||||
*
|
||||
* @return string The error string
|
||||
*/
|
||||
public function error($error)
|
||||
{
|
||||
$ret = 'Error: ' . $error . "\n";
|
||||
if ($this->parser->add_help_option) {
|
||||
$name = $this->name();
|
||||
$ret .= $this->wrap(
|
||||
$this->parser->message_provider->get(
|
||||
'PROG_HELP_LINE',
|
||||
array('progname' => $name)
|
||||
)
|
||||
) . "\n";
|
||||
if (count($this->parser->commands) > 0) {
|
||||
$ret .= $this->wrap(
|
||||
$this->parser->message_provider->get(
|
||||
'COMMAND_HELP_LINE',
|
||||
array('progname' => $name)
|
||||
)
|
||||
) . "\n";
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
// }}}
|
||||
// version() {{{
|
||||
|
||||
/**
|
||||
* Returns the program version string.
|
||||
*
|
||||
* @return string The version string
|
||||
*/
|
||||
public function version()
|
||||
{
|
||||
return $this->parser->message_provider->get(
|
||||
'PROG_VERSION_LINE',
|
||||
array(
|
||||
'progname' => $this->name(),
|
||||
'version' => $this->parser->version
|
||||
)
|
||||
) . "\n";
|
||||
}
|
||||
|
||||
// }}}
|
||||
// name() {{{
|
||||
|
||||
/**
|
||||
* Returns the full name of the program or the sub command
|
||||
*
|
||||
* @return string The name of the program
|
||||
*/
|
||||
protected function name()
|
||||
{
|
||||
$name = $this->parser->name;
|
||||
$parent = $this->parser->parent;
|
||||
while ($parent) {
|
||||
if (count($parent->options) > 0) {
|
||||
$name = '['
|
||||
. strtolower(
|
||||
$this->parser->message_provider->get(
|
||||
'OPTION_WORD',
|
||||
array('plural' => 's')
|
||||
)
|
||||
) . '] ' . $name;
|
||||
}
|
||||
$name = $parent->name . ' ' . $name;
|
||||
$parent = $parent->parent;
|
||||
}
|
||||
return $this->wrap($name);
|
||||
}
|
||||
|
||||
// }}}
|
||||
// description() {{{
|
||||
|
||||
/**
|
||||
* Returns the command line description message.
|
||||
*
|
||||
* @return string The description message
|
||||
*/
|
||||
protected function description()
|
||||
{
|
||||
return $this->wrap($this->parser->description);
|
||||
}
|
||||
|
||||
// }}}
|
||||
// usageLine() {{{
|
||||
|
||||
/**
|
||||
* Returns the command line usage message
|
||||
*
|
||||
* @return string the usage message
|
||||
*/
|
||||
protected function usageLine()
|
||||
{
|
||||
$usage = $this->parser->message_provider->get('USAGE_WORD') . ":\n";
|
||||
$ret = $usage . ' ' . $this->name();
|
||||
if (count($this->parser->options) > 0) {
|
||||
$ret .= ' ['
|
||||
. strtolower($this->parser->message_provider->get('OPTION_WORD'))
|
||||
. ']';
|
||||
}
|
||||
if (count($this->parser->args) > 0) {
|
||||
foreach ($this->parser->args as $name=>$arg) {
|
||||
$arg_str = $arg->help_name;
|
||||
if ($arg->multiple) {
|
||||
$arg_str .= '1 ' . $arg->help_name . '2 ...';
|
||||
}
|
||||
if ($arg->optional) {
|
||||
$arg_str = '[' . $arg_str . ']';
|
||||
}
|
||||
$ret .= ' ' . $arg_str;
|
||||
}
|
||||
}
|
||||
return $this->columnWrap($ret, 2);
|
||||
}
|
||||
|
||||
// }}}
|
||||
// commandUsageLine() {{{
|
||||
|
||||
/**
|
||||
* Returns the command line usage message for subcommands.
|
||||
*
|
||||
* @return string The usage line
|
||||
*/
|
||||
protected function commandUsageLine()
|
||||
{
|
||||
if (count($this->parser->commands) == 0) {
|
||||
return '';
|
||||
}
|
||||
$ret = ' ' . $this->name();
|
||||
if (count($this->parser->options) > 0) {
|
||||
$ret .= ' ['
|
||||
. strtolower($this->parser->message_provider->get('OPTION_WORD'))
|
||||
. ']';
|
||||
}
|
||||
$ret .= " <command>";
|
||||
$hasArgs = false;
|
||||
$hasOptions = false;
|
||||
foreach ($this->parser->commands as $command) {
|
||||
if (!$hasArgs && count($command->args) > 0) {
|
||||
$hasArgs = true;
|
||||
}
|
||||
if (!$hasOptions && ($command->add_help_option
|
||||
|| $command->add_version_option
|
||||
|| count($command->options) > 0)
|
||||
) {
|
||||
$hasOptions = true;
|
||||
}
|
||||
}
|
||||
if ($hasOptions) {
|
||||
$ret .= ' [options]';
|
||||
}
|
||||
if ($hasArgs) {
|
||||
$ret .= ' [args]';
|
||||
}
|
||||
return $this->columnWrap($ret, 2);
|
||||
}
|
||||
|
||||
// }}}
|
||||
// argumentList() {{{
|
||||
|
||||
/**
|
||||
* Render the arguments list that will be displayed to the user, you can
|
||||
* override this method if you want to change the look of the list.
|
||||
*
|
||||
* @return string The formatted argument list
|
||||
*/
|
||||
protected function argumentList()
|
||||
{
|
||||
$col = 0;
|
||||
$args = array();
|
||||
foreach ($this->parser->args as $arg) {
|
||||
$argstr = ' ' . $arg->toString();
|
||||
$args[] = array($argstr, $arg->description);
|
||||
$ln = strlen($argstr);
|
||||
if ($col < $ln) {
|
||||
$col = $ln;
|
||||
}
|
||||
}
|
||||
$ret = $this->parser->message_provider->get('ARGUMENT_WORD') . ":";
|
||||
foreach ($args as $arg) {
|
||||
$text = str_pad($arg[0], $col) . ' ' . $arg[1];
|
||||
$ret .= "\n" . $this->columnWrap($text, $col+2);
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
// }}}
|
||||
// optionList() {{{
|
||||
|
||||
/**
|
||||
* Render the options list that will be displayed to the user, you can
|
||||
* override this method if you want to change the look of the list.
|
||||
*
|
||||
* @return string The formatted option list
|
||||
*/
|
||||
protected function optionList()
|
||||
{
|
||||
$col = 0;
|
||||
$options = array();
|
||||
foreach ($this->parser->options as $option) {
|
||||
$delim = $this->options_on_different_lines ? "\n" : ', ';
|
||||
$optstr = $option->toString($delim);
|
||||
$lines = explode("\n", $optstr);
|
||||
$lines[0] = ' ' . $lines[0];
|
||||
if (count($lines) > 1) {
|
||||
$lines[1] = ' ' . $lines[1];
|
||||
$ln = strlen($lines[1]);
|
||||
} else {
|
||||
$ln = strlen($lines[0]);
|
||||
}
|
||||
$options[] = array($lines, $option->description);
|
||||
if ($col < $ln) {
|
||||
$col = $ln;
|
||||
}
|
||||
}
|
||||
$ret = $this->parser->message_provider->get('OPTION_WORD') . ":";
|
||||
foreach ($options as $option) {
|
||||
if (count($option[0]) > 1) {
|
||||
$text = str_pad($option[0][1], $col) . ' ' . $option[1];
|
||||
$pre = $option[0][0] . "\n";
|
||||
} else {
|
||||
$text = str_pad($option[0][0], $col) . ' ' . $option[1];
|
||||
$pre = '';
|
||||
}
|
||||
$ret .= "\n" . $pre . $this->columnWrap($text, $col+2);
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
// }}}
|
||||
// commandList() {{{
|
||||
|
||||
/**
|
||||
* Render the command list that will be displayed to the user, you can
|
||||
* override this method if you want to change the look of the list.
|
||||
*
|
||||
* @return string The formatted subcommand list
|
||||
*/
|
||||
protected function commandList()
|
||||
{
|
||||
|
||||
$commands = array();
|
||||
$col = 0;
|
||||
foreach ($this->parser->commands as $cmdname=>$command) {
|
||||
$cmdname = ' ' . $cmdname;
|
||||
$commands[] = array($cmdname, $command->description, $command->aliases);
|
||||
$ln = strlen($cmdname);
|
||||
if ($col < $ln) {
|
||||
$col = $ln;
|
||||
}
|
||||
}
|
||||
$ret = $this->parser->message_provider->get('COMMAND_WORD') . ":";
|
||||
foreach ($commands as $command) {
|
||||
$text = str_pad($command[0], $col) . ' ' . $command[1];
|
||||
if ($aliasesCount = count($command[2])) {
|
||||
$pad = '';
|
||||
$text .= ' (';
|
||||
$text .= $aliasesCount > 1 ? 'aliases: ' : 'alias: ';
|
||||
foreach ($command[2] as $alias) {
|
||||
$text .= $pad . $alias;
|
||||
$pad = ', ';
|
||||
}
|
||||
$text .= ')';
|
||||
}
|
||||
$ret .= "\n" . $this->columnWrap($text, $col+2);
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
// }}}
|
||||
// wrap() {{{
|
||||
|
||||
/**
|
||||
* Wraps the text passed to the method.
|
||||
*
|
||||
* @param string $text The text to wrap
|
||||
* @param int $lw The column width (defaults to line_width property)
|
||||
*
|
||||
* @return string The wrapped text
|
||||
*/
|
||||
protected function wrap($text, $lw=null)
|
||||
{
|
||||
if ($this->line_width > 0) {
|
||||
if ($lw === null) {
|
||||
$lw = $this->line_width;
|
||||
}
|
||||
return wordwrap($text, $lw, "\n", false);
|
||||
}
|
||||
return $text;
|
||||
}
|
||||
|
||||
// }}}
|
||||
// columnWrap() {{{
|
||||
|
||||
/**
|
||||
* Wraps the text passed to the method at the specified width.
|
||||
*
|
||||
* @param string $text The text to wrap
|
||||
* @param int $cw The wrap width
|
||||
*
|
||||
* @return string The wrapped text
|
||||
*/
|
||||
protected function columnWrap($text, $cw)
|
||||
{
|
||||
$tokens = explode("\n", $this->wrap($text));
|
||||
$ret = $tokens[0];
|
||||
$text = trim(substr($text, strlen($ret)));
|
||||
if (empty($text)) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$chunks = $this->wrap($text, $this->line_width - $cw);
|
||||
$tokens = explode("\n", $chunks);
|
||||
foreach ($tokens as $token) {
|
||||
if (!empty($token)) {
|
||||
$ret .= "\n" . str_repeat(' ', $cw) . $token;
|
||||
} else {
|
||||
$ret .= "\n";
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
// }}}
|
||||
}
|
72
system/autoload/PEAR2/Console/CommandLine/Result.php
Normal file
72
system/autoload/PEAR2/Console/CommandLine/Result.php
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* This file is part of the PEAR2\Console\CommandLine package.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE: This source file is subject to the MIT license that is available
|
||||
* through the world-wide-web at the following URI:
|
||||
* http://opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @version 0.2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since File available since release 0.1.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace PEAR2\Console\CommandLine;
|
||||
|
||||
/**
|
||||
* A lightweight class to store the result of the command line parsing.
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since Class available since release 0.1.0
|
||||
*/
|
||||
class Result
|
||||
{
|
||||
// Public properties {{{
|
||||
|
||||
/**
|
||||
* The result options associative array.
|
||||
* Key is the name of the option and value its value.
|
||||
*
|
||||
* @var array $options Result options array
|
||||
*/
|
||||
public $options = array();
|
||||
|
||||
/**
|
||||
* The result arguments array.
|
||||
*
|
||||
* @var array $args Result arguments array
|
||||
*/
|
||||
public $args = array();
|
||||
|
||||
/**
|
||||
* Name of the command invoked by the user, false if no command invoked.
|
||||
*
|
||||
* @var string $command_name Result command name
|
||||
*/
|
||||
public $command_name = false;
|
||||
|
||||
/**
|
||||
* A result instance for the subcommand.
|
||||
*
|
||||
* @var static $command Result instance for the subcommand
|
||||
*/
|
||||
public $command = false;
|
||||
|
||||
// }}}
|
||||
}
|
303
system/autoload/PEAR2/Console/CommandLine/XmlParser.php
Normal file
303
system/autoload/PEAR2/Console/CommandLine/XmlParser.php
Normal file
@ -0,0 +1,303 @@
|
||||
<?php
|
||||
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* This file is part of the PEAR2\Console\CommandLine package.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* LICENSE: This source file is subject to the MIT license that is available
|
||||
* through the world-wide-web at the following URI:
|
||||
* http://opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @version 0.2.1
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since File available since release 0.1.0
|
||||
* @filesource
|
||||
*/
|
||||
|
||||
namespace PEAR2\Console\CommandLine;
|
||||
|
||||
use PEAR2\Console\CommandLine;
|
||||
|
||||
/**
|
||||
* Parser for command line xml definitions.
|
||||
*
|
||||
* @category Console
|
||||
* @package PEAR2\Console\CommandLine
|
||||
* @author David JEAN LOUIS <izimobil@gmail.com>
|
||||
* @copyright 2007-2009 David JEAN LOUIS
|
||||
* @license http://opensource.org/licenses/mit-license.php MIT License
|
||||
* @link http://pear2.php.net/PEAR2_Console_CommandLine
|
||||
* @since Class available since release 0.1.0
|
||||
*/
|
||||
class XmlParser
|
||||
{
|
||||
// parse() {{{
|
||||
|
||||
/**
|
||||
* Parses the given xml definition file and returns a
|
||||
* PEAR2\Console\CommandLine instance constructed with the xml data.
|
||||
*
|
||||
* @param string $xmlfile The xml file to parse
|
||||
*
|
||||
* @return PEAR2\Console\CommandLine A parser instance
|
||||
*/
|
||||
public static function parse($xmlfile)
|
||||
{
|
||||
if (!is_readable($xmlfile)) {
|
||||
CommandLine::triggerError(
|
||||
'invalid_xml_file',
|
||||
E_USER_ERROR,
|
||||
array('{$file}' => $xmlfile)
|
||||
);
|
||||
}
|
||||
$doc = new \DomDocument();
|
||||
$doc->load($xmlfile);
|
||||
self::validate($doc);
|
||||
$nodes = $doc->getElementsByTagName('command');
|
||||
$root = $nodes->item(0);
|
||||
return self::_parseCommandNode($root, true);
|
||||
}
|
||||
|
||||
// }}}
|
||||
// parseString() {{{
|
||||
|
||||
/**
|
||||
* Parses the given xml definition string and returns a
|
||||
* PEAR2\Console\CommandLine instance constructed with the xml data.
|
||||
*
|
||||
* @param string $xmlstr The xml string to parse
|
||||
*
|
||||
* @return PEAR2\Console\CommandLine A parser instance
|
||||
*/
|
||||
public static function parseString($xmlstr)
|
||||
{
|
||||
$doc = new \DomDocument();
|
||||
$doc->loadXml($xmlstr);
|
||||
self::validate($doc);
|
||||
$nodes = $doc->getElementsByTagName('command');
|
||||
$root = $nodes->item(0);
|
||||
return self::_parseCommandNode($root, true);
|
||||
}
|
||||
|
||||
// }}}
|
||||
// validate() {{{
|
||||
|
||||
/**
|
||||
* Validates the xml definition using Relax NG.
|
||||
*
|
||||
* @param DomDocument $doc The document to validate
|
||||
*
|
||||
* @return boolean Whether the xml data is valid or not.
|
||||
* @throws PEAR2\Console\CommandLine\Exception
|
||||
* @todo use exceptions only
|
||||
*/
|
||||
public static function validate($doc)
|
||||
{
|
||||
$rngfile = __DIR__
|
||||
. '/../../../../data/pear2.php.net/PEAR2_Console_CommandLine/xmlschema.rng';
|
||||
if (!is_file($rngfile)) {
|
||||
$rngfile = __DIR__ . '/../../../../data/xmlschema.rng';
|
||||
}
|
||||
if (!is_readable($rngfile)) {
|
||||
CommandLine::triggerError(
|
||||
'invalid_xml_file',
|
||||
E_USER_ERROR,
|
||||
array('{$file}' => $rngfile)
|
||||
);
|
||||
}
|
||||
return $doc->relaxNGValidate($rngfile);
|
||||
}
|
||||
|
||||
// }}}
|
||||
// _parseCommandNode() {{{
|
||||
|
||||
/**
|
||||
* Parses the root command node or a command node and returns the
|
||||
* constructed PEAR2\Console\CommandLine or PEAR2\Console\CommandLine_Command
|
||||
* instance.
|
||||
*
|
||||
* @param DomDocumentNode $node The node to parse
|
||||
* @param bool $isRootNode Whether it is a root node or not
|
||||
*
|
||||
* @return mixed PEAR2\Console\CommandLine or PEAR2\Console\CommandLine_Command
|
||||
*/
|
||||
private static function _parseCommandNode($node, $isRootNode = false)
|
||||
{
|
||||
if ($isRootNode) {
|
||||
$obj = new CommandLine();
|
||||
} else {
|
||||
$obj = new CommandLine\Command();
|
||||
}
|
||||
foreach ($node->childNodes as $cNode) {
|
||||
$cNodeName = $cNode->nodeName;
|
||||
switch ($cNodeName) {
|
||||
case 'name':
|
||||
case 'description':
|
||||
case 'version':
|
||||
$obj->$cNodeName = trim($cNode->nodeValue);
|
||||
break;
|
||||
case 'add_help_option':
|
||||
case 'add_version_option':
|
||||
case 'force_posix':
|
||||
$obj->$cNodeName = self::_bool(trim($cNode->nodeValue));
|
||||
break;
|
||||
case 'option':
|
||||
$obj->addOption(self::_parseOptionNode($cNode));
|
||||
break;
|
||||
case 'argument':
|
||||
$obj->addArgument(self::_parseArgumentNode($cNode));
|
||||
break;
|
||||
case 'command':
|
||||
$obj->addCommand(self::_parseCommandNode($cNode));
|
||||
break;
|
||||
case 'aliases':
|
||||
if (!$isRootNode) {
|
||||
foreach ($cNode->childNodes as $subChildNode) {
|
||||
if ($subChildNode->nodeName == 'alias') {
|
||||
$obj->aliases[] = trim($subChildNode->nodeValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'messages':
|
||||
$obj->messages = self::_messages($cNode);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $obj;
|
||||
}
|
||||
|
||||
// }}}
|
||||
// _parseOptionNode() {{{
|
||||
|
||||
/**
|
||||
* Parses an option node and returns the constructed
|
||||
* PEAR2\Console\CommandLine_Option instance.
|
||||
*
|
||||
* @param DomDocumentNode $node The node to parse
|
||||
*
|
||||
* @return PEAR2\Console\CommandLine\Option The built option
|
||||
*/
|
||||
private static function _parseOptionNode($node)
|
||||
{
|
||||
$obj = new CommandLine\Option($node->getAttribute('name'));
|
||||
foreach ($node->childNodes as $cNode) {
|
||||
$cNodeName = $cNode->nodeName;
|
||||
switch ($cNodeName) {
|
||||
case 'choices':
|
||||
foreach ($cNode->childNodes as $subChildNode) {
|
||||
if ($subChildNode->nodeName == 'choice') {
|
||||
$obj->choices[] = trim($subChildNode->nodeValue);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'messages':
|
||||
$obj->messages = self::_messages($cNode);
|
||||
break;
|
||||
default:
|
||||
if (property_exists($obj, $cNodeName)) {
|
||||
$obj->$cNodeName = trim($cNode->nodeValue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($obj->action == 'Password') {
|
||||
$obj->argument_optional = true;
|
||||
}
|
||||
return $obj;
|
||||
}
|
||||
|
||||
// }}}
|
||||
// _parseArgumentNode() {{{
|
||||
|
||||
/**
|
||||
* Parses an argument node and returns the constructed
|
||||
* PEAR2\Console\CommandLine_Argument instance.
|
||||
*
|
||||
* @param DomDocumentNode $node The node to parse
|
||||
*
|
||||
* @return PEAR2\Console\CommandLine\Argument The built argument
|
||||
*/
|
||||
private static function _parseArgumentNode($node)
|
||||
{
|
||||
$obj = new CommandLine\Argument($node->getAttribute('name'));
|
||||
foreach ($node->childNodes as $cNode) {
|
||||
$cNodeName = $cNode->nodeName;
|
||||
switch ($cNodeName) {
|
||||
case 'description':
|
||||
case 'help_name':
|
||||
case 'default':
|
||||
$obj->$cNodeName = trim($cNode->nodeValue);
|
||||
break;
|
||||
case 'multiple':
|
||||
$obj->multiple = self::_bool(trim($cNode->nodeValue));
|
||||
break;
|
||||
case 'optional':
|
||||
$obj->optional = self::_bool(trim($cNode->nodeValue));
|
||||
break;
|
||||
case 'messages':
|
||||
$obj->messages = self::_messages($cNode);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $obj;
|
||||
}
|
||||
|
||||
// }}}
|
||||
// _bool() {{{
|
||||
|
||||
/**
|
||||
* Returns a boolean according to true/false possible strings.
|
||||
*
|
||||
* @param string $str The string to process
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private static function _bool($str)
|
||||
{
|
||||
return in_array((string)$str, array('true', '1', 'on', 'yes'));
|
||||
}
|
||||
|
||||
// }}}
|
||||
// _messages() {{{
|
||||
|
||||
/**
|
||||
* Returns an array of custom messages for the element
|
||||
*
|
||||
* @param DOMNode $node The messages node to process
|
||||
*
|
||||
* @return array an array of messages
|
||||
*
|
||||
* @see PEAR2\Console\CommandLine::$messages
|
||||
* @see PEAR2\Console\CommandLine_Element::$messages
|
||||
*/
|
||||
private static function _messages(DOMNode $node)
|
||||
{
|
||||
$messages = array();
|
||||
|
||||
foreach ($node->childNodes as $cNode) {
|
||||
if ($cNode->nodeType == XML_ELEMENT_NODE) {
|
||||
$name = $cNode->getAttribute('name');
|
||||
$value = trim($cNode->nodeValue);
|
||||
|
||||
$messages[$name] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
// }}}
|
||||
}
|
819
system/autoload/PEAR2/Net/RouterOS/Client.php
Normal file
819
system/autoload/PEAR2/Net/RouterOS/Client.php
Normal file
@ -0,0 +1,819 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* RouterOS API client implementation.
|
||||
*
|
||||
* RouterOS is the flag product of the company MikroTik and is a powerful router software. One of its many abilities is to allow control over it via an API. This package provides a client for that API, in turn allowing you to use PHP to control RouterOS hosts.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_RouterOS
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Vasil Rangelov
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0b5
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
*/
|
||||
/**
|
||||
* The namespace declaration.
|
||||
*/
|
||||
namespace PEAR2\Net\RouterOS;
|
||||
|
||||
/**
|
||||
* Refers to transmitter direction constants.
|
||||
*/
|
||||
use PEAR2\Net\Transmitter\Stream as S;
|
||||
|
||||
/**
|
||||
* Refers to the cryptography constants.
|
||||
*/
|
||||
use PEAR2\Net\Transmitter\NetworkStream as N;
|
||||
|
||||
/**
|
||||
* Catches arbitrary exceptions at some points.
|
||||
*/
|
||||
use Exception as E;
|
||||
|
||||
/**
|
||||
* A RouterOS client.
|
||||
*
|
||||
* Provides functionality for easily communicating with a RouterOS host.
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_RouterOS
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
*/
|
||||
class Client
|
||||
{
|
||||
/**
|
||||
* Used in {@link static::isRequestActive()} to limit search only to
|
||||
* requests that have a callback.
|
||||
*/
|
||||
const FILTER_CALLBACK = 1;
|
||||
/**
|
||||
* Used in {@link static::isRequestActive()} to limit search only to
|
||||
* requests that use the buffer.
|
||||
*/
|
||||
const FILTER_BUFFER = 2;
|
||||
/**
|
||||
* Used in {@link static::isRequestActive()} to indicate no limit in search.
|
||||
*/
|
||||
const FILTER_ALL = 3;
|
||||
|
||||
/**
|
||||
* @var Communicator The communicator for this client.
|
||||
*/
|
||||
protected $com;
|
||||
|
||||
/**
|
||||
* @var int The number of currently pending requests.
|
||||
*/
|
||||
protected $pendingRequestsCount = 0;
|
||||
|
||||
/**
|
||||
* @var array An array of responses that have not yet been extracted or
|
||||
* passed to a callback. Key is the tag of the request, and the value
|
||||
* is an array of associated responses.
|
||||
*/
|
||||
protected $responseBuffer = array();
|
||||
|
||||
/**
|
||||
* @var array An array of callbacks to be executed as responses come.
|
||||
* Key is the tag of the request, and the value is the callback for it.
|
||||
*/
|
||||
protected $callbacks = array();
|
||||
|
||||
/**
|
||||
* @var Registry A registry for the operations. Particularly helpful at
|
||||
* persistent connections.
|
||||
*/
|
||||
protected $registry = null;
|
||||
|
||||
/**
|
||||
* @var bool Whether to stream future responses.
|
||||
*/
|
||||
private $_streamingResponses = false;
|
||||
|
||||
/**
|
||||
* Creates a new instance of a RouterOS API client.
|
||||
*
|
||||
* Creates a new instance of a RouterOS API client with the specified
|
||||
* settings.
|
||||
*
|
||||
* @param string $host Hostname (IP or domain) of the RouterOS server.
|
||||
* @param string $username The RouterOS username.
|
||||
* @param string $password The RouterOS password.
|
||||
* @param int|null $port The port on which the RouterOS server provides
|
||||
* the API service. You can also specify NULL, in which case the port
|
||||
* will automatically be chosen between 8728 and 8729, depending on the
|
||||
* value of $crypto.
|
||||
* @param bool $persist Whether or not the connection should be a
|
||||
* persistent one.
|
||||
* @param float $timeout The timeout for the connection.
|
||||
* @param string $crypto The encryption for this connection. Must be one
|
||||
* of the PEAR2\Net\Transmitter\NetworkStream::CRYPTO_* constants. Off
|
||||
* by default. RouterOS currently supports only TLS, but the setting is
|
||||
* provided in this fashion for forward compatibility's sake. And for
|
||||
* the sake of simplicity, if you specify an encryption, don't specify a
|
||||
* context and your default context uses the value "DEFAULT" for
|
||||
* ciphers, "ADH" will be automatically added to the list of ciphers.
|
||||
* @param resource $context A context for the socket.
|
||||
*
|
||||
* @see sendSync()
|
||||
* @see sendAsync()
|
||||
*/
|
||||
public function __construct(
|
||||
$host,
|
||||
$username,
|
||||
$password = '',
|
||||
$port = 8728,
|
||||
$persist = false,
|
||||
$timeout = null,
|
||||
$crypto = N::CRYPTO_OFF,
|
||||
$context = null
|
||||
) {
|
||||
$this->com = new Communicator(
|
||||
$host,
|
||||
$port,
|
||||
$persist,
|
||||
$timeout,
|
||||
$username . '/' . $password,
|
||||
$crypto,
|
||||
$context
|
||||
);
|
||||
$timeout = null == $timeout
|
||||
? ini_get('default_socket_timeout')
|
||||
: (int) $timeout;
|
||||
//Login the user if necessary
|
||||
if ((!$persist
|
||||
|| !($old = $this->com->getTransmitter()->lock(S::DIRECTION_ALL)))
|
||||
&& $this->com->getTransmitter()->isFresh()
|
||||
) {
|
||||
if (!static::login($this->com, $username, $password, $timeout)) {
|
||||
$this->com->close();
|
||||
throw new DataFlowException(
|
||||
'Invalid username or password supplied.',
|
||||
DataFlowException::CODE_INVALID_CREDENTIALS
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($old)) {
|
||||
$this->com->getTransmitter()->lock($old, true);
|
||||
}
|
||||
|
||||
if ($persist) {
|
||||
$this->registry = new Registry("{$host}:{$port}/{$username}");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A shorthand gateway.
|
||||
*
|
||||
* This is a magic PHP method that allows you to call the object as a
|
||||
* function. Depending on the argument given, one of the other functions in
|
||||
* the class is invoked and its returned value is returned by this function.
|
||||
*
|
||||
* @param mixed $arg Value can be either a {@link Request} to send, which
|
||||
* would be sent asynchoniously if it has a tag, and synchroniously if
|
||||
* not, a number to loop with or NULL to complete all pending requests.
|
||||
* Any other value is converted to string and treated as the tag of a
|
||||
* request to complete.
|
||||
*
|
||||
* @return mixed Whatever the long form function would have returned.
|
||||
*/
|
||||
public function __invoke($arg = null)
|
||||
{
|
||||
if (is_int($arg) || is_double($arg)) {
|
||||
return $this->loop($arg);
|
||||
} elseif ($arg instanceof Request) {
|
||||
return '' == $arg->getTag() ? $this->sendSync($arg)
|
||||
: $this->sendAsync($arg);
|
||||
} elseif (null === $arg) {
|
||||
return $this->completeRequest();
|
||||
}
|
||||
return $this->completeRequest((string) $arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Login to a RouterOS connection.
|
||||
*
|
||||
* @param Communicator $com The communicator to attempt to login to.
|
||||
* @param string $username The RouterOS username.
|
||||
* @param string $password The RouterOS password.
|
||||
* @param int|null $timeout The time to wait for each response. NULL
|
||||
* waits indefinetly.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public static function login(
|
||||
Communicator $com,
|
||||
$username,
|
||||
$password = '',
|
||||
$timeout = null
|
||||
) {
|
||||
if (null !== ($remoteCharset = $com->getCharset($com::CHARSET_REMOTE))
|
||||
&& null !== ($localCharset = $com->getCharset($com::CHARSET_LOCAL))
|
||||
) {
|
||||
$password = iconv(
|
||||
$localCharset,
|
||||
$remoteCharset . '//IGNORE//TRANSLIT',
|
||||
$password
|
||||
);
|
||||
}
|
||||
$old = null;
|
||||
try {
|
||||
if ($com->getTransmitter()->isPersistent()) {
|
||||
$old = $com->getTransmitter()->lock(S::DIRECTION_ALL);
|
||||
$result = self::_login($com, $username, $password, $timeout);
|
||||
$com->getTransmitter()->lock($old, true);
|
||||
return $result;
|
||||
}
|
||||
return self::_login($com, $username, $password, $timeout);
|
||||
} catch (E $e) {
|
||||
if ($com->getTransmitter()->isPersistent() && null !== $old) {
|
||||
$com->getTransmitter()->lock($old, true);
|
||||
}
|
||||
throw ($e instanceof NotSupportedException
|
||||
|| $e instanceof UnexpectedValueException
|
||||
|| !$com->getTransmitter()->isDataAwaiting()) ? new SocketException(
|
||||
'This is not a compatible RouterOS service',
|
||||
SocketException::CODE_SERVICE_INCOMPATIBLE,
|
||||
$e
|
||||
) : $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Login to a RouterOS connection.
|
||||
*
|
||||
* This is the actual login procedure, applied regardless of persistence and
|
||||
* charset settings.
|
||||
*
|
||||
* @param Communicator $com The communicator to attempt to login to.
|
||||
* @param string $username The RouterOS username.
|
||||
* @param string $password The RouterOS password. Potentially parsed
|
||||
* already by iconv.
|
||||
* @param int|null $timeout The time to wait for each response. NULL
|
||||
* waits indefinetly.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
private static function _login(
|
||||
Communicator $com,
|
||||
$username,
|
||||
$password = '',
|
||||
$timeout = null
|
||||
) {
|
||||
$request = new Request('/login');
|
||||
$request->send($com);
|
||||
$response = new Response($com, false, $timeout);
|
||||
$request->setArgument('name', $username);
|
||||
$request->setArgument(
|
||||
'response',
|
||||
'00' . md5(
|
||||
chr(0) . $password
|
||||
. pack('H*', $response->getProperty('ret'))
|
||||
)
|
||||
);
|
||||
$request->send($com);
|
||||
$response = new Response($com, false, $timeout);
|
||||
return $response->getType() === Response::TYPE_FINAL
|
||||
&& null === $response->getProperty('ret');
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the charset(s) for this connection.
|
||||
*
|
||||
* Sets the charset(s) for this connection. The specified charset(s) will be
|
||||
* used for all future requests and responses. When sending,
|
||||
* {@link Communicator::CHARSET_LOCAL} is converted to
|
||||
* {@link Communicator::CHARSET_REMOTE}, and when receiving,
|
||||
* {@link Communicator::CHARSET_REMOTE} is converted to
|
||||
* {@link Communicator::CHARSET_LOCAL}. Setting NULL to either charset will
|
||||
* disable charset convertion, and data will be both sent and received "as
|
||||
* is".
|
||||
*
|
||||
* @param mixed $charset The charset to set. If $charsetType is
|
||||
* {@link Communicator::CHARSET_ALL}, you can supply either a string to
|
||||
* use for all charsets, or an array with the charset types as keys, and
|
||||
* the charsets as values.
|
||||
* @param int $charsetType Which charset to set. Valid values are the
|
||||
* Communicator::CHARSET_* constants. Any other value is treated as
|
||||
* {@link Communicator::CHARSET_ALL}.
|
||||
*
|
||||
* @return string|array The old charset. If $charsetType is
|
||||
* {@link Communicator::CHARSET_ALL}, the old values will be returned as
|
||||
* an array with the types as keys, and charsets as values.
|
||||
* @see Communicator::setDefaultCharset()
|
||||
*/
|
||||
public function setCharset(
|
||||
$charset,
|
||||
$charsetType = Communicator::CHARSET_ALL
|
||||
) {
|
||||
return $this->com->setCharset($charset, $charsetType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the charset(s) for this connection.
|
||||
*
|
||||
* @param int $charsetType Which charset to get. Valid values are the
|
||||
* Communicator::CHARSET_* constants. Any other value is treated as
|
||||
* {@link Communicator::CHARSET_ALL}.
|
||||
*
|
||||
* @return string|array The current charset. If $charsetType is
|
||||
* {@link Communicator::CHARSET_ALL}, the current values will be
|
||||
* returned as an array with the types as keys, and charsets as values.
|
||||
* @see setCharset()
|
||||
*/
|
||||
public function getCharset($charsetType)
|
||||
{
|
||||
return $this->com->getCharset($charsetType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a request and waits for responses.
|
||||
*
|
||||
* @param Request $request The request to send.
|
||||
* @param callback $callback Optional. A function that is to be executed
|
||||
* when new responses for this request are available. The callback takes
|
||||
* two parameters. The {@link Response} object as the first, and the
|
||||
* {@link Client} object as the second one. If the function returns
|
||||
* TRUE, the request is canceled. Note that the callback may be executed
|
||||
* one last time after that with a response that notifies about the
|
||||
* canceling.
|
||||
*
|
||||
* @return $this The client object.
|
||||
* @see completeRequest()
|
||||
* @see loop()
|
||||
* @see cancelRequest()
|
||||
*/
|
||||
public function sendAsync(Request $request, $callback = null)
|
||||
{
|
||||
//Error checking
|
||||
$tag = $request->getTag();
|
||||
if ('' == $tag) {
|
||||
throw new DataFlowException(
|
||||
'Asynchonous commands must have a tag.',
|
||||
DataFlowException::CODE_TAG_REQUIRED
|
||||
);
|
||||
}
|
||||
if ($this->isRequestActive($tag)) {
|
||||
throw new DataFlowException(
|
||||
'There must not be multiple active requests sharing a tag.',
|
||||
DataFlowException::CODE_TAG_UNIQUE
|
||||
);
|
||||
}
|
||||
if (null !== $callback && !is_callable($callback, true)) {
|
||||
throw new UnexpectedValueException(
|
||||
'Invalid callback provided.',
|
||||
UnexpectedValueException::CODE_CALLBACK_INVALID
|
||||
);
|
||||
}
|
||||
|
||||
$this->send($request);
|
||||
|
||||
if (null === $callback) {
|
||||
//Register the request at the buffer
|
||||
$this->responseBuffer[$tag] = array();
|
||||
} else {
|
||||
//Prepare the callback
|
||||
$this->callbacks[$tag] = $callback;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a request is active.
|
||||
*
|
||||
* Checks if a request is active. A request is considered active if it's a
|
||||
* pending request and/or has responses that are not yet extracted.
|
||||
*
|
||||
* @param string $tag The tag of the request to look for.
|
||||
* @param int $filter One of the FILTER_* consntants. Limits the search
|
||||
* to the specified places.
|
||||
*
|
||||
* @return bool TRUE if the request is active, FALSE otherwise.
|
||||
* @see getPendingRequestsCount()
|
||||
* @see completeRequest()
|
||||
*/
|
||||
public function isRequestActive($tag, $filter = self::FILTER_ALL)
|
||||
{
|
||||
$result = 0;
|
||||
if ($filter & self::FILTER_CALLBACK) {
|
||||
$result |= (int) array_key_exists($tag, $this->callbacks);
|
||||
}
|
||||
if ($filter & self::FILTER_BUFFER) {
|
||||
$result |= (int) array_key_exists($tag, $this->responseBuffer);
|
||||
}
|
||||
return 0 !== $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a request and gets the full response.
|
||||
*
|
||||
* @param Request $request The request to send.
|
||||
*
|
||||
* @return ResponseCollection The received responses as a collection.
|
||||
* @see sendAsync()
|
||||
* @see close()
|
||||
*/
|
||||
public function sendSync(Request $request)
|
||||
{
|
||||
$tag = $request->getTag();
|
||||
if ('' == $tag) {
|
||||
$this->send($request);
|
||||
} else {
|
||||
$this->sendAsync($request);
|
||||
}
|
||||
return $this->completeRequest($tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Completes a specified request.
|
||||
*
|
||||
* Starts an event loop for the RouterOS callbacks and finishes when a
|
||||
* specified request is completed.
|
||||
*
|
||||
* @param string $tag The tag of the request to complete. Setting NULL
|
||||
* completes all requests.
|
||||
*
|
||||
* @return ResponseCollection A collection of {@link Response} objects that
|
||||
* haven't been passed to a callback function or previously extracted
|
||||
* with {@link static::extractNewResponses()}. Returns an empty
|
||||
* collection when $tag is set to NULL (responses can still be
|
||||
* extracted).
|
||||
*/
|
||||
public function completeRequest($tag = null)
|
||||
{
|
||||
$hasNoTag = '' == $tag;
|
||||
$result = $hasNoTag ? array()
|
||||
: $this->extractNewResponses($tag)->toArray();
|
||||
while ((!$hasNoTag && $this->isRequestActive($tag))
|
||||
|| ($hasNoTag && 0 !== $this->getPendingRequestsCount())
|
||||
) {
|
||||
$newReply = $this->dispatchNextResponse(null);
|
||||
if ($newReply->getTag() === $tag) {
|
||||
if ($hasNoTag) {
|
||||
$result[] = $newReply;
|
||||
}
|
||||
if ($newReply->getType() === Response::TYPE_FINAL) {
|
||||
if (!$hasNoTag) {
|
||||
$result = array_merge(
|
||||
$result,
|
||||
$this->isRequestActive($tag)
|
||||
? $this->extractNewResponses($tag)->toArray()
|
||||
: array()
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new ResponseCollection($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts responses for a request.
|
||||
*
|
||||
* Gets all new responses for a request that haven't been passed to a
|
||||
* callback and clears the buffer from them.
|
||||
*
|
||||
* @param string $tag The tag of the request to extract new responses for.
|
||||
* Specifying NULL with extract new responses for all requests.
|
||||
*
|
||||
* @return ResponseCollection A collection of {@link Response} objects for
|
||||
* the specified request.
|
||||
* @see loop()
|
||||
*/
|
||||
public function extractNewResponses($tag = null)
|
||||
{
|
||||
if (null === $tag) {
|
||||
$result = array();
|
||||
foreach (array_keys($this->responseBuffer) as $tag) {
|
||||
$result = array_merge(
|
||||
$result,
|
||||
$this->extractNewResponses($tag)->toArray()
|
||||
);
|
||||
}
|
||||
return new ResponseCollection($result);
|
||||
} elseif ($this->isRequestActive($tag, self::FILTER_CALLBACK)) {
|
||||
return new ResponseCollection(array());
|
||||
} elseif ($this->isRequestActive($tag, self::FILTER_BUFFER)) {
|
||||
$result = $this->responseBuffer[$tag];
|
||||
if (!empty($result)) {
|
||||
if (end($result)->getType() === Response::TYPE_FINAL) {
|
||||
unset($this->responseBuffer[$tag]);
|
||||
} else {
|
||||
$this->responseBuffer[$tag] = array();
|
||||
}
|
||||
}
|
||||
return new ResponseCollection($result);
|
||||
} else {
|
||||
throw new DataFlowException(
|
||||
'No such request, or the request has already finished.',
|
||||
DataFlowException::CODE_UNKNOWN_REQUEST
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts an event loop for the RouterOS callbacks.
|
||||
*
|
||||
* Starts an event loop for the RouterOS callbacks and finishes when there
|
||||
* are no more pending requests or when a specified timeout has passed
|
||||
* (whichever comes first).
|
||||
*
|
||||
* @param int $sTimeout Timeout for the loop. If NULL, there is no time
|
||||
* limit.
|
||||
* @param int $usTimeout Microseconds to add to the time limit.
|
||||
*
|
||||
* @return bool TRUE when there are any more pending requests, FALSE
|
||||
* otherwise.
|
||||
* @see extractNewResponses()
|
||||
* @see getPendingRequestsCount()
|
||||
*/
|
||||
public function loop($sTimeout = null, $usTimeout = 0)
|
||||
{
|
||||
try {
|
||||
if (null === $sTimeout) {
|
||||
while ($this->getPendingRequestsCount() !== 0) {
|
||||
$this->dispatchNextResponse(null);
|
||||
}
|
||||
} else {
|
||||
list($usStart, $sStart) = explode(' ', microtime());
|
||||
while ($this->getPendingRequestsCount() !== 0
|
||||
&& ($sTimeout >= 0 || $usTimeout >= 0)
|
||||
) {
|
||||
$this->dispatchNextResponse($sTimeout, $usTimeout);
|
||||
list($usEnd, $sEnd) = explode(' ', microtime());
|
||||
|
||||
$sTimeout -= $sEnd - $sStart;
|
||||
$usTimeout -= $usEnd - $usStart;
|
||||
if ($usTimeout <= 0) {
|
||||
if ($sTimeout > 0) {
|
||||
$usTimeout = 1000000 + $usTimeout;
|
||||
$sTimeout--;
|
||||
}
|
||||
}
|
||||
|
||||
$sStart = $sEnd;
|
||||
$usStart = $usEnd;
|
||||
}
|
||||
}
|
||||
} catch (SocketException $e) {
|
||||
if ($e->getCode() !== SocketException::CODE_NO_DATA) {
|
||||
// @codeCoverageIgnoreStart
|
||||
// It's impossible to reliably cause any other SocketException.
|
||||
// This line is only here in case the unthinkable happens:
|
||||
// The connection terminates just after it was supposedly
|
||||
// about to send back some data.
|
||||
throw $e;
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
}
|
||||
return $this->getPendingRequestsCount() !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of pending requests.
|
||||
*
|
||||
* @return int The number of pending requests.
|
||||
* @see isRequestActive()
|
||||
*/
|
||||
public function getPendingRequestsCount()
|
||||
{
|
||||
return $this->pendingRequestsCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels a request.
|
||||
*
|
||||
* Cancels an active request. Using this function in favor of a plain call
|
||||
* to the "/cancel" command is highly reccomended, as it also updates the
|
||||
* counter of pending requests properly. Note that canceling a request also
|
||||
* removes any responses for it that were not previously extracted with
|
||||
* {@link static::extractNewResponses()}.
|
||||
*
|
||||
* @param string $tag Tag of the request to cancel. Setting NULL will cancel
|
||||
* all requests.
|
||||
*
|
||||
* @return $this The client object.
|
||||
* @see sendAsync()
|
||||
* @see close()
|
||||
*/
|
||||
public function cancelRequest($tag = null)
|
||||
{
|
||||
$cancelRequest = new Request('/cancel');
|
||||
$hasTag = !('' == $tag);
|
||||
$hasReg = null !== $this->registry;
|
||||
if ($hasReg && !$hasTag) {
|
||||
$tags = array_merge(
|
||||
array_keys($this->responseBuffer),
|
||||
array_keys($this->callbacks)
|
||||
);
|
||||
$this->registry->setTaglessMode(true);
|
||||
foreach ($tags as $t) {
|
||||
$cancelRequest->setArgument(
|
||||
'tag',
|
||||
$this->registry->getOwnershipTag() . $t
|
||||
);
|
||||
$this->sendSync($cancelRequest);
|
||||
}
|
||||
$this->registry->setTaglessMode(false);
|
||||
} else {
|
||||
if ($hasTag) {
|
||||
if ($this->isRequestActive($tag)) {
|
||||
if ($hasReg) {
|
||||
$this->registry->setTaglessMode(true);
|
||||
$cancelRequest->setArgument(
|
||||
'tag',
|
||||
$this->registry->getOwnershipTag() . $tag
|
||||
);
|
||||
} else {
|
||||
$cancelRequest->setArgument('tag', $tag);
|
||||
}
|
||||
} else {
|
||||
throw new DataFlowException(
|
||||
'No such request. Canceling aborted.',
|
||||
DataFlowException::CODE_CANCEL_FAIL
|
||||
);
|
||||
}
|
||||
}
|
||||
$this->sendSync($cancelRequest);
|
||||
if ($hasReg) {
|
||||
$this->registry->setTaglessMode(false);
|
||||
}
|
||||
}
|
||||
|
||||
if ($hasTag) {
|
||||
if ($this->isRequestActive($tag, self::FILTER_BUFFER)) {
|
||||
$this->responseBuffer[$tag] = $this->completeRequest($tag);
|
||||
} else {
|
||||
$this->completeRequest($tag);
|
||||
}
|
||||
} else {
|
||||
$this->loop();
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets response streaming setting.
|
||||
*
|
||||
* Sets whether future responses are streamed. If responses are streamed,
|
||||
* the argument values are returned as streams instead of strings. This is
|
||||
* particularly useful if you expect a response that may contain one or more
|
||||
* very large words.
|
||||
*
|
||||
* @param bool $streamingResponses Whether to stream future responses.
|
||||
*
|
||||
* @return bool The previous value of the setting.
|
||||
* @see isStreamingResponses()
|
||||
*/
|
||||
public function setStreamingResponses($streamingResponses)
|
||||
{
|
||||
$oldValue = $this->_streamingResponses;
|
||||
$this->_streamingResponses = (bool) $streamingResponses;
|
||||
return $oldValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets response streaming setting.
|
||||
*
|
||||
* Gets whether future responses are streamed.
|
||||
*
|
||||
* @return bool The value of the setting.
|
||||
* @see setStreamingResponses()
|
||||
*/
|
||||
public function isStreamingResponses()
|
||||
{
|
||||
return $this->_streamingResponses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the opened connection, even if it is a persistent one.
|
||||
*
|
||||
* Closes the opened connection, even if it is a persistent one. Note that
|
||||
* {@link static::extractNewResponses()} can still be used to extract
|
||||
* responses collected prior to the closing.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
$result = true;
|
||||
/*
|
||||
* The check below is done because for some unknown reason
|
||||
* (either a PHP or a RouterOS bug) calling "/quit" on an encrypted
|
||||
* connection makes one end hang.
|
||||
*
|
||||
* Since encrypted connections only appeared in RouterOS 6.1, and
|
||||
* the "/quit" call is needed for all <6.0 versions, problems due
|
||||
* to its absence should be limited to some earlier 6.* versions
|
||||
* on some RouterBOARD devices.
|
||||
*/
|
||||
if ($this->com->getTransmitter()->getCrypto() === N::CRYPTO_OFF) {
|
||||
if (null !== $this->registry) {
|
||||
$this->registry->setTaglessMode(true);
|
||||
}
|
||||
try {
|
||||
$response = $this->sendSync(new Request('/quit'));
|
||||
$result = $response[0]->getType() === Response::TYPE_FATAL;
|
||||
} catch (SocketException $e) {
|
||||
$result
|
||||
= $e->getCode() === SocketException::CODE_REQUEST_SEND_FAIL;
|
||||
} catch (E $e) {
|
||||
//Ignore unknown errors.
|
||||
}
|
||||
if (null !== $this->registry) {
|
||||
$this->registry->setTaglessMode(false);
|
||||
}
|
||||
}
|
||||
$result = $result && $this->com->close();
|
||||
$this->callbacks = array();
|
||||
$this->pendingRequestsCount = 0;
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the connection, unless it's a persistent one.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if ($this->com->getTransmitter()->isPersistent()) {
|
||||
if (0 !== $this->pendingRequestsCount) {
|
||||
$this->cancelRequest();
|
||||
}
|
||||
} else {
|
||||
$this->close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a request to RouterOS.
|
||||
*
|
||||
* @param Request $request The request to send.
|
||||
*
|
||||
* @return $this The client object.
|
||||
* @see sendSync()
|
||||
* @see sendAsync()
|
||||
*/
|
||||
protected function send(Request $request)
|
||||
{
|
||||
$request->send($this->com, $this->registry);
|
||||
$this->pendingRequestsCount++;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches the next response in queue.
|
||||
*
|
||||
* Dispatches the next response in queue, i.e. it executes the associated
|
||||
* callback if there is one, or places the response in the response buffer.
|
||||
*
|
||||
* @param int $sTimeout If a response is not immediatly available, wait
|
||||
* this many seconds. If NULL, wait indefinetly.
|
||||
* @param int $usTimeout Microseconds to add to the waiting time.
|
||||
*
|
||||
* @throws SocketException When there's no response within the time limit.
|
||||
* @return Response The dispatched response.
|
||||
*/
|
||||
protected function dispatchNextResponse($sTimeout = 0, $usTimeout = 0)
|
||||
{
|
||||
$response = new Response(
|
||||
$this->com,
|
||||
$this->_streamingResponses,
|
||||
$sTimeout,
|
||||
$usTimeout,
|
||||
$this->registry
|
||||
);
|
||||
if ($response->getType() === Response::TYPE_FATAL) {
|
||||
$this->pendingRequestsCount = 0;
|
||||
$this->com->close();
|
||||
return $response;
|
||||
}
|
||||
|
||||
$tag = $response->getTag();
|
||||
$isLastForRequest = $response->getType() === Response::TYPE_FINAL;
|
||||
if ($isLastForRequest) {
|
||||
$this->pendingRequestsCount--;
|
||||
}
|
||||
|
||||
if ('' != $tag) {
|
||||
if ($this->isRequestActive($tag, self::FILTER_CALLBACK)) {
|
||||
if ($this->callbacks[$tag]($response, $this)) {
|
||||
$this->cancelRequest($tag);
|
||||
} elseif ($isLastForRequest) {
|
||||
unset($this->callbacks[$tag]);
|
||||
}
|
||||
} else {
|
||||
$this->responseBuffer[$tag][] = $response;
|
||||
}
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
}
|
671
system/autoload/PEAR2/Net/RouterOS/Communicator.php
Normal file
671
system/autoload/PEAR2/Net/RouterOS/Communicator.php
Normal file
@ -0,0 +1,671 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* RouterOS API client implementation.
|
||||
*
|
||||
* RouterOS is the flag product of the company MikroTik and is a powerful router software. One of its many abilities is to allow control over it via an API. This package provides a client for that API, in turn allowing you to use PHP to control RouterOS hosts.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_RouterOS
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Vasil Rangelov
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0b5
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
*/
|
||||
/**
|
||||
* The namespace declaration.
|
||||
*/
|
||||
namespace PEAR2\Net\RouterOS;
|
||||
|
||||
/**
|
||||
* Using transmitters.
|
||||
*/
|
||||
use PEAR2\Net\Transmitter as T;
|
||||
|
||||
/**
|
||||
* A RouterOS communicator.
|
||||
*
|
||||
* Implementation of the RouterOS API protocol. Unlike the other classes in this
|
||||
* package, this class doesn't provide any conviniences beyond the low level
|
||||
* implementation details (automatic word length encoding/decoding, charset
|
||||
* translation and data integrity), and because of that, its direct usage is
|
||||
* strongly discouraged.
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_RouterOS
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
* @see Client
|
||||
*/
|
||||
class Communicator
|
||||
{
|
||||
/**
|
||||
* Used when getting/setting all (default) charsets.
|
||||
*/
|
||||
const CHARSET_ALL = -1;
|
||||
|
||||
/**
|
||||
* Used when getting/setting the (default) remote charset.
|
||||
*
|
||||
* The remote charset is the charset in which RouterOS stores its data.
|
||||
* If you want to keep compatibility with your Winbox, this charset should
|
||||
* match the default charset from your Windows' regional settings.
|
||||
*/
|
||||
const CHARSET_REMOTE = 0;
|
||||
|
||||
/**
|
||||
* Used when getting/setting the (default) local charset.
|
||||
*
|
||||
* The local charset is the charset in which the data from RouterOS will be
|
||||
* returned as. This charset should match the charset of the place the data
|
||||
* will eventually be written to.
|
||||
*/
|
||||
const CHARSET_LOCAL = 1;
|
||||
|
||||
/**
|
||||
* @var array An array with the default charset types as keys, and the
|
||||
* default charsets as values.
|
||||
*/
|
||||
protected static $defaultCharsets = array(
|
||||
self::CHARSET_REMOTE => null,
|
||||
self::CHARSET_LOCAL => null
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array An array with the current charset types as keys, and the
|
||||
* current charsets as values.
|
||||
*/
|
||||
protected $charsets = array();
|
||||
|
||||
/**
|
||||
* @var T\TcpClient The transmitter for the connection.
|
||||
*/
|
||||
protected $trans;
|
||||
|
||||
/**
|
||||
* Creates a new connection with the specified options.
|
||||
*
|
||||
* @param string $host Hostname (IP or domain) of the RouterOS server.
|
||||
* @param int|null $port The port on which the RouterOS server provides
|
||||
* the API service. You can also specify NULL, in which case the port
|
||||
* will automatically be chosen between 8728 and 8729, depending on the
|
||||
* value of $crypto.
|
||||
* @param bool $persist Whether or not the connection should be a
|
||||
* persistent one.
|
||||
* @param float $timeout The timeout for the connection.
|
||||
* @param string $key A string that uniquely identifies the
|
||||
* connection.
|
||||
* @param string $crypto The encryption for this connection. Must be one
|
||||
* of the PEAR2\Net\Transmitter\NetworkStream::CRYPTO_* constants. Off
|
||||
* by default. RouterOS currently supports only TLS, but the setting is
|
||||
* provided in this fashion for forward compatibility's sake. And for
|
||||
* the sake of simplicity, if you specify an encryption, don't specify a
|
||||
* context and your default context uses the value "DEFAULT" for
|
||||
* ciphers, "ADH" will be automatically added to the list of ciphers.
|
||||
* @param resource $context A context for the socket.
|
||||
*
|
||||
* @see sendWord()
|
||||
*/
|
||||
public function __construct(
|
||||
$host,
|
||||
$port = 8728,
|
||||
$persist = false,
|
||||
$timeout = null,
|
||||
$key = '',
|
||||
$crypto = T\NetworkStream::CRYPTO_OFF,
|
||||
$context = null
|
||||
) {
|
||||
$isUnencrypted = T\NetworkStream::CRYPTO_OFF === $crypto;
|
||||
if (($context === null) && !$isUnencrypted) {
|
||||
$context = stream_context_get_default();
|
||||
$opts = stream_context_get_options($context);
|
||||
if (!isset($opts['ssl']['ciphers'])
|
||||
|| 'DEFAULT' === $opts['ssl']['ciphers']
|
||||
) {
|
||||
stream_context_set_option($context, 'ssl', 'ciphers', 'ADH');
|
||||
}
|
||||
}
|
||||
// @codeCoverageIgnoreStart
|
||||
// The $port is customizable in testing.
|
||||
if (null === $port) {
|
||||
$port = $isUnencrypted ? 8728 : 8729;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
try {
|
||||
$this->trans = new T\TcpClient(
|
||||
$host,
|
||||
$port,
|
||||
$persist,
|
||||
$timeout,
|
||||
$key,
|
||||
$crypto,
|
||||
$context
|
||||
);
|
||||
} catch (T\Exception $e) {
|
||||
throw new SocketException(
|
||||
'Error connecting to RouterOS',
|
||||
SocketException::CODE_CONNECTION_FAIL,
|
||||
$e
|
||||
);
|
||||
}
|
||||
$this->setCharset(
|
||||
self::getDefaultCharset(self::CHARSET_ALL),
|
||||
self::CHARSET_ALL
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* A shorthand gateway.
|
||||
*
|
||||
* This is a magic PHP method that allows you to call the object as a
|
||||
* function. Depending on the argument given, one of the other functions in
|
||||
* the class is invoked and its returned value is returned by this function.
|
||||
*
|
||||
* @param string $string A string of the word to send, or NULL to get the
|
||||
* next word as a string.
|
||||
*
|
||||
* @return int|string If a string is provided, returns the number of bytes
|
||||
* sent, otherwise retuns the next word as a string.
|
||||
*/
|
||||
public function __invoke($string = null)
|
||||
{
|
||||
return null === $string ? $this->getNextWord()
|
||||
: $this->sendWord($string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a variable is a seekable stream resource.
|
||||
*
|
||||
* @param mixed $var The value to check.
|
||||
*
|
||||
* @return bool TRUE if $var is a seekable stream, FALSE otherwise.
|
||||
*/
|
||||
public static function isSeekableStream($var)
|
||||
{
|
||||
if (T\Stream::isStream($var)) {
|
||||
$meta = stream_get_meta_data($var);
|
||||
return $meta['seekable'];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses iconv to convert a stream from one charset to another.
|
||||
*
|
||||
* @param string $inCharset The charset of the stream.
|
||||
* @param string $outCharset The desired resulting charset.
|
||||
* @param resource $stream The stream to convert. The stream is assumed
|
||||
* to be seekable, and is read from its current position to its end,
|
||||
* after which, it is seeked back to its starting position.
|
||||
*
|
||||
* @return resource A new stream that uses the $out_charset. The stream is a
|
||||
* subset from the original stream, from its current position to its
|
||||
* end, seeked at its start.
|
||||
*/
|
||||
public static function iconvStream($inCharset, $outCharset, $stream)
|
||||
{
|
||||
$bytes = 0;
|
||||
$result = fopen('php://temp', 'r+b');
|
||||
$iconvFilter = stream_filter_append(
|
||||
$result,
|
||||
'convert.iconv.' . $inCharset . '.' . $outCharset,
|
||||
STREAM_FILTER_WRITE
|
||||
);
|
||||
|
||||
flock($stream, LOCK_SH);
|
||||
while (!feof($stream)) {
|
||||
$bytes += stream_copy_to_stream($stream, $result, 0xFFFFF);
|
||||
}
|
||||
fseek($stream, -$bytes, SEEK_CUR);
|
||||
flock($stream, LOCK_UN);
|
||||
|
||||
stream_filter_remove($iconvFilter);
|
||||
rewind($result);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default charset(s) for new connections.
|
||||
*
|
||||
* @param mixed $charset The charset to set. If $charsetType is
|
||||
* {@link self::CHARSET_ALL}, you can supply either a string to use for
|
||||
* all charsets, or an array with the charset types as keys, and the
|
||||
* charsets as values.
|
||||
* @param int $charsetType Which charset to set. Valid values are the
|
||||
* CHARSET_* constants. Any other value is treated as
|
||||
* {@link self::CHARSET_ALL}.
|
||||
*
|
||||
* @return string|array The old charset. If $charsetType is
|
||||
* {@link self::CHARSET_ALL}, the old values will be returned as an
|
||||
* array with the types as keys, and charsets as values.
|
||||
* @see setCharset()
|
||||
*/
|
||||
public static function setDefaultCharset(
|
||||
$charset,
|
||||
$charsetType = self::CHARSET_ALL
|
||||
) {
|
||||
if (array_key_exists($charsetType, self::$defaultCharsets)) {
|
||||
$oldCharset = self::$defaultCharsets[$charsetType];
|
||||
self::$defaultCharsets[$charsetType] = $charset;
|
||||
return $oldCharset;
|
||||
} else {
|
||||
$oldCharsets = self::$defaultCharsets;
|
||||
self::$defaultCharsets = is_array($charset) ? $charset : array_fill(
|
||||
0,
|
||||
count(self::$defaultCharsets),
|
||||
$charset
|
||||
);
|
||||
return $oldCharsets;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default charset(s).
|
||||
*
|
||||
* @param int $charsetType Which charset to get. Valid values are the
|
||||
* CHARSET_* constants. Any other value is treated as
|
||||
* {@link self::CHARSET_ALL}.
|
||||
*
|
||||
* @return string|array The current charset. If $charsetType is
|
||||
* {@link self::CHARSET_ALL}, the current values will be returned as an
|
||||
* array with the types as keys, and charsets as values.
|
||||
* @see setDefaultCharset()
|
||||
*/
|
||||
public static function getDefaultCharset($charsetType)
|
||||
{
|
||||
return array_key_exists($charsetType, self::$defaultCharsets)
|
||||
? self::$defaultCharsets[$charsetType] : self::$defaultCharsets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the length of a seekable stream.
|
||||
*
|
||||
* Gets the length of a seekable stream.
|
||||
*
|
||||
* @param resource $stream The stream to check. The stream is assumed to be
|
||||
* seekable.
|
||||
*
|
||||
* @return double The number of bytes in the stream between its current
|
||||
* position and its end.
|
||||
*/
|
||||
public static function seekableStreamLength($stream)
|
||||
{
|
||||
$streamPosition = (double) sprintf('%u', ftell($stream));
|
||||
fseek($stream, 0, SEEK_END);
|
||||
$streamLength = ((double) sprintf('%u', ftell($stream)))
|
||||
- $streamPosition;
|
||||
fseek($stream, $streamPosition, SEEK_SET);
|
||||
return $streamLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the charset(s) for this connection.
|
||||
*
|
||||
* Sets the charset(s) for this connection. The specified charset(s) will be
|
||||
* used for all future words. When sending, {@link self::CHARSET_LOCAL} is
|
||||
* converted to {@link self::CHARSET_REMOTE}, and when receiving,
|
||||
* {@link self::CHARSET_REMOTE} is converted to {@link self::CHARSET_LOCAL}.
|
||||
* Setting NULL to either charset will disable charset convertion, and data
|
||||
* will be both sent and received "as is".
|
||||
*
|
||||
* @param mixed $charset The charset to set. If $charsetType is
|
||||
* {@link self::CHARSET_ALL}, you can supply either a string to use for
|
||||
* all charsets, or an array with the charset types as keys, and the
|
||||
* charsets as values.
|
||||
* @param int $charsetType Which charset to set. Valid values are the
|
||||
* CHARSET_* constants. Any other value is treated as
|
||||
* {@link self::CHARSET_ALL}.
|
||||
*
|
||||
* @return string|array The old charset. If $charsetType is
|
||||
* {@link self::CHARSET_ALL}, the old values will be returned as an
|
||||
* array with the types as keys, and charsets as values.
|
||||
* @see setDefaultCharset()
|
||||
*/
|
||||
public function setCharset($charset, $charsetType = self::CHARSET_ALL)
|
||||
{
|
||||
if (array_key_exists($charsetType, $this->charsets)) {
|
||||
$oldCharset = $this->charsets[$charsetType];
|
||||
$this->charsets[$charsetType] = $charset;
|
||||
return $oldCharset;
|
||||
} else {
|
||||
$oldCharsets = $this->charsets;
|
||||
$this->charsets = is_array($charset) ? $charset : array_fill(
|
||||
0,
|
||||
count($this->charsets),
|
||||
$charset
|
||||
);
|
||||
return $oldCharsets;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the charset(s) for this connection.
|
||||
*
|
||||
* @param int $charsetType Which charset to get. Valid values are the
|
||||
* CHARSET_* constants. Any other value is treated as
|
||||
* {@link self::CHARSET_ALL}.
|
||||
*
|
||||
* @return string|array The current charset. If $charsetType is
|
||||
* {@link self::CHARSET_ALL}, the current values will be returned as an
|
||||
* array with the types as keys, and charsets as values.
|
||||
* @see getDefaultCharset()
|
||||
* @see setCharset()
|
||||
*/
|
||||
public function getCharset($charsetType)
|
||||
{
|
||||
return array_key_exists($charsetType, $this->charsets)
|
||||
? $this->charsets[$charsetType] : $this->charsets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the transmitter for this connection.
|
||||
*
|
||||
* @return T\TcpClient The transmitter for this connection.
|
||||
*/
|
||||
public function getTransmitter()
|
||||
{
|
||||
return $this->trans;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a word.
|
||||
*
|
||||
* Sends a word and automatically encodes its length when doing so.
|
||||
*
|
||||
* @param string $word The word to send.
|
||||
*
|
||||
* @return int The number of bytes sent.
|
||||
* @see sendWordFromStream()
|
||||
* @see getNextWord()
|
||||
*/
|
||||
public function sendWord($word)
|
||||
{
|
||||
if (null !== ($remoteCharset = $this->getCharset(self::CHARSET_REMOTE))
|
||||
&& null !== ($localCharset = $this->getCharset(self::CHARSET_LOCAL))
|
||||
) {
|
||||
$word = iconv(
|
||||
$localCharset,
|
||||
$remoteCharset . '//IGNORE//TRANSLIT',
|
||||
$word
|
||||
);
|
||||
}
|
||||
$length = strlen($word);
|
||||
static::verifyLengthSupport($length);
|
||||
if ($this->trans->isPersistent()) {
|
||||
$old = $this->trans->lock(T\Stream::DIRECTION_SEND);
|
||||
$bytes = $this->trans->send(self::encodeLength($length) . $word);
|
||||
$this->trans->lock($old, true);
|
||||
return $bytes;
|
||||
}
|
||||
return $this->trans->send(self::encodeLength($length) . $word);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a word based on a stream.
|
||||
*
|
||||
* Sends a word based on a stream and automatically encodes its length when
|
||||
* doing so. The stream is read from its current position to its end, and
|
||||
* then returned to its current position. Because of those operations, the
|
||||
* supplied stream must be seekable.
|
||||
*
|
||||
* @param string $prefix A string to prepend before the stream contents.
|
||||
* @param resource $stream The seekable stream to send.
|
||||
*
|
||||
* @return int The number of bytes sent.
|
||||
* @see sendWord()
|
||||
*/
|
||||
public function sendWordFromStream($prefix, $stream)
|
||||
{
|
||||
if (!self::isSeekableStream($stream)) {
|
||||
throw new InvalidArgumentException(
|
||||
'The stream must be seekable.',
|
||||
InvalidArgumentException::CODE_SEEKABLE_REQUIRED
|
||||
);
|
||||
}
|
||||
if (null !== ($remoteCharset = $this->getCharset(self::CHARSET_REMOTE))
|
||||
&& null !== ($localCharset = $this->getCharset(self::CHARSET_LOCAL))
|
||||
) {
|
||||
$prefix = iconv(
|
||||
$localCharset,
|
||||
$remoteCharset . '//IGNORE//TRANSLIT',
|
||||
$prefix
|
||||
);
|
||||
$stream = self::iconvStream(
|
||||
$localCharset,
|
||||
$remoteCharset . '//IGNORE//TRANSLIT',
|
||||
$stream
|
||||
);
|
||||
}
|
||||
|
||||
flock($stream, LOCK_SH);
|
||||
$totalLength = strlen($prefix) + self::seekableStreamLength($stream);
|
||||
static::verifyLengthSupport($totalLength);
|
||||
|
||||
$bytes = $this->trans->send(self::encodeLength($totalLength) . $prefix);
|
||||
$bytes += $this->trans->send($stream);
|
||||
|
||||
flock($stream, LOCK_UN);
|
||||
return $bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the length is supported.
|
||||
*
|
||||
* Verifies if the specified length is supported by the API. Throws a
|
||||
* {@link LengthException} if that's not the case. Currently, RouterOS
|
||||
* supports words up to 0xFFFFFFFF in length, so that's the only check
|
||||
* performed.
|
||||
*
|
||||
* @param int $length The length to verify.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function verifyLengthSupport($length)
|
||||
{
|
||||
if ($length > 0xFFFFFFFF) {
|
||||
throw new LengthException(
|
||||
'Words with length above 0xFFFFFFFF are not supported.',
|
||||
LengthException::CODE_UNSUPPORTED,
|
||||
null,
|
||||
$length
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the length as requred by the RouterOS API.
|
||||
*
|
||||
* @param int $length The length to encode.
|
||||
*
|
||||
* @return string The encoded length.
|
||||
*/
|
||||
public static function encodeLength($length)
|
||||
{
|
||||
if ($length < 0) {
|
||||
throw new LengthException(
|
||||
'Length must not be negative.',
|
||||
LengthException::CODE_INVALID,
|
||||
null,
|
||||
$length
|
||||
);
|
||||
} elseif ($length < 0x80) {
|
||||
return chr($length);
|
||||
} elseif ($length < 0x4000) {
|
||||
return pack('n', $length |= 0x8000);
|
||||
} elseif ($length < 0x200000) {
|
||||
$length |= 0xC00000;
|
||||
return pack('n', $length >> 8) . chr($length & 0xFF);
|
||||
} elseif ($length < 0x10000000) {
|
||||
return pack('N', $length |= 0xE0000000);
|
||||
} elseif ($length <= 0xFFFFFFFF) {
|
||||
return chr(0xF0) . pack('N', $length);
|
||||
} elseif ($length <= 0x7FFFFFFFF) {
|
||||
$length = 'f' . base_convert($length, 10, 16);
|
||||
return chr(hexdec(substr($length, 0, 2))) .
|
||||
pack('N', hexdec(substr($length, 2)));
|
||||
}
|
||||
throw new LengthException(
|
||||
'Length must not be above 0x7FFFFFFFF.',
|
||||
LengthException::CODE_BEYOND_SHEME,
|
||||
null,
|
||||
$length
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next word in queue as a string.
|
||||
*
|
||||
* Get the next word in queue as a string, after automatically decoding its
|
||||
* length.
|
||||
*
|
||||
* @return string The word.
|
||||
* @see close()
|
||||
*/
|
||||
public function getNextWord()
|
||||
{
|
||||
if ($this->trans->isPersistent()) {
|
||||
$old = $this->trans->lock(T\Stream::DIRECTION_RECEIVE);
|
||||
$word = $this->trans->receive(
|
||||
self::decodeLength($this->trans),
|
||||
'word'
|
||||
);
|
||||
$this->trans->lock($old, true);
|
||||
} else {
|
||||
$word = $this->trans->receive(
|
||||
self::decodeLength($this->trans),
|
||||
'word'
|
||||
);
|
||||
}
|
||||
|
||||
if (null !== ($remoteCharset = $this->getCharset(self::CHARSET_REMOTE))
|
||||
&& null !== ($localCharset = $this->getCharset(self::CHARSET_LOCAL))
|
||||
) {
|
||||
$word = iconv(
|
||||
$remoteCharset,
|
||||
$localCharset . '//IGNORE//TRANSLIT',
|
||||
$word
|
||||
);
|
||||
}
|
||||
|
||||
return $word;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next word in queue as a stream.
|
||||
*
|
||||
* Get the next word in queue as a stream, after automatically decoding its
|
||||
* length.
|
||||
*
|
||||
* @return resource The word, as a stream.
|
||||
* @see close()
|
||||
*/
|
||||
public function getNextWordAsStream()
|
||||
{
|
||||
$filters = new T\FilterCollection();
|
||||
if (null !== ($remoteCharset = $this->getCharset(self::CHARSET_REMOTE))
|
||||
&& null !== ($localCharset = $this->getCharset(self::CHARSET_LOCAL))
|
||||
) {
|
||||
$filters->append(
|
||||
'convert.iconv.' .
|
||||
$remoteCharset . '.' . $localCharset . '//IGNORE//TRANSLIT'
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->trans->isPersistent()) {
|
||||
$old = $this->trans->lock(T\Stream::DIRECTION_RECEIVE);
|
||||
$stream = $this->trans->receiveStream(
|
||||
self::decodeLength($this->trans),
|
||||
$filters,
|
||||
'stream word'
|
||||
);
|
||||
$this->trans->lock($old, true);
|
||||
} else {
|
||||
$stream = $this->trans->receiveStream(
|
||||
self::decodeLength($this->trans),
|
||||
$filters,
|
||||
'stream word'
|
||||
);
|
||||
}
|
||||
|
||||
return $stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes the lenght of the incoming message.
|
||||
*
|
||||
* Decodes the lenght of the incoming message, as specified by the RouterOS
|
||||
* API.
|
||||
*
|
||||
* @param T\Stream $trans The transmitter from which to decode the length of
|
||||
* the incoming message.
|
||||
*
|
||||
* @return int The decoded length.
|
||||
*/
|
||||
public static function decodeLength(T\Stream $trans)
|
||||
{
|
||||
if ($trans->isPersistent() && $trans instanceof T\TcpClient) {
|
||||
$old = $trans->lock($trans::DIRECTION_RECEIVE);
|
||||
$length = self::_decodeLength($trans);
|
||||
$trans->lock($old, true);
|
||||
return $length;
|
||||
}
|
||||
return self::_decodeLength($trans);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes the lenght of the incoming message.
|
||||
*
|
||||
* Decodes the lenght of the incoming message, as specified by the RouterOS
|
||||
* API.
|
||||
*
|
||||
* Difference with the non private function is that this one doesn't perform
|
||||
* locking if the connection is a persistent one.
|
||||
*
|
||||
* @param T\Stream $trans The transmitter from which to decode the length of
|
||||
* the incoming message.
|
||||
*
|
||||
* @return int The decoded length.
|
||||
*/
|
||||
private static function _decodeLength(T\Stream $trans)
|
||||
{
|
||||
$byte = ord($trans->receive(1, 'initial length byte'));
|
||||
if ($byte & 0x80) {
|
||||
if (($byte & 0xC0) === 0x80) {
|
||||
return (($byte & 077) << 8 ) + ord($trans->receive(1));
|
||||
} elseif (($byte & 0xE0) === 0xC0) {
|
||||
$rem = unpack('n~', $trans->receive(2));
|
||||
return (($byte & 037) << 16 ) + $rem['~'];
|
||||
} elseif (($byte & 0xF0) === 0xE0) {
|
||||
$rem = unpack('n~/C~~', $trans->receive(3));
|
||||
return (($byte & 017) << 24 ) + ($rem['~'] << 8) + $rem['~~'];
|
||||
} elseif (($byte & 0xF8) === 0xF0) {
|
||||
$rem = unpack('N~', $trans->receive(4));
|
||||
return (($byte & 007) * 0x100000000/* '<< 32' or '2^32' */)
|
||||
+ (double) sprintf('%u', $rem['~']);
|
||||
}
|
||||
throw new NotSupportedException(
|
||||
'Unknown control byte encountered.',
|
||||
NotSupportedException::CODE_CONTROL_BYTE,
|
||||
null,
|
||||
$byte
|
||||
);
|
||||
} else {
|
||||
return $byte;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the opened connection, even if it is a persistent one.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
return $this->trans->close();
|
||||
}
|
||||
}
|
44
system/autoload/PEAR2/Net/RouterOS/DataFlowException.php
Normal file
44
system/autoload/PEAR2/Net/RouterOS/DataFlowException.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* RouterOS API client implementation.
|
||||
*
|
||||
* RouterOS is the flag product of the company MikroTik and is a powerful router software. One of its many abilities is to allow control over it via an API. This package provides a client for that API, in turn allowing you to use PHP to control RouterOS hosts.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_RouterOS
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Vasil Rangelov
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0b5
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
*/
|
||||
/**
|
||||
* The namespace declaration.
|
||||
*/
|
||||
namespace PEAR2\Net\RouterOS;
|
||||
|
||||
/**
|
||||
* Base of this class.
|
||||
*/
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* Exception thrown when the request/response cycle goes an unexpected way.
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_RouterOS
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
*/
|
||||
class DataFlowException extends RuntimeException implements Exception
|
||||
{
|
||||
const CODE_INVALID_CREDENTIALS = 10000;
|
||||
const CODE_TAG_REQUIRED = 10500;
|
||||
const CODE_TAG_UNIQUE = 10501;
|
||||
const CODE_UNKNOWN_REQUEST = 10900;
|
||||
const CODE_CANCEL_FAIL = 11200;
|
||||
}
|
34
system/autoload/PEAR2/Net/RouterOS/Exception.php
Normal file
34
system/autoload/PEAR2/Net/RouterOS/Exception.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* RouterOS API client implementation.
|
||||
*
|
||||
* RouterOS is the flag product of the company MikroTik and is a powerful router software. One of its many abilities is to allow control over it via an API. This package provides a client for that API, in turn allowing you to use PHP to control RouterOS hosts.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_RouterOS
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Vasil Rangelov
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0b5
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
*/
|
||||
/**
|
||||
* The namespace declaration.
|
||||
*/
|
||||
namespace PEAR2\Net\RouterOS;
|
||||
|
||||
/**
|
||||
* Generic exception class of this package.
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_RouterOS
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
*/
|
||||
interface Exception
|
||||
{
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* RouterOS API client implementation.
|
||||
*
|
||||
* RouterOS is the flag product of the company MikroTik and is a powerful router software. One of its many abilities is to allow control over it via an API. This package provides a client for that API, in turn allowing you to use PHP to control RouterOS hosts.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_RouterOS
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Vasil Rangelov
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0b5
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
*/
|
||||
/**
|
||||
* The namespace declaration.
|
||||
*/
|
||||
namespace PEAR2\Net\RouterOS;
|
||||
|
||||
use InvalidArgumentException as I;
|
||||
|
||||
/**
|
||||
* Exception thrown when there's something wrong with message arguments.
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_RouterOS
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
*/
|
||||
class InvalidArgumentException extends I implements Exception
|
||||
{
|
||||
const CODE_SEEKABLE_REQUIRED = 1100;
|
||||
const CODE_NAME_INVALID = 20100;
|
||||
const CODE_ABSOLUTE_REQUIRED = 40200;
|
||||
const CODE_CMD_UNRESOLVABLE = 40201;
|
||||
const CODE_CMD_INVALID = 40202;
|
||||
const CODE_NAME_UNPARSABLE = 41000;
|
||||
const CODE_VALUE_UNPARSABLE = 41001;
|
||||
}
|
93
system/autoload/PEAR2/Net/RouterOS/LengthException.php
Normal file
93
system/autoload/PEAR2/Net/RouterOS/LengthException.php
Normal file
@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* RouterOS API client implementation.
|
||||
*
|
||||
* RouterOS is the flag product of the company MikroTik and is a powerful router software. One of its many abilities is to allow control over it via an API. This package provides a client for that API, in turn allowing you to use PHP to control RouterOS hosts.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_RouterOS
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Vasil Rangelov
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0b5
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
*/
|
||||
/**
|
||||
* The namespace declaration.
|
||||
*/
|
||||
namespace PEAR2\Net\RouterOS;
|
||||
|
||||
/**
|
||||
* Base of this class.
|
||||
*/
|
||||
use LengthException as L;
|
||||
|
||||
/**
|
||||
* Exception thrown when there is a problem with a word's length.
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_RouterOS
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
*/
|
||||
class LengthException extends L implements Exception
|
||||
{
|
||||
|
||||
const CODE_UNSUPPORTED = 1200;
|
||||
const CODE_INVALID = 1300;
|
||||
const CODE_BEYOND_SHEME = 1301;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var mixed The problematic length.
|
||||
*/
|
||||
private $_length;
|
||||
|
||||
/**
|
||||
* Creates a new LengthException.
|
||||
*
|
||||
* @param string $message The Exception message to throw.
|
||||
* @param int $code The Exception code.
|
||||
* @param \Exception $previous The previous exception used for the exception
|
||||
* chaining.
|
||||
* @param number $length The length.
|
||||
*/
|
||||
public function __construct(
|
||||
$message,
|
||||
$code = 0,
|
||||
$previous = null,
|
||||
$length = null
|
||||
) {
|
||||
parent::__construct($message, $code, $previous);
|
||||
$this->_length = $length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the length.
|
||||
*
|
||||
* @return number The length.
|
||||
*/
|
||||
public function getLength()
|
||||
{
|
||||
return $this->_length;
|
||||
}
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
// String representation is not reliable in testing
|
||||
|
||||
/**
|
||||
* Returns a string representation of the exception.
|
||||
*
|
||||
* @return string The exception as a string.
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return parent::__toString() . "\nLength:{$this->_length}";
|
||||
}
|
||||
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
237
system/autoload/PEAR2/Net/RouterOS/Message.php
Normal file
237
system/autoload/PEAR2/Net/RouterOS/Message.php
Normal file
@ -0,0 +1,237 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* RouterOS API client implementation.
|
||||
*
|
||||
* RouterOS is the flag product of the company MikroTik and is a powerful router software. One of its many abilities is to allow control over it via an API. This package provides a client for that API, in turn allowing you to use PHP to control RouterOS hosts.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_RouterOS
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Vasil Rangelov
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0b5
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
*/
|
||||
/**
|
||||
* The namespace declaration.
|
||||
*/
|
||||
namespace PEAR2\Net\RouterOS;
|
||||
|
||||
/**
|
||||
* Implements this interface.
|
||||
*/
|
||||
use Countable;
|
||||
|
||||
/**
|
||||
* Implements this interface.
|
||||
*/
|
||||
use IteratorAggregate;
|
||||
|
||||
/**
|
||||
* Requred for IteratorAggregate::getIterator() to work properly with foreach.
|
||||
*/
|
||||
use ArrayObject;
|
||||
|
||||
/**
|
||||
* Represents a RouterOS message.
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_RouterOS
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
*/
|
||||
abstract class Message implements IteratorAggregate, Countable
|
||||
{
|
||||
|
||||
/**
|
||||
* @var array An array with message attributes. Each array key is the the
|
||||
* name of an attribute, and the correspding array value is the value
|
||||
* for that attribute.
|
||||
*/
|
||||
protected $attributes = array();
|
||||
|
||||
/**
|
||||
* @var string An optional tag to associate the message with.
|
||||
*/
|
||||
private $_tag = null;
|
||||
|
||||
/**
|
||||
* A shorthand gateway.
|
||||
*
|
||||
* This is a magic PHP method that allows you to call the object as a
|
||||
* function. Depending on the argument given, one of the other functions in
|
||||
* the class is invoked and its returned value is returned by this function.
|
||||
*
|
||||
* @param string $name The name of an attribute to get the value of, or NULL
|
||||
* to get the tag.
|
||||
*
|
||||
* @return string|resource The value of the specified attribute,
|
||||
* or the tag if NULL is provided.
|
||||
*/
|
||||
public function __invoke($name = null)
|
||||
{
|
||||
if (null === $name) {
|
||||
return $this->getTag();
|
||||
}
|
||||
return $this->getAttribute($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes a name of an attribute (message or query one).
|
||||
*
|
||||
* @param mixed $name The name to sanitize.
|
||||
*
|
||||
* @return string The sanitized name.
|
||||
*/
|
||||
public static function sanitizeAttributeName($name)
|
||||
{
|
||||
$name = (string) $name;
|
||||
if ((empty($name) && $name !== '0')
|
||||
|| preg_match('/[=\s]/s', $name)
|
||||
) {
|
||||
throw new InvalidArgumentException(
|
||||
'Invalid name of argument supplied.',
|
||||
InvalidArgumentException::CODE_NAME_INVALID
|
||||
);
|
||||
}
|
||||
return $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes a value of an attribute (message or query one).
|
||||
*
|
||||
* @param mixed $value The value to sanitize.
|
||||
*
|
||||
* @return string The sanitized value.
|
||||
*/
|
||||
public static function sanitizeAttributeValue($value)
|
||||
{
|
||||
if (Communicator::isSeekableStream($value)) {
|
||||
return $value;
|
||||
} else {
|
||||
return (string) $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the tag that the message is associated with.
|
||||
*
|
||||
* @return string The current tag or NULL if there isn't a tag.
|
||||
* @see setTag()
|
||||
*/
|
||||
public function getTag()
|
||||
{
|
||||
return $this->_tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tag to associate the request with.
|
||||
*
|
||||
* Sets the tag to associate the message with. Setting NULL erases the
|
||||
* currently set tag.
|
||||
*
|
||||
* @param string $tag The tag to set.
|
||||
*
|
||||
* @return $this The message object.
|
||||
* @see getTag()
|
||||
*/
|
||||
protected function setTag($tag)
|
||||
{
|
||||
$this->_tag = (null === $tag) ? null : (string) $tag;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of an attribute.
|
||||
*
|
||||
* @param string $name The name of the attribute.
|
||||
*
|
||||
* @return string|resource|null The value of the specified attribute.
|
||||
* Returns NULL if such an attribute is not set.
|
||||
* @see setAttribute()
|
||||
*/
|
||||
protected function getAttribute($name)
|
||||
{
|
||||
$name = self::sanitizeAttributeName($name);
|
||||
if (array_key_exists($name, $this->attributes)) {
|
||||
return $this->attributes[$name];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all arguments in an array.
|
||||
*
|
||||
* @return ArrayObject An ArrayObject with the keys being argument names,
|
||||
* and the array values being argument values.
|
||||
* @see getArgument()
|
||||
* @see setArgument()
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
return new ArrayObject($this->attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the number of arguments.
|
||||
*
|
||||
* @param int $mode The counter mode.
|
||||
* Either COUNT_NORMAL or COUNT_RECURSIVE.
|
||||
* When in normal mode, counts the number of arguments.
|
||||
* When in recursive mode, counts the number of API words
|
||||
* (including the empty word at the end).
|
||||
*
|
||||
* @return int The number of arguments/words.
|
||||
*/
|
||||
public function count($mode = COUNT_NORMAL)
|
||||
{
|
||||
$result = count($this->attributes);
|
||||
if ($mode !== COUNT_NORMAL) {
|
||||
$result += 2/*first+last word*/
|
||||
+ (int)(null !== $this->getTag());
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an attribute for the message.
|
||||
*
|
||||
* @param string $name Name of the attribute.
|
||||
* @param string|resource|null $value Value of the attribute as a string or
|
||||
* seekable stream.
|
||||
* Setting the value to NULL removes an argument of this name.
|
||||
* If a seekable stream is provided, it is sent from its current
|
||||
* posistion to its end, and the pointer is seeked back to its current
|
||||
* position after sending.
|
||||
* Non seekable streams, as well as all other types, are casted to a
|
||||
* string.
|
||||
*
|
||||
* @return $this The message object.
|
||||
* @see getArgument()
|
||||
*/
|
||||
protected function setAttribute($name, $value = '')
|
||||
{
|
||||
if (null === $value) {
|
||||
unset($this->attributes[self::sanitizeAttributeName($name)]);
|
||||
} else {
|
||||
$this->attributes[self::sanitizeAttributeName($name)]
|
||||
= self::sanitizeAttributeValue($value);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all attributes from the message.
|
||||
*
|
||||
* @return $this The message object.
|
||||
*/
|
||||
protected function removeAllAttributes()
|
||||
{
|
||||
$this->attributes = array();
|
||||
return $this;
|
||||
}
|
||||
}
|
91
system/autoload/PEAR2/Net/RouterOS/NotSupportedException.php
Normal file
91
system/autoload/PEAR2/Net/RouterOS/NotSupportedException.php
Normal file
@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* RouterOS API client implementation.
|
||||
*
|
||||
* RouterOS is the flag product of the company MikroTik and is a powerful router software. One of its many abilities is to allow control over it via an API. This package provides a client for that API, in turn allowing you to use PHP to control RouterOS hosts.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_RouterOS
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Vasil Rangelov
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0b5
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
*/
|
||||
/**
|
||||
* The namespace declaration.
|
||||
*/
|
||||
namespace PEAR2\Net\RouterOS;
|
||||
|
||||
/**
|
||||
* Base of this class.
|
||||
*/
|
||||
use Exception as E;
|
||||
|
||||
/**
|
||||
* Exception thrown when encountering something not supported by RouterOS or
|
||||
* this package.
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_RouterOS
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
*/
|
||||
class NotSupportedException extends E implements Exception
|
||||
{
|
||||
|
||||
const CODE_CONTROL_BYTE = 1601;
|
||||
|
||||
/**
|
||||
* @var mixed The unsuppported value.
|
||||
*/
|
||||
private $_value;
|
||||
|
||||
/**
|
||||
* Creates a new NotSupportedException.
|
||||
*
|
||||
* @param string $message The Exception message to throw.
|
||||
* @param int $code The Exception code.
|
||||
* @param \Exception $previous The previous exception used for the exception
|
||||
* chaining.
|
||||
* @param mixed $value The unsupported value.
|
||||
*/
|
||||
public function __construct(
|
||||
$message,
|
||||
$code = 0,
|
||||
$previous = null,
|
||||
$value = null
|
||||
) {
|
||||
parent::__construct($message, $code, $previous);
|
||||
$this->_value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the unsupported value.
|
||||
*
|
||||
* @return mixed The unsupported value.
|
||||
*/
|
||||
public function getValue()
|
||||
{
|
||||
return $this->_value;
|
||||
}
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
// String representation is not reliable in testing
|
||||
|
||||
/**
|
||||
* Returns a string representation of the exception.
|
||||
*
|
||||
* @return string The exception as a string.
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return parent::__toString() . "\nValue:{$this->_value}";
|
||||
}
|
||||
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
267
system/autoload/PEAR2/Net/RouterOS/Query.php
Normal file
267
system/autoload/PEAR2/Net/RouterOS/Query.php
Normal file
@ -0,0 +1,267 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* RouterOS API client implementation.
|
||||
*
|
||||
* RouterOS is the flag product of the company MikroTik and is a powerful router software. One of its many abilities is to allow control over it via an API. This package provides a client for that API, in turn allowing you to use PHP to control RouterOS hosts.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_RouterOS
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Vasil Rangelov
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0b5
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
*/
|
||||
/**
|
||||
* The namespace declaration.
|
||||
*/
|
||||
namespace PEAR2\Net\RouterOS;
|
||||
|
||||
/**
|
||||
* Refers to transmitter direction constants.
|
||||
*/
|
||||
use PEAR2\Net\Transmitter as T;
|
||||
|
||||
/**
|
||||
* Represents a query for RouterOS requests.
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_RouterOS
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
*/
|
||||
class Query
|
||||
{
|
||||
|
||||
/**
|
||||
* Checks if the property exists.
|
||||
*/
|
||||
const OP_EX = '';
|
||||
|
||||
/**
|
||||
* Checks if the property does not exist.
|
||||
*/
|
||||
const OP_NEX = '-';
|
||||
|
||||
/**
|
||||
* Checks if the property equals a certain value.
|
||||
*/
|
||||
const OP_EQ = '=';
|
||||
|
||||
/**
|
||||
* Checks if the property is less than a certain value.
|
||||
*/
|
||||
const OP_LT = '<';
|
||||
|
||||
/**
|
||||
* Checks if the property is greather than a certain value.
|
||||
*/
|
||||
const OP_GT = '>';
|
||||
|
||||
/**
|
||||
* @var array An array of the words forming the query. Each value is an
|
||||
* array with the first member being the predicate (operator and name),
|
||||
* and the second member being the value for the predicate.
|
||||
*/
|
||||
protected $words = array();
|
||||
|
||||
/**
|
||||
* This class is not to be instantiated normally, but by static methods
|
||||
* instead. Use {@link static::where()} to create an instance of it.
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes the operator of a condition.
|
||||
*
|
||||
* @param string $operator The operator to sanitize.
|
||||
*
|
||||
* @return string The sanitized operator.
|
||||
*/
|
||||
protected static function sanitizeOperator($operator)
|
||||
{
|
||||
$operator = (string) $operator;
|
||||
switch ($operator) {
|
||||
case Query::OP_EX:
|
||||
case Query::OP_NEX:
|
||||
case Query::OP_EQ:
|
||||
case Query::OP_LT:
|
||||
case Query::OP_GT:
|
||||
return $operator;
|
||||
default:
|
||||
throw new UnexpectedValueException(
|
||||
'Unknown operator specified',
|
||||
UnexpectedValueException::CODE_ACTION_UNKNOWN,
|
||||
null,
|
||||
$operator
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new query with an initial condition.
|
||||
*
|
||||
* @param string $name The name of the property to test.
|
||||
* @param string|resource|null $value Value of the property as a string
|
||||
* or seekable stream. Not required for existence tests.
|
||||
* If a seekable stream is provided, it is sent from its current
|
||||
* posistion to its end, and the pointer is seeked back to its current
|
||||
* position after sending.
|
||||
* Non seekable streams, as well as all other types, are casted to a
|
||||
* string.
|
||||
* @param string $operator One of the OP_* constants.
|
||||
* Describes the operation to perform.
|
||||
*
|
||||
* @return static A new query object.
|
||||
*/
|
||||
public static function where(
|
||||
$name,
|
||||
$value = null,
|
||||
$operator = self::OP_EX
|
||||
) {
|
||||
$query = new static;
|
||||
return $query->addWhere($name, $value, $operator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Negates the query.
|
||||
*
|
||||
* @return $this The query object.
|
||||
*/
|
||||
public function not()
|
||||
{
|
||||
$this->words[] = array('#!', null);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a condition as an alternative to the query.
|
||||
*
|
||||
* @param string $name The name of the property to test.
|
||||
* @param string|resource|null $value Value of the property as a string
|
||||
* or seekable stream. Not required for existence tests.
|
||||
* If a seekable stream is provided, it is sent from its current
|
||||
* posistion to its end, and the pointer is seeked back to its current
|
||||
* position after sending.
|
||||
* Non seekable streams, as well as all other types, are casted to a
|
||||
* string.
|
||||
* @param string $operator One of the OP_* constants.
|
||||
* Describes the operation to perform.
|
||||
*
|
||||
* @return $this The query object.
|
||||
*/
|
||||
public function orWhere($name, $value = null, $operator = self::OP_EX)
|
||||
{
|
||||
$this->addWhere($name, $value, $operator)->words[] = array('#|', null);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a condition in addition to the query.
|
||||
*
|
||||
* @param string $name The name of the property to test.
|
||||
* @param string|resource|null $value Value of the property as a string
|
||||
* or seekable stream. Not required for existence tests.
|
||||
* If a seekable stream is provided, it is sent from its current
|
||||
* posistion to its end, and the pointer is seeked back to its current
|
||||
* position after sending.
|
||||
* Non seekable streams, as well as all other types, are casted to a
|
||||
* string.
|
||||
* @param string $operator One of the OP_* constants.
|
||||
* Describes the operation to perform.
|
||||
*
|
||||
* @return $this The query object.
|
||||
*/
|
||||
public function andWhere($name, $value = null, $operator = self::OP_EX)
|
||||
{
|
||||
$this->addWhere($name, $value, $operator)->words[] = array('#&', null);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the query over a communicator.
|
||||
*
|
||||
* @param Communicator $com The communicator to send the query over.
|
||||
*
|
||||
* @return int The number of bytes sent.
|
||||
*/
|
||||
public function send(Communicator $com)
|
||||
{
|
||||
if ($com->getTransmitter()->isPersistent()) {
|
||||
$old = $com->getTransmitter()->lock(T\Stream::DIRECTION_SEND);
|
||||
$bytes = $this->_send($com);
|
||||
$com->getTransmitter()->lock($old, true);
|
||||
return $bytes;
|
||||
}
|
||||
return $this->_send($com);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the query over a communicator.
|
||||
*
|
||||
* The only difference with the non private equivalent is that this one does
|
||||
* not do locking.
|
||||
*
|
||||
* @param Communicator $com The communicator to send the query over.
|
||||
*
|
||||
* @return int The number of bytes sent.
|
||||
*/
|
||||
private function _send(Communicator $com)
|
||||
{
|
||||
if (!$com->getTransmitter()->isAcceptingData()) {
|
||||
throw new SocketException(
|
||||
'Transmitter is invalid. Sending aborted.',
|
||||
SocketException::CODE_QUERY_SEND_FAIL
|
||||
);
|
||||
}
|
||||
$bytes = 0;
|
||||
foreach ($this->words as $queryWord) {
|
||||
list($predicate, $value) = $queryWord;
|
||||
$prefix = '?' . $predicate;
|
||||
if (null === $value) {
|
||||
$bytes += $com->sendWord($prefix);
|
||||
} else {
|
||||
$prefix .= '=';
|
||||
if (is_string($value)) {
|
||||
$bytes += $com->sendWord($prefix . $value);
|
||||
} else {
|
||||
$bytes += $com->sendWordFromStream($prefix, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a condition.
|
||||
*
|
||||
* @param string $name The name of the property to test.
|
||||
* @param string|resource|null $value Value of the property as a string
|
||||
* or seekable stream. Not required for existence tests.
|
||||
* If a seekable stream is provided, it is sent from its current
|
||||
* posistion to its end, and the pointer is seeked back to its current
|
||||
* position after sending.
|
||||
* Non seekable streams, as well as all other types, are casted to a
|
||||
* string.
|
||||
* @param string $operator One of the ACTION_* constants.
|
||||
* Describes the operation to perform.
|
||||
*
|
||||
* @return $this The query object.
|
||||
*/
|
||||
protected function addWhere($name, $value, $operator)
|
||||
{
|
||||
$this->words[] = array(
|
||||
static::sanitizeOperator($operator)
|
||||
. Message::sanitizeAttributeName($name),
|
||||
(null === $value ? null : Message::sanitizeAttributeValue($value))
|
||||
);
|
||||
return $this;
|
||||
}
|
||||
}
|
279
system/autoload/PEAR2/Net/RouterOS/Registry.php
Normal file
279
system/autoload/PEAR2/Net/RouterOS/Registry.php
Normal file
@ -0,0 +1,279 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* RouterOS API client implementation.
|
||||
*
|
||||
* RouterOS is the flag product of the company MikroTik and is a powerful router software. One of its many abilities is to allow control over it via an API. This package provides a client for that API, in turn allowing you to use PHP to control RouterOS hosts.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_RouterOS
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Vasil Rangelov
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0b5
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
*/
|
||||
/**
|
||||
* The namespace declaration.
|
||||
*/
|
||||
namespace PEAR2\Net\RouterOS;
|
||||
|
||||
/**
|
||||
* Uses shared memory to keep responses in.
|
||||
*/
|
||||
use PEAR2\Cache\SHM;
|
||||
|
||||
/**
|
||||
* A RouterOS registry.
|
||||
*
|
||||
* Provides functionality for managing the request/response flow. Particularly
|
||||
* useful in persistent connections.
|
||||
*
|
||||
* Note that this class is not meant to be called directly.
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_RouterOS
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
*/
|
||||
class Registry
|
||||
{
|
||||
/**
|
||||
* @var SHM The storage.
|
||||
*/
|
||||
protected $shm;
|
||||
|
||||
/**
|
||||
* @var int ID of request. Populated at first instance in request.
|
||||
*/
|
||||
protected static $requestId = -1;
|
||||
|
||||
/**
|
||||
* @var int ID to be given to next instance, after incrementing it.
|
||||
*/
|
||||
protected static $instanceIdSeed = -1;
|
||||
|
||||
/**
|
||||
* @var int ID of instance within the request.
|
||||
*/
|
||||
protected $instanceId;
|
||||
|
||||
/**
|
||||
* Creates a registry.
|
||||
*
|
||||
* @param string $uri An URI to bind the registry to.
|
||||
*/
|
||||
public function __construct($uri)
|
||||
{
|
||||
$this->shm = SHM::factory(__CLASS__ . ' ' . $uri);
|
||||
if (-1 === self::$requestId) {
|
||||
self::$requestId = $this->shm->add('requestId', 0)
|
||||
? 0 : $this->shm->inc('requestId');
|
||||
}
|
||||
$this->instanceId = ++self::$instanceIdSeed;
|
||||
$this->shm->add('responseBuffer_' . $this->getOwnershipTag(), array());
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a tag.
|
||||
*
|
||||
* Parses a tag to reveal the ownership part of it, and the original tag.
|
||||
*
|
||||
* @param string $tag The tag (as received) to parse.
|
||||
*
|
||||
* @return array An array with the first member being the ownership tag, and
|
||||
* the second one being the original tag.
|
||||
*/
|
||||
public static function parseTag($tag)
|
||||
{
|
||||
if (null === $tag) {
|
||||
return array(null, null);
|
||||
}
|
||||
$result = explode('__', $tag, 2);
|
||||
$result[0] .= '__';
|
||||
if ('' === $result[1]) {
|
||||
$result[1] = null;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this instance is the tagless mode owner.
|
||||
*
|
||||
* @return bool TRUE if this instance is the tagless mode owner, FALSE
|
||||
* otherwise.
|
||||
*/
|
||||
public function isTaglessModeOwner()
|
||||
{
|
||||
$this->shm->lock('taglessModeOwner');
|
||||
$result = $this->shm->exists('taglessModeOwner')
|
||||
&& $this->getOwnershipTag() === $this->shm->get('taglessModeOwner');
|
||||
$this->shm->unlock('taglessModeOwner');
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the "tagless mode" setting.
|
||||
*
|
||||
* While in tagless mode, this instance will claim owhership of any
|
||||
* responses without a tag. While not in this mode, any requests without a
|
||||
* tag will be given to all instances.
|
||||
*
|
||||
* Regardless of mode, if the type of the response is
|
||||
* {@link Response::TYPE_FATAL}, it will be given to all instances.
|
||||
*
|
||||
* @param bool $taglessMode TRUE to claim tagless ownership, FALSE to
|
||||
* release such ownership, if taken.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function setTaglessMode($taglessMode)
|
||||
{
|
||||
return $taglessMode
|
||||
? ($this->shm->lock('taglessMode')
|
||||
&& $this->shm->lock('taglessModeOwner')
|
||||
&& $this->shm->add('taglessModeOwner', $this->getOwnershipTag())
|
||||
&& $this->shm->unlock('taglessModeOwner'))
|
||||
: ($this->isTaglessModeOwner()
|
||||
&& $this->shm->lock('taglessModeOwner')
|
||||
&& $this->shm->delete('taglessModeOwner')
|
||||
&& $this->shm->unlock('taglessModeOwner')
|
||||
&& $this->shm->unlock('taglessMode'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ownership tag for this instance.
|
||||
*
|
||||
* @return string The ownership tag for this registry instance.
|
||||
*/
|
||||
public function getOwnershipTag()
|
||||
{
|
||||
return self::$requestId . '_' . $this->instanceId . '__';
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a response to the registry.
|
||||
*
|
||||
* @param Response $response The response to add. The caller of this
|
||||
* function is responsible for ensuring that the ownership tag and the
|
||||
* original tag are separated, so that only the original one remains in
|
||||
* the response.
|
||||
* @param string $ownershipTag The ownership tag that the response had.
|
||||
*
|
||||
* @return bool TRUE if the request was added to its buffer, FALSE if
|
||||
* this instance owns the response, and therefore doesn't need to add
|
||||
* the response to its buffer.
|
||||
*/
|
||||
public function add(Response $response, $ownershipTag)
|
||||
{
|
||||
if ($this->getOwnershipTag() === $ownershipTag
|
||||
|| ($this->isTaglessModeOwner()
|
||||
&& $response->getType() !== Response::TYPE_FATAL)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (null === $ownershipTag) {
|
||||
$this->shm->lock('taglessModeOwner');
|
||||
if ($this->shm->exists('taglessModeOwner')
|
||||
&& $response->getType() !== Response::TYPE_FATAL
|
||||
) {
|
||||
$ownershipTag = $this->shm->get('taglessModeOwner');
|
||||
$this->shm->unlock('taglessModeOwner');
|
||||
} else {
|
||||
$this->shm->unlock('taglessModeOwner');
|
||||
foreach ($this->shm->getIterator(
|
||||
'/^(responseBuffer\_)/',
|
||||
true
|
||||
) as $targetBufferName) {
|
||||
$this->_add($response, $targetBufferName);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
$this->_add($response, 'responseBuffer_' . $ownershipTag);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a response to a buffer.
|
||||
*
|
||||
* @param Response $response The response to add.
|
||||
* @param string $targetBufferName The name of the buffer to add the
|
||||
* response to.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function _add(Response $response, $targetBufferName)
|
||||
{
|
||||
if ($this->shm->lock($targetBufferName)) {
|
||||
$targetBuffer = $this->shm->get($targetBufferName);
|
||||
$targetBuffer[] = $response;
|
||||
$this->shm->set($targetBufferName, $targetBuffer);
|
||||
$this->shm->unlock($targetBufferName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next response from this instance's buffer.
|
||||
*
|
||||
* @return Response|null The next response, or NULL if there isn't one.
|
||||
*/
|
||||
public function getNextResponse()
|
||||
{
|
||||
$response = null;
|
||||
$targetBufferName = 'responseBuffer_' . $this->getOwnershipTag();
|
||||
if ($this->shm->exists($targetBufferName)
|
||||
&& $this->shm->lock($targetBufferName)
|
||||
) {
|
||||
$targetBuffer = $this->shm->get($targetBufferName);
|
||||
if (!empty($targetBuffer)) {
|
||||
$response = array_shift($targetBuffer);
|
||||
$this->shm->set($targetBufferName, $targetBuffer);
|
||||
}
|
||||
$this->shm->unlock($targetBufferName);
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the registry.
|
||||
*
|
||||
* Closes the registry, meaning that all buffers are cleared.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
self::$requestId = -1;
|
||||
self::$instanceIdSeed = -1;
|
||||
$this->shm->clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a buffer.
|
||||
*
|
||||
* @param string $targetBufferName The buffer to remove.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function _close($targetBufferName)
|
||||
{
|
||||
if ($this->shm->lock($targetBufferName)) {
|
||||
$this->shm->delete($targetBufferName);
|
||||
$this->shm->unlock($targetBufferName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes this instance's buffer.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
$this->_close('responseBuffer_' . $this->getOwnershipTag());
|
||||
}
|
||||
}
|
403
system/autoload/PEAR2/Net/RouterOS/Request.php
Normal file
403
system/autoload/PEAR2/Net/RouterOS/Request.php
Normal file
@ -0,0 +1,403 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* RouterOS API client implementation.
|
||||
*
|
||||
* RouterOS is the flag product of the company MikroTik and is a powerful router software. One of its many abilities is to allow control over it via an API. This package provides a client for that API, in turn allowing you to use PHP to control RouterOS hosts.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_RouterOS
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Vasil Rangelov
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0b5
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
*/
|
||||
/**
|
||||
* The namespace declaration.
|
||||
*/
|
||||
namespace PEAR2\Net\RouterOS;
|
||||
|
||||
/**
|
||||
* Refers to transmitter direction constants.
|
||||
*/
|
||||
use PEAR2\Net\Transmitter as T;
|
||||
|
||||
/**
|
||||
* Represents a RouterOS request.
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_RouterOS
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
*/
|
||||
class Request extends Message
|
||||
{
|
||||
|
||||
/**
|
||||
* @var string The command to be executed.
|
||||
*/
|
||||
private $_command;
|
||||
|
||||
/**
|
||||
* @var Query A query for the command.
|
||||
*/
|
||||
private $_query;
|
||||
|
||||
/**
|
||||
* Creates a request to send to RouterOS.
|
||||
*
|
||||
* @param string $command The command to send. Can also contain arguments
|
||||
* expressed in a shell-like syntax.
|
||||
* @param Query $query A query to associate with the request.
|
||||
* @param string $tag The tag for the request.
|
||||
*
|
||||
* @see setCommand()
|
||||
* @see setArgument()
|
||||
* @see setTag()
|
||||
* @see setQuery()
|
||||
*/
|
||||
public function __construct($command, Query $query = null, $tag = null)
|
||||
{
|
||||
if (false !== strpos($command, '=')
|
||||
&& false !== ($spaceBeforeEquals = strrpos(
|
||||
strstr($command, '=', true),
|
||||
' '
|
||||
))
|
||||
) {
|
||||
$this->parseArgumentString(substr($command, $spaceBeforeEquals));
|
||||
$command = rtrim(substr($command, 0, $spaceBeforeEquals));
|
||||
}
|
||||
$this->setCommand($command);
|
||||
$this->setQuery($query);
|
||||
$this->setTag($tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* A shorthand gateway.
|
||||
*
|
||||
* This is a magic PHP method that allows you to call the object as a
|
||||
* function. Depending on the argument given, one of the other functions in
|
||||
* the class is invoked and its returned value is returned by this function.
|
||||
*
|
||||
* @param Query|Communicator|string|null $arg A {@link Query} to associate
|
||||
* the request with, a {@link Communicator} to send the request over,
|
||||
* an argument to get the value of, or NULL to get the tag. If a
|
||||
* second argument is provided, this becomes the name of the argument to
|
||||
* set the value of, and the second argument is the value to set.
|
||||
*
|
||||
* @return string|resource|int|$this Whatever the long form
|
||||
* function returns.
|
||||
*/
|
||||
public function __invoke($arg = null)
|
||||
{
|
||||
if (func_num_args() > 1) {
|
||||
return $this->setArgument(func_get_arg(0), func_get_arg(1));
|
||||
}
|
||||
if ($arg instanceof Query) {
|
||||
return $this->setQuery($arg);
|
||||
}
|
||||
if ($arg instanceof Communicator) {
|
||||
return $this->send($arg);
|
||||
}
|
||||
return parent::__invoke($arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the command to send to RouterOS.
|
||||
*
|
||||
* Sets the command to send to RouterOS. The command can use the API or CLI
|
||||
* syntax of RouterOS, but either way, it must be absolute (begin with a
|
||||
* "/") and without arguments.
|
||||
*
|
||||
* @param string $command The command to send.
|
||||
*
|
||||
* @return $this The request object.
|
||||
* @see getCommand()
|
||||
* @see setArgument()
|
||||
*/
|
||||
public function setCommand($command)
|
||||
{
|
||||
$command = (string) $command;
|
||||
if (strpos($command, '/') !== 0) {
|
||||
throw new InvalidArgumentException(
|
||||
'Commands must be absolute.',
|
||||
InvalidArgumentException::CODE_ABSOLUTE_REQUIRED
|
||||
);
|
||||
}
|
||||
if (substr_count($command, '/') === 1) {
|
||||
//Command line syntax convertion
|
||||
$cmdParts = preg_split('#[\s/]+#sm', $command);
|
||||
$cmdRes = array($cmdParts[0]);
|
||||
for ($i = 1, $n = count($cmdParts); $i < $n; $i++) {
|
||||
if ('..' === $cmdParts[$i]) {
|
||||
$delIndex = count($cmdRes) - 1;
|
||||
if ($delIndex < 1) {
|
||||
throw new InvalidArgumentException(
|
||||
'Unable to resolve command',
|
||||
InvalidArgumentException::CODE_CMD_UNRESOLVABLE
|
||||
);
|
||||
}
|
||||
unset($cmdRes[$delIndex]);
|
||||
$cmdRes = array_values($cmdRes);
|
||||
} else {
|
||||
$cmdRes[] = $cmdParts[$i];
|
||||
}
|
||||
}
|
||||
$command = implode('/', $cmdRes);
|
||||
}
|
||||
if (!preg_match('#^/\S+$#sm', $command)) {
|
||||
throw new InvalidArgumentException(
|
||||
'Invalid command supplied.',
|
||||
InvalidArgumentException::CODE_CMD_INVALID
|
||||
);
|
||||
}
|
||||
$this->_command = $command;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the command that will be send to RouterOS.
|
||||
*
|
||||
* Gets the command that will be send to RouterOS in its API syntax.
|
||||
*
|
||||
* @return string The command to send.
|
||||
* @see setCommand()
|
||||
*/
|
||||
public function getCommand()
|
||||
{
|
||||
return $this->_command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the query to send with the command.
|
||||
*
|
||||
* @param Query $query The query to be set. Setting NULL will remove the
|
||||
* currently associated query.
|
||||
*
|
||||
* @return $this The request object.
|
||||
* @see getQuery()
|
||||
*/
|
||||
public function setQuery(Query $query = null)
|
||||
{
|
||||
$this->_query = $query;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the currently associated query
|
||||
*
|
||||
* @return Query The currently associated query.
|
||||
* @see setQuery()
|
||||
*/
|
||||
public function getQuery()
|
||||
{
|
||||
return $this->_query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tag to associate the request with.
|
||||
*
|
||||
* Sets the tag to associate the request with. Setting NULL erases the
|
||||
* currently set tag.
|
||||
*
|
||||
* @param string $tag The tag to set.
|
||||
*
|
||||
* @return $this The request object.
|
||||
* @see getTag()
|
||||
*/
|
||||
public function setTag($tag)
|
||||
{
|
||||
return parent::setTag($tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an argument for the request.
|
||||
*
|
||||
* @param string $name Name of the argument.
|
||||
* @param string|resource|null $value Value of the argument as a string or
|
||||
* seekable stream.
|
||||
* Setting the value to NULL removes an argument of this name.
|
||||
* If a seekable stream is provided, it is sent from its current
|
||||
* posistion to its end, and the pointer is seeked back to its current
|
||||
* position after sending.
|
||||
* Non seekable streams, as well as all other types, are casted to a
|
||||
* string.
|
||||
*
|
||||
* @return $this The request object.
|
||||
* @see getArgument()
|
||||
*/
|
||||
public function setArgument($name, $value = '')
|
||||
{
|
||||
return parent::setAttribute($name, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of an argument.
|
||||
*
|
||||
* @param string $name The name of the argument.
|
||||
*
|
||||
* @return string|resource|null The value of the specified argument.
|
||||
* Returns NULL if such an argument is not set.
|
||||
* @see setAttribute()
|
||||
*/
|
||||
public function getArgument($name)
|
||||
{
|
||||
return parent::getAttribute($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all arguments from the request.
|
||||
*
|
||||
* @return $this The request object.
|
||||
*/
|
||||
public function removeAllArguments()
|
||||
{
|
||||
return parent::removeAllAttributes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a request over a communicator.
|
||||
*
|
||||
* @param Communicator $com The communicator to send the request over.
|
||||
* @param Registry $reg An optional registry to sync the request with.
|
||||
*
|
||||
* @return int The number of bytes sent.
|
||||
* @see Client::sendSync()
|
||||
* @see Client::sendAsync()
|
||||
*/
|
||||
public function send(Communicator $com, Registry $reg = null)
|
||||
{
|
||||
if (null !== $reg
|
||||
&& (null != $this->getTag() || !$reg->isTaglessModeOwner())
|
||||
) {
|
||||
$originalTag = $this->getTag();
|
||||
$this->setTag($reg->getOwnershipTag() . $originalTag);
|
||||
$bytes = $this->send($com);
|
||||
$this->setTag($originalTag);
|
||||
return $bytes;
|
||||
}
|
||||
if ($com->getTransmitter()->isPersistent()) {
|
||||
$old = $com->getTransmitter()->lock(T\Stream::DIRECTION_SEND);
|
||||
$bytes = $this->_send($com);
|
||||
$com->getTransmitter()->lock($old, true);
|
||||
return $bytes;
|
||||
}
|
||||
return $this->_send($com);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a request over a communicator.
|
||||
*
|
||||
* The only difference with the non private equivalent is that this one does
|
||||
* not do locking.
|
||||
*
|
||||
* @param Communicator $com The communicator to send the request over.
|
||||
*
|
||||
* @return int The number of bytes sent.
|
||||
* @see Client::sendSync()
|
||||
* @see Client::sendAsync()
|
||||
*/
|
||||
private function _send(Communicator $com)
|
||||
{
|
||||
if (!$com->getTransmitter()->isAcceptingData()) {
|
||||
throw new SocketException(
|
||||
'Transmitter is invalid. Sending aborted.',
|
||||
SocketException::CODE_REQUEST_SEND_FAIL
|
||||
);
|
||||
}
|
||||
$bytes = 0;
|
||||
$bytes += $com->sendWord($this->getCommand());
|
||||
if (null !== ($tag = $this->getTag())) {
|
||||
$bytes += $com->sendWord('.tag=' . $tag);
|
||||
}
|
||||
foreach ($this->attributes as $name => $value) {
|
||||
$prefix = '=' . $name . '=';
|
||||
if (is_string($value)) {
|
||||
$bytes += $com->sendWord($prefix . $value);
|
||||
} else {
|
||||
$bytes += $com->sendWordFromStream($prefix, $value);
|
||||
}
|
||||
}
|
||||
$query = $this->getQuery();
|
||||
if ($query instanceof Query) {
|
||||
$bytes += $query->send($com);
|
||||
}
|
||||
$bytes += $com->sendWord('');
|
||||
return $bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the arguments of a command.
|
||||
*
|
||||
* @param string $string The argument string to parse.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function parseArgumentString($string)
|
||||
{
|
||||
/*
|
||||
* Grammar:
|
||||
*
|
||||
* <arguments> := (<<\s+>>, <argument>)*,
|
||||
* <argument> := <name>, <value>?
|
||||
* <name> := <<[^\=\s]+>>
|
||||
* <value> := "=", (<quoted string> | <unquoted string>)
|
||||
* <quotedString> := <<">>, <<([^"]|\\"|\\\\)*>>, <<">>
|
||||
* <unquotedString> := <<\S+>>
|
||||
*/
|
||||
|
||||
$token = '';
|
||||
$name = null;
|
||||
while ($string = substr($string, strlen($token))) {
|
||||
if (null === $name) {
|
||||
if (preg_match('/^\s+([^\s=]+)/sS', $string, $matches)) {
|
||||
$token = $matches[0];
|
||||
$name = $matches[1];
|
||||
} else {
|
||||
throw new InvalidArgumentException(
|
||||
"Parsing of argument name failed near '{$string}'",
|
||||
InvalidArgumentException::CODE_NAME_UNPARSABLE
|
||||
);
|
||||
}
|
||||
} elseif (preg_match('/^\s/s', $string, $matches)) {
|
||||
//Empty argument
|
||||
$token = '';
|
||||
$this->setArgument($name);
|
||||
$name = null;
|
||||
} elseif (preg_match(
|
||||
'/^="(([^\\\"]|\\\"|\\\\)*)"/sS',
|
||||
$string,
|
||||
$matches
|
||||
)) {
|
||||
$token = $matches[0];
|
||||
$this->setArgument(
|
||||
$name,
|
||||
str_replace(
|
||||
array('\\"', '\\\\'),
|
||||
array('"', '\\'),
|
||||
$matches[1]
|
||||
)
|
||||
);
|
||||
$name = null;
|
||||
} elseif (preg_match('/^=(\S+)/sS', $string, $matches)) {
|
||||
$token = $matches[0];
|
||||
$this->setArgument($name, $matches[1]);
|
||||
$name = null;
|
||||
} else {
|
||||
throw new InvalidArgumentException(
|
||||
"Parsing of argument value failed near '{$string}'",
|
||||
InvalidArgumentException::CODE_VALUE_UNPARSABLE
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (null !== $name && ('' !== ($name = trim($name)))) {
|
||||
$this->setArgument($name, '');
|
||||
}
|
||||
|
||||
}
|
||||
}
|
335
system/autoload/PEAR2/Net/RouterOS/Response.php
Normal file
335
system/autoload/PEAR2/Net/RouterOS/Response.php
Normal file
@ -0,0 +1,335 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* RouterOS API client implementation.
|
||||
*
|
||||
* RouterOS is the flag product of the company MikroTik and is a powerful router software. One of its many abilities is to allow control over it via an API. This package provides a client for that API, in turn allowing you to use PHP to control RouterOS hosts.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_RouterOS
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Vasil Rangelov
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0b5
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
*/
|
||||
/**
|
||||
* The namespace declaration.
|
||||
*/
|
||||
namespace PEAR2\Net\RouterOS;
|
||||
|
||||
/**
|
||||
* Refers to transmitter direction constants.
|
||||
*/
|
||||
use PEAR2\Net\Transmitter as T;
|
||||
|
||||
/**
|
||||
* Locks are released upon any exception from anywhere.
|
||||
*/
|
||||
use Exception as E;
|
||||
|
||||
/**
|
||||
* Represents a RouterOS response.
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_RouterOS
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
*/
|
||||
class Response extends Message
|
||||
{
|
||||
|
||||
/**
|
||||
* The last response for a request.
|
||||
*/
|
||||
const TYPE_FINAL = '!done';
|
||||
|
||||
/**
|
||||
* A response with data.
|
||||
*/
|
||||
const TYPE_DATA = '!re';
|
||||
|
||||
/**
|
||||
* A response signifying error.
|
||||
*/
|
||||
const TYPE_ERROR = '!trap';
|
||||
|
||||
/**
|
||||
* A response signifying a fatal error, due to which the connection would be
|
||||
* terminated.
|
||||
*/
|
||||
const TYPE_FATAL = '!fatal';
|
||||
|
||||
/**
|
||||
* @var array An array of unrecognized words in network order.
|
||||
*/
|
||||
protected $unrecognizedWords = array();
|
||||
|
||||
/**
|
||||
* @var string The response type.
|
||||
*/
|
||||
private $_type;
|
||||
|
||||
/**
|
||||
* Extracts a new response from a communicator.
|
||||
*
|
||||
* @param Communicator $com The communicator from which to extract
|
||||
* the new response.
|
||||
* @param bool $asStream Whether to populate the argument values
|
||||
* with streams instead of strings.
|
||||
* @param int $sTimeout If a response is not immediatly
|
||||
* available, wait this many seconds. If NULL, wait indefinetly.
|
||||
* @param int $usTimeout Microseconds to add to the waiting time.
|
||||
* @param Registry $reg An optional registry to sync the
|
||||
* response with.
|
||||
*
|
||||
* @see getType()
|
||||
* @see getArgument()
|
||||
*/
|
||||
public function __construct(
|
||||
Communicator $com,
|
||||
$asStream = false,
|
||||
$sTimeout = 0,
|
||||
$usTimeout = null,
|
||||
Registry $reg = null
|
||||
) {
|
||||
if (null === $reg) {
|
||||
if ($com->getTransmitter()->isPersistent()) {
|
||||
$old = $com->getTransmitter()
|
||||
->lock(T\Stream::DIRECTION_RECEIVE);
|
||||
try {
|
||||
$this->_receive($com, $asStream, $sTimeout, $usTimeout);
|
||||
} catch (E $e) {
|
||||
$com->getTransmitter()->lock($old, true);
|
||||
throw $e;
|
||||
}
|
||||
$com->getTransmitter()->lock($old, true);
|
||||
} else {
|
||||
$this->_receive($com, $asStream, $sTimeout, $usTimeout);
|
||||
}
|
||||
} else {
|
||||
while (null === ($response = $reg->getNextResponse())) {
|
||||
$newResponse = new self($com, true, $sTimeout, $usTimeout);
|
||||
$tagInfo = $reg::parseTag($newResponse->getTag());
|
||||
$newResponse->setTag($tagInfo[1]);
|
||||
if (!$reg->add($newResponse, $tagInfo[0])) {
|
||||
$response = $newResponse;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->_type = $response->_type;
|
||||
$this->attributes = $response->attributes;
|
||||
$this->unrecognizedWords = $response->unrecognizedWords;
|
||||
$this->setTag($response->getTag());
|
||||
|
||||
if (!$asStream) {
|
||||
foreach ($this->attributes as $name => $value) {
|
||||
$this->setAttribute(
|
||||
$name,
|
||||
stream_get_contents($value)
|
||||
);
|
||||
}
|
||||
foreach ($response->unrecognizedWords as $i => $value) {
|
||||
$this->unrecognizedWords[$i] = stream_get_contents($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts a new response from a communicator.
|
||||
*
|
||||
* This is the function that performs the actual receiving, while the
|
||||
* constructor is also involved in locks and registry sync.
|
||||
*
|
||||
* @param Communicator $com The communicator from which to extract
|
||||
* the new response.
|
||||
* @param bool $asStream Whether to populate the argument values
|
||||
* with streams instead of strings.
|
||||
* @param int $sTimeout If a response is not immediatly
|
||||
* available, wait this many seconds. If NULL, wait indefinetly.
|
||||
* Note that if an empty sentence is received, the timeout will be
|
||||
* reset for another sentence receiving.
|
||||
* @param int $usTimeout Microseconds to add to the waiting time.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function _receive(
|
||||
Communicator $com,
|
||||
$asStream = false,
|
||||
$sTimeout = 0,
|
||||
$usTimeout = null
|
||||
) {
|
||||
do {
|
||||
if (!$com->getTransmitter()->isDataAwaiting(
|
||||
$sTimeout,
|
||||
$usTimeout
|
||||
)) {
|
||||
throw new SocketException(
|
||||
'No data within the time limit',
|
||||
SocketException::CODE_NO_DATA
|
||||
);
|
||||
}
|
||||
$type = $com->getNextWord();
|
||||
} while ('' === $type);
|
||||
$this->setType($type);
|
||||
if ($asStream) {
|
||||
for ($word = $com->getNextWordAsStream(), fseek($word, 0, SEEK_END);
|
||||
ftell($word) !== 0;
|
||||
$word = $com->getNextWordAsStream(), fseek(
|
||||
$word,
|
||||
0,
|
||||
SEEK_END
|
||||
)) {
|
||||
rewind($word);
|
||||
$ind = fread($word, 1);
|
||||
if ('=' === $ind || '.' === $ind) {
|
||||
$prefix = stream_get_line($word, null, '=');
|
||||
}
|
||||
if ('=' === $ind) {
|
||||
$value = fopen('php://temp', 'r+b');
|
||||
$bytesCopied = ftell($word);
|
||||
while (!feof($word)) {
|
||||
$bytesCopied += stream_copy_to_stream(
|
||||
$word,
|
||||
$value,
|
||||
0xFFFFF,
|
||||
$bytesCopied
|
||||
);
|
||||
}
|
||||
rewind($value);
|
||||
$this->setAttribute($prefix, $value);
|
||||
continue;
|
||||
}
|
||||
if ('.' === $ind && 'tag' === $prefix) {
|
||||
$this->setTag(stream_get_contents($word, -1, -1));
|
||||
continue;
|
||||
}
|
||||
rewind($word);
|
||||
$this->unrecognizedWords[] = $word;
|
||||
}
|
||||
} else {
|
||||
for ($word = $com->getNextWord(); '' !== $word;
|
||||
$word = $com->getNextWord()) {
|
||||
if (preg_match('/^=([^=]+)=(.*)$/sS', $word, $matches)) {
|
||||
$this->setAttribute($matches[1], $matches[2]);
|
||||
} elseif (preg_match('/^\.tag=(.*)$/sS', $word, $matches)) {
|
||||
$this->setTag($matches[1]);
|
||||
} else {
|
||||
$this->unrecognizedWords[] = $word;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the response type.
|
||||
*
|
||||
* Sets the response type. Valid values are the TYPE_* constants.
|
||||
*
|
||||
* @param string $type The new response type.
|
||||
*
|
||||
* @return $this The response object.
|
||||
* @see getType()
|
||||
*/
|
||||
protected function setType($type)
|
||||
{
|
||||
switch ($type) {
|
||||
case self::TYPE_FINAL:
|
||||
case self::TYPE_DATA:
|
||||
case self::TYPE_ERROR:
|
||||
case self::TYPE_FATAL:
|
||||
$this->_type = $type;
|
||||
return $this;
|
||||
default:
|
||||
throw new UnexpectedValueException(
|
||||
'Unrecognized response type.',
|
||||
UnexpectedValueException::CODE_RESPONSE_TYPE_UNKNOWN,
|
||||
null,
|
||||
$type
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the response type.
|
||||
*
|
||||
* @return string The response type.
|
||||
* @see setType()
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
return $this->_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of an argument.
|
||||
*
|
||||
* @param string $name The name of the argument.
|
||||
*
|
||||
* @return string|resource|null The value of the specified argument.
|
||||
* Returns NULL if such an argument is not set.
|
||||
* @deprecated 1.0.0b5 Use {@link static::getProperty()} instead.
|
||||
* This method will be removed upon final release, and is currently
|
||||
* left standing merely because it can't be easily search&replaced in
|
||||
* existing code, due to the fact the name "getArgument()" is shared
|
||||
* with {@link Request::getArgument()}, which is still valid.
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function getArgument($name)
|
||||
{
|
||||
trigger_error(
|
||||
'Response::getArgument() is deprecated in favor of ' .
|
||||
'Response::getProperty() (but note that Request::getArgument() ' .
|
||||
'is still valid)',
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
return $this->getAttribute($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of a property.
|
||||
*
|
||||
* @param string $name The name of the property.
|
||||
*
|
||||
* @return string|resource|null The value of the specified property.
|
||||
* Returns NULL if such a property is not set.
|
||||
*/
|
||||
public function getProperty($name)
|
||||
{
|
||||
return parent::getAttribute($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of unrecognized words.
|
||||
*
|
||||
* @return array The list of unrecognized words.
|
||||
*/
|
||||
public function getUnrecognizedWords()
|
||||
{
|
||||
return $this->unrecognizedWords;
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the number of arguments or words.
|
||||
*
|
||||
* @param int $mode The counter mode.
|
||||
* Either COUNT_NORMAL or COUNT_RECURSIVE.
|
||||
* When in normal mode, counts the number of arguments.
|
||||
* When in recursive mode, counts the number of API words.
|
||||
*
|
||||
* @return int The number of arguments/words.
|
||||
*/
|
||||
public function count($mode = COUNT_NORMAL)
|
||||
{
|
||||
$result = parent::count($mode);
|
||||
if ($mode !== COUNT_NORMAL) {
|
||||
$result += count($this->unrecognizedWords);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
569
system/autoload/PEAR2/Net/RouterOS/ResponseCollection.php
Normal file
569
system/autoload/PEAR2/Net/RouterOS/ResponseCollection.php
Normal file
@ -0,0 +1,569 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* RouterOS API client implementation.
|
||||
*
|
||||
* RouterOS is the flag product of the company MikroTik and is a powerful router software. One of its many abilities is to allow control over it via an API. This package provides a client for that API, in turn allowing you to use PHP to control RouterOS hosts.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_RouterOS
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Vasil Rangelov
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0b5
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
*/
|
||||
/**
|
||||
* The namespace declaration.
|
||||
*/
|
||||
namespace PEAR2\Net\RouterOS;
|
||||
|
||||
/**
|
||||
* Implemented by this class.
|
||||
*/
|
||||
use ArrayAccess;
|
||||
|
||||
/**
|
||||
* Implemented by this class.
|
||||
*/
|
||||
use Countable;
|
||||
|
||||
/**
|
||||
* Implemented by this class.
|
||||
*/
|
||||
use SeekableIterator;
|
||||
|
||||
/**
|
||||
* Represents a collection of RouterOS responses.
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_RouterOS
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
*
|
||||
* @method string getType()
|
||||
* Calls {@link Response::getType()}
|
||||
* on the response pointed by the pointer.
|
||||
* @method string[] getUnrecognizedWords()
|
||||
* Calls {@link Response::getUnrecognizedWords()}
|
||||
* on the response pointed by the pointer.
|
||||
* @method string|resource|null getProperty(string $name)
|
||||
* Calls {@link Response::getProperty()}
|
||||
* on the response pointed by the pointer.
|
||||
* @method string getTag()
|
||||
* Calls {@link Response::getTag()}
|
||||
* on the response pointed by the pointer.
|
||||
*/
|
||||
class ResponseCollection implements ArrayAccess, SeekableIterator, Countable
|
||||
{
|
||||
|
||||
/**
|
||||
* @var array An array with all {@link Response} objects.
|
||||
*/
|
||||
protected $responses = array();
|
||||
|
||||
/**
|
||||
* @var array An array with each {@link Response} object's type.
|
||||
*/
|
||||
protected $responseTypes = array();
|
||||
|
||||
/**
|
||||
* @var array An array with each {@link Response} object's tag.
|
||||
*/
|
||||
protected $responseTags = array();
|
||||
|
||||
/**
|
||||
* @var array An array with positions of responses, based on an property
|
||||
* name. The name of each property is the array key, and the array value
|
||||
* is another array where the key is the value for that property, and
|
||||
* the value is the posistion of the response. For performance reasons,
|
||||
* each key is built only when {@link static::setIndex()} is called with
|
||||
* that property, and remains available for the lifetime of this
|
||||
* collection.
|
||||
*/
|
||||
protected $responsesIndex = array();
|
||||
|
||||
/**
|
||||
* @var array An array with all distinct properties across all
|
||||
* {@link Response} objects. Created at the first call of
|
||||
* {@link static::getPropertyMap()}.
|
||||
*/
|
||||
protected $propertyMap = null;
|
||||
|
||||
/**
|
||||
* @var int A pointer, as required by SeekableIterator.
|
||||
*/
|
||||
protected $position = 0;
|
||||
|
||||
/**
|
||||
* @var string|null Name of property to use as index. NULL when disabled.
|
||||
*/
|
||||
protected $index = null;
|
||||
|
||||
/**
|
||||
* @var array Criterias used by {@link compare()} to determine the order
|
||||
* between two respones. See {@link orderBy()} for a detailed
|
||||
* description of this array's format.
|
||||
*/
|
||||
protected $compareBy = array();
|
||||
|
||||
/**
|
||||
* Creates a new collection.
|
||||
*
|
||||
* @param array $responses An array of responses, in network order.
|
||||
*/
|
||||
public function __construct(array $responses)
|
||||
{
|
||||
$pos = 0;
|
||||
foreach ($responses as $response) {
|
||||
if ($response instanceof Response) {
|
||||
$this->responseTypes[$pos] = $response->getType();
|
||||
$this->responseTags[$pos] = $response->getTag();
|
||||
$this->responses[$pos++] = $response;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A shorthand gateway.
|
||||
*
|
||||
* This is a magic PHP method that allows you to call the object as a
|
||||
* function. Depending on the argument given, one of the other functions in
|
||||
* the class is invoked and its returned value is returned by this function.
|
||||
*
|
||||
* @param int|string|null $offset The offset of the response to seek to.
|
||||
* If the offset is negative, seek to that relative to the end.
|
||||
* If the collection is indexed, you can also supply a value to seek to.
|
||||
* Setting NULL will get the current response's interator.
|
||||
*
|
||||
* @return Response|ArrayObject The {@link Response} at the specified
|
||||
* offset, the current response's iterator (which is an ArrayObject)
|
||||
* when NULL is given, or FALSE if the offset is invalid
|
||||
* or the collection is empty.
|
||||
*/
|
||||
public function __invoke($offset = null)
|
||||
{
|
||||
return null === $offset
|
||||
? $this->current()->getIterator()
|
||||
: $this->seek($offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a property to be usable as a key in the collection.
|
||||
*
|
||||
* @param string|null $name The name of the property to use. Future calls
|
||||
* that accept a position will then also be able to search values of
|
||||
* that property for a matching value.
|
||||
* Specifying NULL will disable such lookups (as is by default).
|
||||
* Note that in case this value occures multiple times within the
|
||||
* collection, only the last matching response will be accessible by
|
||||
* that value.
|
||||
*
|
||||
* @return $this The object itself.
|
||||
*/
|
||||
public function setIndex($name)
|
||||
{
|
||||
if (null !== $name) {
|
||||
$name = (string)$name;
|
||||
if (!isset($this->responsesIndex[$name])) {
|
||||
$this->responsesIndex[$name] = array();
|
||||
foreach ($this->responses as $pos => $response) {
|
||||
$val = $response->getProperty($name);
|
||||
if (null !== $val) {
|
||||
$this->responsesIndex[$name][$val] = $pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->index = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the property used as an index.
|
||||
*
|
||||
* @return string|null Name of property used as index. NULL when disabled.
|
||||
*/
|
||||
public function getIndex()
|
||||
{
|
||||
return $this->index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the whole collection as an array.
|
||||
*
|
||||
* @param bool $useIndex Whether to use the index values as keys for the
|
||||
* resulting array.
|
||||
*
|
||||
* @return array An array with all responses, in network order.
|
||||
*/
|
||||
public function toArray($useIndex = false)
|
||||
{
|
||||
if ($useIndex) {
|
||||
$positions = $this->responsesIndex[$this->index];
|
||||
asort($positions, SORT_NUMERIC);
|
||||
$positions = array_flip($positions);
|
||||
return array_combine(
|
||||
$positions,
|
||||
array_intersect_key($this->responses, $positions)
|
||||
);
|
||||
}
|
||||
return $this->responses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the responses/words in the collection.
|
||||
*
|
||||
* @param int $mode The counter mode.
|
||||
* Either COUNT_NORMAL or COUNT_RECURSIVE.
|
||||
* When in normal mode, counts the number of responses.
|
||||
* When in recursive mode, counts the total number of API words.
|
||||
*
|
||||
* @return int The number of responses in the collection.
|
||||
*/
|
||||
public function count($mode = COUNT_NORMAL)
|
||||
{
|
||||
if ($mode !== COUNT_NORMAL) {
|
||||
$result = 0;
|
||||
foreach ($this->responses as $response) {
|
||||
$result += $response->count($mode);
|
||||
}
|
||||
return $result;
|
||||
} else {
|
||||
return count($this->responses);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an offset exists.
|
||||
*
|
||||
* @param int|string $offset The offset to check. If the
|
||||
* collection is indexed, you can also supply a value to check.
|
||||
* Note that negative numeric offsets are NOT accepted.
|
||||
*
|
||||
* @return bool TRUE if the offset exists, FALSE otherwise.
|
||||
*/
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return is_int($offset)
|
||||
? array_key_exists($offset, $this->responses)
|
||||
: array_key_exists($offset, $this->responsesIndex[$this->index]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a {@link Response} from a specified offset.
|
||||
*
|
||||
* @param int|string $offset The offset of the desired response. If the
|
||||
* collection is indexed, you can also supply the value to search for.
|
||||
*
|
||||
* @return Response The response at the specified offset.
|
||||
*/
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return is_int($offset)
|
||||
? $this->responses[$offset >= 0
|
||||
? $offset
|
||||
: count($this->responses) + $offset]
|
||||
: $this->responses[$this->responsesIndex[$this->index][$offset]];
|
||||
}
|
||||
|
||||
/**
|
||||
* N/A
|
||||
*
|
||||
* This method exists only because it is required for ArrayAccess. The
|
||||
* collection is read only.
|
||||
*
|
||||
* @param int|string $offset N/A
|
||||
* @param Response $value N/A
|
||||
*
|
||||
* @return void
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* N/A
|
||||
*
|
||||
* This method exists only because it is required for ArrayAccess. The
|
||||
* collection is read only.
|
||||
*
|
||||
* @param int|string $offset N/A
|
||||
*
|
||||
* @return void
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the pointer to 0, and returns the first response.
|
||||
*
|
||||
* @return Response The first response in the collection, or FALSE if the
|
||||
* collection is empty.
|
||||
*/
|
||||
public function rewind()
|
||||
{
|
||||
return $this->seek(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the position pointer to a specified position.
|
||||
*
|
||||
* @param int|string $position The position to move to. If the collection is
|
||||
* indexed, you can also supply a value to move the pointer to.
|
||||
* A non-existent index will move the pointer to "-1".
|
||||
*
|
||||
* @return Response The {@link Response} at the specified position, or FALSE
|
||||
* if the specified position is not valid.
|
||||
*/
|
||||
public function seek($position)
|
||||
{
|
||||
$this->position = is_int($position)
|
||||
? ($position >= 0
|
||||
? $position
|
||||
: count($this->responses) + $position)
|
||||
: ($this->offsetExists($position)
|
||||
? $this->responsesIndex[$this->index][$position]
|
||||
: -1);
|
||||
return $this->current();
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the pointer forward by 1, and gets the next response.
|
||||
*
|
||||
* @return Response The next {@link Response} object, or FALSE if the
|
||||
* position is not valid.
|
||||
*/
|
||||
public function next()
|
||||
{
|
||||
++$this->position;
|
||||
return $this->current();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the response at the current pointer position.
|
||||
*
|
||||
* @return Response The response at the current pointer position, or FALSE
|
||||
* if the position is not valid.
|
||||
*/
|
||||
public function current()
|
||||
{
|
||||
return $this->valid() ? $this->responses[$this->position] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the pointer backwards by 1, and gets the previous response.
|
||||
*
|
||||
* @return Response The next {@link Response} object, or FALSE if the
|
||||
* position is not valid.
|
||||
*/
|
||||
public function prev()
|
||||
{
|
||||
--$this->position;
|
||||
return $this->current();
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the pointer to the last valid position, and returns the last
|
||||
* response.
|
||||
*
|
||||
* @return Response The last response in the collection, or FALSE if the
|
||||
* collection is empty.
|
||||
*/
|
||||
public function end()
|
||||
{
|
||||
$this->position = count($this->responses) - 1;
|
||||
return $this->current();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the key at the current pointer position.
|
||||
*
|
||||
* @return int The key at the current pointer position, i.e. the pointer
|
||||
* position itself, or FALSE if the position is not valid.
|
||||
*/
|
||||
public function key()
|
||||
{
|
||||
return $this->valid() ? $this->position : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the pointer is still pointing to an existing offset.
|
||||
*
|
||||
* @return bool TRUE if the pointer is valid, FALSE otherwise.
|
||||
*/
|
||||
public function valid()
|
||||
{
|
||||
return $this->offsetExists($this->position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all distinct property names.
|
||||
*
|
||||
* Gets all distinct property names across all responses.
|
||||
*
|
||||
* @return array An array with all distinct property names as keys, and the
|
||||
* indexes at which they occur as values.
|
||||
*/
|
||||
public function getPropertyMap()
|
||||
{
|
||||
if (null === $this->propertyMap) {
|
||||
$properties = array();
|
||||
foreach ($this->responses as $index => $response) {
|
||||
$names = array_keys($response->getIterator()->getArrayCopy());
|
||||
foreach ($names as $name) {
|
||||
if (!isset($properties[$name])) {
|
||||
$properties[$name] = array();
|
||||
}
|
||||
$properties[$name][] = $index;
|
||||
}
|
||||
}
|
||||
$this->propertyMap = $properties;
|
||||
}
|
||||
return $this->propertyMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all responses of a specified type.
|
||||
*
|
||||
* @param string $type The response type to filter by. Valid values are the
|
||||
* Response::TYPE_* constants.
|
||||
*
|
||||
* @return static A new collection with responses of the
|
||||
* specified type.
|
||||
*/
|
||||
public function getAllOfType($type)
|
||||
{
|
||||
$result = array();
|
||||
foreach (array_keys($this->responseTypes, $type, true) as $index) {
|
||||
$result[] = $this->responses[$index];
|
||||
}
|
||||
return new static($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all responses with a specified tag.
|
||||
*
|
||||
* @param string $tag The tag to filter by.
|
||||
*
|
||||
* @return static A new collection with responses having the
|
||||
* specified tag.
|
||||
*/
|
||||
public function getAllTagged($tag)
|
||||
{
|
||||
$result = array();
|
||||
foreach (array_keys($this->responseTags, $tag, true) as $index) {
|
||||
$result[] = $this->responses[$index];
|
||||
}
|
||||
return new static($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Order resones by criteria.
|
||||
*
|
||||
* @param mixed[] $criteria The criteria to order respones by. It takes the
|
||||
* form of an array where each key is the name of the property to use
|
||||
* as (N+1)th sorting key. The value of each member can be either NULL
|
||||
* (for that property, sort normally in ascending order), a single sort
|
||||
* order constant (SORT_ASC or SORT_DESC) to sort normally in the
|
||||
* specified order, an array where the first member is an order
|
||||
* constant, and the second one is sorting flags (same as built in PHP
|
||||
* array functions) or a callback.
|
||||
* If a callback is provided, it must accept two arguments
|
||||
* (the two values to be compared), and return -1, 0 or 1 if the first
|
||||
* value is respectively less than, equal to or greather than the second
|
||||
* one.
|
||||
* Each key of $criteria can also be numeric, in which case the
|
||||
* value is the name of the property, and sorting is done normally in
|
||||
* ascending order.
|
||||
*
|
||||
* @return static A new collection with the responses sorted in the
|
||||
* specified order.
|
||||
*/
|
||||
public function orderBy(array $criteria)
|
||||
{
|
||||
$this->compareBy = $criteria;
|
||||
$sortedResponses = $this->responses;
|
||||
usort($sortedResponses, array($this, 'compare'));
|
||||
return new static($sortedResponses);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls a method of the response pointed by the pointer.
|
||||
*
|
||||
* Calls a method of the response pointed by the pointer. This is a magic
|
||||
* PHP method, thanks to which any function you call on the collection that
|
||||
* is not defined will be redirected to the response.
|
||||
*
|
||||
* @param string $method The name of the method to call.
|
||||
* @param array $args The arguments to pass to the method.
|
||||
*
|
||||
* @return mixed Whatever the called function returns.
|
||||
*/
|
||||
public function __call($method, array $args)
|
||||
{
|
||||
return call_user_func_array(
|
||||
array($this->current(), $method),
|
||||
$args
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two respones.
|
||||
*
|
||||
* Compares two respones, based on criteria defined in
|
||||
* {@link static::$compareBy}.
|
||||
*
|
||||
* @param Response $itemA The response to compare.
|
||||
* @param Response $itemB The response to compare $a against.
|
||||
*
|
||||
* @return int Returns 0 if the two respones are equal according to every
|
||||
* criteria specified, -1 if $a should be placed before $b, and 1 if $b
|
||||
* should be placed before $a.
|
||||
*/
|
||||
protected function compare(Response $itemA, Response $itemB)
|
||||
{
|
||||
foreach ($this->compareBy as $name => $spec) {
|
||||
if (!is_string($name)) {
|
||||
$name = $spec;
|
||||
$spec = null;
|
||||
}
|
||||
|
||||
$members = array(
|
||||
0 => $itemA->getProperty($name),
|
||||
1 => $itemB->getProperty($name)
|
||||
);
|
||||
|
||||
if (is_callable($spec)) {
|
||||
uasort($members, $spec);
|
||||
} elseif ($members[0] === $members[1]) {
|
||||
continue;
|
||||
} else {
|
||||
$flags = SORT_REGULAR;
|
||||
$order = SORT_ASC;
|
||||
if (is_array($spec)) {
|
||||
list($order, $flags) = $spec;
|
||||
} elseif (null !== $spec) {
|
||||
$order = $spec;
|
||||
}
|
||||
|
||||
if (SORT_ASC === $order) {
|
||||
asort($members, $flags);
|
||||
} else {
|
||||
arsort($members, $flags);
|
||||
}
|
||||
}
|
||||
return (key($members) === 0) ? -1 : 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
44
system/autoload/PEAR2/Net/RouterOS/SocketException.php
Normal file
44
system/autoload/PEAR2/Net/RouterOS/SocketException.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* RouterOS API client implementation.
|
||||
*
|
||||
* RouterOS is the flag product of the company MikroTik and is a powerful router software. One of its many abilities is to allow control over it via an API. This package provides a client for that API, in turn allowing you to use PHP to control RouterOS hosts.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_RouterOS
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Vasil Rangelov
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0b5
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
*/
|
||||
/**
|
||||
* The namespace declaration.
|
||||
*/
|
||||
namespace PEAR2\Net\RouterOS;
|
||||
|
||||
/**
|
||||
* Base of this class.
|
||||
*/
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* Exception thrown when something goes wrong with the connection.
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_RouterOS
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
*/
|
||||
class SocketException extends RuntimeException implements Exception
|
||||
{
|
||||
const CODE_SERVICE_INCOMPATIBLE = 10200;
|
||||
const CODE_CONNECTION_FAIL = 100;
|
||||
const CODE_QUERY_SEND_FAIL = 30600;
|
||||
const CODE_REQUEST_SEND_FAIL = 40900;
|
||||
const CODE_NO_DATA = 50000;
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* RouterOS API client implementation.
|
||||
*
|
||||
* RouterOS is the flag product of the company MikroTik and is a powerful router software. One of its many abilities is to allow control over it via an API. This package provides a client for that API, in turn allowing you to use PHP to control RouterOS hosts.
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_RouterOS
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Vasil Rangelov
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0b5
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
*/
|
||||
/**
|
||||
* The namespace declaration.
|
||||
*/
|
||||
namespace PEAR2\Net\RouterOS;
|
||||
|
||||
use UnexpectedValueException as U;
|
||||
|
||||
/**
|
||||
* Exception thrown when encountering an invalid value in a function argument.
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_RouterOS
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
*/
|
||||
class UnexpectedValueException extends U implements Exception
|
||||
{
|
||||
const CODE_CALLBACK_INVALID = 10502;
|
||||
const CODE_ACTION_UNKNOWN = 30100;
|
||||
const CODE_RESPONSE_TYPE_UNKNOWN = 50100;
|
||||
|
||||
/**
|
||||
* @var mixed The unexpected value.
|
||||
*/
|
||||
private $_value;
|
||||
|
||||
/**
|
||||
* Creates a new UnexpectedValueException.
|
||||
*
|
||||
* @param string $message The Exception message to throw.
|
||||
* @param int $code The Exception code.
|
||||
* @param \Exception $previous The previous exception used for the exception
|
||||
* chaining.
|
||||
* @param mixed $value The unexpected value.
|
||||
*/
|
||||
public function __construct(
|
||||
$message,
|
||||
$code = 0,
|
||||
$previous = null,
|
||||
$value = null
|
||||
) {
|
||||
parent::__construct($message, $code, $previous);
|
||||
$this->_value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the unexpected value.
|
||||
*
|
||||
* @return mixed The unexpected value.
|
||||
*/
|
||||
public function getValue()
|
||||
{
|
||||
return $this->_value;
|
||||
}
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
// String representation is not reliable in testing
|
||||
|
||||
/**
|
||||
* Returns a string representation of the exception.
|
||||
*
|
||||
* @return string The exception as a string.
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return parent::__toString() . "\nValue:{$this->_value}";
|
||||
}
|
||||
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
1177
system/autoload/PEAR2/Net/RouterOS/Util.php
Normal file
1177
system/autoload/PEAR2/Net/RouterOS/Util.php
Normal file
File diff suppressed because it is too large
Load Diff
36
system/autoload/PEAR2/Net/Transmitter/Exception.php
Normal file
36
system/autoload/PEAR2/Net/Transmitter/Exception.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Wrapper for network stream functionality.
|
||||
*
|
||||
* PHP has built in support for various types of network streams, such as HTTP and TCP sockets. One problem that arises with them is the fact that a single fread/fwrite call might not read/write all the data you intended, regardless of whether you're in blocking mode or not. While the PHP manual offers a workaround in the form of a loop with a few variables, using it every single time you want to read/write can be tedious.
|
||||
|
||||
This package abstracts this away, so that when you want to get exactly N amount of bytes, you can be sure the upper levels of your app will be dealing with N bytes. Oh, and the functionality is nicely wrapped in an object (but that's just the icing on the cake).
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_Transmitter
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Vasil Rangelov
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0a5
|
||||
* @link http://pear2.php.net/PEAR2_Net_Transmitter
|
||||
*/
|
||||
/**
|
||||
* The namespace declaration.
|
||||
*/
|
||||
namespace PEAR2\Net\Transmitter;
|
||||
|
||||
/**
|
||||
* Generic exception class of this package.
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_Transmitter
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Net_Transmitter
|
||||
*/
|
||||
interface Exception
|
||||
{
|
||||
}
|
229
system/autoload/PEAR2/Net/Transmitter/FilterCollection.php
Normal file
229
system/autoload/PEAR2/Net/Transmitter/FilterCollection.php
Normal file
@ -0,0 +1,229 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Wrapper for network stream functionality.
|
||||
*
|
||||
* PHP has built in support for various types of network streams, such as HTTP and TCP sockets. One problem that arises with them is the fact that a single fread/fwrite call might not read/write all the data you intended, regardless of whether you're in blocking mode or not. While the PHP manual offers a workaround in the form of a loop with a few variables, using it every single time you want to read/write can be tedious.
|
||||
|
||||
This package abstracts this away, so that when you want to get exactly N amount of bytes, you can be sure the upper levels of your app will be dealing with N bytes. Oh, and the functionality is nicely wrapped in an object (but that's just the icing on the cake).
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_Transmitter
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Vasil Rangelov
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0a5
|
||||
* @link http://pear2.php.net/PEAR2_Net_Transmitter
|
||||
*/
|
||||
/**
|
||||
* The namespace declaration.
|
||||
*/
|
||||
namespace PEAR2\Net\Transmitter;
|
||||
|
||||
/**
|
||||
* A filter collection.
|
||||
*
|
||||
* Represents a collection of stream filters.
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_Transmitter
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Net_Transmitter
|
||||
* @see Client
|
||||
*/
|
||||
class FilterCollection implements \SeekableIterator, \Countable
|
||||
{
|
||||
/**
|
||||
* @var array The filter collection itself.
|
||||
*/
|
||||
protected $filters = array();
|
||||
|
||||
/**
|
||||
* @var int A pointer, as required by SeekableIterator.
|
||||
*/
|
||||
protected $position = 0;
|
||||
|
||||
/**
|
||||
* Appends a filter to the collection
|
||||
*
|
||||
* @param string $name The name of the filter.
|
||||
* @param array $params An array of parameters for the filter.
|
||||
*
|
||||
* @return $this The collection itself.
|
||||
*/
|
||||
public function append($name, array $params = array())
|
||||
{
|
||||
$this->filters[] = array((string) $name, $params);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the filter before a position.
|
||||
*
|
||||
* Inserts the specified filter before a filter at a specified position. The
|
||||
* new filter takes the specified position, while previous filters are moved
|
||||
* forward by one.
|
||||
*
|
||||
* @param int $position The position before which the filter will be
|
||||
* inserted.
|
||||
* @param string $name The name of the filter.
|
||||
* @param array $params An array of parameters for the filter.
|
||||
*
|
||||
* @return $this The collection itself.
|
||||
*/
|
||||
public function insertBefore($position, $name, array $params = array())
|
||||
{
|
||||
$position = (int) $position;
|
||||
if ($position <= 0) {
|
||||
$this->filters = array_merge(
|
||||
array(0 => array((string) $name, $params)),
|
||||
$this->filters
|
||||
);
|
||||
return $this;
|
||||
}
|
||||
if ($position > count($this->filters)) {
|
||||
return $this->append($name, $params);
|
||||
}
|
||||
$this->filters = array_merge(
|
||||
array_slice($this->filters, 0, $position),
|
||||
array(0 => array((string) $name, $params)),
|
||||
array_slice($this->filters, $position)
|
||||
);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a filter at a specified position.
|
||||
*
|
||||
* @param int $position The position from which to remove a filter.
|
||||
*
|
||||
* @return $this The collection itself.
|
||||
*/
|
||||
public function removeAt($position)
|
||||
{
|
||||
unset($this->filters[$position]);
|
||||
$this->filters = array_values($this->filters);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the collection
|
||||
*
|
||||
* @return $this The collection itself.
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->filters = array();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of filters in the collection.
|
||||
*
|
||||
* @return int The number of filters in the collection.
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return count($this->filters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the pointer to 0.
|
||||
*
|
||||
* @return bool TRUE if the collection is not empty, FALSE otherwise.
|
||||
*/
|
||||
public function rewind()
|
||||
{
|
||||
return $this->seek(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the pointer to a specified position.
|
||||
*
|
||||
* @param int $position The position to move to.
|
||||
*
|
||||
* @return bool TRUE if the specified position is valid, FALSE otherwise.
|
||||
*/
|
||||
public function seek($position)
|
||||
{
|
||||
$this->position = $position;
|
||||
return $this->valid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current position.
|
||||
*
|
||||
* @return int The current position.
|
||||
*/
|
||||
public function getCurrentPosition()
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the pointer forward by 1.
|
||||
*
|
||||
* @return bool TRUE if the new position is valid, FALSE otherwise.
|
||||
*/
|
||||
public function next()
|
||||
{
|
||||
++$this->position;
|
||||
return $this->valid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the filter name at the current pointer position.
|
||||
*
|
||||
* @return string The name of the filter at the current position.
|
||||
*/
|
||||
public function key()
|
||||
{
|
||||
return $this->valid() ? $this->filters[$this->position][0] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the filter parameters at the current pointer position.
|
||||
*
|
||||
* @return array An array of parameters for the filter at the current
|
||||
* position.
|
||||
*/
|
||||
public function current()
|
||||
{
|
||||
return $this->valid() ? $this->filters[$this->position][1] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the pointer backwards by 1.
|
||||
*
|
||||
* @return bool TRUE if the new position is valid, FALSE otherwise.
|
||||
*/
|
||||
public function prev()
|
||||
{
|
||||
--$this->position;
|
||||
return $this->valid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the pointer to the last valid position.
|
||||
*
|
||||
* @return bool TRUE if the collection is not empty, FALSE otherwise.
|
||||
*/
|
||||
public function end()
|
||||
{
|
||||
$this->position = count($this->filters) - 1;
|
||||
return $this->valid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the pointer is still pointing to an existing offset.
|
||||
*
|
||||
* @return bool TRUE if the pointer is valid, FALSE otherwise.
|
||||
*/
|
||||
public function valid()
|
||||
{
|
||||
return array_key_exists($this->position, $this->filters);
|
||||
}
|
||||
}
|
36
system/autoload/PEAR2/Net/Transmitter/LockException.php
Normal file
36
system/autoload/PEAR2/Net/Transmitter/LockException.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Wrapper for network stream functionality.
|
||||
*
|
||||
* PHP has built in support for various types of network streams, such as HTTP and TCP sockets. One problem that arises with them is the fact that a single fread/fwrite call might not read/write all the data you intended, regardless of whether you're in blocking mode or not. While the PHP manual offers a workaround in the form of a loop with a few variables, using it every single time you want to read/write can be tedious.
|
||||
|
||||
This package abstracts this away, so that when you want to get exactly N amount of bytes, you can be sure the upper levels of your app will be dealing with N bytes. Oh, and the functionality is nicely wrapped in an object (but that's just the icing on the cake).
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_Transmitter
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Vasil Rangelov
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0a5
|
||||
* @link http://pear2.php.net/PEAR2_Net_Transmitter
|
||||
*/
|
||||
/**
|
||||
* The namespace declaration.
|
||||
*/
|
||||
namespace PEAR2\Net\Transmitter;
|
||||
|
||||
/**
|
||||
* Exception thrown when something goes wrong when dealing with locks.
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_Transmitter
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Net_Transmitter
|
||||
*/
|
||||
class LockException extends \RuntimeException implements Exception
|
||||
{
|
||||
}
|
181
system/autoload/PEAR2/Net/Transmitter/NetworkStream.php
Normal file
181
system/autoload/PEAR2/Net/Transmitter/NetworkStream.php
Normal file
@ -0,0 +1,181 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Wrapper for network stream functionality.
|
||||
*
|
||||
* PHP has built in support for various types of network streams, such as HTTP and TCP sockets. One problem that arises with them is the fact that a single fread/fwrite call might not read/write all the data you intended, regardless of whether you're in blocking mode or not. While the PHP manual offers a workaround in the form of a loop with a few variables, using it every single time you want to read/write can be tedious.
|
||||
|
||||
This package abstracts this away, so that when you want to get exactly N amount of bytes, you can be sure the upper levels of your app will be dealing with N bytes. Oh, and the functionality is nicely wrapped in an object (but that's just the icing on the cake).
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_Transmitter
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Vasil Rangelov
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0a5
|
||||
* @link http://pear2.php.net/PEAR2_Net_Transmitter
|
||||
*/
|
||||
/**
|
||||
* The namespace declaration.
|
||||
*/
|
||||
namespace PEAR2\Net\Transmitter;
|
||||
|
||||
/**
|
||||
* A network transmitter.
|
||||
*
|
||||
* This is a convinience wrapper for network streams. Used to ensure data
|
||||
* integrity.
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_Transmitter
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Net_Transmitter
|
||||
*/
|
||||
abstract class NetworkStream extends Stream
|
||||
{
|
||||
/**
|
||||
* Used in {@link setCrypto()} to disable encryption.
|
||||
*/
|
||||
const CRYPTO_OFF = '';
|
||||
|
||||
/**
|
||||
* Used in {@link setCrypto()} to set encryption to either SSLv2 or SSLv3,
|
||||
* depending on what the other end supports.
|
||||
*/
|
||||
const CRYPTO_SSL = 'SSLv23';
|
||||
|
||||
/**
|
||||
* Used in {@link setCrypto()} to set encryption to SSLv2.
|
||||
*/
|
||||
const CRYPTO_SSL2 = 'SSLv2';
|
||||
|
||||
/**
|
||||
* Used in {@link setCrypto()} to set encryption to SSLv3.
|
||||
*/
|
||||
const CRYPTO_SSL3 = 'SSLv3';
|
||||
|
||||
/**
|
||||
* Used in {@link setCrypto()} to set encryption to TLS (exact version
|
||||
* negotiated between 1.0 and 1.2).
|
||||
*/
|
||||
const CRYPTO_TLS = 'TLS';
|
||||
|
||||
/**
|
||||
* @var string The type of stream. Can be either "_CLIENT" or "_SERVER".
|
||||
* Used to complement the encryption type. Must be set by child classes
|
||||
* for {@link setCrypto()} to work properly.
|
||||
*/
|
||||
protected $streamType = '';
|
||||
|
||||
/**
|
||||
* @var string The current cryptography setting.
|
||||
*/
|
||||
protected $crypto = '';
|
||||
|
||||
/**
|
||||
* Wraps around the specified stream.
|
||||
*
|
||||
* @param resource $stream The stream to wrap around.
|
||||
*/
|
||||
public function __construct($stream)
|
||||
{
|
||||
parent::__construct($stream, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current cryptography setting.
|
||||
*
|
||||
* @return string One of this class' CRYPTO_* constants.
|
||||
*/
|
||||
public function getCrypto()
|
||||
{
|
||||
return $this->crypto;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current connection's cryptography setting.
|
||||
*
|
||||
* @param string $type The encryption type to set. Must be one of this
|
||||
* class' CRYPTO_* constants.
|
||||
*
|
||||
* @return boolean TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function setCrypto($type)
|
||||
{
|
||||
if (self::CRYPTO_OFF === $type) {
|
||||
$result = stream_socket_enable_crypto($this->stream, false);
|
||||
} else {
|
||||
$result = stream_socket_enable_crypto(
|
||||
$this->stream,
|
||||
true,
|
||||
constant("STREAM_CRYPTO_METHOD_{$type}{$this->streamType}")
|
||||
);
|
||||
}
|
||||
|
||||
if ($result) {
|
||||
$this->crypto = $type;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the stream is available for operations.
|
||||
*
|
||||
* @return bool TRUE if the stream is available, FALSE otherwise.
|
||||
*/
|
||||
public function isAvailable()
|
||||
{
|
||||
if (parent::isStream($this->stream)) {
|
||||
if ($this->isBlocking && feof($this->stream)) {
|
||||
return false;
|
||||
}
|
||||
$meta = stream_get_meta_data($this->stream);
|
||||
return !$meta['eof'];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size of a stream's buffer.
|
||||
*
|
||||
* @param int $size The desired size of the buffer, in bytes.
|
||||
* @param string $direction The buffer of which direction to set. Valid
|
||||
* values are the DIRECTION_* constants.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function setBuffer($size, $direction = self::DIRECTION_ALL)
|
||||
{
|
||||
$result = parent::setBuffer($size, $direction);
|
||||
if (self::DIRECTION_SEND === $direction
|
||||
&& function_exists('stream_set_chunk_size') && !$result
|
||||
) {
|
||||
return false !== @stream_set_chunk_size($this->stream, $size);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown a full-duplex connection
|
||||
*
|
||||
* Shutdowns (partially or not) a full-duplex connection.
|
||||
*
|
||||
* @param string $direction The direction for which to disable further
|
||||
* communications.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function shutdown($direction = self::DIRECTION_ALL)
|
||||
{
|
||||
$directionMap = array(
|
||||
self::DIRECTION_ALL => STREAM_SHUT_RDWR,
|
||||
self::DIRECTION_SEND => STREAM_SHUT_WR,
|
||||
self::DIRECTION_RECEIVE => STREAM_SHUT_RD
|
||||
);
|
||||
return array_key_exists($direction, $directionMap)
|
||||
&& stream_socket_shutdown($this->stream, $directionMap[$direction]);
|
||||
}
|
||||
}
|
124
system/autoload/PEAR2/Net/Transmitter/SocketException.php
Normal file
124
system/autoload/PEAR2/Net/Transmitter/SocketException.php
Normal file
@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Wrapper for network stream functionality.
|
||||
*
|
||||
* PHP has built in support for various types of network streams, such as HTTP and TCP sockets. One problem that arises with them is the fact that a single fread/fwrite call might not read/write all the data you intended, regardless of whether you're in blocking mode or not. While the PHP manual offers a workaround in the form of a loop with a few variables, using it every single time you want to read/write can be tedious.
|
||||
|
||||
This package abstracts this away, so that when you want to get exactly N amount of bytes, you can be sure the upper levels of your app will be dealing with N bytes. Oh, and the functionality is nicely wrapped in an object (but that's just the icing on the cake).
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_Transmitter
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Vasil Rangelov
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0a5
|
||||
* @link http://pear2.php.net/PEAR2_Net_Transmitter
|
||||
*/
|
||||
/**
|
||||
* The namespace declaration.
|
||||
*/
|
||||
namespace PEAR2\Net\Transmitter;
|
||||
|
||||
/**
|
||||
* Used to enable any exception in chaining.
|
||||
*/
|
||||
use Exception as E;
|
||||
|
||||
/**
|
||||
* Exception thrown when something goes wrong with the connection.
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_Transmitter
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Net_Transmitter
|
||||
*/
|
||||
class SocketException extends StreamException
|
||||
{
|
||||
|
||||
/**
|
||||
* @var int The system level error code.
|
||||
*/
|
||||
protected $errorNo;
|
||||
|
||||
/**
|
||||
* @var string The system level error message.
|
||||
*/
|
||||
protected $errorStr;
|
||||
|
||||
/**
|
||||
* Creates a new socket exception.
|
||||
*
|
||||
* @param string $message The Exception message to throw.
|
||||
* @param int $code The Exception code.
|
||||
* @param E|null $previous Previous exception thrown,
|
||||
* or NULL if there is none.
|
||||
* @param int|string|resource|null $fragment The fragment up until the
|
||||
* point of failure.
|
||||
* On failure with sending, this is the number of bytes sent
|
||||
* successfully before the failure.
|
||||
* On failure when receiving, this is a string/stream holding
|
||||
* the contents received successfully before the failure.
|
||||
* NULL if the failure occured before the operation started.
|
||||
* @param int $errorNo The system level error number.
|
||||
* @param string $errorStr The system level
|
||||
* error message.
|
||||
*/
|
||||
public function __construct(
|
||||
$message = '',
|
||||
$code = 0,
|
||||
E $previous = null,
|
||||
$fragment = null,
|
||||
$errorNo = null,
|
||||
$errorStr = null
|
||||
) {
|
||||
parent::__construct($message, $code, $previous, $fragment);
|
||||
$this->errorNo = $errorNo;
|
||||
$this->errorStr = $errorStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the system level error code on the socket.
|
||||
*
|
||||
* @return int The system level error number.
|
||||
*/
|
||||
public function getSocketErrorNumber()
|
||||
{
|
||||
return $this->errorNo;
|
||||
}
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
// Unreliable in testing.
|
||||
|
||||
/**
|
||||
* Gets the system level error message on the socket.
|
||||
*
|
||||
* @return string The system level error message.
|
||||
*/
|
||||
public function getSocketErrorMessage()
|
||||
{
|
||||
return $this->errorStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the exception.
|
||||
*
|
||||
* @return string The exception as a string.
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
$result = parent::__toString();
|
||||
if (null !== $this->getSocketErrorNumber()) {
|
||||
$result .= "\nSocket error number:" . $this->getSocketErrorNumber();
|
||||
}
|
||||
if (null !== $this->getSocketErrorMessage()) {
|
||||
$result .= "\nSocket error message:"
|
||||
. $this->getSocketErrorMessage();
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
605
system/autoload/PEAR2/Net/Transmitter/Stream.php
Normal file
605
system/autoload/PEAR2/Net/Transmitter/Stream.php
Normal file
@ -0,0 +1,605 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Wrapper for network stream functionality.
|
||||
*
|
||||
* PHP has built in support for various types of network streams, such as HTTP and TCP sockets. One problem that arises with them is the fact that a single fread/fwrite call might not read/write all the data you intended, regardless of whether you're in blocking mode or not. While the PHP manual offers a workaround in the form of a loop with a few variables, using it every single time you want to read/write can be tedious.
|
||||
|
||||
This package abstracts this away, so that when you want to get exactly N amount of bytes, you can be sure the upper levels of your app will be dealing with N bytes. Oh, and the functionality is nicely wrapped in an object (but that's just the icing on the cake).
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_Transmitter
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Vasil Rangelov
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0a5
|
||||
* @link http://pear2.php.net/PEAR2_Net_Transmitter
|
||||
*/
|
||||
/**
|
||||
* The namespace declaration.
|
||||
*/
|
||||
namespace PEAR2\Net\Transmitter;
|
||||
|
||||
use Exception as E;
|
||||
|
||||
/**
|
||||
* A stream transmitter.
|
||||
*
|
||||
* This is a convinience wrapper for stream functionality. Used to ensure data
|
||||
* integrity. Designed for TCP sockets, but it has intentionally been made to
|
||||
* accept any stream.
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_Transmitter
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Net_Transmitter
|
||||
*/
|
||||
class Stream
|
||||
{
|
||||
/**
|
||||
* Used to stop settings in either direction being applied.
|
||||
*/
|
||||
const DIRECTION_NONE = 0;
|
||||
/**
|
||||
* Used to apply settings only to receiving.
|
||||
*/
|
||||
const DIRECTION_RECEIVE = 1;
|
||||
/**
|
||||
* Used to apply settings only to sending.
|
||||
*/
|
||||
const DIRECTION_SEND = 2;
|
||||
/**
|
||||
* Used to apply settings to both sending and receiving.
|
||||
*/
|
||||
const DIRECTION_ALL = 3;
|
||||
|
||||
/**
|
||||
* @var resource The stream to wrap around.
|
||||
*/
|
||||
protected $stream;
|
||||
|
||||
/**
|
||||
* @var bool Whether to automaticaly close the stream on
|
||||
* object destruction if it's not a persistent one. Setting this to
|
||||
* FALSE may be useful if you're only using this class "part time",
|
||||
* while setting it to TRUE might be useful if you're doing some
|
||||
* "on offs".
|
||||
*/
|
||||
protected $autoClose = false;
|
||||
|
||||
/**
|
||||
* @var bool A flag that tells whether or not the stream is persistent.
|
||||
*/
|
||||
protected $persist;
|
||||
|
||||
/**
|
||||
* @var bool Whether the wrapped stream is in blocking mode or not.
|
||||
*/
|
||||
protected $isBlocking = true;
|
||||
|
||||
/**
|
||||
* @var array An associative array with the chunk size of each direction.
|
||||
* Key is the direction, value is the size in bytes as integer.
|
||||
*/
|
||||
protected $chunkSize = array(
|
||||
self::DIRECTION_SEND => 0xFFFFF, self::DIRECTION_RECEIVE => 0xFFFFF
|
||||
);
|
||||
|
||||
/**
|
||||
* Wraps around the specified stream.
|
||||
*
|
||||
* @param resource $stream The stream to wrap around.
|
||||
* @param bool $autoClose Whether to automaticaly close the stream on
|
||||
* object destruction if it's not a persistent one. Setting this to
|
||||
* FALSE may be useful if you're only using this class "part time",
|
||||
* while setting it to TRUE might be useful if you're doing some
|
||||
* "on offs".
|
||||
*
|
||||
* @see static::isFresh()
|
||||
*/
|
||||
public function __construct($stream, $autoClose = false)
|
||||
{
|
||||
if (!self::isStream($stream)) {
|
||||
throw $this->createException('Invalid stream supplied.', 1);
|
||||
}
|
||||
$this->stream = $stream;
|
||||
$this->autoClose = (bool) $autoClose;
|
||||
$this->persist = (bool) preg_match(
|
||||
'#\s?persistent\s?#sm',
|
||||
get_resource_type($stream)
|
||||
);
|
||||
$meta = stream_get_meta_data($stream);
|
||||
$this->isBlocking = isset($meta['blocked']) ? $meta['blocked'] : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* PHP error handler for connection errors.
|
||||
*
|
||||
* @param string $level Level of PHP error raised. Ignored.
|
||||
* @param string $message Message raised by PHP.
|
||||
*
|
||||
* @return void
|
||||
* @throws SocketException That's how the error is handled.
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
protected function handleError($level, $message)
|
||||
{
|
||||
throw $this->createException($message, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given variable is a stream resource.
|
||||
*
|
||||
* @param mixed $var The variable to check.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public static function isStream($var)
|
||||
{
|
||||
return is_resource($var)
|
||||
&& (bool) preg_match('#\s?stream$#sm', get_resource_type($var));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the wrapped stream is fresh.
|
||||
*
|
||||
* Checks whether the wrapped stream is fresh. A stream is considered fresh
|
||||
* if there hasn't been any activity on it. Particularly useful for
|
||||
* detecting reused persistent connections.
|
||||
*
|
||||
* @return bool TRUE if the socket is fresh, FALSE otherwise.
|
||||
*/
|
||||
public function isFresh()
|
||||
{
|
||||
return ftell($this->stream) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the wrapped stream is a persistent one.
|
||||
*
|
||||
* @return bool TRUE if the stream is a persistent one, FALSE otherwise.
|
||||
*/
|
||||
public function isPersistent()
|
||||
{
|
||||
return $this->persist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the wrapped stream is a blocking one.
|
||||
*
|
||||
* @return bool TRUE if the stream is a blocking one, FALSE otherwise.
|
||||
*/
|
||||
public function isBlocking()
|
||||
{
|
||||
return $this->isBlocking;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets blocking mode.
|
||||
*
|
||||
* @param bool $block Sets whether the stream is in blocking mode.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function setIsBlocking($block)
|
||||
{
|
||||
$block = (bool)$block;
|
||||
if (stream_set_blocking($this->stream, (int)$block)) {
|
||||
$this->isBlocking = $block;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the timeout for the stream.
|
||||
*
|
||||
* @param int $seconds Timeout in seconds.
|
||||
* @param int $microseconds Timeout in microseconds to be added to the
|
||||
* seconds.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function setTimeout($seconds, $microseconds = 0)
|
||||
{
|
||||
return stream_set_timeout($this->stream, $seconds, $microseconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size of a stream's buffer.
|
||||
*
|
||||
* @param int $size The desired size of the buffer, in bytes.
|
||||
* @param string $direction The buffer of which direction to set. Valid
|
||||
* values are the DIRECTION_* constants.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function setBuffer($size, $direction = self::DIRECTION_ALL)
|
||||
{
|
||||
switch($direction) {
|
||||
case self::DIRECTION_SEND:
|
||||
return stream_set_write_buffer($this->stream, $size) === 0;
|
||||
case self::DIRECTION_RECEIVE:
|
||||
return stream_set_read_buffer($this->stream, $size) === 0;
|
||||
case self::DIRECTION_ALL:
|
||||
return $this->setBuffer($size, self::DIRECTION_RECEIVE)
|
||||
&& $this->setBuffer($size, self::DIRECTION_SEND);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size of the chunk.
|
||||
*
|
||||
* To ensure data integrity, as well as to allow for lower memory
|
||||
* consumption, data is sent/received in chunks. This function
|
||||
* allows you to set the size of each chunk. The default is 0xFFFFF.
|
||||
*
|
||||
* @param int $size The desired size of the chunk, in bytes.
|
||||
* @param string $direction The chunk of which direction to set. Valid
|
||||
* values are the DIRECTION_* constants.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function setChunk($size, $direction = self::DIRECTION_ALL)
|
||||
{
|
||||
$size = (int) $size;
|
||||
if ($size <= 0) {
|
||||
return false;
|
||||
}
|
||||
switch($direction) {
|
||||
case self::DIRECTION_SEND:
|
||||
case self::DIRECTION_RECEIVE:
|
||||
$this->chunkSize[$direction] = $size;
|
||||
return true;
|
||||
case self::DIRECTION_ALL:
|
||||
$this->chunkSize[self::DIRECTION_SEND]
|
||||
= $this->chunkSize[self::DIRECTION_RECEIVE] = $size;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the size of the chunk.
|
||||
*
|
||||
* @param string $direction The chunk of which direction to get. Valid
|
||||
* values are the DIRECTION_* constants.
|
||||
*
|
||||
* @return int|array|false The chunk size in bytes,
|
||||
* or an array of chunk sizes with the directions as keys.
|
||||
* FALSE on invalid direction.
|
||||
*/
|
||||
public function getChunk($direction = self::DIRECTION_ALL)
|
||||
{
|
||||
switch($direction) {
|
||||
case self::DIRECTION_SEND:
|
||||
case self::DIRECTION_RECEIVE:
|
||||
return $this->chunkSize[$direction];
|
||||
case self::DIRECTION_ALL:
|
||||
return $this->chunkSize;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a string or stream over the wrapped stream.
|
||||
*
|
||||
* Sends a string or stream over the wrapped stream. If a seekable stream is
|
||||
* provided, it will be seeked back to the same position it was passed as,
|
||||
* regardless of the $offset parameter.
|
||||
*
|
||||
* @param string|resource $contents The string or stream to send.
|
||||
* @param int $offset The offset from which to start sending.
|
||||
* If a stream is provided, and this is set to NULL, sending will start
|
||||
* from the current stream position.
|
||||
* @param int $length The maximum length to send. If omitted,
|
||||
* the string/stream will be sent to its end.
|
||||
*
|
||||
* @return int The number of bytes sent.
|
||||
*/
|
||||
public function send($contents, $offset = null, $length = null)
|
||||
{
|
||||
$bytes = 0;
|
||||
$chunkSize = $this->chunkSize[self::DIRECTION_SEND];
|
||||
$lengthIsNotNull = null !== $length;
|
||||
$offsetIsNotNull = null !== $offset;
|
||||
if (self::isStream($contents)) {
|
||||
if ($offsetIsNotNull) {
|
||||
$oldPos = ftell($contents);
|
||||
fseek($contents, $offset, SEEK_SET);
|
||||
}
|
||||
while (!feof($contents)) {
|
||||
if ($lengthIsNotNull
|
||||
&& 0 === $chunkSize = min($chunkSize, $length - $bytes)
|
||||
) {
|
||||
break;
|
||||
}
|
||||
$bytesNow = @fwrite(
|
||||
$this->stream,
|
||||
fread($contents, $chunkSize)
|
||||
);
|
||||
if (0 != $bytesNow) {
|
||||
$bytes += $bytesNow;
|
||||
} elseif ($this->isBlocking || false === $bytesNow) {
|
||||
throw $this->createException(
|
||||
'Failed while sending stream.',
|
||||
2,
|
||||
null,
|
||||
$bytes
|
||||
);
|
||||
} else {
|
||||
usleep(300000);
|
||||
}
|
||||
$this->isAcceptingData(null);
|
||||
}
|
||||
if ($offsetIsNotNull) {
|
||||
fseek($contents, $oldPos, SEEK_SET);
|
||||
} else {
|
||||
fseek($contents, -$bytes, SEEK_CUR);
|
||||
}
|
||||
} else {
|
||||
$contents = (string) $contents;
|
||||
if ($offsetIsNotNull) {
|
||||
$contents = substr($contents, $offset);
|
||||
}
|
||||
if ($lengthIsNotNull) {
|
||||
$contents = substr($contents, 0, $length);
|
||||
}
|
||||
$bytesToSend = (double) sprintf('%u', strlen($contents));
|
||||
while ($bytes < $bytesToSend) {
|
||||
$bytesNow = @fwrite(
|
||||
$this->stream,
|
||||
substr($contents, $bytes, $chunkSize)
|
||||
);
|
||||
if (0 != $bytesNow) {
|
||||
$bytes += $bytesNow;
|
||||
} elseif ($this->isBlocking || false === $bytesNow) {
|
||||
throw $this->createException(
|
||||
'Failed while sending string.',
|
||||
3,
|
||||
null,
|
||||
$bytes
|
||||
);
|
||||
} else {
|
||||
usleep(300000);
|
||||
}
|
||||
$this->isAcceptingData(null);
|
||||
}
|
||||
}
|
||||
return $bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads from the wrapped stream to receive.
|
||||
*
|
||||
* Reads from the wrapped stream to receive content as a string.
|
||||
*
|
||||
* @param int $length The number of bytes to receive.
|
||||
* @param string $what Descriptive string about what is being received
|
||||
* (used in exception messages).
|
||||
*
|
||||
* @return string The received content.
|
||||
*/
|
||||
public function receive($length, $what = 'data')
|
||||
{
|
||||
$result = '';
|
||||
$chunkSize = $this->chunkSize[self::DIRECTION_RECEIVE];
|
||||
while ($length > 0) {
|
||||
while ($this->isAvailable()) {
|
||||
$fragment = fread($this->stream, min($length, $chunkSize));
|
||||
if ('' != $fragment) {
|
||||
$length -= strlen($fragment);
|
||||
$result .= $fragment;
|
||||
continue 2;
|
||||
} elseif (!$this->isBlocking && !(false === $fragment)) {
|
||||
usleep(3000);
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
throw $this->createException(
|
||||
"Failed while receiving {$what}",
|
||||
4,
|
||||
null,
|
||||
$result
|
||||
);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads from the wrapped stream to receive.
|
||||
*
|
||||
* Reads from the wrapped stream to receive content as a stream.
|
||||
*
|
||||
* @param int $length The number of bytes to receive.
|
||||
* @param FilterCollection $filters A collection of filters to apply to the
|
||||
* stream while receiving. Note that the filters will not be present on
|
||||
* the stream after receiving is done.
|
||||
* @param string $what Descriptive string about what is being
|
||||
* received (used in exception messages).
|
||||
*
|
||||
* @return resource The received content.
|
||||
*/
|
||||
public function receiveStream(
|
||||
$length,
|
||||
FilterCollection $filters = null,
|
||||
$what = 'stream data'
|
||||
) {
|
||||
$result = fopen('php://temp', 'r+b');
|
||||
$appliedFilters = array();
|
||||
if (null !== $filters) {
|
||||
foreach ($filters as $filtername => $params) {
|
||||
$appliedFilters[] = stream_filter_append(
|
||||
$result,
|
||||
$filtername,
|
||||
STREAM_FILTER_WRITE,
|
||||
$params
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$chunkSize = $this->chunkSize[self::DIRECTION_RECEIVE];
|
||||
while ($length > 0) {
|
||||
while ($this->isAvailable()) {
|
||||
$fragment = fread($this->stream, min($length, $chunkSize));
|
||||
if ('' != $fragment) {
|
||||
$length -= strlen($fragment);
|
||||
fwrite($result, $fragment);
|
||||
continue 2;
|
||||
} elseif (!$this->isBlocking && !(false === $fragment)) {
|
||||
usleep(3000);
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($appliedFilters as $filter) {
|
||||
stream_filter_remove($filter);
|
||||
}
|
||||
rewind($result);
|
||||
throw $this->createException(
|
||||
"Failed while receiving {$what}",
|
||||
5,
|
||||
null,
|
||||
$result
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($appliedFilters as $filter) {
|
||||
stream_filter_remove($filter);
|
||||
}
|
||||
rewind($result);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the stream is available for operations.
|
||||
*
|
||||
* For network streams, this means whether the other end has closed the
|
||||
* connection.
|
||||
*
|
||||
* @return bool TRUE if the stream is available, FALSE otherwise.
|
||||
*/
|
||||
public function isAvailable()
|
||||
{
|
||||
return self::isStream($this->stream) && !feof($this->stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether there is data to be read from the wrapped stream.
|
||||
*
|
||||
* @param int|null $sTimeout If theere isn't data awaiting currently,
|
||||
* wait for it this many seconds for data to arrive. If NULL is
|
||||
* specified, wait indefinetly for that.
|
||||
* @param int $usTimeout Microseconds to add to the waiting time.
|
||||
*
|
||||
* @return bool TRUE if there is data to be read, FALSE otherwise.
|
||||
* @SuppressWarnings(PHPMD.ShortVariable)
|
||||
*/
|
||||
public function isDataAwaiting($sTimeout = 0, $usTimeout = 0)
|
||||
{
|
||||
if (self::isStream($this->stream)) {
|
||||
if (null === $sTimeout && !$this->isBlocking) {
|
||||
$meta = stream_get_meta_data($this->stream);
|
||||
return !$meta['eof'];
|
||||
}
|
||||
|
||||
$w = $e = null;
|
||||
$r = array($this->stream);
|
||||
return 1 === @/* due to PHP bug #54563 */stream_select(
|
||||
$r,
|
||||
$w,
|
||||
$e,
|
||||
$sTimeout,
|
||||
$usTimeout
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the wrapped stream can be written to without a block.
|
||||
*
|
||||
* @param int|null $sTimeout If the stream isn't currently accepting data,
|
||||
* wait for it this many seconds to start accepting data. If NULL is
|
||||
* specified, wait indefinetly for that.
|
||||
* @param int $usTimeout Microseconds to add to the waiting time.
|
||||
*
|
||||
* @return bool TRUE if the wrapped stream would not block on a write, FALSE
|
||||
* otherwise.
|
||||
* @SuppressWarnings(PHPMD.ShortVariable)
|
||||
*/
|
||||
public function isAcceptingData($sTimeout = 0, $usTimeout = 0)
|
||||
{
|
||||
if (self::isStream($this->stream)) {
|
||||
if (!$this->isBlocking) {
|
||||
$meta = stream_get_meta_data($this->stream);
|
||||
return !$meta['eof'];
|
||||
} elseif (feof($this->stream)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$r = $e = null;
|
||||
$w = array($this->stream);
|
||||
return 1 === @/* due to PHP bug #54563 */stream_select(
|
||||
$r,
|
||||
$w,
|
||||
$e,
|
||||
$sTimeout,
|
||||
$usTimeout
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the opened stream, unless it's a persistent one.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if ((!$this->persist) && $this->autoClose) {
|
||||
$this->close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the opened stream, even if it is a persistent one.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
return self::isStream($this->stream) && fclose($this->stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new exception.
|
||||
*
|
||||
* Creates a new exception. Used by the rest of the functions in this class.
|
||||
* Override in derived classes for custom exception handling.
|
||||
*
|
||||
* @param string $message The exception message.
|
||||
* @param int $code The exception code.
|
||||
* @param E|null $previous Previous exception thrown,
|
||||
* or NULL if there is none.
|
||||
* @param int|string|resource|null $fragment The fragment up until the
|
||||
* point of failure.
|
||||
* On failure with sending, this is the number of bytes sent
|
||||
* successfully before the failure.
|
||||
* On failure when receiving, this is a string/stream holding
|
||||
* the contents received successfully before the failure.
|
||||
*
|
||||
* @return StreamException The exception to then be thrown.
|
||||
*/
|
||||
protected function createException(
|
||||
$message,
|
||||
$code = 0,
|
||||
E $previous = null,
|
||||
$fragment = null
|
||||
) {
|
||||
return new StreamException($message, $code, $previous, $fragment);
|
||||
}
|
||||
}
|
119
system/autoload/PEAR2/Net/Transmitter/StreamException.php
Normal file
119
system/autoload/PEAR2/Net/Transmitter/StreamException.php
Normal file
@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Wrapper for network stream functionality.
|
||||
*
|
||||
* PHP has built in support for various types of network streams, such as HTTP and TCP sockets. One problem that arises with them is the fact that a single fread/fwrite call might not read/write all the data you intended, regardless of whether you're in blocking mode or not. While the PHP manual offers a workaround in the form of a loop with a few variables, using it every single time you want to read/write can be tedious.
|
||||
|
||||
This package abstracts this away, so that when you want to get exactly N amount of bytes, you can be sure the upper levels of your app will be dealing with N bytes. Oh, and the functionality is nicely wrapped in an object (but that's just the icing on the cake).
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_Transmitter
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Vasil Rangelov
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0a5
|
||||
* @link http://pear2.php.net/PEAR2_Net_Transmitter
|
||||
*/
|
||||
/**
|
||||
* The namespace declaration.
|
||||
*/
|
||||
namespace PEAR2\Net\Transmitter;
|
||||
|
||||
/**
|
||||
* Base for this exception.
|
||||
*/
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* Used to enable any exception in chaining.
|
||||
*/
|
||||
use Exception as E;
|
||||
|
||||
/**
|
||||
* Exception thrown when something goes wrong with the connection.
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_Transmitter
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Net_Transmitter
|
||||
*/
|
||||
class StreamException extends RuntimeException implements Exception
|
||||
{
|
||||
/**
|
||||
* @var int|string|resource|null The fragment up until the point of failure.
|
||||
* On failure with sending, this is the number of bytes sent
|
||||
* successfully before the failure.
|
||||
* On failure when receiving, this is a string/stream holding
|
||||
* the contents received successfully before the failure.
|
||||
* NULL if the failure occured before the operation started.
|
||||
*/
|
||||
protected $fragment = null;
|
||||
|
||||
/**
|
||||
* Creates a new stream exception.
|
||||
*
|
||||
* @param string $message The Exception message to throw.
|
||||
* @param int $code The Exception code.
|
||||
* @param E|null $previous Previous exception thrown,
|
||||
* or NULL if there is none.
|
||||
* @param int|string|resource|null $fragment The fragment up until the
|
||||
* point of failure.
|
||||
* On failure with sending, this is the number of bytes sent
|
||||
* successfully before the failure.
|
||||
* On failure when receiving, this is a string/stream holding
|
||||
* the contents received successfully before the failure.
|
||||
* NULL if the failure occured before the operation started.
|
||||
*/
|
||||
public function __construct(
|
||||
$message,
|
||||
$code,
|
||||
E $previous = null,
|
||||
$fragment = null
|
||||
) {
|
||||
parent::__construct($message, $code, $previous);
|
||||
$this->fragment = $fragment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the stream fragment.
|
||||
*
|
||||
* @return int|string|resource|null The fragment up until the
|
||||
* point of failure.
|
||||
* On failure with sending, this is the number of bytes sent
|
||||
* successfully before the failure.
|
||||
* On failure when receiving, this is a string/stream holding
|
||||
* the contents received successfully before the failure.
|
||||
* NULL if the failure occured before the operation started.
|
||||
*/
|
||||
public function getFragment()
|
||||
{
|
||||
return $this->fragment;
|
||||
}
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
// Unreliable in testing.
|
||||
|
||||
/**
|
||||
* Returns a string representation of the exception.
|
||||
*
|
||||
* @return string The exception as a string.
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
$result = parent::__toString();
|
||||
if (null !== $this->fragment) {
|
||||
$result .= "\nFragment: ";
|
||||
if (is_scalar($this->fragment)) {
|
||||
$result .= (string)$this->fragment;
|
||||
} else {
|
||||
$result .= stream_get_contents($this->fragment);
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
400
system/autoload/PEAR2/Net/Transmitter/TcpClient.php
Normal file
400
system/autoload/PEAR2/Net/Transmitter/TcpClient.php
Normal file
@ -0,0 +1,400 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Wrapper for network stream functionality.
|
||||
*
|
||||
* PHP has built in support for various types of network streams, such as HTTP and TCP sockets. One problem that arises with them is the fact that a single fread/fwrite call might not read/write all the data you intended, regardless of whether you're in blocking mode or not. While the PHP manual offers a workaround in the form of a loop with a few variables, using it every single time you want to read/write can be tedious.
|
||||
|
||||
This package abstracts this away, so that when you want to get exactly N amount of bytes, you can be sure the upper levels of your app will be dealing with N bytes. Oh, and the functionality is nicely wrapped in an object (but that's just the icing on the cake).
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_Transmitter
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Vasil Rangelov
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0a5
|
||||
* @link http://pear2.php.net/PEAR2_Net_Transmitter
|
||||
*/
|
||||
/**
|
||||
* The namespace declaration.
|
||||
*/
|
||||
namespace PEAR2\Net\Transmitter;
|
||||
|
||||
/**
|
||||
* Used for managing persistent connections.
|
||||
*/
|
||||
use PEAR2\Cache\SHM;
|
||||
|
||||
/**
|
||||
* Used for matching arbitrary exceptions in
|
||||
* {@link TcpClient::createException()} and releasing locks properly.
|
||||
*/
|
||||
use Exception as E;
|
||||
|
||||
/**
|
||||
* A socket transmitter.
|
||||
*
|
||||
* This is a convinience wrapper for socket functionality. Used to ensure data
|
||||
* integrity.
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_Transmitter
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Net_Transmitter
|
||||
*/
|
||||
class TcpClient extends NetworkStream
|
||||
{
|
||||
|
||||
/**
|
||||
* @var int The error code of the last error on the socket.
|
||||
*/
|
||||
protected $errorNo = 0;
|
||||
|
||||
/**
|
||||
* @var string The error message of the last error on the socket.
|
||||
*/
|
||||
protected $errorStr = null;
|
||||
|
||||
/**
|
||||
* @var SHM Persistent connection handler. Remains NULL for non-persistent
|
||||
* connections.
|
||||
*/
|
||||
protected $shmHandler = null;
|
||||
|
||||
/**
|
||||
* @var array An array with all connections from this PHP request (as keys)
|
||||
* and their lock state (as a value).
|
||||
*/
|
||||
protected static $lockState = array();
|
||||
|
||||
protected static $cryptoScheme = array(
|
||||
parent::CRYPTO_OFF => 'tcp',
|
||||
parent::CRYPTO_SSL2 => 'sslv2',
|
||||
parent::CRYPTO_SSL3 => 'sslv3',
|
||||
parent::CRYPTO_SSL => 'ssl',
|
||||
parent::CRYPTO_TLS => 'tls'
|
||||
);
|
||||
|
||||
/**
|
||||
* @var string The URI of this connection.
|
||||
*/
|
||||
protected $uri;
|
||||
|
||||
/**
|
||||
* Creates a new connection with the specified options.
|
||||
*
|
||||
* @param string $host Hostname (IP or domain) of the server.
|
||||
* @param int $port The port on the server.
|
||||
* @param bool $persist Whether or not the connection should be a
|
||||
* persistent one.
|
||||
* @param float $timeout The timeout for the connection.
|
||||
* @param string $key A string that uniquely identifies the
|
||||
* connection.
|
||||
* @param string $crypto Encryption setting. Must be one of the
|
||||
* NetworkStream::CRYPTO_* constants. By default, encryption is
|
||||
* disabled. If the setting has an associated scheme for it, it will be
|
||||
* used, and if not, the setting will be adjusted right after the
|
||||
* connection is estabilished.
|
||||
* @param resource $context A context for the socket.
|
||||
*/
|
||||
public function __construct(
|
||||
$host,
|
||||
$port,
|
||||
$persist = false,
|
||||
$timeout = null,
|
||||
$key = '',
|
||||
$crypto = parent::CRYPTO_OFF,
|
||||
$context = null
|
||||
) {
|
||||
$this->streamType = '_CLIENT';
|
||||
|
||||
if (strpos($host, ':') !== false) {
|
||||
$host = "[{$host}]";
|
||||
}
|
||||
$flags = STREAM_CLIENT_CONNECT;
|
||||
if ($persist) {
|
||||
$flags |= STREAM_CLIENT_PERSISTENT;
|
||||
}
|
||||
|
||||
$timeout
|
||||
= null == $timeout ? ini_get('default_socket_timeout') : $timeout;
|
||||
|
||||
$key = rawurlencode($key);
|
||||
|
||||
if (null === $context) {
|
||||
$context = stream_context_get_default();
|
||||
} elseif ((!is_resource($context))
|
||||
|| ('stream-context' !== get_resource_type($context))
|
||||
) {
|
||||
throw $this->createException('Invalid context supplied.', 6);
|
||||
}
|
||||
$hasCryptoScheme = array_key_exists($crypto, static::$cryptoScheme);
|
||||
$scheme = $hasCryptoScheme ? static::$cryptoScheme[$crypto] : 'tcp';
|
||||
$this->uri = "{$scheme}://{$host}:{$port}/{$key}";
|
||||
set_error_handler(array($this, 'handleError'));
|
||||
try {
|
||||
parent::__construct(
|
||||
stream_socket_client(
|
||||
$this->uri,
|
||||
$this->errorNo,
|
||||
$this->errorStr,
|
||||
$timeout,
|
||||
$flags,
|
||||
$context
|
||||
)
|
||||
);
|
||||
restore_error_handler();
|
||||
} catch (E $e) {
|
||||
restore_error_handler();
|
||||
if (0 === $this->errorNo) {
|
||||
throw $this->createException(
|
||||
'Failed to initialize socket.',
|
||||
7,
|
||||
$e
|
||||
);
|
||||
}
|
||||
throw $this->createException(
|
||||
'Failed to connect with socket.',
|
||||
8,
|
||||
$e
|
||||
);
|
||||
}
|
||||
|
||||
if ($hasCryptoScheme) {
|
||||
$this->crypto = $crypto;
|
||||
} elseif (parent::CRYPTO_OFF !== $crypto) {
|
||||
$this->setCrypto($crypto);
|
||||
}
|
||||
$this->setIsBlocking(parent::CRYPTO_OFF === $crypto);
|
||||
|
||||
if ($persist) {
|
||||
$this->shmHandler = SHM::factory(
|
||||
__CLASS__ . ' ' . $this->uri . ' '
|
||||
);
|
||||
self::$lockState[$this->uri] = self::DIRECTION_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new exception.
|
||||
*
|
||||
* Creates a new exception. Used by the rest of the functions in this class.
|
||||
*
|
||||
* @param string $message The exception message.
|
||||
* @param int $code The exception code.
|
||||
* @param E|null $previous Previous exception thrown,
|
||||
* or NULL if there is none.
|
||||
* @param int|string|resource|null $fragment The fragment up until the
|
||||
* point of failure.
|
||||
* On failure with sending, this is the number of bytes sent
|
||||
* successfully before the failure.
|
||||
* On failure when receiving, this is a string/stream holding
|
||||
* the contents received successfully before the failure.
|
||||
*
|
||||
* @return SocketException The exception to then be thrown.
|
||||
*/
|
||||
protected function createException(
|
||||
$message,
|
||||
$code = 0,
|
||||
E $previous = null,
|
||||
$fragment = null
|
||||
) {
|
||||
return new SocketException(
|
||||
$message,
|
||||
$code,
|
||||
$previous,
|
||||
$fragment,
|
||||
$this->errorNo,
|
||||
$this->errorStr
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Locks transmission.
|
||||
*
|
||||
* Locks transmission in one or more directions. Useful when dealing with
|
||||
* persistent connections. Note that every send/receive call implicitly
|
||||
* calls this function and then restores it to the previous state. You only
|
||||
* need to call this function if you need to do an uninterrputed sequence of
|
||||
* such calls.
|
||||
*
|
||||
* @param int $direction The direction(s) to have locked. Acceptable values
|
||||
* are the DIRECTION_* constants. If a lock for a direction can't be
|
||||
* obtained immediatly, the function will block until one is aquired.
|
||||
* Note that if you specify {@link DIRECTION_ALL}, the sending lock will
|
||||
* be obtained before the receiving one, and if obtaining the receiving
|
||||
* lock afterwards fails, the sending lock will be released too.
|
||||
* @param bool $replace Whether to replace all locks with the specified
|
||||
* ones. Setting this to FALSE will make the function only obtain the
|
||||
* locks which are not already obtained.
|
||||
*
|
||||
* @return int|false The previous state or FALSE if the connection is not
|
||||
* persistent or arguments are invalid.
|
||||
*/
|
||||
public function lock($direction = self::DIRECTION_ALL, $replace = false)
|
||||
{
|
||||
if ($this->persist && is_int($direction)) {
|
||||
$old = self::$lockState[$this->uri];
|
||||
|
||||
if ($direction & self::DIRECTION_SEND) {
|
||||
if (($old & self::DIRECTION_SEND)
|
||||
|| $this->shmHandler->lock(self::DIRECTION_SEND)
|
||||
) {
|
||||
self::$lockState[$this->uri] |= self::DIRECTION_SEND;
|
||||
} else {
|
||||
throw new LockException('Unable to obtain sending lock.');
|
||||
}
|
||||
} elseif ($replace) {
|
||||
if (!($old & self::DIRECTION_SEND)
|
||||
|| $this->shmHandler->unlock(self::DIRECTION_SEND)
|
||||
) {
|
||||
self::$lockState[$this->uri] &= ~self::DIRECTION_SEND;
|
||||
} else {
|
||||
throw new LockException('Unable to release sending lock.');
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if ($direction & self::DIRECTION_RECEIVE) {
|
||||
if (($old & self::DIRECTION_RECEIVE)
|
||||
|| $this->shmHandler->lock(self::DIRECTION_RECEIVE)
|
||||
) {
|
||||
self::$lockState[$this->uri] |= self::DIRECTION_RECEIVE;
|
||||
} else {
|
||||
throw new LockException(
|
||||
'Unable to obtain receiving lock.'
|
||||
);
|
||||
}
|
||||
} elseif ($replace) {
|
||||
if (!($old & self::DIRECTION_RECEIVE)
|
||||
|| $this->shmHandler->unlock(self::DIRECTION_RECEIVE)
|
||||
) {
|
||||
self::$lockState[$this->uri]
|
||||
&= ~self::DIRECTION_RECEIVE;
|
||||
} else {
|
||||
throw new LockException(
|
||||
'Unable to release receiving lock.'
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (LockException $e) {
|
||||
if ($direction & self::DIRECTION_SEND
|
||||
&& !($old & self::DIRECTION_SEND)
|
||||
) {
|
||||
$this->shmHandler->unlock(self::DIRECTION_SEND);
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
return $old;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sends a string or stream to the server.
|
||||
*
|
||||
* Sends a string or stream to the server. If a seekable stream is
|
||||
* provided, it will be seeked back to the same position it was passed as,
|
||||
* regardless of the $offset parameter.
|
||||
*
|
||||
* @param string|resource $contents The string or stream to send.
|
||||
* @param int $offset The offset from which to start sending.
|
||||
* If a stream is provided, and this is set to NULL, sending will start
|
||||
* from the current stream position.
|
||||
* @param int $length The maximum length to send. If omitted,
|
||||
* the string/stream will be sent to its end.
|
||||
*
|
||||
* @return int The number of bytes sent.
|
||||
*/
|
||||
public function send($contents, $offset = null, $length = null)
|
||||
{
|
||||
if (false === ($previousState = $this->lock(self::DIRECTION_SEND))
|
||||
&& $this->persist
|
||||
) {
|
||||
throw $this->createException(
|
||||
'Unable to obtain sending lock',
|
||||
10
|
||||
);
|
||||
}
|
||||
try {
|
||||
$result = parent::send($contents, $offset, $length);
|
||||
} catch (E $e) {
|
||||
$this->lock($previousState, true);
|
||||
throw $e;
|
||||
}
|
||||
$this->lock($previousState, true);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives data from the server.
|
||||
*
|
||||
* Receives data from the server as a string.
|
||||
*
|
||||
* @param int $length The number of bytes to receive.
|
||||
* @param string $what Descriptive string about what is being received
|
||||
* (used in exception messages).
|
||||
*
|
||||
* @return string The received content.
|
||||
*/
|
||||
public function receive($length, $what = 'data')
|
||||
{
|
||||
if (false === ($previousState = $this->lock(self::DIRECTION_RECEIVE))
|
||||
&& $this->persist
|
||||
) {
|
||||
throw $this->createException(
|
||||
'Unable to obtain receiving lock',
|
||||
9
|
||||
);
|
||||
}
|
||||
try {
|
||||
$result = parent::receive($length, $what);
|
||||
} catch (E $e) {
|
||||
$this->lock($previousState, true);
|
||||
throw $e;
|
||||
}
|
||||
$this->lock($previousState, true);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives data from the server.
|
||||
*
|
||||
* Receives data from the server as a stream.
|
||||
*
|
||||
* @param int $length The number of bytes to receive.
|
||||
* @param FilterCollection $filters A collection of filters to apply to the
|
||||
* stream while receiving. Note that the filters will not be present on
|
||||
* the stream after receiving is done.
|
||||
* @param string $what Descriptive string about what is being
|
||||
* received (used in exception messages).
|
||||
*
|
||||
* @return resource The received content.
|
||||
*/
|
||||
public function receiveStream(
|
||||
$length,
|
||||
FilterCollection $filters = null,
|
||||
$what = 'stream data'
|
||||
) {
|
||||
if (false === ($previousState = $this->lock(self::DIRECTION_RECEIVE))
|
||||
&& $this->persist
|
||||
) {
|
||||
throw $this->createException(
|
||||
'Unable to obtain receiving lock',
|
||||
9
|
||||
);
|
||||
}
|
||||
try {
|
||||
$result = parent::receiveStream($length, $filters, $what);
|
||||
} catch (E $e) {
|
||||
$this->lock($previousState, true);
|
||||
throw $e;
|
||||
}
|
||||
$this->lock($previousState, true);
|
||||
return $result;
|
||||
}
|
||||
}
|
147
system/autoload/PEAR2/Net/Transmitter/TcpServerConnection.php
Normal file
147
system/autoload/PEAR2/Net/Transmitter/TcpServerConnection.php
Normal file
@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Wrapper for network stream functionality.
|
||||
*
|
||||
* PHP has built in support for various types of network streams, such as HTTP and TCP sockets. One problem that arises with them is the fact that a single fread/fwrite call might not read/write all the data you intended, regardless of whether you're in blocking mode or not. While the PHP manual offers a workaround in the form of a loop with a few variables, using it every single time you want to read/write can be tedious.
|
||||
|
||||
This package abstracts this away, so that when you want to get exactly N amount of bytes, you can be sure the upper levels of your app will be dealing with N bytes. Oh, and the functionality is nicely wrapped in an object (but that's just the icing on the cake).
|
||||
*
|
||||
* PHP version 5
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_Transmitter
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @copyright 2011 Vasil Rangelov
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @version 1.0.0a5
|
||||
* @link http://pear2.php.net/PEAR2_Net_Transmitter
|
||||
*/
|
||||
/**
|
||||
* The namespace declaration.
|
||||
*/
|
||||
namespace PEAR2\Net\Transmitter;
|
||||
|
||||
use Exception as E;
|
||||
|
||||
/**
|
||||
* A transmitter for connections to a socket server.
|
||||
*
|
||||
* This is a convinience wrapper for functionality of socket server connections.
|
||||
* Used to ensure data integrity. Server handling is not part of the class in
|
||||
* order to allow its usage as part of various server implementations (e.g. fork
|
||||
* and/or sequential).
|
||||
*
|
||||
* @category Net
|
||||
* @package PEAR2_Net_Transmitter
|
||||
* @author Vasil Rangelov <boen.robot@gmail.com>
|
||||
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
|
||||
* @link http://pear2.php.net/PEAR2_Net_Transmitter
|
||||
*/
|
||||
class TcpServerConnection extends NetworkStream
|
||||
{
|
||||
|
||||
/**
|
||||
* @var string The IP address of the connected client.
|
||||
*/
|
||||
protected $peerIP;
|
||||
|
||||
/**
|
||||
* @var int The port of the connected client.
|
||||
*/
|
||||
protected $peerPort;
|
||||
|
||||
/**
|
||||
* Creates a new connection with the specified options.
|
||||
*
|
||||
* @param resource $server A socket server, created with
|
||||
* {@link stream_socket_server()}.
|
||||
* @param float $timeout The timeout for the connection.
|
||||
*/
|
||||
public function __construct($server, $timeout = null)
|
||||
{
|
||||
$this->streamType = '_SERVER';
|
||||
|
||||
if (!self::isStream($server)) {
|
||||
throw $this->createException('Invalid server supplied.', 9);
|
||||
}
|
||||
$timeout
|
||||
= null == $timeout ? ini_get('default_socket_timeout') : $timeout;
|
||||
|
||||
set_error_handler(array($this, 'handleError'));
|
||||
try {
|
||||
parent::__construct(
|
||||
stream_socket_accept($server, $timeout, $peername)
|
||||
);
|
||||
restore_error_handler();
|
||||
$portString = strrchr($peername, ':');
|
||||
$this->peerPort = (int) substr($portString, 1);
|
||||
$ipString = substr(
|
||||
$peername,
|
||||
0,
|
||||
strlen($peername) - strlen($portString)
|
||||
);
|
||||
if (strpos($ipString, '[') === 0
|
||||
&& strpos(strrev($ipString), ']') === 0
|
||||
) {
|
||||
$ipString = substr($ipString, 1, strlen($ipString) - 2);
|
||||
}
|
||||
$this->peerIP = $ipString;
|
||||
} catch (E $e) {
|
||||
restore_error_handler();
|
||||
throw $this->createException(
|
||||
'Failed to initialize connection.',
|
||||
10,
|
||||
$e
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the IP address of the connected client.
|
||||
*
|
||||
* @return string The IP address of the connected client.
|
||||
*/
|
||||
public function getPeerIP()
|
||||
{
|
||||
return $this->peerIP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the port of the connected client.
|
||||
*
|
||||
* @return int The port of the connected client.
|
||||
*/
|
||||
public function getPeerPort()
|
||||
{
|
||||
return $this->peerPort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new exception.
|
||||
*
|
||||
* Creates a new exception. Used by the rest of the functions in this class.
|
||||
*
|
||||
* @param string $message The exception message.
|
||||
* @param int $code The exception code.
|
||||
* @param E|null $previous Previous exception thrown, or NULL if there
|
||||
* is none.
|
||||
* @param string|null $fragment The fragment up until the point of failure.
|
||||
* NULL if the failure occured before the operation started.
|
||||
*
|
||||
* @return SocketException The exception to then be thrown.
|
||||
*/
|
||||
protected function createException(
|
||||
$message,
|
||||
$code = 0,
|
||||
E $previous = null,
|
||||
$fragment = null
|
||||
) {
|
||||
return new SocketException(
|
||||
$message,
|
||||
$code,
|
||||
$previous,
|
||||
$fragment
|
||||
);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user