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
107 if String2.check_prefix
cmd "ed2k://" ||
108 String2.check_prefix
cmd "ftp://" ||
109 String2.check_prefix
cmd "http://" then "dllink " ^
cmd
110 else if String2.check_prefix
cmd "fha://" then "ovlink " ^
cmd
112 let l = String2.tokens
cmd in
115 | "longhelp"::subs
| "??"::subs
->
116 let filter cmd = List.for_all
(String2.contains
cmd) subs
in
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 let show (cmd, _
, _
, help
) =
129 let ncmd = ref cmd in (* why? *)
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";
141 (List.sort
(fun (c1
,_
, _
,_
) (c2
,_
, _
,_
) -> compare c1 c2
)
142 (List.filter (fun (c
,_
,_
,_
) -> filter c
) !CommonNetwork.network_commands
));
143 Printf.bprintf
buf "\\</table\\>\\</div\\>";
144 html_mods_table_header
buf "helpTable" "results" [];
145 Printf.bprintf
buf "\\<tr class=\\\"dl-1\\\"\\>";
147 ("", "sr", "< > : required parameter");
148 ("", "sr", "[< >] : optional parameter");
149 ("", "sr", "< 1 | 2 > : alternative parameter"); ];
150 Printf.bprintf
buf "\\</table\\>\\</div\\>\\</div\\>"
153 Buffer.add_string
buf M.available_commands_are
;
154 let list = Hashtbl2.to_list2 commands_by_kind
in
155 let list = List.sort
(fun (s1
,_
) (s2
,_
) -> compare s1 s2
) list in
156 List.iter
(fun (s
,list) ->
157 match List.sort
(fun (s1
,_
) (s2
,_
) -> compare s1 s2
) (List.filter (fun (s
,_
) -> filter s
) !list) with
160 Printf.bprintf
buf "\n $b%s$n:\n" s
;
161 List.iter
(fun (cmd, help
) -> Printf.bprintf
buf "$r%s$n %s\n" cmd help
) list
165 | ["help"] | ["?"] | ["man"] ->
166 let module M
= CommonMessages
in
167 if o
.conn_output
= HTML
then
169 Buffer.add_string
buf "\\<div class=\\\"cs\\\"\\>";
170 html_mods_table_header
buf "helpTable" "results" [];
171 Buffer.add_string
buf "\\<tr\\>";
173 ("", "srh", M.main_commands_are
);
175 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-1\\\"\\>";
177 ("", "sr", "$bServers:$n");
179 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-2\\\"\\>";
181 ("", "sr", "$r\\<a href=\\\"submit?q=vm\\\"\\>" ^
183 ("", "sr", "list connected servers"); ];
184 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-2\\\"\\>";
186 ("", "sr", "$r\\<a href=\\\"submit?q=vma\\\"\\>" ^
188 ("", "sr", "list all servers"); ];
189 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-2\\\"\\>";
191 ("", "sr", "$rc/x <num>$n");
192 ("", "sr", "connect/disconnect from a server"); ];
193 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-1\\\"\\>";
195 ("", "sr", "$bDownloads:$n");
197 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-2\\\"\\>";
199 ("", "sr", "$r\\<a href=\\\"submit?q=vd\\\"\\>" ^
201 ("", "sr", "view current downloads"); ];
202 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-2\\\"\\>";
204 ("", "sr", "$rcancel/pause/resume <num>$n");
205 ("", "sr", "cancel/pause/resume download <num>"); ];
206 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-1\\\"\\>";
208 ("", "sr", "$bSearches:$n");
210 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-2\\\"\\>";
212 ("", "sr", "$rs <keywords>$n");
213 ("", "sr", "start a search for keywords <keywords> on the network"); ];
214 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-2\\\"\\>";
216 ("", "sr", "$r\\<a href=\\\"submit?q=vr\\\"\\>" ^
218 ("", "sr", "view results of the last search"); ];
219 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-2\\\"\\>";
221 ("", "sr", "$rd <num>$n");
222 ("", "sr", "download result number <num>"); ];
223 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-2\\\"\\>";
225 ("", "sr", "$r\\<a href=\\\"submit?q=vs\\\"\\>" ^
227 ("", "sr", "view previous searches"); ];
228 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-2\\\"\\>";
230 ("", "sr", "$rvr <num>$n");
231 ("", "sr", "view results of search <num>"); ];
232 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-1\\\"\\>";
234 ("", "sr", "$bGeneral:$n");
236 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-2\\\"\\>";
238 ("", "sr", "$r\\<a href=\\\"submit?q=save\\\"\\>" ^
240 ("", "sr", "save configuration files"); ];
241 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-2\\\"\\>";
243 ("", "sr", "$rkill$n");
244 ("", "sr", "kill mldonkey properly"); ];
245 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-2\\\"\\>";
248 ("", "sr", "quit this interface"); ];
249 Buffer.add_string
buf "\\</tr\\>\\</table\\>\\</div\\>\n";
250 html_mods_table_header
buf "helpTable" "results" [];
251 Buffer.add_string
buf "\\<tr class=\\\"dl-1\\\"\\>";
253 ("", "sr", "Use '$r\\<a href=\\\"submit?q=longhelp\\\"\\>" ^
254 "longhelp\\</a\\>$n' or '$r\\<a href=\\\"submit?q=longhelp\\\"\\>" ^
255 "??\\</a\\>$n' for all commands. Specify substring to filter."); ];
256 Buffer.add_string
buf "\\</tr\\>\\<tr class=\\\"dl-1\\\"\\>";
258 ("", "sr", "Use '$rhelp command$n' or '$r? command$n' for help on a command."); ];
259 Buffer.add_string
buf "\\</tr\\>\\</table\\>\\</div\\>\\</div\\>\n"
262 Buffer.add_string
buf
266 $rvm$n : list connected servers
267 $rvma$n : list all servers
268 $rc/x <num>$n : connect/disconnect from a server
271 $rvd$n : view current downloads
272 $rcancel/pause/resume <num>$n : cancel/pause/resume download <num>
275 $rs <keywords>$n : start a search for keywords <keywords> on the network
276 $rvr$n : view results of the last search
277 $rd <num>$n : download result number <num>
278 $rvs$n : view previous searches
279 $rvr <num>$n : view results of search <num>
282 $rsave$n : save configuration files
283 $rkill$n : kill mldonkey properly
284 $rq$n : quit this interface
286 Use '$rlonghelp$n' or '$r??$n' for all commands.
287 Use '$rlonghelp str$n' or '$r?? str$n' for all commands that contain specified substring.
288 Use '$rhelp command$n' or '$r? command$n' for help on a command.
290 | "?" :: args
| "help" :: args
| "man" :: args
->
291 List.iter
(fun arg
->
292 match List.filter (fun (cmd, _
, _
, _
) -> cmd = arg
) !CommonNetwork.network_commands
with
293 | [] -> Printf.bprintf
buf "Unknown command : %s\n" arg
294 | l -> List.iter
(fun (_
,_
,_
,help
) -> Printf.bprintf
buf "%s %s\n" arg help
) l)
299 let command = List.assoc one
!!alias_commands
in
300 match String2.split
command ' '
with
301 [] -> raise Not_found
(* can't happen *)
303 | a
::b
-> a
, (b
@ two
)
305 Not_found
-> one
, two
)
308 raise
CommonTypes.CommandCloseSocket
313 [] -> failwith
"Usage: auth <user> <password>"
314 | [s1
] -> (admin_user
()).CommonTypes.user_name
, s1
315 | user :: pass
:: _
-> user, pass
317 if valid_password
user pass
then begin
319 o
.conn_user
<- find_ui_user
user;
320 if not
!verbose_no_login
then lprintf_nl "Authenticated user: %s" user;
321 let module M
= CommonMessages
in
322 Buffer.add_string
buf M.full_access
;
323 (match DriverInteractive.real_startup_message
() with
324 Some s
-> Buffer.add_string
buf ("\n" ^ s
);
327 let module M
= CommonMessages
in
328 Buffer.add_string
buf M.bad_login
331 DriverCommands.execute_command
332 !CommonNetwork.network_commands o
cmd args
334 let module M
= CommonMessages
in
335 Buffer.add_string
buf M.command_not_authorized
338 (* This function is called every hour to check if we have something to do
341 let calendar_options = {
342 conn_buf
= Buffer.create
1000;
344 conn_sortvd
= NotSorted
;
345 conn_filter
= (fun _
-> ());
346 conn_user
= find_ui_user
CommonUserDb.admin_user_name
;
347 conn_width
= 80; conn_height
= 0;
348 conn_info
= Some
(CALENDAR
, (Ip.null
, 0));
351 let check_calendar () =
352 let time = last_time
() in
353 let tm = Unix.localtime
(date_of_int
time) in
354 List.iter
(fun (days
, hours
, command) ->
355 if (List.mem
tm.Unix.tm_wday days
|| days
= []) &&
356 (List.mem
tm.Unix.tm_hour hours
|| hours
= []) then begin
357 lprintf_nl "Calendar execute: %s" command;
358 eval (ref true) command calendar_options;
359 lprintf_nl "Calendar result: %s" (Buffer.contents
calendar_options.conn_buf
);
360 Buffer.reset
calendar_options.conn_buf
;
365 (*************************************************************
369 **************************************************************)
371 let before_telnet_output o sock
=
372 if o
.conn_output
= ANSI
&& o
.conn_height
<> 0 then
373 write_string sock
(Printf.sprintf
375 (Terminal.gotoxy
0 (o
.conn_height
-3))
376 Terminal.ANSI.ansi_CLREOL
377 Terminal.ANSI.ansi_CLREOL
378 (Terminal.gotoxy
0 (o
.conn_height
-3)))
380 let after_telnet_output o sock
=
381 if o
.conn_output
= ANSI
&& o
.conn_height
<> 0 then
382 write_string sock
(Printf.sprintf
"\n\n%s"
383 (Terminal.gotoxy
0 (o
.conn_height
- 2)));
384 if o
.conn_output
= ANSI
then
385 write_string sock
(Printf.sprintf
"%sMLdonkey command-line:%s\n> "
386 Terminal.ANSI.ansi_REVERSE
387 Terminal.ANSI.ansi_NORMAL
)
390 let user_reader o telnet sock nread =
391 let b = TcpBufferedSocket.buf sock in
392 let end_pos = b.pos + b.len in
393 let new_pos = end_pos - nread in
395 let end_pos = b.pos + b.len in
396 for i = b.pos to b.pos + b.len - 1 do
397 let c = int_of_char b.buf.[i] in
398 if c <> 13 && c <> 10 && (c < 32 || c > 127) then
399 lprintf "term[%d] = %d\n" i c;
404 let c = int_of_char c in
405 if c = 13 || c = 10 || c = 0 then
406 let len = i - b.pos in
407 let cmd = String.sub b.buf b.pos len in
408 buf_used sock (len+1);
409 if cmd <> "" then begin
410 before_telnet_output o sock;
411 let buf = o.conn_buf in
413 if o.conn_output = ANSI then Printf.bprintf buf "> $c%s$n\n" cmd;
414 eval telnet.telnet_auth cmd o;
415 Buffer.add_char buf '\n';
416 if o.conn_output = ANSI then Buffer.add_string buf "$n";
417 TcpBufferedSocket.write_string sock
418 (dollar_escape o false (Buffer.contents buf));
419 after_telnet_output o sock;
428 | CommonTypes.CommandCloseSocket ->
430 shutdown sock "user quit";
433 before_telnet_output o sock;
434 TcpBufferedSocket.write_string sock
435 (Printf.sprintf "exception [%s]\n" (Printexc2.to_string e));
436 after_telnet_output o sock
451 telnet_buffer
: Buffer.t
;
452 mutable telnet_iac
: bool;
453 mutable telnet_wait
: int;
454 telnet_auth
: bool ref;
457 let iac_will_8bit = "\255\253\000"
458 let iac_will_naws = "\255\253\031"
460 let user_reader o telnet sock nread
=
461 let b = TcpBufferedSocket.buf sock
in
464 let c = b.buf.[b.pos
] in
466 (* lprintf "char %d\n" (int_of_char c); *)
467 if c = '
\255'
&& not telnet
.telnet_iac
then begin
468 telnet
.telnet_iac
<- true;
471 if c <> '
\255'
&& telnet
.telnet_iac
then begin
472 telnet
.telnet_iac
<- false;
475 Buffer.add_char telnet
.telnet_buffer
c;
476 telnet
.telnet_wait
<- 1
478 Buffer.reset telnet
.telnet_buffer
483 let i = int_of_char
c in
484 telnet
.telnet_iac
<- false;
485 let is_normal_char = i > 31 in
487 if telnet
.telnet_wait
= 1 then begin
488 Buffer.add_char telnet
.telnet_buffer
c;
489 let cmd = Buffer.contents telnet
.telnet_buffer
in
490 telnet
.telnet_wait
<- 0;
491 let len = String.length
cmd in
495 Buffer.reset telnet
.telnet_buffer
497 telnet
.telnet_wait
<- 4
500 lprintf "telnet server: Unknown control sequence %s\n"
501 (String.escaped cmd); *)
502 Buffer.reset telnet
.telnet_buffer
504 let s = String.sub
cmd 0 2 in
505 Buffer.reset telnet
.telnet_buffer
;
508 let dx = BigEndian.get_int16
cmd 2 in
509 let dy = BigEndian.get_int16
cmd 4 in
512 (* lprintf "SIZE RECEIVED %d x %d\n" dx dy; *)
515 lprintf "telnet server: Unknown control sequence %s\n"
516 (String.escaped cmd); *)
519 if telnet
.telnet_wait
> 1 then begin
520 Buffer.add_char telnet
.telnet_buffer
c;
521 telnet
.telnet_wait
<- telnet
.telnet_wait
- 1;
523 if is_normal_char then
524 Buffer.add_char telnet
.telnet_buffer
c
526 (* evaluate the command *)
527 let cmd = Buffer.contents telnet
.telnet_buffer
in
528 Buffer.reset telnet
.telnet_buffer
;
529 if cmd <> "" then begin
530 before_telnet_output o sock
;
531 let buf = o
.conn_buf
in
533 if o
.conn_output
= ANSI
then Printf.bprintf
buf "> $c%s$n\n" cmd;
534 eval telnet
.telnet_auth
cmd o
;
535 Buffer.add_char
buf '
\n'
;
536 if o
.conn_output
= ANSI
then Buffer.add_string
buf "$n";
537 TcpBufferedSocket.write_string sock
538 (dollar_escape o
false (Buffer.contents
buf));
539 after_telnet_output o sock
;
541 if i = 255 then telnet
.telnet_wait
<- 2;
548 | CommonTypes.CommandCloseSocket
->
550 shutdown sock Closed_by_user
;
553 before_telnet_output o sock
;
554 TcpBufferedSocket.write_string sock
555 (Printf.sprintf
"exception [%s]\n" (Printexc2.to_string e
));
556 after_telnet_output o sock
559 let user_closed sock msg
=
560 user_socks
:= List2.removeq sock
!user_socks
;
563 let telnet_handler t event
=
565 TcpServerSocket.CONNECTION
(s, Unix.ADDR_INET
(from_ip
, from_port
)) ->
566 let from_ip = Ip.of_inet_addr
from_ip in
567 if not
!verbose_no_login
then lprintf_nl "Telnet connection from %s" (Ip.to_string
from_ip);
568 let token = create_token unlimited_connection_manager
in
569 let sock = TcpBufferedSocket.create_simple
token
573 telnet_auth
= ref (has_empty_password
(admin_user
()));
576 telnet_buffer
= Buffer.create
100;
579 conn_buf
= Buffer.create
1000;
580 conn_output
= (if !!term_ansi
then ANSI
else TEXT
);
581 conn_sortvd
= NotSorted
;
582 conn_filter
= (fun _
-> ());
583 conn_user
= find_ui_user
CommonUserDb.admin_user_name
;
586 conn_info
= Some
(TELNET
, (from_ip, from_port
));
588 (match Ip_set.match_ip
!allowed_ips_set
from_ip with
590 TcpBufferedSocket.prevent_close
sock;
591 TcpBufferedSocket.set_max_output_buffer
sock !!interface_buffer
;
592 TcpBufferedSocket.set_reader
sock (user_reader o telnet);
593 TcpBufferedSocket.set_closer
sock user_closed;
594 user_socks
:= sock :: !user_socks
;
596 TcpBufferedSocket.write_string
sock iac_will_8bit;
597 TcpBufferedSocket.write_string
sock iac_will_naws;
599 before_telnet_output o sock;
600 TcpBufferedSocket.write_string
sock
601 (Printf.sprintf
"Welcome to MLDonkey %s\n" Autoconf.current_version
);
603 TcpBufferedSocket.write_string
sock (dollar_escape o false
604 "$cWelcome on mldonkey command-line$n\n\nUse $r?$n for help\n\n");
606 after_telnet_output o sock
609 before_telnet_output o sock;
611 Printf.sprintf
"Telnet connection from %s rejected (see allowed_ips setting)\n"
612 (Ip.to_string
from_ip)
614 TcpBufferedSocket.write_string
sock (dollar_escape o false reject_message);
615 shutdown
sock Closed_connect_failed
;
616 if not
!verbose_no_login
then lprintf_n "%s" reject_message;
621 (*************************************************************
625 **************************************************************)
629 let buf = Buffer.create
1000
662 let http_file_type = ref UNK
664 let extension_to_file_ext extension
=
702 let ext_to_file_type ext
=
727 let ext_to_mime_type ext
=
730 | BINARY
-> "application/octet-stream"
732 | HTMLS
-> "text/html"
733 | ICON
-> "image/x-icon"
734 | JAVASCRIPT
-> "text/javascript"
735 | JPEG
-> "image/jpg"
736 | MPEG
-> "video/mpeg"
737 | AVI
-> "video/x-msvideo"
738 | WMV
-> "video/x-ms-wmv"
739 | ASF
-> "video/x-ms-asf"
740 | MOV
-> "video/quicktime"
741 | OGM
-> "application/ogg" (* is that correct ? *)
742 | RM
-> "audio/x-pn-realaudio"
743 | MKV
-> "video/x-matroska" (* is that correct ? *)
746 | MP3
-> "audio/mpeg"
747 | WMA
-> "audio/x-ms-wma"
748 | OGG
-> "application/ogg" (* is that correct ? *)
749 | TEXTS
-> "text/plain"
750 | WML
-> "text/vnd.wap.wml"
752 let default_charset = "charset=UTF-8"
754 let get_theme_page page
=
755 let theme = Filename.concat html_themes_dir
!!html_mods_theme
in
756 let fname = Filename.concat
theme page
in fname
758 let theme_page_exists page
=
759 Sys.file_exists
(get_theme_page page
)
761 (* if files are small really_input should be okay *)
762 let read_theme_page page
=
763 let theme_page = get_theme_page page
in
764 Unix2.tryopen_read
theme_page (fun file
->
765 let size = (Unix.stat
theme_page).Unix.st_size
in
766 let s = String.make
size ' '
in
767 really_input file
s 0 size;
770 let http_add_gen_header r
=
771 add_reply_header r
"Server" ("MLdonkey/"^
Autoconf.current_version
);
772 add_reply_header r
"Connection" "close"
774 let add_gzip_headers r
=
775 if !!html_use_gzip
then begin
776 add_reply_header r
"Content-Encoding" "gzip";
777 add_reply_header r
"Vary" "Accept-Encoding";
780 let http_add_html_header r
=
781 let ext = extension_to_file_ext "html" in
782 http_file_type := ext_to_file_type ext;
783 http_add_gen_header r
;
784 add_reply_header r
"Pragma" "no-cache";
785 add_reply_header r
"Content-Type" ((ext_to_mime_type ext) ^
";" ^
default_charset);
788 let http_add_text_header r
ext =
789 http_file_type := ext_to_file_type ext;
790 http_add_gen_header r
;
791 add_reply_header r
"Content-Type" ((ext_to_mime_type ext) ^
";" ^
default_charset);
794 let http_add_bin_info_header r clen
=
795 add_reply_header r
"Accept-Ranges" "bytes";
796 add_reply_header r
"Content-Length" (Printf.sprintf
"%d" clen
)
797 (* FIXME Content-Length is duplicated *)
799 let http_add_bin_header r
ext clen
=
800 http_file_type := ext_to_file_type ext;
801 http_add_gen_header r
;
802 add_reply_header r
"Content-Type" (ext_to_mime_type ext);
803 http_add_bin_info_header r clen
805 let http_add_bin_stream_header r
ext =
806 http_file_type := BIN
;
807 http_add_gen_header r
;
808 let mime_type = ext_to_mime_type ext in
809 let mime_type = if mime_type <> "" then mime_type
810 else "application/binary" in
811 add_reply_header r
"Content-Type" mime_type;
812 add_reply_header r
"Accept-Ranges" "bytes"
814 let http_send_bin r
buf filename
=
816 if theme_page_exists filename
then
817 File.to_string
(get_theme_page filename
)
820 File.to_string filename
821 with _
-> raise Not_found
823 let ext = extension_to_file_ext (Filename2.last_extension2 filename
) in
824 http_add_bin_header r
ext (String.length
file_to_send);
825 add_reply_header r
"Cache-Control" "no-cache";
826 add_reply_header r
"Pragma" "no-cache";
827 Buffer.add_string
buf file_to_send
829 let http_send_bin_pictures r
buf filename
=
832 Hashtbl.find
CommonPictures.files filename
835 if String.sub filename
0 4 = "flag" then
836 Hashtbl.find
CommonPictures.files
"flag_--.png"
839 with _
-> raise Not_found
841 let ext = extension_to_file_ext (Filename2.last_extension2 filename
) in
842 http_add_bin_header r
ext (String.length
file_to_send);
843 Buffer.add_string
buf file_to_send
845 let http_error_no_gd img_type
=
848 (match Autoconf.has_gd_jpg
with
850 | false -> lprintf_nl "Warning: GD jpg support disabled"; true)
852 (match Autoconf.has_gd_png
with
854 | false -> lprintf_nl "Warning: GD png support disabled"; true)
856 (match Autoconf.has_gd
with
858 | false -> lprintf_nl "Warning: GD support disabled"; true)
859 let any_ip = Ip.of_inet_addr
Unix.inet_addr_any
861 let html_open_page buf t r open_body
=
863 http_add_html_header r
;
865 if not
!!html_mods
then
866 (Buffer.add_string
buf
867 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\"
868 \"http://www.w3.org/TR/html4/frameset.dtd\">\n<HTML>\n<HEAD>\n";)
869 else Buffer.add_string
buf "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n";
870 if !CommonInteractive.display_vd
then begin
871 let this_page = "dheader.html" in
872 Buffer.add_string
buf
874 if !!html_mods_theme
<> "" && theme_page_exists this_page then
875 read_theme_page this_page else
876 if !!html_mods
then !!CommonMessages.download_html_header_mods0
877 else !!CommonMessages.download_html_header_old
);
878 Printf.bprintf
buf "<meta http-equiv=\"refresh\" content=\"%d\">" !!vd_reload_delay
;
880 if !CommonInteractive.display_bw_stats
then
881 Printf.bprintf
buf "<meta http-equiv=\"refresh\" content=\"%d\">" !!html_mods_bw_refresh_delay
;
883 let this_page = "header.html" in
884 Buffer.add_string
buf (
885 if !!html_mods_theme
<> "" && theme_page_exists this_page then
886 read_theme_page this_page else
887 if !!html_mods
then !!CommonMessages.html_header_mods0
888 else !!CommonMessages.html_header_old
);
890 Buffer.add_string
buf "</head>\n";
891 if open_body
then Buffer.add_string
buf "<body>\n"
893 let html_close_page buf close_body
=
894 if close_body
then Buffer.add_string
buf "</body>\n";
895 Buffer.add_string
buf "</html>\n"
899 http_file_type := UNK
901 let send_preview r file fd
size filename exten
=
902 let (begin_pos
, end_pos) =
904 let (begin_pos
, end_pos) = request_range r
in
905 let end_pos = match end_pos with
907 | Some
end_pos -> end_pos in
908 let range_size = end_pos -- begin_pos
in
909 add_reply_header r
"Content-Length"
910 (Int64.to_string
range_size);
911 add_reply_header r
"Content-Range"
912 (Printf.sprintf
"bytes %Ld-%Ld/%Ld"
913 begin_pos
(end_pos -- one
)
915 r
.reply_head
<- "206 Partial Content";
918 add_reply_header r
"Content-Length"
919 (Int64.to_string
size);
922 let len = String.length exten
in
923 let exten = if len = 0 then exten
924 else String.lowercase
(String.sub
exten 1 (len - 1)) in
925 http_add_bin_stream_header r
(extension_to_file_ext exten);
927 add_reply_header r
"Content-Disposition"
928 (Printf.sprintf
"inline;filename=\"%s\"" (Filename.basename filename
));
929 let s = String.create
200000 in
930 set_max_output_buffer r
.sock (String.length
s);
931 set_rtimeout r
.sock 10000.;
932 let rec stream_file file pos
sock =
933 let max = (max_refill
sock) - 1 in
934 if max > 0 && !pos
< end_pos then
935 let max64 = min
(end_pos -- !pos
) (Int64.of_int
max) in
936 let max = Int64.to_int
max64 in
937 Unix32.read fd
!pos
s 0 max;
938 pos
:= !pos
++ max64;
939 set_lifetime
sock 60.;
940 (* lprintf "HTTPSEND: refill %d %Ld\n" max !pos;*)
941 (* lprintf "HTTPSEND: [%s]\n" (String.escaped
942 (String.sub s 0 max)); *)
944 if output_buffered
sock = 0 then begin
945 (* lprintf "Recursing STREAM\n"; *)
946 stream_file file pos
sock
949 r
.reply_stream
<- Some
(stream_file file
(ref begin_pos
))
952 let http_handler o t r
=
953 CommonInteractive.display_vd
:= false;
954 CommonInteractive.display_bw_stats
:= false;
956 if !Http_server.verbose
&& r
.get_url
.Url.short_file
<> "" then
957 lprintf_nl "received URL %s %s"
958 r
.get_url
.Url.short_file
959 (let b = Buffer.create
100 in
960 List.iter (fun (arg
, value) -> Printf.bprintf
b " %s %s" arg
value) r
.get_url
.Url.args
;
961 if Buffer.contents
b <> "" then Printf.sprintf
"(%s)" (Buffer.contents
b) else "");
963 let user = if r
.options
.login
= "" then (admin_user
()).CommonTypes.user_name
else r
.options
.login
in
964 if not
(valid_password
user r
.options
.passwd
) || (r
.get_url
.Url.short_file
= "logout") then begin
966 http_file_type := TXT
;
967 let _, error_text_long
, header
= Http_server.error_page
"401" "" ""
968 (Ip.to_string
(TcpBufferedSocket.my_ip r
.sock))
969 (string_of_int
!!http_port
) None
in
970 Buffer.add_string
buf error_text_long
;
971 r
.reply_head
<- header
;
973 "Connection", "close";
974 "WWW-Authenticate", Printf.sprintf
"Basic realm=\"%s\"" !!http_realm
]
978 let user = find_ui_user
user in
979 let o = match user.ui_http_conn
with
980 Some oo
-> oo
.conn_buf
<- o.conn_buf
;
981 oo
.conn_info
<- Some
(WEB
, peer_addr t
); oo
982 | None
-> let oo = { o with conn_user
= user;
983 conn_info
= Some
(WEB
, peer_addr t
)} in
984 user.ui_http_conn
<- Some
oo; oo
987 match r
.get_url
.Url.short_file
with
991 http_add_text_header r WML
;
993 (( (float_of_int
!udp_download_rate
) +. (float_of_int
!control_download_rate
)) /. 1024.0) in
995 (( (float_of_int
!udp_upload_rate
) +. (float_of_int
!control_upload_rate
)) /. 1024.0) in
997 <?xml version=\"1.0\"?>
998 <!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\" \"http://www.wapforum.org/DTD/wml_1.1.xml\">
1001 <card id=\"main\" title=\"MLDonkey Index Page\"> ";
1003 Printf.bprintf
buf "<p align=\"left\">
1005 DL %.1f KB/s (%d|%d) UL: %.1f KB/s (%d|%d)
1007 </p>" dlkbs !udp_download_rate
!control_download_rate
ulkbs !udp_upload_rate
!control_upload_rate
;
1011 List.iter (fun (arg
, value) ->
1014 let num = int_of_string
value in
1015 let file = file_find
num in
1016 file_cancel
file o.conn_user
.ui_user
1018 let num = int_of_string
value in
1019 let file = file_find
num in
1020 file_pause
file o.conn_user
.ui_user
1022 let num = int_of_string
value in
1023 let file = file_find
num in
1024 file_resume
file o.conn_user
.ui_user
1026 ) r
.get_url
.Url.args
;
1029 Printf.bprintf
buf "<p align=\"left\"><small>";
1030 let mfiles = List2.tail_map file_info
!!files
in
1031 List.iter (fun file ->
1032 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 />"
1033 (if downloading
file then "VDP" else "VDR" )
1035 (if downloading
file then "P" else "R" )
1038 (file.file_download_rate
/. 1024.)
1040 (print_human_readable
file (file.file_size
-- file.file_downloaded
))
1041 (print_human_readable
file file.file_size
);
1043 Printf.bprintf
buf "<br />Downloaded %d/%d files " (List.length
!!done_files
) (List.length
!!files
);
1044 Printf.bprintf
buf "</small></p>";
1045 Printf.bprintf
buf "</card></wml>";
1047 | "commands.html" ->
1048 html_open_page buf t r
true;
1049 let this_page = "commands.html" in
1050 Buffer.add_string
buf (
1051 if !!html_mods_theme
<> "" && theme_page_exists this_page then
1052 read_theme_page this_page else
1053 if !!html_mods
then !!CommonMessages.web_common_header_mods0
1054 else !!CommonMessages.web_common_header_old
)
1055 | "multidllink.html" ->
1056 html_open_page buf t r
true;
1057 let this_page = "multidllink.html" in
1058 Buffer.add_string
buf (
1059 if !!html_mods_theme
<> "" && theme_page_exists this_page then
1060 read_theme_page this_page else
1061 if !!html_mods
then !!CommonMessages.multidllink_mods0
1062 else !!CommonMessages.multidllink_old
)
1063 | "" | "index.html" ->
1064 html_open_page buf t r
false;
1065 let this_page = "frames.html" in
1066 if !!html_mods_theme
<> "" && theme_page_exists this_page then
1067 Buffer.add_string
buf (read_theme_page this_page) else
1069 (if !!html_frame_border
then
1071 "<frameset src=\"index\" rows=\"%d,25,*\">
1072 <frame name=\"commands\" noresize scrolling=\"no\" noshade marginwidth=0 marginheight=0 border=0 framespacing=0 src=\"commands.html\">
1073 <frame name=\"fstatus\" noresize scrolling=\"no\" noshade marginwidth=0 marginheight=0 border=0 framespacing=0 src=\"noframe.html\">
1074 <frame name=\"output\" noresize noshade marginwidth=0 marginheight=0 border=0 framespacing=0 src=\"oneframe.html\">
1076 " !!commands_frame_height
1079 "<frameset src=\"index\" rows=\"%d,25,*\" frameborder=\"no\">
1080 <frame name=\"commands\" noresize scrolling=\"no\" noshade marginwidth=0 marginheight=0 border=0 framespacing=0 src=\"commands.html\">
1081 <frame name=\"fstatus\" noresize scrolling=\"no\" noshade marginwidth=0 marginheight=0 border=0 framespacing=0 src=\"noframe.html\">
1082 <frame name=\"output\" noresize noshade marginwidth=0 marginheight=0 border=0 framespacing=0 src=\"oneframe.html\">
1084 " !!commands_frame_height
)
1087 "<frameset src=\"index\" rows=\"%d,2*\">
1088 <frameset src=\"index\" cols=\"5*,1*\">
1089 <frame name=\"commands\" src=\"commands.html\">
1090 <frame name=\"fstatus\" src=\"noframe.html\">
1092 <frame name=\"output\" src=\"oneframe.html\">
1094 " !!commands_frame_height
1095 | "complex_search.html" ->
1096 html_open_page buf t r
true;
1097 CommonSearch.complex_search
buf
1099 html_open_page buf t r
true
1101 | "oneframe.html" ->
1102 html_open_page buf t r
true;
1103 Buffer.add_string
buf (Printf.sprintf
"<br><div align=\"center\"><h3>%s %s</h3></div>"
1104 (Printf.sprintf
(_b
"Welcome to MLDonkey")) Autoconf.current_version
);
1105 if !!motd_html
<> "" then Buffer.add_string
buf !!motd_html
;
1106 if user2_is_admin
o.conn_user
.ui_user
then
1107 (match DriverInteractive.real_startup_message
() with
1108 Some
s -> Buffer.add_string
buf (Printf.sprintf
"<p><pre><b><h3>%s</b></h3></pre>" s);
1111 | "bw_updown.png" ->
1112 (match http_error_no_gd "png" with
1114 G.do_draw_pic
"Traffic" "s(kb)" "t(h:m:s)" download_history upload_history
;
1115 http_send_bin r
buf "bw_updown.png"
1116 | true -> raise Not_found
)
1118 | "bw_updown.jpg" ->
1119 (match http_error_no_gd "jpg" with
1121 G.do_draw_pic
"Traffic" "s(kb)" "t(h:m:s)" download_history upload_history
;
1122 http_send_bin r
buf "bw_updown.jpg"
1123 | true -> raise Not_found
)
1125 | "bw_download.png" ->
1126 (match http_error_no_gd "png" with
1128 G.do_draw_down_pic
"Traffic" "download" "s(kb)" "t(h:m:s)" download_history
;
1129 http_send_bin r
buf "bw_download.png"
1130 | true -> raise Not_found
)
1132 | "bw_download.jpg" ->
1133 (match http_error_no_gd "jpg" with
1135 G.do_draw_down_pic
"Traffic" "download" "s(kb)" "t(h:m:s)" download_history
;
1136 http_send_bin r
buf "bw_download.jpg"
1137 | true -> raise Not_found
)
1139 | "bw_upload.png" ->
1140 (match http_error_no_gd "png" with
1142 G.do_draw_up_pic
"Traffic" "upload" "s(kb)" "t(h:m:s)" upload_history
;
1143 http_send_bin r
buf "bw_upload.png"
1144 | true -> raise Not_found
)
1146 | "bw_upload.jpg" ->
1147 (match http_error_no_gd "jpg" with
1149 G.do_draw_up_pic
"Traffic" "upload" "s(kb)" "t(h:m:s)" upload_history
;
1150 http_send_bin r
buf "bw_upload.jpg"
1151 | true -> raise Not_found
)
1153 | "bw_h_updown.png" ->
1154 (match http_error_no_gd "png" with
1156 G.do_draw_h_pic
"Traffic" "s(kb)" "t(h:m:s)" download_h_history upload_h_history
;
1157 http_send_bin r
buf "bw_h_updown.png"
1158 | true -> raise Not_found
)
1160 | "bw_h_updown.jpg" ->
1161 (match http_error_no_gd "jpg" with
1163 G.do_draw_h_pic
"Traffic" "s(kb)" "t(h:m:s)" download_h_history upload_h_history
;
1164 http_send_bin r
buf "bw_h_updown.jpg"
1165 | true -> raise Not_found
)
1167 | "bw_h_download.png" ->
1168 (match http_error_no_gd "png" with
1170 G.do_draw_down_h_pic
"Traffic" "download" "s(kb)" "t(h:m:s)" download_h_history
;
1171 http_send_bin r
buf "bw_h_download.png"
1172 | true -> raise Not_found
)
1174 | "bw_h_download.jpg" ->
1175 (match http_error_no_gd "jpg" with
1177 G.do_draw_down_h_pic
"Traffic" "download" "s(kb)" "t(h:m:s)" download_h_history
;
1178 http_send_bin r
buf "bw_h_download.jpg"
1179 | true -> raise Not_found
)
1181 | "bw_h_upload.png" ->
1182 (match http_error_no_gd "png" with
1184 G.do_draw_up_h_pic
"Traffic" "upload" "s(kb)" "t(h:m:s)" upload_h_history
;
1185 http_send_bin r
buf "bw_h_upload.png"
1186 | true -> raise Not_found
)
1188 | "bw_h_upload.jpg" ->
1189 (match http_error_no_gd "jpg" with
1191 G.do_draw_up_h_pic
"Traffic" "upload" "s(kb)" "t(h:m:s)" upload_h_history
;
1192 http_send_bin r
buf "bw_h_upload.jpg"
1193 | true -> raise Not_found
)
1196 (match http_error_no_gd "png" with
1198 G.do_draw_tag
!!html_mods_vd_gfx_tag_title download_history upload_history
;
1199 http_send_bin r
buf "tag.png"
1200 | true -> raise Not_found
)
1203 (match http_error_no_gd "jpg" with
1205 G.do_draw_tag
!!html_mods_vd_gfx_tag_title download_history upload_history
;
1206 http_send_bin r
buf "tag.jpg"
1207 | true -> raise Not_found
)
1210 html_open_page buf t r
true;
1211 let b = Buffer.create
10000 in
1212 let filter = ref (fun _ -> ()) in
1214 match r
.get_url
.Url.args
with
1215 ("num", num) :: args
->
1216 List.iter (fun (arg
, value) ->
1219 let old_filter = !filter in
1221 if r
.result_type
= value then raise Not_found
;
1225 let old_filter = !filter in
1227 if r
.result_format
= value then raise Not_found
;
1231 let old_filter = !filter in
1232 let mega5 = Int64.of_int
(5 * 1024 * 1024) in
1233 let mega20 = Int64.of_int
(20 * 1024 * 1024) in
1234 let mega400 = Int64.of_int
(400 * 1024 * 1024) in
1235 let min, max = match value with
1236 "0to5" -> Int64.zero
, mega5
1237 | "5to20" -> mega5, mega20
1238 | "20to400" -> mega20, mega400
1239 | "400+" -> mega400, Int64.max_int
1240 | _ -> Int64.zero
, Int64.max_int
1243 if r
.result_size
>= min &&
1244 r
.result_size
<= max then
1251 let num = int_of_string
num in
1252 let s = search_find
num in
1254 DriverInteractive.print_search
b s
1255 { o with conn_filter
= !filter };
1257 Buffer.add_string
buf (html_escaped
1258 (Buffer.contents
b))
1261 Buffer.add_string
buf "Bad filter"
1265 html_open_page buf t r
true;
1266 let b = Buffer.create
10000 in
1267 List.iter (fun (arg
, value) ->
1271 let num = int_of_string
value in
1272 let r = find_result
num in
1273 let files = result_download
r [] false o.conn_user
.ui_user
in
1274 List.iter CommonInteractive.start_download
files;
1276 let module M
= CommonMessages
in
1277 Gettext.buftext
buf M.download_started
num
1279 Printf.bprintf
buf "Error %s with %s<br>"
1280 (Printexc2.to_string e
) value;
1283 ) r.get_url
.Url.args
;
1284 Buffer.add_string
buf (html_escaped
(Buffer.contents
b))
1288 List.iter (fun (arg
, value) ->
1291 let num = int_of_string
value in
1292 let file = file_find
num in
1293 file_cancel
file o.conn_user
.ui_user
1295 let num = int_of_string
value in
1296 let file = file_find
num in
1297 file_pause
file o.conn_user
.ui_user
1299 let num = int_of_string
value in
1300 let file = file_find
num in
1301 file_resume
file 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 true o.conn_user
.ui_user
1307 let num = int_of_string
value in
1308 let file = file_find
num in
1309 set_file_release
file false o.conn_user
.ui_user
1313 | "Percent" -> o.conn_sortvd
<- ByPercent
1314 | "%" -> o.conn_sortvd
<- ByPercent
1315 | "File" -> o.conn_sortvd
<- ByName
1316 | "Downloaded" -> o.conn_sortvd
<- ByDone
1317 | "DLed" -> o.conn_sortvd
<- ByDone
1318 | "Size" -> o.conn_sortvd
<- BySize
1319 | "Rate" -> o.conn_sortvd
<- ByRate
1320 | "ETA" -> o.conn_sortvd
<- ByETA
1321 | "Priority" -> o.conn_sortvd
<- ByPriority
1322 | "Age" -> o.conn_sortvd
<- ByAge
1323 | "Last" -> o.conn_sortvd
<- ByLast
1324 | "Srcs" -> o.conn_sortvd
<- BySources
1325 | "A" -> o.conn_sortvd
<- ByASources
1326 | "N" -> o.conn_sortvd
<- ByNet
1327 | "Avail" -> o.conn_sortvd
<- ByAvail
1328 | "Cm" -> o.conn_sortvd
<- ByComments
1329 | "User" -> o.conn_sortvd
<- ByUser
1330 | "Group" -> o.conn_sortvd
<- ByGroup
1334 ) r.get_url
.Url.args
;
1335 let b = Buffer.create
10000 in
1337 let list = List2.tail_map file_info
(user2_filter_files
!!files o.conn_user
.ui_user
) in
1338 DriverInteractive.display_file_list
b o list;
1339 html_open_page buf t
r true;
1340 Buffer.add_string
buf (html_escaped
(Buffer.contents
b))
1345 match r.get_url
.Url.args
with
1346 | [ "jvcmd", "multidllink" ; "links", links
] ->
1347 html_open_page buf t
r true;
1348 List.iter (fun url
->
1349 let url = fst
(String2.cut_at
url '
\013'
) in
1352 Buffer.add_string
buf (html_escaped
(dllink_parse
(o.conn_output
= HTML
) url o.conn_user
.ui_user
));
1353 Buffer.add_string
buf (html_escaped
"\\<P\\>")
1355 ) (String2.split links '
\n'
)
1357 | ("q", cmd) :: other_args
->
1358 List.iter (fun arg
->
1360 | "sortby", "size" -> o.conn_sortvd
<- BySize
1361 | "sortby", "name" -> o.conn_sortvd
<- ByName
1362 | "sortby", "rate" -> o.conn_sortvd
<- ByRate
1363 | "sortby", "done" -> o.conn_sortvd
<- ByDone
1364 | "sortby", "percent" -> o.conn_sortvd
<- ByPercent
1365 | "sortby", "priority" -> o.conn_sortvd
<- ByPriority
1369 let b = o.conn_buf
in
1371 eval (ref true) cmd o;
1372 html_escaped
(Buffer.contents
b)
1374 html_open_page buf t
r true;
1376 (* Konqueror doesn't like html within <pre> *)
1377 let drop_pre = ref false in
1378 let rawcmd = ref cmd in
1380 if String.contains
cmd ' '
then
1381 rawcmd := String.sub
cmd 0 (String.index
cmd ' '
);
1384 | "vm" | "vma" | "view_custom_queries" | "xs" | "vr"
1385 | "afr" | "friend_remove" | "reshare" | "recover_temp"
1386 | "c" | "commit" | "bw_stats" | "ovweb" | "friends"
1387 | "message_log" | "friend_add" | "remove_old_servers"
1388 | "downloaders" | "uploaders" | "scan_temp" | "cs"
1389 | "version" | "rename" | "force_download" | "close_fds"
1390 | "vd" | "vo" | "voo" | "upstats" | "shares" | "share"
1391 | "unshare" | "stats" | "users" | "block_list" ->
1394 Printf.bprintf
buf "%s\n"
1395 (if use_html_mods
o && !drop_pre then s else "\n<pre>\n" ^
s ^
"</pre>");
1397 | [ ("custom", query
) ] ->
1398 html_open_page buf t
r true;
1399 CommonSearch.custom_query
buf query
1401 | ("custom", query
) :: args
->
1402 html_open_page buf t
r true;
1403 send_custom_query
o.conn_user
buf query args
1405 | [ "setoption", _ ; "option", name
; "value", value ] ->
1406 html_open_page buf t
r true;
1407 let gui_type, ip
, port
=
1408 match o.conn_info
with
1409 | None
-> None
, None
, None
1410 | Some
(gui_type, (ip
, port
)) -> Some
gui_type, Some ip
, Some port
1412 if user2_is_admin
o.conn_user
.ui_user
then
1414 CommonInteractive.set_fully_qualified_options name
value
1415 ~
user:(Some
o.conn_user
.ui_user
.CommonTypes.user_name
)
1416 ~ip
:ip ~port
:port ~
gui_type:gui_type ();
1417 Buffer.add_string
buf "Option value changed"
1420 Buffer.add_string
buf "You are not allowed to change options"
1423 List.iter (fun (s,v
) ->
1424 lprintf_nl "[%s]=[%s]" (String.escaped
s) (String.escaped v
))
1429 | "preview_download" ->
1432 match r.get_url
.Url.args
with
1434 let file_num = int_of_string
file_num in
1435 let file = file_find
file_num in
1436 let fd = file_fd
file in
1437 let size = file_size
file in
1438 let filename = file_best_name
file in
1439 let exten = Filename2.last_extension
filename in
1440 send_preview r file fd size filename exten
1443 List.iter (fun (s,v
) ->
1444 lprintf_nl "[%s]=[%s]" (String.escaped
s) (String.escaped v
))
1449 | "preview_upload" ->
1452 match r.get_url
.Url.args
with
1454 let file_num = int_of_string
file_num in
1455 let file = shared_find
file_num in
1456 let impl = as_shared_impl
file in
1457 let info = shared_info
file in
1458 let filename = impl.impl_shared_fullname
in
1459 let exten = Filename2.last_extension
impl.impl_shared_codedname
in
1460 if not
(Sys.file_exists
filename) then
1462 lprintf_nl "file %s not found" filename;
1465 let fd = Unix32.create_ro
filename in
1466 let size = info.shared_size
in
1467 send_preview r file fd size filename exten
1470 List.iter (fun (s,v
) ->
1471 lprintf_nl "[%s]=[%s]" (String.escaped
s) (String.escaped v
))
1478 http_add_text_header r CSS
;
1479 let this_page = "h.css" in
1480 Buffer.add_string
buf (
1481 if !!html_mods_theme
<> "" && theme_page_exists this_page then
1482 read_theme_page this_page else
1483 if !!html_mods
then !CommonMessages.html_css_mods
1484 else !!CommonMessages.html_css_old
)
1488 http_add_text_header r CSS
;
1489 let this_page = "dh.css" in
1490 Buffer.add_string
buf (
1491 if !!html_mods_theme
<> "" && theme_page_exists this_page then
1492 read_theme_page this_page else
1493 if !!html_mods
then !CommonMessages.download_html_css_mods
1494 else !!CommonMessages.download_html_css_old
)
1498 http_add_text_header r JAVASCRIPT
;
1499 let this_page = "i.js" in
1500 Buffer.add_string
buf (
1501 if !!html_mods_theme
<> "" && theme_page_exists this_page then
1502 read_theme_page this_page else
1503 if !!html_mods
then !!CommonMessages.html_js_mods0
1504 else !!CommonMessages.html_js_old
)
1508 http_add_text_header r JAVASCRIPT
;
1509 let this_page = "di.js" in
1510 Buffer.add_string
buf (
1511 if !!html_mods_theme
<> "" && theme_page_exists this_page then
1512 read_theme_page this_page else
1513 if !!html_mods
then !!CommonMessages.download_html_js_mods0
1514 else !!CommonMessages.download_html_js_old
)
1515 | s -> http_send_bin_pictures r buf (String.lowercase
s)
1518 let _, error_text_long
, header
= Http_server.error_page
"404" "" ""
1519 (Ip.to_string
(TcpBufferedSocket.my_ip
r.sock))
1520 (string_of_int
!!http_port
)
1521 (Some
(Url_not_found
r.get_url
.Url.full_file
)) in
1522 r.reply_head
<- header
;
1523 Buffer.add_string
buf error_text_long
1525 Printf.bprintf
buf "\nException %s\n" (Printexc2.to_string e
);
1526 r.reply_stream
<- None
1530 match !http_file_type with
1531 HTM
-> html_close_page buf false; dollar_escape o true (Buffer.contents
buf)
1532 | MLHTM
-> html_close_page buf true; dollar_escape o true (Buffer.contents
buf)
1535 | BIN
-> Buffer.contents
buf
1538 if !http_file_type <> BIN
&& !!html_use_gzip
then
1542 let http_options = {
1543 conn_buf
= Buffer.create
10000;
1545 conn_sortvd
= NotSorted
;
1546 conn_filter
= (fun _ -> ());
1547 conn_user
= find_ui_user
CommonUserDb.admin_user_name
;
1548 conn_width
= 80; conn_height
= 0;
1549 conn_info
= Some
(WEB
, (Ip.null
, 0));
1552 let create_http_handler () =
1554 bind_addr
= Ip.to_inet_addr
!!http_bind_addr
;
1557 addrs
= Ip_set.of_list
!!allowed_ips
;
1558 (* do not limit access to MLDonkey web interface by IP blocklist *)
1559 use_ip_block_list
= false;
1561 default
= http_handler http_options;
1563 option_hook allowed_ips
(fun _ ->
1564 config.addrs
<- Ip_set.of_list
!!allowed_ips
);
1565 ignore
(find_port
"http server" !!http_bind_addr http_port
1566 (Http_server.handler
config));
1567 config.port
<- !!http_port