#!/usr/bin/perl -w # Sidekick Address Exporter 0.2.1 # $Date: 2003/12/25$ # Copyright (C) 2003 Leonard Lin # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # http://www.gnu.org/copyleft/gpl.html # Usage: enter the login info, and run # Issues # * Palm output doesn't work right now # * Palm Categories # * Track down uninitialized value strings # * Turn into Module # * Add Calendar, Notes, Photo parsing # * vCard output not 100% -- use Text::vCard / Net::vCard ? , reread rfc use strict; use WWW::Mechanize; use HTML::TokeParser; ### DEBUG # use Data::Dumper; # Login Info my $phnum = '0123456789'; # enter your ph# my $passwd = '012345678'; # enter your p/w my $output = 'mac'; # mac or palm (individual VCard 3.0 vs mass VCard 2.1) # palm option not there yet #### Shouldn't have to touch below # User Agent my $a = WWW::Mechanize->new(); $a->agent_alias('Mac Mozilla'); # TokeParser my $stream; login(); print "Login OK.\n"; ### DEBUG address(); # Login sub login { $a->get('http://www.t-mobile.com/'); $a->field('txtMSISDN', $phnum); $a->field('txtPassword', $passwd); $a->submit(); $a->follow_link(text => 'Desktop Interface'); } # Get Address sub address { $a->get('http://address.sidekick.dngr.com/'); ### DEBUG # $stream = HTML::TokeParser->new('test/address.1.html'); $stream = HTML::TokeParser->new(\$a->content()); print "Stream OK.\n"; ### DEBUG my @indexes; # Rest of the Indexes while(my $token = $stream->get_tag('a')) { my $text = $stream->get_text(); if($text =~ /^[A-Z]-[A-Z]$/) { print "$text: $token->[1]{'href'}\n"; push(@indexes, 'http://address.sidekick.dngr.com/' . $token->[1]{'href'}); } } # Save First Page $stream = HTML::TokeParser->new(\$a->content()); address_save(); # Save Rest of the Pages foreach my $index (@indexes) { $a->get($index); $stream = HTML::TokeParser->new(\$a->content()); address_save(); } } sub address_save { # Extracted Values my $first_name, my $middle_name, my $last_name, my $nickname; my $job_title, my $company; my $category_id; my $birth_month, my $birth_day, my $birth_year; my @phone_number, my @phone_type; my @address_label, my @address_street; my @address_city, my @address_state, my @address_zip, my @address_country; my @email_address, my @email_type; my @url_address, my @url_type; my $notes; while(my $token = $stream->get_tag('a')) { if($token->[1]{'href'} =~ /show\?contact_id/) { $token->[1]{'href'}=~s/show/edit/; my $add = 'http://address.sidekick.dngr.com/' . $token->[1]{'href'} . "\n"; $token->[1]{'href'} =~ /contact_id=(\d+)/; print "Saving contact: $1\n"; ### DEBUG # Get Address $a->get($add); ### DEBUG # my $str2 = HTML::TokeParser->new('test/address.edit.html'); my $str2 = HTML::TokeParser->new(\$a->content()); while(my $tok2 = $str2->get_token()) { # Name Info if($tok2->[1] eq '') { while($tok2 = $str2->get_token()) { if($tok2->[1] eq '') { last; } if($tok2->[1] eq 'input') { if($tok2->[2]{'name'} eq 'first_name') { $first_name = $tok2->[2]{'value'}; } if($tok2->[2]{'name'} eq 'job_title') { $job_title = $tok2->[2]{'value'}; } if($tok2->[2]{'name'} eq 'middle_name') { $middle_name = $tok2->[2]{'value'}; } if($tok2->[2]{'name'} eq 'company') { $company = $tok2->[2]{'value'}; } if($tok2->[2]{'name'} eq 'last_name') { $last_name = $tok2->[2]{'value'}; } if($tok2->[2]{'name'} eq 'nickname') { $nickname = $tok2->[2]{'value'}; } if($tok2->[2]{'name'} eq 'birth_day') { $birth_day = $tok2->[2]{'value'}; } if($tok2->[2]{'name'} eq 'birth_year') { $birth_year = $tok2->[2]{'value'}; } } if($tok2->[0] eq 'S' && $tok2->[1] eq 'select'){ if($tok2->[2]{'name'} eq 'category_id') { while($tok2 = $str2->get_token()) { if($tok2->[0] eq 'E' && $tok2->[1] eq 'select') { last; } if($tok2->[0] eq 'S' && $tok2->[1] eq 'option') { if($tok2->[2]{'selected'}) { $category_id = $str2->get_token()->[1]; } } } } elsif($tok2->[2]{'name'} eq 'birth_month') { while($tok2 = $str2->get_token()) { if($tok2->[0] eq 'E' && $tok2->[1] eq 'select') { last; } if($tok2->[0] eq 'S' && $tok2->[1] eq 'option') { if($tok2->[2]{'selected'}) { $birth_month = $tok2->[2]{'value'}; } } } } } } } # Phone Numbers if($tok2->[1] eq '') { while($tok2 = $str2->get_token()) { if($tok2->[1] eq '') { last; } if($tok2->[0] eq 'T' && $tok2->[1] eq 'Phone') { while($tok2 = $str2->get_token()) { if($tok2->[1] eq 'Phone') { $str2->unget_token($tok2); last; } if($tok2->[1] eq 'New Phone') { last; } if($tok2->[1] eq 'input') { if($tok2->[2]{'type'} eq 'text') { push(@phone_number, $tok2->[2]{'value'}); while($tok2 = $str2->get_token()) { if($tok2->[0] eq 'E' && $tok2->[1] eq 'select') { last; } if($tok2->[0] eq 'S' && $tok2->[1] eq 'option') { if($tok2->[2]{'selected'}) { push(@phone_type, $str2->get_token()->[1]); } } } } } } } } } # Addresses if($tok2->[1] eq '') { while($tok2 = $str2->get_token()) { if($tok2->[1] eq '') { last; } if($tok2->[0] eq 'T' && $tok2->[1] =~ '^Address \d') { while($tok2 = $str2->get_token()) { if($tok2->[1] =~ '^Address \d') { $str2->unget_token($tok2); last; } if($tok2->[1] eq 'New Address') { last; } if($tok2->[0] eq 'S' && $tok2->[1] eq 'option') { if($tok2->[2]{'selected'}) { push(@address_label, $tok2->[2]{'value'}); } } if($tok2->[0] eq 'S' && $tok2->[1] eq 'textarea') { push(@address_street, $str2->get_token()->[1]); } if($tok2->[1] eq 'input') { if($tok2->[2]{'name'} =~ /^city/) { push(@address_city, $tok2->[2]{'value'}); } if($tok2->[2]{'name'} =~ /^state/) { push(@address_state, $tok2->[2]{'value'}); } if($tok2->[2]{'name'} =~ /^zip/) { push(@address_zip, $tok2->[2]{'value'}); } if($tok2->[2]{'name'} =~ /^country/) { push(@address_country, $tok2->[2]{'value'}); } } } } } } # Internet Info if($tok2->[1] eq '') { while($tok2 = $str2->get_token()) { if($tok2->[1] eq '') { last; } if($tok2->[0] eq 'T' && ($tok2->[1] eq 'Email' || $tok2->[1] eq 'URL')) { my $type = $tok2->[1]; while($tok2 = $str2->get_token()) { if($tok2->[1] eq 'Email' || $tok2->[1] eq 'URL') { $str2->unget_token($tok2); last; } if($tok2->[1] eq 'New Email' || $tok2->[1] eq 'New URL') { last; } if($tok2->[1] eq 'input') { if($tok2->[2]{'type'} eq 'text') { if($type eq 'Email') { push(@email_address, $tok2->[2]{'value'}); } elsif($type eq 'URL') { push(@url_address, $tok2->[2]{'value'}); } while($tok2 = $str2->get_token()) { if($tok2->[0] eq 'E' && $tok2->[1] eq 'select') { last; } if($tok2->[0] eq 'S' && $tok2->[1] eq 'option') { if($tok2->[2]{'selected'}) { if($type eq 'Email') { push(@email_type, $str2->get_token()->[1]); } elsif($type eq 'URL') { push(@url_type, $str2->get_token()->[1]); } } } } } } } } } } # Notes if($tok2->[1] eq '') { while($tok2 = $str2->get_token()) { if($tok2->[0] eq 'S' && $tok2->[1] eq 'textarea') { $notes = $str2->get_token()->[1]; last; } } } } # Output my $i; my $fullname = join ' ', $first_name, $middle_name, $last_name; $fullname =~ s/(^\ +|\ +$|(?<=\ )\ +)//g; if($output eq 'mac') { open(OUTPUT, "> $fullname.vcf") or die "Couldn't open $fullname.vcf for writing: $!\n"; print OUTPUT "BEGIN:VCARD\n"; print OUTPUT "VERSION:3.0\n"; print OUTPUT "N:$last_name;$first_name;$middle_name;;\n"; print OUTPUT "FN:$fullname\n"; if($nickname) { print OUTPUT "NICKNAME:$nickname\n"; } if($birth_day) { print OUTPUT "BDAY:$birth_year-$birth_month-$birth_day\n"; } if($company) { print OUTPUT "ORG:$company\n"; } for($i=0; $i<=$#email_address; $i++ ) { print OUTPUT "EMAIL;type=INTERNET;type=$email_type[$i]:$email_address[$i]\n"; } for($i=0; $i<=$#phone_number; $i++ ) { print OUTPUT "TEL;type=$phone_type[$i]:$phone_number[$i]\n"; } for($i=0; $i<=$#address_label; $i++ ) { print OUTPUT "ADR;type=$address_label[$i]:;;$address_street[$i];$address_city[$i];$address_zip[$i];$address_country[$i]\n"; } for($i=0; $i<=$#url_address; $i++ ) { print OUTPUT "URL;type=$url_type[$i]:$url_address[$i]\n"; } if($notes && $notes ne 'textarea') { print OUTPUT "NOTE:$notes\n"; } print OUTPUT "END:VCARD\n"; close(OUTPUT); # Deinitialize all variables undef($first_name); undef($middle_name); undef($last_name); undef($nickname); undef($job_title), undef($company); undef($category_id); undef($birth_month); undef($birth_day); undef($birth_year); undef(@phone_number); undef(@phone_type); undef(@address_label); undef(@address_street); undef(@address_city); undef(@address_state); undef(@address_zip); undef(@address_country); undef(@email_address); undef(@email_type); undef(@url_address); undef(@url_type); undef($notes); } } } }