Skip to content

Commit 68a0459

Browse files
committed
Added a color to the console's "SEND" verbose prompt;
Added "-- " as a prefix to non-verbose console messages (inspired by the MikroTik wiki example); Util::escapeValue() now uses a timestamp for the unix epoch, as opposed to a formatted string, eliminating any timezone issues; Adjusted Util::get() to try a "/get" command, before reverting to a print request (which now uses Util::getall()); Console's multiline mode now works as expected - EOL,\03,\03,EOL results in EOL,\03, allowing the user to write out EOL,\03,\03 as EOL,\03,\03,EOL,\03,\03,EOL; bootstrap.php now explicitly sets CWD.
1 parent 5611fea commit 68a0459

File tree

4 files changed

+126
-110
lines changed

4 files changed

+126
-110
lines changed

bin/roscon.php

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -319,8 +319,11 @@
319319
);
320320
}
321321

322+
$dislayedLength = $length > 9999999999
323+
? '0x' . strtoupper(dechex($length))
324+
: $length;
322325
$details = str_pad(
323-
'0x' . strtoupper(dechex($length)),
326+
$dislayedLength,
324327
$c_columns['length'],
325328
' ',
326329
STR_PAD_LEFT
@@ -356,7 +359,7 @@
356359
}
357360
: function ($mode, $word, $msg = '') use ($c_colors) {
358361
if ('ERR' === $mode || 'NOTE' === $mode) {
359-
fwrite(STDERR, "{$c_colors[$mode]}{$msg}");
362+
fwrite(STDERR, "{$c_colors[$mode]}-- {$msg}");
360363
if ('' !== $word) {
361364
fwrite(STDERR, ": {$word}");
362365
}
@@ -383,11 +386,13 @@
383386
while (true) {
384387
if ($cmd->options['verbose']) {
385388
fwrite(
386-
STDOUT,
389+
STDOUT,
387390
implode(
388391
$c_sep,
389392
array(
390-
str_pad('SEND', $c_columns['mode'], ' ', STR_PAD_RIGHT),
393+
$c_colors['SEND'] .
394+
str_pad('SEND', $c_columns['mode'], ' ', STR_PAD_RIGHT)
395+
. $c_colors[''],
391396
str_pad(
392397
'<prompt>',
393398
$c_columns['length'],
@@ -409,42 +414,36 @@
409414
fwrite(STDOUT, $c_colors['SEND']);
410415

411416
if ($cmd->options['multiline']) {
412-
$line = stream_get_line(STDIN, PHP_INT_MAX, PHP_EOL);
413-
if (chr(3) !== $line) {
414-
if ('' === $line) {
415-
$word .= PHP_EOL;
417+
while (true) {
418+
$line = stream_get_line(STDIN, PHP_INT_MAX, PHP_EOL);
419+
if (chr(3) === $line) {
420+
break;
421+
}
422+
if ((chr(3) . chr(3)) === $line) {
423+
$word .= chr(3);
416424
} else {
417-
$word .= $line;
425+
$word .= $line . PHP_EOL;
418426
}
419-
while (true) {
420-
if ($cmd->options['verbose']) {
421-
fwrite(
422-
STDOUT,
423-
"\n{$c_colors['']}" .
424-
implode(
425-
$c_sep,
426-
array(
427-
str_repeat(' ', $c_columns['mode']),
428-
str_repeat(' ', $c_columns['length']),
429-
str_repeat(' ', $c_columns['encodedLength']),
430-
''
431-
)
427+
if ($cmd->options['verbose']) {
428+
fwrite(
429+
STDOUT,
430+
"\n{$c_colors['']}" .
431+
implode(
432+
$c_sep,
433+
array(
434+
str_repeat(' ', $c_columns['mode']),
435+
str_repeat(' ', $c_columns['length']),
436+
str_repeat(' ', $c_columns['encodedLength']),
437+
''
432438
)
433-
. $c_colors['SEND']
434-
);
435-
}
436-
$line = stream_get_line(STDIN, PHP_INT_MAX, PHP_EOL);
437-
if (chr(3) === $line) {
438-
break;
439-
}
440-
$word .= PHP_EOL;
441-
if ((chr(3) . chr(3)) === $line) {
442-
$word .= chr(3);
443-
} else {
444-
$word .= $line;
445-
}
439+
)
440+
. $c_colors['SEND']
441+
);
446442
}
447443
}
444+
if ('' !== $word) {
445+
$word = substr($word, 0, -strlen(PHP_EOL));
446+
}
448447
} else {
449448
$word = stream_get_line(STDIN, PHP_INT_MAX, PHP_EOL);
450449
}
@@ -459,7 +458,10 @@
459458
break;
460459
}
461460
if ('' === $word) {
462-
if ('s' === $cmd->options['commandMode'] || '' === $prevWord) {
461+
if ('s' === $cmd->options['commandMode']) {
462+
break;
463+
} elseif ('' === $prevWord) {//'e' === $cmd->options['commandMode']
464+
array_pop($words);
463465
break;
464466
}
465467
}
@@ -479,7 +481,7 @@
479481
$printWord(
480482
'ERR',
481483
substr($word, 0, $e->getFragment()),
482-
"Partial word sent"
484+
'Partial word sent'
483485
);
484486
}
485487
}

data/roscon.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ Defaults to PHP's default_socket_timeout ini option.</description>
6565
<description>Mode to send commands in. Can be one of:
6666
"w" - send every word as soon as it is entered
6767
"s" - wait for a sentence to be formed, and send all its words then
68-
"e" - wait for an empty sentence, and send all of the sentences then.
68+
"e" - wait for an empty sentence, and send all previous sentences then. You can send an empty sentence by sending two consecutive empty words.
6969
(Default: "s")
7070
</description>
7171
<action>StoreString</action>

src/PEAR2/Net/RouterOS/Util.php

Lines changed: 84 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public static function parseValue($value)
9292
{
9393
$value = (string)$value;
9494

95-
if ('' === $value) {
95+
if (in_array($value, array('', 'nil'), true)) {
9696
return null;
9797
} elseif (in_array($value, array('true', 'false', 'yes', 'no'), true)) {
9898
return $value === 'true' || $value === 'yes';
@@ -207,7 +207,7 @@ public static function escapeValue($value)
207207
if ('000000' === $usec) {
208208
unset($usec);
209209
}
210-
$unixEpoch = new DateTime('1970-01-01 00:00:00.000000');
210+
$unixEpoch = new DateTime('@0');
211211
$value = $unixEpoch->diff($value);
212212
}
213213
if ($value instanceof DateInterval) {
@@ -480,7 +480,7 @@ public function find()
480480
*
481481
* @return string|null|bool The value of the specified property. If the
482482
* property is not set, NULL will be returned. If no such item exists,
483-
* FALSE will be returned.
483+
* or the property name is not valid, FALSE will be returned.
484484
*/
485485
public function get($number, $value_name)
486486
{
@@ -493,16 +493,28 @@ public function get($number, $value_name)
493493
}
494494
}
495495

496-
$request = new Request($this->menu . '/print');
496+
//For new RouterOS versions
497+
$request = new Request($this->menu . '/get');
498+
$request->setArgument('number', $number);
499+
$request->setArgument('value-name', $value_name);
500+
$responses = $this->client->sendSync($request);
501+
if (Response::TYPE_ERROR === $responses->getType()) {
502+
return false;
503+
}
504+
$result = $responses->getArgument('ret');
505+
if (null !== $result) {
506+
return $result;
507+
}
508+
509+
// The "get" of old RouterOS versions return an empty !done response.
510+
// This is a backup for them, although this should also execute on new
511+
// versions when a valid property is not set.
512+
$query = null;
497513
if (null !== $number) {
498514
$number = (string)$number;
499-
$request->setQuery(
500-
Query::where('.id', $number)->orWhere('name', $number)
501-
);
515+
$query = Query::where('.id', $number)->orWhere('name', $number);
502516
}
503-
$request->setArgument('.proplist', $value_name);
504-
$responses = $this->client->sendSync($request)
505-
->getAllOfType(Response::TYPE_DATA);
517+
$responses = $this->getall(array('.proplist' => $value_name), $query);
506518

507519
if (0 === count($responses)) {
508520
return false;
@@ -691,6 +703,68 @@ public function move($numbers, $destination)
691703
return $this->client->sendSync($moveRequest);
692704
}
693705

706+
/**
707+
* Counts items at the current menu.
708+
*
709+
* Counts items at the current menu. This executes a dedicated command
710+
* ("print" with a "count-only" argument) on RouterOS, which is why only
711+
* queries are allowed as a criteria, in contrast with {@link find()},
712+
* where numbers and callbacks are allowed also.
713+
*
714+
* @param Query $query A query to filter items by. Without it, all items
715+
* are included in the count.
716+
*
717+
* @return int The number of items, or -1 on failure (e.g. if the
718+
* current menu does not have a "print" command or items to be counted).
719+
*/
720+
public function count(Query $query = null)
721+
{
722+
$result = self::parseValue(
723+
$this->client->sendSync(
724+
new Request($this->menu . '/print count-only=""', $query)
725+
)->getLast()->getArgument('ret')
726+
);
727+
728+
if (null === $result) {
729+
return -1;
730+
}
731+
return $result;
732+
}
733+
734+
/**
735+
* Gets all items in the current menu.
736+
*
737+
* Gets all items in the current menu, using a print request.
738+
*
739+
* @param string[] $args Additional arguments to pass to the request.
740+
* Each array key is the name of the argument, and each array value is
741+
* the value of the argument to be passed. Empty arguments can also be
742+
* specified using a numeric key, and the name of the argument as the
743+
* array value.
744+
* @param Query $query A query to filter items by.
745+
*
746+
* @return ResponseCollection|bool A response collection with all
747+
* {@link Response::TYPE_DATA} responses. The collection will be empty
748+
* when there are no matching items. FALSE on failure.
749+
*/
750+
public function getall(array $args = array(), Query $query = null)
751+
{
752+
$printRequest = new Request($this->menu . '/print', $query);
753+
foreach ($args as $name => $value) {
754+
if (is_int($name)) {
755+
$printRequest->setArgument($value);
756+
} else {
757+
$printRequest->setArgument($name, $value);
758+
}
759+
}
760+
$responses = $this->client->sendSync($printRequest);
761+
762+
if (count($responses->getAllOfType(Response::TYPE_ERROR)) > 0) {
763+
return false;
764+
}
765+
return $responses->getAllOfType(Response::TYPE_DATA);
766+
}
767+
694768
/**
695769
* Puts a file on RouterOS's file system.
696770
*
@@ -866,66 +940,4 @@ private function _exec(
866940

867941
return $result;
868942
}
869-
870-
/**
871-
* Counts items at the current menu.
872-
*
873-
* Counts items at the current menu. This executes a dedicated command
874-
* ("print" with a "count-only" argument) on RouterOS, which is why only
875-
* queries are allowed as a criteria, in contrast with {@link find()},
876-
* where numbers and callbacks are allowed also.
877-
*
878-
* @param Query $query A query to filter items by. Without it, all items
879-
* are included in the count.
880-
*
881-
* @return int The number of items, or -1 on failure (e.g. if the
882-
* current menu does not have a "print" command or items to be counted).
883-
*/
884-
public function count(Query $query = null)
885-
{
886-
$result = self::parseValue(
887-
$this->client->sendSync(
888-
new Request($this->menu . '/print count-only=""', $query)
889-
)->getLast()->getArgument('ret')
890-
);
891-
892-
if (null === $result) {
893-
return -1;
894-
}
895-
return $result;
896-
}
897-
898-
/**
899-
* Gets all items in the current menu.
900-
*
901-
* Gets all items in the current menu, using a print request.
902-
*
903-
* @param string[] $args Additional arguments to pass to the request.
904-
* Each array key is the name of the argument, and each array value is
905-
* the value of the argument to be passed. Empty arguments can also be
906-
* specified using a numeric key, and the name of the argument as the
907-
* array value.
908-
* @param Query $query A query to filter items by.
909-
*
910-
* @return ResponseCollection|bool A response collection with all
911-
* {@link Response::TYPE_DATA} responses. The collection will be empty
912-
* when there are no matching items. FALSE on failure.
913-
*/
914-
public function getall(array $args = array(), Query $query = null)
915-
{
916-
$printRequest = new Request($this->menu . '/print', $query);
917-
foreach ($args as $name => $value) {
918-
if (is_int($name)) {
919-
$printRequest->setArgument($value);
920-
} else {
921-
$printRequest->setArgument($name, $value);
922-
}
923-
}
924-
$responses = $this->client->sendSync($printRequest);
925-
926-
if (!empty($responses->getAllOfType(Response::TYPE_ERROR))) {
927-
return false;
928-
}
929-
return $responses->getAllOfType(Response::TYPE_DATA);
930-
}
931943
}

tests/bootstrap.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
*/
2222
use PEAR2\Autoload;
2323

24+
chdir(__DIR__);
25+
2426
$autoloader = stream_resolve_include_path('../vendor/autoload.php');
2527
if (false !== $autoloader) {
2628
include_once $autoloader;

0 commit comments

Comments
 (0)