#!/usr/bin/perl 
# 
# CKN another Perl example for CMSC 331
# CKN credit to King Beetle http://kingbeetle66.blogspot.com
# CKN blog entry /2009/10/using-perls-lwpuseragent-and-htmlform_3083.html
# CKN with comments added by CKN
#

use strict; 
 
use LWP::UserAgent;   # CKN Library for WWW in Perl interface
use HTML::Form;       # CKN another module for working with HTML
 
# CKN the general form of my
# CKN illustrates the Perl rule than when a list has just one element,
# CKN the parens can be omitted e.g. my $aList is the same as my ($aList)
                            
my ($quote_count,$return_count,$user_agent,$response,@forms, 
    @checkbox_values,@form_out,$form,@inputs,$inp,$type, 
    $value,$check_value,$name,$page,$display_count,$quote, 
    $quote_string,$author); 

# CKN look at bottom of quotations web page for these checkboxes
# CKN may need to view source to see these actual names
# CKN would need to update this list if web site changes
# Store the web form's checkbox names in an array  
@checkbox_values = ("mgm","motivate","classic","coles", 
                    "lindsly","poorc","altq","20thcent", 
                    "bywomen","devils","contrib"); 
 
# CKN we can run this script with a parameter for number of quotes to 
# CKN return, with default being one

# If the number of quotes to display is passed as a  
# command line parameter, store it in $quote_count,  
# otherwise set $quote_count to 1 
if (@ARGV) {$quote_count = $ARGV[0]}  
else {$quote_count = 1}  
 
# www.quotationspage.com's form has a minimum number of 4 
# and a maximum of 15 quotes.  If the number of requested  
# quotes is less than 4 or greater than 15, set the number 
# of returned quotes within those limits 
$return_count = $quote_count;  
if ($quote_count < 4) {$return_count = 4}  
if ($quote_count > 15) {$return_count = 15} 
 
# Create the UserAgent object 
$user_agent = LWP::UserAgent->new;

# Retrieve the form from the webpage and store the form  
# in an HTML::Form hash 
# CKN invoke the get method on the $user_agent object
$response = $user_agent->get("http://www.quotationspage.com/random.php3");  
# CKN two forms come back in the HTML response, so store them both
@forms = HTML::Form->parse($response);  
 
# Clear the array that the modified form will be "pushed"  
# into, ignore the first form (it's not the one we want) 
# and store the form hash in an array (@inputs) 
undef(@form_out);  
$form = shift(@forms);  
$form = shift(@forms);  
@inputs = $form->inputs;

# Parse the array containing the form data, entering the  
# number of quotes to request, checking all the checkboxes, 
# and filling out the outgoing form to be returned to the 
# web page's php program that processes the form 
# CKN note the weird syntax forcing inputs into a scalar context
for (my $i=0 ; $i<=$#inputs ; $i++)  
{ 
  $inp = $inputs[$i]; 
  $type = $inp->type; 
  if ($type eq "option") # Set the quote count  
  {$inp->value($return_count)} 
  if ($type eq "checkbox") # Check the checkboxes 
  { 
    $check_value = shift(@checkbox_values); 
    $inp->value($check_value); 
  }  
  $value = $inp->value; 
  $name = $inp->name; 
  if ($type ne "submit") {push(@form_out,$name,$value)}  
} 
 
# Send the completed form to the php script that processes 
# the web form, and store the HTML that comes back in a  
# string called $page 
# CKN note that a pointer to the list @form_out is sent
# CKN possibly to allow post method to modify form_out 
$response = $user_agent->post('http://www.quotationspage.com/random.php3',
\@form_out); 
$page = $response->as_string;

# Parse the HTML stored in $page, extracting the quotations 
# formatting the text, and displaying the requested number 
# of quotes 
 
$display_count = 0; 
 
# Look for a quote in the HTML 
# CKN note gs modifiers to string match function
while ($page =~ m/<dt class=\"quote\">(.*?)<\/dd>/gs) 
{ 
  $quote = $1;  
  if ($quote =~ m/\.html">(.*?)<\/a>/) # Extract the quote 
  {  
    $quote_string = $1; 
 
    # Replace any HTML break statements with Newlines 
    $quote_string =~ s/<br>/\n/gs;  
  }  
  if ($quote =~ m/<b>(.*?)<\/b>/) # Extract the author 
  {  
    $author = $1; 
    # If the author is imbedded in a link, remove the link HTML 
    if ($author =~ m/\/">(.*?)$/)  
    {  
      $author = $1; 
      $author =~ s/<\/a>//;  
    } 
    $display_count++; 
    if ($display_count <= $quote_count)  
    {print $quote_string." - ".$author."\n\n"}  
  } 
}
