1 (* Copyright 2001, 2002 b8_bavard, b8_fee_carabine, INRIA *)
3 This file is part of mldonkey.
5 mldonkey is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 mldonkey is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with mldonkey; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 open CommonInteractive
30 open CommonComplexOptions
34 open TcpBufferedSocket
36 open DriverInteractive
40 let log_prefix = "[dCon]"
43 lprintf_nl2
log_prefix fmt
46 lprintf2
log_prefix fmt
48 let rec dollar_escape o with_frames s
=
49 String2.convert
false (fun b escaped c
->
52 | 'O'
-> if with_frames
then
53 if !!html_mods
then Buffer.add_string b
"output"
54 else Buffer.add_string b
" target=\"output\"";
56 | 'S'
-> if with_frames
then
57 if !!html_mods
then Buffer.add_string b
"fstatus"
58 else Buffer.add_string b
" target=\"fstatus\"";
60 | 'P'
-> if with_frames
then
61 if !!html_mods
then Buffer.add_string b
"_parent"
62 else Buffer.add_string b
" target=\"_parent\"";
67 if o
.conn_output
= ANSI
then
68 Buffer.add_string b
Terminal.ANSI.ansi_RED
;
72 if o
.conn_output
= ANSI
then
73 Buffer.add_string b
Terminal.ANSI.ansi_BLUE
;
77 if o
.conn_output
= ANSI
then
78 Buffer.add_string b
Terminal.ANSI.ansi_GREEN
;
82 if o
.conn_output
= ANSI
then
83 Buffer.add_string b
Terminal.ANSI.ansi_CYAN
;
87 if o
.conn_output
= ANSI
then
88 Buffer.add_string b
Terminal.ANSI.ansi_NORMAL
;
94 Buffer.add_string b (dollar_escape with_frames
95 (CommonNetwork.escape_char c));
99 Buffer.add_char b '$'
; Buffer.add_char b c
; false
101 if c
= '$'
then true else
102 (Buffer.add_char b c
; false)) s
104 let eval auth cmd o
=
105 let buf = o
.conn_buf
in
106 let cmd = Url.decode ~raw
:false cmd in
108 if String2.check_prefix
cmd "ed2k://" ||
109 String2.check_prefix
cmd "ftp://" ||
110 String2.check_prefix
cmd "http://" then "dllink " ^
cmd
111 else if String2.check_prefix
cmd "fha://" then "ovlink " ^
cmd
113 let l = String2.tokens
cmd in
116 | ["longhelp"] | ["??"] ->
117 let module M
= CommonMessages
in
118 if o
.conn_output
= HTML
then begin
119 Buffer.add_string
buf "\\<div class=\\\"cs\\\"\\>";
120 html_mods_table_header
buf "helpTable" "results" [];
121 Buffer.add_string
buf "\\<tr\\>";
123 ("", "srh", M.available_commands_are
);
126 Buffer.add_string
buf "\\</tr\\>";
127 html_mods_cntr_init
();
128 List.iter
(fun (cmd, _
, _
, help
) ->
129 let ncmd = ref cmd in
130 let nhelp = ref help
in
131 Printf.bprintf
buf "\\<tr class=\\\"dl-%d\\\"\\>" (html_mods_cntr
());
133 ("", "sr", "\\<a href=\\\"submit?q=" ^
!ncmd ^
134 "\\\"\\>" ^
!ncmd ^
"\\</a\\>");
135 ("", "srw", Str.global_replace
(Str.regexp
"\n") "\\<br\\>" !nhelp);
136 ("", "sr", "\\<a href=\\\"http://mldonkey.sourceforge.net/" ^
(String2.upp_initial
!ncmd) ^
137 "\\\"\\>wiki\\</a\\>"); ];
138 Printf.bprintf
buf "\\</tr\\>\n";
140 (List.sort
(fun (c1
,_
, _
,_
) (c2
,_
, _
,_
) -> compare c1 c2
)
141 !CommonNetwork.network_commands
);
142 Printf.bprintf
buf "\\</table\\>\\</div\\>";
143 html_mods_table_header
buf "helpTable" "results" [];
144 Printf.bprintf
buf "\\<tr class=\\\"dl-1\\\"\\>";
146 ("", "sr", "< > : required parameter");
147 ("", "sr", "[< >] : optional parameter");
148 ("", "sr", "< 1 | 2 > : alternative parameter"); ];
149 Printf.bprintf
buf "\\</table\\>\\</div\\>\\</div\\>"
152 Buffer.add_string
buf M.available_commands_are
;
153 let list = Hashtbl2.to_list2 commands_by_kind
in
154 let list = List.sort
(fun (s1
,_
) (s2
,_
) -> compare s1 s2
) list in
155 List.iter
(fun (s
,list) ->
156 Printf.bprintf
buf "\n $b%s$n:\n" s
;
157 let list = List.sort
(fun (s1
,_
) (s2
,_
) -> compare s1 s2
) !list in
158 List.iter
(fun (cmd, help
) ->
159 Printf.bprintf
buf "$r%s$n %s\n" cmd help
;
164 | ["help"] | ["?"] ->
165 let module M
= CommonMessages
in
166 if o
.conn_output
= HTML
then
168 Buffer.add_string
buf "\\<div class=\\\"cs\\\"\\>";
169 html_mods_table_header
buf "helpTable" "results" [];
170 Buffer.add_string
buf "\\<tr\\>";
172 ("", "srh", M.main_commands_are
);
174 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-1\\\"\\>";
176 ("", "sr", "$bServers:$n");
178 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-2\\\"\\>";
180 ("", "sr", "$r\\<a href=\\\"submit?q=vm\\\"\\>" ^
182 ("", "sr", "list connected servers"); ];
183 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-2\\\"\\>";
185 ("", "sr", "$r\\<a href=\\\"submit?q=vma\\\"\\>" ^
187 ("", "sr", "list all servers"); ];
188 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-2\\\"\\>";
190 ("", "sr", "$rc/x <num>$n");
191 ("", "sr", "connect/disconnect from a server"); ];
192 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-1\\\"\\>";
194 ("", "sr", "$bDownloads:$n");
196 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-2\\\"\\>";
198 ("", "sr", "$r\\<a href=\\\"submit?q=vd\\\"\\>" ^
200 ("", "sr", "view current downloads"); ];
201 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-2\\\"\\>";
203 ("", "sr", "$rcancel/pause/resume <num>$n");
204 ("", "sr", "cancel/pause/resume download <num>"); ];
205 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-1\\\"\\>";
207 ("", "sr", "$bSearches:$n");
209 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-2\\\"\\>";
211 ("", "sr", "$rs <keywords>$n");
212 ("", "sr", "start a search for keywords <keywords> on the network"); ];
213 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-2\\\"\\>";
215 ("", "sr", "$r\\<a href=\\\"submit?q=vr\\\"\\>" ^
217 ("", "sr", "view results of the last search"); ];
218 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-2\\\"\\>";
220 ("", "sr", "$rd <num>$n");
221 ("", "sr", "download result number <num>"); ];
222 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-2\\\"\\>";
224 ("", "sr", "$r\\<a href=\\\"submit?q=vs\\\"\\>" ^
226 ("", "sr", "view previous searches"); ];
227 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-2\\\"\\>";
229 ("", "sr", "$rvr <num>$n");
230 ("", "sr", "view results of search <num>"); ];
231 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-1\\\"\\>";
233 ("", "sr", "$bGeneral:$n");
235 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-2\\\"\\>";
237 ("", "sr", "$r\\<a href=\\\"submit?q=save\\\"\\>" ^
239 ("", "sr", "save configuration files"); ];
240 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-2\\\"\\>";
242 ("", "sr", "$rkill$n");
243 ("", "sr", "kill mldonkey properly"); ];
244 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-2\\\"\\>";
247 ("", "sr", "quit this interface"); ];
248 Buffer.add_string
buf "\\</tr\\>\\</table\\>\\</div\\>\n";
249 html_mods_table_header
buf "helpTable" "results" [];
250 Buffer.add_string
buf "\\<tr class=\\\"dl-1\\\"\\>";
252 ("", "sr", "Use '$r\\<a href=\\\"submit?q=longhelp\\\"\\>" ^
253 "longhelp\\</a\\>$n' or '$r\\<a href=\\\"submit?q=longhelp\\\"\\>" ^
254 "??\\</a\\>$n' for all commands."); ];
255 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-1\\\"\\>";
257 ("", "sr", "Use '$rhelp command$n' or '$r? command$n' for help on a command."); ];
258 Buffer.add_string
buf "\\</tr\\>\\</table\\>\\</div\\>\\</div\\>\n"
261 Buffer.add_string
buf
265 $rvm$n : list connected servers
266 $rvma$n : list all servers
267 $rc/x <num>$n : connect/disconnect from a server
270 $rvd$n : view current downloads
271 $rcancel/pause/resume <num>$n : cancel/pause/resume download <num>
274 $rs <keywords>$n : start a search for keywords <keywords> on the network
275 $rvr$n : view results of the last search
276 $rd <num>$n : download result number <num>
277 $rvs$n : view previous searches
278 $rvr <num>$n : view results of search <num>
281 $rsave$n : save configuration files
282 $rkill$n : kill mldonkey properly
283 $rq$n : quit this interface
285 Use '$rlonghelp$n' or '$r??$n' for all commands.
286 Use '$rhelp command$n' or '$r? command$n' for help on a command.
288 | "?" :: args
| "help" :: args
| "man" :: args
->
289 List.iter
(fun arg
->
290 List.iter
(fun (cmd, _
, _
, help
) ->
292 Printf.bprintf
buf "%s %s\n" cmd help
)
293 !CommonNetwork.network_commands
)
298 let command = List.assoc one
!!alias_commands
in
299 match String2.split
command ' '
with
300 [] -> raise Not_found
(* can't happen *)
302 | a
::b
-> a
, (b
@ two
)
304 Not_found
-> one
, two
)
307 raise
CommonTypes.CommandCloseSocket
312 [] -> failwith
"Usage: auth <user> <password>"
313 | [s1
] -> (admin_user
()).CommonTypes.user_name
, s1
314 | user :: pass
:: _
-> user, pass
316 if valid_password
user pass
then begin
318 o
.conn_user
<- find_ui_user
user;
319 if not
!verbose_no_login
then lprintf_nl "Authenticated user: %s" user;
320 let module M
= CommonMessages
in
321 Buffer.add_string
buf M.full_access
;
322 (match DriverInteractive.real_startup_message
() with
323 Some s
-> Buffer.add_string
buf ("\n" ^ s
);
326 let module M
= CommonMessages
in
327 Buffer.add_string
buf M.bad_login
330 DriverCommands.execute_command
331 !CommonNetwork.network_commands o
cmd args
333 let module M
= CommonMessages
in
334 Buffer.add_string
buf M.command_not_authorized
337 (* This function is called every hour to check if we have something to do
340 let calendar_options = {
341 conn_buf
= Buffer.create
1000;
343 conn_sortvd
= NotSorted
;
344 conn_filter
= (fun _
-> ());
345 conn_user
= find_ui_user
CommonUserDb.admin_user_name
;
346 conn_width
= 80; conn_height
= 0;
347 conn_info
= Some
(CALENDAR
, (Ip.null
, 0));
350 let check_calendar () =
351 let time = last_time
() in
352 let tm = Unix.localtime
(date_of_int
time) in
353 List.iter
(fun (days
, hours
, command) ->
354 if (List.mem
tm.Unix.tm_wday days
|| days
= []) &&
355 (List.mem
tm.Unix.tm_hour hours
|| hours
= []) then begin
356 lprintf_nl "Calendar execute: %s" command;
357 eval (ref true) command calendar_options;
358 lprintf_nl "Calendar result: %s" (Buffer.contents
calendar_options.conn_buf
);
359 Buffer.reset
calendar_options.conn_buf
;
364 (*************************************************************
368 **************************************************************)
370 let before_telnet_output o sock
=
371 if o
.conn_output
= ANSI
&& o
.conn_height
<> 0 then
372 write_string sock
(Printf.sprintf
374 (Terminal.gotoxy
0 (o
.conn_height
-3))
375 Terminal.ANSI.ansi_CLREOL
376 Terminal.ANSI.ansi_CLREOL
377 (Terminal.gotoxy
0 (o
.conn_height
-3)))
379 let after_telnet_output o sock
=
380 if o
.conn_output
= ANSI
&& o
.conn_height
<> 0 then
381 write_string sock
(Printf.sprintf
"\n\n%s"
382 (Terminal.gotoxy
0 (o
.conn_height
- 2)));
383 if o
.conn_output
= ANSI
then
384 write_string sock
(Printf.sprintf
"%sMLdonkey command-line:%s\n> "
385 Terminal.ANSI.ansi_REVERSE
386 Terminal.ANSI.ansi_NORMAL
)
389 let user_reader o telnet sock nread =
390 let b = TcpBufferedSocket.buf sock in
391 let end_pos = b.pos + b.len in
392 let new_pos = end_pos - nread in
394 let end_pos = b.pos + b.len in
395 for i = b.pos to b.pos + b.len - 1 do
396 let c = int_of_char b.buf.[i] in
397 if c <> 13 && c <> 10 && (c < 32 || c > 127) then
398 lprintf "term[%d] = %d\n" i c;
403 let c = int_of_char c in
404 if c = 13 || c = 10 || c = 0 then
405 let len = i - b.pos in
406 let cmd = String.sub b.buf b.pos len in
407 buf_used sock (len+1);
408 if cmd <> "" then begin
409 before_telnet_output o sock;
410 let buf = o.conn_buf in
412 if o.conn_output = ANSI then Printf.bprintf buf "> $c%s$n\n" cmd;
413 eval telnet.telnet_auth cmd o;
414 Buffer.add_char buf '\n';
415 if o.conn_output = ANSI then Buffer.add_string buf "$n";
416 TcpBufferedSocket.write_string sock
417 (dollar_escape o false (Buffer.contents buf));
418 after_telnet_output o sock;
427 | CommonTypes.CommandCloseSocket ->
429 shutdown sock "user quit";
432 before_telnet_output o sock;
433 TcpBufferedSocket.write_string sock
434 (Printf.sprintf "exception [%s]\n" (Printexc2.to_string e));
435 after_telnet_output o sock
450 telnet_buffer
: Buffer.t
;
451 mutable telnet_iac
: bool;
452 mutable telnet_wait
: int;
453 telnet_auth
: bool ref;
456 let iac_will_8bit = "\255\253\000"
457 let iac_will_naws = "\255\253\031"
459 let user_reader o telnet sock nread
=
460 let b = TcpBufferedSocket.buf sock
in
463 let c = b.buf.[b.pos
] in
465 (* lprintf "char %d\n" (int_of_char c); *)
466 if c = '
\255'
&& not telnet
.telnet_iac
then begin
467 telnet
.telnet_iac
<- true;
470 if c <> '
\255'
&& telnet
.telnet_iac
then begin
471 telnet
.telnet_iac
<- false;
474 Buffer.add_char telnet
.telnet_buffer
c;
475 telnet
.telnet_wait
<- 1
477 Buffer.reset telnet
.telnet_buffer
482 let i = int_of_char
c in
483 telnet
.telnet_iac
<- false;
484 let is_normal_char = i > 31 in
486 if telnet
.telnet_wait
= 1 then begin
487 Buffer.add_char telnet
.telnet_buffer
c;
488 let cmd = Buffer.contents telnet
.telnet_buffer
in
489 telnet
.telnet_wait
<- 0;
490 let len = String.length
cmd in
494 Buffer.reset telnet
.telnet_buffer
496 telnet
.telnet_wait
<- 4
499 lprintf "telnet server: Unknown control sequence %s\n"
500 (String.escaped cmd); *)
501 Buffer.reset telnet
.telnet_buffer
503 let s = String.sub
cmd 0 2 in
504 Buffer.reset telnet
.telnet_buffer
;
507 let dx = BigEndian.get_int16
cmd 2 in
508 let dy = BigEndian.get_int16
cmd 4 in
511 (* lprintf "SIZE RECEIVED %d x %d\n" dx dy; *)
514 lprintf "telnet server: Unknown control sequence %s\n"
515 (String.escaped cmd); *)
518 if telnet
.telnet_wait
> 1 then begin
519 Buffer.add_char telnet
.telnet_buffer
c;
520 telnet
.telnet_wait
<- telnet
.telnet_wait
- 1;
522 if is_normal_char then
523 Buffer.add_char telnet
.telnet_buffer
c
525 (* evaluate the command *)
526 let cmd = Buffer.contents telnet
.telnet_buffer
in
527 Buffer.reset telnet
.telnet_buffer
;
528 if cmd <> "" then begin
529 before_telnet_output o sock
;
530 let buf = o
.conn_buf
in
532 if o
.conn_output
= ANSI
then Printf.bprintf
buf "> $c%s$n\n" cmd;
533 eval telnet
.telnet_auth
cmd o
;
534 Buffer.add_char
buf '
\n'
;
535 if o
.conn_output
= ANSI
then Buffer.add_string
buf "$n";
536 TcpBufferedSocket.write_string sock
537 (dollar_escape o
false (Buffer.contents
buf));
538 after_telnet_output o sock
;
540 if i = 255 then telnet
.telnet_wait
<- 2;
547 | CommonTypes.CommandCloseSocket
->
549 shutdown sock Closed_by_user
;
552 before_telnet_output o sock
;
553 TcpBufferedSocket.write_string sock
554 (Printf.sprintf
"exception [%s]\n" (Printexc2.to_string e
));
555 after_telnet_output o sock
558 let user_closed sock msg
=
559 user_socks
:= List2.removeq sock
!user_socks
;
562 let telnet_handler t event
=
564 TcpServerSocket.CONNECTION
(s, Unix.ADDR_INET
(from_ip
, from_port
)) ->
565 let from_ip = Ip.of_inet_addr
from_ip in
566 if not
!verbose_no_login
then lprintf_nl "Telnet connection from %s" (Ip.to_string
from_ip);
567 let token = create_token unlimited_connection_manager
in
568 let sock = TcpBufferedSocket.create_simple
token
572 telnet_auth
= ref (has_empty_password
(admin_user
()));
575 telnet_buffer
= Buffer.create
100;
578 conn_buf
= Buffer.create
1000;
579 conn_output
= (if !!term_ansi
then ANSI
else TEXT
);
580 conn_sortvd
= NotSorted
;
581 conn_filter
= (fun _
-> ());
582 conn_user
= find_ui_user
CommonUserDb.admin_user_name
;
585 conn_info
= Some
(TELNET
, (from_ip, from_port
));
587 (match Ip_set.match_ip
!allowed_ips_set
from_ip with
589 TcpBufferedSocket.prevent_close
sock;
590 TcpBufferedSocket.set_max_output_buffer
sock !!interface_buffer
;
591 TcpBufferedSocket.set_reader
sock (user_reader o telnet);
592 TcpBufferedSocket.set_closer
sock user_closed;
593 user_socks
:= sock :: !user_socks
;
595 TcpBufferedSocket.write_string
sock iac_will_8bit;
596 TcpBufferedSocket.write_string
sock iac_will_naws;
598 before_telnet_output o sock;
599 TcpBufferedSocket.write_string
sock
600 (Printf.sprintf
"Welcome to MLDonkey %s\n" Autoconf.current_version
);
602 TcpBufferedSocket.write_string
sock (dollar_escape o false
603 "$cWelcome on mldonkey command-line$n\n\nUse $r?$n for help\n\n");
605 after_telnet_output o sock
608 before_telnet_output o sock;
610 Printf.sprintf
"Telnet connection from %s rejected (see allowed_ips setting)\n"
611 (Ip.to_string
from_ip)
613 TcpBufferedSocket.write_string
sock (dollar_escape o false reject_message);
614 shutdown
sock Closed_connect_failed
;
615 if not
!verbose_no_login
then lprintf_n "%s" reject_message;
620 (*************************************************************
624 **************************************************************)
628 let buf = Buffer.create
1000
661 let http_file_type = ref UNK
663 let extension_to_file_ext extension
=
701 let ext_to_file_type ext
=
726 let ext_to_mime_type ext
=
729 | BINARY
-> "application/octet-stream"
731 | HTMLS
-> "text/html"
732 | ICON
-> "image/x-icon"
733 | JAVASCRIPT
-> "text/javascript"
734 | JPEG
-> "image/jpg"
735 | MPEG
-> "video/mpeg"
736 | AVI
-> "video/x-msvideo"
737 | WMV
-> "video/x-ms-wmv"
738 | ASF
-> "video/x-ms-asf"
739 | MOV
-> "video/quicktime"
740 | OGM
-> "application/ogg" (* is that correct ? *)
741 | RM
-> "audio/x-pn-realaudio"
742 | MKV
-> "video/x-matroska" (* is that correct ? *)
745 | MP3
-> "audio/mpeg"
746 | WMA
-> "audio/x-ms-wma"
747 | OGG
-> "application/ogg" (* is that correct ? *)
748 | TEXTS
-> "text/plain"
749 | WML
-> "text/vnd.wap.wml"
751 let default_charset = "charset=UTF-8"
753 let get_theme_page page
=
754 let theme = Filename.concat html_themes_dir
!!html_mods_theme
in
755 let fname = Filename.concat
theme page
in fname
757 let theme_page_exists page
=
758 Sys.file_exists
(get_theme_page page
)
760 (* if files are small really_input should be okay *)
761 let read_theme_page page
=
762 let theme_page = get_theme_page page
in
763 Unix2.tryopen_read
theme_page (fun file
->
764 let size = (Unix.stat
theme_page).Unix.st_size
in
765 let s = String.make
size ' '
in
766 really_input file
s 0 size;
769 let http_add_gen_header r
=
770 add_reply_header r
"Server" "MLdonkey";
771 add_reply_header r
"Connection" "close"
773 let add_gzip_headers r
=
774 if !!html_use_gzip
then begin
775 add_reply_header r
"Content-Encoding" "gzip";
776 add_reply_header r
"Vary" "Accept-Encoding";
779 let http_add_html_header r
=
780 let ext = extension_to_file_ext "html" in
781 http_file_type := ext_to_file_type ext;
782 http_add_gen_header r
;
783 add_reply_header r
"Pragma" "no-cache";
784 add_reply_header r
"Content-Type" ((ext_to_mime_type ext) ^
";" ^
default_charset);
787 let http_add_text_header r
ext =
788 http_file_type := ext_to_file_type ext;
789 http_add_gen_header r
;
790 add_reply_header r
"Content-Type" ((ext_to_mime_type ext) ^
";" ^
default_charset);
793 let http_add_bin_info_header r clen
=
794 add_reply_header r
"Accept-Ranges" "bytes";
795 add_reply_header r
"Content-Length" (Printf.sprintf
"%d" clen
)
797 let http_add_bin_header r
ext clen
=
798 http_file_type := ext_to_file_type ext;
799 http_add_gen_header r
;
800 add_reply_header r
"Content-Type" (ext_to_mime_type ext);
801 http_add_bin_info_header r clen
803 let http_add_bin_stream_header r
ext =
804 http_file_type := BIN
;
805 http_add_gen_header r
;
806 let mime_type = ext_to_mime_type ext in
807 let mime_type = if mime_type <> "" then mime_type
808 else "application/binary" in
809 add_reply_header r
"Content-Type" mime_type;
810 add_reply_header r
"Accept-Ranges" "bytes"
812 let http_send_bin r
buf filename
=
814 if theme_page_exists filename
then
815 File.to_string
(get_theme_page filename
)
818 File.to_string filename
819 with _
-> raise Not_found
821 let ext = extension_to_file_ext (Filename2.last_extension2 filename
) in
822 http_add_bin_header r
ext (String.length
file_to_send);
823 Buffer.add_string
buf file_to_send
825 let http_send_bin_pictures r
buf filename
=
828 Hashtbl.find
CommonPictures.files filename
831 if String.sub filename
0 4 = "flag" then
832 Hashtbl.find
CommonPictures.files
"flag_--.png"
835 with _
-> raise Not_found
837 let ext = extension_to_file_ext (Filename2.last_extension2 filename
) in
838 http_add_bin_header r
ext (String.length
file_to_send);
839 Buffer.add_string
buf file_to_send
841 let http_error_no_gd img_type
=
844 (match Autoconf.has_gd_jpg
with
846 | false -> lprintf_nl "Warning: GD jpg support disabled"; true)
848 (match Autoconf.has_gd_png
with
850 | false -> lprintf_nl "Warning: GD png support disabled"; true)
852 (match Autoconf.has_gd
with
854 | false -> lprintf_nl "Warning: GD support disabled"; true)
855 let any_ip = Ip.of_inet_addr
Unix.inet_addr_any
857 let html_open_page buf t r open_body
=
859 http_add_html_header r
;
861 if not
!!html_mods
then
862 (Buffer.add_string
buf
863 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\"
864 \"http://www.w3.org/TR/html4/frameset.dtd\">\n<HTML>\n<HEAD>\n";)
865 else Buffer.add_string
buf "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n";
866 if !CommonInteractive.display_vd
then begin
867 let this_page = "dheader.html" in
868 Buffer.add_string
buf
870 if !!html_mods_theme
<> "" && theme_page_exists this_page then
871 read_theme_page this_page else
872 if !!html_mods
then !!CommonMessages.download_html_header_mods0
873 else !!CommonMessages.download_html_header_old
);
874 Printf.bprintf
buf "<meta http-equiv=\"refresh\" content=\"%d\">" !!vd_reload_delay
;
876 if !CommonInteractive.display_bw_stats
then
877 Printf.bprintf
buf "<meta http-equiv=\"refresh\" content=\"%d\">" !!html_mods_bw_refresh_delay
;
879 let this_page = "header.html" in
880 Buffer.add_string
buf (
881 if !!html_mods_theme
<> "" && theme_page_exists this_page then
882 read_theme_page this_page else
883 if !!html_mods
then !!CommonMessages.html_header_mods0
884 else !!CommonMessages.html_header_old
);
886 Buffer.add_string
buf "</head>\n";
887 if open_body
then Buffer.add_string
buf "<body>\n"
889 let html_close_page buf close_body
=
890 if close_body
then Buffer.add_string
buf "</body>\n";
891 Buffer.add_string
buf "</html>\n"
895 http_file_type := UNK
897 let send_preview r file fd
size filename exten
=
898 let (begin_pos
, end_pos) =
900 let (begin_pos
, end_pos) = request_range r
in
901 let end_pos = match end_pos with
903 | Some
end_pos -> end_pos in
904 let range_size = end_pos -- begin_pos
in
905 add_reply_header r
"Content-Length"
906 (Int64.to_string
range_size);
907 add_reply_header r
"Content-Range"
908 (Printf.sprintf
"bytes %Ld-%Ld/%Ld"
909 begin_pos
(end_pos -- one
)
911 r
.reply_head
<- "206 Partial Content";
914 add_reply_header r
"Content-Length"
915 (Int64.to_string
size);
918 let len = String.length exten
in
919 let exten = if len = 0 then exten
920 else String.lowercase
(String.sub
exten 1 (len - 1)) in
921 http_add_bin_stream_header r
(extension_to_file_ext exten);
923 add_reply_header r
"Content-Disposition"
924 (Printf.sprintf
"inline;filename=\"%s\"" (Filename.basename filename
));
925 let s = String.create
200000 in
926 set_max_output_buffer r
.sock (String.length
s);
927 set_rtimeout r
.sock 10000.;
928 let rec stream_file file pos
sock =
929 let max = (max_refill
sock) - 1 in
930 if max > 0 && !pos
< end_pos then
931 let max64 = min
(end_pos -- !pos
) (Int64.of_int
max) in
932 let max = Int64.to_int
max64 in
933 Unix32.read fd
!pos
s 0 max;
934 pos
:= !pos
++ max64;
935 set_lifetime
sock 60.;
936 (* lprintf "HTTPSEND: refill %d %Ld\n" max !pos;*)
937 (* lprintf "HTTPSEND: [%s]\n" (String.escaped
938 (String.sub s 0 max)); *)
940 if output_buffered
sock = 0 then begin
941 (* lprintf "Recursing STREAM\n"; *)
942 stream_file file pos
sock
945 r
.reply_stream
<- Some
(stream_file file
(ref begin_pos
))
948 let http_handler o t r
=
949 CommonInteractive.display_vd
:= false;
950 CommonInteractive.display_bw_stats
:= false;
952 if !Http_server.verbose
&& r
.get_url
.Url.short_file
<> "" then
953 lprintf_nl "received URL %s %s"
954 r
.get_url
.Url.short_file
955 (let b = Buffer.create
100 in
956 List.iter (fun (arg
, value) -> Printf.bprintf
b " %s %s" arg
value) r
.get_url
.Url.args
;
957 if Buffer.contents
b <> "" then Printf.sprintf
"(%s)" (Buffer.contents
b) else "");
959 let user = if r
.options
.login
= "" then (admin_user
()).CommonTypes.user_name
else r
.options
.login
in
960 if not
(valid_password
user r
.options
.passwd
) || (r
.get_url
.Url.short_file
= "logout") then begin
962 http_file_type := TXT
;
963 let _, error_text_long
, header
= Http_server.error_page
"401" "" ""
964 (Ip.to_string
(TcpBufferedSocket.my_ip r
.sock))
965 (string_of_int
!!http_port
) None
in
966 Buffer.add_string
buf error_text_long
;
967 r
.reply_head
<- header
;
969 "Connection", "close";
970 "WWW-Authenticate", Printf.sprintf
"Basic realm=\"%s\"" !!http_realm
]
974 let user = find_ui_user
user in
975 let o = match user.ui_http_conn
with
976 Some oo
-> oo
.conn_buf
<- o.conn_buf
;
977 oo
.conn_info
<- Some
(WEB
, peer_addr t
); oo
978 | None
-> let oo = { o with conn_user
= user;
979 conn_info
= Some
(WEB
, peer_addr t
)} in
980 user.ui_http_conn
<- Some
oo; oo
983 match r
.get_url
.Url.short_file
with
987 http_add_text_header r WML
;
989 (( (float_of_int
!udp_download_rate
) +. (float_of_int
!control_download_rate
)) /. 1024.0) in
991 (( (float_of_int
!udp_upload_rate
) +. (float_of_int
!control_upload_rate
)) /. 1024.0) in
993 <?xml version=\"1.0\"?>
994 <!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\" \"http://www.wapforum.org/DTD/wml_1.1.xml\">
997 <card id=\"main\" title=\"MLDonkey Index Page\"> ";
999 Printf.bprintf
buf "<p align=\"left\">
1001 DL %.1f KB/s (%d|%d) UL: %.1f KB/s (%d|%d)
1003 </p>" dlkbs !udp_download_rate
!control_download_rate
ulkbs !udp_upload_rate
!control_upload_rate
;
1007 List.iter (fun (arg
, value) ->
1010 let num = int_of_string
value in
1011 let file = file_find
num in
1012 file_cancel
file o.conn_user
.ui_user
1014 let num = int_of_string
value in
1015 let file = file_find
num in
1016 file_pause
file o.conn_user
.ui_user
1018 let num = int_of_string
value in
1019 let file = file_find
num in
1020 file_resume
file o.conn_user
.ui_user
1022 ) r
.get_url
.Url.args
;
1025 Printf.bprintf
buf "<p align=\"left\"><small>";
1026 let mfiles = List2.tail_map file_info
!!files
in
1027 List.iter (fun file ->
1028 Printf.bprintf
buf "<a href=\"wap.wml?%s=%d\">%s</a> <a href=\"wap.wml?VDC=%d\">C</a> [%-5d] %5.1f %s %s/%s <br />"
1029 (if downloading
file then "VDP" else "VDR" )
1031 (if downloading
file then "P" else "R" )
1034 (file.file_download_rate
/. 1024.)
1036 (print_human_readable
file (file.file_size
-- file.file_downloaded
))
1037 (print_human_readable
file file.file_size
);
1039 Printf.bprintf
buf "<br />Downloaded %d/%d files " (List.length
!!done_files
) (List.length
!!files
);
1040 Printf.bprintf
buf "</small></p>";
1041 Printf.bprintf
buf "</card></wml>";
1043 | "commands.html" ->
1044 html_open_page buf t r
true;
1045 let this_page = "commands.html" in
1046 Buffer.add_string
buf (
1047 if !!html_mods_theme
<> "" && theme_page_exists this_page then
1048 read_theme_page this_page else
1049 if !!html_mods
then !!CommonMessages.web_common_header_mods0
1050 else !!CommonMessages.web_common_header_old
)
1051 | "multidllink.html" ->
1052 html_open_page buf t r
true;
1053 let this_page = "multidllink.html" in
1054 Buffer.add_string
buf (
1055 if !!html_mods_theme
<> "" && theme_page_exists this_page then
1056 read_theme_page this_page else
1057 if !!html_mods
then !!CommonMessages.multidllink_mods0
1058 else !!CommonMessages.multidllink_old
)
1059 | "" | "index.html" ->
1060 html_open_page buf t r
false;
1061 let this_page = "frames.html" in
1062 if !!html_mods_theme
<> "" && theme_page_exists this_page then
1063 Buffer.add_string
buf (read_theme_page this_page) else
1065 (if !!html_frame_border
then
1067 "<frameset src=\"index\" rows=\"%d,25,*\">
1068 <frame name=\"commands\" noresize scrolling=\"no\" noshade marginwidth=0 marginheight=0 border=0 framespacing=0 src=\"commands.html\">
1069 <frame name=\"fstatus\" noresize scrolling=\"no\" noshade marginwidth=0 marginheight=0 border=0 framespacing=0 src=\"noframe.html\">
1070 <frame name=\"output\" noresize noshade marginwidth=0 marginheight=0 border=0 framespacing=0 src=\"oneframe.html\">
1072 " !!commands_frame_height
1075 "<frameset src=\"index\" rows=\"%d,25,*\" frameborder=\"no\">
1076 <frame name=\"commands\" noresize scrolling=\"no\" noshade marginwidth=0 marginheight=0 border=0 framespacing=0 src=\"commands.html\">
1077 <frame name=\"fstatus\" noresize scrolling=\"no\" noshade marginwidth=0 marginheight=0 border=0 framespacing=0 src=\"noframe.html\">
1078 <frame name=\"output\" noresize noshade marginwidth=0 marginheight=0 border=0 framespacing=0 src=\"oneframe.html\">
1080 " !!commands_frame_height
)
1083 "<frameset src=\"index\" rows=\"%d,2*\">
1084 <frameset src=\"index\" cols=\"5*,1*\">
1085 <frame name=\"commands\" src=\"commands.html\">
1086 <frame name=\"fstatus\" src=\"noframe.html\">
1088 <frame name=\"output\" src=\"oneframe.html\">
1090 " !!commands_frame_height
1091 | "complex_search.html" ->
1092 html_open_page buf t r
true;
1093 CommonSearch.complex_search
buf
1095 html_open_page buf t r
true
1097 | "oneframe.html" ->
1098 html_open_page buf t r
true;
1099 Buffer.add_string
buf (Printf.sprintf
"<br><div align=\"center\"><h3>%s %s</h3></div>"
1100 (Printf.sprintf
(_b
"Welcome to MLDonkey")) Autoconf.current_version
);
1101 if !!motd_html
<> "" then Buffer.add_string
buf !!motd_html
;
1102 if user2_is_admin
o.conn_user
.ui_user
then
1103 (match DriverInteractive.real_startup_message
() with
1104 Some
s -> Buffer.add_string
buf (Printf.sprintf
"<p><pre><b><h3>%s</b></h3></pre>" s);
1107 | "bw_updown.png" ->
1108 (match http_error_no_gd "png" with
1110 G.do_draw_pic
"Traffic" "s(kb)" "t(h:m:s)" download_history upload_history
;
1111 http_send_bin r
buf "bw_updown.png"
1112 | true -> raise Not_found
)
1114 | "bw_updown.jpg" ->
1115 (match http_error_no_gd "jpg" with
1117 G.do_draw_pic
"Traffic" "s(kb)" "t(h:m:s)" download_history upload_history
;
1118 http_send_bin r
buf "bw_updown.jpg"
1119 | true -> raise Not_found
)
1121 | "bw_download.png" ->
1122 (match http_error_no_gd "png" with
1124 G.do_draw_down_pic
"Traffic" "download" "s(kb)" "t(h:m:s)" download_history
;
1125 http_send_bin r
buf "bw_download.png"
1126 | true -> raise Not_found
)
1128 | "bw_download.jpg" ->
1129 (match http_error_no_gd "jpg" with
1131 G.do_draw_down_pic
"Traffic" "download" "s(kb)" "t(h:m:s)" download_history
;
1132 http_send_bin r
buf "bw_download.jpg"
1133 | true -> raise Not_found
)
1135 | "bw_upload.png" ->
1136 (match http_error_no_gd "png" with
1138 G.do_draw_up_pic
"Traffic" "upload" "s(kb)" "t(h:m:s)" upload_history
;
1139 http_send_bin r
buf "bw_upload.png"
1140 | true -> raise Not_found
)
1142 | "bw_upload.jpg" ->
1143 (match http_error_no_gd "jpg" with
1145 G.do_draw_up_pic
"Traffic" "upload" "s(kb)" "t(h:m:s)" upload_history
;
1146 http_send_bin r
buf "bw_upload.jpg"
1147 | true -> raise Not_found
)
1149 | "bw_h_updown.png" ->
1150 (match http_error_no_gd "png" with
1152 G.do_draw_h_pic
"Traffic" "s(kb)" "t(h:m:s)" download_h_history upload_h_history
;
1153 http_send_bin r
buf "bw_h_updown.png"
1154 | true -> raise Not_found
)
1156 | "bw_h_updown.jpg" ->
1157 (match http_error_no_gd "jpg" with
1159 G.do_draw_h_pic
"Traffic" "s(kb)" "t(h:m:s)" download_h_history upload_h_history
;
1160 http_send_bin r
buf "bw_h_updown.jpg"
1161 | true -> raise Not_found
)
1163 | "bw_h_download.png" ->
1164 (match http_error_no_gd "png" with
1166 G.do_draw_down_h_pic
"Traffic" "download" "s(kb)" "t(h:m:s)" download_h_history
;
1167 http_send_bin r
buf "bw_h_download.png"
1168 | true -> raise Not_found
)
1170 | "bw_h_download.jpg" ->
1171 (match http_error_no_gd "jpg" with
1173 G.do_draw_down_h_pic
"Traffic" "download" "s(kb)" "t(h:m:s)" download_h_history
;
1174 http_send_bin r
buf "bw_h_download.jpg"
1175 | true -> raise Not_found
)
1177 | "bw_h_upload.png" ->
1178 (match http_error_no_gd "png" with
1180 G.do_draw_up_h_pic
"Traffic" "upload" "s(kb)" "t(h:m:s)" upload_h_history
;
1181 http_send_bin r
buf "bw_h_upload.png"
1182 | true -> raise Not_found
)
1184 | "bw_h_upload.jpg" ->
1185 (match http_error_no_gd "jpg" with
1187 G.do_draw_up_h_pic
"Traffic" "upload" "s(kb)" "t(h:m:s)" upload_h_history
;
1188 http_send_bin r
buf "bw_h_upload.jpg"
1189 | true -> raise Not_found
)
1192 (match http_error_no_gd "png" with
1194 G.do_draw_tag
!!html_mods_vd_gfx_tag_title download_history upload_history
;
1195 http_send_bin r
buf "tag.png"
1196 | true -> raise Not_found
)
1199 (match http_error_no_gd "jpg" with
1201 G.do_draw_tag
!!html_mods_vd_gfx_tag_title download_history upload_history
;
1202 http_send_bin r
buf "tag.jpg"
1203 | true -> raise Not_found
)
1206 html_open_page buf t r
true;
1207 let b = Buffer.create
10000 in
1208 let filter = ref (fun _ -> ()) in
1210 match r
.get_url
.Url.args
with
1211 ("num", num) :: args
->
1212 List.iter (fun (arg
, value) ->
1215 let old_filter = !filter in
1217 if r
.result_type
= value then raise Not_found
;
1221 let old_filter = !filter in
1223 if r
.result_format
= value then raise Not_found
;
1227 let old_filter = !filter in
1228 let mega5 = Int64.of_int
(5 * 1024 * 1024) in
1229 let mega20 = Int64.of_int
(20 * 1024 * 1024) in
1230 let mega400 = Int64.of_int
(400 * 1024 * 1024) in
1231 let min, max = match value with
1232 "0to5" -> Int64.zero
, mega5
1233 | "5to20" -> mega5, mega20
1234 | "20to400" -> mega20, mega400
1235 | "400+" -> mega400, Int64.max_int
1236 | _ -> Int64.zero
, Int64.max_int
1239 if r
.result_size
>= min &&
1240 r
.result_size
<= max then
1247 let num = int_of_string
num in
1248 let s = search_find
num in
1250 DriverInteractive.print_search
b s
1251 { o with conn_filter
= !filter };
1253 Buffer.add_string
buf (html_escaped
1254 (Buffer.contents
b))
1257 Buffer.add_string
buf "Bad filter"
1261 html_open_page buf t r
true;
1262 let b = Buffer.create
10000 in
1263 List.iter (fun (arg
, value) ->
1267 let num = int_of_string
value in
1268 let r = find_result
num in
1269 let files = result_download
r [] false o.conn_user
.ui_user
in
1270 List.iter CommonInteractive.start_download
files;
1272 let module M
= CommonMessages
in
1273 Gettext.buftext
buf M.download_started
num
1275 Printf.bprintf
buf "Error %s with %s<br>"
1276 (Printexc2.to_string e
) value;
1279 ) r.get_url
.Url.args
;
1280 Buffer.add_string
buf (html_escaped
(Buffer.contents
b))
1284 List.iter (fun (arg
, value) ->
1287 let num = int_of_string
value in
1288 let file = file_find
num in
1289 file_cancel
file o.conn_user
.ui_user
1291 let num = int_of_string
value in
1292 let file = file_find
num in
1293 file_pause
file o.conn_user
.ui_user
1295 let num = int_of_string
value in
1296 let file = file_find
num in
1297 file_resume
file o.conn_user
.ui_user
1299 let num = int_of_string
value in
1300 let file = file_find
num in
1301 set_file_release
file true o.conn_user
.ui_user
1303 let num = int_of_string
value in
1304 let file = file_find
num in
1305 set_file_release
file false o.conn_user
.ui_user
1309 | "Percent" -> o.conn_sortvd
<- ByPercent
1310 | "%" -> o.conn_sortvd
<- ByPercent
1311 | "File" -> o.conn_sortvd
<- ByName
1312 | "Downloaded" -> o.conn_sortvd
<- ByDone
1313 | "DLed" -> o.conn_sortvd
<- ByDone
1314 | "Size" -> o.conn_sortvd
<- BySize
1315 | "Rate" -> o.conn_sortvd
<- ByRate
1316 | "ETA" -> o.conn_sortvd
<- ByETA
1317 | "Priority" -> o.conn_sortvd
<- ByPriority
1318 | "Age" -> o.conn_sortvd
<- ByAge
1319 | "Last" -> o.conn_sortvd
<- ByLast
1320 | "Srcs" -> o.conn_sortvd
<- BySources
1321 | "A" -> o.conn_sortvd
<- ByASources
1322 | "N" -> o.conn_sortvd
<- ByNet
1323 | "Avail" -> o.conn_sortvd
<- ByAvail
1324 | "Cm" -> o.conn_sortvd
<- ByComments
1325 | "User" -> o.conn_sortvd
<- ByUser
1326 | "Group" -> o.conn_sortvd
<- ByGroup
1330 ) r.get_url
.Url.args
;
1331 let b = Buffer.create
10000 in
1333 let list = List2.tail_map file_info
(user2_filter_files
!!files o.conn_user
.ui_user
) in
1334 DriverInteractive.display_file_list
b o list;
1335 html_open_page buf t
r true;
1336 Buffer.add_string
buf (html_escaped
(Buffer.contents
b))
1341 match r.get_url
.Url.args
with
1342 | [ "jvcmd", "multidllink" ; "links", links
] ->
1343 html_open_page buf t
r true;
1344 List.iter (fun url
->
1345 let url = fst
(String2.cut_at
url '
\013'
) in
1348 Buffer.add_string
buf (html_escaped
(dllink_parse
(o.conn_output
= HTML
) url o.conn_user
.ui_user
));
1349 Buffer.add_string
buf (html_escaped
"\\<P\\>")
1351 ) (String2.split links '
\n'
)
1353 | ("q", cmd) :: other_args
->
1354 List.iter (fun arg
->
1356 | "sortby", "size" -> o.conn_sortvd
<- BySize
1357 | "sortby", "name" -> o.conn_sortvd
<- ByName
1358 | "sortby", "rate" -> o.conn_sortvd
<- ByRate
1359 | "sortby", "done" -> o.conn_sortvd
<- ByDone
1360 | "sortby", "percent" -> o.conn_sortvd
<- ByPercent
1361 | "sortby", "priority" -> o.conn_sortvd
<- ByPriority
1365 let b = o.conn_buf
in
1367 eval (ref true) cmd o;
1368 html_escaped
(Buffer.contents
b)
1370 html_open_page buf t
r true;
1372 (* Konqueror doesn't like html within <pre> *)
1373 let drop_pre = ref false in
1374 let rawcmd = ref cmd in
1376 if String.contains
cmd ' '
then
1377 rawcmd := String.sub
cmd 0 (String.index
cmd ' '
);
1380 | "vm" | "vma" | "view_custom_queries" | "xs" | "vr"
1381 | "afr" | "friend_remove" | "reshare" | "recover_temp"
1382 | "c" | "commit" | "bw_stats" | "ovweb" | "friends"
1383 | "message_log" | "friend_add" | "remove_old_servers"
1384 | "downloaders" | "uploaders" | "scan_temp" | "cs"
1385 | "version" | "rename" | "force_download" | "close_fds"
1386 | "vd" | "vo" | "voo" | "upstats" | "shares" | "share"
1387 | "unshare" | "stats" | "users" | "block_list" ->
1390 Printf.bprintf
buf "%s\n"
1391 (if use_html_mods
o && !drop_pre then s else "\n<pre>\n" ^
s ^
"</pre>");
1393 | [ ("custom", query
) ] ->
1394 html_open_page buf t
r true;
1395 CommonSearch.custom_query
buf query
1397 | ("custom", query
) :: args
->
1398 html_open_page buf t
r true;
1399 send_custom_query
o.conn_user
buf query args
1401 | [ "setoption", _ ; "option", name
; "value", value ] ->
1402 html_open_page buf t
r true;
1403 let gui_type, ip
, port
=
1404 match o.conn_info
with
1405 | None
-> None
, None
, None
1406 | Some
(gui_type, (ip
, port
)) -> Some
gui_type, Some ip
, Some port
1408 if user2_is_admin
o.conn_user
.ui_user
then
1410 CommonInteractive.set_fully_qualified_options name
value
1411 ~
user:(Some
o.conn_user
.ui_user
.CommonTypes.user_name
)
1412 ~ip
:ip ~port
:port ~
gui_type:gui_type ();
1413 Buffer.add_string
buf "Option value changed"
1416 Buffer.add_string
buf "You are not allowed to change options"
1419 List.iter (fun (s,v
) ->
1420 lprintf_nl "[%s]=[%s]" (String.escaped
s) (String.escaped v
))
1425 | "preview_download" ->
1428 match r.get_url
.Url.args
with
1430 let file_num = int_of_string
file_num in
1431 let file = file_find
file_num in
1432 let fd = file_fd
file in
1433 let size = file_size
file in
1434 let filename = file_best_name
file in
1435 let exten = Filename2.last_extension
filename in
1436 send_preview r file fd size filename exten
1439 List.iter (fun (s,v
) ->
1440 lprintf_nl "[%s]=[%s]" (String.escaped
s) (String.escaped v
))
1445 | "preview_upload" ->
1448 match r.get_url
.Url.args
with
1450 let file_num = int_of_string
file_num in
1451 let file = shared_find
file_num in
1452 let impl = as_shared_impl
file in
1453 let info = shared_info
file in
1454 let filename = impl.impl_shared_fullname
in
1455 let exten = Filename2.last_extension
impl.impl_shared_codedname
in
1456 if not
(Sys.file_exists
filename) then
1458 lprintf_nl "file %s not found" filename;
1461 let fd = Unix32.create_ro
filename in
1462 let size = info.shared_size
in
1463 send_preview r file fd size filename exten
1466 List.iter (fun (s,v
) ->
1467 lprintf_nl "[%s]=[%s]" (String.escaped
s) (String.escaped v
))
1474 http_add_text_header r CSS
;
1475 let this_page = "h.css" in
1476 Buffer.add_string
buf (
1477 if !!html_mods_theme
<> "" && theme_page_exists this_page then
1478 read_theme_page this_page else
1479 if !!html_mods
then !CommonMessages.html_css_mods
1480 else !!CommonMessages.html_css_old
)
1484 http_add_text_header r CSS
;
1485 let this_page = "dh.css" in
1486 Buffer.add_string
buf (
1487 if !!html_mods_theme
<> "" && theme_page_exists this_page then
1488 read_theme_page this_page else
1489 if !!html_mods
then !CommonMessages.download_html_css_mods
1490 else !!CommonMessages.download_html_css_old
)
1494 http_add_text_header r JAVASCRIPT
;
1495 let this_page = "i.js" in
1496 Buffer.add_string
buf (
1497 if !!html_mods_theme
<> "" && theme_page_exists this_page then
1498 read_theme_page this_page else
1499 if !!html_mods
then !!CommonMessages.html_js_mods0
1500 else !!CommonMessages.html_js_old
)
1504 http_add_text_header r JAVASCRIPT
;
1505 let this_page = "di.js" in
1506 Buffer.add_string
buf (
1507 if !!html_mods_theme
<> "" && theme_page_exists this_page then
1508 read_theme_page this_page else
1509 if !!html_mods
then !!CommonMessages.download_html_js_mods0
1510 else !!CommonMessages.download_html_js_old
)
1511 | s -> http_send_bin_pictures r buf (String.lowercase
s)
1514 let _, error_text_long
, header
= Http_server.error_page
"404" "" ""
1515 (Ip.to_string
(TcpBufferedSocket.my_ip
r.sock))
1516 (string_of_int
!!http_port
)
1517 (Some
(Url_not_found
r.get_url
.Url.full_file
)) in
1518 r.reply_head
<- header
;
1519 Buffer.add_string
buf error_text_long
1521 Printf.bprintf
buf "\nException %s\n" (Printexc2.to_string e
);
1522 r.reply_stream
<- None
1526 match !http_file_type with
1527 HTM
-> html_close_page buf false; dollar_escape o true (Buffer.contents
buf)
1528 | MLHTM
-> html_close_page buf true; dollar_escape o true (Buffer.contents
buf)
1531 | BIN
-> Buffer.contents
buf
1534 if !http_file_type <> BIN
&& !!html_use_gzip
then
1538 let http_options = {
1539 conn_buf
= Buffer.create
10000;
1541 conn_sortvd
= NotSorted
;
1542 conn_filter
= (fun _ -> ());
1543 conn_user
= find_ui_user
CommonUserDb.admin_user_name
;
1544 conn_width
= 80; conn_height
= 0;
1545 conn_info
= Some
(WEB
, (Ip.null
, 0));
1548 let create_http_handler () =
1550 bind_addr
= Ip.to_inet_addr
!!http_bind_addr
;
1553 addrs
= Ip_set.of_list
!!allowed_ips
;
1554 (* do not limit access to MLDonkey web interface by IP blocklist *)
1555 use_ip_block_list
= false;
1557 default
= http_handler http_options;
1559 option_hook allowed_ips
(fun _ ->
1560 config.addrs
<- Ip_set.of_list
!!allowed_ips
);
1561 ignore
(find_port
"http server" !!http_bind_addr http_port
1562 (Http_server.handler
config));
1563 config.port
<- !!http_port