ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/Coro/myhttpd/diridx.pl
Revision: 1.27
Committed: Mon Dec 3 21:45:45 2001 UTC (22 years, 7 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.26: +5 -6 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 use List::Util qw(sum);
2
3 use Storable ();
4
5 my $SD_VERSION = 1;
6
7 my $ignore = qr/ ^(?:robots.txt$|\.) /x;
8
9 our %diridx;
10
11 if ($db_env) {
12 tie %diridx, BerkeleyDB::Hash,
13 -Env => $db_env,
14 -Filename => "directory",
15 -Flags => DB_CREATE,
16 or die "unable to create database index";
17 }
18
19 sub conn::gen_statdata {
20 my $self = shift;
21 my $data;
22
23 {
24 my $path = "";
25 my $prefix = "";
26
27 for ("http://".$self->server_hostport, split /\//, substr $self->{name}, 1) {
28 next if $_ eq ".";
29 $path .= "<a href='".escape_uri("$prefix$_")."/'>$_</a> / ";
30 $prefix .= "$_/";
31 }
32 $data->{path} = $path;
33 }
34
35 sub read_file {
36 local ($/, *X);
37 (open X, "<$_[0]\x00") ? <X> : ();
38 }
39
40 {
41 my $path = $self->{path};
42 do {
43 $data->{top} ||= read_file "$path.dols/top";
44 $data->{bot} ||= read_file "$path.dols/bot";
45 $path =~ s/[^\/]*\/+$//
46 or die "malformed path: $path";
47 } while $path ne "";
48 }
49
50 local *DIR;
51 if (opendir DIR, $self->{path}) {
52 my $dlen = 0;
53 my $flen = 0;
54 my $slen = 0;
55 for (sort readdir DIR) {
56 next if /$ignore/;
57 stat "$self->{path}$_";
58 if (-d _) {
59 next unless 0555 == ((stat _)[2] & 0555);
60 $dlen = length $_ if length $_ > $dlen;
61 push @{$data->{d}}, $_;
62 } else {
63 next unless 0444 == ((stat _)[2] & 0444);
64 my $s = -s _;
65 $flen = length $_ if length $_ > $dlen;
66 $slen = length $s if length $s > $dlen;
67 push @{$data->{f}}, [$_, $s];
68 }
69 }
70 $data->{dlen} = $dlen;
71 $data->{flen} = $flen;
72 $data->{slen} = $slen;
73 }
74
75 $data;
76 }
77
78 sub conn::get_statdata {
79 my $self = shift;
80
81 my $mtime = $self->{stat}[9];
82
83 $statdata = $diridx{$self->{path}};
84
85 if (defined $statdata) {
86 $$statdata = Storable::thaw $statdata;
87 return $$statdata
88 if $$statdata->{version} == $SD_VERSION
89 && $$statdata->{mtime} == $mtime;
90 }
91
92 $self->slog(8, "creating index cache for $self->{path}");
93
94 $$statdata = $self->gen_statdata;
95 $$statdata->{version} = $SD_VERSION;
96 $$statdata->{mtime} = $mtime;
97
98 $diridx{$self->{path}} = Storable::freeze $$statdata;
99 (tied %diridx)->db_sync;
100
101 $$statdata;
102 }
103
104 sub handle_redirect { # unused
105 if (-f ".redirect") {
106 if (open R, "<.redirect") {
107 while (<R>) {
108 if (/^(?:$host$port)$uri([^ \tr\n]*)[ \t\r\n]+(.*)$/) {
109 my $rem = $1;
110 my $url = $2;
111 print $nph ? "HTTP/1.0 302 Moved\n" : "Status: 302 Moved\n";
112 print <<EOF;
113 Location: $url
114 Content-Type: text/html
115
116 <html>
117 <head><title>Page Redirection to $url</title></head>
118 <meta http-equiv="refresh" content="0;URL=$url">
119 </head>
120 <body text="black" link="#1010C0" vlink="#101080" alink="red" bgcolor="white">
121 <large>
122 This page has moved to $url.<br />
123 <a href="$url">
124 The automatic redirection has failed. Please try a <i>slightly</i>
125 newer browser next time, and in the meantime <i>please</i> follow this link ;)
126 </a>
127 </large>
128 </body>
129 </html>
130 EOF
131 }
132 }
133 }
134 }
135 }
136
137 sub format_time {
138 if ($_[0] < 0) {
139 "--:--:--";
140 } elsif ($_[0] >= 60*60*24) {
141 sprintf "%02dd&#160;%02d:%02d:%02d",
142 int ($_[0] / (60 * 60 * 24)),
143 int ($_[0] / (60 * 60)) % 24,
144 int ($_[0] / 60) % 60,
145 int ($_[0]) % 60;
146 } else {
147 sprintf "%02d:%02d:%02d",
148 int ($_[0] / (60 * 60)) % 24,
149 int ($_[0] / 60) % 60,
150 int ($_[0]) % 60;
151 }
152 }
153
154 sub conn::diridx {
155 my $self = shift;
156
157 my $data = $self->get_statdata;
158
159 my $stat;
160 if ($data->{dlen}) {
161 $stat .= "<table><tr><th>Directories</th></tr>";
162 $data->{dlen} += 1;
163 my $cols = int ((79 + $data->{dlen}) / $data->{dlen});
164 $cols = @{$data->{d}} if @{$data->{d}} < $cols;
165 my $col = $cols;
166 for (@{$data->{d}}) {
167 if (++$col >= $cols) {
168 $stat .= "<tr>";
169 $col = 0;
170 }
171 if ("$self->{path}$_" =~ $conn::blockuri{$self->{country}}) {
172 $stat .= "<td>$_ ";
173 } else {
174 $stat .= "<td><a href='".escape_uri("$_/")."'>$_</a> ";
175 }
176 }
177 $stat .= "</table>";
178 }
179 if ($data->{flen}) {
180 $data->{flen} += 1 + $data->{slen} + 1 + 3;
181 my $cols = int ((79 + $data->{flen}) / $data->{flen});
182 $cols = @{$data->{f}} if @{$data->{f}} < $cols;
183 my $col = $cols;
184 $stat .= "<table><tr>". ("<th align='left'>File<th>Size<th>&nbsp;" x $cols);
185 for (@{$data->{f}}) {
186 if (++$col >= $cols) {
187 $stat .= "<tr>";
188 $col = 0;
189 }
190 $stat .= "<td><a href='".escape_uri($_->[0])."'>$_->[0]</a><td align='right'>$_->[1]<td>&nbsp;";
191 }
192 $stat .= "</table>";
193 }
194
195 <<EOF;
196 <html>
197 <head><title>$self->{uri}</title></head>
198 <body bgcolor="#ffffff" text="#000000" link="#0000ff" vlink="#000080" alink="#ff0000">
199 <h1>$data->{path}</h1>
200 $data->{top}
201 <hr />
202 <a href="/internal/status">Server Status Page &amp; Queueing Info</a>
203 <hr />
204 $stat
205 $data->{bot}
206 </body>
207 </html>
208 EOF
209 }
210
211 sub statuspage {
212 my ($self, $verbose) = @_;
213
214 my $uptime = format_time ($::NOW - $::starttime);
215
216 my $content = <<EOF;
217 <html>
218 <head><title>Server Status Page</title></head>
219 <body bgcolor="#ffffff" text="#000000" link="#0000ff" vlink="#000080" alink="#ff0000">
220 <h1>Server Status Page</h1>
221 <h2>Myhttpd</h2>
222 version <b>$VERSION</b>; current:max connection count: <b>$::conns</b>:<b>$::maxconns</b>; uptime: <b>$uptime</b>;<br />
223 client-id <b>$self->{remote_id}</b>; client country <b>$self->{country}</b>;<br />
224 <h2>Queue Statistics</h2>
225 <ul>
226 EOF
227
228 for (
229 ["download queue", $queue_file],
230 ["other queue", $queue_index],
231 ) {
232 my ($name, $queue) = @$_;
233 my @waiters = $queue->waiters;
234 $waiters[$_]{idx} = $_ + 1 for 0..$#waiters;
235
236 if (@waiters) {
237 $content .= "<li>$name<br />".(scalar @waiters)." client(s); $queue->{started} downloads started;";
238
239 $content .= "<p>Waiting time until download starts, estimated:<ul>";
240 for (
241 ["by most recently started transfer", $queue->{lastspb}],
242 ["by queue average", $queue->{avgspb}],
243 ["by next client in queue", $waiters[0]{spb}],
244 ) {
245 my ($by, $spb) = @$_;
246 $content .= "<li>$by<br />";
247 if ($spb) {
248 $content .= sprintf "100 KB file: <b>%s</b>; 1 MB file: <b>%s</b>; 100MB file: <b>%s</b>;",
249 format_time($spb* 100_000),
250 format_time($spb* 1_000_000),
251 format_time($spb*100_000_000);
252 } else {
253 $content .= "(unavailable)";
254 }
255 $content .= "</li>";
256 }
257 $content .= "</ul></p>";
258
259 @waiters = grep { $verbose || $_->{coro}{conn}{remote_id} eq $self->{remote_id} } @waiters;
260 if (@waiters) {
261 $content .= "<table border='1' width='100%'><tr><th>#</th><th>Remote ID</th>".
262 "<th>CN</th><th>Size</th><th>Waiting</th><th>ETA</th><th>URI</th></tr>";
263 for (@waiters) {
264 my $conn = $_->{coro}{conn};
265 my $time = format_time ($::NOW - $_->{time});
266 my $eta = $queue->{avgspb} * $_->{size} - ($::NOW - $_->{time});
267
268 $content .= "<tr>".
269 "<td align='right'>$_->{idx}</td>".
270 "<td>$conn->{remote_id}</td>".
271 "<td>$conn->{country}</td>".
272 "<td align='right'>$_->{size}</td>".
273 "<td align='right'>$time</td>".
274 "<td align='right'>".($eta < 0 ? "<font color='red'>overdue</font>" : format_time $eta)."</td>".
275 "<td>".escape_html($conn->{name})."</td>".
276 "</tr>";
277 }
278 $content .= "</table></li>";
279 }
280 $content .= "</li>";
281 } else {
282 $content .= "<li>$name<br />(empty)</li>";
283 }
284 }
285
286 $content .= <<EOF;
287 </ul>
288 </body>
289 </html>
290 EOF
291
292 $self->response(200, "ok",
293 {
294 "Content-Type" => "text/html",
295 "Content-Length" => length $content,
296 },
297 $content);
298 };
299
300 $::internal{status} = sub { statuspage($_[0], 0) };
301 $::internal{queue} = sub { statuspage($_[0], 1) };
302
303 1;