API PHP package

From MikroTik Wiki
Revision as of 15:06, 3 August 2012 by Boen robot (talk | contribs)
Jump to: navigation, search

Client

The examples on this page use the PEAR2_Net_RouterOS package. You can install it with the PEAR(2) installer, or just download the ".phar" file and include it into your PHP file.

If you use the PEAR(2) installer, all required dependencies will be installed automatically from the pear2.php.net channel (and you shold pass "-o" to also get the optional ones, like PEAR2_Autoload). All dependencies are also included in the archive.

NOTE: The client requires PHP 5.3.0 or later.

NOTE: The package should, in theory, work for large replies and commands, but has not been tested with such. Please report any such experiences (positive or negative ones) at the forums.

Credits and legal stuff

Author: Vasil Rangelov, a.k.a. boen_robot (boen [dot] robot [at] gmail [dot] com)

License: LGPL 2.1

Examples

All examples assume that you used the PEAR(2) installer and have installed PEAR2_Autoload. Also, the router is assumed to be accessible with a local IP to the device PHP runs from. The client itself could work without these restrictions - they are specified here for clarity.

An HTML form to make RouterOS ping someone

This example is particularly useful when you want to ping someone from inside the network while browsing the page from outside the network.

<?php
namespace PEAR2\Net\RouterOS;
require_once 'PEAR2/Autoload.php';

if (isset($_GET['act'])) {//This is merely to ensure the form was submitted.

    //Adjust RouterOS IP, username and password accordingly.
    $client = new Client('192.168.0.1', 'admin', 'password');

    //This is just one approach that allows you to create a multy purpose form,
    //with ping being just one action.
    if ($_GET['act'] === 'Ping' && isset($_GET['address'])) {
        //Ping can run for unlimited time, but for PHP,
        //we need to actually stop it at some point.
        $pingRequest = new Request('/ping count=3');
        $results = $client->sendSync($pingRequest->setArgument('address', $_GET['address']));
    }
}
?><!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>Ping someone</title>
    </head>
    <body>
        <div>
            <form action="" method="get">
                <ul>
                    <li>
                        <label for="address">Address:</label>
                        <input type="text" id="address" name="address" value="<?php
                            if (isset($_GET['address'])) {
                                echo htmlspecialchars($_GET['address']);
                            }
                        ?>" />
                    <li>
                    <li>
                        <input type="submit" id="act" name="act" value="Ping" />
                    </li>
                </ul>
            </form>
        </div>
        <?php
if (isset($_GET['act'])) {//There's no need to execute this if the form was not submitted yet.
    echo '<div>Results:<ul>';
    foreach ($results as $result) {
        //Add whatever you want displayed in this section.
        echo '<li>Time:', $result->getArgument('time'), '</li>';
    }
    echo '</ul></div>';
}
        ?>
    </body>
</html>

A form that lets hotspot users change their own password

The script assumes you have already made a hotspot and do NOT make this file accessible in a walled garden, i.e. users must be logged in to access it.

<?php
namespace PEAR2\Net\RouterOS;
require_once 'PEAR2/Autoload.php';

$errors = array();

try {
    //Adjust RouterOS IP, username and password accordingly.
    $client = new Client('192.168.0.1', 'admin', 'password');

    $printRequest = new Request('/ip hotspot active print');
    $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 {
        //Here's the fun part - actually changing the password
        $setRequest = new Request('/ip hotspot users 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('name')))
                )->getArgument('.id'))
        );
    }
}

?><!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;}</style>
    </head>
    <body>
        <div>
            <?php if (!isset($activeUserEntry)) { ?>
                <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 $activeUserEntry->getArgument('name');
                ?>"</h1>

            <?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>
</html>

"Forgotten password" form for hotspot users

The following script needs to be accessible from a server in a walled garden, i.e. users must not need to be logged in to access it. You should link to it from the login page.

To prevent arbitrary people from resetting passwords, the script here requires users to provide two pieces of personal information: Email, and phone. The latter is expected to be the "comment" for a user. If both pieces are correct, the password is set to a new password the user defines.

This scheme is used for the sake of simplicity. Depending on the rest of your setup (e.g. if you have a public trial account, or an SMS gateway...), you may have better ways to deal with confirming the user's identity.

<?php
namespace PEAR2\Net\RouterOS;
require_once 'PEAR2/Autoload.php';

$errors = array();

//Check if the form was submitted. Don't bother with the checks if not.
if (isset($_POST['act'])) {
    try {
        //Adjust RouterOS IP, username and password accordingly.
        $client = new Client('192.168.0.1', 'admin', 'password');
    } catch(\Exception $e) {
        $errors[] = $e->getMessage();
    }

    if (empty($_POST['email'])) {
        $errors[] = 'Email is required.';
    }

    if (empty($_POST['phone'])) {
        $errors[] = 'Phone is required.';
    }

    if (empty($errors)) {
        //Check if this is an imposter or not
        $printRequest = new Request('/ip hotspot user print .proplist=.id');
        $printRequest->setQuery(Query::where('email', $_POST['email'])->andWhere('comment', $_POST['phone']));
        $id = $client->sendSync($printRequest)->getArgument('.id');
        if (null === $id) {
            $errors[] = 'Email or phone does not match that of any user.';
        }
    }

    if (!isset($_POST['password']) || !isset($_POST['password2'])) {
        $errors[] = 'Setting a new password is required.';
    }

    if (empty($errors)) {
        if ($_POST['password'] !== $_POST['password2']) {
            $errors[] = 'Passwords do not match.';
        } else {
            //Here's the fun part - actually changing the password
            $setRequest = new Request('/ip hotspot users set');
            $client->sendSync($setRequest
                ->setArgument('password', $_POST['password'])
                ->setArgument('numbers', $id)
            );

            //Redirect back to the login page, thus indicating success.
            header('Location: http://192.168.0.1/login.html');
        }
    }
}

?><!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>Forgot your hotspot password?</title>
        <style type="text/css">#errors {background-color:darkred;color:white;}</style>
    </head>
    <body>
        <div>
            <h1>You can reset your hotspot password by filling the following form.
            You'll be redirected back to the login page once you're done</h1>
            <?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="email">Email:</label>
                        <input type="text" id="email" name="email" value="" />
                    </li>
                    <li>
                        <label for="phone">Phone:</label>
                        <input type="text" id="phone" name="phone" 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="Reset password" />
                    </li>
                </ul>
            </form>
        </div>
    </body>
</html>

MAC finder

Tired of asking your customers to tell you their MAC address (and go over the same "click here and..." instructions over and over again)? Well, using the following script, you can now... switch the insructions to "go to this web page... by clicking here and...":

<?php
namespace PEAR2\Net\RouterOS;
require_once 'PEAR2/Autoload.php';

?><!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>Your MAC address</title>
    </head>
    <body>
        <h1>
            <?php
try {
    //Adjust RouterOS IP, username and password accordingly.
    $client = new Client('192.168.0.1', 'admin', 'password');

    $printRequest = new Request('/ip arp print .proplist=mac-address');
    $printRequest->setQuery(Query::where('address', $_SERVER['REMOTE_ADDR']));
    $mac = $client->sendSync($printRequest)->getArgument('mac-address');

    if (null !== $mac) {
        echo 'Your MAC address is: ', $mac;
    } else {
        echo 'Your IP (', $_SERVER['REMOTE_ADDR'],
        ") is not part of our network, and because of that, we can't determine your MAC address.";
    }
} catch(\Exception $e) {
    echo "We're sorry, but we can't determine your MAC address right now.";
}
?>
        </h1>
    </body>
</html>