diff options
Diffstat (limited to '')
-rwxr-xr-x | scripts/dirlist.cgi.in | 536 |
1 files changed, 536 insertions, 0 deletions
diff --git a/scripts/dirlist.cgi.in b/scripts/dirlist.cgi.in new file mode 100755 index 0000000..5cba1a8 --- /dev/null +++ b/scripts/dirlist.cgi.in @@ -0,0 +1,536 @@ +#!@PERL@ +# +# Directory list CGI by Hironori Sakamoto (hsaka@mth.biglobe.ne.jp) +# + +if ( $^O =~ /^(ms)?(dos|win(32|nt)?)/i ) { + $WIN32 = 1; + $CYGPATH = 1; +} +elsif ( $^O =~ /cygwin|os2/i ) { + $WIN32 = 1; + $CYGPATH = 0; +} +else { + $WIN32 = 0; + $CYGPATH = 0; +} +$RC_DIR = '@RC_DIR@'; +$RC_DIR =~ s@^~/@$ENV{'HOME'}/@; +if ($CYGPATH) { + $RC_DIR = &cygwin_pathconv("$RC_DIR"); +} +$CONFIG = "$RC_DIR/dirlist"; +$CGI = $ENV{'SCRIPT_NAME'} || $0; +$CGI = "file://" . &file_encode("$CGI"); + +$AFMT = '<a href="%s"><nobr>%s</nobr></a>'; +$NOW = time(); + +@OPT = &init_option($CONFIG); + +$query = $ENV{'QUERY_STRING'}; +$dir = ''; +$cmd = ''; +$cookie = ''; +$local_cookie = ''; +foreach(split(/\&/, $query)) { + if (s/^dir=//) { + $dir = &form_decode($_); + } +} +$body = undef; +if ($ENV{'REQUEST_METHOD'} eq 'POST') { + sysread(STDIN, $body, $ENV{'CONTENT_LENGTH'}); + foreach(split(/\&/, $body)) { + if (s/^dir=//) { + $dir = &form_decode($_); + } elsif (s/^opt(\d+)=//) { + $OPT[$1] = $_; + } elsif (s/^cmd=//) { + $cmd = $_; + } elsif (s/^cookie=//) { + $cookie = &form_decode($_); + } + } +} +$cookie_file = $ENV{'LOCAL_COOKIE_FILE'}; +if (-f $cookie_file) { + open(F, "< $cookie_file"); + $local_cookie = <F>; + close(F); +} +if ($local_cookie eq '' || (defined($body) && $cookie ne $local_cookie)) { + print <<EOF; +Content-Type: text/plain + +Local cookie doesn't match: It may be an illegal execution +EOF + exit(1); +} +$local_cookie = &html_quote($local_cookie); +if ($dir !~ m@/$@) { + $dir .= '/'; +} +if ($dir =~ m@^/@ && $CYGPATH) { + $dir = &cygwin_pathconv("$dir"); +} +$ROOT = ''; +if ($WIN32) { + if (($dir =~ s@^//[^/]+@@) || ($dir =~ s@^[a-z]:@@i)) { + $ROOT = $&; + } + if ($CYGPATH) { + $ROOT = &cygwin_pathconv("$ROOT"); + } +} +$dir = &cleanup($dir); + +$TYPE = $OPT[$OPT_TYPE]; +$FORMAT = $OPT[$OPT_FORMAT]; +$SORT = $OPT[$OPT_SORT]; +if ($cmd) { + &update_option($CONFIG); +} + +$qdir = "$ROOT" . &html_quote("$dir"); +$edir = "$ROOT" . &file_encode("$dir"); +if (! opendir(DIR, "$ROOT$dir")) { + print <<EOF; +Content-Type: text/html + +<html> +<head> +<title>Directory list of $qdir</title> +</head> +<body> +<b>$qdir</b>: $! ! +</body> +</html> +EOF + exit 1; +} + +print <<EOF; +Content-Type: text/html + +<html> +<head> +<title>Directory list of $qdir</title> +</head> +<body> +<h1>Directory list of $qdir</h1> +EOF +&print_form($qdir, @OPT); +print <<EOF; +<hr> +EOF +$dir =~ s@/$@@; +@sdirs = split('/', $dir); +$_ = $sdirs[0]; +if ($_ eq '') { + $_ = '/'; +} +if ($TYPE eq $TYPE_TREE) { + print <<EOF; +<table hborder width="640"> +<tr valign=top><td width="160"> +<pre> +EOF + $q = "$ROOT". &html_quote("$_"); + $e = "$ROOT" . &file_encode("$_"); + if ($dir =~ m@^$@) { + $n = "\" name=\"current"; + } else { + $n = ''; + } + printf("$AFMT\n", "$e$n", "<b>$q</b>"); + $N = 0; + $SKIPLINE = ""; + + &left_dir('', @sdirs); + + print <<EOF; +</pre> +</td><td width="400"> +<pre>$SKIPLINE +EOF +} else { + print <<EOF; +<pre> +EOF +} + +&right_dir($dir); + +if ($TYPE eq $TYPE_TREE) { + print <<EOF; +</pre> +</td></tr> +</table> +</body> +</html> +EOF +} else { + print <<EOF; +</pre> +</body> +</html> +EOF +} + +sub left_dir { + local($pre, $dir, @sdirs) = @_; + local($ok) = (@sdirs == 0); + local(@cdirs) = (); + local($_, $dir0, $d, $qdir, $q, $edir, $e); + + $dir0 = "$dir/"; + $dir = "$dir0"; + opendir(DIR, "$ROOT$dir") || return; + + foreach(sort readdir(DIR)) { + -d "$ROOT$dir$_" || next; + /^\.$/ && next; + /^\.\.$/ && next; + push(@cdirs, $_); + } + closedir(DIR); + + $qdir = "$ROOT" . &html_quote($dir); + $edir = "$ROOT" . &file_encode($dir); + while(@cdirs) { + $_ = shift @cdirs; + $q = &html_quote($_); + $e = &file_encode($_); + $N++; + if (!$ok && $_ eq $sdirs[0]) { + $d = $dir0 . shift @sdirs; + if (!@sdirs) { + $n = "\" name=\"current"; + $SKIPLINE = "\n" x $N; + } else { + $n = ''; + } + printf("${pre}o-$AFMT\n", "$edir$e$n", "<b>$q</b>"); + &left_dir(@cdirs ? "$pre| " : "$pre ", $d, @sdirs); + $ok = 1; + } else { + printf("${pre}+-$AFMT\n", "$edir$e", $q); + } + } +} + +sub right_dir { + local($dir) = @_; + local(@list); + local($_, $qdir, $q, $edir, $e, $f, $max, @d, $type, $u, $g); + local($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, + $atime,$mtime,$ctime,$blksize,$blocks); + local(%sizes, %ctimes, %prints); + + $dir = "$dir/"; + opendir(DIR, "$ROOT$dir") || return; + + $qdir = "$ROOT" . &html_quote($dir); + $edir = "$ROOT" . &file_encode($dir); + if ($TYPE eq $TYPE_TREE) { + print "<b>$qdir</b>\n"; + } + @list = (); + $max = 0; + foreach(readdir(DIR)) { + /^\.$/ && next; +# if ($TYPE eq $TYPE_TREE) { +# /^\.\.$/ && next; +# } + $f = "$ROOT$dir$_"; + (($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, + $atime,$mtime,$ctime,$blksize,$blocks) = lstat($f)) || next; + push(@list, $_); + $sizes{$_} = $size; + $ctimes{$_} = $ctime; + + if ($FORMAT eq $FORMAT_COLUMN) { + if (length($_) > $max) { + $max = length($_); + } + next; + } + $type = &utype($mode); + if ($FORMAT eq $FORMAT_SHORT) { + $prints{$_} = sprintf("%-6s ", "[$type]"); + next; + } + if ($type =~ /^[CB]/) { + $size = sprintf("%3u, %3u", ($rdev >> 8) & 0xff, $rdev & 0xffff00ff); + } + if ($FORMAT eq $FORMAT_LONG) { + $u = $USER{$uid} || ($USER{$uid} = getpwuid($uid) || $uid); + $g = $GROUP{$gid} || ($GROUP{$gid} = getgrgid($gid) || $gid); + $prints{$_} = sprintf( "%s %-8s %-8s %8s %s ", + &umode($mode), $u, $g, $size, &utime($ctime)); +# } elsif ($FORMAT eq $FORMAT_STANDARD) { + } else { + $prints{$_} = sprintf("%-6s %8s %s ", "[$type]", $size, &utime($ctime)); + } + } + closedir(DIR); + if ($SORT eq $SORT_SIZE) { + @list = sort { $sizes{$b} <=> $sizes{$a} || $a cmp $b } @list; + } elsif ($SORT eq $SORT_TIME) { + @list = sort { $ctimes{$b} <=> $ctimes{$a} || $a cmp $b } @list; + } else { + @list = sort @list; + } + if ($FORMAT eq $FORMAT_COLUMN) { + local($COLS, $l, $nr, $n); + if ($TYPE eq $TYPE_TREE) { + $COLS = 60; + } else { + $COLS = 80; + } + $l = int($COLS / ($max + 2)) || 1; + $nr = int($#list / $l + 1); + $n = 0; + print "<table>\n<tr valign=top>"; + foreach(@list) { + $f = "$ROOT$dir$_"; + $q = &html_quote($_); + $e = &file_encode($_); + if ($n % $nr == 0) { + print "<td>"; + } + if (-d $f) { + printf($AFMT, "$edir$e", "$q/"); + } else { + printf($AFMT, "$edir$e", $q); + } + $n++; + if ($n % $nr == 0) { + print "</td>\n"; + } else { + print "<br>\n"; + } + } + print "</tr></table>\n"; + return; + } + foreach(@list) { + $f = "$ROOT$dir$_"; + $q = &html_quote($_); + $e = &file_encode($_); + print $prints{$_}; + if (-d $f) { + printf($AFMT, "$edir$e", "$q/"); + } else { + printf($AFMT, "$edir$e", $q); + } + if (-l $f) { + print " -> ", &html_quote(readlink($f)); + } + print "\n"; + } +} + +sub init_option { + local($config) = @_; + $OPT_TYPE = 0; + $OPT_FORMAT = 1; + $OPT_SORT = 2; + $TYPE_TREE = 't'; + $TYPE_STANDARD = 'd'; + $FORMAT_SHORT = 's'; + $FORMAT_STANDARD = 'd'; + $FORMAT_LONG = 'l'; + $FORMAT_COLUMN = 'c'; + $SORT_NAME = 'n'; + $SORT_SIZE = 's'; + $SORT_TIME = 't'; + local(@opt) = ($TYPE_TREE, $FORMAT_STANDARD, $SORT_NAME); + local($_); + + open(CONFIG, "< $config") || return @opt; + while(<CONFIG>) { + chop; + s/^\s+//; + tr/A-Z/a-z/; + if (/^type\s+(\S)/i) { + $opt[$OPT_TYPE] = $1; + } elsif (/^format\s+(\S)/i) { + $opt[$OPT_FORMAT] = $1 + } elsif (/^sort\s+(\S)/i) { + $opt[$OPT_SORT] = $1; + } + } + close(CONFIG); + return @opt; +} + +sub update_option { + local($config) = @_; + + open(CONFIG, "> $config") || return; + print CONFIG <<EOF; +type $TYPE +format $FORMAT +sort $SORT +EOF + close(CONFIG); +} + +sub print_form { + local($d, @OPT) = @_; + local(@disc) = ('Type', 'Format', 'Sort'); + local(@val) = ( + "('t', 'd')", + "('s', 'd', 'c')", + "('n', 's', 't')", + ); + local(@opt) = ( + "('Tree', 'Standard')", + "('Short', 'Standard', 'Column')", + "('By Name', 'By Size', 'By Time')" + ); + local($_, @vs, @os, $v, $o); + + print <<EOF; +<form method=post action=\"$CGI#current\"> +<center> +<table cellpadding=0> +<tr valign=top> +EOF + foreach(0 .. 2) { + print "<td align> $disc[$_]</td>\n"; + } + print "</tr><tr>\n"; + foreach(0 .. 2) { + print "<td><select name=opt$_>\n"; + eval "\@vs = $val[$_]"; + eval "\@os = $opt[$_]"; + foreach $v (@vs) { + $o = shift(@os); + if ($v eq $OPT[$_]) { + print "<option value=$v selected>$o\n"; + } else { + print "<option value=$v>$o\n"; + } + } + print "</select></td>\n"; + } + print <<EOF; +<td><input type=submit name=cmd value="Update"></td> +</tr> +</table> +</center> +<input type=hidden name=dir value="$d"> +<input type=hidden name=cookie value="$local_cookie"> +</form> +EOF +} + +sub html_quote { + local($_) = @_; + local(%QUOTE) = ( + '<', '<', + '>', '>', + '&', '&', + '"', '"', + ); + s/[<>&"]/$QUOTE{$&}/g; + return $_; +} +sub file_encode { + local($_) = @_; + s/[\000-\040\+:#?&%<>"\177-\377]/sprintf('%%%02X', unpack('C', $&))/eg; + return $_; +} + +sub form_decode { + local($_) = @_; + s/\+/ /g; + s/%([\da-f][\da-f])/pack('C', hex($1))/egi; + return $_; +} + +sub cleanup { + local($_) = @_; + + s@//+@/@g; + s@/\./@/@g; + while(m@/\.\./@) { + s@^/(\.\./)+@/@; + s@/[^/]+/\.\./@/@; + } + return $_; +} + +sub utype { + local($_) = @_; + local(%T) = ( + 0010000, 'PIPE', + 0020000, 'CHR', + 0040000, 'DIR', + 0060000, 'BLK', + 0100000, 'FILE', + 0120000, 'LINK', + 0140000, 'SOCK', + ); + return $T{($_ & 0170000)} || 'FILE'; +} + +sub umode { + local($_) = @_; + local(%T) = ( + 0010000, 'p', + 0020000, 'c', + 0040000, 'd', + 0060000, 'b', + 0100000, '-', + 0120000, 'l', + 0140000, 's', + ); + + return ($T{($_ & 0170000)} || '-') + . (($_ & 00400) ? 'r' : '-') + . (($_ & 00200) ? 'w' : '-') + . (($_ & 04000) ? 's' : + (($_ & 00100) ? 'x' : '-')) + . (($_ & 00040) ? 'r' : '-') + . (($_ & 00020) ? 'w' : '-') + . (($_ & 02000) ? 's' : + (($_ & 00010) ? 'x' : '-')) + . (($_ & 00004) ? 'r' : '-') + . (($_ & 00002) ? 'w' : '-') + . (($_ & 01000) ? 't' : + (($_ & 00001) ? 'x' : '-')); +} + +sub utime { + local($_) = @_; + local(@MON) = ( + 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', + 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' + ); + local($sec,$min,$hour,$mday,$mon, + $year,$wday,$yday,$isdst) = localtime($_); + + if ($_ > $NOW - 182*24*60*60 && $_ < $NOW + 183*24*60*60) { + return sprintf("%3s %2d %.2d:%.2d", $MON[$mon], $mday, $hour, $min); + } else { + return sprintf("%3s %2d %5d", $MON[$mon], $mday, 1900+$year); + } +} + +sub cygwin_pathconv { + local($_) = @_; + local(*CYGPATH); + + open(CYGPATH, '-|') || exec('cygpath', '-w', $_); + $_ = <CYGPATH>; + close(CYGPATH); + s/\r?\n$//; + s!\\!/!g; + s!/$!!; + return $_; +} |