#!/usr/bin/perl
# $Id: lonhttpd,v 1.6 2003/02/24 23:32:32 albertel Exp $
$VERSION = "1.3.2 (Demonic/Linux/LON-CAPA Derivative $Revison$)";
# HTTPi Hypertext Tiny Truncated Process Implementation
# Copyright 1999-2001 Cameron Kaiser # All rights reserved
# Please read LICENSE # Do not strip this copyright message.
#
# LON-CAPA: find httpi license and readme at CVS loncom/license
#
use lib '/home/httpd/lib/perl/';
use LONCAPA::Configuration();
%loncapavar=%{&LONCAPA::Configuration::read_conf('loncapa.conf')};
$port_to_use=$loncapavar{'lonhttpdPort'};
if (!defined($port_to_use)) {
$port_to_use='8080';
}
# The main server is running on 80, so exit in this case
if ($port_to_use eq '80') { die('Apache is already on Port 80'); }
%system_content_types =
("html" => "text/html",
"htm" => "text/html",
"wml" => "text/vnd.wap.wml",
"wbmp" => "image/vnd.wap.wbmp",
"wbm" => "image/vnd.wap.wbmp",
"xbm" => "image/x-xbitmap",
"pdf" => "application/pdf",
"fdf" => "application/vnd.fdf",
"bin" => "application/octet-stream",
"class" => "application/octet-stream",
"jar" => "application/octet-stream",
"js" => "application/x-javascript",
"lnk" => "application/x-hyperlink",
"wav" => "audio/x-wav",
"mp3" => "audio/x-mpeg",
"tif" => "image/tiff",
"tiff" => "image/tiff",
"mid" => "audio/x-midi",
"txt" => "text/plain",
"gif" => "image/gif",
"sit" => "application/x-stuffit",
"zip" => "application/x-zip-compressed",
"lzh" => "application/octet-stream",
"lha" => "application/octet-stream",
"gz" => "application/x-gzip",
"mov" => "movie/quicktime",
"mpeg" => "video/mpeg",
"mpg" => "video/mpeg",
"jpeg" => "image/jpeg",
"jpg" => "image/jpeg");
$logfile = "/home/httpd/perl/logs/lonhttpd.log";
# Write out PID
$pidfile="/home/httpd/perl/logs/lonhttpd.pid";
if (-e $pidfile) {
open(LFH,"$pidfile");
my $pide=<$LFH>;
chomp($pide);
close(LFH);
if (kill 0 => $pide) { die "already running"; }
}
$path = "/home/httpd/html";
$sockaddr = 'S n a4 x8';
%content_types =
("html" => "text/html",
"htm" => "text/html");
%restrictions =
("/" => "#.##", # deny everything
"/res/adm" => ".###", # allow /res/adm
"/adm" => ".###", # allow /adm
"/status" => ".####lonadm:oeRooOvb3HtpI");
# See documentation for interpreting this string.
$headers = <<"EOF";
Server: HTTPi/$VERSION
MIME-Version: 1.0
EOF
%virtual_files =
(
"/adm/lonLCDfont/0.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/0.gif" ] ,
"/adm/lonLCDfont/1.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/1.gif" ] ,
"/adm/lonLCDfont/2.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/2.gif" ] ,
"/adm/lonLCDfont/3.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/3.gif" ] ,
"/adm/lonLCDfont/4.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/4.gif" ] ,
"/adm/lonLCDfont/5.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/5.gif" ] ,
"/adm/lonLCDfont/6.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/6.gif" ] ,
"/adm/lonLCDfont/7.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/7.gif" ] ,
"/adm/lonLCDfont/8.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/8.gif" ] ,
"/adm/lonLCDfont/9.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/9.gif" ] ,
"/adm/lonLCDfont/a.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/a.gif" ] ,
"/adm/lonLCDfont/b.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/b.gif" ] ,
"/adm/lonLCDfont/c.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/c.gif" ] ,
"/adm/lonLCDfont/d.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/d.gif" ] ,
"/adm/lonLCDfont/e.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/e.gif" ] ,
"/adm/lonLCDfont/f.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/f.gif" ] ,
"/adm/lonLCDfont/g.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/g.gif" ] ,
"/adm/lonLCDfont/h.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/h.gif" ] ,
"/adm/lonLCDfont/i.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/i.gif" ] ,
"/adm/lonLCDfont/j.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/j.gif" ] ,
"/adm/lonLCDfont/k.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/k.gif" ] ,
"/adm/lonLCDfont/l.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/l.gif" ] ,
"/adm/lonLCDfont/m.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/m.gif" ] ,
"/adm/lonLCDfont/n.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/n.gif" ] ,
"/adm/lonLCDfont/o.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/o.gif" ] ,
"/adm/lonLCDfont/p.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/p.gif" ] ,
"/adm/lonLCDfont/q.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/q.gif" ] ,
"/adm/lonLCDfont/r.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/r.gif" ] ,
"/adm/lonLCDfont/s.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/s.gif" ] ,
"/adm/lonLCDfont/t.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/t.gif" ] ,
"/adm/lonLCDfont/u.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/u.gif" ] ,
"/adm/lonLCDfont/v.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/v.gif" ] ,
"/adm/lonLCDfont/w.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/w.gif" ] ,
"/adm/lonLCDfont/x.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/x.gif" ] ,
"/adm/lonLCDfont/y.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/y.gif" ] ,
"/adm/lonLCDfont/z.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/z.gif" ] ,
"/adm/lonLCDfont/colon.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/colon.gif" ] ,
"/adm/lonLCDfont/slash.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/slash.gif" ] ,
"/adm/lonLCDfont/hyphen.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/hyphen.gif" ] ,
"/adm/lonLCDfont/space.gif" => [ "image/gif", "FILE",
"/home/httpd/html/adm/lonLCDfont/space.gif" ] ,
);
%content_types = (%system_content_types, %content_types);
undef %system_content_types;
while (($file, $arrayref) = each(%virtual_files)) {
my ($mime, $type, $block) = (@{ $arrayref });
next if ($type ne 'FILE');
if(open(S, "$block")) {
$j = $/; undef $/; $virtual_files{$file}->[2] = scalar();
$/ = $j; close(S);
} else {
warn "while getting virtual file $file: $!\n";
map_delete(%virtual_files, $file);
}
}
if ($pid = fork()) { exit; }
#
# Store parent PID
#
open (PIDSAVE,">$pidfile");
print PIDSAVE "$$\n";
close(PIDSAVE);
$0 = "lonhttpd: (dhttpi) binding port ...";
$bindthis = pack($sockaddr, 2, $port_to_use,
pack('l', chr(0).chr(0).chr(0).chr(0)));
socket(S, 2, 1, 6);
setsockopt(S, 1, 2, 1);
bind(S, $bindthis) || die("$0: while binding port $port_to_use:\n\"$!\"\n");
listen(S, 128);
$0 = "lonhttpd: (dhttpi) connected and waiting ANY:$port_to_use";
$statiosuptime = time();
###############################################################
# WHITE HATS ONLY BELOW THIS POINT -- SEE DOCUMENTATION FIRST #
###############################################################
sub sock_to_host {
local($sock) = getpeername(STDIN);
return (undef, undef, undef) if (!$sock);
local($AFC, $port, $thataddr, $zero) = unpack($sockaddr, $sock);
local($ip) = join('.', unpack("C4", $thataddr));
return ($ip, $port, $ip);
}
sub htsponse {
($currentcode, $currentstring) = (@_);
return if (0+$httpver < 1);
local($what) = <<"EOF";
HTTP/$httpver $currentcode $currentstring
${headers}Date: $rfcdate
EOF
$what =~ s/\n/\r\n/g;
print stdout $what;
&hthead("Connection: close") if (0+$httpver > 1);
}
sub hthead {
local($header, $term) = (@_);
return if (0+$httpver < 1);
print stdout "$header\r\n" , ($term) ? "\r\n" : "";
}
sub htcontent {
local($what, $ctype, $mode) = (@_);
($contentlength) = $mode || length($what);
&hthead("Content-Length: $contentlength");
&hthead("Content-Type: $ctype", 1);
return if ($method eq 'HEAD' || $mode);
print stdout $what;
}
sub log {
if (open(J, ">>$logfile")) {
local $q = $address . (($variables) ? "?$variables" : "");
$contentlength += 0;
$contentlength = 0 if ($method eq 'HEAD');
local ($hostname, $port, $ip) = &sock_to_host();
$hostname = $hostname || "-";
$httpuser = $httpuser || "-";
print J <<"EOF";
$hostname - $httpuser [$date] "$method $q HTTP/$httpver" $currentcode $contentlength "$httpref" "$httpua"
EOF
close(J); }
}
sub bye { unlink($pidfile); exit; }
sub dead {
&htsponse(500, "Server Error");
&hterror("Server Error", <<"EOF");
While handling a request for resource $address, the server crashed. Please
attempt to notify the administrators.
Useful(?) debugging information:
@_EOF &log; unlink($pidfile); exit; } $SIG{'__DIE__'} = \&dead; $SIG{'ALRM'} = $SIG{'TERM'} = $SIG{'INT'} = \&bye; sub master { $0 = "lonhttpd: (dhttpi) handling request"; # $sock = getpeername(STDIN); $rfcdate = scalar gmtime; ($dow, $mon, $dt, $tm, $yr) = ($rfcdate =~ m/(...) (...) (..) (..:..:..) (....)/); $dt += 0; $yr += 0; $rfcdate = "$dow, $dt $mon $yr $tm GMT"; $date = scalar localtime; ($dow, $mon, $dt, $tm, $yr) = ($date =~ m/(...) (...) (..) (..:..:..) (....)/); $dt += 0; $dt = substr("0$dt", length("0$dt") - 2, 2); $date = "$dt/$mon/$yr:$tm +0000"; select(STDOUT); $|=1; $address = 0; alarm 1; while (
$VERSION
)
Requests received: $statiosreq
Average time between requests: ${rps}s
Most recent requests: