#!/usr/bin/perl use Encode qw(decode_utf8); use File::Find; use HTML::Escape qw(escape_html); my $search_text = ''; if ($ENV{QUERY_STRING} =~ /^q=([^&]*)/) { $search_text = decode_utf8($1 // ""); $search_text =~ s/\P{Print}//g; # toss any non-printable utf-8 characters $search_text = substr($search_text, 0, 64); } my $directory = '../_site/log/'; my @results; my %excluded_files = ( 'index.html' => 1, # /log/index.html ); if ($search_text =~ /\S/) { find({ wanted => sub { # Ignore directories and only process index.html return unless -f $_ && $_ eq 'index.html'; # Calculate the relative path for the URL (prevents leaking server file structure) my $rel_path = $File::Find::name; $rel_path =~ s|^\Q$directory\E/?||; return if $excluded_files{$rel_path}; if (open my $fh, '<', $_) { my $content = do { local $/; <$fh> }; close $fh; if ($content =~ /\Q$search_text\E/i) { # Extract Title my ($title) = $content =~ /
tag content my ($p_content) = $content =~ /
]*>(.*?)<\/p>/is; # Process the snippet my $snippet = $p_content || ""; $snippet =~ s/<[^>]*>//g; # Remove internal tags $snippet =~ s/\s+/ /g; # Collapse whitespace # Escape HTML entities AFTER stripping tags # but BEFORE sending to the user to prevent XSS. $snippet = escape_html(substr($snippet, 0, 50)); $snippet .= "..." if length($p_content || "") > 50; push @results, { path => $File::Find::name, title => $title, snippet => $snippet }; } } }, no_chdir => 0, follow => 0, }, $directory); } print "Content-Type: text/html\n\n"; my $list; if ($search_text eq '') { $list = "
Please enter a search term above.
"; } elsif (@results == 0) { $list = "No results found for \"$search_text\".
"; } else { $list = "