#!/usr/bin/perl5 # # ------------- # Links # ------------- # Links Manager # # File: search.cgi # Description: Searches the database and produces a list of results. If no options are # given, the script will produce a search form found in site_html.pl. # Author: Alex Krohn # Email: alex@gossamer-threads.com # Web: http://www.gossamer-threads.com/ # Version: 1.0 # # COPYRIGHT NOTICE: # # Copyright 1997 Gossamer Threads Inc. All Rights Reserved. # # This program is being distributed as shareware. It may be used and # modified free of charge for personal, academic, government or non-profit # use, so long as this copyright notice and the header above remain intact. # Any commercial use should be registered. Please also send me an email, # and let me know where you are using this script. By using this program # you agree to indemnify Gossamer Threads Inc. from any liability. # # Selling the code for this program without prior written consent is # expressly forbidden. Obtain written permission before redistributing this # program over the Internet or in any other medium. In all cases # copyright and header must remain intact. # # Please check the README file for full details on registration. # ===================================================================== # # Form Input: # 'type' : can be either 'keyword' or 'phrase'. # 'bool' : can be either 'and' or 'or'. # 'mh' : the maximum number of hits, can be either 10, 25, 50, 100. # # Setup: # Make sure the require statement below points to the config file. # Required Librariers # -------------------------------------------------------- eval { ($0 =~ m,(.*)/[^/]+,) && unshift (@INC, "$1"); # Get the script location: UNIX / ($0 =~ m,(.*)\\[^\\]+,) && unshift (@INC, "$1"); # Get the script location: Windows \ require "/webfiles/www.antiqueradios.com/links/admin/links.cfg"; # Change this to full path to links.cfg if you have problems. require "/webfiles/www.antiqueradios.com/resources/admin/db.pl"; require "/webfiles/www.antiqueradios.com/links/admin/site_html.pl"; }; if ($@) { 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 { # -------------------------------------------------------- local (%in) = &parse_form; if (keys %in > 0) { local (%link_results, @category_results); # Holds our Link and Category Search Results. local ($date) = &get_date; # Current Date. local ($time) = &get_time; # Current Time. local ($link_hits, $cat_hits, $maxhits, $nh) = 0; local ($next, $next_hits, @search_terms, $grand_total); my($cat_clean); if ($in{'nh'}) { $nh = $in{'nh'}; } # 'nh' controls the search next n results variable. # Determine the maximum number of hits, can only be 10, 25, 50 or 100. Defaults to 25. if ($in{'mh'} && (($in{'mh'} == 10) || ($in{'mh'} == 25) || ($in{'mh'} == 50) || ($in{'mh'} = 100))) { $maxhits = $in{'mh'}; } else { $maxhits = 25; # Default Value. } # See whether we are searching for phrases or keywords.. # If it's a phrase, we only have one search term, otherwise we have # multiple terms. if ($in{'type'}) { @search_terms = ($in{'query'}) if ($in{'type'} eq 'phrase'); @search_terms = split (/\s/, $in{'query'}) if ($in{'type'} eq 'keyword'); } else { $in{'type'} = 'keyword'; @search_terms = split (/\s/, $in{'query'}) if ($in{'type'} eq 'keyword'); } # Boolean connector defaults to "and". if (!$in{'bool'}) { $in{'bool'} = 'and'; } # See if we have something to search for. if ($in{'query'}) { &search(); # Performs the search and stores results in link_results and category_results. if ((keys %link_results > 0) || ($#category_results > 0)) { # Build the HTML for the category results and store it in "$category_results". foreach $category (@category_results) { $cat_hits++; $cat_clean = &build_clean($category); $linked_title = &build_linked_title ($category); $category_results .= qq|
  • $linked_title\n|; } $cat_hits = 0 if (!$cat_hits); $lowrange = $nh * $maxhits + 1; $highrange = ($nh+1) * $maxhits; # Go through each category of links returned, and build the HTML. Store in hash %link_output. SETOFLINKS: foreach $setoflinks (sort keys %link_results) { LINK: for ($i = 0; $i < ($#{$link_results{$setoflinks}}+1) / ($#db_cols + 1); $i++) { $link_hits++; if (($link_hits <= $highrange) && ($link_hits >= $lowrange)) { %tmp = &array_to_hash ($i, @{$link_results{$setoflinks}}); $link_output{$setoflinks} .= &site_html_link (%tmp) . "\n"; } } } # Go through the hash just built, and build the complete link output. Store in $link_results. foreach $setoflinks (sort keys %link_output) { $cat_clean = &build_clean ($setoflinks); $title_linked = &build_linked_title ($setoflinks); $link_results .= qq|

    $title_linked\n|; $link_results .= $link_output{$setoflinks}; } # If we want to bold the search terms... if ($search_bold) { foreach $term (@search_terms) { # This reg expression will do the trick, and doesn't bold things inside <> tags such as # URL's. $link_results =~ s,(<[^>]+>)|(\Q$term\E),defined($1) ? $1 : "$2",gie; $category_results =~ s,(<[^>]+>)|(\Q$term\E),defined($1) ? $1 : "$2",gie; } } # Check to see if we've returned more hits then are maximum allowed.. if ($link_hits > ($maxhits * ($nh+1))) { # If so, we build a $next variable that has the url to get then next n hits. $next = $ENV{'QUERY_STRING'}; if ($in{'nh'}) { $nh = $in{'nh'} + 1; $next =~ s/&nh=(\d+)/&nh=$nh/; } else { $next .= "&nh=1"; } $next = $build_search_url . "?" . $next; if (($link_hits - ($maxhits * ($in{'nh'}+1))) <= $maxhits) { $next_hits = ($link_hits - ($maxhits * ($in{'nh'}+1))); } else { $next_hits = $maxhits; } } else { $next = ""; } # Print out the HTML results. &site_html_search_results; } else { &site_html_search_failure ("no matching records"); } } else { &site_html_search_failure ("no keywords specified"); } } else { &site_html_search_form(); } } sub search { # -------------------------------------------------------- # This routine does the actual search of the database. open (DB, "<$db_file_name") or &cgierr("error in search. unable to open database: $db_file_name. Reason: $!"); @lines = ; # Open the Database and read in all the lines. close (DB); $numhits = 0; LINE: foreach $line (@lines) { # Search through the database if ($line =~ /^#/) { next LINE; } # Skip comment lines. if ($line =~ /^\s*$/) { next LINE; } # Skip Blank Lines. $grand_total++; chomp ($line); @values = &split_decode($line); $match = 0; $andmatch = 1; # Go through each term we have to search, and then check every field # we have to match against. TERM: foreach $term (@search_terms) { FIELD: foreach $field (@search_fields) { # If it's a boolean OR search, we only need to match one field, and can quit # if we do match. if ($in{'bool'} eq "or") { $match = $match || ($values[$field] =~ /\Q$term\E/i); last TERM if ($match); } else { # Otherwise it's an AND search, so we have to match every term. $match = ($values[$field] =~ /\Q$term\E/i); last FIELD if ($match); } } # This will go to 0 and stay 0 if $match ever equals 0. $andmatch = $andmatch && $match; } if (($in{'bool'} eq "or") && $match) { # We have a match! push (@{$link_results{$values[$db_category]}}, @values); $numhits++; } elsif ($andmatch) { # We have a match! push (@{$link_results{$values[$db_category]}}, @values); $numhits++; } else { # No Match. } # Check to see if the category matches. First we check to make sure the # category is not already in our @category_results. if (!(grep $_ eq $values[$db_category], @category_results)) { $match=0; $andmatch = 1; TERM: foreach $term (@search_terms) { if ($in{'bool'} eq "or") { $match = $match || ($values[$db_category] =~ /\Q$term\E/i); last TERM if ($match); } else { $match = ($values[$db_category] =~ /\Q$term\E/i); } $andmatch = $andmatch && $match; } if (($in{'bool'} eq "or") && $match) { $numcat++; push (@category_results, $values[$db_category]); } elsif ($andmatch) { $numcat++; push (@category_results, $values[$db_category]); } else { # No Match. } } } # Now let's Sort the Results, we borrow the link sort found in nph-build.cgi to # sort the links. foreach $link ( keys %link_results ) { @{$link_results{$link}} = &build_sorthit (@{$link_results{$link}}); } @category_results = sort (@category_results); } sub build_linked_title { # -------------------------------------------------------- # A little different then the one found in nph-build.cgi as it also # links up the last field as well. my ($input) = $_[0]; my (@dirs, $dir, $output, $path, $last); @dirs = split (/\//, $input); foreach $dir (@dirs) { $path .= "/$dir"; $dir = &build_clean ($dir); $output .= qq|$dir:|; } chop ($output); return $output; }