patch #7318
[mldonkey.git] / src / daemon / common / commonOptions.ml
blob16b3e8e037998fc0a47df92a0f2bdcc38af1c2fd
1 (* Copyright 2001, 2002 b8_bavard, b8_fee_carabine, INRIA *)
2 (*
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
20 open Gettext
21 open Printf2
22 open Md4
23 open BasicSocket
24 open TcpBufferedSocket
25 open Options
26 open Unix
27 open CommonTypes
29 let log_prefix = "[cO]"
31 let lprintf_nl fmt =
32 lprintf_nl2 log_prefix fmt
34 let lprintf_n fmt =
35 lprintf2 log_prefix fmt
37 let _s x = _s "CommonOptions" x
38 let _b x = _b "CommonOptions" x
40 let startup_message = ref ""
42 let bin_dir = Filename.dirname Sys.argv.(0)
44 let hidden_dir_prefix =
45 if Autoconf.windows then "" else "."
47 let config_dir_basename = hidden_dir_prefix ^ "mldonkey"
49 let pid_filename = Printf.sprintf "%s.pid" (Filename.basename Sys.argv.(0))
51 let security_space_filename = "config_files_space.tmp"
53 let home_dir =
54 match Autoconf.system with
55 | "cygwin"
56 | "mingw" -> "."
57 | _ -> Filename.concat (try Sys.getenv "HOME" with _ -> ".") config_dir_basename
59 let installer_ini = create_options_file (Filename.concat home_dir
60 "installer.ini")
62 let installer_section = file_section installer_ini [] ""
64 let created_new_base_directory = ref None
66 let mldonkey_directory = define_option installer_section ["mldonkey_directory"]
67 "The directory where mldonkey's option files are"
68 string_option home_dir
70 let _ =
71 (try Options.load installer_ini with _ -> ())
73 let file_basedir_pre =
74 try
75 if (String2.starts_with
76 (Filename.basename Sys.argv.(0)) "mlgui")
77 then raise Exit;
78 let chroot_dir = Sys.getenv "MLDONKEY_CHROOT" in
79 try
80 Unix.chdir chroot_dir;
81 let new_passwd = Filename.concat chroot_dir "/etc/passwd" in
82 if not (Sys.file_exists new_passwd) then
83 lprintf_nl "No /etc/passwd in your chroot directory\n create one if you want to use 'run_as_user' option";
84 MlUnix.chroot chroot_dir;
85 lprintf_nl "mldonkey is now running in %s" chroot_dir;
86 "."
88 with e ->
89 lprintf_nl "Exception %s trying to chroot %s"
90 (Printexc2.to_string e) chroot_dir;
91 exit 2
92 with _ ->
93 try
94 let s = Sys.getenv "MLDONKEY_DIR" in
95 if s = "" then home_dir else Filename2.normalize s
96 with _ ->
97 home_dir
99 let file_basedir =
100 (* Creating dirs does work differently on Windows than Unix.
101 Dirs like c:\b are split down by unix2.safe_mkdir to "c".
102 This function splits the directory name into the drive name
103 and chdir to it before creating directories.
104 Non-absolute paths in $MLDONKEY_DIR do not work as well *)
105 if Sys.file_exists (Filename.concat (Sys.getcwd ()) "downloads.ini") then
107 else
108 if Autoconf.windows && file_basedir_pre <> home_dir then
109 match String2.split file_basedir_pre ':' with
110 | drive :: directory :: _ ->
111 Unix.chdir (drive ^ ":\\");
112 directory
113 | _ -> lprintf "Please provide an absolute path in MLDONKEY_DIR like d:\\mldonkey, exiting...\n"; exit 2
114 else file_basedir_pre
116 let exit_message file = Printf.sprintf
117 "\nThis means another MLDonkey process could still be working
118 in this directory. Please shut it down before starting
119 a new instance here. If you are sure no other process uses
120 this directory delete %s and restart the core.\n" file
122 let exit_message_dev file exit = Printf.sprintf
123 "\n/dev/%s does not exist, please create it%s
124 If you are using a chroot environment, create it inside the chroot.\n"
125 file (if exit then ", exiting..." else "")
127 let windows_sleep seconds =
128 lprintf_nl "waiting %d seconds to exit..." seconds;
129 Unix.sleep seconds
131 let min_reserved_fds = 50
132 let min_connections = 50
134 let () =
135 lprintf_nl "Starting MLDonkey %s ... " Autoconf.current_version;
136 let ulof_old = Unix2.c_getdtablesize () in
137 lprintf_nl "Language %s, locale %s, ulimit for open files %d"
138 Charset.Locale.default_language Charset.Locale.locale_string ulof_old;
140 let nofile = Unix2.ml_getrlimit Unix2.RLIMIT_NOFILE in
141 if nofile.Unix2.rlim_max > 0 && nofile.Unix2.rlim_max > nofile.Unix2.rlim_cur then
142 Unix2.ml_setrlimit Unix2.RLIMIT_NOFILE nofile.Unix2.rlim_max;
143 let ulof = Unix2.c_getdtablesize () in
144 if ulof_old <> ulof then
145 lprintf_nl "raised ulimit for open files from %d to %d" ulof_old ulof;
146 let absolute_min = Unix32.max_cache_size_default +
147 min_reserved_fds + min_connections in
148 if ulof < absolute_min then begin
149 lprintf_nl "ulimit for open files is set to %d, at least %d is required, exiting..." ulof absolute_min;
150 exit 2
151 end;
153 lprintf_nl "MLDonkey is working in %s" file_basedir;
154 if not (Sys.file_exists file_basedir) ||
155 not (Sys.file_exists (Filename.concat file_basedir "downloads.ini")) then begin
156 lprint_newline ();
157 lprintf_nl "creating new MLDonkey base directory in %s\n" file_basedir;
158 created_new_base_directory := Some file_basedir
159 end;
160 (try
161 Unix2.safe_mkdir file_basedir
162 with e ->
163 lprintf_nl "Exception (%s) trying to create dir %s"
164 (Printexc2.to_string e) file_basedir;
165 exit 2);
166 Unix2.can_write_to_directory file_basedir;
167 Unix.chdir file_basedir;
169 let filename =
171 Sys.getenv "MLDONKEY_STRINGS"
172 with _ ->
173 "mlnet_strings"
175 set_strings_file filename;
176 lprintf_nl (_b "loaded language resource file");
178 let uname = Unix32.uname () in
179 if uname = "" then
180 begin
181 lprintf_nl "Unknown operating system, please report to the MLDonkey development team";
182 lprintf_nl "at http://savannah.nongnu.org/bugs/?group=mldonkey"
184 else
185 if not (Unix32.os_supported ()) then begin
186 lprintf_nl "WARNING: MLDonkey is not supported on %s" uname;
187 if Autoconf.windows then
188 lprintf_nl "WARNING: MLDonkey is only supported on Windows NT/2000/XP/Server 2003."
189 end;
191 if (String2.starts_with (Filename.basename Sys.argv.(0)) "mlnet")
192 && not Autoconf.windows && not (Autoconf.system = "morphos")
193 && Autoconf.donkey_sui = "yes" && not (Sys.file_exists "/dev/urandom") then
194 begin
195 Autoconf.donkey_sui_urandom := false;
196 lprintf "%s" (exit_message_dev "urandom" false);
197 if Autoconf.system = "hpux" then
198 lprintf_nl "For HP-UX get urandom support from http://www.josvisser.nl/hpux11-random";
200 else
201 Autoconf.donkey_sui_urandom := true;
203 if (String2.starts_with (Filename.basename Sys.argv.(0)) "mlnet")
204 && not Autoconf.windows && not (Sys.file_exists "/dev/null") then begin
205 lprintf "%s" (exit_message_dev "null" true);
206 exit 2
207 end;
209 (* Charset conversion self-test *)
210 let filename = "abcdefghijklmnopqrstuvwxyz" in
211 let conv_filename = Charset.Locale.to_locale filename in
212 if filename <> conv_filename then Charset.Locale.conversion_enabled := false;
214 (try
215 ignore (Sys.getenv "MLDONKEY_TEMP")
216 with Not_found ->
217 Unix.putenv "MLDONKEY_TEMP" ((Filename.basename Sys.argv.(0)) ^ "_tmp")
220 Unix2.can_write_to_directory (Filename2.temp_dir_name ());
222 if (String2.starts_with (Filename.basename Sys.argv.(0)) "mlnet") then begin
223 if Sys.file_exists pid_filename then begin
224 lprintf_nl "PID file %s exists." (Filename.concat file_basedir pid_filename);
225 let pid =
227 Unix2.tryopen_read pid_filename (fun pid_ci ->
228 int_of_string (input_line pid_ci))
229 with _ ->
230 lprintf_nl "But it couldn't be read to check if the process still exists.";
231 lprintf_nl "To avoid doing any harm, MLDonkey will now stop.";
232 if Autoconf.windows then windows_sleep 10;
233 exit 2
236 lprintf_nl "Checking whether PID %d is still used..." pid;
237 Unix.kill pid 0;
238 lprintf "%s" (exit_message pid_filename);
239 exit 2
240 with (* stalled pid file, disregard it *)
241 | Unix.Unix_error (Unix.ESRCH, _, _) ->
242 lprintf_nl "Removing stalled file %s..." pid_filename;
243 (try Sys.remove pid_filename with _ -> ())
244 | e ->
245 lprintf "%s" (exit_message pid_filename);
246 if Autoconf.system = "mingw" then lprintf_nl
247 "can not check for stalled pid file because Unix.kill is not implemented on MinGW";
248 lprintf_nl "Exception %s, exiting..." (Printexc2.to_string e);
249 if Autoconf.system = "mingw" then windows_sleep 10;
250 exit 2
251 end;
252 if Sys.file_exists security_space_filename then begin
254 let security_space_oc =
255 Unix.openfile security_space_filename [Unix.O_WRONLY; Unix.O_CREAT] 0o600 in
256 Unix.lockf security_space_oc Unix.F_TLOCK 0;
257 Unix.close security_space_oc;
258 lprintf_nl "Removing stalled file %s..."
259 (Filename.concat file_basedir security_space_filename);
260 begin
262 (try Unix.close security_space_oc with _ -> ());
263 Sys.remove security_space_filename
264 with e ->
265 lprintf_nl "can not remove %s: %s"
266 (Filename.concat file_basedir security_space_filename)
267 (Printexc2.to_string e);
268 if Autoconf.windows then windows_sleep 10;
269 exit 2
271 with
272 Unix.Unix_error ((Unix.EAGAIN | Unix.EACCES), _, _) ->
273 lprintf_nl "%s exists and is locked by another process."
274 (Filename.concat file_basedir security_space_filename);
275 lprintf "%s" (exit_message security_space_filename);
276 if Autoconf.windows then windows_sleep 10;
277 exit 2
278 | e ->
279 lprintf_nl "error while checking file %s: %s"
280 (Filename.concat file_basedir security_space_filename)
281 (Printexc2.to_string e);
282 lprintf "%s" (exit_message security_space_filename);
283 if Autoconf.windows then windows_sleep 10;
284 exit 2
288 let define_option a b ?desc ?restart ?public ?internal c d e =
289 match desc with
290 None -> define_option a b (_s c) d e ?restart ?public ?internal
291 | Some desc -> define_option a b ~desc: (_s desc) (_s c) d e ?restart ?public ?internal
293 let define_expert_option a b ?desc ?restart ?public ?internal c d e =
294 match desc with
295 None -> define_expert_option a b (_s c) d e ?restart ?public ?internal
296 | Some desc -> define_expert_option a b ~desc: (_s desc) (_s c) d e ?restart ?public ?internal
298 let html_themes_dir = "html_themes"
299 let downloads_ini = create_options_file "downloads.ini"
300 let servers_ini = create_options_file "servers.ini"
301 let searches_ini = create_options_file "searches.ini"
302 let results_ini = create_options_file "results.ini"
303 let files_ini = create_options_file "files.ini"
304 let friends_ini = create_options_file "friends.ini"
306 let messages_log = "messages.log"
308 let servers_section = file_section servers_ini [] ""
310 let ip_list_option = list_option Ip.option
312 let ip_range_list_option = list_option Ip.range_option
314 let int_list_option = list_option int_option
316 let string_list_option = list_option string_option
318 let allow_browse_share_option = define_option_class "Integer"
319 (fun v ->
320 match v with
321 StringValue "true" -> 2
322 | StringValue "false" -> 0
323 | _ -> value_to_int v)
324 int_to_value
326 let addr_option = define_option_class "Addr"
327 (fun value ->
328 let s = value_to_string value in
329 let addr, port = String2.cut_at s ':' in
330 addr, int_of_string port)
331 (fun (addr, port) -> string_to_value (Printf.sprintf "%s:%d" addr port))
333 let _ =
334 Options.set_string_wrappers ip_list_option
335 (fun list ->
336 List.fold_left (fun s ip ->
337 Printf.sprintf "%s %s" (Ip.to_string ip) s
338 ) "" list
340 (fun s ->
341 let list = String2.tokens s in
342 List.map (fun ip -> Ip.of_string ip) list
345 Options.set_string_wrappers ip_range_list_option
346 (fun list ->
347 String.concat " " (List.map Ip.string_of_range (List.rev list))
349 (fun s ->
350 let list = String2.tokens s in
351 List.map (fun ip -> Ip.range_of_string ip) list
354 Options.set_string_wrappers int_list_option
355 (fun list ->
356 List.fold_left (fun s i ->
357 Printf.sprintf "%s %s" (string_of_int i) s
358 ) "" (List.rev list)
360 (fun s ->
361 let list = String2.tokens s in
362 List.map (fun i -> int_of_string i) list
364 Options.set_string_wrappers string_list_option
365 (String.concat " ")
366 String2.tokens
368 let is_not_spam = ref (fun _ -> true)
369 let is_not_comment_spam = ref (fun _ -> true)
374 (*************************************************************************)
375 (* *)
376 (* BASIC OPTIONS *)
377 (* *)
378 (*************************************************************************)
380 let _ = Random.self_init ()
382 let random_letter () =
383 char_of_int (97 + Random.int 26)
385 let new_name () =
386 (Printf.sprintf "%c%c%c%c%c%c"
387 (random_letter ()) (random_letter ()) (random_letter ())
388 (random_letter ()) (random_letter ()) (random_letter ()))
391 let main_section = file_section downloads_ini ["Main"]
392 "Main options"
393 let interfaces_section = file_section downloads_ini ["Interfaces"]
394 "Options to control ports used by mldonkey interfaces"
395 let bandwidth_section = file_section downloads_ini ["Bandwidth"]
396 "Bandwidth options"
397 let networks_section = file_section downloads_ini ["Networks"]
398 "Networks options"
399 let network_section = file_section downloads_ini ["Network Config"]
400 "Network config options"
401 let html_section = file_section downloads_ini ["HTML mods"]
402 "Options to configure HTML mode"
403 let debug_section = file_section downloads_ini ["Debug"]
404 "Debug options"
405 let download_section = file_section downloads_ini ["Download"]
406 "Download options"
407 let startup_section = file_section downloads_ini ["Startup"]
408 "Startup options"
409 let mail_section = file_section downloads_ini ["Mail"]
410 "Mail options"
411 let path_section = file_section downloads_ini ["Paths"]
412 "Paths options"
413 let security_section = file_section downloads_ini ["Security"]
414 "Security options"
415 let other_section = file_section downloads_ini ["Other"]
416 "Other options"
421 (*************************************************************************)
422 (* *)
423 (* Main section *)
424 (* *)
425 (*************************************************************************)
427 let current_section = main_section
429 let global_login = define_option current_section ["client_name"]
430 "small name of client"
431 string_option (new_name ())
436 (*************************************************************************)
437 (* *)
438 (* Interfaces section *)
439 (* *)
440 (*************************************************************************)
442 let current_section = interfaces_section
444 let allowed_ips = define_option current_section ["allowed_ips"]
445 ~desc: "Allowed IPs"
446 "list of IP address allowed to connect to the core via telnet/GUI/WEB
447 for internal command set: list separated by spaces
448 example for internal command: set allowed_ips \"127.0.0.0/8 192.168.1.2\"
449 or for editing the ini-file: list separated by semi-colon
450 example for ini-file: allowed_ips = [ \"127.0.0.0/8\"; \"192.168.1.2\";]
451 CIDR and range notations are supported: ie use 192.168.0.0/24
452 or 192.168.0.0-192.168.0.255 for 192.168.0.*"
453 ip_range_list_option [ Ip.RangeSingleIp Ip.localhost ]
455 let allowed_ips_set = ref Ip_set.bl_empty
457 let _ =
458 option_hook allowed_ips (fun _ ->
459 let new_list = ref [] in
460 List.iter (fun i ->
461 let new_range =
462 match i with
463 | Ip.RangeSingleIp ip ->
464 (let a, b, c, d = Ip.to_ints ip in
465 match a = 255, b = 255, c = 255, d = 255 with
466 | true, true, true, true -> Ip.RangeCIDR (Ip.null, 0)
467 | false, true, true, true -> Ip.RangeCIDR ((Ip.of_string (Printf.sprintf "%d.0.0.0" a)), 8)
468 | false, false, true, true -> Ip.RangeCIDR ((Ip.of_string (Printf.sprintf "%d.%d.0.0" a b)), 16)
469 | false, false, false, true -> Ip.RangeCIDR ((Ip.of_string (Printf.sprintf "%d.%d.%d.0" a b c)), 24)
470 | false, false, false, false -> i
471 | _ -> i)
472 | Ip.RangeRange (ip1, ip2) -> i
473 | Ip.RangeCIDR (ip, shift) -> i
475 if i <> new_range then
476 lprintf_nl "allowed_ips: converted %s to %s" (Ip.string_of_range i) (Ip.string_of_range new_range);
477 new_list := new_range :: !new_list
478 ) !!allowed_ips;
479 new_list := if !new_list = [] then [ Ip.localhost_range ] else List.rev !new_list;
480 if !new_list <> !!allowed_ips then allowed_ips =:= !new_list;
481 allowed_ips_set := (Ip_set.of_list !!allowed_ips))
484 let gui_port = define_option current_section ["gui_port"]
485 ~desc: "The port to connect the GUI"
486 ~restart: true
487 "port for Graphical Interfaces, 0 to deactivate GUI interface"
488 port_option 4001
490 let gift_port = define_option current_section ["gift_port"]
491 ~desc: "The port to connect for GiFT GUIs."
492 ~restart: true
493 "port for GiFT Graphical Interfaces interaction. It was 1213, but the default is
494 now 0 for disabled, because it does not check for a password."
495 port_option 0
497 let http_port = define_option current_section ["http_port"]
498 ~desc: "The port to connect via HTTP"
499 ~public: true
500 ~restart: true
501 "The port used to connect to your client with a web browser, 0 to deactivate web interface"
502 port_option 4080
504 let telnet_port = define_option current_section ["telnet_port"]
505 ~desc: "The port to connect via telnet"
506 ~restart: true
507 "port for user interaction, 0 to deactivate telnet interface"
508 port_option 4000
510 let http_bind_addr = define_expert_option current_section ["http_bind_addr"]
511 ~restart: true
512 "The IP address used to bind the http server"
513 Ip.option (Ip.any)
515 let gui_bind_addr = define_expert_option current_section ["gui_bind_addr"]
516 ~restart: true
517 "The IP address used to bind the gui server"
518 Ip.option (Ip.of_inet_addr Unix.inet_addr_any)
520 let telnet_bind_addr = define_expert_option current_section ["telnet_bind_addr"]
521 ~restart: true
522 "The IP address used to bind the telnet server"
523 Ip.option (Ip.of_inet_addr Unix.inet_addr_any)
525 let print_all_sources = define_expert_option current_section ["print_all_sources"]
526 "Should *all* sources for a file be shown on HTML/telnet vd <num>"
527 bool_option true
529 let improved_telnet = define_expert_option current_section ["improved_telnet"]
530 "Improved telnet interface"
531 bool_option true
533 let alias_commands = define_option current_section ["alias_commands"]
534 "Aliases to commands. The alias (fist string) has to be
535 whitespaceless, the outcome of the alias (second string)
536 may have spaces (put it in quotation then)."
537 (list_option (tuple2_option (string_option, string_option)))
538 [ "quit", "q";
539 "exit", "q";
542 let verbosity = define_expert_option current_section ["verbosity"]
543 "A space-separated list of keywords. Each keyword triggers
544 printing information on the corresponding messages:
545 verb : verbose mode (interesting not only for coders)
546 mc : debug client messages
547 mr|raw : debug raw messages
548 mct : debug emule clients tags
549 ms : debug server messages
550 sm : debug source management
551 net : debug net
552 gui : debug gui
553 no-login : disable login messages
554 file : debug file handling
555 do : some download warnings
556 up : some upload warnings
557 unk : unknown messages
558 ov : overnet
559 loc : debug source research/master servers
560 share: debug sharing
561 md4 : md4 computation
562 connect : debug connections
563 udp : udp messages
564 ultra|super : debug supernode
565 swarming : debug swarming
566 hc : http_client messages
567 hs : http_server messages
568 com : commands by non-admin users
569 act : debug activity
570 bw : debug bandwidth
571 geo : debug GeoIP
572 unexp : debug unexpected messages"
573 string_option ""
578 (*************************************************************************)
579 (* *)
580 (* Bandwidth section *)
581 (* *)
582 (*************************************************************************)
584 let current_section = bandwidth_section
586 let max_hard_upload_rate = define_option current_section ["max_hard_upload_rate"]
587 "The maximal upload rate you can tolerate on your link in kBytes/s (0 = no limit)
588 The limit will apply on all your connections (clients and servers) and both
589 control and data messages."
590 int_option 10
592 let max_hard_download_rate = define_option current_section ["max_hard_download_rate"]
593 "The maximal download rate you can tolerate on your link in kBytes/s (0 = no limit)
594 The limit will apply on all your connections (clients and servers) and both
595 control and data messages. Maximum value depends on max_hard_upload_rate:
596 >= 10 -> unlimited download
597 < 10 > 3 -> download limited to upload * 4
598 < 4 -> download limited to upload * 3"
599 int_option 50
601 let max_hard_upload_rate_2 = define_option current_section ["max_hard_upload_rate_2"]
602 "Second maximal upload rate for easy toggling (use bw_toggle)"
603 int_option 5
605 let max_hard_download_rate_2 = define_option current_section ["max_hard_download_rate_2"]
606 "Second maximal download rate for easy toggling (use bw_toggle)"
607 int_option 20
609 let max_opened_connections = define_option current_section ["max_opened_connections"]
610 "Maximal number of opened connections"
611 int_option 200
613 let max_opened_connections_2 = define_option current_section ["max_opened_connections_2"]
614 "Second maximal number of opened connections for easy toggling (use bw_toggle)"
615 int_option 100
617 let max_indirect_connections = define_option current_section ["max_indirect_connections"]
618 "Amount of indirect connections in percent (min 30, max 70) of max_opened_connections"
619 int_option 30
621 let max_upload_slots = define_option current_section ["max_upload_slots"]
622 "How many slots can be used for upload, minimum 3"
623 int_option 5
625 let max_release_slots = define_option current_section ["max_release_slots"]
626 "How many percent of upload slots can be used for downloading files
627 tagged as release, maximum 75%"
628 percent_option 20
630 let friends_upload_slot = define_option current_section ["friends_upload_slot"]
631 "Set aside a single reserved slot to upload to friends"
632 bool_option true
634 let small_files_slot_limit = define_option current_section ["small_files_slot_limit"]
635 "Maximum file size to benefit from the reserved slot for small files (0 to disable)"
636 int64_option 10240L
638 let dynamic_slots = define_option current_section ["dynamic_slots"]
639 "Set this to true if you want to have dynamic upload slot allocation (experimental)"
640 bool_option false
642 let max_connections_per_second = define_option current_section ["max_connections_per_second"]
643 "Maximal number of connections that can be opened per second"
644 int_option 5
646 let loop_delay = define_expert_option current_section ["loop_delay"]
647 "The delay in milliseconds to wait in the event loop. Can be decreased to
648 increase the bandwidth usage, or increased to lower the CPU usage."
649 int_option 5
651 let nolimit_ips = define_option current_section ["nolimit_ips"]
652 ~desc: "No-limit IPs"
653 "list of IP addresses allowed to connect to the core with no limit on
654 upload/download and upload slots. List separated by spaces, wildcard=255
655 ie: use 192.168.0.255 for 192.168.0.* "
656 ip_list_option [Ip.localhost]
658 let copy_read_buffer = define_option current_section ["copy_read_buffer"]
659 "This option enables MLdonkey to always read as much data as possible
660 from a channel, but use more CPU as it must then copy the data in the
661 channel buffer."
662 bool_option true
667 (*************************************************************************)
668 (* *)
669 (* Networks section *)
670 (* *)
671 (*************************************************************************)
673 let current_section = networks_section
675 let enable_overnet = define_option current_section ["enable_overnet"]
676 "Set to true if you also want mldonkey to run as an overnet client
677 (enable_donkey must be true)"
678 bool_option false
680 let enable_kademlia = define_option current_section ["enable_kademlia"]
681 "Set to true if you also want mldonkey to run as an kademlia client
682 (enable_donkey must be true, and only experimental)"
683 bool_option false
685 let enable_servers = define_option current_section ["enable_servers"]
686 "Set to true if you want mldonkey to connect to edonkey servers
687 (enable_donkey must be true, and only experimental)"
688 bool_option true
690 let enable_bittorrent = define_option current_section ["enable_bittorrent"]
691 "Set to true if you also want mldonkey to run as an Bittorrent client"
692 bool_option false
694 let enable_donkey = define_option current_section ["enable_donkey"]
695 "Set to true if you also want mldonkey to run as a donkey client"
696 bool_option false
698 let enable_opennap = define_option current_section ["enable_opennap"]
699 "Set to true if you also want mldonkey to run as a napster client (experimental)"
700 bool_option false
702 let enable_soulseek = define_option current_section ["enable_soulseek"]
703 "Set to true if you also want mldonkey to run as a soulseek client (experimental)"
704 bool_option false
706 let enable_gnutella = define_option current_section ["enable_gnutella"]
707 "Set to true if you also want mldonkey to run as a gnutella1 sub node (experimental)"
708 bool_option false
710 let enable_gnutella2 = define_option current_section ["enable_gnutella2"]
711 "Set to true if you also want mldonkey to run as a gnutella2 sub node (experimental)"
712 bool_option false
714 let enable_fasttrack = define_option current_section ["enable_fasttrack"]
715 "Set to true if you also want mldonkey to run as a Fasttrack sub node (experimental)"
716 bool_option false
718 let enable_directconnect = define_option current_section ["enable_directconnect"]
719 "Set to true if you also want mldonkey to run as a direct-connect node (experimental)"
720 bool_option false
722 let enable_openft = define_expert_option current_section ["enable_openft"]
723 "Set to true if you also want mldonkey to run as a OpenFT sub node (experimental)"
724 bool_option false
726 let enable_fileTP = define_option current_section ["enable_fileTP"]
727 "Set to true if you also want mldonkey to download HTTP files (experimental)"
728 bool_option true
733 (*************************************************************************)
734 (* *)
735 (* HTML section *)
736 (* *)
737 (*************************************************************************)
739 let current_section = html_section
741 let html_mods = define_expert_option current_section ["html_mods"]
742 "Whether to use the modified WEB interface"
743 bool_option true
745 let html_mods_style = define_expert_option current_section ["html_mods_style"]
746 "Which html_mods style to use (set with html_mods_style command)"
747 int_option 0
749 let html_mods_human_readable = define_expert_option current_section ["html_mods_human_readable"]
750 "Whether to use human readable GMk number format"
751 bool_option true
753 let html_mods_use_relative_availability = define_expert_option current_section ["html_mods_use_relative_availability"]
754 "Whether to use relative availability in the WEB interface"
755 bool_option true
757 let html_mods_vd_network = define_expert_option current_section ["html_mods_vd_network"]
758 "Whether to display the Net column in vd output"
759 bool_option true
761 let html_mods_vd_comments = define_expert_option current_section ["html_mods_vd_comments"]
762 "Whether to display the Comments column in vd output"
763 bool_option true
765 let html_mods_vd_user = define_expert_option current_section ["html_mods_vd_user"]
766 "Whether to display the User column in vd output"
767 bool_option false
769 let html_mods_vd_group = define_expert_option current_section ["html_mods_vd_group"]
770 "Whether to display the Group column in vd output"
771 bool_option false
773 let html_mods_vd_active_sources = define_expert_option current_section ["html_mods_vd_active_sources"]
774 "Whether to display the Active Sources column in vd output"
775 bool_option true
777 let html_mods_vd_age = define_expert_option current_section ["html_mods_vd_age"]
778 "Whether to display the Age column in vd output"
779 bool_option true
781 let html_flags = define_expert_option current_section ["html_flags"]
782 "Whether to display flags instead of country codes"
783 bool_option true
785 let html_mods_vd_gfx = define_expert_option current_section ["html_mods_vd_gfx"]
786 "Show graph in vd output"
787 bool_option true
789 let html_mods_vd_gfx_remove = define_expert_option current_section ["html_mods_vd_gfx_remove"]
790 "Remove graph files on core shutdown"
791 bool_option false
793 let html_mods_vd_gfx_fill = define_expert_option current_section ["html_mods_vd_gfx_fill"]
794 "Fill graph in vd output"
795 bool_option true
797 let html_mods_vd_gfx_split = define_expert_option current_section ["html_mods_vd_gfx_split"]
798 "Split download and upload graph in vd output"
799 bool_option false
801 let html_mods_vd_gfx_stack = define_expert_option current_section ["html_mods_vd_gfx_stack"]
802 "Stacked download and upload graph"
803 bool_option true
805 let html_mods_vd_gfx_flip = define_expert_option current_section ["html_mods_vd_gfx_flip"]
806 "Flip up/side graph position in vd output"
807 bool_option true
809 let html_mods_vd_gfx_mean = define_expert_option current_section ["html_mods_vd_gfx_mean"]
810 "Show mean line on graph in vd output"
811 bool_option true
813 let html_mods_vd_gfx_transparent = define_expert_option current_section ["html_mods_vd_gfx_transparent"]
814 "Show transparent graph in vd output (only for png)"
815 bool_option true
817 let html_mods_vd_gfx_png = define_expert_option current_section ["html_mods_vd_gfx_png"]
818 "Draw graph as png if true, else draw as jpg in vd output"
819 bool_option true
821 let html_mods_vd_gfx_h = define_expert_option current_section ["html_mods_vd_gfx_h"]
822 "Show hourly graph in vd output"
823 bool_option true
825 let html_mods_vd_gfx_x_size = define_expert_option current_section ["html_mods_vd_gfx_x_size"]
826 "Graph x size in vd output ( 365 < x < 3665 )"
827 int_option 795
829 let html_mods_vd_gfx_y_size = define_expert_option current_section ["html_mods_vd_gfx_y_size"]
830 "Graph y size in vd output ( 200 < y < 1200 )"
831 int_option 200
833 let html_mods_vd_gfx_h_intervall = define_expert_option current_section ["html_mods_vd_gfx_h_intervall"]
834 ~restart: true
835 "compute values for hourly graph every 1,2,3,4,5,10,15,20,30,60 min
836 Changes to this option require a core restart."
837 int_option 60
839 let html_mods_vd_gfx_h_dynamic = define_expert_option current_section ["html_mods_vd_gfx_h_dymamic"]
840 "Dynamic grid width, start with 1 h/grid, maximum html_mods_vd_gfx_h_grid_time h/grid"
841 bool_option true
843 let html_mods_vd_gfx_h_grid_time = define_expert_option current_section ["html_mods_vd_gfx_h_grid_time"]
844 "Max hours on time scale per grid (0 = no limit)"
845 int_option 0
847 let html_mods_vd_gfx_subgrid = define_expert_option current_section ["html_mods_vd_gfx_subgrid"]
848 "Number of shown subgrids on graph (0 = no subgrids)"
849 int_option 0
851 let html_mods_vd_gfx_tag = define_expert_option current_section ["html_mods_vd_gfx_tag"]
852 "Draw tag graph"
853 bool_option false
855 let html_mods_vd_gfx_tag_use_source = define_expert_option current_section ["html_mods_vd_gfx_tag_use_source"]
856 "Use tag source image "
857 bool_option false
859 let html_mods_vd_gfx_tag_source = define_expert_option current_section ["html_mods_vd_gfx_tag_source"]
860 "Tag source image name"
861 string_option "image"
863 let html_mods_vd_gfx_tag_png = define_expert_option current_section ["html_mods_vd_gfx_tag_png"]
864 "Draw tag as png if true, else draw as jpg in vd output"
865 bool_option true
867 let html_mods_vd_gfx_tag_enable_title = define_expert_option current_section ["html_mods_vd_gfx_tag_enable_title"]
868 "Enable tag graph title"
869 bool_option true
871 let html_mods_vd_gfx_tag_title = define_expert_option current_section ["html_mods_vd_gfx_tag_title"]
872 "Tag graph title"
873 string_option "MLNet traffic"
875 let html_mods_vd_gfx_tag_title_x_pos = define_expert_option current_section ["html_mods_vd_gfx_tag_title_x_pos"]
876 "Tag graph title x pos in vd output"
877 int_option 4
879 let html_mods_vd_gfx_tag_title_y_pos = define_expert_option current_section ["html_mods_vd_gfx_tag_title_y_pos"]
880 "Tag graph title y pos in vd output"
881 int_option 1
883 let html_mods_vd_gfx_tag_dl_x_pos = define_expert_option current_section ["html_mods_vd_gfx_tag_dl_x_pos"]
884 "Tag graph download x pos in vd output"
885 int_option 4
887 let html_mods_vd_gfx_tag_dl_y_pos = define_expert_option current_section ["html_mods_vd_gfx_tag_dl_y_pos"]
888 "Tag graph download y pos in vd output"
889 int_option 17
891 let html_mods_vd_gfx_tag_ul_x_pos = define_expert_option current_section ["html_mods_vd_gfx_tag_ul_x_pos"]
892 "Tag graph upload x pos in vd output"
893 int_option 4
895 let html_mods_vd_gfx_tag_ul_y_pos = define_expert_option current_section ["html_mods_vd_gfx_tag_ul_y_pos"]
896 "Tag graph upload y pos in vd output"
897 int_option 33
899 let html_mods_vd_gfx_tag_x_size = define_expert_option current_section ["html_mods_vd_gfx_tag_x_size"]
900 "Tag graph x size in vd output ( 130 < x < 3600 )"
901 int_option 80
903 let html_mods_vd_gfx_tag_y_size = define_expert_option current_section ["html_mods_vd_gfx_tag_y_size"]
904 "Tag graph y size in vd output ( 50 < x < 1200 )"
905 int_option 50
907 let html_mods_vd_last = define_expert_option current_section ["html_mods_vd_last"]
908 "Whether to display the Last column in vd output"
909 bool_option true
911 let html_mods_vd_prio = define_expert_option current_section ["html_mods_vd_prio"]
912 "Whether to display the Priority column in vd output"
913 bool_option true
915 let html_vd_barheight = define_expert_option current_section ["html_vd_barheight"]
916 "Change height of download indicator bar in vd output"
917 int_option 2
919 let html_vd_chunk_graph = define_expert_option current_section ["html_vd_chunk_graph"]
920 "Whether to display chunks list as graph or text in vd output"
921 bool_option true
923 let html_vd_chunk_graph_style = define_expert_option current_section ["html_vd_chunk_graph_style"]
924 "Change style of chunk graph"
925 int_option 0
927 let html_vd_chunk_graph_max_width = define_expert_option current_section ["html_vd_chunk_graph_max_width"]
928 "Change max width of chunk graph"
929 int_option 200
931 let html_mods_show_pending = define_expert_option current_section ["html_mods_show_pending"]
932 "Whether to display the pending slots in uploaders command"
933 bool_option true
935 let html_mods_load_message_file = define_expert_option current_section ["html_mods_load_message_file"]
936 "Whether to load the mldonkey_messages.ini file (false=use internal settings)"
937 bool_option false
939 let html_mods_max_messages = define_expert_option current_section ["html_mods_max_messages"]
940 "Maximum chat messages to log in memory"
941 int_option 50
943 let html_mods_bw_refresh_delay = define_option current_section ["html_mods_bw_refresh_delay"]
944 "bw_stats refresh delay (seconds)"
945 int_option 11
947 let html_mods_theme = define_option current_section ["html_mods_theme"]
948 "html_mods_theme to use (located in relative html_themes/<theme_name> directory
949 leave blank to use internal theme"
950 string_option ""
952 let use_html_mods o =
953 o.conn_output = HTML && !!html_mods
955 let html_checkbox_vd_file_list = define_expert_option current_section ["html_checkbox_vd_file_list"]
956 "Whether to use checkboxes in the WEB interface for download list"
957 bool_option true
959 let html_checkbox_search_file_list = define_expert_option current_section ["html_checkbox_search_file_list"]
960 "Whether to use checkboxes in the WEB interface for search result list"
961 bool_option false
963 let html_use_gzip = define_expert_option current_section ["html_use_gzip"]
964 "Use gzip compression on web pages"
965 bool_option false
967 let html_mods_use_js_tooltips = define_expert_option current_section ["html_mods_use_js_tooltips"]
968 "Whether to use the fancy javascript tooltips or plain html-title"
969 bool_option true
971 let html_mods_js_tooltips_wait = define_expert_option current_section ["html_mods_js_tooltips_wait"]
972 "How long to wait before displaying the tooltips"
973 int_option 0
975 let html_mods_js_tooltips_timeout = define_expert_option current_section ["html_mods_js_tooltips_timeout"]
976 "How long to display the tooltips"
977 int_option 100000
979 let html_mods_use_js_helptext = define_expert_option current_section ["html_mods_use_js_helptext"]
980 "Use javascript to display option help text as js popup (true=use js, false=use html tables)"
981 bool_option true
986 (*************************************************************************)
987 (* *)
988 (* Network section *)
989 (* *)
990 (*************************************************************************)
992 let current_section = network_section
994 let set_client_ip = define_option current_section ["client_ip"]
995 "The last IP address used for this client" Ip.option
996 (Ip.my ())
998 let force_client_ip = define_option current_section ["force_client_ip"]
999 "Use the IP specified by 'client_ip' instead of trying to determine it
1000 ourself. Don't set this option to true if you have dynamic IP."
1001 bool_option false
1003 let discover_ip = define_option current_section ["discover_ip"]
1004 "Use http://ip.discoveryvip.com/ip.asp to obtain WAN IP"
1005 bool_option true
1007 let user_agent = define_option current_section ["user_agent"]
1008 "User agent string (default = \"default\")"
1009 string_option "default"
1011 let get_user_agent () =
1012 if !!user_agent = "default" then
1013 Printf.sprintf "MLDonkey/%s" Autoconf.current_version
1014 else !!user_agent
1016 let web_infos = define_option current_section ["web_infos"]
1017 "A list of lines to download on the WEB: each line has
1018 the format: (kind, period, url), where kind is either
1019 'server.met' for a server.met file (also in gz/bz2/zip format)
1020 containing ed2k server, or
1021 'comments.met' for a file of comments, or
1022 'guarding.p2p' for a blocklist file (also in gz/bz2/zip format), or
1023 'ocl' for file in the ocl format containing overnet peers, or
1024 'contact.dat' for an contact.dat file containing overnet peers,
1025 'nodes.gzip' for a fasttrack nodes.gzip,
1026 'hublist' for DirectConnect hubs list,
1027 and period is the period between updates (in hours),
1028 a period of zero means the file is only loaded once on startup,
1029 and url is the url of the file to download.
1030 IMPORTANT: Put the URL and the kind between quotes.
1031 EXAMPLE:
1032 web_infos = [
1033 (\"server.met\", 0, \"http://www.gruk.org/server.met.gz\");
1034 (\"hublist\", 0, \"http://dchublist.com/hublist.xml.bz2\");
1035 (\"guarding.p2p\", 96, \"http://www.bluetack.co.uk/config/level1.gz\");
1036 (\"ocl\", 24, \"http://members.lycos.co.uk/appbyhp2/FlockHelpApp/contact-files/contact.ocl\");
1037 (\"contact.dat\", 168, \"http://download.overnet.org/contact.dat\");
1038 (\"geoip.dat\", 168, \"http://www.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz\");
1041 (list_option (tuple3_option (string_option, int_option, string_option)))
1043 ("guarding.p2p", 96,
1044 "http://www.bluetack.co.uk/config/level1.gz");
1045 ("server.met", 0,
1046 "http://www.gruk.org/server.met.gz");
1047 ("contact.dat", 168,
1048 "http://download.overnet.org/contact.dat");
1049 ("geoip.dat", 0,
1050 "http://www.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz");
1051 ("nodes.gzip", 0,
1052 "http://update.kceasy.com/update/fasttrack/nodes.gzip");
1053 ("hublist", 0,
1054 "http://dchublist.com/hublist.config.bz2");
1056 ("slsk_boot", 0,
1057 "http://www.slsknet.org/slskinfo2");
1061 let rss_feeds = define_expert_option current_section ["rss_feeds"]
1062 "URLs of RSS feeds"
1063 (list_option Url.option) []
1065 let rss_preprocessor = define_expert_option current_section ["rss_preprocessor"]
1066 "If MLDonkey can not read broken RSS feeds, use this program to preprocess them"
1067 string_option "xmllint"
1069 let ip_blocking_descriptions = define_expert_option current_section ["ip_blocking_descriptions"]
1070 "Keep IP blocking ranges descriptions in memory"
1071 bool_option false
1073 let ip_blocking = define_expert_option current_section ["ip_blocking"]
1074 "IP blocking list filename (peerguardian format), can also be in gz/bz2/zip format
1075 Zip files must contain either a file named guarding.p2p or guarding_full.p2p."
1076 string_option ""
1078 let ip_blocking_countries = define_expert_option current_section ["ip_blocking_countries"]
1079 "List of countries to block connections from/to (requires Geoip).
1080 Names are in ISO 3166 format, see http://www.maxmind.com/app/iso3166
1081 You can also at your own risk use \"Unknown\" for IPs Geoip won't recognize."
1082 string_list_option []
1084 let ip_blocking_countries_block = define_expert_option current_section ["ip_blocking_countries_block"]
1085 "false: use ip_blocking_countries as block list, all other countries are allowed
1086 true: use ip_blocking_countries as allow list, all other countries are blocked"
1087 bool_option false
1089 let geoip_dat = define_expert_option current_section ["geoip_dat"]
1090 "Location of GeoIP.dat (Get one from http://www.maxmind.com/download/geoip/database/)"
1091 string_option ""
1093 let _ =
1094 option_hook ip_blocking_descriptions (fun _ ->
1095 Ip_set.store_blocking_descriptions := !!ip_blocking_descriptions
1098 let tcpip_packet_size = define_expert_option current_section ["tcpip_packet_size"]
1099 "The size of the header of a TCP/IP packet on your connection (ppp adds
1100 14 bytes sometimes, so modify to take that into account)"
1101 int_option 40
1103 let mtu_packet_size = define_expert_option current_section ["mtu_packet_size"]
1104 "The size of the MTU of a TCP/IP packet on your connection"
1105 int_option 1500
1107 let minimal_packet_size = define_expert_option current_section ["minimal_packet_size"]
1108 "The size of the minimal packet you want mldonkey to send when data is
1109 available on the connection"
1110 int_option !TcpBufferedSocket.minimal_packet_size
1112 let socket_keepalive = define_expert_option current_section ["socket_keepalive"]
1113 "Should a connection check if the peer we are connected to is still alive?
1114 This implies some bandwidth-cost (with 200 connections ~10-20%)"
1115 bool_option !BasicSocket.socket_keepalive
1117 let referers = define_option current_section ["referers"]
1118 "Cookies send with a http request (used for .torrent files and web_infos)"
1119 (list_option (tuple2_option (string_option, string_option))) [(".*suprnova.*", "http://www.suprnova.org/")]
1121 let cookies = define_option current_section ["cookies"]
1122 "Cookies send with a http request (used for .torrent files and web_infos)"
1123 (list_option (tuple2_option (string_option, list_option (tuple2_option (string_option, string_option))))) []
1125 let http_proxy_server = define_option current_section ["http_proxy_server"]
1126 "Direct HTTP queries to HTTP proxy"
1127 string_option ""
1129 let http_proxy_port = define_option current_section ["http_proxy_port"]
1130 "Port of HTTP proxy"
1131 port_option 8080
1133 let http_proxy_login = define_option current_section ["http_proxy_login"]
1134 "HTTP proxy login (leave empty if proxy doesn't require authentication)"
1135 string_option ""
1137 let http_proxy_password = define_option current_section ["http_proxy_password"]
1138 "HTTP proxy password"
1139 string_option ""
1141 let http_proxy_tcp = define_option current_section ["http_proxy_tcp"]
1142 "Direct TCP connections to HTTP proxy (the proxy should support CONNECT)"
1143 bool_option false
1146 (*************************************************************************)
1147 (* *)
1148 (* Mail section *)
1149 (* *)
1150 (*************************************************************************)
1152 let current_section = mail_section
1154 let smtp_server = define_option current_section ["smtp_server"]
1155 "The mail server you want to use (must be SMTP). Use hostname or IP address"
1156 string_option "127.0.0.1"
1158 let smtp_port = define_option current_section ["smtp_port"]
1159 "The port to use on the mail server (default 25)"
1160 port_option 25
1162 let mail = define_option current_section ["mail"]
1163 "Your e-mail if you want to receive mails when downloads are completed"
1164 string_option ""
1166 let add_mail_brackets = define_option current_section ["add_mail_brackets"]
1167 "Set to false if your mail server cannot handle angle-brackets around addresses (RFC 5321)"
1168 bool_option true
1170 let filename_in_subject = define_option current_section ["filename_in_subject"]
1171 "Send filename in mail subject"
1172 bool_option true
1174 let url_in_mail = define_option current_section ["url_in_mail"]
1175 "Put a prefix for the filename here which shows up in the notification mail"
1176 string_option ""
1181 (*************************************************************************)
1182 (* *)
1183 (* Download section *)
1184 (* *)
1185 (*************************************************************************)
1187 let current_section = download_section
1189 let auto_commit = define_option current_section ["auto_commit"]
1190 "Set to false if you don't want mldonkey to automatically put completed files
1191 in incoming directory"
1192 bool_option true
1194 let pause_new_downloads = define_option current_section ["pause_new_downloads"]
1195 "Set to true if you want all new downloads be paused immediatly
1196 will be set to false on core start."
1197 bool_option false
1199 let release_new_downloads = define_option current_section ["release_new_downloads"]
1200 "Set to true if you want to activate the release slot feature for all new downloads."
1201 bool_option false
1203 (* emulate_sparsefiles does not work, temporarily disabled
1204 let emulate_sparsefiles = define_expert_option current_section ["emulate_sparsefiles"]
1205 "Set to true if you want MLdonkey to emulate sparse files on your disk.
1206 Files will use less space, but <preview> and <recover> won't work anymore.
1207 Works only on Edonkey plugin. EXPERIMENTAL."
1208 bool_option false
1211 let max_concurrent_downloads = define_option current_section ["max_concurrent_downloads"]
1212 "The maximal number of files in Downloading state (other ones are Queued)"
1213 int_option 50
1215 let sources_per_chunk = define_expert_option current_section ["sources_per_chunk"]
1216 "How many sources to use to download each chunk"
1217 int_option 3
1219 let max_recover_gap = define_option current_section ["max_recover_zeroes_gap"]
1220 "The maximal length of zero bytes between non-zero bytes in a file that
1221 should be interpreted as downloaded during a recovery"
1222 int64_option 16L
1224 let file_completed_cmd = define_option current_section ["file_completed_cmd"]
1225 "A command that is called when a file is committed, does not work on MinGW.
1226 Arguments are (kept for compatibility):
1227 $1 - temp file name, without path
1228 $2 - file size
1229 $3 - filename of the committed file
1230 Also these environment variables can be used (preferred way):
1231 $TEMPNAME - temp file name, including path
1232 $FILEID - same as $1
1233 $FILESIZE - same as $2
1234 $FILENAME - same as $3
1235 $FILEHASH - internal hash
1236 $DURATION - download duration
1237 $INCOMING - directory used for commit
1238 $NETWORK - network used for downloading
1239 $ED2K_HASH - ed2k hash if MD4 is known
1240 $FILE_OWNER - user who started the download
1241 $FILE_GROUP - group the file belongs to
1242 $USER_MAIL - mail address of file_owner
1244 string_option ""
1246 let file_started_cmd = define_option current_section ["file_started_cmd"]
1247 "The command which is called when a download is started. Arguments
1248 are '-file <num>'
1249 Also these environment variables can be used (preferred way):
1250 $TEMPNAME - temp file name, including path
1251 $FILEID - same as $1
1252 $FILESIZE - same as $2
1253 $FILENAME - same as $3
1254 $FILEHASH - internal hash
1255 $NETWORK - network used for downloading
1256 $ED2K_HASH - ed2k hash if MD4 is known
1257 $FILE_OWNER - user who started the download
1258 $FILE_GROUP - group the file belongs to
1259 $USER_MAIL - mail address of file_owner
1261 string_option ""
1265 (*************************************************************************)
1266 (* *)
1267 (* Startup section *)
1268 (* *)
1269 (*************************************************************************)
1271 let current_section = startup_section
1273 let run_as_user = define_option current_section ["run_as_user"]
1274 ~restart: true
1275 "The login of the user you want mldonkey to run as, after the ports
1276 have been bound (can be used not to run with root privileges when
1277 a port < 1024 is needed)"
1278 string_option ""
1280 let run_as_useruid = define_option current_section ["run_as_useruid"]
1281 ~restart: true
1282 "The UID of the user (0=disabled) you want mldonkey to run as, after the ports
1283 have been bound (can be used not to run with root privileges when
1284 a port < 1024 is needed)"
1285 int_option 0
1287 let run_as_group = define_option current_section ["run_as_group"]
1288 ~restart: true
1289 "The group of run_as_user user to be used"
1290 string_option ""
1292 let run_as_groupgid = define_option current_section ["run_as_groupgid"]
1293 ~restart: true
1294 "The group of run_as_user user to be used"
1295 int_option 0
1297 let ask_for_gui = define_option current_section ["ask_for_gui"]
1298 "Ask for GUI start"
1299 bool_option false
1301 let start_gui = define_option current_section ["start_gui"]
1302 "Automatically Start the GUI"
1303 bool_option false
1305 let recover_temp_on_startup = define_option current_section ["recover_temp_on_startup"]
1306 "Should MLdonkey try to recover downloads of files in temp/ at startup"
1307 bool_option true
1309 let config_files_security_space = define_expert_option current_section ["config_files_security_space"]
1310 ~restart: true
1311 "How many megabytes should MLdonkey keep for saving configuration files."
1312 int_option 10
1317 (*************************************************************************)
1318 (* *)
1319 (* Path section *)
1320 (* *)
1321 (*************************************************************************)
1323 let current_section = path_section
1325 let temp_directory = define_option current_section ["temp_directory"]
1326 "The directory where temporary files should be put"
1327 string_option "temp"
1329 let share_scan_interval = define_option current_section ["share_scan_interval"]
1330 ~restart: true
1331 "How often (in minutes) should MLDonkey scan all shared directories for new/removed files.
1332 Minimum 5, 0 to disable. Use command reshare to manually scan shares.
1333 When core starts, shared directories are scanned once, independent of this option."
1334 int_option 30
1336 let create_file_mode = define_option current_section ["create_file_mode"]
1337 "New download files are created with these rights (in octal)"
1338 string_option "664"
1340 let create_dir_mode = define_option current_section ["create_dir_mode"]
1341 "New directories in incoming_directories are created with these rights (in octal)"
1342 string_option "755"
1344 let create_file_sparse = define_option current_section ["create_file_sparse"]
1345 "Create new files as sparse (not supported on FAT volumes)"
1346 bool_option true
1348 let hdd_temp_minfree = define_option current_section ["hdd_temp_minfree"]
1349 "Mininum free space in MB on temp_directory, minimum 50"
1350 int_option 50
1352 let hdd_temp_stop_core = define_option current_section ["hdd_temp_stop_core"]
1353 "If true core shuts down when free space on temp dir is below hdd_temp_minfree,
1354 otherwise all downloads are paused and a warning email is sent."
1355 bool_option false
1357 let hdd_coredir_minfree = define_option current_section ["hdd_coredir_minfree"]
1358 "Mininum free space in MB on core directory, minimum 20"
1359 int_option 50
1361 let hdd_coredir_stop_core = define_option current_section ["hdd_coredir_stop_core"]
1362 "If true core shuts down when free space on core dir is below hdd_coredir_minfree,
1363 otherwise all downloads are paused and a warning email is sent."
1364 bool_option true
1366 let hdd_send_warning_interval = define_option current_section ["hdd_send_warning_interval"]
1367 "Send a warning mail each <interval> hours for each directory, 0 to deactivate mail warnings."
1368 int_option 1
1370 let previewer = define_expert_option current_section ["previewer"]
1371 "Name of program used for preview (first arg is local filename, second arg
1372 is name of file as searched on eDonkey"
1373 string_option "mldonkey_previewer"
1375 let mldonkey_bin = define_expert_option current_section ["mldonkey_bin"]
1376 "Directory where mldonkey binaries are installed"
1377 string_option bin_dir
1379 let mldonkey_gui = define_expert_option current_section ["mldonkey_gui"]
1380 "Name of GUI to start"
1381 string_option (Filename.concat bin_dir "mlgui")
1386 (*************************************************************************)
1387 (* *)
1388 (* Security section *)
1389 (* *)
1390 (*************************************************************************)
1392 let current_section = security_section
1394 let allowed_commands = define_option current_section ["allowed_commands"]
1395 "Commands that you are allowed to be call from the interface. These
1396 commands should short, so that the core is not blocked more than necessary."
1397 (list_option (tuple2_option (string_option, string_option)))
1398 [ "df", "df";
1399 "ls", "ls incoming";
1402 let allow_any_command = define_option current_section ["allow_any_command"]
1403 "Allow you to use any command with ! in the interface instead of only the
1404 ones in allowed_commands"
1405 bool_option false
1407 let allow_browse_share = define_option current_section ["allow_browse_share"]
1408 "Allow others to browse our share list (0: none, 1: friends only, 2: everyone"
1409 allow_browse_share_option 1
1411 let messages_filter = define_option current_section ["messages_filter"]
1412 "Regexp of messages to filter out, example: string1|string2|string3"
1413 string_option "DI-Emule|ZamBoR|Ketamine|eMule FX|AUTOMATED MESSAGE|Hi Honey!|Do you live in my area|download HyperMule"
1415 let comments_filter = define_option current_section ["comments_filter"]
1416 "Regexp of comments to filter out, example: string1|string2|string3"
1417 string_option "http://|https://|www\\."
1422 (*************************************************************************)
1423 (* *)
1424 (* Other section *)
1425 (* *)
1426 (*************************************************************************)
1428 let current_section = other_section
1430 let save_results = define_option current_section ["save_results"]
1431 "(experimental)"
1432 int_option 0
1434 let buffer_writes = define_option current_section ["buffer_writes"]
1435 "Buffer writes and flush after buffer_writes_delay seconds (experimental)"
1436 bool_option false
1438 let buffer_writes_delay = define_expert_option current_section ["buffer_writes_delay"]
1439 ~restart: true
1440 "Buffer writes and flush after buffer_writes_delay seconds (experimental)"
1441 float_option 30.
1443 let buffer_writes_threshold = define_expert_option current_section ["buffer_writes_threshold"]
1444 "Flush buffers if buffers exceed buffer_writes_threshold kB (experimental)"
1445 int_option 1024
1447 let emule_mods_count = define_option current_section ["emule_mods_count"]
1448 "build statistics about eMule mods"
1449 bool_option false
1451 let emule_mods_showall = define_option current_section ["emule_mods_showall"]
1452 "show all eMule mods in statistics"
1453 bool_option false
1455 let backup_options_delay = define_option current_section ["backup_options_delay"]
1456 "How often (in hours) should a backup of the ini files be written into old_config.
1457 A value of zero means that a backup is written only when the core shuts down."
1458 int_option 0
1460 let backup_options_generations = define_option current_section ["backup_options_generations"]
1461 "Define the total number of options archives in old_config."
1462 int_option 10
1464 let backup_options_format = define_option current_section ["backup_options_format"]
1465 "Define the format of the archive, zip or tar.gz are valid."
1466 string_option "tar.gz"
1468 let shutdown_timeout = define_option current_section ["shutdown_timeout"]
1469 "The maximum time in seconds to wait for networks to cleanly shutdown."
1470 int_option 3
1473 (*************************************************************************)
1474 (* *)
1475 (* EXPERT OPTIONS *)
1476 (* *)
1477 (*************************************************************************)
1479 let safe_utf8 s =
1480 if Charset.is_utf8 s
1481 then s
1482 else failwith (Printf.sprintf "%s is not an UTF-8 string.\n" s)
1484 let value_to_utf8 v =
1485 let s = Options.value_to_string v in
1486 safe_utf8 s
1488 let utf8_to_value s =
1489 let s = safe_utf8 s in
1490 Options.string_to_value s
1492 let utf8_option =
1493 define_option_class "Utf8"
1494 value_to_utf8 utf8_to_value
1496 let utf8_filename_conversions = define_expert_option current_section ["utf8_filename_conversions"]
1497 "The conversions to apply on Unicode characters"
1498 (list_option (tuple2_option (int_option, utf8_option))) []
1500 let interface_buffer = define_expert_option current_section ["interface_buffer"]
1501 "The size of the buffer between the client and its GUI. Can be useful
1502 to increase when the connection between them has a small bandwith"
1503 int_option 1000000
1505 let max_name_len = define_expert_option current_section ["max_name_len"]
1506 "The size long names will be shortened to in the interface"
1507 int_option 50
1509 let max_result_name_len = define_expert_option current_section ["max_result_name_len"]
1510 "The size filenames will be shortened to in search results"
1511 int_option 50
1513 let max_filenames = define_expert_option current_section ["max_filenames"]
1514 "The maximum number of different filenames used by MLDonkey"
1515 int_option 50
1517 let max_client_name_len = define_expert_option current_section ["max_client_name_len"]
1518 "The size long client names will be shortened to in the interface"
1519 int_option 25
1521 let term_ansi = define_expert_option current_section ["term_ansi"]
1522 "Is the default terminal an ANSI terminal (escape sequences can be used)"
1523 bool_option true
1525 let update_gui_delay = define_expert_option current_section ["update_gui_delay"]
1526 "Delay between updates to the GUI"
1527 float_option 1.
1529 let http_realm = define_expert_option current_section ["http_realm"]
1530 "The realm shown when connecting with a WEB browser"
1531 string_option "MLdonkey"
1533 let html_frame_border = define_expert_option current_section ["html_frame_border"]
1534 "This option controls whether the WEB interface should show frame borders or not"
1535 bool_option true
1537 let commands_frame_height = define_expert_option current_section ["commands_frame_height"]
1538 "The height of the command frame in pixel (depends on your screen and browser sizes)"
1539 int_option 46
1541 let motd_html = define_expert_option current_section ["motd_html"]
1542 "Message printed at startup additional to welcome text"
1543 string_option ""
1545 let compaction_delay = define_expert_option current_section ["compaction_delay"]
1546 "Force compaction every <n> hours (in [1..24])"
1547 int_option 2
1549 let vd_reload_delay = define_expert_option current_section ["vd_reload_delay"]
1550 "The delay between reloads of the vd output in the WEB interface"
1551 int_option 120
1553 let client_bind_addr = define_option current_section ["client_bind_addr"]
1554 ~restart: true
1555 "The IP address used to bind the p2p clients"
1556 Ip.option (Ip.of_inet_addr Unix.inet_addr_any)
1558 let _ =
1559 option_hook client_bind_addr (fun _ ->
1560 TcpBufferedSocket.bind_address := Ip.to_inet_addr !!client_bind_addr
1563 let _ =
1564 option_hook copy_read_buffer (fun _ ->
1565 TcpBufferedSocket.copy_read_buffer := !!copy_read_buffer
1568 let () =
1569 option_hook create_file_mode (fun _ ->
1570 Unix32.create_file_mode := Misc.int_of_octal_string !!create_file_mode
1572 option_hook create_dir_mode (fun _ ->
1573 Unix32.create_dir_mode := Misc.int_of_octal_string !!create_dir_mode
1576 let create_mlsubmit = define_expert_option current_section ["create_mlsubmit"]
1577 "Should the MLSUBMIT.REG file be created"
1578 bool_option true
1580 let minor_heap_size = define_expert_option current_section ["minor_heap_size"]
1581 "Size of the minor heap in kB"
1582 int_option 32
1584 let relevant_queues = define_expert_option current_section ["relevant_queues"]
1585 "The source queues to display in source lists (see 'sources' command)"
1586 int_list_option [0;1;2;3;4;5;6;8;9;10]
1588 let min_reask_delay = define_expert_option current_section ["min_reask_delay"]
1589 "The minimal delay between two connections to the same client (in seconds)"
1590 int_option 600
1592 let display_downloaded_results = define_expert_option current_section ["display_downloaded_results"]
1593 "Whether to display results already downloaded"
1594 bool_option true
1596 let filter_table_threshold = define_expert_option current_section ["filter_table_threshold"]
1597 "Minimal number of results for filter form to appear"
1598 int_option 50
1600 let client_buffer_size = define_expert_option current_section ["client_buffer_size"]
1601 "Maximal size in byte of the buffers of a client, minimum 50.000 byte.
1602 For high-volume links raise this value to 1.000.000 or higher."
1603 int_option 500000
1605 let save_options_delay = define_expert_option current_section ["save_options_delay"]
1606 ~restart: true
1607 "The delay between two saves of the 'downloads.ini' file (default is 15 minutes).
1608 Changes to this option require a core restart."
1609 float_option 900.0
1611 let server_connection_timeout = define_expert_option current_section ["server_connection_timeout"]
1612 "timeout when connecting to a server"
1613 float_option 30.
1615 let download_sample_rate = define_expert_option current_section ["download_sample_rate"]
1616 ~restart: true
1617 "The delay between one glance at a file and another"
1618 float_option 1.
1620 let download_sample_size = define_expert_option current_section ["download_sample_size"]
1621 "How many samples go into an estimate of transfer rates"
1622 int_option 100
1624 let calendar = define_expert_option current_section ["calendar"]
1625 "This option defines a set of date at which some commands have to be executed.
1626 For each tuple, the first argument is a list of week days (from 0 to 6),
1627 the second is a list of hours (from 0 to 23) and the last one a command to
1628 execute. Can be used with 'pause all' and 'resume all' for example to
1629 resume and pause downloads automatically for the night."
1630 (list_option (tuple3_option (list_option int_option,list_option int_option, string_option)))
1633 let compaction_overhead = define_expert_option current_section ["compaction_overhead"]
1634 "The percentage of free memory before a compaction is triggered"
1635 int_option 25
1637 let space_overhead = define_expert_option current_section ["space_overhead"]
1638 "The major GC speed is computed from this parameter. This is the memory
1639 that will be \"wasted\" because the GC does not immediatly collect
1640 unreachable blocks. It is expressed as a percentage of the memory used
1641 for live data. The GC will work more (use more CPU time and collect
1642 blocks more eagerly) if space_overhead is smaller."
1643 percent_option 80
1645 let max_displayed_results = define_expert_option current_section ["max_displayed_results"]
1646 "Maximal number of results displayed for a search"
1647 int_option 1000
1649 let options_version = define_expert_option current_section ["options_version"]
1650 ~internal: true
1651 "(internal option)"
1652 int_option 21
1654 let max_comments_per_file = define_expert_option current_section ["max_comments_per_file"]
1655 "Maximum number of comments per file"
1656 int_option 100
1658 let max_comment_length = define_expert_option current_section ["max_comment_length"]
1659 "Maximum length of file comments"
1660 int_option 256
1663 (*************************************************************************)
1664 (* *)
1665 (* Debug section *)
1666 (* *)
1667 (*************************************************************************)
1669 let current_section = debug_section
1671 let allow_local_network = define_expert_option current_section ["allow_local_network"]
1672 "If this option is set, IP addresses on the local network are allowed
1673 (only for debugging)"
1674 bool_option false
1676 let log_size = define_expert_option current_section ["log_size"]
1677 "size of log in number of records"
1678 int_option 300
1680 let log_file_size = define_expert_option current_section ["log_file_size"]
1681 "Maximum size of log_file in MB, this value is only checked on startup,
1682 log_file will be deleted if its bigger than log_file_size."
1683 int_option 2
1685 let log_file = define_expert_option current_section ["log_file"]
1686 "The file in which you want mldonkey to log its debug messages. If you
1687 set this option, mldonkey will log this info in the file until you use the
1688 'close_log' command. The log file may become very large. You can
1689 also enable logging in a file after startup using the 'log_file' command."
1690 string_option "mlnet.log"
1692 let log_to_syslog = define_expert_option current_section ["log_to_syslog"]
1693 "Post log messages to syslog. This setting is independent of log_file
1694 and its associated commands, therefore close_log does not stop log to syslog.
1695 Its therefore possible to log to syslog and log_file at the same time."
1696 bool_option false
1698 let gui_log_size = define_expert_option current_section ["gui_log_size"]
1699 "number of lines for GUI console messages"
1700 int_option 30
1705 (*************************************************************************)
1706 (* *)
1707 (* HOOKS On options *)
1708 (* *)
1709 (*************************************************************************)
1711 let current_section = other_section
1713 let last_high_id = ref Ip.null
1715 let client_ip sock =
1716 if !!force_client_ip then !!set_client_ip
1717 else
1718 if !last_high_id <> Ip.null then
1719 begin
1720 if Ip.usable !last_high_id && !!set_client_ip <> !last_high_id then
1721 set_client_ip =:= !last_high_id;
1722 !last_high_id
1724 else
1725 match sock with
1726 None -> !!set_client_ip
1727 | Some sock ->
1728 let ip = TcpBufferedSocket.my_ip sock in
1729 if Ip.usable ip && !!set_client_ip <> ip then
1730 set_client_ip =:= ip;
1733 let start_running_plugins = ref false
1735 let filter_search_delay = 5.0
1737 (* Infer which nets to start depending on the name used *)
1738 let _ =
1739 let name = String.lowercase (Filename.basename Sys.argv.(0)) in
1740 let name = try
1741 let pos = String.index name '+' in
1742 String.sub name 0 pos
1743 with _ -> name in
1744 let name = try
1745 let pos = String.index name '.' in
1746 String.sub name 0 pos
1747 with _ -> name in
1749 match name with
1750 | "mldc" -> enable_directconnect =:= true
1751 | "mlgnut" -> enable_gnutella =:= true
1752 | "mldonkey" -> enable_donkey =:= true; enable_overnet =:= true
1753 | "mlslsk" -> enable_soulseek =:= true
1754 | "mlbt" -> enable_bittorrent =:= true
1755 | "mlnap" -> enable_opennap =:= true
1756 | _ ->
1757 (* default *)
1758 enable_donkey =:= true;
1759 enable_overnet =:= true;
1760 enable_bittorrent =:= true
1762 let win_message =
1763 "\n\nNEVER close this window with the close button
1764 on the top right corner of this window!
1765 Instead use the kill command in Telnet or HTML,
1766 the kill function of a GUI or CTRL+C.\n\n"
1768 let real_max_indirect_connections = ref 0
1770 let calc_real_max_indirect_connections () =
1771 real_max_indirect_connections :=
1772 !!max_opened_connections * !!max_indirect_connections / 100
1774 let _ =
1775 option_hook max_indirect_connections (fun _ ->
1776 begin
1777 if !!max_indirect_connections > 70 then max_indirect_connections =:= 70
1778 else if !!max_indirect_connections < 30 then max_indirect_connections =:= 30
1779 end;
1780 calc_real_max_indirect_connections ()
1782 option_hook max_release_slots (fun _ ->
1783 if !!max_release_slots > 75 then max_release_slots =:= 75
1785 option_hook min_reask_delay (fun _ ->
1786 if !!min_reask_delay < 600 then min_reask_delay =:= 600
1788 option_hook share_scan_interval (fun _ ->
1789 if !!share_scan_interval < 5 && !!share_scan_interval <> 0 then share_scan_interval =:= 5
1791 option_hook global_login (fun _ ->
1792 let len = String.length !!global_login in
1793 let prefix = "mldonkey_" in
1794 let prefix_len = String.length prefix in
1795 if len > prefix_len &&
1796 String.sub !!global_login 0 prefix_len = prefix then
1797 global_login =:= new_name ()
1800 let lprintf_to_file = ref false in
1801 option_hook log_file (fun _ ->
1802 if !!log_file <> "" then
1804 if Unix32.file_exists !!log_file then
1805 if (Unix32.getsize !!log_file)
1806 > (Int64ops.megabytes !!log_file_size) then begin
1807 Sys.remove !!log_file;
1808 lprintf_nl (_b "Logfile %s reset: bigger than %d MB") !!log_file !!log_file_size
1809 end;
1810 let oc = open_out_gen [Open_creat; Open_wronly; Open_append] 0o644 !!log_file in
1811 lprintf_to_file := true;
1812 if Autoconf.system = "cygwin" then lprintf "%s" win_message;
1813 lprintf_nl (_b "Logging in %s") ( Filename.concat file_basedir !!log_file);
1814 log_to_file oc;
1815 lprintf_nl "Started logging..."
1816 with e ->
1817 lprintf_nl "Exception %s while opening log file: %s"
1818 (Printexc2.to_string e) !!log_file
1819 else
1820 if !lprintf_to_file then begin
1821 lprintf_to_file := false;
1822 close_log ()
1825 option_hook buffer_writes_threshold (fun _ ->
1826 Unix32.max_buffered := Int64.of_int (1024 * !!buffer_writes_threshold));
1827 option_hook log_size (fun _ ->
1828 lprintf_max_size := !!log_size
1830 option_hook hdd_temp_minfree (fun _ ->
1831 if !!hdd_temp_minfree < 50 then
1832 hdd_temp_minfree =:= 50);
1833 option_hook hdd_coredir_minfree (fun _ ->
1834 if !!hdd_coredir_minfree < 20 then
1835 hdd_coredir_minfree =:= 20);
1836 option_hook compaction_overhead (fun _ ->
1837 let gc_control = Gc.get () in
1838 Gc.set { gc_control with Gc.max_overhead = !!compaction_overhead };
1840 option_hook space_overhead (fun _ ->
1841 let gc_control = Gc.get () in
1842 Gc.set { gc_control with Gc.space_overhead = !!space_overhead };
1844 option_hook tcpip_packet_size (fun _ ->
1845 TcpBufferedSocket.ip_packet_size := !!tcpip_packet_size
1847 option_hook mtu_packet_size (fun _ ->
1848 TcpBufferedSocket.mtu_packet_size := !!mtu_packet_size
1850 option_hook minimal_packet_size (fun _ ->
1851 TcpBufferedSocket.minimal_packet_size := !!minimal_packet_size
1853 option_hook minor_heap_size (fun _ ->
1854 let gc_control = Gc.get () in
1855 Gc.set { gc_control with Gc.minor_heap_size =
1856 (!!minor_heap_size * 1024) };
1858 option_hook client_buffer_size (fun _ ->
1859 TcpBufferedSocket.max_buffer_size := max 50000 !!client_buffer_size
1861 if Autoconf.has_gd then begin
1862 option_hook html_mods_vd_gfx_png (fun _ ->
1863 if not Autoconf.has_gd_png && !!html_mods_vd_gfx_png then html_mods_vd_gfx_png =:= false;
1864 if not Autoconf.has_gd_jpg && not !!html_mods_vd_gfx_png then html_mods_vd_gfx_png =:= true
1866 option_hook html_mods_vd_gfx_h_intervall (fun _ ->
1867 let values = [1; 2; 3; 4; 5; 10; 15; 20; 30; 60] in
1868 let v = List.find ((<=) (min !!html_mods_vd_gfx_h_intervall 60)) values in
1869 if v <> !!html_mods_vd_gfx_h_intervall then html_mods_vd_gfx_h_intervall =:= v
1873 let verbose_msg_clients = ref false
1874 let verbose_msg_raw = ref false
1875 let verbose_msg_clienttags = ref false
1876 let verbose_msg_servers = ref false
1877 let verbose = ref false
1878 let verbose_sources = ref 0
1879 let verbose_download = ref false
1880 let verbose_no_login = ref false
1881 let verbose_upload = ref false
1882 let verbose_unknown_messages = ref false
1883 let verbose_overnet = ref false
1884 let verbose_location = ref false
1885 let verbose_share = ref false
1886 let verbose_md4 = ref false
1887 let verbose_connect = ref false
1888 let verbose_udp = ref false
1889 let verbose_supernode = ref false
1890 let verbose_swarming = ref false
1891 let verbose_activity = ref false
1892 let verbose_user_commands = ref false
1893 let verbose_geoip = ref false
1894 let verbose_unexpected_messages = ref false
1896 let set_all v =
1897 verbose_msg_clients := v;
1898 verbose_msg_raw := v;
1899 verbose_msg_clienttags := v;
1900 verbose_msg_servers := v;
1901 verbose := v;
1902 BasicSocket.debug := v;
1903 TcpServerSocket.debug := v;
1904 UdpSocket.debug := v;
1905 Unix32.verbose := v;
1906 GuiProto.verbose_gui_decoding := v;
1907 verbose_download := v;
1908 verbose_upload := v;
1909 verbose_no_login := v;
1910 verbose_unknown_messages := v;
1911 verbose_overnet := v;
1912 verbose_location := v;
1913 verbose_share := v;
1914 verbose_md4 := v;
1915 verbose_connect := v;
1916 verbose_udp := v;
1917 verbose_supernode := v;
1918 verbose_swarming := v;
1919 Http_client.verbose := v;
1920 Http_server.verbose := v;
1921 verbose_activity := v;
1922 verbose_user_commands := v;
1923 Geoip.verbose := v;
1924 verbose_unexpected_messages := v
1926 let _ =
1927 option_hook verbosity (fun _ ->
1928 BasicSocket.verbose_bandwidth := 0;
1929 verbose_sources := 0;
1930 set_all false;
1931 List.iter (fun s ->
1932 match s with
1933 | "mc" -> verbose_msg_clients := true
1934 | "mr" | "raw" -> verbose_msg_raw := true
1935 | "mct" -> verbose_msg_clienttags := true
1936 | "ms" -> verbose_msg_servers := true
1937 | "verb" -> verbose := true
1938 | "sm" -> incr verbose_sources
1939 | "net" -> BasicSocket.debug := true; TcpServerSocket.debug := true; UdpSocket.debug := true
1940 | "file" -> Unix32.verbose := true
1941 | "gui" -> GuiProto.verbose_gui_decoding := true
1942 | "no-login" -> verbose_no_login := true
1943 | "do" -> verbose_download := true
1944 | "up" -> verbose_upload := true
1945 | "unk" -> verbose_unknown_messages := true
1946 | "ov" -> verbose_overnet := true
1947 | "loc" -> verbose_location := true
1948 | "share" -> verbose_share := true
1949 | "md4" -> verbose_md4 := true
1950 | "connect" -> verbose_connect := true
1951 | "udp" -> verbose_udp := true
1952 | "ultra" | "super" -> verbose_supernode := true
1953 | "swarming" -> verbose_swarming := true
1954 | "hc" -> Http_client.verbose := true
1955 | "hs" -> Http_server.verbose := true
1956 | "act" -> verbose_activity := true
1957 | "bw" -> incr BasicSocket.verbose_bandwidth
1958 | "unexp" -> verbose_unexpected_messages := true
1959 | "com" -> verbose_user_commands := true
1960 | "geo" -> Geoip.verbose := true
1962 | "all" ->
1964 verbose_sources := 1;
1965 set_all true;
1967 | _ -> lprintf_nl "Unknown verbosity tag: %s" s
1969 ) (String2.split_simplify !!verbosity ' ')
1973 let _ =
1974 option_hook log_to_syslog (fun _ ->
1975 match !Printf2.syslog_oc with
1976 None ->
1977 if !!log_to_syslog then
1978 begin
1979 Printf2.syslog_oc := (
1981 Some (Syslog.openlog (Filename.basename Sys.argv.(0)))
1982 with e -> log_to_syslog =:= false;
1983 lprintf_nl "error while opening syslog %s" (Printexc2.to_string e); None);
1984 lprintf_nl "activated syslog"
1986 | Some oc ->
1987 if not !!log_to_syslog then
1988 begin
1989 lprintf_nl "deactivated syslog";
1990 Syslog.closelog oc;
1991 Printf2.syslog_oc := None
1994 option_hook loop_delay (fun _ ->
1995 BasicSocket.loop_delay := (float_of_int !!loop_delay) /. 1000.;
1997 option_hook socket_keepalive (fun _ ->
1998 BasicSocket.socket_keepalive := !!socket_keepalive
2001 (* convert "|" to "\|" and "\|" to "|" *)
2002 let quote_unquote_bars m =
2003 let len = String.length m in
2004 let result = Buffer.create len in
2005 let rec aux i =
2006 if i = len then
2007 Buffer.contents result
2008 else match m.[i] with
2009 | '|' ->
2010 Buffer.add_string result "\\|";
2011 aux (i+1)
2012 | '\\' ->
2013 aux_escaped (i+1)
2014 | _ ->
2015 Buffer.add_char result m.[i];
2016 aux (i+1)
2017 and aux_escaped i =
2018 if i = len then begin
2019 Buffer.add_char result '\\';
2020 Buffer.contents result
2021 end else match m.[i] with
2022 | '|' ->
2023 Buffer.add_char result '|';
2024 aux (i+1)
2025 | _ ->
2026 Buffer.add_char result '\\';
2027 aux i
2028 in aux 0
2030 let _ =
2031 let regex_fun str =
2032 if str <> "" then
2033 let r = Str.regexp_case_fold (quote_unquote_bars str) in
2034 (fun s ->
2036 ignore (Str.search_forward r s 0);
2037 false
2038 with Not_found -> true
2040 else (fun _ -> true)
2043 option_hook messages_filter (fun _ ->
2044 is_not_spam := regex_fun !!messages_filter
2047 option_hook comments_filter (fun _ ->
2048 is_not_comment_spam := regex_fun !!comments_filter
2051 let http_proxy = ref None
2053 let http_proxy_tcp_update _ =
2054 if !!http_proxy_tcp then
2055 TcpBufferedSocket.http_proxy := !http_proxy
2056 else
2057 TcpBufferedSocket.http_proxy := None
2059 let _ =
2060 let proxy_update _ =
2061 let auth = match !!http_proxy_login with
2062 | "" -> None
2063 | _ -> Some (!!http_proxy_login, !!http_proxy_password)
2065 http_proxy :=
2066 (match !!http_proxy_server with
2067 | "" -> None
2068 | _ -> Some (!!http_proxy_server, !!http_proxy_port, auth));
2069 http_proxy_tcp_update ()
2071 option_hook http_proxy_server proxy_update;
2072 option_hook http_proxy_port proxy_update;
2073 option_hook http_proxy_login proxy_update;
2074 option_hook http_proxy_password proxy_update;
2075 option_hook http_proxy_tcp http_proxy_tcp_update
2077 let _ =
2078 option_hook allow_local_network (fun _ ->
2079 Ip.allow_local_network := !!allow_local_network)
2081 let web_infos_table = Hashtbl.create 10
2083 exception Found_web_infos of web_infos
2085 let web_infos_find url =
2086 let found = ref None in
2087 (try
2088 Hashtbl.iter (fun key w ->
2089 if w.url = url then raise (Found_web_infos w)
2090 ) web_infos_table
2091 with Found_web_infos w -> found := Some w);
2092 !found
2094 let web_infos_remove url =
2095 let delete_list = ref [] in
2096 Hashtbl.iter (fun key w ->
2097 if w.url = url then delete_list := !delete_list @ [key]
2098 ) web_infos_table;
2099 List.iter (fun key -> Hashtbl.remove web_infos_table key) !delete_list
2101 let web_infos_add kind period url =
2102 (match web_infos_find url with
2103 | None -> ()
2104 | Some w -> web_infos_remove w.url);
2105 Hashtbl.add web_infos_table (kind, period, url)
2107 kind = kind;
2108 period = period;
2109 url = url;
2110 state = None;
2113 let web_infos_replace old_url new_url =
2114 Hashtbl.iter (fun key w ->
2115 if w.url = old_url then w.url <- new_url
2116 ) web_infos_table
2118 let _ =
2119 (* convert list option web_infos to a hashtable for better usage *)
2120 set_after_load_hook downloads_ini (fun _ ->
2121 List.iter (fun (kind, period, url) ->
2122 web_infos_add kind period url
2123 ) !!web_infos;
2124 web_infos =:= []
2126 set_before_save_hook downloads_ini (fun _ ->
2127 Hashtbl.iter (fun _ w ->
2128 web_infos =:= !!web_infos @ [(w.kind, w.period, w.url)]
2129 ) web_infos_table
2131 set_after_save_hook downloads_ini (fun _ ->
2132 web_infos =:= []
2135 let rec update_options () =
2136 let update v =
2137 lprintf_nl "Updating options to version %i" v;
2138 options_version =:= v;
2139 update_options ()
2142 match !!options_version with
2143 0 ->
2144 web_infos =:= List.map (fun (kind, period, url) ->
2145 kind, period * Date.day_in_hours, url
2146 ) !!web_infos;
2147 web_infos_add "rss" 6 "http://www.ed2k-it.com/forum/news_rss.php";
2148 web_infos_add "rss" 6 "http://www.torrents.co.uk/backend.php";
2149 web_infos_add "rss" 6 "http://varchars.com/rss/suprnova-movies.rss";
2150 update 1
2152 | 1 ->
2153 (* 5 ms is a good unit, for measuring latency between clients. *)
2154 loop_delay =:= 5;
2155 update 2
2157 | 2 ->
2158 web_infos_remove "http://www.ed2k-it.com/forum/news_rss.php";
2159 web_infos_remove "http://www.torrents.co.uk/backend.php";
2160 web_infos_remove "http://varchars.com/rss/suprnova-movies.rss";
2161 if !!min_reask_delay = 720 then min_reask_delay =:= 600;
2162 update 3
2164 | 3 ->
2165 web_infos_remove "http://members.lycos.co.uk/appbyhp2/FlockHelpApp/contact-files/contact.ocl";
2166 web_infos_add "contact.dat" 168 "http://www.overnet.org/download/contact.dat";
2167 update 4
2169 | 4 ->
2170 web_infos_remove "http://ocbmaurice.dyndns.org/pl/slist.pl/server.met?download/server-best.met";
2171 web_infos_add "server.met" 0 "http://www.gruk.org/server.met.gz";
2172 update 5
2174 | 5 ->
2175 if !!max_indirect_connections > 50 then
2176 max_indirect_connections =:= 20;
2177 update 6
2179 | 6 ->
2180 (* it's more natural to use | instead of \| for simple case *)
2181 messages_filter =:= quote_unquote_bars !!messages_filter;
2182 update 7
2184 | 7 ->
2185 (* update to 20 because of dynamic_loop_delay patch *)
2186 loop_delay =:= 20;
2187 update 8
2189 | 8 ->
2190 web_infos_add "geoip.dat" 0 "http://www.maxmind.com/download/geoip/database/GeoIP.dat.gz";
2191 update 9
2193 | 9 ->
2194 web_infos_remove "http://www.gruk.org/server.met.gz";
2195 web_infos_add "server.met" 0 "http://www.jd2k.com/server.met";
2196 update 10
2198 | 10 ->
2199 web_infos_remove "http://www.overnet.org/download/contact.dat";
2200 web_infos_add "contact.dat" 168 "http://download.overnet.org/contact.dat";
2201 update 11
2203 | 11 ->
2204 web_infos_remove "http://www.bluetack.co.uk/config/antip2p.txt";
2205 web_infos_add "guarding.p2p" 0 "http://www.bluetack.co.uk/config/level1.gz";
2206 update 12
2208 | 12 ->
2209 web_infos_add "nodes.gzip" 0 "http://update.kceasy.com/update/fasttrack/nodes.gzip";
2210 update 13
2212 | 13 ->
2213 web_infos_remove "http://www.jd2k.com/server.met";
2214 web_infos_add "server.met" 0 "http://www.gruk.org/server.met.gz";
2215 update 14
2217 | 14 ->
2218 (* set back to 5 because dynamic_loop_delay patch was removed *)
2219 loop_delay =:= 5;
2220 update 15
2222 | 15 ->
2223 if !!messages_filter = "Your client is connecting too fast" then
2224 messages_filter =:= "DI-Emule|ZamBoR|Ketamine|eMule FX|AUTOMATED MESSAGE";
2225 update 16
2227 | 16 ->
2228 if !!download_sample_size = 10 then download_sample_size =:= 100;
2229 update 17
2231 | 17 ->
2232 web_infos_add "hublist" 0 "http://dchublist.com/hublist.config.bz2";
2233 update 18
2235 | 18 ->
2236 if !!messages_filter = "DI-Emule|ZamBoR|Ketamine|eMule FX|AUTOMATED MESSAGE" then
2237 messages_filter =:= "DI-Emule|ZamBoR|Ketamine|eMule FX|AUTOMATED MESSAGE|Hi Honey!|Do you live in my area|download HyperMule";
2238 update 19
2240 | 19 ->
2241 if !!share_scan_interval = 5 then share_scan_interval =:= 30;
2242 update 20
2244 | 20 ->
2245 web_infos_replace
2246 "http://www.maxmind.com/download/geoip/database/GeoIP.dat.gz"
2247 "http://www.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz";
2248 update 21
2250 | _ -> ()