JavaScript for Sysadmins, again

1 person likes this post.

Following up on the previous post, let me show you other ways to trick web application into doing what they’ve not been designed to do: saving the Sysadmin some typing and avoding errors. I’ll use JavaScript, jQuery, Greasemonkey and Perl to automate Firefox and implement a sort of dynamic form filling. Let’s start with a screencast:

The config I had to do (on a SonicWALL firewall), involves about 70 subnets, each similar to the other. Only the subnet’s addressing scheme changes, making creation of VLANs/objects/rules a repetitive and error-prone task.

What’s happening in the screencast? VLAN sub-interfaces are being automatically created without me having to type anything at all. How could that be? A simple Greasemonkey script calls a “web service” (AJAX style) fetching the needed data and filling the form for me (I just click the “OK” or “Cancel” buttons). Why this whole Greasemonkey/web service mess? Because here, as in the previous post, JavaScript code is basically being injected into a “page”. Pages (or tabs, or windows) are ran by the browser into a sandbox: they can’t exchange data between each other. Thus page A (the webapp) can’t access code/data in page B (our code). Moreover, injected JavaScript gets lost when the page is closed (think ugly GUIs where dialog windows pop up just to be destroyed shortly after). We need a way (Greasemonkey) to re-inject the code each time our page is shown and some external, long lived, entity to update/keep status (the web service).

Thanks to the HTTP::Server::Simple Perl module, building the web service is trivial. The only logic behind it is keeping track of the current VLAN’s index, iterating through each value on subsequent web service calls:

use strict;
package LameServer;
use base qw(HTTP::Server::Simple::CGI);

my @VLANS = qw(10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98);

my $COUNTER = 0;

sub handle_request {
    my ($self, $cgi) = @_;

        print "HTTP/1.0 200 OK\r\n";
        print "Content-type:text/plain\r\n\r\n";
        print STDERR "$VLANS[$COUNTER] index $COUNTER\n";
        print $VLANS[$COUNTER];
        $COUNTER = 0 if $COUNTER >= @VLANS;


package main;

my $server = LameServer->new(3333);

And here’s the Greasemonkey script. It runs automatically when the “add VLAN” page pops up, does the sort-of-AJAX call, uses jQuery to properly fill the form.

// ==UserScript==
// @name           CurrentVLAN
// @namespace      dontcare
// @require        http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js
// @include*
// ==/UserScript==

if (window.location.toString().match(/*editInterface/)) {
        method: "GET",
        url: "http://localhost:3333/",
        onload: function(response) {
            window.GM_CurrentVLAN = parseInt(response.responseText);
    function GM_wait() {
        if(typeof unsafeWindow.jQuery == 'undefined') {
        else {
            $ = unsafeWindow.jQuery;

    window.setTimeout(function() {
            unsafeWindow.setIfaceContent(); // "Zone" onchange function.
            $('input[name=lan_iface_ping_mgmt]').attr('checked', true);
            }, 1000);

I built similar scripts to create static ARP entries and routes. Another one took care of firewall symbolic objects (names) but, as that part of the config is itself carried out by AJAX (in a non reloading window), I didn’t need Greasemonkey, just Firebug.
No kidding, the above tricks saved me half a day of tedium…