Приглашаем посетить
File Seek
#!/usr/local/bin/perl
############################################################################
# #
# FileSeek Version 1.5 #
# Written by Craig Patchett craig@patchett.com #
# Created 7/25/96 Last Modified 3/14/97 #
# #
# Copyright 1997 Craig Patchett & Matthew Wright. All Rights Reserved. #
# This program is part of The CGI/Perl Cookbook from John Wiley & Sons. #
# License to use this program or install it on a server (in original or #
# modified form) is granted only to those who have purchased a copy of The #
# CGI/Perl Cookbook. (This notice must remain as part of the source code.) #
# #
############################################################################
############################################################################
# Define configuration constants #
############################################################################
# $ROOT_DIR is the full path to the root directory that FileSeek will look
# for files in. (Note that it should end with a directory delimiter.)
$ROOT_DIR = '/home/web/downloads/';
# $ROOT_URL is the URL of the directory specified by $ROOT_DIR
$ROOT_URL = 'http://www.domain.com/downloads';
# $ROOT_NAME is the name of the root directory that will be used within the
# program.
$ROOT_NAME = 'Downloads';
# $ICON_DIR is relative path from your server's root directory where the
# icons for the different file types will be kept. (Note that it should end
# with a forward slash.)
$ICON_DIR = '/fileseek/icons/';
# %TYPES matches file types to the corresponding icon files. With the
# exception of 'directory' and 'binary' default file types, each file
# type corresponds to a filename extension.
%TYPES = ('parent', $ICON_DIR . 'parent.gif',
'directory', $ICON_DIR . 'directory.gif',
'binary', $ICON_DIR . 'binary.gif',
'txt', $ICON_DIR . 'text.gif',
'gif', $ICON_DIR . 'graphic.gif',
'jpg', $ICON_DIR . 'graphic.gif',
'jpeg', $ICON_DIR . 'graphic.gif',
'htm', $ICON_DIR . 'html.gif',
'html', $ICON_DIR . 'html.gif',
'pdf', $ICON_DIR . 'pdf.gif');
# $ALLOWED_DIR is the full path to the root directory that any files
# specified by the user must be in (e.g., template files). (Note that
# it should include a directory delimiter at the end.)
$ALLOWED_DIR = '/home/web/fileseek/';
# $DATE_FORMAT holds the &format_date() format for the file mod date & time
$DATE_FORMAT = '<wday>, <mon> <d>, <year>, <h>:<0n> <AP>';
# $PROGRAM_URL is the URL of this program
$PROGRAM_URL = 'http://www.domain.com/cgi-bin/fileseek.cgi';
# $ERROR_PAGE is the error page template that will be used by the error
# subroutine.
$ERROR_PAGE = "/home/web/error_page.html";
# $REQUIRE_DIR is the directory in which all of your required files are
# placed. On most systems, if you leave the required files in the same
# directory as the CGI program, you can leave this variable blank.
# Otherwise, if you move the required files to another directory, specify
# the full or relative path here.
$REQUIRE_DIR = 'require';
############################################################################
# Get required subroutines which need to be included. #
############################################################################
# Push $REQUIRE_DIR onto the @INC array for include file directories
# and list required files.
push(@INC, $REQUIRE_DIR) if $REQUIRE_DIR;
require 'formdate.pl';
require 'template.pl';
require 'error.pl';
############################################################################
# Initialize other constants #
############################################################################
@DAYS = ('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
'Saturday');
@MONTHS = ('January', 'February', 'March', 'April', 'May', 'June', 'July',
'August', 'September', 'October', 'November', 'December');
$DAY_SECS = 24 * 60 * 60;
if ($ENV{'QUERY_STRING'} !~ /sort=\d/ && $ENV{'QUERY_STRING'}) {
$adjust = '&' . $ENV{'QUERY_STRING'};
}
$NAME_TITLE = "<A HREF=\"$PROGRAM_URL?$`sort=0$'$adjust\">Name</A>";
$SIZE_TITLE = "<A HREF=\"$PROGRAM_URL?$`sort=1$'$adjust\">Size</A>";
$DATE_TITLE = "<A HREF=\"$PROGRAM_URL?$`sort=2$'$adjust\">Last Modified</A>";
############################################################################
# Parse query string #
############################################################################
(@args) = split(/&/, $ENV{'QUERY_STRING'});
foreach $arg (@args) {
($arg, $value) = split(/=/, $arg);
$value =~ tr/+/ /;
$value =~ s/%([\dA-Fa-f][\dA-Fa-f])/pack("C", hex($1))/eg;
if (($arg eq 'query') && ($value ne '')) { $ARGS{$arg} = '.*' }
else { $ARGS{$arg} = $value }
}
$sort_order = ($ARGS{'sort'} || 0);
$directory = $ARGS{'dir'};
$VAR{'query'} = $ARGS{'query'} if $ARGS{'query'};
$VAR{'root_name'} = $ROOT_NAME;
############################################################################
# Perform security and validity checks on directories and files #
############################################################################
# Set the directory delimiter based on $ROOT_DIR and make sure the
# different directory variables end or don't end with a delimiter as
# called for.
$DD = substr($ROOT_DIR, -1);
if ($DD !~ /[\/:]/) {
&error("\$ICON_DIR must end with a directory delimiter.");
}
if ($ALLOWED_DIR !~ /$DD$/) { $ALLOWED_DIR .= $DD }
if ($directory && (substr($directory, 0, 1) ne $DD)) {
$directory = "$DD$directory";
}
$directory =~ s/$DD$//g;
$VAR{'directory'} = $directory if $directory;
$VAR{'full_dir'} = "$ROOT_NAME$directory";
# Change to root in case an invalid directory was specified
if (!$ROOT_DIR) { &error('$ROOT_DIR has not been defined.') }
if (!(-d $ROOT_DIR)) { &error("$ROOT_DIR is not a valid directory ($!).") }
if (!(-r $ROOT_DIR)) { &error("$ROOT_DIR is not readable ($!).") }
chdir($ROOT_DIR);
# Make sure they're not trying to access an invalid directory
if ($directory =~ /$DD\.\./) { $directory = '' }
$ARGS{'head'} =~ s/(^$ALLOWED_DIR)|(^$DD)|(\.\.($DD|$))//g;
$ARGS{'foot'} =~ s/(^$ALLOWED_DIR)|(^$DD)|(\.\.($DD|$))//g;
############################################################################
# Perform search or get directory listing #
############################################################################
if ($ARGS{'query'}) {
$VAR{'page_title'} = "Search of $ROOT_NAME$directory for \"$ARGS{'query'}\"";
# Recursively search directory
&search("$ROOT_DIR$directory", '', $ARGS{'query'});
chdir("$ROOT_DIR$directory");
}
else {
$VAR{'page_title'} = "Directory of $ROOT_NAME$directory";
# Read list of files
chdir("$ROOT_DIR$directory");
@link_files = @files = <*>;
}
$num_items = @files;
############################################################################
# Get file information #
############################################################################
$count = 0;
foreach $file (@link_files) {
$filename = $files[$count];
$directory{$filename} = -d $file; # Directory flag
if (!$directory{$filename}) { $size{$filename} = -s $file } # Size (in bytes)
$modify{$filename} = $^T - int((-M $file) * $DAY_SECS); # Modification date
$readable{$filename} = -r $file; # Read permission
$full_path{$filename} = $file; # Path from dir
# Determine file type
$_ = $file;
tr/A-Z/a-z/;
if ((/\.([^.]+)$/) && $TYPES{$1}) { $type{$filename} = $1 } # Use extension
elsif (-B $file) { $type{$filename} = 'binary' } # Check for binary
else { $type{$filename} = 'txt' } # Otherwise text
++$count;
}
############################################################################
# Sort files #
############################################################################
if ($sort_order == 1) {
@sorted_files = sort by_size @files;
$SIZE_TITLE = "<B>Size</B>";
}
elsif ($sort_order == 2) {
@sorted_files = sort by_date @files;
$DATE_TITLE = "<B>Last Modified</B>"
}
else {
@sorted_files = sort by_name @files;
$NAME_TITLE = "<B>Name</B>";
}
############################################################################
# Generate the HTML page #
############################################################################
# Generate the arguments for links back to the program
if ($ARGS{'sort'}) { $sort_arg = "sort=$sort_order&"} else { $sort_arg = '' }
if ($ARGS{'head'}) {
$temp_arg .= "head=$ARGS{'head'}&";
}
if ($ARGS{'foot'}) {
$temp_arg .= "foot=$ARGS{'foot'}&";
}
# Generate the HTML header
print "Content-type: text/html\n\n";
# Insert the page header if specified
if ($ARGS{'head'}) {
if (!&parse_template("$ALLOWED_DIR$ARGS{'head'}", *STDOUT)) {
&error($Error_Message, '', '', 1);
}
}
else {
print <<END_HTML;
<HTML>
<HEAD>
<TITLE>$VAR{'page_title'}</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF">
END_HTML
}
# Generate the directory header
print <<END_HTML;
<FORM ACTION="$PROGRAM_URL" METHOD=GET>
Enter your single word search here:
<INPUT SIZE=20 TYPE=TEXT NAME="query">
<INPUT TYPE="submit" VALUE="Search">
<INPUT TYPE="hidden" NAME="sort" VALUE="$sort_order">
<INPUT TYPE="hidden" NAME="dir" VALUE="$directory">
<INPUT TYPE="hidden" NAME="head" VALUE="$ARGS{'head'}">
<INPUT TYPE="hidden" NAME="foot" VALUE="$ARGS{'foot'}">
</FORM>
<P>
<B>$VAR{'page_title'}:</B>
<P>
<TABLE BORDER=0 CELLPADDING=0 WIDTH=100%>
<TR>
<TD HEIGHT=17 ALIGN=CENTER WIDTH=50 NOWRAP>
$num_items items
</TD><TD WIDTH=5 ALIGN=LEFT>
</TD><TD ALIGN=LEFT>
$NAME_TITLE
</TD><TD ALIGN=RIGHT WIDTH=100>
$SIZE_TITLE
</TD><TD WIDTH=5 ALIGN=LEFT>
</TD><TD ALIGN=LEFT WIDTH=900>
$DATE_TITLE
</TD></TR>
<TR>
<TD COLSPAN=6 HEIGHT=10>
<HR>
</TD></TR>
END_HTML
# Generate the link to the parent directory if appropriate
if ($directory && !$ARGS{'query'}) {
$parent = substr($directory, 0, rindex($directory, $DD));
$file_link = "<A HREF=\"$PROGRAM_URL?$sort_arg$temp_arg";
$file_link .= "dir=$parent\">\n";
$file = '<I>Parent Directory</I>';
$link_close = '</A>';
print <<END_HTML;
<TR>
<TD HEIGHT=17 ALIGN=CENTER>
$file_link
<IMG SRC="$TYPES{'parent'}" WIDTH=16 HEIGHT=16 BORDER=0>$link_close
</TD><TD ALIGN=RIGHT>
</TD><TD ALIGN=LEFT>
$file_link$file$link_close
</TD><TD ALIGN=RIGHT>
</TD><TD WIDTH=5 ALIGN=LEFT>
</TD><TD ALIGN=LEFT>
</TD></TR>
END_HTML
}
# Generate the directory listing
foreach $file (@sorted_files) {
# If the file is a directory, link back to the program
if ($directory{$file}) {
$file_link = "<A HREF=\"$PROGRAM_URL?$sort_arg$temp_arg";
$file_link .= "dir=$directory$full_path{$file}\">";
$image_link = $TYPES{'directory'};
$file_size = '-';
}
else {
# Otherwise link to the file and format the file size
$file_link = "<A HREF=\"$ROOT_URL$directory$DD$full_path{$file}\">";
$image_link = $TYPES{$type{$file}};
$file_size = &size_format($size{$file});
}
# Remove the link if the file isn't readable by the user
if (!$readable{$file}) { $file_link = $link_close = '' }
else { $link_close = '</A>' }
# Calculate the modification date
$mod_date = &format_date($modify{$file}, $DATE_FORMAT);
# Print the file information
print <<END_HTML;
<TR>
<TD HEIGHT=17 ALIGN=CENTER>
$file_link
<IMG SRC="$image_link" WIDTH=16 HEIGHT=16 BORDER=0>$link_close
</TD><TD ALIGN=RIGHT>
</TD><TD ALIGN=LEFT>
$file_link$file$link_close
</TD><TD ALIGN=RIGHT>
$file_size
</TD><TD WIDTH=5 ALIGN=LEFT>
</TD><TD ALIGN=LEFT>
$mod_date
</TD></TR>
END_HTML
}
print " </TABLE>\n <HR>\n";
# Insert the page footer if specified
if ($ARGS{'foot'}) {
if (!&parse_template("$ALLOWED_DIR$ARGS{'foot'}", *STDOUT)) {
&error($Error_Message, '', '', 1);
}
}
else { print " </BODY>\n</HTML>" }
############################################################################
# Search subroutine #
############################################################################
sub search {
# Initialize
local($SEARCH_ROOT, $search_dir, $search_query) = @_;
chdir("$SEARCH_ROOT$DD$search_dir");
local(@filenames) = <*>;
local($file);
# Scan directory & subdirectories
foreach $file (@filenames) {
if (-d $file && -r $file) {
if ($search_dir) {
&search($SEARCH_ROOT, "$search_dir$DD$file", $search_query);
}
else { &search($SEARCH_ROOT, $file, $search_query) }
chdir("$SEARCH_ROOT$DD$search_dir");
}
if ($file =~ /$search_query/i) {
if ($search_dir) { push(@link_files, "$search_dir$DD$file") }
else { push(@link_files, $file) }
push(@files, $file);
}
}
}
############################################################################
# File size format subroutine #
############################################################################
sub size_format {
# Initialize
local($size) = $_[0];
# Format
if ($size < 1024) { return("1K") }
elsif ($size < 1048576) { return(int($size/1024 + .5) . "K") }
else { return((int(10 * $size/1048576 + .5) / 10) . " MB") }
}
############################################################################
# Custom sort subroutines #
############################################################################
sub by_size {
$a2 = $a;
$a2 =~ tr/A-Z/a-z/;
$b2 = $b;
$b2 =~ tr/A-Z/a-z/;
($size{$b} <=> $size{$a}) || ($a2 cmp $b2) || ($modify{$b} <=> $modify{$a});
}
sub by_date {
$a2 = $a;
$a2 =~ tr/A-Z/a-z/;
$b2 = $b;
$b2 =~ tr/A-Z/a-z/;
($modify{$b} <=> $modify{$a}) || ($a2 cmp $b2) || ($size{$b} <=> $size{$a});
}
sub by_name {
$a2 = $a;
$a2 =~ tr/A-Z/a-z/;
$b2 = $b;
$b2 =~ tr/A-Z/a-z/;
($a2 cmp $b2) || ($a cmp $b);
}