#!/usr/bin/perl
##############################################################################
# Simple Search                 Version 1.0                                  #
# Copyright 1996 Matt Wright    mattw@worldwidemart.com                      #
# Created 12/16/95              Last Modified 12/16/95                       #
# Scripts Archive at:           http://www.worldwidemart.com/scripts/        #
##############################################################################
# COPYRIGHT NOTICE                                                           #
# Copyright 1996 Matthew M. Wright  All Rights Reserved.                     #
#                                                                            #
# Simple Search may be used and modified free of charge by anyone so long as #
# this copyright notice and the comments above remain intact.  By using this #
# code you agree to indemnify Matthew M. Wright from any liability that      #  
# might arise from it's use.                                                 #  
#                                                                            #
# Selling the code for this program without prior written consent is         #
# expressly forbidden.  In other words, please ask first before you try and  #
# make money off of my program.                                              #
#                                                                            #
# Obtain permission before redistributing this software over the Internet or #
# in any other medium.  In all cases copyright and header must remain intact.#
##############################################################################
# 6/23/98 - The Puppet Master <pmaster@ravensclaw.com>                       #
# Added some debug information to the script to help debug blank results     #
# Set $debug to '1' and perform search as normal.  Debug information         #
# will be displayed instead of search results.                               #
# When you are sure you have everything set correctly, change $debug to '0'  #
# and your search script should now work.                                    #
#                                                                            #
# NOTE: THERE ARE NO GUARANTEES THAT THE SCRIPT WILL FIND ANY FILES EVEN IF  #
#       DEBUG IS SET TO 0!  This script is for assistance only and may or    #
#       may not help you.                                                    #
#                                                                            #
# 10/26/98 added "Total Hits" counter and no hits found page if $count = 0   #
# 12/06/98 color coded file types, added gif, jpg, bmp, cgi, pl, shtml, htm, #
#          txt support.  Also added underlining between files/directories    #
#                                                                            #
# 4/1/99 - Added @IGNORE array.  Place in it, the directories you wish to    #
# ignore from the search.  Note: Your @files array must be set as follows:   # 
#                                                                            #
# @files = ('*.html','*/*.html','*/*/*.html','*/*/*/*.html');                #
#                                                                            #
# This searches all html files up to 4 levels deep...  But any directory in  #
# @ignore will be skipped.  You can add more *'s for more levels...          #  
#                                                                            #
# NOTE: THIS SCRIPT IS A UNIX ONLY SCRIPT, and will not work on NT, 95/98,   #
# MAC, OS/2, etc....                                                         #
##############################################################################

##############################################################################
# Define Variables							     #

# $basedir is the system path to the files/directories you with to search.
# Think of DOS/WINDOWS for a minute: You have a C:\TEMP directory, and also a 
# C:\WINDOWS\TEMP directory, when you want to change to the latter directory,
# would you type: 'cd temp' ?  NO!  You would have to type 'cd windows\temp'
# Unix is the same way, a URL is only how a browser locates and displays a 
# webpage, that webpage, actually sits on a computer, just like yours, and
# will almost always be in a directory structure.  This structure is different
# for each server and may be under your home directory 
# (/home/yourname/public_html/...), which is the most common for Unix servers
# running Apache, or if it is your own Unix server, it may be under 
# (/htdoc or /htdocs or /WWW), it just depends.  Regardless, if you are using
# an ISP (Internet Service Provider), your $basedir will NEVER be just "/".
# 
# Here's another explanation:   
#
# The script uses the CD (Change Directory) command to change to the
# $basedir.  If it can not do it, it will usually default to the path where
# your scripts reside (usually the cgi-bin directory).  Since there are 
# usually no HTML files (or whatever you desginate in @files) contained within
# that cgi-bin directory, you will get no results.
# 
$basedir = '/usr/home/yourname/public_html/';
# 
# As explained above, a URL (Uniform Resource Locator), is how a browser 
# locates and displays your webpage.  Each URL has a system path.  The  
# $baseurl is the URL pointing to your homepage.
#
$baseurl = 'http://www.domain.com/~yourname/';
#
# Directories and files to search...  Each section below (delimited by commas)
# is one level deeper in the directory structure to search.  Example:   
# the first *.html searches all HTML files found in the $basedir, the next 
# */*.html searches all HTML files in any directories found in $basedir, the
# third */*/*.html searches all HTML files in any directories under the 
# previous directory found in the $basedir and so on...
#
@files = ('*.html','*/*.html','*/*/*.html','*/*/*/*.html');
#
# Directories in the @ignore array are directories the search script will skip.
#
@ignore = ('perl','games');
#
# $title is the title of your main page...
#
$title = "Simple Search Plus";
#
# $title_url is the URL to your main index page...  Example: On your main page
# you might have a link, "Click Here" to search.  This link allows a user to
# return to your main page rather than the search page.
#
$title_url = 'http://www.domain.com/~yourname/search/index.html';
#
# $search_url is similar to $title_url, only it links back to the search.html
# file so that a user can return to your search page to perhaps search again.
#
$search_url = 'http://www.domain.com/~yourname/search/search.html';

