#!/usr/local/bin/perl # ------------- # Links # ------------- # Links Manager # # File: nph-build.cgi # Description: Builds a set of HTML pages from the template directory. This is a # non parsed header script, and should display the output directly as it may # take quite a while to perform. It can also be called from the # command line or via a cron routine. Read the README for more details. # Author: Alex Krohn # Email: alex@gossamer-threads.com # Web: http://www.gossamer-threads.com/ # Version: 2.01 # # (c) 1998 Gossamer Threads Inc. # # This script is not freeware! Please read the README for full details # on registration and terms of use. # ===================================================================== # Required Librariers # -------------------------------------------------------- eval { ($0 =~ m,(.*)/[^/]+,) && unshift (@INC, "$1"); # Get the script location: UNIX / ($0 =~ m,(.*)\\[^\\]+,) && unshift (@INC, "$1"); # Get the script location: Windows \ require "links.cfg"; # Change this to full path to links.cfg if you have problems. require "$db_lib_path/db_utils.pl"; require "$db_lib_path/links.def"; $build_use_templates ? require "$db_lib_path/site_html_templates.pl" : require "$db_lib_path/site_html.pl"; use vars qw(%category %subcategories @links @new_links @cool_links %stats $grand_total $use_html $nph $date $time); }; if ($@) { print "HTTP/1.0 200 OK\n"; print "Content-type: text/plain\n\n"; print "Error including libraries: $@\n"; print "Make sure they exist, permissions are set properly, and paths are set correctly."; exit; } # ======================================================== eval { &main; }; # Trap any fatal errors so the program hopefully if ($@) { &cgierr("fatal error: $@"); } # never produces that nasty 500 server error page. exit; # There are only two exit calls in the script, here and in in &cgierr. sub main { # -------------------------------------------------------- # $|++; $use_html = 0; $ENV{'REQUEST_METHOD'} and $use_html++; $use_html and (%in = &parse_form); # Either build the whole directory, parts of it, or just the new/popular section. if ($use_html) { if ($in{'staggered'}) { &build_staggered; } else { &build_all; } } else { &build_all; } } sub build_staggered { # -------------------------------------------------------- # Builds the directory in steps. # my %in = &parse_form; $nph++; &html_print_headers() if ($use_html); my %steps = ( 1 => 'Updating New and Popular Records and rebuilding URL database', 2 => 'Rebuilding Category Pages', 3 => 'Building Detailed View Pages', 4 => 'Updating Home/New/Cool Pages' ); my $step = $in{'step'} || 1; my $limit = $in{'limit'} || 20; my $offset = $in{'offset'} || 0; my $auto = $in{'auto'} || 0; my $start = time(); my $date = &get_date; my $time = &get_time; my $header = qq~
Step: $steps{$step}
Pages built on $date at $time -------------------------------------------------------- ~; CASE: { ($step == 1) and do { print $header; print qq~~ if ($auto); print $sub_head; my $t1 = time(); print "Backing up database . . .\n"; &build_backup; print "Done (", time - $t1, " s)\n\n"; $t1 = time(); print "Building URL Index . . .\n"; &build_url_index; print "Done (", time - $t1, " s)\n\n"; print "Updating New and Popular Records . . .\n"; $t1 = time(); &build_update_newpop; print "Done (", time - $t1, " s)\n\n"; print "Updating ratings .. \n"; $t1 = time(); &build_update_ratings; print "Done (", time - $t1, " s)\n\n"; my $elapsed = time() - $start; print "------------------------------------------------\n"; print "Step 1 took $elapsed seconds.\n\n"; print qq~~; last CASE; }; ($step == 2) and do { my @category_list = &category_list; my $i; print $header; if ($auto) { ($offset > $#category_list) ? (print qq~~) : (print qq~~); } print $sub_head; print "Rebuilding Categories $offset -> ", $offset + $limit - 1, ".\n\n"; for ($i = $offset; $i <= $offset + $limit -1; $i++) { last unless ($category_list[$i] =~ /\w+/); %category = (); %subcategories = (); @links = (); @new_links = (); @cool_links = (); %stats = (); $grand_total = 0; my $t1 = time(); print "** Building Category: $category_list[$i] ... \n"; &build_single_category ($category_list[$i]); print "** Done (", time - $t1, " s)!\n\n"; } $offset = $offset + $limit; my $elapsed = time() - $start; print "------------------------------------------------\n"; print "This phase of step 2 took $elapsed seconds.\n\n"; ($offset > $#categories) ? print qq~~ : print qq~~; last CASE; }; ($step == 3) and do { print $header; print qq~~ if ($auto); print $sub_head; if ($build_detailed) { my $t1 = time(); print "Generating detailed view pages . . . \n"; &build_detailed_view; print "** Done (", time - $t1, " s)!\n"; } else { print "Detailed Building is not turned on -- Skipping!\n\n"; } my $elapsed = time() - $start; print "------------------------------------------------\n"; print "Step 3 took $elapsed seconds.\n\n"; print qq~~; last CASE; }; ($step == 4) and do { print $header, $sub_head; my $t1 = time(); print "** Loading Category information . . .\n"; &build_category_information; print "** Done (", time - $t1, " s)!\n\n"; $t1 = time(); print "** Loading Summary information . . .\n"; &build_stats (1); print "** Done (", time - $t1, " s)!\n\n"; $t1 = time(); print "** Creating Home Page . . .\n"; &build_home_page; print "** Done (", time - $t1, " s)!\n\n"; $t1 = time(); print "** Creating What's New Pages . . .\n"; &build_new_page; print "** Done (", time - $t1, " s)!\n\n"; $t1 = time(); print "** Creating What's Cool Page. . .\n"; &build_cool_page; print "** Done (", time - $t1, " s)!\n\n"; $t1 = time(); print "** Creating Top Rated Page. . .\n"; &build_rate_page; print "** Done (", time - $t1, " s)!\n\n"; my $elapsed = time() - $start; print "------------------------------------------------\n"; print qq~Step 4 took $elapsed seconds.\n\nYour site is now up to date!~; last CASE; }; &cgierr("Unkown step: $step."); }; } sub build_all { # -------------------------------------------------------- # Rebuild the entire directory. # Determine if we are printing to command line, or to browser. $nph++; &html_print_headers() if ($use_html); my $start = time(); my $date = &get_date; my $time = &get_time; # Print HTML Header $use_html ? print qq|
| : print qq|Building Pages\n|; print "Pages built on " . $date . " at " . $time . "\n"; print "--------------------------------------------------------\n\n"; # Backup the database. print "Backing up database . . .\n"; &build_backup; print "Done.\n\n"; # Rebuild URL Index (This file is auto-generated, you will never need to touch it! print "Building URL Index . . .\n"; &build_url_index; print "Done.\n\n"; # Update New and Popular Records.. print "Updating New and Popular Records . . .\n"; &build_update_newpop; print "Done.\n\n"; # Update voting information .. print "Updating ratings .. \n"; &build_update_ratings; print "Done.\n\n"; # Load Category Information print "Loading Category Information . . .\n"; &build_category_information; print "Done.\n\n"; # Generate some stats for future pages... print "Gathering Category and Link information . . .\n"; &build_stats; print "Done\n\n"; # Generate detailed view pages. if ($build_detailed) { print "Generating detailed view pages . . . \n"; &build_detailed_view; print "Done\n\n"; } # Create Home Page $use_html ? print qq|Building Home Pages . . .\n| : print qq|Building Home Page . . .\n|; &build_home_page; print "\tDone\n\n"; # Create What's New Page $use_html ? print "Building What's New Page . . .\n" : print "Building What's New Page . . .\n"; &build_new_page; print "Done\n\n"; # Create What's Cool Page $use_html ? print "Building What's Cool Page . . .\n" : print "Building What's Cool Page . . .\n"; &build_cool_page; print "Done\n\n"; # Create Top Rated Page $use_html ? print "Building Top Rated Page . . .\n" : print "Building Top Rated . . .\n"; &build_rate_page; print "Done\n\n"; # Create Category Pages print "Building Category Pages . . .\n"; &build_category_pages; print "Done\n\n"; # We are finished! print "Pages Built (", time() - $start, " s)!"; print "" if ($use_html); } sub build_backup { # -------------------------------------------------------- # Backs up important database files. # my $date = &get_date; if (-e "$db_script_path/backup/$date.links.db") { print "\tBackup exists for today.. Skipping\n"; return; } # Try to do it the right way.. eval { require File::Copy; }; if (!$@) { print "\tBacking up links, category and email database (File::Copy) ... \n"; &File::Copy::copy ("$db_script_path/data/links.db", "$db_script_path/backup/$date.links.db") or &cgierr ("Unable to copy links backup. Reason: $!"); &File::Copy::copy ("$db_script_path/data/categories.db", "$db_script_path/backup/$date.category.db") or &cgierr ("Unable to copy category backup. Reason: $!"); &File::Copy::copy ("$db_script_path/data/email.db", "$db_script_path/backup/$date.email.db") or &cgierr ("Unable to copy email backup. Reason: $!"); } # Otherwise, the ugly way. else { print "\tBacking up links, category and email database (Regular - $@) ... \n"; foreach (qw!links categories email!) { open (TMP, "$db_script_path/data/$_.db") or &cgierr ("Unable to open $db_script_path/data/$_.db. Reason: $!"); open (TMPOUT, ">$db_script_path/backup/$date.$_.db") or &cgierr ("Unable to open $db_script_path/$date.$_.db. Reason: $!"); while (
$long_date\n
"; } CATEGORY: foreach $category (sort keys %{$link_output{$date}}) { $category_clean = &build_clean ($category); $link_results .= qq|"; } } if ($build_span_pages) { $link_results = "$category_clean\n|; $link_results .= ${$link_output{$date}}{$category}; } # Crete the new page, and do a bit of HTML work for the main page. if ($build_span_pages) { open (NEW, ">$build_new_path/$date$build_extension") or cgierr ("unable to open what's new page: $build_new_path/$build_index. Reason: $!"); $use_html ? print qq|\tNew Links for $date: $total\n| : print qq|\tNew Links for $date: $total\n|; print NEW &site_html_new; close NEW; $main_link_results .= qq|
$long_date ($total).|; $main_total += $total; } else { $link_results .= "
$category_clean\n|;
$link_results .= $link_output{$category};
}
$title_linked = &build_linked_title ("Cool");
open (COOL, ">$build_cool_path/$build_index") or cgierr ("unable to open what's cool page: $build_cool_path/$build_index. Reason: $!");
print "\tCool Links: $total\n";
($db_popular_cutoff < 1) ?
($percent = $db_popular_cutoff * 100 . "%") :
($percent = $db_popular_cutoff);
print COOL &site_html_cool(@cool_links);
close COOL;
}
sub build_rate_page {
# --------------------------------------------------------
# Creates a Top 10 ratings page.
my (@values, $id, $votes, $rate, @top_votes, %top_votes, @top_rate, %top_rate);
local ($top_rated, $top_votes);
if ($build_ratings_path =~ m,^$build_root_path/(.*)$,) {
&build_dir ($1);
}
$total = 0;
open (LINKS, $db_links_name) or &cgierr ("unable to open links database: $db_links_name. Reason: $!");
LINE: while ( \n~;
}
foreach (sort { $b <=> $a } @top_rate) {
$seen{$_}++;
%link = &array_to_hash ($seen{$_} - 1, @{$top_rate{$_}});
$top_rated .= qq~$link{'Rating'} $link{'Votes'} $link{'Title'} \n~;
}
open (RATE, ">$build_ratings_path/$build_index") or &cgierr ("unable to open top rated page: $build_ratings_path/$build_index. Reason: $!");
print "\tVote Range: $top_votes[0] .. $top_votes[$#top_votes]\n";
print "\tRate Range: $top_rate[0] .. $top_rate[$#top_rate]\n";
print RATE &site_html_ratings;
close RATE;
}
sub build_dir {
# --------------------------------------------------------
# Verifies that all neccessary directories have been created
# before we create the category file. Takes as input, the category
# to verify, and returns the full directory path.
my $input = shift;
my ($dir, $path) = '';
my @dirs = split /\//, $input;
foreach $dir (@dirs) {
$path .= "/$dir";
&build_check_dir ($build_root_path, $path);
if (! (-e "$build_root_path$path")) {
print "\tMaking Directory ($build_dir_per): '$build_root_path$path' ...";
if (mkdir ("$build_root_path$path", "$build_dir_per")) {;
print "Made. CHMOD ($build_dir_per) ...";
if (chmod ($build_dir_per, "$build_root_path$path")) {;
print "Done.";
}
else { print "CHMOD ($build_dir_per) failed! Reason: $!."; }
}
else { print "mkdir failed! Reason: $!."; }
print "\n";
}
}
return "$build_root_path$path";
}
sub build_linked_title {
# --------------------------------------------------------
# Returns a string of the current category broken up
# by section, with each part linked to the respective section.
my $input = shift;
my (@dirs, $dir, $output, $path, $last);
@dirs = split (/\//, $input);
$last = &build_clean(pop @dirs);
$output = qq| Top :|;
foreach $dir (@dirs) {
$path .= "/$dir";
$dir = &build_clean ($dir);
$output .= qq| $dir :|;
}
$output .= " $last";
return $output;
}
sub build_unlinked_title {
# --------------------------------------------------------
# Returns a string of the current category broken up by section.
# Useful for printing in the title.
my $input = shift;
my (@dirs, $dir, $output);
@dirs = split (/\//, $input);
foreach $dir (@dirs) {
$dir = &build_clean ($dir);
$output .= " $dir:";
}
chop ($output);
return $output;
}
sub build_check_dir {
# --------------------------------------------------------
# Checks the directory before we create it to make sure there
# are no funncy characters in it.
my ($root, $dir) = @_;
my $chrs = quotemeta ("/_-");
if (! -e $root) {
&cgierr ("Root directory: $root does not exist!");
}
if ($dir !~ m,^[\w\d$chrs]+$,) {
&cgierr ("Invalid characters in category name: $dir. Must contain only letters, numbers, _, / and -.");
}
return $input;
}
1;$link{'Rating'} $link{'Votes'} $link{'Title'}