|
¾Æ·¡ ¼Ò½º´Â Perl·Î ¸¸µç À¥¼¹öÀÎ HTTPi¸¦
¼³Ä¡ÇÏ¿´À» ¶§ ¸¸µé¾îÁö´Â ÃÖÁ¾ ¼Ò½ºÀÔ´Ï´Ù. ÇöÀç´Â 1.3.2 ¹öÀüÀ¸·Î, HTTPi »çÀÌÆ® °¡½Ã¸é ´Ù¿î·Îµå ¹Þ¾Æ¼ »ç¿ëÇÒ ¼ö ÀÖ½À´Ï´Ù. Á¦°¡
»ý°¢ÇÏ´Â ÀÌ À¥¼¹öÀÇ ¿ëµµ´Â ³»ºÎ ³×Æ®¿÷¿¡¼ÀÇ ½Ã½ºÅÛ °ü¸®³ª, µ¥ÀÌÅÍ °ü¸® µîÀÔ´Ï´Ù. Keep-alive ±â´ÉÀ»
Áö¿øÇÏÁö ¾Ê±â ¶§¹®¿¡ ¸¹Àº ÆÄÀϵéÀ» ´Ù¿î·Îµå ½ÃÄÑ¾ß ÇÏ´Â ÀÏ¹Ý À¥»çÀÌÆ®¿¡¼´Â ¹«¸®°¡ ÀÖ½À´Ï´Ù. ³»ºÎ¿¡¼ »ç¿ëÇÒ ¶§¿¡´Â À̹ÌÁö°¡ ¸¹ÀÌ µé¾î°¡Áö
¾Ê°í, root °èÁ¤À¸·Î ½ÇÇàÇÒ ¼ö ÀÖÀ¸¸ç, ´Ù¾çÇÑ Çڵ鷯¸¦ Á÷Á¢ ÷°¡ÇÏ¿© »ç¿ëÇÒ ¼ö ÀÖÀ¸¹Ç·Î ÈǸ¢ÇÑ °ü¸®ÅøÀÌ µÉ °ÍÀÔ´Ï´Ù. ÇÏÁö¸¸ Á¦°¡
À̰ÍÀ» ¿©±â¿¡ ¼Ò°³ÇÑ ¶Ç ´Ù¸¥ ÀÌÀ¯°¡ ÀÖ½À´Ï´Ù. ¸¹Àº ºÐµéÀÌ CGI¸¦ ¸¸µéÁö¸¸, À¥¼¹öÀÇ µ¿ÀÛ¿¡ ´ëÇØ¼´Â Àß ¸ð¸£´Â ä, ±×Àú ÁüÀÛÀ̳ª Àß
¸øµÈ Áö½Ä¸¸ °¡Áö°í ¸¸µé´Ùº¸´Ï, ¸¹Àº ºÎºÐ¿¡¼ È¥¼±À» ºú°Ô µË´Ï´Ù. ´ç¿¬È÷ °³¹ß±â°£µµ ´Ã¾î³ª°ÚÁö¿ä. ±×·¯³ª, 400ÁÙµµ µÇÁö ¾Ê´Â ÀÌ ÈǸ¢ÇÑ
¼ø¼ö Perl·Î¸¸ ¸¸µç À¥¼¹ö¸¦ ºÐ¼®ÇØ º¸°í ³ª¸é À¥¼¹ö ¹× CGI¿¡ ´ëÇÑ È®½ÇÇÑ ÀÌÇØ¸¦ °¡Áö°í ¹«¾ùÀÌ µÇ´Â °ÍÀÎÁö, ¾ÈµÇ´Â
°ÍÀÎÁö¸¦ ¹Ì¸® ¾Ë°í CGI¸¦ °³¹ßÇÒ ¼ö ÀÖÀ» °ÍÀÔ´Ï´Ù. PerlÀÌ ¾Æ´Ñ ´Ù¸¥ ¾ð¾î·Î CGI¸¦ °³¹ßÇϽô °æ¿ì¶óµµ ¸¶Âù°¡ÁöÀÔ´Ï´Ù. ¿ø¸®¸¦ ¾Ë¸é
¾î¶² ¾ð¾î¸¦ »ç¿ëÇØµµ ¸¶Âù°¡ÁöÀÇ ÁÁÀº È¿°ú¸¦ °ÅµÑ ¼ö ÀÖÀ» °ÍÀÔ´Ï´Ù.
ÀÌ ÇÁ·Î±×·¥ÀÇ ÀúÀÛ±ÇÀº Cameron
Kaiser¿¡°Ô ÀÖ½À´Ï´Ù. ÀÌ ÇÁ·Î±×·¥À» »ç¿ëÇϱâ ÀÌÀü¿¡ ¹Ýµå½Ã ÀúÀ۱ǿ¡ °üÇÑ ³»¿ëÀ» »ìÆìº¸½Ã±â
¹Ù¶ø´Ï´Ù. ¾Æ·¡ ¼Ò½º´Â ¼³Ä¡¸¦ Á¾·áÇÑ ÈÄ¿¡ »ý¼ºµÇ¸ç, ¼³Ä¡ Àü¿¡´Â ´Ù¼Ò ÀÌÇØÇϱ⠾î·Á¿î(ÀÌÇØÇÏ°í ½ÍÁö ¾ÊÀº :-) ¸ð¾çÀ» Çϰí ÀÖ½À´Ï´Ù.
¼³Ä¡ Á¾·á½ÃÀÇ ¼Ò½º¸¦ ¿©±â °ÔÀçÇÑ °ÍÀº ¹æ¹®ÀÚµéÀÇ À¥°ü·Ã ÇÁ·ÎÅäÄÝ¿¡ ´ëÇÑ ÀÌÇØ¸¦ µ½±â À§ÇÑ °Í »ÓÀÌ´Ï »ç¿ë½Ã¿¡´Â ¿øº» ÆÄÀÏÀ» ³»·Á¹Þ¾Æ ¼³Ä¡ÇÏ¿©
»ç¿ëÇϽñ⠹ٶø´Ï´Ù.
1: #!/usr/bin/perl
2: $VERSION = "1.3.1 (Demonic/FreeBSD)";
3:
4: # HTTPi Hypertext Tiny Truncated Process Implementation
5: # Copyright 1999-2001 Cameron Kaiser # All rights reserved
6: # Please read LICENSE # Do not strip this copyright message.
7:
8: %system_content_types =
9: ("html" => "text/html",
10: "htm" => "text/html",
11: "wml" => "text/vnd.wap.wml",
12: "wbmp" => "image/vnd.wap.wbmp",
13: "wbm" => "image/vnd.wap.wbmp",
14: "xbm" => "image/x-xbitmap",
15: "pdf" => "application/pdf",
16: "fdf" => "application/vnd.fdf",
17: "bin" => "application/octet-stream",
18: "class" => "application/octet-stream",
19: "jar" => "application/octet-stream",
20: "js" => "application/x-javascript",
21: "lnk" => "application/x-hyperlink",
22: "wav" => "audio/x-wav",
23: "mp3" => "audio/x-mpeg",
24: "txt" => "text/plain",
25: "gif" => "image/gif",
26: "zip" => "application/x-zip-compressed",
27: "lzh" => "application/octet-stream",
28: "lha" => "application/octet-stream",
29: "gz" => "application/x-gzip",
30: "mov" => "movie/quicktime",
31: "mpeg" => "video/mpeg",
32: "mpg" => "video/mpeg",
33: "jpeg" => "image/jpeg",
34: "jpg" => "image/jpeg");
35:
36: $logfile = "/home/perlabi/httpi/htdocs/access.log";
37: $path = "/home/perlabi/httpi/htdocs";
38: $sockaddr = 'S n a4 x8';
39:
40:
41: %content_types =
42: ("html" => "text/html",
43: "htm" => "text/html");
44: %restrictions =
45: ("/nw" => "^10\.##^Mozilla#MSIE",
46: "/status" => "####voyeur:daNrZR3TcSwD2");
47: # See documentation for interpreting this string.
48:
49: $headers = <<"EOF";
50: Server: HTTPi/$VERSION
51: MIME-Version: 1.0
52: EOF
53:
54:
55: %content_types = (%system_content_types, %content_types);
56: undef %system_content_types;
57:
58: if ($pid = fork()) { exit; }
59: $0 = "dhttpi: binding port ...";
60: $bindthis = pack($sockaddr, 2, 8088, pack('l', chr(0).chr(0).chr(0).chr(0)));
61: socket(S, 2, 1, 6);
62: setsockopt(S, 65535, 4, 1);
63: bind(S, $bindthis) || die("$0: while binding port 8088:\n\"$!\"\n");
64: listen(S, 128);
65: $0 = "dhttpi: connected and waiting ANY:8088";
66:
67: $statiosuptime = time();
68:
69: ###############################################################
70: # WHITE HATS ONLY BELOW THIS POINT -- SEE DOCUMENTATION FIRST #
71: ###############################################################
72:
73: sub sock_to_host {
74: local($sock) = getpeername(STDIN);
75:
76: return (undef, undef, undef) if (!$sock);
77: local($AFC, $port, $thataddr, $zero) = unpack($sockaddr, $sock);
78: local($ip) = join('.', unpack("C4", $thataddr));
79: return ($ip, $port, $ip);
80: }
81:
82: sub htsponse {
83: ($currentcode, $currentstring) = (@_);
84: return if (0+$httpver < 1);
85: local($what) = <<"EOF";
86: HTTP/$httpver $currentcode $currentstring
87: ${headers}Date: $rfcdate
88: EOF
89: $what =~ s/\n/\r\n/g;
90: print stdout $what;
91: &hthead("Connection: close") if (0+$httpver > 1);
92: }
93:
94: sub hthead {
95: local($header, $term) = (@_);
96: return if (0+$httpver < 1);
97: print stdout "$header\r\n" , ($term) ? "\r\n" : "";
98: }
99:
100: sub htcontent {
101: local($what, $ctype, $mode) = (@_);
102: ($contentlength) = $mode || length($what);
103: &hthead("Content-Length: $contentlength");
104: &hthead("Content-Type: $ctype", 1);
105: return if ($method eq 'HEAD' || $mode);
106: print stdout $what;
107: }
108:
109: sub log {
110: if (open(J, ">>$logfile")) {
111: local $q = $address . (($variables) ? "?$variables" : "");
112: $contentlength += 0;
113: $contentlength = 0 if ($method eq 'HEAD');
114: local ($hostname, $port, $ip) = &sock_to_host();
115: $hostname = $hostname || "-";
116: $httpuser = $httpuser || "-";
117: print J qq!$hostname - $httpuser [$date] "$method $q HTTP/$httpver"!,
118: qq! $currentcode $contentlength "$httpref" "$httpua"\n!;
119:
120: close(J); }
121: }
122:
123:
124: sub bye { exit; }
125:
126: sub dead {
127: &htsponse(500, "Server Error");
128: &hterror("Server Error", <<"EOF");
129: While handling a request for resource $address, the server crashed. Please
130: attempt to notify the administrators.
131: <p>Useful(?) debugging information:
132: <pre>
133: @_
134: </pre>
135: EOF
136: &log; exit;
137: }
138:
139: $SIG{'__DIE__'} = \&dead;
140: $SIG{'ALRM'} = \&bye;
141:
142: sub master {
143: $0 = "dhttpi: handling request";
144: # $sock = getpeername(STDIN);
145: $rfcdate = scalar gmtime;
146: ($dow, $mon, $dt, $tm, $yr) = ($rfcdate =~
147: m/(...) (...) (..) (..:..:..) (....)/);
148: $dt += 0; $yr += 0;
149: $rfcdate = "$dow, $dt $mon $yr $tm GMT";
150: $date = scalar localtime;
151: ($dow, $mon, $dt, $tm, $yr) = ($date =~
152: m/(...) (...) (..) (..:..:..) (....)/);
153: $dt += 0;
154: $dt = substr("0$dt", length("0$dt") - 2, 2);
155: $date = "$dt/$mon/$yr:$tm +0900";
156:
157: select(STDOUT); $|=1; $address = 0;
158: alarm 10;
159: while (<STDIN>) {
160: if(/^([A-Z]+)\s+([^\s]+)\s+([^\s\r\l\n]*)/) {
161: $method = $1;
162: $address = $2;
163: $httpver = $3;
164: $httpref = '';
165: $httpua = '';
166: $httpver = ($httpver =~ m#HTTP/([0-9]\.[0-9]+)#) ?
167: ($1) : (0.9);
168: $address =~ s#^http://[^/]+/#/#;
169: next unless ($httpver < 1);
170: } else {
171: s/[\r\l\n\s]+$//;
172: (/^Host: (.+)/i) && ($httphost = $1) && ($httphost =~
173: s/:\d+$//);
174: (/^Referer: (.+)/i) && ($httpref = $1);
175: (/^User-agent: (.+)/i) && ($httpua = $1);
176: (/^Content-length: (\d+)/i) && ($ENV{'CONTENT_LENGTH'} =
177: $httpcl = $1);
178: (/^Content-type: (.+)/i) && ($ENV{'CONTENT_TYPE'} =
179: $httpct = $1);
180: (/^Expect: /) && ($expect = 1);
181: (/^Authorization: Basic (.+)/i) && ($httprawu = $1);
182: (/^Range: (.+)/i) && ($ENV{'CONTENT_RANGE'} = $1);
183: next unless (/^$/);
184: }
185: if ($expect) {
186: &htsponse(417, "Expectation Failed");
187: &hterror("Expectation Failed",
188: "The server does not support this method.");
189: &log; exit;
190: }
191: if (!$address || (0+$httpver > 1 && !$httphost)) {
192: &htsponse(400, "Bad Request");
193: &hterror("Bad Request",
194: "The server cannot understand your request.");
195: &log; exit;
196: }
197: if ($method !~ /^(GET|HEAD|POST)$/) {
198: &htsponse(501, "Illegal Method");
199: &hterror("Illegal Method",
200: "Only GET, HEAD and POST are supported.");
201: &log; exit;
202: }
203: ($address, $variables) = split(/\?/, $address);
204: $address=~ s#^/?#/#;
205: 1 while $address =~ s#/\.(/|$)#\1#;
206: 1 while $address =~ s#/[^/]*/\.\.(/|$)#\1#;
207: 1 while $address =~ s#^/\.\.(/|$)#\1#;
208: $fail = 0;
209: J: foreach(sort { length $a <=> length $b }
210: keys %restrictions) {
211: next if ($address !~ /^$_/);
212: ($allowip, $denyip, $allowua, $denyua, $auser) =
213: split(/#/, $restrictions{$_});
214: if ($allowip || $denyip) {
215: ($hostname, $port, $ip) = &sock_to_host();
216: ($allowip && $ip !~ /$allowip/) && ($fail = 1,
217: last J);
218: ($denyip && $ip =~ /$denyip/) && ($fail = 1,
219: last J);
220: }
221: ($allowua && $httpua !~ /$allowua/) &&
222: ($fail = 2, last J);
223: ($denyua && $httpua =~ /$denyua/) &&
224: ($fail = 2, last J);
225: }
226: if ($fail) {
227: &htsponse(403, "Forbidden");
228: if ($fail == 1) {
229: &hterror("Forbidden (Client Disallowed)", <<"EOF");
230: Your network address (<i>$ip</i>) is not allowed to access this resource.
231: EOF
232: &log; exit;
233: } else {
234: &hterror("Forbidden (Browser Disallowed)", <<"EOF");
235: The browser you are using (<i>$httpua</i>) is not capable of or
236: is not allowed access to this resource.
237: EOF
238: &log; exit;
239: }
240: }
241: if ($auser) {
242: $httprawu =~ tr#A-Za-z0-9+/##cd;
243: $httprawu =~ tr#A-Za-z0-9+/# -_#;
244: $httprawu = unpack("u", pack("c", 32+0.75*length($httprawu))
245: . $httprawu);
246: ($httpuser, $httppw) = split(/:/, $httprawu);
247: $fail = 1;
248: foreach $user (split(/,/, $auser)) {
249: ($user, $pw) = split(/:/, $user);
250: ($fail = 0, last) if ($user eq $httpuser &&
251: crypt($httppw, substr($pw, 0, 2)) eq $pw);
252: }
253: if ($fail) {
254: $httpuser = '';
255: &htsponse(401, "Authorization Required");
256: &hthead("WWW-Authenticate: Basic realm=\"$address\"");
257: &hterror("Authorization Required", <<"EOF");
258: You must provide a username and password to use this resource. Either you
259: entered this information incorrectly, or your browser does not know how to
260: present the credentials required.
261: EOF
262: &log; exit;
263: }
264: }
265:
266:
267: $address =~ s/%([0-9a-fA-F]{2})/pack("H2", $1)/eg;
268: $raddress = "$path$address"
269: ;
270: &hterror301("http://ns.softbrain.co.kr:8088$address/")
271: if ($address !~ m#/$# && -d $raddress);
272: $raddress = "${raddress}index.html" if (-d $raddress);
273: alarm 0;
274: if(!sysopen(S, $raddress, 0)) { &hterror404; } else {
275: if (-x $raddress) {
276: $currentcode = 100;
277: &log;
278: if (!$<) {
279: ($x,$x,$x,$x,$uid,$gid) = stat(S);
280: (!$uid || !$gid) &&
281: die "executable is root-owned";
282: $> = $uid || die "can't set effuid";
283: $) = $gid || die "can't set effgid";
284: }
285: ($hostname, $port, $ip) = &sock_to_host() if (!$port);
286: $ENV{'REQUEST_METHOD'} = $method;
287: $ENV{'SERVER_NAME'} = "ns.softbrain.co.kr";
288: $ENV{'SERVER_PROTOCOL'} = "HTTP/$httpver";
289: $ENV{'SERVER_SOFTWARE'} = "HTTPi/$VERSION";
290: $ENV{'SERVER_PORT'} = "8088";
291: $ENV{'SERVER_URL'} = "http://ns.softbrain.co.kr:8088/";
292: $ENV{'SCRIPT_FILENAME'} = $raddress;
293: $ENV{'SCRIPT_NAME'} = $address;
294: $ENV{'REMOTE_HOST'} = $hostname;
295: $ENV{'REMOTE_ADDR'} = $ip;
296: $ENV{'REMOTE_PORT'} = $port;
297: $ENV{'QUERY_STRING'} = $variables;
298: $ENV{'HTTP_USER_AGENT'} = $httpua;
299: $ENV{'HTTP_REFERER'} = $httpref;
300: if ($pid = fork()) { exit; } else {
301: if ($method eq 'POST') { # needs stdin
302: open(W, "|$raddress") || die
303: "can't POST to $raddress";
304: read(STDIN, $buf, $httpcl);
305: print W $buf;
306: exit;
307: }
308: exec "$raddress", "$variables";
309: die "exec() returned -1";
310: }
311: }
312: ($x,$x,$x,$x,$x,$x,$x,$length,$x,$mtime) = stat(S);
313: $ctype = 0;
314: foreach(keys %content_types) {
315: if ($raddress =~ /\.$_$/i) {
316: $ctype = $content_types{$_};
317: }
318: }
319: SERVEIT: $ctype ||= 'text/plain';
320: &htsponse(200, "OK");
321: $mtime = scalar gmtime $mtime;
322: ($dow, $mon, $dt, $tm, $yr) =
323: ($mtime =~ m/(...) (...) (..) (..:..:..) (....)/);
324: $dt += 0; $yr += 0;
325: &hthead("Last-Modified: $dow, $dt $mon $yr $tm GMT");
326: if ($pid = fork()) { exit; }
327: alarm 25;
328: &htcontent("", $ctype, $length);
329: unless ($method eq 'HEAD') {
330: while(!eof(S)) {
331: read(S, $q, 16384);
332: print stdout $q;
333: }
334: }
335: alarm 0;
336: }
337: &log;
338: exit;
339: }
340:
341: exit;
342: }
343:
344:
345: sub hterror {
346: local($errstr, $expl) = (@_);
347: &htcontent(<<"EOF", "text/html");
348: <html>
349: <body>
350: <h1>$errstr</h1>
351: $expl
352: <hr>
353: <address><a href = "http://httpi.floodgap.com/">httpi/$VERSION</a>
354: by Cameron Kaiser</address>
355: </body>
356: </html>
357: EOF
358: }
359:
360: sub hterror404 {
361: &htsponse(404, "File Not Found");
362: &hterror("File Not Found",
363: "The resource $address was not found on this system.");
364: }
365:
366: sub hterror301 {
367: &htsponse(301, "Moved Permanently");
368: &hthead("Location: @_");
369: &hterror("Resource Moved Permanently",
370: "This resource has moved <a href = \"@_\">here</a>.");
371: $keep = 0; &log; exit;
372: }
373:
374: for (;;) {
375: $addr=accept(NS,S);
376: $statiosltr = scalar localtime;
377: $statiosreq++;
378: if ($pid = fork()) {
379: $0 = "dhttpi: waiting for child process";
380: waitpid($pid, 0);
381: $0 = "dhttpi: on ANY:8088, last request " .
382: scalar localtime;
383: } else {
384: $0 = "dhttpi: child switching to socket";
385: open(STDIN, "<&NS");
386: open(STDOUT, ">&NS");
387: &master;
388: exit;
389: }
390: }
|