#!/usr/local/bin/perl5 # # File: sproxy.pl # Author: Adam Janin (janin@cs.berkeley.edu) # Date: 1/18/97 # Ver: 0.0 (alpha, pre-alpha, whatever) # # Proxy server that adds link labels and JavaScript hotkeys. # # Copyright (C) 1998 Regents of the University of California. # All rights reserved. # # Disclaimer: This software is provided "as is". I take no # responsibility for any problems resulting from its use. # # You may use this software in any way as long as: # o You do not charge for it. # o The original author and copyright information is retained. # # The proxy part of this code is based primarily on phd, a perl # proxy server written by Jerry LeVan (levan@eagle.eku.edu). # # See http://www.icsi.berkeley.edu/~janin/sproxy/sproxy.html for # additional information (including installation, known bugs, etc). # require 5.004; require HTML::TreeBuilder; require HTML::Element; use URI::URL; use Socket; use Getopt::Std; # # User Configuration # # Change if port 8000 is busy or you want to use a "standard" port (e.g. 80). $port = 8000; # Change if you don't like the name or want to provide an absolute path. $logfile = "proxy.log"; # You should probably change these to something reasonable. A * in a # field means "any". To connect, you must match @accesslist and not # match @denylist. @accesslist = ("128.32.201.*"); # Anyone on our subnet @denylist = (); # If $verbose is 0, you only get startup and shut down messages. # If $verbose is 1, you get access log messages. # If $verbose is 2, you get a bit more. # If $verbose is 3, you get a ton. Don't do this unless you're sure! $verbose = 0; # # You shouldn't have to change anything below this line # $version = "0.0"; $program = "sproxy"; open(LOG,">>$logfile") || die "Can't open log file" ; select(LOG) ; $| = 1; select(STDOUT); # # Elements to add labels # %labeledElements = ( 'a' => 'href' ); # # Set up the JavaScript that gets added. # Note that "var jLinks = [ "http://...", "..." ];" gets prepended # to this on a per-page basis. # # If you're on a UNIX machine, you may need to manually add CR/LF pairs. # # Sorry for the lack of comments in the JavaScript. The original parser # couldn't handle comments, so I removed them all. # # Ascii Char # 103 g # 115 s # 13 return # 48 0 (zero) # 57 9 # # jState = 0, start state # = 1, have seen a 's' or 'g', parsing # $ScriptText = <<'EOS'; var jKeyBuf = []; var jState = 0; var jOp = 0; var jOldStatus = window.defaultStatus; function jhandleKey(e) { if (e.target.type != "undefined") { return true; } if (jState == 0) { if (e.which == 103 || e.which == 115) { if (e.type == "keydown") { jState = 1; jOp = e.which; jKeyBuf.length = 0; jOldStatus = window.defaultStatus; window.defaultStatus = String.fromCharCode(e.which); } return false; } else { if (e.type == "keydown") { window.defaultStatus = jOldStatus; } return true; } } else if (jState == 1) { if (e.which == 13) { if (jKeyBuf.length == 0) { if (e.type == "keydown") { jState = 0; window.defaultStatus = jOldStatus; } return true; } if (e.type == "keydown") { window.defaultStatus = jOldStatus; if (jOp == 103) { jLinkTo(jParseBuf()); } else if (jOp == 115) { jShowLink(jParseBuf()); } jState = 0; } return false; } else if (48 <= e.which && e.which <= 57) { if (e.type == "keydown") { jKeyBuf[jKeyBuf.length] = e.which; window.defaultStatus += String.fromCharCode(e.which); } return false; } else { if (e.type == "keydown") { jState = 0; window.defaultStatus = jOldStatus; } return true; } } else { alert("Illegal State!"); return true; } } function jParseBuf() { var total = 0; var i; for (i = 0; i < jKeyBuf.length; i++) { total = total * 10 + jKeyBuf[i] - 48; } return total; } function jLinkTo(index) { if (0 <= index && index < jLinks.length) { window.location.href=jLinks[index]; } } function jShowLink(index) { if (0 <= index && index < jLinks.length) { window.status = jLinks[index]; } } document.captureEvents(Event.KEYUP); document.captureEvents(Event.KEYDOWN); document.captureEvents(Event.KEYPRESS); document.onKeyUp = jhandleKey; document.onKeyDown = jhandleKey; document.onKeyPress = jhandleKey; EOS # # Initialize port, standard perl server boilerplate # $sockaddr = 'S n a4 x8'; ($name, $aliases, $proto) = getprotobyname('tcp'); $thisport = pack($sockaddr, &AF_INET, $port, "\0\0\0\0"); # wildcard addr socket(S, &PF_INET, &SOCK_STREAM, $proto) || die "can't create socket: $!\n"; setsockopt(S, &SOL_SOCKET, &SO_REUSEADDR, pack('i', 1)) || die "can't setsockopt: $!\n"; bind(S,$thisport) || die "can't bind socket: $!\n"; listen(S,5) || die "can't listen to socket: $!\n"; # Don't show the environment of the invoker of this server. foreach $key (keys %ENV) { delete $ENV{$key}; } print LOG ×tamp, " Starting sproxy on port $port, PID = $$\n"; # Answer if someone knocks on the port. for (;;) { if(!accept(NS,S)) { print LOG "Accept Failure, shutting down sproxy, error: $!\n"; exit 1; } # Set the environment. SetupCommand(NS); # Check to see if they can access the server. if(!CheckAccess($ENV{REMOTE_ADDR},@accesslist)) { &ErrorMessage(NS,400,"Access Denied"); exit 0; # Bail out } # Check to see if the caller is explicitly denied access to the server. if(CheckAccess($ENV{REMOTE_ADDR},@denylist)) { &ErrorMessage(NS,400,"Access Denied"); exit 0; # Bail out } # Try to do the proxy thing DoCommand(NS); } # Sets many enviromental variables # # I don't understand why we need this -- AJ # sub SetupCommand { my $sock= $_[0]; $ENV{SERVER_SOFTWARE} = "$program/$version"; my $rem_ip_addr = (unpack($sockaddr, getsockname($sock)))[2]; $ENV{SERVER_NAME} = (gethostbyaddr($rem_ip_addr, &AF_INET))[0]; $ENV{GATEWAY_INTERFACE} = "CGI/1.1"; $ENV{SERVER_PROTOCOL} = "http/1.0"; $ENV{SERVER_PORT} = "$port"; $rem_ip_addr = (unpack($sockaddr, getpeername($sock)))[2]; $ENV{REMOTE_HOST} = (gethostbyaddr($rem_ip_addr, &AF_INET))[0]; $ENV{REMOTE_ADDR} = join(".", unpack("C4", $rem_ip_addr)); } # Print an error message to the client sub ErrorMessage { my($fd,$error,$message) =@_; print $fd "HTTP/1.0 200 OK\n"; print $fd "Content-type: text/html\n\n"; print $fd "