Automating Web Form submission with some small tools
At the ACCU 2006 conference in Oxford, we were faced with a
free Wireless LAN login which was limited to 20 users. This
is fine after about 20 minutes into a session, when laptops
logged in during the breaks have timed-out on the LAN and so
slots are available. During breaks though, it's common to
see people forlornly hitting 'refresh' on their browsers,
hoping to grab a free slot. After a bit of this, I scripted
it. This is a quick description of how I did that.
Starting with the obvious stuff, turning on my Apple iBook
got me connected to the 'tmobile' wireless LAN. However,
there was no internet access available until I opened a
browser and typed in the ACCU username and password, which
were supplied on little pieces of paper from the
registration desk: username G-Randolph.group@t-mobile.co.uk,
password ACCU. After that, my browser was able to access the
internet as well as my mail programs. So, I guess the wireless
infrastructure is recording my MAC address (not Apple Mac!
MAC here is the unique ID of my wireless card. All ethernet
devices have a MAC address. Mine's 00:14:51:87:41:9f) and
keeping a record of the last activity. If I login, then do
nothing with the network for 15 minutes, it times me out.
Fair enough.
So, there are 2 options. First, write a little pinger to
keep my network connection up. This is very simple:
$ while [ 1 ] ; do wget -q www.google.com ; sleep 30 ; done
But that's bad citizenship. You're basically hogging the
connection which someone else will need, so don't do that.
Very naughty.
Instead, we'll write a wee thing that tries to get a
connection - the equivalent of automating the 'refresh'
button press on the LAN login page. That page says "Login
has been rejected. There are already too many users using
this account." The address of that page is
https://hotspot.t-mobile.net/wlan/start.do
So, the first thing to do is to look at the page. We have to
fill in the username, the password, and click 2 checkboxes
to say we agree to the 'Terms & Conditions' and the
'Privacy policy'. (Well, I read those thoroughly, as you can
imagine). Now, view source. Search for the word 'Username',
and we find the relevant section of the HTML. The input
element lines are copied below.
<input type="text" name="username" value="G-Randolph.group@t-mobile.co.uk" maxlength="72">
<input type="password" name="password" value="ACCU" maxlength="72">
<input type="checkbox" name="strAGB" value="AGB" checked="checked">
<input type="checkbox" name="strHinweis" value="Zahlungsbedingungen" checked="checked">
From this, it's straight-forward to construct a query
string - the page URL plus these parameters. If you don't
know query strings, there's basically 3 syntax rules: the
query string comes after the page URL, starts with a
?, each name-value pair is joined with
=, and each name-value pair is seperated with a
&. In the <input>
elements above, the important attributes are
name and value - the other stuff's
just GUI fluff (with all due respect to GUI writers).
So, we get this query string (all on one line).
https://hotspot.t-mobile.net/wlan/index.do?username=G-Randolph.group@t-mobile.co.uk
&password=ACCU&strAGB=AGB&strHinweis=Zahlungsbedingungen
Now, we need to make this request to the server. Well, it's
https so we need a SSL-enabled client. Your browser is one,
so test with that: paste the string above into the address
bar, and presto! It's as if you had submitted the 'proper'
form. It's important to realise that you have NOT submitted a
form, which is an HTTP POST operation - you have submitted an
HTTP GET request, with all the required information in the
URL string.
The point here is to let the computer do the grunt-work, so
we've not got much advantage yet. We need to use a script to
do this. I use perl for all this sort of stuff - I've been
at it for years, and I'm very comfortable with it. Python,
Ruby and innumerable other scripting languages no doubt do
the job. Here's a perl solution wrapped in a shell script.
We're going to use 2 perl libraries - LWP for basic web
stuff, and Crypt::SSLeay for the SSL encryption stuff. perl
generally comes with the cpan program for
accessing and installing CPAN modules. On a unix system such
as the Mac this is typically used with sudo cpan
install LWP and sudo cpan
install Crypt::SSLeay.
OK, now we simply chuck the query string at the server with
the GET program, which LWP has installed in /usr/bin/GET.
(Remember you need to enclose the URL in quotes to avoid the
shell interpreting the & as background operators.)
All of this on one line:
GET 'https://hotspot.t-mobile.net/wlan/index.do?
username=G-Randolph.group@t-mobile.co.uk
&password=ACCU
&strAGB=AGB
&strHinweis=Zahlungsbedingungen'
This works. If there are too many users on the network (like
just now, 3 minutes before the keynote starts), the response
HTML contains the line
<p class="error">Login has been rejected. There are already too many users using this account.</p>
If we get on, then the success page contains the string
'You are now online with high-speed access'.
So, we can now build a little script which looks for either
of these strings and re-tries if not successful. This is as
old as the hills, there's more than one way to do it, and I
solve it with:
#! /bin/sh
SLEEP=20
URL="https://hotspot.t-mobile.net/wlan/index.do"
URL="${URL}?username=G-Randolph.group@t-mobile.co.uk"
URL="${URL}&password=ACCU"
URL="${URL}&strAGB=AGB"
URL="${URL}&strHinweis=Zahlungsbedingungen"
SUCCESS='You.are.now.online.with.high-speed.access'
GET="/usr/bin/GET $URL"
while [ "0$GETOUT" == "0" ] ; do
GETOUT=`$GET | grep $SUCCESS`
if [ "0$GETOUT" == "0" ] ; then
echo "Rejected at $(date), retrying in $SLEEP seconds..."
sleep $SLEEP
fi
done
echo "Connected at $(date)"
Cookies
The t-mobile access application does set a ccookie on your
browser, but I didn't find it was required in my script. Here
it is anyway. If this had been required, we would have had to
ensure the Cookie was passed correctly so I'm pretty glad it's
not used!
hotspot.t-mobile.net /wlan JSESSIONID=08610FAB4B39BD940927A903CB556729.TMOWLanPortalNode116
|