#!/usr/bin/perl -Tw
use strict;
use CGI qw(:standard);
use CGI::Carp qw(fatalsToBrowser);

# The original version of this script was written in Bourne shell by Karl M.
# Hegbloom <karlheg@debian.org>. Colin Watson <cjwatson@debian.org> rewrote
# it in Perl.

# This requires either `cgiwrap' or `suexec' so it runs as the user whose
# browser-history is to be grepped. Place it in
# ~/public_html/cgi-bin/browser-history-search.cgi, and access it with the
# URL: http://localhost/cgi-bin/cgiwrap/~yourid/browser-history-search.cgi
# or, using `suexec',
# http://localhost/~yourid/cgi-bin/browser-history-search.cgi

# Note that anyone who knows this is here can use it to search your
# browser-history. I think that using `suexec', with a handler type for
# `.cgi' files, it may be possible to place this in a basic-auth protected
# location. I'll leave that as an exercise.

my $me = 'browser-history-search.cgi';	# relative URL

print header(-type => 'text/html');

my $zcat = '/bin/zcat';
print "Can't find zcat on this system\n", exit unless -x $zcat;

# Untaint $HOME.
my $HOME = defined($ENV{HOME}) ? $ENV{HOME} : $ENV{LOGDIR};
unless (defined $HOME)
{
    print "Neither \$HOME nor \$LOGDIR is defined; consider using a CGI " .
	  "wrapper.\n";
    exit;
}
unless ($HOME =~ m#(^/(?:[^/]*[^/.][^/]*(?:/|$))*$)#)
{
    print 'Insecure $' . (defined($ENV{HOME}) ? 'HOME' : 'LOGDIR') .
	  ": $HOME\n";
    exit;
}
$HOME = $1;

local *HISTORY;

# Open a history file, whether gzipped or not.
sub open_history ($)
{
    my $history = shift;
    if ($history =~ /\.gz$/)
    {
	my $pid = open HISTORY, '-|';
	croak "Couldn't fork: $!" unless defined $pid;
	unless ($pid)
	{
	    exec $zcat, '-S', '', '-f', $history
		or croak "Couldn't exec $zcat: $!";
	}
    }
    else
    {
	unless (open HISTORY, $history)
	{
	    carp "Couldn't open $history: $!";
	    next;
	}
    }
    return \*HISTORY;
}

my $match = param('match');
if ($match)
{
    print <<EOF;
<html>
<head><title>Search results by browser-history</title></head>
<body>
<h1>Search results by browser-history</h1>
<p><a href="$me">Search again</a></p>
EOF
    chdir "$HOME/.browser-history";
    local *HISTORIES;
    opendir HISTORIES, '.';
    while (defined(my $history = readdir HISTORIES))
    {
	next unless $history =~ /\.html(?:\.gz)?$/;
	my $histfile = open_history $history;
	while (<$histfile>)
	{
	    last if /^<!-- EndOfHeader -->$/;
	}
	while (<$histfile>)
	{
	    if (/$match/)
	    {
		s/^<hr>/<br>/;
		print;
	    }
	}
	close $histfile or carp "Couldn't close history file: $!";
    }
    print <<EOF;
</body>
</html>
EOF
}
else
{
    print <<EOF;
<html>
<head><title>Browser History Search</title></head>
<body>
<h1>Browser History Search</h1>

<form action="$me" method="post">
<p>Enter a Perl regular expression to search your browser-history and
display the results: <input name="match" type="text"></p>
</form>

</body>
</html>
EOF
}

