[PEAR2_Net_RouterOS] Updating Hotspot Users

Hello all,

I’m a web developer, I work for an ISP who uses Mikrotik. In the recent weeks I have developed an Administrative System where it controls everything administrative, now I’m working with integrating that system with the backbone (Create users from a User Friendly, Validated and stored in database Interface and not with WinBox, for example) so of course I started working with APIs; I have tried every API for PHP and I have found PEAR2_Net_RouterOS is just not the better, but it actually works wonderful with the Web server I have and is pretty easy to use, what I have difficult (As any newbie, most likely) it’s with finding Programers-Friendly examples, so far I can add users to hotspost and print and process info. But I cannot update. I do have commands that work just fine in the Console, but I can’t get them to work on the PHP/API combo. So if someone can point me in the right direction, it will be highly appreciated.

Thanks in advance.

What I really mean it’s that I can get something like the following example to work:


$addRequest = $client->sendSync(new RouterOS\Request('ip hotspot user set password="12345" test'));

Any thoughts??

With the API protocol, you need to explicitly specify the names of all arguments. Also, while not required by the protocol, to allow for better copy&pate-ability from API to console, PEAR2_Net_RouterOS requires commands be prefixed with “/” to indicate absolute path.

If you press “?” after a command, you’ll see the names of all arguments, with “<” and “>” around those that have names that can be omitted from the command line.

So, with that in mind, the specific command you’re looking for is:

$client->sendSync(new RouterOS\Request('/ip hotspot user set password="12345" numbers=test')); 

(The name “numbers” can be omitted from the command line, but not from API; Paste it back into the command line, and you’ll see it has the same effect)


If you’re going to let user input into the command though, you should use the Request object’s setArgument() method, so f.e.

$setRequest = new RouterOS\Request('/ip hotspot user set');
$setRequest
    ->setArgument('numbers', $_POST['username'])
    ->setArgument('password', $_POST['password']);
$client->sendSync($setRequest); 

Otherwise, you’re setting yourself up for a command injection (which can have different consequences depending on the command; In this scenario, a malicious user could use it to set their profile to something they aren’t allowed to or set the password for a different user, and then login as them).

The particular example of setting a hotspot user’s password is part of the MikroTik wiki page, and this is where I tend to put the more “full featured” examples, while the GitHub wiki has the “client features” examples. To put it another way, the GitHub wiki is meant to be read like you read a programming language tutorial, while the MikroTik wiki is intended to be read like you read programming blog posts.

If you have any suggestions for other full featured examples, I’ll be happy to hear them and will most likely add them to the MikroTik wiki. Or even better, if you have a blog or anything and write your own tutorial(s), I’ll definitely link to it (possibly from both wikis).

Thank you so much boen_robot; I’ll do one better with your suggestion: once I finish the UI I’m doing, I’ll post it as an example of the use of PHP/HTML5 web app with PEAR2_RouterOS API which is really far better than the other examples out there. I want to help make this tool easier to find examples and uses out there in the NET; it deserves it.

Excellent. :smiley:

To say that I’m looking forward to that moment would be an understatement. :wink:

Hello, boen_robot!

I’m working again on this project and encountered a problem with the API. I wonder if you can help me again.

I’m running an Ubuntu 16.04 fully updated and had problems connecting:

PEAR2\Net\Transmitter\SocketException: stream_socket_client(): unable to connect to tcp://172.16.0.1:8728/user%2Fpass (Failed to parse address "172.16.0.1:8728/user%2Fpass") in phar:///home/mobile/Codigos/PEAR2_Net_RouterOS-1.0.0b5.phar/PEAR2_Net_RouterOS-1.0.0b5/src/PEAR2/Net/Transmitter/TcpClient.php:205

The suggested solution was to update to the PEAR2_Net_RouterOS-1.0.0b6.phar file which solved the issue, but now I get this problem:

Exception: Class PEAR2\Net\RouterOS\Client could not be loaded from PEAR2/Net/RouterOS/Client.php, file does not exist (registered paths="phar:///home/mobile/Codigos/PEAR2_Net_RouterOS-1.0.0b6.phar/PEAR2_Net_RouterOS-1.0.0b6/src") [PEAR2_Autoload-@PACKAGE_VERSION@] in phar:///home/mobile/Codigos/PEAR2_Net_RouterOS-1.0.0b6.phar/PEAR2_Net_RouterOS-1.0.0b6/src/PEAR2/Autoload.php:305 Stack trace: #0 [internal function]: PEAR2\Autoload::load('PEAR2\\Net\\Route...') #1 /var/www/html/testInterfaces.php(12): spl_autoload_call('PEAR2\\Net\\Route...') #2 {main}

I tried to run the php file.phar command to see if there was an issue with the file itself but I get:

PEAR2_Net_RouterOS 1.0.0b6
SHA-1 hash: 44C3A9D4CB2523A1BEDCA42EE77136C869017793

Which seems to indicate everything is fine. Now I think the problem must be in the code, thought the code used to run perfectly before and I haven’t change it. Thought here it is:

<?php
error_reporting(E_ALL);
use PEAR2\Net\RouterOS;
require_once '/home/mobile/Codigos/PEAR2_Net_RouterOS-1.0.0b6.phar';

   
$vIfaceNam = "ether3"; 
$vServerMK = "172.16.0.1";

try {
    $client = new RouterOS\Client($vServerMK, 'user', 'pass', 8728);

    $request = new RouterOS\Request('/ping address="www.google.com" count="3"');
    $results = $client->sendSync($request);

    foreach ($results as $result) {
        $vControl = $result('seq');

        if ( $vControl != ""){
            echo 'Sequency:', $vControl;
            echo " | ";
            echo 'Time:', $result('time');
            echo " | ";
            echo 'Sent:', $result('sent');
            echo " | ";
            echo 'Received:', $result('received');
            echo " | ";
            echo 'Packet Loss:', $result('packet-loss');
            echo " | ";
            echo 'Min:', $result('min-rtt');
            echo " | ";
            echo 'Avg:', $result('avg-rtt');
            echo " | ";
            echo 'Max:', $result('max-rtt');
            echo nl2br("\r\n");
        }
    }
}catch (Exception $e) {
    die($e);
}

Any thoughts on this?

Goddamn it… this Ubuntu version keeps being all messed up…

I can’t duplicate it on other OS-es, but yes, I can duplicate it on Ubuntu 16.04 (good thing I kept the VM used for diagnosing the “Failed to parse address” error…).

The cause has something to do with how this particularly patched PHP version handles is_file() and chdir() checks when inside PHAR files. The first one is required for the autoloader, and the second isn’t “required” per say, but is used in the console at a point, and is broken as well. I tried doing “sudo apt-get update” to check if there were PHP updates, and while there was one, it did not address this particular thing.

The solution is to just not use a PHAR, but extract it instead. You can do so by making the command “phar extract PEAR2_Net_RouterOS-1.0.0b6.phar”. Once you do that, you can include the “PEAR2_Net_RouterOS-1.0.0b6/src/PEAR2/Autoload.php” file.

I’ll try that and let you know. Thanks!

Worked just fine. You should put a warning about the known issues with Ubuntu/Debian/PHP 16.04. Thank you so much for the help.