#!/usr/bin/perl -w

# Program to cat a file.  The purpose is to allow me to easily view in a
# web browser files that usually would be interpreted by the web browser
# (HTML), executed by the server (PHP, CGI), or otherwise handled.  Very
# often I want to say "here's the CGI program" and "here's the source,"
# but I can't do both with hyperlinks.

# The script only allows files matching the following pattern to be
# viewed: webdb/public_html/{php,perl/cgi-bin}/*, since those are the
# problematic ones.

# The CGI script will be owned by webdb, otherwise the suexec module
# will complain.  This conceivably allows the script to be exploited
# to read files that webdb can read, but it would be difficult.
# Perhaps placing a symbolic link in one of the okdirs to a sensitive
# file.

# Scott D. Anderson
# scott.anderson@acm.org
# Spring 2005

# Modified by Tyler Moore Spring 2012 to make CGI scripts readable for qtw class.

use strict;
use English;
use CGI;

my $q = new CGI;

my $file = $q->param('file');
print $q->header('text/plain');

# Apache's UID is 48. This code no longer runs
if ( 0 && $EUID != 48 ) {
    print STDERR "This script should run as EUID 48, not $EUID\n";
    exit;
}

my %okdirs = ( 'code' => 1,
               'python' => 1,
               'perl-scripts' => 1,
               'cgi-bin' => 1,
               'misc' => 1 );

if( !defined $file ) {
    print "no file specified.\n";
    exit;
}

# The short-circuit evaluation of && should avoid complaints here, but
# it doesn't. *sigh*

if( !($file =~ m!^([-\w]+)/[-.\w]+$! && $okdirs{$1} )) {
    print "file $file ($1) can't be viewed: no pattern match.\n";
    exit;
}

my $absfile = "/home/qtw/public_html/" . $file;

if( ! -e $absfile ) {
    printf "File $absfile doesn't seem to exist.\n";
} elsif ( ! -r $absfile ) {
    printf "File $absfile isn't readable.\n";
} else {
    exec('/bin/cat',$absfile);
}
exit;
    
# ================================================================
# old code

my $perms = (stat($absfile))[2];

if( $perms & 0004 ) {
    # it would be more efficient to read the file ourself, rather than
    # exec cat, but I don't care about efficiency for this simple
    # script.
    exec('/bin/cat',$absfile);
} else {
    printf "File $absfile is not world-readable: %o\n", $perms;
}
