package Comments;
# gets comments form parameters, generates comments form
#
use Exporter;
@ISA = qw(Exporter);
use strict;

use CGI;
use CGI::Carp qw( fatalsToBrowser);

# processes POST data from a comments form sent to the program
# create a new object
# to determine if data has been received call commentReceived() 

    

sub new {
# calling sequence
# CommentsProcessingObj->new($cgiObj)

# start by getting data we can't get later
    my $invocant = shift @_;
    my $className = ref($invocant) || $invocant;
    my $self = {};
    bless ($self, $className);
    
    # and our cgi object
    my $cgiObj    = shift;
    
# check whether we've received any post
    $self->{COMMENT_RECEIVED}    = undef;
    my @listOfParamsReceived        = $cgiObj->param();
    foreach my $elem (@listOfParamsReceived) {
        if ( $elem eq "text" ) {
            $self->{COMMENT_RECEIVED}        = 1;
        } # end if
    } # end foreach
    
    # whether we've had post or not
    # I like all relevant parameters to be initialised
    $self->{TEXT}                    = $cgiObj->param('text');
    $self->{TEXT_ERRORS}            = undef;
    $self->{TEXT_DIAGNOSTIC}        = undef;
    $self->{CGI_OBJ}                = $cgiObj;
    
    if ( ! $self->{COMMENT_RECEIVED} ) {
        return $self;
    } # end if
    
    
    validate($self);
    
    
    return $self;


} # end new

sub commentReceived {
my $self    = shift;
    return $self->{COMMENT_RECEIVED};
} # end commentReceived

sub text {
my $self    = shift;
    return $self->{TEXT};
} # end getText

sub textErrors {
my $self    = shift;
    return $self->{TEXT_ERRORS};
} # end getTextErrors

sub textDiagnostic {
my $self    = shift;
    return $self->{TEXT_DIAGNOSTIC};
} # end textDiagnostic


# private
sub validate {
my $self    = shift;
    if ( ! $self->{TEXT} ) {
        $self->{TEXT_ERRORS}            = 1;
        $self->{TEXT_DIAGNOSTIC}        = "empty text field";
        return;
    } #end if
    
    if ( allSpaces($self->{TEXT}) ) {
        $self->{TEXT_ERRORS}            = 1;
        $self->{TEXT_DIAGNOSTIC}        = "empty text";
        return;
    } #end if

    if ( ! validCharacters($self->{TEXT}) ) {
        $self->{TEXT_ERRORS}            = 1;
        $self->{TEXT_DIAGNOSTIC}        = "Text contains invalid characters";
    } #end if
    
    return;

} # end validate


# private
sub allSpaces {
my $pMessage    = shift;
    if ($pMessage =~ /\A\s+\z/)    { return 1; } # nothing there but spaces, tabs or new lines
    
    return undef;
    
} # end allSpaces


# private
sub validCharacters {
my $pMessage    = shift;

    
# we allow the inclusion of all printable characters
# where necessary we convert these into HTML character entities
# Needs updating to allow unicode character set

# the message consists of a set of lines terminated by returns, line feeds etc
# we allow the inclusion of e-mail addresses and hence the e-mail character set
    
    my $esc            = '\\\\';
    my $ctrl1        = '\000-\011';        # \007 = bell, \010 = backspace, \011 = horiz tab
                                        # \012 = line feed
    my $ctrl2        = '\013\014';        # \013 = vertical tab, \014 = form feed
                                        # \015 = carriage return
    my $ctrl3        = '\016-\037';        # other non-printing chars
    my $del            = '\0127';            # del
    my $nonASCII    = '\x80-\xff';        # 128 - 255
    
    my $unwantedChars = "$ctrl1$ctrl2$ctrl3$esc$del"."\^\$";
    
    if ($pMessage =~ /$unwantedChars/)    { return undef; }
    if ($pMessage =~ /~!/) { return undef; } # major threat at start of line, don't allow it at all

    return 1;
    
} # end validCharacters


############## form generation ####################


# public
sub setCommentsFormText {
# returns html code representing the comments form, including the text visitor entered into it previously
# called from anypage.pl
# calling sequence    my $text = $commentsObj->setStandardComments($pictureGroup,$pageFileName);
my $self        = shift;
my $groupName            = shift;
my $pageFileName        = shift;
    my $textSentlastTime    = $self->text();
    my $commentFieldAndText         = "<label for='your_comment_text'>your comments  </label>";
        $commentFieldAndText    .= "<textarea id='your_comment_text' name='text' rows='5' cols='30'>$textSentlastTime</textarea>";
    my $sendButtonAndText    = "If you include your e-mail I may reply!   <input type='submit' value='send' />";
    my $commentHeading        = "";    
    if ( $self->textErrors() ) {    
        $commentHeading    = "<h3 class='commentErrors'>Error:". $self->textDiagnostic() . "</h3>";
        $commentHeading    .= "<p class='commentErrors'> please try again.</p>";
    } elsif ( $self->commentReceived() ) {
    # i.e. the comment was received ok
        $commentHeading    = "<h3 class='commentSetOk'>Thank you</h3>";
        # I do this to prevent people just sitting there clicking the send button
        $commentFieldAndText     = "<label for='text'>What you wrote I now have in my inbox</label>";
        $commentFieldAndText    .= "<textarea name='text' rows='5' cols='30'>$textSentlastTime</textarea>";
        $sendButtonAndText        = "<p  class='commentComment'>If you included your e-mail I may reply!</p>";
    } # end if
    
    
    
    my $text = <<FORM;
<a name='commentsForm'> </a>\n
<form name="comments_form" action="http://yourWebsiteDotCom/cgi-bin/gnu/$groupName/$pageFileName#commentsForm" method="post">
<h3>Send me your comments</h3>
$commentHeading
<p>
$commentFieldAndText
</p>
<p>
$sendButtonAndText
</p>
</form>
FORM
    
    return $text;
    
} # end  setCommentsFormText










1;