#!/usr/bin/perl
##############################################################################
# Guestbook                      Version 2.3.1                               #
# Copyright 1995                 worldwidemart.com                           #
# Created 10/29/95               Last Modified 10/29/95                      #
# Scripts Archive:               https://www.worldwidemart.com/scripts/          #
##############################################################################
# COPYRIGHT NOTICE                                                           #
# This script is distributed under the Artistic License.                     #
# You may freely use and modify it, keeping this copyright notice intact.    #
##############################################################################

use strict;
use warnings;
use CGI qw(:standard);
use CGI::Carp qw(fatalsToBrowser);
use Fcntl qw(:flock);

# Configuration
my $guestbook_file = './guestbook.html';   # Main guestbook display file
my $guestlog_file  = './guestlog.html';    # Log file for entries
my $max_entries    = 100;                   # Maximum entries to display
my $date_format    = '%B %d, %Y at %I:%M %p'; # Date format
my $allow_html     = 0;                     # Allow HTML in comments (0=no, 1=yes)
my $mail_notify    = 0;                     # Email notification
my $admin_email    = 'webmaster@example.com';

# Valid referers (leave empty to allow all)
my @valid_referers = ();

##############################################################################
# Main Script
##############################################################################

my $cgi = CGI->new;
my $action = $cgi->param('action') || 'view';

if ($action eq 'add') {
    add_entry();
} else {
    view_guestbook();
}

##############################################################################
# Subroutines
##############################################################################

sub view_guestbook {
    print $cgi->header('text/html');

    if (-e $guestbook_file) {
        open(my $fh, '<', $guestbook_file) or die "Cannot open guestbook: $!";
        print while <$fh>;
        close($fh);
    } else {
        print_default_page();
    }
}

sub add_entry {
    # Get form data
    my $name    = $cgi->param('name') || '';
    my $email   = $cgi->param('email') || '';
    my $url     = $cgi->param('url') || '';
    my $city    = $cgi->param('city') || '';
    my $country = $cgi->param('country') || '';
    my $comments = $cgi->param('comments') || '';

    # Validate required fields
    unless ($name && $comments) {
        error_page("Name and Comments are required fields.");
        return;
    }

    # Sanitize input
    unless ($allow_html) {
        $name     = $cgi->escapeHTML($name);
        $email    = $cgi->escapeHTML($email);
        $url      = $cgi->escapeHTML($url);
        $city     = $cgi->escapeHTML($city);
        $country  = $cgi->escapeHTML($country);
        $comments = $cgi->escapeHTML($comments);
        $comments =~ s/\n/<br>\n/g;
    }

    # Validate email format
    if ($email && $email !~ /^[\w\.\-]+\@[\w\.\-]+\.\w+$/) {
        error_page("Invalid email address format.");
        return;
    }

    # Validate URL format
    if ($url && $url !~ /^https?:\/\//i) {
        $url = "http://$url";
    }

    # Get timestamp
    my @months = qw(January February March April May June July August September October November December);
    my ($sec,$min,$hour,$mday,$mon,$year) = localtime();
    $year += 1900;
    my $ampm = $hour >= 12 ? 'PM' : 'AM';
    $hour = $hour % 12 || 12;
    my $date = sprintf("%s %d, %d at %d:%02d %s", $months[$mon], $mday, $year, $hour, $min, $ampm);

    # Build entry HTML
    my $entry = build_entry($name, $email, $url, $city, $country, $comments, $date);

    # Add to guestbook
    add_to_guestbook($entry);

    # Add to log
    log_entry($name, $email, $url, $city, $country, $comments, $date);

    # Send notification if enabled
    if ($mail_notify) {
        send_notification($name, $email, $comments);
    }

    # Redirect to guestbook
    print $cgi->redirect($guestbook_file);
}

sub build_entry {
    my ($name, $email, $url, $city, $country, $comments, $date) = @_;

    my $name_display = $name;
    if ($email) {
        $name_display = qq{<a href="mailto:$email">$name</a>};
    }

    my $location = '';
    if ($city || $country) {
        $location = join(', ', grep { $_ } ($city, $country));
        $location = " from $location";
    }

    my $homepage = '';
    if ($url) {
        $homepage = qq{ | <a href="$url" target="_blank">Homepage</a>};
    }

    return <<ENTRY;
<div class="guestbook-entry" style="border: 1px solid #ddd; padding: 15px; margin: 15px 0; border-radius: 5px; background: #fafafa;">
    <p style="margin: 0 0 10px 0;"><strong>$name_display</strong>$location$homepage</p>
    <p style="margin: 0 0 10px 0;">$comments</p>
    <p style="margin: 0; font-size: 0.9em; color: #666;">$date</p>
</div>
ENTRY
}

sub add_to_guestbook {
    my ($entry) = @_;

    my $content = '';

    if (-e $guestbook_file) {
        open(my $fh, '<', $guestbook_file) or die "Cannot read guestbook: $!";
        flock($fh, LOCK_SH);
        local $/;
        $content = <$fh>;
        close($fh);
    } else {
        $content = get_template();
    }

    # Insert new entry after marker
    my $marker = '<!-- GUESTBOOK ENTRIES -->';
    $content =~ s/(\Q$marker\E)/$1\n$entry/;

    # Write back
    open(my $fh, '>', $guestbook_file) or die "Cannot write guestbook: $!";
    flock($fh, LOCK_EX);
    print $fh $content;
    close($fh);
}

sub log_entry {
    my ($name, $email, $url, $city, $country, $comments, $date) = @_;

    open(my $fh, '>>', $guestlog_file) or return;
    flock($fh, LOCK_EX);
    print $fh "$date|$name|$email|$url|$city|$country|$comments\n";
    close($fh);
}

sub send_notification {
    my ($name, $email, $comments) = @_;

    # Simple notification (implement based on your mail setup)
    # open(my $mail, '|-', '/usr/sbin/sendmail -t');
    # print $mail "To: $admin_email\n...";
    # close($mail);
}

sub error_page {
    my ($message) = @_;

    print $cgi->header('text/html');
    print <<HTML;
<!DOCTYPE html>
<html>
<head>
    <title>Guestbook Error</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; }
        .error { background: #fff3cd; padding: 20px; border-radius: 5px; border: 1px solid #ffc107; }
    </style>
</head>
<body>
    <h1>Guestbook Error</h1>
    <div class="error">
        <p>$message</p>
        <p><a href="javascript:history.back()">Go Back</a></p>
    </div>
</body>
</html>
HTML
}

sub print_default_page {
    print get_template();
}

sub get_template {
    return <<'TEMPLATE';
<!DOCTYPE html>
<html>
<head>
    <title>Guestbook</title>
    <style>
        body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
        h1 { color: #333; }
        .sign-link { background: #007bff; color: white; padding: 10px 20px; text-decoration: none; border-radius: 5px; }
    </style>
</head>
<body>
    <h1>Guestbook</h1>
    <p><a href="addguest.html" class="sign-link">Sign the Guestbook</a></p>
    <hr>
    <!-- GUESTBOOK ENTRIES -->
    <p><em>Be the first to sign our guestbook!</em></p>
</body>
</html>
TEMPLATE
}

__END__

=head1 NAME

guestbook.pl - Website Guestbook Script

=head1 DESCRIPTION

Allows visitors to sign your guestbook and leave comments on your website.
A classic feature from the early web era.

=head1 LICENSE

Artistic License

=cut
