1
  
2
  
3
  
4
  
5
  
6
  
7
  
8
  
9
  
10
  
11
  
12
  
13
  
14
  
15
  
16
  
17
  
18
  
19
  
20
  
21
  
22
  
23
  
24
  
25
  
26
  
27
  
28
  
29
  
30
  
31
  
32
  
33
  
34
  
35
  
36
  
37
  
38
  
39
  
40
  
41
  
42
  
43
  
44
  
45
  
46
  
47
  
48
  
49
  
50
  
51
  
52
  
53
  
54
  
55
  
56
  
57
  
58
  
59
  
60
  
61
  
62
  
63
  
64
  
65
  
66
  
67
  
68
  
69
  
70
  
71
  
72
  
73
  
74
  
75
  
76
  
77
  
78
  
79
  
80
  
81
  
82
  
83
  
84
  
85
  
86
  
87
  
88
  
89
  
90
  
91
  
92
  
93
  
94
  
95
  
96
  
97
  
98
  
99
  
100
  
101
  
102
  
103
  
104
  
105
  
106
  
107
  
108
  
109
  
110
  
111
  
112
  
113
  
114
  
115
  
116
  
117
  
118
  
119
  
120
  
#pike __REAL_VERSION__ 
//#pragma strict_types 
 
constant version = sprintf(#"Pike httpserver %d.%d.%d 
",(int)__REAL_VERSION__,__REAL_MINOR__,__REAL_BUILD__); 
 
constant description = "Minimal HTTP-server."; 
 
class Options 
{ 
  inherit Arg.Options; 
 
  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."; 
 
  Opt port = Int(HasOpt("--port")|Default(8080)); 
  Opt version = NoOpt("--version"); 
} 
 
Options opt; 
 
int main(int argc, array(string) argv) 
{ 
  opt = Options(argv); 
 
  if(opt->version) 
    exit(0, version); 
 
  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]; 
  } 
 
  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" 
        "<style>a { text-decoration: none;  }\n" 
        ".odd { background-color:#efefef; }\n" 
        ".even { background-color:#fefefe; }\n" 
        "</style>\n" 
        "</head><body>\n" 
        "<h1>"+Parser.encode_html_entities(dir[2..])+"</h1>" 
        "<table cellspacing='0' cellpadding='2'>\n" 
        "<tr><th align='left'>Filename</th>" 
        "<th align='right'>Type</th>" 
        "<th align='right'>Size</th></tr>\n"; 
 
    foreach( sort( get_dir( dir ) ); int i; string fn ) 
    { 
        Stdio.Stat s = file_stat( combine_path(dir, fn) ); 
        if( !s ) 
            continue; 
 
        string t = s->isdir?"":Protocols.HTTP.Server.filename_to_type(fn); 
        if( t == "application/octet-stream" ) 
            t = "<span style='color:darkgrey'>unknown</span>"; 
 
        res += 
            sprintf("<tr class='%s'><td><a href='%s%s'>%s%[2]s</a></td>" 
                    "<td align='right'>%s</td>" 
                    "<td align='right'>%s</td></tr>\n", 
                    (i&1?"odd":"even"), 
                    Protocols.HTTP.uri_encode(fn), s->isdir?"/":"", 
                    Parser.encode_html_entities(fn), t, 
                    s->isdir?"":String.int2size(s->size)); 
    } 
    return res+"</table></body></html>\n"; 
} 
 
string file_not_found(string fname) 
{ 
  return 
    "<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 ); 
 
    mapping hdr = ([]); 
 
    if( !s ) 
        request->response_and_finish( (["data": 
                                        file_not_found(request->not_query), 
                                        "type":"text/html", 
                                        "extra_heads" : hdr, 
                                        "error":404]) ); 
    else if( s->isdir ) 
        request->response_and_finish( ([ "data":dirlist(file), 
                                         "extra_heads" : hdr, 
                                         "type":"text/html" ]) ); 
    else 
      request->response_and_finish( ([ "file":Stdio.File(file), 
                                       "extra_heads" : hdr, 
                                    ]) ); 
}