# $debug should be set to 1 if you are debugging the script to work.  And 0 if
# you are done debugging and ready to use the search script online.

$debug = 1;    # 1 = Yes | 0 = No
#
# set $disp_ignore, if you want the directories listed in @ignore displayed 
# on the final resultes page or 0 if you do not wish them displayed.
#
$disp_ignore = 1;    # 1 = Yes | 0 = No
#
# Done									     #
##############################################################################

# Parse Form Search Information
&parse_form;

# If debug is set to yes, display files only.
if ($debug eq "1") {
	&debug;
}
else {
	# Get Files To Search Through
	&get_files;
}

if ($debug eq "0") {
	# Search the files
	&search;
}

# Print Results of Search
&return_html;

sub parse_form {

   # Get the input
   read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});

   # Split the name-value pairs
   @pairs = split(/&/, $buffer);

   foreach $pair (@pairs) {
      ($name, $value) = split(/=/, $pair);

      $value =~ tr/+/ /;
      $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;

      $FORM{$name} = $value;
   }
}


sub get_files
  {
    chdir($basedir);
    $pwd=`pwd`;
    
    foreach $file (@files) 
      {
        $ls = `ls $file`;
        @ls = split(/\s+/,$ls);
      NEXTFILE:
        foreach $temp_file (@ls) 
          {
            foreach $ignore (@ignore)
              {
                if ($temp_file =~ $ignore)
                  {
                    push(@SKIP,$temp_file);
                    next NEXTFILE;
                  }
              }
            if (-T $temp_file)
              {
                push(@FILES,$temp_file);
                next NEXTFILE;
              }
          }
      }
  }



sub search {

   @terms = split(/\s+/, $FORM{'terms'});

   foreach $FILE (@FILES) {

      open(FILE,"$FILE");
      @LINES = <FILE>;
      close(FILE);

      $string = join(' ',@LINES);
      $string =~ s/\n//g;
      if ($FORM{'boolean'} eq 'AND') {
         foreach $term (@terms) {
            if ($FORM{'case'} eq 'Insensitive') {
               if (!($string =~ /$term/i)) {
                  $include{$FILE} = 'no';
				last;
               }
               else {
                  $include{$FILE} = 'yes';
               }
            }
            elsif ($FORM{'case'} eq 'Sensitive') {
               if (!($string =~ /$term/)) {
                  $include{$FILE} = 'no';
                  last;
               }
               else {
                  $include{$FILE} = 'yes';
               }
            }
         }
      }
      elsif ($FORM{'boolean'} eq 'OR') {
         foreach $term (@terms) {
            if ($FORM{'case'} eq 'Insensitive') {
               if ($string =~ /$term/i) {
                  $include{$FILE} = 'yes';
                  last;
               }
               else {
                  $include{$FILE} = 'no';
               }
            }
            elsif ($FORM{'case'} eq 'Sensitive') {
               if ($string =~ /$term/) {
		  $include{$FILE} = 'yes';
                  last;
               }
               else {
                  $include{$FILE} = 'no';
               }
            }
         }
      }
      if ($string =~ /<title>(.*)<\/title>/i) {
         $titles{$FILE} = "$1";
      }
      else {
         $titles{$FILE} = "$FILE";
      }
   }
}
      

