#!c:\perl\bin\perl -w #hpl.pl: Program to check if you have any books due in the near future at #Houston Public Library and remind you by email if so. You may schedule a job to #run it at certain time once a day. #For Windows users, you have to download and install the Perl interpreter from #http://www.activestate.com/ActivePerl/. The Perl interpreter is typically installed #at C:\Perl. Make sure Net::SMTP and Crypt::SSLeay modules are included by typing: # perl -e "use Net::SMTP" # perl -e "use Crypt::SSLeay" #It should silently show the next DOS prompt. #To actually run the script, type the command at DOS prompt # perl thisscript.pl -d3 -e"you@domain.com another@domain.com" -i123456789 -lLastName -mmail [-pmyproxy[:port]] #This sends you@domain.com and another@domain.com an email about the books due #in 3 days checked out by LastName with his library card 123456789. The SMTP #mail server is "mail" (most companies use this name). If you have to go through #a proxy server named myproxy to connect to the Internet, append "-pmyproxy" or #"-pmyproxy:8080" to the end (no brackets or quotes; specify port if it's not 80). #If your proxy server additionally requires username/password, uncomment the two #lines below and set them correctly: #$proxyuser="myproxyusername"; #$proxypasswd="myproxypassword"; #This script is published as freeware at #http://yong321.freeshell.org/freeware/hplhcpl.html #(C) Copyright 1999-2008 Yong Huang (yong321@yahoo.com) use Net::SMTP; use LWP::UserAgent; use Time::Local; use Getopt::Std; $|=1; getopts('d:e:i:l:m:p:'); if (!defined $opt_d or !defined $opt_e or !defined $opt_i or !defined $opt_l or !defined $opt_m) { print "Usage: perl $0 -d3 -e\"you\@domain.com another\@domain.com\" -i123456789 -lLastName -mmail [-pProxy[:port]] -d: from this many days ahead of due date you get email once a day -e: space-separated email addresses the notice will be sent to -i: HPL library card number -l: card holder's last name -m: mail server; usually 'mail' but confirm with your system admin -p (optional): proxy server if you have to go through it to access Internet "; exit; } $daysahead=$opt_d; $email=$opt_e; #($email=$opt_e) =~ s/@/\\@/g; $ID=$opt_i; $LastName=$opt_l; $mailsrvr=$opt_m; $ProxyServer=$opt_p if defined $opt_p; $ua = new LWP::UserAgent; if (defined $opt_p) { $ua->proxy(http => "http://$ProxyServer"); $ua->env_proxy; } else { $ua->agent("AgentName/0.1"); } #Phase 1 #20051206: HPL changed this URL to SSL enabled $req = new HTTP::Request 'GET', 'https://catalog.houstonlibrary.org/patroninfo~S1'; $req->proxy_authorization_basic($proxyuser, $proxypasswd) if defined $proxyuser; { my $cnt=0; sleep 1 while ($cnt++<10 && ($tmp=$ua->request($req)->as_string) eq ""); } #Sometimes this initial connection fails. Try it several times. #print "\n\nPhase 1 output:\n$tmp\n\n\n";#for debugging #20080911: HPL site set cookies now. #Set-Cookie: SESSION_SCOPE=1; path=/ #Set-Cookie: III_SESSION_ID=1221134549.31078; domain=houstonlibrary.org; path=/ #Set-Cookie: PAT_LOGGED_IN=; domain=houstonlibrary.org; expires=Thu, 1 Jan 1970 00:00:00 GMT; path=/ $tmp =~ /Set-Cookie: III_SESSION_ID=([0-9.]+)/; $session = $1; #print "III_SESSION_ID is $session"; #Phase 2 $ua->default_headers->push_header('Cookie' => "SESSION_SCOPE=1"); $ua->default_headers->push_header('Cookie' => "III_SESSION_ID=$session"); $ua->default_headers->push_header('Cookie' => "PAT_LOGGED_IN="); $req = new HTTP::Request POST => 'https://catalog.houstonlibrary.org/patroninfo~S1/'; $req->proxy_authorization_basic($proxyuser, $proxypasswd) if defined $proxyuser; $req->content_type('application/x-www-form-urlencoded'); $req->content("name=$LastName&code=$ID"); #print "LastName: $LastName; ID: $ID.\n"; $ua->request($req); $phase2str = $ua->request($req)->as_string; #print "\n\nPhase 2 output:\n", $phase2str; #$phase2str =~ />0 Items currently checked out/; #if (defined $&) # { print "You did not check out any books."; # exit; # } #$phase2str =~ /\/patroninfo\/(\d+)\/items/; #20080128: items changed to top #$phase2str =~ /\/patroninfo\/(\d+)\/top/; #20080911: patroninfo appened with ~S1 $phase2str =~ /\/patroninfo~S1\/(\d+)\/top/; $patron = $1; #Phase 3 #Set-Cookie: PAT_LOGGED_IN=true; domain=houstonlibrary.org; path=/ #Set-Cookie: SESSION_SCOPE=1; path=/ $ua->default_headers->push_header('Cookie' => "PAT_LOGGED_IN=true"); $ua->default_headers->push_header('Cookie' => "SESSION_SCOPE=1"); #$req = new HTTP::Request POST => "https://catalog.houstonlibrary.org/patroninfo/$patron/items"; $req = new HTTP::Request POST => "https://catalog.houstonlibrary.org/patroninfo~S1/$patron/items"; $req->proxy_authorization_basic($proxyuser, $proxypasswd) if defined $proxyuser; $req->content_type('application/x-www-form-urlencoded'); #Tested changing the number 5 below. It doesn't seem to matter. $req->content("checkedOut=5+Items+currently+checked+out"); $ua->request($req); #print "\n\nPhase 3 output:\n", $ua->request($req)->as_string; undef $/; #string to be slurped in contains LF's $tmp = $ua->request($req)->as_string; @line = split /patFuncEntry/,$tmp; #200801: Changed \n to patFuncEntry $remindtime = 86400*$daysahead + time; #convert to seconds since epoch $seq=1; #Sequence number for checked-out books $msg=""; foreach (@line) { #Commented on 11/05/05: A typical entry used to be: #
Throwing / Richard Phethean.
#
Stage fright on a summer night /
#
# # DUE 09-22-04 # OSBOR # #Commented on 11/05/05: $title = $1 if (/ \)"> (.*?) <\/a>
/); #Commented on 11/05/05: if (/^ DUE (\d\d)-(\d\d)-(\d\d)/) #Change on 11/05/05: #A typical entry beginning a few days ago now is: # Core PHP programming / Leon Atkinson. #
# # # R0119258940 # DUE 11-12-05 # # GIFTF # #200801: Changed the $title matching string: $title = $1 if (/redraw\( 'item\&\d+' \)"> (.*) <\/a>$/); $title = $1 if /patFuncTitle">[^>]+> ([^<]+)/; if (/ DUE (\d\d)-(\d\d)-(\d\d)/) { $month=$1-1; #convert to seconds since epoch, second set to 1 to avoid midnight ambiguity $duetime = timelocal(1,0,0,$2,$month,$3); if ($remindtime>=$duetime) { $msg .= "$seq: $title due on $1-$2-$3\n"; $seq++; } } } if ($msg ne "") { print $msg; $smtp = Net::SMTP->new($mailsrvr); if ($email =~ / /) { @email = split / /,$email; $smtp->mail($email[0]); #Hopefully the first address is your own; in case of error this #address is more likely to receive the mail $smtp->to(@email); #cannot be fake $smtp->data(); $smtp->datasend("To: @email\n"); #can be fake } else { $smtp->mail($email); $smtp->to($email); $smtp->data(); $smtp->datasend("To: $email\n"); #can be fake } $smtp->datasend("From: $email\n"); #can be fake $smtp->datasend("Subject: Houston Public Library books due\n\n"); $smtp->datasend("$msg\n"); $smtp->dataend(); $smtp->quit; }