very easy and makes sense to me however returns a compilation error. here is the full page.cgi:
===============================
#!/usr/bin/perl
# ==============================================================
# -------------
# Links SQL
# -------------
# Links Manager
#
# Author: Alex Krohn
# Email: alex@gossamer-threads.com
# Web: http://www.gossamer-threads.com/
# Version: 1.13
#
# COPYRIGHT NOTICE:
#
# Copyright 1999
Gossamer Threads Inc. All Rights Reserved.
# No redistribution of this script may be made without prior
# written consent.
#
# By using this program you agree to indemnify
Gossamer Threads # Inc. from any liability.
#
# Please see the README for full license details.
#
# ==============================================================
# Load required modules.
# ---------------------------------------------------
use CGI ();
use CGI::Carp qw/fatalsToBrowser/;
use lib 'admin';
use Links;
use Links::DBSQL;
use Links::DB_Utils;
use Links::HTML_Templates;
use strict;
use vars qw!$LINKDB $CATDB $GRAND_TOTAL $USE_HTML!;
&main;
# ==============================================================
sub main {
if (! $USER) {
print $IN->redirect( Links::redirect_login_url ('page') );
return;
}
# --------------------------------------------------------------
# Wrap in a subroutine to prevent possible mod_perl probs.
#
my $in = new CGI;
my $page = $in->param('g');
# Clean up page a little.
$page =~ s,^/*,,g;
$page =~ s,/*$,,g;
# Create our database objects.
$LINKDB = new Links::DBSQL $LINKS{admin_root_path} . "/defs/Links.def";
$CATDB = new Links::DBSQL $LINKS{admin_root_path} . "/defs/Category.def";
$GRAND_TOTAL = $LINKDB->total();
# Make sure we set dynamic mode on.
$in->param('d' => 1);
# Figure out what to look for.
my ($new_match) = $LINKS{build_new_url} =~ m,^$LINKS{build_root_url}/(.+),o;
my ($cool_match) = $LINKS{build_cool_url} =~ m,^$LINKS{build_root_url}/(.+),o;
my ($rate_match) = $LINKS{build_ratings_url} =~ m,^$LINKS{build_root_url}/(.+),o;
my ($detail_match) = $LINKS{build_detail_url} =~ m,^$LINKS{build_root_url}/(.+),o;
CASE: {
($page =~ /^$new_match/o) and do { &generate_new_page ($in); last CASE; };
($page =~ /^$cool_match/o) and do { &generate_cool_page ($in); last CASE; };
($page =~ /^$rate_match/o) and do { &generate_rate_page ($in); last CASE; };
($page =~ /^$detail_match/o) and do { &generate_detailed_page ($in); last CASE;
};
($page =~ /^\s*$/) and do { &generate_home_page ($in); last CASE; };
# Default
&generate_category_page ($in); last CASE;
};
}
sub generate_home_page {
# --------------------------------------------------------
# Display the home page.
#
my $in = shift;
my ($sth, $tmp, $root_cat_r, $cat, $category, $total);
# Get the list of root categories and build the home page.
$sth = $LINKDB->prepare (qq!
SELECT c.*
FROM CategoryHierarchy AS h, Category
AS c
WHERE h.CategoryID = 0 AND
h.SubCategoryID = c.ID
!);
$sth->execute();
if ($sth->rows) {
$tmp = $sth->fetchall_arrayref();
foreach $cat (@{$tmp}) { $root_cat_r->{${$cat}[1]} = $CATDB->array_to_hash($cat);
}
}
else { $root_cat_r = undef; }
$category = &site_html_print_cat ($root_cat_r, $in) if ($root_cat_r);
$total = $LINKDB->total();
# Print the page.
print $in->header();
print &site_html_home ( { category => $category, grand_total => $total }, $in );
}
sub generate_category_page {
# --------------------------------------------------------
# This routine will display a category.
#
my $in = shift;
my ($page, $id, $category_r, $subcat_info, $subcategory_r, $tmp, %OUT, $directory, $url,
$get_links, $links_r, $get_alt, $alt_r, $numlinks, $get_related, $name, $page_num,
$good);
# First thing we do is lookup the category name.
$page_num = 1;
$page = $in->param('g');
$page =~ s,/more(\d+)\.s?html?$,, and ($page_num = $1);
$page =~ s,$LINKS{build_index},,o;
$page =~ s,^/,,g;
$page =~ s,/$,,g;
$good = $page;
$page =~ s,_, ,g;
# Now we get the ID number of the category based on the URL. If
# we have foreign_char on, then the last number is equal to the ID.
if ($LINKS{foreign_char}) {
($id) = $page =~ /(\d+)$/;
}
# If we have build_directory_field, then the whole URL is used to
# look up the ID number.
elsif ($LINKS{build_directory_field}) {
my $sth = $CATDB->prepare (" SELECT ID FROM Category WHERE
$LINKS{build_directory_field} = ? ");
$sth->execute ($good);
($id) = $sth->fetchrow_array;
}
# Otherwise, we just get it based on the URL.
else {
$id = &get_category_id ($page);
# Oops, we probably had a escaped character '_' that wasn't a space. We need
# to look it up manually.
if (!$id) {
$good =~ s/['"]//g;
my $sth = $CATDB->prepare (" SELECT ID from Category WHERE Name LIKE
'$good' ");
$sth->execute();
if ($sth->rows) {
($id) = $sth->fetchrow_array;
}
}
}
# Quit if this isn't a valid category.
if (! $id) {
print $in->header();
&site_html_error ( { error => "We don't seem to have a category by the name
'$page'."}, $in);
return;
}
# Get the category info.
$category_r = $CATDB->get_record ($id, 'HASH');
# Get the subcategory info and store as a ref to a list of array refs.
$subcat_info = $CATDB->prepare ( qq!
SELECT Category.*
FROM Category,
CategoryHierarchy
WHERE
CategoryHierarchy.CategoryID = ? AND
CategoryHierarchy.Depth = 1 AND
CategoryHierarchy.SubCategoryID = Category.ID
!) or die "Can't prepare:
$DBI::errstr";
$subcat_info->execute($id);
$subcategory_r = undef;
if ($subcat_info->rows()) {
$tmp = $subcat_info->fetchall_arrayref();
foreach my $cat (@{$tmp}) { $subcategory_r->{${$cat}[1]} =
$CATDB->array_to_hash($cat) }
}
# Set the category info for displaying purposes.
$OUT{category_id} = $category_r->{'ID'};
$OUT{category_name} = $category_r->{'Name'};
$OUT{header} = $category_r->{'Header'};
$OUT{footer} = $category_r->{'Footer'};
$OUT{description} = $category_r->{'Description'};
$OUT{meta_name} = $category_r->{'Meta_Description'};
$OUT{meta_keywords} = $category_r->{'Meta_Keywords'};
$OUT{random} = rand (10000);
$OUT{random1} = rand (10000);
$OUT{random2} = rand (10000);
$OUT{random3} = rand (10000);
# Clean up the name.
$directory = $LINKS{build_root_path} . "/" . &build_clean_name ($OUT{category_name});
$url = $LINKS{build_root_url} . "/" . &build_clean_name ($OUT{category_name});
if ($page_num > 1) {
$OUT{title_linked} = &build_linked_title ("$OUT{category_name}/Page
$page_num/");
$OUT{title} = &build_unlinked_title ("$OUT{category_name}/Page
$page_num/");
}
else {
$OUT{title_linked} = &build_linked_title ($OUT{category_name});
$OUT{title} = &build_unlinked_title ($OUT{category_name});
}
$OUT{category_name_escaped} = CGI->escape ($OUT{category_name});
$OUT{category_clean} = $OUT{title};
# Fetch the subcategory list.
$subcategory_r ? ($OUT{category} = &site_html_print_cat ($subcategory_r, $in)) :
($OUT{category} = '');
$get_links = $LINKDB->prepare (" SELECT * FROM Links WHERE CategoryID = ? ORDER BY
$LINKS{build_sort_order_category} LIMIT 1000 ");
$get_links->execute ($category_r->{'ID'});
$links_r = $get_links->fetchall_arrayref || [];
# Get any alternates.
$get_alt = $LINKDB->prepare (" SELECT l.* FROM Links as l, CategoryAlternates as c
WHERE l.ID = c.LinkID AND c.CategoryID = ? ORDER BY $LINKS{build_sort_order_category} LIMIT 1000
");
$get_alt->execute ($category_r->{'ID'});
$alt_r = $get_alt->fetchall_arrayref || [];
# Sort them together.
$links_r = &build_sort_links ($links_r, $alt_r) if (@{$alt_r});
$numlinks = $#{$links_r} + 1 || 0;
$OUT{total} = $numlinks;
$OUT{'next_span'} = &toolbar ($url, $numlinks, $page_num) if ($LINKS{build_span_pages}
and ($numlinks > $LINKS{build_links_per_page}));
# Get the header and footer from file if it exists, otherwise assume it is html.
if ($OUT{header} && (length($OUT{header}) < 20) && ($OUT{header} !~ /\s+/) && (-e
"$LINKS{admin_root_path}/headers/$OUT{header}")) {
open (HEAD, "<$LINKS{admin_root_path}/headers/$OUT{header}") or die "Unable to
open header file: $LINKS{admin_root_path}/headers/$OUT{header}. Reason: $!";
$OUT{header} = join "", <HEAD>;
close HEAD;
}
if ($OUT{footer} && (length($OUT{footer}) < 20) && ($OUT{footer} !~ /\s+/) && (-e
"$LINKS{admin_root_path}/footers/$OUT{footer}")) {
open (FOOT, "<$LINKS{admin_root_path}/footers/$OUT{footer}") or die "Unable to
open footer file: $LINKS{admin_root_path}/footers/$OUT{footer}. Reason: $!";
$OUT{footer} = join "", <FOOT>;
close FOOT;
}
# Calculate the related entries and put in a <LI> list.
$get_related = $LINKDB->prepare (" SELECT Category.Name FROM CategoryRelations, Category
WHERE CategoryRelations.CategoryID = ? AND CategoryRelations.RelatedID = Category.ID");
$get_related->execute($OUT{category_id});
$OUT{related} = '';
while (($name) = $get_related->fetchrow_array) {
$OUT{related} .= qq|<li><a href="$LINKS{build_root_url}/|;
$OUT{related} .= &build_clean_name ($name);
$OUT{related} .= qq|/$LINKS{build_index}">$name</a></li>|;
}
$OUT{next} = $OUT{prev} = $OUT{links} = "";
if ($LINKS{build_span_pages}) {
if ($numlinks > $LINKS{build_links_per_page} * $page_num) {
$OUT{next} = $url . "/more" . ($page_num+1) . $LINKS{build_extension};
}
if ($numlinks > $LINKS{build_links_per_page} and ($page_num > 1)) {
($page_num == 2) ?
($OUT{prev} = $url . "/") :
($OUT{prev} = $url . "/more" . ($page_num-1) .
$LINKS{build_extension});
}
@{$links_r} = @{$links_r}[(($page_num-1) * $LINKS{build_links_per_page}) ..
($page_num * $LINKS{build_links_per_page})-1];
}
# Generate the links listing.
for my $i (0 .. $#{$links_r}) {
last if (ref $links_r->[$i] ne 'ARRAY');
$tmp = $LINKDB->array_to_hash ($links_r->[$i]);
$OUT{links} .= &site_html_link ($tmp, $in);
}
# Print the page.
print $in->header();
print &site_html_category (\%OUT, $in);
}
sub generate_new_page {
# --------------------------------------------------------
# Creates a "What's New" page. Set $build_span_pages to 1 in links.cfg
# and it will create a seperate page for each date.
#
my $in = shift;
my (%OUT, $page, $date, $long_date, $sth, $link, $link_output, $link_results, $total,
$grand_total,
$category, $category_clean, $current, $current_cat, $current_date);
print $in->header();
# Figure out if we are getting a specific date, or the main page.
$page = $in->param('g');
if ($page =~ /.*(\d\d\d\d\-\d\d\-\d\d).*/) {
$date = $1;
}
else {
$date = '';
}
# Get the grand total.
$OUT{'grand_total'} = $GRAND_TOTAL;
# We are displaying a single date page.
if ($date) {
$sth = $LINKDB->prepare (qq!
SELECT Links.*, Category.Name
FROM Links, Category
WHERE Links.isNew = 'Yes' AND
Links.Add_Date = '$date' AND Links.CategoryID = Category.ID
ORDER BY Category.Name,
$LINKS{build_sort_order_new}
LIMIT 1000
!);
$sth->execute();
$OUT{'total'} = $sth->rows();
$OUT{'title_linked'} = &build_linked_title ("New/$date");
while ($link = $sth->fetchrow_hashref) {
$category = $link->{Name};
if ($category ne $current) {
$category_clean = &build_clean_name ($category);
$OUT{'link_results'} .= qq|<P><A
HREF="$LINKS{build_root_url}/$category_clean/">$category</A>\n|;
$current = $category;
}
$OUT{'link_results'} .= &site_html_link ($link, $in);
}
}
# We are displaying the main page with links to subpages.
elsif ($LINKS{build_span_pages}) {
$sth = $LINKDB->prepare (qq!
SELECT COUNT(*), Add_Date
FROM Links
WHERE Links.isNew = 'Yes'
GROUP BY Add_Date
ORDER BY Add_Date DESC
LIMIT 50
!);
$sth->execute();
while (($total, $date) = $sth->fetchrow_array) {
$long_date = $LINKDB->long_date ($date);
$link_results .= qq!<li><a
href="$LINKS{build_new_url}/$date$LINKS{build_extension}">$long_date</a> ($total)!;
$grand_total += $total;
}
$OUT{'total'} = $grand_total;
$OUT{'title_linked'} = &build_linked_title ("New");
$OUT{'link_results'} = "<ul>$link_results</ul>";
}
# Otherwise we are displaying the main what's new page with all links on one page.
else {
$sth = $LINKDB->prepare (qq!
SELECT Links.*, Category.Name
FROM Links, Category
WHERE Links.isNew = 'Yes' AND
Links.CategoryID = Category.ID
ORDER BY
Links.Add_Date,Category.Name,$LINKS{build_sort_order_new}
LIMIT 1000
!);
$sth->execute;
$OUT{'total'} = $sth->rows();
$OUT{'title_linked'} = &build_linked_title ("New");
$current_cat = $current_date = '';
while ($link = $sth->fetchrow_hashref) {
$date = $link->{Add_Date};
$category = $link->{Name};
if ($date ne $current_date) {
$OUT{'link_results'} and ($OUT{'link_results'} .=
"</blockquote>");
$OUT{'link_results'} .=
"<p><strong>$long_date</strong>\n<blockquote>";
$current_date = $date;
}
if ($category ne $current_cat) {
$category_clean = &build_clean_name ($category);
$OUT{'link_results'} .= qq|<P><A
HREF="$LINKS{build_root_url}/$category_clean/">$category</A>\n|;
$current_cat = $category;
}
$OUT{'link_results'} .= &site_html_link ($link, $in);
}
$OUT{'link_results'} and ($OUT{'link_results'} .= "</blockquote>");
}
print &site_html_new (\%OUT, $in);
}
sub generate_cool_page {
# --------------------------------------------------------
# Creates a "What's Cool" page.
#
my $in = shift;
my (%link_output, $link, $sth, $total, $category_clean, $category, $link_results,
$title_linked, $percent);
# Get all the cool links.
$sth = $LINKDB->prepare (qq!
SELECT Links.*, Category.Name
FROM Links, Category
WHERE Links.isPopular = 'Yes' AND
Links.CategoryID = Category.ID
ORDER BY $LINKS{build_sort_order_cool}
LIMIT 1000
!);
$sth->execute();
# Create the HTML for the individual links.
$total = $sth->rows();
while ($link = $sth->fetchrow_hashref) {
$link_output{$link->{'Name'}} .= &site_html_link ($link, $in);
}
# Create the HTML for the category headers, and join it all together into link_results.
foreach $category (sort keys %link_output) {
$category_clean = &build_clean_name ($category);
$link_results .= qq|<P><A
HREF="$LINKS{build_root_url}/$category_clean/$LINKS{build_index}">$category</A>\n|;
$link_results .= $link_output{$category};
}
# Write it out to the file.
$title_linked = &build_linked_title ("Cool");
($LINKS{build_pop_cutoff} < 1) ? ($percent = $LINKS{build_pop_cutoff} * 100 . "%") :
($percent = $LINKS{build_pop_cutoff});
print $in->header();
print &site_html_cool ( { grand_total => $GRAND_TOTAL, total => $total, link_results =>
$link_results, title_linked => $title_linked, percent => $percent }, $in );
}
sub generate_rate_page {
# --------------------------------------------------------
# Creates a Top 10 ratings page.
#
my $in = shift;
my ($rated, $voted, $top_rated, $top_votes, $min_v, $max_v, $min_r, $max_r, $link);
# Get the top 10 ratings and votes..
$rated = $LINKDB->prepare (qq!
SELECT *
FROM Links
WHERE Votes >= 10
ORDER BY Rating DESC
LIMIT 10
!);
$rated->execute();
$voted = $LINKDB->prepare (qq!
SELECT *
FROM Links
WHERE Votes >= 10
ORDER BY Votes DESC
LIMIT 10
!);
$voted->execute();
# Now build the html.
$top_rated = ''; $top_votes = '';
$min_v = 99999999; $max_v = 0;
while ($link = $voted->fetchrow_hashref) {
$min_v = $link->{'Votes'} if ($min_v > $link->{'Votes'});
$max_v = $link->{'Votes'} if ($max_v < $link->{'Votes'});
$top_votes .= qq~<tr><td align=center>${$link}{'Rating'}</td><td
align=center>${$link}{'Votes'}</td><td><a
href="${$link}{'URL'}">${$link}{'Title'}</a></td></tr>\n~;
}
$min_r = 99999999; $max_r = 0;
while ($link = $rated->fetchrow_hashref) {
$min_r = $link->{'Votes'} if ($min_r > $link->{'Votes'});
$max_r = $link->{'Votes'} if ($max_r < $link->{'Votes'});
$top_rated .= qq~<tr><td align=center>${$link}{'Rating'}</td><td
align=center>${$link}{'Votes'}</td><td><a
href="${$link}{'URL'}">${$link}{'Title'}</a></td></tr>\n~;
}
# And write it to a file.
($min_v == 99999999) and ($min_v = 0);
($min_r == 99999999) and ($min_r = 0);
print $in->header();
print &site_html_ratings ( { top_rated => $top_rated, top_votes => $top_votes }, $in );
}
sub generate_detailed_page {
# --------------------------------------------------------
# This routine build a single page for every link.
#
my $in = shift;
my ($page, $id, $link, $category, $title_linked, $total, $output, $detail_match);
$page = $in->param('g');
($detail_match) = $LINKS{build_detail_url} =~ m,^$LINKS{build_root_url}/(.+),o;
($id) = $page =~ m,$detail_match/(\d+),o;
if (!$id) {
print $in->header();
&site_html_error ( { error => "Sorry, I'm not sure what page you are asking for:
'$page'" }, $in);
return;
}
$link = $LINKDB->get_record ($id, 'HASH');
if (!$link) {
print $in->header();
&site_html_error ( { error => "Sorry, we don't seem to have link '$id'" }, $in);
return;
}
$category = $CATDB->get_record ($link->{'CategoryID'}, 'HASH');
$title_linked = &build_linked_title ($category->{'Name'} . "/" . $link->{'Title'});
print $in->header();
print &site_html_detailed ($link, { grand_total => $GRAND_TOTAL, title_linked =>
$title_linked }, $in);
}
sub build_sort_links {
# --------------------------------------------------------
# Merges two array refs into one link list.
#
my ($arr_a, $arr_b) = @_;
my @names = split /,/, $LINKS{build_sort_order};
my @fields = map { $LINKDB->position($_) - 1 } @names;
my @c = sort { lc join ("", @{$a}[@fields]) cmp lc join ("", @{$b}[@fields]) } @{$arr_b},
@{$arr_a};
return \@c;
}
sub toolbar {
# --------------------------------------------------------
# Create an Altavista style toolbar for the next and previous pages.
#
my ($root_url, $numhits, $nh) = @_;
my ($next_hit, $prev_hit, $maxhits, $left, $right, $upper, $lower, $url, $i);
$maxhits = $LINKS{build_links_per_page};
$next_hit = $nh + 1;
$prev_hit = $nh - 1;
# First, set how many pages we have on the left and the right.
$left = $nh; $right = int($numhits/$maxhits) - $nh;
# Then work out what page number we can go above and below.
($left > 7) ? ($lower = $left - 7) : ($lower = 1);
($right > 7) ? ($upper = $nh + 7) : ($upper = int($numhits/$maxhits) + 1);
# Finally, adjust those page numbers if we are near an endpoint.
(7 - $nh >= 0) and ($upper = $upper + (8 - $nh));
($nh > ($numhits/$maxhits - 7)) and ($lower = $lower - ($nh - int($numhits/$maxhits - 7)
- 1));
$url = "";
# Then let's go through the pages and build the HTML.
($nh > 1) and (($nh == 2) ? ($url .= qq~<a href="$root_url/$LINKS{build_index}">[<<]</a>
~) : ($url .= qq~<a href="$root_url/more$prev_hit$LINKS{build_extension}">[<<]</a> ~));
for ($i = 1; $i <= int($numhits/$maxhits) + 1; $i++) {
if ($i < $lower) { $url .= " ... "; $i = ($lower-1); next; }
if ($i > $upper) { $url .= " ... "; last; }
if ($i == 1) { ($i == $nh) ? ($url .= qq~$i ~) : ($url .= qq~<a
href="$root_url/$LINKS{build_index}">$i</a> ~); }
else { ($i == $nh) ? ($url .= qq~$i ~) : ($url .= qq~<a
href="$root_url/more$i$LINKS{build_extension}">$i</a> ~); }
if ($i * $maxhits == $numhits) { $nh == $i and $next_hit = $i; last; }
}
$url .= qq~<a href="$root_url/more$next_hit$LINKS{build_extension}">[>>]</a> ~ unless
($next_hit == $nh or ($nh * $maxhits > $numhits));
return $url;
}
1;