A lot of wireless venues require their users to open a browser and submit some information (email address, agree to terms of service, etc.). For example, I often work from Caribou Coffee, which requires me to give my email address before I can use their network. This is an annoying hassle and I decided to cheat instead.

I have written a Perl script which automates this process; based on a passed-in wireless SSID, it will run an automated web client through a specified sequence of actions to register with the network. The means of getting that SSID is OS-specific. For Mac OS, I use:

/usr/sbin/ioreg -l -n AirPortDriver | grep APCurrentSSID | sed 's/^.*= "\(.*\)".*$/\1/; s/ /_/g'

This should then be passed to the script as an argument:

perl register_with_network.pl <ssid>

Notes:

Comments welcome.

UPDATE: Improved URL parsing and revised set of steps for Caribou Coffee.

FURTHER UPDATE: Improved URL parsing at the end of registration, agent alias set to fool annoying gateways, and hack added for The Coffee Bean.

#!/usr/bin/perl # This script accepts a wireless SSID as an argument, and will automat +ically register # the computer with that network if it has a specified list of actions + to do so. # Copyright 2010, Chuck Hardin. Released under GPL v3.0. I accept no + liability # for anyone's use of this script. Use at your own risk. # Invocation: # perl register_with_network.pl <SSID> use strict; use lib qw(/sw/lib/perl5 /sw/lib/perl5/darwin); use WWW::Mechanize; use HTTP::Response; use HTTP::Cookies; use APR::URI; use APR::Pool; # Pick a page you ought to be able to fetch, unless you're behind a re +gistration # firewall. my $target_url='google.com'; my $ssid = $ARGV[0]; exit 1 unless $ssid; # The %shops hash is of the following form: # # SSID -> listref of actions # Each action is a listref of forms on the page # Each form is a hash of relevant data for the form: # form_number specifies form number as per WWW::Mechanize->form_numbe +r() # form_name specifies form name # fields is a hashref of data for the form # if no_submit_p is set, the form is not submitted upon completion # # A default is provided below for a known venue, Caribou Coffee. my %shops = ( 'Caribou' => [[{ 'form_number' => 1 } ], [{ 'form_number' => 1, 'fields' => { 'Action' => 'Logi +n' } } ], [{ 'form_number' => 1 } ], [{ 'form_number' => 1, 'fields' => { 'Action' => 'Cont +inue' } } ], [{ 'form_number' => 1 } ] , [{ 'form_number' => 1, 'final_action' => 1 } ] ] , 'ByerlysGuest' => [[{ 'fields' => { 'email' => 'c +hardin@gmail.com' } } ] ], 'VIOC-Guest' => [[{ 'button' => 'Yes, I agree'} ] +], 'CoffeeBeanWifi' => [[{ 'form_number' => '1', 'fields' => {'code' => $ARGV[1 +] }} ], [{ 'form_number' => '1'} + ] ] ); # Get the appropriate action list for the SSID my $shop_action_list = $shops{$ssid}; exit 1 unless $shop_action_list; # Set up the automated web client my $mech = WWW::Mechanize->new( quiet => 1 ); $mech->cookie_jar(HTTP::Cookies->new(file => "$ENV{HOME}/.cookies.txt" +)); $mech->agent_alias( 'Mac Safari' ); # Check to see if we need to log in at all my $response = $mech->get('http://www.'.$target_url.'/'); my $apr_pool = new APR::Pool; my $parsed = parse APR::URI($apr_pool, ${$response->base()}); if ($parsed->hostname() =~ /$target_url/) { exit 1; } # If we do, iterate through each required action foreach my $action (@$shop_action_list) { # Iterate through each form foreach my $form (@$action) { # Specify the form: # * If a form_name is given, select the form with that name if ($form->{'form_name'}) { $mech->form_name($form->{'form_name'}); } # * Otherwise, if a form_number is given, select that form (one- +based index as per WWW::Mechanize) elsif ($form->{'form_number'}) { $mech->form_number($form->{'form_number'}); } # * Otherwise, if a list of fields is given, select the form wit +h those fieldnames elsif ($form->{'fields'}) { $mech->form_with_fields(keys %{$form->{'fields'}}); } # * Otherwise, default to the first form else { $mech->form_number(1); } # If fields are specified, fill them in if ($form->{'fields'}) { my %fields = %{$form->{'fields'}}; foreach my $fieldname (keys %fields) { $mech->field($fieldname, $fields{$fieldname}); } } # Unless otherwise directed, submit the form $response = $mech->submit($form->{'button'}) unless $form->{'no_su +bmit_p'}; } } # See if the registration succeeded $response = $mech->get('http://www.'.$target_url.'/'); unless ($response->is_success()) { die "No luck, boss." } $response = $mech->get('http://www.'.$target_url.'/'); $parsed = parse APR::URI($apr_pool, ${$response->base()}); unless ($parsed->hostname() =~ /$target_url/) { die "Did not join network: code=".$response->code(); } 1;

Replies are listed 'Best First'.
Re: Register automatically with wireless networks
by locked_user sundialsvc4 (Abbot) on Oct 30, 2010 at 12:31 UTC

    This definitely qualifies as a “Cool Use of Perl.™”

    I presume that you had consumed a good bit of their very-good coffee before writing this.   It would indeed be an excellent time-saver during the initial morning moments when you are still sleep-walking ... trying to find the counter and to mumble the words, “triple-shot espresso, please.”