#!/usr/bin/perl # # Semi-automatically manages an SPA942 and probably other SPA900 # series phones' phone directory. # # Copyright (C) 2007, Saxon Jones # # Distributed under the GPL: # http://www.fsf.org/licensing/licenses/gpl.html # # To read the directory to a CSV: # # spa900-pdir.pl # # Redirect that to a file, edit it, then to update each phone # you want to have the same directory using: # # spa900-pdir.pl # # The CSV has two fields, name and number. There are other fields # I could support, like ringtone, and other stuff, but I don't use # them and don't really care about them either, so this little # script doesn't support them. # use URI::Escape; use WWW::Mechanize; use HTML::TokeParser; #usage: spa900-pdir.pl [filename] my $hostname; my $password; my $filename; my $mode; if( defined($ARGV[0]) and $ARGV[0] =~ /^[0-9a-zA-Z\.]+$/ ) { $hostname = $ARGV[0]; } else { print "usage: spa900-pdir.pl \n"; exit; } if( defined($ARGV[1]) and $ARGV[1] =~ /^\w+$/ ) { $password = $ARGV[1]; } else { print "usage: spa900-pdir.pl \n"; exit; } if( defined($ARGV[2]) ) { $filename = $ARGV[2]; $mode = "write"; } else { $mode = "read"; } my $phone_read_url = "http://$hostname/pdir.htm"; my $phone_write_url = "http://$hostname/pdir.spa"; my %phonebook; my %phonebook_names; my %phonebook_numbers; my $browser = WWW::Mechanize->new(timeout => 60, parse_head => 0); $browser->agent("Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)"); # # The SPA's identifiers in pdir change between firmware updates, so read # what they're using before updating. # my $page = $browser->get($phone_read_url); $browser->success() or die "Unable to get phone directory page (" . $page->status_line . ")\n"; $stream = HTML::TokeParser->new( $page->content_ref() ); while( my $tag = $stream->get_tag('input') ) { my $name = $tag->[1]{'name'}; my $value = $tag->[1]{'value'}; my $type = $tag->[1]{'type'}; # parse out the name and number if( $name =~ /^([0-9]+)$/ ) { $phonebook{$name} = $value; my @components = split(/;/,$value); foreach $component (@components) { if( $component =~ /n=([^;]+)/ ) { $phonebook_names{$name} = $1; } if( $component =~ /p=([^;]+)/ ) { $phonebook_numbers{$name} = $1; } } } } # # If we just want to dump what's in there already, print it out in CSV format. # if( $mode eq "read" ) { foreach $key (keys %phonebook_names) { print "\"$phonebook_names{$key}\", \"$phonebook_numbers{$key}\"\n"; } } # # Otherwise parse the CSV they gave us and upload it to the phone. # elsif( $mode eq "write" ) { # first blow away what's in there foreach $key (keys %phonebook) { $phonebook_names{$key} = ''; $phonebook_numbers{$key} = ''; $phonebook = ''; } # parse the input my @newbook_names; my @newbook_numbers; open(CSV,$filename); my $num = 0; while( $line = ) { if( $line =~ /\"([^\"]+)\",\s*\"([^\"]+)\"/ ) { $newbook_names[$num] = $1; $newbook_numbers[$num] = $2; $num++; } } close(CSV); # enter the parsed input into the phone book $num = 0; foreach $key (keys %phonebook) { if( defined($newbook_names[$num]) and $phonebook_names{$key} =~ /^\s*$/ ) { $phonebook_names{$key} = $newbook_names[$num]; $phonebook_numbers{$key} = $newbook_numbers[$num]; $num++; } $phonebook{$key} = "n=$phonebook_names{$key};p=$phonebook_numbers{$key}"; } # and post them to the phone my $posting = $browser -> submit_form( form_number => 1, fields => \%phonebook ) or die "couldn't post form.\n"; $browser->success() or die "couldn't post new phone directory (" . $posting->status_line . ")\n"; }