#!/home/rebelsky/perl/bin/perl
#This program parses the add annotation web page and creates the 
#annotation by creating and storing the annotation file and updating any 
#index that needs updating.  It then prints out a confirmation.
#(POD documentation at end)

##################
# Package Begins #
##################
#package declaration
package ParseForm;
use Exporter ();
@ISA = (Exporter);
@EXPORT = qw(parse_form_execute);

#import modules
use Ambiguity;
use LWP::Simple;
use Network;
use Search;                     #to use convertSpecialChars
use HTTP::Request;
use HTTP::Daemon;
use URI::Escape;

###########################################################################
# parse_form_execute #
###########################################################################
# This subroutine gets the user information from ravel and then calls the
# apropriate subroutines in order to store an added annotation.
# ARGUMENTS: The user's name in string form, the user information in
# string form, the client connection in order to send the client a
# response, and the original client request.
# RETURNS: Returns 1 to show that it ran correctly.
###########################################################################
sub parse_form_execute
  {
    #read arguments
    my $name = shift;               #id of the user for this request
    my $user_info = shift;          #a string with info on the user
    my $client = shift;             #client connection
    my $client_request = shift;     #request from the client
    #other variables
    local(*fields);                 #hash that stores data for annotation
    my $html;                       #html source code
    my $dir;                        #directory for annotation files
    my $file;                       #the annotation file created
    my $response;                   #response to send the client
    my $response_object;            #client response object

    #parse the string of user information
    $user_info =~ /<EMAIL>(.*)<\/EMAIL/;
    $fields{'email'} = $1;
    $fields{'name'} = $name;
    $query = $client_request->url;
    $query =~ /\?(.*)/i;
    $query = $1;
    $query =~ s/\+/ /sig;
    $query = uri_unescape($query);

    #parse the add annotation form
    &parseForm(*fields,$query);

    #TEMP - get the html source code associated with the URL using 
    #LWP::Simple->get
    $html = get($fields{'url'});

    # Added by Sarah:
    # If the HTML box was not checked, run convertSpecialChars on the 
    # annotation text so it is not displayed as HTML
    if ($fields{'htmlCheck'} ne "checked") 
      {
        $fields{'annotation'} = convertSpecialChars($fields{'annotation'});
      }                             #if ($fields{'htmlCheck'} ne "checked")
    else 
      {
        #$fields{'annotation'} =~ s/<a\s*?href/<a target=\"_main\" href/isg;
        $fields{'annotation'} =~ s/(<a\s[^>]*?href\s*?=\s*?\")([^\#>][^>]*?)(\"[^>]*?>)/$1javascript:newLink\(\'$2\'\)$3/isg;
      }

    #if this is a new annotation, see if the annotated_text is ambiguous
    if ($fields{'type'} eq "new")
      {
        #to see if it is ambiguous, run Ambiguity->ambiguity
        $fields{'times'} = ambiguity($html,$fields{'text'},*fields);
      }                             #if ($fields{'type'} eq "new")

    #if the annotation is a reply, 'times' will be "" and if it is new, it 
    #will only be "error" if the annotated_text did not exist in the web page.
    if ($fields{'times'} ne "error")
      { 
        #testing for updating the index
        $dir = &indexUrl($fields{'url'});
        
        #store the annotation with results from indexUrl
        $file = &createTextFile($dir,*fields, $html);
        
        #if it was a new annotation, take care of ambiguous annotated_text
        if (($fields{'times'} != 1) && ($fields{'type'} eq "new"))
          {
            #determine which instance of the annotated_text is the right one 
            #by running Ambiguity->whichOne 
            whichOne($html,$file,$client);
          }                         #if (($fields{'times'} != 1) && ...)
        else
          {
            #if it wasn't new and ambiguous, confirm
            confirm(*fields,$file,$client);
          }                         #else
      }                             #if ($fields{'times'} ne "error")

    #if there was an error, print an error message
    else
      {
        $response = <<"EOF";
<html>
<meta name=\"Ravel\" content=\"disallow: .*?-.*?-.*?-.*?\$\">
<head>
<title>Sorry<\/title>
<\/head>
<body bgcolor=\"white\">
<center><h1>Sorry<\/h1><\/center>
<p>
That text does not exist in the document.
<\/p>
<form>
<input type=\"button\" onClick=self.close() name=\"OK\" value=\"OK\">
<\/form>
<\/body>
<\/html>
EOF

        #create the response object and send it to the client
        $response_object = HTTP::Response->new(200);
        $response_object->content($response);
        $client->send_response($response_object);
      }                             #else

    #return the true value to show that it ran correctly
    return 1;

  }#sub parse_form_execute


###########################################################################
# parseForm #                 
###########################################################################
# This subroutine parses the form found at http://www.math.grin.edu/
# ~rebelsky/Blazers/Annotations/Summer1999/add.html and stores the results
# in a referenced hash.                                     
# ARGUMENTS:  It takes in a typeglob to be used as a hash and the query
# string from the proxy url.                 
# RETURNS:  The subroutine returns 1 to show that it ran correctly.        
###########################################################################
sub parseForm 
  {
    #read in the argument
    local(*form) = shift;       #hash for storing results from html form
    my $query = shift; #the query string generated by the form
    #other variables
    my $first;                  #boolean: first group in list

    #set the values in the typeglob to the values found in the query
    $query =~ /url=([^\&]*)/i;
    $form{'url'} = $1;
    $query =~ /title=([^\&]*)/i;
    $form{'title'} = $1;
    $query =~ /annotated_text=([^\&]*)/i;
    $form{'text'} = $1;
    $query =~ /annotation=([^\&]*)/i;
    $form{'annotation'} = $1;
    $query =~ /htmlCheck=([^\&]*)/i;
    $form{'htmlCheck'} = $1;
    $query =~ /type=([^\&]*)/i;
    $form{'type'} = $1;
    $query =~ /file=([^\&]*)/i;
    $form{'file'} = $1;
    $query =~ /protection=([^\&]*)/i;
    $form{'protection'} = $1;
    $query =~ /last_time=([^\&]*)/i;
    $form{'last_time'} = $1;

    #Get the list of groups
    if ($form{'protection'} == "group")
      {
        $first = 1;
        while ($query =~ /groups=([^\&]*)/i)
          {
            $group = $1;
            $query =~ s/groups=([^\&]*)//si;
            if ($first == 1)
              {
                $form{'groups'} = $group;
                $first = 0;
              }                 #if ($first == 1)
            else
              {
                $form{'groups'} = "$form{'groups'},$group";
              }                 #else
          }                     #while ($query =~ /groups=([^\&]*)/i)
      }                         #if ($form{'protection'} == "group")

    #if URL is empty use default test url
    if ($form{'url'} eq "")
      {
        $form{'url'} = "http://www.math.grin.edu/~rebelsky/Blazers/Annotations/Summer1999/test.html";
      }                         #if ($form{'url'} eq ""

    #escape vertical bars using the standard uri escape sequence %7C
    foreach $item (keys(%form))
      {
        $form{$item} =~ s/\|/%7C/gis;
      }#foreach $item (keys(%form))
    
    #return the true value  
    return 1;
  }                             #sub parseForm


###########################################################################
# createTextFile #
###########################################################################
# This subroutine creates an annotation file and stores it in a specified 
# directory.
# ARGUMENTS:  It takes the name of the directory that is used for a
# specified page's annotations (stored in /home/rebelsky/public_html/
# Blazers/Annotations/Summer1999/Stored_Annotations/index.txt) in string
# form, a typeglob that has the results from parseForm stored in it, and 
# the html source code for the page being annotated in string form.
# RETURNS:  The address for the annotation file that was just created.
###########################################################################
sub createTextFile 
  {
    #read in the arguments
    my $anndir = shift;         #the directory of the url being annotated
    local(*form) = shift;       #hash containing info for the annotation
    my $page = shift;           #the html source code
    #other variables  
    my @date;                   #date and time from Perl's localtime()
    my $day;                    #the day
    my $mon;                    #the month
    my $year;                   #the year
    my $sec;                    #the seconds
    my $min;                    #the minutes
    my $hour;                   #the hours
    my $today;                  #the date
    my $time;                   #the time
    my $num;                    #iteration variable
    my $annfile;                #the file name for the annotation file
    my $file;                   #file beginning in a reply w/o directory
    my $annotate_file;          #file beginning in a reply w/ directory
    my $data;                   #data string stored in the annotation file
    my $protection;             #protection line in annotation file
    
    #get the current date 
    @date = localtime(time());
    $day = $date[3];
    $mon = $date[4] + 1;
    $year = $date[5];
    $sec = $date[0];
    $min = $date[1];
    $hour = $date[2];
    
    #make the day and month values 2-digit numbers
    if ($day<10)
      {
        $day = "0" . "$day";
      }                         #if ($day<10)
    if ($mon < 10)
      {
        $mon = "0" . "$mon";
      }                         #if ($mon < 10)
    
    #combine the date into one string and do the same for the time
    $today = "$mon" . "$day" . "$year";
    $time = $hour . ":" . $min . ":" . $sec;
    
    
    #determine protection line
    if ($form{'protection'} eq "group")
      {
        $protection = $form{'groups'};
      }                         #if ($form{'protection'} == "group")
    else
      {
        $protection = $form{'protection'};
      }                         #else
    
    #create new annotation file with the above name  
    $data = "$form{'name'}\n$form{'email'}\n$today\/$time\n$form{'title'}\n\|\n$form{'text'}\n\|\n$form{'annotation'}\n\|\n$form{'context'}\n\|\nonly one\n\|\n$protection";
    
    #See if the annotation is a new annotation or a reply to another one
    if ($form{'type'} eq "new")
      {
        
        #a temporary interation variable
        $num = 1;
        
        #find a file name not already existing for the new annotation in 
        #the annotation directory and then store the data there
        while (existsAndStore("/home/rebelsky/public_html/Blazers/Annotations/Summer1999/Stored_Annotations/" . "$anndir" . "/" . "$num" . ".txt",$data))
          {
            $num = $num + 1;
          }                     # while (fileExists("..."$num" . ".txt"))
        
        $annfile = "$num" . ".txt";
      }                         #if ($form{'type'} eq "new")
    
    elsif ($form{'type'} eq "reply")
      {
        $file = $form{'file'};
        
        $file =~ s/(.*)\.(txt|r)$/$1/i;
        
        $annotate_file = $file;
        
        while ($file =~ /\//)
          {
            $file =~ s/(.*)\/(.*)/$2/i;
          }                     #while ($file =~ /\//)
        
        #a temporary iteration variable
        $num = 1;
        
        #find a file name not already existing for the new annotation in 
        #the annotation directory
        while (existsAndStore("/home/rebelsky/public_html/Blazers/Annotations/Summer1999/Stored_Annotations/" . "$anndir" . "/" . "$file" . "_" . "$num" . ".r",$data))
          {
            $num = $num + 1;
          }                     # while (fileExists("...."$num" . ".r"))
        
        $annfile = "$file" . "_" . "$num" . ".r";
        rIndex($annotate_file,"/home/rebelsky/public_html/Blazers/Annotations/Summer1999/Stored_Annotations/" . "$anndir" . "\/" . "$annfile",$form{'title'});
      }                         #elsif ($form{'type'} eq "reply")
    else 
      {
        #if it is not a new annotation and not a reply so we need to code 
        #what should happen in that case
        return "error";
      }                         #else

    #return the annotation file address
    return "/home/rebelsky/public_html/Blazers/Annotations/Summer1999/Stored_Annotations/" . "$anndir" . "/" . "$annfile";
  }                             #sub createTextFile


###########################################################################
# indexUrl #
###########################################################################
# This subroutine finds the page that is to be annotated in the index.  If
# it is there it gets the directory name stored with it.  If it is not
# there, it creates a new directory for the page and adds a line to the 
# url index documenting this addition.
# ARGUMENTS:  The URL of the page that is to be annotated.
# RETURNS:  The directory where the annotation file should be stored.
###########################################################################
sub indexUrl 
  {
    #read in the argument
    my $url = shift;            #url of page being annotated
    #other variables
    my @info;                   #the data from the url index in array form
    my $info;                   #the data from the url index in string form
    my $found = 0;              #boolean: has the url directory been found
    my $dir;                    #the directory associated with the url
    my $num;                    #iteration variable
    
    #read in the annotated-url index file
    $info = readInFile("/home/rebelsky/public_html/Blazers/Annotations/Summer1999/Stored_Annotations/index.txt");
    @info = split(/^/m,$info);

    #search the index for the url
    foreach $line (@info) 
      {
        if ($line =~ /$url\|/)
          {
            $line =~ /.*?\|(.*)/;
            $dir = $1;
            $found = 1;
            last;
          }                     #if ($line =~ /$url\|/)
        else
          {
            next;
          }                     #else
      }                         #foreach $line (@info)
    
    #see if the url was not found in the index and act accordingly
    if ($found == 0)
      {
        #temporary variable for iteration
        $num = 1;
        
        #see if the directory exists...find one that doesn't
        while (fileExists("/home/rebelsky/public_html/Blazers/Annotations/Summer1999/Stored_Annotations/URL" . "$num"))
          {
            $num = $num + 1;
          }                     #while (fileExists("..."$num"))
        
        $dir = "URL" . "$num";
        
        #make the directory
        makeDir("/home/rebelsky/public_html/Blazers/Annotations/Summer1999/Stored_Annotations/" . "$dir");
        
        #add the url directory pair to the annotated-url index
        appendFile("/home/rebelsky/public_html/Blazers/Annotations/Summer1999/Stored_Annotations/index.txt","$url\|$dir\n");
        
      }                         #if ($found == 0)
    
    #return the directory for the url
    return $dir;
  }                             #sub indexUrl

###########################################################################
# rIndex #
###########################################################################
# This subroutine updates the reply index after a reply is made.
# ARGUMENTS: The reply index address without the ".ri" extention in string
# form, the reply file address in string form, and the title of the new
# reply in string form.
# RETURNS: It returns 1 to say that it ran smoothly unless the reply index address is "".  Then it returns "error."
###########################################################################
sub rIndex 
  {
    #read in arguments
    my $file = shift;           #beginning of reply index address
    my $link = shift;           #the reply file address
    my $title = shift;          #the title of the reply
    
    #if the file is "", return an error
    if ($file eq "")
      {
        return "error";
      }                         #if ($file == "")
    
    #turn the file name into a reply index name
    $file = $file . ".ri";
    
    #if the reply index exists, update it
    if (fileExists($file))
      {
        appendFile($file,"$link\|$title\n");
      }                         #if (fileExists($file))
    #if the reply index does not exist, create it
    else
      {
        writeFile($file,"$link\|$title\n");
      }                         #else
    #return the true value to show that it ran correctly
    return 1;
  }                             #sub rIndex

###########################################################################
# confirm #
###########################################################################
# Displays a confirmation that an annotation has been submitted.  If it
# was a reply annotation, when ok is pressed, the new annotation is
# displayed along with the the reply tree.
# ARGUMENTS: A typeglob that is a reference to a hash containing all the
# data for the annotation just made, the file address for the
# annotation just made, and the client connection in order to send a
# response.
# RETURNS: Returns 1 to show that it ran correctly.
###########################################################################
sub confirm 
  {
    #read in arguments
    local(*data) = shift;       #hash containing data for the annotation
    my $file = shift;           #file address for the annotation just made
    my $client = shift;         #client connection
    #other variables
    my $response;               #the response to send the client
    my $response_object;        #the client response object
    #if its a new annotation, print confirmation
    if ($data{'type'} eq "new")
      {
        #print out a web page to confirm the submission
        $response = <<"EOF";
<html>
<meta name=\"Ravel\" content=\"disallow: .*?-.*?-.*?-.*?\$\">
<head>
<script language=\"javascript1.1\">
function pageReload()
  {
    opener.location.reload(true)
  }
<\/script>
<title>Annotation Submitted<\/title>
<\/head>
<body bgcolor=\"white\" onLoad=\"pageReload()\">
<center><h1>Annotation Submitted<\/h1><\/center>
<p>
Your annotation has been submitted.
<\/p>
<form>
<input type=\"button\" onClick=\"self.close()\" name=\"OK\" value=\"OK\">
<\/form>
<\/body>
<\/html>
EOF
      }                         #if ($data{'type'} eq "new"
    #if its a reply annotation, display confirmation and, when ok is 
    #pressed, load the new annotation and reply tree
    elsif ($data{'type'} eq "reply")
      { 
        #Print confirmation with button for reloading annotation with 
        #reply tree
        $response = <<"EOF"; 
<html>
<meta name=\"Ravel\" content=\"disallow: .*?-.*?-.*?-.*?\$\">
<head>
<title>Annotation Submitted<\/title>
<\/head>
<body bgcolor=\"white\">
<center><h1>Annotation Submitted<\/h1><\/center>
Your annotation has been submitted.
<br>
<form>
<input type=\"button\" name=\"ok\" value=\"OK\" onClick=document.location=\"http://ravel/Annotation/annotation.cgi?$file\&$data{'url'}\&$data{'last_time'}\">
<\/form>
<\/body>
<\/html>
EOF
      }                         #elsif ($data{'type'} eq "reply")
    #create the response object and send the response
    $response_object = HTTP::Response->new(200);
    $response_object->content($response);
    $client->send_response($response_object);

    #return the true value to show that it ran correctly
    return 1;
  }                             #sub confirm

#####################
# Pod Documentation #
#####################
=pod

=head1 ID

=over 4

=item Package

ParseForm.pm (Previously known as parse_form.cgi)

=item Author

Rachel Heck (edited by Sarah Luebke)

=item Description

Displays a confirmation that an annotation has been submitted.  If it was
a reply annotation, when ok is pressed, the new annotation is displayed 
along with the the reply tree.

=back

=head1 Subroutines

=over 4

=item parse_form_execute

This subroutine gets the user information from ravel and then calls the 
apropriate subroutines in order to store an added annotation.

=item parseForm

This subroutine parses the form found at http://www.math.grin.edu/
~rebelsky/Blazers/Annotations/Summer1999/add.html and stores the results 
in a referenced hash.

=item createTextFile

This subroutine creates an annotation file and stores it in a specified 
directory.

=item indexUrl

This subroutine finds the page that is to be annotated in the index.  If 
it is there it gets the directory name stored with it.  If it is not 
there, it creates a new directory for the page and adds a line to the url 
index documenting this addition.

=item rIndex

This subroutine updates the reply index after a reply is made.

=item confirm

Displays a confirmation that an annotation has been submitted.  If it was 
a reply annotation, when ok is pressed, the base annotation is displayed 
along with the the reply tree.

=back

=head1 History

=over 4 

=item [9 July 1999]

The script and the subroutines parseForm, createTextFile, indexUrl, 
rIndex, and confirm work and are fully commented.

=item [12 July 1999]

Edited parseForm to read in protection information from new annotations and 
createTextFile so that it will put the protection information on the end of 
the annotation file.  Also updated to pass group information.

=item [13 July 1999]

Uses the networked database.

=item [16 July 1999]

Pop-up annotation windows will not use plug-ins in the Ravel server 
anymore.

=item [23 July 1999]

Sarah added the line to change all links in an annotation to load in the 
main window.  In addition, when a base annotation is made, the main page 
will automatically reload now.

=item [27 July 1999]

Edited the reload command making it an unconditional reload (it will not 
reload the page from cache).  The script is now getting and passing the 
last time that the user viewed the main web page.

=item [28 July 1999]

When you get the confirmation from a new reply annotation and press the ok 
button, the new annotation will be displayed with the whole reply tree 
instead of just the base annotation.  It now escapes the special uri characters before storing the annotation data.

=item [30 July 1999]

Now it only escapes vertical bars instead of all special uri characters.

=item [4 August 1999]

Turned the script (parse_form.cgi) into a package (ParseForm.pm) in 
order to use Proxy URLs.  This adds security.  All cgi calls are now Proxy 
URLs.  The name, email, and groups information are no longer being passed 
to cgi scripts.

=item [5 August 1999]

The subroutine parse_form_execute is working and is fully commented.

=back

=cut

