PHP API bug - expects '!done' as last data - this fix OK?

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.

Nick,

Thanks for advise. I’ve just tring to export ppp/secrets using MT API - and I was able to do this only by 37 records.
After making your update all scecrets where exported just fine!

Mikolaj (Nick in english:))

NAB would be nice if you could add these to the wiki article about PHP API implementation or create a new article with fixes you have made. as this and proper return length calculation should be on the wiki.

I have edited the original article - without the changes the PHP class simply doesn’t work, so it makes no sense to keep the incorrect version listed.

Cheers,

Nick.