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;

In reply to Register automatically with wireless networks by chardin

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.