When using the following code:
<?php
require('routeros_api.class.php');
$API = new routeros_api();
$API->debug = false;
if ($API->connect('1.2.3.4', 'apiuser', 'apipassword')) {
$API->write('/tool/user-manager/user/add',false);
$API->write('=name=fred',false);
$API->write('=password=abc',false);
$API->write('=add-credit=1h',false);
$API->write('=group-name=low',false);
$API->write('=subscriber=admin',false);
$API->write('=comment=testing',false);
$API->write('=disabled=no');
$ARRAY = $API->read(false);
print_r($ARRAY);
$API->disconnect();
}
?>
It loops forever as the read() function expects the last line of output to be “!done”, whereas for this function, the last line is the return code (e.g. “=ret=*5”) and the penultimate line is “!done”.
I’ve cobbled together some changes which test for the existance of “!done” somewhere in the return values and then exit if there are no more characters left to read and we’ve already received “!done”.
function read($parse = true) {
$RESPONSE = array();
while (true) {
$LENGTH = ord(fread($this->socket, 1) );
if ($LENGTH > 0) {
$_ = fread($this->socket, $LENGTH);
$RESPONSE[] = $_;
}
if ($_ == "!done")
$receiveddone=true;
$STATUS = socket_get_status($this->socket);
if ($LENGTH > 0)
$this->debug('>>> [' . $LENGTH . ', ' . $STATUS['unread_bytes'] . '] ' . $_);
if ( (!$this->connected && !$STATUS['unread_bytes']) ||
($this->connected && !$STATUS['unread_bytes'] && $receiveddone) )
break;
}
if ($parse)
$RESPONSE = $this->parse_response($RESPONSE);
return $RESPONSE;
}
My main worry with this approach is that if the line(s) following the “!done” are delayed, what happens then. Please can somebody with better PHP skills than me have a look and see if it can be optimised? If there’s no response within a few days, I’ll make the changes on the wiki.
Nick.