pike.git
/
lib
/
modules
/
Tools.pmod
/
Standalone.pmod
/
httpserver.pike
version
»
Context lines:
10
20
40
80
file
none
3
pike.git/lib/modules/Tools.pmod/Standalone.pmod/httpserver.pike:12:
constant help_pre = #"Usage: httpserver [flags] [path] Starts a simple HTTP server on port 8080 unless another port is specified. The server will present the contents of the current directory and it's children to the world without any authentication. "; constant port_help = "Port to use. Defaults to 8080."; constant version_help = "Displays version information."; constant headers_help = "Set additional header and value, e.g. --header X-Content-Type-Options:nosniff";
+
constant allow_help = "Limit access to a specific IP, IP-range or CIDR net.";
constant log_help = "Logs request in 'commonlog', 'raw' or 'string' format."; Opt port = Int(HasOpt("--port")|Default(8080)); Opt version = NoOpt("--version"); Opt headers = Multiple(HasOpt("--header"));
-
+
Opt allow = Multiple(HasOpt("--allow"));
Opt log = HasOpt("--log"); } Options opt; mapping headers = ([]);
-
+
NetUtils.IpRangeLookup ip_whitelist;
int main(int argc, array(string) argv) { opt = Options(argv); if(opt->version) exit(0, version);
-
+
if(opt->help)
+
exit(0);
int port = opt->port; if(sizeof(argv=opt[Arg.REST])) { string home = combine_path(getcwd(), argv[-1]); if( Stdio.is_dir(home) ) cd(home); else if(port==8080 && (int)argv[-1]) port=(int)argv[-1]; }
pike.git/lib/modules/Tools.pmod/Standalone.pmod/httpserver.pike:50:
if( opt->headers ) { foreach(opt->headers, string hdr) { array h = hdr/":"; if(sizeof(h)<2) error("Illegal header format %O.\n", hdr); headers[h[0]] = h[1..]*":"; } }
+
if( opt->allow )
+
{
+
ip_whitelist = NetUtils.IpRangeLookup( ([ 1 : opt->allow ]) );
+
}
+
Protocols.HTTP.Server.Port(handle_request, port, NetUtils.ANY); write("%s is now accessible on port %d through http, " "without password.\n", getcwd(), port); return -1; } string dirlist( string dir ) { string res = "<html><head>\n"
pike.git/lib/modules/Tools.pmod/Standalone.pmod/httpserver.pike:106:
"<html><body><h1>File not found</h1>\n" "<tt>" + Parser.encode_html_entities(fname) + "</tt><br />\n" "</body></html>\n"; } void handle_request(Protocols.HTTP.Server.Request request) { string file = "."+combine_path("/",request->not_query); file = Protocols.HTTP.uri_decode(file); Stdio.Stat s = file_stat( file );
+
int ipblock = ip_whitelist &&
+
!ip_whitelist->lookup_range(request->my_fd->query_address());
switch(opt->log) { case 1: case "commonlog": { object now = Calendar.now();
-
+
int code = 404;
+
if( s ) code = 200;
+
if( ipblock ) code = 401;
write("%s - - [%d/%s/%d:%02d:%02d:%02d %s] %O %d %d\n", (request->my_fd->query_address()/" ")[0], now->month_day(), now->month_name()[..2], now->year_no(), now->hour_no(), now->minute_no(), now->second_no(), now->tzname_utc_offset(),
-
request->request_raw,
-
s ? 200 : 404
,
+
request->request_raw,
code
,
s && s->isreg && s->size); // Not showing generated data. } break; case "raw": write("%s\n\n", request->raw); break; case "string": write("%O\n\n", request->raw); break; default: break; }
-
if( !s )
+
if(
ipblock )
+
request->response_and_finish( (["data": "Permission denied for "+
+
(request->my_fd->query_address()/" ")[0],
+
"type":"text/plain",
+
"extra_heads" : headers,
+
"error":401]) );
+
else if(
!s )
request->response_and_finish( (["data": file_not_found(request->not_query), "type":"text/html", "extra_heads" : headers, "error":404]) ); else if( s->isdir ) request->response_and_finish( ([ "data":dirlist(file), "extra_heads" : headers, "type":"text/html" ]) ); else request->response_and_finish( ([ "file":Stdio.File(file), "extra_heads" : headers, ]) ); }