Skip to content

Commit de8cd0b

Browse files
committed
Workaround for sudden exceptions when the last command is /system/reboot;
Countable objects now implement the $mode argument; Renamed changeMenu() to setMenu(), and added getMenu() for the purpose of chaneMenu() with an empty string; Tweaked the VM settings, so that one arrives quicker at the copy&paste phase; Moved the test callback into a separate file, thus making the tests no longer requiring allow_url_fopen; CS and MD fixes (argument renames, mostly).
1 parent 55979f3 commit de8cd0b

22 files changed

+390
-212
lines changed

.scrutinizer.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
imports:
22
- php
33
inherit: true
4+
before_commands:
5+
- composer require pear2/net_transmitter:dev-develop
6+
- composer require pear2/cache_shm:dev-develop
7+
- composer require pear2/console_commandline
8+
- composer require pear2/console_color
49
tools:
510
php_sim: false
611
php_cpd: true
712
php_code_sniffer:
813
config:
9-
standard: PEAR
14+
standard: PEAR

RELEASE-1.0.0b5

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,20 @@ Console and some overall improvements.
44
* __BREAKING CHANGES:__
55
- Removed Message::getAllArguments() in favor of IteratorAggregate implementation that returns an ArrayObject. For most intents and purposes, you should be able to just search&replace "->getAllArguments()" with an empty string (that will implicitly call getIterator()). If you require the arguments as a "real" array, you can replace "->getAllArguments()" with "->getIterator()->getArrayCopy()".
66
- Message::\_\_invoke() without arguments is now a shortcut for getTag() instead of getting all arguments.
7-
- Util::changeMenu() now returns the Util object itself, except when you supply an empty string, when the current menu is returned (as before).
7+
- Util::changeMenu() is now renamed to Util::setMenu() and always returns the Util object itself.
88
* New Util methods:
9-
- getall()
10-
- count()
9+
- getMenu() (serves the same purpose as previously Util::changeMenu() with an emptry string)
10+
- getAll()
11+
- count() (implementation of Countable, reports the number of items at the current menu)
1112
- prepareScript()
12-
* Message now implements Countable, reporting the number of arguments.
13+
* Message now implements Countable, reporting the number of arguments (on COUNTER_NORMAL) or words (on COUNT_RECURSIVE).
1314
* Util::get() now uses RouterOS' "get" command, unless it returns an empty !done response (as it does for RouterOS versions prior to 6.0), in which case it automatically fallbacks to a print with a query.
1415
* Util::escapeValue() and Util::parseValue() now support associative arrays (introduced in RouterOS 6.2).
1516
* Util::escapeValue() now correctly converts DateTime objects to DateInterval objects relative to UNIX epoch time in UTC. Previously, the current time zone was used instead of UTC.
1617
* Util::add() and Util::set()/Util::edit() now support flags as values with a numeric key.
1718
* ResponseCollection can now be searched by argument values, if you first designate an argument name with the new ResponseCollection::setIndex() method.
1819
* ResponseCollection can now produce a sorted response collection based on user defined criteria using the new ResponseCollection::orderBy() method.
20+
* Util::find() now always returns a comma separated list when used without arguments (as opposed to ";" separated, in more recent RouterOS versions).
21+
* Response receiving now resets if an empty sentence is received, instead of throwing an exception.
1922
* Doc fixes (Notably: Clarified the acceptability of seekable streams as argument values, which has been present for a long time, but never documented).
2023
* CS fixes.

