API PHP why only change on top list user

why this code only change password on top list user in mikrotik…not by user login :confused: :confused:

<?php namespace PEAR2\Net\RouterOS; require_once 'PEAR2_Net_RouterOS-1.0.0b4.phar'; $errors = array(); try { $client = new Client('192.168.4.2', 'admin', ''); $printRequest = new Request('/ip hotspot active print .proplist=user,address'); $printRequest->setQuery(Query::where('address', $_SERVER['REMOTE_ADDR'])); $activeUserEntry = $client->sendSync($printRequest); } catch(\Exception $e) { $errors[] = $e->getMessage(); } if (isset($_POST['password']) && isset($_POST['password2'])) { if ($_POST['password'] !== $_POST['password2']) { $errors[] = 'Passwords do not match.'; } else { $setRequest = new Request('/ip hotspot user set'); $client($setRequest ->setArgument('password', $_POST['password']) ->setArgument('numbers', $client($printRequest ->setCommand('/ip hotspot user print') ->setArgument('.proplist', '.id') ->setQuery(Query::where('name', $activeUserEntry->getArgument('user'))) )->getArgument('.id')) ); echo " DONE"; } } ?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"

http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd”>

Change your hotspot password #errors {background-color:darkred;color:white;}
<?php if (!isset($activeUserEntry)) { ?>

We're sorry, but we can't change your password right now. Please try again later

<?php } else { ?>

You are currently logged in as "<?php echo $activeUserEntry->getArgument('user'); ?>"

        <?php if(!empty($errors)) { ?>
        <div id="errors"><ul>
            <?php foreach ($errors as $error) { ?>
            <li><?php echo $error; ?></li>
            <?php } ?>
        </ul></div>
        <?php } ?>

        <form action="" method="post">
            <ul>
                <li>
                    <label for="password">New password:</label>
                    <input type="password" id="password" name="password" value="" />
                </li>
                <li>
                    <label for="password2">Confirm new password:</label>
                    <input type="password" id="password2" name="password2" value="" />
                </li>
                <li>
                    <input type="submit" id="act" name="act" value="Change password" />
                </li>
            </ul>
        </form>
        <?php } ?>
    </div>
</body>

It should be taking the “first” user that is logged in from the IP address visiting the page, which could only be the “only” user from that IP. This assumes that the web server is within the local network, so that it can see each individual user’s IP.

AFAIK, you can’t have multiple usernames logging in over the same (local) IP, so taking just “the top match” should be OK, because at any one time, there will always be exactly one match between a logged in user, and the IP they are logged in with.


Can you describe a scenario where this fails? Suggestions on how to more accurately detect automatically the user that is visiting the web page?

oooo…thanks mate, your answer help us.have handbook/e-book guide API-PHP in mikrotik using your PEAR2? blacklist, show user online, delete & bla bla bla :smiley: :smiley: :smiley:

There’s the GitHub wiki that contains some generic examples of most available functionality, and there’s also the API reference (linked from the wiki), that gives you a full list and descriptions of all methods and everything (though without example code).

I’m not aware of any tutorials for specific applications, other than the sample ones on the MikroTik wiki page, and perhaps some of my own posts in this forum (like this one). If you know of some such specialized tutorials (or better yet - if you create one), I’ll be very happy to link them from both the GitHub wiki and the MikroTik wiki.

ok thanks…very help.I will try to learn
:slight_smile: :slight_smile:

1 more i got confuse here
$API->write(‘/ip/hotspot/user/print’);
$A = $API->read();
$A = $A[0];
$API->write(‘/ip/hotspot/user/set’, false);
$API->write(‘=.id=’.$A[‘.id’], false);
$API->write(‘=disabled=yes’);
$API->read();why its only disable top user? i need disable/remove by name :confused:

In that particular menu, you should be able to just write the name in place of “$A[‘.id’]”. No need to do a print. In general, when the items in a menu have to be unique by name, the name can be used, be it the interface menu, the simple queues menu, etc.

But… if I may… What made you change your mind, and use the other PHP client? Was there something important enough missing from the docs*? How did you find what you needed with that other client?


\

  • Sometimes I fear I’m unintentionally doing the opposite - providing too much documentation, that makes it seem as if my client is difficult to work with (like, perhaps the logic goes that “if it has tons of documentation, surely it needs to have that much docs, meaning that if it has too much instructions, it takes too much time to set up and use”), when that’s false… It’s simply feature rich (with the docs describing the full richness, and not just the basics), but still easy to use in general.

no im not change my mind…i just get some eror, and try to use another way :smiley:
this my eror “Class Client could not be loaded from Client.php, file does not exist”…i dont know why

Now that you’ve mentioned it… I’m seeing you’re actually using an older version of the code (from a few months back…). Where did you get that code from? (I’d like to contact the source to update their sample, if they could…)