sub return_html {
	$count=0;
	foreach $key (keys %include) {
		if ($include{$key} eq 'yes') {
			$count++;
		}
	}
	if ($count eq "0" && ($debug eq "0")) {
		&display_no_hits;
	}
	else {
	   print "Content-type: text/html\n\n";
	   print "<html>\n <head>\n  <title>Results of Search</title>\n </head>\n";
	   print "<body bgcolor=\"WHITE\">\n <center>\n  <h1>Results of Search in $title</h1>\n </center>\n";
		print "Below are the results of your Search in no particular order:<p><hr size=7 width=75%><p>\n";
		if ($debug eq "1") {
				print "<font color=\"BLUE\">DEBUG MODE ON! SEARCH IS DISABLED!</font><p>\n";
				if ($basedir =~http) {
				   print "<font color=\"RED\">Your \$basedir is incorrect, it needs to be a path not a URL!</font>\n";
					exit;
				}
				else {
					print "<font color=\"GREEN\">Your \$basedir has the correct (system path) format.</font><br>\n";
				}
				if ($ENV{'REQUEST_METHOD'} eq 'GET') {
					print "<font color=\"RED\">Your METHOD is incorrect.  Change it from GET to POST</font>\n";
					exit;
				}
				else {
					print "<font color=\"GREEN\">METHOD used: POST (This is correct)</font><br>\n";
				}
				chop($pwd);
				if ($pwd eq $basedir) {
					print "<font color=\"GREEN\">I was successful in changing to the </font>\$basedir: <b>$basedir</b><p>\n";
				}
				else {
					print "<font color=\"RED\">I tried changing to: </font><b>$basedir</b>, which is what you defined as your \$basedir.<br>";
					print "However, I was unable to change to that directory, (perhaps because your \$basedir is invalid),<br>instead I defaulted to <b>$pwd</b>.<br>";
				}
				if ($filedir eq "") {
					print "<p>There are either no files in this directory, or authorization (permissions) will not allow me to list those files here.<p>\n";
				}
				else {
					print "If the following files are not the files you are attempting to search, or there are no files listed, your \$basedir is set up incorrectly!<p>\n";
					print "<p><pre><b>$filedir</b></pre>\n";
				}
			   print "Search Script written by Matt Wright and can be found at <a href=\"http://www.worldwidemart.com/scripts/\">Matt's Script Archive</a><br>\n";
				print "Modifications to Simple Search written by The Puppet Master and can be found at <a href=\"http://www.ravensclaw.com/~pmaster/perl/my_scripts/\">Puppet Master's Scripts</a>\n";
			}
			else {
			   print "<ul>\n";
				foreach $key (keys %include) {
					if ($include{$key} eq 'yes') {
						print "<li><a href=\"$baseurl$key\">$titles{$key}</a>\n";
					}
				}
			}   

			print "</ul>\n";
  		 print "<hr size=7 width=75%>\n";
			if ($debug eq "0") {
			   print "Search Information:<p>\n";
				print "<ul>\n";
				print "<li><b>Terms:</b> ";
				$i = 0;
				foreach $term (@terms) {
					print "$term";
			      $i++;
					if (!($i == @terms)) {
		   			 print ", ";
			      }
				}
			   print "\n";
			   print "<li><b>Boolean Used:</b> $FORM{'boolean'}</li>\n";
			   print "<li><b>Case</b> $FORM{'case'}</li>\n";
				print "<li><b>Total Hits Found:</b> $count</li>\n";
				if ($disp_ignore eq "1") {
					print "<li><b>Ignored The Following Directories:</b> ";
					$h = 0;
					foreach $ignore (@ignore) {
						print "$ignore";
						$h++;
						if (!($h == @ignore)) {
							print ", ";
						}
					}
				}
			   print "</ul><br><hr size=7 width=75%><P>\n";
			   print "<ul>\n<li><a href=\"$search_url\">Back to Search Page</a></li>\n";
			   print "<li><a href=\"$title_url\">$title</a></li>\n";
			   print "</ul>\n";
			   print "<hr size=7 width=75%>\n";
			   print "Search Script written by Matt Wright and can be found at <a href=\"http://www.worldwidemart.com/scripts/\">Matt's Script Archive</a><br>\n";
				print "Modifications to Simple Search written by The Puppet Master and can be found at <a href=\"http://www.ravensclaw.com/~pmaster/perl/my_scripts/\">Puppet Master's Scripts</a>\n";
			}
			 print "</body>\n</html>\n";
		}
}

sub debug {
	chdir($basedir);
	$pwd=`pwd`;
	$filedir=`ls -l`;
}
		


sub display_no_hits {
   print "Content-type: text/html\n\n";
   print "<html>\n <head>\n  <title>No Hits</title>\n </head>\n";
	print "<body>\n <center>\n  <h1>Sorry - Your Search Yielded No Results</h1>\n </center>\n";
   print "<ul>\n<li><a href=\"$search_url\">Back to Search Page</a>\n";
   print "<li><a href=\"$title_url\">$title</a>\n";
   print "</ul>\n";
   print "<hr size=7 width=75%>\n";
   print "Search Script written by Matt Wright and can be found at <a href=\"http://www.worldwidemart.com/scripts/\">Matt's Script Archive</a><br>\n";
	print "Modifications to Simple Search written by The Puppet Master and can be found at <a href=\"http://www.ravensclaw.com/~pmaster/perl/my_scripts/\">Puppet Master's Scripts</a>\n";
	print "</body>\n</html>\n";
	exit;
}