composer.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,12 @@
2121
},
2222
"require-dev": {
2323
"phpunit/phpunit": "@stable",
24-
"squizlabs/php_codesniffer": "@stable",
25-
"scrutinizer/php-analyzer": "dev-master"
24+
"squizlabs/php_codesniffer": "@stable"
2625
},
2726
"suggest": {
2827
"pear2/cache_shm": "Enables persistent connections.",
28+
"pear2/console_commandline": "Enables the console",
29+
"pear2/console_color": "Enables colors in the console",
2930
"ext-apc": "This or Wincache is required for persistent connections.",
3031
"ext-wincache": "This or APC is required for persistent connections. Reccomended instead of APC on Windows.",
3132
"ext-openssl": "Enables encrypted connections."

src/PEAR2/Net/RouterOS/Client.php

Lines changed: 43 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -527,41 +527,41 @@ public function extractNewResponses($tag = null)
527527
* are no more pending requests or when a specified timeout has passed
528528
* (whichever comes first).
529529
*
530-
* @param int $timeout_s Timeout for the loop. If NULL, there is no time
530+
* @param int $timeoutS Timeout for the loop. If NULL, there is no time
531531
* limit.
532-
* @param int $timeout_us Microseconds to add to the time limit.
532+
* @param int $timeoutUs Microseconds to add to the time limit.
533533
*
534534
* @return bool TRUE when there are any more pending requests, FALSE
535535
* otherwise.
536536
* @see extractNewResponses()
537537
* @see getPendingRequestsCount()
538538
*/
539-
public function loop($timeout_s = null, $timeout_us = 0)
539+
public function loop($timeoutS = null, $timeoutUs = 0)
540540
{
541541
try {
542-
if (null === $timeout_s) {
542+
if (null === $timeoutS) {
543543
while ($this->getPendingRequestsCount() !== 0) {
544544
$this->dispatchNextResponse(null);
545545
}
546546
} else {
547-
list($start_us, $start_s) = explode(' ', microtime());
547+
list($startUs, $startS) = explode(' ', microtime());
548548
while ($this->getPendingRequestsCount() !== 0
549-
&& ($timeout_s >= 0 || $timeout_us >= 0)
549+
&& ($timeoutS >= 0 || $timeoutUs >= 0)
550550
) {
551-
$this->dispatchNextResponse($timeout_s, $timeout_us);
552-
list($end_us, $end_s) = explode(' ', microtime());
553-
554-
$timeout_s -= $end_s - $start_s;
555-
$timeout_us -= $end_us - $start_us;
556-
if ($timeout_us <= 0) {
557-
if ($timeout_s > 0) {
558-
$timeout_us = 1000000 + $timeout_us;
559-
$timeout_s--;
551+
$this->dispatchNextResponse($timeoutS, $timeoutUs);
552+
list($endUs, $endS) = explode(' ', microtime());
553+
554+
$timeoutS -= $endS - $startS;
555+
$timeoutUs -= $endUs - $startUs;
556+
if ($timeoutUs <= 0) {
557+
if ($timeoutS > 0) {
558+
$timeoutUs = 1000000 + $timeoutUs;
559+
$timeoutS--;
560560
}
561561
}
562562

563-
$start_s = $end_s;
564-
$start_us = $end_us;
563+
$startS = $endS;
564+
$startUs = $endUs;
565565
}
566566
}
567567
} catch (SocketException $e) {
@@ -706,25 +706,34 @@ public function isStreamingResponses()
706706
public function close()
707707
{
708708
$result = true;
709-
try {
710-
if ($this->com->getTransmitter()->getCrypto() === N::CRYPTO_OFF) {
711-
if (null !== $this->registry) {
712-
$this->registry->setTaglessMode(true);
713-
}
709+
/*
710+
* The check below is done because for some unknown reason
711+
* (either a PHP or a RouterOS bug) calling "/quit" on an encrypted
712+
* connection makes one end hang.
713+
*
714+
* Since encrypted connections only appeared in RouterOS 6.1, and
715+
* the "/quit" call is needed for all <6.0 versions, problems due
716+
* to its absence should be limited to some earlier 6.* versions
717+
* on some RouterBOARD devices.
718+
*/
719+
if ($this->com->getTransmitter()->getCrypto() === N::CRYPTO_OFF) {
720+
if (null !== $this->registry) {
721+
$this->registry->setTaglessMode(true);
722+
}
723+
try {
714724
$response = $this->sendSync(new Request('/quit'));
715-
if (null !== $this->registry) {
716-
$this->registry->setTaglessMode(false);
717-
}
718725
$result = $response[0]->getType() === Response::TYPE_FATAL;
726+
} catch (SocketException $e) {
727+
$result
728+
= $e->getCode() === SocketException::CODE_REQUEST_SEND_FAIL;
729+
} catch (E $e) {
730+
//Ignore unknown errors.
719731
}
720-
$result = $result && $this->com->close();
721-
} catch (SocketException $e) {
722-
$result
723-
= $e->getCode() === SocketException::CODE_UNACCEPTING_REQEUST;
724732
if (null !== $this->registry) {
725733
$this->registry->setTaglessMode(false);
726734
}
727735
}
736+
$result = $result && $this->com->close();
728737
$this->callbacks = array();
729738
$this->pendingRequestsCount = 0;
730739
return $result;
@@ -766,20 +775,20 @@ protected function send(Request $request)
766775
* Dispatches the next response in queue, i.e. it executes the associated
767776
* callback if there is one, or places the response in the response buffer.
768777
*
769-
* @param int $timeout_s If a response is not immediatly available, wait
778+
* @param int $timeoutS If a response is not immediatly available, wait
770779
* this many seconds. If NULL, wait indefinetly.
771-
* @param int $timeout_us Microseconds to add to the waiting time.
780+
* @param int $timeoutUs Microseconds to add to the waiting time.
772781
*
773782
* @throws SocketException When there's no response within the time limit.
774783
* @return Response The dispatched response.
775784
*/
776-
protected function dispatchNextResponse($timeout_s = 0, $timeout_us = 0)
785+
protected function dispatchNextResponse($timeoutS = 0, $timeoutUs = 0)
777786
{
778787
$response = new Response(
779788
$this->com,
780789
$this->_streamingResponses,
781-
$timeout_s,
782-
$timeout_us,
790+
$timeoutS,
791+
$timeoutUs,
783792
$this->registry
784793
);
785794
if ($response->getType() === Response::TYPE_FATAL) {

src/PEAR2/Net/RouterOS/Communicator.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -197,21 +197,21 @@ public static function isSeekableStream($var)
197197
/**
198198
* Uses iconv to convert a stream from one charset to another.
199199
*
200-
* @param string $in_charset The charset of the stream.
201-
* @param string $out_charset The desired resulting charset.
202-
* @param resource $stream The stream to convert.
200+
* @param string $inCharset The charset of the stream.
201+
* @param string $outCharset The desired resulting charset.
202+
* @param resource $stream The stream to convert.
203203
*
204204
* @return resource A new stream that uses the $out_charset. The stream is a
205205
* subset from the original stream, from its current position to its
206206
* end.
207207
*/
208-
public static function iconvStream($in_charset, $out_charset, $stream)
208+
public static function iconvStream($inCharset, $outCharset, $stream)
209209
{
210210
$bytes = 0;
211211
$result = fopen('php://temp', 'r+b');
212212
$iconvFilter = stream_filter_append(
213213
$result,
214-
'convert.iconv.' . $in_charset . '.' . $out_charset,
214+
'convert.iconv.' . $inCharset . '.' . $outCharset,
215215
STREAM_FILTER_WRITE
216216
);
217217

src/PEAR2/Net/RouterOS/Message.php

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,10 @@ abstract class Message implements IteratorAggregate, Countable
6666
* the class is invoked and its returned value is returned by this function.
6767
*
6868
* @param string $name The name of an argument to get the value of, or NULL
69-
* to get all arguments as an array.
69+
* to get the tag.
7070
*
71-
* @return string|array The value of the specified argument, or an array of
72-
* all arguments if NULL is provided.
71+
* @return string|resource The value of the specified argument,
72+
* or the tag if NULL is provided.
7373
*/
7474
public function __invoke($name = null)
7575
{
@@ -178,11 +178,20 @@ public function getIterator()
178178
/**
179179
* Counts the number of arguments.
180180
*
181-
* @return int The number of arguments.
181+
* @param int $mode The counter mode.
182+
* Either COUNT_NORMAL or COUNT_RECURSIVE.
183+
* When in normal mode, counts the number of arguments.
184+
* When in recursive mode, counts the number of API words.
185+
*
186+
* @return int The number of arguments/words.
182187
*/
183-
public function count()
188+
public function count($mode = COUNT_NORMAL)
184189
{
185-
return count($this->arguments);
190+
$result = count($this->arguments);
191+
if ($mode !== COUNT_NORMAL) {
192+
$result += 2/*first+last word*/ + (int)(string)$this->getTag();
193+
}
194+
return $result;
186195
}
187196

188197
/**

src/PEAR2/Net/RouterOS/Query.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ private function _send(Communicator $com)
213213
if (!$com->getTransmitter()->isAcceptingData()) {
214214
throw new SocketException(
215215
'Transmitter is invalid. Sending aborted.',
216-
SocketException::CODE_UNACCEPTING_QUERY
216+
SocketException::CODE_QUERY_SEND_FAIL
217217
);
218218
}
219219
$bytes = 0;

src/PEAR2/Net/RouterOS/Request.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class Request extends Message
6262
*/
6363
public function __construct($command, Query $query = null, $tag = null)
6464
{
65-
if (false !== ($firstEquals = strpos($command, '='))
65+
if (false !== strpos($command, '=')
6666
&& false !== ($spaceBeforeEquals = strrpos(
6767
strstr($command, '=', true),
6868
' '
@@ -83,13 +83,14 @@ public function __construct($command, Query $query = null, $tag = null)
8383
* function. Depending on the argument given, one of the other functions in
8484
* the class is invoked and its returned value is returned by this function.
8585
*
86-
* @param mixed $arg A {@link Query} to associate the request
87-
* with, a {@link Communicator} to send the request over, an argument to
88-
* get the value of, or NULL to get all arguments as an array. If a
86+
* @param Query|Communicator|string|null $arg A {@link Query} to associate
87+
* the request with, a {@link Communicator} to send the request over,
88+
* an argument to get the value of, or NULL to get the tag. If a
8989
* second argument is provided, this becomes the name of the argument to
9090
* set the value of, and the second argument is the value to set.
9191
*
92-
* @return mixed Whatever the long form function would have returned.
92+
* @return string|resource|int|$this Whatever the long form
93+
* function returns.
9394
*/
9495
public function __invoke($arg = null)
9596
{
@@ -291,7 +292,7 @@ private function _send(Communicator $com)
291292
if (!$com->getTransmitter()->isAcceptingData()) {
292293
throw new SocketException(
293294
'Transmitter is invalid. Sending aborted.',
294-
SocketException::CODE_UNACCEPTING_REQEUST
295+
SocketException::CODE_REQUEST_SEND_FAIL
295296
);
296297
}
297298
$bytes = 0;

0 commit comments

Comments
 (0)