forked from kevinowino869/mitrobill
update PEAR
This commit is contained in:
@ -2,17 +2,18 @@
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @version 1.0.0b6
|
||||
* @link http://pear2.php.net/PEAR2_Net_RouterOS
|
||||
*/
|
||||
/**
|
||||
@ -27,13 +28,13 @@ 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
|
||||
* package, this class doesn't provide any conveniences 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>
|
||||
@ -47,67 +48,76 @@ 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.
|
||||
* An array with the default charset.
|
||||
*
|
||||
* Charset types as keys, and the default charsets as values.
|
||||
*
|
||||
* @var array<string,string|null>
|
||||
*/
|
||||
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.
|
||||
* An array with the current charset.
|
||||
*
|
||||
* Charset types as keys, and the current charsets as values.
|
||||
*
|
||||
* @var array<string,string|null>
|
||||
*/
|
||||
protected $charsets = array();
|
||||
|
||||
/**
|
||||
* @var T\TcpClient The transmitter for the connection.
|
||||
* The transmitter for the connection.
|
||||
*
|
||||
* @var T\TcpClient
|
||||
*/
|
||||
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
|
||||
*
|
||||
* @param string $host Hostname (IP or domain) of RouterOS.
|
||||
* @param int|null $port The port on which the RouterOS host
|
||||
* 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
|
||||
* @param double|null $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.
|
||||
*
|
||||
* @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|null $context A context for the socket.
|
||||
*
|
||||
* @see sendWord()
|
||||
*/
|
||||
public function __construct(
|
||||
@ -126,7 +136,16 @@ class Communicator
|
||||
if (!isset($opts['ssl']['ciphers'])
|
||||
|| 'DEFAULT' === $opts['ssl']['ciphers']
|
||||
) {
|
||||
stream_context_set_option($context, 'ssl', 'ciphers', 'ADH');
|
||||
stream_context_set_option(
|
||||
$context,
|
||||
array(
|
||||
'ssl' => array(
|
||||
'ciphers' => 'ADH',
|
||||
'verify_peer' => false,
|
||||
'verify_peer_name' => false
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
// @codeCoverageIgnoreStart
|
||||
@ -158,31 +177,31 @@ class Communicator
|
||||
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.
|
||||
*
|
||||
*
|
||||
* @param string|null $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.
|
||||
* sent, otherwise returns 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)
|
||||
@ -193,16 +212,16 @@ class Communicator
|
||||
}
|
||||
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.
|
||||
@ -216,22 +235,25 @@ class Communicator
|
||||
'convert.iconv.' . $inCharset . '.' . $outCharset,
|
||||
STREAM_FILTER_WRITE
|
||||
);
|
||||
|
||||
|
||||
flock($stream, LOCK_SH);
|
||||
while (!feof($stream)) {
|
||||
$bytes += stream_copy_to_stream($stream, $result, 0xFFFFF);
|
||||
$reader = new T\Stream($stream, false);
|
||||
$writer = new T\Stream($result, false);
|
||||
$chunkSize = $reader->getChunk(T\Stream::DIRECTION_RECEIVE);
|
||||
while ($reader->isAvailable() && $reader->isDataAwaiting()) {
|
||||
$bytes += $writer->send(fread($stream, $chunkSize));
|
||||
}
|
||||
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
|
||||
@ -239,10 +261,11 @@ class Communicator
|
||||
* @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(
|
||||
@ -263,17 +286,18 @@ class Communicator
|
||||
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)
|
||||
@ -284,12 +308,12 @@ class Communicator
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@ -302,17 +326,17 @@ class Communicator
|
||||
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
|
||||
* Setting NULL to either charset will disable charset conversion, 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
|
||||
@ -320,10 +344,11 @@ class Communicator
|
||||
* @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)
|
||||
@ -342,17 +367,18 @@ class Communicator
|
||||
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()
|
||||
*/
|
||||
@ -364,7 +390,7 @@ class Communicator
|
||||
|
||||
/**
|
||||
* Gets the transmitter for this connection.
|
||||
*
|
||||
*
|
||||
* @return T\TcpClient The transmitter for this connection.
|
||||
*/
|
||||
public function getTransmitter()
|
||||
@ -374,12 +400,13 @@ class Communicator
|
||||
|
||||
/**
|
||||
* 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()
|
||||
*/
|
||||
@ -407,16 +434,17 @@ class Communicator
|
||||
|
||||
/**
|
||||
* 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)
|
||||
@ -441,31 +469,31 @@ class Communicator
|
||||
$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)
|
||||
public static function verifyLengthSupport($length)
|
||||
{
|
||||
if ($length > 0xFFFFFFFF) {
|
||||
throw new LengthException(
|
||||
@ -478,10 +506,10 @@ class Communicator
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the length as requred by the RouterOS API.
|
||||
*
|
||||
* Encodes the length as required by the RouterOS API.
|
||||
*
|
||||
* @param int $length The length to encode.
|
||||
*
|
||||
*
|
||||
* @return string The encoded length.
|
||||
*/
|
||||
public static function encodeLength($length)
|
||||
@ -519,11 +547,12 @@ class Communicator
|
||||
|
||||
/**
|
||||
* 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()
|
||||
@ -541,7 +570,7 @@ class Communicator
|
||||
'word'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
if (null !== ($remoteCharset = $this->getCharset(self::CHARSET_REMOTE))
|
||||
&& null !== ($localCharset = $this->getCharset(self::CHARSET_LOCAL))
|
||||
) {
|
||||
@ -551,17 +580,18 @@ class Communicator
|
||||
$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()
|
||||
@ -575,7 +605,7 @@ class Communicator
|
||||
$remoteCharset . '.' . $localCharset . '//IGNORE//TRANSLIT'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
if ($this->trans->isPersistent()) {
|
||||
$old = $this->trans->lock(T\Stream::DIRECTION_RECEIVE);
|
||||
$stream = $this->trans->receiveStream(
|
||||
@ -591,20 +621,21 @@ class Communicator
|
||||
'stream word'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
return $stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes the lenght of the incoming message.
|
||||
*
|
||||
* Decodes the lenght of the incoming message, as specified by the RouterOS
|
||||
* Decodes the length of the incoming message.
|
||||
*
|
||||
* Decodes the length 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.
|
||||
*
|
||||
* @return int|double The decoded length.
|
||||
* Is of type "double" only for values above "2 << 31".
|
||||
*/
|
||||
public static function decodeLength(T\Stream $trans)
|
||||
{
|
||||
@ -618,18 +649,19 @@ class Communicator
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes the lenght of the incoming message.
|
||||
*
|
||||
* Decodes the lenght of the incoming message, as specified by the RouterOS
|
||||
* Decodes the length of the incoming message.
|
||||
*
|
||||
* Decodes the length 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.
|
||||
*
|
||||
* @return int|double The decoded length.
|
||||
* Is of type "double" only for values above "2 << 31".
|
||||
*/
|
||||
private static function _decodeLength(T\Stream $trans)
|
||||
{
|
||||
@ -661,7 +693,7 @@ class Communicator
|
||||
|
||||
/**
|
||||
* Closes the opened connection, even if it is a persistent one.
|
||||
*
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure.
|
||||
*/
|
||||
public function close()
|
||||
|
Reference in New Issue
Block a user