1. Perl·Î ¸¸µç À¥¼­¹ö
2. mod_perl - Apache À¥¼­¹ö¿Í    PerlÀÇ °áÇÕ(µî·Ï¿¹Á¤)

 

¡Ú Perl·Î ¸¸µç À¥¼­¹ö

2002³â 3¿ù 18ÀÏ ÀüÁ¾ÇÊ

 ¾Æ·¡ ¼Ò½º´Â 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: }