Annotation of loncom/lonhttpd, revision 1.2
1.1 www 1: #!/usr/bin/perl
2: # The LearningOnline Network with CAPA
3: # lonhttpd server (port 8080)
4: # based on
5: # TinyHTTPD - a minimum-functional HTTP server written in -*- Perl -*-
6: # -ot.0894
1.2 ! www 7: # $Id: lonhttpd,v 1.1 2002/10/29 20:21:32 www Exp $
1.1 www 8:
9: # Currently supported: HTTP 1.0/1.1 GET and POST queries
10: # File types of .html and .gif
11:
1.2 ! www 12: $ENV{'SERVER_SOFTWARE'}="TinyHTTPD $Revision: 1.1 $ -ot.0894 (LON-CAPA)";
1.1 www 13:
14:
15: use POSIX;
16:
17: $pid=fork;
18: exit if $pid;
19: die "Could not fork: $!" unless defined($pid);
20: POSIX::setsid() or die "Can't start new session: $!";
21: open (PIDSAVE,">/home/httpd/perl/logs/lonhttpd.pid");
22: print PIDSAVE "$$\n";
23: close(PIDSAVE);
24:
25: sub REAPER {
26: 1 until (-1==waitpid(-1,WNOHANG));
27: $SIG{CHLD}=\&REAPER;
28: }
29:
30: $SIG{CHLD}=\&REAPER;
31:
32: ## Configuration section
33: $port=8080; # Port on which we listen
34: $htmldir="/home/httpd/html/"; # Base directory for HTML files
35:
36: # the following substitutes "require 'sys/socket.ph';" on ultrix
37: # Check if the definitions are correct with /usr/include/sys/socket.h
38: $AF_INET=2; $PF_INET=$AF_INET; $SOCK_STREAM=1;
39:
40: # Messages
41: %errors=
42: (
43: "403", "Forbidden",
44: "404", "Not Found",
45: "500", "Internal Error",
46: "501", "Not Implemented",
47: );
48: %verrors=
49: (
50: "403", "Your client is not allowed to request this item",
51: "404", "The requested item was not found on this server",
52: "500", "An error occurred while trying to retrieve item",
53: "501", "This server does not support the given request type",
54: );
55:
56: (($>)&&($<==$>)&&($(==$))) || die "Don't run this program with privileges!\n";
57:
58: # set up a server socket, redirect stderr to logfile
59: $IPPROTO_TCP=6;
60: $sockaddr = 'S n a4 x8';
61: $this = pack($sockaddr, $AF_INET, $port, "\0\0\0\0");
62: socket(S, $PF_INET, $SOCK_STREAM, $IPPROTO_TCP) || die "socket: $!";
63: bind(S, $this) || die "bind: $!";
64: listen(S, 5) || die "listen: $!";
65: open(LOG,">>/home/httpd/perl/logs/lonhttpd.log");
66: select(LOG); $|=1;
67: open(STDERR, ">&LOG") || die "dup2 log->stderr";
68:
69: # accept incoming calls
70: for (;;) {
71: ($addr=accept(NS,S)) || die "accept: $!";
72: next if $pid=fork;
73: die "fork: $!" unless defined $pid;
74: close(S);
75: ($a,$p,$inetaddr) = unpack($sockaddr, $addr);
76: @inetaddr = unpack('C4', $inetaddr);
77: ($host,$aliases) = gethostbyaddr($inetaddr, $AF_INET);
78: $inetaddr = join(".", @inetaddr);
79: @host=split(' ', "$host $aliases");
80: $host || do { $host = $inetaddr; };
81: @t=localtime;
82: open(STDIN, "+<&NS") || die "dup2 ns->stdin";
83: open(STDOUT, "+>&NS") || die "dup2 ns->stdout";
84: select(STDOUT); $|=1;
85: &serve_request;
86: close(STDIN); close(STDOUT);
87: exit;
88: }
89:
90: # Read request from stdin and produce output
91: sub serve_request {
92:
93: # Analyze HTTP input.
94: $_=<STDIN>;
95: ($method, $url, $proto) = split;
96: if ($proto) {
97: while (<STDIN>) {
98: s/\n|\r//g; # kill CR and NL chars
99: /^Content-Length: (\S*)/i && ($content_length=$1);
100: /^Content-Type: (\S*)/i && ($content_type=$1);
101: length || last; # empty line - end of header
102: }
103: } else {
104: $proto="HTTP/0.9";
105: }
106: ($method=~/^(GET|POST)$/) || do { &error(501,$method); return; };
107:
108: # prevent directory go-back
109: $url=~/\.\./ && do { &error(403,$url,"contains go-back"); return; };
1.2 ! www 110:
! 111: # Multiple slashes do happen
! 112: $url=~s/\/+/\//g;
1.1 www 113:
114: # Check access control
115: unless (($url=~/^\/res\/adm\//) || ($url=~/^\/adm\//)) {
116: do { &error(403,$url,"not on allow list"); return; };
117: }
118: print LOG "$$: $url\n";
119:
120: # Get and return file
121:
122: $file="$htmldir$url";
123: (-r "$file") || do { &error(404,$url); return; };
124: # output the file
125: print "HTTP/1.0 200 OK\nMIME-Version: 1.0\nContent-Type: ";
126: CASE:
127: {
128: $url=~/\.html$/ && do { print "text/html\n\n"; last CASE; };
129: $url=~/\.gif$/ && do { print "image/gif\n\n"; last CASE; };
130: print "text/plain\n\n";
131: }
132: system("cat $file");
133: }
134:
135: sub error {
136: # generate error response
137: local($errno) = @_[0];
138: local($errmsg) = "$errno $errors{$errno}";
139: print LOG "$$ $errmsg (@_[1,2])\n";
140: print <<TheEnd;
141: HTTP/1.0 $errmsg
142: MIME-version: 1.0
143: Content-type: text/html
144:
145: <HTML>
146: <HEAD><TITLE>$errmsg</TITLE></HEAD>
147: <BODY><H1>$errmsg</H1>
148: $verrors{$errno}: <PRE> @_[1] </PRE>
149: <HR>
150: <ADDRESS><A HREF="http://www.lon-capa.org/">
151: $ENV{'SERVER_SOFTWARE'} by Olaf Titz, modified by LON-CAPA</A></ADDRESS>
152: </BODY>
153: </HTML>
154: TheEnd
155: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>