The latest one - the one in the MikroTik wiki page uses “use” notation instead of “namespace” notation.

It’s not that using “namespace” is wrong… it isn’t… but it can be error prone, since “namespace” must come at the very top… whereas “use” doesn’t have to, which is why I changed it - to make it easier for this to “just work”.

Here’s the latest “Change password” code, adjusted for using the PHAR file, and your RouterOS credentials you used at the top:

<?php
use PEAR2\Net\RouterOS;

require_once 'PEAR2_Net_RouterOS-1.0.0b4.phar';

$errors = array();

try {
    $client = new RouterOS\Client('192.168.4.2', 'admin', '');

    $printRequest = new RouterOS\Request(
        '/ip hotspot active print',
        RouterOS\Query::where('address', $_SERVER['REMOTE_ADDR'])
    );
    $hotspotUsername = $client->sendSync($printRequest)->getArgument('user');
} catch(Exception $e) {
    $errors[] = $e->getMessage();
}

if (isset($_POST['password']) && isset($_POST['password2'])) {
    if ($_POST['password'] !== $_POST['password2']) {
        $errors[] = 'Passwords do not match.';
    } elseif (empty($errors)) {
        $setRequest = new RouterOS\Request('/ip hotspot user set');
        $client($setRequest
            ->setArgument('numbers', $hotspotUsername)
            ->setArgument('password', $_POST['password'])
        );
    }
}

?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>Change your hotspot password</title>
        <style type="text/css">
            #errors {background-color: darkred; color: white;}
            #success {background-color: darkgreen; color: white;}
        </style>
    </head>
    <body>
        <div>
            <?php if (!isset($hotspotUsername)) { ?>
                <h1>We're sorry, but we can't change your password right now.
                Please try again later</h1>
            <?php } else { ?>
            <h1>You are currently logged in as "<?php
                    echo $hotspotUsername;
                ?>"</h1>

            <?php if(!empty($errors)) { ?>
            <div id="errors"><ul>
                <?php foreach ($errors as $error) { ?>
                <li><?php echo $error; ?></li>
                <?php } ?>
            </ul></div>
            <?php } elseif (isset($_POST['password'])) { ?>
            <div id="success">Your password has been changed.</div>
            <?php } ?>

            <form action="" method="post">
                <ul>
                    <li>
                        <label for="password">New password:</label>
                        <input type="password" id="password" name="password" value="" />
                    </li>
                    <li>
                        <label for="password2">Confirm new password:</label>
                        <input type="password" id="password2" name="password2" value="" />
                    </li>
                    <li>
                        <input type="submit" id="act" name="act" value="Change password" />
                    </li>
                </ul>
            </form>
            <?php } ?>
        </div>
    </body>
</html>

Here i find old code and working though only change pass in top user not by login …but i use from wiki not working, i dont know why.

You may be using PHP 5.2, which would be the problem - PHP 5.3.0 at minimum is required.

To check, rename the file from “.phar” to “.php”, and run it. It will tell you if that’s the problem.

If that doesn’t appear to be the problem, rename it back to “.phar”. Just in case (to double check…), create a new file in the same folder with the following contents:

<?php phpinfo(); ?>

run it, and check it’s output.

im using php 5.5.x…i think its not my problem
->getArgument(‘user’)do you see that code…i think its my problem.why this code different place with old code?

When you said “not working”, I thought you mean the form is not showing up…

So you mean it’s “not working”, in that it isn’t changing the password when you submit the form, yet you do see the form, and it DOES identify your username correctly?

OK, that’s another thing… Back when I first wrote that, I didn’t had a hotspot to test on… I still don’t have a “real” one, but I can now do a “lab” setup (with GNS3…). I’ll try it, and report back…

As for the

->getArgument('user')

thing… It’s just a simplification. In the old code, there was constantly $activeUserEntry->getArgument(‘user’). Since there’s zero cases where there’s $activeUserEntry, followed by anything else, it would make sense to simplify this to just be the username.

naaah exaclty…form not showing up.only show “We’re sorry, but we can’t change…” im already login hotspot, but the problem same.form not showing up only that words showing up.

OK, I tested it… and the problem is somewhat embarrassingly silly (as expected…).


Because the web server needs to be part of the hotspot subnet, it also would “normally” need to be logged in as a hotspot user itself. Because it isn’t logged into the hotspot, it fails to connect to the router, and due to the connection failure, it says “We can’t change your password right now”.

The solution is to add a hotspot binding for the web server that is of type “bypassed”, so that the web server doesn’t need to log in with hotspot. Go to “/ip hotspot host”, find your web server’s IP, and press “make binding”, or just type from terminal:
/ip hotspot host make-binding [find address=129.168.4.254](assuming your web server is at “192.168.4.254”; adjust accordingly)

Also, you may want to make the lease static, so that the server doesn’t suddenly move, making the binding invalid.


I’ll adjust the instructions in the wiki…