aboutsummaryrefslogtreecommitdiffstats
path: root/net-p2p
diff options
context:
space:
mode:
authorlioux <lioux@FreeBSD.org>2006-12-25 14:14:03 +0800
committerlioux <lioux@FreeBSD.org>2006-12-25 14:14:03 +0800
commit2a9bb9cc21e9d618a5ead8b6da10d9419fde8b3b (patch)
tree595a1abdee79f64b4ff0ab782a82da4e6dbace99 /net-p2p
parente7871d619fde6798da3e5474cf0ed67d0a8fc5e6 (diff)
downloadfreebsd-ports-gnome-2a9bb9cc21e9d618a5ead8b6da10d9419fde8b3b.tar.gz
freebsd-ports-gnome-2a9bb9cc21e9d618a5ead8b6da10d9419fde8b3b.tar.zst
freebsd-ports-gnome-2a9bb9cc21e9d618a5ead8b6da10d9419fde8b3b.zip
Update to 2.8.2 cvs release as of date 2006122500
Diffstat (limited to 'net-p2p')
-rw-r--r--net-p2p/mldonkey-devel/Makefile3
-rw-r--r--net-p2p/mldonkey-devel/distinfo6
-rw-r--r--net-p2p/mldonkey-devel/files/patch-cvs-200611210019589
-rw-r--r--net-p2p/mldonkey-devel/files/patch-cvs-20061225007533
4 files changed, 7537 insertions, 19594 deletions
diff --git a/net-p2p/mldonkey-devel/Makefile b/net-p2p/mldonkey-devel/Makefile
index cdd6239d59b1..3ee991f06a35 100644
--- a/net-p2p/mldonkey-devel/Makefile
+++ b/net-p2p/mldonkey-devel/Makefile
@@ -6,8 +6,7 @@
#
PORTNAME= mldonkey
-PORTVERSION= 2.8.1
-PORTREVISION= 3
+PORTVERSION= 2.8.2
CATEGORIES+= net-p2p
MASTER_SITES= ${MASTER_SITE_SOURCEFORGE_EXTENDED} \
${MASTER_SITE_SAVANNAH}
diff --git a/net-p2p/mldonkey-devel/distinfo b/net-p2p/mldonkey-devel/distinfo
index 23d93aa2219e..adbd3292e7b7 100644
--- a/net-p2p/mldonkey-devel/distinfo
+++ b/net-p2p/mldonkey-devel/distinfo
@@ -1,3 +1,3 @@
-MD5 (mldonkey-2.8.1.tar.bz2) = 10452ad305f105d0d0761977f825694d
-SHA256 (mldonkey-2.8.1.tar.bz2) = 6ac802a918bb71c47e06193936b07d4ea161dc68d35853793986d0b6b51fa3c4
-SIZE (mldonkey-2.8.1.tar.bz2) = 2642676
+MD5 (mldonkey-2.8.2.tar.bz2) = 123aeb79a3ca91a4943b59f044e98d4a
+SHA256 (mldonkey-2.8.2.tar.bz2) = 51efc1c339b8cbafde93f4444f18e4243f41008b1c4107a41602542e9eeaa68e
+SIZE (mldonkey-2.8.2.tar.bz2) = 2652074
diff --git a/net-p2p/mldonkey-devel/files/patch-cvs-2006112100 b/net-p2p/mldonkey-devel/files/patch-cvs-2006112100
deleted file mode 100644
index 6a153b3b328d..000000000000
--- a/net-p2p/mldonkey-devel/files/patch-cvs-2006112100
+++ /dev/null
@@ -1,19589 +0,0 @@
-Index: config/Makefile.config.in
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/config/Makefile.config.in,v
-retrieving revision 1.62
-retrieving revision 1.63
-diff -u -r1.62 -r1.63
---- config/Makefile.config.in 26 Aug 2006 12:04:25 -0000 1.62
-+++ config/Makefile.config.in 23 Oct 2006 12:18:27 -0000 1.63
-@@ -58,6 +58,7 @@
- GD_JPG=@GD_JPG@
- GD_PNG=@GD_PNG@
- GD_LIBS=@GD_LIBS@
-+GD_STATIC_LIBS=@GD_STATIC_LIBS@
- GD_CFLAGS=@GD_CFLAGS@
- GD_LDFLAGS=@GD_LDFLAGS@
-
-Index: config/Makefile.in
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/config/Makefile.in,v
-retrieving revision 1.169
-retrieving revision 1.173
-diff -u -r1.169 -r1.173
---- config/Makefile.in 16 Aug 2006 19:08:21 -0000 1.169
-+++ config/Makefile.in 21 Nov 2006 22:29:58 -0000 1.173
-@@ -206,8 +206,6 @@
- $(NET)/cobs.ml \
- $(NET)/terminal.ml
-
--# $(NET)/tcpClientSocket.ml
--
- XML_SRCS= \
- $(XML)/xml_types.ml $(XML)/xml_parser.mly $(XML)/xml_lexer.mll \
- $(XML)/xml_dtd.ml $(XML)/xmlParser.ml $(XML)/xml.ml
-@@ -435,7 +433,6 @@
- $(SRC_BITTORRENT)/bTStats.ml \
- $(SRC_BITTORRENT)/bTTracker.ml \
- $(SRC_BITTORRENT)/bTChooser.ml \
-- $(SRC_BITTORRENT)/bTShare.ml \
- $(SRC_BITTORRENT)/bTClients.ml \
- $(SRC_BITTORRENT)/bTInteractive.ml \
- $(SRC_BITTORRENT)/bTMain.ml
-@@ -530,6 +527,9 @@
-
- ifeq ("$(GD)", "yes")
- GD_LIBS_flags=-cclib "-lgd $(GD_LIBS)" -ccopt "$(GD_LDFLAGS)"
-+ ifneq ("$(GD_STATIC_LIBS)", "")
-+ GD_STATIC_LIBS_opt=-cclib "-lgd $(GD_STATIC_LIBS)" -ccopt "$(GD_LDFLAGS)"
-+ endif
- DRIVER_SRCS= \
- $(CDK)/gd.ml \
- $(CDK)/gdstubs.c \
-@@ -1921,7 +1921,7 @@
- ./svg_converter.byte $@
-
- .ml.cmx :
-- $(OCAMLOPT) $(DEVFLAGS) $(PLUGIN_FLAG) $(OFLAGS) $(INCLUDES) -c $<
-+ $(OCAMLOPT) $(DEVFLAGSOPT) $(DEVFLAGS) $(PLUGIN_FLAG) $(OFLAGS) $(INCLUDES) -c $<
-
- .ml.cmo :
- $(OCAMLC) $(DEVFLAGS) $(OFLAGS) $(INCLUDES) -c $<
-Index: config/configure.in
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/config/configure.in,v
-retrieving revision 1.283
-retrieving revision 1.288
-diff -u -r1.283 -r1.288
---- config/configure.in 17 Sep 2006 18:42:57 -0000 1.283
-+++ config/configure.in 31 Oct 2006 15:40:05 -0000 1.288
-@@ -143,7 +143,7 @@
- SYSTEM=hpux
- ;;
- *darwin*|*rhapsody*|*macosx*)
-- SYSTEM=macosx
-+ SYSTEM=macos
- AC_CHECK_PROG(SED, sed, sed)
- if test "$ac_cv_prog_SED" = "sed"; then
- FIX_BROKEN_CPP="| sed -n '/^\#pragma/!p'"
-@@ -234,7 +234,7 @@
- AC_CHECK_PROG(CUT, cut, cut)
- if test "$ac_cv_prog_CUT" = "cut"; then
- SUB_VERSION3="CVS"
-- if [ test "$SYSTEM" = "freebsd"] || [ test "$SYSTEM" = "netbsd"] || ( [ test "$SYSTEM" = "macosx" ] && [ test "$ac_cv_prog_STAT" != "gstat" ] ); then
-+ if [ test "$SYSTEM" = "freebsd"] || [ test "$SYSTEM" = "netbsd"] || ( [ test "$SYSTEM" = "macos" ] && [ test "$ac_cv_prog_STAT" != "gstat" ] ); then
- SCM_VERSION=`$STAT -f "%Sm" ./CVS/Entries | $SED -e 's/\(.*\) \(.*\) \(.*\) \(.*\)/\4-\1-\2 \3/'`
- else
- if [ test "$SYSTEM" = "openbsd"]; then
-@@ -279,9 +279,9 @@
- MLDONKEY_VERSION=$MLDONKEY_VERSION.$SUB_VERSION3
- fi
-
--REQUIRED_OCAML=3.09.2
-+REQUIRED_OCAML=3.09.3
- DOWNLOAD_OCAML_MAJOR=3.09
--DOWNLOAD_OCAML=3.09.2
-+DOWNLOAD_OCAML=3.09.3
-
- REQUIRED_LABLGTK=1.2.7
-
-@@ -477,9 +477,10 @@
-
- AC_PATH_PROG(OCAMLC,ocamlc.opt,"",[$LOCAL_DIR/bin:$PATH])
- AC_CHECK_TOOL(OCAMLC,ocamlc,ocamlrun ocamlc)
-+AC_PATH_PROG(CAMLP4, camlp4,"",[$LOCAL_DIR/bin:$PATH])
-
- BUILD_OCAML=no
--if [ test -z "$OCAMLC" ] || [ test "$REQUIRED_OCAML" = "CVS" ]; then
-+if [ test -z "$OCAMLC" ] || [ test -z "$CAMLP4" ] || [ test "$REQUIRED_OCAML" = "CVS" ]; then
- BUILD_OCAML=yes
- else
- OCAMLVERSION=`$OCAMLC -v | sed -n -e 's|.*version* *\(.*\)$|\1|p' `
-@@ -487,7 +488,7 @@
- "$REQUIRED_OCAML"*) ;;
- 3.09.0*) ;;
- 3.09.1*) ;;
-- 3.09.3*) ;;
-+ 3.09.2*) ;;
- 3.08.4*) ;;
- 3.08.3*) ;;
- *)
-@@ -640,7 +641,7 @@
- "$REQUIRED_OCAML"*) ;;
- 3.09.0*) ;;
- 3.09.1*) ;;
-- 3.09.3*) ;;
-+ 3.09.2*) ;;
- 3.08.4*) ;;
- 3.08.3*) ;;
- *)
-@@ -789,6 +790,10 @@
- AC_CHECK_PROG(GDLIBCONFIG, gdlib-config, gdlib-config)
- if test "$ac_cv_prog_GDLIBCONFIG" = "gdlib-config"; then
- GD_LIBS=`$GDLIBCONFIG --libs`
-+ $GDLIBCONFIG --static-libs > /dev/null 2>&1
-+ if test "$?" = "0"; then
-+ GD_STATIC_LIBS=`$GDLIBCONFIG --static-libs`
-+ fi
- GD_LIBS2="$LIBS -lgd $GD_LIBS"
- LIBS=$GD_LIBS2
- GD_CFLAGS=`$GDLIBCONFIG --cflags`
-@@ -1330,11 +1335,6 @@
- echo "---------------------------------------------------------"
- fi
-
--case "$OCAMLVERSION" in
-- 3.06* | 3.07* | 3.08* ) TYPE_FORMAT="";;
-- *) TYPE_FORMAT="type ('a,'b,'c) ml_format = ('a,'b, 'c,'c) format4 type ('a,'b,'c) format = ('a,'b, 'c) ml_format";;
--esac
--
- if test "$OS_FILES" = "mingw"; then
- OCAMLDEP_OPTIONS="-slash"
- fi
-@@ -1351,7 +1351,6 @@
- AC_SUBST(CXX)
- AC_SUBST(FIX_BROKEN_CPP)
- AC_SUBST(CONFIG_INCLUDES)
--AC_SUBST(TYPE_FORMAT)
- AC_SUBST(OCAMLC)
- AC_SUBST(OCAMLLIB)
- AC_SUBST(OCAMLOPT)
-@@ -1411,6 +1410,7 @@
- AC_SUBST(GD_PNG)
- AC_SUBST(GDGRAPHICS)
- AC_SUBST(GD_LIBS)
-+AC_SUBST(GD_STATIC_LIBS)
- AC_SUBST(GD_CFLAGS)
- AC_SUBST(GD_LDFLAGS)
- AC_SUBST(BZIP2)
-Index: config/mldonkey.rc.in
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/config/mldonkey.rc.in,v
-retrieving revision 1.6
-retrieving revision 1.7
-diff -u -r1.6 -r1.7
---- config/mldonkey.rc.in 19 Jul 2005 19:01:38 -0000 1.6
-+++ config/mldonkey.rc.in 1 Oct 2006 17:46:11 -0000 1.7
-@@ -18,17 +18,16 @@
- {
- BLOCK "000004b0" // LANG_NEUTRAL,UNICODE_CP
- {
-- VALUE "Comments","MLdonkey is distributed under the terms of the GNU General Public License Version 2. Sourcecode is available at http://www.mldonkey.net\000"
-- VALUE "CompanyName", "mldonkey team\000"
-- VALUE "FileDescription", "MLdonkey - multiuser P2P daemon\000"
-- VALUE "FileVersion", "\000"
-- VALUE "InternalName", "Counter Counter\000"
-- VALUE "LegalCopyright", " (C) 2000-2005 mldonkey team (see README)\000"
-- // VALUE "LegalTrademarks"," "\000"
-- VALUE "OriginalFilename", "mlnet.exe\000"
-- VALUE "ProductName", "MLdonkey - multiuser P2P daemon\000"
-- VALUE "ProductVersion", "\000"
-- VALUE "SpecialBuild","\000"
-+ VALUE "Comments", "MLdonkey is distributed under the terms of the GNU General Public License Version 2. Sourcecode is available at http://mldonkey.sf.net"
-+ VALUE "CompanyName", "MLdonkey team, http://mldonkey.sf.net"
-+ VALUE "FileDescription", "MLdonkey - multiuser P2P daemon"
-+ VALUE "FileVersion", "@MLDONKEY_VERSION@"
-+ VALUE "InternalName", "MLdonkey"
-+ VALUE "LegalCopyright", "Copyright © 2000-2006 MLdonkey team (see README)"
-+ VALUE "OriginalFilename", "mlnet.exe"
-+ VALUE "ProductName", "MLdonkey - multiuser P2P daemon"
-+ VALUE "ProductVersion", "@MLDONKEY_VERSION@"
-+ VALUE "SpecialBuild", ""
- }
- }
- BLOCK "VarFileInfo"
-Index: distrib/Authors.txt
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/distrib/Authors.txt,v
-retrieving revision 1.5
-retrieving revision 1.6
-diff -u -r1.5 -r1.6
---- distrib/Authors.txt 4 Feb 2006 22:26:36 -0000 1.5
-+++ distrib/Authors.txt 23 Oct 2006 12:58:35 -0000 1.6
-@@ -36,12 +36,9 @@
- Schlumpf
- su_blanc
- bogeyman
--
--rlimit code taken from Ocaml-annexlib:
--Shawn Wagner <raevnos@pennmush.org>
--http://raevnos.pennmush.org/code/extlib/
--
--Fasttrack plugin from giFT-fasttrack:
--Markus Kern
-+jave
-
- This product includes GeoLite data created by MaxMind, available from http://maxmind.com/
-+
-+A complete overview about 3rd party libraries used can be found here:
-+http://mldonkey.sourceforge.net/3rdParty
-Index: distrib/Bugs.txt
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/distrib/Bugs.txt,v
-retrieving revision 1.2
-retrieving revision 1.3
-diff -u -r1.2 -r1.3
---- distrib/Bugs.txt 4 Feb 2004 12:13:36 -0000 1.2
-+++ distrib/Bugs.txt 23 Oct 2006 12:58:35 -0000 1.3
-@@ -1,7 +1,9 @@
--Before feeling a bug report form on
-- http://savannah.gnu.org/bugs/?group=mldonkey
-+Before sending a bug report form on
-+ http://savannah.nongnu.org/bugs/?group=mldonkey
- please, check that the bug is not already registered (then, add a comment).
-
-+To send a feature request please use the Task tracker
-+ http://savannah.nongnu.org/task/?group=mldonkey
- --------------------------------------------------------------------------
- If you think your bug is a very important one, and nobody has fixed it in a
- long time, it might be that we don't have enough information to reproduce it
-Index: distrib/ChangeLog
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/distrib/ChangeLog,v
-retrieving revision 1.1015
-retrieving revision 1.1108
-diff -u -r1.1015 -r1.1108
---- distrib/ChangeLog 17 Sep 2006 18:42:57 -0000 1.1015
-+++ distrib/ChangeLog 21 Nov 2006 22:34:33 -0000 1.1108
-@@ -14,6 +14,280 @@
- ChangeLog
- =========
-
-+2006/11/21
-+5579: Remove BasicSocket.[mini|maxi], replace them with Pervasives functions
-+- small fix for DonkeyOptions.max_allowed_connected_servers
-+5578: Remove unused files
-+- src/utils/net/tcpClientSocket.ml
-+- src/utils/net/tcpClientSocket.mli
-+- src/utils/net/tcpSocket.mli
-+5577: EDK: Send correct SUI tags
-+- sometimes MLDonkey sent SUI=true tag when CryptoPP was not linked
-+
-+2006/11/20
-+5568: EDK: Support CIDR and IP ranges in server_black_list (pango)
-+5574: allowed_ips: Fix list usage when 0.0.0.0/0 is part of the list (pango)
-+5570: Some log messages in gettext module (Schlumpf)
-+5569: HTML: Fix display bug in server list after js popups
-+ introduced by patch #5549 (Schlumpf)
-+5564: HTML: Remove non-working option use_html_frames (Schlumpf)
-+5563: EDK: Fix broken log message when master server changes (Schlumpf)
-+
-+2006/11/15
-+5556: web_infos: new option rss_preprocessor used for fixing broken RSS feeds,
-+ safer process spawning for command "!" (pango)
-+- broken feeds like http://thepiratebay.org/rss.php?cat=D601 can now be parsed
-+ directly using (for example) xmllint, if a feed can not be read be MLDonkey
-+ its piped through rss_preprocessor and read again
-+5560: EDK: Parse some more server.met fields, log unknown server tags
-+
-+2006/11/14
-+5424: web_infos/rss: shell:// type url
-+5549: EDK: Parse all data from server.met, new HTML javascript popup
-+5553: EDK/OV/KAD: small updates (bogeyman)
-+- EDK: log unknown client tags with verbosity mct
-+- OV/KAD: ignore OvernetPeerNotFound and log number of peers every
-+ 60 secs when logging
-+5551: web_infos: Fix mtime detection, old files were not updated
-+5550: debug_fileinfo: Print [a|c|m]time values
-+5530: GD: Improve graph output (skeeve, Schlumpf)
-+- html_mods_vd_gfx_h_grid_variable
-+ "Stretch hourly until at program start", default true
-+- html_mods_vd_gfx_h_grid_time
-+ "Max hours on time scale per grid (0 = no limit)", default 0
-+- html_mods_vd_gfx_subgrid
-+ "Number of shown subgrids on graph (0 = no subgrids)", default 0
-+
-+2006/11/13
-+5548: New search parameters: "-and", "-or", "-not", removed "-without"
-+ (Schlumpf)
-+5546: Some sharing updates
-+- solved bug 10957, updating the prio of an already shared dir is now possible
-+- fix bug where missing shared dirs with strategy incoming_* where not recreated
-+- remove "network = []" from downloads.ini, currently not supported
-+- created workaround to fix bug on MinGW: no files were shared. Introduced by
-+ patch 5475, but source of problem is Ocaml bug 4159
-+5547: HTML: Fix unicode display in vd & upstats javascript popups
-+
-+2006/11/12
-+5545: EDK: Do not show empty server message lines in GUI
-+5509: Common: Merge file_print functions,
-+ BT: print BT-specific source infos in Telnet (thx to jave)
-+5544: Clean up code to avoid otags warnings (pango)
-+5543: Improve exception handling, fix some indentions (pango)
-+5542: CommonSources: Work-around division-by-zero bug in Ocaml
-+ on Alpha platform (pango)
-+
-+2006/11/09
-+5526: Multiuser: Internal restructuring, new commands
-+- from ftp://ftp.berlios.de/pub/mldonkey/pango/userdb-cleanups_v2.patch (pango)
-+ - create commonUserDb.mli to protect userdb data from other modules
-+ - cleanups
-+- replace strings in commonFile with multiuser commonTypes.userdb/groupdb
-+- implement security checks when core starts
-+ - user "admin" must exist
-+ - group "mldonkey" must exist and must have admin status
-+- update HTML interface, command "users"
-+ - create link to remove a group from a user
-+ - create link to change group admin status
-+ - new column group members
-+- Telnet: Show all data in command "users"
-+- do not allow removal of users or groups with downloads,
-+ groups with members, user "admin" and group "mldonkey"
-+- filter files shown with command "downloaders"
-+- fixed bug where wrong group list was displayed in HTML, vd #file_num
-+- Display user and groups columns
-+ new options html_mods_vd_user & html_mods_vd_group to en-/disable display in HTML, vd
-+ - Javascript popups show User:Group infos
-+ - Telnet support
-+- implement new commands
-+ - usergroupadd <user> <group> : add a group to a mldonkey user
-+ - usergroupdel user> <group> : remove a group from a mldonkey user
-+ - userdgroup <user> <group|None> : change user default group
-+ - groupdel <group> : remove an unused mldonkey group
-+ - groupadmin <group> <true|false> : change group admin status
-+- Restrict commands to admin users:
-+ - bw_toggle
-+ - enable
-+ - disable
-+
-+2006/11/06
-+5527: mlguistarter: print correct syntax (fixes Debian bug #396754)
-+
-+2006/11/05
-+5481: Overnet: Small updates
-+- do not print opcode 18 (OvernetNoResult) as unknown message
-+- parse bcp type bcp://xxxxxxxxxxxxxxxxxxxxxxxxxxx:ip:tcpport:udpport
-+- print debug log message when a new source was added
-+5513: HTML: Let webinterface work in a HTML frame (ported from Knockers Mulus)
-+- third button row does not work yet, patches welcome
-+5521: BT: Fix non-working EDK upload when BT is enabled,
-+ introduced by patch 5461
-+
-+2006/10/31
-+5508: OV/KAD eMule style search and some small fixes (bogeyman)
-+5486: UDP bandwidth monitor fix (bogeyman)
-+5505: EDK: Support aMule/Hydranode style OS_INFO tag
-+
-+2006/10/30
-+5488: Multiuser: New commands
-+- groups -> displays groups of the logged-in user
-+- dgroup -> displays default group of the logged-in user
-+- restrict command "unshare" to admin users
-+
-+2006/10/29
-+5475: Multiuser: Implement user_commit_dir
-+- directories with strategy incoming_files are shared recursively now
-+- support several directories with incoming_* strategies, use the
-+ first one with enough space to commit the finished file
-+
-+2006/10/27
-+5499: Configure: find camlp4 in local, fix patch 5479 (dunk)
-+
-+2006/10/26
-+5477: BT: Add downloads to share list after core restart
-+
-+2006/10/25
-+5474: updated bw_toggle
-+- fix cosmetic bug, wrong values were displayed
-+ as a result if option_hook changed values
-+5489: HTML: Improve serverlist display (Schlumpf)
-+5487: Update URLs, change mldonkey.net to mldonkey.org
-+5485: HTML: Print sharing strategies in command "shares"
-+5461: Release slot, fix missing filenames in upstats
-+- Each downloading file can be set to status "Release", this can
-+ be done by clicking the "R" column in HTML, Transfers or by
-+ using the new "release <file_num>" command to toggle the state.
-+- A new option max_release_slots exists, default 20% of the default
-+ 5 max_upload_slots. This means 1 upload slot is available per default
-+ and granted for files with status "Release" when requested.
-+- Show filenames in pending upload slots list
-+5484: Fix DNS test, test other domains besides www.mldonkey.net
-+
-+2006/10/23
-+5474: New command bw_toggle (ported from Knockers Mulus client)
-+- two new options: max_hard_upload_rate_2 and max_hard_download_rate_2
-+- new command bw_toggle, quickly switch between two bandwidth options
-+5480: Update Mozilla protocol handler, cleanup docs in distrib/
-+5479: Configure: Force presence of camlp4
-+5478: Support gdlib-config --static-libs function (new on Debian Etch)
-+5476: Urladd: Change default period to 0 (load file only when core starts)
-+
-+2006/10/21
-+5473: Log: Redirect CryptoPP messages to MLDonkey logfile (Schlumpf)
-+5472: Urladd: New optional parameter period (in hours) (thx to Schlumpf)
-+5471: HTML: New colums for pending slots list: SUI, GeoIP, Filename
-+5470: Options: New type percent_option, values are bound to be >= 0 and <= 100
-+5469: HTML: Implement 404 error page for unknown URLs
-+
-+2006/10/20
-+5419: EDK: Re-implement titanesel.ws links - service is up again (thx to sk38)
-+
-+2006/10/13
-+5458: OV/KAD: tweak and bugfix the search (bogeyman)
-+
-+2006/10/12
-+5454: OV/KAD: Block blocked ips + small Overnet updates (bogeyman)
-+5451: HTML: clickable new messages indicator (jave)
-+
-+2006/10/09
-+5428: HTML: Fix style sheet errors (rwruck)
-+5446: EDK: Small update for EDK publish patch 5430
-+- new option max_published_files
-+ maximum number of files published to servers per minute, eMule default 200
-+- bug fix for patch 5430, publish also to non-preferred servers
-+
-+2006/10/08
-+5430: EDK: Improve file publishing
-+- publish no more than 200 files/minute to avoid server-side blacklisting,
-+ eMule uses the same limit,
-+ least published files are published first (thx to pango)
-+- respect server hard_limit, never publish more files to servers
-+- HTML: in server list display number of files published by server, by clicking
-+ on this number the list of files is displayed (new command server_shares num)
-+- HTML: diplay master server status, only master server are used for publishing
-+- HTML: in upstats display number of server the file was published to,
-+ also display server name + IP in javascript popup
-+- bug fix: properly update DonkeyGlobals.master_server to be used in
-+ DonkeyClient.read_first_message, this is used when replying to non-Overnet
-+ clients so they know to which server MLdonkey is connected to,
-+- remove development option become_master_delay
-+5445: Self-test charset conversion, disable conversion if test fails
-+5444: BT: Correctly display client connected time,
-+ also allow correct upload speed calculation (tradie)
-+5443: BT: do not allow connections with ourselves (tradie)
-+
-+2006/10/06
-+5442: BT: Verbose error messages when torrent is sent from GUI,
-+ BT-multiuser: Protect command seeded_torrents
-+5441: BT: Re-enable all trackers when file is resumed
-+5440: HTML: Strip CR from multiline dllink input to fix FileTP filenames
-+
-+2006/10/03
-+5439: Increase required ocaml version to 3.09.3 (schlumpf),
-+ remove old TYPE_FORMAT stuff needed for Ocaml < 3.06 (pango)
-+
-+2006/10/02
-+5297: In addition to previous patch 5297 force conversion of allowed_ips to
-+ IP blocklist when $MLDONKEY_DIR points to an existing directory
-+ and ini files are created for the first time
-+5429: Fix compile bug in Ocaml 3.08.3 (thx to eike for reporting)
-+
-+2006/10/01
-+5404: New command porttest, support for eMule- and Azureus-style porttest
-+ (thx to pango for Azureus result parsing)
-+5421: HTML: Add "Users" to options frame (unease)
-+5429: New common lprintf_file_nl function
-+5432: Updates and fixes for the Win resource file (schlumpf)
-+
-+2006/09/26
-+5407: BT: Improve handling of tracker error messages
-+- print additional information in telnet, vd #num already present in HTML
-+- show tracker errors in Telnet and HTML popups over tracker info lines
-+- pause torrents with no valid trackers left
-+5336: EDK: Fix lowid support (krissn)
-+5427: EDK: Increase hash speed when threads are available (pango)
-+
-+2006/09/25
-+5426: CommonSources: Reduce CPU load when refilling queues
-+ of many non-BT downloads (pango)
-+5425: FileTP: Support options file_started_cmd and pause_new_downloads
-+5423: Print warning for empty admin password only if allowed_ips was altered
-+5422: Command "sources": Display only downloading files
-+
-+2006/09/24
-+5405: BT: Use field "encoding" from .torrent to convert strings to UTF-8
-+5419: EDK: Remove titanesel.ws links
-+5418: Gnutella/G2/Fasttrack: Support client_bind_addr
-+5417: Edonkey comments: Telnet support, UTF-8 output in HTML
-+5416: Makefile.in: New variable $DEVFLAGSOPT for .cmx files (jave)
-+5415: New command option: rem disc - remove all disconnected servers
-+
-+2006/09/23
-+5414: Edonkey comments, update gui prot, some bt peer ids (zet)
-+- Reimplement edonkey file comments with ratings (ro)
-+ (fixes exploitable DOS introduced in patch #5371)
-+- Add options "comments_filter", "max_comments_per_file", "max_comment_length"
-+- GUI protocol updated for comments, stats, libmagic, users/groups
-+- BT: Identify some more peer ids, as well as the reserved bits
-+- Fix some html code and other bugs
-+- Minor code cleanup
-+
-+2006/09/22
-+5411: Portinfo: Rename gift_port to gift_port GUI
-+
-+2006/09/19
-+5406: Multiuser: Small bug fixed in recover_temp (mu2.patch)
-+5406: Main multiuser patch, see docs/multiuser.txt for details
-+ thx to jave, pango, zet and many other people who have helped
-+ to make this work possible
-+- this patch is experimental, if it breaks, you can keep the pieces;-)
-+- multigroup_usercommit.patch and multigroup_su.patch are not included
-+- this patch is still not finished, the To-Do list in docs/multiuser.txt
-+ is still long, also GUI protocol updates have to be implemented.
-+ To manage users, groups and files, its best to use the HTML interface,
-+ multiuser commands can also be used in Telnet interface.
-+-------------------------------------------------------------------------------
- 2006/09/17 version 2.8.1 = tag release-2-8-1
- 5401: Fix question whether to compile Ocaml with some bash versions (pango)
- 5400: Allow use of Ocaml 3.09.3, keep 3.09.2 as default
-Index: distrib/Developers.txt
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/distrib/Developers.txt,v
-retrieving revision 1.7
-retrieving revision 1.8
-diff -u -r1.7 -r1.8
---- distrib/Developers.txt 2 May 2005 17:50:33 -0000 1.7
-+++ distrib/Developers.txt 23 Oct 2006 12:58:35 -0000 1.8
-@@ -1,5 +1,5 @@
-
-- Yes, we are looking for developpers. If you have some programming skills,
-+ Yes, we are looking for developers. If you have some programming skills,
- you are welcome to help the development of mldonkey. There are different ways
- to help us. You can see a bug, or a missing feature, and fix it, and then
- send us a patch. If you want to spend more time, you can fix a lot of bugs, or
-Index: distrib/FAQ.html
-===================================================================
-RCS file: distrib/FAQ.html
-diff -N distrib/FAQ.html
---- distrib/FAQ.html 2 May 2005 17:50:33 -0000 1.6
-+++ /dev/null 1 Jan 1970 00:00:00 -0000
-@@ -1,1129 +0,0 @@
--<html>
--<head>
--<META name="robots" content="noindex, nofollow">
--<title>mldonkey FAQ</title>
--</head>
--<body bgcolor="#ffffff">
--
--
--<center>
--
-- <H1> <a href=index.html> mldonkey </a>: Frequently Asked Questions </H1>
--
--
-- <a href=faq.html> English </a>,
-- <a href=faq.html.de> Deutsch </a>,
-- <a href=faq.html.fr> Francais </a>
--o&nbsp;<a href=faq.html.es>Español</a>
--
--</center>
--
--<ol>
--
-- <a name=index_back>
-- <li> <h3> Background </h3> </a>
-- <ol>
-- <li> <strong> <a href=#back1> What is mldonkey ? </a> </strong>
-- <li> <strong> <a href=#back2> Why use Objective-Caml to program mldonkey ? </a> </strong>
-- <li> <strong> <a href=#back3> Where can I find support on mldonkey ? </a> </strong>
-- <li> <strong> <a href=#back4> Where can I download mldonkey ? </a> </strong>
-- <li> <strong> <a href=#back5> Where can I find mldonkey for Windows ? </a> </strong>
-- <li> <strong> <a href=#back6> What's new with MLdonkey 2.00 ? </a> </strong>
-- </ol>
--
-- <a name=index_run>
-- <li> <h3> Running mldonkey </h3> </a>
--
-- <ol>
-- <li> <strong> <a href=#run1> How should I start mldonkey ? </a> </strong>
-- <li> <strong> <a href=#run2> How can I control mldonkey ? </a> </strong>
-- <li> <strong> <a href=#run3> Where/what are mldonkey configuration files ? </a> </strong>
-- <li> <strong> <a href=#run4> How can I control the bandwidth used by mldonkey ? </a> </strong>
-- <li> <strong> <a href=#run5> When I modify an option in the config file, mldonkey overwrites it with its old value ? </a> </strong>
-- <li> <strong> <a href=#run6> Where are the files I have downloaded with mldonkey ? </a> </strong>
-- <li> <strong> <a href=#run7> Why does MLdonkey automatically pause some of my downloads ? </a> </strong>
-- <li> <strong> <a href=#run8> How can I reach mldonkey WEB interface
--if my firewall only allows port 80 ? </a> </strong>
-- </ol>
--
-- <a name=index_gui>
-- <li> <h3> Running the GTK GUI </h3> </a>
--
-- <ol>
-- <li> <strong> <a href=#gui1> When I start the GUI, I get a lot of error messages, and the GUI terminates with a "Segmentation Fault" ? </a> </strong>
-- <li> <strong> <a href=#gui2> I can't connect to mldonkey from a remote host, neither by telnet, WWW or the GUI ? </a> </strong>
-- <li> <strong> <a href=#gui3> The GUI is immediatly disconnected from the core, or keeps connecting and disconnecting very fast ? </a> </strong>
-- </ol>
--
-- <a name=index_build>
-- <li> <h3> Building mldonkey </h3> </a>
--
-- <ol>
-- <li> <strong> <a href=#build1> How can I download the latest sources of mldonkey ? </a> </strong>
-- <li> <strong> <a href=#build2> What do I need to compile mldonkey on my system ? </a> </strong>
-- <li> <strong> <a href=#build3> How do I compile mldonkey on my system ? </a> </strong>
-- <li> <strong> <a href=#build4> I just updated from CVS, and I get an error while compiling ? </a> </strong>
-- </ol>
--
-- <a name=index_edonkey>
-- <li> <h3> The eDonkey plugin </h3> </a>
--
-- <ol>
-- <li> <strong> <a href=#edonkey0> What is the eDonkey network ? </a> </strong>
-- <li> <strong> <a href=#edonkey1> Why can't mldonkey connect to any server ? </a> </strong>
-- <li> <strong> <a href=#edonkey2> How can I import my old edonkey files under mldonkey ? </a> </strong>
-- <li> <strong> <a href=#edonkey3> Where can I find files on eDonkey without searching on servers ? </a> </strong>
-- <li> <strong> <a href=#edonkey4> Why does mldonkey only connect 5
--servers, whereas <tt> max_connected_servers </tt> is greater ? </a> </strong>
-- <li> <strong> <a href=#edonkey5> What's about Overnet ? </a> </strong>
-- <li> <strong> <a href=#edonkey6> I'm behind a firewall, what should I do ? </a> </strong>
-- <li> <strong> <a href=#edonkey7> How can I share multiple directories ? </a> </strong>
-- </ol>
--
-- <a name=index_soulseek>
-- <li> <h3> The Soulseek plugin </h3> </a>
--
-- <ol>
-- <li> <strong> <a href=#slsk0> What is the Soulseek network ? </a> </strong>
-- <li> <strong> <a href=#slsk1> I can't connect to the server ? </a> </strong>
-- </ol>
--
-- <a name=index_limewire>
-- <li> <h3> The LimeWire plugin </h3>
--
-- <ol>
-- <li> <strong> <a href=#limewire0> What is the LimeWire network ? </a> </strong>
-- <li> <strong> <a href=#limewire1> When I search for files, I receive unrelated results ? </a> </strong>
-- </ol>
--
-- <li> <h3> The other plugins </h3>
-- <ol>
-- <li> <strong> <a href=#other1> What is the current Development Status of
--mldonkey plugins ? </a> </strong>
-- </ol>
--</ol>
--
--
--
--
--
--
--<ol>
--
--<hr>
--<li> <h2> Background </H2>
--
--<ol>
-- <li> <h3> <a name=back1> What is mldonkey ? </a> </h3>
--
--Formerly, mldonkey was a Linux client for the eDonkey network, built from
--a reverse-engineered version of the protocol. Now, it is also able to connect
--to multiple networks (gnutella, Direct-Connect, Soulseek, etc).
--
--<p>
--MLdonkey runs on most Unix clones: Linux (x86, alpha, sparc), Mac OS X,
--Solaris x86, Free/OpenBSD, etc.
--
--<p>
--
--It runs as a daemon, in the background, that can run, downloading and sharing
--files, 24 hours a day. You can interact with your mldonkey daemon, either
--locally or remotely, by a telnet interface, a WEB interface or a GTK
--GUI. Other GUIs have also been created for mldonkey.
--
-- <li> <h3> <a name=back2> Why use Objective-Caml to program mldonkey ? </a> </h3>
--
--Most programmers associate functional languages with languages theory,
--lambda-calculus, recursivity, and non-mutable variables, ie the most
--boring lectures at university.
--
--<p>
-- Fortunately, Objective-Caml is not only a functional language: it also
--provides many other programming paradigms, such as imperative constructs
--(<tt>while</tt> and <tt>for</tt> loops, mutable variables, records),
--object-oriented constructs, and a powerful C-interface. Moreover, its
--native-code compiler carefully checks your program for typing errors (no
--more segfaults !), and produces a very efficient code (even faster than C
--on many examples).
--
--<p>
--If you don't believe me, check the following links:
--<ul>
--<li>
--<a href="http://www.bagley.org/~doug/shootout/"> A comparison between many languages </a>
--<li> Two Objective Caml programs win first and second prizes at the
--<a href="http://www.cs.cornell.edu/icfp/"> ICFP'2000 programming contest </a>,
-- to write a ray-tracer program.
--<li> An Objective Caml program ranks first at the
--<a href="http://www.cs.virginia.edu/~jks6b/icfp/"> ICFP'1999 programming contest </a>.
--</ul>
--
--<li> <h3> <a name=back3> Where can I find support on mldonkey ? </a> </h3>
--
--The first place is the
--<a href="http://savannah.nongnu.org/projects/mldonkey/"> MLdonkey Project Site</a>
-- where you will find:
--
--<ul>
-- <li> The <a href="mailto:mldonkey-users@mail.freesoftware.fsf.org">
--mldonkey-users@mail.freesoftware.fsf.org </a> Mailing-list, where you can
--either contact the developpers or ask other users for advises.
-- <li> The
--<a href="http://savannah.nongnu.org/bugs/?group=mldonkey"> Bug Report
--system </a>
-- to report bugs appearing when running mldonkey.
-- <li> The
--<a href="http://savannah.nongnu.org/support/?group=mldonkey">
--Support system </a> where you can ask for support in running mldonkey.
--</ul>
--
--<p> You can also try to read/post in the
--<a href="http://www.mldonkeyworld.com/">
-- MLDonkey Forums </a> or on the IRC Channel #mldonkey on irc.freenode.net .
--
-- <li> <h3> <a name=back4> Where can I download mldonkey ? </a> </h3>
--
--The latest stable binaries can be downloaded from the
--<a href="http://savannah.nongnu.org/download/mldonkey/">
-- Project Download page </a>.
--
--If you want a more recent version of mldonkey, you need to check out the
--sources from the CVS, and compile it yourself.
--See <a href=#index_build> Building Mldonkey </a> for help.
--
--<li> <h3> <a name=back5> Where can I find mldonkey for Windows ? </a> </h3>
--
--MLdonkey does not run very well under Cygwin on Windows. Moreover, there
--is no native port of MLdonkey to Windows, so you will not be able to run
--it on these systems.
--
-- <p>
--
-- If you have some knowledge of MinGW, you might try to compile
-- Objective-Caml and mldonkey. It would probably run better than under
-- Cygwin. Note that mldonkey does not use threads, and the select call
-- is only used to descriminate between sockets (read/write/connect/accept).
--
--<li> <h3> <a name=back6> What's new with MLdonkey 2.00 ? </a> </h3>
--
-- If you were using MLdonkey 1.16, you might be interested in knowing what is new
-- with MLdonkey 2.00. Here are the main improvements:
--
-- <ul>
--
-- <li> Overnet support.
-- <li> Completely New GUI: upload panel, icons, configuration of many options.
-- <li> Post-filtering of results (see Overnet or LimeWire plugins).
-- <li> Multi-networks support (sources and CVS only).
-- <li> Many bug fixes: memory leak, "too many open file descrs", sharing,
-- upload/download rates, ...
-- </ul>
--
--</ol>
--
--<hr>
--<li> <h2> Running mldonkey </H2>
--
--<ol>
--
--<li> <H3> <a name=run1> How should I start mldonkey ? </a> </H3>
--
--mldonkey will install its configuration files in the directory where you
--start it. So, first, choose the right directory, where you want it to run.
--Then, copy the "servers.ini" file that is in the distribution in this
--directory. I suppose here that mldonkey is started in its directory.
--
--Start mldonkey with:
--
--<pre>
--./mldonkey
--</pre>
--
--It should display some debug info. DON'T CLOSE THE TERMINAL WHERE IT
--WAS STARTED, otherwise it might get blocked on terminal output.
--
-- Once you are sure it works correctly, you can dump the debug info in a file
--(but it can become very big) or better in /dev/null, the next time you
--start it:
--
--<pre>
--./mldonkey &> /dev/null
--</pre>
--
--<li> <h3> <a name=run2> How can I control mldonkey ? </a> </h3>
--
-- You have three different ways to control the mldonkey daemon (note that, by
--default, mldonkey is configured to accept only control connections from the
--host running mldonkey (<a href=#gui2> more info </a>)):
--
--<ul>
--
--<li> The telnet interface: the telnet interface allows you to control
--mldonkey locally or remotely from a terminal with simple commands:
--<pre>
--telnet localhost 4000
--</pre>
--where <tt> localhost </tt> is the host running mldonkey and 4000 is the
--default port for the telnet interface.
--
--<p>
--There are many commands available. Use the <tt> help </tt> command to
--display all of them.
--
--<li> The WEB interface: the WEB interface allows you to control mldonkey
--through your favorite navigator. The default url is:
--
--<pre>
--http://localhost:4080/
--</pre>
--
--where <tt> localhost </tt> is the host running mldonkey and 4080 is the
--default port for the WEB interface.
--
--<li> The GTK GUI: you can use a powerful GTK interface to control mldonkey.
--It is called <tt> mldonkey_gui </tt>. Use the File::Setting menu to
--configure how to connect to your mldonkey daemon.
--
--
--</ul>
--
--<li> <h3> <a name=run3> Where/what are mldonkey configuration files ? </a> </h3>
--
--MLdonkey creates its configuration files in the directory where it is
--started. All of them terminate with a .ini extension. You should not
--modify them while mldonkey is running since it periodically overwrites
--them. Instead you should either stop it, or modify the options using one of
--the interfaces.
--
--<ul>
--
--<li> <tt> downloads.ini </tt> : the basic options (and historically, the
--edonkey plugin options)
--<li> <tt> files.ini </tt> : the list of files being currently downloaded,
--and informations needed to recover the download after a stop.
--<li> <tt> servers.ini </tt> : the list of all known servers for all networks.
--<li> <tt> friends.ini </tt> : the list of your friends (peers you like to
--browse files) on all networks.
--
--<li> Other configuration files are used by mldonkey plugins, normally one
--per network.
--
--<li> <tt> ~/.mldonkey_gui.ini </tt> : the GUI configuration file is the
--only one which is not stored in the mldonkey directory.
--
--</ul>
--
--<li> <h3> <a name=run4> How can I control the bandwidth used by mldonkey ? </a> </H3>
--
--There are two options in the downloads.ini file: max_hard_upload_rate and
--max_hard_download_rate. Setting these options to 0 means that there are no
--limits. They are expressed in kilobytes/second (not kilobits/second !).
--The upload limit both applies to the files which are downloaded from you,
--and for the messages you send to ask for files: be careful not to limit
--your upload too much !
--
--<p>
--<table border="1" cellpadding="5" align=center>
--
--<tr>
--<td align=center> </td>
--<td align=center colspan=2> Low Bandwidth Usage </td>
--<td align=center colspan=2> High Bandwidth Usage </td>
--</tr>
--
--<tr>
--<td align=center> Your Connection Type </td>
--<td align=center> max_hard_upload_rate </td>
--<td align=center> max_hard_download_rate </td>
--<td align=center> max_hard_upload_rate </td>
--<td align=center> max_hard_download_rate </td>
--</tr>
--
--</tr>
--<td> T1 and more </td>
--<td align=center> 50 </td>
--<td align=center> 0 </td>
--<td align=center> 0 </td>
--<td align=center> 0 </td>
--</tr>
--
--</tr>
--<td> Cable/ADSL 512/128 kbs </td>
--<td align=center> 2 </td>
--<td align=center> 6 </td>
--<td align=center> 6 </td>
--<td align=center> 12 </td>
--</tr>
--
--</tr>
--
--If you have troubles with these values, find the best one corresponding to
--your link and send us the information to fix this table !
--
--</table>
--
--<li> <h3> <a name=run5> When I modify an option in the config file, mldonkey overwrites it
--with its old value ? </a> </h3>
--
--There are two cases:
--<ul>
-- <li> When you edit a config file, mldonkey must not run. Indeed, mldonkey
--saves its configuration periodically, overwritting any changes made in the
--files.
-- <li> Be careful with the syntax. If mldonkey can't parse the config file, it
--will generate a new file with the old values for all options that couldn't
--be read correctly. You must remember that you must put filenames and directory
--names between "" (they are not always required if there are no special
--characters inside the name (such as spaces, slashes, etc...), so mldonkey can
--remove them in some cases).
--
--</ul>
--
--<li> <h3> <a name=run6> Where are the files I have downloaded with
--mldonkey ? </a> </h3>
--
--Files being currently downloaded are temporarily stored in the <tt>
--temp/ </tt> directory at the level of mldonkey config files. Files in this
--directory are identified by their MD4 (for edonkey files) or by a random
--identifier.
--
--<p> When the download of a file is finished, the file is added to a list
--of files that have to be "committed". These files are not renamed, so they
--are still kept in the temp directory.
--
-- <p> To move finished downloads into the <tt> incoming/ </tt> directory with
--their final name, you need to use the command <tt> commit </tt> in the
--telnet, or the "Save" buttons in the GUI.
--
--<li> <h3> <a name=run7> Why does MLdonkey automatically pause some of my downloads ? </a> </h3>
--
-- When mldonkey receives data for a file from the network, it tries to write
--this data in the file in the temp/ directory. If, for some reason, it cannot
--write the data, it immediatly pauses the file.
--
--<p> This can happen for different reasons:
--
--<ul>
-- <li> You have no space left on the disk. You can verify it with the "df"
-- command, and free some space for the downloads to continue.
-- <li> The user running mldonkey has not write permissions to write in
-- your temp/ directory, or on the file temporary file.
--</ul>
--
--<li> <h3> <a name=run8> How can I reach mldonkey WEB interface
--if my firewall only allows port 80 ? </a> </h3>
--
--If you want to access the WEB interface (port 4080) through a firewall,
--and the firewall only allows port 80, and you don't want to run mldonkey
--as root, you can set up the apache WEB server to redirect requests to mldonkey:
--
--<ul>
-- <li> Edit your "httpd.conf" : Insert the following lines somewhere in the
--"Section 2: main server configuration":
--
--<pre>
--RewriteEngine on
--ProxyRequests on
--RewriteRule /mldonkey http://localhost:4080/$1 [P,L]
--RewriteRule /(submit.*) http://localhost:4080/$1 [P,L]
--RewriteRule /(files.*) http://localhost:4080/$1 [P,L]
--ProxyPassReverse /(.*) http://localhost:4080/$1
--</pre>
--
--where, of course, <tt> localhost </tt> is your mldonkey host, and <tt>
--4080 </tt> is the <tt> http_port </tt> of mldonkey.
--
--<li> With these rules, <tt> http://aaa.bbb.ccc.ddd/mldonkey </tt>,
--where <tt>aaa.bbb.ccc.ddd</tt> is the IP address of the host running the
--apache server, should connect to your mldonkey.
--
--</ul>
--
--</ol>
--
--<hr>
--<li> <h2> Running the GTK GUI </h2>
--
--<ol>
--
--<li> <H3> <a name=gui1> When I start the GUI, I get a lot of error messages,
--and the GUI terminates with a "Segmentation Fault" ? </a> </H3>
--
--You probably use the "static" binary of mldonkey GUI. Download the
--"shared" binaries from this site, and use that GUI. This bug is caused by
--an incompatibility between the statically linked GTK library and the
--themes installed on your distribution.
--
--<li> <H3> <a name=gui2> I can't connect to mldonkey from a remote host,
--neither by telnet, WWW or the GUI ? </a> </H3>
--
--You need to modify the "allowed_ips" option in the downloads.ini file to
--define which hosts are allowed to control your mldonkey core.
--
--You can either stop mldonkey, and edit the downloads.ini file:
--
--<pre>
--allowed_ips = ["127.0.0.1"; "192.168.255.255"; "65.64.43.63"]
--</pre>
--
--for example allows your localhost (127.0.0.1) to control mldonkey, all the
--hosts from the network 192.168.*.*, and the host 65.64.43.63.
--
--If you don't want to stop mldonkey, just connect locally with the telnet,
--and type:
--
--<pre>
--set allowed_ips "127.0.0.1 192.168.255.255 65.64.43.63"
--</pre>
--
--<li> <h3> <a name=gui3> The GUI is immediatly disconnected from the core, or keeps connecting and disconnecting very fast ? </a> </h3>
--
--There are two cases to consider:
--
--<ul>
--
--<li> You have set a password in the core to access it through the GUI: you
--must enter the password in the GUI too (use the <tt> Files :: Settings
--</tt> menu for that.
--
-- <li> You have two GUIs connected to the same core: the core (1.99 and
--later) only allows one GUI to be connected simultaneously. When you connect,
--it immediatly disconnects the previous GUI. This can only work if the
--previous GUI does not try to reconnect automatically: <tt> mldonkey_gui </tt>
--will not reconnect, but maybe you are using another contributed GUI, which
--tries to automatically reconnect, and make the core disconnect your GUI ?
--Then, tell its author to remove this feature or to put an option to disable
--it.
--
--</ul>
--
--</ol>
--
--<hr>
--<li> <h2> Building mldonkey </h2>
--
--<ol>
-- <li> <h3> <a name=build1> How can I download the latest sources
--of mldonkey ? </a> </h3>
--
-- Checkout the sources of mldonkey from the
--<a href="http://savannah.nongnu.org/cvs/?group_id=1409"> CVS repository </a>.
--Here is the standard procedure:
--
--<!--
--or download the
--<a href="http://freesoftware.fsf.org/cvs.backups/mldonkey.tar.gz">
--CVS tarball
--</a> (be careful, .
---->
--
--<pre>
--cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/mldonkey login
--(password: just hit enter)
--cvs -z3 -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/mldonkey co mldonkey
--</pre>
--
--
-- <li> <h3> <a name=build2> What do I need to compile mldonkey on my system ? </a> </h3>
--
-- You need ocaml-3.06 (<a href="http://caml.inria.fr/ocaml/distrib.html">
--Ocaml site </a>) installed
-- for the code
-- and <a href="http://wwwfun.kurims.kyoto-u.ac.jp/soft/olabl/lablgtk.html">
--lablgtk </a> compiled in native code with ocaml 3.06 for the GTK gui.
--
--The easiest way is to download binaries for your system. Otherwise, use
--the following lines to install them:
--
--<ul>
-- <li> Installing Objective-Caml 3.06 in <tt>/usr/local/bin</tt>
--
--<pre>
-- ~/tmp> tar zxf ocaml-3.06.tar.gz
-- ~/tmp> cd ocaml-3.06
-- ~/tmp/ocaml-3.06> ./configure
-- ~/tmp/ocaml-3.06> make world opt opt.opt
-- ~/tmp/ocaml-3.06> make install
--</pre>
--
--<li> LablGTK 1.2.3 for example
--
--<pre>
-- ~/tmp> tar zxf lablgtk-1.2.3.tar.gz
-- ~/tmp> cd lablgtk-1.2.3
-- ~/tmp/lablgtk-1.2.3> make configure
-- ~/tmp/lablgtk-1.2.3> make
-- ~/tmp/lablgtk-1.2.3> make opt
-- ~/tmp/lablgtk-1.2.3> make install
--</pre>
--
--Do not forget the "make opt" which is required to get a native-code version
--of the libraries.
--
--</ul>
--
-- <li> <h3> <a name=build3> How do I compile mldonkey on my system ? </a> </h3>
--
--
-- To compile the core, you just need to use the following commands:
-- <pre>
-- cd mldonkey
-- ./configure [...options...]
-- make depend
-- make
-- </pre>
--
-- You should now have a "mldonkey" executable ... No "make install" is
-- provided.
--
--<p> If you get strange errors from make, you probably need to use "gmake"
--on your system.
--
-- <p>
-- You can use the following options for the configure:
--<ul>
--<li> --enable-batch : install Objective-Caml and Lablgtk locally just
--to be able to compile mldonkey.
--<li> --disable-multinet: allows you to only compile support for edonkey
--<li> --disable-opennap: allows you to remove support for Open Napster
--<li> --disable-limewire: allows you to remove support for LimeWire
--<li> --disable-directconnect: allows you to remove support for Direct Connect
--<li> --disable-soulseek: allows you to remove support for SoulSeek
--<li> --disable-openft: allows you to remove support for OpenFT
--<li> --disable-donkey: allows you to remove support for eDonkey
--</ul>
--
--<li> <h3> <a name=build4> I just updated from CVS, and I get an error while compiling ? </a> </h3>
--
-- After an update from the CVS, you MUST restart the configure script, and
--rebuild the dependencies:
--
-- <pre>
-- cd mldonkey
-- cvs login
-- cvs -z3 up -d
-- ./configure [...options...]
-- make depend
-- make
-- </pre>
--
-- If the error messages are related to camlzip, a workaround is to edit
--manually the file <tt> config/Makefile.config </tt>, and to change the line
--<tt> ZLIB=no </tt> and <tt> SOULSEEK=no </tt> (only soulseek requires
--camlzip).
--
--</ol>
--
--<hr>
--<li> <h2> The eDonkey plugin </h2>
--
--<ol>
--
--<li> <H3> <a name=edonkey0> What is the eDonkey network ? </a> </H3>
--
-- The <a href="http://www.edonkey2000.com"> eDonkey network </a> is a network
--specialized in sharing really big files (between 0 to 1.4 GB).
--
--<p>
--This network offers a set of characteristics that cannot be found on other networks:
--<ul>
-- <li> Files can be downloaded from different sources at the same time.
-- <li> Files are identified by uniq identifiers (MD4) that can be used to find
-- new sources for a file.
-- <li> Files are checked using checksums, and chunks (9MB) that are corrupted
-- are downloaded again.
-- <li> Files chunks can be downloaded in any order.
-- <li> Files are shared as soon as a checked chunk has been downloaded, to
-- speed up the spreading of files.
--</ul>
--
--<li> <H3> <a name=edonkey1> Why can't mldonkey connect to any server ? </a> </H3>
--
--<ul>
-- <li> First, check that you have some servers known by mldonkey: connect
--to mldonkey by telnet (telnet localhost 4000) and use the "vma" command to
--display all known servers.
-- <li> If you have no servers known, you need to add a list of servers for
--mldonkey to connect to them: you can either:
-- <ul>
-- <li> Manually add them in the telnet :)
-- <li> Import a Windows server.met file (downloaded on the WEB):
-- use the "servers" command in the telnet, for example:
--
--<pre>
--servers "/mnt/windows/bureau/edonkey server list/server.met"
--</pre>
--
-- <li> You can restart mldonkey after copying the "servers.ini" file that
--was in the distribution.
-- </ul>
-- <li> If you already have a list of known servers, maybe the list is not
--up-to-date, and maybe the servers are full. Try to add some new servers
--like above.
--</ul>
--
--<li> <h3> <a name=edonkey2> How can I import my old edonkey files under mldonkey ? </a> </h3>
--
--<ul>
-- <li> Use the <tt>import</tt> command with the donkey directory containing your old
--config as parameter. If your old edonkey was running on
--<tt> /home/bidule/edonkey </tt> (mldonkey should find a "pref.met" file in
--this directory), you can send the following command on mldonkey console:
--
--<pre>
--import "/home/bidule/edonkey"
--</pre>
--
-- <li> This might not work for a Windows configuration, since the absolute
--path under windows is not the same as under linux (different mount points).
--In this case, retry this command, but before, make sure that:
--
--<ul>
-- <li> The files you want to import are in a "temp" directory, inside the
--directory you give to the "import" command.
-- <li> Remove the "pref.met" file, so that mldonkey does not try to use the
--temp directory specified in this file.
--</ul>
--
--</ul>
--
-- <li> <h3> <a name=edonkey3> Where can I find files on eDonkey without searching on servers ? </a> </h3>
--
-- There are two kinds of WEB sites where you can find <a href=#edonkey4>
--ed2k:// links </a> for files on eDonkey:
--
--<ul>
-- <li> Recommandation Engines: on these Web sites, you will find commented
-- files, that you are sure to find complete on the eDonkey network.
--
--<ul>
-- <li> The most famous is <a href="http://www.sharereactor.com"> Share
--Reactor </a>
--</ul>
--
-- <li> Search Engines: these Web sites allow you to search for files
--that are currently available on some servers. However, you have no
--guaranty they are complete:
--
--<ul>
-- <li> <a href="http://www.filedonkey.com"> File Donkey </a>
-- <li> <a href="http://www.jigle.com"> Jigle </a>
--</ul>
--</ul>
--
-- <li> <h3> <a name=edonkey4> Why does mldonkey only connect 5
--servers, whereas <tt> max_connected_servers </tt> is greater ? </a> </h3>
--
--Being connected to several servers can be useful to spread the files you
--are uploading, and to initially find more sources to begin a download.
--
--<p> However, each server on which you are connected is not available for
--another user. For this reason, you should not stay connected to too many
--servers. mldonkey enforces this policy by limiting to 5 the number of
--servers on which you remain connected for a long time, whatever the value
--of <tt> max_connected_servers </tt> is.
--
--<p> Thus, you should simply see <tt> max_connected_servers </tt> as the
--number of servers mldonkey tries to connect concurrently to at the
--startup, not as the number of servers he will remain connected to.
--
--<li> <h3> <a name=edonkey5> What's about Overnet ? </a> </h3>
--
-- <a href="http://www.overnet.com"> Overnet </a> is a network using the same
-- download protocol as edonkey, but a different
-- <a href="http://citeseer.nj.nec.com/529075.html"> search/localisation protocol </a>,
-- that doesn't need servers.
--
-- <p>
--
-- MLdonkey 2.00 is able to search for files and sources on Overnet. For that, you must
-- make sure that:
--
-- <ol>
--
-- <li> The "overnet_search_sources" and "overnet_search_keywords" options are set to
-- true.
--
-- <li> You have a (recent) list of Overnet peers that you can connect to. For that, you
-- can:
--
-- <ul>
-- <li> Use the "servers.ini" file from the most recent distribution of mldonkey. It
-- contains a long list of Overnet peers.
--
-- <li> Use the "boot IP PORT" command, to add a new peer.
--
-- <li> Use the "ovweb URL" command, to download a .ocl file from url URL
-- containing a list of recent peers.
--
-- </ul>
--
-- You can use the "ovstats" command, to display how many peers you have been able
-- to connect to (well, they have replied to a connect UDP packet).
--
-- <li> If you have enabled "overnet_search_keywords", replies to search can arrive from
-- Overnet peers. These results are not very accurate (they only need to match only
-- one of the keywords, instead of all for example).
--
-- <p>
--
-- As for all networks, you can activate post-filtering of results (very useful on
-- Gnutella too): set the "filter_search" option to true, and maybe the "filter_search_delay"
-- option (period between results updates in seconds). Then, only results matching exactly
-- your query will be displayed.
--
-- </ol>
--
-- <li> <h3> <a name=edonkey6> I'm behind a firewall, what should I do ? </a> </h3>
--
--MLdonkey uses two ports for incoming connections, one on TCP (default is
--4662) and the other one for UDP (4666). Thus, you should open these ports
--in your firewall, and forward them to the computer running mldonkey. More
--generally, you can do that for all ports between 4660 and 4670.
--
--<p> Allowing incoming connections is important as it is the only way for
--you to connect other sources which are behind a firewall.
--
--<p> If you have no control on the firewall, and your administrator blocks
--port 4660 to 4670, you should change the port used by mldonkey in the configuration
--file <tt> downloads.ini </tt> : <tt> port </tt> is the TCP port, while the
--UDP port is always computed as <tt> port + 4 </tt>.
--
--<li> <h3> <a name=edonkey7> How can I share multiple directories ? </a> </h3>
--
--Just edit the <tt> shared_directories </tt> option in <tt> downloads.ini </tt>:
--
--<pre>
--shared_directories = [ "/usr/share/documents"; "/usr/share/videos"]
--</pre>
--
--</ol>
--
--
--<hr>
--<li> <h2> The Soulseek plugin </h2>
--
--<ol>
--
--<li> <H3> <a name=slsk0> What is the Soulseek network ? </a> </H3>
--
--The <a href="http://www.soulseek.org"> Soulseek Network </a> is a network
--similar to Napster.
--
-- <p> You connect on a single server, and there, you can search for (mainly
--audio) files, you can join rooms to chat with other users, and you can browse
--other users files.
--
--<li> <H3> <a name=slsk1> Why can't mldonkey connect to any server ? </a> </H3>
--
--There is only one server on Soulseek, and the one you have in soulseek.ini
--is probably not up-to-date. Normally, mldonkey will download another one, so
--that you will have to servers in your list of servers.
--
--<p>
--By default, mldonkey_gui does not display the servers you are not
--connected to. So you have to use the "Display All Servers" button, and ask
--mldonkey to try to connect to the second soulseek server.
--
--<p>
--Currently, the server is <tt> mail.slsk.org </tt>, port 2242.
--
--<p>
--Mldonkey behavior will be improved to automatically connect to the current
-- server from the soulseek site Web page.
--
--</ol>
--
--<hr>
--<li> <h2> The LimeWire plugin </h2>
--
--<ol>
--
-- <li> <h3> <a name=limewire0> What is the LimeWire network ? </a> </h3>
--
-- The <a href="http://www.limewire.org"> LimeWire network </a> is a
--network built upon the <a href="http://www.gnutella.org"> Gnutella network </a>.
--
--<p>
--The main difference is that all nodes in this network do not broadcast each
--received message to its neighbours. Instead, special nodes, called
--ultra-peers, with higher connectivity are dedicated for this task, whereas
--other smaller nodes (such as mldonkey) only connect and ask ultra-peers.
--
--<p>
--Currently, the LimeWire support in MLdonkey also allows mldonkey client to
--use <a href="http://www.gnucleus.org"> Gnucleus </a>,
--<a href="http://www.morpheus.com"> Morpheus </a>, and MyNapster
--ultra-peers as servers.
--
--<p>
--On this network, you can mainly search for small files, you have no way to
--chat nor browse other peers.
--
-- <li> <h3> <a name=limewire1> When I search for files, I receive unrelated results ? </a> </h3>
--
--On Gnutella, there is no specified protocol for asking complex queries to
--other peers. Instead, each peer is free to interpret your query as it
--wants and reply what it wants.
--
--<p>
--In particular, multiple-words queries are often understood as logical-or
--queries between words, ie each document that contains at least one word is returned.
--
--<p>
-- As for Overnet, you can activate post-filtering of sources. Then, results
-- which are received are checked by mldonkey against the query and only displayed if
-- they are accurate. Post-Filtering is activated by setting the "filter_search" option
-- to true, and modifying the "filter_search_delay" depending on the period you
-- want between updates (for example, 30 means that results will be added only every
-- 30 seconds).
--
--</ol>
--
--<hr>
--<li> <h2> The other plugins </h2>
--
--<ol>
--<li> <h3> <a name=other1> What is the current Development Status of
--mldonkey plugins ? </a> </h3>
--
-- The current Development Status of mldonkey (in the CVS) at 2002/09/09 is
--shown on the following table (also have a look at the
--<a href="http://savannah.nongnu.org/cgi-bin/viewcvs/*checkout*/mldonkey/mldonkey/distrib/ChangeLog?rev=HEAD&content-type=text/plain">
--ChangeLog
--</a>)
--
--
--<table border="1" cellpadding="5">
--<tr bgcolor="#80FF80">
--<td align=center width="12%"> Features </td>
--<td align=center width="9%"> <a href=http://www.edonkey2000.com/> eDonkey </a> </td>
--<td align=center width="9%"> <a href=http://www.neo-modus.com/> Direct
--Connect </a> </td>
--<td align=center width="9%"> <a href=http://opennap.sourceforge.net/> Open
--Napster </a> </td>
--<td align=center width="9%"> <a href=http://www.limewire.org> Gnutella
--LimeWire </a> </td>
--<td align=center width="9%"> <a href=http://www.slsk.org> Soulseek </a> </td>
--<td align=center width="9%"> <a href=http://gift.sourceforge.net> OpenFT </a> </td>
--</tr>
--
--
--<tr>
--<td> Download Server List </td>
--<td align=center> 1.16 </td>
--<td align=center> CVS </td>
--<td align=center> CVS </td>
--<td align=center> CVS </td>
--<td align=center> CVS </td>
--<td align=center> CVS </td>
--<td align=center> &nbsp; </td>
--</tr>
--
--
--<tr>
--<td> Server Connect </td>
--<td align=center> 1.16 </td>
--<td align=center> CVS </td>
--<td align=center> CVS </td>
--<td align=center> CVS </td>
--<td align=center> CVS </td>
--<td align=center> CVS </td>
--<td align=center> CVS </td>
--</tr>
--
--
--<tr>
--<td> View Server Users </td>
--<td align=center> 1.16 </td>
--<td align=center> CVS </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--</tr>
--
--<tr bgcolor=yellow>
--<td> Search Files </td>
--<td align=center> 1.16 </td>
--<td align=center> CVS </td>
--<td align=center> CVS </td>
--<td align=center> CVS </td>
--<td align=center> CVS </td>
--<td align=center> (web) </td>
--<td align=center> CVS </td>
--</tr>
--
--<tr>
--<td> Browse Peer </td>
--<td align=center> 1.16 </td>
--<td align=center> CVS </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> CVS </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--</tr>
--
--<tr bgcolor=yellow>
--<td> Download Files </td>
--<td align=center> 1.16 </td>
--<td align=center> CVS </td>
--<td align=center> CVS </td>
--<td align=center> CVS </td>
--<td align=center> CVS </td>
--<td align=center> CVS </td>
--<td align=center> CVS </td>
--</tr>
--
--<tr>
--<td> Recover Files </td>
--<td align=center> 1.16 </td>
--<td align=center> CVS </td>
--<td align=center> CVS </td>
--<td align=center> CVS </td>
--<td align=center> &nbsp; </td>
--<td align=center> CVS </td>
--<td align=center> &nbsp; </td>
--</tr>
--
--<tr>
--<td> Recover Sources </td>
--<td align=center> 1.16 </td>
--<td align=center> CVS </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> CVS </td>
--<td align=center> CVS </td>
--</tr>
--
--<tr>
--<td> Pause Downloads </td>
--<td align=center> 1.16 </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> CVS </td>
--<td align=center> &nbsp; </td>
--</tr>
--
--<tr>
--<td> Cancel Downloads </td>
--<td align=center> 1.16 (not CVS) </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> CVS </td>
--<td align=center> &nbsp; </td>
--</tr>
--
--
--<tr bgcolor=yellow>
--<td> Upload Files </td>
--<td align=center> 1.16 </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--</tr>
--
--
--<tr>
--<td> Upload File List </td>
--<td align=center> 1.16 </td>
--<td align=center> CVS </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--</tr>
--
--
--<tr>
--<td> Friends </td>
--<td align=center> 1.16 </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--</tr>
--
--<tr>
--<td> Public Messages </td>
--<td align=center> &nbsp; </td>
--<td align=center> CVS </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> CVS </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--</tr>
--
--
--<tr>
--<td> Private Messages </td>
--<td align=center> 1.16 </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--</tr>
--
--<tr>
--<td> Import Windows Config </td>
--<td align=center> 1.16 </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--<td align=center> &nbsp; </td>
--</tr>
--
--<tr>
--<td> Config File </td>
--<td align=center> downloads.ini </td>
--<td align=center> directconnect.ini </td>
--<td align=center> opennap.ini </td>
--<td align=center> limewire.ini </td>
--<td align=center> soulseek.ini </td>
--<td align=center> openft.ini </td>
--</tr>
--
--<tr>
--<td> Disable Network </td>
--<td align=center> CVS </td>
--<td align=center> CVS </td>
--<td align=center> CVS </td>
--<td align=center> CVS </td>
--<td align=center> CVS </td>
--<td align=center> CVS </td>
--<td align=center> CVS </td>
--</tr>
--
--</table>
--
--
--</ol>
--
--</ol>
--
--<p>
--
--If you have any comments, if you want to add some questions, or improve
--this FAQ, send a mail to <a href="mailto:mldonkey@mldonkey.net">
--mldonkey@mldonkey.net </a>
--
--</body>
--</html>
-Index: distrib/Install.txt
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/distrib/Install.txt,v
-retrieving revision 1.10
-retrieving revision 1.11
-diff -u -r1.10 -r1.11
---- distrib/Install.txt 3 Feb 2006 00:45:15 -0000 1.10
-+++ distrib/Install.txt 23 Oct 2006 12:58:35 -0000 1.11
-@@ -63,17 +63,17 @@
- is compiled.
-
- ------------------------------------------------------------------------
--1) Installing required tools: Objective-Caml 3.08.3 and LablGTK
-+1) Installing required tools: Objective-Caml 3.09.3 and LablGTK
-
-- 1.1) Objective-Caml 3.08.4 (from http://pauillac.inria.fr/caml)
-+ 1.1) Objective-Caml 3.09.3 (from http://pauillac.inria.fr/caml)
-
-- ~/tmp> wget http://caml.inria.fr/distrib/ocaml-3.08/ocaml-3.08.4.tar.gz
-- ~/tmp> tar zxf ocaml-3.08.4.tar.gz
-- ~/tmp> cd ocaml-3.08.4
-+ ~/tmp> wget http://caml.inria.fr/distrib/ocaml-3.09/ocaml-3.09.3.tar.gz
-+ ~/tmp> tar zxf ocaml-3.09.3.tar.gz
-+ ~/tmp> cd ocaml-3.09.3
-
-- ~/tmp/ocaml-3.08.4> ./configure
-- ~/tmp/ocaml-3.08.4> make world.opt
-- ~/tmp/ocaml-3.08.4> make install
-+ ~/tmp/ocaml-3.09.3> ./configure
-+ ~/tmp/ocaml-3.09.3> make world.opt
-+ ~/tmp/ocaml-3.09.3> make install
-
- 1.2.1) LablGTK 1.2.7 for GTK1
- (from http://wwwfun.kurims.kyoto-u.ac.jp/soft/olabl/lablgtk.html)
-@@ -86,22 +86,22 @@
- ~/tmp/lablgtk-1.2.7> make opt
- ~/tmp/lablgtk-1.2.7> make install
-
-- 1.2.2) LablGTK-2.4.0 for GTK2
-+ 1.2.2) LablGTK-2.6.0 for GTK2
- (from http://wwwfun.kurims.kyoto-u.ac.jp/soft/olabl/lablgtk.html)
-
-- ~/tmp> wget http://wwwfun.kurims.kyoto-u.ac.jp/soft/olabl/dist/lablgtk-2.4.0.tar.gz
-- ~/tmp> tar zxf lablgtk-2.4.0.tar.gz
-- ~/tmp> cd lablgtk-2.4.0
-- ~/tmp/lablgtk-2.4.0> ./configure
-- ~/tmp/lablgtk-2.4.0> make world
-- ~/tmp/lablgtk-2.4.0> make install
-+ ~/tmp> wget http://wwwfun.kurims.kyoto-u.ac.jp/soft/olabl/dist/lablgtk-2.6.0.tar.gz
-+ ~/tmp> tar zxf lablgtk-2.6.0.tar.gz
-+ ~/tmp> cd lablgtk-2.6.0
-+ ~/tmp/lablgtk-2.6.0> ./configure
-+ ~/tmp/lablgtk-2.6.0> make world
-+ ~/tmp/lablgtk-2.6.0> make install
-
- 2) Compiling mldonkey with GUI:
-
- To build GTK1 newgui: ./configure --enable-gui=newgui1
- To build GTK1 oldgui: ./configure --enable-gui=oldgui
- To build GTK2 GUI: ./configure --enable-gui[=newgui2]
-- lablgtk-1.2.7 and lablgtk-2.4.0 can both be installed at the same time.
-+ lablgtk-1.2.7 and lablgtk-2.6.0 can both be installed at the same time.
-
- ~/tmp/mldonkey> make
-
-Index: distrib/Readme.txt
-===================================================================
-RCS file: distrib/Readme.txt
-diff -N distrib/Readme.txt
---- distrib/Readme.txt 1 May 2005 17:43:11 -0000 1.16
-+++ /dev/null 1 Jan 1970 00:00:00 -0000
-@@ -1,433 +0,0 @@
-- *** THIS FILE IS OUTDATED. PLEASE HAVE A LOOK AT THE ***
-- *** WIKI PAGE FOR BASIC INFORMATION ABOUT INSTALLING ***
--
--
-- MLDonkey
-- ========
--
--Release: 1.16
--Authors: [b8]_bavard (Communication engine) and [b8]_Zoggy (GUI)
--
-- MLDonkey is a door to the 'donkey' network, a decentralized network used to
--exchange big files on the Internet. It is written in a wonderful language,
--called Objective-Caml, and present most features of the basic Windows donkey
--client, plus some more:
-- - It should work on most UNIX-compatible platforms.
-- - You can remotely command your client, either by telnet, on a WEB browser,
-- or with the GTK interface.
-- - You can connect to several servers, and each search will query all the
-- connected servers.
-- - You can select mp3s by bitrates in queries (useful ?).
-- - You can select the name of a downloaded file before moving it to your
-- incoming directory.
-- - You can have several queries in the graphical user interface at the same
-- time.
-- - You can remember your old queries results in the command-line interface.
-- - You can search in the history of all files you have seen on the network.
--
--
--USAGE:
--======
--
-- This package contains three files: 'mldonkey', 'mldonkey_gui' and
--servers.ini'.
--
--'mldonkey' is the main program, a daemon which is used to download files.
--It takes no argument, and outputs some debugging messages on his terminal,
--so you should not close it. So, to start your program in the background,
--you can use:
--
--prompt> ./mldonkey > mldonkey.log &
--
-- 'mldonkey' expects to find several .ini files in the directory
--where it is started. You can use the file provided in this package, or your
--old one if you already used 'mldonkey' before. It contains a list of servers
--that were available when the release was done. You can edit 'downloads.ini'
--to modify its parameters before starting 'mldonkey', but you can also
--modify the parameters in the graphical user interface 'mldonkey_gui'.
--
-- 'mldonkey_gui', the graphical user interface, can be started by:
--
--prompt> ./mldonkey_gui &
--
-- 'mldonkey_gui' doesn't need to be started in the same directory as
--'mldonkey'. Without parameters, it expects to find 'mldonkey' running on the
--same computer on the default port. If you started 'mldonkey' on another
--computer, you should specify the hostname (myhost.mydomain.mydot for example)
--on the command line:
--
--prompt> ./mldonkey_gui myhost.mydomain.mydot
--
-- If you also modified the GUI port, you can also specify it (here 9999 for
--example) on the command line:
--
--prompt> ./mldonkey_gui myhost.mydomain.mydot 9999
--
-- You can also start the GUI, and modify these settings in the Options panel,
--and then try to reconnect. This is anyway necessary if you have put a
--password.
--
-- Instead of using the GUI, you can also telnet to the daemon:
--
--prompt> telnet localhost 4000
--
--(on your local computer) or
--
--prompt> telnet myhost.mydomain.mydot
--
--(if the client was started on that host).
--
--Using the config the standard core :
--===================================
-- Connect to mldonkey by telnet:
--
--prompt> telnet localhost 4000
--
-- Use the 'import' command with the donkey directory containing your old
--config as parameter.
--
--import '/.../donkey2000'
--
-- All the files which were currently downloading will be moved to mldonkey
--temp directory, and the server list will be imported too.
--
-- If you only want to import the server.met file, use the 'servers' command:
--
--servers '/.../donkey2000/server.met'
--
-- Filenames containing special characters (such as spaces) should be put
--inside ''.
--
--
--Frequently Asked Questions
--==========================
--
--*) How can I contact the authors ?
------------------------------------
--
--You can reach us for a short time on
--
-- mldonkey@mldonkey.net
-- mldonkey-users@non-gnu.org
--
--Please don't bother us too much with questions on how to use mldonkey. We
--prefer bug reports, containing USEFUL information to find the bug. You can
--also submit bugs on the savannah WEB site:
--
-- http://www.freesoftware.fsf.org/mldonkey/
--
--For advices on how to use mldonkey, you can check several forums:
--
-- http://www.mldonkeyworld.com/
-- http://www.mldonkey.org/ (German forum)
--
--*) What about the sources ? What about the protocol ?
-------------------------------------------------------
--
--All sources are available on the savannah WEB site:
--
-- http://www.freesoftware.fsf.org/mldonkey/
--
--*) The GUI/telnet/WEB can't connect to the core.
-------------------------------------------------
--
--Since version 1.12, there is an option to control which computers can
--connect to mldonkey: allowed_ips
--
--By default, this option only allows your local computer to connect to the
--core. You can change this either by editing the downloads.ini file, or, in
--the console, using the
--
--set allowed_ips '127.0.0.1 A.B.C.D ...'
--
--command, where A.B.C.D ... are IP addresses separated by spaces.
--
--*) I added a password, and now the connection between the client and
-- the GUI is immediatly aborded at startup. What should I do ?
----------------------------------------------------------------
--
-- Start the GUI. In the Options panel, type your password, and ENTER.
-- Then reconnect to the client (menu or CTRL-R).
--
--*) How can I see the upload information ?
-------------------------------------------
--
--In mldonkey, you cannot directly know the current upload state of your
--core. There is a 'upstats' command which can be used to get sorted
--information on the files which have been requested.
--
--Two options are used to control upload:
--- 'max_upload_rate' controls the maximal bandwidth you accept to provide
--on upload. The minimun is 1 (kB/s).
--- 'shared_directories' is the list of directories that you want to share.
--By default, the list is empty, since the temp/ and incoming/ dirs are always
--shared.
--
--You can also disable upload for short periods of time with the 'nu' command.
--Before you must have ran mldonkey at least 5*m minutes if you want to
--disable upload for m minutes. You cannot disable upload for more than
--5 hours per day. Your credit can be displayed with the 'vu' command.
--
--*) How can I modify parameters that don't appear in the GUI nor in the
--command-line client ?
------------------------
--
--mldonkey uses a file called 'downloads.ini'. You must stop your donkey client
--(use the Kill menu in the GUI or the 'kill' command in the telnet client).
--Then, edit this file and change the values of the options you want.
--
--Some options can also be modified by the 'set' command (in the command-line
--client or in the console of the GUI). These options appear when you use
--the 'vo' command.
--
--*) How can I communicate with the client ?
--------------------------------------------
--
--There are three ways to communicate with the client. In all the cases, you
--can run the client on one computer and control it from another computer.
--In these examples, we suppose they both run on the local computer 'localhost':
--
-- 1) Use the GUI, called 'mldonkey_gui':
--
--prompt> ./mldonkey_gui localhost
--
-- 2) Use the command-line client:
--
--prompt> telnet localhost 4000
--
-- 3) Use a WEB browser:
--
--prompt> lynx http://localhost:4080/
--
--*) How can use the GUI on MacOS X ?
-------------------------------------
--
--First, you need to have an X server installed. See for more information:
--
-- http://fink.sourceforge.net/doc/x11/index.php
--
--You will find a script in the tar file to start the GUI, that set the
--correct library path for most systems. If it doesn't work, you need to
--modify it according to your non-standard configuration.
--
--*) Previewing doesn't work ?
------------------------------
--
--mldonkey tries to start a script, specified by the 'previewer' option.
--By default, this option calls 'mldonkey_previewer', which must be in your
--path. Its first arg is the name of the file on the local disk, while its
--second arg is the name of the file on the donkey network.
--
--*) I started mldonkey, and it didn't connect to any server !
-------------------------------------------------------------
--
--Depending on your list of servers, the process of finding a server available
--can take a while. You can try to modify some options, such as the server
--connection timeout or the delay between connections attempts. If you know
--a good server, use 'c 34' if 34 is for example the number of the server
--in the list 'vma'. You can also select some servers in the GUI, and use the
--connect button/menu.
--
--*) Which ports should I open on my firewall ?
----------------------------------------------
--
--By default, mldonkey uses ports 4662 for tcp connections, and port 4666 for
--udp connections. If you change the tcp port, udp port will be tcp_port + 4.
--Therefore, you should allow your firewall to send incoming connections and
--messages on these ports to your local network.
--
--
--Help on the command-line interface
--==================================
--
--In a different shell, telnet to your application by:
--
--prompt> telnet localhost 4000
--
--4000 is the default port for connecting with the command-line client.
--Command-line client is disabled if you have set a password.
--
--Then, use ? to find some help on available commands. Some commands are only
--available in the graphical interface (setting options for example), others
--only in the command-line interface (import of old donkey config for example).
--
--Here is the output of the help command for version 1.12:
--n <ip> [<port>]: add a server
--vu : view upload credits
--nu <m> : disable upload during <m> minutes (multiple of 5)
--import <dirname> : import the config from dirname
--x <num> : disconnect from server
--servers <filename> : add the servers from a server.met file
--commit : move downloaded files to incoming directory
--vd <num>: view file info
--reshare : check shared files for removal
--vm : list connected servers
--vma : list all known servers
--q : close telnet
--kill : save and kill the server
--save : save
--d <size> <md4> : download this file
--upstats : statistics on upload
--port <port> : change connection port
--vo : print options
--set <option_name> <option_value> : change option value
--vr [<num>]: view results of a search
--forget <num> : forget search <num>
--ls <query> : local search
--s <query> : search for files
--
-- With special args:
-- -minsize <size>
-- -maxsize <size>
-- -media <Video|Audio|...>
-- -Video
-- -Audio
-- -format <format>
-- -field <field> <fieldvalue>
-- -not <word>
-- -and <word>
-- -or <word> :
--
--vs : view all queries
--cancel <num> : cancel download
--xs : extended search
--clh : clear local history
--c [<num>]: connect to more servers (or to server <num>)
--
--
--Help on the graphical user interface
--====================================
--1. Servers page:
--
--The server page presents the list of known servers. For each server, the list
--provides information on its IP address, port, connexion status, name,
--description, number of users and number of files.
--
--The list is automatically updated when new servers are discovered. MLDonkey
--tries to automatically connect to servers until enough (see the
--'Max connected servers' option) of them have replied.
--
--To add a server: enter its IP and Port, and press the 'Add server' button.
--To remove a server: select the server, and click the 'Remove' button.
--To connect a server: select the server, and click the 'Connect' button.
--To view server users: select the server, and click the 'View Users' button.
-- If the list of users is already available, it is automatically displayed in
-- the list on the right when the server is selected.
--To add some user to your friend list: select the users, and click the
-- 'Add to friends' button. Direct users (those with a valid IP address)
-- are immediatly added, while others are only added when they are
-- connected.
--The 'Connect more servers' button: if not enough servers are connected,
-- you can click this button to speed connections to servers.
--The 'Remove old servers' button: this button allows to clean the list of
-- servers which have not been connected for a while (see the
-- 'Max server age' option).
--
--2. Downloads page:
--
--When you select a file, its full name is displayed under the list of
--files. A bar indicates which chunks of the file are available:
--red means the chunks is not available and blue is for chunks which are
--available on only one client. Black is for chunks that are available on
--several clients, whereas green means you already have the chunk.
--Chunks are 9mb of consecutive bytes in the file.
--
--You can put ed2k:// URLs (those found on www.sharereactor.com) in the
--upper entry (after the ed2k: label). Press ENTER then.
--
--If you started a download and lost the config files for some reason, you can
--recover it in the upper right entry (Recover MD4) if it is still present under
--this MD4 in your temp/ directory.
--
--When selecting a file in the 'Downloading' list, the GUI will display the list
--of its locations on the right side. You can select some of these locations,
--and click the 'Add to friends' button to add them to your friends.
--
--When a download is finished, files are displayed in the 'Downloaded' list.
--You can use the 'Save all files' button to move these files to your
--incoming/ directory. This is not done automatically. You can also click on the
--right button of the mouse to have a contextual menu where you can select the
--name of the file. You can edit the tags of mp3 too in this menu.
--
--3. Friends page:
--
--Friends are displayed on the left, with the list of their files on the
--right. You can remove a friend by selecting it and clicking the 'Remove'
--button. You can also search all connected servers for a friend by
--putting its name in the 'Find Friend' entry and pressing ENTER.
--
--You can select files in the list on the right, then click
--'Download Selected Files' to add them to your download list.
--
--4. Queries page:
--
--'Max Hits' is not working yet.
--
--Use the 'Stop' button to stop receiving results for a query.
--
--5. Options page:
--
--This page can be used to update the simple options of the configuration
--file 'downloads.ini', which can be found in the directory where
--'donkey_downloads' was started.
--
--Interesting options are:
--
--'Name': your name on the donkey network.
--
--'Max Connected Servers': the maximum number of servers you can remain
--connected to. This is an old option, that was useful before UDP packets.
--1 is now enough, since all servers will eventually be searched by UDP.
--
--'Upload limit': default is 30 kB/s (good for ADSL/Cable). You can't set it
-- under 1kB/s. If you have a large bandwith, set it to 500 kB/s or +
--
--'Client hostname': the name of the host were your client is running if not
-- the same host as the graphical interface.
--
--'Password': the password used to control your client.
--
--The different ports that can be modified in the Option panel can be used to
--allow several clients to run on the same computer. Moreover, several user
--interfaces can connect to the same client at the same time (command-line
--interfaces and graphical interfaces).
--
--6. Console
--
--In the console, you have access to the command-line commands.
--
--Using auxiliary programs for local indexation (in development)
--=============================================
--
--mldonkey now uses auxiliary programs to help find results to search.
--Currently, two types of programs are supported:
--
--- Finder (set by the 'local_index_find_cmd' option)
-- The finder receives a query on its standard input, and replies by
-- the results on its standard output.
--
--Query format: the query finishes with 'end_query' on one line. On each line
--of the query, there is one keyword, a colon :, and a value. Keywords are:
-- words, minsize, maxsize, minrate, media, format, title, album, artist
--
--Result format: the result finishes with 'end result' on one line. On each line
--of the result, there is one keyword, a colon :, and a value.
--Keywords are:
-- Required: md4, size
-- Optional: name, format, type, string_tag, int_tag
--
--There can be several name, string_tag, int_tag lines. The value on the
--string_tag line should be the name of the tag, a colon : and the value of
--the tag. Idem for int_tag, but the value should be an integer.
--
--- Indexer (set by the 'local_index_add_cmd' option)
--The indexer is called each time a new result is received by mldonkey,
--and the result is given on its standard input in the same format as specified
--above. It can be used to add the result to the index that is used by the
--Finder.
--
--Known bugs:
--===========
-- * When clicking on the columns it sorts on that column, when
-- clicking again it should do a reverse sort on it, but it doesn't.
--
-Index: distrib/Todo.txt
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/distrib/Todo.txt,v
-retrieving revision 1.10
-retrieving revision 1.11
-diff -u -r1.10 -r1.11
---- distrib/Todo.txt 1 Nov 2004 11:22:59 -0000 1.10
-+++ distrib/Todo.txt 23 Oct 2006 12:58:35 -0000 1.11
-@@ -9,15 +9,6 @@
- (1) Why is the QRT sent so often ?
- (2) Implement PUSH in Gnutella and Fasttrack
-
--(9) When a file is commited, it should not be shared anymore in temp/.
-- Moreover, in temp, it should not be shared under is URN name.
--(10) CANCEL A FILE, AND RESTART THE DOWNLOAD: <<<<<<<<<
--
--
--
--
--
--Before 2.6:
- * Re-implement contributors in CommonSwarming
- * Re-implement already downloaded files.
-
-@@ -27,7 +18,6 @@
- downloaded chunks for itself or the primary network.
- * Does the PartialChunk strategy work ?
- * Why are chunks verified before completeness ?
-- * After a while, shared files are not shared anymore ! why ???
- * When a connection succeeds and downloads, we should retry the connection
- ASAP.
- * How to remove servers from disabled networks ?
-@@ -61,30 +51,14 @@
-
- BUGS:
-
--* "FT not respecting max sources per file settings"
--http://savannah.nongnu.org/bugs/index.php?func=detailitem&item_id=3761
--FT plugin AFAIK has no limits regarding the size of the serverlist
--
--* FT plugin is not able to get a list of working peers
--http://savannah.nongnu.org/bugs/index.php?func=detailitem&item_id=7776
--
--* "Search results appear in the wrong search"
--http://savannah.nongnu.org/bugs/index.php?func=detailitem&item_id=6956
--
- Flush buffers after do_at_exit (wait 5 secondes after exit ?).
--Share only on some networks.
--Add information in the GIU protocol on who uploads what.
- Send relative times in the GUI protocol
--IP blocking in net/ : http://www.peerguardian.net/pgipdb/guarding.p2p
-
- ************************************************************************
- Edonkey:
-- * Extension to download small files immediatly (files smaller than 10k for
-- example)
- * Verify that make_xs is always synchronized with sources searches.
- * Add command 'export_temp' so that they can be used from emule/edonkey
- * EmuleMobile ?
-- * BUG: commited files are not shared
- * BUG: MLdonkey client generates "Exceeding Block Boundaries" errors which
- loses bandwidth
- * Implement more Emule packets
-@@ -93,8 +67,6 @@
- OP_REASKACK (0x91) (size=2)
- OP_FILENOTFOUND (0x92)
- * Extended search doesnot work after connect because no ping was sent.
-- * BUG: Cancel and Redownload doesnot work
-- * BUG: Files randomly pause
-
- BitTorrent:
- * Implement file availability as in edonkey.
-@@ -113,7 +85,6 @@
- downloading clients
-
- Gnutella2:
-- * Why doesn't TigerTree work on Mac ?
- * Allow browsing other clients.
- * ADD urn:sha1:<HASH> and urn:tree:tiger/:<HASH> to QRT
- * Search using all URI (ed2k, etc...)
-@@ -124,6 +95,7 @@
- * Send more information in HTTP/1.1 headers (alt-locs, thex)
-
- Soulseek:
-+ * Network does currently not work due to missing bindings with common module
- * In case of Message from server LOGIN FAILURE INVALIDPASS
- prevent any new reconnection without changing the password. Done ?
- + Implement more of the protocol
-@@ -138,10 +110,12 @@
- + Display the number of new message per room
-
- Opennap:
-+ * Network does currently not work due to missing bindings with common module
- * Register files on server
- * Implement Upload completely
-
- Direct-Connect:
-+ * Network does currently not work due to missing bindings with common module
- * Implement Upload completely
- * How do you know your IP in Direct-Connect if you are behind a firewall
- * Send replies to active searches
-@@ -154,110 +128,12 @@
- Core:
- * LittleEndian: is buf_int correct with negative values
- * Change ClientKind so that it does not depend on edonkey anymore.
-- * Configurable map to translate characters appearing in the file names.
- * BUG: What happens when the writes are buffered, mtime does not correspond to
- the real value ? We should probably call Unix2.flush_all before saving
- the config.
-- * Download one file from multiple networks:
-- 1) A download must be started on a verified network (donkey, bittorrent
-- or gnutella)
-- 2) Complementary downloads can be started from other networks:
-- 2a) Start a download as attached to a main download
-- 2b) The attached download does not create a main file, but a set of
-- chunks that are potentially downloaded
-- 2c) If the download of the attached file is finished, and the file
-- can be verified, then the attchaed download can be permuted
-- with the main download (the attached download becomes the main
-- download, and reciprocally).
-- * Associate kinds with networks, and only download useful urls
-- * Make difference between Subscribe and Submit searches clear: Submit
-- searches all networks and stops when all servers have replied.
-- Subscribe is a long term search, it should query the servers
-- periodically, and display new results (and probably save them).
-- Not implemented yet anyway.
- * CD get and Collections
-- * Change temporary files names to allow recover on all networks.
-- * Socks 5 support
- * The core sends more File_info messages than File_downloaded, which is
- not normal !
- * Send messages to GUI with a classifier (to be able to display messages
- in different consoles, server console, download console, clients console)
-
--***********************************************************************
--GUI:
-- * Suppress all classes in newgui: object-oriented programming makes
-- modifying the GUI even harder, and is not useful at all. We should
-- replace classes by simple records when possible.
-- * Give more information on why a connection failed: we should now at
-- which stage a connection has failed, when it was, and when was the
-- last correct connection.
-- * Interactive downloads (popups for one file with progress bar): for
-- example, it could be used when starting a download under bittorrent
-- (use a network flag to say when it should be used ?) from a
-- WEB navigator so that the user see a popup from the GUI immediatly
-- and see the progress of the download (as does the python bittorrent).
-- * Change the color of tabs when things change
-- * Add information about:
-- * When a download was started and when a file was last seen _complete_:
-- 3d/8d : we have been downloading this file for 8 days, and
-- saw it complete three days ago
-- --/8d : idem, but we have never seen it complete
--
--
--***********************************************************************
--
-- And bug reports
--
--***********************************************************************
--Fasttrack
--=========
--FT not respecting max sources per file settings
--http://savannah.nongnu.org/bugs/?func=detailitem&item_id=3761
--
--
--GUI bugs
--========
--"max hits" doesn't work
--http://savannah.nongnu.org/bugs/index.php?func=detailitem&item_id=3675
--
--Source-state error in GUI
--http://savannah.nongnu.org/bugs/?func=detailitem&item_id=2443
--
--Commited file is not removed from GUI
--http://savannah.nongnu.org/bugs/?func=detailitem&item_id=3705
--
--Right click to file option save doesn't show all file names
--http://savannah.nongnu.org/bugs/?func=detailitem&item_id=3179
--
--"old" gtk gui column sizes
--http://savannah.nongnu.org/bugs/?func=detailitem&item_id=6917
--
--
--HTML_mods bugs
--==============
--Cancel and Pause-"Feature" at same time
--http://savannah.nongnu.org/bugs/?func=detailitem&item_id=3227
--
--
--Requests for GUI enhancements
--=============================
--Change the serach-for field into a combo box
--http://savannah.nongnu.org/bugs/index.php?func=detailitem&item_id=3445
--
--Remember current tab on exit
--http://savannah.nongnu.org/bugs/index.php?func=detailitem&item_id=3476
--
--Better GUI for identifying what files are in good states
--http://savannah.nongnu.org/bugs/index.php?func=detailitem&item_id=4316
--
--ed2k-links of all files available (might be best for html_mods)
--https://savannah.nongnu.org/bugs/index.php?func=detailitem&item_id=4378
--
--
--Others
--======
--Wrong filename used when downloading ed2k links? (Patch attached)
--http://savannah.nongnu.org/bugs/index.php?func=detailitem&item_id=4080
--
--Handling of foreign characters
--http://savannah.nongnu.org/bugs/index.php?func=detailitem&item_id=4154
-Index: distrib/ed2k_mozilla/README
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/distrib/ed2k_mozilla/README,v
-retrieving revision 1.7
-retrieving revision 1.8
-diff -u -r1.7 -r1.8
---- distrib/ed2k_mozilla/README 14 Dec 2005 20:15:39 -0000 1.7
-+++ distrib/ed2k_mozilla/README 23 Oct 2006 12:58:35 -0000 1.8
-@@ -1,10 +1,10 @@
--Mozilla MLdonkey/eMule Protocol Handler 1.7
--Copyright (C) 2003 - 2005 Simon Peter <dn.tlp@gmx.net>
-+Firefox MLdonkey/eMule Protocol Handler 1.8
-+Copyright (C) 2003 - 2006 Simon Peter <dn.tlp@gmx.net>
-
- Description:
- ------------
--This is a protocol handler for Mozilla and Firefox (see
--www.mozilla.org) that forwards some link types to a running MLdonkey
-+This is a protocol handler for Firefox 1.5 and later (see
-+www.mozilla.com) that forwards some link types to a running MLdonkey
- (see www.mldonkey.net) or eMule (see www.emule-project.net) client.
-
- Supported protocols are ed2k:, magnet: and sig2dat:. For eMule, only
-@@ -15,13 +15,13 @@
- specific questions to Dan Fritz.
-
- The protocol handler is implemented in JavaScript and should run on
--any platform supported by Mozilla and Firefox.
-+any platform supported by Firefox.
-
- Prerequisites:
- --------------
- The Web interface of your Donkey client must be enabled and access for
--the host this extension should be running on must be enabled in order
--for this extension to work.
-+the host, this extension should be running on, must be enabled in
-+order for this extension to work.
-
- For eMule, it is advised that you set your web interface template to
- default (eMule.tmpl). It may work with other templates but this has
-@@ -29,8 +29,8 @@
-
- Installation:
- -------------
--Just open the .xpi installer file in Mozilla/Firefox and follow the
--on-screen instructions.
-+Just open the .xpi installer file in Firefox and follow the on-screen
-+instructions.
-
- If you are on a UNIX derivative system (e.g. Linux, BSD, MacOS X and
- the like) and like to install this extension for all users on your
-@@ -51,48 +51,34 @@
-
- Configuration:
- --------------
--The protocol handler is configurable through Mozilla's preferences
--scheme. The preferences can be set in multiple ways, depending on your
--browser version.
--
--For Mozilla 1.3, newer versions and Firefox, the preferences are
--accessible by visiting the URL "about:config" inside the browser. This
--opens a page containing a table of all available preference
--options. Right clicking on the table opens a menu to create, modify
--and reset the options. Note that the preference defaults of this
--protocol handler are internal and NOT visible initially in the list!
--To set your own preferences, you have to create them.
--
--For Mozilla versions below 1.3, you can set the preferences by
--creating a file 'user.js' in your profile directory (this is
--$HOME/.mozilla/default/<profile>/ on UNIX systems, where <profile> has
--to be replaced by some cryptic string -- just look in that directory)
--and set the options there by adding lines of the form:
--user_pref("option", "value"); to it.
-+The protocol handler is GUI configurable through Firefox' extensions
-+menu, for Firefox versions 1.5 and later. Go to the extensions menu,
-+by clicking on Tools->Extensions from the main bar of pull-down
-+menus. There, select the MLdonkey Protocol Handler and click on
-+Options. A GUI configuration dialog should pop up, which allows you to
-+set all options. The following preference options are available:
-
--The following preference options are available:
--
--Option: network.mldonkey.server
-+Option: Server
- Default: localhost
- Description: Hostname on which MLdonkey/eMule is running
-
--Option: network.mldonkey.port
-+Option: Port
- Default: 4080
--Description: Port of the MLdonkey/eMule WEB service
-+Description: Port of the MLdonkey/eMule web service
-
--Option: network.mldonkey.pass
-+Option: Password
- Default: (empty)
- Description: Password for eMule clients (MLdonkey is handled
--automatically by Mozilla's password manager)
-+automatically by Firefox' password manager)
-
--Option: network.mldonkey.mode
-+Option: Mode
- Default: mldonkey
- Description: Donkey client to send the data to. This can be set to
--'mldonkey' or 'emule' (without the quotes) to talk to an MLdonkey or
--an eMule client, respectively.
-+'mldonkey', 'emule' (without the quotes) to talk to an MLdonkey or
-+eMule client, respectively.
-
--All these options are string options. Remember to restart your browser
--before any of them can take effect!
-+Remember to restart your browser before any of these options can take
-+effect!
-
- Deinstallation:
- ---------------
-@@ -100,16 +86,25 @@
- the extensions dialog by clicking on Extensions in the Tools
- menu. Select the plugin there and click on Uninstall.
-
--On Mozilla, you have to manually deinstall the plugin by removing the
--file 'ed2kprotocol.js' from Mozilla's components directory. On a UNIX
--system, this normally is /usr/lib/mozilla/components.
--
- News:
- -----
-+Changes for version 1.8:
-+- Support for GUI configuration through Firefox' extensions menu
-+ (thanks to David Ciecierski <dawid.ciecierski@googlemail.com>).
-+
-+ ATTENTION upgraders: If you manually set configuration options
-+ through the about:config dialog for a previous version of this
-+ extension, you first have to go to this dialog and reset all user
-+ set options back to their defaults in order to be able to use the
-+ new GUI configuration dialog!
-+
-+- Since this version, only Firefox version 1.5 and higher is
-+ supported.
-+
- Changes for version 1.7:
- - eMule communication is now faster (thanks to ZZ
-- http://forum.emule-project.net/index.php?showuser=9079)
--- Added support for eMule 0.46a
-+ http://forum.emule-project.net/index.php?showuser=9079).
-+- Added support for eMule 0.46a.
- - eMule response is now displayed in the same way as MLdonkey
- responses.
-
-@@ -161,13 +156,14 @@
-
- The Initial Developer of the Original Code is
- Simon Peter <dn.tlp@gmx.net>.
--Portions created by the Initial Developer are Copyright (C) 2003 - 2005
-+Portions created by the Initial Developer are Copyright (C) 2003 - 2006
- the Initial Developer. All Rights Reserved.
-
- Contributor(s):
- Sven Koch
- Len Walter <len@unsw.edu.au>
- Dan Fritz <templar_of_ni@yahoo.se>
-+David Ciecierski <dawid.ciecierski@gmail.com>
-
- Alternatively, the contents of this file may be used under the terms of
- either the GNU General Public License Version 2 or later (the "GPL"), or
-Index: distrib/ed2k_mozilla/mldonkey_protocol_handler-1.7.xpi
-===================================================================
-RCS file: distrib/ed2k_mozilla/mldonkey_protocol_handler-1.7.xpi
-diff -N distrib/ed2k_mozilla/mldonkey_protocol_handler-1.7.xpi
-Binary files /tmp/cvspWYDF7 and /dev/null differ
-Index: distrib/ed2k_mozilla/mldonkey_protocol_handler-1.8.xpi
-===================================================================
-RCS file: distrib/ed2k_mozilla/mldonkey_protocol_handler-1.8.xpi
-diff -N distrib/ed2k_mozilla/mldonkey_protocol_handler-1.8.xpi
-Binary files /dev/null and /tmp/cvsJexOXS differ
-Index: distrib/ed2k_mozilla/src/contents.rdf
-===================================================================
-RCS file: distrib/ed2k_mozilla/src/contents.rdf
-diff -N distrib/ed2k_mozilla/src/contents.rdf
---- distrib/ed2k_mozilla/src/contents.rdf 8 Jun 2003 12:48:08 -0000 1.2
-+++ /dev/null 1 Jan 1970 00:00:00 -0000
-@@ -1,13 +0,0 @@
--<?xml version="1.0"?>
--<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-- xmlns:chrome="http://www.mozilla.org/rdf/chrome#">
--
--<!-- list all the packages being supplied -->
-- <RDF:Seq about="urn:mozilla:package:root">
-- <RDF:li resource="urn:mozilla:package:hdl"/>
-- </RDF:Seq> <!-- package information -->
-- <RDF:Description about="urn:mozilla:package:ed2k"
-- chrome:displayName="Mozilla MLdonkey Protocol Handler"
-- chrome:author="Simon Peter <dn.tlp@gmx.net>"
-- chrome:name="ed2k">
-- </RDF:Description> </RDF:RDF>
-Index: distrib/ed2k_mozilla/src/install.js
-===================================================================
-RCS file: distrib/ed2k_mozilla/src/install.js
-diff -N distrib/ed2k_mozilla/src/install.js
---- distrib/ed2k_mozilla/src/install.js 14 Dec 2005 20:15:39 -0000 1.7
-+++ /dev/null 1 Jan 1970 00:00:00 -0000
-@@ -1,56 +0,0 @@
--/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
--/* ***** BEGIN LICENSE BLOCK *****
-- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
-- *
-- * The contents of this file are subject to the Mozilla Public License Version
-- * 1.1 (the "License"); you may not use this file except in compliance with
-- * the License. You may obtain a copy of the License at
-- * http://www.mozilla.org/MPL/
-- *
-- * Software distributed under the License is distributed on an "AS IS" basis,
-- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-- * for the specific language governing rights and limitations under the
-- * License.
-- *
-- * The Original Code is the MLdonkey protocol handler installer.
-- *
-- * The Initial Developer of the Original Code is
-- * Simon Peter <dn.tlp@gmx.net>.
-- * Portions created by the Initial Developer are Copyright (C) 2003 - 2005
-- * the Initial Developer. All Rights Reserved.
-- *
-- * Contributor(s):
-- * Len Walter <len@unsw.edu.au>
-- *
-- * Alternatively, the contents of this file may be used under the terms of
-- * either the GNU General Public License Version 2 or later (the "GPL"), or
-- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-- * in which case the provisions of the GPL or the LGPL are applicable instead
-- * of those above. If you wish to allow use of your version of this file only
-- * under the terms of either the GPL or the LGPL, and not to allow others to
-- * use your version of this file under the terms of the MPL, indicate your
-- * decision by deleting the provisions above and replace them with the notice
-- * and other provisions required by the GPL or the LGPL. If you do not delete
-- * the provisions above, a recipient may use your version of this file under
-- * the terms of any one of the MPL, the GPL or the LGPL.
-- *
-- * ***** END LICENSE BLOCK ***** */
--
--const G_MSG = "Mozilla MLdonkey Protocol Handler 1.6";
--const G_NAME = "ed2k";
--const G_VER = "1.7";
--
--var err = initInstall(G_MSG, G_NAME, G_VER);
--logComment("initInstall: " + err);
--
--addFile("protocol handler", "components/ed2kprotocol.js", getFolder("Components"), "");
--
--// needed for older versions to see the new component
--var f = getFolder("Program", "component.reg");
--if (File.exists(f)) File.remove(f);
--
--err = getLastError();
--if (err==SUCCESS)
-- performInstall();
--else
-- cancelInstall(err);
-Index: distrib/ed2k_mozilla/src/install.rdf
-===================================================================
-RCS file: distrib/ed2k_mozilla/src/install.rdf
-diff -N distrib/ed2k_mozilla/src/install.rdf
---- distrib/ed2k_mozilla/src/install.rdf 14 Dec 2005 20:15:40 -0000 1.3
-+++ /dev/null 1 Jan 1970 00:00:00 -0000
-@@ -1,29 +0,0 @@
--<?xml version="1.0"?>
--
--<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-- xmlns:em="http://www.mozilla.org/2004/em-rdf#">
--
-- <Description about="urn:mozilla:install-manifest">
-- <em:id>{bc72206d-b3ce-4b49-88b9-d59b388a0cde}</em:id>
-- <em:version>1.7</em:version>
--
-- <!-- Target Application this extension can install into,
-- with minimum and maximum supported versions. -->
-- <em:targetApplication>
-- <Description>
-- <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
-- <em:minVersion>0.7</em:minVersion>
-- <em:maxVersion>1.9</em:maxVersion>
-- </Description>
-- </em:targetApplication>
--
-- <!-- Front End MetaData -->
-- <em:name>Mozilla MLdonkey Protocol Handler</em:name>
-- <em:description>Mozilla/Firefox MLdonkey Protocol Handler</em:description>
-- <em:creator>Simon Peter</em:creator>
-- <em:contributor>Len Walter</em:contributor>
-- <em:contributor>Sven Koch</em:contributor>
-- <em:contributor>Dan Fritz</em:contributor>
-- <em:homepageURL>http://www.informatik.uni-oldenburg.de/~dyna/mldonkey/</em:homepageURL>
-- </Description>
--</RDF>
-Index: distrib/ed2k_mozilla/src/components/ed2kprotocol.js
-===================================================================
-RCS file: distrib/ed2k_mozilla/src/components/ed2kprotocol.js
-diff -N distrib/ed2k_mozilla/src/components/ed2kprotocol.js
---- distrib/ed2k_mozilla/src/components/ed2kprotocol.js 14 Dec 2005 20:15:40 -0000 1.3
-+++ /dev/null 1 Jan 1970 00:00:00 -0000
-@@ -1,251 +0,0 @@
--/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
--/* ***** BEGIN LICENSE BLOCK *****
-- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
-- *
-- * The contents of this file are subject to the Mozilla Public License Version
-- * 1.1 (the "License"); you may not use this file except in compliance with
-- * the License. You may obtain a copy of the License at
-- * http://www.mozilla.org/MPL/
-- *
-- * Software distributed under the License is distributed on an "AS IS" basis,
-- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-- * for the specific language governing rights and limitations under the
-- * License.
-- *
-- * The Original Code is the MLdonkey protocol handler 1.7.
-- *
-- * The Initial Developer of the Original Code is
-- * Simon Peter <dn.tlp@gmx.net>.
-- * Portions created by the Initial Developer are Copyright (C) 2003 - 2005
-- * the Initial Developer. All Rights Reserved.
-- *
-- * Contributor(s):
-- * Sven Koch
-- * Len Walter <len@unsw.edu.au>
-- * Dan Fritz (eMule bindings)
-- *
-- * Alternatively, the contents of this file may be used under the terms of
-- * either the GNU General Public License Version 2 or later (the "GPL"), or
-- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-- * in which case the provisions of the GPL or the LGPL are applicable instead
-- * of those above. If you wish to allow use of your version of this file only
-- * under the terms of either the GPL or the LGPL, and not to allow others to
-- * use your version of this file under the terms of the MPL, indicate your
-- * decision by deleting the provisions above and replace them with the notice
-- * and other provisions required by the GPL or the LGPL. If you do not delete
-- * the provisions above, a recipient may use your version of this file under
-- * the terms of any one of the MPL, the GPL or the LGPL.
-- *
-- * ***** END LICENSE BLOCK ***** */
--
--/***** Defines *****/
--
--// components defined in this file
--const ED2KPROT_HANDLER_CONTRACTID =
-- "@mozilla.org/network/protocol;1?name=ed2k";
--const ED2KPROT_HANDLER_CID =
-- Components.ID("{af8d664a-d002-438f-84a3-01f3a8ff325b}");
--
--const MAGNETPROT_HANDLER_CONTRACTID =
-- "@mozilla.org/network/protocol;1?name=magnet";
--const MAGNETPROT_HANDLER_CID =
-- Components.ID("{3e022170-58b0-4548-ba4c-1f47d54c7767}");
--
--const SIG2DATPROT_HANDLER_CONTRACTID =
-- "@mozilla.org/network/protocol;1?name=sig2dat";
--const SIG2DATPROT_HANDLER_CID =
-- Components.ID("{2a2e71ea-e857-4c71-9c93-04ff681df88a}");
--
--// components used in this file
--const NS_IOSERVICE_CID = "{9ac9e770-18bc-11d3-9337-00104ba0fd40}";
--const NS_PREFSERVICE_CONTRACTID = "@mozilla.org/preferences-service;1";
--const URI_CONTRACTID = "@mozilla.org/network/simple-uri;1";
--const NS_WINDOWWATCHER_CONTRACTID = "@mozilla.org/embedcomp/window-watcher;1";
--const INPUTSTREAMCHANNEL_CONTRACTID = "@mozilla.org/network/input-stream-channel;1";
--
--// interfaces used in this file
--const nsIProtocolHandler = Components.interfaces.nsIProtocolHandler;
--const nsIURI = Components.interfaces.nsIURI;
--const nsISupports = Components.interfaces.nsISupports;
--const nsIIOService = Components.interfaces.nsIIOService;
--const nsIPrefService = Components.interfaces.nsIPrefService;
--const nsIWindowWatcher = Components.interfaces.nsIWindowWatcher;
--const nsIChannel = Components.interfaces.nsIChannel;
--
--// some misc. constants
--const PREF_BRANCH = "network.mldonkey.";
--const WND_WIDTH = 320;
--const WND_HEIGHT = 200;
--
--const WND_EMULE_WIDTH = 450;
--const WND_EMULE_HEIGHT = 75;
--
--// configuration (and defaults)
--cfgServer = "localhost";
--cfgPort = "4080";
--myWnd = null;
--cfgMode = "mldonkey"
--cfgPass = ""
--
--/***** MLdonkeyProtocolHandler *****/
--
--function MLdonkeyProtocolHandler(scheme)
--{
-- this.scheme = scheme;
-- this.readPreferences(PREF_BRANCH);
--}
--
--// attribute defaults
--MLdonkeyProtocolHandler.prototype.defaultPort = -1;
--MLdonkeyProtocolHandler.prototype.protocolFlags = nsIProtocolHandler.URI_NORELATIVE;
--
--MLdonkeyProtocolHandler.prototype.allowPort = function(aPort, aScheme)
--{
-- return false;
--}
--
--MLdonkeyProtocolHandler.prototype.newURI = function(aSpec, aCharset, aBaseURI)
--{
-- var uri = Components.classes[URI_CONTRACTID].createInstance(nsIURI);
-- uri.spec = aSpec;
-- return uri;
--}
--
--MLdonkeyProtocolHandler.prototype.newChannel = function(aURI)
--{
-- var myUri = "";
-- var myTitle = "";
-- var myWidth = WND_WIDTH;
-- var myHeight = WND_HEIGHT
--
-- if (cfgMode == "mldonkey") {
-- myTitle = "MLDonkey";
--
-- // rewrite the URI into a http URL to the mldonkey client
-- myURI = "http://";
-- // if(cfgUser != "") myURI += cfgUser + ":" + cfgPass + "@";
-- myURI += cfgServer + ":" + cfgPort + "/submit?q=dllink+" +
-- encodeURIComponent(decodeURI(aURI.spec));
-- } else {
-- // eMule mode
-- myTitle = "eMule";
-- myWidth = WND_EMULE_WIDTH;
-- myHeight = WND_EMULE_HEIGHT
--
-- // rewrite the URI into a http URL to the eMule client
-- myURI = "http://";
-- myURI += cfgServer + ":" + cfgPort + "/?w=password&p=" + cfgPass;
-- myURI += "&cat=0&c=" + encodeURIComponent(decodeURI(aURI.spec));
-- }
--
-- // open up a window with our newly generated http URL
-- var wwatch = Components.classes[NS_WINDOWWATCHER_CONTRACTID].getService(nsIWindowWatcher);
-- if(myWnd == null || myWnd.closed == true)
-- myWnd = wwatch.openWindow(wwatch.activeWindow, myURI, myTitle,
-- "width=" + myWidth + ", height=" + myHeight, null);
-- else
-- myWnd.location.href = myURI;
--
-- // return a fake empty channel so current window doesn't change
-- var chan = Components.classes[INPUTSTREAMCHANNEL_CONTRACTID].createInstance(nsIChannel);
-- return chan;
--}
--
--MLdonkeyProtocolHandler.prototype.readPreferences = function(pref_branch)
--{
-- // get preferences branch
-- var PrefService = Components.classes[NS_PREFSERVICE_CONTRACTID].getService(nsIPrefService);
-- var myPrefs = PrefService.getBranch(null); // Mozilla bug #107617
--
-- // read preferences (if available)
-- if(myPrefs.getPrefType(pref_branch + "server") == myPrefs.PREF_STRING)
-- cfgServer = myPrefs.getCharPref(pref_branch + "server");
-- if(myPrefs.getPrefType(pref_branch + "port") == myPrefs.PREF_STRING)
-- cfgPort = myPrefs.getCharPref(pref_branch + "port");
-- if(myPrefs.getPrefType(pref_branch + "mode") == myPrefs.PREF_STRING)
-- cfgMode = myPrefs.getCharPref(pref_branch + "mode");
-- if(myPrefs.getPrefType(pref_branch + "pass") == myPrefs.PREF_STRING)
-- cfgPass = myPrefs.getCharPref(pref_branch + "pass");
--}
--
--/***** MLdonkeyProtocolHandlerFactory *****/
--
--function MLdonkeyProtocolHandlerFactory(scheme)
--{
-- this.scheme = scheme;
--}
--
--MLdonkeyProtocolHandlerFactory.prototype.createInstance = function(outer, iid)
--{
-- if(outer != null) throw Components.results.NS_ERROR_NO_AGGREGATION;
--
-- if(!iid.equals(nsIProtocolHandler) && !iid.equals(nsISupports))
-- throw Components.results.NS_ERROR_INVALID_ARG;
--
-- return new MLdonkeyProtocolHandler(this.scheme);
--}
--
--var factory_ed2k = new MLdonkeyProtocolHandlerFactory("ed2k");
--var factory_magnet = new MLdonkeyProtocolHandlerFactory("magnet");
--var factory_sig2dat = new MLdonkeyProtocolHandlerFactory("sig2dat");
--
--/***** Ed2kzillaModule *****/
--
--var Ed2kzillaModule = new Object();
--
--Ed2kzillaModule.registerSelf = function(compMgr, fileSpec, location, type)
--{
-- compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
--
-- // register ed2k protocol handler
-- compMgr.registerFactoryLocation(ED2KPROT_HANDLER_CID,
-- "ED2K protocol handler",
-- ED2KPROT_HANDLER_CONTRACTID,
-- fileSpec, location, type);
--
-- // register magnet protocol handler
-- compMgr.registerFactoryLocation(MAGNETPROT_HANDLER_CID,
-- "Magnet protocol handler",
-- MAGNETPROT_HANDLER_CONTRACTID,
-- fileSpec, location, type);
--
-- // register sig2dat protocol handler
-- compMgr.registerFactoryLocation(SIG2DATPROT_HANDLER_CID,
-- "Sig2dat protocol handler",
-- SIG2DATPROT_HANDLER_CONTRACTID,
-- fileSpec, location, type);
--}
--
--Ed2kzillaModule.unregisterSelf = function(compMgr, fileSpec, location)
--{
-- compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
--
-- // unregister our components
-- compMgr.unregisterFactoryLocation(ED2KPROT_HANDLER_CID, fileSpec);
-- compMgr.unregisterFactoryLocation(MAGNETPROT_HANDLER_CID, fileSpec);
-- compMgr.unregisterFactoryLocation(SIG2DATPROT_HANDLER_CID, fileSpec);
--}
--
--Ed2kzillaModule.getClassObject = function(compMgr, cid, iid)
--{
-- if(!iid.equals(Components.interfaces.nsIFactory))
-- throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
--
-- if(cid.equals(ED2KPROT_HANDLER_CID)) return factory_ed2k;
-- if(cid.equals(MAGNETPROT_HANDLER_CID)) return factory_magnet;
-- if(cid.equals(SIG2DATPROT_HANDLER_CID)) return factory_sig2dat;
--
-- throw Components.results.NS_ERROR_NO_INTERFACE;
--}
--
--Ed2kzillaModule.canUnload = function(compMgr)
--{
-- return true; // our objects can be unloaded
--}
--
--/***** Entrypoint *****/
--
--function NSGetModule(compMgr, fileSpec)
--{
-- return Ed2kzillaModule;
--}
-Index: distrib/html_themes/ease/commands.html
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/distrib/html_themes/ease/commands.html,v
-retrieving revision 1.1
-retrieving revision 1.2
-diff -u -r1.1 -r1.2
---- distrib/html_themes/ease/commands.html 14 Jan 2004 20:43:57 -0000 1.1
-+++ distrib/html_themes/ease/commands.html 25 Oct 2006 11:34:45 -0000 1.2
-@@ -57,14 +57,14 @@
- class="bu bbig bbig2"
- onMouseOver="mOvr(this,'mOvr1');"
- onMouseOut="mOut(this);"
--onClick="top.output.location.href='http://www.mldonkey.net/'">Homepage
-+onClick="top.output.location.href='http://www.mldonkey.org/'">Homepage
- </td>
- <td
- title="English/German support forums"
- class="bu bbig bbig2"
- onMouseOver="mOvr(this,'mOvr1');"
- onMouseOut="mOut(this);"
--onClick="top.output.location.href='http://www.mldonkeyworld.com/'">Forums
-+onClick="top.output.location.href='http://www.mldonkey.org/'">Forums
- </td>
- <td
- title="Kill/Close the MLdonkey core"
-Index: distrib/html_themes/old/commands.html
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/distrib/html_themes/old/commands.html,v
-retrieving revision 1.1
-retrieving revision 1.2
-diff -u -r1.1 -r1.2
---- distrib/html_themes/old/commands.html 14 Jan 2004 20:43:57 -0000 1.1
-+++ distrib/html_themes/old/commands.html 25 Oct 2006 11:34:45 -0000 1.2
-@@ -13,14 +13,14 @@
- class="bu bsmall1 b2"
- onMouseOver="mOvr(this,'mOvr1');"
- onMouseOut="mOut(this);"
--onClick="top.output.location.href='http://www.mldonkey.net/'">Homepage
-+onClick="top.output.location.href='http://www.mldonkey.org/'">Homepage
- </td>
- <td
- title="English/German support forums"
- class="bu bsmall1 b2"
- onMouseOver="mOvr(this,'mOvr1');"
- onMouseOut="mOut(this);"
--onClick="top.output.location.href='http://www.mldonkeyworld.com/'">Forums
-+onClick="top.output.location.href='http://www.mldonkey.org/'">Forums
- </td>
- <td
- title="Options"
-Index: docs/multiuser.txt
-===================================================================
-RCS file: docs/multiuser.txt
-diff -N docs/multiuser.txt
---- /dev/null 1 Jan 1970 00:00:00 -0000
-+++ docs/multiuser.txt 9 Nov 2006 21:32:25 -0000 1.2
-@@ -0,0 +1,158 @@
-+Description of multiuser patch
-+==============================
-+This file provides some HowTos and internals about the new multiuser
-+functionality of MLDonkey. The goal is to provide a p2p-service to be
-+used by more than user and where each user has its own environment
-+provided by the daemon.
-+
-+Some basics and definitions
-+===========================
-+User "admin" and all users belonging to a group where group_admin = true can
-+see all files in any case and can use all functions of MLDonkey.
-+
-+file_owner in this text means the user which owns a downloading file,
-+file_group means the group the file belongs to, file_owner must be a member of
-+this group, both values are saved in files.ini.
-+
-+New options (displayed options are default values)
-+==================================================
-+users.ini
-+---------
-+- "users" is kept unchanged for compatibility, all users from "users2"
-+ are saved in "users" as well, so password are updated.
-+- "users2" is extended with these settings:
-+
-+A list of groups the user belongs to, this user can view all files
-+which belong to one of the groups
-+ user_groups = []
-+
-+The default group of the user, the user must also be a member of this
-+group. File_group of new downloads started by the user are automatically
-+assigned to this value. This value can be None, this means the file is a
-+private one only visible to the file_owner (and admins, of course).
-+ user_default_group = mldonkey
-+
-+E-mail address to sent commit notifications to. Global option "mail"
-+can still be used for admins, if both addresses match only one mail is sent.
-+ user_mail = ""
-+
-+Commit files to <incoming>/<user_commit_dir>
-+The current incoming directory is appended with user_commit_dir.
-+All incoming dirs are shared recursively now to share these files
-+committed into user specific dirs.
-+ user_commit_dir = ""
-+
-+Like global option max_concurrent_downloads this implements a user-specific
-+limit of the maximum number of concurrent files a user can download. Other
-+downloads are queued, this is done by round-robin. If the sum of
-+user_max_concurrent_downloads from all users is bigger than
-+max_concurrent_downloads less downloads than user_max_concurrent_downloads
-+are in downloading state. 0 means no user-specific limit.
-+Users can change file priorities the control which files are not queued.
-+ user_max_concurrent_downloads = 0
-+
-+- groups, new option
-+At least one group named "mldonkey" with group_admin = true must exist
-+and will be re-created on startup if missing.
-+
-+Option to control if the group has admin rights. All users belonging to such a
-+group have the same rights as user "admin".
-+ group_admin = true
-+
-+
-+files.ini
-+---------
-+- each file has two new options in files.ini
-+file_owner: the incoming directory of the owner is used for commit,
-+ if the user does not exist "admin" is used. If this data
-+ field does not exist, the file will belong to user "admin".
-+file_group: default value for a new download is user_default_group
-+ if file_owner is not member of file_group or the group does not
-+ exist, the user_default_group of file_owner is used.
-+
-+downloads.ini
-+-------------
-+These two options control the display of user/group column in HTML, vd
-+ html_mods_vd_user false
-+ html_mods_vd_group false
-+
-+
-+Commands to control multiuser features/data
-+===========================================
-+chgrp <group> <num>
-+change group of download <num> to <group>, group = none for private file
-+
-+chown <user> <num>
-+change owner of download <num> to <user>
-+
-+dgroup
-+print default group of logged-in user
-+
-+groupadd <group> <admin: true | false>
-+add new mldonkey group, only admin users can use this command
-+
-+groupadmin <group> <admin: true | false>
-+change group admin status, only admin users can use this command
-+
-+groupdel <group>
-+remove an unused mldonkey group, only admin users can use this command
-+only possible if group has no members
-+
-+groups
-+print groups of logged-in user
-+
-+passwd <passwd>
-+change own password
-+
-+useradd <user> <passwd>
-+add new mldonkey user/change user password, only admin users can use this command
-+
-+usercommit <user> <dir>
-+change user specific commit directory
-+
-+userdel <user>
-+remove a mldonkey user, only admin users can use this command, user "admin" can not be removed
-+deleting a user is only possible if the user does not own any downloads
-+
-+userdgroup <user> <group|None>
-+change user default group
-+
-+userdls <user> <num>
-+change number of allowed concurrent downloads, only admin users can use this command
-+
-+usergroupadd <user> <group>
-+add a group to a mldonkey user, only admin users can use this command
-+
-+usergroupdel <user> <group>
-+remove a group from a mldonkey user
-+
-+usermail <user> <mail>
-+change user mail address
-+
-+users
-+use this command in HTML interface for a small GUI to control users
-+
-+whoami
-+print logged-in user name
-+
-+
-+Updating from a non-multiuser MLDonkey
-+======================================
-+When updating all files will have file_owner "admin" and file_group "mldonkey".
-+All existing users will have user_default_group = "mldonkey" and
-+user_groups = ["mldonkey"]. This means all users can use all features of
-+MLDonkey and see all files in use by MLDonkey core, just like before.
-+
-+To hide user downloads from each other, create a new group with
-+group_admin = false and assign all users to this group and remove them
-+from all admin groups
-+
-+
-+Additional features
-+===================
-+- file_completed_cmd has new environment variables $FILE_OWNER and $FILE_GROUP
-+- remove option enable_user_config, replaced by membership of admin groups
-+
-+To-Do
-+======
-+- Suggestions ?
-Index: packages/rpm/mldonkey.spec.in
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/packages/rpm/mldonkey.spec.in,v
-retrieving revision 1.5
-retrieving revision 1.6
-diff -u -r1.5 -r1.6
---- packages/rpm/mldonkey.spec.in 27 Jun 2006 10:38:34 -0000 1.5
-+++ packages/rpm/mldonkey.spec.in 25 Oct 2006 11:34:45 -0000 1.6
-@@ -8,7 +8,7 @@
- Summary: %{summary}
- License: GPL
- Source0: %{name}.sources.tar.bz2
--URL: http://www.mldonkey.net/
-+URL: http://www.mldonkey.org
- Group: System/Servers
- BuildRoot: %{_tmppath}/%{name}-buildroot
-
-Index: packages/slackware/slack-desc
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/packages/slackware/slack-desc,v
-retrieving revision 1.1
-retrieving revision 1.2
-diff -u -r1.1 -r1.2
---- packages/slackware/slack-desc 5 Nov 2005 16:21:25 -0000 1.1
-+++ packages/slackware/slack-desc 25 Oct 2006 11:34:46 -0000 1.2
-@@ -6,6 +6,5 @@
- mldonkey: Overnet, Bittorrent, Gnutella (Bearshare, Limewire, etc), Gnutella2
- mldonkey: (Shareaza), Fasttrack (Kazaa, Imesh, Grobster), Soulseek, etc.
- mldonkey:
--mldonkey: http://www.mldonkey.net
- mldonkey: http://www.mldonkey.org
- mldonkey:
-Index: src/daemon/common/commonClient.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonClient.ml,v
-retrieving revision 1.30
-retrieving revision 1.33
-diff -u -r1.30 -r1.33
---- src/daemon/common/commonClient.ml 14 Sep 2006 17:31:00 -0000 1.30
-+++ src/daemon/common/commonClient.ml 5 Nov 2006 14:09:38 -0000 1.33
-@@ -33,9 +33,8 @@
- mutable impl_client_type : client_type;
- mutable impl_client_state : host_state;
- mutable impl_client_update : int;
-- mutable impl_client_has_slot : bool;
-- mutable impl_client_has_friend_slot : bool;
-- mutable impl_client_upload : shared option;
-+ mutable impl_client_slot : slot_kind;
-+ mutable impl_client_upload : file option;
- mutable impl_client_num : int;
- mutable impl_client_val : 'a;
- mutable impl_client_ops : 'a client_ops;
-@@ -102,8 +101,7 @@
- impl_client_type = 0;
- impl_client_state = NewHost;
- impl_client_update = 1;
-- impl_client_has_slot = false;
-- impl_client_has_friend_slot = false;
-+ impl_client_slot = NoSlot;
- impl_client_upload = None;
- impl_client_num = 0;
- impl_client_val = 0;
-@@ -322,24 +320,26 @@
- let set_initialized c =
- set_client_type c (client_type c lor client_initialized_tag)
-
--let client_has_a_slot c =
-- (as_client_impl c).impl_client_has_slot
-+let client_slot c =
-+ (as_client_impl c).impl_client_slot
-
--let client_has_a_friend_slot c =
-- (as_client_impl c).impl_client_has_friend_slot
-+let client_has_a_slot c =
-+ match (as_client_impl c).impl_client_slot with
-+ NoSlot -> false
-+ | _ -> true
-
- let client_upload c =
- (as_client_impl c).impl_client_upload
-
- let set_client_upload c sh =
-- (as_client_impl c).impl_client_upload <- sh;
-+ (as_client_impl c).impl_client_upload <- Some sh;
- client_must_update c
-
--let set_client_has_a_slot c b =
-+let set_client_has_a_slot c slot =
- let impl = as_client_impl c in
-- if not b && impl.impl_client_has_slot then begin
-- impl.impl_client_has_slot <- false;
-- impl.impl_client_has_friend_slot <- false;
-+ match slot with
-+ NoSlot -> if client_has_a_slot c then begin
-+ impl.impl_client_slot <- NoSlot;
- uploaders := Intmap.remove (client_num c) !uploaders;
- client_must_update c;
- (*
-@@ -353,17 +353,15 @@
- *)
- Unix32.close_all ()
- end
-- else
-- if b && not impl.impl_client_has_slot then begin
-+ | slot -> if not (client_has_a_slot c) then begin
- uploaders := Intmap.add (client_num c) c !uploaders;
-- impl.impl_client_has_slot <- true;
-- impl.impl_client_has_friend_slot <- is_friend c;
-+ impl.impl_client_slot <- slot;
- client_must_update c
- end
-
- let set_client_disconnected c reason =
- let impl = as_client_impl c in
-- set_client_has_a_slot c false;
-+ set_client_has_a_slot c NoSlot;
-
- match impl.impl_client_state with
- Connected n -> set_client_state c (NotConnected (reason, n))
-@@ -402,6 +400,7 @@
- let counter = ref 0 in
- H.iter (fun _ -> incr counter) clients_by_num;
- Printf.bprintf buf " clients: %d\n" !counter;
-+ Printf.bprintf buf " uploaders: %d\n" (Intmap.length !uploaders);
- )
-
- let clients_get_all () =
-@@ -473,7 +472,7 @@
- client_disconnect c;
- if !verbose then lprintf_nl "disconnected client %d: [%s %s] %s after %d %s of silence."
- (client_num c)
-- i.GuiTypes.client_software
-+ (GuiTypes.client_software i.GuiTypes.client_software i.GuiTypes.client_os)
- i.GuiTypes.client_release
- i.GuiTypes.client_name
- ctime
-@@ -498,6 +497,7 @@
- T.client_connect_time = BasicSocket.last_time ();
- T.client_kind = Indirect_location ("", Md4.Md4.null, Ip.null, 0);
- T.client_software = "";
-+ T.client_os = None;
- T.client_release = "";
- T.client_emulemod = "";
- T.client_downloaded = 0L;
-Index: src/daemon/common/commonClient.mli
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonClient.mli,v
-retrieving revision 1.12
-retrieving revision 1.13
-diff -u -r1.12 -r1.13
---- src/daemon/common/commonClient.mli 16 Aug 2006 19:12:08 -0000 1.12
-+++ src/daemon/common/commonClient.mli 25 Oct 2006 11:12:38 -0000 1.13
-@@ -2,9 +2,8 @@
- mutable impl_client_type : CommonTypes.client_type;
- mutable impl_client_state : CommonTypes.host_state;
- mutable impl_client_update : int;
-- mutable impl_client_has_slot : bool;
-- mutable impl_client_has_friend_slot : bool;
-- mutable impl_client_upload : CommonTypes.shared option;
-+ mutable impl_client_slot : CommonTypes.slot_kind;
-+ mutable impl_client_upload : CommonTypes.file option;
- mutable impl_client_num : int;
- mutable impl_client_val : 'a;
- mutable impl_client_ops : 'a client_ops;
-@@ -70,11 +69,11 @@
- val check_client_implementations : unit -> unit
- val client_can_upload : CommonTypes.client -> int -> unit
- val client_enter_upload_queue : CommonTypes.client -> unit
--val client_upload : CommonTypes.client -> CommonTypes.shared option
--val set_client_upload : CommonTypes.client -> CommonTypes.shared option -> unit
-+val client_upload : CommonTypes.client -> CommonTypes.file option
-+val set_client_upload : CommonTypes.client -> CommonTypes.file -> unit
-+val client_slot : CommonTypes.client -> CommonTypes.slot_kind
- val client_has_a_slot : CommonTypes.client -> bool
--val client_has_a_friend_slot : CommonTypes.client -> bool
--val set_client_has_a_slot : CommonTypes.client -> bool -> unit
-+val set_client_has_a_slot : CommonTypes.client -> CommonTypes.slot_kind -> unit
-
- val uploaders : CommonTypes.client Intmap.t ref
-
-Index: src/daemon/common/commonComplexOptions.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonComplexOptions.ml,v
-retrieving revision 1.60
-retrieving revision 1.69
-diff -u -r1.60 -r1.69
---- src/daemon/common/commonComplexOptions.ml 1 Sep 2006 16:22:14 -0000 1.60
-+++ src/daemon/common/commonComplexOptions.ml 21 Nov 2006 22:34:33 -0000 1.69
-@@ -27,6 +27,7 @@
- open CommonServer
- open CommonNetwork
- open CommonOptions
-+open CommonUserDb
- open CommonTypes
- open CommonFile
- open Gettext
-@@ -102,6 +103,61 @@
- impl.impl_file_age <-
- normalize_time (get_value "file_age" value_to_int)
- with _ -> ());
-+
-+ (try
-+ impl.impl_file_release <-
-+ get_value "file_release" value_to_bool
-+ with _ -> ());
-+
-+ let file_user =
-+ let filename = get_value "file_filename" value_to_string in
-+ try
-+ let u = get_value "file_owner" value_to_string in
-+ begin
-+ try
-+ user2_user_find u
-+ with Not_found ->
-+ lprintf_nl "file_owner %s of %s does not exist, changing to %s"
-+ u filename admin_user.user_name;
-+ admin_user
-+ end
-+ with Not_found ->
-+ lprintf_nl "file_owner of %s is empty, changing to %s"
-+ filename admin_user.user_name;
-+ admin_user
-+ in
-+ set_file_owner file file_user;
-+
-+ let file_group =
-+ let filename = get_value "file_filename" value_to_string in
-+ let dgroup = user2_print_user_default_group file_user in
-+ try
-+ match (get_value "file_group" stringvalue_to_option) with
-+ None -> None
-+ | Some g ->
-+ begin
-+ try
-+ let g = user2_group_find g in
-+ if List.mem g file_user.user_groups then
-+ Some g
-+ else
-+ begin
-+ lprintf_nl "file_owner %s is not member of file_group %s, changing file_group of %s to user_default_group %s"
-+ file_user.user_name g.group_name filename dgroup;
-+ file_user.user_default_group
-+ end
-+ with Not_found ->
-+ lprintf_nl "file_group %s of %s not found, changing to user_default_group %s of user %s"
-+ g filename dgroup file_user.user_name;
-+ file_user.user_default_group
-+ end
-+ with Not_found ->
-+ lprintf_nl "file_group of %s is empty, changing to user_default_group %s of user %s"
-+ filename dgroup file_user.user_name;
-+ file_user.user_default_group
-+ in
-+ set_file_group file file_group;
-+
- set_file_state file file_state;
-
- (try
-@@ -138,6 +194,9 @@
- ("file_filenames", List
- (List.map string_to_value impl.impl_file_filenames)) ::
- ("file_age", IntValue (Int64.of_int impl.impl_file_age)) ::
-+ ("file_release", bool_to_value impl.impl_file_release) ::
-+ ("file_owner", string_to_value (file_owner file).user_name) ::
-+ ("file_group", option_to_stringvalue (match file_group file with Some g -> Some g.group_name | None -> None)) ::
- (file_to_option file)
- )
-
-@@ -512,7 +571,7 @@
- "-movies", "avi -minsize 650000000 -1cd";
- "-mp3s", "mp3 -minsize 3000000 -maxsize 10000000";
- "-albums", "album -minsize 30000000 -maxsize 150000000";
-- "-nosex", "-without xxx";
-+ "-nosex", "-not xxx";
- ]
-
- let customized_queries =
-@@ -664,7 +723,7 @@
- sharing_directories = false;
- sharing_extensions = [];
- sharing_recursive = false;
-- sharing_minsize = Int64.one;
-+ sharing_minsize = zero;
- sharing_maxsize = Int64.max_int;
- }
-
-@@ -673,7 +732,7 @@
- sharing_directories = true;
- sharing_extensions = [];
- sharing_recursive = false;
-- sharing_minsize = Int64.one;
-+ sharing_minsize = zero;
- sharing_maxsize = Int64.max_int;
- }
-
-@@ -681,8 +740,8 @@
- sharing_incoming = true;
- sharing_directories = false;
- sharing_extensions = [];
-- sharing_recursive = false;
-- sharing_minsize = Int64.one;
-+ sharing_recursive = true;
-+ sharing_minsize = zero;
- sharing_maxsize = Int64.max_int;
- }
-
-@@ -691,7 +750,7 @@
- sharing_directories = true;
- sharing_extensions = [];
- sharing_recursive = false;
-- sharing_minsize = Int64.one;
-+ sharing_minsize = zero;
- sharing_maxsize = Int64.max_int;
- }
-
-@@ -726,7 +785,7 @@
- sharing_directories = false;
- sharing_extensions = [];
- sharing_recursive = true;
-- sharing_minsize = Int64.one;
-+ sharing_minsize = zero;
- sharing_maxsize = Int64.max_int;
- };
-
-@@ -758,7 +817,7 @@
-
- )
-
--let sharing_strategies name =
-+let sharing_strategy name =
- match name with
- | "incoming_files" -> sharing_incoming_files
- | "incoming_directories" -> sharing_incoming_directories
-@@ -790,16 +849,18 @@
- in
- let shdir_priority = get_value_safe "priority" value_to_int 0
- in
-+(*
- let shdir_networks = get_value_safe "networks"
- (value_to_list value_to_string) []
- in
-+*)
- let shdir_strategy = get_value_safe "strategy"
- value_to_string "only_directory"
- in
- {
- shdir_dirname = shdir_dirname;
- shdir_strategy = shdir_strategy;
-- shdir_networks = shdir_networks;
-+ shdir_networks = []; (* shdir_networks; *)
- shdir_priority = shdir_priority;
- }
- end
-@@ -825,8 +886,10 @@
- let shared_directory_to_value s =
- let list = [
- "dirname", filename_to_value s.shdir_dirname;
-+(*
- "networks",
- list_to_value string_to_value s.shdir_networks;
-+*)
- "strategy",
- string_to_value s.shdir_strategy;
- "priority", int_to_value s.shdir_priority;
-@@ -839,8 +902,21 @@
- shared_directory_to_value
-
- end
--
--
-+
-+let default_incoming_files = {
-+ shdir_dirname = Filename.concat "incoming" "files";
-+ shdir_priority = 0;
-+ shdir_networks = [];
-+ shdir_strategy = "incoming_files";
-+ }
-+
-+let default_incoming_directories = {
-+ shdir_dirname = Filename.concat "incoming" "directories";
-+ shdir_priority = 0;
-+ shdir_networks = [];
-+ shdir_strategy = "incoming_directories";
-+ }
-+
- let shared_directories =
- define_option CommonOptions.path_section ["shared_directories" ]
- " Incoming and shared directories.
-@@ -852,8 +928,8 @@
- Finished BT multifile downloads are committed to the first directory
- with strategy incoming_directories. Other downloads are committed
- to the first directory with the strategy incoming_files.
-- If more than one directory has one of the incoming_* strategies
-- it will be ignored on commit, but they are shared nonetheless.
-+ MLdonkey searches all shared_directories with incoming_* strategies
-+ on commit and uses the first one with enough free diskspace.
- Other strategies can be found in searches.ini, section customized_sharing."
- (list_option SharedDirectoryOption.t)
- [
-@@ -863,64 +939,92 @@
- shdir_networks = [];
- shdir_strategy = "all_files";
- };
-- {
-- shdir_dirname = "incoming/files";
-- shdir_priority = 0;
-- shdir_networks = [];
-- shdir_strategy = "incoming_files";
-- };
-- {
-- shdir_dirname = "incoming/directories";
-- shdir_priority = 0;
-- shdir_networks = [];
-- shdir_strategy = "incoming_directories";
-- }
-+ default_incoming_files;
-+ default_incoming_directories;
- ]
-
-
- let search_incoming_files () =
-- try
-- List.find (fun s -> s.shdir_strategy = "incoming_files")
-- !!shared_directories
-- with Not_found ->
-- let dirname = Filename.concat "incoming" "files" in
-- let s = {
-- shdir_dirname = dirname;
-- shdir_priority = 0;
-- shdir_networks = [];
-- shdir_strategy = "incoming_files";
-- }
-- in
-- shared_directories =:= s :: !!shared_directories;
-- s
--
--let incoming_files () =
-- let dir = search_incoming_files () in
-- Unix2.safe_mkdir dir.shdir_dirname;
-- Unix2.can_write_to_directory dir.shdir_dirname;
-- dir
-+ let list =
-+ List.filter (fun s -> s.shdir_strategy = "incoming_files") !!shared_directories
-+ in
-+ match list with
-+ | [] -> shared_directories =:= default_incoming_files :: !!shared_directories;
-+ [default_incoming_files]
-+ | l -> l
-
- let search_incoming_directories () =
-- try
-- List.find (fun s -> s.shdir_strategy = "incoming_directories")
-- !!shared_directories
-- with Not_found ->
-- let dirname = Filename.concat "incoming" "directories" in
-- let s = {
-- shdir_dirname = dirname;
-- shdir_priority = 0;
-- shdir_networks = [];
-- shdir_strategy = "incoming_directories";
-- }
-- in
-- shared_directories =:= s :: !!shared_directories;
-- s
-+ let list =
-+ List.filter (fun s -> s.shdir_strategy = "incoming_directories") !!shared_directories
-+ in
-+ match list with
-+ | [] -> shared_directories =:= default_incoming_directories :: !!shared_directories;
-+ [default_incoming_directories]
-+ | l -> l
-+
-+exception Incoming_full
-+
-+let incoming_dir usedir ?user ?needed_space ?network () =
-+
-+ let directories =
-+ if usedir then
-+ search_incoming_directories ()
-+ else
-+ search_incoming_files ()
-+ in
-+
-+ let dirname_user =
-+ match user with
-+ | None -> ""
-+ | Some user -> user.user_commit_dir
-+ in
-+
-+(*
-+ let dirname_network =
-+ match network with
-+ | None -> ""
-+ | Some network -> network
-+ in
-+*)
-+(* todo: make the dir naming order user configurable *)
-+ let compute_dir_name dir =
-+ let dirname = Filename2.normalize (Filename.concat dir dirname_user) in
-+(* let dirname = Filename.concat dirname dirname_network in *)
-+ dirname
-+ in
-+
-+ let checkdir =
-+ try
-+ List.find (fun d ->
-+ let dirname = compute_dir_name d.shdir_dirname in
-+(* check if temp_directory and incoming are on different partitions *)
-+ try
-+ if (Unix.stat dirname).Unix.st_dev <> (Unix.stat !!temp_directory).Unix.st_dev then
-+ begin
-+ match needed_space with
-+ | None -> true
-+ | Some needed_space ->
-+ match Unix32.diskfree dirname with
-+ Some v -> v >= needed_space
-+ | _ -> true
-+ end
-+ else true
-+ with _ -> true
-+ ) directories
-+ with Not_found -> raise Incoming_full;
-+ in
-+
-+ let newdir = {
-+ shdir_dirname = (compute_dir_name checkdir.shdir_dirname);
-+ shdir_priority = checkdir.shdir_priority;
-+ shdir_networks = checkdir.shdir_networks;
-+ shdir_strategy = checkdir.shdir_strategy;
-+ }
-+ in
-+ Unix2.safe_mkdir newdir.shdir_dirname;
-+ Unix2.can_write_to_directory newdir.shdir_dirname;
-+ newdir
-
--let incoming_directories () =
-- let dir = search_incoming_directories () in
-- Unix2.safe_mkdir dir.shdir_dirname;
-- Unix2.can_write_to_directory dir.shdir_dirname;
-- dir
-
- let _ =
- (* Check the definition of the incoming_files and incoming_directories in
-@@ -929,8 +1033,8 @@
- option_hook shared_directories (fun _ ->
- if not !verification then begin
- verification := true;
-- ignore (incoming_files ());
-- ignore (incoming_directories ());
-+ ignore (incoming_dir false ());
-+ ignore (incoming_dir true ());
- verification := false
- end
- )
-@@ -1038,19 +1142,15 @@
- Pervasives.really_input ic s 0 size;
- header, s) in
- Tar.output otar header s
-- with e ->
-- let error = Printexc2.to_string e in
-- if error = "Gzip.Error(\"error during compression\")"
-- && Autoconf.windows && arg = "fasttrack.ini" then begin
-- (* for whatever reason this error is raised on Windows,
-- but fasttrack.ini is stored correctly *)
-- if !verbose then
-- lprintf_nl "Tar: Windows specific pseudo error %s in %s" error arg
-- end
-- else begin
-+ with
-+ | (Gzip.Error "error during compression") as e when Autoconf.windows && arg = "fasttrack.ini" ->
-+ (* for whatever reason this error is raised on Windows,
-+ but fasttrack.ini is stored correctly *)
-+ if !verbose then
-+ lprintf_nl "Tar: Windows specific pseudo error %s in %s" (Printexc2.to_string e) arg
-+ | e ->
- failed_files := arg :: !failed_files;
-- lprintf_nl "Tar: error %s in %s" error arg
-- end
-+ lprintf_nl "Tar: error %s in %s" (Printexc2.to_string e) arg
- ) files);
- if !failed_files <> [] then
- failwith (Printf.sprintf "Tar: error backing up %s"
-@@ -1141,7 +1241,7 @@
- let reserved_fds = 40 in (* ini files, dynamic libs, etc. *)
-
- let total_files = (* maximum number of files in use at the same time *)
-- (maxi (List.length !!files) !!max_concurrent_downloads) + !!max_upload_slots + reserved_fds
-+ (max (List.length !!files) !!max_concurrent_downloads) + !!max_upload_slots + reserved_fds
- in
-
- let wanted_socks = !!max_opened_connections + total_files in
-@@ -1158,7 +1258,7 @@
- else
- begin
- let new_max_opened_connections =
-- maxi (max_all_sockets - total_files) (max_all_sockets / 2)
-+ max (max_all_sockets - total_files) (max_all_sockets / 2)
- in
- lprintf_nl "max_opened_connections is set too high (%d), reducing to %d"
- !!max_opened_connections new_max_opened_connections;
-Index: src/daemon/common/commonComplexOptions.mli
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonComplexOptions.mli,v
-retrieving revision 1.17
-retrieving revision 1.20
-diff -u -r1.17 -r1.20
---- src/daemon/common/commonComplexOptions.mli 19 Mar 2006 17:38:08 -0000 1.17
-+++ src/daemon/common/commonComplexOptions.mli 9 Nov 2006 21:32:26 -0000 1.20
-@@ -34,15 +34,15 @@
- (string * CommonTypes.query_entry) list
- val special_queries : (string * string) list Options.option_record
-
--val sharing_strategies : string -> CommonTypes.sharing_strategy
-+val sharing_strategies : (string * CommonTypes.sharing_strategy) list Options.option_record
-+val sharing_strategy : string -> CommonTypes.sharing_strategy
-
- val shared_directories :
- CommonTypes.shared_directory list Options.option_record
-
--val incoming_files : unit -> CommonTypes.shared_directory
--val incoming_directories : unit -> CommonTypes.shared_directory
--val search_incoming_files : unit -> CommonTypes.shared_directory
--val search_incoming_directories : unit -> CommonTypes.shared_directory
-+val incoming_dir : bool -> ?user:CommonTypes.userdb -> ?needed_space:int64 -> ?network:string -> unit -> CommonTypes.shared_directory
-+val search_incoming_files : unit -> CommonTypes.shared_directory list
-+val search_incoming_directories : unit -> CommonTypes.shared_directory list
-
- val sharing_only_directory : CommonTypes.sharing_strategy
-
-Index: src/daemon/common/commonFile.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonFile.ml,v
-retrieving revision 1.60
-retrieving revision 1.70
-diff -u -r1.60 -r1.70
---- src/daemon/common/commonFile.ml 5 Sep 2006 14:18:24 -0000 1.60
-+++ src/daemon/common/commonFile.ml 15 Nov 2006 12:37:13 -0000 1.70
-@@ -25,6 +25,7 @@
- open CommonTypes
- open CommonOptions
- open CommonGlobals
-+open CommonUserDb
-
- let log_prefix = "[cF]"
-
-@@ -41,10 +42,12 @@
- (*************************************************************************)
-
- type 'a file_impl = {
-+ mutable impl_file_owner : userdb;
-+ mutable impl_file_group : groupdb option;
- mutable impl_file_update : int;
- mutable impl_file_state : file_state;
-
-- mutable impl_file_comment : string list;
-+ mutable impl_file_comment : string;
- mutable impl_file_num : int;
- mutable impl_file_val : 'a;
- mutable impl_file_ops : 'a file_ops;
-@@ -59,6 +62,7 @@
- mutable impl_file_filenames : string list;
- mutable impl_file_magic : string option;
- mutable impl_file_priority: int; (* normal = 0, low < 0, high > 0 *)
-+ mutable impl_file_release : bool;
- mutable impl_file_last_seen : int;
- mutable impl_file_probable_name : string option;
- }
-@@ -75,6 +79,7 @@
- has been changed. The method should not perform the move, just know that
- it will happen soon. *)
- mutable op_file_save_as : ('a -> string -> unit);
-+ mutable op_file_shared : ('a -> CommonTypes.shared option);
- mutable op_file_to_option : ('a -> (string * option_value) list);
- mutable op_file_cancel : ('a -> unit);
- mutable op_file_pause : ('a -> unit);
-@@ -85,9 +90,10 @@
- mutable op_file_recover : ('a -> unit);
- mutable op_file_all_sources : ('a -> client list);
- mutable op_file_active_sources : ('a -> client list);
-+ mutable op_file_comment : ('a -> string);
- mutable op_file_set_priority : ('a -> int -> unit);
-- mutable op_file_print_html : ('a -> Buffer.t -> unit);
-- mutable op_file_print_sources_html : ('a -> Buffer.t -> unit);
-+ mutable op_file_print : ('a -> CommonTypes.ui_conn -> unit);
-+ mutable op_file_print_sources : ('a -> CommonTypes.ui_conn -> unit);
- mutable op_file_files : ('a -> 'a file_impl -> file list);
- (* added in 2.5.27 to remove use of network names in global modules *)
- mutable op_file_debug : ('a -> string);
-@@ -130,9 +136,12 @@
- impl_file_filenames = [];
- impl_file_magic = None;
- impl_file_priority = 0;
-+ impl_file_release = false;
- impl_file_last_seen = 0;
-- impl_file_comment = [];
-+ impl_file_comment = "";
- impl_file_probable_name = None;
-+ impl_file_owner = admin_user;
-+ impl_file_group = Some system_user_default_group;
- }
-
- let dummy_file = as_file dummy_file_impl
-@@ -198,16 +207,18 @@
- let file = as_file_impl file in
- file.impl_file_ops.op_file_to_option file.impl_file_val
-
-- (*
--let file_print (file : file) buf =
-- let file = as_file_impl file in
-- file.impl_file_ops.op_file_print file.impl_file_val buf
-- *)
--
- let file_save_as (file : file) name =
- let file = as_file_impl file in
- file.impl_file_ops.op_file_save_as file.impl_file_val name
-
-+let file_shared (file : file) =
-+ let file = as_file_impl file in
-+ file.impl_file_ops.op_file_shared file.impl_file_val
-+
-+let file_comment (file : file) =
-+ let file = as_file_impl file in
-+ file.impl_file_ops.op_file_comment file.impl_file_val
-+
- let file_network (file : file) =
- let file = as_file_impl file in
- file.impl_file_ops.op_file_network
-@@ -216,7 +227,17 @@
- let file = as_file_impl file in
- file.impl_file_ops.op_file_info file.impl_file_val
-
--let file_pause (file : file) =
-+let file_owner file =
-+ (as_file_impl file).impl_file_owner
-+
-+let file_group file =
-+ (as_file_impl file).impl_file_group
-+
-+let user2_allow_file_admin file user =
-+ user2_is_admin user || file_owner file = user
-+
-+let file_pause (file : file) user =
-+ if user2_allow_file_admin file user then
- let file = as_file_impl file in
- match file.impl_file_state with
- | FileDownloading | FileQueued ->
-@@ -224,7 +245,8 @@
- file.impl_file_ops.op_file_pause file.impl_file_val
- | _ -> ()
-
--let file_resume (file : file) =
-+let file_resume (file : file) user =
-+ if user2_allow_file_admin file user then
- let file = as_file_impl file in
- match file.impl_file_state with
- | FilePaused | FileAborted _ ->
-@@ -232,20 +254,47 @@
- file.impl_file_ops.op_file_resume file.impl_file_val
- | _ -> ()
-
-+let set_file_release file status user =
-+ if user2_allow_file_admin file user then
-+ let impl = as_file_impl file in
-+ impl.impl_file_release <- status
-+
-+let file_release (file: file) =
-+ let impl = as_file_impl file in
-+ impl.impl_file_release
-+
-+let set_file_owner file owner =
-+ (as_file_impl file).impl_file_owner <- owner
-+
-+let set_file_group file group =
-+ (as_file_impl file).impl_file_group <- group
-+
-+let user2_filter_files files gui_user =
-+ let newlist = List.filter
-+ (fun file -> user2_can_view_file gui_user (file_owner file) (file_group file)) files in
-+ newlist
-+
-+let user2_num_user_dls user =
-+ let n = ref 0 in
-+ H.iter (fun f -> if file_owner f = user then incr n) files_by_num;
-+ !n
-+
-+let user2_num_group_dls group =
-+ let n = ref 0 in
-+ H.iter (fun f -> if file_group f = Some group then incr n) files_by_num;
-+ !n
-+
- let set_file_state file state =
- let impl = as_file_impl file in
- update_file_state impl state
-
- let set_file_comment file comment =
-- if not (List.mem comment (as_file_impl file).impl_file_comment) then
-- (as_file_impl file).impl_file_comment <-
-- (as_file_impl file).impl_file_comment @ [(HashComments.merge file_comments comment)]
-+ let impl = as_file_impl file in
-+ impl.impl_file_comment <- comment
-
- let file_comment file =
-- (as_file_impl file).impl_file_comment
--
--let file_comment_length file =
-- List.length (as_file_impl file).impl_file_comment
-+ let impl = as_file_impl file in
-+ impl.impl_file_comment
-
- let file_best_name (file : file) =
- let file = as_file_impl file in
-@@ -316,7 +365,9 @@
- try impl.impl_file_ops.op_file_active_sources impl.impl_file_val with _ -> []
-
- (* Default for networks that don't implement it *)
--let default_file_print_sources_html file buf =
-+let default_file_print_sources file o =
-+ let buf = o.conn_buf in
-+ if use_html_mods o then begin
- let cfile = as_file file in
- let allsources = ref (file_all_sources cfile) in
- if List.length !allsources > 0 then begin
-@@ -346,7 +397,8 @@
- ("", "sr br ar", Printf.sprintf "%d" (client_num c));
- ("", "sr br", cinfo.GuiTypes.client_name);
- ("", "sr br", addr);
-- ("", "sr br", cinfo.GuiTypes.client_software);
-+ (GuiTypes.client_software cinfo.GuiTypes.client_software cinfo.GuiTypes.client_os,
-+ "sr br", GuiTypes.client_software_short cinfo.GuiTypes.client_software cinfo.GuiTypes.client_os);
- ("", "sr ar", (size_of_int64 cinfo.GuiTypes.client_uploaded));
- ("", "sr ar br", (size_of_int64 cinfo.GuiTypes.client_downloaded)); ];
-
-@@ -357,16 +409,26 @@
- Printf.bprintf buf "\\</table\\>\\</div\\>\\<br\\>";
-
- end
-+ end
-+ else
-+ let cfile = as_file file in
-+ let srcs = ref (file_all_sources cfile) in
-+ Printf.bprintf buf "%d sources:\n" (List.length !srcs);
-+ let print_source c =
-+ Printf.bprintf buf " [%4d] " (client_num c);
-+ client_bprint c buf;
-+ in
-+ List.iter print_source !srcs;
-+ ()
-
--
--let file_print_sources_html (file : file) buf =
-+let file_print_sources (file : file) conn =
- let file = as_file_impl file in
-- try file.impl_file_ops.op_file_print_sources_html file.impl_file_val buf with _ ->
-- default_file_print_sources_html file buf
-+ try file.impl_file_ops.op_file_print_sources file.impl_file_val conn with _ ->
-+ default_file_print_sources file conn
-
--let file_print_html file buf =
-+let file_print file o =
- let impl = as_file_impl file in
-- impl.impl_file_ops.op_file_print_html impl.impl_file_val buf
-+ impl.impl_file_ops.op_file_print impl.impl_file_val o
-
- let file_find num =
- H.find files_by_num (as_file {
-@@ -469,7 +531,9 @@
- let set_file_magic file magic =
- match magic with
- None -> ()
-- | Some magic -> (as_file_impl file).impl_file_magic <- Some (HashMagic.merge files_magic magic)
-+ | Some magic ->
-+ (as_file_impl file).impl_file_magic <- Some (intern magic);
-+ file_must_update file
-
- let check_magic file =
- let check file =
-@@ -488,9 +552,10 @@
- impl.impl_file_last_seen <- age
-
- let file_preview (file : file) =
-- let cmd = Printf.sprintf "%s \"%s\" \"%s\"" !!previewer
-- (file_disk_name file) (file_best_name file) in
-- ignore (Sys.command cmd)
-+ ignore(
-+ Unix.create_process !!previewer
-+ [| Filename2.basename !!previewer; file_disk_name file; file_best_name file |]
-+ Unix.stdin Unix.stdout Unix.stderr)
-
- (*************************************************************************)
- (* *)
-@@ -627,6 +692,77 @@
- ("", "sr", Printf.sprintf "%d" (file_priority file)) ];
-
- Printf.bprintf buf "\\</tr\\>\\<tr class=\\\"dl-%d\\\"\\>" (html_mods_cntr ());
-+ if user2_allow_file_admin file o.conn_user.ui_user then
-+ let optionlist = ref "" in
-+ user2_users_iter (fun user ->
-+ if user <> (file_owner file) then
-+ optionlist := !optionlist ^ Printf.sprintf "\\<option value=\\\"%s\\\"\\>%s\\</option\\>\n" user.user_name user.user_name;
-+ );
-+
-+ html_mods_td buf [("Change file owner by selecting an alternate user", "sr br", "User");
-+ ("Change owner", "sr", Printf.sprintf "
-+\\<script type=\\\"text/javascript\\\"\\>
-+\\<!--
-+function submitChownForm(i) {
-+var formID = document.getElementById(\\\"chownForm\\\" + i)
-+var v = formID.newOwner.value;
-+parent.fstatus.location.href='submit?q=chown+'+v+'+%d';
-+}
-+//--\\>
-+\\</script\\>" (file_num file)
-+ ^ "\\<table border=0 cellspacing=0 cellpadding=0\\>\\<tr\\>"
-+ ^ "\\<form name=\\\"chownForm1\\\" id=\\\"chownForm1\\\" action=\\\"javascript:submitChownForm(1);\\\"\\>"
-+ ^ "\\<td\\>"
-+ ^ "\\<select name=\\\"newOwner\\\" id=\\\"newOwner\\\" "
-+ ^ "style=\\\"padding: 0px; font-size: 10px; font-family: verdana\\\" onchange=\\\"this.form.submit()\\\"\\>"
-+ ^ Printf.sprintf "\\<option value=\\\"%s\\\" selected\\>%s\\</option\\>\n" (file_owner file).user_name (file_owner file).user_name
-+ ^ !optionlist ^ "\\</select\\>\\</td\\>\\</form\\>\\</tr\\>\\</table\\>"
-+ ) ];
-+
-+ else
-+ html_mods_td buf [("File owner", "sr br", "User"); ("", "sr", (file_owner file).user_name)];
-+
-+ Printf.bprintf buf "\\</tr\\>\\<tr class=\\\"dl-%d\\\"\\>" (html_mods_cntr ());
-+ if user2_allow_file_admin file o.conn_user.ui_user &&
-+ o.conn_user.ui_user.user_groups <> [] then
-+ let optionlist =
-+ if (file_group file) = None then
-+ ref ""
-+ else
-+ ref "\\<option value=\\\"None\\\"\\>None\\</option\\>\n"
-+ in
-+ user2_user_groups_iter (file_owner file) (fun group ->
-+ if Some group <> (file_group file) then
-+ optionlist := !optionlist ^ Printf.sprintf "\\<option value=\\\"%s\\\"\\>%s\\</option\\>\n" group.group_name group.group_name;
-+ );
-+
-+ html_mods_td buf [("Change file group by selecting an alternate group", "sr br", "Group");
-+ ("Change group", "sr", Printf.sprintf "
-+\\<script type=\\\"text/javascript\\\"\\>
-+\\<!--
-+function submitChgrpForm(i) {
-+var formID = document.getElementById(\\\"chgrpForm\\\" + i)
-+var v = formID.newGroup.value;
-+parent.fstatus.location.href='submit?q=chgrp+'+v+'+%d';
-+}
-+//--\\>
-+\\</script\\>" (file_num file)
-+ ^ "\\<table border=0 cellspacing=0 cellpadding=0\\>\\<tr\\>"
-+ ^ "\\<form name=\\\"chgrpForm1\\\" id=\\\"chgrpForm1\\\" action=\\\"javascript:submitChgrpForm(1);\\\"\\>"
-+ ^ "\\<td\\>"
-+ ^ "\\<select name=\\\"newGroup\\\" id=\\\"newGroup\\\" "
-+ ^ "style=\\\"padding: 0px; font-size: 10px; font-family: verdana\\\" onchange=\\\"this.form.submit()\\\"\\>"
-+ ^ Printf.sprintf "\\<option value=\\\"%s\\\" selected\\>%s\\</option\\>\n" (user2_print_group (file_group file)) (user2_print_group (file_group file))
-+ ^ !optionlist ^ "\\</select\\>\\</td\\>\\</form\\>\\</tr\\>\\</table\\>"
-+ ) ];
-+
-+ else
-+ html_mods_td buf [("File group", "sr br", "Group");
-+ ("", "sr", (match file_group file with
-+ Some group -> Printf.sprintf "%s" group.group_name
-+ | None -> "None"))];
-+
-+ Printf.bprintf buf "\\</tr\\>\\<tr class=\\\"dl-%d\\\"\\>" (html_mods_cntr ());
- html_mods_td buf [
- ("Number of file sources", "sr br", "Sources");
- ("", "sr", Printf.sprintf "%d" (List.length srcs)) ];
-@@ -671,30 +807,14 @@
- ("", "sr", magic) ]
- | _ -> ());
-
-- (
-- if file_comment file <> [] then
-- begin
-- let list_header = ref true in
-- List.iter (fun s ->
-- Printf.bprintf buf "\\</tr\\>\\<tr class=\\\"dl-%d\\\"\\>" (html_mods_cntr ());
-- if !list_header then html_mods_td buf [
-- ("File comments", "sr br", "File comments");
-- ("", "sr", s) ]
-- else
-- html_mods_td buf [
-- ("", "sr br", "");
-- ("", "sr", s) ];
-- if !list_header then list_header := false) (file_comment file);
-- end);
--
-- file_print_html file buf;
-+ file_print file o;
-
- Printf.bprintf buf "\\</tr\\>\\</table\\>\\</div\\>";
- Printf.bprintf buf "\\</td\\>\\</tr\\>\\</table\\>\\</div\\>\\<br\\>";
-
- end else
- begin
-- Printf.bprintf buf "[%-s %5d]\n%s\n%s%s\nTotal %10s\nPartial %10s\npriority %d\n"
-+ Printf.bprintf buf "[%-s %5d]\n%s\n%s%s\nTotal %10s\nPartial %10s\npriority %d\nOwner/Group: %s/%s\n"
- n.network_name
- (file_num file)
- (shorten (file_best_name file) 80)
-@@ -704,7 +824,11 @@
- (string_of_uids info.G.file_uids)
- (Int64.to_string info.G.file_size)
- (Int64.to_string info.G.file_downloaded)
-- (file_priority file);
-+ (file_priority file)
-+ (file_owner file).user_name
-+ (match file_group file with
-+ Some group -> Printf.sprintf "%s" group.group_name
-+ | None -> "private");
- Printf.bprintf buf "Chunks: [%-s]\n"
- (match info.G.file_chunks with
- | None -> ""
-@@ -713,24 +837,12 @@
- None -> ()
- | Some filename ->
- Printf.bprintf buf "Probable name: %s\n" filename);
-- List.iter (fun name -> Printf.bprintf buf " (%s)\n" name) info.G.file_names
-+ List.iter (fun name -> Printf.bprintf buf " (%s)\n" name) info.G.file_names;
-+ file_print file o
- end;
-
- (try
--
-- if !!print_all_sources then begin
-- if use_html_mods o then
-- file_print_sources_html file buf
-- else begin
-- Printf.bprintf buf "%d sources:\n" (List.length srcs);
-- let print_source c =
-- Printf.bprintf buf " [%4d] " (client_num c);
-- client_bprint c buf;
-- in
-- List.iter print_source srcs;
-- end;
-- end
--
-+ if !!print_all_sources then file_print_sources file o
- with _ -> ())
-
- let file_print_ed2k_link filename filesize md4hash =
-@@ -869,6 +981,7 @@
- op_file_commit = (fun _ _ -> ni_ok network "file_commit");
- op_file_save_as = (fun _ _ -> ni_ok network "file_save_as");
- (* op_file_print = (fun _ _ -> ni_ok network "file_print"); *)
-+ op_file_shared = (fun _ -> None);
- op_file_to_option = (fun _ -> fni network "file_to_option");
- op_file_cancel = (fun _ -> ni_ok network "file_cancel");
- op_file_info = (fun _ -> fni network "file_info");
-@@ -881,9 +994,10 @@
- op_file_set_format = (fun _ -> fni network "file_set_format");
- op_file_all_sources = (fun _ -> fni network "file_all_sources");
- op_file_active_sources = (fun _ -> fni network "file_active_sources");
-+ op_file_comment = (fun _ -> ni_ok network "file_comment"; "");
- op_file_set_priority = (fun _ _ -> ni_ok network "file_set_priority");
-- op_file_print_html = (fun _ _ -> ni_ok network "file_print_html");
-- op_file_print_sources_html = (fun _ _ -> fni network "file_print_sources_html");
-+ op_file_print = (fun _ _ -> ni_ok network "file_print_html");
-+ op_file_print_sources = (fun _ _ -> fni network "file_print_sources");
- op_file_debug = (fun _ -> "");
- op_file_proposed_filenames = (fun impl -> []);
- }
-@@ -906,6 +1020,8 @@
- lprintf_nl "op_file_commit";
- if c.op_file_save_as == cc.op_file_save_as then
- lprintf_nl "op_file_save_as";
-+ if c.op_file_shared == cc.op_file_shared then
-+ lprintf_nl "op_file_shared";
- if c.op_file_cancel == cc.op_file_cancel then
- lprintf_nl "op_file_cancel";
- if c.op_file_pause == cc.op_file_pause then
-@@ -924,10 +1040,10 @@
- lprintf_nl "op_file_all_sources";
- if c.op_file_active_sources == cc.op_file_active_sources then
- lprintf_nl "op_file_active_sources";
-- if c.op_file_print_html == cc.op_file_print_html then
-- lprintf_nl "op_file_print_html";
-- if c.op_file_print_sources_html == cc.op_file_print_sources_html then
-- lprintf_nl "op_file_print_sources_html";
-+ if c.op_file_print == cc.op_file_print then
-+ lprintf_nl "op_file_print";
-+ if c.op_file_print_sources == cc.op_file_print_sources then
-+ lprintf_nl "op_file_print_sources";
- ) !files_ops;
- lprint_newline ()
-
-@@ -949,12 +1065,6 @@
- ) files_by_num;
- Printf.bprintf buf " files: %d\n" !counter;
- Printf.bprintf buf " files_ops: %d\n" (List.length !files_ops);
-- let counter = ref 0 in
-- HashMagic.iter (fun _ -> incr counter) files_magic;
-- Printf.bprintf buf " files_magic: %d\n" !counter;
-- let counter = ref 0 in
-- HashComments.iter (fun _ -> incr counter) file_comments;
-- Printf.bprintf buf " files_comments: %d\n" !counter
- )
-
-
-@@ -1072,7 +1182,7 @@
- let module T = GuiTypes in
- {
- T.file_fields = T.Fields_file_info.all;
-- T.file_comment = "";
-+ T.file_comment = impl.impl_file_comment;
- T.file_name = impl.impl_file_best_name;
- T.file_names = impl.impl_file_filenames;
- T.file_num = impl.impl_file_num;
-@@ -1095,4 +1205,14 @@
- T.file_chunks_age = [||];
- T.file_uids = [];
- T.file_sub_files = [];
-+ T.file_magic = impl.impl_file_magic;
-+ T.file_comments = [];
-+ T.file_user = impl.impl_file_owner.user_name;
-+ T.file_group = user2_print_group impl.impl_file_group;
-+ T.file_release = impl.impl_file_release;
- }
-+
-+let lprintf_file_nl file fmt =
-+ lprintf_nl2 ("[" ^ (file_network file).network_shortname ^
-+ "] [file_num " ^ (string_of_int (file_num file)) ^ "]" ^
-+ "[temp " ^ (file_disk_name file) ^ "]") fmt
-Index: src/daemon/common/commonFile.mli
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonFile.mli,v
-retrieving revision 1.20
-retrieving revision 1.30
-diff -u -r1.20 -r1.30
---- src/daemon/common/commonFile.mli 5 Sep 2006 14:18:24 -0000 1.20
-+++ src/daemon/common/commonFile.mli 12 Nov 2006 12:44:24 -0000 1.30
-@@ -18,10 +18,12 @@
- *)
-
- type 'a file_impl = {
-+ mutable impl_file_owner : CommonTypes.userdb;
-+ mutable impl_file_group : CommonTypes.groupdb option;
- mutable impl_file_update : int;
- mutable impl_file_state : CommonTypes.file_state;
-
-- mutable impl_file_comment : string list;
-+ mutable impl_file_comment : string;
- mutable impl_file_num : int;
- mutable impl_file_val : 'a;
- mutable impl_file_ops : 'a file_ops;
-@@ -36,6 +38,7 @@
- mutable impl_file_filenames : string list;
- mutable impl_file_magic : string option;
- mutable impl_file_priority : int;
-+ mutable impl_file_release : bool;
- mutable impl_file_last_seen : int;
- mutable impl_file_probable_name : string option;
- }
-@@ -43,6 +46,7 @@
- mutable op_file_network : CommonTypes.network;
- mutable op_file_commit : 'a -> string -> unit;
- mutable op_file_save_as : 'a -> string -> unit;
-+ mutable op_file_shared : 'a -> CommonTypes.shared option;
- mutable op_file_to_option : 'a -> (string * Options.option_value) list;
- mutable op_file_cancel : 'a -> unit;
- mutable op_file_pause : 'a -> unit;
-@@ -53,9 +57,10 @@
- mutable op_file_recover : 'a -> unit;
- mutable op_file_all_sources : 'a -> CommonTypes.client list;
- mutable op_file_active_sources : 'a -> CommonTypes.client list;
-+ mutable op_file_comment : 'a -> string;
- mutable op_file_set_priority : 'a -> int -> unit;
-- mutable op_file_print_html: 'a -> Buffer.t -> unit;
-- mutable op_file_print_sources_html : 'a -> Buffer.t -> unit;
-+ mutable op_file_print: 'a -> CommonTypes.ui_conn -> unit;
-+ mutable op_file_print_sources : 'a -> CommonTypes.ui_conn -> unit;
- mutable op_file_files : ('a -> 'a file_impl -> CommonTypes.file list);
- mutable op_file_debug : 'a -> string;
- mutable op_file_proposed_filenames : 'a -> string list;
-@@ -75,10 +80,14 @@
- val update_file_state : 'a file_impl -> CommonTypes.file_state -> unit
- val file_to_option : CommonTypes.file -> (string * Options.option_value) list
- val file_save_as : CommonTypes.file -> string -> unit
-+val file_shared : CommonTypes.file -> CommonTypes.shared option
-+val file_comment : CommonTypes.file -> string
- val file_network : CommonTypes.file -> CommonTypes.network
- val file_info : CommonTypes.file -> GuiTypes.file_info
--val file_pause : CommonTypes.file -> unit
--val file_resume : CommonTypes.file -> unit
-+val file_pause : CommonTypes.file -> CommonTypes.userdb -> unit
-+val file_resume : CommonTypes.file -> CommonTypes.userdb -> unit
-+val set_file_release : CommonTypes.file -> bool -> CommonTypes.userdb -> unit
-+val file_release : CommonTypes.file -> bool
- val set_file_state : CommonTypes.file -> CommonTypes.file_state -> unit
- val file_best_name : CommonTypes.file -> string
- val set_file_best_name : CommonTypes.file -> string -> string -> int -> unit
-@@ -90,7 +99,7 @@
- val file_preview : CommonTypes.file -> unit
- val file_all_sources : CommonTypes.file -> CommonTypes.client list
- val file_active_sources : CommonTypes.file -> CommonTypes.client list
--val file_print_sources_html : CommonTypes.file -> Buffer.t -> unit
-+val file_print_sources : CommonTypes.file -> CommonTypes.ui_conn -> unit
- val files_ops : (int file_ops * int file_ops) list ref
- val new_file_ops : CommonTypes.network -> 'a file_ops
- val check_file_implementations : unit -> unit
-@@ -118,8 +127,7 @@
- val set_file_last_seen : CommonTypes.file -> int -> unit
- val file_debug : CommonTypes.file -> string
- val set_file_comment : CommonTypes.file -> string -> unit
--val file_comment : CommonTypes.file -> string list
--val file_comment_length : CommonTypes.file -> int
-+val file_comment : CommonTypes.file -> string
- val file_magic : CommonTypes.file -> string option
- val set_file_magic : CommonTypes.file -> string option -> unit
- val check_magic : CommonTypes.file -> unit
-@@ -136,3 +144,13 @@
-
- val forceable_download : CommonTypes.result_info list ref
- val impl_file_info : 'a file_impl -> GuiTypes.file_info
-+
-+val user2_filter_files : CommonTypes.file list -> CommonTypes.userdb -> CommonTypes.file list
-+val user2_num_user_dls : CommonTypes.userdb -> int
-+val user2_num_group_dls : CommonTypes.groupdb -> int
-+val user2_allow_file_admin : CommonTypes.file -> CommonTypes.userdb -> bool
-+val set_file_owner : CommonTypes.file -> CommonTypes.userdb -> unit
-+val file_owner : CommonTypes.file -> CommonTypes.userdb
-+val set_file_group : CommonTypes.file -> CommonTypes.groupdb option -> unit
-+val file_group : CommonTypes.file -> CommonTypes.groupdb option
-+val lprintf_file_nl : CommonTypes.file -> ('a, unit, unit) Pervasives.format -> 'a
-Index: src/daemon/common/commonGlobals.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonGlobals.ml,v
-retrieving revision 1.71
-retrieving revision 1.76
-diff -u -r1.71 -r1.76
---- src/daemon/common/commonGlobals.ml 16 Sep 2006 15:36:08 -0000 1.71
-+++ src/daemon/common/commonGlobals.ml 21 Nov 2006 22:34:33 -0000 1.76
-@@ -117,7 +117,7 @@
- with e -> slen
- in
- let diff_len_utf8_ascii = slen - len in
-- let max_len = maxi limit 10 in
-+ let max_len = max limit 10 in
- if len > max_len then
- let prefix = String.sub name 0 (max_len - 7 + diff_len_utf8_ascii) in
- let suffix = String.sub name (len - 4 + diff_len_utf8_ascii) 4 in
-@@ -177,7 +177,7 @@
- cc.control_state <- cc.control_state + 1
-
- let connection_next_try cc =
-- cc.control_last_try + mini (cc.control_min_reask * cc.control_state)
-+ cc.control_last_try + min (cc.control_min_reask * cc.control_state)
- cc.control_min_reask
-
- let connection_can_try cc =
-@@ -238,7 +238,7 @@
- float_of_int (if !!max_hard_upload_rate = 0 then
- 10000 * 1024
- else
-- maxi (!!max_hard_upload_rate * 1024) 1024) *. 0.90;
-+ max (!!max_hard_upload_rate * 1024) 1024) *. 0.90;
- );
- option_hook max_hard_download_rate (fun _ ->
- check_ul_dl_ratio ();
-@@ -481,17 +481,18 @@
-
- let log_chat_message i num n s =
- Fifo.put chat_message_fifo (last_time(),i,num,n,s);
-- try
-+ (try
- Unix2.tryopen_write_gen !messages_log [Open_creat; Open_wronly; Open_append]
- 0o600 (fun oc ->
- Printf.fprintf oc "%s: %s (%s): %s\n" (Date.simple (BasicSocket.date_of_int (last_time ()))) n i s)
- with e ->
- lprintf_nl "[ERROR] Exception %s while trying to log message to %s"
-- (Printexc2.to_string e) !messages_log;
-+ (Printexc2.to_string e) !messages_log);
-
- while (Fifo.length chat_message_fifo) > !!html_mods_max_messages do
- ignore(Fifo.take chat_message_fifo)
- done
-+
- let last_message_log = ref 0
-
-
-@@ -499,7 +500,7 @@
- let debug_clients = ref Intset.empty
-
- let default_user = {
-- ui_user_name = CommonUserDb.admin_user;
-+ ui_user = CommonUserDb.admin_user;
- ui_user_searches = [];
- ui_last_search = None;
- ui_last_results = [];
-@@ -513,7 +514,7 @@
- match list with
- [] ->
- let u = {
-- ui_user_name = user;
-+ ui_user = (CommonUserDb.user2_user_find user);
- ui_user_searches = [];
- ui_last_search = None;
- ui_last_results = [];
-@@ -522,7 +523,7 @@
- ui_users := u :: !ui_users;
- u
- | u :: tail ->
-- if u.ui_user_name = user then u else iter tail
-+ if u.ui_user = (CommonUserDb.user2_user_find user) then u else iter tail
- in
- iter !ui_users
-
-@@ -617,8 +618,12 @@
- put time sample short_delay_bandwidth_samples;
- trimto 5 short_delay_bandwidth_samples
-
-+let history_step = 5
- let history_size = 720
-+let history_h_step = history_size * history_step
- let history_h_size = 720
-+let history_timeflag = ref 0.
-+let history_h_timeflag = ref 0.
-
- let upload_history = Fifo.create ()
- let download_history = Fifo.create ()
-@@ -637,7 +642,7 @@
- let update_download_history () =
- Fifo.put download_history (download_usage ());
- let len = ref (Fifo.length download_history) in
-- while !len > history_size do
-+ while !len > history_size+1 do
- ignore (Fifo.take download_history);
- decr len
- done
-@@ -645,7 +650,7 @@
- let update_upload_history () =
- Fifo.put upload_history (upload_usage ());
- let len = ref (Fifo.length upload_history) in
-- while !len > history_size do
-+ while !len > history_size+1 do
- ignore (Fifo.take upload_history);
- decr len
- done
-@@ -653,7 +658,7 @@
- let update_h_download_history () =
- Fifo.put download_h_history ((List.fold_left (+) 0 (Fifo.to_list download_history)) / ((Fifo.length download_history)));
- let len = ref (Fifo.length download_h_history) in
-- while !len > history_h_size do
-+ while !len > history_h_size+1 do
- ignore (Fifo.take download_h_history);
- decr len
- done
-@@ -661,19 +666,19 @@
- let update_h_upload_history () =
- Fifo.put upload_h_history ((List.fold_left (+) 0 (Fifo.to_list upload_history)) / ((Fifo.length upload_history)));
- let len = ref (Fifo.length upload_h_history) in
-- while !len > history_h_size do
-+ while !len > history_h_size+1 do
- ignore (Fifo.take upload_h_history);
- decr len
- done
-
- let detected_link_capacity link =
-- List.fold_left maxi 0 (Fifo.to_list link)
-+ List.fold_left max 0 (Fifo.to_list link)
-
- let detected_uplink_capacity () =
-- List.fold_left maxi 0 (Fifo.to_list upload_history)
-+ List.fold_left max 0 (Fifo.to_list upload_history)
-
- let detected_downlink_capacity () =
-- List.fold_left maxi 0 (Fifo.to_list download_history)
-+ List.fold_left max 0 (Fifo.to_list download_history)
-
-
- let new_tag name v =
-@@ -890,18 +895,36 @@
- activity := new_activity ()
- )
-
--module HashMagic = Weak.Make(struct
-+module StringIntern = Weak.Make(struct
- type t = string
- let hash s = Hashtbl.hash s
- let equal x y = x = y
- end)
-
--let files_magic = HashMagic.create 100
-+let intern_table = StringIntern.create 1000
-+let intern s = StringIntern.merge intern_table s
-
--module HashComments = Weak.Make(struct
-- type t = string
-- let hash s = Hashtbl.hash s
-- let equal x y = x = y
-- end)
-+let print_command_result o buf result =
-+ if use_html_mods o then
-+ html_mods_table_one_row buf "serversTable" "servers" [
-+ ("", "srh", result); ]
-+ else
-+ Printf.bprintf buf "%s" result
-
--let file_comments = HashComments.create 1000
-+let _ =
-+ Heap.add_memstat "CommonGlobals" (fun level buf ->
-+ let counter = ref 0 in
-+ StringIntern.iter (fun f -> incr counter;) intern_table;
-+ Printf.bprintf buf " intern_table: %d\n" !counter;
-+ Printf.bprintf buf " core_gui_fifo: %d\n" (Fifo.length core_gui_fifo);
-+ Printf.bprintf buf " gui_core_fifo: %d\n" (Fifo.length gui_core_fifo);
-+ Printf.bprintf buf " chat_message_fifo: %d\n" (Fifo.length chat_message_fifo);
-+ Printf.bprintf buf " upload_history: %d\n" (Fifo.length upload_history);
-+ Printf.bprintf buf " download_history: %d\n" (Fifo.length download_history);
-+ Printf.bprintf buf " upload_h_history: %d\n" (Fifo.length upload_h_history);
-+ Printf.bprintf buf " download_h_history: %d\n" (Fifo.length download_h_history);
-+ Printf.bprintf buf " bandwidth_samples: %d\n" (Fifo.length bandwidth_samples);
-+ Printf.bprintf buf " short_delay_bandwidth_samples: %d\n" (Fifo.length short_delay_bandwidth_samples);
-+ Printf.bprintf buf " dummy_sample: %d\n" (Array.length dummy_sample);
-+ Printf.bprintf buf " activities: %d\n" (Fifo.length activities);
-+ )
-Index: src/daemon/common/commonInteractive.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonInteractive.ml,v
-retrieving revision 1.80
-retrieving revision 1.84
-diff -u -r1.80 -r1.84
---- src/daemon/common/commonInteractive.ml 5 Sep 2006 14:18:24 -0000 1.80
-+++ src/daemon/common/commonInteractive.ml 9 Nov 2006 21:32:26 -0000 1.84
-@@ -40,6 +40,7 @@
- open CommonServer
- open CommonTypes
- open CommonComplexOptions
-+open CommonUserDb
-
- let log_prefix = "[cInt]"
-
-@@ -179,7 +180,11 @@
- ("DLFILES", string_of_int (List.length !!files));
- ("INCOMING", incoming);
- ("NETWORK", network.network_name);
-- ("ED2K_HASH", (file_print_ed2k_link filename (file_size file) info.G.file_md4))]
-+ ("ED2K_HASH", (file_print_ed2k_link filename (file_size file) info.G.file_md4));
-+ ("FILE_OWNER",(file_owner file).user_name);
-+ ("FILE_GROUP",user2_print_group (file_group file));
-+ ]
-+
- with e ->
- lprintf_nl "Exception %s while executing %s"
- (Printexc2.to_string e) !!file_completed_cmd
-@@ -207,26 +212,13 @@
- (try
- let file_name = file_disk_name file in
- let incoming =
-- if Unix2.is_directory file_name then
-- incoming_directories ()
-- else
-- incoming_files ()
-+ incoming_dir
-+ (Unix2.is_directory file_name)
-+ ~needed_space:(file_size file)
-+ ~user:(file_owner file)
-+ ()
- in
-
--(* check if temp_directory and incoming are on different partitions *)
-- if (Unix.stat incoming.shdir_dirname).Unix.st_dev <>
-- (Unix.stat !!temp_directory).Unix.st_dev
-- then
-- begin
-- match Unix32.diskfree incoming.shdir_dirname with
-- Some v -> if v < (file_size file) then begin
-- send_dirfull_warning incoming.shdir_dirname true
-- (Printf.sprintf "can not commit %s" (file_best_name file));
-- raise Incoming_full
-- end
-- | _ -> ()
-- end;
--
- let new_name = file_commited_name incoming.shdir_dirname file in
- if Unix2.is_directory file_name then begin
- Unix2.safe_mkdir new_name;
-@@ -275,11 +267,15 @@
- with e ->
- lprintf_nl "Exception %s in file_commit secondaries" (Printexc2.to_string e);
- ) secondary_files
-- with e ->
-- lprintf_nl "Exception in file_commit: %s" (Printexc2.to_string e))
-+ with
-+ Incoming_full ->
-+ send_dirfull_warning "" true
-+ (Printf.sprintf "all incoming dirs are full, can not commit %s" (file_best_name file))
-+ | e -> lprintf_nl "Exception in file_commit: %s" (Printexc2.to_string e))
- | _ -> assert false
-
--let file_cancel file =
-+let file_cancel file user =
-+ if user2_allow_file_admin file user then
- try
- let impl = as_file_impl file in
- if impl.impl_file_state <> FileCancelled then
-@@ -308,7 +304,8 @@
- lprintf_nl "Exception in file_cancel: %s" (Printexc2.to_string e)
-
- let mail_for_completed_file file =
-- if !!mail <> "" then
-+ let usermail = (file_owner file).user_mail in
-+ if !!mail <> "" || usermail <> "" then begin
- let module M = Mailer in
- let info = file_info file in
- let line1 = "mldonkey has completed the download of:\r\n\r\n" in
-@@ -320,11 +317,8 @@
- (let age = (BasicSocket.last_time ()) - info.G.file_age in Date.time_to_string age "verbose")
- in
-
-- let line3 = if (file_comment file) = [] then "" else
-- let buf = Buffer.create 1000 in
-- Printf.bprintf buf "\r\nComments:\r\n";
-- List.iter (fun s -> Printf.bprintf buf "%s\r\n" s;) (file_comment file);
-- Buffer.contents buf
-+ let line3 = if (file_comment file) = "" then "" else
-+ Printf.sprintf "\r\nComment: %s\r\n" (file_comment file)
- in
-
- let subject = if !!filename_in_subject then
-@@ -333,12 +327,8 @@
- Printf.sprintf "mldonkey@%s, file received" (Unix.gethostname ())
- in
-
-- let incoming =
-- if Unix2.is_directory (file_disk_name file) then
-- incoming_directories ()
-- else
-- incoming_files ()
-- in
-+(* TODO: This information can be wrong *)
-+ let incoming = incoming_dir (Unix2.is_directory (file_disk_name file)) () in
-
- let line4 = if !!url_in_mail = "" then "" else
- Printf.sprintf "\r\n<%s/%s/%s>\r\n" !!url_in_mail incoming.shdir_dirname (Url.encode (file_best_name file))
-@@ -348,13 +338,22 @@
- Printf.sprintf "\r\nauto_commit is disabled, file is not committed to incoming"
- in
-
-- let mail = {
-- M.mail_to = !!mail;
-- M.mail_from = !!mail;
-+ let line6 =
-+ Printf.sprintf "\r\nUser/Group: %s:%s\r\n" (file_owner file).user_name (user2_print_group (file_group file))
-+ in
-+
-+ let send_mail address admin =
-+ let mail = {
-+ M.mail_to = address;
-+ M.mail_from = address;
- M.mail_subject = subject;
-- M.mail_body = line1 ^ line2 ^ line3 ^ line4 ^ line5;
-+ M.mail_body = line1 ^ line2 ^ line3 ^ line4 ^ line5 ^ (if admin then line6 else "");
- } in
-- M.sendmail !!smtp_server !!smtp_port !!add_mail_brackets mail
-+ M.sendmail !!smtp_server !!smtp_port !!add_mail_brackets mail
-+ in
-+ if !!mail <> "" then send_mail !!mail true; (* Multiuser ToDo: this mail is for the admin user, optional? *)
-+ if usermail <> "" && usermail <> !!mail then (try send_mail usermail false with Not_found -> ())
-+ end
-
- let file_completed (file : file) =
- try
-@@ -502,7 +501,7 @@
- let display_bw_stats = ref false
-
- let start_download file =
-- if !!pause_new_downloads then file_pause file;
-+ if !!pause_new_downloads then file_pause file admin_user;
- if !!file_started_cmd <> "" then
- MlUnix.fork_and_exec !!file_started_cmd
- [|
-@@ -521,7 +520,7 @@
- | Some s ->
- let result = List.assoc (int_of_string arg) user.ui_last_results in
- let files = CommonResult.result_download
-- result [] false in
-+ result [] false user.ui_user in
- List.iter start_download files;
- "download started"
- with
-@@ -940,92 +939,123 @@
- and the ones with lowest priority in FileQueued state, if there
- is a max_concurrent_downloads constraint.
-
--In the future, we could try to mix this with the multi-users
--system to give some fairness between downloads of different
--users.
--
- **************************************************************)
-
- open CommonFile
-
-+type user_file_list = {
-+ file_list : file list;
-+ downloads_allowed : int option;
-+}
-+
- let force_download_quotas () =
-- let files = List.sort (fun f1 f2 ->
-- let v = file_priority f2 - file_priority f1 in
-- if v <> 0 then v else
-- (**
-- * [egs] do not start downloading
-- * a small file against an already active download
-- **)
-- let d1 = file_downloaded f1 in
-- let d2 = file_downloaded f2 in
-- if d1 = 0L && d2 > 0L then 1
-- else
-- if d1 > 0L && d2 = 0L then -1
-- else
-- (* Try to download in priority files with fewer bytes missing
-- Rationale: once completed, it may allow to recover some disk space *)
-- let r1 = file_size f1 -- d1 in
-- let r2 = file_size f2 -- d2 in
-- if r1 = r2 then 0 else
-- if r2 < r1 then 1 else -1
-- ) !!CommonComplexOptions.files in
--
-- (** move running and queued downloads from [list] to [files]
-- accumulator, until a drop of priority (or end of list) is
-- encountered; Then submit the batches of downloads with same
-- priority to [iter_line].
--
-- @param ndownloads number of running downloads no longer in [list]
-- @param nqueued number of queued downloads in [files]
-- *)
-- let rec iter list priority files ndownloads nqueued =
-- match list, files with
-- | [], [] -> ()
-- | [], _ ->
-- iter_line list priority files ndownloads nqueued
-- | f :: tail , _ :: _ when file_priority f < priority ->
-- iter_line list priority files ndownloads nqueued
-- | f :: tail, files ->
-- match file_state f with
-- | FileDownloading ->
-- iter tail (file_priority f) (f :: files) (ndownloads+1) nqueued
-- | FileQueued ->
-- iter tail (file_priority f) (f :: files) ndownloads (nqueued+1)
-- | _ ->
-- iter tail (file_priority f) files ndownloads nqueued
--
-- (** queue or unqueue downloads from [files] list to match quotas *)
-- and iter_line list priority files ndownloads nqueued =
-- if ndownloads > !!max_concurrent_downloads then
-- match files with
-- | [] -> assert false
-- | f :: tail ->
-- match file_state f with
-- | FileDownloading ->
-- set_file_state f FileQueued;
-- iter_line list priority tail (ndownloads-1) nqueued
-- | _ -> iter_line list priority tail ndownloads (nqueued-1)
-- else
-- if ndownloads < !!max_concurrent_downloads && nqueued > 0 then
-- match files with
-- | [] -> assert false
-- | f :: tail ->
-- match file_state f with
-- | FileQueued ->
-- set_file_state f FileDownloading;
-- iter_line list priority tail (ndownloads+1) (nqueued-1)
-- | _ -> iter_line list priority tail ndownloads nqueued
-- else
-- iter list priority [] ndownloads 0
-
-- in
-- if not !all_temp_queued then
-- iter files max_int [] 0 0
-+ let queue_files files =
-+ List.iter (fun file ->
-+ if file_state file = FileDownloading then
-+ set_file_state file FileQueued
-+ ) files in
-+
-+ let queue_user_file_list (_user, user_file_list) =
-+ queue_files user_file_list.file_list in
-+
-+ if !all_temp_queued then
-+ queue_files !!CommonComplexOptions.files
- else
-- List.iter (fun f ->
-- if file_state f = FileDownloading then
-- set_file_state f FileQueued
-- ) files
-+
-+ (* create the assoc list of downloads of each user *)
-+ let files_by_user = List.fold_left (fun acc f ->
-+ let owner = CommonFile.file_owner f in
-+ try
-+ let owner_file_list = List.assoc owner acc in
-+ (owner, { owner_file_list with
-+ file_list = f :: owner_file_list.file_list }) ::
-+ List.remove_assoc owner acc
-+ with Not_found ->
-+ (owner, {
-+ downloads_allowed =
-+ (match owner.user_max_concurrent_downloads with
-+ | 0 -> None
-+ | i -> Some i);
-+ file_list = [f] }) :: acc
-+ ) [] !!CommonComplexOptions.files in
-+
-+ (* sort each user's list separately *)
-+ let files_by_user = List.map (fun (owner, owner_file_list) ->
-+ owner, { owner_file_list with
-+ file_list = List.sort (fun f1 f2 ->
-+ let v = compare (file_priority f2) (file_priority f1) in
-+ if v <> 0 then v else
-+ (* [egs] do not start downloading a small file
-+ against an already active download *)
-+ let d1 = file_downloaded f1 in
-+ let d2 = file_downloaded f2 in
-+ let active1 = d1 > 0L in
-+ let active2 = d2 > 0L in
-+ if not active1 && active2 then 1
-+ else if active1 && not active2 then -1
-+ else
-+ (* Try to download in priority files with fewer bytes missing
-+ Rationale: once completed, it may allow to recover some disk space *)
-+ let remaining1 = file_size f1 -- d1 in
-+ let remaining2 = file_size f2 -- d2 in
-+ compare remaining1 remaining2
-+ ) owner_file_list.file_list }
-+ ) files_by_user in
-+
-+ (* sort the assoc list itself with user with highest quota first *)
-+ let files_by_user =
-+ List.sort (fun (_owner1, { downloads_allowed = allowed1 })
-+ (_owner2, { downloads_allowed = allowed2 }) ->
-+ match allowed1, allowed2 with
-+ | None, None -> 0
-+ | None, _ -> -1
-+ | _, None -> 1
-+ | Some allowed1, Some allowed2 -> compare allowed2 allowed1
-+ ) files_by_user in
-+
-+ (* serve users round-robin, starting with the one with highest quota *)
-+ let rec iter downloads_left to_serve served =
-+ if downloads_left = 0 then begin
-+ List.iter queue_user_file_list to_serve;
-+ List.iter queue_user_file_list served
-+ end else
-+ match to_serve with
-+ | [] ->
-+ if served = [] then () (* nothing left to rotate *)
-+ else (* new round *)
-+ iter downloads_left served []
-+ | (_owner, { file_list = [] }) :: others ->
-+ (* user satisfied, remove from lists *)
-+ iter downloads_left others served
-+ | ((_owner, { downloads_allowed = Some 0 }) as first) :: others ->
-+ (* reached quota, remove from future rounds *)
-+ queue_user_file_list first;
-+ iter downloads_left others served
-+ | (owner, { file_list = first_file :: other_files;
-+ downloads_allowed = allowed }) :: others ->
-+ let is_downloading =
-+ match file_state first_file with
-+ | FileDownloading -> true
-+ | FileQueued ->
-+ set_file_state first_file FileDownloading;
-+ true
-+ | _ -> false in
-+ if is_downloading then
-+ iter (downloads_left - 1) others
-+ ((owner, {
-+ file_list = other_files;
-+ downloads_allowed = match allowed with
-+ | None -> None
-+ | Some i -> Some (i - 1)
-+ }) :: served)
-+ else
-+ iter downloads_left others
-+ ((owner, {
-+ file_list = other_files;
-+ downloads_allowed = allowed
-+ }) :: served) in
-+ iter !!max_concurrent_downloads files_by_user []
-
- let _ =
- option_hook max_concurrent_downloads (fun _ ->
-Index: src/daemon/common/commonMessages.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonMessages.ml,v
-retrieving revision 1.55
-retrieving revision 1.60
-diff -u -r1.55 -r1.60
---- src/daemon/common/commonMessages.ml 26 Aug 2006 12:05:53 -0000 1.55
-+++ src/daemon/common/commonMessages.ml 5 Nov 2006 14:11:29 -0000 1.60
-@@ -47,103 +47,354 @@
- string_option
- "
- body {
--background: @color_background@; margin-top: 3px; margin-left: 5px; margin-right: 5px;
--font-family: Verdana, sans-serif; font-size: 12px;
--scrollbar-face-color: @color_scrollbar_face@; scrollbar-shadow-color: @color_scrollbar_face@;
--scrollbar-highlight-color: @color_scrollbar_highlight@; scrollbar-3dlight-color: @color_some_scrollbar@;
--scrollbar-darkshadow-color: @color_some_scrollbar@; scrollbar-track-color: @color_background@;
--scrollbar-arrow-color: @color_some_scrollbar@; }
--table.commands { border: @color_general_border@ solid 1px; background: @color_background@ }
--table.topcommands { background: @color_background@; border: @color_general_border@ solid 1px; border-top: @color_scrollbar_highlight@ solid 1px; border-left: @color_scrollbar_highlight@ solid 1px; }
--pre { color: @color_general_text@; font-family: Courier, Arial, Helvetica, sans-serif; font-size: 12px; }
--p { color: @color_general_text@; font-family: Verdana, Courier, Arial, Helvetica, sans-serif; font-size: 12px; }
--input.txt { background: @color_input_text@ }
--input.txt2 { background: @color_bbig_background@;
--font: 12px courier; padding: 0px;
--width: 38px; height: 18px; line-height: 14px; color: @color_general_text@;
--border-right: @color_some_border@ 2px solid; border-top: @color_general_border@ 1px solid; border-left: @color_general_border@ 1px solid; border-bottom: @color_some_border@ 2px solid; }
--input.but2 { background: @color_bsmall3@;
--border: 0px; padding: 0px; font: bold 10px verdana;
--width: 36px; height: 14px; }
--input.but { background: @color_input_button@ };
--
--a:link,a:active,a:visited { text-decoration: none; font-face: verdana;
--font-size: 10px; color: @color_anchor@; }
--a:hover { color: @color_anchor_hover@; text-decoration: underline;}
-+ background: @color_background@;
-+ margin-top: 3px;
-+ margin-left: 5px;
-+ margin-right: 5px;
-+ font-family: Verdana, sans-serif;
-+ font-size: 12px;
-+ }
-+table.commands {
-+ border: @color_general_border@ solid 1px;
-+ background: @color_background@;
-+ }
-+table.topcommands {
-+ background: @color_background@;
-+ border: @color_general_border@ solid 1px;
-+ border-top: @color_scrollbar_highlight@ solid 1px;
-+ border-left: @color_scrollbar_highlight@ solid 1px;
-+ }
-+pre {
-+ color: @color_general_text@;
-+ font-family: Courier, Arial, Helvetica, sans-serif;
-+ font-size: 12px;
-+ }
-+p {
-+ color: @color_general_text@;
-+ font-family: Verdana, Courier, Arial, Helvetica, sans-serif;
-+ font-size: 12px;
-+ }
-+input.txt {
-+ background: @color_input_text@;
-+ }
-+input.txt2 {
-+ background: @color_bbig_background@;
-+ font: 12px courier;
-+ padding: 0px;
-+ width: 38px;
-+ height: 18px;
-+ line-height: 14px;
-+ color: @color_general_text@;
-+ border-right: @color_some_border@ 2px solid;
-+ border-top: @color_general_border@ 1px solid;
-+ border-left: @color_general_border@ 1px solid;
-+ border-bottom: @color_some_border@ 2px solid;
-+ }
-+input.but2 {
-+ background: @color_bsmall3@;
-+ border: 0px;
-+ padding: 0px;
-+ font: bold 10px verdana;
-+ width: 36px;
-+ height: 14px;
-+ }
-+input.but {
-+ background: @color_input_button@;
-+ }
-+a:link, a:active, a:visited {
-+ text-decoration: none;
-+ font-family: verdana;
-+ font-size: 10px;
-+ color: @color_anchor@;
-+ }
-+a:hover {
-+ color: @color_anchor_hover@;
-+ text-decoration: underline;
-+ }
- .bu {
--vertical-align: middle; white-space: nowrap;
--background: @color_chunk3@; color: @color_foreground_text_for_top_buttons@;
--font-family: Verdana; font-size: 9px; line-height: 12px;
--margin-top: 0px; margin-bottom: 0px;
--padding-left: 6px; padding-right: 6px; padding-top: 1px; padding-bottom: 1px;
--border: @color_some_border@ 0px solid; }
-+ vertical-align: middle;
-+ white-space: nowrap;
-+ background: @color_chunk3@;
-+ color: @color_foreground_text_for_top_buttons@;
-+ font-family: Verdana;
-+ font-size: 9px;
-+ line-height: 12px;
-+ margin-top: 0px;
-+ margin-bottom: 0px;
-+ padding-left: 6px;
-+ padding-right: 6px;
-+ padding-top: 1px;
-+ padding-bottom: 1px;
-+ border: @color_some_border@ 0px solid;
-+ }
- .bbig {
--text-align: center; font-size: 10px; font-family: Verdana; font-weight: 500;
--border-top: @color_scrollbar_highlight@ 1px solid; border-left: @color_scrollbar_highlight@ 1px solid; border-bottom: @color_general_border@ 1px solid; border-right: @color_general_border@ 1px solid;
--padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px;
--color: @color_general_text@; background: @color_bbig_background@; }
-+ text-align: center;
-+ font-size: 10px;
-+ font-family: Verdana;
-+ font-weight: 500;
-+ border-top: @color_scrollbar_highlight@ 1px solid;
-+ border-left: @color_scrollbar_highlight@ 1px solid;
-+ border-bottom: @color_general_border@ 1px solid;
-+ border-right: @color_general_border@ 1px solid;
-+ padding-left: 4px;
-+ padding-right: 4px;
-+ padding-top: 1px;
-+ padding-bottom: 1px;
-+ color: @color_general_text@;
-+ background: @color_bbig_background@;
-+ }
- .bbigm {
--text-align: center; font: bold 10px verdana;
--border-top: @color_scrollbar_highlight@ 1px solid; border-left: @color_scrollbar_highlight@ 1px solid; border-bottom: @color_general_border@ 1px solid; border-right: @color_general_border@ 1px solid;
--padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px;
--color: @color_general_text@; background: @color_bsmall3@; }
--.bsmall { background: @color_bsmall_back@; }
--.bsmall1 { background: @color_bbig_background@; }
--.bsmall2 { background: @color_bsmall2@; }
--.bsmall3 { background: @color_bsmall3@; }
--.bbig2 { background: @color_bsmall3@; }
--.bbig3 { background: @color_scrollbar_face@; }
--.b1 { border-left: @color_border_of_top_buttons@ solid 1px; border-top: @color_border_of_top_buttons@ solid 1px; border-right: @color_border_of_top_buttons@ solid 1px; border-bottom: @color_border_of_top_buttons@ solid 1px; }
--.b2 { border-left: @color_border_of_top_buttons@ solid 0px; border-top: @color_border_of_top_buttons@ solid 1px; border-right: @color_border_of_top_buttons@ solid 1px; border-bottom: @color_border_of_top_buttons@ solid 1px; }
--.b3 { border-left: @color_border_of_top_buttons@ solid 1px; border-top: @color_border_of_top_buttons@ solid 0px; border-right: @color_border_of_top_buttons@ solid 1px; border-bottom: @color_border_of_top_buttons@ solid 1px; }
--.b4 { border-left: @color_border_of_top_buttons@ solid 0px; border-top: @color_border_of_top_buttons@ solid 0px; border-right: @color_border_of_top_buttons@ solid 1px; border-bottom: @color_border_of_top_buttons@ solid 1px; }
--.bb1 { border-left: @color_general_border@ solid 1px; border-top: @color_scrollbar_highlight@ solid 1px; border-right: @color_scrollbar_highlight@ solid 1px; border-bottom: @color_general_border@ solid 1px; }
--.bb2 { border-left: @color_big_buttons_and_border_highlight@ solid 1px; border-top: @color_scrollbar_highlight@ solid 1px; border-right: @color_scrollbar_highlight@ solid 0px; border-bottom: @color_general_border@ solid 1px; }
--.bb3 { border-left: @color_big_buttons_and_border_highlight@ solid 1px; border-top: @color_scrollbar_highlight@ solid 1px; border-right: @color_general_border@ solid 0px; border-bottom: @color_general_border@ solid 0px; }
--.bb4 { border-left: @color_big_buttons_and_border_highlight@ solid 1px; border-top: @color_scrollbar_highlight@ solid 1px; border-right: @color_general_border@ solid 1px; border-bottom: @color_general_border@ solid 0px; }
--.src { border-left: @color_general_border@ solid 0px; border-top: @color_general_border@ solid 0px; border-right: @color_general_border@ solid 1px; border-bottom: @color_general_border@ solid 1px; }
--.srctd { font-family: Verdana; font-size: 8px; }
--td.fbig { color: @color_general_text@; cursor: pointer; padding-left: 2px; padding-right: 2px; font-family: Verdana; font-size: 10px; background: @color_fbig_background@;
--border-top: @color_general_border@ solid 1px; border-left: @color_general_border@ solid 1px; }
--td.pr { border-right: @color_general_border@ solid 1px; }
--td.fbigb { border-top: @color_general_border@ solid 0px; border-bottom: @color_general_border@ solid 1px; }
--td.fbigpad { padding-top: 2px; padding-bottom: 2px; }
--td, tr {font-size: 12px; font-face: verdana; }
--td.sr { white-space: nowrap; padding-top: 2px; padding-bottom: 2px; padding-left: 4px; padding-right: 4px; font-family: verdana; font-size: 10px; color: @color_general_text@; }
--td.srp { white-space: nowrap; padding-top: 2px; padding-bottom: 2px; padding-left: 0px; padding-right: 4px; font-family: verdana; font-size: 10px; color: @color_one_td_text@; }
--td.srw { padding-top: 2px; padding-bottom: 2px; padding-left: 4px; padding-right: 4px; font-family: verdana; font-size: 10px; color: @color_general_text@; }
--td.srh { cursor: pointer; vertical-align: top; background: @color_table_header_background@; white-space: nowrap; padding-top: 2px; padding-bottom: 2px; padding-left: 4px; padding-right: 4px;
--font-family: verdana; font-size: 10px; color: @color_general_text@; }
--td.total { border-top: @color_general_border@ solid 1px; border-bottom: @color_general_border@ solid 1px; }
--tr.dl-1, td.dl-1 { background: @color_dl1_back@; }
--tr.dl-2, td.dl-2 { background: @color_dl2_back@; }
--.mOvr1, tr.mOvr1 {background: @color_mOver1_back@; cursor: pointer; }
--.mOvr2, tr.mOvr2 {background: @color_mOver2_back@; cursor: pointer; }
--.mOvr3, tr.mOvr3 {background: @color_mOver3_back@; cursor: pointer; }
-+ text-align: center;
-+ font: bold 10px verdana;
-+ border-top: @color_scrollbar_highlight@ 1px solid;
-+ border-left: @color_scrollbar_highlight@ 1px solid;
-+ border-bottom: @color_general_border@ 1px solid;
-+ border-right: @color_general_border@ 1px solid;
-+ padding-left: 4px;
-+ padding-right: 4px;
-+ padding-top: 1px;
-+ padding-bottom: 1px;
-+ color: @color_general_text@;
-+ background: @color_bsmall3@;
-+ }
-+.bsmall {
-+ background: @color_bsmall_back@;
-+ }
-+.bsmall1 {
-+ background: @color_bbig_background@;
-+ }
-+.bsmall2 {
-+ background: @color_bsmall2@;
-+ }
-+.bsmall3 {
-+ background: @color_bsmall3@;
-+ }
-+.bbig2 {
-+ background: @color_bsmall3@;
-+ }
-+.bbig3 {
-+ background: @color_scrollbar_face@;
-+ }
-+.b1 {
-+ border-left: @color_border_of_top_buttons@ solid 1px;
-+ border-top: @color_border_of_top_buttons@ solid 1px;
-+ border-right: @color_border_of_top_buttons@ solid 1px;
-+ border-bottom: @color_border_of_top_buttons@ solid 1px;
-+ }
-+.b2 {
-+ border-left: @color_border_of_top_buttons@ solid 0px;
-+ border-top: @color_border_of_top_buttons@ solid 1px;
-+ border-right: @color_border_of_top_buttons@ solid 1px;
-+ border-bottom: @color_border_of_top_buttons@ solid 1px;
-+ }
-+.b3 {
-+ border-left: @color_border_of_top_buttons@ solid 1px;
-+ border-top: @color_border_of_top_buttons@ solid 0px;
-+ border-right: @color_border_of_top_buttons@ solid 1px;
-+ border-bottom: @color_border_of_top_buttons@ solid 1px;
-+ }
-+.b4 {
-+ border-left: @color_border_of_top_buttons@ solid 0px;
-+ border-top: @color_border_of_top_buttons@ solid 0px;
-+ border-right: @color_border_of_top_buttons@ solid 1px;
-+ border-bottom: @color_border_of_top_buttons@ solid 1px;
-+ }
-+.bb1 {
-+ border-left: @color_general_border@ solid 1px;
-+ border-top: @color_scrollbar_highlight@ solid 1px;
-+ border-right: @color_scrollbar_highlight@ solid 1px;
-+ border-bottom: @color_general_border@ solid 1px;
-+ }
-+.bb2 {
-+ border-left: @color_big_buttons_and_border_highlight@ solid 1px;
-+ border-top: @color_scrollbar_highlight@ solid 1px;
-+ border-right: @color_scrollbar_highlight@ solid 0px;
-+ border-bottom: @color_general_border@ solid 1px;
-+ }
-+.bb3 {
-+ border-left: @color_big_buttons_and_border_highlight@ solid 1px;
-+ border-top: @color_scrollbar_highlight@ solid 1px;
-+ border-right: @color_general_border@ solid 0px;
-+ border-bottom: @color_general_border@ solid 0px;
-+ }
-+.bb4 {
-+ border-left: @color_big_buttons_and_border_highlight@ solid 1px;
-+ border-top: @color_scrollbar_highlight@ solid 1px;
-+ border-right: @color_general_border@ solid 1px;
-+ border-bottom: @color_general_border@ solid 0px;
-+ }
-+.src {
-+ border-left: @color_general_border@ solid 0px;
-+ border-top: @color_general_border@ solid 0px;
-+ border-right: @color_general_border@ solid 1px;
-+ border-bottom: @color_general_border@ solid 1px;
-+ }
-+.srctd {
-+ font-family: Verdana;
-+ font-size: 8px;
-+ }
-+td.fbig {
-+ color: @color_general_text@;
-+ cursor: pointer;
-+ padding-left: 2px;
-+ padding-right: 2px;
-+ font-family: Verdana;
-+ font-size: 10px;
-+ background: @color_fbig_background@;
-+ border-top: @color_general_border@ solid 1px;
-+ border-left: @color_general_border@ solid 1px;
-+ }
-+td.pr {
-+ border-right: @color_general_border@ solid 1px;
-+ }
-+td.fbigb {
-+ border-top: @color_general_border@ solid 0px;
-+ border-bottom: @color_general_border@ solid 1px;
-+ }
-+td.fbigpad {
-+ padding-top: 2px;
-+ padding-bottom: 2px;
-+ }
-+td, tr {
-+ font-size: 12px;
-+ font-family: verdana;
-+ }
-+td.sr {
-+ white-space: nowrap;
-+ padding-top: 2px;
-+ padding-bottom: 2px;
-+ padding-left: 4px;
-+ padding-right: 4px;
-+ font-family: verdana;
-+ font-size: 10px;
-+ color: @color_general_text@;
-+ }
-+td.srp {
-+ white-space: nowrap;
-+ padding-top: 2px;
-+ padding-bottom: 2px;
-+ padding-left: 0px;
-+ padding-right: 4px;
-+ font-family: verdana;
-+ font-size: 10px;
-+ color: @color_one_td_text@;
-+ }
-+td.srw {
-+ padding-top: 2px;
-+ padding-bottom: 2px;
-+ padding-left: 4px;
-+ padding-right: 4px;
-+ font-family: verdana;
-+ font-size: 10px;
-+ color: @color_general_text@;
-+ }
-+td.srh {
-+ cursor: pointer;
-+ vertical-align: top;
-+ background: @color_table_header_background@;
-+ white-space: nowrap;
-+ padding-top: 2px;
-+ padding-bottom: 2px;
-+ padding-left: 4px;
-+ padding-right: 4px;
-+ font-family: verdana;
-+ font-size: 10px;
-+ color: @color_general_text@;
-+ }
-+td.total {
-+ border-top: @color_general_border@ solid 1px;
-+ border-bottom: @color_general_border@ solid 1px;
-+ }
-+tr.dl-1, td.dl-1 {
-+ background: @color_dl1_back@;
-+ }
-+tr.dl-2, td.dl-2 {
-+ background: @color_dl2_back@;
-+ }
-+.mOvr1, tr.mOvr1 {
-+ background: @color_mOver1_back@;
-+ cursor: pointer;
-+ }
-+.mOvr2, tr.mOvr2 {
-+ background: @color_mOver2_back@;
-+ cursor: pointer;
-+ }
-+.mOvr3, tr.mOvr3 {
-+ background: @color_mOver3_back@;
-+ cursor: pointer;
-+ }
- table.uploaders, table.friends, table.bw_stats, table.vo, table.cs, table.servers,
- table.shares, table.downloaders, table.scan_temp, table.upstats, table.messages,
- table.shares, table.vc, table.results, table.networkInfo, table.memstats {
-- margin-right: auto;
-- margin-left: auto;
-- border: 1;
-- border: @color_general_border@ solid 1px;
-- border-collapse: collapse; }
--table.sourcesInfo, table.serversC { width: 100%; margin-right: auto; margin-left: auto; border: 1; border: @color_general_border@ solid 1px; border-collapse: collapse; }
--table.sources {border: 1; border: @color_general_border@ solid 1px; border-collapse: collapse; }
--table.main { margin-right: auto; margin-left: auto; }
-+ margin-right: auto;
-+ margin-left: auto;
-+ border: @color_general_border@ solid 1px;
-+ border-collapse: collapse;
-+ }
-+table.sourcesInfo, table.serversC {
-+ width: 100%;
-+ margin-right: auto;
-+ margin-left: auto;
-+ border: @color_general_border@ solid 1px;
-+ border-collapse: collapse;
-+ }
-+table.sources {
-+ border: @color_general_border@ solid 1px;
-+ border-collapse: collapse;
-+ }
-+table.main {
-+ margin-right: auto;
-+ margin-left: auto;
-+ }
- div.main, div.uploaders, div.friends, div.cs, div.shares, div.upstats, div.servers, div.serversC, div.vo,
--div.downloaders, div.messages, div.vc, div.bw_stats, div.scan_temp, div.results, div.memstats { text-align: center; }
--td.srb { padding-top: 1px; padding-bottom: 1px; font-size: 10px; font-family: Verdana; white-space: nowrap; border-right: @color_general_border@ solid 1px; border-bottom: @color_general_border@ solid 1px;
--border-left: @color_general_border@ solid 1px; border-top: @color_general_border@ solid 0px; padding-left: 3px; padding-right: 3px; }
--td.act { font-size: 10px; font-weight: 700; }
--td.br {border-right: @color_general_border@ dotted 1px;}
--td.ar {text-align: right;}
--td.al {text-align: left;}
--td.ac {text-align: center;}
--td.chunk0 { height:12px; background: @color_chunk0@}
--td.chunk1 { height:12px; background: @color_chunk1@}
--td.chunk2 { height:12px; background: @color_chunk2@}
--td.chunk3 { height:12px; background: @color_chunk3@}
-+div.downloaders, div.messages, div.vc, div.bw_stats, div.scan_temp, div.results, div.memstats {
-+ text-align: center;
-+ }
-+td.srb {
-+ padding-top: 1px;
-+ padding-bottom: 1px;
-+ font-size: 10px;
-+ font-family: Verdana;
-+ white-space: nowrap;
-+ border-right: @color_general_border@ solid 1px;
-+ border-bottom: @color_general_border@ solid 1px;
-+ border-left: @color_general_border@ solid 1px;
-+ border-top: @color_general_border@ solid 0px;
-+ padding-left: 3px;
-+ padding-right: 3px;
-+ }
-+td.act {
-+ font-size: 10px;
-+ font-weight: 700;
-+ }
-+td.br {
-+ border-right: @color_general_border@ dotted 1px;
-+ }
-+td.ar {
-+ text-align: right;
-+ }
-+td.al {
-+ text-align: left;
-+ }
-+td.ac {
-+ text-align: center;
-+ }
-+td.chunk0 {
-+ height: 12px;
-+ background: @color_chunk0@;
-+ }
-+td.chunk1 {
-+ height: 12px;
-+ background: @color_chunk1@;
-+ }
-+td.chunk2 {
-+ height: 12px;
-+ background: @color_chunk2@;
-+ }
-+td.chunk3 {
-+ height: 12px;
-+ background: @color_chunk3@;
-+ }
- "
-
- let html_js_mods0 = define_option message_section ["html_js_mods0"]
-@@ -161,23 +412,28 @@
- src.className=mOvrClass;
- }
- function mSub(target,cmd) {
-- if (target != \"\") {
-- if (cmd==\"kill\") {
-- if (confirm(\"Are you sure?\")) {
-- top[target].location.href=\"submit?q=\" + cmd;
-- }
-- } else {
-- if (cmd.substring(0,6)==\"custom\") {top[target].location.href=\"submit?\" + cmd;}
-- else {top[target].location.href=\"submit?q=\" + cmd;
-- }
-+if (target != '') {
-+ if (cmd=='kill') {
-+ if (confirm('Are you sure?')) {
-+ parent.document.getElementsByName(target).item(0).src='submit?q=' + cmd;
-+ }
-+ }
-+ else {
-+ if (cmd.substring(0,6)=='custom') {
-+ parent.document.getElementsByName(target).item(0).src='submit?' + cmd;
-+ }
-+ else {
-+ parent.document.getElementsByName(target).item(0).src='submit?q=' + cmd;
-+ }
- }
-- } else {
-- location.href=\"submit?q=\" + cmd;
-- }
-+}
-+else {
-+ parent.document.getElementsByName(target).item(0).src='submit?q=' + cmd;
-+}
- }
- function showTab(t){
-- for (i=1; i<=6; i++) document.getElementById(\"tab\" + i).style.display = \"none\";
-- document.getElementById(\"tab\" + t).style.display = \"block\";
-+ for (i=1; i<=6; i++) document.getElementById('tab' + i).style.display = 'none';
-+ document.getElementById(\"tab\" + t).style.display = 'block';
- }
- var _tabLast=null;
- function _rObj (s,ar) {
-@@ -415,41 +671,168 @@
- "Download CSS - style 0"
- string_option
- "
--body{ background-color:@color_vd_page_background@;color: @color_general_text@; font-family: Verdana, Arial, Helvetica, sans-serif;font-size: 13px; margin-top: 10px; margin: 2;}
--td,pre { color: @color_general_text@; font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; }
--table.downloaders { margin-right: auto; margin-left: auto; border: 1; border: @color_general_border@ solid 1px; }
--div.main { text-align: center; }
--table.main { margin-right: auto; margin-left: auto; }
--td.loaded{ padding-top: 0px; padding-bottom: 0px; background-color:@color_vd_downloaded@; font-size:1px; line-height: 2px; }
--td.remain{ padding-top: 0px; padding-bottom: 0px; background-color:@color_vd_remaining@; font-size:1px; line-height: 2px; }
--td.downloaded{ font-family: Verdana; font-weight: 500; font-size: 12px; color: @color_general_text@; }
--td.dl { white-space: nowrap; padding-top: 2px; padding-bottom: 2px; padding-left: 5px; padding-right: 5px; font-family: verdana; font-size: 10px; color: @color_general_text@; }
--td.dlheader { cursor: pointer; color: @color_general_text@; font-family: Verdana, serif; font-size: 10px;
--border-bottom: solid 1px; background: @color_table_header_background@; padding-left: 3px;
--padding-right: 3px; }
--input.checkbox { background: @color_table_header_background@; vertical-align: middle; height: 10px; width: 10px; }
--td.sr { white-space: nowrap; padding-top: 2px; padding-bottom: 2px; padding-left: 5px; padding-right: 5px; font-family: verdana; font-size: 10px; color: @color_general_text@; }
--table { cellspacing: 0; cellpadding: 0; }
--td.ar { text-align: right; }
--td.al { text-align: left; }
--td.ac { text-align: center; }
--td.brs { border-right: @color_general_border@ solid 1px; padding-left: 2px; padding-right: 2px; text-align: center; }
--td.np { padding-left: 2px; padding-right: 0px; text-align: center; }
--td.big { border-top: @color_general_border@ solid 1px; border-left: @color_general_border@ solid 1px; }
--td.pr { border-right: @color_general_border@ solid 1px; }
--.bigbutton { color: @color_general_text@; font-family: Verdana, serif; font-size: 10px; background: @color_background@; border: @color_background@ solid 1px; cursor: pointer; }
-+body {
-+ background-color: @color_vd_page_background@;
-+ color: @color_general_text@;
-+ font-family: Verdana, Arial, Helvetica, sans-serif;
-+ font-size: 13px;
-+ margin-top: 10px;
-+ margin: 2;
-+ }
-+td, pre {
-+ color: @color_general_text@;
-+ font-family: Verdana, Arial, Helvetica, sans-serif;
-+ font-size: 10px;
-+ }
-+table.downloaders {
-+ margin-right: auto;
-+ margin-left: auto;
-+ border: @color_general_border@ solid 1px;
-+ }
-+div.main {
-+ text-align: center;
-+ }
-+table.main {
-+ margin-right: auto;
-+ margin-left: auto;
-+ }
-+td.loaded {
-+ padding-top: 0px;
-+ padding-bottom: 0px;
-+ background-color: @color_vd_downloaded@;
-+ font-size: 1px;
-+ line-height: 2px;
-+ }
-+td.remain {
-+ padding-top: 0px;
-+ padding-bottom: 0px;
-+ background-color: @color_vd_remaining@;
-+ font-size: 1px;
-+ line-height: 2px;
-+ }
-+td.downloaded {
-+ font-family: Verdana;
-+ font-weight: 500;
-+ font-size: 12px;
-+ color: @color_general_text@;
-+ }
-+td.dl {
-+ white-space: nowrap;
-+ padding-top: 2px;
-+ padding-bottom: 2px;
-+ padding-left: 5px;
-+ padding-right: 5px;
-+ font-family: verdana;
-+ font-size: 10px;
-+ color: @color_general_text@;
-+ }
-+td.dlheader {
-+ cursor: pointer;
-+ color: @color_general_text@;
-+ font-family: Verdana, serif;
-+ font-size: 10px;
-+ border-bottom: solid 1px;
-+ background: @color_table_header_background@;
-+ padding-left: 3px;
-+ padding-right: 3px;
-+ }
-+input.checkbox {
-+ background: @color_table_header_background@;
-+ vertical-align: middle;
-+ height: 10px;
-+ width: 10px;
-+ }
-+td.sr {
-+ white-space: nowrap;
-+ padding-top: 2px;
-+ padding-bottom: 2px;
-+ padding-left: 5px;
-+ padding-right: 5px;
-+ font-family: verdana;
-+ font-size: 10px;
-+ color: @color_general_text@;
-+ }
-+table {
-+ border-spacing: 0px;
-+ }
-+td {
-+ padding: 0px;
-+ }
-+td.ar {
-+ text-align: right;
-+ }
-+td.al {
-+ text-align: left;
-+ }
-+td.ac {
-+ text-align: center;
-+ }
-+td.brs {
-+ border-right: @color_general_border@ solid 1px;
-+ padding-left: 2px;
-+ padding-right: 2px;
-+ text-align: center;
-+ }
-+td.np {
-+ padding-left: 2px;
-+ padding-right: 0px;
-+ text-align: center;
-+ }
-+td.big {
-+ border-top: @color_general_border@ solid 1px;
-+ border-left: @color_general_border@ solid 1px;
-+ }
-+td.pr {
-+ border-right: @color_general_border@ solid 1px;
-+ }
-+.bigbutton {
-+ color: @color_general_text@;
-+ font-family: Verdana, serif;
-+ font-size: 10px;
-+ background: @color_background@;
-+ border: @color_background@ solid 1px;
-+ cursor: pointer;
-+ }
- .headbutton {
-- font-family: Verdana, serif; font-size: 10px; border: @color_table_header_background@ solid 1px; background: @color_table_header_background@;
-- padding-left: 5px; padding-right: 5px; cursor: pointer; }
--tr.dl-1 { background: @color_dl1_back@; }
--tr.dl-2 { background: @color_dl2_back@; }
--tr.mOvrDL, .mOvrDL { background: @color_mOver1_back@; cursor: pointer; }
--input { font-family: tahoma; font-size: 10px; }
--a{ text-decoration: none; font-weight: bold;}
--a:link,a:active,a:visited { color: @color_download_anchor@; }
--a:hover { color: @color_download_anchor_hover@; text-decoration: underline; }
--a.extern:visited,a.extern:hover,a.extern:active { color: @color_external_anchor@; }
--.extern:hover { color: @color_external_anchor_hover@; }
-+ font-family: Verdana, serif;
-+ font-size: 10px;
-+ border: @color_table_header_background@ solid 1px;
-+ background: @color_table_header_background@;
-+ padding-left: 5px;
-+ padding-right: 5px;
-+ cursor: pointer;
-+ }
-+tr.dl-1 {
-+ background: @color_dl1_back@;
-+ }
-+tr.dl-2 {
-+ background: @color_dl2_back@;
-+ }
-+tr.mOvrDL, .mOvrDL {
-+ background: @color_mOver1_back@;
-+ cursor: pointer;
-+ }
-+input {
-+ font-family: tahoma;
-+ font-size: 10px;
-+ }
-+a {
-+ text-decoration: none;
-+ font-weight: bold;
-+ }
-+a:link,a:active,a:visited {
-+ color: @color_download_anchor@;
-+ }
-+a:hover {
-+ color: @color_download_anchor_hover@;
-+ text-decoration: underline;
-+ }
-+a.extern:visited,a.extern:hover,a.extern:active {
-+ color: @color_external_anchor@;
-+ }
-+.extern:hover {
-+ color: @color_external_anchor_hover@;
-+ }
- "
-
- let download_html_js_mods0 = define_option message_section ["download_html_js_mods0"]
-@@ -598,6 +981,9 @@
- <TD class=\"bu bbig\" title=\"Bandwidth statistics (set html_mods_bw_refresh_delay)\"
- onMouseOver=\"mOvr(this,'mOvr1');\" onMouseOut=\"mOut(this);\"
- onClick=\"mSub('fstatus','bw_stats');mSub('output','gdstats')\">Bandwidth stats</TD>
-+<TD class=\"bu bbig\" title=\"Bandwidth toggle\"
-+onMouseOver=\"mOvr(this,'mOvr1');\" onMouseOut=\"mOut(this);\"
-+onClick=\"mSub('fstatus','bw_stats');mSub('output','bw_toggle')\">Bandwidth toggle</TD>
- </TR></TBODY></TABLE></DIV>
-
- <DIV ID=\"tab2\" style=\"display: none\">
-@@ -693,6 +1079,9 @@
- <TD class=\"bu bbig\" title=\"Settings\"
- onMouseOver=\"mOvr(this,'mOvr1');\" onMouseOut=\"mOut(this);\"
- onClick=\"mSub('fstatus','version');mSub('output','voo+1')\">Settings</TD>
-+<TD class=\"bu bbig\" title=\"Users\"
-+onMouseOver=\"mOvr(this,'mOvr1');\" onMouseOut=\"mOut(this);\"
-+onclick=\"mSub('fstatus','version');mSub('output','users')\">Users</TD>
- <TD class=\"bu bbig\" title=\"View/edit shared directories\"
- onMouseOver=\"mOvr(this,'mOvr1');\" onMouseOut=\"mOut(this);\"
- onClick=\"mSub('fstatus','version');mSub('output','shares')\">Shares</TD>
-@@ -827,7 +1216,7 @@
- "
- <table width=\"100%\" border=\"0\">
- <tr>
--<td align=\"left\" valign=\"middle\" width=\"*\"><a href=\"http://www.mldonkey.net/\" $O><b>MLDonkey Home</b></a></td>
-+<td align=\"left\" valign=\"middle\" width=\"*\"><a href=\"http://www.mldonkey.org/\" $O><b>MLDonkey Home</b></a></td>
- <form action=\"submit\" $O name=\"cmdFormular\" onSubmit=\"return CheckInput();\">
- <td><input type=\"text\" name=\"q\" size=60 value=\"\"></td>
- <td><input type=\"submit\" value=\"Execute\"></td>
-@@ -861,7 +1250,7 @@
- <td><a href=\"submit?q=commit\" onMouseOver=\"window.status='Move finished downloads to incoming directory';return true;\" onMouseOut=\"window.status='';return true;\" onFocus=\"this.blur();\" $S>Commit</a></td>
- <td><a href=\"submit?q=vr\" onMouseOver=\"window.status='View results to your queries';return true;\" onMouseOut=\"window.status='';return true;\" onFocus=\"this.blur();\" $O>Search results</a></td>
- <td><a href=\"submit?q=ovweb\" onMouseOver=\"window.status='Boot Overnet peers from http list';return true;\" onMouseOut=\"window.status='';return true;\" onFocus=\"this.blur();\" $S>Load Overnet peers</a></td>
--<td><a class=\"extern\" href=\"http://www.mldonkeyworld.com/\" onMouseOver=\"window.status='MLDonkey World';return true;\" onMouseOut=\"window.status='';return true;\" onFocus=\"this.blur();\" $O>English forum</a></td>
-+<td><a class=\"extern\" href=\"http://mldonkey.sf.net/forums/\" onMouseOver=\"window.status='MLDonkey World';return true;\" onMouseOut=\"window.status='';return true;\" onFocus=\"this.blur();\" $O>English forum</a></td>
- <td><a class=\"extern\" href=\"http://www.mldonkey.org/\" onMouseOver=\"window.status='German Forum';return true;\" onMouseOut=\"window.status='';return true;\" onFocus=\"this.blur();\" $O>German forum</a></td>
- <td><a href=\"submit?q=kill\" onMouseOver=\"window.status='Save and quit MLDonkey';return true;\" onMouseOut=\"window.status='';return true;\" onFocus=\"this.blur();\" $O>Kill MLDonkey</a></td>
- </tr>
-@@ -1051,8 +1440,8 @@
- color_vd_remaining = "#000";
- color_general_text = "#000";
- color_general_border = "#000";
-- color_anchor = "#000";
-- color_anchor_hover = "#000";
-+ color_anchor = "#0000ff";
-+ color_anchor_hover = "#0000ff";
- color_download_anchor = "#000";
- color_download_anchor_hover = "#000";
- color_external_anchor = "#000";
-@@ -1094,8 +1483,8 @@
- color_vd_remaining = "#EEE";
- color_general_text = "#000";
- color_general_border = "#000";
-- color_anchor = "#000";
-- color_anchor_hover = "#000";
-+ color_anchor = "#0000ff";
-+ color_anchor_hover = "#0000ff";
- color_download_anchor = "#000";
- color_download_anchor_hover = "#000";
- color_external_anchor = "#000";
-@@ -1134,8 +1523,8 @@
- color_vd_remaining = "#EEE";
- color_general_text = "#000";
- color_general_border = "#000";
-- color_anchor = "#000";
-- color_anchor_hover = "#000";
-+ color_anchor = "#0000ff";
-+ color_anchor_hover = "#0000ff";
- color_download_anchor = "#000";
- color_download_anchor_hover = "#000";
- color_external_anchor = "#000";
-@@ -1174,8 +1563,8 @@
- color_vd_remaining = "#EEE";
- color_general_text = "#000";
- color_general_border = "#000";
-- color_anchor = "#000";
-- color_anchor_hover = "#000";
-+ color_anchor = "#0000ff";
-+ color_anchor_hover = "#0000ff";
- color_download_anchor = "#000";
- color_download_anchor_hover = "#000";
- color_external_anchor = "#000";
-@@ -1214,8 +1603,8 @@
- color_vd_remaining = "#EEE";
- color_general_text = "#000";
- color_general_border = "#000";
-- color_anchor = "#000";
-- color_anchor_hover = "#000";
-+ color_anchor = "#0000ff";
-+ color_anchor_hover = "#0000ff";
- color_download_anchor = "#000";
- color_download_anchor_hover = "#000";
- color_external_anchor = "#000";
-@@ -1254,8 +1643,8 @@
- color_vd_remaining = "#EEE";
- color_general_text = "#000";
- color_general_border = "#000";
-- color_anchor = "#000";
-- color_anchor_hover = "#000";
-+ color_anchor = "#0000ff";
-+ color_anchor_hover = "#0000ff";
- color_download_anchor = "#000";
- color_download_anchor_hover = "#000";
- color_external_anchor = "#000";
-@@ -1294,8 +1683,8 @@
- color_vd_remaining = "#EEE";
- color_general_text = "#000";
- color_general_border = "#000";
-- color_anchor = "#000";
-- color_anchor_hover = "#000";
-+ color_anchor = "#0000ff";
-+ color_anchor_hover = "#0000ff";
- color_download_anchor = "#000";
- color_download_anchor_hover = "#000";
- color_external_anchor = "#000";
-@@ -1334,8 +1723,8 @@
- color_vd_remaining = "#EEE";
- color_general_text = "#D4C9B7";
- color_general_border = "#000";
-- color_anchor = "#000";
-- color_anchor_hover = "#000";
-+ color_anchor = "#0000ff";
-+ color_anchor_hover = "#0000ff";
- color_download_anchor = "#000";
- color_download_anchor_hover = "#000";
- color_external_anchor = "#000";
-@@ -1374,8 +1763,8 @@
- color_vd_remaining = "#EEE";
- color_general_text = "#D4C9B7";
- color_general_border = "#000";
-- color_anchor = "#000";
-- color_anchor_hover = "#000";
-+ color_anchor = "#0000ff";
-+ color_anchor_hover = "#0000ff";
- color_download_anchor = "#000";
- color_download_anchor_hover = "#000";
- color_external_anchor = "#000";
-Index: src/daemon/common/commonNetwork.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonNetwork.ml,v
-retrieving revision 1.29
-retrieving revision 1.32
-diff -u -r1.29 -r1.32
---- src/daemon/common/commonNetwork.ml 5 Sep 2006 14:15:19 -0000 1.29
-+++ src/daemon/common/commonNetwork.ml 1 Oct 2006 17:53:59 -0000 1.32
-@@ -99,6 +99,8 @@
- lprintf_nl "op_network_clean_servers";
- if c.op_network_display_stats == cc.op_network_display_stats then
- lprintf_nl "op_network_display_stats";
-+ if c.op_network_stat_info_list == cc.op_network_stat_info_list then
-+ lprintf_nl "op_network_stat_info_list";
- if c.op_network_info == cc.op_network_info then
- lprintf_nl "op_network_info";
- if c.op_network_clean_exit == cc.op_network_clean_exit then
-@@ -107,6 +109,10 @@
- lprintf_nl "op_network_reset";
- if c.op_network_ports == cc.op_network_ports then
- lprintf_nl "op_network_ports";
-+ if c.op_network_porttest_start == cc.op_network_porttest_start then
-+ lprintf_nl "op_network_porttest_start";
-+ if c.op_network_porttest_result == cc.op_network_porttest_result then
-+ lprintf_nl "op_network_porttest_result";
- ) !networks_ops;
- lprint_newline ()
-
-@@ -127,6 +133,8 @@
- let network_clean_exit n = try n.op_network_clean_exit () with _ -> true
- let network_reset n = try n.op_network_reset () with _ -> ()
- let network_ports n = n.op_network_ports ()
-+let network_porttest_start n = n.op_network_porttest_start ()
-+let network_porttest_result n = n.op_network_porttest_result ()
-
- let networks_iter f =
- List.iter (fun r ->
-@@ -257,7 +265,7 @@
- op_network_update_options = (fun _ -> ni_ok name "update_options");
- op_network_disable = (fun _ -> ni_ok name "disable");
- op_network_server_of_option = (fun _ -> fni name "op_network_server_of_option");
-- op_network_file_of_option = (fun _ _ -> fni name "op_network_file_of_option");
-+ op_network_file_of_option = (fun _ _ _ -> fni name "op_network_file_of_option");
- op_network_client_of_option = (fun _ -> fni name "op_network_client_of_option");
- op_network_recover_temp = (fun _ -> ni_ok name "recover_temp");
- op_network_search = (fun _ _ -> ni_ok name "search");
-@@ -268,16 +276,19 @@
- op_network_close_search = (fun _ -> ni_ok name "close_search");
- op_network_extend_search = (fun _ _ -> ni_ok name "extend search");
- op_network_clean_servers = (fun _ -> ni_ok name "clean servers");
-- op_network_parse_url = (fun _ -> ni_ok name "parse_url"; "", false);
-+ op_network_parse_url = (fun _ _ -> ni_ok name "parse_url"; "", false);
- op_network_info = (fun _ -> fni name "network_info");
- op_network_connected = (fun _ -> ni_ok name "connected"; false);
- op_network_add_server = (fun _ -> fni name "op_network_add_server");
-- op_network_gui_message = (fun _ -> ni_ok name "gui_message");
-- op_network_download = (fun _ -> fni name "network_download");
-+ op_network_gui_message = (fun _ _ -> ni_ok name "gui_message");
-+ op_network_download = (fun _ _ -> fni name "network_download");
- op_network_display_stats = (fun _ _ -> ni_ok name "display_stats");
-+ op_network_stat_info_list = (fun _ -> []);
- op_network_clean_exit = (fun _ -> true);
- op_network_reset = (fun _ -> ni_ok name "reset");
- op_network_ports = (fun _ -> ni_ok name "ports"; []);
-+ op_network_porttest_start = (fun _ -> ni_ok name "porttest_start");
-+ op_network_porttest_result = (fun _ -> fni name "porttest_result");
- }
- in
- let rr = (Obj.magic r: network) in
-Index: src/daemon/common/commonNetwork.mli
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonNetwork.mli,v
-retrieving revision 1.15
-retrieving revision 1.18
-diff -u -r1.15 -r1.18
---- src/daemon/common/commonNetwork.mli 5 Sep 2006 14:15:19 -0000 1.15
-+++ src/daemon/common/commonNetwork.mli 9 Nov 2006 21:32:26 -0000 1.18
-@@ -48,6 +48,8 @@
- val register_commands : (string * string * CommonTypes.arg_kind * string) list -> unit
- val network_connect_servers : CommonTypes.network -> unit
- val network_ports : CommonTypes.network -> (int * string) list
-+val network_porttest_start : CommonTypes.network -> unit
-+val network_porttest_result : CommonTypes.network -> CommonTypes.network_porttest
- val network_forget_search : CommonTypes.network -> CommonTypes.search -> unit
- val network_close_search : CommonTypes.network -> CommonTypes.search -> unit
- val network_private_message : CommonTypes.network -> string -> string -> unit
-@@ -56,6 +58,6 @@
- CommonTypes.search -> CommonTypes.extend_search -> unit
- val network_connected : CommonTypes.network -> bool
- val network_clean_servers : CommonTypes.network -> unit
--val network_parse_url : CommonTypes.network -> string -> string * bool
-+val network_parse_url : CommonTypes.network -> string -> CommonTypes.userdb -> string * bool
- val network_info : CommonTypes.network -> CommonTypes.network_info
- val commands_by_kind : (string, (string * string) list ref) Hashtbl.t
-Index: src/daemon/common/commonOptions.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonOptions.ml,v
-retrieving revision 1.176
-retrieving revision 1.189
-diff -u -r1.176 -r1.189
---- src/daemon/common/commonOptions.ml 16 Sep 2006 15:36:59 -0000 1.176
-+++ src/daemon/common/commonOptions.ml 21 Nov 2006 22:34:33 -0000 1.189
-@@ -145,7 +145,8 @@
- end;
-
- lprintf_nl "MLDonkey is working in %s" file_basedir;
-- if not (Sys.file_exists file_basedir) then begin
-+ if not (Sys.file_exists file_basedir) ||
-+ not (Sys.file_exists (Filename.concat file_basedir "downloads.ini")) then begin
- lprint_newline ();
- lprintf_nl "creating new MLDonkey base directory in %s\n" file_basedir;
- created_new_base_directory := Some file_basedir
-@@ -199,6 +200,11 @@
- exit 2
- end;
-
-+ (* Charset conversion self-test *)
-+ let filename = "abcdefghijklmnopqrstuvwxyz" in
-+ let conv_filename = Charset.to_locale filename in
-+ if filename <> conv_filename then Charset.conversion_enabled := false;
-+
- Unix2.can_write_to_directory (Filename2.temp_directory ());
-
- if (String2.starts_with (Filename.basename Sys.argv.(0)) "mlnet") then begin
-@@ -333,9 +339,7 @@
-
- Options.set_string_wrappers ip_range_list_option
- (fun list ->
-- List.fold_left (fun s ip ->
-- Printf.sprintf "%s %s" (Ip.string_of_range ip) s
-- ) "" list
-+ String.concat " " (List.map Ip.string_of_range (List.rev list))
- )
- (fun s ->
- let list = String2.tokens s in
-@@ -357,6 +361,7 @@
- String2.tokens
-
- let is_not_spam = ref (fun _ -> true)
-+let is_not_comment_spam = ref (fun _ -> true)
-
-
-
-@@ -578,6 +583,14 @@
- < 4 -> download limited to upload * 3"
- int_option 50
-
-+let max_hard_upload_rate_2 = define_option current_section ["max_hard_upload_rate_2"]
-+ "Second maximal upload rate for easy toggling (use bw_toggle)"
-+ int_option 5
-+
-+let max_hard_download_rate_2 = define_option current_section ["max_hard_download_rate_2"]
-+ "Second maximal download rate for easy toggling (use bw_toggle)"
-+ int_option 20
-+
- let max_opened_connections = define_option current_section ["max_opened_connections"]
- "Maximal number of opened connections"
- int_option 200
-@@ -590,6 +603,10 @@
- "How many slots can be used for upload"
- int_option 5
-
-+let max_release_slots = define_option current_section ["max_release_slots"]
-+ "How many percent of upload slots can be used for downloading files tagged as release"
-+ percent_option 20
-+
- let friends_upload_slot = define_option current_section ["friends_upload_slot"]
- "Set aside a single reserved slot to upload to friends"
- bool_option true
-@@ -725,6 +742,14 @@
- "Whether to display the Comments column in vd output"
- bool_option true
-
-+let html_mods_vd_user = define_expert_option current_section ["html_mods_vd_user"]
-+ "Whether to display the User column in vd output"
-+ bool_option false
-+
-+let html_mods_vd_group = define_expert_option current_section ["html_mods_vd_group"]
-+ "Whether to display the Group column in vd output"
-+ bool_option false
-+
- let html_mods_vd_active_sources = define_expert_option current_section ["html_mods_vd_active_sources"]
- "Whether to display the Active Sources column in vd output"
- bool_option true
-@@ -774,13 +799,25 @@
- bool_option true
-
- let html_mods_vd_gfx_x_size = define_expert_option current_section ["html_mods_vd_gfx_x_size"]
-- "Graph x size in vd output ( 320 < x < 3600 )"
-- int_option 630
-+ "Graph x size in vd output ( 365 < x < 3665 )"
-+ int_option 795
-
- let html_mods_vd_gfx_y_size = define_expert_option current_section ["html_mods_vd_gfx_y_size"]
- "Graph y size in vd output ( 200 < y < 1200 )"
- int_option 200
-
-+let html_mods_vd_gfx_h_dynamic = define_expert_option current_section ["html_mods_vd_gfx_h_dymamic"]
-+ "Dynamic grid width, start with 1 h/grid, maximum html_mods_vd_gfx_h_grid_time h/grid"
-+ bool_option true
-+
-+let html_mods_vd_gfx_h_grid_time = define_expert_option current_section ["html_mods_vd_gfx_h_grid_time"]
-+ "Max hours on time scale per grid (0 = no limit)"
-+ int_option 0
-+
-+let html_mods_vd_gfx_subgrid = define_expert_option current_section ["html_mods_vd_gfx_subgrid"]
-+ "Number of shown subgrids on graph (0 = no subgrids)"
-+ int_option 0
-+
- let html_mods_vd_gfx_tag = define_expert_option current_section ["html_mods_vd_gfx_tag"]
- "Draw tag graph"
- bool_option false
-@@ -986,6 +1023,10 @@
- "URLs of RSS feeds"
- (list_option Url.option) []
-
-+let rss_preprocessor = define_expert_option current_section ["rss_preprocessor"]
-+ "If MLDonkey can not read broken RSS feeds, use this program to preprocess them"
-+ string_option "xmllint"
-+
- let ip_blocking_descriptions = define_expert_option current_section ["ip_blocking_descriptions"]
- "Keep IP blocking ranges descriptions in memory"
- bool_option false
-@@ -1288,10 +1329,6 @@
- ones in allowed_commands"
- bool_option false
-
--let enable_user_config = define_option current_section ["enable_user_config"]
-- "Are all users allowed to change MLDonkey options?"
-- bool_option true
--
- let allow_browse_share = define_option current_section ["allow_browse_share"]
- "Allow others to browse our share list (0: none, 1: friends only, 2: everyone"
- allow_browse_share_option 1
-@@ -1300,6 +1337,10 @@
- "Regexp of messages to filter out, example: string1|string2|string3"
- string_option "Your client is connecting too fast"
-
-+let comments_filter = define_option current_section ["comments_filter"]
-+ "Regexp of comments to filter out, example: string1|string2|string3"
-+ string_option "http://|https://|www\\."
-+
-
-
-
-@@ -1417,10 +1458,6 @@
- "The realm shown when connecting with a WEB browser"
- string_option "MLdonkey"
-
--let use_html_frames = define_expert_option current_section ["use_html_frames"]
-- "This option controls whether the WEB interface should use frames or not"
-- bool_option true
--
- let html_frame_border = define_expert_option current_section ["html_frame_border"]
- "This option controls whether the WEB interface should show frame borders or not"
- bool_option true
-@@ -1516,7 +1553,7 @@
-
- let compaction_overhead = define_expert_option current_section ["compaction_overhead"]
- "The percentage of free memory before a compaction is triggered"
-- int_option 25
-+ percent_option 25
-
- let space_overhead = define_expert_option current_section ["space_overhead"]
- "The major GC speed is computed from this parameter. This is the memory
-@@ -1524,7 +1561,7 @@
- unreachable blocks. It is expressed as a percentage of the memory used
- for live data. The GC will work more (use more CPU time and collect
- blocks more eagerly) if space_overhead is smaller."
-- int_option 80
-+ percent_option 80
-
- let max_displayed_results = define_expert_option current_section ["max_displayed_results"]
- "Maximal number of results displayed for a search"
-@@ -1535,6 +1572,13 @@
- int_option 14
-
-
-+let max_comments_per_file = define_expert_option current_section ["max_comments_per_file"]
-+ "Maximum number of comments per file"
-+ int_option 100
-+
-+let max_comment_length = define_expert_option current_section ["max_comment_length"]
-+ "Maximum length of file comments"
-+ int_option 256
-
-
- (*************************************************************************)
-@@ -1748,7 +1792,7 @@
- (!!minor_heap_size * 1024) };
- );
- option_hook client_buffer_size (fun _ ->
-- TcpBufferedSocket.max_buffer_size := maxi 10000000 !!client_buffer_size
-+ TcpBufferedSocket.max_buffer_size := max 10000000 !!client_buffer_size
- );
- if Autoconf.has_gd then
- option_hook html_mods_vd_gfx_png (fun _ ->
-@@ -1908,14 +1952,25 @@
- in aux 0
-
- let _ =
-- option_hook messages_filter (fun _ ->
-- is_not_spam := if !!messages_filter <> "" then
-- let r = Str.regexp_case_fold (quote_unquote_bars !!messages_filter) in
-- (fun s -> try
-+ let regex_fun str =
-+ if str <> "" then
-+ let r = Str.regexp_case_fold (quote_unquote_bars str) in
-+ (fun s ->
-+ try
- ignore (Str.search_forward r s 0);
- false
-- with Not_found -> true)
-- else (fun _ -> true))
-+ with Not_found -> true
-+ )
-+ else (fun _ -> true)
-+ in
-+
-+ option_hook messages_filter (fun _ ->
-+ is_not_spam := regex_fun !!messages_filter
-+ );
-+
-+ option_hook comments_filter (fun _ ->
-+ is_not_comment_spam := regex_fun !!comments_filter
-+ )
-
- let http_proxy = ref None
-
-Index: src/daemon/common/commonResult.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonResult.ml,v
-retrieving revision 1.9
-retrieving revision 1.10
-diff -u -r1.9 -r1.10
---- src/daemon/common/commonResult.ml 17 May 2006 08:52:43 -0000 1.9
-+++ src/daemon/common/commonResult.ml 19 Sep 2006 17:07:42 -0000 1.10
-@@ -142,13 +142,13 @@
- result_source_network = 0;
- }
-
--let result_download rs names force =
-+let result_download rs names force user =
- let r = IndexedResults.get_result rs in
- let files = ref [] in
- CommonNetwork.networks_iter (fun n ->
- (* Temporarily download results only from the network that returned the result *)
- if (n.network_num = r.result_source_network) then
-- files := (n.op_network_download r) :: !files
-+ files := (n.op_network_download r user) :: !files
- );
- !files
-
-Index: src/daemon/common/commonResult.mli
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonResult.mli,v
-retrieving revision 1.5
-retrieving revision 1.7
-diff -u -r1.5 -r1.7
---- src/daemon/common/commonResult.mli 12 May 2006 21:02:38 -0000 1.5
-+++ src/daemon/common/commonResult.mli 9 Nov 2006 21:32:26 -0000 1.7
-@@ -78,7 +78,7 @@
- val find_result : int -> StoredResult.stored_result
- val dummy_result : CommonTypes.result_info
- val result_download :
-- StoredResult.stored_result -> 'a -> 'b -> CommonTypes.file list
-+ StoredResult.stored_result -> 'a -> 'b -> CommonTypes.userdb -> CommonTypes.file list
- val results_iter : (int -> StoredResult.stored_result -> unit) -> unit
- val update_result : StoredResult.result -> unit
- val update_result2 :
-Index: src/daemon/common/commonSearch.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonSearch.ml,v
-retrieving revision 1.17
-retrieving revision 1.18
-diff -u -r1.17 -r1.18
---- src/daemon/common/commonSearch.ml 19 Jan 2006 00:44:47 -0000 1.17
-+++ src/daemon/common/commonSearch.ml 13 Nov 2006 13:14:49 -0000 1.18
-@@ -117,8 +117,12 @@
- | "-network" :: name :: args ->
- net := (network_find_by_name name).network_num;
- iter args q
-- | "-without" :: name :: args ->
-+ | "-not" :: name :: args ->
- iter args ((QAndNot (QHasWord name, QHasWord name)) :: q)
-+ | "-and" :: name :: args ->
-+ iter args ((QAnd (QHasWord name, QHasWord name)) :: q)
-+ | "-or" :: name :: args ->
-+ iter args ((QOr (QHasWord name, QHasWord name)) :: q)
- | s :: args ->
- if s.[0] = '-' then
- let args =
-@@ -134,16 +138,19 @@
- iter args ((QHasWord(s)) :: q)
- in
- let q = iter args [] in
-- (match q with
-+ (match (List.rev q) with
- [] -> failwith "Void query"
-- | [QAndNot _] -> failwith "Bad without query"
- | q1 :: tail ->
- List.fold_left (fun q1 q2 ->
- match q2 with
-- QAndNot (QHasWord x,_) ->
-+ QAndNot (QHasWord x, _) ->
- QAndNot (q1, QHasWord x)
-+ | QAnd (QHasWord x, _) ->
-+ QAnd (q1, QHasWord x)
-+ | QOr (QHasWord x, _) ->
-+ QOr (q1, QHasWord x)
- | _ ->
-- QAnd (q1,q2)
-+ QAnd (q1,q2)
- ) q1 tail), !net
-
-
-Index: src/daemon/common/commonServer.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonServer.ml,v
-retrieving revision 1.33
-retrieving revision 1.38
-diff -u -r1.33 -r1.38
---- src/daemon/common/commonServer.ml 6 Aug 2006 13:59:05 -0000 1.33
-+++ src/daemon/common/commonServer.ml 19 Nov 2006 23:04:25 -0000 1.38
-@@ -53,6 +53,7 @@
- mutable op_server_connect : ('a -> unit);
- mutable op_server_disconnect : ('a -> unit);
- mutable op_server_users : ('a -> user list);
-+ mutable op_server_published : ('a -> file list);
- mutable op_server_query_users : ('a -> unit);
- mutable op_server_find_user : ('a -> string -> unit);
- mutable op_server_cid : ('a -> Ip.t);
-@@ -108,12 +109,15 @@
- T.server_users = None;
- T.server_banner = "";
- T.server_preferred = false;
-+ T.server_master = false;
- T.server_version = "";
- T.server_max_users = 0L;
- T.server_soft_limit = 0L;
- T.server_hard_limit = 0L;
- T.server_lowid_users = 0L;
- T.server_ping = 0;
-+ T.server_published_files = 0;
-+ T.server_features = None;
- }
-
- let server_num s =
-@@ -183,6 +187,10 @@
- let s = as_server_impl s in
- s.impl_server_ops.op_server_users s.impl_server_val
-
-+let server_published s =
-+ let s = as_server_impl s in
-+ s.impl_server_ops.op_server_published s.impl_server_val
-+
- let server_cid s =
- let s = as_server_impl s in
- s.impl_server_ops.op_server_cid s.impl_server_val
-@@ -212,6 +220,7 @@
- op_server_disconnect = (fun _ -> ni_ok network "server_disconnect");
- op_server_find_user = (fun _ -> fni network "find_user");
- op_server_query_users = (fun _ -> ni_ok network "query_users");
-+ op_server_published = (fun _ -> fni network "published");
- op_server_users = (fun _ -> fni network "users");
- op_server_cid = (fun _ -> fni network "cid");
- op_server_low_id = (fun _ -> fni network "low_id");
-@@ -362,24 +371,30 @@
- info.G.server_banner
-
- let server_print_html_header buf ext =
-+ if !!html_mods_use_js_tooltips then Printf.bprintf buf
-+"\\<div id=\\\"object1\\\" style=\\\"position:absolute; background-color:#FFFFDD;color:black;border-color:black;border-width:20px;font-size:8pt; visibility:visible; left:25px; top:
-+-100px; z-index:+1\\\" onmouseover=\\\"overdiv=1;\\\" onmouseout=\\\"overdiv=0; setTimeout(\\\'hideLayer()\\\',1000)\\\"\\>\\&nbsp;\\</div\\>";
-+
- html_mods_table_header buf "serversTable" (Printf.sprintf "servers%s" ext) ([
- ( "1", "srh", "Server number", "#" ) ;
- ( "0", "srh", "Connect|Disconnect", "C/D" ) ;
- ( "0", "srh", "Remove", "Rem" ) ;
- ( "0", "srh", "Preferred", "P" ) ;
-+ ( "0", "srh", "Master servers", "M" ) ;
- ( "0", "srh", "[Hi]gh or [Lo]w ID", "ID" ) ;
- ( "0", "srh", "Network name", "Network" ) ;
- ( "0", "srh", "Connection status", "Status" ) ;
-- ] @ (if !Geoip.active then [( "0", "srh", "Country Code/Name", "CC" )] else []) @ [
- ( "0", "srh br", "IP address", "IP address" ) ;
-+ ] @ (if !Geoip.active then [( "0", "srh br", "Country Code/Name", "CC" )] else []) @ [
- ( "1", "srh ar", "Number of connected users", "Users" ) ;
- ( "1", "srh ar br", "Max number of users", "MaxUsers" ) ;
- ( "1", "srh ar br", "LowID users", "LowID" ) ;
-- ( "1", "srh ar br", "Number of files indexed on server", "Files" ) ;
-+ ( "1", "srh ar", "Number of files indexed on server", "Files" );
-+ ( "1", "srh ar br", "Number of published files on server", "Publ" );
- ( "1", "srh ar", "Soft file limit", "Soft" ) ;
- ( "1", "srh ar br", "Hard file limit", "Hard" ) ;
- ( "0", "srh ar br", "Ping (ms)", "Ping" ) ;
-- ( "0", "srh", "Server version", "Version" ) ;
-+ ( "0", "srh br", "Server version", "Version" ) ;
- ( "0", "srh", "Server name", "Name" ) ;
- ( "0", "srh", "Server details", "Details" ) ])
-
-@@ -397,80 +412,79 @@
- let buf = o.conn_buf in
-
- if use_html_mods o then begin
-- let snum = (server_num s) in
-+ let snum = (server_num s) in
-+ let ip_port_string =
-+ Printf.sprintf "%s:%s%s"
-+ (Ip.string_of_addr info.G.server_addr)
-+ (string_of_int info.G.server_port)
-+ (if info.G.server_realport <> 0
-+ then "(" ^ (string_of_int info.G.server_realport) ^ ")"
-+ else ""
-+ )
-+ in
-+
-+ Printf.bprintf buf "\\<tr class=\\\"dl-%d\\\""
-+ (html_mods_cntr ());
-+
-+ (if !!html_mods_use_js_tooltips then
-+ Printf.bprintf buf " onMouseOver=\\\"mOvr(this);setTimeout('popLayer(\\\\\'%s %s<br>%s\\\\\')',%d);setTimeout('hideLayer()',%d);return true;\\\" onMouseOut=\\\"mOut(this);hideLayer();setTimeout('hideLayer()',%d)\\\"\\>"
-+ info.G.server_name ip_port_string
-+ (match info.G.server_features with
-+ | None -> ""
-+ | Some f -> "server features: " ^ f)
-+ !!html_mods_js_tooltips_wait
-+ !!html_mods_js_tooltips_timeout
-+ !!html_mods_js_tooltips_wait);
-
-- Printf.bprintf buf "
-- \\<tr class=\\\"dl-%d\\\"\\>
-- \\<td class=\\\"srb\\\" %s \\>%d\\</td\\>
-- %s
-- %s
-- %s
-- \\<td class=\\\"sr\\\" %s\\</td\\>
-- \\<td class=\\\"sr\\\"\\>%s\\</td\\>
-- \\<td class=\\\"sr\\\"\\>%s\\</td\\>
-- %s
-- \\<td class=\\\"sr br\\\"\\>%s:%s\\</td\\>
-- \\<td class=\\\"sr ar\\\"\\>%Ld\\</td\\>
-- \\<td class=\\\"sr ar br\\\"\\>%Ld\\</td\\>
-- \\<td class=\\\"sr ar br\\\"\\>%Ld\\</td\\>
-- \\<td class=\\\"sr ar br\\\"\\>%Ld\\</td\\>
-- \\<td class=\\\"sr ar\\\"\\>%Ld\\</td\\>
-- \\<td class=\\\"sr ar br\\\"\\>%Ld\\</td\\>
-- \\<td class=\\\"sr ar br\\\"\\>%d\\</td\\>
-- \\<td class=\\\"sr br\\\"\\>%s\\</td\\>
-- \\<td class=\\\"sr\\\"\\>%s\\</td\\>
-- \\<td width=\\\"100%%\\\" class=\\\"sr\\\"\\>%s\\</td\\>\\</tr\\>\n"
-- (html_mods_cntr ())
-+ Printf.bprintf buf
-+" \\<td class=\\\"srb\\\" %s \\>%d\\</td\\> %s %s %s"
- (match impl.impl_server_state with
-- Connected _ -> Printf.sprintf "title=\\\"Server Banner\\\"
-- onMouseOver=\\\"mOvr(this);\\\"
-- onMouseOut=\\\"mOut(this);\\\"
-- onClick=\\\"location.href='submit?q=server_banner+%d'\\\"" snum
-+ Connected _ ->
-+ Printf.sprintf "title=\\\"Server Banner\\\"
-+ onClick=\\\"location.href='submit?q=server_banner+%d'\\\""
-+ snum
- | _ -> "")
- snum
- (
-- if server_blocked s && (match impl.impl_server_state with
-- NotConnected _ -> true
-- | _ -> false) then "\\<td class=\\\"srb\\\"\\>blk\\</td\\>" else
-- Printf.sprintf
-- "\\<TD class=\\\"srb\\\" onMouseOver=\\\"mOvr(this);\\\"
-- onMouseOut=\\\"mOut(this);\\\" title=\\\"Connect|Disconnect\\\"
-- onClick=\\\"parent.fstatus.location.href='submit?q=%s+%d'\\\"\\>%s\\</TD\\>"
-- (match impl.impl_server_state with
-- NotConnected _ -> "c"
-- | _ -> "x")
-+ let not_connected =
-+ match impl.impl_server_state with
-+ | NotConnected _ -> true
-+ | _ -> false
-+ in
-+ if server_blocked s && not_connected
-+ then "\\<td class=\\\"srb\\\"\\>blk\\</td\\>"
-+ else Printf.sprintf
-+ "\\<td class=\\\"srb\\\" title=\\\"Connect|Disconnect\\\"
-+ onClick=\\\"parent.fstatus.location.href='submit?q=%s+%d'\\\"\\>%s\\</td\\>"
-+ (if not_connected then "c" else "x")
- snum
-- (match impl.impl_server_state with
-- NotConnected _ -> "Conn"
-- | _ -> "Disc")
-+ (if not_connected then "Conn" else "Disc")
- )
- (
- Printf.sprintf
-- "\\<TD class=\\\"srb\\\" onMouseOver=\\\"mOvr(this);\\\"
-- onMouseOut=\\\"mOut(this);\\\" title=\\\"Remove server\\\"
-- onClick=\\\"parent.fstatus.location.href='submit?q=rem+%d'\\\"\\>Rem\\</TD\\>"
-+ "\\<td class=\\\"srb\\\" title=\\\"Remove server\\\"
-+ onClick=\\\"parent.fstatus.location.href='submit?q=rem+%d'\\\"\\>Rem\\</td\\>"
- snum
- )
- (
- if info.G.server_preferred then begin
- Printf.sprintf
-- "\\<TD class=\\\"srb\\\" onMouseOver=\\\"mOvr(this);\\\"
-- onMouseOut=\\\"mOut(this);\\\" title=\\\"Unset preferred\\\"
-- onClick=\\\"parent.fstatus.location.href='submit?q=preferred+false+%s'\\\"\\>T\\</TD\\>"
-+ "\\<td class=\\\"srb\\\" title=\\\"Unset preferred\\\"
-+ onClick=\\\"parent.fstatus.location.href='submit?q=preferred+false+%s'\\\"\\>P\\</td\\>"
- (Ip.string_of_addr info.G.server_addr)
- end else begin
- Printf.sprintf
-- "\\<TD class=\\\"srb\\\" onMouseOver=\\\"mOvr(this);\\\"
-- onMouseOut=\\\"mOut(this);\\\" title=\\\"Set preferred\\\"
-- onClick=\\\"parent.fstatus.location.href='submit?q=preferred+true+%s'\\\"\\>F\\</TD\\>"
-+ "\\<td class=\\\"srb\\\" title=\\\"Set preferred\\\"
-+ onClick=\\\"parent.fstatus.location.href='submit?q=preferred+true+%s'\\\"\\>-\\</td\\>"
- (Ip.string_of_addr info.G.server_addr)
- end
-- )
-- (if n.network_name = "Donkey" then
-- begin
-+ );
-+
-+ let id_title, id_text =
-+ match n.network_name with
-+ "Donkey" -> begin
- match impl.impl_server_state with
-- | Connected _ ->
-- begin
-+ Connected _ -> begin
- let cid = (server_cid s) in
- let (label,shortlabel,our_ip) =
- if not (server_low_id s) then
-@@ -478,49 +492,58 @@
- (if !!set_client_ip <> cid then
- Printf.sprintf "(clientIP: %s)"
- (Ip.to_string !!set_client_ip)
-- else ""
-- )
-- )
-- else
-- ("LowID","Lo","")
-+ else ""))
-+ else ("LowID","Lo","")
- in
-- Printf.sprintf
-- "title=\\\"%s: %s = %s %s\\\" \\>%s"
-+ Printf.sprintf "%s: %s = %s %s"
- label
- (Int64.to_string (Ip.to_int64 (Ip.rev cid)))
- (Ip.to_string cid)
- our_ip
-- shortlabel
-+ ,shortlabel
- end
-- | _ -> "\\>"
-+ | _ -> "",""
- end
-- else "\\>"
-- )
-- n.network_name
-- (match impl.impl_server_state with
-- NotConnected _ -> if server_blocked s then "IP blocked"
-- else (string_of_connection_state impl.impl_server_state)
-- | _ -> (string_of_connection_state impl.impl_server_state))
-- (if !Geoip.active then
-- Printf.sprintf "\\<td class=\\\"sr\\\" title=\\\"%s\\\" \\>%s\\</td\\>" cn cc
-- else "")
-- (Ip.string_of_addr info.G.server_addr)
-- (Printf.sprintf "%s%s"
-- (string_of_int info.G.server_port)
-- (if info.G.server_realport <> 0
-- then "(" ^ (string_of_int info.G.server_realport) ^ ")"
-- else ""))
-- info.G.server_nusers
-- info.G.server_max_users
-- info.G.server_lowid_users
-- info.G.server_nfiles
-- info.G.server_soft_limit
-- info.G.server_hard_limit
-- info.G.server_ping
-- info.G.server_version
-- info.G.server_name
-- info.G.server_description
-+ | _ -> "",""
-+ in
-+
-+ let server_state_string =
-+ match impl.impl_server_state with
-+ NotConnected _ when server_blocked s -> "IP blocked"
-+ | _ -> string_of_connection_state impl.impl_server_state
-+ in
-+
-+ let cc,cn = Geoip.get_country (Ip.ip_of_addr info.G.server_addr) in
-+ html_mods_td buf ([
-+ ("", "srb", if info.G.server_master then "M" else "-");
-+ (id_title, "sr", id_text);
-+ ("", "sr", n.network_name);
-+ ("", "sr", server_state_string);
-+ ("", "sr br", ip_port_string);
-+ ] @ (if !Geoip.active then [(cn, "sr br", cc)] else []) @ [
-+ ("", "sr ar", if info.G.server_nusers = Int64.zero then "" else Printf.sprintf "%Ld" info.G.server_nusers);
-+ ("", "sr ar br", if info.G.server_max_users = Int64.zero then "" else Printf.sprintf "%Ld" info.G.server_max_users);
-+ ("", "sr ar br", if info.G.server_lowid_users = Int64.zero then "" else Printf.sprintf "%Ld" info.G.server_lowid_users);
-+ ("", "sr ar", if info.G.server_nfiles = Int64.zero then "" else Printf.sprintf "%Ld" info.G.server_nfiles)]);
-+
-+ if info.G.server_published_files = 0 then
-+ html_mods_td buf ([("", "sr br", "")])
-+ else
-+ Printf.bprintf buf
-+"\\<TD class=\\\"sr br\\\" title=\\\"Show published files\\\"
-+onClick=\\\"location.href='submit?q=server_shares+%d'\\\"\\>%d\\</TD\\>"
-+ snum info.G.server_published_files;
-+
-+ html_mods_td buf ([
-+ ("", "sr ar", if info.G.server_soft_limit = Int64.zero then "" else Printf.sprintf "%Ld" info.G.server_soft_limit);
-+ ("", "sr ar br", if info.G.server_hard_limit = Int64.zero then "" else Printf.sprintf "%Ld" info.G.server_hard_limit);
-+ ("", "sr ar br", if info.G.server_ping = 0 then "" else Printf.sprintf "%d" info.G.server_ping);
-+ ("", "sr br", info.G.server_version);
-+ ("", "sr", info.G.server_name);
-+ ]);
-
-+ Printf.bprintf buf "\\<td width=\\\"100%%\\\" class=\\\"sr\\\"\\>%s\\</td\\>\\</tr\\>\n"
-+ info.G.server_description;
- end
- else
- begin
-Index: src/daemon/common/commonShared.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonShared.ml,v
-retrieving revision 1.33
-retrieving revision 1.37
-diff -u -r1.33 -r1.37
---- src/daemon/common/commonShared.ml 12 Jun 2006 20:47:21 -0000 1.33
-+++ src/daemon/common/commonShared.ml 29 Oct 2006 18:58:59 -0000 1.37
-@@ -43,7 +43,8 @@
- mutable impl_shared_size : int64;
- mutable impl_shared_id : Md4.t;
- mutable impl_shared_requests : int;
-- mutable impl_shared_magic : string option
-+ mutable impl_shared_magic : string option;
-+ mutable impl_shared_servers : CommonTypes.server list;
- }
-
- and 'a shared_ops = {
-@@ -214,6 +215,7 @@
- impl_shared_id = Md4.null;
- impl_shared_requests = 0;
- impl_shared_magic = None;
-+ impl_shared_servers = []
- }
-
-
-@@ -235,17 +237,17 @@
-
- let shared_scan_directory shared_dir local_dir =
- let incoming_files_inode =
-- ((Unix.stat ((CommonComplexOptions.incoming_files ()).shdir_dirname)).Unix.st_ino)
-+ ((Unix.stat ((CommonComplexOptions.incoming_dir false ()).shdir_dirname)).Unix.st_ino)
- in
- let incoming_directories_inode =
-- ((Unix.stat ((CommonComplexOptions.incoming_directories ()).shdir_dirname)).Unix.st_ino)
-+ ((Unix.stat ((CommonComplexOptions.incoming_dir true ()).shdir_dirname)).Unix.st_ino)
- in
- let temp_directory_inode =
- ((Unix.stat !!temp_directory).Unix.st_ino)
- in
- let dirname = shared_dir.shdir_dirname in
- let strategy =
-- CommonComplexOptions.sharing_strategies shared_dir.shdir_strategy in
-+ CommonComplexOptions.sharing_strategy shared_dir.shdir_strategy in
- let dirname =
- if Filename.is_relative dirname then
- Filename.concat file_basedir dirname
-@@ -352,6 +354,7 @@
- T.shared_requests = impl.impl_shared_requests;
- T.shared_uids = [];
- T.shared_sub_files = [];
-+ T.shared_magic = impl.impl_shared_magic;
- }
-
- let shared_info s =
-Index: src/daemon/common/commonShared.mli
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonShared.mli,v
-retrieving revision 1.7
-retrieving revision 1.8
-diff -u -r1.7 -r1.8
---- src/daemon/common/commonShared.mli 12 Jun 2006 20:47:21 -0000 1.7
-+++ src/daemon/common/commonShared.mli 8 Oct 2006 14:20:21 -0000 1.8
-@@ -9,7 +9,8 @@
- mutable impl_shared_size : int64;
- mutable impl_shared_id : Md4.Md4.t;
- mutable impl_shared_requests : int;
-- mutable impl_shared_magic : string option
-+ mutable impl_shared_magic : string option;
-+ mutable impl_shared_servers : CommonTypes.server list;
- }
- and 'a shared_ops = {
- mutable op_shared_info : 'a -> GuiTypes.shared_info;
-Index: src/daemon/common/commonSources.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonSources.ml,v
-retrieving revision 1.35
-retrieving revision 1.39
-diff -u -r1.35 -r1.39
---- src/daemon/common/commonSources.ml 8 Apr 2006 02:16:21 -0000 1.35
-+++ src/daemon/common/commonSources.ml 21 Nov 2006 22:34:33 -0000 1.39
-@@ -531,7 +531,7 @@
- Sort.list
- (fun f1 f2 ->
- file_best_name (f1.manager_file ()) < file_best_name (f2.manager_file ())
-- ) !file_sources_managers
-+ ) (List.filter (fun m -> file_state (m.manager_file ()) = FileDownloading) !file_sources_managers)
- in
- (* Files *)
- List.iter (fun m ->
-@@ -1739,6 +1739,8 @@
- | _ -> ()
- ) !file_sources_managers;
-
-+ if !files <> [] then begin
-+
- (* 'normalize' to 0 priorities*)
- sum_priority := !sum_priority + (!nfiles * (-(!min_priority)));
- (* update priorities to be > 0 *)
-@@ -1758,7 +1760,7 @@
-
- (* calc sources queue size
- at least 3 sources per file*)
-- let nsources = maxi (!nfiles*3)
-+ let nsources = max (!nfiles*3)
- (functions.function_max_connections_per_second () * 10) in
-
- (* calc how much sources a file can get according to its priority*)
-@@ -1768,99 +1770,93 @@
- (*
- iter through files to queue sources
- flist_todo : next files to test
-- flist_done : already tested files
- assigned : number of sources already queued
-- pos : position in file list
-- len : length of file list
- looped : number of times we allow to loop try to fill queue of sources
- (how hard we try to fill queue)
- *)
-- let rec iter_files flist_todo flist_done assigned pos len looped =
-- if pos==len || assigned>nsources then
-- begin
-- (*
-- assigned>nsources stop!
-- pos=len we are at the end of file list
-- *)
-- (* Cleanup some sources *)
-- List.iter
-- (fun m ->
-- let f = m.manager_file () in
-- if file_state f = FileDownloading then
-- begin
-- let remove_old q t = begin
-- if Queue.length q > 0 then
-- let (request_time, s) = Queue.head q in
-- if request_time + t < last_time () then
-- remove_from_queue s (find_request s m);
-- end in
-- remove_old m.manager_sources.(do_not_try_queue) 14400;
-- remove_old m.manager_sources.(old_sources3_queue) 2400;
-- remove_old m.manager_sources.(old_sources2_queue) 1200;
-- end
-- ) !file_sources_managers;
-- (* more power to the "runaway" (most overloaded) file, pick extra sources *)
-- let em =
-- let q = find_throttled_queue good_sources_queue in
-- if queue_period.(q) > 0 then
-- let max_overloaded = List.hd (find_max_overloaded q !file_sources_managers) in
-- let overhead = count_file_ready_sources max_overloaded q true in
-- if overhead > 0 then
-- get_sources max_consecutive max_overloaded good_sources_queue 0
-- else
-- 0
-- else
-- 0
-- in
-- if assigned + em < nsources && looped>0 then
-- (*
-- if assigned < nsources restart to fill
-- reorder todo files by highest priority first
-- allow at most looped re-iter of list to not loop endlessly
-- *)
-- iter_files (List.rev flist_done) [] (assigned + em) 0 len (looped-1)
-- end
-- else
-- begin
-- (* throw in new sources at high pace and
-- do not care about them in get_sources,
-- this avoids "locking" a file's queue
-- sources with thousands of new sources
-- from SE *)
-- let extr = ref 0 in
-- List.iter
-- (fun m ->
-- let f = m.manager_file () in
-- let q = m.manager_sources.(new_sources_queue) in
-- if file_state f = FileDownloading && Queue.length q > 0 then
-- let (request_time, s) = Queue.head q in
-- source_connecting s;
-- if M.direct_source s.source_uid then
-- begin
-- incr extr;
-- Fifo.put next_direct_sources s
-- end
-- else
-- next_indirect_sources := s :: !next_indirect_sources
-- ) !file_sources_managers;
-+ let rec iter_files assigned looped =
-
-- let fp = List.hd flist_todo in
-- let file = snd fp and
-- prio = fst fp in
-- let tt = min (truncate (sources_per_prio *. float_of_int(prio)))
-- max_consecutive in
-- let to_take = max tt 1 in
-- (*allow at least one source per file :
-- we will overflow a bit the expected next_direct_sources length
-- but it's for the good cause : not 'starving' some files
-- *)
-- let took = get_sources to_take file good_sources_queue 0 in
-- iter_files (List.tl flist_todo) (fp::flist_done)
-- (assigned + took + !extr) (pos+1) len looped
-- end
-- in
-- iter_files !files [] 0 0 (List.length !files) 3;
-+ (* throw in new sources at high pace and do not care
-+ about them in get_sources, this avoids "locking" a
-+ file's queue sources with thousands of new sources
-+ from SE *)
-+ let try_some_new_sources () =
-+ let extr = ref 0 in
-+ List.iter
-+ (fun m ->
-+ let f = m.manager_file () in
-+ let q = m.manager_sources.(new_sources_queue) in
-+ if file_state f = FileDownloading && Queue.length q > 0 then
-+ let (request_time, s) = Queue.head q in
-+ source_connecting s;
-+ if M.direct_source s.source_uid then begin
-+ incr extr;
-+ Fifo.put next_direct_sources s
-+ end
-+ else
-+ next_indirect_sources := s :: !next_indirect_sources
-+ ) !file_sources_managers;
-+ !extr in
-+
-+ let cleanup_some_old_sources () =
-+ (* Cleanup some sources *)
-+ List.iter
-+ (fun m ->
-+ let f = m.manager_file () in
-+ if file_state f = FileDownloading then
-+ let remove_old q t =
-+ if Queue.length q > 0 then
-+ let (request_time, s) = Queue.head q in
-+ if request_time + t < last_time () then
-+ remove_from_queue s (find_request s m) in
-+
-+ remove_old m.manager_sources.(do_not_try_queue) 14400;
-+ remove_old m.manager_sources.(old_sources3_queue) 2400;
-+ remove_old m.manager_sources.(old_sources2_queue) 1200
-+ ) !file_sources_managers in
-+
-+ let rec aux flist_todo assigned =
-+ if assigned >= nsources then
-+ cleanup_some_old_sources ()
-+ else
-+ match flist_todo with
-+ | (prio, file) :: t ->
-+ let tt = min (truncate (sources_per_prio *. (float_of_int prio)))
-+ max_consecutive in
-+ let to_take = max tt 1 in
-+ (* allow at least one source per file :
-+ we will overflow a bit the expected next_direct_sources length
-+ but it's for the good cause : not 'starving' some files
-+ *)
-+ let took = get_sources to_take file good_sources_queue 0 in
-+ aux t (assigned + took)
-+
-+ | [] ->
-+ cleanup_some_old_sources ();
-+
-+ (* more power to the "runaway" (most overloaded) file, pick extra sources *)
-+ let em =
-+ let q = find_throttled_queue good_sources_queue in
-+ if queue_period.(q) > 0 then
-+ let max_overloaded =
-+ List.hd (find_max_overloaded q !file_sources_managers) in
-+ let overhead =
-+ count_file_ready_sources max_overloaded q true in
-+ if overhead > 0 then
-+ get_sources max_consecutive max_overloaded good_sources_queue 0
-+ else 0
-+ else 0 in
-+
-+ if looped > 0 then
-+ (* allow at most looped re-iter of list to not
-+ loop endlessly *)
-+ iter_files (assigned + em) (looped - 1)
-+ in
-+ let extr = try_some_new_sources () in
-+ aux !files (assigned + extr)
-
-+ in
-+ iter_files 0 3;
-
- (* adjust queue throttling *)
- let all_ready = ref 0 in
-@@ -1890,6 +1886,8 @@
- end
- ) [ good_sources_queue; old_sources1_queue; old_sources2_queue; old_sources3_queue ];
-
-+ end;
-+
- if !verbose_sources > 0 then begin
- lprintf_nl "[cSrc] CommonSources.refill_sources AFTER:";
- let buf = Buffer.create 100 in
-Index: src/daemon/common/commonStats.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonStats.ml,v
-retrieving revision 1.3
-retrieving revision 1.4
-diff -u -r1.3 -r1.4
---- src/daemon/common/commonStats.ml 26 Aug 2006 12:05:53 -0000 1.3
-+++ src/daemon/common/commonStats.ml 23 Sep 2006 20:29:46 -0000 1.4
-@@ -87,12 +87,16 @@
- done;
- s
-
--let brandlist_int_to_string l i =
-+let brandlist_int_to_2string l i =
- if List.length l > i then
-- let (_,ls,_) = List.nth l i in
-- ls
-+ let (_,ls,ss) = List.nth l i in
-+ ls,ss
- else
-- "Total"
-+ "Total","Ttl"
-+
-+let brandlist_int_to_string l i =
-+ let (ls,_) = brandlist_int_to_2string l i in
-+ ls
-
- let print_stats_old buf arr l tl uptime =
-
-@@ -234,6 +238,26 @@
- ( "1", "srh", "Total uploads:downloads ratio", "U:DL" );
- ]
-
-+let stats_list l arr =
-+ let sl = ref [] in
-+ for i = 0 to (Array.length arr) - 1 do
-+ let r = arr.(i) in
-+ if r.brand_seen > 0 then begin
-+ let ls,ss = brandlist_int_to_2string l i in
-+ let s = {
-+ string_long = ls;
-+ string_short = ss;
-+ seen = r.brand_seen;
-+ banned = r.brand_banned;
-+ filerequest = r.brand_filerequest;
-+ download = r.brand_download;
-+ upload = r.brand_upload;
-+ } in
-+ sl := s :: !sl
-+ end
-+ done;
-+ !sl
-+
- let print_stats_html_mods buf arr l tl uptime =
-
- let stats_all = build_all arr in
-Index: src/daemon/common/commonTypes.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonTypes.ml,v
-retrieving revision 1.55
-retrieving revision 1.62
-diff -u -r1.55 -r1.62
---- src/daemon/common/commonTypes.ml 5 Sep 2006 14:18:24 -0000 1.55
-+++ src/daemon/common/commonTypes.ml 13 Nov 2006 13:10:17 -0000 1.62
-@@ -88,6 +88,9 @@
- string_of_uid_sep uid "_"
-
- exception Illegal_urn of string
-+exception Torrent_already_exists
-+exception Torrent_can_not_be_used
-+
- let uid_of_string s =
- let s = String.lowercase s in
- let urn = String2.before s 4 in
-@@ -347,7 +350,7 @@
-
- type shared_directory = {
- shdir_dirname : string;
-- shdir_priority : int;
-+ mutable shdir_priority : int;
- shdir_strategy : string;
- shdir_networks : string list;
- }
-@@ -376,6 +379,8 @@
- | ByNet
- | ByAvail
- | ByComments
-+| ByUser
-+| ByGroup
- | NotSorted
-
- type room_state =
-@@ -452,7 +457,38 @@
- ExtendSearchLocally
- | ExtendSearchRemotely
-
--type network = {
-+type network_stat_info = {
-+ mutable string_long : string;
-+ mutable string_short : string;
-+ mutable seen : int;
-+ mutable banned : int;
-+ mutable filerequest : int;
-+ mutable download : Int64.t;
-+ mutable upload : Int64.t;
-+}
-+
-+type network_porttest =
-+ PorttestNotAvailable
-+| PorttestNotStarted
-+| PorttestInProgress of int
-+| PorttestResult of int * string
-+
-+type groupdb = {
-+ group_name : string;
-+ mutable group_admin : bool;
-+}
-+
-+and userdb = {
-+ user_name : string;
-+ mutable user_pass : Md4.t;
-+ mutable user_groups : groupdb list;
-+ mutable user_default_group : groupdb option;
-+ mutable user_mail : string;
-+ mutable user_commit_dir : string;
-+ mutable user_max_concurrent_downloads : int;
-+}
-+
-+and network = {
- network_name : string;
- network_num : int;
- network_connection_manager : TcpBufferedSocket.connection_manager;
-@@ -480,7 +516,7 @@
- mutable op_network_share : (
- string -> string -> int64 -> unit);
- mutable op_network_private_message : (string -> string -> unit);
-- mutable op_network_parse_url : (string -> string * bool);
-+ mutable op_network_parse_url : (string -> userdb -> string * bool);
- mutable op_network_connect_servers : (unit -> unit);
-
- mutable op_network_search : (search -> Buffer.t -> unit);
-@@ -492,17 +528,20 @@
- mutable op_network_info : (unit -> network_info);
-
- mutable op_network_connected : (unit -> bool);
-- mutable op_network_gui_message : (string -> unit);
-+ mutable op_network_gui_message : (string -> userdb -> unit);
-
-- mutable op_network_download : (result_info -> file);
-+ mutable op_network_download : (result_info -> userdb -> file);
- mutable op_network_display_stats : (Buffer.t -> ui_conn -> unit);
-+ mutable op_network_stat_info_list : unit -> (string * int * (network_stat_info list)) list;
- mutable op_network_clean_exit : (unit -> bool);
- mutable op_network_reset : (unit -> unit);
- mutable op_network_ports : (unit -> (int * string) list);
-+ mutable op_network_porttest_start : (unit -> unit);
-+ mutable op_network_porttest_result : (unit -> network_porttest);
- }
-
--and ui_user = {
-- ui_user_name : string;
-+and ui_user = {
-+ ui_user : userdb;
- mutable ui_user_searches : search list;
- mutable ui_last_search : search option;
- mutable ui_last_results : (int * result) list;
-@@ -887,3 +926,20 @@
- f : string -> string -> unit;
- description : string
- }
-+
-+type slot_kind =
-+ NoSlot
-+| FriendSlot
-+| ReleaseSlot
-+| SmallFileSlot
-+| NormalSlot
-+| PrioSlot of string
-+
-+let string_of_slot_kind slot_kind short =
-+ match slot_kind with
-+ NoSlot -> "NoSlot"
-+ | FriendSlot -> "FriendSlot"
-+ | ReleaseSlot -> "ReleaseSlot"
-+ | SmallFileSlot -> "SmallFileSlot"
-+ | NormalSlot -> if short then "" else "NormalSlot"
-+ | PrioSlot dir -> Printf.sprintf "Prio %s" dir
-Index: src/daemon/common/commonUploads.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonUploads.ml,v
-retrieving revision 1.45
-retrieving revision 1.51
-diff -u -r1.45 -r1.51
---- src/daemon/common/commonUploads.ml 5 Sep 2006 14:15:19 -0000 1.45
-+++ src/daemon/common/commonUploads.ml 21 Nov 2006 22:34:33 -0000 1.51
-@@ -244,7 +244,7 @@
- !!http_port, "http_port";
- !!telnet_port, "telnet_port";
- !!gui_port, "gui_port";
-- !!gift_port, "gift_port";
-+ !!gift_port, "gift_port GUI";
- ]);
- network.op_network_connected_servers <- (fun _ -> [])
-
-@@ -279,15 +279,6 @@
- let shared_counter = ref (Int64.zero)
- let shared_files = Hashtbl.create 13
-
--let _ =
-- Heap.add_memstat "CommonUploads" (fun level buf ->
-- Printf.bprintf buf " infos_by_name: %d\n" (Hashtbl.length infos_by_name);
-- Printf.bprintf buf " shareds_by_uid: %d\n" (Hashtbl.length shareds_by_uid);
-- Printf.bprintf buf " shareds_by_id: %d\n" (Hashtbl.length shareds_by_id);
-- Printf.bprintf buf " shared_files: %d\n" (Hashtbl.length shared_files);
-- )
--
--
- let new_shared_dir dirname = {
- shared_dirname = dirname;
- shared_files = [];
-@@ -695,7 +686,8 @@
- impl_shared_ops = shared_ops;
- impl_shared_val = sh;
- impl_shared_requests = 0;
-- impl_shared_magic = None
-+ impl_shared_magic = None;
-+ impl_shared_servers = [];
- }
- and sh = {
- shared_info = index;
-@@ -838,14 +830,7 @@
- end
- else
- if not (Intmap.mem (client_num c) !pending_slots_map) then
-- begin
--(* This is useless since it is the goal of the pending_slots_map
-- else if Fifo.mem pending_slots_fifo (client_num c) then begin
-- lprintf "Avoided inserting a client twice in pending slots\n";
--
-- end else *)
-- pending_slots_map := Intmap.add (client_num c) c !pending_slots_map;
-- end
-+ pending_slots_map := Intmap.add (client_num c) c !pending_slots_map
-
- let remove_pending_slot c =
- if Intmap.mem (client_num c) !pending_slots_map then
-@@ -853,11 +838,11 @@
-
- let rec give_a_slot c =
- remove_pending_slot c;
-- if not (client_is_connected c) then begin
-- find_pending_slot ()
-- end
-- else begin
-- set_client_has_a_slot c true;
-+ if not (client_is_connected c) then
-+ find_pending_slot ()
-+ else
-+ begin
-+ set_client_has_a_slot c NormalSlot;
- client_enter_upload_queue c
- end
-
-@@ -872,36 +857,47 @@
- with _ -> ()
-
- let add_pending_slot c =
-- let csh = client_upload c in
-+ let client_upload c =
-+ match client_upload c with
-+ None -> raise Not_found
-+ | Some file -> file
-+ in
-+ let csh = file_shared (client_upload c) in
- let cdir = shared_dir csh in
- let cprio = ref (shared_prio csh) in
- let cfriend = ref (if is_friend c && !!friends_upload_slot then 1 else 0) in
- let csmallfiles = ref (match csh with
- | None -> 0
- | Some sh -> if shared_size sh <= !!small_files_slot_limit then 1 else 0) in
-- (* if cdir <> "" then
-- lprintf "Testing cdir %s\n" cdir; *)
-+ let allowed_release_slots =
-+ ref (Misc.percentage_of_ints !!max_upload_slots !!max_release_slots) in
-+
-+(* check current upload slots for already used special slots *)
- Intmap.iter (fun _ c ->
-- let sh = client_upload c in
-- if shared_dir sh = cdir then decr cprio;
-- if client_has_a_friend_slot c then decr cfriend;
-- match sh with
-- | None -> ()
-- | Some sh ->
-- if shared_size sh <= !!small_files_slot_limit then
-- decr csmallfiles;
-- ) !CommonClient.uploaders;
-- (* if cdir <> "" then
-- lprintf "Testing cprio %d cfriend %d csmallfiles\n"
-- !cprio !cfriend !csmallfiles; *)
-- if !cprio > 0 || !cfriend > 0 || !csmallfiles > 0 then begin
-- remove_pending_slot c;
-- if client_is_connected c then begin
-- set_client_has_a_slot c true;
-- client_enter_upload_queue c
-- end
-- end else
-- add_pending_slot c
-+ if shared_dir (file_shared (client_upload c)) = cdir then
-+ decr cprio;
-+ match client_slot c with
-+ ReleaseSlot -> decr allowed_release_slots
-+ | FriendSlot -> decr cfriend
-+ | SmallFileSlot -> decr csmallfiles
-+ | _ -> ()) !CommonClient.uploaders;
-+
-+ let slot_type =
-+ if file_release (client_upload c) && !allowed_release_slots > 0 then Some ReleaseSlot else
-+ if !cfriend > 0 then Some FriendSlot else
-+ if !csmallfiles > 0 then Some SmallFileSlot else
-+ if !cprio > 0 then Some (PrioSlot cdir) else
-+ None
-+ in
-+ match slot_type with
-+ Some slot ->
-+ remove_pending_slot c;
-+ if client_is_connected c then
-+ begin
-+ set_client_has_a_slot c slot;
-+ client_enter_upload_queue c
-+ end
-+ | None -> add_pending_slot c
-
- let static_refill_upload_slots () =
- let len = Intmap.length !CommonClient.uploaders in
-@@ -938,7 +934,7 @@
- estimated_capacity
- else
- (* max_hard_upload_rate lowered manually,... *)
-- mini estimated_capacity (!!max_hard_upload_rate * 1024) in
-+ min estimated_capacity (!!max_hard_upload_rate * 1024) in
- if !verbose_upload then
- lprintf_nl "usage: %d(%d) capacity: %d"
- (short_delay_upload_usage ())
-@@ -966,34 +962,18 @@
- end
-
- let turn = ref (-1)
--let turn_h = ref (-1)
-
- let refill_upload_slots () =
- incr turn;
- if !turn = 5 then
- turn := 0;
-- if !turn_h = 360 then
-- turn_h := 0;
- if !!dynamic_slots then begin
- if !turn = 0 then
- (* call every 5s *)
- dynamic_refill_upload_slots ()
- end else
- (* call every 1s *)
-- static_refill_upload_slots ();
--
-- if !turn = 0 then begin
-- (* call every 5s *)
-- incr turn_h;
-- update_download_history ();
-- update_upload_history ()
-- end;
--
-- if !turn_h = 0 then begin
-- (* call every 720 * 5s *)
-- update_h_download_history ();
-- update_h_upload_history ()
-- end
-+ static_refill_upload_slots ()
-
- let consume_bandwidth len =
- streaming_left := !streaming_left - len
-@@ -1067,3 +1047,12 @@
- | l -> l
- in
- get_name_keywords
-+
-+let _ =
-+ Heap.add_memstat "CommonUploads" (fun level buf ->
-+ Printf.bprintf buf " infos_by_name: %d\n" (Hashtbl.length infos_by_name);
-+ Printf.bprintf buf " shareds_by_uid: %d\n" (Hashtbl.length shareds_by_uid);
-+ Printf.bprintf buf " shareds_by_id: %d\n" (Hashtbl.length shareds_by_id);
-+ Printf.bprintf buf " shared_files: %d\n" (Hashtbl.length shared_files);
-+ Printf.bprintf buf " pending_slots: %d\n" (Intmap.length !pending_slots_map);
-+ )
-Index: src/daemon/common/commonUserDb.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonUserDb.ml,v
-retrieving revision 1.5
-retrieving revision 1.7
-diff -u -r1.5 -r1.7
---- src/daemon/common/commonUserDb.ml 12 Aug 2006 20:36:14 -0000 1.5
-+++ src/daemon/common/commonUserDb.ml 9 Nov 2006 21:32:26 -0000 1.7
-@@ -31,18 +31,130 @@
- let lprintf_n fmt =
- lprintf2 log_prefix fmt
-
--type userdb = {
-- user_name : string;
-- user_pass : Md4.t;
-- user_mail : string;
-- }
-+(*************************************************************************)
-+(* DEFAULTS *)
-+(*************************************************************************)
-
--let admin_user = "admin"
-+let users_ini = create_options_file "users.ini"
-+
-+let users2_section = file_section users_ini ["Users"] "User accounts on the core (new format)"
-+let users_section = file_section users_ini ["Users"] "User accounts on the core (old format)"
-
--let user2_is_admin user = user = admin_user
-+let dummy_group = {
-+ group_name = "";
-+ group_admin = true;
-+}
-+
-+let default_group_name = "mldonkey"
-+let system_user_default_group = {
-+ dummy_group with
-+ group_name = default_group_name
-+}
-
- let blank_password = Md4.string ""
-
-+let dummy_user = {
-+ user_name = "";
-+ user_pass = blank_password;
-+ user_groups = [system_user_default_group];
-+ user_default_group = Some system_user_default_group;
-+ user_mail = "";
-+ user_commit_dir = "";
-+ user_max_concurrent_downloads = 0;
-+}
-+
-+let admin_user_name = "admin"
-+let admin_user = {
-+ dummy_user with
-+ user_name = admin_user_name;
-+}
-+
-+(*************************************************************************)
-+(* GroupOption *)
-+(*************************************************************************)
-+
-+module GroupOption = struct
-+
-+ let value_to_group v =
-+ match v with
-+ | Options.Module assocs ->
-+ let get_value name conv = conv (List.assoc name assocs) in
-+ let gname =
-+ try
-+ get_value "group_name" value_to_string
-+ with _ -> default_group_name
-+ in
-+ let gadmin =
-+ try
-+ get_value "group_admin" value_to_bool
-+ with _ -> true
-+ in
-+ { group_name = gname;
-+ group_admin = gadmin;
-+ }
-+
-+ | _ -> failwith "Options: not a valid group"
-+
-+ let group_to_value group =
-+ Options.Module [
-+ "group_name", string_to_value group.group_name;
-+ "group_admin", bool_to_value group.group_admin;
-+ ]
-+
-+ let t = define_option_class "Groups" value_to_group group_to_value
-+
-+ end
-+
-+let grouplist = define_option users2_section ["groups"]
-+ "The groups that are defined on this core.
-+
-+group_admin = Are members of this group MLDonkey admins?
-+ Only members of this group can change settings and see uploads.
-+"
-+ (list_option GroupOption.t) [system_user_default_group]
-+
-+(*************************************************************************)
-+(* Group database functions *)
-+(*************************************************************************)
-+
-+let user2_groups_iter f =
-+ List.iter f ((List.sort (fun g1 g2 -> compare g1.group_name g2.group_name)) !!grouplist)
-+
-+let update_group name new_group =
-+ let other_groups = List.filter (fun g -> g.group_name <> name) !!grouplist in
-+ grouplist =:=
-+ match new_group with
-+ | None -> other_groups
-+ | Some new_group -> new_group :: other_groups
-+
-+let user2_group_add name admin =
-+ let new_group = {
-+ group_name = name;
-+ group_admin = admin;
-+ } in
-+ update_group name (Some new_group)
-+
-+let user2_group_remove group =
-+ update_group group.group_name None
-+
-+let user2_group_find group =
-+ List.find (fun g -> g.group_name = group) !!grouplist
-+
-+let user2_group_exists group =
-+ List.exists (fun g -> g.group_name = group) !!grouplist
-+
-+let user2_default_group_matches_group dgroup group =
-+ match dgroup with
-+ None -> false
-+ | Some g -> group = g
-+
-+let user2_group_admin group admin =
-+ group.group_admin <- admin
-+
-+(*************************************************************************)
-+(* UserOption *)
-+(*************************************************************************)
-+
- module UserOption = struct
-
- let value_to_user v =
-@@ -65,9 +177,49 @@
- get_value "user_mail" value_to_string
- with _ -> ""
- in
-+ let ucdir =
-+ try
-+ get_value "user_commit_dir" value_to_string
-+ with _ -> ""
-+ in
-+ let umaxdl =
-+ try
-+ get_value "user_max_concurrent_downloads" value_to_int
-+ with _ -> 0
-+ in
-+ let ugroups =
-+ try
-+ let ugl = get_value "user_groups" (value_to_list value_to_string) in
-+ List.map user2_group_find ugl
-+ with Not_found -> [system_user_default_group]
-+ in
-+ let udgroup =
-+ try
-+ match get_value "user_default_group" stringvalue_to_option with
-+ None -> None
-+ | Some udg ->
-+ begin try
-+ let g = user2_group_find udg in
-+ if List.mem g ugroups then
-+ Some g
-+ else begin
-+ lprintf_nl "User %s is not member of group %s, setting user_default_group to None" uname udg;
-+ None
-+ end
-+ with Not_found ->
-+ lprintf_nl "user_default_group %s of user %s does not exist, setting to None" udg uname;
-+ None
-+ end
-+ with Not_found -> Some system_user_default_group
-+ in
- { user_name = uname;
- user_pass = upass;
-- user_mail = umail; }
-+ user_groups = ugroups;
-+ user_default_group = udgroup;
-+ user_mail = umail;
-+ user_commit_dir = ucdir;
-+ user_max_concurrent_downloads = umaxdl;
-+ }
-
- | _ -> failwith "Options: not a valid user"
-
-@@ -75,94 +227,220 @@
- Options.Module [
- "user_name", string_to_value user.user_name;
- "user_pass", string_to_value (Md4.to_string user.user_pass);
-- "user_mail", string_to_value user.user_mail; ]
-+ "user_groups", list_to_value (fun v -> string_to_value v.group_name) user.user_groups;
-+ "user_default_group", option_to_stringvalue (match user.user_default_group with Some g -> Some g.group_name | None -> None);
-+ "user_mail", string_to_value user.user_mail;
-+ "user_commit_dir", string_to_value user.user_commit_dir;
-+ "user_max_concurrent_downloads", int_to_value user.user_max_concurrent_downloads;
-+ ]
-
- let t = define_option_class "Users" value_to_user user_to_value
-
- end
-
--let users_ini = create_options_file "users.ini"
--
--let users_section = file_section users_ini ["Users"] "User accounts on the core"
--let users2_section = file_section users_ini ["Users"] "User accounts on the core (new format)"
--
--let users = define_option users_section ["users"]
-- "Depreciated option, kept for compatibility reasons - used by MLDonkey < 2.7.5"
-- (list_option (tuple2_option (string_option, Md4.option)))
-- []
--
- let userlist = define_option users2_section ["users2"]
- "The users that are defined on this core. The default user is
- called 'admin', and uses an empty password. To create new users,
--login as admin in mldonkey, and use the 'useradd' command."
-- (list_option UserOption.t)
-- [ { user_name = admin_user;
-- user_pass = blank_password;
-- user_mail = "" } ]
-+login as admin in mldonkey, and use the 'useradd' command.
-
--let users2 = Hashtbl.create 10
-+user_groups = Files belonging to one of these groups can be seen by the user.
-+user_default_group = New downloads by this user will belong to this group.
-+user_commit_dir = Commit files to <incoming>/<user_commit_dir>
-+user_mail = Address used to sent confirmation mails after comitting a download
-+user_max_concurrent_downloads = Maximum number of downloads allowed, 0 = unlimited
-+"
-+ (list_option UserOption.t) [admin_user]
-
--let user2_iter f =
-- Hashtbl.iter f users2
-+let users = define_option users_section ["users"]
-+ "Depreciated option, kept for compatibility reasons - used by MLDonkey < 2.7.5"
-+ (list_option (tuple2_option (string_option, Md4.option)))
-+ [admin_user.user_name, blank_password]
-
--let user2_add name pass mail =
-- let u = {
-+(*************************************************************************)
-+(* User database functions *)
-+(*************************************************************************)
-+
-+let user2_users_iter f =
-+ List.iter f ((List.sort (fun u1 u2 -> compare u1.user_name u2.user_name)) !!userlist)
-+
-+let update_user name new_user =
-+ let other_users = List.filter (fun u -> u.user_name <> name) !!userlist in
-+ userlist =:=
-+ match new_user with
-+ | None -> other_users
-+ | Some new_user -> new_user :: other_users
-+
-+let user2_user_add name pass ?(groups = [default_group_name])
-+ ?(default_group = Some default_group_name)
-+ ?(mail = "") ?(commit_dir = "") ?(max_dl = 0) () =
-+ (* shouldn't we warn admin about already existing user ? *)
-+ let groups =
-+ let l = List.map user2_group_find (List.filter user2_group_exists groups) in
-+ if l = [] then [system_user_default_group] else l
-+ in
-+ let default_group =
-+ match default_group with
-+ None -> None
-+ | Some group -> if not (user2_group_exists group) then None else Some (user2_group_find group)
-+ in
-+ let new_user = {
- user_name = name;
- user_pass = pass;
-- user_mail = mail
-+ user_groups = groups;
-+ user_default_group = default_group;
-+ user_mail = mail;
-+ user_commit_dir = commit_dir;
-+ user_max_concurrent_downloads = max_dl;
- } in
-- Hashtbl.replace users2 name u;
-- u
-+ update_user name (Some new_user)
-
--let user2_remove user =
-- Hashtbl.remove users2 user
-+let user2_user_remove user =
-+ update_user user None
-
--let user2_find user =
-- try
-- Hashtbl.find users2 user
-- with Not_found -> failwith (Printf.sprintf "User %s does not exist" user)
-+let user2_user_find user =
-+ List.find (fun u -> u.user_name = user) !!userlist
-
--let user2_password user =
-- try
-- let u = user2_find user in
-- u.user_pass
-- with Not_found -> failwith (Printf.sprintf "User %s does not exist" user)
-+let user2_user_exists user =
-+ List.exists (fun u -> u.user_name = user) !!userlist
-
--let user2_mail user =
-- try
-- let u = user2_find user in
-- u.user_mail
-- with Not_found -> failwith (Printf.sprintf "User %s does not exist" user)
-+(*************************************************************************)
-+(* User database functions / passwords *)
-+(*************************************************************************)
-+
-+let user2_user_password user =
-+ (user2_user_find user).user_pass
-+
-+let user2_user_set_password user pass_string =
-+ user.user_pass <- Md4.string pass_string
-
- let valid_password user pass =
- try
-- user2_password user = Md4.string pass
-- with e -> false
-+ user2_user_password user = Md4.string pass
-+ with Not_found -> false
-
--let empty_password user =
-- try
-- let p = user2_password user in
-- p = blank_password
-- with _ -> false
-+let has_empty_password user =
-+ valid_password user.user_name ""
-+
-+(*************************************************************************)
-+(* User database functions *)
-+(*************************************************************************)
-+
-+let user2_user_set_mail user mail =
-+ user.user_mail <- mail
-+
-+let user2_print_user_dls user =
-+ let dls = user.user_max_concurrent_downloads in
-+ if dls = 0 then "unlimited" else string_of_int dls
-+
-+let user2_user_set_dls user dls =
-+ user.user_max_concurrent_downloads <- dls
-+
-+let user2_user_commit_dir user =
-+ (user2_user_find user).user_commit_dir
-+
-+let user2_user_set_commit_dir user dir =
-+ user.user_commit_dir <- dir
-+
-+(*************************************************************************)
-+(* User/Group database functions *)
-+(*************************************************************************)
-+
-+let sort_groups_by_name gl =
-+ List.sort (fun g1 g2 -> compare g1.group_name g2.group_name) gl
-+
-+let user2_user_groups_iter user f =
-+ List.iter f (sort_groups_by_name user.user_groups)
-+
-+let user2_print_user_groups sep user =
-+ String.concat sep (List.map (fun g -> g.group_name) (sort_groups_by_name user.user_groups))
-+
-+let user2_print_group group =
-+ match group with
-+ None -> "none"
-+ | Some group -> group.group_name
-+
-+let user2_print_user_default_group user =
-+ user2_print_group user.user_default_group
-+
-+let user2_user_set_default_group user group =
-+ user.user_default_group <- group
-+
-+let user2_user_add_group user group =
-+ user.user_groups <- group :: user.user_groups
-+
-+let user2_user_remove_group user group =
-+ user.user_groups <- List.filter ((<>) group) user.user_groups
-+
-+let user2_num_group_members group =
-+ let counter = ref 0 in
-+ user2_users_iter (fun u ->
-+ user2_user_groups_iter u (fun g ->
-+ if g = group then incr counter));
-+ !counter
-+
-+(*************************************************************************)
-+(* Access rights *)
-+(*************************************************************************)
-+
-+let user2_is_admin user =
-+ user.user_name = admin_user.user_name ||
-+ List.exists (fun groupname ->
-+ try
-+ groupname.group_admin
-+ with Not_found -> false)
-+ user.user_groups
-+
-+(* could be expanded later *)
-+let user2_can_view_uploads user =
-+ user2_is_admin user
-+
-+let user2_can_view_file user file_owner file_group =
-+ user2_is_admin user || user = file_owner ||
-+ (match file_group with
-+ | None -> false
-+ | Some file_group -> List.mem file_group user.user_groups)
-+
-+(*************************************************************************)
-+(* Hooks *)
-+(*************************************************************************)
-
- let _ =
- set_after_load_hook users_ini (fun _ ->
-- List.iter (fun user ->
-- ignore (user2_add user.user_name user.user_pass user.user_mail)
-- ) !!userlist;
-- userlist =:= [];
-- if !!users <> [] then begin
-- lprintf_nl "converting %d users to new format" (List.length !!users);
-- List.iter (fun (user,pass) -> ignore (user2_add user pass "")) !!users;
-- users =:= []
-- end
-+ List.iter (fun (user,pass) ->
-+ if not (user2_user_exists user) then begin
-+ user2_user_add user pass ();
-+ lprintf_nl "converted user %s to new format" user
-+ end) !!users;
-+(* clean !!users to avoid saving users more than once *)
-+ users =:= [];
-+(* Security and default checks
-+ - user "admin" must exist, it has hard-coded admin rights independent of group membership
-+ - group "mldonkey" must exist and must have admin status *)
-+ if not (user2_user_exists admin_user.user_name) then
-+ begin
-+ user2_user_add admin_user.user_name blank_password ();
-+ lprintf_nl "SECURITY INFO: user 'admin' has to be present, creating with empty password..."
-+ end;
-+ begin
-+ try
-+ let g = user2_group_find default_group_name in
-+ if not g.group_admin then
-+ begin
-+ user2_group_admin g true;
-+ lprintf_nl "SECURITY INFO: group 'mldonkey' must have admin status, updating..."
-+ end
-+ with Not_found ->
-+ user2_group_add default_group_name true;
-+ lprintf_nl "SECURITY INFO: group 'mldonkey' has to be present, creating with admin rights..."
-+ end
- );
-+
-+(* This code provides backward-compatibility for older MLDonkey clients *)
-+(* reading new user db and copying the values into old user db !!users *)
- set_before_save_hook users_ini (fun _ ->
-- user2_iter (fun _ user ->
-- userlist =:= (user2_find user.user_name) :: !!userlist;
-- users =:= (user.user_name, (user2_password user.user_name)) :: !!users
-- )
-+ user2_users_iter (fun user ->
-+ users =:= (user.user_name, (user2_user_password user.user_name)) :: !!users
-+ )
- );
-- set_after_save_hook users_ini (fun _ ->
-- userlist =:= [];
-- users =:= [])
-+(* clean !!users to avoid saving users more than once *)
-+ set_after_save_hook users_ini (fun _ -> users =:= [])
-Index: src/daemon/common/commonWeb.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonWeb.ml,v
-retrieving revision 1.33
-retrieving revision 1.36
-diff -u -r1.33 -r1.36
---- src/daemon/common/commonWeb.ml 14 Jul 2006 13:24:23 -0000 1.33
-+++ src/daemon/common/commonWeb.ml 15 Nov 2006 12:37:13 -0000 1.36
-@@ -57,7 +57,8 @@
- let kind_record = { f = f; description = descr } in
- file_kinds := (kind, kind_record) :: !file_kinds
-
--let mldonkey_wget url f =
-+
-+let mldonkey_wget_url url f =
- let module H = Http_client in
- let r = {
- H.basic_request with
-@@ -100,27 +101,21 @@
- match !date with
- None -> H.wget r f
- | Some date ->
-- let html_time =
-- begin try
-- let t = Date.time_of_string date in
-- r.H.req_save_to_file_time <- t;
-- Unix.gmtime t
-- with e ->
-- let t = Unix.time () in
-- r.H.req_save_to_file_time <- t;
-- Unix.gmtime t
-- end
-- in
- let file = Filename.concat "web_infos" (Filename.basename r.H.req_url.Url.short_file) in
-+ r.H.req_save_to_file_time <- (begin try
-+ Date.time_of_string date
-+ with e ->
-+ Unix.time ()
-+ end);
- if not (Sys.file_exists file) then
- H.wget r f
- else
- begin
- let file_date = Unix.LargeFile.stat file in
-- let file_time = Unix.gmtime file_date.Unix.LargeFile.st_mtime in
-- if html_time <= file_time then
-+ if r.H.req_save_to_file_time <= file_date.Unix.LargeFile.st_mtime then
- begin
-- lprintf_nl (_b "using local version of %s, HTML header (%s)") file date;
-+ lprintf_nl (_b "using local version of %s (%s), HTML header (%s)")
-+ file (Date.to_full_string file_date.Unix.LargeFile.st_mtime) date;
- (f file : unit)
- end
- else
-@@ -135,6 +130,19 @@
- (Printexc2.to_string e) url
- end
-
-+let mldonkey_wget_shell url f =
-+ let command_urlencoded = Str.string_after url 8 in
-+ let command = Url.decode command_urlencoded in
-+ let filename = Filename.temp_file "wget_" ".tmp" in
-+ Sys.command (Printf.sprintf "%s > %s" command filename);
-+ (f filename : unit)
-+
-+let mldonkey_wget url f =
-+ if Str.string_match (Str.regexp "shell://") url 0 then
-+ mldonkey_wget_shell url f
-+ else
-+ mldonkey_wget_url url f
-+
- let load_url can_fail kind url =
- let f =
- try
-@@ -184,13 +192,47 @@
-
- let rss_feeds = Hashtbl.create 10
-
--
- let _ =
- add_web_kind "rss" "Syndication feeds to get periodically updated data"
- (fun url filename ->
- lprintf_nl (_b "parsing feed %s (rss)") url;
-- let c = Rss.channel_of_file filename in
-- (try Sys.remove filename with _ -> ());
-+ let c =
-+ (try
-+ let rss_c = Rss.channel_of_file filename in
-+ (try Sys.remove filename with _ -> ());
-+ rss_c
-+ with Xml.Error _ ->
-+ lprintf_nl (_b "found buggy feed, preprocessing with %s and trying again") !!rss_preprocessor;
-+ (try
-+ let pipe_out, pipe_in = Unix.pipe () in
-+ let pid = Unix.create_process !!rss_preprocessor [| !!rss_preprocessor; filename |]
-+ Unix.stdin pipe_in pipe_in in
-+ Unix.close pipe_in;
-+ let output = Buffer.create 1024 in
-+ let buffersize = 1024 in
-+ let buffer = String.create buffersize in
-+ (try
-+ while true do
-+ let nread = Unix.read pipe_out buffer 0 buffersize in
-+ if nread = 0 then raise End_of_file;
-+ Buffer.add_substring output buffer 0 nread
-+ done
-+ with
-+ | End_of_file -> ()
-+ | Unix.Unix_error (code, f, arg) ->
-+ lprintf_nl "%s failed: %s" !!rss_preprocessor (Unix.error_message code));
-+ (try Unix.close pipe_out with _ -> ());
-+ (try Sys.remove filename with _ -> ());
-+ let _pid, _ = Unix.waitpid [] pid in
-+ let result = Buffer.contents output in
-+ if result = "" then begin
-+ lprintf_nl (_b "%s produced empty content for feed %s, program missing?") !!rss_preprocessor url;
-+ raise Not_found
-+ end;
-+ Rss.channel_of_string result
-+ with Unix.Unix_error (code, f, arg) ->
-+ lprintf_nl (_b "%s failed: %s") !!rss_preprocessor (Unix.error_message code); raise Not_found))
-+ in
- let feed =
- try Hashtbl.find rss_feeds url with
- Not_found ->
-Index: src/daemon/common/guiDecoding.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/common/guiDecoding.ml,v
-retrieving revision 1.59
-retrieving revision 1.65
-diff -u -r1.59 -r1.65
---- src/daemon/common/guiDecoding.ml 1 Sep 2006 16:22:14 -0000 1.59
-+++ src/daemon/common/guiDecoding.ml 14 Nov 2006 18:42:59 -0000 1.65
-@@ -506,13 +506,29 @@
- let get_int_pos s pos =
- get_int s pos, pos + 4
-
--let get_sub_files s pos =
-+let get_sub_files proto s pos =
- get_list (fun s pos ->
- let name, pos = get_string s pos in
- let size, pos = get_int64 s pos, pos+8 in
-- (name, size, Some ""), pos
-+ let magic, pos =
-+ if proto > 40 then
-+ get_string s pos
-+ else
-+ "", pos
-+ in
-+ (name, size, Some magic), pos
- ) s pos
-
-+let get_file_comments proto s pos =
-+ get_list (fun s pos ->
-+ let ip, pos = get_ip2 proto s pos in
-+ let name, pos = get_string s pos in
-+ let rating, pos = get_uint8 s pos, pos+1 in
-+ let comment, pos = get_string s pos in
-+ (ip, name, rating, comment), pos
-+ ) s pos
-+
-+
- let get_file proto s pos =
- let num = get_int s pos in
- let net = get_int s (pos+4) in
-@@ -557,10 +573,31 @@
- in
- let sub_files, pos =
- if proto > 35 then
-- get_sub_files s pos
-+ get_sub_files proto s pos
- else [], pos
- in
--
-+ let magic, pos =
-+ if proto > 40 then
-+ let ms, pos = get_string s pos
-+ in Some ms, pos
-+ else
-+ Some "", pos
-+ in
-+ let comments, pos =
-+ if proto > 40 then
-+ get_file_comments proto s pos
-+ else [], pos
-+ in
-+ let user, pos =
-+ if proto > 40
-+ then get_string s pos
-+ else "", pos
-+ in
-+ let group, pos =
-+ if proto > 40
-+ then get_string s pos
-+ else "", pos
-+ in
- (*
- assert (num = file_info_test.file_num);
- assert (net = file_info_test.file_network);
-@@ -609,6 +646,11 @@
- file_priority = priority;
- file_uids = uids;
- file_sub_files = sub_files;
-+ file_magic = magic;
-+ file_comments = comments;
-+ file_user = user;
-+ file_group = group;
-+ file_release = false;
- }, pos
-
- let get_host_state proto s pos =
-@@ -709,12 +751,15 @@
- server_banner = "";
- server_users = None;
- server_preferred = preferred;
-+ server_master = false;
- server_version = ve;
- server_max_users = ma;
- server_lowid_users = lo;
- server_soft_limit = so;
- server_hard_limit = ha;
- server_ping = pi;
-+ server_published_files = 0;
-+ server_features = None;
- }, pos
-
- let get_client_type s pos =
-@@ -768,6 +813,7 @@
- client_files = None;
- client_connect_time = 0;
- client_software = "";
-+ client_os = None;
- client_release = "";
- client_emulemod = "";
- client_downloaded = zero;
-@@ -826,6 +872,7 @@
- client_files = None;
- client_connect_time = connect_time;
- client_software = software;
-+ client_os = None;
- client_release = release;
- client_emulemod = emulemod;
- client_downloaded = downloaded;
-@@ -940,6 +987,7 @@
- shared_requests = requests;
- shared_uids = [];
- shared_sub_files = [];
-+ shared_magic = Some "";
- }
-
- let get_shared_info_version_10 proto s pos =
-@@ -957,9 +1005,16 @@
- in
- let sub_files, pos =
- if proto > 36 then
-- get_sub_files s pos
-+ get_sub_files proto s pos
- else [], pos
- in
-+ let magic, pos =
-+ if proto > 40 then
-+ let ms, pos = get_string s (pos) in
-+ Some ms, pos
-+ else
-+ Some "", pos
-+ in
- {
- shared_num = num;
- shared_network = network;
-@@ -969,6 +1024,7 @@
- shared_requests = requests;
- shared_uids = uids;
- shared_sub_files = sub_files;
-+ shared_magic = magic;
- }
-
-
-@@ -998,7 +1054,7 @@
- | 5
- | 52 ->
- if proto < 14 then
-- let pass = fst (get_string s 2) in Password (CommonUserDb.admin_user, pass)
-+ let pass = fst (get_string s 2) in Password (CommonUserDb.admin_user.CommonTypes.user_name, pass)
- else
- let pass,pos = get_string s 2 in
- let login,pos = get_string s pos in
-@@ -1262,6 +1318,10 @@
- let b = get_bool s 6 in
- ServerSetPreferred (num, b)
-
-+ | 68 ->
-+ let num = get_int s 2 in
-+ GetStats num
-+
- | _ ->
- lprintf_nl "FROM GUI:Unknown message %d" opcode;
- raise FromGuiMessageNotImplemented
-Index: src/daemon/common/guiEncoding.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/common/guiEncoding.ml,v
-retrieving revision 1.57
-retrieving revision 1.59
-diff -u -r1.57 -r1.59
---- src/daemon/common/guiEncoding.ml 1 Sep 2006 16:22:14 -0000 1.57
-+++ src/daemon/common/guiEncoding.ml 31 Oct 2006 15:40:05 -0000 1.59
-@@ -542,10 +542,25 @@
- buf_int8 buf 18;
- buf_string buf x
-
--let buf_sub_files buf l =
-- buf_list buf (fun buf (name, size, _) ->
-+let magic_string m =
-+ match m with
-+ Some s -> s
-+ | None -> ""
-+
-+let buf_sub_files proto buf l =
-+ buf_list buf (fun buf (name, size, magic) ->
- buf_string buf name;
-- buf_int64 buf size
-+ buf_int64 buf size;
-+ if proto > 40 then
-+ buf_string buf (magic_string magic)
-+ ) l
-+
-+let buf_file_comments proto buf l =
-+ buf_list buf (fun buf (ip, name, rating, comment) ->
-+ buf_ip2 proto buf ip;
-+ buf_string buf name;
-+ buf_int8 buf rating;
-+ buf_string buf comment;
- ) l
-
- let buf_file proto buf f =
-@@ -587,7 +602,13 @@
- if proto > 30 then
- buf_list buf buf_uid f.file_uids;
- if proto > 35 then
-- buf_sub_files buf f.file_sub_files
-+ buf_sub_files proto buf f.file_sub_files;
-+ if proto > 40 then begin
-+ buf_string buf (magic_string f.file_magic);
-+ buf_file_comments proto buf f.file_comments;
-+ buf_string buf f.file_user;
-+ buf_string buf f.file_group;
-+ end
-
- let buf_addr proto buf addr =
- (match addr with
-@@ -645,7 +666,7 @@
- buf_int buf c.client_chat_port
- end else
- begin
-- buf_string buf c.client_software;
-+ buf_string buf (client_software_short c.client_software c.client_os);
- buf_int64 buf c.client_downloaded;
- buf_int64 buf c.client_uploaded;
- (match c.client_upload with
-@@ -727,8 +748,23 @@
- else
- buf_list buf buf_uid s.shared_uids;
- if proto > 36 then
-- buf_sub_files buf s.shared_sub_files
--
-+ buf_sub_files proto buf s.shared_sub_files;
-+ if proto > 40 then
-+ buf_string buf (magic_string s.shared_magic)
-+
-+let buf_stat_info proto buf n =
-+ buf_string buf n.string_long;
-+ buf_string buf n.string_short;
-+ buf_int buf n.seen;
-+ buf_int buf n.banned;
-+ buf_int buf n.filerequest;
-+ buf_int64 buf n.download;
-+ buf_int64 buf n.upload
-+
-+let buf_stat_info_list proto buf (s,i,l) =
-+ buf_string buf s;
-+ buf_int buf i;
-+ buf_list2 proto buf buf_stat_info l
-
- (***************
-
-@@ -1004,6 +1040,13 @@
-
- | GiftServerAttach _ -> assert false
- | GiftServerStats _ -> assert false
-+
-+ | Stats (num, l) ->
-+ let proto = proto.(59) in
-+ buf_opcode buf 59;
-+ buf_int buf num;
-+ buf_list2 proto buf buf_stat_info_list l
-+
- with e ->
- lprintf "GuiEncoding.to_gui: Exception %s\n"
- (Printexc2.to_string e)
-@@ -1217,6 +1260,9 @@
- buf_opcode buf 67;
- buf_int buf num;
- buf_bool buf preferred
-+ | GetStats n ->
-+ buf_opcode buf 68;
-+ buf_int buf n
-
- with e ->
- lprintf "GuiEncoding.from_gui: Exception %s\n"
-Index: src/daemon/common/guiProto.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/common/guiProto.ml,v
-retrieving revision 1.24
-retrieving revision 1.25
-diff -u -r1.24 -r1.25
---- src/daemon/common/guiProto.ml 16 Jan 2006 16:05:14 -0000 1.24
-+++ src/daemon/common/guiProto.ml 23 Sep 2006 20:29:46 -0000 1.25
-@@ -29,9 +29,9 @@
-
- let gui_extension_poll = 1
-
--let to_gui_last_opcode = 58
--let from_gui_last_opcode = 67
--let best_gui_version = 40
-+let to_gui_last_opcode = 59
-+let from_gui_last_opcode = 68
-+let best_gui_version = 41
-
- (* I will try to report all changes to the protocol here: send me patches
- if I don't !
-@@ -166,6 +166,7 @@
- (* Understood by core protocol 32 *)
- | ServerRename of (int * string)
- | ServerSetPreferred of (int * bool)
-+| GetStats of int
-
- type to_gui =
- (* This message is the first message sent by the core *)
-@@ -233,6 +234,7 @@
-
- | GiftServerAttach of string * string
- | GiftServerStats of (string * string * string * string) list
-+| Stats of int * (string * int * network_stat_info list) list
-
-
- let string_of_from_gui t =
-@@ -311,6 +313,7 @@
-
- | ServerRename _ -> "ServerRename"
- | ServerSetPreferred _ -> "ServerSetPreferred"
-+ | GetStats _ -> "GetStats"
-
- let string_of_to_gui t =
- match t with
-@@ -380,6 +383,7 @@
-
- | GiftServerAttach _ -> "GiftServerAttach"
- | GiftServerStats _ -> "GiftServerStats"
-+ | Stats _ -> "Stats"
-
- type gui_record = {
- mutable gui_num : int;
-Index: src/daemon/common/guiTypes.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/common/guiTypes.ml,v
-retrieving revision 1.29
-retrieving revision 1.34
-diff -u -r1.29 -r1.34
---- src/daemon/common/guiTypes.ml 1 Sep 2006 16:22:14 -0000 1.29
-+++ src/daemon/common/guiTypes.ml 14 Nov 2006 18:42:59 -0000 1.34
-@@ -136,6 +136,11 @@
- mutable file_priority : int;
- mutable file_uids : Uid.t list;
- mutable file_sub_files : (string * int64 * string option) list;
-+ mutable file_magic : string option;
-+ mutable file_comments : (Ip.t * string * int * string) list;
-+ mutable file_user : string;
-+ mutable file_group : string;
-+ mutable file_release : bool;
- }
-
- type user_info = {
-@@ -165,12 +170,15 @@
- mutable server_users : int list option;
- mutable server_banner : string;
- mutable server_preferred : bool;
-+ mutable server_master : bool;
- mutable server_version : string;
- mutable server_max_users : int64;
- mutable server_soft_limit : int64;
- mutable server_hard_limit : int64;
- mutable server_lowid_users : int64;
- mutable server_ping : int;
-+ mutable server_published_files : int;
-+ mutable server_features : string option;
-
- }
-
-@@ -208,6 +216,7 @@
- mutable client_chat_port : int;
- mutable client_connect_time : int;
- mutable client_software : string;
-+ mutable client_os : string option;
- mutable client_release : string;
- mutable client_emulemod : string;
- mutable client_downloaded : int64;
-@@ -240,9 +249,32 @@
- mutable shared_requests : int;
- mutable shared_uids : Uid.t list; (* net file UID *)
- mutable shared_sub_files : (string * int64 * string option) list;
-+ mutable shared_magic : string option;
- }
-
-
-+let osinfo_short i =
-+ match i with
-+ Some s when
-+ s = "linux" ||
-+ s = "netbsd" ||
-+ s = "macos" ||
-+ s = "freebsd" ||
-+ s = "windows" -> Some (String.sub s 0 1)
-+ | _ -> i
-+
-+let client_software_short software os =
-+ software ^
-+ match osinfo_short os with
-+ Some s -> "/" ^ s
-+ | None -> ""
-+
-+let client_software software os =
-+ software ^
-+ match os with
-+ Some s -> "/" ^ s
-+ | None -> ""
-+
- let add_file tree dirname r =
- let path = Filename2.path_of_filename dirname in
-
-@@ -326,5 +358,10 @@
- file_priority = 0;
- file_uids = [];
- file_sub_files = [];
-+ file_magic = Some "";
-+ file_comments = [];
-+ file_user = "";
-+ file_group = "";
-+ file_release = false;
- }
-
-Index: src/daemon/driver/driverCommands.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/driver/driverCommands.ml,v
-retrieving revision 1.175
-retrieving revision 1.199
-diff -u -r1.175 -r1.199
---- src/daemon/driver/driverCommands.ml 16 Sep 2006 09:38:59 -0000 1.175
-+++ src/daemon/driver/driverCommands.ml 21 Nov 2006 22:34:33 -0000 1.199
-@@ -325,7 +325,7 @@
- ), ":\t\t\t\t\t$bclose telnet$n";
-
- "kill", Arg_none (fun o ->
-- if user2_is_admin o.conn_user.ui_user_name then
-+ if user2_is_admin o.conn_user.ui_user then
- begin
- CommonInteractive.clean_exit 0;
- _s "exit"
-@@ -334,12 +334,18 @@
- _s "You are not allowed to kill MLDonkey"
- ), ":\t\t\t\t\t$bsave and kill the server$n";
-
-- "urladd", Arg_two (fun kind url o ->
-- web_infos_add kind 1 url;
-+ "urladd", Arg_multiple (fun args o ->
-+ let (kind, url, period) = match args with
-+ | [kind; url; period] -> kind, url, int_of_string period
-+ | [kind; url] -> kind, url, 0
-+ | _ -> failwith "Bad number of arguments"
-+ in
-+ web_infos_add kind period url;
- CommonWeb.load_url true kind url;
- "url added to web_infos. downloading now"
-- ), "<kind> <url> :\t\t\tload this file from the web\n"
-- ^"\t\t\t\t\tkind is either server.met (if the downloaded file is a server.met)";
-+ ), "<kind> <url> [<period>]:\t\tload this file from the web\n"
-+ ^"\t\t\t\t\tkind is either server.met (if the downloaded file is a server.met)\n"
-+ ^"\t\t\t\t\tperiod is the period between updates (in hours, default 0 = only loaded at startup)";
-
- "urlremove", Arg_one (fun url o ->
- if web_infos_exists url then
-@@ -400,7 +406,7 @@
- client_print c o;
- if use_html_mods o then
- html_mods_td buf ([
-- ("", "sr", i.client_software);
-+ (client_software i.client_software i.client_os, "sr", client_software_short i.client_software i.client_os);
- ("", "sr", i.client_release);
- ] @
- (if !!emule_mods_count then [("", "sr", i.client_emulemod)] else []));
-@@ -736,6 +742,16 @@
- end
- ) !!servers;
- Printf.sprintf (_b "Removed %d blocked servers") !counter
-+ | ["disc"] ->
-+ Intmap.iter (fun _ s ->
-+ match server_state s with
-+ NotConnected _ ->
-+ begin
-+ server_remove s;
-+ incr counter
-+ end
-+ | _ -> ()) !!servers;
-+ Printf.sprintf (_b "Removed %d disconnected servers") !counter
- | _ ->
- List.iter (fun num ->
- let num = int_of_string num in
-@@ -743,7 +759,7 @@
- server_remove s
- ) args;
- Printf.sprintf (_b"%d servers removed") (List.length args)
-- ), "<server numbers> :\t\t\tremove server (use 'all' for all servers, 'blocked' for all IP blocked servers)";
-+ ), "<server numbers|all|blocked|disc> :\tremove server(s) ('all'/'blocked'/'disc' = all/IP blocked/disconnected servers)";
-
- "server_banner", Arg_one (fun num o ->
- let num = int_of_string num in
-@@ -754,6 +770,23 @@
- ""
- ), "<num> :\t\t\tprint banner of connected server <num>";
-
-+ "server_shares", Arg_one (fun num o ->
-+ if user2_is_admin o.conn_user.ui_user then
-+ let s = server_find (int_of_string num) in
-+ (match server_state s with
-+ Connected _ -> let list = ref [] in
-+ List.iter (fun f ->
-+ match file_shared f with
-+ None -> ()
-+ | Some sh -> list := (as_shared_impl sh) :: !list)
-+ (server_published s);
-+ print_upstats o !list (Some s)
-+ | _ -> ()
-+ )
-+ else print_command_result o o.conn_buf "You are not allowed to use this command";
-+ _s ""
-+ ), "<num> :\t\t\tshow list of files published on server <num>";
-+
- "c", Arg_multiple (fun args o ->
- let buf = o.conn_buf in
- match args with
-@@ -959,7 +992,7 @@
- let num = int_of_string num in
-
- if num > 0 then (* we want to disable upload for a short time *)
-- let num = mini !CommonUploads.upload_credit num in
-+ let num = min !CommonUploads.upload_credit num in
- CommonUploads.has_upload := !CommonUploads.has_upload + num;
- CommonUploads.upload_credit := !CommonUploads.upload_credit - num;
- Printf.sprintf
-@@ -970,7 +1003,7 @@
- if num < 0 && !CommonUploads.has_upload > 0 then
- (* we want to restart upload probably *)
- let num = - num in
-- let num = mini num !CommonUploads.has_upload in
-+ let num = min num !CommonUploads.has_upload in
- CommonUploads.has_upload := !CommonUploads.has_upload - num;
- CommonUploads.upload_credit := !CommonUploads.upload_credit + num;
- Printf.sprintf
-@@ -1014,13 +1047,31 @@
- Printf.bprintf buf "\\</tr\\>\\</table\\>\\</td\\>\\</tr\\>\\</table\\>\\</div\\>";
-
- Printf.bprintf buf "\\<script type=\\\"text/javascript\\\"\\>window.parent.document.title='(D:%.1f) (U:%.1f) | %s | %s'\\</script\\>"
-- dlkbs ulkbs o.conn_user.ui_user_name (CommonGlobals.version ())
-+ dlkbs ulkbs o.conn_user.ui_user.user_name (CommonGlobals.version ())
- end
- else
- DriverInteractive.print_bw_stats buf;
- ""
- ), ":\t\t\t\tprint current bandwidth stats";
-
-+ "bw_toggle", Arg_none (fun o ->
-+ let buf = o.conn_buf in
-+ if user2_is_admin o.conn_user.ui_user then begin
-+ let ul_bkp = !!max_hard_upload_rate_2 in
-+ let dl_bkp = !!max_hard_download_rate_2 in
-+ max_hard_upload_rate_2 =:= !!max_hard_upload_rate;
-+ max_hard_download_rate_2 =:= !!max_hard_download_rate;
-+ max_hard_upload_rate =:= ul_bkp;
-+ max_hard_download_rate =:= dl_bkp;
-+ print_command_result o buf (Printf.sprintf
-+ "new upload rate: %d | new download rate: %d"
-+ !!max_hard_upload_rate !!max_hard_download_rate)
-+ end
-+ else
-+ print_command_result o buf "You are not allowed to toggle bandwidth";
-+ ""
-+ ), ":\t\t\t\ttoggle between the two rate sets";
-+
- "stats", Arg_none (fun o ->
- let buf = o.conn_buf in
- CommonInteractive.network_display_stats buf o;
-@@ -1053,16 +1104,43 @@
- "!", Arg_multiple (fun arg o ->
- if !!allow_any_command then
- match arg with
-- c :: tail ->
-- let args = String2.unsplit tail ' ' in
-+ c :: args ->
- let cmd = try List.assoc c !!allowed_commands with Not_found -> c in
-- let tmp = Filename.temp_file "com" ".out" in
-- let ret = Sys.command (Printf.sprintf "%s %s > %s"
-- cmd args tmp) in
-- let output = File.to_string tmp in
-- Sys.remove tmp;
-- Printf.sprintf (_b "%s\n---------------- Exited with code %d") output ret
-- | _ -> _s "no command given"
-+ (try
-+ let pipe_out, pipe_in = Unix.pipe () in
-+ let pid = Unix.create_process cmd
-+ (Array.of_list (Filename2.basename c :: args))
-+ Unix.stdin pipe_in pipe_in in
-+ Unix.close pipe_in;
-+ (* can't close pipe_out in the already forked+executed process... *)
-+ let output = Buffer.create 1024 in
-+ let buffersize = 1024 in
-+ let buffer = String.create buffersize in
-+ (try
-+ while true do
-+ let nread = Unix.read pipe_out buffer 0 buffersize in
-+ if nread = 0 then raise End_of_file;
-+ Buffer.add_substring output buffer 0 nread
-+ done
-+ with
-+ | End_of_file -> ()
-+ | Unix.Unix_error (code, f, arg) ->
-+ lprintf_nl "%s failed%s: %s" f (if arg = "" then "" else " on " ^ arg) (Unix.error_message code));
-+ (try Unix.close pipe_out with _ -> ());
-+ let _pid, status = Unix.waitpid [] pid in
-+ Printf.sprintf (_b "%s\n---------------- %s")
-+ (Buffer.contents output)
-+ (match status with
-+ | Unix.WEXITED exitcode ->
-+ Printf.sprintf "Exited with code %d" exitcode
-+ | Unix.WSIGNALED signal ->
-+ Printf.sprintf "Was killed by signal %d" signal
-+ | Unix.WSTOPPED signal -> (* does it matter for us ? *)
-+ Printf.sprintf "Was stopped by signal %d" signal)
-+
-+ with Unix.Unix_error (code, f, arg) ->
-+ Printf.sprintf "%s failed%s: %s" f (if arg = "" then "" else " on " ^ arg) (Unix.error_message code))
-+ | [] -> _s "no command given"
- else
- match arg with
- [arg] ->
-@@ -1100,17 +1178,44 @@
- ) , ":\t\t\t\tprint all networks";
-
- "enable", Arg_one (fun num o ->
-- let n = network_find_by_num (int_of_string num) in
-- network_enable n;
-- _s "network enabled"
-+ let buf = o.conn_buf in
-+ if user2_is_admin o.conn_user.ui_user then
-+ begin
-+ let n = network_find_by_num (int_of_string num) in
-+ network_enable n;
-+ print_command_result o buf "network enabled"
-+ end
-+ else
-+ print_command_result o buf "You are not allowed to enable networks";
-+ _s ""
- ) , "<num> :\t\t\t\tenable a particular network";
-
- "disable", Arg_one (fun num o ->
-- let n = network_find_by_num (int_of_string num) in
-- network_disable n;
-- _s "network disabled"
-+ let buf = o.conn_buf in
-+ if user2_is_admin o.conn_user.ui_user then
-+ begin
-+ let n = network_find_by_num (int_of_string num) in
-+ network_disable n;
-+ print_command_result o buf "network disabled"
-+ end
-+ else
-+ print_command_result o buf "You are not allowed to disable networks";
-+ _s ""
- ) , "<num> :\t\t\t\tdisable a particular network";
-
-+ "porttest", Arg_none (fun o ->
-+ let buf = o.conn_buf in
-+ networks_iter (fun n ->
-+ match network_porttest_result n with
-+ PorttestNotAvailable -> ()
-+ | _ -> network_porttest_start n);
-+ if o.conn_output = HTML then
-+ Printf.bprintf buf "Click this \\<a href=\\\"porttest\\\"\\>link\\</a\\> to see results"
-+ else
-+ Printf.bprintf buf "Test started, you need a HTML browser to display results";
-+ ""
-+ ) , ":\t\t\t\tstart network porttest";
-+
- ]
-
- (*************************************************************************)
-@@ -1301,7 +1406,7 @@
- begin
- let r = List.hd !forceable_download in
- CommonNetwork.networks_iter (fun n ->
-- ignore(n.op_network_download r));
-+ ignore (n.op_network_download r o.conn_user.ui_user));
-
- let output = (if o.conn_output = HTML then begin
- let buf = Buffer.create 100 in
-@@ -1334,7 +1439,7 @@
- [
-
- "set", Arg_two (fun name value o ->
-- if user2_is_admin o.conn_user.ui_user_name then begin
-+ if user2_is_admin o.conn_user.ui_user then begin
- try
- try
- CommonInteractive.set_fully_qualified_options name value;
-@@ -1371,7 +1476,7 @@
- if use_html_mods o then begin
-
- if !!html_mods_use_js_helptext then
-- Printf.bprintf buf "\\<div id=\\\"object1\\\" style=\\\"position:absolute; background-color:FFFFDD;color:black;border-color:black;border-width:20;font-size:8pt; visibility:show; left:25px; top:-100px; z-index:+1\\\" onmouseover=\\\"overdiv=1;\\\" onmouseout=\\\"overdiv=0; setTimeout(\\\'hideLayer()\\\',1000)\\\"\\>\\&nbsp;\\</div\\>";
-+ Printf.bprintf buf "\\<div id=\\\"object1\\\" style=\\\"position:absolute; background-color:#FFFFDD;color:black;border-color:black;border-width:20px;font-size:8pt; visibility:visible; left:25px; top:-100px; z-index:+1\\\" onmouseover=\\\"overdiv=1;\\\" onmouseout=\\\"overdiv=0; setTimeout(\\\'hideLayer()\\\',1000)\\\"\\>\\&nbsp;\\</div\\>";
-
- Printf.bprintf buf "\\<div class=\\\"friends\\\"\\>\\<table class=main cellspacing=0 cellpadding=0\\>
- \\<tr\\>\\<td\\>
-@@ -1386,7 +1491,7 @@
- \\</tr\\>\\</table\\>
- \\</td\\>\\</tr\\>
- \\<tr\\>\\<td\\>"
--(if (user2_is_admin o.conn_user.ui_user_name) then
-+(if (user2_is_admin o.conn_user.ui_user) then
- "\\<td nowrap title=\\\"Show users Tab where you can add/remove Users\\\" class=\\\"fbig fbigpad\\\"\\>\\<a onclick=\\\"javascript:window.location.href='submit?q=users'\\\"\\>Users\\</a\\>\\</td\\>"
- else "");
-
-@@ -1406,7 +1511,7 @@
-
- Printf.bprintf buf "\\</td\\>\\</tr\\>\\<tr\\>\\<td\\>\\<table cellspacing=0 cellpadding=0 width=100%%\\>\\<tr\\>\\<td class=downloaded width=100%%\\>\\</td\\>
- \\<td nowrap title=\\\"Toggle option helptext from javascript popup to html table\\\" class=\\\"fbig fbigb pr fbigpad\\\"\\>
--\\<a onclick=\\\"javascript: {parent.fstatus.location.href='submit?q=set+html_mods_use_js_helptext+%s'; setTimeout('window.location.replace(window.location.href)',1000);return true;}\\\"\\>Toggle js_helptext\\</a\\>
-+\\<a onclick=\\\"javascript: {parent.fstatus.location.href='submit?q=set+html_mods_use_js_helptext+%s'; setTimeout('window.location.replace(window.location.href)',1000);return true;}\\\"\\>toggle js_helptext\\</a\\>
- \\</td\\>\\</tr\\>\\</table\\>\\</td\\>\\</tr\\>\\</table\\>\\</div\\>\\</br\\>" (if !!html_mods_use_js_helptext then "false" else "true");
-
- html_mods_table_one_row buf "downloaderTable" "downloaders" [
-@@ -1461,7 +1566,7 @@
- let mtabs = ref 1 in
-
- if !!html_mods_use_js_helptext then
-- Printf.bprintf buf "\\<div id=\\\"object1\\\" style=\\\"position:absolute; background-color:FFFFDD;color:black;border-color:black;border-width:20;font-size:8pt; visibility:show; left:25px; top:-100px; z-index:+1\\\" onmouseover=\\\"overdiv=1;\\\" onmouseout=\\\"overdiv=0; setTimeout(\\\'hideLayer()\\\',1000)\\\"\\>\\&nbsp;\\</div\\>";
-+ Printf.bprintf buf "\\<div id=\\\"object1\\\" style=\\\"position:absolute; background-color:#FFFFDD;color:black;border-color:black;border-width:20px;font-size:8pt; visibility:visible; left:25px; top:-100px; z-index:+1\\\" onmouseover=\\\"overdiv=1;\\\" onmouseout=\\\"overdiv=0; setTimeout(\\\'hideLayer()\\\',1000)\\\"\\>\\&nbsp;\\</div\\>";
-
- Printf.bprintf buf "\\<div class=\\\"vo\\\"\\>\\<table class=main cellspacing=0 cellpadding=0\\>
- \\<tr\\>\\<td\\>
-@@ -1531,12 +1636,13 @@
- strings_of_option global_login;
- strings_of_option set_client_ip;
- strings_of_option force_client_ip;
-- strings_of_option run_as_user;
-- strings_of_option run_as_useruid;
- strings_of_option max_upload_slots;
-+ strings_of_option max_release_slots;
- strings_of_option dynamic_slots;
- strings_of_option max_hard_upload_rate;
- strings_of_option max_hard_download_rate;
-+ strings_of_option max_hard_upload_rate_2;
-+ strings_of_option max_hard_download_rate_2;
- strings_of_option max_opened_connections;
- strings_of_option max_indirect_connections;
- strings_of_option max_connections_per_second;
-@@ -1560,16 +1666,16 @@
- strings_of_option html_mods_use_relative_availability;
- strings_of_option html_mods_human_readable;
- strings_of_option html_mods_vd_network;
-- strings_of_option html_mods_vd_comments;
- strings_of_option html_mods_vd_active_sources;
- strings_of_option html_mods_vd_age;
-+ strings_of_option html_mods_vd_user;
-+ strings_of_option html_mods_vd_group;
- strings_of_option html_mods_vd_last;
- strings_of_option html_mods_vd_prio;
- strings_of_option html_mods_show_pending;
- strings_of_option html_mods_load_message_file;
- strings_of_option html_mods_max_messages;
- strings_of_option html_mods_bw_refresh_delay;
-- strings_of_option use_html_frames;
- strings_of_option html_frame_border;
- strings_of_option html_checkbox_vd_file_list;
- strings_of_option html_checkbox_search_file_list;
-@@ -1598,6 +1704,9 @@
- strings_of_option html_mods_vd_gfx_mean;
- strings_of_option html_mods_vd_gfx_transparent;
- strings_of_option html_mods_vd_gfx_h;
-+ strings_of_option html_mods_vd_gfx_h_dynamic;
-+ strings_of_option html_mods_vd_gfx_h_grid_time;
-+ strings_of_option html_mods_vd_gfx_subgrid;
- strings_of_option html_mods_vd_gfx_x_size;
- strings_of_option html_mods_vd_gfx_y_size;
- strings_of_option html_mods_vd_gfx_tag;
-@@ -1702,8 +1811,10 @@
- | 8 ->
- [
- strings_of_option term_ansi;
-- strings_of_option enable_user_config;
-+ strings_of_option run_as_user;
-+ strings_of_option run_as_useruid;
- strings_of_option messages_filter;
-+ strings_of_option comments_filter;
- strings_of_option max_displayed_results;
- strings_of_option max_name_len;
- strings_of_option max_filenames;
-@@ -1740,7 +1851,7 @@
- \\<select id=\\\"modsStyle\\\" name=\\\"modsStyle\\\"
- style=\\\"padding: 0px; font-size: 10px; font-family: verdana\\\" onchange=\\\"this.form.submit()\\\"\\>
- \\<option value=\\\"0\\\"\\>style/theme\n"
--(if (user2_is_admin o.conn_user.ui_user_name) then
-+(if (user2_is_admin o.conn_user.ui_user) then
- "\\<td nowrap title=\\\"Show users Tab where you can add/remove Users\\\" class=\\\"fbig fbigb\\\"\\>\\<a onclick=\\\"javascript:window.location.href='submit?q=users'\\\"\\>Users\\</a\\>\\</td\\>"
- else "");
-
-@@ -1762,7 +1873,7 @@
- \\<td class=downloaded width=100%%\\>\\</td\\>
- \\<td nowrap title=\\\"Change to simple Webinterface without html_mods\\\" class=\\\"fbig fbigb fbigpad\\\"\\>\\<a onclick=\\\"javascript:window.location.href='submit?q=html_mods'\\\"\\>toggle html_mods\\</a\\>\\</td\\>
- \\<td nowrap title=\\\"Toggle option helptext from javascript popup to html table\\\" class=\\\"fbig fbigb pr fbigpad\\\"\\>
--\\<a onclick=\\\"javascript: {parent.fstatus.location.href='submit?q=set+html_mods_use_js_helptext+%s'; setTimeout('window.location.replace(window.location.href)',1000);return true;}\\\"\\>Toggle js_helptext\\</a\\>
-+\\<a onclick=\\\"javascript: {parent.fstatus.location.href='submit?q=set+html_mods_use_js_helptext+%s'; setTimeout('window.location.replace(window.location.href)',1000);return true;}\\\"\\>toggle js_helptext\\</a\\>
- \\</td\\>\\</tr\\>\\</table\\>\\</td\\>\\</tr\\>\\</table\\>\\</div\\>\\</br\\>" (if !!html_mods_use_js_helptext then "false" else "true");
- html_mods_table_one_row buf "downloaderTable" "downloaders" [
- ("", "srh", "!! press ENTER to send changes to core !!"); ];
-@@ -1782,7 +1893,7 @@
- \\<table cellspacing=0 cellpadding=0 width=100%%\\>\\<tr\\>
- \\<td class=downloaded width=100%%\\>\\</td\\>
- \\<td nowrap class=\\\"fbig pr\\\"\\>\\<a onclick=\\\"javascript: {
-- var getdir = prompt('Input: <kind> <URL>','server.met URL')
-+ var getdir = prompt('Input: <kind> <URL> [<period>]','server.met URL')
- parent.fstatus.location.href='submit?q=urladd+' + encodeURIComponent(getdir);
- setTimeout('window.location.reload()',1000);
- }\\\"\\>Add URL\\</a\\>
-@@ -1988,6 +2099,9 @@
- Printf.bprintf buf "st_uid %d\n" s.Unix.st_uid;
- Printf.bprintf buf "st_gid %d\n" s.Unix.st_gid;
- Printf.bprintf buf "st_size %d\n" s.Unix.st_size;
-+ Printf.bprintf buf "st_atime %s\n" (Date.to_full_string s.Unix.st_atime);
-+ Printf.bprintf buf "st_mtime %s\n" (Date.to_full_string s.Unix.st_mtime);
-+ Printf.bprintf buf "st_ctime %s\n" (Date.to_full_string s.Unix.st_ctime);
- let user,group = Unix32.owner arg in
- Printf.bprintf buf "username %s\n" user;
- Printf.bprintf buf "groupname %s\n" group;
-@@ -2030,7 +2144,7 @@
- \\<table cellspacing=0 cellpadding=0 width=100%%\\>\\<tr\\>
- \\<td class=downloaded width=100%%\\>\\</td\\>
- \\<td nowrap class=\\\"fbig pr\\\"\\>\\<a onclick=\\\"javascript: {
-- var getdir = prompt('Input: <priority#> <directory> (surround dir with quotes if necessary)','0 /home/mldonkey/share')
-+ var getdir = prompt('Input: <priority#> <directory> [<strategy>] (surround dir with quotes if necessary)','0 /home/mldonkey/share')
- parent.fstatus.location.href='submit?q=share+' + encodeURIComponent(getdir);
- setTimeout('window.location.reload()',1000);
- }\\\"\\>Add Share\\</a\\>
-@@ -2049,12 +2163,10 @@
- ( "1", "srh ar", "% free", "% free" ) ;
- ( "0", "srh", "Filesystem", "FS" ) ];
-
-- let counter = ref 0 in
--
-+ html_mods_cntr_init ();
- List.iter (fun shared_dir ->
- let dir = shared_dir.shdir_dirname in
-- incr counter;
-- Printf.bprintf buf "\\<tr class=\\\"%s\\\"\\>
-+ Printf.bprintf buf "\\<tr class=\\\"dl-%d\\\"\\>
- \\<td title=\\\"Click to unshare this directory\\\"
- onMouseOver=\\\"mOvr(this);\\\"
- onMouseOut=\\\"mOut(this);\\\"
-@@ -2069,7 +2181,7 @@
- \\<td class=\\\"sr ar\\\"\\>%s\\</td\\>
- \\<td class=\\\"sr ar\\\"\\>%s\\</td\\>
- \\<td class=\\\"sr\\\"\\>%s\\</td\\>\\</tr\\>"
-- (if !counter mod 2 == 0 then "dl-1" else "dl-2")
-+ (html_mods_cntr ())
- (Url.encode dir)
- shared_dir.shdir_priority
- dir
-@@ -2088,7 +2200,38 @@
- !!shared_directories;
-
- Printf.bprintf buf "\\</table\\>\\</td\\>\\<tr\\>\\</table\\>\\</div\\>\\<P\\>";
-- print_option_help o shared_directories
-+ print_option_help o shared_directories;
-+ Printf.bprintf buf "\\<P\\>";
-+
-+ html_mods_big_header_start buf "sharesTable" ["Share strategies"];
-+ html_mods_table_header buf "sharesTable" "shares" [
-+ ( "0", "srh", "Name", "Name" ) ;
-+ ( "0", "srh", "Incoming", "Incoming" ) ;
-+ ( "0", "srh", "Directories", "Directories" ) ;
-+ ( "0", "srh", "Recursive", "Recursive" ) ;
-+ ( "0", "srh", "Minsize", "Minsize" ) ;
-+ ( "0", "srh", "Maxsize", "Maxsize" ) ;
-+ ( "0", "srh", "Extensions", "Extensions" ) ];
-+
-+ html_mods_cntr_init ();
-+
-+ let int64_print v =
-+ if v = Int64.max_int then "unlimited" else Int64ops.int64_to_human_readable v in
-+
-+ List.iter (fun (s,t) ->
-+ Printf.bprintf buf "\\<tr class=\\\"dl-%d\\\"\\>" (html_mods_cntr ());
-+ html_mods_td buf [
-+ ("", "sr", s);
-+ ("", "sr", string_of_bool t.sharing_incoming);
-+ ("", "sr", string_of_bool t.sharing_directories);
-+ ("", "sr", string_of_bool t.sharing_recursive);
-+ ("", "sr", (int64_print t.sharing_minsize));
-+ ("", "sr", (int64_print t.sharing_maxsize));
-+ ("", "sr", (String.concat " " t.sharing_extensions));
-+ ];
-+ Printf.bprintf buf "\\</tr\\>\n"
-+ ) !!sharing_strategies;
-+
- end
- else
- begin
-@@ -2119,23 +2262,29 @@
- } in
-
- if Unix2.is_directory arg then
-- if not (List.mem shdir !!shared_directories) then begin
-+ begin
-+ try
-+ let d = List.find (fun d -> d.shdir_dirname = arg) !!shared_directories in
-+ let old_prio = d.shdir_priority in
-+ d.shdir_priority <- prio;
-+ Printf.sprintf "prio of %s changed from %d to %d"
-+ d.shdir_dirname old_prio d.shdir_priority
-+ with Not_found ->
- shared_directories =:= shdir :: !!shared_directories;
- shared_add_directory shdir;
-- "directory added"
-- end (* else
-- if not (List.mem (arg, prio) !!shared_directories) then begin
-- shared_directories =:= (arg, prio) :: List.remove_assoc arg !!shared_directories;
-- shared_add_directory (arg, prio);
-- "prio changed"
-- end *) else
-- "directory already shared"
-+ Printf.sprintf "directory %s added%s"
-+ shdir.shdir_dirname
-+ (if shdir.shdir_priority <> 0 then
-+ Printf.sprintf " with prio %d" shdir.shdir_priority
-+ else "")
-+ end
- else
- "no such directory"
- ), "<priority> <dir> [<strategy>] :\tshare directory <dir> with <priority> [and sharing strategy <strategy>]";
-
- "unshare", Arg_one (fun arg o ->
-
-+ if user2_is_admin o.conn_user.ui_user then begin
- let found = ref false in
- shared_directories =:= List.filter (fun sd ->
- let diff = sd.shdir_dirname <> arg in
-@@ -2154,118 +2303,33 @@
- _s "directory removed"
- end else
- _s "directory already unshared"
--
-- ), "<dir> :\t\t\t\tshare directory <dir>";
-+ end
-+ else
-+ _s "You are not allowed to unshare directories"
-+ ), "<dir> :\t\t\t\tunshare directory <dir>";
-
- "upstats", Arg_none (fun o ->
- let buf = o.conn_buf in
--
-- if use_html_mods o then begin
--
--if !!html_mods_use_js_tooltips then Printf.bprintf buf
--"\\<div id=\\\"object1\\\" style=\\\"position:absolute; background-color:FFFFDD;color:black;border-color:black;border-width:20;font-size:8pt; visibility:show; left:25px; top:
---100px; z-index:+1\\\" onmouseover=\\\"overdiv=1;\\\" onmouseout=\\\"overdiv=0; setTimeout(\\\'hideLayer()\\\',1000)\\\"\\>\\&nbsp;\\</div\\>";
--
-- Printf.bprintf buf "\\<div class=\\\"upstats\\\"\\>";
-- html_mods_table_one_row buf "upstatsTable" "upstats" [
-- ("", "srh", Printf.sprintf "Session: %s uploaded | Shared(%d): %s\n"
-- (size_of_int64 !upload_counter) !nshared_files (size_of_int64 !nshared_bytes)); ]
-- end
-- else begin
-- Printf.bprintf buf "Upload statistics:\n";
-- Printf.bprintf buf "Session: %s uploaded | Shared(%d): %s\n"
-- (size_of_int64 !upload_counter) !nshared_files (size_of_int64 !nshared_bytes)
-- end;
-- let list = ref [] in
-- shared_iter (fun s ->
-- let impl = as_shared_impl s in
-- list := impl :: !list
-- );
--
-- if use_html_mods o then
-- html_mods_table_header buf "upstatsTable" "upstats" [
-- ( "1", "srh", "Total file requests", "Reqs" ) ;
-- ( "1", "srh", "Total bytes sent", "Total" ) ;
-- ( "1", "srh", "Upload Ratio", "UPRatio" ) ;
-- ( "0", "srh", "Preview", "P" ) ;
-- ( "0", "srh", "Filename", "Filename" );
-- ( "0", "srh", "Statistic links", "Stats" ) ]
-+ if not (user2_can_view_uploads o.conn_user.ui_user) then
-+ print_command_result o buf "You are not allowed to see upload statistics"
- else
-- begin
-- Printf.bprintf buf " Requests | Bytes | Uploaded | File\n";
-- Printf.bprintf buf "----------+----------+----------+----------------------------------------------------\n";
-- end;
--
-- let counter = ref 0 in
--
-- let list = Sort.list (fun f1 f2 ->
-- (f1.impl_shared_requests = f2.impl_shared_requests &&
-- f1.impl_shared_uploaded > f2.impl_shared_uploaded) ||
-- (f1.impl_shared_requests > f2.impl_shared_requests )
-- ) !list in
--
-- List.iter (fun impl ->
-- if use_html_mods o then
-- begin
-- incr counter;
--
-- let ed2k = file_print_ed2k_link
-- (Filename.basename impl.impl_shared_codedname)
-- impl.impl_shared_size impl.impl_shared_id in
--
-- Printf.bprintf buf "\\<tr class=\\\"%s\\\""
-- (if (!counter mod 2 == 0) then "dl-1" else "dl-2";);
--
-- (if !!html_mods_use_js_tooltips then
-- Printf.bprintf buf " onMouseOver=\\\"mOvr(this);setTimeout('popLayer(\\\\\'%s<br>%s\\\\\')',%d);setTimeout('hideLayer()',%d);return true;\\\" onMouseOut=\\\"mOut(this);hideLayer();setTimeout('hideLayer()',%d)\\\"\\>"
-- (Http_server.html_real_escaped (Filename.basename impl.impl_shared_codedname))
-- (match impl.impl_shared_magic with
-- None -> ""
-- | Some magic -> "File type: " ^ (Http_server.html_real_escaped magic) ^ "<br>")
-- !!html_mods_js_tooltips_wait
-- !!html_mods_js_tooltips_timeout
-- !!html_mods_js_tooltips_wait
-- else Printf.bprintf buf " onMouseOver=\\\"mOvr(this);return true;\\\" onMouseOut=\\\"mOut(this);\\\"\\>");
--
-- let uploaded = Int64.to_float impl.impl_shared_uploaded in
-- let size = Int64.to_float impl.impl_shared_size in
--
-- html_mods_td buf [
-- ("", "sr ar", Printf.sprintf "%d" impl.impl_shared_requests);
-- ("", "sr ar", size_of_int64 impl.impl_shared_uploaded);
-- ("", "sr ar", Printf.sprintf "%5.1f" ( if size < 1.0 then 0.0 else (uploaded *. 100.) /. size));
-- ("", "sr", Printf.sprintf "\\<a href=\\\"preview_upload?q=%d\\\"\\>P\\</a\\>"
-- impl.impl_shared_num);
-- ("", "sr", (if impl.impl_shared_id = Md4.null then
-- (Filename.basename impl.impl_shared_codedname)
-- else
-- Printf.sprintf "\\<a href=\\\"%s\\\"\\>%s\\</a\\>"
-- ed2k (shorten (Filename.basename impl.impl_shared_codedname) !!max_name_len)));
-- ("", "sr", (if impl.impl_shared_id = Md4.null then "" else
-- Printf.sprintf "\\<a href=\\\"http://tothbenedek.hu/ed2kstats/ed2k?hash=%s\\\"\\>%s\\</a\\>
--\\<a href=\\\"http://ed2k.titanesel.ws/ed2k.php?hash=%s\\\"\\>%s\\</a\\>
--\\<a href=\\\"http://bitzi.com/lookup/ed2k:%s\\\"\\>%s\\</a\\>"
-- (Md4.to_string impl.impl_shared_id) "T1"
-- (Md4.to_string impl.impl_shared_id) "T2"
-- (Md4.to_string impl.impl_shared_id) "B")) ];
-- Printf.bprintf buf "\\</tr\\>\n";
-- end
-- else
-- Printf.bprintf buf "%9d | %8s | %7s%% | %-50s\n"
-- (impl.impl_shared_requests)
-- (size_of_int64 impl.impl_shared_uploaded)
-- (Printf.sprintf "%3.1f" ((Int64.to_float impl.impl_shared_uploaded *. 100.) /. Int64.to_float impl.impl_shared_size))
-- (shorten (Filename.basename impl.impl_shared_codedname) !!max_name_len);
-- ) list;
--
-- if use_html_mods o then Printf.bprintf buf "\\</table\\>\\</div\\>\\</div\\>";
--
--
-+ begin
-+ let list = ref [] in
-+ shared_iter (fun s ->
-+ let impl = as_shared_impl s in
-+ list := impl :: !list
-+ );
-+ print_upstats o !list None;
-+ end;
- _s ""
- ), ":\t\t\t\tstatistics on upload";
-
- "links", Arg_none (fun o ->
- let buf = o.conn_buf in
-+ if not (user2_can_view_uploads o.conn_user.ui_user) then
-+ print_command_result o o.conn_buf "You are not allowed to see shared files list"
-+ else begin
-+
- let list = ref [] in
- shared_iter (fun s ->
- let impl = as_shared_impl s in
-@@ -2285,28 +2349,26 @@
- (Filename.basename impl.impl_shared_codedname)
- impl.impl_shared_size impl.impl_shared_id);
- ) list;
-+ end;
- "Done"
- ), ":\t\t\t\t\tlist links of shared files";
-
- "uploaders", Arg_none (fun o ->
- let buf = o.conn_buf in
-
-- let nuploaders = Intmap.length !uploaders in
-+ if not (user2_can_view_uploads o.conn_user.ui_user) then
-+ print_command_result o buf "You are not allowed to see uploaders list"
-+ else begin
-
-+ let nuploaders = Intmap.length !uploaders in
- if use_html_mods o then
--
- begin
--
- let counter = ref 0 in
- Printf.bprintf buf "\\<div class=\\\"uploaders\\\"\\>";
- html_mods_table_one_row buf "uploadersTable" "uploaders" [
- ("", "srh", Printf.sprintf "Total upload slots: %d (%d) | Pending slots: %d\n" nuploaders
- (Fifo.length CommonUploads.upload_clients)
- (Intmap.length !CommonUploads.pending_slots_map)); ];
--(* Printf.bprintf buf "\\<div class=\\\"uploaders\\\"\\>Total upload slots: %d (%d) | Pending slots: %d\n" nuploaders
-- (Fifo.length CommonUploads.upload_clients)
-- (Intmap.length !CommonUploads.pending_slots_map);
-- *)
- if nuploaders > 0 then
-
- begin
-@@ -2327,6 +2389,7 @@
- @ [
- ( "0", "srh ar", "Total DL bytes from this client for all files", "DL" ) ;
- ( "0", "srh ar", "Total UL bytes to this client for all files", "UL" ) ;
-+ ( "0", "srh ar", "Slot kind", "Slot" ) ;
- ( "0", "srh", "Filename", "Filename" ) ]);
-
- List.iter (fun c ->
-@@ -2359,15 +2422,22 @@
- ("", "sr", ips);
- ] @ (if !Geoip.active then [(cn, "sr", cc)] else []) @ [
- ("", "sr", Printf.sprintf "%d" (((last_time ()) - i.client_connect_time) / 60));
-- ("", "sr", i.client_software);
-+ (client_software i.client_software i.client_os, "sr", client_software_short i.client_software i.client_os);
- ("", "sr", i.client_release);
- ] @
- (if !!emule_mods_count then [("", "sr", i.client_emulemod)] else [])
- @ [
- ("", "sr ar", size_of_int64 i.client_downloaded);
- ("", "sr ar", size_of_int64 i.client_uploaded);
-+ (let text1, text2 =
-+ match client_slot c with
-+ | FriendSlot -> "Friend", "F"
-+ | ReleaseSlot -> "Release", "R"
-+ | SmallFileSlot -> "Small file", "S"
-+ | PrioSlot dir -> "Prio dir: " ^ dir, "P"
-+ | _ -> "", "" in text1, "sr ar", text2);
- ("", "sr", (match i.client_upload with
-- Some cu -> cu
-+ Some f -> shorten f !!max_name_len
- | None -> "") ) ]);
-
- Printf.bprintf buf "\\</tr\\>"
-@@ -2388,6 +2458,9 @@
- ( "0", "srh", "Network", "Network" ) ;
- ( "0", "srh", "Connection type [I]ndirect [D]irect", "C" ) ;
- ( "0", "srh", "Client name", "Client name" ) ;
-+ ( "0", "srh", "Secure User Identification [N]one, [P]assed, [F]ailed", "S" ) ;
-+ ( "0", "srh", "IP address", "IP address" ) ;
-+ ] @ (if !Geoip.active then [( "0", "srh", "Country Code/Name", "CC" )] else []) @ [
- ( "0", "srh", "Client brand", "CB" ) ;
- ( "0", "srh", "Client release", "CR" ) ;
- ] @
-@@ -2395,12 +2468,13 @@
- @ [
- ( "0", "srh ar", "Total DL bytes from this client for all files", "DL" ) ;
- ( "0", "srh ar", "Total UL bytes to this client for all files", "UL" ) ;
-- ( "0", "srh", "IP address", "IP address" ) ]);
-+ ( "0", "srh", "Filename", "Filename" ) ]);
-
- Intmap.iter (fun cnum c ->
-
- try
- let i = client_info c in
-+ let ips,cc,cn = string_of_kind_geo i.client_kind in
- incr counter;
-
- Printf.bprintf buf "\\<tr class=\\\"%s\\\"
-@@ -2414,33 +2488,36 @@
- client_print_html c o;
-
- html_mods_td buf ([
-- ("", "sr", i.client_software);
-+ ("", "sr", (match i.client_sui_verified with
-+ | None -> "N"
-+ | Some b -> if b then "P" else "F"
-+ ));
-+ ("", "sr", ips);
-+ ] @ (if !Geoip.active then [(cn, "sr", cc)] else []) @ [
-+ (client_software i.client_software i.client_os, "sr", client_software_short i.client_software i.client_os);
- ("", "sr", i.client_release);
- ] @
- (if !!emule_mods_count then [("", "sr", i.client_emulemod )] else [])
- @ [
- ("", "sr ar", size_of_int64 i.client_downloaded);
- ("", "sr ar", size_of_int64 i.client_uploaded);
-- ("", "sr", string_of_kind i.client_kind); ]);
-+ ("", "sr", (match i.client_upload with
-+ Some f -> shorten f !!max_name_len
-+ | None -> "") ) ]);
-
- Printf.bprintf buf "\\</tr\\>";
- with _ -> ();
-
- ) !CommonUploads.pending_slots_map;
- Printf.bprintf buf "\\</table\\>\\</div\\>";
--
- end;
--
-- Printf.bprintf buf "\\</div\\>";
-- ""
-+ Printf.bprintf buf "\\</div\\>"
- end
- else
- begin
--
- Intmap.iter (fun _ c ->
- try
- let i = client_info c in
--
- client_print c o;
- Printf.bprintf buf "client: %s downloaded: %s uploaded: %s\n" i.client_software (Int64.to_string i.client_downloaded) (Int64.to_string i.client_uploaded);
- match i.client_upload with
-@@ -2451,14 +2528,12 @@
- Printf.bprintf buf "no info on client %d\n" (client_num c )
- ) !uploaders;
-
-- Printf.sprintf "Total upload slots: %d (%d) | Pending slots: %d\n" nuploaders
-+ Printf.bprintf buf "Total upload slots: %d (%d) | Pending slots: %d\n" nuploaders
- (Fifo.length CommonUploads.upload_clients)
- (Intmap.length !CommonUploads.pending_slots_map);
--
--
- end
--
--
-+ end;
-+ ""
- ), ":\t\t\t\tshow users currently uploading";
-
-
-@@ -2504,7 +2579,7 @@
- "yes" | "y" | "true" ->
- List.iter (fun file ->
- try
-- file_cancel file
-+ file_cancel file o.conn_user.ui_user
- with e ->
- lprintf "Exception %s in cancel file %d\n"
- (Printexc2.to_string e) (file_num file)
-@@ -2541,7 +2616,7 @@
- if not (List.memq num !to_cancel) then
- to_cancel := num :: !to_cancel
- in
-- if args = ["all"] then
-+ if args = ["all"] && user2_is_admin o.conn_user.ui_user then
- List.iter (fun file ->
- file_cancel file
- ) !!files
-@@ -2585,7 +2660,7 @@
- List.iter
- (fun file ->
- if (CommonFile.file_downloaders file o !counter) then counter := 0 else counter := 1;
-- ) !!files;
-+ ) (user2_filter_files !!files o.conn_user.ui_user);
-
- if use_html_mods o then Printf.bprintf buf "\\</table\\>\\</div\\>";
-
-@@ -2611,35 +2686,46 @@
- ), "<num> :\t\t\tverify chunks of file <num>";
-
- "pause", Arg_multiple (fun args o ->
-- if args = ["all"] then
-+ if args = ["all"] && user2_is_admin o.conn_user.ui_user then
- List.iter (fun file ->
-- file_pause file;
-+ file_pause file admin_user;
- ) !!files
- else
- List.iter (fun num ->
- let num = int_of_string num in
- List.iter (fun file ->
-- if (as_file_impl file).impl_file_num = num then begin
-- file_pause file
-- end
-+ if (as_file_impl file).impl_file_num = num then
-+ file_pause file o.conn_user.ui_user
- ) !!files) args; ""
- ), "<num> :\t\t\t\tpause a download (use arg 'all' for all files)";
-
- "resume", Arg_multiple (fun args o ->
-- if args = ["all"] then
-+ if args = ["all"] && user2_is_admin o.conn_user.ui_user then
- List.iter (fun file ->
-- file_resume file
-+ file_resume file admin_user
- ) !!files
- else
- List.iter (fun num ->
- let num = int_of_string num in
- List.iter (fun file ->
-- if (as_file_impl file).impl_file_num = num then begin
-- file_resume file
-- end
-+ if (as_file_impl file).impl_file_num = num then
-+ file_resume file o.conn_user.ui_user
- ) !!files) args; ""
- ), "<num> :\t\t\t\tresume a paused download (use arg 'all' for all files)";
-
-+ "release", Arg_one (fun arg o ->
-+ let num = int_of_string arg in
-+ let file = file_find num in
-+ let old_state = file_release file in
-+ set_file_release file (not (file_release file)) o.conn_user.ui_user;
-+ Printf.sprintf "%s, file: %s"
-+ (match old_state, file_release file with
-+ true, false -> "deactivated release state"
-+ | false, true -> "activated release state"
-+ | _ -> "unchanged status, enough rights?")
-+ (shorten (file_best_name file) !!max_name_len)
-+ ), "<num> :\t\t\t\tchange release state of a download";
-+
- "commit", Arg_none (fun o ->
- List.iter (fun file ->
- file_commit file
-@@ -2655,20 +2741,19 @@
-
- "vd", Arg_multiple (fun args o ->
- let buf = o.conn_buf in
-+ let list = user2_filter_files !!files o.conn_user.ui_user in
-+ let filelist = List2.tail_map file_info list in
- match args with
- | ["queued"] ->
-- let list = List2.tail_map file_info !!files in
-- let list = List.filter ( fun f -> f.file_state = FileQueued ) list in
-+ let list = List.filter ( fun f -> f.file_state = FileQueued ) filelist in
- DriverInteractive.display_active_file_list buf o list;
- ""
- | ["paused"] ->
-- let list = List2.tail_map file_info !!files in
-- let list = List.filter ( fun f -> f.file_state = FilePaused ) list in
-+ let list = List.filter ( fun f -> f.file_state = FilePaused ) filelist in
- DriverInteractive.display_active_file_list buf o list;
- ""
- | ["downloading"] ->
-- let list = List2.tail_map file_info !!files in
-- let list = List.filter ( fun f -> f.file_state = FileDownloading ) list in
-+ let list = List.filter ( fun f -> f.file_state = FileDownloading ) filelist in
- DriverInteractive.display_file_list buf o list;
- ""
- | [arg] ->
-@@ -2696,15 +2781,14 @@
- List.iter
- (fun file -> if (as_file_impl file).impl_file_num = num then
- CommonFile.file_print file o)
-- !!files;
-+ list;
- List.iter
- (fun file -> if (as_file_impl file).impl_file_num = num then
- CommonFile.file_print file o)
- !!done_files;
- ""
- | _ ->
-- let list = List2.tail_map file_info !!files in
-- DriverInteractive.display_file_list buf o list;
-+ DriverInteractive.display_file_list buf o filelist;
- ""
- ), "[<num>|queued|paused|downloading] :\t$bview file info for download <num>, or lists of queued, paused or downloading files, or all downloads if no argument given$n";
-
-@@ -2726,14 +2810,15 @@
- ), "<num> \"<new name>\" :\t\tchange name of download <num> to <new name>";
-
- "filenames_variability", Arg_none (fun o ->
-- let list = List2.tail_map file_info !!files in
-+ let list = List2.tail_map file_info
-+ (user2_filter_files !!files o.conn_user.ui_user) in
- DriverInteractive.filenames_variability o list;
- _s "done"
- ), ":\t\t\ttell which files have several very different names";
-
- "dllink", Arg_multiple (fun args o ->
- let url = String2.unsplit args ' ' in
-- dllink_parse (o.conn_output = HTML) url
-+ dllink_parse (o.conn_output = HTML) url o.conn_user.ui_user
- ), "<link> :\t\t\t\tdownload ed2k, sig2dat, torrent or other link";
-
- "dllinks", Arg_one (fun arg o ->
-@@ -2741,7 +2826,7 @@
- let file = File.to_string arg in
- let lines = String2.split_simplify file '\n' in
- List.iter (fun line ->
-- Buffer.add_string result (dllink_parse (o.conn_output = HTML) line);
-+ Buffer.add_string result (dllink_parse (o.conn_output = HTML) line o.conn_user.ui_user);
- Buffer.add_string result (if o.conn_output = HTML then "\\<P\\>" else "\n")
- ) lines;
- (Buffer.contents result)
-@@ -2758,67 +2843,272 @@
- let _ =
- register_commands "Driver/Users" [
-
-- "useradd", Arg_multiple (fun args o ->
-+ "useradd", Arg_two (fun user pass o ->
- let buf = o.conn_buf in
-- let print_result o result =
-- if o.conn_output = HTML then
-- html_mods_table_one_row buf "serversTable" "servers" [
-- ("", "srh", result); ]
-- else
-- Printf.bprintf buf "%s" result
-- in
-- let add_new_user user pass mail =
-- if o.conn_user == default_user
-- || o.conn_user == (find_ui_user user) then
-- try
-- ignore (user2_find user);
-- ignore (user2_add user (Md4.string pass) "");
-- print_result o (Printf.sprintf "Password of user %s changed" user)
-- with _ ->
-- ignore (user2_add user (Md4.string pass) "");
-- print_result o (Printf.sprintf "User %s added" user)
-+ if user2_is_admin o.conn_user.ui_user
-+ || o.conn_user.ui_user.user_name = user then
-+ if user2_user_exists user then
-+ begin
-+ user2_user_set_password (user2_user_find user) pass;
-+ print_command_result o buf (Printf.sprintf "Password of user %s changed" user)
-+ end
-+ else
-+ begin
-+ user2_user_add user (Md4.string pass) ();
-+ print_command_result o buf (Printf.sprintf "User %s added" user)
-+ end
- else
-- print_result o "Only 'admin' is allowed to add users"
-- in begin
-- match args with
-- user :: pass :: mail :: _ ->
-- add_new_user user pass mail
-- | user :: pass :: _ ->
-- add_new_user user pass "";
-- | _ -> print_result o "Wrong syntax: use 'useradd user pass <mail>'"
-- end;
-+ print_command_result o buf "You are not allowed to add users";
- _s ""
-- ), "<user> <passwd> [<mail>] :\tadd new mldonkey user/change user password";
-+ ), "<user> <passwd> :\t\tadd new mldonkey user/change user password";
-
- "userdel", Arg_one (fun user o ->
- let buf = o.conn_buf in
-- let print_result o result =
-- if o.conn_output = HTML then
-- html_mods_table_one_row buf "serversTable" "servers" [
-- ("", "srh", result); ]
-+ if user <> o.conn_user.ui_user.user_name then
-+ if user2_is_admin o.conn_user.ui_user then
-+ if user = admin_user.user_name then
-+ print_command_result o buf "User 'admin' can not be removed"
-+ else
-+ try
-+ let u = user2_user_find user in
-+ let n = user2_num_user_dls u in
-+ if n <> 0 then print_command_result o buf
-+ (Printf.sprintf "User %s has %d downloads, can not delete" user n)
-+ else
-+ user2_user_remove user;
-+ print_command_result o buf (Printf.sprintf "User %s removed" user)
-+ with
-+ Not_found -> print_command_result o buf (Printf.sprintf "User %s does not exist" user)
- else
-- Printf.bprintf buf "%s" result
-+ print_command_result o buf "You are not allowed to remove users"
-+ else
-+ print_command_result o buf "You can not remove yourself";
-+ _s ""
-+ ), "<user> :\t\t\tremove a mldonkey user";
-+
-+ "usergroupadd", Arg_two (fun user group o ->
-+ let buf = o.conn_buf in
-+ if user2_is_admin o.conn_user.ui_user then
-+ begin
-+ try
-+ let u = user2_user_find user in
-+ begin
-+ try
-+ let g = user2_group_find group in
-+ user2_user_add_group u g;
-+ print_command_result o buf (Printf.sprintf "Added group %s to user %s" g.group_name u.user_name)
-+ with Not_found -> print_command_result o buf (Printf.sprintf "Group %s does not exist" group)
-+ end
-+ with Not_found -> print_command_result o buf (Printf.sprintf "User %s does not exist" user)
-+ end
-+ else
-+ print_command_result o buf "You are not allowed to add groups to a user";
-+ _s ""
-+ ), "<user> <group> :\t\tadd a group to a mldonkey user";
-+
-+ "usergroupdel", Arg_two (fun user group o ->
-+ let buf = o.conn_buf in
-+ if user2_is_admin o.conn_user.ui_user
-+ || o.conn_user.ui_user.user_name = user then
-+ begin
-+ try
-+ let u = user2_user_find user in
-+ begin
-+ try
-+ let g = user2_group_find group in
-+ if not (List.mem g u.user_groups) then
-+ print_command_result o buf (Printf.sprintf "User %s is not member of group %s" user group)
-+ else
-+ if Some g = u.user_default_group then
-+ print_command_result o buf (Printf.sprintf "Group %s is default group of user %s, can not remove. Use command userdgroup to change default_group." group user)
-+ else
-+ begin
-+ let counter = ref 0 in
-+ List.iter (fun f ->
-+ if file_owner f = u && file_group f = Some g then
-+ begin
-+ incr counter;
-+ set_file_group f u.user_default_group
-+ end
-+ ) !!files;
-+ user2_user_remove_group (user2_user_find user) (user2_group_find group);
-+ print_command_result o buf (Printf.sprintf "Removed group %s from user %s%s"
-+ group user
-+ (if !counter = 0 then "" else Printf.sprintf ", changed file_group of %d file%s to default_group %s"
-+ !counter (Printf2.print_plural_s !counter) (user2_print_group u.user_default_group)))
-+ end
-+ with Not_found -> print_command_result o buf (Printf.sprintf "Group %s does not exist" group)
-+ end
-+ with Not_found -> print_command_result o buf (Printf.sprintf "User %s does not exist" user)
-+ end
-+
-+ else
-+ print_command_result o buf "You are not allowed to remove groups from a user";
-+ _s ""
-+ ), "<user> <group> :\t\tremove a group from a mldonkey user";
-+
-+ "userdgroup", Arg_two (fun user group o ->
-+ let buf = o.conn_buf in
-+ if user2_is_admin o.conn_user.ui_user
-+ || o.conn_user.ui_user.user_name = user then
-+ begin
-+ try
-+ let u = user2_user_find user in
-+ begin
-+ try
-+ let g = if String.lowercase group = "none" then None else Some (user2_group_find group) in
-+ let update_dgroup () =
-+ match g with
-+ None -> true
-+ | Some g1 when List.mem g1 u.user_groups -> true
-+ | _ -> false
-+ in
-+ if update_dgroup () then
-+ begin
-+ user2_user_set_default_group u g;
-+ print_command_result o buf (Printf.sprintf "Changed default group of user %s to group %s" u.user_name (user2_print_user_default_group u))
-+ end
-+ else print_command_result o buf (Printf.sprintf "User %s is not member of group %s" u.user_name group)
-+ with Not_found -> print_command_result o buf (Printf.sprintf "Group %s does not exist" group)
-+ end
-+ with Not_found -> print_command_result o buf (Printf.sprintf "User %s does not exist" user)
-+ end
-+ else
-+ print_command_result o buf "You are not allowed to change default group";
-+ _s ""
-+ ), "<user> <group|None> :\tchange user default group";
-+
-+ "passwd", Arg_one (fun passwd o ->
-+ let buf = o.conn_buf in
-+ begin
-+ try
-+ let u = user2_user_find o.conn_user.ui_user.user_name in
-+ user2_user_set_password u passwd;
-+ print_command_result o buf (Printf.sprintf "Password of user %s changed" u.user_name)
-+ with Not_found -> print_command_result o buf (Printf.sprintf "User %s does not exist" o.conn_user.ui_user.user_name)
-+ end;
-+ _s ""
-+ ), "<passwd> :\t\t\tchange own password";
-+
-+ "usermail", Arg_two (fun user mail o ->
-+ let buf = o.conn_buf in
-+ if user2_is_admin o.conn_user.ui_user
-+ || o.conn_user.ui_user.user_name = user then
-+ begin
-+ try
-+ let u = user2_user_find user in
-+ user2_user_set_mail u mail;
-+ print_command_result o buf (Printf.sprintf "User %s has new mail %s" user mail)
-+ with Not_found -> print_command_result o buf (Printf.sprintf "User %s does not exist" user)
-+ end
-+ else print_command_result o buf "You are not allowed to change mail addresses";
-+ _s ""
-+ ), "<user> <mail> :\t\tchange user mail address";
-+
-+ "userdls", Arg_two (fun user dls o ->
-+ let buf = o.conn_buf in
-+ if user2_is_admin o.conn_user.ui_user then
-+ begin
-+ try
-+ let u = user2_user_find user in
-+ user2_user_set_dls u (int_of_string dls);
-+ print_command_result o buf (Printf.sprintf "User %s has now %s downloads allowed" user (user2_print_user_dls (user2_user_find user)))
-+ with Not_found -> print_command_result o buf (Printf.sprintf "User %s does not exist" user)
-+ end
-+ else print_command_result o buf "You are not allowed to change this value";
-+ _s ""
-+ ), "<user> <num> :\t\t\tchange number of allowed concurrent downloads";
-+
-+ "usercommit", Arg_two (fun user dir o ->
-+ let buf = o.conn_buf in
-+ if user2_is_admin o.conn_user.ui_user
-+ || o.conn_user.ui_user.user_name = user then
-+ begin
-+ try
-+ let u = user2_user_find user in
-+ user2_user_set_commit_dir u dir;
-+ print_command_result o buf (Printf.sprintf "User %s has new commit dir %s" u.user_name u.user_commit_dir)
-+ with Not_found -> print_command_result o buf (Printf.sprintf "User %s does not exist" user)
-+ end
-+ else print_command_result o buf "You are not allowed to change this value";
-+ _s ""
-+ ), "<user> <dir> :\t\tchange user specific commit directory";
-+
-+ "groupadd", Arg_two (fun group admin o ->
-+ let buf = o.conn_buf in
-+ let g_admin =
-+ try
-+ bool_of_string admin
-+ with _ -> false
- in
-- if o.conn_user == default_user then
-- if user = admin_user then
-- print_result o "User 'admin' can not be removed"
-+ if user2_is_admin o.conn_user.ui_user then
-+ if user2_group_exists group then
-+ print_command_result o buf (Printf.sprintf "Group %s already exists" group)
- else
-- try
-- ignore (user2_find user);
-- ignore (user2_remove user);
-- print_result o (Printf.sprintf "User %s removed" user)
-- with _ ->
-- print_result o (Printf.sprintf "User %s not found" user)
-+ begin
-+ user2_group_add group g_admin;
-+ print_command_result o buf (Printf.sprintf "Group %s added" group)
-+ end
- else
-- print_result o "Only 'admin' is allowed to remove users";
-+ print_command_result o buf "You are not allowed to add a group";
- _s ""
-- ), "<user> :\t\t\tremove a mldonkey user";
-+ ), "<group> <admin: true | false>: add new mldonkey group";
-
-+ "groupdel", Arg_one (fun group o ->
-+ let buf = o.conn_buf in
-+ if user2_is_admin o.conn_user.ui_user then
-+ begin
-+ try
-+ let g = user2_group_find group in
-+ let g_dls = user2_num_group_dls g in
-+ let g_mem = user2_num_group_members g in
-+ if g_dls <> 0 then
-+ print_command_result o buf
-+ (Printf.sprintf "Can not remove group %s, it has %d download%s"
-+ group g_dls (Printf2.print_plural_s g_dls))
-+ else
-+ if g_mem <> 0 then
-+ print_command_result o buf
-+ (Printf.sprintf "Can not remove group %s, it has %d member%s"
-+ group g_mem (Printf2.print_plural_s g_mem))
-+ else
-+ if g.group_name = system_user_default_group.group_name then
-+ print_command_result o buf (Printf.sprintf "Can not remove system group %s" group)
-+ else
-+ begin
-+ user2_group_remove g;
-+ print_command_result o buf (Printf.sprintf "Removed group %s" group)
-+ end
-+ with Not_found -> print_command_result o buf (Printf.sprintf "Group %s does not exist" group)
-+ end
-+ else
-+ print_command_result o buf "You are not allowed to remove users";
-+ _s ""
-+ ), "<group> :\t\t\tremove an unused mldonkey group";
-
-- "users", Arg_none (fun o ->
-- if o.conn_user == default_user then
-+ "groupadmin", Arg_two (fun group admin o ->
-+ let buf = o.conn_buf in
-+ if user2_is_admin o.conn_user.ui_user then
-+ begin
-+ try
-+ let g = user2_group_find group in
-+ if g.group_name = system_user_default_group.group_name then
-+ print_command_result o buf (Printf.sprintf "Can not change state of system group %s" group)
-+ else
-+ begin
-+ user2_group_admin g (bool_of_string admin);
-+ print_command_result o buf (Printf.sprintf "Changed admin status of group %s to %b" g.group_name g.group_admin)
-+ end
-+ with Not_found -> print_command_result o buf (Printf.sprintf "Group %s does not exist" group)
-+ end
-+ else
-+ print_command_result o buf "You are not allowed to change group admin status";
-+ _s ""
-+ ), "<group> <true|false> :\tchange group admin status";
-
-+ "users", Arg_none (fun o ->
- let buf = o.conn_buf in
-+ if user2_is_admin o.conn_user.ui_user then begin
-
- if use_html_mods o then begin
- Printf.bprintf buf "\\<div class=\\\"shares\\\"\\>\\<table class=main cellspacing=0 cellpadding=0\\>
-@@ -2831,55 +3121,269 @@
- var outstr = getdir.replace(reg, '+');
- parent.fstatus.location.href='submit?q=useradd+' + outstr;
- setTimeout('window.location.reload()',1000);
-- }\\\"\\>Add User\\</a\\>
--\\</td\\>
--\\</tr\\>\\</table\\>
--\\</td\\>\\</tr\\>
--\\<tr\\>\\<td\\>";
-+ }\\\"\\>Add user\\</a\\>
-+\\</td\\>\\</tr\\>\\</table\\>\\</td\\>\\</tr\\>\\<tr\\>\\<td\\>";
-
- html_mods_table_header buf "sharesTable" "shares" [
- ( "0", "srh ac", "Click to remove user", "Remove" ) ;
-- ( "0", "srh", "User", "Username" ) ];
-+ ( "0", "srh", "Username", "User" ) ;
-+ ( "0", "srh ac", "Only member of admin groups have admin rights", "Admin" ) ;
-+ ( "0", "srh", "Member of groups", "Groups" ) ;
-+ ( "0", "srh", "Default group", "Default group" ) ;
-+ ( "0", "srh", "Mail address", "Email" ) ;
-+ ( "0", "srh", "Commit dir", "Commit dir" ) ;
-+ ( "0", "srh ar", "Download quota", "Max DLs" ) ;
-+ ( "0", "srh ar", "Download count", "DLs" ) ];
-
- let counter = ref 0 in
--
-- user2_iter (fun name user ->
-+ user2_users_iter (fun user ->
- incr counter;
-+ let u_dls = user2_num_user_dls user in
- Printf.bprintf buf "\\<tr class=\\\"%s\\\"\\>"
- (if !counter mod 2 == 0 then "dl-1" else "dl-2");
-- if user.user_name <> admin_user then Printf.bprintf buf "
-- \\<td title=\\\"Click to remove user\\\"
-- onMouseOver=\\\"mOvr(this);\\\"
-- onMouseOut=\\\"mOut(this);\\\"
-- onClick=\\\'javascript:{
-- parent.fstatus.location.href=\\\"submit?q=userdel+\\\\\\\"%s\\\\\\\"\\\";
-- setTimeout(\\\"window.location.reload()\\\",1000);}'
-- class=\\\"srb\\\"\\>Remove\\</td\\>" user.user_name
-- else Printf.bprintf buf "
-- \\<td title=\\\"\\\"
-- class=\\\"srb\\\"\\>------\\</td\\>";
-- Printf.bprintf buf
-- "\\<td class=\\\"sr\\\"\\>%s\\</td\\>\\</tr\\>" user.user_name
-+ if user <> admin_user && (u_dls = 0) then Printf.bprintf buf
-+"\\<td title=\\\"Click to remove user\\\"
-+onMouseOver=\\\"mOvr(this);\\\"
-+onMouseOut=\\\"mOut(this);\\\"
-+onClick=\\\'javascript:{
-+parent.fstatus.location.href=\\\"submit?q=userdel+\\\\\\\"%s\\\\\\\"\\\";
-+setTimeout(\\\"window.location.reload()\\\",1000);}'
-+class=\\\"srb\\\"\\>Remove\\</td\\>" user.user_name
-+ else Printf.bprintf buf
-+"\\<td title=\\\"%s\\\"
-+class=\\\"srb\\\"\\>------\\</td\\>"
-+ (if user.user_name = admin_user.user_name then "Admin user can not be removed" else
-+ if u_dls <> 0 then Printf.sprintf "User has %d download%s" u_dls
-+ (Printf2.print_plural_s u_dls) else "");
-+ html_mods_td buf [
-+ ("", "sr", user.user_name);
-+ ("", "sr ac", Printf.sprintf "%b" (user2_is_admin user));
-+ ("Click to remove group", "sr",
-+ let buf1 = Buffer.create 100 in
-+ user2_user_groups_iter user (fun group ->
-+ if user2_default_group_matches_group user.user_default_group group then
-+ Printf.bprintf buf1 "%s " group.group_name
-+ else
-+ Printf.bprintf buf1
-+"\\<a onMouseOver=\\\"mOvr(this);\\\"
-+onMouseOut=\\\"mOut(this);\\\"
-+onClick=\\\'javascript:{
-+parent.fstatus.location.href=\\\"submit?q=usergroupdel+\\\\\\\"%s\\\\\\\"+\\\\\\\"%s\\\\\\\"\\\";
-+setTimeout(\\\"window.location.reload()\\\",1000);}'
-+class=\\\"srb\\\"\\>%s\\</a\\> " user.user_name group.group_name group.group_name
-+ );
-+ Buffer.contents buf1);
-+ ("", "sr", user2_print_user_default_group user);
-+ ("", "sr", user.user_mail);
-+ ("", "sr", user.user_commit_dir);
-+ ("", "sr ar", user2_print_user_dls user);
-+ ("", "sr ar", string_of_int u_dls)];
- );
-+ Printf.bprintf buf "\\</table\\>\\</td\\>\\<tr\\>\\</table\\>\\</div\\>\\<P\\>";
-+ print_option_help o userlist;
-+ Printf.bprintf buf "\\<P\\>";
-+
-+ Printf.bprintf buf "\\<div class=\\\"shares\\\"\\>\\<table class=main cellspacing=0 cellpadding=0\\>
-+\\<tr\\>\\<td\\>
-+\\<table cellspacing=0 cellpadding=0 width=100%%\\>\\<tr\\>
-+\\<td class=downloaded width=100%%\\>\\</td\\>
-+\\<td nowrap class=\\\"fbig pr\\\"\\>\\<a onclick=\\\"javascript: {
-+ var getdir = prompt('Input: <group> <admin: true|false> [<mail>]','group true')
-+ var reg = new RegExp (' ', 'gi') ;
-+ var outstr = getdir.replace(reg, '+');
-+ parent.fstatus.location.href='submit?q=groupadd+' + outstr;
-+ setTimeout('window.location.reload()',1000);
-+ }\\\"\\>Add group\\</a\\>
-+\\</td\\>\\</tr\\>\\</table\\>\\</td\\>\\</tr\\>\\<tr\\>\\<td\\>";
-+
-+ html_mods_table_header buf "sharesTable" "shares" [
-+ ( "0", "srh ac", "Click to remove group", "Remove" );
-+ ( "0", "srh", "Groupname", "Group" );
-+ ( "0", "srh ac", "Click to change status", "Admin" );
-+ ( "0", "srh ar", "Member count", "Mem" );
-+ ( "0", "srh ar", "Download count", "DLs" ) ];
-+
-+ html_mods_cntr_init ();
-+ user2_groups_iter (fun group ->
-+ let g_dls = user2_num_group_dls group in
-+ let g_mem = user2_num_group_members group in
-+ let is_sys_group = group.group_name = system_user_default_group.group_name in
-+ Printf.bprintf buf "\\<tr class=\\\"dl-%d\\\"\\>" (html_mods_cntr ());
-+ if g_dls = 0 && g_mem = 0 && not is_sys_group then Printf.bprintf buf
-+"\\<td title=\\\"Click to remove group\\\"
-+onMouseOver=\\\"mOvr(this);\\\" onMouseOut=\\\"mOut(this);\\\" onClick=\\\'javascript:{
-+parent.fstatus.location.href=\\\"submit?q=groupdel+\\\\\\\"%s\\\\\\\"\\\";
-+setTimeout(\\\"window.location.reload()\\\",1000);}'
-+class=\\\"srb\\\"\\>Remove\\</td\\>" group.group_name
-+ else
-+ Printf.bprintf buf "\\<td title=\\\"%s\\\" class=\\\"srb\\\"\\>------\\</td\\>"
-+ (if g_dls <> 0 then Printf.sprintf "Group is assigned to %d download%s"
-+ g_dls (Printf2.print_plural_s g_dls) else
-+ if g_mem <> 0 then Printf.sprintf "Group has %d member%s"
-+ g_mem (Printf2.print_plural_s g_mem) else
-+ if is_sys_group then "System group can not be removed" else "");
-+
-+ html_mods_td buf [("", "sr", group.group_name)];
-+
-+ if is_sys_group then
-+ html_mods_td buf [("System group, can not change state", "sr ac", Printf.sprintf "%b" group.group_admin)]
-+ else Printf.bprintf buf
-+"\\<td title=\\\"Change admin status\\\"
-+onMouseOver=\\\"mOvr(this);\\\" onMouseOut=\\\"mOut(this);\\\" onClick=\\\'javascript:{
-+parent.fstatus.location.href=\\\"submit?q=groupadmin+\\\\\\\"%s\\\\\\\"+\\\\\\\"%s\\\\\\\"\\\";
-+setTimeout(\\\"window.location.reload()\\\",1000);}'
-+class=\\\"sr ac\\\"\\>%s\\</td\\>"
-+ group.group_name
-+ (if group.group_admin then "false" else "true")
-+ (if group.group_admin then "true" else "false");
-
-- Printf.bprintf buf "\\</table\\>\\</td\\>\\<tr\\>\\</table\\>\\</div\\>";
-+ html_mods_td buf [
-+ ("", "sr ar", Printf.sprintf "%d" (user2_num_group_members group));
-+ ("", "sr ar", Printf.sprintf "%d" g_dls);
-+ ]);
-+
-+ Printf.bprintf buf "\\</table\\>\\</td\\>\\<tr\\>\\</table\\>\\</div\\>\\<P\\>";
-+ print_option_help o grouplist;
-+ Printf.bprintf buf "\\<P\\>";
-+
-+ Buffer.add_string buf "\\<div class=\\\"cs\\\"\\>";
-+ html_mods_table_header buf "helpTable" "results" [];
-+ Buffer.add_string buf "\\<tr\\>";
-+ html_mods_td buf [
-+ ("", "srh", "");
-+ ("", "srh", "Commands to manipulate user data");
-+ ("", "srh", ""); ];
-+ Buffer.add_string buf "\\</tr\\>";
-+ html_mods_cntr_init ();
-+ let list = Hashtbl2.to_list2 commands_by_kind in
-+ let list = List.sort (fun (s1,_) (s2,_) -> compare s1 s2) list in
-+ List.iter (fun (s,list) ->
-+ if s = "Driver/Users" then
-+ let list = List.sort (fun (s1,_) (s2,_) -> compare s1 s2) !list in
-+ List.iter (fun (cmd, help) ->
-+ Printf.bprintf buf "\\<tr class=\\\"dl-%d\\\"\\>" (html_mods_cntr ());
-+ html_mods_td buf [
-+ ("", "sr", "\\<a href=\\\"submit?q=" ^ cmd ^
-+ "\\\"\\>" ^ cmd ^ "\\</a\\>");
-+ ("", "srw", Str.global_replace (Str.regexp "\n") "\\<br\\>" help);
-+ ("", "sr", "\\<a href=\\\"http://mldonkey.sourceforge.net/" ^ (String2.upp_initial cmd) ^
-+ "\\\"\\>wiki\\</a\\>"); ];
-+ Printf.bprintf buf "\\</tr\\>\n"
-+ ) list
-+ ) list
- end
-- else
-- begin
-- Printf.bprintf buf "Users:\n";
-- user2_iter (fun name user ->
-- Printf.bprintf buf " %s\n"
-- user.user_name);
-- end;
-- ""
-- else
-- _s "Only 'admin' is allowed to list users"
-- ), ":\t\t\t\t\tprint users";
-+ else begin
-+ let list = ref [] in
-+ user2_users_iter (fun user -> list := [|
-+ user.user_name;
-+ Printf.sprintf "%b" (user2_is_admin user);
-+ (user2_print_user_groups " " user);
-+ (user2_print_user_default_group user);
-+ user.user_mail;
-+ user.user_commit_dir;
-+ (user2_print_user_dls user);
-+ (string_of_int (user2_num_user_dls user));
-+ |] :: !list );
-+ print_table_text buf
-+ [|
-+ Align_Left; Align_Left; Align_Left; Align_Left; Align_Left; Align_Left; Align_Right; Align_Right |]
-+ [|
-+ "User";
-+ "Admin";
-+ "Groups";
-+ "Dgroup";
-+ "Email";
-+ "Commit dir";
-+ "Max dls";
-+ "Dls";
-+ |] (List.rev !list);
-+ Printf.bprintf buf "\n";
-+ let list = ref [] in
-+ user2_groups_iter (fun group -> list := [|
-+ group.group_name;
-+ Printf.sprintf "%b" group.group_admin;
-+ (string_of_int (user2_num_group_members group));
-+ (string_of_int (user2_num_group_dls group));
-+ |] :: !list );
-+ print_table_text buf
-+ [|
-+ Align_Left; Align_Left; Align_Right; Align_Right |]
-+ [|
-+ "Group";
-+ "Admin";
-+ "Members";
-+ "Downloads";
-+ |] (List.rev !list);
-+ end
-+ end else print_command_result o buf "You are not allowed to list users";
-+ _s ""
-+ ), "\t\t\t\t\tprint users";
-
- "whoami", Arg_none (fun o ->
-- print_command_result o o.conn_buf o.conn_user.ui_user_name;
-+ print_command_result o o.conn_buf o.conn_user.ui_user.user_name;
- _s ""
- ), "\t\t\t\t\tprint logged-in user name";
-+
-+ "groups", Arg_none (fun o ->
-+ print_command_result o o.conn_buf (user2_print_user_groups " " o.conn_user.ui_user);
-+ _s ""
-+ ), "\t\t\t\t\tprint groups of logged-in user";
-+
-+ "dgroup", Arg_none (fun o ->
-+ print_command_result o o.conn_buf (user2_print_user_default_group o.conn_user.ui_user);
-+ _s ""
-+ ), "\t\t\t\t\tprint default group of logged-in user";
-+
-+ "chgrp", Arg_two (fun group filenum o ->
-+ let num = int_of_string filenum in
-+ begin try
-+ let file = file_find num in
-+ if String.lowercase group = "none" then
-+ begin
-+ set_file_group file None;
-+ print_command_result o o.conn_buf (Printf.sprintf (_b "Changed group of download %d to %s") num group)
-+ end
-+ else
-+ begin
-+ try
-+ let g = user2_group_find group in
-+ if user2_allow_file_admin file o.conn_user.ui_user &&
-+ List.mem g (file_owner file).user_groups then
-+ begin
-+ set_file_group file (Some g);
-+ print_command_result o o.conn_buf (Printf.sprintf (_b "Changed group of download %d to %s") num group)
-+ end
-+ else
-+ print_command_result o o.conn_buf (Printf.sprintf (_b "You are not allowed to change group of download %d to %s") num group)
-+ with Not_found -> print_command_result o o.conn_buf (Printf.sprintf (_b "Group %s not found") group)
-+ end
-+ with Not_found -> print_command_result o o.conn_buf (Printf.sprintf (_b "File %d not found") num)
-+ end;
-+ _s ""
-+ ), "<group> <num> :\t\t\tchange group of download <num> to <group>, use group = none for private file";
-+
-+ "chown", Arg_two (fun user filenum o ->
-+ let num = int_of_string filenum in
-+ begin
-+ try
-+ let file = file_find num in
-+ begin
-+ try
-+ let u = user2_user_find user in
-+ if user2_allow_file_admin file o.conn_user.ui_user then
-+ begin
-+ set_file_owner file u;
-+ print_command_result o o.conn_buf (Printf.sprintf (_b "Changed owner of download %d to %s") num user)
-+ end
-+ else
-+ print_command_result o o.conn_buf (Printf.sprintf (_b "You are not allowed to change owner of download %d to %s") num user)
-+ with Not_found -> print_command_result o o.conn_buf (Printf.sprintf (_b "User %s not found") user)
-+ end
-+ with Not_found -> print_command_result o o.conn_buf (Printf.sprintf (_b "File %d not found") num)
-+ end;
-+ _s ""
-+ ), "<user> <num> :\t\t\tchange owner of download <num> to <user>";
-+
- ]
-
-
-@@ -3021,7 +3525,6 @@
- html_mods =:= true;
- html_mods_style =:= 0;
- commands_frame_height =:= CommonMessages.styles.(!!html_mods_style).frame_height;
-- use_html_frames =:= true;
- CommonMessages.colour_changer() ;
- end;
-
-@@ -3039,7 +3542,6 @@
- end
- else begin
- html_mods =:= true;
-- use_html_frames =:= true;
- html_mods_theme =:= "";
- let num = int_of_string (List.hd args) in
-
-@@ -3130,8 +3632,7 @@
- ""
- end
- else begin
--(* html_mods =:= true;
-- use_html_frames =:= true; *)
-+(* html_mods =:= true; *)
- html_mods_theme =:= List.hd args;
- "\\<script type=\\\"text/javascript\\\"\\>top.window.location.reload();\\</script\\>"
- end
-Index: src/daemon/driver/driverControlers.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/driver/driverControlers.ml,v
-retrieving revision 1.85
-retrieving revision 1.93
-diff -u -r1.85 -r1.93
---- src/daemon/driver/driverControlers.ml 12 Sep 2006 22:47:11 -0000 1.85
-+++ src/daemon/driver/driverControlers.ml 19 Nov 2006 23:03:42 -0000 1.93
-@@ -310,7 +310,7 @@
- let user, pass =
- match args with
- [] -> failwith "Usage: auth <user> <password>"
-- | [s1] -> admin_user, s1
-+ | [s1] -> admin_user.CommonTypes.user_name, s1
- | user :: pass :: _ -> user, pass
- in
- if valid_password user pass then begin
-@@ -320,7 +320,7 @@
- let module M = CommonMessages in
- Buffer.add_string buf M.full_access;
- (match DriverInteractive.real_startup_message () with
-- Some s -> Buffer.add_string buf s;
-+ Some s -> Buffer.add_string buf ("\n" ^ s);
- | None -> ());
- end else
- let module M = CommonMessages in
-@@ -581,7 +581,7 @@
- "telnet connection"
- s in
- let telnet = {
-- telnet_auth = ref (empty_password admin_user);
-+ telnet_auth = ref (has_empty_password admin_user);
- telnet_iac = false;
- telnet_wait = 0;
- telnet_buffer = Buffer.create 100;
-@@ -775,14 +775,6 @@
- really_input file s 0 size;
- s)
-
--let add_simple_commands buf =
-- let this_page = "commands.html" in
-- Buffer.add_string buf (
-- if !!html_mods_theme != "" && theme_page_exists this_page then
-- read_theme_page this_page else
-- if !!html_mods then !!CommonMessages.web_common_header_mods0
-- else !!CommonMessages.web_common_header_old)
--
- let http_add_gen_header r =
- add_reply_header r "Server" "MLdonkey";
- add_reply_header r "Connection" "close"
-@@ -883,9 +875,7 @@
- else !!CommonMessages.html_header_old);
-
- Buffer.add_string buf "</head>\n";
-- if open_body then Buffer.add_string buf "<body>\n";
-- if not !!use_html_frames then add_simple_commands buf;
-- ()
-+ if open_body then Buffer.add_string buf "<body>\n"
-
- let html_close_page buf close_body =
- if close_body then Buffer.add_string buf "</body>\n";
-@@ -955,12 +945,18 @@
- List.iter (fun (arg, value) -> Printf.bprintf b " %s %s" arg value) r.get_url.Url.args;
- if Buffer.contents b <> "" then Printf.sprintf "(%s)" (Buffer.contents b) else "");
-
-- let user = if r.options.login = "" then admin_user else r.options.login in
-+ let user = if r.options.login = "" then admin_user.CommonTypes.user_name else r.options.login in
- if not (valid_password user r.options.passwd) then begin
- clear_page buf;
- http_file_type := HTM;
-- Buffer.add_string buf (snd(Http_server.error_page "401" "" "" (Ip.to_string (TcpBufferedSocket.my_ip r.sock)) (string_of_int !!http_port) None));
-- need_auth r !!http_realm
-+ let _, error_text_long, header = Http_server.error_page "401" "" ""
-+ (Ip.to_string (TcpBufferedSocket.my_ip r.sock))
-+ (string_of_int !!http_port) None in
-+ Buffer.add_string buf error_text_long;
-+ r.reply_head <- header;
-+ r.reply_headers <- [
-+ "Connection", "close";
-+ "WWW-Authenticate", Printf.sprintf "Basic realm=\"%s\"" !!http_realm]
- end
- else
- begin
-@@ -1000,15 +996,15 @@
- "VDC" ->
- let num = int_of_string value in
- let file = file_find num in
-- file_cancel file
-+ file_cancel file o.conn_user.ui_user
- | "VDP" ->
- let num = int_of_string value in
- let file = file_find num in
-- file_pause file
-+ file_pause file o.conn_user.ui_user
- | "VDR" ->
- let num = int_of_string value in
- let file = file_find num in
-- file_resume file
-+ file_resume file o.conn_user.ui_user
- | _ -> ()
- ) r.get_url.Url.args;
-
-@@ -1048,7 +1044,6 @@
- if !!html_mods then !!CommonMessages.multidllink_mods0
- else !!CommonMessages.multidllink_old)
- | "" | "index.html" ->
-- if !!use_html_frames then begin
- html_open_page buf t r false;
- let this_page = "frames.html" in
- if !!html_mods_theme != "" && theme_page_exists this_page then
-@@ -1079,9 +1074,7 @@
- </frameset>
- <frame name=\"output\" src=\"oneframe.html\">
- </frameset>
--" !!commands_frame_height;
-- end else
-- html_open_page buf t r true
-+" !!commands_frame_height
- | "complex_search.html" ->
- html_open_page buf t r true;
- CommonSearch.complex_search buf
-@@ -1093,7 +1086,7 @@
- Buffer.add_string buf (Printf.sprintf "<br><div align=\"center\"><h3>%s %s</h3></div>"
- (Printf.sprintf (_b "Welcome to MLDonkey")) Autoconf.current_version);
- if !!motd_html <> "" then Buffer.add_string buf !!motd_html;
-- if user2_is_admin o.conn_user.ui_user_name then
-+ if user2_is_admin o.conn_user.ui_user then
- (match DriverInteractive.real_startup_message () with
- Some s -> Buffer.add_string buf (Printf.sprintf "<p><pre><b><h3>%s</b></h3></pre>" s);
- | None -> ())
-@@ -1265,7 +1258,7 @@
- try
- let num = int_of_string value in
- let r = find_result num in
-- let files = result_download r [] false in
-+ let files = result_download r [] false o.conn_user.ui_user in
- List.iter CommonInteractive.start_download files;
-
- let module M = CommonMessages in
-@@ -1285,15 +1278,23 @@
- "cancel" ->
- let num = int_of_string value in
- let file = file_find num in
-- file_cancel file
-+ file_cancel file o.conn_user.ui_user
- | "pause" ->
- let num = int_of_string value in
- let file = file_find num in
-- file_pause file
-+ file_pause file o.conn_user.ui_user
- | "resume" ->
- let num = int_of_string value in
- let file = file_find num in
-- file_resume file
-+ file_resume file o.conn_user.ui_user
-+ | "release" ->
-+ let num = int_of_string value in
-+ let file = file_find num in
-+ set_file_release file true o.conn_user.ui_user
-+ | "norelease" ->
-+ let num = int_of_string value in
-+ let file = file_find num in
-+ set_file_release file false o.conn_user.ui_user
- | "sortby" ->
- begin
- match value with
-@@ -1313,13 +1314,15 @@
- | "N" -> o.conn_sortvd <- ByNet
- | "Avail" -> o.conn_sortvd <- ByAvail
- | "Cm" -> o.conn_sortvd <- ByComments
-+ | "User" -> o.conn_sortvd <- ByUser
-+ | "Group" -> o.conn_sortvd <- ByGroup
- | _ -> ()
- end
- | _ -> ()
- ) r.get_url.Url.args;
- let b = Buffer.create 10000 in
-
-- let list = (List2.tail_map file_info !!files) in
-+ let list = List2.tail_map file_info (user2_filter_files !!files o.conn_user.ui_user) in
- DriverInteractive.display_file_list b o list;
- html_open_page buf t r true;
- Buffer.add_string buf (html_escaped (Buffer.contents b))
-@@ -1331,9 +1334,10 @@
- | [ "jvcmd", "multidllink" ; "links", links] ->
- html_open_page buf t r true;
- List.iter (fun url ->
-- if url <> "\013" && url <> "" then
-+ let url = fst (String2.cut_at url '\013') in
-+ if url <> "" then
- begin
-- Buffer.add_string buf (html_escaped (dllink_parse (o.conn_output = HTML) url));
-+ Buffer.add_string buf (html_escaped (dllink_parse (o.conn_output = HTML) url o.conn_user.ui_user));
- Buffer.add_string buf (html_escaped "\\<P\\>")
- end
- ) (String2.split links '\n')
-@@ -1388,7 +1392,7 @@
-
- | [ "setoption", _ ; "option", name; "value", value ] ->
- html_open_page buf t r true;
-- if (o.conn_user == default_user) || !!enable_user_config then
-+ if user2_is_admin o.conn_user.ui_user then
- begin
- CommonInteractive.set_fully_qualified_options name value;
- Buffer.add_string buf "Option value changed"
-@@ -1489,11 +1493,34 @@
- read_theme_page this_page else
- if !!html_mods then !!CommonMessages.download_html_js_mods0
- else !!CommonMessages.download_html_js_old)
-- | cmd ->
-- html_open_page buf t r true;
-- Printf.bprintf buf "No page named %s" (html_escaped cmd)
-+ | "porttest" ->
-+ html_open_page buf t r true;
-+ let age time =
-+ Date.time_to_string (BasicSocket.last_time () - time) "verbose" in
-+ networks_iter (fun n ->
-+ let result =
-+ match network_porttest_result n with
-+ PorttestNotAvailable -> None
-+ | PorttestNotStarted -> Some "porttest not started"
-+ | PorttestInProgress time ->
-+ Some (Printf.sprintf "porttest started %s ago" (age time))
-+ | PorttestResult (time, s) ->
-+ Some (Printf.sprintf "porttest finished %s ago, %s" (age time) s)
-+ in
-+ (match result with
-+ None -> ()
-+ | Some result ->
-+ Printf.bprintf buf "%s:<br> %s<br>\n" n.network_name result));
-+ Printf.bprintf buf "<br><br><a href=\"porttest\">Reload</a>"
-+ | _ -> raise Not_found
- with
-- | Not_found -> Printf.bprintf buf "404 Not found"
-+ | Not_found ->
-+ let _, error_text_long, header = Http_server.error_page "404" "" ""
-+ (Ip.to_string (TcpBufferedSocket.my_ip r.sock))
-+ (string_of_int !!http_port)
-+ (Some (Url_not_found r.get_url.Url.full_file)) in
-+ r.reply_head <- header;
-+ Buffer.add_string buf error_text_long
- | e ->
- Printf.bprintf buf "\nException %s\n" (Printexc2.to_string e);
- r.reply_stream <- None
-@@ -1501,11 +1528,11 @@
-
- let s =
- match !http_file_type with
-- HTM -> html_close_page buf false; dollar_escape o !!use_html_frames (Buffer.contents buf)
-- | MLHTM -> html_close_page buf true; dollar_escape o !!use_html_frames (Buffer.contents buf)
-+ HTM -> html_close_page buf false; dollar_escape o true (Buffer.contents buf)
-+ | MLHTM -> html_close_page buf true; dollar_escape o true (Buffer.contents buf)
- | TXT
-+ | UNK
- | BIN -> Buffer.contents buf
-- | UNK -> "Unknown type for content :" ^ (Buffer.contents buf)
- in
- r.reply_content <-
- if !http_file_type <> BIN && !!html_use_gzip then
-Index: src/daemon/driver/driverGraphics_gd.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/driver/driverGraphics_gd.ml,v
-retrieving revision 1.1
-retrieving revision 1.2
-diff -u -r1.1 -r1.2
---- src/daemon/driver/driverGraphics_gd.ml 25 Jan 2006 22:44:08 -0000 1.1
-+++ src/daemon/driver/driverGraphics_gd.ml 14 Nov 2006 11:23:11 -0000 1.2
-@@ -47,14 +47,6 @@
-
- module Graphics : Graphics = struct
-
--(* some thoughts
--type gfx_settings = {
-- win_x : int;
-- win_y : int;
-- vtext : string;
-- }
--*)
--
- (* some defs *)
- let reverse lst =
- let rec reverseAux lst acc =
-@@ -73,144 +65,146 @@
- | [x] -> x
- | x::xs -> max x (maxlist xs)
-
-+(* set some vars *)
-
--(* set some vars *)
--let samples_time = 5
--let samples_h_time = 720
-+let history_time = history_size * history_step
-+let history_h_time = history_h_size * history_h_step
-+
-+(* define margins *)
-+let left_margin = 20
-+let right_margin = 45
-+let top_margin = 16
-+let bottom_margin = 24
-
- (* set _x and _y with boundaries *)
--let tag_x() = if !!html_mods_vd_gfx_tag_x_size < 130 then 130
-- else if !!html_mods_vd_gfx_tag_x_size > 3600 then 3600
-- else !!html_mods_vd_gfx_tag_x_size
--let tag_y() = if !!html_mods_vd_gfx_tag_y_size < 50 then 50
-- else if !!html_mods_vd_gfx_tag_y_size > 1200 then 1200
-- else !!html_mods_vd_gfx_tag_y_size
--let win_x() = if !!html_mods_vd_gfx_x_size < 320 then 320
-- else if !!html_mods_vd_gfx_x_size > 3600 then 3600
-- else !!html_mods_vd_gfx_x_size
--let win_y() = if !!html_mods_vd_gfx_y_size < 200 then 200
-- else if !!html_mods_vd_gfx_y_size > 1200 then 1200
-- else !!html_mods_vd_gfx_y_size
--
--let vtext = "0"
--let x_divisions() = (win_x()) / 80
--let y_divisions() = (win_y()) / 30
--let x_fdivisions() = float_of_int (x_divisions())
--let y_fdivisions() = float_of_int (y_divisions())
--
--(* todo: limit to 4 max *)
--let xmult = 1
--let xgmult = 16
--(* todo: limit to 4 max *)
--let ymult = 1
--let xdivisions() = (x_divisions()) * xmult
--let fxdivisions() = float_of_int (xdivisions())
--let xgdivisions() = (x_divisions()) * xgmult
--let fxgdivisions() = float_of_int (xgdivisions())
--let ydivisions() = (y_divisions()) * ymult
--let fydivisions() = float_of_int (ydivisions())
--let vmax_auto() = if detected_downlink_capacity () < detected_uplink_capacity () then
-- (detected_uplink_capacity ())
-+let tag_x () = min (max 130 !!html_mods_vd_gfx_tag_x_size) 3600
-+let tag_y () = min (max 50 !!html_mods_vd_gfx_tag_y_size) 1200
-+let win_x () = min (max 365 !!html_mods_vd_gfx_x_size) 3665
-+let win_y () = min (max 200 !!html_mods_vd_gfx_y_size) 1200
-+
-+let round_down x =
-+ let values = [120; 60; 30; 15; 12; 10; 6; 4; 3; 2; 1; 0] in
-+ max 1 (List.find ((>=) x) values)
-+
-+let round_up x =
-+ let v = min x 120 in
-+ let values = [0; 1; 2; 3; 4; 5; 10; 15; 30; 60; 120] in
-+ List.find ((<=) v) values
-+
-+let round_h_up x =
-+ let v = min x 840 in
-+ let values = [1; 2; 3; 4; 5; 10; 15; 30; 60; 120; 180; 240; 300; 360; 480; 720; 1440; 2880; 4320; 5760; 7200; 8640; 10080; 11520; 12960; 14400; 15840; 17280; 18720; 20160; 30240; 40320; 50400; 60480; 70560; 80640; 90720] in
-+ List.find ((<=) v) values
-+
-+let round_h_down x =
-+ let values = [90720; 80640; 70560; 60480; 50400; 40320; 30240; 20160; 18720; 17280; 15840; 14400; 12960; 11520; 10080; 8640; 7200; 5760; 4320; 2880; 1440; 720; 480; 360; 300; 240; 180; 120; 60; 30; 15; 10; 5; 4; 3; 2; 1; 0] in
-+ max 1 (List.find ((>=) x) values)
-+
-+(* calculate x-values *)
-+let x_time_per_grid() = 60 * round_up (history_time / (60 * ((win_x () - left_margin - right_margin) / 60)))
-+let x_divisions () = history_time / (x_time_per_grid ())
-+let x_fdivisions () = float_of_int (x_divisions ())
-+
-+let x_h_time_per_grid g = max history_h_step (
-+ if !!html_mods_vd_gfx_h_dynamic then
-+ begin
-+ if !!html_mods_vd_gfx_h_grid_time >= 1 then
-+ min (round_h_down (!!html_mods_vd_gfx_h_grid_time * 60))
-+ (min
-+ ((round_h_up ((((Fifo.length g) + x_divisions () - 2) / (x_divisions())) * history_h_step/60 )) * 60)
-+ ((round_h_down ( history_h_time / (60 * x_divisions()) )) * 60))
-+ else
-+ min ((round_h_up ((((Fifo.length g) + x_divisions () - 2) / (x_divisions ())) * history_h_step / 60)) * 60)
-+ ((round_h_down (history_h_time / (60 * x_divisions ()) )) * 60)
-+ end
- else
-- (detected_downlink_capacity ())
-+ if !!html_mods_vd_gfx_h_grid_time >= 1 then
-+ round_h_down (!!html_mods_vd_gfx_h_grid_time * 60)
-+ else
-+ round_h_down (history_h_time / (60 * x_divisions ())))
-
- let vmax link = (detected_link_capacity link)
-
--let vx() = (fxgdivisions()) /. (x_fdivisions())
--let vy() = (((float_of_int(vmax_auto())) /. 1024.) +. 2.) /. (y_fdivisions())
--let vy_m link = (((float_of_int(vmax link)) /. 1024.) +. 2.) /. (y_fdivisions())
-+let x_h_time g = (x_divisions() * x_h_time_per_grid g)
-+let x_h_values g = ((x_h_time g) / history_h_step)
-
--(* define margins *)
--let left_margin = 20
--let right_margin = 45
--let top_margin = 16
--let bottom_margin = 20
-+(* calculate y-values *)
-+let y_divisions () = ((win_y() - top_margin - bottom_margin)) / 50 * 2
-+let y_fdivisions () = float_of_int (y_divisions())
-+
-+let vmax_auto () = max (detected_uplink_capacity()) (detected_downlink_capacity())
-
- let samples_size = win_x() - (left_margin + right_margin)
-
- let xbl = left_margin
- let xbr() = win_x() - right_margin
- let xbs() = xbr() - xbl
--let ybt = top_margin
--let ybb() = win_y() - bottom_margin
-+let ybt = (top_margin / 2) * 2
-+let ybb() = ((win_y () - bottom_margin) / 2) * 2 - 1
- let ybs() = ybb() - ybt
- let vdt() = float_of_int(ybs()) /. float_of_int(vmax_auto())
- let vdt_m link = float_of_int(ybs()) /. float_of_int(vmax link)
--let vdt_stack link = float_of_int(ybs() / 2) /. float_of_int(vmax link)
-+let vdt_stack link = float_of_int((ybs() / 2)-1) /. float_of_int(vmax link)
-
- let ttl = ref ""
- let vl = ref ""
- let hl = ref ""
-
--let graph_length g =
-- if (Fifo.length g) < (xgdivisions()) then
-- ((Fifo.length g) - 1)
-- else
-- (xgdivisions())
--
--let datas_length g =
-- ((Fifo.length g))
--
--let l_max g =
-- (List.fold_left max 0 (Fifo.to_list g))
--
--let datas = Array.create history_size 0
--
-+let l_max g = (List.fold_left max 0 (Fifo.to_list g))
-
- let draw_borders mypic gcolor =
-- let my_y = (ybb()) in
-- let fx x = int_of_float ((((float_of_int x) /. (fxdivisions())) *. (float_of_int(xbs()))) +. (float_of_int xbl)) in
-- let my_x = (xbr()) in
-- let fy x = int_of_float ((((float_of_int x) /. (fydivisions())) *. (float_of_int(ybs()))) +. (float_of_int ybt)) in
-- mypic#line ~x1:(fx 0) ~y1:ybt ~x2:(fx 0) ~y2:my_y gcolor;
-- mypic#line ~x1:(fx (xdivisions())) ~y1:ybt ~x2:(fx (xdivisions())) ~y2:my_y gcolor;
-- mypic#line ~x1:xbl ~y1:(fy 0) ~x2:my_x ~y2:(fy 0) gcolor;
-- mypic#line ~x1:xbl ~y1:(fy (ydivisions())) ~x2:my_x ~y2:(fy (ydivisions())) gcolor
-+ mypic#line ~x1:(xbl-1) ~y1:(ybt-1) ~x2:(xbl-1) ~y2:(ybb()+1) gcolor;
-+ mypic#line ~x1:(xbr()+1) ~y1:(ybt-1) ~x2:(xbr()+1) ~y2:(ybb()+1) gcolor;
-+ mypic#line ~x1:(xbl-1) ~y1:(ybt-1) ~x2:(xbr()+1) ~y2:(ybt-1) gcolor;
-+ mypic#line ~x1:(xbl-1) ~y1:(ybb()+1) ~x2:(xbr()+1) ~y2:(ybb()+1) gcolor
-
- let draw_stack_borders mypic gcolor =
-- let my_y = (ybb()) in
-- let fx x = int_of_float ((((float_of_int x) /. (fxdivisions())) *. (float_of_int(xbs()))) +. (float_of_int xbl)) in
-- let my_x = (xbr()) in
-- let fy x = int_of_float ((((float_of_int x) /. (fydivisions())) *. (float_of_int(ybs()))) +. (float_of_int ybt)) in
-- mypic#line ~x1:(fx 0) ~y1:ybt ~x2:(fx 0) ~y2:my_y gcolor;
-- mypic#line ~x1:(fx (xdivisions())) ~y1:ybt ~x2:(fx (xdivisions())) ~y2:my_y gcolor;
-- mypic#line ~x1:xbl ~y1:(fy 0) ~x2:my_x ~y2:(fy 0) gcolor;
-- mypic#line ~x1:xbl ~y1:(fy (ydivisions())) ~x2:my_x ~y2:(fy (ydivisions())) gcolor;
-- mypic#line ~x1:xbl ~y1:(my_y - ((my_y - ybt) / 2)) ~x2:my_x ~y2:(my_y - ((my_y - ybt) / 2)) gcolor
-+ draw_borders mypic gcolor;
-+ mypic#line ~x1:(xbl-1) ~y1:(ybt+ybs()/2) ~x2:(xbr()+1) ~y2:(ybt+ybs()/2) gcolor
-
--let draw_x_grid mypic gcolor =
-+let draw_x_grid mypic gcolor gcolor2 my_xdivisons =
-+ let my_sdivisions = max 1 !!html_mods_vd_gfx_subgrid in
-+ let my_xsdivisons = xbs() / my_xdivisons / my_sdivisions in
- let my_y = (ybb()) in
-- let fx x = int_of_float ((((float_of_int x) /. (fxdivisions())) *. (float_of_int(xbs()))) +. (float_of_int xbl)) in
-- for n = 1 to xdivisions() - 1 do
-- mypic#dashed_line ~x1:(fx n) ~y1:ybt ~x2:(fx n) ~y2:my_y gcolor;
-+ let fx x = (((x * xbs()) / my_xdivisons) + xbl + 2) in
-+ let fxs x y = (fx x + my_xsdivisons * y) in
-+ for n = 1 to my_xdivisons - 1 do
-+ (*mypic#string ~font:Gd.Font.small ~x:(fx n) ~y:(2) ~s:(string_of_int (fx n)) gcolor;*)
-+ mypic#dashed_line ~x1:(fx n) ~y1:(ybt) ~x2:(fx n) ~y2:my_y gcolor;
-+ done;
-+ if my_sdivisions > 1 then
-+ for n = 0 to my_xdivisons - 1 do
-+ for m = 1 to my_sdivisions - 1 do
-+ mypic#dashed_line ~x1:(fxs n m) ~y1:(ybt) ~x2:(fxs n m) ~y2:my_y gcolor2;
-+ done;
- done
-
- let draw_y_grid mypic gcolor =
-- let my_x = (xbr()) in
-- let fy x = int_of_float ((((float_of_int x) /. (fydivisions())) *. (float_of_int(ybs()))) +. (float_of_int ybt)) in
-- for n = 1 to ydivisions() - 1 do
-- mypic#dashed_line ~x1:xbl ~y1:(fy n) ~x2:my_x ~y2:(fy n) gcolor;
-- done
-+ let fy x = (((x * ybs()) / y_divisions()) + ybt) in
-+ for n = 1 to y_divisions() - 1 do
-+ mypic#dashed_line ~x1:xbl ~y1:(fy n) ~x2:(xbr()) ~y2:(fy n) gcolor;
-+ done
-
- let draw_arrow mypic gcolor =
-- let my_x = (xbr()) in
-- let my_y = (ybb()) in
-+ let my_x = (xbr()+1) in
-+ let my_y = (ybb()+1) in
- mypic#line ~x1:(my_x - 4) ~y1:(my_y + 4) ~x2:(my_x + 4) ~y2:(my_y) gcolor;
- mypic#line ~x1:(my_x - 4) ~y1:(my_y - 4) ~x2:(my_x + 4) ~y2:(my_y) gcolor;
- mypic#line ~x1:(my_x - 4) ~y1:(my_y - 4) ~x2:(my_x - 4) ~y2:(my_y + 4) gcolor;
- mypic#fill ~x:(my_x - 1) ~y:(my_y - 1) gcolor;
-+ mypic#fill ~x:(my_x - 3) ~y:(my_y - 1) gcolor;
- mypic#fill ~x:(my_x - 1) ~y:(my_y + 1) gcolor;
- mypic#fill ~x:(my_x + 1) ~y:(my_y) gcolor
-
- let draw_tag mypic title gdown gup gcolor =
- let my_sum gl = List.fold_left (+) 0 (Fifo.to_list gl) in
-- let meanx gl = ((float_of_int (my_sum gl)) /. (float_of_int ((Fifo.length gl) - 1))) in
-+ let meanx gl = ((float_of_int (my_sum gl)) /. (float_of_int (Fifo.length gl))) in
- let down_bw = (string_of_float (float_of_int(int_of_float((meanx gdown) /. 1024. *. 100.)) /. 100.)) in
- let up_bw = (string_of_float (float_of_int(int_of_float((meanx gup) /. 1024. *. 100.)) /. 100.)) in
- let bw_d = "Dl: " ^ down_bw ^ "KB/s "
- and bw_u = "Ul: " ^ up_bw ^ "KB/s" in
- if !!html_mods_vd_gfx_tag_enable_title then
-- mypic#string ~font:Gd.Font.giant ~x:!!html_mods_vd_gfx_tag_title_x_pos ~y:!!html_mods_vd_gfx_tag_title_y_pos ~s:title gcolor;
-+ mypic#string ~font:Gd.Font.giant ~x:!!html_mods_vd_gfx_tag_title_x_pos ~y:!!html_mods_vd_gfx_tag_title_y_pos ~s:title gcolor;
- mypic#string ~font:Gd.Font.giant ~x:!!html_mods_vd_gfx_tag_dl_x_pos ~y:!!html_mods_vd_gfx_tag_dl_y_pos ~s:bw_d gcolor;
- mypic#string ~font:Gd.Font.giant ~x:!!html_mods_vd_gfx_tag_ul_x_pos ~y:!!html_mods_vd_gfx_tag_ul_y_pos ~s:bw_u gcolor
-
-@@ -218,16 +212,16 @@
- mypic#string_up ~font:Gd.Font.giant ~x:2 ~y:((win_y / 2) + (((String.length title) * 8) / 2)) ~s:title gcolor
-
- let draw_top_legend mypic title tcolor gcolor scolor win_y =
-- mypic#line ~x1:(xbl + 1) ~y1:9 ~x2:(xbl + 11) ~y2:9 scolor;
-+ mypic#line ~x1:xbl ~y1:9 ~x2:(xbl + 10) ~y2:9 scolor;
- mypic#line ~x1:xbl ~y1:8 ~x2:(xbl + 10) ~y2:8 gcolor;
- mypic#string ~font:Gd.Font.small ~x:(xbl + 16) ~y:2 ~s:title tcolor
-
- let draw_dual_top_legend mypic titlel tcolorl gcolorl scolorl titler tcolorr gcolorr scolorr win_y =
- let my_x = (xbr()) in
-- mypic#line ~x1:(xbl + 1) ~y1:9 ~x2:(xbl + 11) ~y2:9 scolorl;
-+ mypic#line ~x1:xbl ~y1:9 ~x2:(xbl + 10) ~y2:9 scolorl;
- mypic#line ~x1:xbl ~y1:8 ~x2:(xbl + 10) ~y2:8 gcolorl;
- mypic#string ~font:Gd.Font.small ~x:(xbl + 16) ~y:2 ~s:titlel tcolorl;
-- mypic#line ~x1:(my_x - 1) ~y1:9 ~x2:(my_x - 11) ~y2:9 scolorr;
-+ mypic#line ~x1:my_x ~y1:9 ~x2:(my_x - 10) ~y2:9 scolorr;
- mypic#line ~x1:my_x ~y1:8 ~x2:(my_x - 10) ~y2:8 gcolorr;
- mypic#string ~font:Gd.Font.small ~x:(my_x - (((String.length titler) * 8)) - 2) ~y:2 ~s:titler tcolorr
-
-@@ -246,7 +240,7 @@
- let my_y = (ybb() - (ybs() / 2)) in
- let fy x = int_of_float ((float_of_int my_y) -. (((float_of_int x) /. (y_fdivisions())) *. (float_of_int(ybs())))) in
- let vtext n = (string_of_float (float_of_int(int_of_float((float_of_int (my_y - (fy n))) /. (vdt_stack g) /. 1024. *. 100.)) /. 100.)) in
-- for n = 1 to ((y_divisions()) - 1) do
-+ for n = 1 to ((y_divisions()) / 2) do
- mypic#string ~font:Gd.Font.small ~x:(my_x + 5) ~y:((fy n) - 12 + offset) ~s:(vtext n) gcolor;
- done;
- mypic#string ~font:Gd.Font.small ~x:(my_x + 5) ~y:((fy (y_divisions())) - 5) ~s:(legend_text) lcolor
-@@ -256,151 +250,145 @@
- let my_y = (ybb() - (ybs() / 2)) in
- let fy x = int_of_float ((float_of_int my_y) +. (((float_of_int x) /. (y_fdivisions())) *. (float_of_int(ybs())))) in
- let vtext n = (string_of_float (float_of_int(int_of_float((float_of_int ((fy n) - my_y)) /. (vdt_stack g) /. 1024. *. 100.)) /. 100.)) in
-- for n = 1 to ((y_divisions()) - 1) do
-- mypic#string ~font:Gd.Font.small ~x:(my_x + 5) ~y:((fy n) - 12 + offset) ~s:(vtext n) gcolor;
-- done;
-- mypic#string ~font:Gd.Font.small ~x:(my_x + 5) ~y:((fy (y_divisions())) - 5) ~s:(legend_text) lcolor
-+ for n = 1 to ((y_divisions()) / 2) do
-+ mypic#string ~font:Gd.Font.small ~x:(my_x + 5) ~y:((fy n) - 12 + offset) ~s:(vtext n) gcolor;
-+ done;
-+ mypic#string ~font:Gd.Font.small ~x:(my_x + 5) ~y:((fy (y_divisions())) - 5) ~s:(legend_text) lcolor
-
--let draw_h_legend mypic g legend_text gcolor my_time =
-+let draw_h_legend mypic g legend_text gcolor my_time basetime show_days =
- let my_x = (xbr()) in
-- let my_x2 = (xbs()) in
- let my_y = (ybb()) in
-- let fx x = int_of_float((float_of_int my_x) -. (((float_of_int x) /. (x_fdivisions())) *. (float_of_int my_x2))) in
-- (* and vtext n = (string_of_int (int_of_float((float_of_int(n))*. vx ))) in *)
-- let basetime = Unix.gettimeofday () in
-- let timer n = Unix.localtime (basetime -. ((float_of_int(n)) *. float_of_int(my_time) *. vx())) in
-+ let fx x = my_x + 4 - (x * (xbs ()) / x_divisions ()) in
- let time_string n =
-- let time = timer n in
-- let h0 = string_of_int(time.Unix.tm_hour ) and (* H *)
-- m0 = string_of_int(time.Unix.tm_min ) and (* M *)
-- s0 = string_of_int(time.Unix.tm_sec ) in (* S *)
-- (if String.length h0 = 2 then h0 else "0"^h0) ^":"^
-- (if String.length m0 = 2 then m0 else "0"^m0) ^":"^
-- (if String.length s0 = 2 then s0 else "0"^s0) in
--
-- for n = 1 to ((x_divisions()) - 1) do
-- mypic#string ~font:Gd.Font.small ~x:((fx n) - ((String.length (time_string n) * 5) / 2)) ~y:(my_y + 5) ~s:(time_string n) gcolor;
-- done;
-- mypic#string ~font:Gd.Font.small ~x:((fx (x_divisions())) - ((String.length (legend_text) * 4) / 2)) ~y:(my_y + 5) ~s:(legend_text) gcolor
-+ let time = Unix.localtime (basetime -. float_of_int(n * my_time / x_divisions ())) in
-+ Printf.sprintf "%02d:%02d:%02d" time.Unix.tm_hour time.Unix.tm_min time.Unix.tm_sec
-+ in
-+ let day_string n =
-+ let time = Unix.localtime (basetime -. float_of_int(n * my_time / x_divisions ())) in
-+ Printf.sprintf "%02d.%02d." time.Unix.tm_mon time.Unix.tm_mday
-+ in
-+ if show_days then
-+ begin
-+ for n = 0 to (x_divisions() - 1) do
-+ mypic#string ~font:Gd.Font.small ~x:((fx n) - (String.length (time_string n) * 3) ) ~y:(my_y + 1) ~s:(time_string n) gcolor;
-+ mypic#string ~font:Gd.Font.small ~x:((fx n) - (String.length (day_string n) * 3) ) ~y:(my_y + 11) ~s:(day_string n) gcolor;
-+ done;
-+ mypic#string ~font:Gd.Font.small ~x:(4) ~y:(my_y + 2) ~s:(legend_text) gcolor;
-+ mypic#string ~font:Gd.Font.small ~x:(4) ~y:(my_y + 11) ~s:("t(DD.MM.)") gcolor
-+ end
-+ else
-+ begin
-+ for n = 0 to (x_divisions() - 1) do
-+ mypic#string ~font:Gd.Font.small ~x:((fx n) - (String.length (time_string n) * 3) ) ~y:(my_y + 5) ~s:(time_string n) gcolor;
-+ done;
-+ mypic#string ~font:Gd.Font.small ~x:(4) ~y:(my_y + 5) ~s:(legend_text) gcolor
-+ end
-
--let draw_load mypic g my_color shadow_color =
-+let draw_load mypic g my_color shadow_color my_samples =
- let my_x = (xbr()) in
-- let my_x2 = (xbs()) in
- let my_y = (ybb()) in
-+ let my_s = min ((Fifo.length g)-1) my_samples in
-+ let my_s2 = xbs() / my_samples / 4 in
- let datas g n = List.nth (List.rev (Fifo.to_list g)) n in
-- let fx x = int_of_float((float_of_int my_x) -. (((float_of_int x) /. (fxgdivisions())) *. (float_of_int my_x2)))
-+ let fx x = my_x - (x * (xbs ()) / my_samples)
- and y_c1 n = (my_y - (int_of_float(float_of_int(datas g n) *. (vdt_m g))))
- and y_c2 n = (my_y - (int_of_float(float_of_int(datas g (n+1)) *. (vdt_m g)))) in
- (if !!html_mods_vd_gfx_fill then begin
-- mypic#line ~x1:(fx 0) ~y1:my_y
-- ~x2:(fx 0) ~y2:(if y_c1 0 >= my_y - 3 then
-- ((y_c1 0) - 3) else ((y_c1 0))) shadow_color;
-- for n = 0 to ((graph_length(g)) - 1) do
-- (* trick to make sure filling will not fail *)
-- if n = ((graph_length(g)) - 1) then
-- mypic#line ~x1:((fx n)) ~y1:(if y_c1 n >= my_y - 3 then
-- ((y_c1 n) - 3) else ((y_c1 n))) ~x2:((fx (n+1))) ~y2:((y_c2 n)) shadow_color
-- else begin
-- mypic#line ~x1:((fx n)) ~y1:(if y_c1 n >= my_y - 3 then
-- ((y_c1 n) - 3) else ((y_c1 n)))
-- ~x2:((fx (n+1))) ~y2:(if y_c2 n >= my_y - 3 then
-- ((y_c2 n) - 3) else ((y_c2 n))) shadow_color
-- end
-- done;
-+ if my_s2 = 0 then
-+ for n = 0 to my_s - 1 do
-+ mypic#line ~x1:(fx n) ~y1:(min (my_y-1)(y_c1 n)) ~x2:(fx(n+1)) ~y2:(min (my_y-2)(y_c2 n)) shadow_color
-+ done
-+ else
-+ for n = 0 to my_s - 1 do
-+ mypic#line ~x1: (fx n) ~y1:(min (my_y - 1) (y_c1 n)) ~x2:((fx(n + 1)) + my_s2) ~y2:(min (my_y - 1) (y_c1 n)) shadow_color;
-+ mypic#line ~x1:((fx(n + 1)) + my_s2) ~y1:(min (my_y - 1) (y_c1 n)) ~x2: (fx(n + 1)) ~y2:(min (my_y - 1) (y_c2 n)) shadow_color
-+ done;
-+ if (fx my_s) > (xbl + 1) then
-+ mypic#line ~x1:(fx my_s) ~y1:(min (my_y - 1) (y_c1 my_s)) ~x2:(fx my_s) ~y2:(my_y) shadow_color;
- mypic#fill ~x:(my_x - 1) ~y:(my_y - 1) my_color;
- end
- else begin
-- for n = 0 to ((graph_length(g)) - 1) do
-- mypic#line ~x1:((fx n) + 1) ~y1:((y_c1 n) + 1) ~x2:((fx (n+1)) + 1) ~y2:((y_c2 n) + 1) shadow_color;
-- mypic#line ~x1:(fx n) ~y1:(y_c1 n) ~x2:(fx (n+1)) ~y2:(y_c2 n) my_color
-- done;
-+ if my_s2 = 0 then
-+ for n = 0 to my_s - 1 do
-+ mypic#line ~x1:((fx n)+1) ~y1:((y_c1 n)+1) ~x2:((fx (n+1))+1) ~y2:((y_c2 n)+1) shadow_color;
-+ mypic#line ~x1:( fx n) ~y1:(y_c1 n) ~x2:( fx (n+1)) ~y2:(y_c2 n) my_color
-+ done
-+ else
-+ for n = 0 to my_s - 1 do
-+ mypic#line ~x1:((fx n) + 1) ~y1:((y_c1 n)+1) ~x2:((fx(n + 1)) + 1 + my_s2) ~y2:((y_c1 n) + 1) shadow_color;
-+ mypic#line ~x1:((fx(n + 1)) + 1 + my_s2) ~y1:((y_c1 n)+1) ~x2:((fx(n + 1)) + 1) ~y2:((y_c2 n) + 1) shadow_color;
-+ mypic#line ~x1: (fx n) ~y1: (y_c1 n) ~x2:((fx(n + 1)) + my_s2) ~y2: (y_c1 n) my_color;
-+ mypic#line ~x1:((fx(n + 1)) + my_s2) ~y1: (y_c1 n) ~x2:( fx(n + 1)) ~y2: (y_c2 n) my_color
-+ done;
- end
- )
-
--let draw_stack_download mypic g my_color shadow_color =
-+let draw_stack_download mypic g my_color shadow_color my_samples =
- let my_x = (xbr()) in
- let my_x2 = (xbs()) in
-- let my_y = (ybb() - (ybs() / 2)) in
-+ let my_y = (ybt -1 + (ybs() / 2)) in
-+ let my_s = min ((Fifo.length g)-1) my_samples in
- let datas g n = List.nth (List.rev (Fifo.to_list g)) n in
-- let fx x = int_of_float((float_of_int my_x) -. (((float_of_int x) /. (fxgdivisions())) *. (float_of_int my_x2)))
-- and y_c1 n = (my_y - (int_of_float(float_of_int(datas g n) *. (vdt_stack g))))
-- and y_c2 n = (my_y - (int_of_float(float_of_int(datas g (n+1)) *. (vdt_stack g)))) in
-+ let fx x = my_x - (x * my_x2 / my_samples) and
-+ y_c1 n = my_y - int_of_float(float_of_int(datas g n) *. (vdt_stack g)) and
-+ y_c2 n = my_y - int_of_float(float_of_int(datas g (n+1)) *. (vdt_stack g))
-+ in
- (if !!html_mods_vd_gfx_fill then begin
-- mypic#line ~x1:(fx 0) ~y1:my_y
-- ~x2:(fx 0) ~y2:(if y_c1 0 >= my_y - 3 then
-- ((y_c1 0) - 3) else ((y_c1 0))) shadow_color;
-- for n = 0 to ((graph_length(g)) - 1) do
-- (* trick to make sure filling will not fail *)
-- if n = ((graph_length(g)) - 1) then
-- mypic#line ~x1:((fx n)) ~y1:(if y_c1 n >= my_y - 2 then
-- ((y_c1 n) - 2) else ((y_c1 n))) ~x2:((fx (n+1))) ~y2:((y_c2 n)) shadow_color
-- else begin
-- mypic#line ~x1:((fx n)) ~y1:(if y_c1 n >= my_y - 2 then
-- ((y_c1 n) - 2) else ((y_c1 n)))
-- ~x2:((fx (n+1))) ~y2:(if y_c2 n >= my_y - 2 then
-- ((y_c2 n) - 2) else ((y_c2 n))) shadow_color
-- end
-+ for n = 0 to my_s - 1 do
-+ mypic#line ~x1:(fx n) ~y1:(min (my_y-1) (y_c1 n)) ~x2:(fx(n+1)) ~y2:(min (my_y-1) (y_c2 n)) shadow_color
- done;
-- mypic#fill ~x:(my_x - 1) ~y:(my_y - 1) my_color;
-+ if (fx my_s) > (xbl+1) then
-+ mypic#line ~x1:(fx my_s) ~y1:(my_y) ~x2:(fx my_s) ~y2:(min (my_y) (y_c1 my_s)) shadow_color;
-+ mypic#fill ~x:(my_x) ~y:(my_y) my_color;
- end
- else begin
-- for n = 0 to ((graph_length(g)) - 1) do
-- mypic#line ~x1:((fx n) + 1) ~y1:((y_c1 n) + 1) ~x2:((fx (n+1)) + 1) ~y2:((y_c2 n) + 1) shadow_color;
-+ for n = 0 to my_s - 1 do
-+ mypic#line ~x1:((fx n)+1) ~y1:((y_c1 n)+1) ~x2:((fx (n+1))+1) ~y2:((y_c2 n)+1) shadow_color;
- mypic#line ~x1:(fx n) ~y1:(y_c1 n) ~x2:(fx (n+1)) ~y2:(y_c2 n) my_color
- done;
- end
- )
-
--let draw_stack_upload mypic g my_color shadow_color =
-+let draw_stack_upload mypic g my_color shadow_color my_samples =
- let my_x = (xbr()) in
- let my_x2 = (xbs()) in
-- let my_y = (ybb() - (ybs() / 2)) in
-+ let my_y = (ybt + 1 + (ybs() / 2)) in
-+ let my_s = min ((Fifo.length g)-1) my_samples in
- let datas g n = List.nth (List.rev (Fifo.to_list g)) n in
-- let fx x = int_of_float((float_of_int my_x) -. (((float_of_int x) /. (fxgdivisions())) *. (float_of_int my_x2)))
-+ let fx x = my_x - (x * my_x2 / my_samples)
- and y_c1 n = (my_y + (int_of_float(float_of_int(datas g n) *. (vdt_stack g))))
- and y_c2 n = (my_y + (int_of_float(float_of_int(datas g (n+1)) *. (vdt_stack g)))) in
- (if !!html_mods_vd_gfx_fill then begin
-- mypic#line ~x1:(fx 0) ~y1:my_y
-- ~x2:(fx 0) ~y2:(if y_c1 0 >= my_y - 3 then
-- ((y_c1 0) - 3) else ((y_c1 0))) shadow_color;
-- for n = 0 to ((graph_length(g)) - 1) do
-- (* trick to make sure filling will not fail *)
-- if n = ((graph_length(g)) - 1) then
-- mypic#line ~x1:((fx n)) ~y1:(if y_c1 n >= my_y + 2 then
-- ((y_c1 n) + 2) else ((y_c1 n))) ~x2:((fx (n+1))) ~y2:((y_c2 n)) shadow_color
-- else begin
-- mypic#line ~x1:((fx n)) ~y1:(if y_c1 n >= my_y + 2 then
-- ((y_c1 n) + 2) else ((y_c1 n)))
-- ~x2:((fx (n+1))) ~y2:(if y_c2 n >= my_y + 2 then
-- ((y_c2 n) + 2) else ((y_c2 n))) shadow_color
-- end
-+ for n = 0 to my_s - 1 do
-+ mypic#line ~x1:(fx n) ~y1:(max (my_y+1) (y_c1 n)) ~x2:(fx(n+1)) ~y2:(max (my_y+1) (y_c2 n)) shadow_color
- done;
-- mypic#fill ~x:(my_x - 1) ~y:(my_y + 1) my_color;
-+ if (fx my_s) > xbl+1 then
-+ mypic#line ~x1:(fx my_s) ~y1:(my_y) ~x2:(fx my_s) ~y2:(max my_y (y_c1 my_s)) shadow_color;
-+ mypic#fill ~x:(my_x) ~y:(my_y) my_color
- end
- else begin
-- for n = 0 to ((graph_length(g)) - 1) do
-- mypic#line ~x1:((fx n) + 1) ~y1:((y_c1 n) + 1) ~x2:((fx (n+1)) + 1) ~y2:((y_c2 n) + 1) shadow_color;
-- mypic#line ~x1:(fx n) ~y1:(y_c1 n) ~x2:(fx (n+1)) ~y2:(y_c2 n) my_color
-+ for n = 0 to my_s - 1 do
-+ mypic#line ~x1:((fx n)+1) ~y1:(max (my_y+1)((y_c1 n)+1)) ~x2:((fx (n+1))+1) ~y2:(max (my_y+1)((y_c2 n)+1)) shadow_color;
-+ mypic#line ~x1:( fx n) ~y1:(max (my_y+1)(y_c1 n)) ~x2:( fx (n+1)) ~y2:(max (my_y+1)(y_c2 n)) my_color
- done;
- end
- )
-
--
--let draw_mean_line mypic g my_color gcolor =
-- let my_x2 = (xbs())
-- and my_y = (ybb()) in
-+let draw_mean_line mypic g my_color shadow_color tcolor =
- let my_sum gl = List.fold_left (+) 0 (Fifo.to_list gl) in
- let meanx() = ((float_of_int (my_sum g)) /. (float_of_int ((Fifo.length g)))) in
-- let ypos = (my_y - (int_of_float((meanx()) *. (vdt_m g)))) in
-+ let ypos = (ybb() - int_of_float(meanx() *. vdt_m g)) in
- let vtext = (string_of_float (float_of_int(int_of_float(meanx() /. 1024. *. 100.)) /. 100.)) in
-- mypic#line ~x1:xbl ~y1:(ypos - 1) ~x2:(xbl + my_x2 / 10) ~y2:(ypos - 1) my_color;
-- mypic#line ~x1:xbl ~y1:(ypos) ~x2:(xbl + my_x2 / 10) ~y2:(ypos) gcolor;
-- mypic#string ~font:Gd.Font.small ~x:(xbl + 5) ~y:((ypos) + 2) ~s:(vtext) gcolor
-+ mypic#line ~x1:(xbl) ~y1:(ypos) ~x2:(xbl+1+ xbs() / x_divisions()) ~y2:(ypos) my_color;
-+ if ypos+1 < ybb() then
-+ mypic#line ~x1:(xbl) ~y1:(ypos+1) ~x2:(xbl+1+ xbs() / x_divisions()) ~y2:(ypos+1) shadow_color;
-+ mypic#string ~font:Gd.Font.small ~x:(xbl) ~y:(ypos +2 ) ~s:(vtext) tcolor
-
- let draw_mygraph mypic ttl top_title vl hl g =
- (* init pic *)
- (
- let g_y = win_y() in
-+ let mypic = Gd.create ~x:(win_x()) ~y:g_y in
- (* set colors *)
- let black = mypic#colors#black in
- let red = mypic#colors#red in
-@@ -412,11 +400,11 @@
- draw_title mypic ttl black g_y;
- draw_top_legend mypic top_title black red darkgrey g_y;
- draw_v_legend mypic g vl black black 0;
-- draw_h_legend mypic g hl black samples_time;
-- draw_load mypic g green darkgrey;
-- draw_x_grid mypic black;
-+ draw_h_legend mypic g hl black history_time !history_timeflag false;
-+ draw_load mypic g green darkgrey history_size;
-+ draw_x_grid mypic black darkgrey (x_divisions());
- draw_y_grid mypic black;
-- (* draw_mean_line mypic gdown green black; *)
-+ (* draw_mean_line mypic gdown green darkgrey black; *)
- )
-
- (* end of declarations *)
-@@ -444,13 +432,13 @@
- draw_borders mypic black;
- draw_title mypic ttl black win_y;
- draw_v_legend mypic vl black black 0;
-- draw_h_legend mypic gdown hl black samples_time;
-- draw_load mypic gdown green darkgrey;
-- draw_load mypic gup red darkgrey;
-- draw_x_grid mypic black;
-+ draw_h_legend mypic gdown hl black history_time !history_timeflag false;
-+ draw_load mypic gdown green darkgrey history_size;
-+ draw_load mypic gup red darkgrey history_size;
-+ draw_x_grid mypic black darkgrey (x_divisions());
- draw_y_grid mypic black;
-
--(* draw_mean_line mypic gdown green black;*)
-+ (* draw_mean_line mypic gdown green darkgrey black;*)
- (* mypic#out_as_jpeg "line.jpg" ~quality:90; *)
-
- *)
-@@ -477,16 +465,16 @@
- (* draw graph *)
- draw_title mypic ttl black g_y;
- draw_dual_top_legend mypic "download" black green darkgrey "upload" black red darkgrey g_y;
-- draw_h_legend mypic gdown hl black samples_time;
-+ draw_h_legend mypic gdown hl black history_time !history_timeflag false;
- (if !!html_mods_vd_gfx_stack then begin
- draw_stack_borders mypic black;
- draw_stack_v_top_legend mypic gdown vl black darkgreen 5;
- draw_stack_v_bottom_legend mypic gup vl black darkred 5;
- (* enable filling for stack graph *)
- if not !!html_mods_vd_gfx_fill then html_mods_vd_gfx_fill =:= true;
-- draw_stack_download mypic gdown green darkgrey;
-- draw_stack_upload mypic gup red darkgrey;
-- draw_x_grid mypic black;
-+ draw_stack_download mypic gdown green darkgrey history_size;
-+ draw_stack_upload mypic gup red darkgrey history_size;
-+ draw_x_grid mypic black darkgrey (x_divisions());
- draw_y_grid mypic black
- end
- else begin
-@@ -494,13 +482,13 @@
- draw_v_legend mypic gdown vl black darkgreen 0;
- draw_v_legend mypic gup vl black darkred 10;
- if !!html_mods_vd_gfx_fill then html_mods_vd_gfx_fill =:= false;
-- draw_load mypic gdown green darkgrey;
-- draw_load mypic gup red darkgrey;
-- draw_x_grid mypic black;
-- draw_y_grid mypic black;
-+ draw_load mypic gdown green darkgrey history_size;
-+ draw_load mypic gup red darkgrey history_size;
-+ draw_x_grid mypic black darkgrey (x_divisions());
-+ draw_y_grid mypic black;
- (if !!html_mods_vd_gfx_mean then
-- draw_mean_line mypic gdown green black;
-- draw_mean_line mypic gup red black
-+ draw_mean_line mypic gdown green darkgrey black;
-+ draw_mean_line mypic gup red darkgrey black
- );
- end);
- draw_arrow mypic darkred;
-@@ -514,9 +502,8 @@
- let do_draw_down_pic ttl top_title vl hl gdown =
- (* init pic *)
- (
-- let g_x = win_x() in
- let g_y = win_y() in
-- let mypic = Gd.create ~x:g_x ~y:g_y in
-+ let mypic = Gd.create ~x:(win_x()) ~y:g_y in
-
- (* set colors *)
- let white = mypic#colors#white in
-@@ -532,13 +519,13 @@
- draw_title mypic ttl black g_y;
- draw_top_legend mypic top_title black green darkgrey g_y;
- draw_v_legend mypic gdown vl black black 6;
-- draw_h_legend mypic gdown hl black samples_time;
-- draw_load mypic gdown green darkgrey;
-- draw_x_grid mypic black;
-+ draw_h_legend mypic gdown hl black history_time !history_timeflag false;
-+ draw_load mypic gdown green darkgrey history_size;
-+ draw_x_grid mypic black darkgrey (x_divisions());
- draw_y_grid mypic black;
- draw_arrow mypic darkred;
- if !!html_mods_vd_gfx_mean then
-- draw_mean_line mypic gdown green black;
-+ draw_mean_line mypic gdown green darkgrey black;
-
- (if !!html_mods_vd_gfx_png then
- mypic#save_as_png "bw_download.png"
-@@ -550,9 +537,8 @@
- let do_draw_up_pic ttl top_title vl hl gup =
- (* init pic *)
- (
-- let g_x = win_x() in
- let g_y = win_y() in
-- let mypic = Gd.create ~x:g_x ~y:g_y in
-+ let mypic = Gd.create ~x:(win_x()) ~y:g_y in
-
- (* set colors *)
- let white = mypic#colors#white in
-@@ -568,13 +554,13 @@
- draw_title mypic ttl black g_y;
- draw_top_legend mypic top_title black red darkgrey g_y;
- draw_v_legend mypic gup vl black black 6;
-- draw_h_legend mypic gup hl black samples_time;
-- draw_load mypic gup red darkgrey;
-- draw_x_grid mypic black;
-+ draw_h_legend mypic gup hl black history_time !history_timeflag false;
-+ draw_load mypic gup red darkgrey history_size;
-+ draw_x_grid mypic black darkgrey (x_divisions());
- draw_y_grid mypic black;
- draw_arrow mypic darkred;
- if !!html_mods_vd_gfx_mean then
-- draw_mean_line mypic gup red black;
-+ draw_mean_line mypic gup red darkgrey black;
-
- (if !!html_mods_vd_gfx_png then
- mypic#save_as_png "bw_upload.png"
-@@ -588,7 +574,8 @@
- (
- let g_y = win_y() in
- let mypic = Gd.create ~x:(win_x()) ~y:g_y in
--
-+ let x_legend_days = (int_of_float !history_h_timeflag) mod 86400 < (x_h_time gdown) in
-+
- (* set colors *)
- let white = mypic#colors#white in
- let black = mypic#colors#black in
-@@ -606,16 +593,16 @@
- draw_dual_top_legend mypic "download" black green darkgrey "upload" black red darkgrey g_y;
- draw_v_legend mypic gdown vl black darkgreen 0;
- draw_v_legend mypic gup vl black darkred 10;
-- draw_h_legend mypic gdown hl black samples_h_time;
-+ draw_h_legend mypic gup hl black (x_h_time gdown) !history_h_timeflag x_legend_days;
- if !!html_mods_vd_gfx_fill then html_mods_vd_gfx_fill =:= false;
-- draw_load mypic gdown green darkgrey;
-- draw_load mypic gup red darkgrey;
-- draw_x_grid mypic black;
-+ draw_load mypic gdown green darkgrey (x_h_values gdown);
-+ draw_load mypic gup red darkgrey (x_h_values gdown);
-+ draw_x_grid mypic black darkgrey (x_divisions());
- draw_y_grid mypic black;
- draw_arrow mypic darkred;
- (if !!html_mods_vd_gfx_mean then
-- draw_mean_line mypic gdown green black;
-- draw_mean_line mypic gup red black
-+ draw_mean_line mypic gdown green darkgrey black;
-+ draw_mean_line mypic gup red darkgrey black
- );
- (if !!html_mods_vd_gfx_png then
- mypic#save_as_png "bw_h_updown.png"
-@@ -627,9 +614,9 @@
- let do_draw_down_h_pic ttl top_title vl hl gdown =
- (* init pic *)
- (
-- let g_x = win_x() in
- let g_y = win_y() in
-- let mypic = Gd.create ~x:g_x ~y:g_y in
-+ let mypic = Gd.create ~x:(win_x()) ~y:g_y in
-+ let x_legend_days = (int_of_float !history_h_timeflag) mod 86400 < (x_h_time gdown) in
-
- (* set colors *)
- let white = mypic#colors#white in
-@@ -645,13 +632,13 @@
- draw_title mypic ttl black g_y;
- draw_top_legend mypic top_title black green darkgrey g_y;
- draw_v_legend mypic gdown vl black black 6;
-- draw_h_legend mypic gdown hl black samples_h_time;
-- draw_load mypic gdown green darkgrey;
-- draw_x_grid mypic black;
-+ draw_h_legend mypic gdown hl black (x_h_time gdown) !history_h_timeflag x_legend_days;
-+ draw_load mypic gdown green darkgrey (x_h_values gdown);
-+ draw_x_grid mypic black darkgrey (x_divisions());
- draw_y_grid mypic black;
- draw_arrow mypic darkred;
- if !!html_mods_vd_gfx_mean then
-- draw_mean_line mypic gdown green black;
-+ draw_mean_line mypic gdown green darkgrey black;
-
- (if !!html_mods_vd_gfx_png then
- mypic#save_as_png "bw_h_download.png"
-@@ -663,9 +650,9 @@
- let do_draw_up_h_pic ttl top_title vl hl gup =
- (* init pic *)
- (
-- let g_x = win_x() in
- let g_y = win_y() in
-- let mypic = Gd.create ~x:g_x ~y:g_y in
-+ let x_legend_days = (int_of_float !history_h_timeflag) mod 86400 < (x_h_time gup) in
-+ let mypic = Gd.create ~x:(win_x()) ~y:g_y in
-
- (* set colors *)
- let white = mypic#colors#white in
-@@ -681,13 +668,13 @@
- draw_title mypic ttl black g_y;
- draw_top_legend mypic top_title black red darkgrey g_y;
- draw_v_legend mypic gup vl black black 6;
-- draw_h_legend mypic gup hl black samples_h_time;
-- draw_load mypic gup red darkgrey;
-- draw_x_grid mypic black;
-+ draw_h_legend mypic gup hl black (x_h_time gup) !history_h_timeflag x_legend_days;
-+ draw_load mypic gup red darkgrey (x_h_values gup);
-+ draw_x_grid mypic black darkgrey (x_divisions());
- draw_y_grid mypic black;
- draw_arrow mypic darkred;
- if !!html_mods_vd_gfx_mean then
-- draw_mean_line mypic gup red black;
-+ draw_mean_line mypic gup red darkgrey black;
-
- (if !!html_mods_vd_gfx_png then
- mypic#save_as_png "bw_h_upload.png"
-Index: src/daemon/driver/driverInteractive.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/driver/driverInteractive.ml,v
-retrieving revision 1.101
-retrieving revision 1.115
-diff -u -r1.101 -r1.115
---- src/daemon/driver/driverInteractive.ml 7 Sep 2006 10:55:11 -0000 1.101
-+++ src/daemon/driver/driverInteractive.ml 21 Nov 2006 22:34:33 -0000 1.115
-@@ -21,6 +21,8 @@
-
- open Printf2
- open CommonClient
-+open CommonShared
-+open CommonServer
- open CommonNetwork
- open CommonResult
- open CommonFile
-@@ -49,19 +51,11 @@
- lprintf2 log_prefix fmt
-
- let verify_user_admin () =
-- let empty_pwd = ref false in
-- begin try
-- if user2_password admin_user = blank_password then
-- empty_pwd := true
-- with e ->
-- lprintf_nl (_b "SECURITY INFO: user 'admin' has to be present, creating...");
-- empty_pwd := true;
-- ignore (user2_add admin_user blank_password "")
-- end;
- let warning =
- "SECURITY WARNING: user admin has an empty password, use command: useradd admin password\n"
- in
-- if !empty_pwd && not !!enable_user_config then
-+ if has_empty_password admin_user && !!allowed_ips <>
-+ [(Ip.range_of_string (strings_of_option allowed_ips).option_default)] then
- begin
- lprintf_n "%s" warning;
- warning
-@@ -83,6 +77,7 @@
- let s =
- !startup_message ^ (verify_user_admin ()) ^ (check_supported_os ())
- ^ (if not !dns_works then "DNS resolution does not work\n" else "")
-+ ^ (if not !Charset.conversion_enabled then "Charset conversion does not work, disabled\n" else "")
- ^ (match !created_new_base_directory with
- None -> ""
- | Some dir -> (Printf.sprintf "MLDonkey created a new home directory in %s\n" dir))
-@@ -239,6 +234,8 @@
- then file_availability f
- else string_availability f.file_availability
-
-+let number_of_comments f =
-+ List.length f.file_comments
-
- (* WARNING: these computations are much more expensive as they seem.
- We use the ShortLazy to avoid recomputing the result too many times,
-@@ -575,7 +572,7 @@
- Printf.bprintf buf "\\</form\\>"
-
-
-- let print_file_html_mods buf guifiles =
-+let print_file_html_mods buf guifiles =
-
- if (List.length guifiles) > 0 then begin
- let tsize = ref Int64.zero in
-@@ -636,7 +633,7 @@
- \\<div class=main\\>";
-
- if !!html_mods_use_js_tooltips then Printf.bprintf buf
--"\\<div id=\\\"object1\\\" style=\\\"position:absolute; background-color:FFFFDD;color:black;border-color:black;border-width:20;font-size:8pt; visibility:show; left:25px; top:
-+"\\<div id=\\\"object1\\\" style=\\\"position:absolute; background-color:#FFFFDD;color:black;border-color:black;border-width:20px;font-size:8pt; visibility:visible; left:25px; top:
- -100px; z-index:+1\\\" onmouseover=\\\"overdiv=1;\\\" onmouseout=\\\"overdiv=0; setTimeout(\\\'hideLayer()\\\',1000)\\\"\\>\\&nbsp;\\</div\\>";
-
- Printf.bprintf buf "\\<form id=\\\"selectForm\\\" name=\\\"selectForm\\\" action=\\\"files\\\"\\>
-@@ -660,7 +657,8 @@
-
- \\<td title=\\\"Pause\\\" class=\\\"dlheader np\\\"\\>P\\</td\\>
- \\<td title=\\\"Resume\\\" class=\\\"dlheader np\\\"\\>R\\</td\\>
--\\<td title=\\\"Cancel\\\" class=\\\"dlheader brs\\\"\\>C\\</td\\>"
-+\\<td title=\\\"Cancel\\\" class=\\\"dlheader brs\\\"\\>C\\</td\\>
-+\\<td title=\\\"Click to switch release status\\\" class=\\\"dlheader brs\\\"\\>R\\</td\\>"
- (if !qnum > 0 then begin
- Printf.sprintf "title=\\\"Active(%d): %s/%s | Queued(%d): %s/%s\\\""
- (List.length guifiles - !qnum) (size_of_int64 (!tdl -- !qdl)) (size_of_int64 (!tsize -- !qsize))
-@@ -670,17 +668,24 @@
- (List.length guifiles) (size_of_int64 !tdl) (size_of_int64 !tsize) (!trate /. 1024.)
- (let unread = ref 0 in
- Fifo.iter (fun (t,i,num,n,s) -> if t > !last_message_log then incr unread) chat_message_fifo;
--if !unread > 0 then Printf.sprintf "\\<td class=downloaded title=\\\"%d unread messages\\\"\\>(+%d)\\&nbsp;\\</td\\>" !unread !unread else "");
-+if !unread > 0 then Printf.sprintf "\\<td class=downloaded title=\\\"%d unread messages\\\"\\>\\<a onClick=\\\"mSub('fstatus','version');mSub('output','message')\\\"\\>(+%d)\\</a\\>\\&nbsp;\\</td\\>" !unread !unread else "");
-
- if !!html_mods_vd_network then Printf.bprintf buf
- "\\<td title=\\\"Sort by network\\\" class=dlheader\\>\\<input style=\\\"padding-left: 0px; padding-right: 0px;\\\" class=headbutton type=submit value=N name=sortby\\>\\</td\\>";
-
- Printf.bprintf buf
--"\\<td title=\\\"Sort by filename\\\" class=dlheader\\>\\<input class=headbutton type=submit value=File name=sortby\\>\\</td\\>
--\\<td title=\\\"Sort by size\\\" class=dlheader\\>\\<input class=headbutton type=submit value=Size name=sortby\\>\\</td\\>
-+"\\<td title=\\\"Sort by filename\\\" class=dlheader\\>\\<input class=headbutton type=submit value=File name=sortby\\>\\</td\\>";
-+
-+if !!html_mods_vd_user then Printf.bprintf buf
-+"\\<td title=\\\"Sort by user\\\" class=dlheader\\>\\<input class=headbutton type=submit value=User name=sortby\\>\\</td\\>";
-+
-+if !!html_mods_vd_group then Printf.bprintf buf
-+"\\<td title=\\\"Sort by group\\\" class=dlheader\\>\\<input class=headbutton type=submit value=Group name=sortby\\>\\</td\\>";
-+
-+Printf.bprintf buf
-+"\\<td title=\\\"Sort by size\\\" class=dlheader\\>\\<input class=headbutton type=submit value=Size name=sortby\\>\\</td\\>
- \\<td title=\\\"Sort by size downloaded\\\" class=dlheader\\>\\<input class=\\\"headbutton ar\\\" type=submit value=DLed name=sortby\\>\\</td\\>
- \\<td title=\\\"Sort by percent\\\" class=dlheader\\>\\<input class=headbutton type=submit value=%% name=sortby\\>\\</td\\>";
--
- if !!html_mods_vd_comments then Printf.bprintf buf
- "\\<td title=\\\"Sort by comments\\\" class=dlheader\\>\\<input style=\\\"padding-left: 0px; padding-right: 0px;\\\" class=headbutton type=submit value=Cm name=sortby\\>\\</td\\>";
-
-@@ -715,26 +720,36 @@
- [|
- (if !!html_mods_use_js_tooltips then
- Printf.sprintf "
-- onMouseOver=\\\"mOvr(this);setTimeout('popLayer(\\\\\'%s<br>%sFile#: %d<br>Network: %s%s\\\\\')',%d);setTimeout('hideLayer()',%d);return true;\\\" onMouseOut=\\\"mOut(this);hideLayer();setTimeout('hideLayer()',%d)\\\"\\>"
-- (Http_server.html_real_escaped file.file_name)
-+ onMouseOver=\\\"mOvr(this);setTimeout('popLayer(\\\\\'%s<br>%sFile#: %d<br>Network: %s<br>User%s %s%s%s\\\\\')',%d);setTimeout('hideLayer()',%d);return true;\\\" onMouseOut=\\\"mOut(this);hideLayer();setTimeout('hideLayer()',%d)\\\"\\>"
-+ (Http_server.html_real_escaped (Charset.to_utf8 file.file_name))
- (match file_magic (file_find file.file_num) with
- None -> ""
- | Some magic -> "File type: " ^ (Http_server.html_real_escaped magic) ^ "<br>")
- file.file_num
- (net_name file)
-- (let comments = file_comment (file_find file.file_num) in
-- if comments = [] then "" else
-+ (if file.file_group = "none" then "" else ":Group")
-+ file.file_user
-+ (if file.file_group = "none" then "" else Printf.sprintf ":%s" file.file_group)
-+
-+ (if file.file_comments = [] then "" else
- begin
-- let buf1 = Buffer.create 100 in
-- Printf.bprintf buf1 "<br><br>Comments:<br>";
-- List.iter (fun s -> Printf.bprintf buf1 "%s<br>" (Http_server.html_real_escaped s)) comments;
-+ let num_comments = number_of_comments file in
-+ let buf1 = Buffer.create (!!max_comment_length * num_comments) in
-+ Printf.bprintf buf1 "<br><br>Comments(%d):<br>" (num_comments);
-+ let comments =
-+ if List.length file.file_comments > 5 then
-+ fst (List2.cut 5 file.file_comments) @ [Ip.null, "", 0, (_s "MLDonkey note: click file for more comments")]
-+ else
-+ file.file_comments
-+ in
-+ List.iter (fun (_,_,_,s) -> Printf.bprintf buf1 "%s<br>" (Http_server.html_real_escaped (Charset.to_utf8 s))) comments;
- Buffer.contents buf1
- end)
-+
- !!html_mods_js_tooltips_wait
- !!html_mods_js_tooltips_timeout
- !!html_mods_js_tooltips_wait
-- else Printf.sprintf "
-- onMouseOver=\\\"mOvr(this);return true;\\\" onMouseOut=\\\"mOut(this);\\\"\\>");
-+ else Printf.sprintf " onMouseOver=\\\"mOvr(this);return true;\\\" onMouseOut=\\\"mOut(this);\\\"\\>");
-
- (if downloading file then
- Printf.sprintf "\\<td class=\\\"dl al np\\\"\\>\\<input class=checkbox name=pause type=checkbox value=%d\\>\\</td\\>
-@@ -749,6 +764,10 @@
- file.file_num
- file.file_num);
-
-+ Printf.sprintf "\\<td onClick=\\\"location.href='files?%s=%d';return true;\\\" class=\\\"dl al brs\\\"\\>\\%s\\</td\\>"
-+ (if file.file_release then "norelease" else "release")
-+ file.file_num (if file.file_release then "R" else "-");
-+
- (if !!html_mods_vd_network then
- Printf.sprintf "\\<td onClick=\\\"location.href='submit?q=vd+%d';return true;\\\"
- title=\\\"%s\\\" class=\\\"dl al\\\"\\>%s\\</td\\>"
-@@ -772,14 +791,14 @@
- (truncate ( (1. -. downloaded /. size) *. 100.))
- else
- Printf.sprintf "\\<TD onClick=\\\"location.href='submit?q=vd+%d';return true;\\\"
-- title=\\\"[File#: %d] [Net: %s]%s\\\" class=\\\"dl al\\\"\\>%s\\<br\\>
-+ title=\\\"[File#: %d] [Net: %s] [Comments: %d]%s\\\" class=\\\"dl al\\\"\\>%s\\<br\\>
- \\<table cellpadding=0 cellspacing=0 width=100%%\\>\\<tr\\>
- \\<td class=\\\"loaded\\\" style=\\\"height:%dpx\\\" width=\\\"%d%%\\\"\\> \\</td\\>
- \\<td class=\\\"remain\\\" style=\\\"height:%dpx\\\" width=\\\"%d%%\\\"\\> \\</td\\>
- \\</tr\\>\\</table\\>\\</td\\>"
- file.file_num
- file.file_num
-- (net_name file)
-+ (net_name file) (number_of_comments file)
- (if !!max_name_len < String.length file.file_name then " " ^ file.file_name else "")
- (short_name file)
- (!!html_vd_barheight)
-@@ -788,14 +807,16 @@
- (truncate ( (1. -. downloaded /. size) *. 100.)));
- );
-
-+ (if !!html_mods_vd_user then ctd file.file_num file.file_user else "");
-+ (if !!html_mods_vd_group then ctd file.file_num file.file_group else "");
-+
- (ctd file.file_num (size_of_int64 file.file_size));
- (ctd file.file_num (size_of_int64 file.file_downloaded));
- (ctd file.file_num (Printf.sprintf "%.1f" (percent file)));
-
- (if !!html_mods_vd_comments then
-- Printf.sprintf "\\<td onClick=\\\"location.href='submit?q=vd+%d';return true;\\\"
-- class=\\\"dl al\\\"\\>%d\\</td\\>"
-- file.file_num (file_comment_length (file_find file.file_num)) else "");
-+ ctd file.file_num (Printf.sprintf "%d" (number_of_comments file))
-+ else "");
-
- (ctd file.file_num (Printf.sprintf "%d" (number_of_sources file)));
-
-@@ -936,7 +957,7 @@
- else
- print_table buf
- [|
-- Align_Left; Align_Left; Align_Right; Align_Right;
-+ Align_Left; Align_Left; Align_Right; Align_Left; Align_Left; Align_Left;
- Align_Right; Align_Right; Align_Right |]
- (if format.conn_output = HTML then
- [|
-@@ -951,6 +972,10 @@
- |] else
- [|
- "$nNum";
-+ "Rele";
-+ "Comm";
-+ "User";
-+ "Group";
- "File";
- " %";
- " Done";
-@@ -995,6 +1020,10 @@
- file.file_num
- (if downloading file then "PAUSE" else "RESUME")
- else ""));
-+ (Printf.sprintf "%s" (if file.file_release then "R" else "-"));
-+ (Printf.sprintf "%4d" (number_of_comments file));
-+ file.file_user;
-+ file.file_group;
- (short_name file);
- (Printf.sprintf "%3.1f" (percent file));
- (if !!improved_telnet then (print_human_readable file file.file_downloaded)
-@@ -1112,7 +1141,9 @@
- | ByLast -> (fun f1 f2 -> f1.file_last_seen >= f2.file_last_seen)
- | ByNet -> (fun f1 f2 -> net_name f1 <= net_name f2)
- | ByAvail -> (fun f1 f2 -> get_file_availability f1 >= get_file_availability f2)
-- | ByComments -> (fun f1 f2 -> file_comment_length (file_find f1.file_num) >= file_comment_length (file_find f2.file_num))
-+ | ByComments -> (fun f1 f2 -> (number_of_comments f1) >= (number_of_comments f2))
-+ | ByUser -> (fun f1 f2 -> f1.file_user <= f2.file_user)
-+ | ByGroup -> (fun f1 f2 -> f1.file_group <= f2.file_group)
- | NotSorted -> raise Not_found
- in
- Sort.list sorter list
-@@ -1158,7 +1189,7 @@
- let counter = ref 0 in
- if use_html_mods o then
- begin
-- if !!html_mods_use_js_tooltips then Printf.bprintf buf "\\<div id=\\\"object1\\\" style=\\\"position:absolute; background-color:FFFFDD;color:black;border-color:black;border-width:20;font-size:8pt; visibility:show; left:25px; top:-100px; z-index:+1\\\" onmouseover=\\\"overdiv=1;\\\" onmouseout=\\\"overdiv=0; setTimeout(\\\'hideLayer()\\\',1000)\\\"\\>\\&nbsp;\\</div\\>\n";
-+ if !!html_mods_use_js_tooltips then Printf.bprintf buf "\\<div id=\\\"object1\\\" style=\\\"position:absolute; background-color:#FFFFDD;color:black;border-color:black;border-width:20px;font-size:8pt; visibility:visible; left:25px; top:-100px; z-index:+1\\\" onmouseover=\\\"overdiv=1;\\\" onmouseout=\\\"overdiv=0; setTimeout(\\\'hideLayer()\\\',1000)\\\"\\>\\&nbsp;\\</div\\>\n";
- html_mods_table_header_colspan buf "resultsTable" "results" [
- ( "1", "0", "srh", "Network", "Network" ) ;
- ( "1", "0", "srh", "File", "File (mouseover)" ) ;
-@@ -1703,7 +1734,8 @@
- ( "0", "srh br", "Has search", "Search" ) ;
- ( "0", "srh br", "Has chat", "Chat" ) ;
- ( "0", "srh br", "Has rooms", "Rooms" ) ;
-- ( "0", "srh", "Has multinet", "Multinet" ) ]
-+ ( "0", "srh", "Has multinet", "Multinet" ) ;
-+ ( "0", "srh", "Has porttest", "Porttest" ) ]
-
- let print_network_modules buf o =
- let buf = o.conn_buf in
-@@ -1718,6 +1750,10 @@
- if not (List.mem VirtualNetwork n.network_flags) then
- try
- let net_has e = if List.mem e n.network_flags then "yes" else "" in
-+ let net_has_porttest () =
-+ match network_porttest_result n with
-+ PorttestNotAvailable -> ""
-+ | _ -> "yes" in
- Printf.bprintf buf "\\<tr class=\\\"dl-%d\\\"\\>" (html_mods_cntr ());
- html_mods_td buf [
- ("", "sr br", n.network_name);
-@@ -1728,7 +1764,8 @@
- ("", "sr br", net_has NetworkHasSearch);
- ("", "sr br", net_has NetworkHasChat);
- ("", "sr br", net_has NetworkHasRooms);
-- ("", "sr" , net_has NetworkHasMultinet); ];
-+ ("", "sr br", net_has NetworkHasMultinet);
-+ ("", "sr" , (net_has_porttest ())); ];
- Printf.bprintf buf "\\</tr\\>";
- with _ -> ()
- );
-@@ -1867,7 +1904,8 @@
- tack list
- (
- "Features:\t",
-- (if BasicSocket.has_threads () then "threads" else "no-threads") ^
-+ ("multiuser") ^
-+ (if BasicSocket.has_threads () then " threads" else " no-threads") ^
- (let s = Zlib.zlib_version_num () in
- Printf.sprintf " zlib%s" (if s <> "" then "-" ^ s else "")) ^
- (if Autoconf.bzip2 then
-@@ -1886,7 +1924,10 @@
- " gd(jpg)"
- | _, false, false ->
- " gd(neither jpg nor png ?)") ^
-- (if Autoconf.has_iconv then " iconv" else " no-iconv") ^
-+ (match Autoconf.has_iconv, !Charset.conversion_enabled with
-+ | true, true -> " iconv(active)"
-+ | true, false -> " iconv(inactive)"
-+ | false, _ -> " no-iconv") ^
- (match Autoconf.magic, !Autoconf.magic_works with
- | true, true -> " magic(active)"
- | true, false -> " magic(inactive)"
-@@ -1924,8 +1965,8 @@
- (
- "User:\t\t",
- Printf.sprintf "%s (%s) - uptime: %s"
-- o.conn_user.ui_user_name
-- (if empty_password o.conn_user.ui_user_name then "Warning: empty Password"
-+ o.conn_user.ui_user.user_name
-+ (if has_empty_password o.conn_user.ui_user then "Warning: empty Password"
- else "PW Protected")
- (Date.time_to_string (last_time () - start_time) "verbose")
- );
-@@ -2089,8 +2130,8 @@
- let len_dir = ref 9 in
- let len_strategy = ref 29 in (* "shared (incoming_directories)" *)
- List.iter ( fun (dir, strategy) ->
-- len_dir := maxi !len_dir (String.length dir);
-- len_strategy := maxi !len_strategy (String.length strategy)
-+ len_dir := max !len_dir (String.length dir);
-+ len_strategy := max !len_strategy (String.length strategy)
- ) !list;
- let fill_dir = String.make (!len_dir - 9) ' ' in
- let fill_dir_line = String.make (!len_dir - 9) '-' in
-@@ -2139,8 +2180,8 @@
- end
- else
- Printf.bprintf buf "%-*s|%-*s|%8s|%8s|%5s|%-s\n"
-- (maxi !len_dir (!len_dir - String.length dir)) dir
-- (maxi !len_strategy (!len_strategy - String.length strategy)) strategy
-+ (max !len_dir (!len_dir - String.length dir)) dir
-+ (max !len_strategy (!len_strategy - String.length strategy)) strategy
- diskused diskfree percentfree filesystem
- ) !list;
- if html then
-@@ -2186,11 +2227,11 @@
- if html then Printf.bprintf buf "\\</tr\\>\\</table\\>\\</div\\>\\</div\\>";
- Buffer.contents buf
-
--let dllink_query_networks html url =
-+let dllink_query_networks html url user =
- let result = ref [] in
- if not (networks_iter_until_true (fun n ->
- try
-- let s,r = network_parse_url n url in
-+ let s,r = network_parse_url n url user in
- if s = "" then
- r
- else
-@@ -2208,7 +2249,7 @@
- else
- dllink_print_result html url "Added link" !result
-
--let dllink_parse html url =
-+let dllink_parse html url user =
- if (String2.starts_with url "http") then (
- let u = Url.of_string url in
- let module H = Http_client in
-@@ -2242,21 +2283,14 @@
- let concat_headers =
- (List.fold_right (fun (n, c) t -> n ^ ": " ^ c ^ "\n" ^ t) headers "")
- in
-- ignore (dllink_query_networks html concat_headers)
-+ ignore (dllink_query_networks html concat_headers user)
- );
- dllink_print_result html url "Parsing HTTP url" [])
- else
- if (String2.starts_with url "ftp") then
-- dllink_query_networks html (Printf.sprintf "Location: %s" url)
-+ dllink_query_networks html (Printf.sprintf "Location: %s" url) user
- else
-- dllink_query_networks html url
--
--let print_command_result o buf result =
-- if use_html_mods o then
-- html_mods_table_one_row buf "serversTable" "servers" [
-- ("", "srh", result); ]
-- else
-- Printf.bprintf buf "%s" result
-+ dllink_query_networks html url user
-
- module UnionFind = struct
- type t = int array
-@@ -2378,3 +2412,119 @@
- shorten fileinfo.file_name 80;
- string_of_int nc |]
- ) sorted_score_list)
-+
-+let print_upstats o list server =
-+ let buf = o.conn_buf in
-+ if use_html_mods o then
-+ begin
-+ if !!html_mods_use_js_tooltips then Printf.bprintf buf
-+"\\<div id=\\\"object1\\\" style=\\\"position:absolute; background-color:#FFFFDD;color:black;border-color:black;border-width:20px;font-size:8pt; visibility:visible; left:25px; top:
-+-100px; z-index:+1\\\" onmouseover=\\\"overdiv=1;\\\" onmouseout=\\\"overdiv=0; setTimeout(\\\'hideLayer()\\\',1000)\\\"\\>\\&nbsp;\\</div\\>";
-+
-+ Printf.bprintf buf "\\<div class=\\\"upstats\\\"\\>";
-+ match server with
-+ None ->
-+ html_mods_table_one_row buf "upstatsTable" "upstats" [
-+ ("", "srh", Printf.sprintf "Session: %s uploaded | Shared(%d): %s\n"
-+ (size_of_int64 !upload_counter) !nshared_files (size_of_int64 !nshared_bytes)); ]
-+ | Some s -> let info = server_info s in
-+ html_mods_table_one_row buf "upstatsTable" "upstats" [
-+ ("", "srh", Printf.sprintf "%d files shared on %s (%s:%s)"
-+ info.G.server_published_files info.G.server_name
-+ (Ip.string_of_addr info.G.server_addr)
-+ (string_of_int info.G.server_port)); ]
-+ end
-+ else
-+ begin
-+ Printf.bprintf buf "Upload statistics:\n";
-+ Printf.bprintf buf "Session: %s uploaded | Shared(%d): %s\n"
-+ (size_of_int64 !upload_counter) !nshared_files (size_of_int64 !nshared_bytes)
-+ end;
-+
-+ if use_html_mods o then
-+ html_mods_table_header buf "upstatsTable" "upstats" [
-+ ( "1", "srh", "Total file requests", "Reqs" ) ;
-+ ( "1", "srh", "Total bytes sent", "Total" ) ;
-+ ( "1", "srh", "Upload Ratio", "UPRatio" ) ;
-+ ( "0", "srh", "Preview", "P" ) ;
-+ ( "0", "srh", "Filename", "Filename" );
-+ ( "0", "srh", "Statistic links", "Stats" );
-+ ( "0", "srh", "Published on servers", "Publ" ) ]
-+ else
-+ begin
-+ Printf.bprintf buf " Requests | Bytes | Uploaded | File\n";
-+ Printf.bprintf buf "----------+----------+----------+----------------------------------------------------\n";
-+ end;
-+
-+ html_mods_cntr_init ();
-+ let list = Sort.list (fun f1 f2 ->
-+ (f1.impl_shared_requests = f2.impl_shared_requests &&
-+ f1.impl_shared_uploaded > f2.impl_shared_uploaded) ||
-+ (f1.impl_shared_requests > f2.impl_shared_requests )
-+ ) list in
-+
-+ List.iter (fun impl ->
-+ if use_html_mods o then
-+ begin
-+ let published = List.length impl.impl_shared_servers in
-+ let ed2k = file_print_ed2k_link
-+ (Filename.basename impl.impl_shared_codedname)
-+ impl.impl_shared_size impl.impl_shared_id in
-+
-+ Printf.bprintf buf "\\<tr class=\\\"dl-%d\\\"" (html_mods_cntr ());
-+ (if !!html_mods_use_js_tooltips then
-+ Printf.bprintf buf " onMouseOver=\\\"mOvr(this);setTimeout('popLayer(\\\\\'%s<br>%s%s\\\\\')',%d);setTimeout('hideLayer()',%d);return true;\\\" onMouseOut=\\\"mOut(this);hideLayer();setTimeout('hideLayer()',%d)\\\"\\>"
-+ (Http_server.html_real_escaped (Filename.basename (Charset.to_utf8 impl.impl_shared_codedname)))
-+ (match impl.impl_shared_magic with
-+ None -> ""
-+ | Some magic -> "File type: " ^ (Http_server.html_real_escaped magic) ^ "<br>")
-+ (if impl.impl_shared_servers = [] then "" else
-+ Printf.sprintf "<br>Published on %d %s<br>%s"
-+ published (if published = 1 then "server" else "servers")
-+ (let listbuf = Buffer.create 100 in
-+ List.iter (fun s -> let info = server_info s in
-+ Printf.bprintf listbuf "%s (%s:%s%s)<br>"
-+ info.server_name
-+ (Ip.string_of_addr info.server_addr)
-+ (string_of_int info.server_port)
-+ (if info.server_realport <> 0
-+ then "(" ^ (string_of_int info.server_realport) ^ ")" else "")
-+ ) impl.impl_shared_servers;
-+ Buffer.contents listbuf))
-+ !!html_mods_js_tooltips_wait
-+ !!html_mods_js_tooltips_timeout
-+ !!html_mods_js_tooltips_wait
-+ else Printf.bprintf buf " onMouseOver=\\\"mOvr(this);return true;\\\" onMouseOut=\\\"mOut(this);\\\"\\>");
-+
-+ let uploaded = Int64.to_float impl.impl_shared_uploaded in
-+ let size = Int64.to_float impl.impl_shared_size in
-+
-+ html_mods_td buf [
-+ ("", "sr ar", Printf.sprintf "%d" impl.impl_shared_requests);
-+ ("", "sr ar", size_of_int64 impl.impl_shared_uploaded);
-+ ("", "sr ar", Printf.sprintf "%5.1f" ( if size < 1.0 then 0.0 else (uploaded *. 100.) /. size));
-+ ("", "sr", Printf.sprintf "\\<a href=\\\"preview_upload?q=%d\\\"\\>P\\</a\\>" impl.impl_shared_num);
-+ ("", "sr", (if impl.impl_shared_id = Md4.null then
-+ (Filename.basename impl.impl_shared_codedname)
-+ else
-+ Printf.sprintf "\\<a href=\\\"%s\\\"\\>%s\\</a\\>"
-+ ed2k (shorten (Filename.basename impl.impl_shared_codedname) !!max_name_len)));
-+ ("", "sr", (if impl.impl_shared_id = Md4.null then "" else
-+ Printf.sprintf "\\<a href=\\\"http://tothbenedek.hu/ed2kstats/ed2k?hash=%s\\\"\\>%s\\</a\\>
-+\\<a href=\\\"http://ed2k.titanesel.ws/ed2k.php?hash=%s\\\"\\>%s\\</a\\>
-+\\<a href=\\\"http://bitzi.com/lookup/ed2k:%s\\\"\\>%s\\</a\\>"
-+ (Md4.to_string impl.impl_shared_id) "T1"
-+ (Md4.to_string impl.impl_shared_id) "T2"
-+ (Md4.to_string impl.impl_shared_id) "B"));
-+ ("", "sr ar", Printf.sprintf "%d" published ) ];
-+ Printf.bprintf buf "\\</tr\\>\n";
-+ end
-+ else
-+ Printf.bprintf buf "%9d | %8s | %7s%% | %-50s\n"
-+ (impl.impl_shared_requests)
-+ (size_of_int64 impl.impl_shared_uploaded)
-+ (Printf.sprintf "%3.1f" ((Int64.to_float impl.impl_shared_uploaded *. 100.) /. Int64.to_float impl.impl_shared_size))
-+ (shorten (Filename.basename impl.impl_shared_codedname) !!max_name_len)
-+ ) list;
-+
-+ if use_html_mods o then Printf.bprintf buf "\\</table\\>\\</div\\>\\</div\\>"
-Index: src/daemon/driver/driverInterface.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/driver/driverInterface.ml,v
-retrieving revision 1.52
-retrieving revision 1.60
-diff -u -r1.52 -r1.60
---- src/daemon/driver/driverInterface.ml 12 Aug 2006 20:36:14 -0000 1.52
-+++ src/daemon/driver/driverInterface.ml 21 Nov 2006 22:34:33 -0000 1.60
-@@ -246,6 +246,8 @@
-
- let send_update_file gui file_num update =
- let file = file_find file_num in
-+ if user2_can_view_file gui.gui_conn.conn_user.ui_user (file_owner file) (file_group file) then
-+ begin
- let impl = as_file_impl file in
- let file_info = if update then
- P.File_info (file_info file)
-@@ -256,6 +258,7 @@
- impl.impl_file_last_seen)
- in
- gui_send gui file_info
-+ end
-
- let send_update_user gui user_num update =
- let user = user_find user_num in
-@@ -428,7 +431,7 @@
- (File_add_source_event (file,c))
- :: gui.gui_events.gui_new_events
- ) sources
-- ) !!files;
-+ ) (user2_filter_files !!files gui.gui_conn.conn_user.ui_user);
-
- List.iter (fun file ->
- addevent gui.gui_events.gui_files (file_num file) true;
-@@ -458,6 +461,7 @@
- end
- );
-
-+ if user2_can_view_uploads gui.gui_conn.conn_user.ui_user then
- shared_iter (fun s ->
- addevent gui.gui_events.gui_shared_files (shared_num s) true
- );
-@@ -466,8 +470,11 @@
- gui.gui_events.gui_new_events <- ev :: gui.gui_events.gui_new_events
- ) console_messages;
-
-+ if user2_is_admin gui.gui_conn.conn_user.ui_user then
- gui_send gui (
- P.Options_info (simple_options "" downloads_ini));
-+
-+ if user2_is_admin gui.gui_conn.conn_user.ui_user then
- networks_iter_all (fun r ->
- List.iter (fun opfile ->
- let prefix = r.network_shortname ^ "-" in
-@@ -475,6 +482,7 @@
- gui_send gui (P.Options_info args)) r.network_config_file);
-
- (* Options panels defined in downloads.ini *)
-+ if user2_is_admin gui.gui_conn.conn_user.ui_user then
- List.iter (fun s ->
- let section = section_name s in
- List.iter (fun o ->
-@@ -484,6 +492,7 @@
- ) (sections downloads_ini);
-
- (* Options panels defined in users.ini *)
-+ if user2_is_admin gui.gui_conn.conn_user.ui_user then
- List.iter (fun s ->
- let section = section_name s in
- List.iter (fun o ->
-@@ -493,6 +502,7 @@
- ) (sections users_ini);
-
- (* Options panels defined in each plugin *)
-+ if user2_is_admin gui.gui_conn.conn_user.ui_user then
- networks_iter_all (fun r ->
- let prefix = r.network_shortname ^ "-" in
- List.iter (fun file ->
-@@ -554,7 +564,7 @@
- (File_add_source_event (file,c))
- :: gui.gui_events.gui_new_events
- ) (file_active_sources file)
-- ) !!files;
-+ ) (user2_filter_files !!files gui.gui_conn.conn_user.ui_user);
-
- end
-
-@@ -613,7 +623,7 @@
- ) list
-
- | P.SetOption (name, value) ->
-- if user2_is_admin gui.gui_conn.conn_user.ui_user_name || !!enable_user_config then
-+ if user2_is_admin gui.gui_conn.conn_user.ui_user then
- CommonInteractive.set_fully_qualified_options name value
- else
- begin
-@@ -644,6 +654,7 @@
- end
-
- | P.EnableNetwork (num, bool) ->
-+ if user2_is_admin gui.gui_conn.conn_user.ui_user then
- let n = network_find_by_num num in
- if n.op_network_is_enabled () <> bool then
- (try
-@@ -670,7 +681,7 @@
- network_extend_search r s e)
-
- | P.KillServer ->
-- if user2_is_admin gui.gui_conn.conn_user.ui_user_name then
-+ if user2_is_admin gui.gui_conn.conn_user.ui_user then
- CommonInteractive.clean_exit 0
- else
- begin
-@@ -689,7 +700,7 @@
- add_timer 60. (fun _ ->
- gui_send gui (Search_waiting (search_num, 0))
- );
-- gui.gui_id_counter <- maxi gui.gui_id_counter search_num;
-+ gui.gui_id_counter <- max gui.gui_id_counter search_num;
-
- let user = gui.gui_conn.conn_user in
- let query =
-@@ -720,7 +731,7 @@
-
- | P.Download_query (filenames, num, force) ->
- let r = find_result num in
-- let files = result_download r filenames force in
-+ let files = result_download r filenames force gui.gui_conn.conn_user.ui_user in
- List.iter CommonInteractive.start_download files
-
- | P.ConnectMore_query ->
-@@ -731,7 +742,7 @@
- if not (networks_iter_until_true
- (fun n ->
- try
-- let s,r = network_parse_url n url in r
-+ let s,r = network_parse_url n url gui.gui_conn.conn_user.ui_user in r
- with e ->
- lprintf "Exception %s for network %s\n"
- (Printexc2.to_string e) (n.network_name);
-@@ -765,11 +776,13 @@
- query_networks url
-
- | P.GetUploaders ->
-+ if user2_can_view_uploads gui.gui_conn.conn_user.ui_user then
- gui_send gui (P.Uploaders
- (List2.tail_map (fun c -> client_num c)
- (Intmap.to_list !uploaders)))
-
- | P.GetPending ->
-+ if user2_can_view_uploads gui.gui_conn.conn_user.ui_user then
- gui_send gui (P.Pending (
- List2.tail_map (fun c -> client_num c)
- (Intmap.to_list !CommonUploads.pending_slots_map)))
-@@ -778,13 +791,13 @@
- server_remove (server_find num)
-
- | P.SaveOptions_query list ->
--
-+ if user2_is_admin gui.gui_conn.conn_user.ui_user then
- List.iter (fun (name, value) ->
- CommonInteractive.set_fully_qualified_options name value) list;
- DriverInteractive.save_config ()
-
- | P.RemoveDownload_query num ->
-- file_cancel (file_find num)
-+ file_cancel (file_find num) gui.gui_conn.conn_user.ui_user
-
- | P.ViewUsers num ->
- let s = server_find num in
-@@ -868,6 +881,7 @@
- client_connect c
-
- | P.DisconnectClient num ->
-+ if user2_can_view_uploads gui.gui_conn.conn_user.ui_user then
- let c = client_find num in
- client_disconnect c
-
-@@ -905,9 +919,9 @@
- | P.SwitchDownload (num, resume) ->
- let file = file_find num in
- if resume then
-- file_resume file
-+ file_resume file gui.gui_conn.conn_user.ui_user
- else
-- file_pause file
-+ file_pause file gui.gui_conn.conn_user.ui_user
-
- | P.FindFriend user ->
- networks_iter (fun n ->
-@@ -1026,7 +1040,7 @@
-
- | NetworkMessage (num, s) ->
- let n = network_find_by_num num in
-- n.op_network_gui_message s
-+ n.op_network_gui_message s gui.gui_conn.conn_user.ui_user
-
- | AddServer_query (num, ip, port) ->
- let n = network_find_by_num num in
-@@ -1036,7 +1050,7 @@
- let s = n.op_network_add_server (Ip.addr_of_ip ip) port in
- server_connect s
- | RefreshUploadStats ->
--
-+ if user2_can_view_uploads gui.gui_conn.conn_user.ui_user then
- shared_iter (fun s ->
- update_shared_info s;
- )
-@@ -1044,6 +1058,11 @@
- | P.GetVersion ->
- gui_send gui (P.Version Autoconf.current_version)
-
-+ | P.GetStats num ->
-+ let n = network_find_by_num num in
-+ let l = n.op_network_stat_info_list () in
-+ gui_send gui (P.Stats (num, l))
-+
- | P.GiftAttach (profile, version, client) ->
- let user, pass =
- try
-@@ -1080,13 +1099,13 @@
- with
- Failure s ->
- gui_send gui (Console (Printf.sprintf "Failure: %s\n" s))
-+ | Torrent_can_not_be_used ->
-+ gui_send gui (Console (Printf.sprintf "\nError: This torrent does not have valid tracker URLs\n"))
-+ | Torrent_already_exists ->
-+ gui_send gui (Console (Printf.sprintf "\nError: This torrent is already in download queue\n"))
- | e ->
-- let error_text = Printexc2.to_string e in
-- if error_text = "BTInteractive.Torrent_can_not_be_used" then
-- gui_send gui (Console (Printf.sprintf "\nError: This torrent does not have valid tracker URLs\n"))
-- else
-- gui_send gui (Console (Printf.sprintf "from_gui: exception %s for message %s\n"
-- (Printexc2.to_string e) (GuiProto.string_of_from_gui t)))
-+ gui_send gui (Console (Printf.sprintf "from_gui: exception %s for message %s\n"
-+ (Printexc2.to_string e) (GuiProto.string_of_from_gui t)))
-
- let gui_events () =
- {
-Index: src/daemon/driver/driverMain.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/daemon/driver/driverMain.ml,v
-retrieving revision 1.125
-retrieving revision 1.132
-diff -u -r1.125 -r1.132
---- src/daemon/driver/driverMain.ml 5 Sep 2006 14:15:19 -0000 1.125
-+++ src/daemon/driver/driverMain.ml 19 Nov 2006 23:04:59 -0000 1.132
-@@ -84,7 +84,7 @@
- update_link_stats ()
- with e ->
- lprintf_nl (_b "Exception %s") (Printexc2.to_string e));
-- (try
-+ (try
- CommonUploads.refill_upload_slots ()
- with e ->
- lprintf_nl (_b "Exception %s") (Printexc2.to_string e));
-@@ -102,7 +102,8 @@
- | Some dir -> allowed_ips =:= !!allowed_ips
- );
-
-- if !!http_port <> 0 then begin try
-+ if !!http_port <> 0 then begin
-+ try
- ignore (DriverControlers.create_http_handler ());
- with e ->
- lprintf_nl (_b "Exception %s while starting HTTP interface")
-@@ -218,7 +219,6 @@
- (try
- Options.load downloads_ini;
- Options.load users_ini;
-- ignore (DriverInteractive.verify_user_admin ());
- DriverInteractive.hdd_check ()
- with e ->
- lprintf_nl "Exception %s during options load" (Printexc2.to_string e);
-@@ -341,15 +341,18 @@
- CommonGlobals.exit_properly 71
- end;
-
-- (
-- let hostname = "www.mldonkey.net" in
-- try
-- ignore(Ip.from_name hostname);
-- DriverInteractive.dns_works := true
-- with e ->
-- lprintf (_b "\nDNS resolution does not work! Looking up %s failed with %s.")
-- hostname (Printexc2.to_string e);
-- lprintf "
-+ ( let resolve_name hostname =
-+ try
-+ ignore (Ip.from_name hostname);
-+ true
-+ with _ -> false
-+ in
-+ let hostnames =
-+ ["www.mldonkey.org"; "mldonkey.sf.net"; "www.mldonkey.net"; "www.google.com"]
-+ in
-+ DriverInteractive.dns_works := List.exists resolve_name hostnames;
-+
-+ if not !DriverInteractive.dns_works then lprintf "
- The core therefore is unable to get eDonkey serverlists and loading
- .torrent files via dllink from websites is also impossible.
- If you are using MLDonkey in a chroot environment you should
-@@ -382,6 +385,9 @@
- end
- end
- );
-+ if not !Charset.conversion_enabled then
-+ lprintf_nl (_b "Self-test failed, charset conversion disabled.");
-+
- load_config ();
-
- add_infinite_option_timer download_sample_rate CommonFile.sample_timer;
-@@ -399,7 +405,7 @@
- save_results =:= old_save_results;
- end;
-
-- lprintf_nl (_b "Check http://www.mldonkey.net/ for updates");
-+ lprintf_nl (_b "Check http://www.mldonkey.org for updates");
- networks_iter (fun r -> network_load_complex_options r);
- lprintf_nl (_b "enabling networks: ");
- networks_iter (fun r ->
-@@ -413,7 +419,7 @@
- lprintf_nl (_b "---- enabling interfaces ----");
- List.iter (fun (p,s) -> if p <> 0 then lprintf_nl "using port %d (%s)" p s)
- (network_ports (network_find_by_name "Global Shares"));
-- lprintf (_b "%sdisabled networks: ") (log_time ());
-+ lprintf (_b "%s[dMain] disabled networks: ") (log_time ());
- let found = ref false in
- networks_iter_all (fun r ->
- if not (network_is_enabled r) then
-@@ -440,6 +446,23 @@
- add_infinite_timer 0.1 CommonUploads.upload_download_timer;
- add_infinite_timer !!buffer_writes_delay (fun _ -> Unix32.flush ());
-
-+ history_timeflag := (Unix.time());
-+ update_download_history ();
-+ update_upload_history ();
-+ history_h_timeflag := (Unix.time());
-+ update_h_download_history ();
-+ update_h_upload_history ();
-+
-+ add_infinite_timer (float_of_int history_step) (fun timer ->
-+ history_timeflag := (Unix.time());
-+ update_download_history ();
-+ update_upload_history ());
-+
-+ add_infinite_timer (float_of_int history_h_step) (fun timer ->
-+ history_h_timeflag := (Unix.time());
-+ update_h_download_history ();
-+ update_h_upload_history ());
-+
- if Autoconf.system = "mingw" then
- add_infinite_timer 1. (fun timer ->
- MlUnix.set_console_title (DriverInteractive.console_topic ()));
-Index: src/gtk/gui/gui_messages.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/gtk/gui/gui_messages.ml,v
-retrieving revision 1.7
-retrieving revision 1.8
-diff -u -r1.7 -r1.8
---- src/gtk/gui/gui_messages.ml 5 Aug 2005 00:56:13 -0000 1.7
-+++ src/gtk/gui/gui_messages.ml 25 Oct 2006 11:34:46 -0000 1.8
-@@ -493,7 +493,7 @@
- ========
-
- Release: %s
--Authors: MLDonkey project, http://www.mldonkey.net/
-+Authors: MLDonkey project, http://www.mldonkey.org
-
- This documentation file is now obsolete. Read the FAQ instead (either
- on the project WEB site or in the FAQ.html file).
-@@ -503,9 +503,7 @@
- IRC channel: irc.freenode.net, chat #mldonkey
-
- Web sites:
--http://www.mldonkey.net/ Official site, bug reports
--http://www.mldonkeyworld.com/ English forum
--http://www.mldonkey.org/ German forum
-+http://www.mldonkey.org Official site
-
- Mailing-lists:
- mldonkey-users@nongnu.org
-Index: src/gtk/newgui/gui_friends.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/gtk/newgui/gui_friends.ml,v
-retrieving revision 1.17
-retrieving revision 1.19
-diff -u -r1.17 -r1.19
---- src/gtk/newgui/gui_friends.ml 21 Aug 2006 10:45:51 -0000 1.17
-+++ src/gtk/newgui/gui_friends.ml 31 Oct 2006 15:40:05 -0000 1.19
-@@ -72,7 +72,7 @@
- if len > maxlen then
- (String.sub s 0 (maxlen-3)) ^ "..."
- else if s = "" then
-- "http://www.mldonkey.net/"
-+ "http://www.mldonkey.org/"
- else s
-
- let state_pix state =
-@@ -430,6 +430,7 @@
- client_chat_port = 0;
- client_connect_time = c.gclient_connect_time;
- client_software = c.gclient_software;
-+ client_os = None;
- client_release = c.gclient_release;
- client_emulemod = c.gclient_emulemod;
- client_downloaded = c.gclient_downloaded;
-@@ -637,6 +638,7 @@
- client_chat_port = 0;
- client_connect_time = c.gclient_connect_time;
- client_software = c.gclient_software;
-+ client_os = None;
- client_release = c.gclient_release;
- client_emulemod = c.gclient_emulemod;
- client_downloaded = c.gclient_downloaded;
-Index: src/gtk/newgui/gui_installer_base.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/gtk/newgui/gui_installer_base.ml,v
-retrieving revision 1.5
-retrieving revision 1.6
-diff -u -r1.5 -r1.6
---- src/gtk/newgui/gui_installer_base.ml 1 Nov 2004 11:22:59 -0000 1.5
-+++ src/gtk/newgui/gui_installer_base.ml 12 Nov 2006 12:42:55 -0000 1.6
-@@ -0,0 +1 @@
-+let () = ()
-Index: src/gtk/newgui/gui_main.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/gtk/newgui/gui_main.ml,v
-retrieving revision 1.18
-retrieving revision 1.19
-diff -u -r1.18 -r1.19
---- src/gtk/newgui/gui_main.ml 27 Jun 2006 10:38:35 -0000 1.18
-+++ src/gtk/newgui/gui_main.ml 31 Oct 2006 15:40:05 -0000 1.19
-@@ -460,6 +460,7 @@
- | GiftServerAttach _
- | GiftServerStats _ -> assert false
- | Version _
-+ | Stats (_, _)
- | Search _ -> ()
-
- with e ->
-Index: src/gtk/newgui/gui_messages.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/gtk/newgui/gui_messages.ml,v
-retrieving revision 1.12
-retrieving revision 1.13
-diff -u -r1.12 -r1.13
---- src/gtk/newgui/gui_messages.ml 27 Jun 2006 10:38:35 -0000 1.12
-+++ src/gtk/newgui/gui_messages.ml 25 Oct 2006 11:34:46 -0000 1.13
-@@ -1645,7 +1645,7 @@
- ========
-
- Release: %s
--Authors: MLDonkey project, http://www.mldonkey.net/
-+Authors: MLDonkey project, http://www.mldonkey.org
-
- This documentation file is now obsolete. Read the FAQ instead (either
- on the project WEB site or in the FAQ.html file).
-@@ -1655,9 +1655,7 @@
- IRC channel: irc.freenode.net, chat #mldonkey
-
- Web sites:
--http://www.mldonkey.net/ Official site, bug reports
--http://www.mldonkeyworld.com/ English forum
--http://www.mldonkey.org/ German forum
-+http://www.mldonkey.org Official site
-
- Mailing-lists:
- mldonkey-users@nongnu.org
-Index: src/gtk/newgui/gui_misc.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/gtk/newgui/gui_misc.ml,v
-retrieving revision 1.6
-retrieving revision 1.7
-diff -u -r1.6 -r1.7
---- src/gtk/newgui/gui_misc.ml 16 Oct 2005 20:42:52 -0000 1.6
-+++ src/gtk/newgui/gui_misc.ml 25 Oct 2006 11:34:46 -0000 1.7
-@@ -44,7 +44,7 @@
-
- let short_name n =
- let n = if n="" then
-- "http://www.mldonkey.net/"
-+ "http://www.mldonkey.org"
- else n
- in
- let len = String.length n in
-Index: src/gtk2/gui/guiMessages.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/gtk2/gui/guiMessages.ml,v
-retrieving revision 1.12
-retrieving revision 1.13
-diff -u -r1.12 -r1.13
---- src/gtk2/gui/guiMessages.ml 1 Sep 2006 16:22:14 -0000 1.12
-+++ src/gtk2/gui/guiMessages.ml 25 Oct 2006 11:34:46 -0000 1.13
-@@ -1258,7 +1258,7 @@
- ========
-
- Release: %s
--Authors: MLDonkey project, http://www.mldonkey.net/
-+Authors: MLDonkey project, http://www.mldonkey.org/
-
- This documentation file is now obsolete. Read the FAQ instead (either
- on the project WEB site or in the FAQ.html file).
-@@ -1268,9 +1268,7 @@
- IRC channel: irc.freenode.net, chat #mldonkey
-
- Web sites:
--http://www.mldonkey.net/ Official site, bug reports
--http://www.mldonkeyworld.com/ English forum
--http://www.mldonkey.org/ German forum
-+http://www.mldonkey.org Official site
-
- Mailing-lists:
- mldonkey-users@nongnu.org
-Index: src/gtk2/gui/guiRooms.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/gtk2/gui/guiRooms.ml,v
-retrieving revision 1.3
-retrieving revision 1.4
-diff -u -r1.3 -r1.4
---- src/gtk2/gui/guiRooms.ml 12 Nov 2005 11:16:36 -0000 1.3
-+++ src/gtk2/gui/guiRooms.ml 9 Nov 2006 21:32:26 -0000 1.4
-@@ -524,7 +524,7 @@
- let find_user_name user_num =
- try
- let u = Hashtbl.find G.users user_num in
-- u.user_name
-+ u.GuiTypes.user_name
- with _ -> raise Not_found
-
- let message_from_server s =
-Index: src/gtk2/gui/guiStarter.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/gtk2/gui/guiStarter.ml,v
-retrieving revision 1.3
-retrieving revision 1.4
-diff -u -r1.3 -r1.4
---- src/gtk2/gui/guiStarter.ml 31 Oct 2005 18:34:02 -0000 1.3
-+++ src/gtk2/gui/guiStarter.ml 6 Nov 2006 18:06:08 -0000 1.4
-@@ -22,6 +22,17 @@
- let _s_ x = (_s x) ^ ":"
-
- let main () =
-+ let arg_1 =
-+ try
-+ Sys.argv.(1)
-+ with _ -> ""
-+ in
-+ if not (Sys.file_exists arg_1) then
-+ begin
-+ if arg_1 <> "" then Printf.printf "File %s not found\n%!" arg_1;
-+ Printf.printf "Syntax: mlguistarter FILE\n%!";
-+ exit 0
-+ end;
- ignore (GMain.Main.init ());
- let window = GWindow.window
- ~title:(_s "MLdonkey GUI starter")
-@@ -57,7 +68,7 @@
- ignore (wb_5#connect#clicked ~callback:
- (fun () ->
- window#destroy ();
-- ignore (Sys.command (Printf.sprintf "%s &" Sys.argv.(1)));
-+ ignore (Sys.command (Printf.sprintf "%s &" arg_1));
- ));
- ignore (wb_6#connect#clicked ~callback:
- (fun () ->
-Index: src/gtk2/gui/guiUsers.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/gtk2/gui/guiUsers.ml,v
-retrieving revision 1.3
-retrieving revision 1.4
-diff -u -r1.3 -r1.4
---- src/gtk2/gui/guiUsers.ml 12 Nov 2005 11:16:36 -0000 1.3
-+++ src/gtk2/gui/guiUsers.ml 9 Nov 2006 21:32:26 -0000 1.4
-@@ -184,7 +184,7 @@
- (*************************************************************************)
-
- method from_item row (u : user_info) =
-- store#set ~row ~column:user_name (U.utf8_of u.user_name);
-+ store#set ~row ~column:user_name (U.utf8_of u.GuiTypes.user_name);
- store#set ~row ~column:user_ip_port (Mi.ip_to_string u.user_ip u.user_port);
- store#set ~row ~column:user_md4 (Md4.to_string u.user_md4);
- store#set ~row ~column:user_tags (Mi.tags_to_string u.user_tags)
-@@ -262,7 +262,7 @@
- let u1 = user_of_key k1 in
- let u2 = user_of_key k2 in
- match c with
-- Col_user_name -> compare (String.lowercase u1.user_name) (String.lowercase u2.user_name)
-+ Col_user_name -> compare (String.lowercase u1.GuiTypes.user_name) (String.lowercase u2.GuiTypes.user_name)
- | Col_user_addr -> compare u1.user_ip u2.user_ip
- | Col_user_tags -> compare u1.user_tags u2.user_tags
- | Col_user_md4 -> compare u1.user_md4 u2.user_md4
-Index: src/networks/bittorrent/bTClients.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/bittorrent/bTClients.ml,v
-retrieving revision 1.77
-retrieving revision 1.84
-diff -u -r1.77 -r1.84
---- src/networks/bittorrent/bTClients.ml 16 Sep 2006 09:47:17 -0000 1.77
-+++ src/networks/bittorrent/bTClients.ml 5 Nov 2006 14:09:38 -0000 1.84
-@@ -131,14 +131,24 @@
- in
-
- let enabled_trackers =
-- let enabled_trackers = List.filter (fun t -> t.tracker_enabled) file.file_trackers in
-+ let enabled_trackers = List.filter (fun t -> tracker_is_enabled t) file.file_trackers in
- if enabled_trackers <> [] then enabled_trackers
- else begin
- (* if there is no tracker left, do something ? *)
- if !verbose_msg_servers then
-- lprintf_nl "No trackers left, reenabling all of them...";
-- List.iter (fun t -> t.tracker_enabled <- can_handle_tracker t) file.file_trackers;
-- file.file_trackers
-+ lprintf_nl "No trackers left for %s, reenabling all of them..." (file_best_name (as_file file));
-+ List.iter (fun t ->
-+ match t.tracker_status with
-+ (* only re-enable after normal error *)
-+ Disabled _ -> t.tracker_status <- Enabled
-+ | _ -> ()) file.file_trackers;
-+ let enabled_trackers = List.filter (fun t -> t.tracker_status = Enabled) file.file_trackers in
-+ if enabled_trackers = [] && (file_state file) <> FilePaused then
-+ begin
-+ file_pause (as_file file) CommonUserDb.admin_user;
-+ lprintf_file_nl (as_file file) "Paused %s, no usable trackers left" (file_best_name (as_file file))
-+ end;
-+ file.file_trackers;
- end in
-
- List.iter (fun t ->
-@@ -155,13 +165,12 @@
- t.tracker_last_conn + !!min_tracker_reask_interval < last_time() ))
- then
- begin
-- (* if we already tried to connect but failed, remove tracker *)
-+ (* if we already tried to connect but failed, disable tracker, but allow re-enabling *)
- if file.file_tracker_connected && t.tracker_last_clients_num = 0 &&
- t.tracker_last_conn < 1 then begin
- if !verbose_msg_servers then
- lprintf_nl "Request error from tracker: disabling %s" t.tracker_url;
-- t.tracker_enabled <- false;
-- (* remove_tracker t.tracker_url file *)
-+ t.tracker_status <- Disabled (intern "MLDonkey: Request error from tracker")
- end
- (* Send request to tracker *)
- else begin
-@@ -205,6 +214,15 @@
- t.tracker_url (t.tracker_interval - (last_time () - t.tracker_last_conn)) file.file_name
- ) enabled_trackers
-
-+let start_upload c =
-+ set_client_upload (as_client c) (as_file c.client_file);
-+ set_client_has_a_slot (as_client c) NormalSlot;
-+ Rate.update_no_change c.client_downloaded_rate;
-+ Rate.update_no_change c.client_upload_rate;
-+ c.client_last_optimist <- last_time();
-+ client_enter_upload_queue (as_client c);
-+ send_client c Unchoke
-+
- (** In this function we decide which peers will be
- uploaders. We send a choke message to current uploaders
- that are not in the next uploaders list. We send Unchoke
-@@ -216,21 +234,14 @@
- (*Send choke if a current_uploader is not in next_uploaders*)
- List.iter ( fun c -> if ((List.mem c !next_uploaders)==false) then
- begin
-- set_client_has_a_slot (as_client c) false;
-+ set_client_has_a_slot (as_client c) NoSlot;
- (*we will let him finish his download and choke him on next_request*)
- end
- ) !current_uploaders;
-
- (*don't send Choke if new uploader is already an uploaders *)
-- List.iter ( fun c -> if ((List.mem c !current_uploaders)==false) then
-- begin
-- set_client_has_a_slot (as_client c) true;
-- Rate.update_no_change c.client_downloaded_rate;
-- Rate.update_no_change c.client_upload_rate;
-- c.client_last_optimist <- last_time();
-- client_enter_upload_queue (as_client c);
-- send_client c Unchoke;
-- end
-+ List.iter ( fun c ->
-+ if not (List.mem c !current_uploaders) then start_upload c
- ) !next_uploaders;
- current_uploaders := !next_uploaders
-
-@@ -322,7 +333,7 @@
- if not ( !must_keep && (client_has_a_slot (as_client c) || c.client_interested)) then
- begin
- if !verbose_msg_clients then
-- lprintf_file_nl file "disconnect since download is finished";
-+ lprintf_file_nl (as_file file) "disconnect since download is finished";
- disconnect_client c Closed_by_user
- end
- ) file.file_clients
-@@ -414,6 +425,17 @@
-
- let counter = ref 0
-
-+let parse_reserved rbits c =
-+ let has_bit pos h = Char.code rbits.[pos] land h <> 0 in
-+
-+ c.client_dht <- has_bit 7 0x01;
-+ c.client_cache_extension <- has_bit 7 0x02;
-+ c.client_fast_extension <- has_bit 7 0x04;
-+
-+ c.client_utorrent_extension <- has_bit 5 0x10;
-+
-+ c.client_azureus_messaging_protocol <- has_bit 0 0x80
-+
-
- (** This function is called to parse the first message that
- a client send.
-@@ -428,7 +450,7 @@
- (* removed: @param peer_id The hash (sha1) of the client. (Should be checked)
- *)
- let rec client_parse_header counter cc init_sent gconn sock
-- (proto, file_id) =
-+ (proto, rbits, file_id) =
- try
- set_lifetime sock 600.;
- if !verbose_msg_clients then
-@@ -436,12 +458,12 @@
-
- let file = Hashtbl.find files_by_uid file_id in
- if !verbose_msg_clients then
-- lprintf_file_nl file "file found";
-+ lprintf_file_nl (as_file file) "file found";
- let c =
- match !cc with
- None ->
- let c = new_client file Sha1.null (TcpBufferedSocket.peer_addr sock) in
-- if !verbose_connect then lprintf_file_nl file "Client %d: incoming connection" (client_num c);
-+ if !verbose_connect then lprintf_file_nl (as_file file) "Client %d: incoming connection" (client_num c);
- cc := Some c;
- c
- | Some c ->
-@@ -482,6 +504,8 @@
- (Ip.to_string ip) port;
- end;
-
-+ parse_reserved rbits c;
-+
- (match c.client_sock with
- NoConnection ->
- if !verbose_msg_clients then begin
-@@ -603,9 +627,8 @@
-
- let num, x,y, r =
-
-- if !verbose_msg_clients then begin
-- lprintf_file_nl file "CLIENT %d: Finding new range to send" (client_num c);
-- end;
-+ if !verbose_msg_clients then
-+ lprintf_file_nl (as_file file) "CLIENT %d: Finding new range to send" (client_num c);
-
- if !verbose_swarming then begin
- lprintf_n "Current download:\n Current chunks: ";
-@@ -638,7 +661,7 @@
-
- lprint_newline ();
-
-- lprintf_file_nl file "Finding Range:";
-+ lprintf_file_nl (as_file file) "Finding Range:";
- end;
-
- try
-@@ -653,7 +676,7 @@
-
- | None ->
-
-- if !verbose_swarming then lprintf_file_nl file "No block";
-+ if !verbose_swarming then lprintf_file_nl (as_file file) "No block";
- update_client_bitmap c;
- (try CommonSwarming.verify_one_chunk swarmer with _ -> ());
- (*Find a free block in the swarmer*)
-@@ -707,7 +730,7 @@
- number. Only matters with merged downloads, and even then other
- clients didn't seem to care (?), so the bug remained hidden *)
- if !verbose_swarming then
-- lprintf_file_nl file "Asking %d For Range %Ld-%Ld" chunk x y;
-+ lprintf_file_nl (as_file file) "Asking %d For Range %Ld-%Ld" chunk x y;
-
- chunk, x -- file.file_piece_size ** Int64.of_int chunk, y -- x, r
-
-@@ -742,12 +765,12 @@
- send_client c (Request (num,x,y));
-
- if !verbose_msg_clients then
-- lprintf_file_nl file "CLIENT %d: Asking %s For Range %Ld-%Ld"
-+ lprintf_file_nl (as_file file) "CLIENT %d: Asking %s For Range %Ld-%Ld"
- (client_num c) (Sha1.to_string c.client_uid) x y
-
- with Not_found ->
- if not (CommonSwarming.check_finished swarmer) && !verbose_download then
-- lprintf_file_nl file "BTClient.get_from_client ERROR: can't find a block to download and file is not yet finished for file : %s..." file.file_name
-+ lprintf_file_nl (as_file file) "BTClient.get_from_client ERROR: can't find a block to download and file is not yet finished for file : %s..." file.file_name
-
-
- (** In this function we match a message sent by a client
-@@ -799,10 +822,10 @@
-
- if !verbose_msg_clients then
- (match c.client_ranges_sent with
-- [] -> lprintf_file_nl file "EMPTY Ranges !!!"
-+ [] -> lprintf_file_nl (as_file file) "EMPTY Ranges !!!"
- | (p1,p2,r) :: _ ->
- let (x,y) = CommonSwarming.range_range r in
-- lprintf_file_nl file "Current range from %s : %Ld [%d] (asked %Ld-%Ld[%Ld-%Ld])"
-+ lprintf_file_nl (as_file file) "Current range from %s : %Ld [%d] (asked %Ld-%Ld[%Ld-%Ld])"
- (brand_to_string c.client_brand) position len
- p1 p2 x y
- );
-@@ -822,10 +845,10 @@
- Rate.update c.client_downloaded_rate (float_of_int len);
- if !verbose_msg_clients then
- (match c.client_ranges_sent with
-- [] -> lprintf_file_nl file "EMPTY Ranges !!!"
-+ [] -> lprintf_file_nl (as_file file) "EMPTY Ranges !!!"
- | (p1,p2,r) :: _ ->
- let (x,y) = CommonSwarming.range_range r in
-- lprintf_file_nl file "Received %Ld [%d] %Ld-%Ld[%Ld-%Ld] -> %Ld"
-+ lprintf_file_nl (as_file file) "Received %Ld [%d] %Ld-%Ld[%Ld-%Ld] -> %Ld"
- position len
- p1 p2 x y
- (new_downloaded -- old_downloaded)
-@@ -852,12 +875,7 @@
- *)
- current_uploaders := c::(!current_uploaders);
- c.client_sent_choke <- false;
-- set_client_has_a_slot (as_client c) true;
-- Rate.update_no_change c.client_downloaded_rate;
-- Rate.update_no_change c.client_upload_rate;
-- c.client_last_optimist <- last_time();
-- client_enter_upload_queue (as_client c);
-- send_client c Unchoke;
-+ start_upload c
- end;
-
- (* Check if the client is still interesting for us... *)
-@@ -865,6 +883,7 @@
-
- | PeerID p ->
- (* Disconnect if that is ourselves. *)
-+ c.client_uid <- Sha1.direct_of_string p;
- if not (c.client_uid = !!client_uid) then
- begin
- let brand, release = parse_software p in
-@@ -873,7 +892,6 @@
- (* TODO : enable it
- c.client_release <- (parse_release p c.client_brand);
- *)
-- c.client_uid <- Sha1.direct_of_string p;
-
- if (List.length !current_uploaders < (!!max_bt_uploaders-1)) &&
- (List.mem c (!current_uploaders)) == false then
-@@ -882,12 +900,7 @@
- don't miss the opportunity if we can *)
- current_uploaders := c::(!current_uploaders);
- c.client_sent_choke <- false;
-- set_client_has_a_slot (as_client c) true;
-- Rate.update_no_change c.client_downloaded_rate;
-- Rate.update_no_change c.client_upload_rate;
-- c.client_last_optimist <- last_time();
-- client_enter_upload_queue (as_client c);
-- send_client c Unchoke;
-+ start_upload c
- end
- else
- begin
-@@ -911,7 +924,7 @@
- let nbits = String.length p * 8 in
-
- if nbits < npieces then begin
-- lprintf_file_nl file "Error: expected bitfield of atleast %d but got %d" npieces nbits;
-+ lprintf_file_nl (as_file file) "Error: expected bitfield of atleast %d but got %d" npieces nbits;
- disconnect_client c (Closed_for_error "Wrong bitfield length")
- end else begin
-
-@@ -934,7 +947,7 @@
- send_interested c;
-
- if !verbose_msg_clients then
-- lprintf_file_nl file "New BitField Registered";
-+ lprintf_file_nl (as_file file) "New BitField Registered";
-
- (* for i = 1 to max_range_requests - List.length c.client_ranges do
- (try get_from_client sock c with _ -> ())
-@@ -1003,7 +1016,7 @@
- (* Afaik this is no protocol violation and happens if the client
- didn't send a client bitmap after the handshake. *)
- let (ip,port) = c.client_host in
-- if !verbose_msg_clients then lprintf_file_nl file "%s:%d with software %s : Choke send, but no client bitmap"
-+ if !verbose_msg_clients then lprintf_file_nl (as_file file) "%s:%d with software %s : Choke send, but no client bitmap"
- (Ip.to_string ip) port (brand_to_string c.client_brand)
- | Some up ->
- CommonSwarming.clear_uploader_intervals up
-@@ -1068,10 +1081,10 @@
- c.client_upload_requests <- List2.remove_first (n, pos, len) c.client_upload_requests
- else
- if !verbose_msg_clients then
-- lprintf_file_nl file "Error: received cancel request but client has no slot"
-+ lprintf_file_nl (as_file file) "Error: received cancel request but client has no slot"
-
- with e ->
-- lprintf_file_nl file "Error %s while handling MESSAGE: %s" (Printexc2.to_string e) (TcpMessages.to_string msg)
-+ lprintf_file_nl (as_file file) "Error %s while handling MESSAGE: %s" (Printexc2.to_string e) (TcpMessages.to_string msg)
-
-
- (** The function used to connect to a client.
-@@ -1136,7 +1149,7 @@
- let file = c.client_file in
-
- if !verbose_msg_clients then
-- lprintf_file_nl file "READY TO DOWNLOAD FILE";
-+ lprintf_file_nl (as_file file) "READY TO DOWNLOAD FILE";
-
- send_init !!client_uid file.file_id sock;
- (* Fabrice: Initialize the client bitmap and uploader fields to <> None *)
-@@ -1284,7 +1297,7 @@
- with _ -> ())
- with e ->
- if !verbose_connect then
-- lprintf_file_nl file "Exception %s in resume_clients" (Printexc2.to_string e)
-+ lprintf_file_nl (as_file file) "Exception %s in resume_clients" (Printexc2.to_string e)
- ) file.file_clients
-
- (** Check if the value replied by the tracker is correct.
-@@ -1321,13 +1334,13 @@
- let tracker_reply =
- try
- File.to_string filename
-- with e -> lprintf_file_nl file "Empty reply from tracker"; ""
-+ with e -> lprintf_file_nl (as_file file) "Empty reply from tracker"; ""
- in
- let v =
- match tracker_reply with
- | "" ->
- if !verbose_connect then
-- lprintf_file_nl file "Empty reply from tracker";
-+ lprintf_file_nl (as_file file) "Empty reply from tracker";
- Bencode.decode ""
- | _ -> Bencode.decode tracker_reply
- in
-@@ -1339,13 +1352,12 @@
- List.iter (fun (key,value) ->
- match (key, value) with
- | String "failure reason", String failure ->
-- (* On failure, remove the faulty tracker from file.file_trackers list *)
-- t.tracker_enabled <- false;
-- (* remove_tracker t.tracker_url file; *)
-- lprintf_file_nl file "Failure from Tracker %s in file: %s Reason: %s\nBT: Tracker %s disabled for failure"
-+ (* On failure, disable the tracker and forbid re-enabling *)
-+ t.tracker_status <- Disabled_failure (intern failure);
-+ lprintf_file_nl (as_file file) "Failure from Tracker %s in file: %s Reason: %s\nBT: Tracker %s disabled for failure"
- t.tracker_url file.file_name (Charset.to_utf8 failure) t.tracker_url
- | String "warning message", String warning ->
-- lprintf_file_nl file "Warning from Tracker %s in file: %s Reason: %s" t.tracker_url file.file_name warning
-+ lprintf_file_nl (as_file file) "Warning from Tracker %s in file: %s Reason: %s" t.tracker_url file.file_name warning
- | String "interval", Int n ->
- t.tracker_interval <- chk_keyval (Bencode.print key) n t.tracker_url file.file_name;
- (* in case we don't receive "min interval" *)
-@@ -1376,11 +1388,11 @@
- | String "key", String n ->
- t.tracker_key <- n;
- if !verbose_msg_clients then
-- lprintf_file_nl file "%s in file: %s has key: %s" t.tracker_url file.file_name n
-+ lprintf_file_nl (as_file file) "%s in file: %s has key: %s" t.tracker_url file.file_name n
- | String "tracker id", String n ->
- t.tracker_id <- n;
- if !verbose_msg_clients then
-- lprintf_file_nl file "%s in file: %s has tracker id %s" t.tracker_url file.file_name n
-+ lprintf_file_nl (as_file file) "%s in file: %s has tracker id %s" t.tracker_url file.file_name n
-
- | String "peers", List list ->
- List.iter (fun v ->
-@@ -1412,13 +1424,13 @@
- None -> true
- | Some reason ->
- if !verbose_connect then
-- lprintf_file_nl file "%s:%d blocked: %s"
-+ lprintf_file_nl (as_file file) "%s:%d blocked: %s"
- (Ip.to_string !peer_ip) !port reason;
- false)
- then
- let _ = new_client file !peer_id (!peer_ip,!port)
- in
-- if !verbose_sources > 1 then lprintf_file_nl file "Received %s:%d" (Ip.to_string !peer_ip)
-+ if !verbose_sources > 1 then lprintf_file_nl (as_file file) "Received %s:%d" (Ip.to_string !peer_ip)
- !port;
- ()
- | _ -> assert false
-@@ -1439,12 +1451,12 @@
- | String "private", Int n -> ()
- (* TODO: if set to 1, disable peer exchange *)
-
-- | _ -> lprintf_file_nl file "received unknown entry in answer from tracker: %s : %s" (Bencode.print key) (Bencode.print value)
-+ | _ -> lprintf_file_nl (as_file file) "received unknown entry in answer from tracker: %s : %s" (Bencode.print key) (Bencode.print value)
- ) list;
- (*Now, that we have added new clients to a file, it's time
- to connect to them*)
- if !verbose_sources > 0 then
-- lprintf_file_nl file "get_sources_from_tracker: got %i source(s) for file %s"
-+ lprintf_file_nl (as_file file) "get_sources_from_tracker: got %i source(s) for file %s"
- t.tracker_last_clients_num file.file_name;
- resume_clients file
-
-@@ -1473,7 +1485,7 @@
- (try
- connect_trackers file "" (fun _ _ -> ()) with _ -> ())
- | FilePaused -> () (*when we are paused we do nothing, not even logging this vvvv*)
-- | s -> lprintf_file_nl file "Other state %s!!" (string_of_state s)
-+ | s -> lprintf_file_nl (as_file file) "Other state %s!!" (string_of_state s)
- ) !current_files
-
- let upload_buffer = String.create 100000
-@@ -1554,13 +1566,12 @@
- iter_upload sock c
- )
-
--
--(** Probably useless now
--*)
- let file_resume file =
-- (*useless with no saving of sources
-- resume_clients file;
-- *)
-+ List.iter (fun t ->
-+ match t.tracker_status with
-+ Enabled -> ()
-+ | _ -> t.tracker_status <- Enabled
-+ ) file.file_trackers;
- (try get_sources_from_tracker file with _ -> ())
-
-
-@@ -1573,7 +1584,7 @@
- if file.file_tracker_connected then
- begin
- connect_trackers file "stopped" (fun _ _ ->
-- lprintf_file_nl file "Tracker return: stopped %s" file.file_name;
-+ lprintf_file_nl (as_file file) "Tracker return: stopped %s" file.file_name;
- file.file_tracker_connected <- false)
- end
-
-Index: src/networks/bittorrent/bTComplexOptions.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/bittorrent/bTComplexOptions.ml,v
-retrieving revision 1.36
-retrieving revision 1.38
-diff -u -r1.36 -r1.38
---- src/networks/bittorrent/bTComplexOptions.ml 16 Sep 2006 09:47:17 -0000 1.36
-+++ src/networks/bittorrent/bTComplexOptions.ml 1 Oct 2006 17:47:11 -0000 1.38
-@@ -183,8 +183,9 @@
- (Printf.sprintf "BT-%s" (Sha1.to_string file_id)) in
- file_temp
- in
-- let file = new_file file_id torrent torrent_diskname file_temp file_state in
--
-+ let file = new_file file_id torrent torrent_diskname
-+ file_temp file_state CommonUserDb.admin_user in
-+
- let file_uploaded = try
- value_to_int64 (List.assoc "file_uploaded" assocs)
- with _ -> zero
-@@ -249,7 +250,7 @@
- CommonSwarming.frontend_to_value swarmer assocs
- with
- e ->
-- lprintf_file_nl file "exception %s in file_to_value"
-+ lprintf_file_nl (as_file file) "exception %s in file_to_value"
- (Printexc2.to_string e); raise e
-
-
-Index: src/networks/bittorrent/bTGlobals.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/bittorrent/bTGlobals.ml,v
-retrieving revision 1.63
-retrieving revision 1.71
-diff -u -r1.63 -r1.71
---- src/networks/bittorrent/bTGlobals.ml 16 Sep 2006 09:47:17 -0000 1.63
-+++ src/networks/bittorrent/bTGlobals.ml 9 Nov 2006 21:32:27 -0000 1.71
-@@ -31,6 +31,7 @@
- open CommonServer
- open CommonResult
- open CommonFile
-+open CommonShared
- open BasicSocket
- open CommonGlobals
- open Options
-@@ -107,6 +108,45 @@
- let (client_ops : client CommonClient.client_ops) =
- CommonClient.new_client_ops network
-
-+let must_share_file file codedname has_old_impl =
-+ match file.file_shared with
-+ | Some _ -> ()
-+ | None ->
-+ begin
-+ let impl = {
-+ impl_shared_update = 1;
-+ impl_shared_fullname = file_disk_name file;
-+ impl_shared_codedname = codedname;
-+ impl_shared_size = file_size file;
-+ impl_shared_id = Md4.null;
-+ impl_shared_num = 0;
-+ impl_shared_uploaded = Int64.zero;
-+ impl_shared_ops = shared_ops;
-+ impl_shared_val = file;
-+ impl_shared_requests = 0;
-+ impl_shared_magic = None;
-+ impl_shared_servers = [];
-+ } in
-+ file.file_shared <- Some impl;
-+ incr CommonGlobals.nshared_files;
-+ CommonShared.shared_calculate_total_bytes ();
-+ match has_old_impl with
-+ None -> update_shared_num impl
-+ | Some old_impl -> replace_shared old_impl impl
-+ end
-+
-+let must_share_file file = must_share_file file (file_best_name (as_file file)) None
-+
-+let unshare_file file =
-+ match file.file_shared with
-+ None -> ()
-+ | Some s ->
-+ begin
-+ file.file_shared <- None;
-+ decr CommonGlobals.nshared_files;
-+ CommonShared.shared_calculate_total_bytes ()
-+ end
-+
- module DO = CommonOptions
-
- let current_files = ref ([] : BTTypes.file list)
-@@ -126,10 +166,6 @@
- let lprintf_nl fmt =
- lprintf_nl2 log_prefix fmt
-
--let lprintf_file_nl file fmt =
-- lprintf_nl2 (log_prefix^" [file_num "^(string_of_int (file_num file))^"]") fmt
--
--
- let lprintf_n fmt =
- lprintf2 log_prefix fmt
-
-@@ -217,13 +253,14 @@
- tracker_torrent_last_dl_req = 0;
- tracker_id = "";
- tracker_key = "";
-- tracker_enabled = true
-+ tracker_status = Enabled
- } in
-- t.tracker_enabled <- can_handle_tracker t;
-+ if not (can_handle_tracker t) then
-+ t.tracker_status <- Disabled_mld (intern "Tracker type not supported");
- file.file_trackers <- t :: file.file_trackers;
- set_trackers file q
-
--let new_file file_id t torrent_diskname file_temp file_state =
-+let new_file file_id t torrent_diskname file_temp file_state user =
- try
- Hashtbl.find files_by_uid file_id
- with Not_found ->
-@@ -233,7 +270,7 @@
- file_file = file_impl;
- file_piece_size = t.torrent_piece_size;
- file_id = file_id;
-- file_name = t.torrent_name;
-+ file_name = Charset.safe_convert t.torrent_encoding t.torrent_name;
- file_comment = t.torrent_comment;
- file_created_by = t.torrent_created_by;
- file_creation_date = t.torrent_creation_date;
-@@ -252,6 +289,8 @@
- file_shared = None;
- } and file_impl = {
- dummy_file_impl with
-+ impl_file_owner = user;
-+ impl_file_group = user.user_default_group;
- impl_file_fd = Some file_fd;
- impl_file_size = t.torrent_length;
- impl_file_downloaded = Int64.zero;
-@@ -296,18 +335,18 @@
- current_files := file :: !current_files;
- Hashtbl.add files_by_uid file_id file;
- file_add file_impl file_state;
--(* lprintf "ADD FILE TO DOWNLOAD LIST\n"; *)
-+ must_share_file file;
- file
-
--let new_download file_id t torrent_diskname =
-+let new_download file_id t torrent_diskname user =
- let file_temp = Filename.concat !!DO.temp_directory
- (Printf.sprintf "BT-%s" (Sha1.to_string file_id)) in
-- new_file file_id t torrent_diskname file_temp FileDownloading
-+ new_file file_id t torrent_diskname file_temp FileDownloading user
-
- let ft_by_num = Hashtbl.create 13
- let ft_counter = ref 0
-
--let new_ft file_name =
-+let new_ft file_name user =
- incr ft_counter;
- let rec ft = {
- ft_file = file_impl;
-@@ -316,6 +355,8 @@
- ft_retry = (fun _ -> ());
- } and file_impl = {
- dummy_file_impl with
-+ impl_file_owner = user;
-+ impl_file_group = user.user_default_group;
- impl_file_fd = None;
- impl_file_size = zero;
- impl_file_downloaded = Int64.zero;
-@@ -419,6 +460,11 @@
- | "TR" -> Brand_transmission
- | "HN" -> Brand_hydranode
- | "RT" -> Brand_retriever
-+ | "PC" -> Brand_cachelogic
-+ | "ES" -> Brand_electricsheep
-+ | "qB" -> Brand_qbittorrent
-+ | "QT" -> Brand_qt4
-+ | "UL" -> Brand_uleecher
- | _ -> Brand_unknown
- in
- if brand = Brand_unknown then None else
-@@ -450,6 +496,7 @@
- | "A" -> Brand_abc
- | "U" -> Brand_upnp
- | "O" -> Brand_osprey
-+ | "R" -> Brand_tribler
- | _ -> Brand_unknown
- in
- let bv = ref None in
-@@ -742,7 +789,7 @@
- client_downloaded = zero;
- client_upload_rate = Rate.new_rate ();
- client_downloaded_rate = Rate.new_rate ();
-- client_optimist_time=0;
-+ client_connect_time = last_time ();
- client_blocks_sent = [];
- client_new_chunks = [];
- client_good = false;
-@@ -753,6 +800,11 @@
- client_incoming = false;
- client_registered_bitfield = false;
- client_last_optimist = 0;
-+ client_dht = false;
-+ client_cache_extension = false;
-+ client_fast_extension = false;
-+ client_utorrent_extension = false;
-+ client_azureus_messaging_protocol = false;
- } and impl = {
- dummy_client_impl with
- impl_client_val = c;
-@@ -789,6 +841,11 @@
- lprintf_nl "New tracker list :%s" tracker.tracker_url
- ) file.file_trackers
-
-+let tracker_is_enabled t =
-+ match t.tracker_status with
-+ Enabled -> true
-+ | _ -> false
-+
- let torrents_directory = "torrents"
- let new_torrents_directory = Filename.concat torrents_directory "incoming"
- let downloads_directory = Filename.concat torrents_directory "downloads"
-Index: src/networks/bittorrent/bTInteractive.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/bittorrent/bTInteractive.ml,v
-retrieving revision 1.108
-retrieving revision 1.123
-diff -u -r1.108 -r1.123
---- src/networks/bittorrent/bTInteractive.ml 16 Sep 2006 09:47:17 -0000 1.108
-+++ src/networks/bittorrent/bTInteractive.ml 12 Nov 2006 14:17:45 -0000 1.123
-@@ -52,8 +52,34 @@
-
- module VB = VerificationBitmap
-
--exception Already_exists
--exception Torrent_can_not_be_used
-+let porttest_result = ref PorttestNotStarted
-+
-+let interpret_azureus_porttest s =
-+ let failure_message fmt =
-+ Printf.sprintf ("Port test failure, " ^^ fmt) in
-+ try
-+ let value = decode s in
-+ match value with
-+ | Dictionary alist ->
-+ (try
-+ match List.assoc (String "result") alist with
-+ | Int 1L -> "Port test OK!"
-+ | Int 0L ->
-+ (try
-+ match List.assoc (String "reason") alist with
-+ | String reason -> failure_message "%s" reason
-+ | _ -> raise Not_found
-+ with Not_found ->
-+ failure_message "%s" "no reason given")
-+ | Int status ->
-+ failure_message "unknown status code (%Ld)" status
-+ | _ -> raise Not_found
-+ with Not_found ->
-+ failure_message "%s" "no status given")
-+ | _ ->
-+ failure_message "unexpected value type %s" (Bencode.print value)
-+ with _ ->
-+ failure_message "%s" "broken bencoded value"
-
- let op_file_all_sources file =
- let list = ref [] in
-@@ -101,7 +127,7 @@
- set_file_state file FileShared;
-
- if Unix32.destroyed (file_fd file) then
-- if !verbose then lprintf_file_nl file "op_file_commit: FD is destroyed... repairing";
-+ if !verbose then lprintf_file_nl (as_file file) "op_file_commit: FD is destroyed... repairing";
-
- (* During the commit operation, for security, the file_fd is destroyed. So
- we create it again to be able to share this file again. *)
-@@ -110,7 +136,7 @@
- (create_temp_file new_name (List.map (fun (file,size,_) -> (file,size)) file.file_files) (file_state file));
-
- if Unix32.destroyed (file_fd file) then
-- lprintf_file_nl file "op_file_commit: FD is destroyed... could not repair!";
-+ lprintf_file_nl (as_file file) "op_file_commit: FD is destroyed... could not repair!";
-
- let new_torrent_diskname =
- Filename.concat seeded_directory
-@@ -119,20 +145,20 @@
- (try
- Unix2.rename file.file_torrent_diskname new_torrent_diskname;
- with _ ->
-- (lprintf_file_nl file "op_file_commit: failed to rename %s to %s"
-+ (lprintf_file_nl (as_file file) "op_file_commit: failed to rename %s to %s"
- file.file_torrent_diskname new_torrent_diskname));
- file.file_torrent_diskname <- new_torrent_diskname;
-
- end
-
--let op_file_print_html file buf =
--
-- html_mods_cntr_init ();
-+let op_file_print file o =
-
-+ let buf = o.conn_buf in
-+ if use_html_mods o then begin
- Printf.bprintf buf "\\</tr\\>\\<tr class=\\\"dl-%d\\\"\\>" (html_mods_cntr ());
- html_mods_td buf [
- ("Filename", "sr br", "Filename");
-- ("", "sr", file.file_name) ];
-+ ("", "sr", (Charset.safe_convert file.file_encoding file.file_name)) ];
-
- Printf.bprintf buf "\\</tr\\>\\<tr class=\\\"dl-%d\\\"\\>" (html_mods_cntr ());
- html_mods_td buf [
-@@ -143,24 +169,27 @@
- ];
-
- Printf.bprintf buf "\\</tr\\>\\<tr class=\\\"dl-%d\\\"\\>" (html_mods_cntr ());
-- html_mods_td buf [
-- ("Tracker(s)", "sr br", "Tracker(s)");
-- ("", "sr",
-- (let enabled_tracker_string = ref "" in
-- let disabled_tracker_string = ref "" in
-- List.iter (fun tracker ->
-- if tracker.tracker_enabled then
-- enabled_tracker_string := !enabled_tracker_string ^ (shorten tracker.tracker_url !!max_name_len) ^ " "
-- else
-- disabled_tracker_string := !disabled_tracker_string ^ (shorten tracker.tracker_url !!max_name_len) ^ " "
-- ) file.file_trackers;
-- (!enabled_tracker_string ^ (if !disabled_tracker_string <> "" then " - disabled: " ^ !disabled_tracker_string else "")))) ];
--
-- Printf.bprintf buf "\\</tr\\>\\<tr class=\\\"dl-%d\\\"\\>" (html_mods_cntr ());
-+ let tracker_header_printed = ref false in
-+ List.iter (fun tracker ->
-+ let tracker_text, tracker_error =
-+ (match tracker.tracker_status with
-+ Disabled s | Disabled_mld s | Disabled_failure s ->
-+ Printf.sprintf "disabled: %s" tracker.tracker_url, s
-+ | _ -> tracker.tracker_url, "")
-+ in
-+ html_mods_td buf [
-+ (if not !tracker_header_printed then
-+ ("Tracker(s) (mouseover for errors)", "sr br", "Tracker(s)")
-+ else
-+ ("", "sr br", ""));
-+ (tracker_error, "sr", tracker_text)];
-+ Printf.bprintf buf "\\</tr\\>\\<tr class=\\\"dl-%d\\\"\\>" (html_mods_cntr ());
-+ tracker_header_printed := true;
-+ ) file.file_trackers;
-
- html_mods_td buf [
- ("Torrent Filename", "sr br", "Torrent Fname");
-- ("", "sr", file.file_torrent_diskname) ];
-+ ("", "sr", (Charset.safe_convert file.file_encoding file.file_torrent_diskname)) ];
-
- Printf.bprintf buf "\\</tr\\>\\<tr class=\\\"dl-%d\\\"\\>" (html_mods_cntr ());
-
-@@ -168,14 +197,14 @@
- ("Comment", "sr br", "Comment");
- ("", "sr", match file.file_comment with
- "" -> "-"
-- | _ -> file.file_comment) ];
-+ | _ -> (Charset.safe_convert file.file_encoding file.file_comment)) ];
-
- Printf.bprintf buf "\\</tr\\>\\<tr class=\\\"dl-%d\\\"\\>" (html_mods_cntr ());
- html_mods_td buf [
- ("Created by", "sr br", "Created by");
- ("", "sr", match file.file_created_by with
- "" -> "-"
-- | _ -> file.file_created_by) ];
-+ | _ -> (Charset.safe_convert file.file_encoding file.file_created_by)) ];
-
- Printf.bprintf buf "\\</tr\\>\\<tr class=\\\"dl-%d\\\"\\>" (html_mods_cntr ());
- html_mods_td buf [
-@@ -187,7 +216,7 @@
- ("Modified by", "sr br", "Modified by");
- ("", "sr", match file.file_modified_by with
- "" -> "-"
-- | _ -> file.file_modified_by) ];
-+ | _ -> (Charset.safe_convert file.file_encoding file.file_modified_by)) ];
-
- Printf.bprintf buf "\\</tr\\>\\<tr class=\\\"dl-%d\\\"\\>" (html_mods_cntr ());
- html_mods_td buf [
-@@ -200,7 +229,7 @@
- match l with
- | [] -> ()
- | t :: q ->
-- if not t.tracker_enabled then print_first_tracker q
-+ if not (tracker_is_enabled t) then print_first_tracker q
- else begin
- Printf.bprintf buf "\\</tr\\>\\<tr class=\\\"dl-%d\\\"\\>" (html_mods_cntr ());
- html_mods_td buf [
-@@ -262,24 +291,42 @@
- end in
- print_first_tracker file.file_trackers;
-
-+ (* This is bad. Magic info should be automatically filled in when
-+ the corresponding chunks complete. (see CommonSwarming)
-+
-+ This code only fills in the magic info for subfiles when a user
-+ manually performs a "vd #". (interfaces out of sync)
-+
-+ Magic info for shared files with subfiles is missing as well?
-+ *)
-+ if !Autoconf.magic_works then begin
- let check_magic file =
- match Magic.M.magic_fileinfo file false with
- None -> None
-- | Some s -> Some (HashMagic.merge CommonGlobals.files_magic s)
-+ | Some s -> Some (intern s)
- in
-+ let fdn = file_disk_name file in
-+ let new_file_files = ref [] in
-+
-+ List.iter (fun (f, s, m) ->
-+ let subfile = Filename.concat fdn f in
-+ new_file_files := (f,s, check_magic subfile) :: !new_file_files;
-+ ) file.file_files;
-+
-+ file.file_files <- List.rev !new_file_files;
-+ file_must_update file; (* Send update to guis *)
-+
-+ end;
-+ (* -- End bad -- *)
-+
- let cntr = ref 0 in
-- List.iter (fun (filename, size, _) ->
-+ List.iter (fun (filename, size, magic) ->
- Printf.bprintf buf "\\</tr\\>\\<tr class=\\\"dl-%d\\\"\\>" (html_mods_cntr ());
- let fs = Printf.sprintf "File %d" !cntr in
- let magic_string =
-- if !Autoconf.magic_works then
-- begin
-- let subfile = Filename.concat (file_disk_name file) filename in
-- match check_magic subfile with
-+ match magic with
- None -> ""
-- | Some magic -> Printf.sprintf " / %s" magic
-- end
-- else ""
-+ | Some m -> Printf.sprintf " / %s" m;
- in
- html_mods_td buf [
- (fs, "sr br", fs);
-@@ -287,8 +334,68 @@
- ];
- incr cntr;
- ) file.file_files
-+ end else begin
-
--let op_file_print_sources_html file buf =
-+ Printf.bprintf buf "Trackers:\n";
-+ List.iter (fun tracker ->
-+ match tracker.tracker_status with
-+ Disabled s | Disabled_mld s | Disabled_failure s ->
-+ Printf.bprintf buf "%s, disabled: %s\n" tracker.tracker_url s
-+ | _ -> Printf.bprintf buf "%s\n" tracker.tracker_url
-+ ) file.file_trackers;
-+ let s = Charset.safe_convert file.file_encoding file.file_torrent_diskname in
-+ if s <> "" then Printf.bprintf buf "Torrent diskname: %s\n" s;
-+ let s = Charset.safe_convert file.file_encoding file.file_comment in
-+ if s <> "" then Printf.bprintf buf "Comment: %s\n" s;
-+ let s = Charset.safe_convert file.file_encoding file.file_created_by in
-+ if s <> "" then Printf.bprintf buf "Created by %s\n" s;
-+ let s = Date.to_string (Int64.to_float file.file_creation_date) in
-+ if s <> "" then Printf.bprintf buf "Creation date: %s\n" s;
-+ let s = Charset.safe_convert file.file_encoding file.file_modified_by in
-+ if s <> "" then Printf.bprintf buf "Modified by %s\n" s;
-+ if file.file_encoding <> "" then Printf.bprintf buf "Encoding: %s\n" file.file_encoding;
-+ if file.file_files <> [] then Printf.bprintf buf "Subfiles: %d\n" (List.length file.file_files);
-+ let cntr = ref 0 in
-+ List.iter (fun (filename, size, magic) ->
-+ incr cntr;
-+ let magic_string =
-+ match magic with
-+ None -> ""
-+ | Some m -> Printf.sprintf " / %s" m;
-+ in
-+ Printf.bprintf buf "File %d: %s (%Ld bytes)%s\n" !cntr filename size magic_string
-+ ) file.file_files
-+ end
-+
-+let op_file_print_sources file o =
-+ let buf = o.conn_buf in
-+
-+(* redefine functions for telnet output *)
-+ let html_mods_td buf l =
-+ if use_html_mods o then
-+ html_mods_td buf l
-+ else
-+ (* List *)
-+ List.iter (fun (t,c,d) ->
-+ (* Title Class Value *)
-+ Printf.bprintf buf "%s "
-+ d;
-+ ) l
-+ in
-+ let html_mods_table_header buf n c l =
-+ if use_html_mods o then
-+ html_mods_table_header buf n c l
-+ else
-+ if List.length l > 0 then begin
-+ Printf.bprintf buf "\n";
-+ List.iter (fun (w,x,y,z) ->
-+ (* Sort Class Title Value *)
-+ Printf.bprintf buf "%s "
-+ z;
-+ ) l;
-+ Printf.bprintf buf "\n"
-+ end
-+ in
-
- if Hashtbl.length file.file_clients > 0 then begin
-
-@@ -312,10 +419,15 @@
- ( "0", "srh ar", "Incoming [T]rue, [F]alse", "I" );
- ( "0", "srh br ar", "Registered bitfield [T]rue, [F]alse", "B" );
-
-- ( "0", "srh ar", "Optimist Time", "O" );
-+ ( "0", "srh ar", "Connect Time", "T" );
- ( "0", "srh ar", "Last optimist", "L.Opt" );
- ( "0", "srh br ar", "Num try", "N" );
-
-+ ( "0", "srh", "DHT [T]rue, [F]alse", "D" );
-+ ( "0", "srh", "Cache extensions [T]rue, [F]alse", "C" );
-+ ( "0", "srh", "Fast extensions [T]rue, [F]alse", "F" );
-+ ( "0", "srh", "uTorrent extensions [T]rue, [F]alse", "U" );
-+ ( "0", "srh br", "Azureus messaging protocol [T]rue, [F]alse", "A" );
- (*
- ( "0", "srh", "Bitmap (absent|partial|present|verified)", (colored_chunks
- (Array.init (String.length info.G.file_chunks)
-@@ -334,8 +446,10 @@
- html_mods_table_header buf "sourcesTable" "sources al" header_list;
-
- Hashtbl.iter (fun _ c ->
-+ if use_html_mods o then
- Printf.bprintf buf "\\<tr class=\\\"dl-%d\\\"\\>" (html_mods_cntr());
-
-+ let btos b = if b then "T" else "F" in
- let cc,cn = Geoip.get_country (fst c.client_host) in
- let td_list = [
- ("", "sr br ar", Printf.sprintf "%d" (client_num c));
-@@ -346,25 +460,31 @@
- ] @ (if !Geoip.active then [( cn, "sr br", cc)] else []) @ [
- ("", "sr ar", (size_of_int64 c.client_uploaded));
- ("", "sr ar br", (size_of_int64 c.client_downloaded));
-- ("", "sr", (if c.client_interested then "T" else "F"));
-- ("", "sr", (if c.client_choked then "T" else "F"));
-+ ("", "sr", (btos c.client_interested));
-+ ("", "sr", (btos c.client_choked));
- ("", "sr br ar", (Int64.to_string c.client_allowed_to_write));
- (* This is way too slow for 1000's of chunks on a page with 100's of sources
- ("", "sr", (CommonFile.colored_chunks (Array.init (String.length c.client_bitmap)
- (fun i -> (if c.client_bitmap.[i] = '1' then 2 else 0)) )) );
- *)
-- ("", "sr", (if c.client_interesting then "T" else "F"));
-- ("", "sr", (if c.client_alrd_sent_interested then "T" else "F"));
-- ("", "br sr", (if c.client_alrd_sent_notinterested then "T" else "F"));
--
-- ("", "sr", (if c.client_good then "T" else "F"));
-- ("", "sr", (if c.client_incoming then "T" else "F"));
-- ("", "br sr", (if c.client_registered_bitfield then "T" else "F"));
-+ ("", "sr", (btos c.client_interesting));
-+ ("", "sr", (btos c.client_alrd_sent_interested));
-+ ("", "br sr", (btos c.client_alrd_sent_notinterested));
-+
-+ ("", "sr", (btos c.client_good));
-+ ("", "sr", (btos c.client_incoming));
-+ ("", "br sr", (btos c.client_registered_bitfield));
-
-- ("", "sr", Printf.sprintf "%d" c.client_optimist_time);
-+ ("", "sr", Printf.sprintf "%d" c.client_connect_time);
- ("", "ar sr", string_of_date c.client_last_optimist);
- ("", "br sr", Printf.sprintf "%d" c.client_num_try);
-
-+ ("", "sr", (btos c.client_dht));
-+ ("", "sr", (btos c.client_cache_extension));
-+ ("", "sr", (btos c.client_fast_extension));
-+ ("", "sr", (btos c.client_utorrent_extension));
-+ ("", "br sr", (btos c.client_azureus_messaging_protocol));
-+
- ("", "sr ar", (let fc = ref 0 in
- (match c.client_bitmap with
- None -> ()
-@@ -374,19 +494,21 @@
- ] in
-
- html_mods_td buf td_list;
-- Printf.bprintf buf "\\</tr\\>";
-+ if use_html_mods o then Printf.bprintf buf "\\</tr\\>"
-+ else Printf.bprintf buf "\n";
-
- ) file.file_clients;
-
-- Printf.bprintf buf "\\</table\\>\\</div\\>\\<br\\>";
-+ if use_html_mods o then Printf.bprintf buf "\\</table\\>\\</div\\>\\<br\\>"
-+ else Printf.bprintf buf "\n";
-
- end
-
- let op_file_check file =
-- lprintf_file_nl file "Checking chunks of %s" file.file_name;
-+ lprintf_file_nl (as_file file) "Checking chunks of %s" file.file_name;
- match file.file_swarmer with
- None ->
-- lprintf_file_nl file "verify_chunks: no swarmer to verify chunks"
-+ lprintf_file_nl (as_file file) "verify_chunks: no swarmer to verify chunks"
- | Some swarmer ->
- CommonSwarming.verify_all_chunks_immediately swarmer
-
-@@ -434,6 +556,7 @@
- P.file_sub_files = file.file_files;
- P.file_active_sources = List.length (op_file_active_sources file);
- P.file_all_sources = (Hashtbl.length file.file_clients);
-+ P.file_comment = file.file_comment;
- }
-
- let op_ft_info ft =
-@@ -443,7 +566,7 @@
- {
- P.file_fields = P.Fields_file_info.all;
-
-- P.file_comment = "";
-+ P.file_comment = file_comment (as_ft ft);
- P.file_name = ft.ft_filename;
- P.file_num = ft_num ft;
- P.file_network = network.network_num;
-@@ -465,11 +588,16 @@
- P.file_priority = 0;
- P.file_uids = [];
- P.file_sub_files = [];
-+ P.file_magic = None;
-+ P.file_comments = [];
-+ P.file_user = "";
-+ P.file_group = "";
-+ P.file_release = file_release (as_ft ft);
- }
-
-
-
--let load_torrent_string s =
-+let load_torrent_string s user =
- let file_id, torrent = BTTorrent.decode_torrent s in
-
- (* Save the torrent, because we later want to put
-@@ -488,20 +616,19 @@
- if Sys.file_exists torrent_diskname then
- begin
- if !verbose then lprintf_nl "load_torrent_string: %s already exists, ignoring" torrent_diskname;
-- raise Already_exists
-+ raise Torrent_already_exists
- end;
- File.from_string torrent_diskname s;
-
- if !verbose then
- lprintf_nl "Starting torrent download with diskname: %s"
- torrent_diskname;
-- let file = new_download file_id torrent torrent_diskname in
-+ let file = new_download file_id torrent torrent_diskname user in
- BTClients.get_sources_from_tracker file;
-- BTShare.must_share_file file;
- CommonInteractive.start_download (file_find (file_num file));
- file
-
--let load_torrent_file filename =
-+let load_torrent_file filename user =
- if !verbose then
- lprintf_nl "load_torrent_file %s" filename;
- let s = File.to_string filename in
-@@ -510,27 +637,27 @@
- if Sys.file_exists filename
- && (Filename.dirname filename) = downloads_directory then
- Sys.remove filename;
-- ignore (load_torrent_string s)
-+ ignore (load_torrent_string s user)
-
- let parse_tracker_reply file t filename =
- (*This is the function which will be called by the http client
- for parsing the response*)
- (* Interested only in interval*)
-- if !verbose_msg_servers then lprintf_file_nl file "Filename %s" filename;
-+ if !verbose_msg_servers then lprintf_file_nl (as_file file) "Filename %s" filename;
- let tracker_reply =
- try
- File.to_string filename
-- with e -> lprintf_file_nl file "Empty reply from tracker"; ""
-+ with e -> lprintf_file_nl (as_file file) "Empty reply from tracker"; ""
- in
- let v =
- match tracker_reply with
- | "" ->
- if !verbose_connect then
-- lprintf_file_nl file "Empty reply from tracker";
-+ lprintf_file_nl (as_file file) "Empty reply from tracker";
- Bencode.decode ""
- | _ -> Bencode.decode tracker_reply
- in
-- if !verbose_msg_servers then lprintf_file_nl file "Received: %s" (Bencode.print v);
-+ if !verbose_msg_servers then lprintf_file_nl (as_file file) "Received: %s" (Bencode.print v);
- t.tracker_interval <- 600;
- match v with
- Dictionary list ->
-@@ -538,9 +665,9 @@
- match (key, value) with
- String "interval", Int n ->
- t.tracker_interval <- Int64.to_int n;
-- if !verbose_msg_servers then lprintf_file_nl file ".. interval %d .." t.tracker_interval
-+ if !verbose_msg_servers then lprintf_file_nl (as_file file) ".. interval %d .." t.tracker_interval
- | String "failure reason", String failure ->
-- lprintf_file_nl file "Failure from Tracker in file: %s Reason: %s" file.file_name failure
-+ lprintf_file_nl (as_file file) "Failure from Tracker in file: %s Reason: %s" file.file_name failure
- (*TODO: merge with f from get_sources_from_tracker and parse the rest of the answer, too.
- also connect to the sources we receive or instruct tracker to send none, perhaps based
- on an config option. firewalled people could activate the option and then seed torrents, too.*)
-@@ -559,7 +686,7 @@
- match list with
- [] -> raise Not_found
- | sh :: tail ->
-- let s = sharing_strategies sh.shdir_strategy in
-+ let s = sharing_strategy sh.shdir_strategy in
- if match torrent.torrent_files with
- [] -> not s.sharing_directories
- | _ -> s.sharing_directories then
-@@ -576,9 +703,8 @@
- in
-
- let file = new_file file_id torrent torrent_diskname
-- filename FileShared in
-- BTShare.must_share_file file;
-- if !verbose_share then lprintf_file_nl file "Sharing file %s" filename;
-+ filename FileShared CommonUserDb.admin_user in
-+ if !verbose_share then lprintf_file_nl (as_file file) "Sharing file %s" filename;
- BTClients.connect_trackers file "started"
- (parse_tracker_reply file)
- with
-@@ -636,13 +762,17 @@
- let file_basename = Filename.basename file in
- if not (Unix2.is_directory file) then
- try
-- load_torrent_file file;
-+ let user = fst (Unix32.owner file) in
-+ load_torrent_file file (try CommonUserDb.user2_user_find user with Not_found -> CommonUserDb.admin_user);
- (try Sys.remove file with _ -> ())
- with
- Torrent_can_not_be_used ->
- Unix2.rename file (Filename.concat old_directory file_basename);
- lprintf_nl "Torrent %s does not have valid tracker URLs, moved to torrents/old ..." file_basename
-- | e -> lprintf_nl "Error %s in scan_new_torrents_directory for %s" (Printexc2.to_string e) file_basename
-+ | e ->
-+ Unix2.rename file (Filename.concat old_directory file_basename);
-+ lprintf_nl "Error %s in scan_new_torrents_directory for %s, moved to torrents/old ..."
-+ (Printexc2.to_string e) file_basename
- ) filenames
-
- let retry_all_ft () =
-@@ -651,12 +781,12 @@
- lprintf_nl "ft_retry: exception %s" (Printexc2.to_string e)
- ) ft_by_num
-
--let load_torrent_from_web r ft =
-+let load_torrent_from_web r user ft =
- let module H = Http_client in
- H.wget r (fun filename ->
- if ft_state ft = FileDownloading then begin
-- load_torrent_file filename;
-- file_cancel (as_ft ft)
-+ load_torrent_file filename user;
-+ file_cancel (as_ft ft) CommonUserDb.admin_user
- end)
-
- let valid_torrent_extension url =
-@@ -669,7 +799,7 @@
- let b = Str.group_end 1 in
- String.sub text a (b - a)
-
--let op_network_parse_url url =
-+let op_network_parse_url url user =
- let location_regexp = "Location: \\(.*\\)" in
- try
- let real_url = get_regexp_string url (Str.regexp location_regexp) in
-@@ -700,13 +830,13 @@
- ) "" cookies
- ) ]
- with Not_found -> []);
-- H.req_max_retry = 10;
-+ H.req_max_retry = 10;
- } in
-
- let file_diskname = Filename.basename u.Url.short_file in
-- let ft = new_ft file_diskname in
-- ft.ft_retry <- load_torrent_from_web r ;
-- load_torrent_from_web r ft;
-+ let ft = new_ft file_diskname user in
-+ ft.ft_retry <- (load_torrent_from_web r user);
-+ load_torrent_from_web r user ft;
- "started download", true
- )
- else
-@@ -717,10 +847,10 @@
- try
- if !verbose then lprintf_nl "Not_found and trying to load %s" url;
- try
-- load_torrent_file url;
-+ load_torrent_file url user;
- "", true
- with
-- Already_exists -> "A torrent with this name is already in the download queue", false
-+ Torrent_already_exists -> "A torrent with this name is already in the download queue", false
- | Torrent_can_not_be_used -> "This torrent does not have valid tracker URLs", false
- with e ->
- lprintf_nl "Exception %s while 2nd loading" (Printexc2.to_string e);
-@@ -753,6 +883,7 @@
- P.client_downloaded = c.client_downloaded;
- P.client_uploaded = c.client_uploaded;
- P.client_upload = Some (c.client_file.file_name);
-+ P.client_connect_time = c.client_connect_time;
-
- }
-
-@@ -909,12 +1040,15 @@
- ), _s ":\t\t\t\tprint all .torrent files on this server";
-
- "seeded_torrents", "Network/Bittorrent", Arg_none (fun o ->
-+ if CommonUserDb.user2_is_admin o.conn_user.ui_user then begin
- List.iter (fun file ->
- if file_state file = FileShared then
- Printf.bprintf o.conn_buf "%s [%s]\n" file.file_name (Int64.to_string file.file_uploaded)
- ) !current_files;
- _s "done"
--
-+ end else
-+ begin print_command_result o o.conn_buf "You are not allowed to use seeded_torrents";
-+ "" end
- ), _s ":\t\t\tprint all seeded .torrent files on this server";
-
- "reshare_torrents", "Network/Bittorrent", Arg_none (fun o ->
-@@ -950,13 +1084,13 @@
- let buf = o.conn_buf in
- if Sys.file_exists url then
- begin
-- load_torrent_file url;
-+ load_torrent_file url o.conn_user.ui_user;
- Printf.bprintf buf "loaded file %s\n" url
- end
- else
- begin
- let url = "Location: " ^ url ^ "\nContent-Type: application/x-bittorrent" in
-- let result = fst (op_network_parse_url url) in
-+ let result = fst (op_network_parse_url url o.conn_user.ui_user) in
- Printf.bprintf buf "%s\n" result
- end;
- _s ""
-@@ -986,7 +1120,7 @@
- Hashtbl.iter (fun _ file ->
- if file_num file = num then begin
- if !verbose then
-- lprintf_file_nl file "adding trackers for file %i" num;
-+ lprintf_file_nl (as_file file) "adding trackers for file %i" num;
- set_trackers file !urls;
- raise Exit
- end
-@@ -1031,12 +1165,18 @@
- open LittleEndian
- open GuiDecoding
-
--let op_gui_message s =
-+let op_gui_message s user =
- match get_int16 s 0 with
- 0 ->
- let text = String.sub s 2 (String.length s - 2) in
- if !verbose then lprintf_nl "received torrent from gui...";
-- ignore (load_torrent_string text)
-+ (try
-+ ignore (load_torrent_string text user)
-+ with e -> (match e with
-+ Torrent_can_not_be_used -> lprintf_nl "Loading torrent from GUI: this torrent can not be used"
-+ | Torrent_already_exists -> lprintf_nl "Loading torrent from GUI: this torrent is already in download queue"
-+ | _ -> ());
-+ raise e)
- | 1 -> (* 34+ *)
- let n = get_int s 2 in
- let a, pos = get_string s 6 in
-@@ -1057,12 +1197,17 @@
- file_ops.op_file_active_sources <- op_file_active_sources;
- file_ops.op_file_debug <- op_file_debug;
- file_ops.op_file_commit <- op_file_commit;
-- file_ops.op_file_print_html <- op_file_print_html;
-- file_ops.op_file_print_sources_html <- op_file_print_sources_html;
-+ file_ops.op_file_print <- op_file_print;
-+ file_ops.op_file_print_sources <- op_file_print_sources;
- file_ops.op_file_check <- op_file_check;
- file_ops.op_file_cancel <- op_file_cancel;
- file_ops.op_file_info <- op_file_info;
- file_ops.op_file_save_as <- (fun file name -> ());
-+ file_ops.op_file_shared <- (fun file ->
-+ match file.file_shared with
-+ None -> None
-+ | Some sh -> Some (as_shared sh)
-+ );
-
- network.op_network_gui_message <- op_gui_message;
- network.op_network_connected <- op_network_connected;
-@@ -1072,7 +1217,7 @@
- network.op_network_forget_search <- (fun s -> ());
- network.op_network_connect_servers <- (fun s -> ());
- network.op_network_search <- (fun ss buf -> ());
-- network.op_network_download <- (fun r -> dummy_file);
-+ network.op_network_download <- (fun r user -> dummy_file);
- network.op_network_recover_temp <- (fun s -> ());
- let clean_exit_started = ref false in
- network.op_network_clean_exit <- (fun s ->
-@@ -1090,7 +1235,25 @@
- !!client_port, "client_port TCP";
- !!BTTracker.tracker_port, "tracker_port TCP";
- ]);
--
-+ network.op_network_porttest_result <- (fun _ -> !porttest_result);
-+ network.op_network_porttest_start <- (fun _ ->
-+ let module H = Http_client in
-+ azureus_porttest_random := (Random.int 100000);
-+ porttest_result := PorttestInProgress (last_time ());
-+ let r = {
-+ H.basic_request with
-+ H.req_url =
-+ Url.of_string (Printf.sprintf
-+ "http://azureus.aelitis.com/natcheck.php?port=%d&check=azureus_rand_%d"
-+ !!client_port !azureus_porttest_random);
-+ H.req_proxy = !CommonOptions.http_proxy;
-+ H.req_user_agent = get_user_agent ();
-+ } in
-+ H.wget r (fun file ->
-+ let result = interpret_azureus_porttest (File.to_string file) in
-+ porttest_result := PorttestResult (last_time (), result)
-+ )
-+ );
- client_ops.op_client_info <- op_client_info;
- client_ops.op_client_connect <- op_client_connect;
- client_ops.op_client_disconnect <- op_client_disconnect;
-@@ -1101,8 +1264,8 @@
- CommonNetwork.register_commands commands;
-
- shared_ops.op_shared_unshare <- (fun file ->
-- (if !verbose_share then lprintf_file_nl file "unshare file");
-- BTShare.unshare_file file);
-+ (if !verbose_share then lprintf_file_nl (as_file file) "unshare file");
-+ BTGlobals.unshare_file file);
- shared_ops.op_shared_info <- (fun file ->
- let module T = GuiTypes in
- match file.file_shared with
-Index: src/networks/bittorrent/bTProtocol.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/bittorrent/bTProtocol.ml,v
-retrieving revision 1.25
-retrieving revision 1.27
-diff -u -r1.25 -r1.27
---- src/networks/bittorrent/bTProtocol.ml 15 Dec 2005 19:41:46 -0000 1.25
-+++ src/networks/bittorrent/bTProtocol.ml 1 Oct 2006 17:54:00 -0000 1.27
-@@ -231,9 +231,16 @@
- open AnyEndian
- open BTTypes
-
-+let log_prefix = "[BT]"
-+
-+let lprintf_nl fmt =
-+ lprintf_nl2 log_prefix fmt
-+
-+let azureus_porttest_random = ref 0
-+
- type ghandler =
- BTHeader of (gconn -> TcpBufferedSocket.t ->
-- (string * Sha1.t) -> unit)
-+ (string * string * Sha1.t) -> unit)
- | Reader of (gconn -> TcpBufferedSocket.t -> unit)
-
- and gconn = {
-@@ -538,9 +545,13 @@
- let file_id = Sha1.direct_of_string
- (String.sub b.buf (b.pos+9+slen) 20) in
- let proto,pos = get_string8 b.buf b.pos in
-+ let rbits = (String.sub b.buf (b.pos+pos) 8) in
- buf_used b (slen+29);
-- h gconn sock (proto, file_id);
-+ h gconn sock (proto, rbits, file_id);
- end
-+ else
-+ if (String.sub b.buf b.pos (min b.len 100)) = "NATCHECK_HANDSHAKE" then
-+ write_string sock (Printf.sprintf "azureus_rand_%d" !azureus_porttest_random)
- else if (TcpBufferedSocket.closed sock) then
- let (ip,port) = (TcpBufferedSocket.peer_addr sock) in
- lprintf_nl "bt-handshake: closed sock from %s:%d b.len:%i slen:%i"
-Index: src/networks/bittorrent/bTShare.ml
-===================================================================
-RCS file: src/networks/bittorrent/bTShare.ml
-diff -N src/networks/bittorrent/bTShare.ml
---- src/networks/bittorrent/bTShare.ml 12 May 2006 21:08:30 -0000 1.3
-+++ /dev/null 1 Jan 1970 00:00:00 -0000
-@@ -1,67 +0,0 @@
--(* Copyright 2001, 2002, 2005 b8_bavard, b8_fee_carabine, INRIA *)
--(*
-- This file is part of mldonkey.
--
-- mldonkey is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
--
-- mldonkey is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with mldonkey; if not, write to the Free Software
-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
--*)
--
--open CommonGlobals
--open Printf2
--open Md4
--open CommonDownloads
--open CommonFile
--open CommonShared
--open CommonTypes
--open Options
--open BTTypes
--open BTGlobals
--
--let must_share_file file codedname has_old_impl =
-- match file.file_shared with
-- | Some _ -> ()
-- | None ->
-- begin
-- let impl = {
-- impl_shared_update = 1;
-- impl_shared_fullname = file_disk_name file;
-- impl_shared_codedname = codedname;
-- impl_shared_size = file_size file;
-- impl_shared_id = Md4.null;
-- impl_shared_num = 0;
-- impl_shared_uploaded = Int64.zero;
-- impl_shared_ops = shared_ops;
-- impl_shared_val = file;
-- impl_shared_requests = 0;
-- impl_shared_magic = None;
-- } in
-- file.file_shared <- Some impl;
-- incr CommonGlobals.nshared_files;
-- CommonShared.shared_calculate_total_bytes ();
-- match has_old_impl with
-- None -> update_shared_num impl
-- | Some old_impl -> replace_shared old_impl impl
-- end
--
--let must_share_file file = must_share_file file (file_best_name (as_file file)) None
--
--let unshare_file file =
-- match file.file_shared with
-- None -> ()
-- | Some s ->
-- begin
-- file.file_shared <- None;
-- decr CommonGlobals.nshared_files;
-- CommonShared.shared_calculate_total_bytes ()
-- end
-Index: src/networks/bittorrent/bTStats.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/bittorrent/bTStats.ml,v
-retrieving revision 1.7
-retrieving revision 1.8
-diff -u -r1.7 -r1.8
---- src/networks/bittorrent/bTStats.ml 26 Jan 2006 10:34:53 -0000 1.7
-+++ src/networks/bittorrent/bTStats.ml 23 Sep 2006 20:29:47 -0000 1.8
-@@ -93,6 +93,14 @@
- let _ =
- network.op_network_display_stats <- (fun buf o -> print_stats o New);
-
-+ network.op_network_stat_info_list <- (fun _ ->
-+ let l1 = stats_list brand_list stats_array in
-+ let l2 = stats_list brand_list !!gstats_array in
-+ let u1 = BasicSocket.last_time () - BasicSocket.start_time in
-+ let u2 = (guptime() + u1) in
-+ [("Session clients", u1, l1); ("Global clients", u2, l2)]
-+ );
-+
- register_commands
- [
- "client_stats_bt", "Network/Bittorrent",Arg_none (fun o ->
-Index: src/networks/bittorrent/bTTypes.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/bittorrent/bTTypes.ml,v
-retrieving revision 1.36
-retrieving revision 1.39
-diff -u -r1.36 -r1.39
---- src/networks/bittorrent/bTTypes.ml 12 Sep 2006 22:44:52 -0000 1.36
-+++ src/networks/bittorrent/bTTypes.ml 8 Oct 2006 14:02:05 -0000 1.39
-@@ -104,6 +104,14 @@
- | Brand_retriever
- | Brand_osprey
- | Brand_rufus
-+| Brand_tribler
-+| Brand_cachelogic
-+| Brand_electricsheep
-+| Brand_qbittorrent
-+| Brand_qt4
-+| Brand_uleecher
-+
-+
-
- let brand_list = [
- ( Brand_unknown , "unknown" , "unk" ) ;
-@@ -163,6 +171,12 @@
- ( Brand_retriever , "Retriever" , "ret" ) ;
- ( Brand_osprey , "Osprey permaseed" , "osp" ) ;
- ( Brand_rufus , "Rufus" , "ruf" ) ;
-+ ( Brand_tribler , "Tribler" , "trb" ) ;
-+ ( Brand_cachelogic , "CacheLogic" , "cl" ) ;
-+ ( Brand_electricsheep , "Electric sheep" , "els" ) ;
-+ ( Brand_qbittorrent , "qBittorrent" , "qbt" ) ;
-+ ( Brand_qt4 , "QT4" , "qt4" ) ;
-+ ( Brand_uleecher , "uLeecher!" , "ul!" ) ;
- ]
-
- let brand_count = List.length brand_list
-@@ -176,6 +190,12 @@
- let brand_to_int brand =
- find_int_of_brand brand brand_list
-
-+type tracker_status =
-+ Enabled
-+| Disabled of string
-+| Disabled_mld of string
-+| Disabled_failure of string
-+
- type client = {
- client_client : client CommonClient.client_impl;
- mutable client_file : file;
-@@ -207,7 +227,7 @@
- mutable client_downloaded_rate : Rate.t;
- mutable client_downloaded : int64;
- mutable client_uploaded : int64;
-- mutable client_optimist_time : int;
-+ mutable client_connect_time : int;
-
- mutable client_blocks_sent : int list;
- mutable client_good : bool;
-@@ -218,6 +238,13 @@
- mutable client_incoming : bool;
- mutable client_registered_bitfield : bool;
- mutable client_last_optimist : int;
-+
-+ mutable client_dht : bool;
-+ mutable client_cache_extension : bool;
-+ mutable client_fast_extension : bool;
-+ mutable client_utorrent_extension : bool;
-+ mutable client_azureus_messaging_protocol : bool;
-+
- }
-
- and tracker_info = {
-@@ -233,7 +260,7 @@
- mutable tracker_torrent_last_dl_req : int;
- mutable tracker_id : string;
- mutable tracker_key : string;
-- mutable tracker_enabled : bool;
-+ mutable tracker_status : tracker_status;
- }
-
- and file = {
-Index: src/networks/direct_connect/dcClients.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/direct_connect/dcClients.ml,v
-retrieving revision 1.12
-retrieving revision 1.13
-diff -u -r1.12 -r1.13
---- src/networks/direct_connect/dcClients.ml 10 Apr 2006 19:16:36 -0000 1.12
-+++ src/networks/direct_connect/dcClients.ml 21 Nov 2006 22:34:33 -0000 1.13
-@@ -273,7 +273,7 @@
- let rec refill sock =
- lprintf "FILL SOCKET"; lprint_newline ();
- let len = remaining_to_write sock in
-- let can = maxi (8192 - len) 0 in
-+ let can = max (8192 - len) 0 in
- if can > 0 then
- match c.client_download with
- DcUploadList list ->
-@@ -281,7 +281,7 @@
- let slen = String.length list in
- let pos = Int64.to_int c.client_pos in
- if pos < slen then begin
-- let send_len = mini (slen - pos) can in
-+ let send_len = min (slen - pos) can in
- lprintf "Sending %d" send_len; lprint_newline ();
- TcpBufferedSocket.write sock list pos send_len;
- lprintf "sent"; lprint_newline ();
-Index: src/networks/direct_connect/dcInteractive.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/direct_connect/dcInteractive.ml,v
-retrieving revision 1.27
-retrieving revision 1.28
-diff -u -r1.27 -r1.28
---- src/networks/direct_connect/dcInteractive.ml 5 Sep 2006 14:15:19 -0000 1.27
-+++ src/networks/direct_connect/dcInteractive.ml 1 Oct 2006 17:54:00 -0000 1.28
-@@ -380,6 +380,7 @@
- [
- !!dc_port, "client_port";
- ]);
-+ network.op_network_porttest_result <- (fun _ -> PorttestNotAvailable);
- network.op_network_recover_temp <- (fun s -> ());
- network.op_network_load_complex_options <- (fun _ -> ());
- network.op_network_save_complex_options <- (fun _ -> ());
-Index: src/networks/direct_connect/dcProtocol.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/direct_connect/dcProtocol.ml,v
-retrieving revision 1.4
-retrieving revision 1.5
-diff -u -r1.4 -r1.5
---- src/networks/direct_connect/dcProtocol.ml 6 Sep 2005 11:24:59 -0000 1.4
-+++ src/networks/direct_connect/dcProtocol.ml 12 Nov 2006 12:42:55 -0000 1.5
-@@ -601,7 +601,7 @@
- module MultiConnectToMe = NickAndAddr(struct let msg = "MultiConnectToMe" end)
-
- module Msg = struct
-- type t = ()
-+ type t = unit
-
- let parse s = ()
-
-@@ -950,4 +950,4 @@
- in
- iter 0 shared_tree;
- Buffer.contents buf
--
-\ No newline at end of file
-+
-Index: src/networks/donkey/donkeyClient.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyClient.ml,v
-retrieving revision 1.99
-retrieving revision 1.109
-diff -u -r1.99 -r1.109
---- src/networks/donkey/donkeyClient.ml 5 Sep 2006 14:18:24 -0000 1.99
-+++ src/networks/donkey/donkeyClient.ml 21 Nov 2006 22:34:33 -0000 1.109
-@@ -80,7 +80,7 @@
- (* without server, we can't request a callback *)
- let s = Hashtbl.find servers_by_key serverIP in
- if serverPort = s.server_port then
-- Indirect_address ( serverIP, serverPort, id_of_ip ip, port, ip )
-+ Indirect_address ( serverIP, serverPort, id_of_ip ip, 0, Ip.null )
- else
- raise Not_found
- with _ ->
-@@ -192,9 +192,13 @@
- M.AvailableSlotReq Q.t);
-
- if !verbose then
-- lprintf_nl "New uploader %s"
-- (full_client_identifier c);
--
-+ lprintf_nl "New uploader %s%s%s"
-+ (full_client_identifier c)
-+ (let slot_text = string_of_slot_kind (client_slot (as_client c)) true in
-+ if slot_text = "" then "" else Printf.sprintf "(%s)" slot_text)
-+ (match client_upload (as_client c) with
-+ None -> ""
-+ | Some f -> Printf.sprintf " for file %s" (CommonFile.file_best_name f))
- )
- in
- client_ops.op_client_enter_upload_queue <- client_enter_upload_queue
-@@ -262,7 +266,7 @@
- c.client_connect_time <- 0;
- (try Hashtbl.remove connected_clients c.client_md4 with _ -> ());
- (try CommonUploads.remove_pending_slot (as_client c) with _ -> ());
-- set_client_has_a_slot (as_client c) false;
-+ set_client_has_a_slot (as_client c) NoSlot;
- (* connection_failed c.client_connection_control; *)
- (try TcpBufferedSocket.close sock reason with _ -> ());
-
-@@ -673,6 +677,11 @@
- DonkeyProtoClient.update_emule_proto_from_miscoptions1
- c.client_emule_proto i
- )
-+ | Field_UNKNOWN "emule_compatoptions" ->
-+ for_int_tag tag (fun i ->
-+ DonkeyProtoClient.update_emule_proto_from_compatoptions
-+ c.client_emule_proto i
-+ );
- | Field_UNKNOWN "emule_version" ->
- for_int_tag tag (fun i ->
- c.client_emule_proto.emule_version <- i;
-@@ -686,8 +695,9 @@
- | Field_UNKNOWN "mod_version" ->
- let s = to_lowercase (string_of_tag_value tag.tag_value) in
- parse_mod_version s c
-- | _ -> ()
--
-+ | _ ->
-+ if !verbose_msg_clienttags then
-+ lprintf_nl "Unknown Emule tag: [%s] (update_client_from_tags)" (escaped_string_of_field tag)
- ) tags
-
- let update_emule_proto_from_tags c tags =
-@@ -727,9 +737,15 @@
- | Field_UNKNOWN "mod_version" ->
- let s = to_lowercase (string_of_tag_value tag.tag_value) in
- parse_mod_version s c;
-+
-+ | Field_UNKNOWN "os_info" ->
-+ let s = to_lowercase (string_of_tag_value tag.tag_value) in
-+ (match c.client_osinfo with
-+ Some _ -> ()
-+ | _ -> if s <> "" then c.client_osinfo <- Some s)
- | _ ->
-- if !verbose_msg_clients then
-- lprintf_nl "Unknown Emule tag: [%s]" (escaped_string_of_field tag)
-+ if !verbose_msg_clienttags then
-+ lprintf_nl "Unknown Emule tag: [%s] (update_emule_proto_from_tags)" (escaped_string_of_field tag)
- ) tags
-
- let fight_disguised_mods c =
-@@ -743,6 +759,19 @@
- if c.client_brand = Brand_emuleplus && c.client_brand_mod = Brand_mod_plus then
- c.client_brand_mod <- Brand_mod_unknown
-
-+let request_osinfo c =
-+ if c.client_emule_proto.emule_osinfosupport = 1 && not c.client_osinfo_sent then
-+ begin
-+ let emule_osinfo = {
-+ emule_info with
-+ DonkeyProtoClient.EmuleClientInfo.protversion = 255;
-+ DonkeyProtoClient.EmuleClientInfo.tags = [
-+ string_tag (Field_UNKNOWN "os_info") (String2.upp_initial Autoconf.system);
-+ ]} in
-+ client_send c (DonkeyProtoClient.EmuleClientInfoReq emule_osinfo);
-+ c.client_osinfo_sent <- true
-+ end
-+
- let rec query_id ip port id =
- let client_ip = client_ip None in
-
-@@ -1049,14 +1078,14 @@
- let process_mule_info c t =
- update_emule_proto_from_tags c t;
- update_emule_release c;
-- if !!enable_sui
-+ client_must_update c;
-+ if sec_ident_enabled ()
- && (c.client_md4 <> Md4.null)
- && (c.client_sent_challenge == Int64.zero)
- && (c.client_emule_proto.emule_secident > 0)
- then begin
-- if !verbose_msg_clients then begin
-+ if !verbose_msg_clients then
- lprintf_nl "%s [process_mule_info] [verify_ident]" (full_client_identifier c);
-- end;
- verify_ident c
- end
-
-@@ -1108,7 +1137,7 @@
-
- init_client_after_first_message sock c;
-
-- set_client_has_a_slot (as_client c) false;
-+ set_client_has_a_slot (as_client c) NoSlot;
-
- let module CR = M.Connect in
-
-@@ -1178,14 +1207,10 @@
- if !!emule_mods_count then
- identify_client_brand_mod c t.CI.tags;
-
-- (* TODO : remove this comment
-- ERR! i think the peer support eep if it send an emule client info
-- PLUS this message is sent _before_ we received an md4 so
-- client_brand is unknown here.
-- if supports_eep c.client_brand then begin
-- *)
-- let module E = M.EmuleClientInfo in
-- client_send c (M.EmuleClientInfoReplyReq emule_info)
-+ let module E = M.EmuleClientInfo in
-+ client_send c (M.EmuleClientInfoReplyReq emule_info);
-+ request_osinfo c;
-+
-
- | M.EmuleClientInfoReplyReq t ->
-
-@@ -1272,9 +1297,6 @@
- (Printexc2.to_string e);
- end;
-
-- | M.EmuleFileDescReq (rate, comment) ->
-- if comment <> "" then set_file_comment c.client_last_asked_file comment
--
- | M.AvailableSlotReq _ ->
- set_lifetime sock active_lifetime;
- set_rtimeout sock !!queued_timeout;
-@@ -1367,8 +1389,11 @@
- end else *)
- CommonUploads.add_pending_slot (as_client c);
- if !verbose_upload then
-- lprintf_nl "donkeyClient: uploader couldn't get a slot: %s"
-- (full_client_identifier c);
-+ lprintf_nl "added to pending slots: %s %s"
-+ (full_client_identifier c)
-+ (match client_upload (as_client c) with
-+ None -> ""
-+ | Some f -> CommonFile.file_best_name f);
- (* end *)
-
- | M.CloseSlotReq _ ->
-@@ -1424,6 +1449,28 @@
- with _ -> ()
- end
-
-+ | M.EmuleFileDescReq t ->
-+ begin
-+ match c.client_last_file_req_md4 with
-+ Some md4 ->
-+ begin
-+ try
-+ let file = find_file md4 in
-+ let module Q = M.EmuleFileDesc in
-+ let slen = String.length t.Q.comment in
-+ if slen > 0 && slen <= !!max_comment_length && (!is_not_comment_spam) t.Q.comment then begin
-+ (* Disallow dups from single IP, but allow comment updates *)
-+ file.file_comments <- List.filter (fun (i,_,_,_) -> i <> c.client_ip) file.file_comments;
-+ if List.length file.file_comments < !!max_comments_per_file then begin
-+ file.file_comments <- (c.client_ip, c.client_name, t.Q.rating, (intern t.Q.comment)) :: file.file_comments;
-+ file_must_update file;
-+ end;
-+ end
-+ with _ -> ()
-+ end
-+ | None -> ()
-+ end
-+
- | M.QueryChunksReplyReq t ->
- let module Q = M.QueryChunksReply in
- begin
-@@ -1675,7 +1722,7 @@
- shared_must_update_downloaded (as_shared impl);
- impl.impl_shared_requests <- impl.impl_shared_requests + 1);
- request_for c file sock;
-- set_client_upload (as_client c) (shared_of_file file);
-+ set_client_upload (as_client c) (as_file file);
- client_send c (
- let module Q = M.QueryFileReply in
- let filename = file_best_name file in
-@@ -1708,7 +1755,7 @@
- end
-
- | M.EmuleSignatureReq t ->
-- if !!enable_sui then
-+ if sec_ident_enabled () then
- begin
- let module Q = M.EmuleSignatureReq in
-
-@@ -1763,7 +1810,7 @@
- end
-
- | M.EmulePublicKeyReq t ->
-- if !!enable_sui then
-+ if sec_ident_enabled () then
- begin
- let module Q = M.EmulePublicKeyReq in
- (match c.client_public_key with
-@@ -1788,12 +1835,11 @@
- );
- end
- else
-- if !verbose_msg_clients then begin
-- lprintf_nl "%s [EPubKeyReq] [DISABLED]" (full_client_identifier c) ;
-- end
-+ if !verbose_msg_clients then
-+ lprintf_nl "%s [EPubKeyReq] [DISABLED]" (full_client_identifier c);
-
- | M.EmuleSecIdentStateReq t ->
-- if !!enable_sui then
-+ if sec_ident_enabled () then
- begin
- let module Q = M.EmuleSecIdentStateReq in
-
-@@ -1816,9 +1862,8 @@
- then send_signature c;
-
- end else
-- if !verbose_msg_clients then begin
-- lprintf_nl "%s [ESecIdentStateReq] [DISABLED]" (full_client_identifier c) ;
-- end
-+ if !verbose_msg_clients then
-+ lprintf_nl "%s [ESecIdentStateReq] [DISABLED]" (full_client_identifier c);
-
- | M.EmuleRequestSourcesReplyReq t ->
- (* lprintf "Emule sent sources\n"; *)
-@@ -1964,7 +2009,7 @@
- let module Q = M.QueryBloc in
- let file = find_file t.Q.md4 in
- let prio = (file_priority file) in
-- let client_upload_lifetime = ref ((maxi 0 !!upload_lifetime) * 60) in
-+ let client_upload_lifetime = ref ((max 0 !!upload_lifetime) * 60) in
- begin
-
- if !!dynamic_upload_lifetime
-@@ -2011,7 +2056,7 @@
- new_chunk up t.Q.start_pos2 t.Q.end_pos2;
- new_chunk up t.Q.start_pos3 t.Q.end_pos3;
- c.client_upload <- Some up;
-- set_client_upload (as_client c) (shared_of_file file);
-+ set_client_upload (as_client c) (as_file file);
- if not waiting && !CommonUploads.has_upload = 0 then begin
- CommonUploads.ready_for_upload (as_client c);
- up.up_waiting <- true
-@@ -2107,7 +2152,7 @@
- (* c.client_block <- None; *)
- (* c.client_zones <- []; *)
- c.client_file_queue <- [];
-- set_client_has_a_slot (as_client c) false;
-+ set_client_has_a_slot (as_client c) NoSlot;
- c.client_upload <- None;
- c.client_rank <- 0;
- c.client_requests_received <- 0;
-@@ -2118,7 +2163,8 @@
- let module M = DonkeyProtoClient in
-
- if !verbose_msg_clients then begin
-- lprintf_nl "Message from incoming client";
-+ lprintf_nl "Message from incoming client %s:%d"
-+ (Ip.to_string (peer_ip sock)) (peer_port sock);
- M.print m;
- end;
-
-@@ -2224,6 +2270,7 @@
- client_send c (M.EmuleClientInfoReq emule_info)
- end;
-
-+ request_osinfo c;
- client_send c (
- let module M = DonkeyProtoClient in
- let module C = M.Connect in
-@@ -2261,7 +2308,14 @@
- | M.NewUserIDReq _ ->
- lprintf_nl "NewUserIDReq: "; M.print m;
- None
--
-+
-+ | M.EmulePortTestReq t ->
-+ porttest_sock := Some sock;
-+ set_closer sock (fun _ _ -> porttest_sock := None);
-+ set_lifetime sock 30.;
-+ write_string sock (client_msg_to_string (emule_proto ()) m);
-+ None
-+
- | _ ->
- if !verbose_unknown_messages then
- begin
-@@ -2446,11 +2500,11 @@
- (if is_connecting_server then
- ( try
- let s = Hashtbl.find servers_by_key from_ip in
-- Printf.sprintf " %s (%s)" s.server_name (Ip.to_string s.server_ip)
-+ Printf.sprintf " %s (%s)" s.server_name (string_of_server s)
- with _ ->
- try
- let s = Hashtbl.find servers_by_key connecting_server in
-- Printf.sprintf " %s (%s)" s.server_name (Ip.to_string s.server_ip)
-+ Printf.sprintf " %s (%s)" s.server_name (string_of_server s)
- with _ -> "Unknown server"
- )
- else ""
-@@ -2510,7 +2564,6 @@
- try
- let c = find_client_by_key s_uid in
- let file = find_file (Md4.of_string file_uid) in
-- c.client_last_asked_file <- (as_file file);
- c.client_requests_sent <- c.client_requests_sent + 1;
- let module M = DonkeyProtoClient in
-
-@@ -2538,6 +2591,7 @@
- (* TODO build the extension if needed *)
- M.QueryFile.emule_extension = emule_extension;
- });
-+ c.client_last_file_req_md4 <- Some file.file_md4;
- let know_file_chunks = List.exists (fun (f,_,_) -> f == file) c.client_file_queue in
- if not know_file_chunks then
- DonkeyProtoCom.client_send c (
-@@ -2560,7 +2614,7 @@
- | Invalid_address _ -> ()
- | Indirect_address (server_ip, server_port, id, port, real_ip) ->
-
-- if low_id server_ip && Ip.reachable server_ip then
-+ if Ip.reachable server_ip then
- query_id server_ip server_port id;
-
- with e ->
-@@ -2598,7 +2652,7 @@
- (CommonClient.as_client c.client_client);
-
- with
-- Not_found -> ()
-+ | Not_found -> ()
- | e ->
- if !verbose then
- lprintf_nl "add_location: exception %s" (Printexc2.to_string e)
-@@ -2613,9 +2667,9 @@
- (CommonClient.as_client c.client_client);
-
- with
-- Not_found -> ()
-+ | Not_found -> ()
- | e ->
- if !verbose then
- lprintf_nl "remove_location for file_md4 %s: exception %s"
-- file_uid (Printexc2.to_string e)
-+ file_uid (Printexc2.to_string e)
- )
-Index: src/networks/donkey/donkeyComplexOptions.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyComplexOptions.ml,v
-retrieving revision 1.57
-retrieving revision 1.59
-diff -u -r1.57 -r1.59
---- src/networks/donkey/donkeyComplexOptions.ml 5 Sep 2006 14:15:19 -0000 1.57
-+++ src/networks/donkey/donkeyComplexOptions.ml 21 Nov 2006 22:34:33 -0000 1.59
-@@ -193,7 +193,7 @@
- with _ -> ());
- (try
- connection_set_last_conn l.server_connection_control
-- (normalize_time (mini (get_value "server_age" value_to_int)
-+ (normalize_time (min (get_value "server_age" value_to_int)
- (BasicSocket.last_time ())));
- with _ -> ());
- as_server l.server_server
-@@ -273,7 +273,7 @@
- in
-
- let file = DonkeyGlobals.new_file file_diskname file_state
-- (Md4.of_string file_md4) file_size "" true in
-+ (Md4.of_string file_md4) file_size "" true CommonUserDb.admin_user in
-
- (try
- set_file_best_name (as_file file)
-Index: src/networks/donkey/donkeyFiles.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyFiles.ml,v
-retrieving revision 1.20
-retrieving revision 1.22
-diff -u -r1.20 -r1.22
---- src/networks/donkey/donkeyFiles.ml 19 May 2006 23:43:54 -0000 1.20
-+++ src/networks/donkey/donkeyFiles.ml 21 Nov 2006 22:34:33 -0000 1.22
-@@ -79,8 +79,8 @@
- (* let len_int = Int32.to_int len in *)
- try
- if !verbose_upload then
-- lprintf_nl "send_small_block (%s) %Ld %d"
-- (full_client_identifier c)
-+ lprintf_nl "Sending %s to %s, begin %Ld len %d"
-+ (file_best_name file) (full_client_identifier c)
- (begin_pos) (len_int);
-
- let msg =
-@@ -130,12 +130,12 @@
- end else
- let max_len = up.up_end_chunk -- up.up_pos in
- let max_len = Int64.to_int max_len in
-- let msg_block_size_int = mini msg_block_size_int per_client in
-+ let msg_block_size_int = min msg_block_size_int per_client in
- if max_len <= msg_block_size_int then
- (* last block from chunk *)
- begin
- if !verbose_upload then
-- lprintf_nl "END OF CHUNK (%d) %Ld" max_len up.up_end_chunk;
-+ lprintf_nl "End of chunk (%d) %Ld %s" max_len up.up_end_chunk (file_best_name up.up_file);
- send_small_block c sock up.up_file up.up_pos max_len;
- up.up_chunks <- chunks;
- let per_client = per_client - max_len in
-@@ -165,7 +165,7 @@
- do_if_connected c.client_source.DonkeySources.source_sock (fun sock ->
- (* lprintf "upload_to_client %d connected\n" (maxi max_msg_size size); *)
-
-- let size = mini max_msg_size size in
-+ let size = min max_msg_size size in
- send_client_block c sock size;
- (match c.client_upload with
- None -> ()
-Index: src/networks/donkey/donkeyGlobals.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyGlobals.ml,v
-retrieving revision 1.96
-retrieving revision 1.107
-diff -u -r1.96 -r1.107
---- src/networks/donkey/donkeyGlobals.ml 16 Sep 2006 15:36:59 -0000 1.96
-+++ src/networks/donkey/donkeyGlobals.ml 21 Nov 2006 21:38:00 -0000 1.107
-@@ -125,8 +125,6 @@
- let tag_server = 201
- let tag_file = 202
-
--let page_size = 4096L
--
- let donkey_download_counter = ref Int64.zero
- let donkey_upload_counter = ref Int64.zero
-
-@@ -140,6 +138,8 @@
- E.tags = [];
- }
-
-+let sec_ident_enabled () = !!enable_sui && (Autoconf.donkey_sui_works ())
-+
- let overnet_connectreply_tags = ref ([] : tag list)
- let overnet_connect_tags = ref ([] : tag list)
-
-@@ -184,8 +184,7 @@
- let master_server = ref (None: DonkeyTypes.server option)
- let udp_sock = ref (None: UdpSocket.t option)
- let listen_sock = ref (None : TcpServerSocket.t option)
--let reversed_sock = ref (None : TcpServerSocket.t option)
--let new_shared = ref false
-+let porttest_sock = ref (None : TcpBufferedSocket.t option)
-
- (*************************************************************************)
- (* *)
-@@ -230,7 +229,6 @@
- let shared_files_info = (Hashtbl.create 127
- : (string * int64 * float, shared_file_info) Hashtbl.t)
- let shared_files = ref ([] : file_to_share list)
--let new_shared_files = ref []
-
- let udp_servers_replies = (Hashtbl.create 127 : (Md4.t, server) Hashtbl.t)
-
-@@ -311,7 +309,7 @@
- set_file_best_name file best_name "" 0
- with Not_found -> ()
-
--let new_file file_diskname file_state md4 file_size filename writable =
-+let new_file file_diskname file_state md4 file_size filename writable user =
-
- try
- let file = find_file md4 in
-@@ -379,8 +377,8 @@
- (try
- Unix32.remove t
- with e ->
-- lprintf_nl "Unix32.remove %s exception %s"
-- (file_diskname) (Printexc2.to_string e));
-+ lprintf_nl "Unix32.remove %s exception %s"
-+ (file_diskname) (Printexc2.to_string e));
- Unix32.destroy t;
- failwith (Printf.sprintf "file size %s is too big, exception: %s"
- (size_of_int64 file_size) (Printexc2.to_string e))
-@@ -398,10 +396,13 @@
- file_computed_md4s = Array.of_list md4s;
- file_format = FormatNotComputed 0;
- file_sources = DonkeySources.create_file_sources_manager
-- (Md4.to_string md4)
-+ (Md4.to_string md4);
-+ file_comments = [];
- }
- and file_impl = {
- dummy_file_impl with
-+ impl_file_owner = user;
-+ impl_file_group = user.user_default_group;
- impl_file_val = file;
- impl_file_ops = file_ops;
- impl_file_age = last_time ();
-@@ -427,10 +428,7 @@
- Verification (Array.of_list (List.map (fun md4 -> Ed2k md4) md4s))
- );
- CommonSwarming.set_verified swarmer (fun nblocks num ->
-- if nblocks = 1 then begin
-- new_shared_files := file :: !new_shared_files;
-- file_must_update file
-- end)
-+ if nblocks = 1 then file_must_update file)
- );
-
- update_best_name file;
-@@ -466,7 +464,10 @@
- let is_black_address ip port =
- !!black_list && not (low_id ip) && (
- (* lprintf "is black ="; *)
-- not (Ip.reachable ip) || (Ip.matches ip !!server_black_list) ||
-+ not (Ip.reachable ip) ||
-+ (match Ip_set.match_ip !server_black_list_set ip with
-+ | Some br -> true
-+ | None -> false) ||
- (List.mem port !!port_black_list) ||
- (match !Ip.banned ip with
- None -> false
-@@ -513,13 +514,27 @@
- server_id_requests = Fifo.create ();
- server_flags = 0;
- server_has_zlib = false;
-+ server_has_newtags = false;
-+ server_has_unicode = false;
-+ server_has_related_search = false;
-+ server_has_tag_integer = false;
-+ server_has_largefiles = false;
-+ server_has_udp_obfuscation = false;
-+ server_has_tcp_obfuscation = false;
- server_version = "";
- server_lowid_users = None;
- server_soft_limit = None;
- server_hard_limit = None;
-+ server_obfuscation_port_tcp = None;
-+ server_obfuscation_port_udp = None;
-+ server_udp_key = None;
-+ server_udp_keyip = None;
-+ server_sent_shared = [];
- server_max_users = None;
- server_last_ping = 0.;
- server_ping = 0;
-+ server_dynip = "";
-+ server_auxportslist = "";
-
- }
- and server_impl =
-@@ -565,11 +580,11 @@
- client_file_queue = [];
- client_tags = [];
- client_name = "";
-- client_last_asked_file = dummy_file;
- client_all_files = None;
- client_rating = 0;
- client_brand = Brand_unknown;
- client_brand_mod = Brand_mod_unknown;
-+ client_osinfo = None;
- client_checked = false;
- client_connected = false;
- client_downloaded = Int64.zero;
-@@ -592,6 +607,8 @@
- client_sent_challenge = Int64.zero;
- client_public_key = None;
- client_sui_verified = None;
-+ client_last_file_req_md4 = None;
-+ client_osinfo_sent = false;
- } and
- client_impl = {
- dummy_client_impl with
-@@ -604,7 +621,9 @@
-
- let create_client key =
- let module D = DonkeyProtoClient in
-- let s = DonkeySources.find_source_by_uid key in
-+ let s = DonkeySources.find_source_by_uid (match key with
-+ Indirect_address (server_ip, server_port, id, port, real_ip) -> Indirect_address (server_ip, server_port, id, 0, Ip.null)
-+ | _ -> key) in
- let rec c = {
- client_client = client_impl;
- client_kind = key;
-@@ -616,11 +635,11 @@
- client_file_queue = [];
- client_tags = [];
- client_name = "";
-- client_last_asked_file = dummy_file;
- client_all_files = None;
- client_rating = 0;
- client_brand = Brand_unknown;
- client_brand_mod = Brand_mod_unknown;
-+ client_osinfo = None;
- client_checked = false;
- client_connected = false;
- client_downloaded = Int64.zero;
-@@ -643,6 +662,8 @@
- client_sent_challenge = Int64.zero;
- client_public_key = None;
- client_sui_verified = None;
-+ client_last_file_req_md4 = None;
-+ client_osinfo_sent = false;
- } and client_impl = {
- dummy_client_impl with
- impl_client_val = c;
-@@ -656,17 +677,27 @@
- clients_root := c :: !clients_root;
- c
-
-+exception ClientFound of client
-+let find_client_by_key key =
-+ try
-+ H.iter (fun c ->
-+ if (match c.client_kind with
-+ Indirect_address (server_ip, server_port, id, port, real_ip) -> Indirect_address (server_ip, server_port, id, 0, Ip.null)
-+ | _ -> c.client_kind) = (match key with
-+ Indirect_address (server_ip, server_port, id, port, real_ip) -> Indirect_address (server_ip, server_port, id, 0, Ip.null)
-+ | _ -> key) then raise (ClientFound c)
-+ ) clients_by_kind;
-+ raise Not_found
-+ with ClientFound c -> c
-+
- let new_client key =
- try
-- H.find clients_by_kind { dummy_client with client_kind = key }
-+ find_client_by_key key
- with _ ->
- create_client key
-
- let create_client = ()
-
--let find_client_by_key key =
-- H.find clients_by_kind { dummy_client with client_kind = key }
--
- let client_type c =
- client_type (as_client c)
-
-@@ -687,6 +718,8 @@
- | Invalid_address _ -> ""
- )
-
-+let string_of_server s =
-+ Printf.sprintf "%s:%d" (Ip.to_string s.server_ip) s.server_port
-
- let set_client_name c name md4 =
- if name <> c.client_name || c.client_md4 <> md4 then begin
-@@ -798,7 +831,6 @@
- Printf.bprintf buf " udp_servers_list: %d\n" (List.length !udp_servers_list);
- Printf.bprintf buf " interesting_clients: %d\n" (List.length !interesting_clients);
- Printf.bprintf buf " shared_files: %d\n" (List.length !shared_files);
-- Printf.bprintf buf " new_shared_files: %d\n" (List.length !new_shared_files);
- Printf.bprintf buf " servers_by_key: %d\n" (Hashtbl.length servers_by_key);
- Printf.bprintf buf " banned_ips: %d\n" (Hashtbl.length banned_ips);
- Printf.bprintf buf " old_requests: %d\n" (Hashtbl.length old_requests);
-Index: src/networks/donkey/donkeyImport.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyImport.ml,v
-retrieving revision 1.9
-retrieving revision 1.10
-diff -u -r1.9 -r1.10
---- src/networks/donkey/donkeyImport.ml 3 Apr 2006 20:50:09 -0000 1.9
-+++ src/networks/donkey/donkeyImport.ml 14 Nov 2006 18:42:59 -0000 1.10
-@@ -54,14 +54,28 @@
-
-
- let names_of_tag =
-+(* eMule sourcefile opcodes.h //server.met *)
- [
-- "\001", Field_UNKNOWN "name";
-- "\015", Field_UNKNOWN "port";
-- "\016", Field_UNKNOWN "ip";
-- "\012", Field_UNKNOWN "ping";
-- "\014", Field_UNKNOWN "prof";
-- "\013", Field_UNKNOWN "history";
-- "\011", Field_UNKNOWN "description";
-+ "\001", Field_UNKNOWN "name"; (* 0x01 string *)
-+ "\011", Field_UNKNOWN "description"; (* 0x0B string *)
-+ "\012", Field_UNKNOWN "ping"; (* 0x0C uint32 *)
-+ "\013", Field_UNKNOWN "history"; (* 0x0D ST_FAIL *)
-+ "\014", Field_UNKNOWN "prof"; (* 0x0E ST_PREFERENCE *)
-+ "\015", Field_UNKNOWN "port"; (* 0x0F uint32 *)
-+ "\016", Field_UNKNOWN "ip"; (* 0x10 uint32 *)
-+ "\133", Field_UNKNOWN "dynip"; (* 0x85 string *)
-+ "\135", Field_UNKNOWN "maxusers"; (* 0x87 uint32 *)
-+ "\136", Field_UNKNOWN "softfiles"; (* 0x88 uint32 *)
-+ "\137", Field_UNKNOWN "hardfiles"; (* 0x89 uint32 *)
-+ "\144", Field_UNKNOWN "lastping"; (* 0x90 uint32 *)
-+ "\145", Field_UNKNOWN "version"; (* 0x91 string|uint32 *)
-+ "\146", Field_UNKNOWN "udpflags"; (* 0x92 uint32 *)
-+ "\147", Field_UNKNOWN "auxportslist"; (* 0x93 string *)
-+ "\148", Field_UNKNOWN "lowidusers"; (* 0x94 uint32 *)
-+ "\149", Field_UNKNOWN "udpkey"; (* 0x95 uint32 *)
-+ "\150", Field_UNKNOWN "udpkeyip"; (* 0x96 uint32 *)
-+ "\151", Field_UNKNOWN "tcpportobfuscation"; (* 0x97 uint16 *)
-+ "\152", Field_UNKNOWN "udpportobfuscation"; (* 0x98 uint16 *)
- ]
-
-
-Index: src/networks/donkey/donkeyInteractive.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyInteractive.ml,v
-retrieving revision 1.122
-retrieving revision 1.138
-diff -u -r1.122 -r1.138
---- src/networks/donkey/donkeyInteractive.ml 5 Sep 2006 14:18:24 -0000 1.122
-+++ src/networks/donkey/donkeyInteractive.ml 20 Nov 2006 22:48:43 -0000 1.138
-@@ -21,6 +21,8 @@
- open Printf2
- open Md4
- open Options
-+open LittleEndian
-+open AnyEndian
-
- open BasicSocket
- open TcpBufferedSocket
-@@ -60,8 +62,15 @@
- let _s x = _s "DonkeyInteractive" x
- let _b x = _b "DonkeyInteractive" x
-
-+let porttest_result = ref PorttestNotStarted
-+
- module VB = VerificationBitmap
-
-+let log_prefix = "[EDK]"
-+
-+let lprintf_nl fmt =
-+ lprintf_nl2 log_prefix fmt
-+
- let result_name r =
- match r.result_names with
- [] -> None
-@@ -104,12 +113,49 @@
- let server = check_add_server r.S.ip r.S.port in
- List.iter (fun tag ->
- match tag with
-- { tag_name = Field_UNKNOWN "name"; tag_value = String s } ->
-+ | { tag_name = Field_UNKNOWN "name"; tag_value = String s } ->
- server.server_name <- s;
- | { tag_name = Field_UNKNOWN "description" ; tag_value = String s } ->
- server.server_description <- s
-- | _ -> ()
-- ) r.S.tags
-+ | { tag_name = Field_UNKNOWN "version" ; tag_value = Uint64 s } ->
-+ server.server_version <- Printf.sprintf "%d.%d"
-+ ((Int64.to_int s) lsr 16) ((Int64.to_int s) land 0xFFFF)
-+ | { tag_name = Field_UNKNOWN "ping" ; tag_value = Uint64 s } ->
-+ server.server_ping <- (Int64.to_int s)
-+ | { tag_name = Field_UNKNOWN "dynip" ; tag_value = String s } ->
-+ server.server_dynip <- s
-+ | { tag_name = Field_UNKNOWN "users" ; tag_value = Uint64 s } ->
-+ (match server.server_nusers with
-+ | None -> server.server_nusers <- Some s | _ -> ())
-+ | { tag_name = Field_UNKNOWN "files" ; tag_value = Uint64 s } ->
-+ (match server.server_nfiles with
-+ | None -> server.server_nfiles <- Some s | _ -> ())
-+ | { tag_name = Field_UNKNOWN "maxusers" ; tag_value = Uint64 s } ->
-+ (match server.server_max_users with
-+ | None -> server.server_max_users <- Some s | _ -> ())
-+ | { tag_name = Field_UNKNOWN "softfiles" ; tag_value = Uint64 s } ->
-+ (match server.server_soft_limit with
-+ | None -> server.server_soft_limit <- Some s | _ -> ())
-+ | { tag_name = Field_UNKNOWN "hardfiles" ; tag_value = Uint64 s } ->
-+ (match server.server_hard_limit with
-+ | None -> server.server_hard_limit <- Some s | _ -> ())
-+ | { tag_name = Field_UNKNOWN "auxportslist" ; tag_value = String s } ->
-+ server.server_auxportslist <- s
-+ | { tag_name = Field_UNKNOWN "lowusers" ; tag_value = Uint64 s } ->
-+ (match server.server_lowid_users with
-+ | None -> server.server_lowid_users <- Some s | _ -> ())
-+ | { tag_name = Field_UNKNOWN "tcpportobfuscation" ; tag_value = Uint64 s } ->
-+ (match server.server_obfuscation_port_tcp with
-+ | None -> server.server_obfuscation_port_tcp <- Some (Int64.to_int s) | _ -> ())
-+ | { tag_name = Field_UNKNOWN "udpportobfuscation" ; tag_value = Uint64 s } ->
-+ (match server.server_obfuscation_port_udp with
-+ | None -> server.server_obfuscation_port_udp <- Some (Int64.to_int s) | _ -> ())
-+ | { tag_name = Field_UNKNOWN "country" ; tag_value = String s } -> ()
-+ | { tag_name = Field_UNKNOWN "udpflags" ; tag_value = Uint64 s } -> ()
-+ | { tag_name = Field_UNKNOWN "refs" ; tag_value = Uint64 s } -> ()
-+ | _ -> lprintf_nl "parsing server.met, unknown field %s" (string_of_tag tag)
-+ ) r.S.tags;
-+ server_must_update server
- with _ -> ()
- ) ss;
- List.length ss
-@@ -181,14 +227,11 @@
- )
-
- let already_done = Failure (Printf.sprintf (_b "File already downloaded (use 'force_download' if necessary)"))
--
- let no_download_to_force = Failure (Printf.sprintf (_b "No forceable download found"))
-+exception Already_downloading of string
-+exception Already_shared of string
-
--let already_downloading = Failure (Printf.sprintf (_b "File is already in download queue"))
--
--let already_shared = Failure (Printf.sprintf (_b "File is already shared"))
--
--let really_query_download filename size md4 location old_file absents =
-+let really_query_download filename size md4 location old_file absents user =
-
- begin
- try
-@@ -226,7 +269,7 @@
- end;
-
- (* TODO RESULT let other_names = DonkeyIndexer.find_names md4 in *)
-- let file = new_file file_diskname FileDownloading md4 size filename true in
-+ let file = new_file file_diskname FileDownloading md4 size filename true user in
- begin
- match absents with
- None -> ()
-@@ -295,7 +338,7 @@
- );
- as_file file
-
--let query_download filename size md4 location old_file absents force =
-+let query_download filename size md4 location old_file absents force user =
- if force then
- if !forceable_download = [] then
- raise no_download_to_force
-@@ -303,20 +346,23 @@
- begin
- let f = List.hd !forceable_download in
- forceable_download := [];
-- really_query_download (List.hd f.result_names) f.result_size md4 None None None
-+ really_query_download (List.hd f.result_names) f.result_size md4 None None None user
- end
- else
- begin
- try
- let file = find_file md4 in
- if (file_state file) = FileShared then
-- raise already_shared
-+ raise (Already_shared (Printf.sprintf (_b "File is already shared%s")
-+ (match file.file_shared with
-+ None -> ""
-+ | Some sh -> (" in " ^ (Filename2.dirname sh.impl_shared_fullname)))))
- else
- begin
- (* jave TODO: if a user currently not downloading this file is requesting the download add this user
- to the list of users currently downloading this file *)
- forceable_download := [];
-- raise already_downloading
-+ raise (Already_downloading (Printf.sprintf (_b "File is already in download queue of %s") (file_owner (as_file file)).CommonTypes.user_name))
- end
- with Not_found ->
- begin
-@@ -336,19 +382,19 @@
- else
- begin
- forceable_download := [];
-- really_query_download filename size md4 location old_file absents
-+ really_query_download filename size md4 location old_file absents user
- end
- end
- end
-
--let result_download r filenames force =
-+let result_download r filenames force user =
- let rec iter uids =
- match uids with
- [] -> raise IgnoreNetwork
- | uid :: tail ->
- match Uid.to_uid uid with
- Ed2k md4 ->
-- query_download (List.hd filenames) r.result_size md4 None None None force
-+ query_download (List.hd filenames) r.result_size md4 None None None force user
- | _ -> iter tail
- in
- iter r.result_uids
-@@ -391,7 +437,7 @@
- (match !filename_met with
- None -> filename
- | Some s -> s) !size f.P.md4 None
-- (Some filename) (Some (List.rev f.P.absents)));
-+ (Some filename) (Some (List.rev f.P.absents)) CommonUserDb.admin_user);
- with _ -> ()
- ) list
-
-@@ -508,7 +554,7 @@
-
-
-
--let parse_donkey_url url =
-+let parse_donkey_url url user =
- let url = Str.global_replace (Str.regexp "|sources,") "|sources|" url in
- match String2.split url '|' with
- (* TODO RESULT *)
-@@ -536,7 +582,7 @@
- begin
- try
- let file = query_download name (Int64.of_string size)
-- (Md4.of_string md4) None None None false in
-+ (Md4.of_string md4) None None None false user in
- let new_file = find_file (Md4.of_string md4) in
- CommonInteractive.start_download file;
- if !new_sources <> [] then
-@@ -547,7 +593,10 @@
- (Printf.sprintf (_b "added %d sources to new download") (List.length !new_sources)), true
- end
- else "", true
-- with e -> (Printexc2.to_string e), false
-+ with
-+ Already_downloading (s)
-+ | Already_shared (s) -> s, false
-+ | e -> (Printexc2.to_string e), false
- end
- end
- | "ed2k://" :: "file" :: name :: size :: md4 :: _
-@@ -566,12 +615,14 @@
- in
- begin try
- let file = query_download name (Int64.of_string size)
-- (Md4.of_string md4) None None None false;
-+ (Md4.of_string md4) None None None false user;
- in
- CommonInteractive.start_download file;
- "", true
-- with e ->
-- (Printexc2.to_string e), false
-+ with
-+ Already_downloading (s)
-+ | Already_shared (s) -> s, false
-+ | e -> (Printexc2.to_string e), false
- end
- | "ed2k://" :: "server" :: ip :: port :: _
- | "server" :: ip :: port :: _ ->
-@@ -713,8 +764,8 @@
- "id", Arg_none (fun o ->
- let buf = o.conn_buf in
- List.iter (fun s ->
-- Printf.bprintf buf "For %s:%d (%s) ---> %s\n"
-- (Ip.to_string s.server_ip) s.server_port s.server_name
-+ Printf.bprintf buf "For %s (%s) ---> %s\n"
-+ (string_of_server s) s.server_name
- (match s.server_cid with
- None -> "waiting"
- | Some ip ->
-@@ -764,11 +815,11 @@
-
- "bs", Arg_multiple (fun args o ->
- List.iter (fun arg ->
-- let ip = Ip.of_string arg in
-- server_black_list =:= ip :: !!server_black_list;
-+ let range = Ip.range_of_string arg in
-+ server_black_list =:= range :: !!server_black_list;
- ) args;
- "done"
-- ), "<ip1> <ip2> ... :\t\t\tadd these IPs to the servers black list";
-+ ), "<range1> <range2> ... :\t\t\tadd these IPs to the servers black list (can be single IPs, CIDR ranges or begin-end ranges)";
-
- "port", Arg_one (fun arg o ->
- donkey_port =:= int_of_string arg;
-@@ -776,6 +827,7 @@
- "<port> :\t\t\t\tchange connection port";
-
- "scan_temp", Arg_none (fun o ->
-+ if CommonUserDb.user2_is_admin o.conn_user.ui_user then begin
- let buf = o.conn_buf in
- let list = Unix2.list_directory !!temp_directory in
-
-@@ -873,24 +925,22 @@
- ) list;
-
- if use_html_mods o then Printf.bprintf buf "\\</table\\>\\</div\\>";
-+ "" end
-+ else begin
-+ print_command_result o o.conn_buf "You are not allowed to use scan_temp";
-+ "" end
-
-- ""
- ), ":\t\t\t\tprint temp directory content";
-
- "sources", Arg_none (fun o ->
-- let buf = o.conn_buf in
-- DonkeySources.print buf o.conn_output;
-- ""
-+ if CommonUserDb.user2_is_admin o.conn_user.ui_user then begin
-+ DonkeySources.print o.conn_buf o.conn_output;
-+ "" end
-+ else begin
-+ print_command_result o o.conn_buf "You are not allowed to list sources";
-+ "" end
- ), ":\t\t\t\tshow sources currently known";
-
-- (*
-- "update_sources", Arg_none (fun o ->
-- let buf = o.conn_buf in
-- DonkeySources.recompute_ready_sources ();
-- "done"
-- ), ":\t\t\trecompute order of connections to sources (experimental)";
--*)
--
- "xs", Arg_none (fun o ->
- let buf = o.conn_buf in
- if !xs_last_search >= 0 then begin
-@@ -920,7 +970,7 @@
- (* TODO RESULT *)
- "dd", Arg_two(fun size md4 o ->
- let file = query_download md4 (Int64.of_string size)
-- (Md4.of_string md4) None None None false in
-+ (Md4.of_string md4) None None None false o.conn_user.ui_user in
- CommonInteractive.start_download file;
- "download started"
- ), "<size> <md4> :\t\t\tdownload from size and md4";
-@@ -1003,8 +1053,8 @@
- with
- Not_found -> ()
- );
-- network.op_network_download <- (fun r ->
-- result_download r r.result_names r.result_force
-+ network.op_network_download <- (fun r user ->
-+ result_download r r.result_names r.result_force user
- )
-
- module P = GuiTypes
-@@ -1042,6 +1092,7 @@
- P.file_format = file.file_format;
- P.file_chunks_age = last_seen;
- P.file_uids = [Uid.create (Ed2k file.file_md4)];
-+ P.file_comments = file.file_comments
- } in
- v
- with e ->
-@@ -1066,13 +1117,28 @@
- P.server_description = s.server_description;
- P.server_banner = s.server_banner;
- P.server_preferred = s.server_preferred;
-+ P.server_master = s.server_master;
-+ P.server_published_files = (List.length s.server_sent_shared);
- P.server_version = s.server_version;
- P.server_max_users = (match s.server_max_users with None -> 0L | Some v -> v);
- P.server_soft_limit = (match s.server_soft_limit with None -> 0L | Some v -> v);
- P.server_hard_limit = (match s.server_hard_limit with None -> 0L | Some v -> v);
- P.server_lowid_users = (match s.server_lowid_users with None -> 0L | Some v -> v);
- P.server_ping = s.server_ping;
--
-+ P.server_features = let temp_buf = Buffer.create 100 in
-+ if s.server_has_zlib then Printf.bprintf temp_buf "zlib ";
-+ if s.server_has_newtags then Printf.bprintf temp_buf "newtags ";
-+ if s.server_has_unicode then Printf.bprintf temp_buf "unicode ";
-+ if s.server_has_related_search then Printf.bprintf temp_buf "related_search ";
-+ if s.server_has_tag_integer then Printf.bprintf temp_buf "tag_integer ";
-+ if s.server_has_largefiles then Printf.bprintf temp_buf "largefiles ";
-+ (match s.server_obfuscation_port_tcp with
-+ | Some p -> Printf.bprintf temp_buf "tcp_obfuscation(%d) " p | _ -> ());
-+ (match s.server_obfuscation_port_udp with
-+ | Some p -> Printf.bprintf temp_buf "udp_obfuscation(%d) " p | _ -> ());
-+ if s.server_auxportslist <> "" then Printf.bprintf temp_buf "auxportslist %s " s.server_auxportslist;
-+ if s.server_dynip <> "" then Printf.bprintf temp_buf "dynip %s " s.server_dynip;
-+ if Buffer.contents temp_buf <> "" then Some (Buffer.contents temp_buf) else None;
- }
- else raise Not_found
- )
-@@ -1125,14 +1191,15 @@
- P.client_rating = c.client_rating;
- P.client_connect_time = c.client_connect_time;
- P.client_software = brand_to_string_short c.client_brand;
-+ P.client_os = c.client_osinfo;
- P.client_release = c.client_emule_proto.emule_release;
- P.client_emulemod = brand_mod_to_string_short c.client_brand_mod;
- P.client_downloaded = c.client_downloaded;
- P.client_uploaded = c.client_uploaded;
- (* P.client_source.source_sock_addr = (); *)
- P.client_upload =
-- (match c.client_upload with
-- Some cu -> Some (file_best_name cu.up_file)
-+ (match client_upload (as_client c) with
-+ Some f -> Some (CommonFile.file_best_name f)
- | None -> None);
- P.client_sui_verified = c.client_sui_verified;
- }
-@@ -1165,6 +1232,9 @@
- server_ops.op_server_users <- (fun s ->
- List2.tail_map (fun u -> as_user u.user_user) s.server_users) ;
-
-+ server_ops.op_server_published <- (fun s ->
-+ List.map (fun f -> as_file f) s.server_sent_shared);
-+
- server_ops.op_server_cid <- (fun s -> ip_of_server_cid s);
-
- server_ops.op_server_low_id <- (fun s -> low_id (ip_of_server_cid s));
-@@ -1184,6 +1254,11 @@
- add_file_filenames (as_file file) name;
- set_file_best_name (as_file file) name "" 0
- );
-+ file_ops.op_file_shared <- (fun file ->
-+ match file.file_shared with
-+ None -> None
-+ | Some sh -> Some (as_shared sh)
-+ );
- file_ops.op_file_set_format <- (fun file format ->
- file.file_format <- format);
- file_ops.op_file_check <- op_file_check;
-@@ -1208,10 +1283,16 @@
- ) file.file_sources;
- !list
- );
-- file_ops.op_file_print_html <- (fun file buf ->
--
-- html_mods_cntr_init ();
-+ file_ops.op_file_print <- (fun file o ->
-
-+ let buf = o.conn_buf in
-+ if not (use_html_mods o) then begin
-+ let cntr = ref 0 in
-+ List.iter (fun (ip, n, r, c) ->
-+ incr cntr;
-+ Printf.bprintf buf
-+ "Comment %d: Rating(%d): %s (%s/%s)\n" !cntr r (Charset.to_utf8 c) n (Ip.to_string ip)) file.file_comments
-+ end else begin
- let tr () =
- Printf.bprintf buf "\\</tr\\>\\<tr class=\\\"dl-%d\\\"\\>" (html_mods_cntr ())
- in
-@@ -1223,6 +1304,16 @@
- (Md4.to_string file.file_md4) (Md4.to_string file.file_md4)
- ) ];
-
-+ let cntr = ref 0 in
-+ List.iter (fun (ip, n, r, c) ->
-+ incr cntr;
-+ tr ();
-+ html_mods_td buf [
-+ ("Comment", "sr br", Printf.sprintf "Comment %d" !cntr);
-+ ("User rating and comment", "sr", Printf.sprintf "Rating(%d): %s (%s/%s)" r (Charset.to_utf8 c) n (Ip.to_string ip));
-+ ];
-+ ) file.file_comments;
-+
- tr ();
- html_mods_td buf [
- ("File History Links", "sr br", "File History");
-@@ -1257,19 +1348,22 @@
- //--\\>
- \\</script\\>" (file_num file)
-
-- ^ "\\<table border=0 cellspacing=0 cellpadding=0\\>\\<tr\\>\\<td\\>"
-+ ^ "\\<table border=0 cellspacing=0 cellpadding=0\\>\\<tr\\>"
- ^ "\\<form name=\\\"renameForm1\\\" id=\\\"renameForm1\\\" action=\\\"javascript:submitRenameForm(1);\\\"\\>"
-+ ^ "\\<td\\>"
- ^ "\\<select name=\\\"newName\\\" id=\\\"newName\\\" onchange=\\\"javascript:renameForm2.newName.value=renameForm1.newName.options[renameForm1.newName.selectedIndex].value;this.form.submit();\\\"\\>"
- ^ Printf.sprintf "\\<option value=\\\"%s\\\" selected\\>%s\n" (file_best_name file) (file_best_name file)
- ^ !optionlist
-- ^ "\\</select\\>\\</td\\>\\</tr\\>\\</form\\>\\<tr\\>\\<td\\>\\<form name=\\\"renameForm2\\\" id=\\\"renameForm2\\\" action=\\\"javascript:submitRenameForm(2);\\\"\\>"
-- ^ "\\<input name=\\\"newName\\\" type=text size=" ^ input_size ^ " value=\\\"" ^ (file_best_name file) ^ "\\\"\\>\\</input\\>\\</td\\>\\</tr\\>\\</form\\>\\</table\\>"
-+ ^ "\\</select\\>\\</td\\>\\</form\\>\\</tr\\>\\<tr\\>\\<form name=\\\"renameForm2\\\" id=\\\"renameForm2\\\" action=\\\"javascript:submitRenameForm(2);\\\"\\>"
-+ ^ "\\<td\\>"
-+ ^ "\\<input name=\\\"newName\\\" type=text size=" ^ input_size ^ " value=\\\"" ^ (file_best_name file) ^ "\\\"\\>\\</input\\>\\</td\\>\\</form\\>\\</tr\\>\\</table\\>"
- ) ];
--
--
-+ end
- );
-- file_ops.op_file_print_sources_html <- (fun file buf ->
-+ file_ops.op_file_print_sources <- (fun file o ->
-
-+ if not (use_html_mods o) then raise Not_found;
-+ let buf = o.conn_buf in
- let sources_list = ref [] in
- DonkeySources.iter_relevant_sources (fun s ->
- let s_uid = s.DonkeySources.source_uid in
-@@ -1362,7 +1456,8 @@
- ((string_of_connection_state (client_state c)), "sr",
- (short_string_of_connection_state (client_state c)) );
- (String.escaped c.client_name, "sr", client_short_name c.client_name);
-- (brand_to_string c.client_brand, "sr", brand_to_string_short c.client_brand);
-+ (client_software (brand_to_string c.client_brand) c.client_osinfo, "sr",
-+ client_software_short (brand_to_string_short c.client_brand) c.client_osinfo);
- ("", "sr", c.client_emule_proto.emule_release);
-
- ] @
-@@ -1456,7 +1551,7 @@
- let size = Unix32.getsize file_diskname in
- if size <> zero then
- begin
-- ignore (really_query_download (Md4.to_string md4) size md4 None (Some file_diskname) None);
-+ ignore (really_query_download (Md4.to_string md4) size md4 None (Some file_diskname) None CommonUserDb.admin_user);
- recover_md4s md4
- end
-
-@@ -1508,6 +1603,28 @@
- network.op_network_reset <- (fun _ -> ());
-
- network.op_network_close_search <- (fun s -> ());
-+ network.op_network_porttest_start <- (fun _ ->
-+ porttest_result := PorttestInProgress (last_time ());
-+ let module H = Http_client in
-+ let r = { H.basic_request with
-+ H.req_url = Url.of_string
-+ (Printf.sprintf "http://porttest.emule-project.net:81/ct_noframe.php?lang=&tcpport=%d&udpport=%d"
-+ !!donkey_port (!!donkey_port + 4));
-+ H.req_proxy = !CommonOptions.http_proxy;
-+ H.req_max_retry = 10;
-+ H.req_user_agent = get_user_agent () } in
-+ H.wget r (fun file ->
-+ Unix2.tryopen_read file (fun cin ->
-+ try
-+ while true do
-+ let line = input_line cin in
-+ try
-+ if Str.string_match (Str.regexp "^<P>Testing IP") line 0 then
-+ porttest_result := PorttestResult (last_time (), line)
-+ with _ -> ()
-+ done
-+ with End_of_file -> ())
-+ ));
- network.op_network_forget_search <- forget_search
-
- (* emule<->mldonkey disconnects during chat, and this doesn't seem to auto reconnect
-@@ -1685,18 +1802,17 @@
- (fun url filename ->
- if !!enable_donkey && !!update_server_list_server_met then
- begin
-- lprintf_n "server.met loaded from %s" url;
-+ lprintf_nl "server.met loaded from %s" url;
- begin
- try
- let s = unpack_server_met filename url in
- let nservers = List.length (Hashtbl2.to_list servers_by_key) in
- let n = load_server_met s in
- if s <> filename then Sys.remove s;
-- lprintf ", %d servers found, %d new ones inserted"
-+ lprintf_nl "%d servers found, %d new ones inserted"
- n ((List.length (Hashtbl2.to_list servers_by_key)) - nservers)
- with _ -> ()
- end;
-- lprint_newline ()
- end
- else
- if not !!enable_donkey then
-Index: src/networks/donkey/donkeyMain.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyMain.ml,v
-retrieving revision 1.57
-retrieving revision 1.61
-diff -u -r1.57 -r1.61
---- src/networks/donkey/donkeyMain.ml 5 Sep 2006 14:15:20 -0000 1.57
-+++ src/networks/donkey/donkeyMain.ml 21 Nov 2006 21:38:00 -0000 1.61
-@@ -69,7 +69,6 @@
- clean_join_queue_tables ()
-
- let fivemin_timer timer =
-- DonkeyShare.send_new_shared ();
- clients_root := []
-
- let second_timer timer =
-@@ -95,10 +94,7 @@
- (try
- DonkeyServers.query_locations_timer ();
- with _ -> ());
-- (List.iter (fun file -> DonkeyShare.must_share_file file) !new_shared_files;
-- new_shared_files := [])
--(* DonkeyIndexer.add_to_local_index_timer () *)
--
-+ DonkeyShare.send_new_shared ()
-
- let local_login () =
- if !!login = "" then !!global_login else !!login
-@@ -118,10 +114,6 @@
- | Some sock ->
- listen_sock := None;
- TcpServerSocket.close sock Closed_by_user);
-- (match !reversed_sock with None -> ()
-- | Some sock ->
-- reversed_sock := None;
-- TcpServerSocket.close sock Closed_by_user);
- (match !udp_sock with None -> ()
- | Some sock ->
- udp_sock := None;
-@@ -136,11 +128,12 @@
- let module D = DonkeyProtoClient in
- let m = D.mldonkey_emule_proto in
-
-- let secident = if !!enable_sui then 3 else 0 in
-+ let secident = if sec_ident_enabled () then 3 else 0 in
- m.emule_secident <- secident;
- m.emule_features <- secident;
-
- let emule_miscoptions1 = D.emule_miscoptions1 m in
-+ let emule_compatoptions = D.emule_compatoptions m in
- client_to_client_tags :=
- [
- string_tag (Field_UNKNOWN "name") (local_login ());
-@@ -149,6 +142,7 @@
- int_tag (Field_UNKNOWN "emule_udpports") (!!donkey_port+4);
- int_tag (Field_UNKNOWN "emule_version") m.emule_version;
- int64_tag (Field_UNKNOWN "emule_miscoptions1") emule_miscoptions1;
-+ int_tag (Field_UNKNOWN "emule_compatoptions") emule_compatoptions;
- ];
-
- let extended = ref 0x04 in (* support of auxport *)
-@@ -302,9 +296,7 @@
-
- Options.option_hook global_login reset_tags;
- Options.option_hook login reset_tags;
-- Options.option_hook enable_sui ( fun _ ->
-- if not (Autoconf.donkey_sui_works ()) && !!enable_sui then enable_sui =:= false;
-- reset_tags ());
-+ Options.option_hook enable_sui reset_tags;
-
- (**** START TIMERS ****)
- add_session_option_timer enabler check_client_connections_delay
-@@ -392,6 +384,8 @@
- !overnet_port_info, "overnet_port TCP+UDP";
- !kademlia_port_info, "kademlia_port UDP";
- ]);
-+ network.op_network_porttest_result <-
-+ (fun _ -> !DonkeyInteractive.porttest_result);
- CommonInteractive.register_gui_options_panel "eDonkey"
- gui_donkey_options_panel;
- CommonInteractive.register_gui_options_panel "Overnet"
-Index: src/networks/donkey/donkeyOneFile.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyOneFile.ml,v
-retrieving revision 1.42
-retrieving revision 1.46
-diff -u -r1.42 -r1.46
---- src/networks/donkey/donkeyOneFile.ml 8 Aug 2006 23:55:28 -0000 1.42
-+++ src/networks/donkey/donkeyOneFile.ml 21 Nov 2006 22:34:34 -0000 1.46
-@@ -100,7 +100,7 @@
- end
-
- let remove_client_slot c =
-- set_client_has_a_slot (as_client c) false;
-+ set_client_has_a_slot (as_client c) NoSlot;
- client_send c (
- let module M = DonkeyProtoClient in
- let module Q = M.CloseSlot in
-@@ -111,8 +111,11 @@
- match file.file_shared with
- None -> ()
- | Some s ->
-- if !verbose_share then
-- lprintf_nl "unshare_file %s" file.file_diskname;
-+ if !verbose_share || !verbose then
-+ lprintf_nl "Unsharing file %s" (file_best_name file);
-+ List.iter (fun s ->
-+ s.server_sent_shared <- List2.removeq file s.server_sent_shared;
-+ ) (connected_servers ());
- file.file_shared <- None;
- decr nshared_files;
- CommonShared.shared_calculate_total_bytes ();
-@@ -269,7 +272,7 @@
- | _ -> assert false
- in
- let msg = M.QueryBlocReq msg in
-- set_read_power sock (!!upload_power + maxi 0 (file_priority file));
-+ set_read_power sock (!!upload_power + max 0 (file_priority file));
- (* lprintf "QUEUE DOWNLOAD REQUEST\n"; *)
- (* CommonUploads.queue_download_request (fun _ -> *)
- client_send c msg
-@@ -435,7 +438,7 @@
- (file_best_name file) (Printexc2.to_string e) in
- Printf2.lprint_string m;
- CommonEvent.add_event (Console_message_event m);
-- file_pause (as_file file);
-+ file_pause (as_file file) CommonUserDb.admin_user;
- raise e
- end
-
-Index: src/networks/donkey/donkeyOptions.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyOptions.ml,v
-retrieving revision 1.52
-retrieving revision 1.56
-diff -u -r1.52 -r1.56
---- src/networks/donkey/donkeyOptions.ml 4 Sep 2006 21:30:27 -0000 1.52
-+++ src/networks/donkey/donkeyOptions.ml 21 Nov 2006 22:34:34 -0000 1.56
-@@ -45,6 +45,10 @@
- "The number of servers you want to stay connected to"
- int_option 3
-
-+let max_allowed_connected_servers () =
-+ min (int_of_string ((strings_of_option max_connected_servers).option_default))
-+ !!max_connected_servers
-+
- let reliable_sources = define_option donkey_section ["reliable_sources"]
- "Should mldonkey try to detect sources responsible for corruption and ban them, currently disabled"
- bool_option true
-@@ -53,13 +57,16 @@
- "Should mldonkey try to detect sources masquerading as others and ban them"
- bool_option true
-
--let max_allowed_connected_servers () =
-- BasicSocket.mini 5 !!max_connected_servers
--
- let server_black_list = define_option donkey_section ["server_black_list"]
-- "A list of server IP to remove from server list.
-+ "A list of server IP to remove from server list. Can contain single IPs, CIDR ranges, or begin-end ranges.
- Servers on this list can't be added, and will eventually be removed"
-- (list_option Ip.option) []
-+ CommonOptions.ip_range_list_option []
-+
-+let server_black_list_set = ref Ip_set.BL_Empty
-+
-+let () =
-+ option_hook server_black_list (fun _ ->
-+ server_black_list_set := Ip_set.of_list !!server_black_list)
-
- let force_high_id = define_option donkey_section ["force_high_id"]
- "immediately close connection to servers that don't grant a High ID"
-@@ -100,8 +107,7 @@
- int_option 1
-
- let walker_server_lifetime = define_expert_option donkey_section ["walker_server_lifetime"]
-- "The maximal delay a connection with a server should last when walking
-- through the list (should be greater than become_master_delay)"
-+ "The maximal delay a connection with a server should last when walking through the list"
- int_option 300
-
- let log_clients_on_console = define_expert_option donkey_section ["log_clients_on_console"]
-@@ -247,6 +253,10 @@
- "min connected users for each server"
- int_option 0
-
-+let max_published_files = define_option donkey_section ["max_published_files"]
-+ "maximum number of files published to servers per minute, eMule default 200"
-+ int_option 200
-+
- let login = define_option donkey_section ["login"]
- "login of client on eDonkey network (nothing default to global one)"
- string_option ""
-@@ -260,10 +270,6 @@
- "port for overnet"
- int_option (2000 + Random.int 20000)
-
--let become_master_delay = define_expert_option donkey_section ["become_master_delay"]
-- "(only for development tests)"
-- int_option 120
--
- let options_version = define_expert_option donkey_section ["options_version"]
- "(internal option)"
- int_option 3
-Index: src/networks/donkey/donkeyOvernet.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyOvernet.ml,v
-retrieving revision 1.68
-retrieving revision 1.74
-diff -u -r1.68 -r1.74
---- src/networks/donkey/donkeyOvernet.ml 5 Sep 2006 14:15:20 -0000 1.68
-+++ src/networks/donkey/donkeyOvernet.ml 14 Nov 2006 16:35:53 -0000 1.74
-@@ -270,6 +270,13 @@
- end
- )
-
-+module KnownPeers = Weak.Make(struct
-+ type t = peer
-+ let hash c = Hashtbl.hash (c.peer_ip, c.peer_port)
-+ let equal x y = x.peer_port = y.peer_port
-+ && x.peer_ip = y.peer_ip
-+ end)
-+
- type search_for =
- | FileSearch of file
- | KeywordSearch of CommonTypes.search
-@@ -293,14 +300,22 @@
- search_md4 : Md4.t;
- mutable search_kind : search_for;
-
-- search_waiting_peers : peer Fifo.t array;
-- search_asked_peers : peer Fifo.t array;
-- search_ok_peers : peer Fifo.t array;
-+(* Peer queues of the search *)
-+(* Stage 1: This peers we know for this search *)
-+ search_peers : peer Fifo.t array;
-+(* Stage 2: We send a OvernetSearch *)
-+ search_asked_peers : KnownPeers.t;
-+(* Stage 3: We received from this peer a OvernetSearchReply *)
-+ search_ok_peers : KnownPeers.t;
-+(* Stage 4: We picked peers from search_ok_peers and send them a
-+ OvernetSearch.*Results *)
-+ search_result_asked_peers : KnownPeers.t;
-
- mutable search_queries : int;
- mutable search_requests : int;
- mutable search_start : int;
-- mutable search_last_query : int;
-+ mutable search_lifetime : int;
-+ mutable search_last_recv : int;
- mutable search_results : (Md4.t, tag list) Hashtbl.t;
- mutable search_nresults : int; (* number of results messages *)
- mutable search_hits : int; (* number of diff results *)
-@@ -347,11 +362,10 @@
- *********************************************************************)
-
- let max_peers_per_bucket = 20
--let max_peers_per_prebucket = 40
--(* how many peers a search may ask for more search peers *)
--let max_search_queries = 50
--(* how many peers we ask for results *)
--let max_search_requests = 20
-+let max_peers_per_prebucket = 20
-+(* number of peers a search start with *)
-+(* get_any_peers and get_closest_peers change the order of the peers in the bucket fifo *)
-+let init_peers_per_search = ((max_peers_per_bucket*2)/3)
- let max_boot_peers = 200
-
- let is_enabled = ref false
-@@ -451,7 +465,16 @@
- let pre_connected_peers = ref 0
-
- let is_overnet_ip ip =
-- Ip.usable ip && Ip.of_string "1.0.0.0" <> ip
-+ let is_not_banned ip =
-+ match !Ip.banned ip with
-+ None -> true
-+ | Some reason ->
-+ if !verbose_overnet then
-+ lprintf_nl "%s blocked: %s"
-+ (Ip.to_string ip) reason;
-+ false
-+ in
-+ Ip.usable ip && Ip.of_string "1.0.0.0" <> ip && is_not_banned ip
-
- module LimitedList = struct
-
-@@ -557,13 +580,6 @@
- let prebuckets = Array.init 129 (fun _ -> Fifo.create ())
-
- let to_ping = ref []
--module KnownPeers = Weak.Make(struct
-- type t = peer
-- let hash c = Hashtbl.hash (c.peer_ip, c.peer_port)
-- let equal x y = x.peer_port = y.peer_port
-- && x.peer_ip = y.peer_ip
-- end)
--
- let known_peers = KnownPeers.create 1023
-
- (*
-@@ -607,17 +623,11 @@
- let bucket_number md4 =
- common_bits md4 !!overnet_md4
-
-- (*
--(* TODO: this structure MUST disappear. It is not Kademlia ! *)
--let global_peers : (Md4.t, peer) Hashtbl.t array Options.option_record =
-- raise Not_found
-- *)
--
--(*let firewalled_overnet_peers = Hashtbl.create 13*)
--
- let search_hits = ref 0
- let source_hits = ref 0
-
-+(* when we created the searches for all files last time*)
-+let last_check_current_downloads = ref 0
-
- let udp_sock = ref None
-
-@@ -756,12 +766,16 @@
- match !udp_sock with
- None -> ()
- | Some sock ->
-+(* Why check this? Because it may have been blocked since it was added *)
-+ if ip <> Ip.localhost && is_overnet_ip ip && port <> 0 then
- Proto.udp_send sock ip port false msg
-
- let udp_send_ping ip port msg =
- match !udp_sock with
- None -> ()
- | Some sock ->
-+(* Why check this? Because it may have been blocked since it was added *)
-+ if ip <> Ip.localhost && is_overnet_ip ip && port <> 0 then
- Proto.udp_send sock ip port true msg
-
- let udp_send p msg =
-@@ -802,7 +816,12 @@
- if bucket < !n_used_buckets && bucket <> 128 &&
- p.peer_md4 <> Md4.null then begin
-
-- if Fifo.length prebuckets.(bucket) = max_peers_per_prebucket then
-+(* If this is a good peer add it directly to the bucket. Helps at startup *)
-+ if p.peer_kind < 3 && Fifo.length buckets.(bucket) < max_peers_per_bucket then begin
-+ Fifo.put buckets.(bucket) p;
-+ incr connected_peers;
-+ end
-+ else if Fifo.length prebuckets.(bucket) >= max_peers_per_prebucket then
- begin
- let pp = Fifo.take prebuckets.(bucket) in
- Fifo.put prebuckets.(bucket)
-@@ -847,11 +866,10 @@
- if n > 0 then
- let p = Fifo.take fifo in
- Fifo.put fifo p;
-- (* kind < 4 so we do not send too much requests and avoid dead contacts not
-+ (* kind < 3 so we do not send too much requests and avoid dead contacts not
- yet removed because of timeouts *)
- (* TODO: Keep order? Then we need a in_use flag? *)
-- if p.peer_kind < 4 && p.peer_expire > last_time () &&
-- p.peer_last_send <> 0 then begin
-+ if p.peer_kind < 3 && p.peer_expire > last_time () then begin
- if !verbose_overnet then begin
- lprintf_nl "Adding good search peer %s:%d"
- (Ip.to_string p.peer_ip) p.peer_port;
-@@ -928,50 +946,59 @@
- if p.peer_ip <> Ip.localhost && is_overnet_ip p.peer_ip &&
- p.peer_port <> 0 && p.peer_created <> 0 then begin
- let nbits = common_bits p.peer_md4 s.search_md4 in
-- begin
-+(* Don't add ourself *)
-+ if not (nbits = 128 && s.search_kind == FillBuckets) then begin
- try
-- Fifo.iter (fun pp ->
-+ let is_in pp =
- if pp.peer_ip = p.peer_ip &&
- pp.peer_port = p.peer_port then
- raise Exit
-- ) s.search_waiting_peers.(nbits);
-- Fifo.put s.search_waiting_peers.(nbits) p;
-+ in
-+ Fifo.iter is_in s.search_peers.(nbits);
-+ Fifo.put s.search_peers.(nbits) p;
- with Exit -> ()
- end
- end
-
- let create_search kind md4 =
- if !verbose_overnet then lprintf_nl "create_search";
-- let starttime = last_time () + (2 * List.length !overnet_searches) in
-+ let starttime = last_time () + (3 * List.length !overnet_searches) in
- let s = ref {
- search_md4 = md4;
- search_kind = kind;
- search_queries = 0;
- search_requests = 0;
-- search_waiting_peers = Array.init 129 (fun _ -> Fifo.create ());
-- search_asked_peers = Array.init 129 (fun _ -> Fifo.create ());
-- search_ok_peers = Array.init 129 (fun _ -> Fifo.create ());
-+ search_peers = Array.init 129 (fun _ -> Fifo.create ());
-+ search_asked_peers = KnownPeers.create 129;
-+ search_ok_peers = KnownPeers.create 129;
-+ search_result_asked_peers = KnownPeers.create 129;
-+(* taken from eMule0.47c-Sources/srchybrid/kademlia/kademlia/Defines.h *)
-+ search_lifetime = (match kind with
-+ _ -> 45 );(* SEARCH_LIFETIME *)
- search_start = (match kind with
- KeywordSearch s -> last_time ()
- | FillBuckets -> last_time ()
- | FileSearch s -> starttime);
-- search_last_query = (match kind with
-- KeywordSearch s -> last_time ()
-- | FillBuckets -> last_time ()
-- | FileSearch s -> starttime);
-+ search_last_recv = last_time ();
- search_hits = 0;
- search_nresults = 0;
- search_results = Hashtbl.create 64;
- } in
-- List.iter (fun ss ->
-- if ss.search_md4 = !s.search_md4 && (search_for_equals ss.search_kind !s.search_kind) then begin
-- ss.search_start <- !s.search_start;
-- s := ss;
-- end
-- ) !overnet_searches;
-- List.iter (add_search_peer !s) (get_closest_peers md4 max_search_queries);
-- if !verbose_overnet then lprintf_nl "create_search done";
-- overnet_searches := !s :: !overnet_searches;
-+ begin try
-+ List.iter (fun ss ->
-+ if ss.search_md4 = !s.search_md4 && (search_for_equals ss.search_kind !s.search_kind) then begin
-+(* ss.search_start <- !s.search_start; *)
-+ s := ss;
-+ raise Exit;
-+ end
-+ ) !overnet_searches;
-+ begin match kind with
-+ FillBuckets -> List.iter (add_search_peer !s) (get_any_peers init_peers_per_search)
-+ | _ -> List.iter (add_search_peer !s) (get_closest_peers md4 init_peers_per_search)
-+ end;
-+ if !verbose_overnet then lprintf_nl "create_search done";
-+ overnet_searches := !s :: !overnet_searches;
-+ with Exit -> () end;
- !s
-
- let create_keyword_search w s =
-@@ -979,6 +1006,54 @@
- let search = create_search (KeywordSearch s) md4 in
- search
-
-+(* query the best todo peers of a search s or ask it for results *)
-+let rec overnet_search_iter s nbits todo =
-+ let nresults = match s.search_kind with
-+ FillBuckets -> 10
-+ | _ -> 2
-+ in
-+ if nbits >= 0 then
-+ let len = Fifo.length s.search_peers.(nbits) in
-+ if len > 0 then
-+ let process_peer p =
-+ if not (KnownPeers.mem s.search_asked_peers p) then begin
-+(* Not asked: send a OvernetSearch *)
-+ checking_kind p;
-+ udp_send p (OvernetSearch (nresults, s.search_md4, Some p.peer_md4));
-+ s.search_queries <- s.search_queries + 1;
-+ KnownPeers.add s.search_asked_peers p;
-+ raise Exit;
-+ end
-+ else if (KnownPeers.mem s.search_ok_peers p) &&
-+ not (KnownPeers.mem s.search_result_asked_peers p) then begin
-+(* Is ok but we did not request a result yet *)
-+ let kind = match s.search_kind with
-+ FillBuckets -> Search_for_file
-+ | FileSearch _ -> Search_for_file
-+ | _ -> Search_for_keyword None
-+ in
-+ checking_kind p;
-+ udp_send p ( OvernetGetSearchResults (s.search_md4, kind, 0, 100));
-+ s.search_requests <- s.search_requests + 1;
-+ KnownPeers.add s.search_result_asked_peers p;
-+ raise Exit;
-+ end
-+ (* raised an Exit if we send something to the peer *)
-+ in
-+ try
-+ Fifo.iter process_peer s.search_peers.(nbits);
-+ overnet_search_iter s (nbits-1) todo;
-+ with Exit ->
-+ (if todo > 1 then overnet_search_iter s nbits (todo - 1))
-+ else
-+ overnet_search_iter s (nbits-1) todo
-+ else
-+ begin
-+ if !verbose_overnet then
-+ lprintf_nl "overnet_search_iter: call add_search_peer";
-+ List.iter (add_search_peer s) (get_closest_peers s.search_md4 init_peers_per_search);
-+ end
-+
- let ip_of_udp_packet p =
- match p.UdpSocket.udp_addr with
- Unix.ADDR_INET (inet, port) ->
-@@ -1005,7 +1080,7 @@
-
- | OvernetConnect p ->
- if is_overnet_ip sender.peer_ip && sender.peer_port <> 0 then
-- let sender = new_peer { p with peer_ip = other_ip } in
-+ let sender = new_peer { p with peer_ip = other_ip; peer_kind = 2 } in
- (* let sender = new_peer { p with peer_port = other_port ; peer_ip = other_ip } in *)
- new_peer_message sender;
- udp_send sender (OvernetConnectReply (get_any_peers 20))
-@@ -1014,7 +1089,6 @@
- if !verbose_overnet then
- lprintf_nl "Connect: invalid IP %s:%d received from %s:%d"
- (Ip.to_string p.peer_ip) p.peer_port (Ip.to_string other_ip) other_port;
-- failwith "Message not understood"
- end
-
- | OvernetConnectReply ps ->
-@@ -1023,7 +1097,8 @@
- match list with
- [] -> ()
- | [p] ->
-- let sender = new_peer { p with peer_ip = other_ip } in
-+ (* last one is always the peer itself *)
-+ let sender = new_peer { p with peer_ip = other_ip; peer_kind = 2 } in
- new_peer_message sender
- | p :: tail ->
- let _ = new_peer p in
-@@ -1032,7 +1107,7 @@
- iter ps;
-
- | OvernetPublicize p ->
-- let sender = new_peer { p with peer_ip = other_ip } in
-+ let sender = new_peer { p with peer_ip = other_ip; peer_kind = 2 } in
- new_peer_message sender;
- if is_overnet_ip sender.peer_ip && sender.peer_port <> 0 then
- udp_send sender (OvernetPublicized (Some (my_peer ())))
-@@ -1040,7 +1115,6 @@
- if !verbose_overnet then
- lprintf_nl "Publicize: invalid IP %s:%d received from %s:%d"
- (Ip.to_string p.peer_ip) p.peer_port (Ip.to_string other_ip) other_port;
-- failwith "Message not understood"
- end
-
- | OvernetPublicized None ->
-@@ -1049,6 +1123,9 @@
- | OvernetPublicized (Some p) ->
- ()
-
-+ | OvernetNoResult (md4) ->
-+ ()
-+
- | OvernetSearch (nresults, md4, from_who) ->
- let peers = get_closest_peers md4 nresults in
- udp_send sender (OvernetSearchReply (md4,peers))
-@@ -1059,8 +1136,10 @@
- List.iter (fun s ->
- if s.search_md4 = md4 then begin
- List.iter (add_search_peer s) peers;
-- let nbits = common_bits sender.peer_md4 s.search_md4 in
-- Fifo.put s.search_ok_peers.(nbits) sender;
-+ KnownPeers.add s.search_ok_peers sender;
-+ s.search_last_recv <- last_time ();
-+ (* Now ask the next best peer *)
-+ overnet_search_iter s 128 1;
- end
- ) !overnet_searches;
-
-@@ -1113,6 +1192,9 @@
- if is_overnet_ip ip && port <> 0 then
- let s = DonkeySources.find_source_by_uid
- (Direct_address (ip, port)) in
-+ if !verbose_overnet then
-+ lprintf_nl "added new source %s:%d for file %s"
-+ (Ip.to_string ip) port (Md4.to_string md4);
- incr source_hits;
- DonkeySources.set_request_result s
- file.file_sources File_new_source;
-@@ -1167,18 +1249,18 @@
- (* send the answer *)
- | OvernetGetMyIP other_port ->
- if !verbose_overnet && debug_client other_ip then
-- lprintf_nl "GET MY IP (port=%d)\n" other_port;
-+ lprintf_nl "GET MY IP (port=%d)" other_port;
- (* FIXME : should be able to flush the UDP buffer*)
- udp_send sender (OvernetGetMyIPResult other_ip);
- udp_send sender OvernetGetMyIPDone
-
- | OvernetGetMyIPResult(ip) ->
- if !verbose_overnet && debug_client other_ip then
-- lprintf_nl "GET MY IP RESULT (%s)\n" (Ip.to_string ip)
-+ lprintf_nl "GET MY IP RESULT (%s)" (Ip.to_string ip)
-
- | OvernetGetMyIPDone ->
- if !verbose_overnet && debug_client other_ip then
-- lprintf_nl "GET MY IP DONE\n"
-+ lprintf_nl "GET MY IP DONE"
-
- | OvernetPeerNotFound peer ->
- begin
-@@ -1186,24 +1268,34 @@
- lprintf_nl "Peer NOT FOUND %s (%s:%d) kind: %d (msg 33)"
- (Md4.to_string peer.peer_md4) (Ip.to_string peer.peer_ip)
- peer.peer_port peer.peer_kind;
-+(* We ignore OvernetPeerNotFound, the original client sends this message very often (even if the peer is alive)
- let dp = { dummy_peer with peer_port = peer.peer_port ; peer_ip = peer.peer_ip } in
- if KnownPeers.mem known_peers dp
- then begin
--(* remove it from the prebuckets and known_peers only *)
-+(* remove it from the buckets, put it into prebuckets and set kind to 3 *)
- try
- for i = 0 to !n_used_buckets do
-- let b = prebuckets.(i) in
-+ let b = buckets.(i) in
-+ let pb = prebuckets.(i) in
- for j = 1 to Fifo.length b do
- let p = Fifo.take b in
- if p.peer_ip = peer.peer_ip &&
- p.peer_port = peer.peer_port then begin
-- decr pre_connected_peers;
-- KnownPeers.remove known_peers dp;
-+ decr connected_peers;
-+ if !pre_connected_peers < max_peers_per_prebucket then begin
-+ incr pre_connected_peers;
-+ Fifo.put pb p;
-+ p.peer_kind <- 3;
-+ end
-+ else begin if !verbose_overnet then lprintf_nl "peernotfound: removing %s:%d" (Ip.to_string p.peer_ip) p.peer_port;
-+ KnownPeers.remove known_peers p;
-+ end
- end else Fifo.put b p
- done;
- done;
- with Exit -> ();
- end;
-+*)
- end
-
- | OvernetUnknown21 peer ->
-@@ -1215,77 +1307,19 @@
-
- | _ -> failwith "Message not understood"
-
--let query_next_peers () =
-- let overnet_query_peer_period = int_of_float !!overnet_query_peer_period in
-- let timeout = last_time () - overnet_query_peer_period in
-+(* Start unstarted searches, retry stalled searches *)
-+let overnet_search_tick () =
- List.iter (fun s ->
-- let nresults = match s.search_kind with
-- FillBuckets -> 10
-- | _ -> 2
-- in
--
-- let rec iter nbits todo =
-- if nbits >= 0 then
-- let len = Fifo.length s.search_waiting_peers.(nbits) in
-- if len > 0 then
-- let p = Fifo.take s.search_waiting_peers.(nbits) in
--
-- if p.peer_last_send < timeout then begin
-- checking_kind p;
-- udp_send p (OvernetSearch (nresults, s.search_md4, Some p.peer_md4));
-- s.search_queries <- s.search_queries + 1;
-- Fifo.put s.search_asked_peers.(nbits) p;
--
-- (if todo > 1 then iter nbits (todo - 1))
-- end else
-- iter nbits todo
-- else
-- iter (nbits-1) todo
-- else
-- if s.search_queries < max_search_queries then
-- List.iter (fun p ->
-- add_search_peer s p
-- ) (get_closest_peers s.search_md4 max_search_queries)
-- in
-- if s.search_last_query < timeout then begin
-- s.search_last_query <- s.search_last_query + overnet_query_peer_period;
--(* Query next search peers *)
-- if s.search_queries < max_search_queries then
-- (if s.search_queries = 0 then
-- iter 128 3
-- else
-- iter 128 2);
--(* Request next results *)
-- if s.search_requests < max_search_requests then begin
-- let nrequests =
-- match s.search_kind with
-- FillBuckets -> 0
-- | FileSearch _ -> 1
-- | KeywordSearch _ -> 5
-- in
-- for i = 1 to nrequests do
-- try
-- for j = 128 downto 5 do
-- if Fifo.length s.search_ok_peers.(j) > 0 then
-- let p = Fifo.take s.search_ok_peers.(j) in
-- if p.peer_last_send < timeout then begin
-- checking_kind p;
-- udp_send p (
-- OvernetGetSearchResults (s.search_md4,
-- (match s.search_kind with
-- FillBuckets -> Search_for_file
-- | FileSearch _ -> Search_for_file
-- | _ -> Search_for_keyword None
-- ), 0, 100));
-- s.search_requests <- s.search_requests + 1;
-- raise Exit
-- end else
-- Fifo.put s.search_ok_peers.(j) p
-- done
-- with Exit -> ()
-- done
-- end
-- end;
-+(* Start a search, if search_start is reached *)
-+ if (s.search_lifetime + s.search_start - 20) > last_time () &&
-+ s.search_start < last_time () then begin
-+ (if s.search_queries = 0 then
-+ overnet_search_iter s 128 3
-+ else if (s.search_last_recv + 3) < last_time () then
-+(* The search has stalled. We do what eMule call a JumpStart *)
-+(* FIXME: with implemented firewalling this should be 1 peer not 2*)
-+ overnet_search_iter s 128 2);
-+ end
- ) !overnet_searches
-
- let recover_file file =
-@@ -1305,7 +1339,8 @@
- for j = 1 to Fifo.length b do
- let p = Fifo.take b in
- (* bad peers have kind = 4 and did not respond within peer_expire *)
-- if not (p.peer_kind = 4 && p.peer_expire <= last_time ()) then
-+ (* Why check is_overnet_ip? Because it may have been blocked since it was added *)
-+ if not (p.peer_kind = 4 && p.peer_expire <= last_time ()) && is_overnet_ip p.peer_ip then
- Fifo.put b p
- else
- begin
-@@ -1335,7 +1370,9 @@
- incr connected_peers;
- decr pre_connected_peers;
- (* bad peers are removed *)
-- end else if p.peer_kind = 4 && p.peer_expire <= last_time () then begin
-+ (* Why check is_overnet_ip? Because it may have been blocked since it was added *)
-+ end else if (p.peer_kind = 4 && p.peer_expire <= last_time ()) ||
-+ not (is_overnet_ip p.peer_ip) then begin
- decr pre_connected_peers;
- KnownPeers.remove known_peers p;
- if !verbose_overnet then lprintf_nl "update_bucket2: removing %s:%d" (Ip.to_string p.peer_ip) p.peer_port;
-@@ -1418,14 +1455,13 @@
-
- (* copy all boot_peers to unknown_peers *)
- LimitedList.iter (fun (ip, port) ->
-- LimitedList.add unknown_peers (ip, port)
-+ if ip <> Ip.localhost && is_overnet_ip ip && port <> 0 then
-+ LimitedList.add unknown_peers (ip, port)
- ) !!boot_peers;
-
- add_session_timer enabler 1. (fun _ ->
- if !!enable_overnet then begin
--(* Searches have a search_last_query controlled by !!overnet_query_peer_period *)
--(* Here also the result request a done *)
-- query_next_peers ();
-+ overnet_search_tick ();
-
- let my_peer = my_peer () in
-
-@@ -1437,7 +1473,7 @@
- | p :: tail ->
- (* do not hammer a peer, we could have send already a search reqeust
- since to_ping is rebuild at least every 60 seconds *)
-- if (last_time () - p.peer_last_send) > 60 then begin
-+ if (last_time () - p.peer_last_send) > 61 then begin
- checking_kind p;
- udp_send p (OvernetPublicize my_peer);
- end;
-@@ -1445,12 +1481,20 @@
- end;
- in
- process_to_ping ();
-+(* When we start with 50 searches and no peers, we have to update the buckets
-+ fast, otherwise we cannot add search peers (rest: sanity check) *)
-+ begin
-+ if !connected_peers < 20 && !pre_connected_peers <> 0 &&
-+ LimitedList.length unknown_peers <> 0 then
-+ update_buckets ();
-+ compute_to_ping ();
-+ end;
- (* Send OvernetConnects and ping more peers *)
- (* TODO: How does eMule it? are 50 ok? *)
- begin
- try
-- if !connected_peers < 50 then
-- for i = 1 to 4 do
-+ if !connected_peers < 10 then
-+ for i = 1 to 2 do
- process_to_ping ();
- done;
- (* Do not send too much OvernetConnect, there is no use *)
-@@ -1476,12 +1520,25 @@
-
- compute_to_ping ();
-
-- let l = last_time () - 180 in
--(* remove searches that are older than 3 minutes *)
-+(* remove searches that are older than their lifetime *)
- overnet_searches := List.filter (fun s ->
-- s.search_requests < max_search_requests &&
-- s.search_start > l
-+ (* s.search_lifetime + s.search_start > last_time () *)
-+(*DEBUG:show longer *) 360 + s.search_start > last_time ()
- ) !overnet_searches;
-+
-+ (* FIXE: Dump latencies to logfile *)
-+ if !verbose_overnet then ignore (UdpSocket.get_latencies (ref true));
-+
-+ if !verbose_overnet then begin
-+ lprintf_nl "%d peers (prebucket: %d peers)" !connected_peers !pre_connected_peers;
-+ for i = 0 to !n_used_buckets do
-+ if (Fifo.length buckets.(i)) <> 0 || (Fifo.length prebuckets.(i)) <> 0 then
-+ lprintf_nl "bucket[%d] : %d peers (prebucket %d)"
-+ i (Fifo.length buckets.(i)) (Fifo.length prebuckets.(i));
-+ done;
-+ lprintf_nl "unknown_peers: %d" (LimitedList.length unknown_peers);
-+ lprintf_nl "boot_peers: %d" (LimitedList.length !!boot_peers);
-+ end;
- );
-
- (* every 15min for light operations *)
-@@ -1489,12 +1546,18 @@
- if !!enable_overnet then begin
- let _ = create_search FillBuckets !!overnet_md4 in
- check_current_downloads ();
-+ last_check_current_downloads := last_time ();
- end
- );
-
- begin
-- let _ = create_search FillBuckets !!overnet_md4 in
- check_current_downloads ();
-+(* Delay the first normal searches, so we can fill the buckets first *)
-+ List.iter (fun s ->
-+ s.search_start <- s.search_start + 30;
-+ ) !overnet_searches;
-+ ignore (create_search FillBuckets !!overnet_md4);
-+ last_check_current_downloads := last_time ();
- end;
-
- add_infinite_timer 1800. (fun _ ->
-@@ -1571,6 +1634,28 @@
- (List.map (fun (command, args, help) ->
- command_prefix ^ command, args, help)
- [
-+ "dump_searches", Arg_none (fun o ->
-+ let buf = o.conn_buf in
-+ List.iter ( fun s ->
-+ Printf.bprintf buf "Search %s for %s\nrequests:%d queries:%d seconds alive:%d lifetime:%d\n"
-+ (match s.search_kind with
-+ KeywordSearch _ -> "keyword"
-+ | FileSearch _ -> "file"
-+ | FillBuckets -> "fillbuckets" )
-+ (Md4.to_string s.search_md4) s.search_requests s.search_queries (last_time ()-s.search_start) s.search_lifetime;
-+ let pp p = print_peer buf p in
-+ Printf.bprintf buf "search_peers\n";
-+ Array.iter (fun a -> Fifo.iter (fun p -> pp p) a) s.search_peers;
-+ Printf.bprintf buf "search_asked_peers\n";
-+ KnownPeers.iter pp s.search_asked_peers;
-+ Printf.bprintf buf "search_ok_peers\n";
-+ KnownPeers.iter pp s.search_ok_peers;
-+ Printf.bprintf buf "search_result_asked_peers\n";
-+ KnownPeers.iter pp s.search_result_asked_peers;
-+ Printf.bprintf buf "\n";
-+ ) !overnet_searches;
-+ ""
-+ ), ("<bucket_nr> :\t\tdumps a search (Devel)");
- "dump_bucket", Arg_one (fun i o ->
- let i = int_of_string i in
- let i = min i !n_used_buckets in
-@@ -1593,7 +1678,7 @@
- Fifo.put pb p;
- done;
- ""
-- ), ("<bucket_nr> :\t\tdumps a bucket");
-+ ), ("<bucket_nr> :\t\tdumps a bucket (Devel)");
-
- "dump_known_peers", Arg_none (fun o ->
- let buf = o.conn_buf in
-@@ -1604,7 +1689,7 @@
- print_peer buf p;
- ) known_peers;
- ""
-- ), (":\t\t\tdumps known_peers");
-+ ), (":\t\t\tdumps known_peers (Devel)");
-
- "boot", Arg_two (fun ip port o ->
- let ip = Ip.from_name ip in
-@@ -1648,6 +1733,8 @@
- Printf.bprintf buf "\\<tr\\>";
- html_mods_td buf [
- ("", "srh", Printf.sprintf "%s statistics" command_prefix_to_net);
-+ ("", "srh", Printf.sprintf "Last file search started %d seconds ago\n"
-+ (last_time () - !last_check_current_downloads));
- ("", "srh", Printf.sprintf "Search hits: %d\n" !search_hits);
- ("", "srh", Printf.sprintf "Source hits: %d\n" !source_hits); ];
- Printf.bprintf buf "\\</tr\\>\\</table\\>\\</div\\>\n";
-@@ -1656,6 +1743,8 @@
- begin
- Printf.bprintf buf "%s statistics:\n"
- (command_prefix_to_net);
-+ Printf.bprintf buf " Last file search started %d seconds ago\n"
-+ (last_time () - !last_check_current_downloads);
- Printf.bprintf buf " Search hits: %d\n" !search_hits;
- Printf.bprintf buf " Source hits: %d\n" !source_hits;
- end;
-@@ -1675,35 +1764,44 @@
- Printf.bprintf buf "\\</tr\\>";
- Printf.bprintf buf "\\<tr class=\\\"dl-1\\\"\\>";
- html_mods_td buf [
-- ("", "sr", Printf.sprintf "requests:%d queries:%d search_last_query:%d\n" s.search_requests s.search_queries s.search_last_query); ];
-+ ("", "sr", Printf.sprintf "requests:%d queries:%d seconds alive:%d lifetime:%d\n"
-+ s.search_requests s.search_queries (last_time ()-s.search_start) s.search_lifetime); ];
- Printf.bprintf buf "\\</tr\\>";
- end
- else
-- Printf.bprintf buf "Search %s for %s\nrequests:%d queries:%d search_last_query:%d\n"
-+ Printf.bprintf buf "Search %s for %s\nrequests:%d queries:%d seconds alive:%d lifetime:%d\n"
- (match s.search_kind with
- KeywordSearch _ -> "keyword"
- | FileSearch _ -> "file"
- | FillBuckets -> "fillbuckets" )
-- (Md4.to_string s.search_md4) s.search_requests s.search_queries s.search_last_query;
-+ (Md4.to_string s.search_md4) s.search_requests s.search_queries (last_time ()-s.search_start) s.search_lifetime;
- for i = 128 downto 0 do
-- let npeers = Fifo.length s.search_waiting_peers.(i) in
-- let nasked = Fifo.length s.search_asked_peers.(i) in
-- let nok = Fifo.length s.search_ok_peers.(i) in
-+ let npeers = Fifo.length s.search_peers.(i) in
-+ let count = ref 0 in
-+ let cp p = if (common_bits p.peer_md4 s.search_md4) = i then count := !count + 1 in
-+ KnownPeers.iter cp s.search_asked_peers;
-+ let nasked = !count in
-+ count := 0;
-+ KnownPeers.iter cp s.search_ok_peers;
-+ let nok = !count in
-+ count := 0;
-+ KnownPeers.iter cp s.search_result_asked_peers;
-+ let nres = !count in
- if npeers > 0 || nasked > 0 then
- if o.conn_output = HTML then
- begin
- Printf.bprintf buf "\\<tr class=\\\"dl-1\\\"\\>";
- html_mods_td buf [
- ("", "sr",
-- Printf.sprintf "nbits[%d] = %d peer(s) not asked, %d peer(s) asked, %d peer(s) ok"
-- i npeers nasked nok); ];
-+ Printf.sprintf "nbits[%d] = %d peer(s) total, %d peer(s) asked, %d peer(s) ok, %d peer(s) result asked"
-+ i npeers nasked nok nres); ];
- Printf.bprintf buf "\\</tr\\>";
-
- end
- else
- Printf.bprintf buf
-- " nbits[%d] = %d peers not asked, %d peers asked\n"
-- i npeers nasked
-+ " nbits[%d] = %d peer(s) total, %d peer(s) asked, %d peer(s) ok, %d peer(s) result asked\n"
-+ i npeers nasked nok nres
- done;
- if o.conn_output = HTML then
- Printf.bprintf buf "\\</table\\>\\</div\\>\n";
-@@ -1864,18 +1962,6 @@
-
- let forget_search ss =
- begin
--(* reset the Hashtbls and Fifos *)
-- List.iter ( fun s ->
-- match s.search_kind with
-- KeywordSearch sss when ss == sss ->
-- begin
-- Array.iter (fun a -> Fifo.clear a) s.search_waiting_peers;
-- Array.iter (fun a -> Fifo.clear a) s.search_asked_peers;
-- Array.iter (fun a -> Fifo.clear a) s.search_ok_peers;
-- Hashtbl.clear s.search_results;
-- end
-- | _ -> ()
-- ) !overnet_searches;
- (* Remove from overnet_searches *)
- overnet_searches := List.filter (fun s ->
- match s.search_kind with
-@@ -1885,18 +1971,6 @@
-
- let cancel_recover_file file =
- begin
--(* reset the Hashtbls and Fifos *)
-- List.iter ( fun s ->
-- match s.search_kind with
-- FileSearch f when f == file ->
-- begin
-- Array.iter (fun a -> Fifo.clear a) s.search_waiting_peers;
-- Array.iter (fun a -> Fifo.clear a) s.search_asked_peers;
-- Array.iter (fun a -> Fifo.clear a) s.search_ok_peers;
-- Hashtbl.clear s.search_results;
-- end
-- | _ -> ()
-- ) !overnet_searches;
- (* Remove from overnet_searches *)
- overnet_searches := List.filter (fun s ->
- match s.search_kind with
-@@ -1954,8 +2028,8 @@
- Printf.bprintf buf " unknown_peers: %d\n" (LimitedList.length unknown_peers);
- update_buckets ();
- Printf.bprintf buf " boot_peers: %d\n" (LimitedList.length !!boot_peers);
-- Printf.bprintf buf " %d buckets with %d peers and %d prebucket peers\n"
-- !n_used_buckets !connected_peers !pre_connected_peers;
-+ Printf.bprintf buf " %d peers and %d prebucket peers\n"
-+ !connected_peers !pre_connected_peers;
-
- Printf.bprintf buf " Search hits: %d\n" !search_hits;
- Printf.bprintf buf " Source hits: %d\n" !source_hits;
-@@ -1970,27 +2044,19 @@
-
-
- Printf.bprintf buf " to_ping: %d\n" (List.length !to_ping);
-- let n_search_waiting_peers = ref 0 in
-- let n_search_asked_peers = ref 0 in
-- let n_search_ok_peers = ref 0 in
-+ let n_search_peers = ref 0 in
- let n_search_results = ref 0 in
- let n_overnet_searches = ref 0 in
- List.iter ( fun s ->
- for i = 128 downto 0 do
-- n_search_waiting_peers :=
-- !n_search_waiting_peers + (Fifo.length s.search_waiting_peers.(i));
-- n_search_asked_peers :=
-- !n_search_asked_peers + (Fifo.length s.search_asked_peers.(i));
-- n_search_ok_peers :=
-- !n_search_ok_peers + (Fifo.length s.search_ok_peers.(i));
-+ n_search_peers :=
-+ !n_search_peers + (Fifo.length s.search_peers.(i));
- n_search_results :=
- !n_search_results + (Hashtbl.length s.search_results);
- done;
- incr n_overnet_searches
- ) !overnet_searches;
-- Printf.bprintf buf " n_search_waiting_peers: %d\n" !n_search_waiting_peers;
-- Printf.bprintf buf " n_search_asked_peers: %d\n" !n_search_asked_peers;
-- Printf.bprintf buf " n_search_ok_peers: %d\n" !n_search_ok_peers;
-+ Printf.bprintf buf " n_search_peers: %d\n" !n_search_peers;
- Printf.bprintf buf " n_search_results: %d\n" !n_search_results;
- Printf.bprintf buf " n_overnet_searches: %d\n" !n_overnet_searches;
- );
-Index: src/networks/donkey/donkeyProtoClient.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyProtoClient.ml,v
-retrieving revision 1.36
-retrieving revision 1.39
-diff -u -r1.36 -r1.39
---- src/networks/donkey/donkeyProtoClient.ml 5 Sep 2006 14:18:24 -0000 1.36
-+++ src/networks/donkey/donkeyProtoClient.ml 31 Oct 2006 15:40:06 -0000 1.39
-@@ -51,6 +51,7 @@
- emule_secident = 3; (* Emule uses v1 if advertising both, v2 if only advertising 2 *)
- emule_noviewshared = 0;
- emule_supportpreview = 0;
-+ emule_osinfosupport = 1;
- emule_compression = 1; (* 1 *)
- emule_sourceexchange = 2; (* 2 : +client_md4 3 : +IdHybrid (emule Kademlia?)*)
- emule_multipacket = 0; (* 1 *)
-@@ -85,6 +86,12 @@
- m.emule_multipacket <- (o lsr 1) land 0x1;
- m.emule_supportpreview <- (o lsr 0) land 0x1
-
-+let emule_compatoptions m =
-+ (m.emule_osinfosupport lsl 0)
-+
-+let update_emule_proto_from_compatoptions m o =
-+ m.emule_osinfosupport <- (o lsr 0) land 0x1
-+
- let extendedrequest e =
- min e.emule_extendedrequest mldonkey_emule_proto.emule_extendedrequest
-
-@@ -133,6 +140,7 @@
- "\060", Field_UNKNOWN "downloadtime";
- "\061", Field_UNKNOWN "incompleteparts";
- "\085", Field_UNKNOWN "mod_version";
-+ "\239", Field_UNKNOWN "emule_compatoptions";
- "\249", Field_UNKNOWN "emule_udpports";
- "\250", Field_UNKNOWN "emule_miscoptions1";
- "\251", Field_UNKNOWN "emule_version";
-@@ -799,7 +807,7 @@
- "\135", "mod_lsd";
- "\136", "mod_lsd_version";
- "\144", "mod_lovelace_version";
-- "\148", "mod_oxy";
-+ "\148", "os_info"; (* reused by aMule to transfer client OS type *)
- "\153", "mod_plus";
- "\160", "mod_wombat";
- "\161", "dev_wombat";
-@@ -1044,6 +1052,43 @@
- done
-
- end
-+module EmuleFileDesc = struct
-+
-+ type t = {
-+ rating : int;
-+ comment : string;
-+ }
-+
-+ let parse len s =
-+ let rating = get_uint8 s 1 in
-+ let (comment, _) = get_string32 s 2 in
-+ {
-+ rating = rating;
-+ comment = comment;
-+ }
-+
-+ let print t =
-+ lprintf_nl "EmuleFileDesc [%d][%s]" t.rating t.comment
-+
-+ let write buf t =
-+ buf_int8 buf t.rating;
-+ buf_string buf t.comment
-+ end
-+
-+
-+module EmulePortTestReq = struct
-+
-+ type t = string
-+
-+ let print s =
-+ lprintf_nl "Emule porttest request %s" (String.escaped s)
-+
-+ let parse s = s
-+
-+ let write buf =
-+ buf_int8 buf 0x12
-+
-+ end
-
- type t =
- | ConnectReq of Connect.t
-@@ -1081,13 +1126,14 @@
- | EmuleQueueRankingReq of EmuleQueueRanking.t
- | EmuleRequestSourcesReq of EmuleRequestSources.t
- | EmuleRequestSourcesReplyReq of EmuleRequestSourcesReply.t
--| EmuleFileDescReq of int * string
-+| EmuleFileDescReq of EmuleFileDesc.t
- | EmulePublicKeyReq of EmulePublicKeyReq.t
- | EmuleSignatureReq of EmuleSignatureReq.t
- | EmuleSecIdentStateReq of EmuleSecIdentStateReq.t
- | EmuleMultiPacketReq of Md4.t * t list
- | EmuleMultiPacketAnswerReq of Md4.t * t list
- | EmuleCompressedPart of Md4.t * int64 * int64 * string
-+| EmulePortTestReq of EmulePortTestReq.t
-
- let rec print t =
- begin
-@@ -1133,8 +1179,8 @@
- | EmuleRequestSourcesReplyReq t ->
- EmuleRequestSourcesReply.print t
-
-- | EmuleFileDescReq (rating, comment) ->
-- lprintf "EMULE FILE DESC %s" comment
-+ | EmuleFileDescReq t ->
-+ EmuleFileDesc.print t
-
- | EmuleMultiPacketReq (md4, list) ->
- lprintf_nl "EmuleMultiPacket for %s:" (Md4.to_string md4);
-@@ -1155,11 +1201,11 @@
- EmuleSignatureReq.print t
- | EmulePublicKeyReq t ->
- EmulePublicKeyReq.print t
--
- | EmuleCompressedPart (md4, statpos, newsize, bloc) ->
- lprintf_nl "EmuleCompressedPart for %s %Ld %Ld len %d"
- (Md4.to_string md4) statpos newsize (String.length bloc)
--
-+ | EmulePortTestReq t ->
-+ EmulePortTestReq.print t
- | UnknownReq (opcode, s) ->
- let len = String.length s in
- lprintf_nl "UnknownReq: magic (%d), opcode (%d) len (%d)" opcode
-@@ -1195,10 +1241,7 @@
-
- | 0x60 (* 96 *) -> EmuleQueueRankingReq (EmuleQueueRanking.parse len s)
-
-- | 0x61 (* 97 *) ->
-- let rating = get_uint8 s 1 in
-- let (comment,_) = get_string32 s 2 in
-- EmuleFileDescReq (rating, comment)
-+ | 0x61 (* 97 *) -> EmuleFileDescReq (EmuleFileDesc.parse len s)
-
- | 0x81 (* 129 *) -> EmuleRequestSourcesReq (EmuleRequestSources.parse len s)
- | 0x82 (* 130 *) ->
-@@ -1294,6 +1337,9 @@
- in
- EmuleMultiPacketAnswerReq (md4, iter s 17 len)
-
-+ | 0xfe (* 254 *) ->
-+ EmulePortTestReq s
-+
- | code ->
- if !CommonOptions.verbose_unknown_messages then
- lprintf_nl "EDK: unknown eMule message %d" code;
-@@ -1514,11 +1560,9 @@
- | EmuleRequestSourcesReplyReq t ->
- buf_int8 buf 0x82;
- EmuleRequestSourcesReply.write emule buf t
-- | EmuleFileDescReq (rating, comment) ->
-+ | EmuleFileDescReq t ->
- buf_int8 buf 0x61;
-- buf_int8 buf rating;
-- buf_string buf comment
--
-+ EmuleFileDesc.write buf t
- | EmuleCompressedPart (md4, statpos, newsize, bloc) ->
- buf_int8 buf 0x40;
- buf_md4 buf md4;
-@@ -1578,6 +1622,10 @@
- buf_int8 buf 0x85;
- EmulePublicKeyReq.write buf t
-
-+ | EmulePortTestReq t ->
-+ buf_int8 buf 0xfe;
-+ EmulePortTestReq.write buf;
-+
- | UnknownReq (opcode, s) ->
- Buffer.add_string buf s
-
-Index: src/networks/donkey/donkeyProtoCom.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyProtoCom.ml,v
-retrieving revision 1.32
-retrieving revision 1.33
-diff -u -r1.32 -r1.33
---- src/networks/donkey/donkeyProtoCom.ml 19 May 2006 23:43:54 -0000 1.32
-+++ src/networks/donkey/donkeyProtoCom.ml 8 Oct 2006 14:20:22 -0000 1.33
-@@ -341,7 +341,7 @@
- if !verbose_share || !verbose then
- lprintf_nl "Sending %d share(s) to server %s:%d%s"
- nfiles (Ip.to_string (peer_ip sock)) (peer_port sock)
-- (if compressed then "(zlib)" else "");
-+ (if compressed then " (zlib)" else "");
- Buffer.reset buf;
- let s_c =
- if compressed then
-Index: src/networks/donkey/donkeyProtoKademlia.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyProtoKademlia.ml,v
-retrieving revision 1.20
-retrieving revision 1.21
-diff -u -r1.20 -r1.21
---- src/networks/donkey/donkeyProtoKademlia.ml 19 May 2006 23:43:54 -0000 1.20
-+++ src/networks/donkey/donkeyProtoKademlia.ml 31 Oct 2006 15:42:48 -0000 1.21
-@@ -45,6 +45,7 @@
-
- let names_of_tag =
- [
-+ "\243", Field_UNKNOWN "encryption"; (* 0xF3 *)
- "\248", Field_UNKNOWN "buddyhash"; (* 0xF8 *)
- "\249", Field_UNKNOWN "clientlowid"; (* 0xF9 *)
- "\250", Field_UNKNOWN "serverport"; (* 0xFA *)
-Index: src/networks/donkey/donkeyProtoOvernet.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyProtoOvernet.ml,v
-retrieving revision 1.30
-retrieving revision 1.31
-diff -u -r1.30 -r1.31
---- src/networks/donkey/donkeyProtoOvernet.ml 19 May 2006 23:43:54 -0000 1.30
-+++ src/networks/donkey/donkeyProtoOvernet.ml 5 Nov 2006 14:13:51 -0000 1.31
-@@ -189,15 +189,21 @@
- match tag.tag_name with
- Field_UNKNOWN "loc" ->
- for_string_tag tag (fun bcp ->
-- if !verbose_overnet then
-- lprintf_nl "loc tag : [%s]" bcp;
-+ if !verbose_overnet then lprintf_nl "loc tag : [%s]" bcp;
- if String2.starts_with bcp "bcp://" then
- let bcp2 = String.sub bcp 6 (String.length bcp - 6)
- in
- match String2.split_simplify bcp2 ':' with
-+ | [_;ip;udpport;tcpport] ->
-+ if !verbose_overnet then
-+ lprintf_nl "Received BCP type 3 %s" bcp;
-+ peer_ip := Ip.of_string ip;
-+ peer_udpport := int_of_string udpport;
-+ peer_tcpport := int_of_string tcpport;
-+
- | [_;ip;port] ->
- if !verbose_overnet then
-- lprintf_nl "Received BCP type 2 %s"
-+ lprintf_nl "Received BCP type 2 %s, ignoring"
- bcp;
-
- (* FIXME: A firewalled peer...
-Index: src/networks/donkey/donkeyProtoServer.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyProtoServer.ml,v
-retrieving revision 1.21
-retrieving revision 1.22
-diff -u -r1.21 -r1.22
---- src/networks/donkey/donkeyProtoServer.ml 6 Oct 2005 10:21:09 -0000 1.21
-+++ src/networks/donkey/donkeyProtoServer.ml 14 Nov 2006 18:42:59 -0000 1.22
-@@ -154,22 +154,30 @@
- module SetID = struct
- type t = {
- ip : Ip.t;
-+ port : int option;
- zlib : bool;
-- port : int option
-+ newtags : bool;
-+ unicode : bool;
-+ related_search : bool;
-+ tag_integer : bool;
-+ largefiles : bool;
-+ udp_obfuscation : bool;
-+ tcp_obfuscation : bool;
- }
-
- let parse len s =
-- let ip = get_ip s 1 in
-- let zlib = (0x01 land get_int s 5) = 0x01 in
-- let port =
-- if len <= 9 then
-- None
-- else
-- Some (get_int s 9) in
-+ let flags = get_int s 5 in
- {
-- ip = ip;
-- zlib = zlib;
-- port = port;
-+ ip = get_ip s 1;
-+ port = if len <= 9 then None else Some (get_int s 9);
-+ zlib = 0x01 land flags = 0x01;
-+ newtags = 0x08 land flags = 0x08;
-+ unicode = 0x10 land flags = 0x10;
-+ related_search = 0x40 land flags = 0x40;
-+ tag_integer = 0x80 land flags = 0x80;
-+ largefiles = 0x100 land flags = 0x100;
-+ udp_obfuscation = 0x200 land flags = 0x200;
-+ tcp_obfuscation = 0x400 land flags = 0x400;
- }
-
- let print t =
-Index: src/networks/donkey/donkeyProtoUdp.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyProtoUdp.ml,v
-retrieving revision 1.14
-retrieving revision 1.15
-diff -u -r1.14 -r1.15
---- src/networks/donkey/donkeyProtoUdp.ml 16 Jan 2006 16:05:14 -0000 1.14
-+++ src/networks/donkey/donkeyProtoUdp.ml 1 Oct 2006 17:54:00 -0000 1.15
-@@ -455,6 +455,7 @@
- | EmuleReaskAckUdpReq of Md4.t
- | EmuleFileNotFoundUdpReq
- | EmuleQueueFullUdpReq
-+| EmulePortTestReq
-
- | UnknownUdpReq of int * string
-
-@@ -484,6 +485,7 @@
- | 145 -> EmuleReaskAckUdpReq (get_md4 s 1)
- (* | 146 -> EmuleFileNotFoundUdpReq *)
- | 147 -> EmuleQueueFullUdpReq
-+ | 254 -> EmulePortTestReq
-
- | _ -> raise Exit
- with
-@@ -524,6 +526,8 @@
- Printf.bprintf b "EmuleFileNotFoundUdpReq"
- | EmuleQueueFullUdpReq ->
- Printf.bprintf b "EmuleQueueFullUdpReq"
-+ | EmulePortTestReq ->
-+ Printf.bprintf b "EmulePortTestReq"
-
- | UnknownUdpReq (magic, s) ->
- Printf.bprintf b "UnknownReq magic %d\n" magic;
-@@ -613,6 +617,14 @@
- buf_int8 buf 53;
- QueryIDReplyUdp.write buf t
-
-+ | EmulePortTestReq ->
-+ buf_int8 buf 2;
-+ buf_int8 buf 0;
-+ buf_int8 buf 0;
-+ buf_int8 buf 0;
-+ buf_int8 buf 0xfe;
-+ buf_int8 buf 0x31
-+
- | EmuleQueueFullUdpReq
- | EmuleFileNotFoundUdpReq
- | EmuleReaskAckUdpReq _
-Index: src/networks/donkey/donkeyServers.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyServers.ml,v
-retrieving revision 1.59
-retrieving revision 1.66
-diff -u -r1.59 -r1.66
---- src/networks/donkey/donkeyServers.ml 1 Sep 2006 16:25:15 -0000 1.59
-+++ src/networks/donkey/donkeyServers.ml 21 Nov 2006 22:34:34 -0000 1.66
-@@ -34,6 +34,7 @@
- open CommonOptions
- open CommonGlobals
- open CommonSources
-+open CommonShared
-
- open DonkeyMftp
- open DonkeyImport
-@@ -210,6 +211,35 @@
-
-
- let disconnect_server s reason =
-+ let choose_new_master_server s =
-+ match !DonkeyGlobals.master_server with
-+ | Some ss when s == ss ->
-+ DonkeyGlobals.master_server := None;
-+ (try
-+ DonkeyGlobals.master_server :=
-+ Some (List.find (fun s -> s.server_master) !servers_list);
-+ if !verbose_location then begin
-+ match !DonkeyGlobals.master_server with
-+ | Some ns ->
-+ lprintf_nl "changed main master server from %s (%s) to %s (%s)"
-+ ss.server_name (string_of_server ss) ns.server_name (string_of_server ns)
-+ | _ -> ()
-+ end
-+ with Not_found -> ())
-+ | _ -> ();
-+ in
-+(* remove this server from the list of servers a file was published to *)
-+ let remove_server_from_shared_files s =
-+ List.iter (fun file ->
-+ shared_iter (fun sh ->
-+ let impl = as_shared_impl sh in
-+ impl.impl_shared_servers <-
-+ List2.removeq (as_server s.server_server) impl.impl_shared_servers)
-+ ) s.server_sent_shared;
-+ s.server_sent_shared <- []
-+ in
-+ choose_new_master_server s;
-+ remove_server_from_shared_files s;
- match s.server_sock with
- NoConnection -> ()
- | ConnectionWaiting token ->
-@@ -225,16 +255,11 @@
- s.server_users <- [];
- set_server_state s (NotConnected (reason, -1));
- s.server_master <- false;
-- (match !DonkeyGlobals.master_server with
-- | Some ss when s == ss ->
-- DonkeyGlobals.master_server := None;
-- | _ -> ());
- s.server_banner <- "";
- s.server_sent_all_queries <- false;
- remove_connecting_server s;
- remove_connected_server s
-
--
- let server_handler s sock event =
- match event with
- BASIC_EVENT (CLOSED r) ->
-@@ -259,6 +284,13 @@
- match t with
- M.SetIDReq t ->
- s.server_has_zlib <- t.M.SetID.zlib;
-+ s.server_has_newtags <- t.M.SetID.newtags;
-+ s.server_has_unicode <- t.M.SetID.unicode;
-+ s.server_has_related_search <- t.M.SetID.related_search;
-+ s.server_has_tag_integer <- t.M.SetID.tag_integer;
-+ s.server_has_largefiles <- t.M.SetID.largefiles;
-+ s.server_has_udp_obfuscation <- t.M.SetID.udp_obfuscation;
-+ s.server_has_tcp_obfuscation <- t.M.SetID.tcp_obfuscation;
- if low_id t.M.SetID.ip && !!force_high_id then
- disconnect_server s (Closed_for_error "Low ID")
- else begin
-@@ -281,23 +313,24 @@
- end
-
- | M.MessageReq msg ->
-+ if msg <> "" then begin
- if !last_message_sender <> server_num s then begin
-- let server_header = Printf.sprintf "\n+-- From server %s [%s:%d] ------"
-- s.server_name (Ip.to_string s.server_ip) s.server_port in
-+ let server_header = Printf.sprintf "\n+-- From server %s [%s] ------"
-+ s.server_name (string_of_server s) in
- CommonEvent.add_event (Console_message_event (Printf.sprintf "%s\n" server_header));
- if !CommonOptions.verbose_msg_servers then
-- lprintf_nl "%s" server_header;
-+ lprintf_nl "%s" server_header;
- last_message_sender := server_num s
- end;
- s.server_banner <- s.server_banner ^ Printf.sprintf "%s\n" msg;
- let msg = Printf.sprintf "| %s" msg in
- CommonEvent.add_event (Console_message_event (Printf.sprintf "%s\n" msg));
-- if !CommonOptions.verbose_msg_servers then
-- lprintf_nl "%s" msg
-+ if !CommonOptions.verbose_msg_servers then lprintf_nl "%s" msg
-+ end
-
- | M.ServerListReq l ->
- if !!update_server_list_server then begin
-- if !verbose_msg_servers then lprintf_nl "Received serverlist from server";
-+ if !verbose_msg_servers then lprintf_nl "Received %d servers from server" (List.length l);
- let module Q = M.ServerList in
- List.iter (fun s ->
- safe_add_server s.Q.ip s.Q.port
-@@ -318,7 +351,7 @@
- s.server_name <- name
- | { tag_name = Field_UNKNOWN "description"; tag_value = String desc } ->
- s.server_description <- desc
-- | _ -> ()
-+ | _ -> lprintf_nl "parsing donkeyServers.ServerInfo, unknown field %s" (string_of_tag tag)
- ) s.server_tags;
-
- (* nice and ugly, but it doesn't require any new fields *)
-@@ -339,8 +372,8 @@
- s.server_nfiles <- Some (Int64.of_int files);
- if (users < !!min_users_on_server && not s.server_preferred) then
- begin
-- lprintf_nl "%s:%d remove server min_users_on_server limit hit!"
-- (Ip.to_string s.server_ip) s.server_port;
-+ lprintf_nl "%s remove server min_users_on_server limit hit!"
-+ (string_of_server s);
-
- disconnect_server s Closed_for_timeout;
- server_remove (as_server s.server_server);
-@@ -618,8 +651,7 @@
- if ls < min_last_conn && s.server_sock = NoConnection
- && not s.server_preferred then begin
- if !verbose then
-- lprintf_nl "old servers: Server too old: %s:%d"
-- (Ip.to_string s.server_ip) s.server_port;
-+ lprintf_nl "old servers: Server too old: %s" (string_of_server s);
-
- to_remove := s :: !to_remove
- end
-@@ -674,16 +706,14 @@
- if connection_can_try s.server_connection_control then
- begin
- if !verbose then
-- lprintf_nl "WALKER: try connect %s"
-- (Ip.to_string s.server_ip);
-+ lprintf_nl "WALKER: try connect %s" (string_of_server s);
- connect_server s
- end
- else
- begin
- delayed_list := s :: !delayed_list;
- if !verbose then
-- lprintf_nl "WALKER: connect %s delayed"
-- (Ip.to_string s.server_ip);
-+ lprintf_nl "WALKER: connect %s delayed" (string_of_server s);
- end
- | _ -> ()
-
-@@ -749,13 +779,13 @@
- match s.server_sock with
- | Connection _ ->
- if !verbose_location then begin
-- if !tag2 then begin
-+ if !tag2 then begin
- lprintf_n "master servers (old):";
-- tag1 := false;
-- tag2 := false
-- end;
-- lprintf " %s" (Ip.to_string s.server_ip)
-- end;
-+ tag1 := false;
-+ tag2 := false
-+ end;
-+ lprintf " %s" (string_of_server s)
-+ end;
- masters := s :: !masters
- | _ -> s.server_master <- false
- ) server_list;
-@@ -772,8 +802,7 @@
- masters := s :: !masters;
- masters := List.rev (List.sort compare_servers !masters);
-
-- server_send_share s.server_has_zlib sock
-- (DonkeyShare.all_shared ())
-+ DonkeyGlobals.master_server := Some s;
- )
- in
-
-@@ -786,7 +815,7 @@
- if !nconnected_servers > max_allowed_connected_servers then
- begin
- if !verbose_location then
-- lprintf_nl "master servers: disconnect %s" (Ip.to_string s.server_ip);
-+ lprintf_nl "master servers: disconnect %s" (string_of_server s);
- nconnected_servers := !nconnected_servers - 3;
- do_if_connected s.server_sock (fun sock ->
- (* We will disconnect from this server.
-@@ -805,23 +834,17 @@
- - connection_last_conn s.server_connection_control
- in
- if !verbose_location then
-- lprintf_nl "master servers: Checking ip:%s, users: %Ld, ct:%d"
-- (Ip.to_string s.server_ip)
-- (match s.server_nusers with None -> 0L | Some v -> v)
-- connection_time;
-- if not s.server_master
-- && (s.server_preferred
-- || connection_time > !!become_master_delay
-- )
-- then
-+ lprintf_nl "master servers: Checking %s, users: %Ld, ct:%d"
-+ (string_of_server s)
-+ (match s.server_nusers with None -> 0L | Some v -> v)
-+ connection_time;
-+ if not s.server_master then
- begin
-- if (!nmasters < max_allowed_connected_servers) then
-- begin
-- if !verbose_location then
-- lprintf_nl "master servers: raising %s"
-- (Ip.to_string s.server_ip);
-+ if (!nmasters < max_allowed_connected_servers) then begin
-+ if !verbose_location then
-+ lprintf_nl "master servers: raising %s" (string_of_server s);
- make_master s
-- end
-+ end
- else if s.server_sent_all_queries then
- match !masters with
- [] -> disconnect_old_server s
-@@ -838,7 +861,7 @@
- or is a preferred one *)
- if (s.server_preferred && not ss.server_preferred)
- || (!!keep_best_server
-- && mini ((Int64.to_int ss_nusers) + 1000)
-+ && min ((Int64.to_int ss_nusers) + 1000)
- ((Int64.to_int ss_nusers) * 5)
- < (Int64.to_int s_nusers)
- )
-@@ -847,7 +870,7 @@
- if !verbose_location then
- lprintf_nl
- "master servers: raising %s, disconnected %s"
-- (Ip.to_string s.server_ip) (Ip.to_string ss.server_ip);
-+ (string_of_server s) (string_of_server ss);
- ss.server_master <- false;
- masters := tail;
- make_master s
-Index: src/networks/donkey/donkeyShare.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyShare.ml,v
-retrieving revision 1.50
-retrieving revision 1.55
-diff -u -r1.50 -r1.55
---- src/networks/donkey/donkeyShare.ml 1 Sep 2006 16:22:15 -0000 1.50
-+++ src/networks/donkey/donkeyShare.ml 9 Oct 2006 16:17:19 -0000 1.55
-@@ -39,18 +39,15 @@
-
- module VB = VerificationBitmap
-
--let new_shared_files = ref []
--
- let must_share_file file codedname has_old_impl =
- match file.file_shared with
- | Some _ -> ()
- | None ->
-- new_shared := true;
- let full_name = file_disk_name file in
- let magic =
- match Magic.M.magic_fileinfo full_name false with
- None -> None
-- | Some magic -> Some (HashMagic.merge files_magic magic)
-+ | Some magic -> Some (intern magic)
- in
-
- let impl = {
-@@ -65,9 +62,9 @@
- impl_shared_val = file;
- impl_shared_requests = 0;
- impl_shared_magic = magic;
-+ impl_shared_servers = []
- } in
- file.file_shared <- Some impl;
-- new_shared_files := file :: !new_shared_files;
- incr CommonGlobals.nshared_files;
- CommonShared.shared_calculate_total_bytes ();
- match has_old_impl with
-@@ -99,7 +96,7 @@
- lprintf_nl "Sharing file with MD4: %s" (Md4.to_string md4);
-
- let file = new_file sh.sh_name FileShared md4 sh.sh_size
-- "" false in
-+ "" false CommonUserDb.admin_user in
- must_share_file file codedname old_impl;
- file.file_computed_md4s <- md4s;
- add_file_filenames (as_file file) (Filename.basename sh.sh_name);
-@@ -162,41 +159,69 @@
- None -> ()
- | Some _ -> shared_files := file :: !shared_files
- ) files_by_md4;
-- if !verbose_share then lprintf_nl "%d files shared" (List.length !shared_files);
-+ if !verbose_share then lprintf_nl "scanned shared files, %d files found" (List.length !shared_files);
- !shared_files
-
--(* Check whether new files are shared, and send them to connected servers.
-- Do it only once per 5 minutes to prevent sending to many times all files.
-- Change: Just send *new* shared files to servers, they never forget a
-- clients files until disconnection.
-- Should I only do it for master servers, no ?
--*)
-+(* publish shared files to servers, called once per minute *)
- let send_new_shared () =
-- let tag = ref false in
-- if !new_shared then
-- begin
-- new_shared := false;
-- if !new_shared_files <> [] then
-- begin
-- List.iter (fun s ->
-- if s.server_master then
-- begin
-- if !verbose_share || !verbose then
-- lprintf_nl "send_new_shared: found master server %s:%d"
-- (Ip.to_string s.server_ip) s.server_port;
-- tag := true;
-- do_if_connected s.server_sock (fun sock ->
-- server_send_share s.server_has_zlib sock !new_shared_files)
-- end
-- ) (connected_servers ());
-- if !tag && (!verbose_share || !verbose) then
-- lprintf_nl "send_new_shared: Sent %d new shared files to servers"
-- (List.length !new_shared_files);
-- new_shared_files := []
-- end
-- else
-- lprintf_nl "donkey send_new_share: No new shared files to send to servers"
-- end
-+(* sort list to publish least published files first *)
-+ let ( |> ) x f = f x in
-+ let all_shared =
-+ all_shared ()
-+ |> List.map (fun e ->
-+ (match e.file_shared with
-+ Some s -> List.length s.impl_shared_servers
-+ | _ -> 0) , e)
-+ |> List.sort (fun (a,_) (b,_) -> compare a b)
-+ |> List.map snd
-+ in
-+
-+(* iter through connected servers *)
-+ List.iter (fun s ->
-+
-+(* publish files only on master servers and do not publish more files than hard limit allows *)
-+ if s.server_master &&
-+ (match s.server_hard_limit with
-+ Some v when (Int64.to_int v) < List.length s.server_sent_shared -> false
-+ | _ -> true) then
-+
-+(* iter through all shared files and check if the file is already published on the current server
-+ build a list of files_to_send with yet unpublished files *)
-+ begin
-+ let files_to_send = ref [] in
-+ List.iter (fun f ->
-+ match f.file_shared with
-+ Some impl ->
-+ if not (List.mem (CommonServer.as_server s.server_server) impl.impl_shared_servers)
-+ && List.length !files_to_send < !!max_published_files then
-+ files_to_send := f :: !files_to_send
-+ | _ -> () (* this case never happens *)
-+ ) all_shared;
-+
-+ if !files_to_send <> [] then
-+ begin
-+ if !verbose_share || !verbose then
-+ lprintf_nl "publishing %d new files to %s (holds %d files)"
-+ (List.length !files_to_send) (string_of_server s)
-+ (List.length s.server_sent_shared);
-+
-+(* publish files on server *)
-+ do_if_connected s.server_sock (fun sock ->
-+ server_send_share s.server_has_zlib sock !files_to_send);
-+
-+(* append new published files to server structure *)
-+ s.server_sent_shared <- !files_to_send @ s.server_sent_shared;
-+
-+(* iter through published files and append current server *)
-+ List.iter (fun file ->
-+ match file.file_shared with
-+ Some impl -> impl.impl_shared_servers <-
-+ impl.impl_shared_servers @ [(CommonServer.as_server s.server_server)]
-+ | _ -> ()) !files_to_send
-+
-+ end
-+ end
-+ ) (connected_servers ());
-
- (*
- The problem: sh.shared_fd might be closed during the execution of the
-@@ -209,7 +234,7 @@
- let computing = ref false
-
- (* Compute (at most) one MD4 chunk if needed. *)
--let check_shared_files () =
-+let rec check_shared_files () =
- let module M = CommonHasher in
- if not !computing then
- match !shared_files with
-@@ -259,7 +284,11 @@
- new_file_to_share s sh.shared_shared.impl_shared_codedname (Some sh.shared_shared);
- end
- else
-- job_creater ()
-+ job_creater ();
-+ (* only try back-to-back hashing if hashing is
-+ handled by a separate thread *)
-+ if BasicSocket.has_threads () then
-+ check_shared_files ()
- )
- with
- Wrong_file_size (real,computed) ->
-@@ -307,7 +336,7 @@
- let magic =
- match Magic.M.magic_fileinfo fullname false with
- None -> None
-- | Some magic -> Some (HashMagic.merge files_magic magic)
-+ | Some magic -> Some (intern magic)
- in
-
- let rec impl = {
-@@ -322,6 +351,7 @@
- impl_shared_val = pre_shared;
- impl_shared_requests = 0;
- impl_shared_magic = magic;
-+ impl_shared_servers = [];
- } and
- pre_shared = {
- shared_shared = impl;
-Index: src/networks/donkey/donkeyStats.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyStats.ml,v
-retrieving revision 1.24
-retrieving revision 1.25
-diff -u -r1.24 -r1.25
---- src/networks/donkey/donkeyStats.ml 26 Jan 2006 10:34:53 -0000 1.24
-+++ src/networks/donkey/donkeyStats.ml 23 Sep 2006 20:29:47 -0000 1.25
-@@ -170,6 +170,21 @@
- let _ =
- network.op_network_display_stats <- (fun buf o -> print_stats o New false);
-
-+ network.op_network_stat_info_list <- (fun _ ->
-+ let r = ref [] in
-+ let l1 = stats_list brand_list stats_array in
-+ let l2 = stats_list brand_list !!gstats_array in
-+ let u1 = BasicSocket.last_time () - !start_session in
-+ let u2 = (guptime() + u1) in
-+ r := [("Session clients", u1, l1); ("Global clients", u2, l2)];
-+ if !!emule_mods_count then begin
-+ let l3 = stats_list brand_mod_list stats_mod_array in
-+ let l4 = stats_list brand_mod_list !!gstats_mod_array in
-+ r := !r @ [ ("Session mods", u1, l3); ("Global mods", u2, l4)]
-+ end;
-+ !r
-+ );
-+
- register_commands
- [
- "client_stats", "Network/Donkey",Arg_none (fun o ->
-Index: src/networks/donkey/donkeySui1.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeySui1.ml,v
-retrieving revision 1.1
-retrieving revision 1.2
-diff -u -r1.1 -r1.2
---- src/networks/donkey/donkeySui1.ml 26 Jan 2006 00:25:25 -0000 1.1
-+++ src/networks/donkey/donkeySui1.ml 21 Oct 2006 20:01:23 -0000 1.2
-@@ -30,3 +30,8 @@
- external create_signature : string -> int -> int64 -> int -> int64 -> string = "ml_createSignature"
- external verify_signature : string -> int -> string -> int -> int64 -> int -> int64 -> bool = "ml_verifySignature_bytecode" "ml_verifySignature"
- end
-+
-+let ext_lprintf_nl msg =
-+ if !CommonOptions.verbose_unexpected_messages then Printf2.lprintf_nl ("%s") msg
-+
-+let _ = Callback.register "ml_lprintf_nl" ext_lprintf_nl
-Index: src/networks/donkey/donkeyTypes.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyTypes.ml,v
-retrieving revision 1.47
-retrieving revision 1.51
-diff -u -r1.47 -r1.51
---- src/networks/donkey/donkeyTypes.ml 5 Sep 2006 14:18:24 -0000 1.47
-+++ src/networks/donkey/donkeyTypes.ml 14 Nov 2006 18:42:59 -0000 1.51
-@@ -39,6 +39,7 @@
- mutable emule_secident : int;
- mutable emule_noviewshared : int;
- mutable emule_supportpreview : int;
-+ mutable emule_osinfosupport : int;
-
- mutable emule_compression : int;
- mutable emule_sourceexchange : int;
-@@ -430,7 +431,21 @@
- | Invalid_address _ -> failwith "Invalid address"
- end)
-
--type server = (*[]*){
-+type file = {
-+ file_file : file CommonFile.file_impl;
-+ file_md4 : Md4.t;
-+ mutable file_swarmer : CommonSwarming.t option;
-+ mutable file_nchunks : int;
-+ mutable file_nchunk_hashes : int;
-+ mutable file_diskname : string;
-+ mutable file_computed_md4s : Md4.t array;
-+ mutable file_format : format;
-+ mutable file_shared : file CommonShared.shared_impl option;
-+ mutable file_sources : DonkeySources.file_sources_manager;
-+ mutable file_comments : (Ip.t * string * int * string) list;
-+ }
-+
-+and server = (*[]*){
- mutable server_server : server CommonServer.server_impl;
- mutable server_ip : Ip.t;
- mutable server_cid : Ip.t option;
-@@ -463,6 +478,19 @@
- mutable server_waiting_queries : file list;
- mutable server_sent_all_queries : bool;
- mutable server_has_zlib : bool;
-+ mutable server_has_newtags : bool;
-+ mutable server_has_unicode : bool;
-+ mutable server_has_related_search : bool;
-+ mutable server_has_tag_integer : bool;
-+ mutable server_has_largefiles : bool;
-+ mutable server_has_udp_obfuscation : bool;
-+ mutable server_has_tcp_obfuscation : bool;
-+ mutable server_obfuscation_port_tcp : int option;
-+ mutable server_obfuscation_port_udp : int option;
-+ mutable server_udp_key : int option;
-+ mutable server_udp_keyip : Ip.t option;
-+ mutable server_dynip : string;
-+ mutable server_auxportslist : string;
-
- mutable server_flags : int;
- mutable server_version : string;
-@@ -470,6 +498,7 @@
- mutable server_soft_limit : int64 option;
- mutable server_hard_limit : int64 option;
- mutable server_max_users : int64 option;
-+ mutable server_sent_shared : file list
- }
-
-
-@@ -519,7 +548,6 @@
- CommonSwarming.uploader
- ) list;
- mutable client_all_files : result list option;
-- mutable client_last_asked_file : CommonTypes.file;
- mutable client_tags: CommonTypes.tag list;
- mutable client_name : string;
- mutable client_rating : int ;
-@@ -531,6 +559,8 @@
- mutable client_uploaded : Int64.t;
- mutable client_brand : brand;
- mutable client_brand_mod : brand_mod;
-+ mutable client_osinfo_sent : bool;
-+ mutable client_osinfo : string option;
- mutable client_banned : bool;
- mutable client_score : int;
- mutable client_next_queue : int;
-@@ -549,6 +579,7 @@
- mutable client_req_challenge : Int64.t;
- mutable client_public_key : string option;
- mutable client_sui_verified : bool option;
-+ mutable client_last_file_req_md4 : Md4.t option;
- }
-
- and compressed_parts = {
-@@ -579,19 +610,6 @@
- int * (* last connection attempt *)
- int (* booked client num *)
-
--and file = {
-- file_file : file CommonFile.file_impl;
-- file_md4 : Md4.t;
-- mutable file_swarmer : CommonSwarming.t option;
-- mutable file_nchunks : int;
-- mutable file_nchunk_hashes : int;
-- mutable file_diskname : string;
-- mutable file_computed_md4s : Md4.t array;
-- mutable file_format : format;
-- mutable file_shared : file CommonShared.shared_impl option;
-- mutable file_sources : DonkeySources.file_sources_manager;
-- }
--
- and file_to_share = {
- shared_name : string;
- shared_size : int64;
-@@ -674,6 +692,7 @@
- emule_secident = 0;
- emule_noviewshared = 0;
- emule_supportpreview = 0;
-+ emule_osinfosupport = 0;
-
- emule_compression = 0; (* 1 *)
- emule_sourceexchange = 0; (* 3 *)
-Index: src/networks/donkey/donkeyUdp.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyUdp.ml,v
-retrieving revision 1.23
-retrieving revision 1.25
-diff -u -r1.23 -r1.25
---- src/networks/donkey/donkeyUdp.ml 1 Sep 2006 16:25:15 -0000 1.23
-+++ src/networks/donkey/donkeyUdp.ml 15 Nov 2006 12:34:30 -0000 1.25
-@@ -223,7 +223,7 @@
-
- let udp_client_handler t p =
- if !verbose_udp then
-- lprintf "Received UDP message:\n%s\n" (Udp.print t);
-+ lprintf_nl "Received UDP message:\n%s" (Udp.print t);
-
- let udp_from_server p =
- match p.UdpSocket.udp_addr with
-@@ -296,7 +296,11 @@
- s.server_name <- name
- | { tag_name = Field_UNKNOWN "description"; tag_value = String desc } ->
- s.server_description <- desc
-- | _ -> ()
-+ | { tag_name = Field_UNKNOWN "auxportslist" ; tag_value = String aux } ->
-+ s.server_auxportslist <- aux
-+ | { tag_name = Field_UNKNOWN "dynip" ; tag_value = String dynip } ->
-+ s.server_dynip <- dynip
-+ | _ -> lprintf_nl "parsing Udp.ServerDescReplyUdp, unknown field %s" (string_of_tag tag)
- ) t.M.tags;
-
- if s.server_tags = [] then
-@@ -306,6 +310,15 @@
-
- | Udp.EmuleReaskFilePingUdpReq t -> ()
-
-+ | Udp.EmulePortTestReq ->
-+ (match !porttest_sock with
-+ None -> ()
-+ | Some sock ->
-+ let s = Buffer.create 10 in
-+ DonkeyProtoUdp.write s Udp.EmulePortTestReq;
-+ TcpBufferedSocket.write_string sock (Buffer.contents s);
-+ porttest_sock := None)
-+
- | _ ->
- if !verbose_unexpected_messages then
- lprintf "Unexpected UDP message: %s\n"
-Index: src/networks/fasttrack/fasttrackGlobals.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/fasttrack/fasttrackGlobals.ml,v
-retrieving revision 1.41
-retrieving revision 1.43
-diff -u -r1.41 -r1.43
---- src/networks/fasttrack/fasttrackGlobals.ml 1 Sep 2006 16:22:15 -0000 1.41
-+++ src/networks/fasttrack/fasttrackGlobals.ml 9 Nov 2006 21:32:27 -0000 1.43
-@@ -267,7 +267,7 @@
-
- let min_range_size = megabyte
-
--let new_file file_temporary file_name file_size file_hash =
-+let new_file file_temporary file_name file_size file_hash user =
- let file_temp = Filename.concat !!temp_directory file_temporary in
- (* (Printf.sprintf "FT-%s" (Md4.to_string file_id)) in *)
- let t = Unix32.create_rw file_temp in
-@@ -293,6 +293,8 @@
- impl_file_fd = Some t;
- impl_file_size = file_size;
- impl_file_downloaded = Int64.zero;
-+ impl_file_owner = user;
-+ impl_file_group = user.user_default_group;
- impl_file_val = file;
- impl_file_ops = file_ops;
- impl_file_age = last_time ();
-@@ -335,7 +337,7 @@
-
- exception FileFound of file
-
--let new_file file_id file_name file_size file_uids =
-+let new_file file_id file_name file_size file_uids user =
- let file = ref None in
- List.iter (fun uid ->
- match Uid.to_uid uid with
-@@ -343,7 +345,7 @@
- file := Some (try
- Hashtbl.find files_by_uid file_hash
- with _ ->
-- let file = new_file file_id file_name file_size file_hash in
-+ let file = new_file file_id file_name file_size file_hash user in
- Hashtbl.add files_by_uid file_hash file;
- file)
- | _ -> ()
-Index: src/networks/fasttrack/fasttrackPandora.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/fasttrack/fasttrackPandora.ml,v
-retrieving revision 1.9
-retrieving revision 1.10
-diff -u -r1.9 -r1.10
---- src/networks/fasttrack/fasttrackPandora.ml 14 Dec 2005 21:17:46 -0000 1.9
-+++ src/networks/fasttrack/fasttrackPandora.ml 21 Nov 2006 22:34:34 -0000 1.10
-@@ -223,7 +223,7 @@
- let check1 = check_xinu s (pos + 5 + len1) len (depth+1) in
- let check2 = check_xinu s (pos + 5 + len2) len (depth+1) in
-
-- maxi check0 (maxi check1 check2)
-+ max check0 (max check1 check2)
- else depth
- | _ -> -10
-
-Index: src/networks/fasttrack/fasttrackServers.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/fasttrack/fasttrackServers.ml,v
-retrieving revision 1.29
-retrieving revision 1.30
-diff -u -r1.29 -r1.30
---- src/networks/fasttrack/fasttrackServers.ml 19 May 2006 23:43:54 -0000 1.29
-+++ src/networks/fasttrack/fasttrackServers.ml 19 Sep 2006 17:07:43 -0000 1.30
-@@ -322,7 +322,7 @@
- ) file.file_searches
- ) !connected_servers
-
--let really_download_file (r : CommonTypes.result_info) =
-+let really_download_file (r : CommonTypes.result_info) user =
- let rec iter uids =
- match uids with
- uid :: tail ->
-@@ -334,7 +334,7 @@
- let hash,file_temp = iter r.result_uids in
-
- let file = new_file file_temp (List.hd r.result_names)
-- r.result_size [Uid.create (Md5Ext hash)] in
-+ r.result_size [Uid.create (Md5Ext hash)] user in
- if !verbose then
- lprintf "DOWNLOAD FILE %s\n" file.file_name;
- if not (List.memq file !current_files) then begin
-Index: src/networks/fileTP/fileTPClients.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/fileTP/fileTPClients.ml,v
-retrieving revision 1.22
-retrieving revision 1.23
-diff -u -r1.22 -r1.23
---- src/networks/fileTP/fileTPClients.ml 8 Aug 2006 23:55:28 -0000 1.22
-+++ src/networks/fileTP/fileTPClients.ml 19 Sep 2006 17:07:43 -0000 1.23
-@@ -63,9 +63,9 @@
- if (filesize = 0L || !!chunk_size = 0) then 1
- else Int64.to_int ((filesize) // (min_range_size file)) + 5
-
--let pause_for_cause f r =
-+let pause_for_cause f r user =
- lprintf_nl "Pausing file %s (%s)" (file_best_name f) r;
-- file_pause (as_file f)
-+ file_pause (as_file f) user
-
- let disconnect_client c r =
- match c.client_sock with
-Index: src/networks/fileTP/fileTPComplexOptions.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/fileTP/fileTPComplexOptions.ml,v
-retrieving revision 1.16
-retrieving revision 1.17
-diff -u -r1.16 -r1.17
---- src/networks/fileTP/fileTPComplexOptions.ml 25 May 2006 19:47:25 -0000 1.16
-+++ src/networks/fileTP/fileTPComplexOptions.ml 19 Sep 2006 17:07:43 -0000 1.17
-@@ -78,8 +78,7 @@
- Md4.of_string (get_value "file_id" value_to_string)
- with _ -> failwith "Bad file_id"
- in
--
-- let file = new_file file_id file_name file_size in
-+ let file = new_file file_id file_name file_size CommonUserDb.admin_user in
-
- (match file.file_swarmer with
- None -> ()
-Index: src/networks/fileTP/fileTPFTP.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/fileTP/fileTPFTP.ml,v
-retrieving revision 1.13
-retrieving revision 1.14
-diff -u -r1.13 -r1.14
---- src/networks/fileTP/fileTPFTP.ml 30 May 2006 10:54:14 -0000 1.13
-+++ src/networks/fileTP/fileTPFTP.ml 19 Sep 2006 17:07:43 -0000 1.14
-@@ -278,13 +278,13 @@
- | "530 " ->
- let reason = String.sub line 4 (slen - 4) in
- if not (retry_530 reason) then begin
-- pause_for_cause d.download_file "530";
-+ pause_for_cause d.download_file "530" CommonUserDb.admin_user;
- end else begin
- c.client_reconnect <- true;
- end;
- disconnect_client c Closed_by_user;
- | "550 " ->
-- pause_for_cause d.download_file "550";
-+ pause_for_cause d.download_file "550" CommonUserDb.admin_user;
- disconnect_client c Closed_by_user;
- | _ ->
- if !verbose then lprintf_nl "Unexpected line %s" line;
-@@ -443,11 +443,11 @@
- | "530 " ->
- let reason = String.sub line 4 (slen - 4) in
- if not (retry_530 reason) then begin
-- pause_for_cause file "530";
-+ pause_for_cause file "530" CommonUserDb.admin_user;
- end;
- close sock Closed_by_user;
- | "550 " ->
-- pause_for_cause file "550";
-+ pause_for_cause file "550" CommonUserDb.admin_user;
- close sock Closed_by_user;
- | _ ->
- if !verbose then lprintf_nl "Unexpected line %s" line;
-Index: src/networks/fileTP/fileTPGlobals.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/fileTP/fileTPGlobals.ml,v
-retrieving revision 1.28
-retrieving revision 1.30
-diff -u -r1.28 -r1.30
---- src/networks/fileTP/fileTPGlobals.ml 1 Sep 2006 16:22:15 -0000 1.28
-+++ src/networks/fileTP/fileTPGlobals.ml 9 Nov 2006 21:32:27 -0000 1.30
-@@ -138,7 +138,7 @@
- file_must_update (as_file file);
- end
-
--let new_file file_id file_name file_size =
-+let new_file file_id file_name file_size user =
- let file_temp = Filename.concat !!temp_directory
- (Printf.sprintf "FileTP-%s" (Md4.to_string file_id)) in
- let t = Unix32.create_rw file_temp in
-@@ -152,6 +152,8 @@
- file_nconnected_clients = 0;
- } and file_impl = {
- dummy_file_impl with
-+ impl_file_owner = user;
-+ impl_file_group = user.user_default_group;
- impl_file_fd = Some t;
- impl_file_size = zero;
- impl_file_downloaded = zero;
-@@ -168,11 +170,11 @@
- (* lprintf "ADD FILE TO DOWNLOAD LIST\n"; *)
- file
-
--let new_file file_id file_name file_size =
-+let new_file file_id file_name file_size users =
- try
- Hashtbl.find files_by_uid file_id
- with _ ->
-- let file = new_file file_id file_name file_size in
-+ let file = new_file file_id file_name file_size users in
- Hashtbl.add files_by_uid file_id file;
- file
-
-Index: src/networks/fileTP/fileTPHTTP.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/fileTP/fileTPHTTP.ml,v
-retrieving revision 1.25
-retrieving revision 1.26
-diff -u -r1.25 -r1.26
---- src/networks/fileTP/fileTPHTTP.ml 10 Aug 2006 17:41:20 -0000 1.25
-+++ src/networks/fileTP/fileTPHTTP.ml 19 Sep 2006 17:07:43 -0000 1.26
-@@ -174,7 +174,7 @@
- end;
-
- if code < 200 || code > 299 then begin
-- pause_for_cause file (Printf.sprintf "%d" code);
-+ pause_for_cause file (Printf.sprintf "%d" code) CommonUserDb.admin_user;
- failwith "Bad HTTP code";
- end;
-
-@@ -386,7 +386,7 @@
- (fun c ->
- match c with
- x when x < 200 || x > 299 ->
-- pause_for_cause file (string_of_int x);
-+ pause_for_cause file (string_of_int x) CommonUserDb.admin_user;
- | _ -> ()
- )
-
-Index: src/networks/fileTP/fileTPInteractive.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/fileTP/fileTPInteractive.ml,v
-retrieving revision 1.46
-retrieving revision 1.52
-diff -u -r1.46 -r1.52
---- src/networks/fileTP/fileTPInteractive.ml 5 Sep 2006 15:32:17 -0000 1.46
-+++ src/networks/fileTP/fileTPInteractive.ml 12 Nov 2006 12:44:24 -0000 1.52
-@@ -234,7 +234,7 @@
-
- let previous_url = ref ""
-
--let download_file url referer =
-+let download_file url referer user =
- let u = Url.of_string url in
-
- if List.mem u !!old_files && !previous_url <> url then begin
-@@ -242,7 +242,7 @@
- failwith "URL already downloaded: repeat command again to force";
- end;
-
-- let file = new_file (Md4.random ()) u.Url.full_file zero in
-+ let file = new_file (Md4.random ()) u.Url.full_file zero user in
-
- if !verbose then
- lprintf_nl "Started new download: %s from %s" (file_best_name file) url;
-@@ -250,6 +250,7 @@
- current_files := file :: !current_files;
- end;
-
-+ CommonInteractive.start_download (as_file file);
- download_file_from_mirror file u referer;
- find_mirrors file u
-
-@@ -276,7 +277,7 @@
- It returns true if this file can be handled by fileTP,
- and false otherwise.
- *)
--let op_network_parse_url url =
-+let op_network_parse_url url user =
- let location_regexp = "Location: \\(.*\\)" in
- let real_url = get_regexp_string url (Str.regexp location_regexp) in
- if (is_http_torrent url real_url) && !!enable_bittorrent then
-@@ -286,7 +287,7 @@
- let length_regexp = "Content-Length: \\(.*\\)" in
- try let length = get_regexp_int url (Str.regexp length_regexp) in
- if (length > 0) then begin
-- download_file real_url ""; "started FileTP download", true
-+ download_file real_url "" user; "started FileTP download", true
- end
- else "can not parse Content-Length", false
- with Not_found ->
-@@ -295,7 +296,7 @@
- else
- if (String2.check_prefix real_url "ftp://") ||
- (String2.check_prefix real_url "ssh://") then (
-- download_file real_url "";
-+ download_file url "" user;
- "started FileTP download", true)
- else
- "invalid URL", false
-@@ -310,8 +311,8 @@
- "http", "Network/FileTP", Arg_multiple (fun args o ->
- try
- (match args with
-- url :: [referer] -> download_file url referer
-- | [url] -> download_file url ""
-+ url :: [referer] -> download_file url referer o.conn_user.ui_user
-+ | [url] -> download_file url "" o.conn_user.ui_user
- | _ -> raise Not_found);
- let buf = o.conn_buf in
- if o.conn_output = HTML then
-@@ -405,7 +406,7 @@
- CommonNetwork.register_commands commands;
- network.op_network_share <- (fun fullname codedname size -> ());
- network.op_network_search <- (fun ss buf -> ());
-- network.op_network_download <- (fun r -> dummy_file);
-+ network.op_network_download <- (fun r user -> dummy_file);
- file_ops.op_file_commit <- (fun file new_name -> clean_stop file);
- file_ops.op_file_pause <- (fun file ->
- List.iter (fun c ->
-@@ -416,9 +417,10 @@
- ) file.file_clients
- );
- file_ops.op_file_resume <- (fun file -> ());
-- file_ops.op_file_print_html <- (fun file buf -> ());
-+ file_ops.op_file_print <- (fun file buf -> ());
- network.op_network_close_search <- (fun s -> ());
- network.op_network_forget_search <- (fun s -> ());
- network.op_network_connect_servers <- (fun s -> ());
- network.op_network_reset <- (fun _ -> ());
-+ network.op_network_porttest_result <- (fun _ -> PorttestNotAvailable);
- network.op_network_recover_temp <- (fun s -> ())
-Index: src/networks/gnutella/gnutellaClients.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/gnutella/gnutellaClients.ml,v
-retrieving revision 1.43
-retrieving revision 1.45
-diff -u -r1.43 -r1.45
---- src/networks/gnutella/gnutellaClients.ml 8 Aug 2006 23:55:28 -0000 1.43
-+++ src/networks/gnutella/gnutellaClients.ml 21 Nov 2006 22:34:34 -0000 1.45
-@@ -997,7 +997,7 @@
- if get_request then
- let pos = uc.uc_chunk_pos in
- let to_write = uc.uc_chunk_end -- pos in
-- let rlen = mini (max_refill sock) (Int64.to_int to_write) in
-+ let rlen = min (max_refill sock) (Int64.to_int to_write) in
- if !verbose_msg_clients then
- lprintf "[GUP] to_write: %d/%Ld/%d\n" rlen to_write
- (remaining_to_write sock);
-@@ -1041,7 +1041,7 @@
- let listen () =
- try
- let sock = TcpServerSocket.create "gnutella client server"
-- Unix.inet_addr_any
-+ (Ip.to_inet_addr !!client_bind_addr)
- !!client_port
- (fun sock event ->
- match event with
-Index: src/networks/gnutella/gnutellaComplexOptions.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/gnutella/gnutellaComplexOptions.ml,v
-retrieving revision 1.28
-retrieving revision 1.29
-diff -u -r1.28 -r1.29
---- src/networks/gnutella/gnutellaComplexOptions.ml 25 May 2006 19:47:25 -0000 1.28
-+++ src/networks/gnutella/gnutellaComplexOptions.ml 19 Sep 2006 17:07:43 -0000 1.29
-@@ -130,7 +130,7 @@
- file_uids := hash :: !file_uids;
- with _ -> ());
-
-- let file = new_file file_temp file_name file_size !file_uids in
-+ let file = new_file file_temp file_name file_size !file_uids CommonUserDb.admin_user in
-
- (try
- file.file_ttr <- Some (get_value "file_ttr" (value_to_array
-Index: src/networks/gnutella/gnutellaGlobals.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/gnutella/gnutellaGlobals.ml,v
-retrieving revision 1.42
-retrieving revision 1.44
-diff -u -r1.42 -r1.44
---- src/networks/gnutella/gnutellaGlobals.ml 1 Sep 2006 16:22:15 -0000 1.42
-+++ src/networks/gnutella/gnutellaGlobals.ml 9 Nov 2006 21:32:27 -0000 1.44
-@@ -310,7 +310,7 @@
- let megabyte = Int64.of_int (1024 * 1024)
- let megabytes10 = Int64.of_int (10 * 1024 * 1024)
-
--let new_file file_temporary file_name file_size file_uids =
-+let new_file file_temporary file_name file_size file_uids user =
- let file_temp = Filename.concat !!temp_directory file_temporary in
- let t = Unix32.create_rw file_temp in
- let rec file = {
-@@ -329,6 +329,8 @@
- impl_file_fd = Some t;
- impl_file_size = file_size;
- impl_file_downloaded = Int64.zero;
-+ impl_file_owner = user;
-+ impl_file_group = user.user_default_group;
- impl_file_val = file;
- impl_file_ops = file_ops;
- impl_file_age = last_time ();
-@@ -357,7 +359,7 @@
-
- exception FileFound of file
-
--let new_file file_id file_name file_size file_uids =
-+let new_file file_id file_name file_size file_uids user =
- (* if file_uids = [] then
- try Hashtbl.find files_by_key (file_name, file_size) with
- _ ->
-@@ -370,7 +372,7 @@
- try raise (FileFound (Hashtbl.find files_by_uid uid))
- with Not_found -> ()
- ) file_uids;
-- let file = new_file file_id file_name file_size file_uids in
-+ let file = new_file file_id file_name file_size file_uids user in
- List.iter (fun uid ->
- if !verbose then
- lprintf "Adding file %s\n" (Uid.to_string uid);
-Index: src/networks/gnutella/gnutellaHandler.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/gnutella/gnutellaHandler.ml,v
-retrieving revision 1.15
-retrieving revision 1.16
-diff -u -r1.15 -r1.16
---- src/networks/gnutella/gnutellaHandler.ml 28 Aug 2006 18:19:16 -0000 1.15
-+++ src/networks/gnutella/gnutellaHandler.ml 21 Nov 2006 22:34:34 -0000 1.16
-@@ -180,7 +180,7 @@
- let module M = QueryReply in
- let module C = CommonUploads in
- let replies = ref [] in
-- for i = 0 to mini (Array.length files - 1) 9 do
-+ for i = 0 to min (Array.length files - 1) 9 do
- let sh, info = files.(i) in
- let infos = ref [] in
- List.iter (fun uid ->
-Index: src/networks/gnutella/gnutellaInteractive.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/gnutella/gnutellaInteractive.ml,v
-retrieving revision 1.63
-retrieving revision 1.67
-diff -u -r1.63 -r1.67
---- src/networks/gnutella/gnutellaInteractive.ml 5 Sep 2006 15:32:17 -0000 1.63
-+++ src/networks/gnutella/gnutellaInteractive.ml 12 Nov 2006 12:44:24 -0000 1.67
-@@ -77,8 +77,8 @@
- if file_state file = FileDownloading then
- GnutellaServers.really_recover_file file
-
--let download_file r =
-- let file = GnutellaServers.really_download_file r in
-+let download_file r user =
-+ let file = GnutellaServers.really_download_file r user in
- recover_file file;
- as_file file
-
-@@ -219,6 +219,7 @@
- [
- !!client_port, "client_port TCP+UDP";
- ]);
-+ network.op_network_porttest_result <- (fun _ -> PorttestNotAvailable);
- network.op_network_share <- (fun fullname codedname size ->
- (*
- lprintf "*************** op_network_share %s\n
-@@ -241,8 +242,8 @@
- end
- );
- (* TODO RESULT *)
-- network.op_network_download <- (fun r ->
-- result_download r
-+ network.op_network_download <- (fun r user ->
-+ result_download r user
- )
-
- let file_num file =
-@@ -288,7 +289,7 @@
- module P = GuiTypes
-
- let _ =
-- file_ops.op_file_print_html <- (fun file buf -> ());
-+ file_ops.op_file_print <- (fun file buf -> ());
- file_ops.op_file_cancel <- (fun file ->
- CommonSwarming.remove_swarmer file.file_swarmer;
- file.file_swarmer <- None;
-@@ -370,7 +371,7 @@
- List2.tail_map (fun s -> as_server s.server_server)
- !connected_servers
- );
-- network.op_network_parse_url <- (fun url ->
-+ network.op_network_parse_url <- (fun url user ->
- match String2.split (String.escaped url) '|' with
- | "gnut://" :: "server" :: ip :: port :: _ ->
- let ip = Ip.addr_of_string ip in
-@@ -402,7 +403,7 @@
- (* Start a download for this file *)
- let rs = new_result name size [] uids [] in
- let r = IndexedResults.get_result rs in
-- let file = download_file r in
-+ let file = download_file r user in
- CommonInteractive.start_download file;
- "started Gnutella download", true
- end
-Index: src/networks/gnutella/gnutellaServers.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/gnutella/gnutellaServers.ml,v
-retrieving revision 1.28
-retrieving revision 1.29
-diff -u -r1.28 -r1.29
---- src/networks/gnutella/gnutellaServers.ml 19 May 2006 23:43:55 -0000 1.28
-+++ src/networks/gnutella/gnutellaServers.ml 19 Sep 2006 17:07:43 -0000 1.29
-@@ -678,14 +678,14 @@
- (* *)
- (*************************************************************************)
-
--let really_download_file (r : result_info) =
-+let really_download_file (r : result_info) user =
- if !verbose then
- lprintf "download_file\n";
- let file_temp = match r.result_uids with
- [] -> assert false
- | uid :: _ -> Uid.to_file_string uid in
- let file = new_file file_temp
-- (List.hd r.result_names) r.result_size r.result_uids in
-+ (List.hd r.result_names) r.result_size r.result_uids user in
- if !verbose then
- lprintf "DOWNLOAD FILE %s\n" file.file_name;
- if not (List.memq file !current_files) then begin
-Index: src/networks/opennap/opennapClients.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/opennap/opennapClients.ml,v
-retrieving revision 1.10
-retrieving revision 1.11
-diff -u -r1.10 -r1.11
---- src/networks/opennap/opennapClients.ml 10 Apr 2006 19:16:36 -0000 1.10
-+++ src/networks/opennap/opennapClients.ml 12 Nov 2006 12:36:14 -0000 1.11
-@@ -69,8 +69,8 @@
- (try file_completed (as_file file.file_file)
- with e ->
- lprintf "Exception %s in file completed"
-- (Printexc2.to_string e)
-- ; lprint_newline ());
-+ (Printexc2.to_string e);
-+ lprint_newline ());
- current_files := List2.removeq file !current_files;
- old_files =:= (file.file_name, file_size file) :: !!old_files;
- List.iter (fun c ->
-@@ -357,4 +357,4 @@
- lprintf "Exception %s while init limewire server"
- (Printexc2.to_string e);
- lprint_newline ()
--
-\ No newline at end of file
-+
-Index: src/networks/opennap/opennapInteractive.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/opennap/opennapInteractive.ml,v
-retrieving revision 1.25
-retrieving revision 1.26
-diff -u -r1.25 -r1.26
---- src/networks/opennap/opennapInteractive.ml 5 Sep 2006 14:15:20 -0000 1.25
-+++ src/networks/opennap/opennapInteractive.ml 1 Oct 2006 17:54:00 -0000 1.26
-@@ -241,6 +241,7 @@
- [
- !!client_port, "client_port TCP";
- ]);
-+ network.op_network_porttest_result <- (fun _ -> PorttestNotAvailable);
-
- network.op_network_recover_temp <- (fun s -> ());
-
-Index: src/networks/opennap/opennapProtocol.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/opennap/opennapProtocol.ml,v
-retrieving revision 1.4
-retrieving revision 1.5
-diff -u -r1.4 -r1.5
---- src/networks/opennap/opennapProtocol.ml 16 Oct 2005 20:42:54 -0000 1.4
-+++ src/networks/opennap/opennapProtocol.ml 12 Nov 2006 12:42:55 -0000 1.5
-@@ -771,7 +771,7 @@
- end
-
- module Msg = struct
-- type t = ()
-+ type t = unit
-
- let parse s = ()
-
-Index: src/networks/soulseek/slskInteractive.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/networks/soulseek/slskInteractive.ml,v
-retrieving revision 1.23
-retrieving revision 1.24
-diff -u -r1.23 -r1.24
---- src/networks/soulseek/slskInteractive.ml 5 Sep 2006 14:15:20 -0000 1.23
-+++ src/networks/soulseek/slskInteractive.ml 1 Oct 2006 17:54:00 -0000 1.24
-@@ -182,6 +182,7 @@
-
- let _ =
- network.op_network_ports <- (fun _ -> []);
-+ network.op_network_porttest_result <- (fun _ -> PorttestNotAvailable);
- network.op_network_recover_temp <- (fun s -> ());
- network.op_network_load_complex_options <- (fun _ -> ());
- network.op_network_download <- (fun r ->
-Index: src/utils/cdk/filename2.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/utils/cdk/filename2.ml,v
-retrieving revision 1.5
-retrieving revision 1.6
-diff -u -r1.5 -r1.6
---- src/utils/cdk/filename2.ml 20 Jul 2006 15:30:21 -0000 1.5
-+++ src/utils/cdk/filename2.ml 31 Oct 2006 15:40:06 -0000 1.6
-@@ -196,7 +196,7 @@
- let sys_checked_name =
- if Autoconf.windows then
- windows_compliant name
-- else if Autoconf.system = "macosx" then
-+ else if Autoconf.system = "macos" then
- macosx_compliant name
- else
- posix_compliant name in
-Index: src/utils/cdk/printf2.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/utils/cdk/printf2.ml,v
-retrieving revision 1.20
-retrieving revision 1.21
-diff -u -r1.20 -r1.21
---- src/utils/cdk/printf2.ml 24 Jul 2006 20:15:16 -0000 1.20
-+++ src/utils/cdk/printf2.ml 9 Nov 2006 21:32:27 -0000 1.21
-@@ -395,3 +395,6 @@
-
- let html_mods_cntr_init () =
- html_mods_counter := true
-+
-+let print_plural_s v =
-+ if v > 1 then "s" else ""
-Index: src/utils/cdk/printf2.mli
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/utils/cdk/printf2.mli,v
-retrieving revision 1.8
-retrieving revision 1.9
-diff -u -r1.8 -r1.9
---- src/utils/cdk/printf2.mli 24 Jul 2006 20:15:16 -0000 1.8
-+++ src/utils/cdk/printf2.mli 9 Nov 2006 21:32:27 -0000 1.9
-@@ -56,4 +56,4 @@
- val html_mods_td : Buffer.t -> (string * string * string) list -> unit
- val html_mods_cntr_init : unit -> unit
- val html_mods_cntr : unit -> int
--
-+val print_plural_s : int -> string
-Index: src/utils/lib/CryptoPP.cc
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/utils/lib/CryptoPP.cc,v
-retrieving revision 1.5
-retrieving revision 1.6
-diff -u -r1.5 -r1.6
---- src/utils/lib/CryptoPP.cc 2 Dec 2005 12:01:44 -0000 1.5
-+++ src/utils/lib/CryptoPP.cc 21 Oct 2006 20:01:23 -0000 1.6
-@@ -9515,6 +9515,8 @@
- static byte m_publicKey[MAXPUBKEYSIZE+1];
- static unsigned long m_publicKeyLen = 0;
-
-+void cc_lprintf_nl(const char * msg);
-+
- void crypto_exit () {
- if (s_signer) {
- delete (Signer*) s_signer;
-@@ -9539,7 +9541,9 @@
- buf[myString.size()] = 0;
-
- } catch(const CryptoPP::Exception& e) {
-- std::cerr << "createKey: " << e.what() << std::endl;
-+ char buf[256]="[CryptoPP] createKey: ";
-+ strcat(buf, e.what());
-+ cc_lprintf_nl(buf);
- }
-
- }
-@@ -9570,7 +9574,9 @@
- result = m_publicKeyLen;
-
- } catch(const CryptoPP::Exception& e) {
-- std::cerr << "loadKey: " << e.what() << std::endl;
-+ char buf[256]="[CryptoPP] loadKey: ";
-+ strcat(buf, e.what());
-+ cc_lprintf_nl(buf);
- }
-
- return result;
-@@ -9585,7 +9591,7 @@
-
-
- if (s_signer == NULL) {
-- std::cerr << "createSignature: No signer" << std::endl;
-+ cc_lprintf_nl("createSignature: No signer");
- return result;
- }
-
-@@ -9612,7 +9618,9 @@
- result = aSink.TotalPutLength();
-
- } catch(const CryptoPP::Exception& e) {
-- std::cerr << "createSignature: " << e.what() << std::endl;
-+ char buf[256]="[CryptoPP] createSignature: ";
-+ strcat(buf, e.what());
-+ cc_lprintf_nl(buf);
- }
-
- return result;
-@@ -9640,11 +9648,12 @@
- PokeUInt32(bArray+m_publicKeyLen+4,ip);
- PokeUInt8(bArray+m_publicKeyLen+4+4,ipType);
- }
--
- result = pubKey.VerifyMessage(bArray, m_publicKeyLen+4+extra, sig, sigLen);
-
- } catch(const CryptoPP::Exception& e) {
-- std::cerr << "verifySignature: " << e.what() << std::endl;
-+ char buf[256]="[CryptoPP] verifySignature: ";
-+ strcat(buf, e.what());
-+ cc_lprintf_nl(buf);
- }
-
- return result ? 1 : 0;
-Index: src/utils/lib/CryptoPP_stubs.c
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/utils/lib/CryptoPP_stubs.c,v
-retrieving revision 1.2
-retrieving revision 1.3
-diff -u -r1.2 -r1.3
---- src/utils/lib/CryptoPP_stubs.c 29 Jan 2006 19:50:33 -0000 1.2
-+++ src/utils/lib/CryptoPP_stubs.c 21 Oct 2006 20:01:23 -0000 1.3
-@@ -17,10 +17,6 @@
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
--#include <string.h>
--#include <caml/mlvalues.h>
--#include <caml/alloc.h>
--
- #include "CryptoPP_stubs.h"
-
-
-@@ -87,3 +83,11 @@
- ml_verifySignature_bytecode(value *argv, int argn) {
- return ml_verifySignature(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6]);
- }
-+
-+void cc_lprintf_nl(const char * msg)
-+{
-+ static value * caml_func = NULL;
-+ if (caml_func == NULL) caml_func = caml_named_value("ml_lprintf_nl");
-+ caml_callback(*caml_func, caml_copy_string(msg));
-+}
-+
-Index: src/utils/lib/CryptoPP_stubs.h
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/utils/lib/CryptoPP_stubs.h,v
-retrieving revision 1.2
-retrieving revision 1.3
-diff -u -r1.2 -r1.3
---- src/utils/lib/CryptoPP_stubs.h 29 Jan 2006 19:50:33 -0000 1.2
-+++ src/utils/lib/CryptoPP_stubs.h 21 Oct 2006 20:01:23 -0000 1.3
-@@ -20,6 +20,11 @@
-
- #include "../../../config/config.h"
-
-+#include <string.h>
-+#include <caml/mlvalues.h>
-+#include <caml/alloc.h>
-+#include <caml/callback.h>
-+
- #if defined (HAVE_STDINT_H)
- #include <stdint.h>
- #endif
-Index: src/utils/lib/autoconf.ml.new.in
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/utils/lib/autoconf.ml.new.in,v
-retrieving revision 1.25
-retrieving revision 1.26
-diff -u -r1.25 -r1.26
---- src/utils/lib/autoconf.ml.new.in 10 Aug 2006 17:41:20 -0000 1.25
-+++ src/utils/lib/autoconf.ml.new.in 3 Oct 2006 15:23:08 -0000 1.26
-@@ -52,5 +52,3 @@
- let zlib__uncompress_string2 s = Zlib.uncompress_string2 s
- let zlib__compress_string s = Zlib.compress_string s
- let zlib__gzip_string s = Zlib.gzip_string s
--
--@TYPE_FORMAT@
-Index: src/utils/lib/charset.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/utils/lib/charset.ml,v
-retrieving revision 1.7
-retrieving revision 1.9
-diff -u -r1.7 -r1.9
---- src/utils/lib/charset.ml 14 Sep 2006 17:40:29 -0000 1.7
-+++ src/utils/lib/charset.ml 8 Oct 2006 14:12:13 -0000 1.9
-@@ -172,7 +172,7 @@
- (**********************************************************************************)
-
- (* taken from camomile *)
--(* $Id: charset.ml,v 1.7 2006/09/14 17:40:29 spiralvoice Exp $ *)
-+(* $Id: charset.ml,v 1.9 2006/10/08 14:12:13 spiralvoice Exp $ *)
- (* Copyright 2002, 2003 Yamagata Yoriyuki. distributed with LGPL *)
-
- let utf8_look s i =
-@@ -254,7 +254,7 @@
- (**********************************************************************************)
-
- (* taken from camomile *)
--(* $Id: charset.ml,v 1.7 2006/09/14 17:40:29 spiralvoice Exp $ *)
-+(* $Id: charset.ml,v 1.9 2006/10/08 14:12:13 spiralvoice Exp $ *)
- (* Copyright 2002, 2003 Yamagata Yoriyuki. distributed with LGPL *)
-
- let rec length_aux s c i =
-@@ -281,7 +281,7 @@
-
-
- (* taken from camomile *)
--(* $Id: charset.ml,v 1.7 2006/09/14 17:40:29 spiralvoice Exp $ *)
-+(* $Id: charset.ml,v 1.9 2006/10/08 14:12:13 spiralvoice Exp $ *)
- (* Copyright 2002, 2003 Yamagata Yoriyuki. distributed with LGPL *)
-
- external uint_code : uchar -> int = "%identity"
-@@ -1810,6 +1810,8 @@
- (* *)
- (**********************************************************************************)
-
-+let conversion_enabled = ref true
-+
- let convert ~from_charset ~to_charset s =
- if s <> "" then begin
- let t = charset_to_string to_charset in
-@@ -1817,6 +1819,17 @@
- convert_string s t f
- end else s
-
-+let safe_convert enc s =
-+ match enc with
-+ "" -> s
-+ | enc ->
-+ try
-+ convert
-+ ~from_charset: (charset_from_string enc)
-+ ~to_charset: (charset_from_string "UTF-8")
-+ s
-+ with _ -> s
-+
- (**********************************************************************************)
- (* *)
- (* slow_encode_from_utf8 *)
-@@ -1898,7 +1911,7 @@
- (**********************************************************************************)
-
- let to_locale s =
-- if s = ""
-+ if s = "" || not !conversion_enabled
- then s
- else begin
- let s = to_utf8 s in
-Index: src/utils/lib/charset.mli
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/utils/lib/charset.mli,v
-retrieving revision 1.3
-retrieving revision 1.5
-diff -u -r1.3 -r1.5
---- src/utils/lib/charset.mli 1 Aug 2005 20:09:13 -0000 1.3
-+++ src/utils/lib/charset.mli 8 Oct 2006 14:12:14 -0000 1.5
-@@ -141,6 +141,7 @@
- (** [convert ~from_charset ~to_charset s]
- raise CharsetError if the string s is not entirely convertible. *)
- val convert : from_charset : charset -> to_charset : charset -> string -> string
-+val safe_convert: string -> string -> string
-
- (** [is_utf8 s]
- returns TRUE if s is a valid UTF-8, otherwise returns FALSE.
-@@ -171,3 +172,4 @@
-
- val default_language : string
- val locstr : string
-+val conversion_enabled : bool ref
-Index: src/utils/lib/gettext.ml4
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/utils/lib/gettext.ml4,v
-retrieving revision 1.8
-retrieving revision 1.9
-diff -u -r1.8 -r1.9
---- src/utils/lib/gettext.ml4 24 Jul 2006 20:12:32 -0000 1.8
-+++ src/utils/lib/gettext.ml4 19 Nov 2006 23:04:59 -0000 1.9
-@@ -20,6 +20,14 @@
- open Printf2
- open Autoconf
-
-+let log_prefix = "[Gettext]"
-+
-+let lprintf_nl fmt =
-+ lprintf_nl2 log_prefix fmt
-+
-+let lprintf_n fmt =
-+ lprintf2 log_prefix fmt
-+
- type expected_types =
- Type_int
- | Type_char
-@@ -291,7 +299,7 @@
- !verified.(index) <- true;
- true
- end else begin
-- lprintf "Bad format for %s\n" translated;
-+ lprintf_nl "Bad format for %s\n" translated;
- save_strings_file := true;
- !translation.(index) <- no_translation;
- false
-@@ -359,7 +367,7 @@
-
- save_strings_file := false)
- with e ->
-- lprintf "Gettext.save_strings: Error %s\n\n"
-+ lprintf_nl "save_strings: Error %s"
- (Printexc2.to_string e)
- open Genlex2
-
-@@ -404,7 +412,7 @@
- parse_file stream
- with e ->
- strings_file_error := true;
-- lprintf "Gettext.set_strings_file: Exception %s in %s at pos %d\n"
-+ lprintf_nl "set_strings_file: Exception %s in %s at pos %d"
- (Printexc2.to_string e) filename (Stream.count s))
- with e ->
- save_strings_file := true);
-@@ -420,7 +428,7 @@
- let strings = Hashtbl.create 111 in
-
- let translate1 s0 s1 =
-- lprintf "translate0 %s\n" s0;
-+ lprintf_nl "translate0 %s" s0;
- Hashtbl.add strings s0 s1
- in
-
-@@ -444,18 +452,18 @@
- parse_file stream
- with e ->
- strings_file_error := true;
-- lprintf "Gettext.set_strings_file: Exception %s in %s at pos %d\n"
-+ lprintf_nl "set_strings_file: Exception %s in %s at pos %d"
- (Printexc2.to_string e) f1 (Stream.count s))
- with e ->
- save_strings_file := true;
-- lprintf "Gettext.set_strings_file: no message file found. Creating one\n");
-+ lprintf_nl "set_strings_file: no message file found. Creating one");
-
- let translate2 s0 s1 =
- try
-- lprintf "translate2 %s\n" s0;
-+ lprintf_nl "translate2 %s" s0;
- let s0 = Hashtbl.find strings s0 in
- translate "Former Translation" s0 s1
-- with _ -> lprintf "No translation for %s\n" s0
-+ with _ -> lprintf_nl "No translation for %s" s0
- in
-
- let rec parse_file = (parser
-@@ -477,11 +485,11 @@
- parse_file stream
- with e ->
- strings_file_error := true;
-- lprintf "Gettext.set_strings_file: Exception %s in %s at pos %d\n"
-+ lprintf_nl "set_strings_file: Exception %s in %s at pos %d"
- (Printexc2.to_string e) f2 (Stream.count s))
- with e ->
- save_strings_file := true;
-- lprintf "Gettext.set_strings_file: no message file found. Creating one\n"
-+ lprintf_nl "set_strings_file: no message file found. Creating one"
-
-
- with _ -> ()
-Index: src/utils/lib/int64ops.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/utils/lib/int64ops.ml,v
-retrieving revision 1.3
-retrieving revision 1.4
-diff -u -r1.3 -r1.4
---- src/utils/lib/int64ops.ml 15 Jul 2006 11:52:54 -0000 1.3
-+++ src/utils/lib/int64ops.ml 25 Oct 2006 11:14:02 -0000 1.4
-@@ -50,3 +50,12 @@
- let round_up64 x y =
- ((Int64.pred (x ++ y)) // y) ** y
-
-+let int64_to_human_readable size =
-+ if Int64.to_float size >= 1024. && Int64.to_float size < 1048576. then
-+ (Printf.sprintf "%5.1f%s" (Int64.to_float size /. 1024.) ("kb") )
-+ else if size >= Int64.of_float 1048576. && Int64.to_float size < 1073741824. then
-+ (Printf.sprintf "%5.1f%s" (Int64.to_float size /. 1048576.) ("mb") )
-+ else if size >= Int64.of_float 1073741824. then
-+ (Printf.sprintf "%5.1f%s" (Int64.to_float size /. 1073741824.) ("gb") )
-+ else
-+ (Printf.sprintf "%8s%s" (Int64.to_string size) ("b") )
-Index: src/utils/lib/misc.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/utils/lib/misc.ml,v
-retrieving revision 1.6
-retrieving revision 1.7
-diff -u -r1.6 -r1.7
---- src/utils/lib/misc.ml 3 Apr 2006 20:50:09 -0000 1.6
-+++ src/utils/lib/misc.ml 25 Oct 2006 11:12:38 -0000 1.7
-@@ -49,6 +49,10 @@
- let s = string_of_int num in
- int_of_string ("0b" ^ s)
-
-+let percentage_of_ints v percent =
-+ int_of_float (
-+ (float_of_int v *. float_of_int percent /. 100.0) +. 0.5)
-+
- let zip_extract_entry ifile e =
- if e.Zip.is_directory then begin
- try
-Index: src/utils/lib/options.ml4
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/utils/lib/options.ml4,v
-retrieving revision 1.21
-retrieving revision 1.22
-diff -u -r1.21 -r1.22
---- src/utils/lib/options.ml4 31 May 2006 22:26:05 -0000 1.21
-+++ src/utils/lib/options.ml4 21 Oct 2006 19:35:54 -0000 1.22
-@@ -514,6 +514,13 @@
- let int_to_value i = IntValue (Int64.of_int i)
- let int64_to_value i = IntValue i
-
-+let percent_to_value i = IntValue (Int64.of_int i)
-+let value_to_percent v =
-+ match Int64.to_int (value_to_int64 v) with
-+ v when v < 0 -> 0
-+ | v when v > 100 -> 100
-+ | v -> v
-+
- (* The Pervasives version is too restrictive *)
- let bool_of_string s =
- match String.lowercase s with
-@@ -729,6 +736,7 @@
-
- let int_option = define_option_class "Int" value_to_int int_to_value
- let int64_option = define_option_class "Int64" value_to_int64 int64_to_value
-+let percent_option = define_option_class "Int" value_to_percent percent_to_value
-
-
- let bool_option = define_option_class "Bool" value_to_bool bool_to_value
-Index: src/utils/lib/options.mli
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/utils/lib/options.mli,v
-retrieving revision 1.9
-retrieving revision 1.10
-diff -u -r1.9 -r1.10
---- src/utils/lib/options.mli 31 May 2006 22:26:05 -0000 1.9
-+++ src/utils/lib/options.mli 21 Oct 2006 19:35:54 -0000 1.10
-@@ -90,6 +90,7 @@
- val font_option : string option_class
- val int_option : int option_class
- val int64_option : int64 option_class
-+val percent_option : int option_class
- val bool_option : bool option_class
- val float_option : float option_class
- val path_option : string list option_class
-@@ -157,6 +158,8 @@
- val int_to_value : int -> option_value
- val value_to_int64 : option_value -> int64
- val int64_to_value : int64 -> option_value
-+val value_to_percent : option_value -> int
-+val percent_to_value : int -> option_value
- val bool_of_string : string -> bool
- val value_to_bool : option_value -> bool
- val bool_to_value : bool -> option_value
-Index: src/utils/net/basicSocket.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/utils/net/basicSocket.ml,v
-retrieving revision 1.30
-retrieving revision 1.31
-diff -u -r1.30 -r1.31
---- src/utils/net/basicSocket.ml 17 May 2006 08:52:44 -0000 1.30
-+++ src/utils/net/basicSocket.ml 21 Nov 2006 22:34:34 -0000 1.31
-@@ -204,15 +204,9 @@
- let minf (x: float) (y: float) =
- if x > y then y else x
-
--let mini (x: int) (y: int) =
-- if x > y then y else x
--
- let maxf (x: float) (y: float) =
- if x < y then y else x
-
--let maxi (x: int) (y: int) =
-- if x < y then y else x
--
- (*************************************************************************)
- (* *)
- (* Some functions *)
-Index: src/utils/net/basicSocket.mli
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/utils/net/basicSocket.mli,v
-retrieving revision 1.15
-retrieving revision 1.16
-diff -u -r1.15 -r1.16
---- src/utils/net/basicSocket.mli 28 Oct 2005 08:21:49 -0000 1.15
-+++ src/utils/net/basicSocket.mli 21 Nov 2006 22:34:34 -0000 1.16
-@@ -75,9 +75,7 @@
-
- val stats : Buffer.t -> t -> unit
-
--val mini : int -> int -> int
- val minf : float -> float -> float
--val maxi : int -> int -> int
- val maxf : float -> float -> float
-
- val set_allow_write : t -> bool ref -> unit
-Index: src/utils/net/http_client.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/utils/net/http_client.ml,v
-retrieving revision 1.33
-retrieving revision 1.35
-diff -u -r1.33 -r1.35
---- src/utils/net/http_client.ml 30 May 2006 10:54:14 -0000 1.33
-+++ src/utils/net/http_client.ml 21 Nov 2006 22:34:34 -0000 1.35
-@@ -62,7 +62,7 @@
- lprintf_nl2 log_prefix fmt
-
- let basic_request = {
-- req_url = Url.of_string "http://www.mldonkey.net/";
-+ req_url = Url.of_string "http://www.mldonkey.org/";
- req_referer = None;
- req_save_to_file_time = 0.;
- req_request = GET;
-@@ -170,7 +170,7 @@
- let b = TcpBufferedSocket.buf sock in
- let end_pos = b.pos + b.len in
- let new_pos = end_pos - nread in
-- let new_pos = maxi 0 (new_pos - 1) in
-+ let new_pos = max 0 (new_pos - 1) in
- (*
- lprintf "received [%s]" (String.escaped
- (String.sub b.buf new_pos nread));
-@@ -380,7 +380,7 @@
- if nread > 0 then begin
- let left =
- if maxlen >= 0 then
-- mini (maxlen - !file_size) nread
-+ min (maxlen - !file_size) nread
- else nread
- in
- Buffer.add_string file_buf (String.sub buf.buf buf.pos left);
-@@ -452,7 +452,7 @@
- if nread > 0 then begin
- let left =
- if maxlen >= 0 then
-- mini (maxlen - !file_size) nread
-+ min (maxlen - !file_size) nread
- else nread
- in
- Buffer.add_string file_buf (String.sub buf.buf buf.pos left);
-Index: src/utils/net/http_server.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/utils/net/http_server.ml,v
-retrieving revision 1.33
-retrieving revision 1.36
-diff -u -r1.33 -r1.36
---- src/utils/net/http_server.ml 27 Jul 2006 21:45:06 -0000 1.33
-+++ src/utils/net/http_server.ml 21 Nov 2006 22:34:34 -0000 1.36
-@@ -95,6 +95,7 @@
- type error_reason =
- | Blocked
- | Not_allowed
-+| Url_not_found of string
-
- type header =
- Unknown of string * string
-@@ -234,11 +235,13 @@
- | "403" -> "Forbidden",
- (match reason with
- Some Not_allowed -> Printf.sprintf
--"<p>Connection from %s rejected (see downloads.ini, <a href=\"http://mldonkey.sourceforge.net/Allowed_ips\">allowed_ips</a>)</p>\n"
-+"<p>Connection from %s rejected (see downloads.ini, <a href=\"http://mldonkey.sourceforge.net/Allowed_ips\">allowed_ips</a>)</p>"
- from_ip
- | Some Blocked -> Printf.sprintf "IP %s is blocked, its part of the used IP blocklist " from_ip
-- | None -> "")
-- | _ -> Printf.sprintf "Unknown %s" code, ""
-+ | _ -> "")
-+ | "404" -> "Not found", Printf.sprintf "The requested URL %swas not found on this server."
-+ (match reason with Some (Url_not_found url) -> url ^ " " | _ -> "")
-+ | _ -> Printf.sprintf "Unknown error %s" code, ""
- in
- let reject_message = Printf.sprintf
- "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>
-@@ -250,7 +253,8 @@
- Printf.sprintf
- "HTTP/1.1 %s %s\nMLDonkey/%s\nConnection: close
- Content-Type: text/html; charset=iso-8859-1\nContent-length: %d\r\n"
-- code error_text Autoconf.current_version (String.length reject_message), reject_message
-+ code error_text Autoconf.current_version (String.length reject_message), reject_message,
-+ Printf.sprintf "%s %s" code error_text
-
- let parse_head sock s =
- let h = split_head s in
-@@ -681,13 +685,6 @@
- at_write_end buf.fd_task shutdown
- *)
-
--let need_auth r name =
-- r.reply_head <- "401 Unauthorized";
-- r.reply_headers <- [
-- "Connection", "close";
-- "WWW-Authenticate", Printf.sprintf "Basic realm=\"%s\"" name
-- ]
--
- (*
- let simple_give_auth psread pswrite request =
- try
-@@ -788,7 +785,7 @@
- let b = TcpBufferedSocket.buf sock in
- let end_pos = b.pos + b.len in
- let new_pos = end_pos - nread in
-- let new_pos = maxi 0 (new_pos - 1) in
-+ let new_pos = max 0 (new_pos - 1) in
- (* lprintf "received [%s]\n" (String.escaped
- (String.sub b.buf new_pos nread)); - log commented out *)
- let rec iter i =
-@@ -860,7 +857,7 @@
- (if ip_is_blocked from_ip then "IP is blocked" else "see allowed_ips setting");
- let token = create_token unlimited_connection_manager in
- let sock = TcpBufferedSocket.create_simple token "http connection" s in
-- let s1,s2 = error_page "403"
-+ let s1,s2,_ = error_page "403"
- (Ip.to_string from_ip)
- (string_of_int from_port)
- (Ip.to_string (TcpBufferedSocket.my_ip sock))
-Index: src/utils/net/http_server.mli
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/utils/net/http_server.mli,v
-retrieving revision 1.9
-retrieving revision 1.10
-diff -u -r1.9 -r1.10
---- src/utils/net/http_server.mli 27 Jul 2006 21:45:06 -0000 1.9
-+++ src/utils/net/http_server.mli 21 Oct 2006 19:35:09 -0000 1.10
-@@ -17,7 +17,7 @@
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *)
- type auth = No_auth | Read_auth | Write_auth
--type error_reason = Blocked | Not_allowed
-+type error_reason = Blocked | Not_allowed | Url_not_found of string
- and header =
- Unknown of string * string
- | Referer of Url.url
-@@ -67,7 +67,6 @@
- }
-
- val create : config -> TcpServerSocket.t
--val need_auth : request -> string -> unit
- val html_escaped : string -> string
- val html_real_escaped : string -> string
-
-@@ -79,4 +78,4 @@
-
- val request_range : request -> int64 * (int64 option)
- val parse_range : string -> int64 * int64 option * int64 option
--val error_page : string -> string -> string -> string -> string -> error_reason option -> string * string
-+val error_page : string -> string -> string -> string -> string -> error_reason option -> string * string * string
-Index: src/utils/net/ip_set.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/utils/net/ip_set.ml,v
-retrieving revision 1.29
-retrieving revision 1.31
-diff -u -r1.29 -r1.31
---- src/utils/net/ip_set.ml 27 Jul 2006 21:45:06 -0000 1.29
-+++ src/utils/net/ip_set.ml 20 Nov 2006 22:34:40 -0000 1.31
-@@ -259,14 +259,14 @@
- find_in_zip q in
- find_in_zip filenames_list
- with e ->
-- lprintf_nl "Exception %s while extracting %s from %s"
-+ lprintf_nl "Exception %s while extracting %s from %s"
- (Printexc2.to_string e)
- (String.concat "/" filenames_list)
- filename;
-- lprintf_nl "One of the mentioned files has to be present in the zip file";
-+ lprintf_nl "One of the mentioned files has to be present in the zip file";
- bl_empty)
- with e ->
-- lprintf_nl "Exception %s while opening %s"
-+ lprintf_nl "Exception %s while opening %s"
- (Printexc2.to_string e)
- filename;
- bl_empty)
-@@ -281,12 +281,12 @@
- let s = Misc.archive_extract filename filetype in
- load_merge bl_empty s true
- with e ->
-- lprintf_nl "Exception %s while extracting from %s"
-+ lprintf_nl "Exception %s while extracting from %s"
- (Printexc2.to_string e) filename;
- bl_empty)
- | ".tar.bz2" | ".p2p.tar.bz2" | ".dat.tar.bz2"
- | ".tar.gz" | ".p2p.tar.gz" | ".dat.tar.gz" ->
-- lprintf_nl "tar files are not (yet) supported, please untar %s" filename;
-+ lprintf_nl "tar files are not (yet) supported, please untar %s" filename;
- bl_empty
- | _ -> load_merge bl_empty filename false
- else
-@@ -296,6 +296,7 @@
- end
-
- let of_list l =
-+ bl_optimize (
- List.fold_left (fun acc r ->
- let range =
- match r with
-@@ -314,7 +315,7 @@
- blocking_end = Ip.broadcast_address ip mask }
- in
- add_range acc range
-- ) BL_Empty l
-+ ) BL_Empty l)
-
- let print_list buf bl =
- let rec print_list_aux bl =
-Index: src/utils/net/tcpBufferedSocket.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/utils/net/tcpBufferedSocket.ml,v
-retrieving revision 1.43
-retrieving revision 1.45
-diff -u -r1.43 -r1.45
---- src/utils/net/tcpBufferedSocket.ml 3 Apr 2006 20:50:09 -0000 1.43
-+++ src/utils/net/tcpBufferedSocket.ml 21 Nov 2006 22:34:34 -0000 1.45
-@@ -319,7 +319,7 @@
- forecast_download t 0
-
- let best_packet_size nbytes =
-- let nbytes = maxi nbytes !minimal_packet_size in
-+ let nbytes = max nbytes !minimal_packet_size in
- let nip_packets = 1 + nbytes / !mtu_packet_size in
- let headers = nip_packets * !ip_packet_size in
- let nframes = 1 + (nbytes + headers) / packet_frame_size in
-@@ -411,7 +411,7 @@
- lprintf "[TCP_BS]: BUFFER OVERFLOW %d+%d> %d " b.len len b.max_buf_size ;
-
- lprintf "MESSAGE: [";
-- for i = pos1 to pos1 + (mini len 20) - 1 do
-+ for i = pos1 to pos1 + (min len 20) - 1 do
- lprintf "(%d)" (int_of_char s.[i]);
- done;
- if len > 20 then lprintf "...";
-@@ -422,7 +422,7 @@
- socket !!! *)
- end
- else
-- let new_len = mini (maxi (2 * max_len) (b.len + len)) b.max_buf_size in
-+ let new_len = min (max (2 * max_len) (b.len + len)) b.max_buf_size in
- (* if t.monitored then
- (lprintf "Allocate new for %d\n" len; ); *)
- let new_buf = String.create new_len in
-@@ -631,8 +631,8 @@
- buf_len - b.len
- )
- else
-- let new_len = mini
-- (maxi
-+ let new_len = min
-+ (max
- (2 * buf_len) (b.len + min_read_size)) b.max_buf_size
- in
- let new_buf = String.create new_len in
-@@ -645,7 +645,7 @@
- in
- b.buf, b.pos+b.len, can_write_in_buffer
- in
-- let can_read = mini max_len buffer_len in
-+ let can_read = min max_len buffer_len in
- if can_read > 0 then
- let old_len = b.len in
- let nread = try
-@@ -684,8 +684,8 @@
- end else
- b.len <- b.len + nread;
- (* lprintf " %d\n" nread; *)
-- b.min_buf_size <- mini b.max_buf_size (
-- maxi (nread + nread / 2) min_read_size);
-+ b.min_buf_size <- min b.max_buf_size (
-+ max (nread + nread / 2) min_read_size);
-
- (*
- if nread = can_read then begin
-@@ -804,12 +804,9 @@
- | Some bc ->
- if bc.total_bytes = 0 then
- can_write_handler t sock t.wbuf.len
-- else begin
--(* lprintf "DELAYED\n"; *)
-- if bc.remaining_bytes > 0 then begin
-- bc.connections <- t :: bc.connections;
-- bc.nconnections <- t.write_power + bc.nconnections
-- end
-+ else begin
-+ bc.connections <- t :: bc.connections;
-+ bc.nconnections <- t.write_power + bc.nconnections
- end
- end
-
-@@ -1680,9 +1677,9 @@
-
- List.iter (fun t ->
- if bc.remaining_bytes > 0 then
-- let nconnections = maxi bc.nconnections 1 in
-- let can_read = maxi 1 (bc.remaining_bytes / nconnections) in
-- let can_read = maxi !ip_packet_size (can_read * t.read_power) in
-+ let nconnections = max bc.nconnections 1 in
-+ let can_read = max 1 (bc.remaining_bytes / nconnections) in
-+ let can_read = max !ip_packet_size (can_read * t.read_power) in
- (try
- (* lprintf "allow to read %d\n" can_read; *)
- can_read_handler t t.sock_in can_read
-@@ -1731,14 +1728,14 @@
- end;
- List.iter (fun t ->
- if bc.remaining_bytes > 0 then
-- let nconnections = maxi bc.nconnections 1 in
-- let can_write = maxi 1 (bc.remaining_bytes / nconnections) in
-+ let nconnections = max bc.nconnections 1 in
-+ let can_write = max 1 (bc.remaining_bytes / nconnections) in
- let can_write = best_packet_size (can_write * t.write_power)
- in
- let old_nwrite = t.nwrite in
- (try
- (* lprintf "WRITE\n"; *)
-- can_write_handler t t.sock_out (mini can_write t.wbuf.len)
-+ can_write_handler t t.sock_out (min can_write t.wbuf.len)
- with _ -> ());
- bc.remaining_bytes <- bc.remaining_bytes -
- t.nwrite + old_nwrite;
-@@ -1749,7 +1746,7 @@
- t.name (sock_num t.sock_out) (remaining_to_write t)
- end
- ) bc.connections;
--(* if bc.remaining_bytes > 0 then bc.allow_io := false; *)
-+(* if bc.remaining_bytes > 0 then bc.allow_io := false; *)
- end;
- if !verbose_bandwidth > 2 then begin
-
-Index: src/utils/net/tcpBufferedSocket.mli
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/utils/net/tcpBufferedSocket.mli,v
-retrieving revision 1.15
-retrieving revision 1.16
-diff -u -r1.15 -r1.16
---- src/utils/net/tcpBufferedSocket.mli 28 Jun 2005 22:45:57 -0000 1.15
-+++ src/utils/net/tcpBufferedSocket.mli 31 Oct 2006 15:41:55 -0000 1.16
-@@ -79,6 +79,9 @@
- val set_max_output_buffer : t -> int -> unit
- val can_write : t -> bool
- val can_write_len : t -> int -> bool
-+val register_download : t -> int -> unit
-+val register_upload : t -> int -> unit
-+val register_bytes : bandwidth_controler option -> int -> unit
-
- val set_monitored : t -> bool -> unit
- val monitored : t -> bool
-Index: src/utils/net/tcpClientSocket.ml
-===================================================================
-RCS file: src/utils/net/tcpClientSocket.ml
-diff -N src/utils/net/tcpClientSocket.ml
---- src/utils/net/tcpClientSocket.ml 6 Dec 2005 20:26:40 -0000 1.12
-+++ /dev/null 1 Jan 1970 00:00:00 -0000
-@@ -1,789 +0,0 @@
--(* Copyright 2001, 2002 b8_bavard, b8_fee_carabine, INRIA *)
--(*
-- This file is part of mldonkey.
--
-- mldonkey is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
--
-- mldonkey is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with mldonkey; if not, write to the Free Software
-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
--*)
--
--open Printf2
--open BasicSocket
--
--(* let _ = Unix2.init () *)
--
--type event =
-- WRITE_DONE
--| CAN_REFILL
--| BUFFER_OVERFLOW
--| READ_DONE of int
--| BASIC_EVENT of BasicSocket.event
--
--type buf = {
-- mutable buf : string;
-- mutable pos : int;
-- mutable len : int;
-- mutable max_buf_size:int;
-- }
--
--type t = {
-- mutable sock : BasicSocket.t;
-- mutable rbuf : buf;
-- mutable wfifo : string Fifo.t;
-- mutable wlen : int;
-- mutable wfbuf : buf;
-- mutable event_handler : handler;
-- mutable error : string;
-- mutable nread : int;
-- mutable nwrite : int;
-- mutable monitored : bool;
--
-- mutable read_control : bandwidth_controler option;
-- mutable write_control : bandwidth_controler option;
-- mutable write_power : int;
-- mutable read_power : int;
-- }
--
--and handler = t -> event -> unit
--
--and bandwidth_controler = {
-- mutable remaining_bytes : int;
-- mutable total_bytes : int;
-- mutable nconnections : int;
-- mutable connections : t list;
-- allow_io : bool ref;
-- mutable last_remaining : int;
-- mutable moved_bytes : int64;
-- }
--
--
--let tcp_uploaded_bytes = ref Int64.zero
--let tcp_downloaded_bytes = ref Int64.zero
--
--let nread t = t.nread
--
--let min_buffer_read = 500
--let min_read_size = min_buffer_read - 100
--
--let old_strings_size = 20
--let old_strings = Array.create old_strings_size ""
--let old_strings_len = ref 0
--
--let new_string () =
-- if !old_strings_len > 0 then begin
-- decr old_strings_len;
-- let s = old_strings.(!old_strings_len) in
-- old_strings.(!old_strings_len) <- "";
-- s
-- end else
-- String.create min_buffer_read
--
--let delete_string s =
-- if !old_strings_len < old_strings_size &&
-- String.length s = min_buffer_read then begin
-- old_strings.(!old_strings_len) <- s;
-- incr old_strings_len;
-- end
--
--let close t s =
--(*
-- if t.monitored then begin
-- lprintf "close with %s %s" t.error s; lprint_newline ();
--end;
--*)
-- begin
-- try
-- delete_string t.rbuf.buf;
-- t.rbuf.buf <- "";
-- t.wfbuf.buf <- "";
-- close t.sock (Printf.sprintf "%s after %d/%d" s t.nread t.nwrite)
-- with e ->
-- lprintf "Exception %s in TcpBufferedSocket.close\n"
-- (Printexc2.to_string e);
-- raise e
-- end
--
--let shutdown t s =
-- (*
-- if t.monitored then begin
-- lprintf "shutdown"; lprint_newline ();
--end;
-- *)
-- (try BasicSocket.shutdown t.sock s with e ->
-- lprintf "exception %s in shutdown\n" (Printexc2.to_string e));
-- (try close t s with e ->
-- lprintf "exception %s in shutdown\n" (Printexc2.to_string e))
--
--let buf_create max =
-- {
-- buf = "";
-- pos = 0;
-- len = 0;
-- max_buf_size = max;
-- }
--
--let error t = t.error
--
--
--let set_reader t f =
-- let old_handler = t.event_handler in
-- let handler t ev =
--(* if t.monitored then (lprintf "set_reader handler"; lprint_newline ()); *)
-- match ev with
-- READ_DONE nread ->
--(* lprintf "READ_DONE %d" nread; lprint_newline (); *)
-- f t nread
-- |_ -> old_handler t ev
-- in
-- t.event_handler <- handler
--
--let set_closer t f =
-- let old_handler = t.event_handler in
-- let handler t ev =
--(* if t.monitored then (lprintf "set_closer handler"; lprint_newline ()); *)
-- match ev with
-- BASIC_EVENT (CLOSED s) ->
--(* lprintf "READ_DONE %d" nread; lprint_newline (); *)
-- f t s
-- |_ -> old_handler t ev
-- in
-- t.event_handler <- handler
--
--
--let buf_used t nused =
-- let b = t.rbuf in
-- if nused = b.len then
-- ( b.len <- 0;
-- b.pos <- 0;
-- delete_string b.buf;
-- b.buf <- "";
-- )
-- else
-- (b.len <- b.len - nused; b.pos <- b.pos + nused)
--
--let set_handler t event handler =
-- let old_handler = t.event_handler in
-- let handler t ev =
--(* if t.monitored then (lprintf "set_handler handler"; lprint_newline ()); *)
-- if ev = event then
-- handler t
-- else
-- old_handler t ev
-- in
-- t.event_handler <- handler
--
--let set_refill t f =
-- set_handler t CAN_REFILL f;
-- if t.wlen = 0 then (try f t with _ -> ())
--
--let buf t = t.rbuf
--let sock t = t.sock
--
--let closed t = closed t.sock
--
--let buf_add t b s pos1 len =
-- let curpos = b.pos + b.len in
-- let max_len =
-- if b.buf = "" then
-- begin
-- b.buf <- new_string ();
-- min_buffer_read
-- end else
-- String.length b.buf in
-- if max_len - curpos < len then (* resize before blit *)
-- if b.len + len < max_len then (* just move to 0 *)
-- begin
-- String.blit b.buf b.pos b.buf 0 b.len;
-- String.blit s pos1 b.buf b.len len;
-- b.len <- b.len + len;
-- b.pos <- 0;
-- end
-- else
-- if b.len + len > b.max_buf_size then begin
-- lprintf "BUFFER OVERFLOW %d+%d> %d\n" b.len len b.max_buf_size ;
--
-- lprintf "MESSAGE [";
-- for i = pos1 to pos1 + (mini len 20) - 1 do
-- lprintf "(%d)" (int_of_char s.[i]);
-- done;
-- if len > 20 then lprintf "...";
-- lprintf "]\n";
--
-- t.event_handler t BUFFER_OVERFLOW;
-- end
-- else
-- let new_len = mini (maxi (2 * max_len) (b.len + len)) b.max_buf_size in
--(* if t.monitored then
-- (lprintf "Allocate new for %d" len; lprint_newline ()); *)
-- let new_buf = String.create new_len in
-- String.blit b.buf b.pos new_buf 0 b.len;
-- String.blit s pos1 new_buf b.len len;
-- b.len <- b.len + len;
-- b.pos <- 0;
-- if max_len = min_buffer_read then delete_string b.buf;
--(* if t.monitored then
-- (lprintf "new buffer allocated"; lprint_newline ()); *)
-- b.buf <- new_buf
-- else begin
-- String.blit s pos1 b.buf curpos len;
-- b.len <- b.len + len
-- end
--
--let write t s = ()
--let write_uniq t s = ()
--
-- (*
--let write t s pos1 len =
--(* lprintf "want_write %d" len; lprint_newline (); *)
-- if len > 0 && not (closed t) then
-- let pos2 = pos1 + len in
-- let b = t.wbuf in
-- let pos1 =
-- if b.len = 0 && (match t.write_control with
-- None ->
--(* lprintf "NO CONTROL"; lprint_newline (); *)
-- true
-- | Some bc ->
--(* lprintf "LIMIT %d" bc.total_bytes; lprint_newline (); *)
-- bc.total_bytes = 0)
-- then
-- try
--(* lprintf "try write %d" len; lprint_newline (); *)
-- let fd = fd t.sock in
-- let nw = Unix.write fd s pos1 len in
--(* if t.monitored then begin
-- lprintf "write: direct written %d" nw; lprint_newline ();
--end; *)
-- tcp_uploaded_bytes := !tcp_uploaded_bytes ++ (Int64.of_int nw);
-- (match t.write_control with
-- None -> ()
-- | Some bc ->
-- bc.moved_bytes <- bc.moved_bytes ++ (Int64.of_int nw));
-- t.nwrite <- t.nwrite + nw;
-- if nw = 0 then (close t "closed on write"; pos2) else
-- pos1 + nw
-- with
-- Unix.Unix_error ((Unix.EWOULDBLOCK | Unix.EAGAIN | Unix.ENOTCONN), _, _) -> pos1
-- | e ->
-- t.error <- Printf.sprintf "Write Error: %s" (Printexc2.to_string e);
-- close t t.error;
--
--(* lprintf "exce %s in read" (Printexc2.to_string e); lprint_newline (); *)
-- raise e
--
-- else pos1
-- in
-- if pos2 > pos1 then
-- let sock = t.sock in
-- must_write sock true;
-- buf_add t b s pos1 (pos2 - pos1)
--
--let write_string t s = write t s 0 (String.length s)
-- *)
--
--let dummy_sock = Obj.magic 0
--
--let exn_exit = Exit
--
--let can_read_handler t sock max_len =
-- let b = t.rbuf in
-- let curpos = b.pos + b.len in
-- let can_read =
-- if b.buf = "" then begin
-- b.buf <- new_string ();
-- min_buffer_read
-- end
-- else
-- if max_len - curpos < min_read_size then
-- if b.len + min_read_size > b.max_buf_size then
-- (
-- t.event_handler t BUFFER_OVERFLOW;
-- lprintf "[OVERFLOW] in %s" (info sock);
-- close t "buffer overflow";
-- raise exn_exit;
-- 0
-- )
-- else
-- if b.len + min_read_size < max_len then
-- (
-- String.blit b.buf b.pos b.buf 0 b.len;
-- b.pos <- 0;
-- max_len - b.len
-- )
-- else
-- let new_len = mini
-- (maxi
-- (2 * max_len) (b.len + min_read_size)) b.max_buf_size
-- in
-- let new_buf = String.create new_len in
-- String.blit b.buf b.pos new_buf 0 b.len;
-- b.pos <- 0;
-- b.buf <- new_buf;
-- new_len - b.len
-- else
-- max_len - curpos
-- in
-- let can_read = mini max_len can_read in
-- if can_read > 0 then
-- let nread = try
--(* lprintf "try read %d" can_read; lprint_newline ();*)
-- Unix.read (fd sock) b.buf (b.pos + b.len) can_read
-- with
-- Unix.Unix_error((Unix.EWOULDBLOCK | Unix.EAGAIN), _,_) as e -> raise e
-- | e ->
-- t.error <- Printf.sprintf "Can Read Error: %s" (Printexc2.to_string e);
-- close t t.error;
--
--(* lprintf "exce %s in read" (Printexc2.to_string e); lprint_newline (); *)
-- raise e
--
-- in
-- tcp_downloaded_bytes := !tcp_downloaded_bytes ++ (Int64.of_int nread);
-- (match t.read_control with
-- None -> () | Some bc ->
-- bc.moved_bytes <- bc.moved_bytes ++ (Int64.of_int nread));
--
-- t.nread <- t.nread + nread;
-- if nread = 0 then begin
-- close t "closed on read";
-- end else begin
-- let curpos = b.pos in
-- b.len <- b.len + nread;
-- try
--(* if t.monitored then
-- (lprintf "event handler READ DONE"; lprint_newline ()); *)
-- t.event_handler t (READ_DONE nread);
-- with
-- | e ->
--(* if t.monitored then
-- (lprintf "Exception in READ DONE"; lprint_newline ()); *)
-- t.error <- Printf.sprintf "READ_DONE Error: %s" (Printexc2.to_string e);
-- close t t.error;
--
--(* lprintf "exce %s in read" (Printexc2.to_string e); lprint_newline (); *)
-- raise e
-- end
--
--let can_write_handler t sock max_len =
-- (*
--(* if t.monitored then (
-- lprintf "CAN_WRITE (%d)" t.wbuf.len; lprint_newline ();
-- ); *)
-- let b = t.wbuf in
-- if b.len > 0 then
-- begin
-- try
--(* lprintf "try write %d/%d" max_len t.wbuf.len; lprint_newline (); *)
-- let fd = fd sock in
-- let nw = Unix.write fd b.buf b.pos max_len in
--
--(* if t.monitored then
--(lprintf "written %d" nw; lprint_newline ()); *)
-- tcp_uploaded_bytes := !tcp_uploaded_bytes ++ (Int64.of_int nw);
-- (match t.write_control with
-- None -> ()
-- | Some bc ->
-- bc.moved_bytes <- bc.moved_bytes ++ (Int64.of_int nw));
-- t.nwrite <- t.nwrite + nw;
-- b.len <- b.len - nw;
-- b.pos <- b.pos + nw;
-- if nw = 0 then close t "closed on write" else
-- if b.len = 0 then begin
-- b.pos <- 0;
-- delete_string b.buf;
-- b.buf <- "";
-- end
-- with
-- Unix.Unix_error((Unix.EWOULDBLOCK | Unix.EAGAIN), _,_) as e -> raise e
-- | e ->
-- t.error <- Printf.sprintf "Can Write Error: %s" (Printexc2.to_string e);
-- close t t.error;
--
--(* lprintf "exce %s in read" (Printexc2.to_string e); lprint_newline (); *)
-- raise e
--
-- end;
-- if not (closed t) then begin
-- t.event_handler t CAN_REFILL;
-- if b.len = 0 then begin
-- delete_string b.buf;
-- b.pos <- 0;
-- must_write t.sock false;
-- t.event_handler t WRITE_DONE
-- end
-- end
--*)
-- ()
--
--let remaining_to_write t = t.wlen
--
--let tcp_handler t sock event =
-- match event with
-- | CAN_READ ->
--(* lprintf "CAN_READ"; lprint_newline (); *)
-- begin
-- match t.read_control with
-- None ->
-- can_read_handler t sock (String.length t.rbuf.buf)
-- | Some bc ->
-- if bc.total_bytes = 0 then
-- can_read_handler t sock (String.length t.rbuf.buf)
-- else begin
--(* lprintf "DELAYED"; lprint_newline (); *)
-- if bc.remaining_bytes > 0 then
-- begin
-- bc.connections <- t :: bc.connections;
-- bc.nconnections <- t.read_power + bc.nconnections
-- end
-- end
-- end
-- | CAN_WRITE ->
--(* lprintf "CAN_WRITE"; lprint_newline (); *)
-- begin
-- match t.write_control with
-- None ->
-- can_write_handler t sock t.wlen
-- | Some bc ->
-- if bc.total_bytes = 0 then
-- can_write_handler t sock t.wlen
-- else begin
--(* lprintf "DELAYED"; lprint_newline (); *)
-- if bc.remaining_bytes > 0 then begin
-- bc.connections <- t :: bc.connections;
-- bc.nconnections <- t.write_power + bc.nconnections
-- end
-- end
-- end
-- | _ -> t.event_handler t (BASIC_EVENT event)
--
--let read_bandwidth_controlers = ref []
--let write_bandwidth_controlers = ref []
--
--let _ =
-- Heap.add_memstat "tcpClientSocket" (fun level buf ->
-- Printf.bprintf buf " read_bandwidth_controlers: %d\n" (List.length !read_bandwidth_controlers);
-- Printf.bprintf buf " write_bandwidth_controlers: %d\n" (List.length !write_bandwidth_controlers);
-- )
--
--let create_read_bandwidth_controler rate =
-- let bc = {
-- remaining_bytes = rate;
-- total_bytes = rate;
-- nconnections = 0;
-- connections = [];
-- allow_io = ref true;
-- last_remaining = 0;
-- moved_bytes = Int64.zero;
-- } in
-- read_bandwidth_controlers := bc :: !read_bandwidth_controlers;
-- bc
--
--let create_write_bandwidth_controler rate =
-- let bc = {
-- remaining_bytes = rate;
-- total_bytes = rate;
-- nconnections = 0;
-- connections = [];
-- allow_io = ref true;
-- last_remaining = 0;
-- moved_bytes = Int64.zero;
-- } in
-- write_bandwidth_controlers := bc :: !write_bandwidth_controlers;
-- bc
--
--let change_rate bc rate =
-- bc.total_bytes <- rate
--
--let bandwidth_controler t sock =
-- (match t.read_control with
-- None -> ()
-- | Some bc ->
-- must_read sock (bc.total_bytes = 0 || bc.remaining_bytes > 0));
-- (match t.write_control with
-- None -> ()
-- | Some bc ->
-- must_write sock ((bc.total_bytes = 0 || bc.remaining_bytes > 0)
-- && t.wlen > 0))
--
--let set_read_controler t bc =
-- t.read_control <- Some bc;
--(* set_before_select t.sock (bandwidth_controler t); *)
-- set_allow_read t.sock bc.allow_io;
-- bandwidth_controler t t.sock
--
--let set_write_controler t bc =
-- t.write_control <- Some bc;
--(* set_before_select t.sock (bandwidth_controler t); *)
-- set_allow_write t.sock bc.allow_io;
-- bandwidth_controler t t.sock
--
--let max_buffer_size = ref 1000000
--
--let dump_socket t buf =
-- print_socket buf t.sock;
-- Printf.bprintf buf "rbuf: %d/%d wbuf: %d/%d\n" t.rbuf.len (String.length t.rbuf.buf) t.wlen (String.length t.wfbuf.buf)
--
--let create name fd handler =
-- if !debug then begin
-- lprintf_nl "[fd %d %s]\n" (Obj.magic fd) name;
-- end;
-- MlUnix.set_close_on_exec fd;
-- let t = {
-- sock = dummy_sock;
-- rbuf = buf_create !max_buffer_size;
-- wfbuf = buf_create !max_buffer_size;
-- event_handler = handler;
-- error = "";
-- nread = 0;
-- nwrite = 0;
-- monitored = false;
-- read_control = None;
-- write_control = None;
-- write_power = 1;
-- read_power = 1;
-- wlen = 0;
-- wfifo = Fifo.create ();
-- } in
-- let sock = BasicSocket.create name fd (tcp_handler t) in
-- let name = (fun () ->
-- Printf.sprintf "%s (nread: %d nwritten: %d) [U %s,D %s]" name t.nread t.nwrite
-- (string_of_bool (t.read_control <> None))
-- (string_of_bool (t.write_control <> None));
-- ;
-- ) in
-- set_printer sock name;
-- set_dump_info sock (dump_socket t);
-- t.sock <- sock;
-- t
--
--let create_blocking name fd handler =
-- MlUnix.set_close_on_exec fd;
-- let t = {
-- sock = dummy_sock;
-- rbuf = buf_create !max_buffer_size;
-- wfbuf = buf_create !max_buffer_size;
-- event_handler = handler;
-- error = "";
-- nread = 0;
-- nwrite = 0;
-- monitored = false;
-- read_control = None;
-- write_control = None;
-- write_power = 1;
-- read_power = 1;
-- wlen = 0;
-- wfifo = Fifo.create ();
-- } in
-- let sock = create_blocking name fd (tcp_handler t) in
-- t.sock <- sock;
-- set_dump_info sock (dump_socket t);
-- t
--
--let create_simple name fd =
-- create name fd (fun _ _ -> ())
--
--let connect name host port handler =
-- try
--(* lprintf "CONNECT tcpClientSocket\n"; *)
-- let s = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
-- let t = create name s handler in
-- must_write (sock t) true;
-- try
-- Unix.connect s (Unix.ADDR_INET(host,port));
-- t
-- with
-- Unix.Unix_error((Unix.EINPROGRESS|Unix.EINTR),_,_) -> t
-- | Unix.Unix_error (Unix.ENETUNREACH,_,_) as e ->
-- close t "connect failed";
-- raise e
-- | e ->
-- lprintf "For host %s port %d\n"
-- (Unix.string_of_inet_addr host) port;
-- close t "connect failed";
-- raise e
-- with e ->
-- lprintf "+++ Exception BEFORE CONNECT %s\n" (Printexc2.to_string e);
-- raise e
--
--
--
--let set_max_write_buffer t len =
-- t.wfbuf.max_buf_size <- len;
-- t.rbuf.max_buf_size <- len
--
--let can_write t =
-- t.wlen = 0
--
--let can_write_len t len =
--(* lprintf "CAN WRITE %d > %d + %d" t.wbuf.max_buf_size t.wbuf.len len; lprint_newline (); *)
-- t.wfbuf.max_buf_size > t.wlen + len
--
--let close_after_write t =
-- if t.wlen = 0 then begin
-- shutdown t "close after write"
-- end
-- else
-- set_handler t WRITE_DONE (fun t ->
-- shutdown t "close after write")
--
--let set_monitored t =
-- t.monitored <- true
--
--
--let _ =
-- add_infinite_timer 1.0 (fun timer ->
-- List.iter (fun bc ->
-- bc.last_remaining <- bc.remaining_bytes;
-- bc.remaining_bytes <- bc.total_bytes;
-- if bc.remaining_bytes > 0 then bc.allow_io := true
--(* lprintf "READ remaining_bytes: %d" bc.remaining_bytes; *)
-- ) !read_bandwidth_controlers;
-- List.iter (fun bc ->
-- bc.last_remaining <- bc.remaining_bytes;
-- bc.remaining_bytes <- bc.total_bytes;
-- if bc.remaining_bytes > 0 then bc.allow_io := true;
-- (*
-- lprintf "WRITE remaining_bytes: %d" bc.remaining_bytes;
-- lprint_newline (); *)
-- ) !write_bandwidth_controlers
-- );
--
-- set_before_select_hook (fun _ ->
-- List.iter (fun bc ->
-- bc.allow_io := (bc.total_bytes = 0 || bc.remaining_bytes > 0);
-- ) !read_bandwidth_controlers;
-- List.iter (fun bc ->
-- bc.allow_io := (bc.total_bytes = 0 || bc.remaining_bytes > 0);
-- ) !write_bandwidth_controlers;
-- );
--
-- set_after_select_hook (fun _ ->
-- List.iter (fun bc ->
-- List.iter (fun t ->
-- if bc.remaining_bytes > 0 then
-- let can_read = maxi 1 (bc.remaining_bytes / bc.nconnections) in
-- let can_read = can_read * t.read_power in
-- let old_nread = t.nread in
-- (try
-- can_read_handler t t.sock (mini can_read
-- (String.length t.rbuf.buf))
-- with _ -> ());
-- bc.remaining_bytes <- bc.remaining_bytes -
-- t.nread + old_nread;
-- bc.nconnections <- bc.nconnections - t.read_power;
-- ) bc.connections;
-- if bc.remaining_bytes > 0 then bc.allow_io := false;
-- bc.connections <- [];
-- bc.nconnections <- 0;
-- ) !read_bandwidth_controlers;
-- List.iter (fun bc ->
-- List.iter (fun t ->
-- if bc.remaining_bytes > 0 then
-- let can_write = maxi 1 (bc.remaining_bytes / bc.nconnections) in
-- let can_write = can_write * t.write_power in
-- let old_nwrite = t.nwrite in
-- (try
--(* lprintf "WRITE"; lprint_newline (); *)
-- can_write_handler t t.sock (mini can_write t.wlen)
-- with _ -> ());
-- bc.remaining_bytes <- bc.remaining_bytes -
-- t.nwrite + old_nwrite;
-- bc.nconnections <- bc.nconnections - t.write_power;
-- ) bc.connections;
-- if bc.remaining_bytes > 0 then bc.allow_io := false;
-- bc.connections <- [];
-- bc.nconnections <- 0;
-- ) !write_bandwidth_controlers
-- )
--
--
--let my_ip t =
-- let fd = fd t.sock in
-- match Unix.getsockname fd with
-- Unix.ADDR_INET (ip, port) -> Ip.of_inet_addr ip
-- | _ -> raise Not_found
--
--let stats buf t =
-- BasicSocket.stats buf t.sock;
-- Printf.bprintf buf " rbuf size: %d/%d\n" (String.length t.rbuf.buf)
-- t.rbuf.max_buf_size;
-- Printf.bprintf buf " wbuf size: %d/%d\n" (t.wlen)
-- t.wfbuf.max_buf_size
--
--let buf_size t =
-- (String.length t.rbuf.buf),
-- (String.length t.wfbuf.buf)
--
--let can_fill t =
-- t.wlen < (t.wfbuf.max_buf_size / 2)
--
--let if_possible bc len =
-- bc.total_bytes = 0 ||
-- if bc.last_remaining >= len then begin
-- bc.last_remaining <- bc.last_remaining - len;
-- true;
-- end else false
--
--let set_rtimeout s t = set_rtimeout (sock s) t
--let set_wtimeout s t = set_wtimeout (sock s) t
--
--open LittleEndian
--
--let internal_buf = Buffer.create 17000
--
--let simple_send_buf buf sock = ()
-- (*
-- let s = Buffer.contents buf in
-- Buffer.reset buf;
-- buf_int8 buf 228;
-- let len = String.length s in
-- buf_int buf len;
-- write sock (Buffer.contents buf) 0 5;
-- write sock s 0 len
--*)
--
--let value_send sock m = ()
-- (*
-- Buffer.reset internal_buf;
-- Buffer.add_string internal_buf (Marshal.to_string m []);
-- simple_send_buf internal_buf sock
--*)
--
--let value_handler f sock nread = ()
-- (*
-- let b = buf sock in
-- try
-- while b.len >= 5 do
-- let msg_len = get_int b.buf (b.pos+1) in
-- if b.len >= 5 + msg_len then
-- begin
-- let s = String.sub b.buf (b.pos+5) msg_len in
-- let t = Marshal.from_string s 0 in
-- buf_used sock (msg_len + 5);
-- f t sock;
-- ()
-- end
-- else raise Not_found
-- done
-- with Not_found -> ()
-- *)
--
--
--
--let set_write_power t p = t.write_power <- p
--let set_read_power t p = t.read_power <- p
--
--let set_lifetime s = set_lifetime (sock s)
--
--let moved_bytes bc = bc.moved_bytes
--
-Index: src/utils/net/tcpClientSocket.mli
-===================================================================
-RCS file: src/utils/net/tcpClientSocket.mli
-diff -N src/utils/net/tcpClientSocket.mli
---- src/utils/net/tcpClientSocket.mli 22 Apr 2003 22:33:40 -0000 1.1
-+++ /dev/null 1 Jan 1970 00:00:00 -0000
-@@ -1,108 +0,0 @@
--(* Copyright 2001, 2002 b8_bavard, b8_fee_carabine, INRIA *)
--(*
-- This file is part of mldonkey.
--
-- mldonkey is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
--
-- mldonkey is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with mldonkey; if not, write to the Free Software
-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
--*)
--type event =
-- WRITE_DONE
-- | CAN_REFILL
-- | BUFFER_OVERFLOW
-- | READ_DONE of int
-- | BASIC_EVENT of BasicSocket.event
--
--and buf = {
-- mutable buf : string;
-- mutable pos : int;
-- mutable len : int;
-- mutable max_buf_size : int;
-- }
--
--type t
--
--type bandwidth_controler = {
-- mutable remaining_bytes : int;
-- mutable total_bytes : int;
-- mutable nconnections : int;
-- mutable connections : t list;
-- allow_io : bool ref;
-- mutable last_remaining : int;
-- mutable moved_bytes : int64;
-- }
--
--
--and handler = t -> event -> unit
--
--val max_buffer_size : int ref
--
--val sock: t -> BasicSocket.t
--val create : string -> Unix.file_descr -> handler -> t
--val create_simple : string -> Unix.file_descr -> t
--val create_blocking : string -> Unix.file_descr -> handler -> t
--val buf : t -> buf
--val set_reader : t -> (t -> int -> unit) -> unit
--val buf_used : t -> int -> unit
--val set_handler : t -> event -> (t -> unit) -> unit
--val set_refill : t -> (t -> unit) -> unit
--val write: t -> string -> unit
--val write_uniq: t -> string -> unit
--val connect: string -> Unix.inet_addr -> int -> handler -> t
--val close : t -> string -> unit
--val closed : t -> bool
--val shutdown : t -> string -> unit
--val error: t -> string
--val tcp_handler: t -> BasicSocket.t -> BasicSocket.event -> unit
--val set_closer : t -> (t -> string -> unit) -> unit
--val nread : t -> int
--val set_max_write_buffer : t -> int -> unit
--val can_write : t -> bool
--val can_write_len : t -> int -> bool
--val set_monitored : t -> unit
--
--val close_after_write : t -> unit
--
--val create_read_bandwidth_controler : int -> bandwidth_controler
--val create_write_bandwidth_controler : int -> bandwidth_controler
--val set_read_controler : t -> bandwidth_controler -> unit
--val set_write_controler : t -> bandwidth_controler -> unit
--val change_rate : bandwidth_controler -> int -> unit
--
--
--val my_ip : t -> Ip.t
--
--val stats : Buffer.t -> t -> unit
--val buf_size : t -> int * int
--val can_fill : t -> bool
--
--val if_possible : bandwidth_controler -> int -> bool
--
--val set_rtimeout : t -> float -> unit
--val set_wtimeout : t -> float -> unit
--
--val internal_buf : Buffer.t
--val value_send : t -> 'a -> unit
--val value_handler : ('a -> t -> unit) -> t -> int -> unit
--
--val set_write_power : t -> int -> unit
--val set_read_power : t -> int -> unit
--
--val remaining_to_write : t -> int
--
--val set_lifetime : t -> float -> unit
--
--val tcp_uploaded_bytes : int64 ref
--val tcp_downloaded_bytes : int64 ref
--val moved_bytes : bandwidth_controler -> int64
--
-Index: src/utils/net/tcpSocket.mli
-===================================================================
-RCS file: src/utils/net/tcpSocket.mli
-diff -N src/utils/net/tcpSocket.mli
---- src/utils/net/tcpSocket.mli 22 Apr 2003 22:33:40 -0000 1.1
-+++ /dev/null 1 Jan 1970 00:00:00 -0000
-@@ -1,44 +0,0 @@
--(* Copyright 2001, 2002 b8_bavard, b8_fee_carabine, INRIA *)
--(*
-- This file is part of mldonkey.
--
-- mldonkey is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
--
-- mldonkey is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with mldonkey; if not, write to the Free Software
-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
--*)
--type event =
-- WRITE_DONE
-- | CAN_REFILL
-- | BUFFER_OVERFLOW
-- | READ_DONE of int
-- | BASIC_EVENT of BasicSocket.event
--
--and buf = {
-- mutable buf : string;
-- mutable pos : int;
-- mutable len : int;
-- mutable max_buf_size : int;
-- }
--
--type t
--
--and handler = t -> event -> unit
--
--val sock: t -> BasicSocket.t
--val create : Unix.file_descr -> handler -> t
--val buf : t -> buf
--val set_reader : t -> (t -> int -> unit) -> unit
--val buf_used : t -> int -> unit
--val set_handler : t -> event -> (t -> unit) -> unit
--val set_refill : t -> (t -> unit) -> unit
--val write: t -> string -> int -> int -> unit
-\ No newline at end of file
-Index: src/utils/net/udpSocket.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/src/utils/net/udpSocket.ml,v
-retrieving revision 1.20
-retrieving revision 1.22
-diff -u -r1.20 -r1.22
---- src/utils/net/udpSocket.ml 14 Dec 2005 21:17:47 -0000 1.20
-+++ src/utils/net/udpSocket.ml 21 Nov 2006 22:34:34 -0000 1.22
-@@ -23,6 +23,14 @@
- open AnyEndian
- open LittleEndian
-
-+let log_prefix = "[udpSock]"
-+
-+let lprintf_nl fmt =
-+ lprintf_nl2 log_prefix fmt
-+
-+let lprintf_n fmt =
-+ lprintf2 log_prefix fmt
-+
- type event =
- WRITE_DONE
- | CAN_REFILL
-@@ -131,6 +139,7 @@
- mutable allow_io : bool ref;
- mutable count : int;
- mutable base_time : int;
-+ mutable tcp_bc : TcpBufferedSocket.bandwidth_controler;
- }
-
- and handler = t -> event -> unit
-@@ -190,10 +199,10 @@
- lprintf_nl "ADDR_UNIX (%s)" s;
- end
-
--let max_delayed_send = 30
-+let max_delayed_send = 1
-
- let write t ping s ip port =
--(* lprintf "UDP write to %s:%d\n" (Ip.to_string ip) port; *)
-+(* lprintf_nl "UDP write to %s:%d" (Ip.to_string ip) port; *)
- if not (closed t) && t.wlist_size < !max_wlist_size then
- let s, addr = match t.socks_local with
- None -> s, Unix.ADDR_INET(Ip.to_inet_addr ip, port)
-@@ -219,16 +228,19 @@
- let _ =
- try
- if ping then declare_ping ip;
-- ignore(Unix.sendto (fd sock) s 0 len [] addr)
-+ ignore(Unix.sendto (fd sock) s 0 len [] addr);
-+ if !verbose_bandwidth > 1 then begin
-+ lprintf_nl "[BW2] direct send udp %d bytes (write)" len;
-+ end;
- with e ->
-- lprintf "Exception in sendto %s:%d\n" (Ip.to_string ip) port;
-+ lprintf_nl "Exception in sendto %s:%d" (Ip.to_string ip) port;
- raise e
- in
- udp_uploaded_bytes := !udp_uploaded_bytes ++ (Int64.of_int len);
- ()
- (*
--lprintf "UDP sent [%s]" (String.escaped
--(String.sub s pos len)); lprint_newline ();
-+lprintf_nl "UDP sent [%s]" (String.escaped
-+(String.sub s pos len));
- *)
- with
- Unix.Unix_error ((Unix.EWOULDBLOCK | Unix.ENOBUFS), _, _) ->
-@@ -240,7 +252,7 @@
- t.wlist_size <- t.wlist_size + String.length s;
- must_write sock true;
- | e ->
-- lprintf "Exception %s in sendto\n"
-+ lprintf_nl "Exception %s in sendto"
- (Printexc2.to_string e);
- print_addr addr;
- raise e
-@@ -265,6 +277,10 @@
- t.wlist_size <- t.wlist_size + String.length s;
- must_write t.sock true;
- end
-+ else
-+ if !debug then begin
-+ lprintf_nl "UDP DROPPED in write";
-+ end
-
- let dummy_sock = Obj.magic 0
-
-@@ -278,11 +294,16 @@
- begin try
- ignore (local_sendto (fd sock) p);
- udp_uploaded_bytes := !udp_uploaded_bytes ++ (Int64.of_int len);
-+ if !verbose_bandwidth > 1 then begin
-+ lprintf_nl "[BW2] direct send udp %d bytes (iter_write_no_bc)" len;
-+ end
- with
-- Unix.Unix_error ((Unix.EWOULDBLOCK | Unix.ENOBUFS), _, _) as e -> raise e
-+ Unix.Unix_error ((Unix.EWOULDBLOCK | Unix.ENOBUFS), _, _) as e ->
-+ lprintf_nl "Exception %s in sendto next" (Printexc2.to_string e);
-+ raise e
- | e ->
- if !debug then
-- lprintf "Exception %s in sendto next\n"
-+ lprintf_nl "Exception %s in sendto next"
- (Printexc2.to_string e)
- end;
- iter_write_no_bc t sock
-@@ -302,23 +323,27 @@
- t.wlist_size <- t.wlist_size - String.length p.udp_content;
- if time < bc.base_time then begin
- if !debug then begin
-- lprintf "[UDP DROPPED]";
-+ lprintf_nl "UDP DROPPED in iter_write";
- end;
- iter_write t sock bc
- end else
- let len = String.length p.udp_content in
- begin try
--
--
- ignore (local_sendto (fd sock) p);
- udp_uploaded_bytes := !udp_uploaded_bytes ++ (Int64.of_int len);
- bc.remaining_bytes <- bc.remaining_bytes - (len +
- !TcpBufferedSocket.ip_packet_size) ;
-+ TcpBufferedSocket.register_bytes (Some bc.tcp_bc) len;
-+ if !verbose_bandwidth > 1 then begin
-+ lprintf_nl "[BW2] bc send udp %d bytes" len;
-+ end;
- with
-- Unix.Unix_error ((Unix.EWOULDBLOCK | Unix.ENOBUFS), _, _) as e -> raise e
-+ Unix.Unix_error ((Unix.EWOULDBLOCK | Unix.ENOBUFS), _, _) as e ->
-+ lprintf_nl "Exception %s in sendto next" (Printexc2.to_string e);
-+ raise e
- | e ->
- if !debug then
-- lprintf "Exception %s in sendto next\n"
-+ lprintf_nl "Exception %s in sendto next"
- (Printexc2.to_string e)
- end;
- iter_write t sock bc
-@@ -418,26 +443,28 @@
- allow_io = ref false;
- count = 0;
- base_time = 0;
-+ tcp_bc = tcp_bc;
- } in
- let udp_user total n =
--(*
-- if !BasicSocket.debug then begin
-- lprintf "udp_user %d/%d" n total; lprint_newline ();
-- end; *)
-- let n = if total = 0 then 100000 else n in
-+ if !verbose_bandwidth > 0 then
-+ lprintf_nl "udp_user %d/%d" n total;
-+(* let n = if total = 0 then 100000 else n in *)
- udp_bc.base_time <- udp_bc.base_time + 1;
- if udp_bc.count = 0 then begin
- udp_bc.count <- 10;
- TcpBufferedSocket.set_lost_bytes tcp_bc udp_bc.remaining_bytes
- udp_bc.base_time;
-- udp_bc.remaining_bytes <- 0;
- end;
- udp_bc.count <- udp_bc.count - 1;
- udp_bc.total_bytes <- total;
-- udp_bc.remaining_bytes <- udp_bc.remaining_bytes + n;
-+ udp_bc.remaining_bytes <- total / 2;
-+(* udp_bc.remaining_bytes <- udp_bc.remaining_bytes + n; *)
- if total <> 0 && udp_bc.remaining_bytes > total then
- udp_bc.remaining_bytes <- total;
- udp_bc.allow_io := udp_bc.remaining_bytes > 0;
-+ if !verbose_bandwidth > 0 then
-+ lprintf_nl "udp_bc count:%d total_bytes:%d remaining_bytes:%d"
-+ udp_bc.count udp_bc.total_bytes udp_bc.remaining_bytes;
- in
- TcpBufferedSocket.set_remaining_bytes_user tcp_bc udp_user;
- udp_bc
-@@ -510,8 +537,8 @@
-
- MlUnix.set_nonblock fd;
- with e ->
-- lprintf "[SOCKS] proxy error prevent creation of UDP socket: %s"
-- (Printexc2.to_string e); lprint_newline ();
-+ lprintf_nl "[SOCKS] proxy error prevent creation of UDP socket: %s"
-+ (Printexc2.to_string e);
- close t "socks proxy error"; raise e
- *)
-
-@@ -524,7 +551,7 @@
- ) latencies;
- LittleEndian.buf_int b !counter;
- Hashtbl.iter (fun ip (latency, samples) ->
-- if !verbose then lprintf " Latency UDP: %s -> %d (%d samples)\n" (Ip.to_string ip) !latency !samples;
-+ if !verbose then lprintf_nl " Latency UDP: %s -> %d (%d samples)" (Ip.to_string ip) !latency !samples;
- LittleEndian.buf_ip b ip;
- LittleEndian.buf_int16 b !latency;
- LittleEndian.buf_int16 b !samples;
-Index: tools/make_torrent.ml
-===================================================================
-RCS file: /sources/mldonkey/mldonkey/tools/make_torrent.ml,v
-retrieving revision 1.8
-retrieving revision 1.9
-diff -u -r1.8 -r1.9
---- tools/make_torrent.ml 9 Jan 2006 00:25:59 -0000 1.8
-+++ tools/make_torrent.ml 25 Oct 2006 11:34:46 -0000 1.9
-@@ -203,7 +203,7 @@
- "Quick Howto:\n" ^
- "- create a new torrent:\n" ^
- "make_torrent -tracker http://ip:port/announce -torrent file.torrent " ^
-- "-comment \"www.mldonkey.net\" -create file\n\n" ^
-+ "-comment \"www.mldonkey.org\" -create file\n\n" ^
- "- change the tracker of a torrent file:\n" ^
- "make_torrent -tracker http://ip:port/tracker -torrent myfile.torrent -change\n\n" ^
- "- print the infos of a torrent file:\n" ^
diff --git a/net-p2p/mldonkey-devel/files/patch-cvs-2006122500 b/net-p2p/mldonkey-devel/files/patch-cvs-2006122500
new file mode 100644
index 000000000000..6a80f449e25e
--- /dev/null
+++ b/net-p2p/mldonkey-devel/files/patch-cvs-2006122500
@@ -0,0 +1,7533 @@
+Index: config/Makefile.in
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/config/Makefile.in,v
+retrieving revision 1.173
+retrieving revision 1.174
+diff -u -r1.173 -r1.174
+--- config/Makefile.in 21 Nov 2006 22:29:58 -0000 1.173
++++ config/Makefile.in 28 Nov 2006 23:58:01 -0000 1.174
+@@ -148,7 +148,7 @@
+ $(CDK)/filepath.ml $(CDK)/string2.ml \
+ $(CDK)/filename2.ml $(CDK)/list2.ml $(CDK)/hashtbl2.ml \
+ $(CDK)/unix2.ml $(CDK)/file.ml \
+- $(CDK)/heap_c.c $(CDK)/array2.ml $(CDK)/sort2.ml
++ $(CDK)/heap_c.c $(CDK)/array2.ml
+
+ ifneq ("$(PTHREAD_CFLAGS)" , "")
+ CFLAGS += $(PTHREAD_CFLAGS)
+Index: distrib/ChangeLog
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/distrib/ChangeLog,v
+retrieving revision 1.1118
+retrieving revision 1.1133
+diff -u -r1.1118 -r1.1133
+--- distrib/ChangeLog 28 Nov 2006 23:17:31 -0000 1.1118
++++ distrib/ChangeLog 8 Dec 2006 12:26:24 -0000 1.1133
+@@ -14,6 +14,45 @@
+ ChangeLog
+ =========
+
++2006/12/08
++5617: New option share_scan_interval
++- how often (in minutes) should MLDonkey scan all shared directories
++ for new/removed files, default one minute
++- on slow machines raise the interval to a higher value to reduce CPU load
++- to force a re-scan of shared directories use command "reshare"
++
++2006/12/06
++5613: Another longhelp cleanup (anhi)
++5615: EDK: Parse more fields from server.met files
++
++2006/12/04
++5612: EDK: OP_HELLO tag 0x75, print os_info in logfile
++
++2006/12/03
++5602: HTML: Display share status in upstats
++5609: New field type Field_KNOWN, EDK: recognize more HELLO/EmuleInfo tags
++5610: CommonSources: Cleanups and reformatting the code (pango)
++
++2006/12/02
++5608: Multiuser, chgrp: Prevent change of file_group to None
++ if the user is not file_owner
++5607: Multiuser, chown: Change file_group to user_default_group
++ if the new user is not member of file_group
++5606: Introduce display of session transfer values
++- new columns for session up-/download
++- send session values to GUIs
++
++2006/12/01
++5605: HTML: Fix search list display when html_checkbox_search_file_list = true
++
++2006/11/29
++5598: Remove use of deprecated sort module, remove unused sort2.ml* (pango)
++5589: New option create_file_mode,
++ rename create_dir_mask to create_dir_mode (pango)
++5595: EDK: Fully parse emule_miscoptions1/2
++5594: EDK: If update_server_list_client true, add yet unknown server
++ of lowid clients
++-------------------------------------------------------------------------------
+ 2006/11/29 version 2.8.2 = tag release-2-8-2
+ 5597: GD: New option html_mods_vd_gfx_h_intervall
+ (compute values for hourly graph every x minutes) (skeeve)
+Index: src/daemon/common/commonClient.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonClient.ml,v
+retrieving revision 1.33
+retrieving revision 1.34
+diff -u -r1.33 -r1.34
+--- src/daemon/common/commonClient.ml 5 Nov 2006 14:09:38 -0000 1.33
++++ src/daemon/common/commonClient.ml 2 Dec 2006 12:35:45 -0000 1.34
+@@ -467,16 +467,15 @@
+ try
+ let i = client_info c in
+ let ctime = ((BasicSocket.last_time ()) - i.GuiTypes.client_connect_time) / 60 in
+- if i.GuiTypes.client_uploaded = Int64.zero && ctime > 1 then
++ if i.GuiTypes.client_session_uploaded = Int64.zero && ctime > 1 then
+ begin
+ client_disconnect c;
+- if !verbose then lprintf_nl "disconnected client %d: [%s %s] %s after %d %s of silence."
++ if !verbose then lprintf_nl "disconnected client %d: [%s %s] %s after %d minute%s of silence."
+ (client_num c)
+ (GuiTypes.client_software i.GuiTypes.client_software i.GuiTypes.client_os)
+ i.GuiTypes.client_release
+ i.GuiTypes.client_name
+- ctime
+- (if ctime = 1 then "minute" else "minutes")
++ ctime (Printf2.print_plural_s ctime)
+ end
+ with _ -> ()
+ ) !uploaders
+@@ -500,8 +499,10 @@
+ T.client_os = None;
+ T.client_release = "";
+ T.client_emulemod = "";
+- T.client_downloaded = 0L;
+- T.client_uploaded = 0L;
++ T.client_total_downloaded = 0L;
++ T.client_total_uploaded = 0L;
++ T.client_session_downloaded = 0L;
++ T.client_session_uploaded = 0L;
+ T.client_upload = None;
+ T.client_sui_verified = None;
+ }
+Index: src/daemon/common/commonFile.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonFile.ml,v
+retrieving revision 1.70
+retrieving revision 1.71
+diff -u -r1.70 -r1.71
+--- src/daemon/common/commonFile.ml 15 Nov 2006 12:37:13 -0000 1.70
++++ src/daemon/common/commonFile.ml 2 Dec 2006 12:35:45 -0000 1.71
+@@ -399,8 +399,8 @@
+ ("", "sr br", addr);
+ (GuiTypes.client_software cinfo.GuiTypes.client_software cinfo.GuiTypes.client_os,
+ "sr br", GuiTypes.client_software_short cinfo.GuiTypes.client_software cinfo.GuiTypes.client_os);
+- ("", "sr ar", (size_of_int64 cinfo.GuiTypes.client_uploaded));
+- ("", "sr ar br", (size_of_int64 cinfo.GuiTypes.client_downloaded)); ];
++ ("", "sr ar", (size_of_int64 cinfo.GuiTypes.client_total_uploaded));
++ ("", "sr ar br", (size_of_int64 cinfo.GuiTypes.client_total_downloaded)); ];
+
+ Printf.bprintf buf "\\</tr\\>";
+
+Index: src/daemon/common/commonFile.mli
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonFile.mli,v
+retrieving revision 1.30
+retrieving revision 1.31
+diff -u -r1.30 -r1.31
+--- src/daemon/common/commonFile.mli 12 Nov 2006 12:44:24 -0000 1.30
++++ src/daemon/common/commonFile.mli 3 Dec 2006 20:57:56 -0000 1.31
+@@ -129,7 +129,6 @@
+ val set_file_comment : CommonTypes.file -> string -> unit
+ val file_comment : CommonTypes.file -> string
+ val file_magic : CommonTypes.file -> string option
+-val set_file_magic : CommonTypes.file -> string option -> unit
+ val check_magic : CommonTypes.file -> unit
+ val recover_bytes : CommonTypes.file -> (int64 * int64) list
+ val file_write : CommonTypes.file -> int64 -> string -> int -> int -> unit
+Index: src/daemon/common/commonGlobals.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonGlobals.ml,v
+retrieving revision 1.77
+retrieving revision 1.78
+diff -u -r1.77 -r1.78
+--- src/daemon/common/commonGlobals.ml 28 Nov 2006 23:15:21 -0000 1.77
++++ src/daemon/common/commonGlobals.ml 3 Dec 2006 20:49:42 -0000 1.78
+@@ -405,6 +405,7 @@
+ | Field_Lastseencomplete -> "lastcompl"
+ | Field_Medialength -> "mlen"
+ | Field_Mediacodec -> "mediacodec"
++ | Field_KNOWN s -> s
+ | Field_UNKNOWN s -> s
+
+ let field_of_string t =
+@@ -426,10 +427,11 @@
+ | "lastcompl" -> Field_Lastseencomplete
+ | "mlen" -> Field_Medialength
+ | "mediacodec" -> Field_Mediacodec
+- | _ -> Field_UNKNOWN t
++ | _ -> Field_KNOWN t
+
+ let escaped_string_of_field tag =
+ match tag.tag_name with
++ | Field_KNOWN s -> String.escaped s
+ | Field_UNKNOWN s -> String.escaped s
+ | t -> string_of_field t
+
+@@ -438,6 +440,10 @@
+ Printf.sprintf " \"%s\" = %s" (escaped_string_of_field tag)
+ (string_of_tag_value tag.tag_value)
+
++let hexstring_of_tag tag =
++ Printf.sprintf " \"%s\" = %s" (String2.hex_string_of_string (escaped_string_of_field tag))
++ (string_of_tag_value tag.tag_value)
++
+ let rec print_tags tags =
+ match tags with
+ [] -> ()
+Index: src/daemon/common/commonInteractive.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonInteractive.ml,v
+retrieving revision 1.85
+retrieving revision 1.87
+diff -u -r1.85 -r1.87
+--- src/daemon/common/commonInteractive.ml 26 Nov 2006 13:54:09 -0000 1.85
++++ src/daemon/common/commonInteractive.ml 3 Dec 2006 20:49:42 -0000 1.87
+@@ -222,7 +222,7 @@
+ let new_name = file_commited_name incoming.shdir_dirname file in
+ if Unix2.is_directory file_name then begin
+ Unix2.safe_mkdir new_name;
+- Unix2.chmod new_name (Misc.int_of_octal_string !!create_dir_mask)
++ Unix2.chmod new_name !Unix32.create_dir_mode;
+ end;
+
+ (* the next line really moves the file *)
+@@ -714,7 +714,7 @@
+ | Q_MP3_BITRATE _ ->
+ let bitrate = get_arg "bitrate" in
+ if bitrate = "" then raise Not_found;
+- QHasMinVal(Field_UNKNOWN "bitrate", Int64.of_string bitrate)
++ QHasMinVal(Field_KNOWN "bitrate", Int64.of_string bitrate)
+
+ in
+ try
+@@ -874,14 +874,14 @@
+ | QHasMinVal (field, value) ->
+ begin
+ match field with
+- Field_UNKNOWN "bitrate"
++ Field_KNOWN "bitrate"
+ | Field_Size
+ | _ -> ()
+ end
+ | QHasMaxVal (field, value) ->
+ begin
+ match field with
+- Field_UNKNOWN "bitrate"
++ Field_KNOWN "bitrate"
+ | Field_Size
+ | _ -> ()
+ end
+Index: src/daemon/common/commonOptions.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonOptions.ml,v
+retrieving revision 1.190
+retrieving revision 1.193
+diff -u -r1.190 -r1.193
+--- src/daemon/common/commonOptions.ml 28 Nov 2006 23:15:21 -0000 1.190
++++ src/daemon/common/commonOptions.ml 8 Dec 2006 12:26:24 -0000 1.193
+@@ -1267,8 +1267,16 @@
+ "The directory where temporary files should be put"
+ string_option "temp"
+
+-let create_dir_mask = define_option current_section ["create_dir_mask"]
+- "New directories in incoming_directories are created with these rights"
++let share_scan_interval = define_option current_section ["share_scan_interval"]
++ "How often (in minutes) should MLDonkey scan all shared directories for new/removed files"
++ int_option 1
++
++let create_file_mode = define_option current_section ["create_file_mode"]
++ "New download files are created with these rights (in octal)"
++ string_option "664"
++
++let create_dir_mode = define_option current_section ["create_dir_mode"]
++ "New directories in incoming_directories are created with these rights (in octal)"
+ string_option "755"
+
+ let create_file_sparse = define_option current_section ["create_file_sparse"]
+@@ -1497,9 +1505,12 @@
+ TcpBufferedSocket.copy_read_buffer := !!copy_read_buffer
+ )
+
+-let _ =
+- option_hook create_dir_mask (fun _ ->
+- Unix32.create_dir_mask := !!create_dir_mask
++let () =
++ option_hook create_file_mode (fun _ ->
++ Unix32.create_file_mode := Misc.int_of_octal_string !!create_file_mode
++ );
++ option_hook create_dir_mode (fun _ ->
++ Unix32.create_dir_mode := Misc.int_of_octal_string !!create_dir_mode
+ )
+
+ let create_mlsubmit = define_expert_option current_section ["create_mlsubmit"]
+@@ -1558,7 +1569,7 @@
+
+ let compaction_overhead = define_expert_option current_section ["compaction_overhead"]
+ "The percentage of free memory before a compaction is triggered"
+- percent_option 25
++ int_option 25
+
+ let space_overhead = define_expert_option current_section ["space_overhead"]
+ "The major GC speed is computed from this parameter. This is the memory
+@@ -1708,6 +1719,9 @@
+ option_hook min_reask_delay (fun _ ->
+ if !!min_reask_delay < 600 then min_reask_delay =:= 600
+ );
++ option_hook share_scan_interval (fun _ ->
++ if !!share_scan_interval < 1 then share_scan_interval =:= 1
++ );
+ option_hook global_login (fun _ ->
+ let len = String.length !!global_login in
+ let prefix = "mldonkey_" in
+Index: src/daemon/common/commonSearch.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonSearch.ml,v
+retrieving revision 1.19
+retrieving revision 1.20
+diff -u -r1.19 -r1.20
+--- src/daemon/common/commonSearch.ml 26 Nov 2006 13:54:09 -0000 1.19
++++ src/daemon/common/commonSearch.ml 3 Dec 2006 20:49:42 -0000 1.20
+@@ -113,7 +113,7 @@
+ | "-album" :: format :: args ->
+ iter args ((QHasField(Field_Album, format)) :: q)
+ | "-field" :: field :: format :: args ->
+- iter args ((QHasField(Field_UNKNOWN field, format)) :: q)
++ iter args ((QHasField(Field_KNOWN field, format)) :: q)
+ | "-network" :: name :: args ->
+ net := (network_find_by_name name).network_num;
+ iter args q
+@@ -892,7 +892,7 @@
+ try
+ let bitrate = Int64.of_string s
+ in
+- QHasMinVal(Field_UNKNOWN "bitrate", bitrate)
++ QHasMinVal(Field_KNOWN "bitrate", bitrate)
+ with _ -> QNone
+ end
+
+Index: src/daemon/common/commonServer.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonServer.ml,v
+retrieving revision 1.39
+retrieving revision 1.40
+diff -u -r1.39 -r1.40
+--- src/daemon/common/commonServer.ml 26 Nov 2006 16:36:29 -0000 1.39
++++ src/daemon/common/commonServer.ml 28 Nov 2006 23:58:02 -0000 1.40
+@@ -306,8 +306,8 @@
+ (try impl.impl_server_ops.op_server_sort impl.impl_server_val
+ with _ -> 0);
+ ) servers_by_num;
+- Sort.list (fun s1 s2 ->
+- (as_server_impl s1).impl_server_sort >= (as_server_impl s2).impl_server_sort
++ List.sort (fun s1 s2 ->
++ compare (as_server_impl s2).impl_server_sort (as_server_impl s1).impl_server_sort
+ ) !list
+
+ let server_iter f =
+Index: src/daemon/common/commonShared.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonShared.ml,v
+retrieving revision 1.37
+retrieving revision 1.38
+diff -u -r1.37 -r1.38
+--- src/daemon/common/commonShared.ml 29 Oct 2006 18:58:59 -0000 1.37
++++ src/daemon/common/commonShared.ml 3 Dec 2006 20:57:56 -0000 1.38
+@@ -43,13 +43,14 @@
+ mutable impl_shared_size : int64;
+ mutable impl_shared_id : Md4.t;
+ mutable impl_shared_requests : int;
+- mutable impl_shared_magic : string option;
++ mutable impl_shared_file : CommonTypes.file option;
+ mutable impl_shared_servers : CommonTypes.server list;
+ }
+
+ and 'a shared_ops = {
+ mutable op_shared_info : ('a -> GuiTypes.shared_info);
+ mutable op_shared_unshare : ('a -> unit);
++ mutable op_shared_state : (CommonTypes.file -> CommonTypes.ui_conn -> string);
+ }
+
+ let as_shared (shared : 'a shared_impl) =
+@@ -180,6 +181,14 @@
+ shared_remove impl;
+ try impl.impl_shared_ops.op_shared_unshare impl.impl_shared_val with _ -> ()
+
++let shared_state s o =
++ let impl = as_shared_impl s in
++ try
++ match impl.impl_shared_file with
++ | None -> ""
++ | Some f -> impl.impl_shared_ops.op_shared_state f o
++ with _ -> ""
++
+ let shared_dir = function
+ | None -> ""
+ | Some sh ->
+@@ -198,6 +207,7 @@
+ let new_shared_ops network = {
+ op_shared_unshare = (fun _ -> ni_ok network "shared_unshare");
+ op_shared_info = (fun _ -> fni network "shared_info");
++ op_shared_state = (fun _ _ -> fni network "shared_state");
+ }
+
+ let dummy_shared = {
+@@ -209,12 +219,13 @@
+ impl_shared_ops = {
+ op_shared_unshare = (fun _ -> raise Not_found);
+ op_shared_info = (fun _ -> raise Not_found);
++ op_shared_state = (fun _ _ -> raise Not_found);
+ };
+ impl_shared_uploaded = zero;
+ impl_shared_size = zero;
+ impl_shared_id = Md4.null;
+ impl_shared_requests = 0;
+- impl_shared_magic = None;
++ impl_shared_file = None;
+ impl_shared_servers = []
+ }
+
+@@ -354,7 +365,10 @@
+ T.shared_requests = impl.impl_shared_requests;
+ T.shared_uids = [];
+ T.shared_sub_files = [];
+- T.shared_magic = impl.impl_shared_magic;
++ T.shared_magic =
++ match impl.impl_shared_file with
++ | None -> None
++ | Some f -> CommonFile.file_magic f;
+ }
+
+ let shared_info s =
+Index: src/daemon/common/commonShared.mli
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonShared.mli,v
+retrieving revision 1.8
+retrieving revision 1.9
+diff -u -r1.8 -r1.9
+--- src/daemon/common/commonShared.mli 8 Oct 2006 14:20:21 -0000 1.8
++++ src/daemon/common/commonShared.mli 3 Dec 2006 20:57:56 -0000 1.9
+@@ -9,12 +9,13 @@
+ mutable impl_shared_size : int64;
+ mutable impl_shared_id : Md4.Md4.t;
+ mutable impl_shared_requests : int;
+- mutable impl_shared_magic : string option;
++ mutable impl_shared_file : CommonTypes.file option;
+ mutable impl_shared_servers : CommonTypes.server list;
+ }
+ and 'a shared_ops = {
+ mutable op_shared_info : 'a -> GuiTypes.shared_info;
+ mutable op_shared_unshare : 'a -> unit;
++ mutable op_shared_state : CommonTypes.file -> CommonTypes.ui_conn -> string;
+ }
+
+ val dirnames_prio : (string * int) list ref
+@@ -50,5 +51,4 @@
+ val shared_check_files : unit -> unit
+ val impl_shared_info : 'a shared_impl -> GuiTypes.shared_info
+ val shared_info : CommonTypes.shared -> GuiTypes.shared_info
+-
+-
++val shared_state : CommonTypes.shared -> CommonTypes.ui_conn -> string
+Index: src/daemon/common/commonSources.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonSources.ml,v
+retrieving revision 1.39
+retrieving revision 1.41
+diff -u -r1.39 -r1.41
+--- src/daemon/common/commonSources.ml 21 Nov 2006 22:34:33 -0000 1.39
++++ src/daemon/common/commonSources.ml 3 Dec 2006 20:47:12 -0000 1.41
+@@ -99,25 +99,25 @@
+ let busy_sources_queue = 10
+
+ let queue_name = [|
+- "new_sources";
+- "good_sources";
+- "ready_saved_sources";
+- "waiting_saved_sources";
+- "old_sources1";
+- "old_sources2";
+- "old_sources3";
+- "do_not_try_queue";
+- "connected_sources";
+- "connecting_sources";
+- "busy_sources";
+- |]
++ "new_sources";
++ "good_sources";
++ "ready_saved_sources";
++ "waiting_saved_sources";
++ "old_sources1";
++ "old_sources2";
++ "old_sources3";
++ "do_not_try_queue";
++ "connected_sources";
++ "connecting_sources";
++ "busy_sources";
++|]
+
+
+ let nqueues = Array.length queue_name
+
+ let queue_period = Array.create nqueues 600
+
+-let _ =
++let () =
+ queue_period.(new_sources_queue) <- 0;
+ queue_period.(connected_sources_queue) <- 0;
+ queue_period.(connecting_sources_queue) <- 0;
+@@ -178,57 +178,57 @@
+ (* *)
+ (*************************************************************************)
+
+- type source = {
+- source_uid : M.source_uid;
+- mutable source_files : file_request list;
++ type source = {
++ source_uid : M.source_uid;
++ mutable source_files : file_request list;
+
+ (* the 'source_score' increases with failures in connections *)
+- mutable source_score : int;
++ mutable source_score : int;
+
+ (* the 'source_num' that should be used to create the client corresponding to
+ this source *)
+- mutable source_num : int;
++ mutable source_num : int;
+
+ (* the 'source_age' is the time of the last successful connection *)
+- mutable source_age : int;
++ mutable source_age : int;
+
+ (* the 'source_connecting' indicates that this source is currently in the
+ process of being connected. *)
+- mutable source_last_attempt : int;
+- mutable source_sock : tcp_connection;
++ mutable source_last_attempt : int;
++ mutable source_sock : tcp_connection;
+
+- mutable source_brand : M.source_brand;
+- }
++ mutable source_brand : M.source_brand;
++ }
+
+- and file_request = {
+- request_file : file_sources_manager;
+- mutable request_queue : int;
+- mutable request_time : int;
+- mutable request_score : int;
+- }
+-
+- and file_sources_manager = {
+- manager_uid : string;
+- mutable manager_sources : source Queues.Queue.t array;
+- mutable manager_active_sources : int;
+- mutable manager_all_sources : int;
+- mutable manager_file : (unit -> file);
+- }
+-
+- and functions = {
+- mutable function_connect: (M.source_uid -> unit);
+- mutable function_query: (M.source_uid -> string -> unit);
+-
+- mutable function_string_to_manager: (string -> file_sources_manager);
+-
+- mutable function_max_connections_per_second : (unit -> int);
+- mutable function_max_sources_per_file : (unit -> int);
+-
+- mutable function_add_location :
+- (M.source_uid -> string -> unit);
+- mutable function_remove_location :
+- (M.source_uid -> string -> unit);
+- }
++ and file_request = {
++ request_file : file_sources_manager;
++ mutable request_queue : int;
++ mutable request_time : int;
++ mutable request_score : int;
++ }
++
++ and file_sources_manager = {
++ manager_uid : string;
++ mutable manager_sources : source Queues.Queue.t array;
++ mutable manager_active_sources : int;
++ mutable manager_all_sources : int;
++ mutable manager_file : (unit -> file);
++ }
++
++ and functions = {
++ mutable function_connect: (M.source_uid -> unit);
++ mutable function_query: (M.source_uid -> string -> unit);
++
++ mutable function_string_to_manager: (string -> file_sources_manager);
++
++ mutable function_max_connections_per_second : (unit -> int);
++ mutable function_max_sources_per_file : (unit -> int);
++
++ mutable function_add_location :
++ (M.source_uid -> string -> unit);
++ mutable function_remove_location :
++ (M.source_uid -> string -> unit);
++ }
+
+ (*************************************************************************)
+ (* *)
+@@ -236,24 +236,22 @@
+ (* *)
+ (*************************************************************************)
+
+- module HS = Weak.Make(struct
+- type t = source
+- let hash s = Hashtbl.hash s.source_uid
+-
+- let equal x y = x.source_uid = y.source_uid
+- end)
+-
+- module H = Weak.Make(struct
+- type t = source
+- let hash s = Hashtbl.hash s.source_num
+-
+- let equal x y = x.source_num = y.source_num
+- end)
+-
+- module SourcesQueueCreate = Queues.Make(struct
+- type t = source
+- let compare s1 s2 = compare s1.source_uid s2.source_uid
+- end)
++ module HS = Weak.Make(struct
++ type t = source
++ let hash s = Hashtbl.hash s.source_uid
++ let equal x y = x.source_uid = y.source_uid
++ end)
++
++ module H = Weak.Make(struct
++ type t = source
++ let hash s = Hashtbl.hash s.source_num
++ let equal x y = x.source_num = y.source_num
++ end)
++
++ module SourcesQueueCreate = Queues.Make(struct
++ type t = source
++ let compare s1 s2 = compare s1.source_uid s2.source_uid
++ end)
+
+ (*************************************************************************)
+ (* *)
+@@ -261,40 +259,39 @@
+ (* *)
+ (*************************************************************************)
+
+- let dummy_source = {
+- source_uid = M.dummy_source_uid;
+- source_files = [];
++ let dummy_source = {
++ source_uid = M.dummy_source_uid;
++ source_files = [];
++
++ source_num = 0;
++ source_score = 0;
++ source_age = 0;
++ source_last_attempt = 0;
++ source_sock = NoConnection;
++
++ source_brand = M.dummy_source_brand;
++ }
++
++ let last_refill = ref 0
++
++ let not_implemented s _ =
++ failwith (Printf.sprintf "CommonSources.%s not implemented" s)
++
++ let functions = {
++ function_connect = not_implemented "function_connect";
++ function_query = not_implemented "function_query";
++ function_string_to_manager = not_implemented
++ "function_string_to_manager";
++
++ function_max_connections_per_second = (fun _ ->
++ !!max_connections_per_second);
++ function_max_sources_per_file = (fun _ -> 10);
++
++ function_add_location = not_implemented "function_add_location";
++ function_remove_location = not_implemented "function_remove_location";
++ }
+
+- source_num = 0;
+- source_score = 0;
+- source_age = 0;
+- source_last_attempt = 0;
+- source_sock = NoConnection;
+-
+- source_brand = M.dummy_source_brand;
+- }
+-
+- let last_refill = ref 0
+-
+- let not_implemented s _ =
+- failwith (Printf.sprintf "CommonSources.%s not implemented" s)
+-
+- let functions = {
+- function_connect = not_implemented "function_connect";
+- function_query = not_implemented "function_query";
+- function_string_to_manager = not_implemented
+- "function_string_to_manager";
+-
+- function_max_connections_per_second = (fun _ ->
+- !!max_connections_per_second);
+- function_max_sources_per_file = (fun _ -> 10);
+-
+- function_add_location = not_implemented "function_add_location";
+- function_remove_location = not_implemented "function_remove_location";
+-
+- }
+-
+- let indirect_connections = ref 0
++ let indirect_connections = ref 0
+
+ (*************************************************************************)
+ (* *)
+@@ -302,19 +299,19 @@
+ (* *)
+ (*************************************************************************)
+
+- let sources_by_uid = HS.create 13557
+- let sources_by_num = H.create 13557
+-
+- let file_sources_managers = ref []
++ let sources_by_uid = HS.create 13557
++ let sources_by_num = H.create 13557
+
+- let connecting_sources = Fifo.create ()
++ let file_sources_managers = ref []
+
+- let next_direct_sources = Fifo.create ()
+- let next_indirect_sources = ref []
++ let connecting_sources = Fifo.create ()
+
++ let next_direct_sources = Fifo.create ()
++ let next_indirect_sources = ref []
++
+
+- let active_queue q =
+- q >= connected_sources_queue && q <= busy_sources_queue
++ let active_queue q =
++ q >= connected_sources_queue && q <= busy_sources_queue
+
+ (*************************************************************************)
+ (* *)
+@@ -322,10 +319,10 @@
+ (* *)
+ (*************************************************************************)
+
+- let request_score r = r.request_score
++ let request_score r = r.request_score
+
+- let set_score_part r score =
+- r.request_score <- score
++ let set_score_part r score =
++ r.request_score <- score
+
+
+ (*************************************************************************)
+@@ -334,20 +331,20 @@
+ (* *)
+ (*************************************************************************)
+
+-let rec find_throttled_queue queue =
+- if queue_period.(queue) > 0 || queue = old_sources3_queue then
+- queue
+- else
+- find_throttled_queue (queue + 1)
+-
+-let get_throttle_delay m q throttled =
+- if throttled then
+- (max 0
+- (queue_period.(q)
+- - (file_priority (m.manager_file ()))
+- + Queue.length m.manager_sources.(connected_sources_queue))
+- )
+- else 0
++ let rec find_throttled_queue queue =
++ if queue_period.(queue) > 0 || queue = old_sources3_queue then
++ queue
++ else
++ find_throttled_queue (queue + 1)
++
++ let get_throttle_delay m q throttled =
++ if throttled then
++ (max 0
++ (queue_period.(q)
++ - (file_priority (m.manager_file ()))
++ + Queue.length m.manager_sources.(connected_sources_queue))
++ )
++ else 0
+
+ (*
+ * determine the number of (throttled) ready sources for a manager queue
+@@ -357,49 +354,45 @@
+ But that function really needs to be fast.
+ Also, this works because Queues are based on Sets, and that Set.iter
+ gives elements in increasing keys order *)
+-exception BreakOutOfLoop
++ exception BreakOutOfLoop
+
+-let count_file_ready_sources m q throttled =
+- let ready_count = ref 0 in
+- let throttle_delay = get_throttle_delay m q throttled in
+- let ready_threshold = last_time () - !!min_reask_delay - throttle_delay in
+- (try
+- Queue.iter
+- (fun ( time, s ) ->
+- if time >= ready_threshold then
+- raise BreakOutOfLoop;
+- incr ready_count
+- ) m.manager_sources.( q )
+- with BreakOutOfLoop -> ());
+- !ready_count
++ let count_file_ready_sources m q throttled =
++ let ready_count = ref 0 in
++ let throttle_delay = get_throttle_delay m q throttled in
++ let ready_threshold =
++ last_time () - !!min_reask_delay - throttle_delay in
++ (try
++ Queue.iter
++ (fun (time, s) ->
++ if time >= ready_threshold then raise BreakOutOfLoop;
++ incr ready_count
++ ) m.manager_sources.(q)
++ with BreakOutOfLoop -> ());
++ !ready_count
+
+ (*
+ * determine the total number of ready sources for all downloading files per queue
+ *)
+-let count_ready_sources queue throttled =
+- let ready_count = ref 0 in
+- List.iter
+- (fun m ->
+- let f = m.manager_file () in
+- if file_state f = FileDownloading then
+- ready_count := !ready_count + count_file_ready_sources m queue throttled
+- ) !file_sources_managers;
+- !ready_count
+-
+-
+-let rec find_max_overloaded q managers =
+- let current_max = ref (-1) in
+- let remaining_managers = ref [] in
+- List.iter
+- (fun m ->
+- let ready_sources = count_file_ready_sources m q true in
+- if ready_sources > !current_max then begin
+- current_max := ready_sources;
+- remaining_managers := [m]
+- end else if ready_sources = !current_max then
+- remaining_managers := m :: !remaining_managers
+- ) managers;
+- !remaining_managers
++ let count_ready_sources queue throttled =
++ List.fold_left (fun ready_count m ->
++ let f = m.manager_file () in
++ if file_state f = FileDownloading then
++ ready_count + count_file_ready_sources m queue throttled
++ else ready_count
++ ) 0 !file_sources_managers
++
++
++ let rec find_max_overloaded q managers =
++ let _, remaining_managers =
++ List.fold_left (fun ((current_max, remaining_managers) as acc) m ->
++ let ready_sources = count_file_ready_sources m q true in
++ if ready_sources > current_max then
++ (ready_sources, [m])
++ else if ready_sources = current_max then
++ (current_max, m :: remaining_managers)
++ else acc
++ ) (-1, []) managers in
++ remaining_managers
+
+
+ (*************************************************************************)
+@@ -408,19 +401,20 @@
+ (* *)
+ (*************************************************************************)
+
+- let print_source buf s =
+- Printf.bprintf buf "Source %d:\n" s.source_num;
+- Printf.bprintf buf " score: %d\n" s.source_score;
+- if s.source_age <> 0 then
+- Printf.bprintf buf " age: %d\n" s.source_age;
+- if s.source_last_attempt <> 0 then
+- Printf.bprintf buf " last_attemps: %d" s.source_last_attempt;
+- List.iter (fun r ->
+- Printf.bprintf buf " File %s\n" (file_best_name (r.request_file.manager_file ()));
+- Printf.bprintf buf " Score: %d\n" r.request_score;
+- if r.request_time <> 0 then
+- Printf.bprintf buf " Time: %d\n" r.request_time;
+- ) s.source_files
++ let print_source buf s =
++ Printf.bprintf buf "Source %d:\n" s.source_num;
++ Printf.bprintf buf " score: %d\n" s.source_score;
++ if s.source_age <> 0 then
++ Printf.bprintf buf " age: %d\n" s.source_age;
++ if s.source_last_attempt <> 0 then
++ Printf.bprintf buf " last_attemps: %d" s.source_last_attempt;
++ List.iter (fun r ->
++ Printf.bprintf buf " File %s\n"
++ (file_best_name (r.request_file.manager_file ()));
++ Printf.bprintf buf " Score: %d\n" r.request_score;
++ if r.request_time <> 0 then
++ Printf.bprintf buf " Time: %d\n" r.request_time;
++ ) s.source_files
+
+
+ (*
+@@ -429,33 +423,34 @@
+ *
+ *)
+
+- let need_new_sources file =
+- let ready_count = ref 0 in
+- for i = good_sources_queue to old_sources1_queue do
+- let lookin = file.manager_sources.( i ) in
+- let ready_threshold = last_time () - !!min_reask_delay in
+- Queue.iter
+- (fun (time, s) ->
+- if time < ready_threshold then
+- incr ready_count
+- ) lookin
+- done;
+- (* let work_count = !ready_count +
+- (Queue.length ( file.manager_sources.( new_sources_queue ) )) +
+- (Queue.length ( file.manager_sources.( connected_sources_queue ) ))
+- in *)
+- let f = file.manager_file () in
+- (* lprintf "commonSources: need_new_source: ready= %d new= %d con= %d prio= %d %s\n"
+- !readyCount
+- (Queue.length ( file.manager_sources.( new_sources_queue ) ) )
+- (Queue.length ( file.manager_sources.( connected_sources_queue ) ) )
+- (file_priority f)
+- (if (file_priority f) + 20 > workCount then "we need" else "have enough");
+- *)
+- (* (file_priority f) + 20 > work_count *)
+- (* let max_s = functions.function_max_sources_per_file () in
+- (file_priority f)*(max_s/20) + max_s > !all_ready_s + new_s *)
+- (file_priority f) + 20 > !ready_count
++ let need_new_sources file =
++ let ready_threshold = last_time () - !!min_reask_delay in
++ let ready_count = ref 0 in
++ for i = good_sources_queue to old_sources1_queue do
++ let lookin = file.manager_sources.(i) in
++ try
++ Queue.iter (fun (time, s) ->
++ if time >= ready_threshold then raise BreakOutOfLoop;
++ incr ready_count
++ ) lookin
++ with BreakOutOfLoop -> ()
++ done;
++ (* let work_count = !ready_count +
++ (Queue.length ( file.manager_sources.( new_sources_queue ) )) +
++ (Queue.length ( file.manager_sources.( connected_sources_queue ) ))
++ in *)
++ let f = file.manager_file () in
++ (* lprintf "commonSources: need_new_source: ready= %d new= %d con= %d prio= %d %s\n"
++ !readyCount
++ (Queue.length ( file.manager_sources.( new_sources_queue ) ) )
++ (Queue.length ( file.manager_sources.( connected_sources_queue ) ) )
++ (file_priority f)
++ (if (file_priority f) + 20 > workCount then "we need" else "have enough");
++ *)
++ (* (file_priority f) + 20 > work_count *)
++ (* let max_s = functions.function_max_sources_per_file () in
++ (file_priority f)*(max_s/20) + max_s > !all_ready_s + new_s *)
++ (file_priority f) + 20 > !ready_count
+
+
+ (*************************************************************************)
+@@ -465,444 +460,405 @@
+ (*************************************************************************)
+
+
+- let print buf output_type =
+- let pos_to_string v =
+- (if v > 0 then string_of_int(v) else "-")
+- in
+-
+- html_mods_cntr_init();
+- let mycntr = ref 1 in
+-
+- let html_tr () = begin
+- mycntr := html_mods_cntr();
+- Printf.bprintf buf "\\<tr class=\\\"dl-%d\\\"\\>" (!mycntr)
+- end
+- in
+- let html_tr_same () = Printf.bprintf buf "\\<tr class=\\\"dl-%d\\\"\\>" (!mycntr) in
+-
+- (* Header *)
+- if output_type = HTML then
+- begin
+-
+- let header = Printf.sprintf "File sources per manager queue (%d)" (List.length !file_sources_managers) in
+-
+- Printf.bprintf buf "\\<div class=results\\>";
+- html_mods_table_header buf "sourcesTable" "sources" [];
+- Printf.bprintf buf "\\<tr\\>";
+- html_mods_td buf [
+- ("", "srh", "Statistics on sources ");
+- ("", "srh", "@ " ^ log_time ());
+- ("", "srh", header); ];
+- Printf.bprintf buf "\\</tr\\>\\</table\\>\\</div\\>\n";
+-
+- html_mods_table_header buf "sourcesTable" "sources" [
+- ( "0", "srh br", "New sources", Printf.sprintf "New(%d)" new_sources_queue );
+- ( "0", "srh br", "Good sources", Printf.sprintf "Good(%d)" good_sources_queue );
+- ( "0", "srh br", "Ready saved sources", Printf.sprintf "Ready(%d)" ready_saved_sources_queue);
+- ( "0", "srh br", "Waiting saved sources", Printf.sprintf "Wait(%d)" waiting_saved_sources_queue);
+- ( "0", "srh br", "Old sources 1", Printf.sprintf "Old1(%d)" old_sources1_queue );
+- ( "0", "srh br", "Old sources 2", Printf.sprintf "Old2(%d)" old_sources2_queue );
+- ( "0", "srh br", "Old sources 3", Printf.sprintf "Old3(%d)" old_sources3_queue );
+- ( "0", "srh br", "Do not try sources", Printf.sprintf "nTry(%d)" do_not_try_queue );
+- ( "0", "srh br", "Connected sources", Printf.sprintf "Conn(%d)" connected_sources_queue );
+- ( "0", "srh br", "Connecting sources", Printf.sprintf "Cing(%d)" connecting_sources_queue );
+- ( "0", "srh br", "Busy sources", Printf.sprintf "Busy(%d)" busy_sources_queue );
+- ( "0", "srh br", "Total sources", "All" );
+- ( "0", "srh br", "Filename", "Name" ); ];
+- end
+- else
+- begin
+- Printf.bprintf buf "Statistics on sources: time %d\n" (last_time ());
+- Printf.bprintf buf "File sources per manager queue(%d):\n" (List.length !file_sources_managers);
+- Printf.bprintf buf "new good redy wait old1 old2 old3 ntry conn cing busy all\n";
+- (* "9999 9999 9999 9999 9999 9999 9999 9999 9999 9999 9999 9999"
+- 11*5 chars
+- one row each: all,indirect,ready*)
+- end;
+-
+- let nsources_per_queue = Array.create nqueues 0 in
+- let nready_per_queue = Array.create nqueues 0 in
+- let nindirect_per_queue = Array.create nqueues 0 in
+- let ninvalid_per_queue = Array.create nqueues 0 in
+- let nall = ref 0 in
+- let naact = ref 0 in
+- let naneed = ref 0 in
+- let my_file_sources_managers =
+- Sort.list
+- (fun f1 f2 ->
+- file_best_name (f1.manager_file ()) < file_best_name (f2.manager_file ())
+- ) (List.filter (fun m -> file_state (m.manager_file ()) = FileDownloading) !file_sources_managers)
+- in
+- (* Files *)
+- List.iter (fun m ->
+- let name = file_best_name (m.manager_file ()) in
+- if m.manager_all_sources <> 0 then
+- begin
+- let anready = ref 0 in
+- let antready = ref 0 in
+- let anindirect = ref 0 in
+- let aninvalid = ref 0 in
+- let slist = ref [] in
+- let sreadylist = ref [] in
+- let streadylist = ref [] in
+- let sindirectlist = ref [] in
+- let sinvalidlist = ref [] in
+- let sready = ref "" in
+- let stready = ref "" in
+- let sindirect = ref "" in
+- let sinvalid = ref "" in
+- (* Queues *)
+- for i = 0 to nqueues -1 do
+- let q = m.manager_sources.(i) in
+- if output_type = HTML then
+- slist := !slist @ [
+- ("", "sr ar br", (pos_to_string (Queue.length q))); ]
+- else
+- Printf.bprintf buf "%4d " (Queue.length q);
+-
+- let nready = ref 0 in
+- let nindirect = ref 0 in
+- let ninvalid = ref 0 in
+- let nsources = ref 0 in
+- let ready_threshold = last_time () - !!min_reask_delay in
+- (* Sources *)
+- Queue.iter (fun (time, s) ->
+- incr nsources;
+- if M.indirect_source s.source_uid then
+- incr nindirect
+- else if not (M.direct_source s.source_uid) then
+- incr ninvalid;
+- if time < ready_threshold then
+- incr nready
+- else if i = new_sources_queue then
+- begin
+- Printf.bprintf buf "ERROR: Source is not ready in new_sources_queue !\n";
+- print_source buf s
+- end
+- ) q;
+-
+- if output_type = HTML then
+- begin
+- sreadylist := !sreadylist @ [
+- ("", "sr ar br", (pos_to_string (Queue.length q))); ] ;
+- streadylist := !streadylist @ [
+- ("", "sr ar br", (pos_to_string (count_file_ready_sources m i true))); ] ;
+- sindirectlist := !sindirectlist @ [
+- ("", "sr ar br", (pos_to_string !nindirect)); ] ;
+- sinvalidlist := !sinvalidlist @ [
+- ("", "sr ar br", (pos_to_string !ninvalid)); ] ;
+- end
+- else
+- begin
+- sready := Printf.sprintf "%s%4d " !sready !nready;
+- stready := Printf.sprintf "%s%4d " !stready (count_file_ready_sources m i true);
+- sindirect := Printf.sprintf "%s%4d " !sindirect !nindirect;
+- sinvalid := Printf.sprintf "%s%4d " !sinvalid !ninvalid
+- end;
+-
+- anready := !anready + !nready;
+- antready := !antready + (count_file_ready_sources m i true);
+- anindirect := !anindirect + !nindirect;
+- aninvalid := !aninvalid + !ninvalid;
+- nready_per_queue.(i) <- nready_per_queue.(i) + !nready;
+- nindirect_per_queue.(i) <- nindirect_per_queue.(i) + !nindirect;
+- ninvalid_per_queue.(i) <- ninvalid_per_queue.(i) + !ninvalid;
+- nsources_per_queue.(i) <- nsources_per_queue.(i) + !nsources;
+-
+- done; (* end Queues *)
+-
+- if output_type = HTML then
+- begin
+- html_tr ();
+- html_mods_td buf (
+- !slist
+- @ [ ("", "sr ar br", Printf.sprintf "%d" m.manager_all_sources); ]
+- @ [ ("Filename", "sr", (shorten name !!max_name_len)); ] );
+-
+- Printf.bprintf buf "\\</tr\\>\n";
+-
+- html_tr_same ();
+- html_mods_td buf (
+- !sreadylist
+- @ [ ("", "sr ar br", Printf.sprintf "%d" !anready); ]
+- @ [ ("", "sr", ((Printf.sprintf "ready with %d active" m.manager_active_sources)
+- ^ (if file_state (m.manager_file ()) = FileDownloading
+- && need_new_sources m then
+- begin
+- incr naneed;
+- " and needs sources"
+- end
+- else "")
+- ));
+- ]
+- );
+- Printf.bprintf buf "\\</tr\\>\n";
+-
+- html_tr_same ();
+-
+- html_mods_td buf (
+- !streadylist
+- @ [ ("", "sr ar br", Printf.sprintf "%d" !antready); ]
+- @ [("", "sr", "throttled ready"); ]
+- );
+-
+- Printf.bprintf buf "\\</tr\\>\n";
+-
+- (if !anindirect <> 0 then
+- begin
+- html_tr_same ();
+- html_mods_td buf (
+- !sindirectlist
+- @ [ ("", "sr ar br", Printf.sprintf "%d" !anindirect); ]
+- @ [ ("", "sr", "indirect"); ]
+- );
+- Printf.bprintf buf "\\</tr\\>\n";
+- end
+- );
+-
+- (if !aninvalid <> 0 then
+- begin
+- html_tr_same ();
+- html_mods_td buf (
+- !sinvalidlist
+- @ [ ("", "sr ar br", Printf.sprintf "%d" !aninvalid); ]
+- @ [ ("", "sr", "invalid"); ]
+- );
+- Printf.bprintf buf "\\</tr\\>\n";
+- end
+- );
+- end
+- else
+- begin
+- Printf.bprintf buf "%4d %s\n" m.manager_all_sources name;
+- Printf.bprintf buf "%s%4d ready %d active%s\n" !sready !anready m.manager_active_sources
+- (if file_state (m.manager_file ()) = FileDownloading && need_new_sources m then
+- begin
+- incr naneed;
+- " needs sources"
+- end
+- else
+- ""
+- );
+- Printf.bprintf buf "%s%4d throttled ready\n" !stready !antready;
+- if !anindirect <> 0 then
+- Printf.bprintf buf "%s%4d indirect\n" !sindirect !anindirect;
+- if !aninvalid <> 0 then
+- Printf.bprintf buf "%s%4d invalid\n" !sinvalid !aninvalid;
+- end;
+-
+- nall := !nall + m.manager_all_sources;
+- naact := !naact + m.manager_active_sources;
+- end
+- else
+- begin
+-
+- if output_type = HTML then
+- begin
+- html_tr ();
+-
+- html_mods_td buf [
+- ("", "sr ar br", "-"); ("", "sr ar br", ""); ("", "sr ar br", "");
+- ("", "sr ar br", ""); ("", "sr ar br", ""); ("", "sr ar br", "");
+- ("", "sr ar br", ""); ("", "sr ar br", ""); ("", "sr ar br", "");
+- ("", "sr ar br", ""); ("", "sr ar br", ""); ("", "sr ar br", "");
+- ("", "sr br", (shorten name !!max_name_len));
+- ];
+- Printf.bprintf buf "\\</tr\\>\n";
+- end
+- else
+- Printf.bprintf buf "None %55s%s\n" ("") name;
+- if file_state (m.manager_file ()) = FileDownloading && need_new_sources m then
+- incr naneed;
+- end
+- ) my_file_sources_managers; (* end Files *)
+-
+- (* next Header *)
+- if output_type = HTML then
+- begin
+- Printf.bprintf buf "\\</table\\>\\</div\\>\n";
+-
+- html_mods_table_header buf "sourcesTable" "sources" [
+- ( "0", "srh", "New sources", "New" );
+- ( "0", "srh", "Good sources", "Good" );
+- ( "0", "srh", "Ready sources", "Ready" );
+- ( "0", "srh", "Waiting sources", "Wait" );
+- ( "0", "srh", "Old sources 1", "Old1" );
+- ( "0", "srh", "Old sources 2", "Old2" );
+- ( "0", "srh", "Old sources 3", "Old3" );
+- ( "0", "srh", "Do not try", "nTry" );
+- ( "0", "srh", "Connected sources", "Conn" );
+- ( "0", "srh", "Connecting sources", "Cing" );
+- ( "0", "srh", "Busy sources", "Busy" );
+- ( "0", "srh", "Total sources", "All" );
+- ( "0", "srh", "Type", "Type" ); ];
+-
+- end
+- else
+- Printf.bprintf buf "new good redy wait old1 old2 old3 ntry conn cing busy all\n";
+-
+- let slist = ref [] in
+- let sreadylist = ref [] in
+- let streadylist = ref [] in
+- let sindirectlist = ref [] in
+- let sinvalidlist = ref [] in
+- let speriodlist = ref [] in
+- let sready = ref "" in
+- let stready = ref "" in
+- let sindirect = ref "" in
+- let sinvalid = ref "" in
+- let speriod = ref "" in
+- let anready = ref 0 in
+- let antready = ref 0 in
+- let anindirect = ref 0 in
+- let aninvalid = ref 0 in
+- (* Queues *)
+- for i = 0 to nqueues - 1 do
+- if output_type = HTML then
+- begin
+- slist := !slist @ [
+- ("", "sr ar", (pos_to_string nsources_per_queue.(i))); ] ;
+- sreadylist := !sreadylist @ [
+- ("", "sr ar", (pos_to_string nready_per_queue.(i))); ] ;
+- anready := !anready + nready_per_queue.(i);
+- streadylist := !streadylist @ [
+- ("", "sr ar", (pos_to_string (count_ready_sources i true))); ] ;
+- antready := !antready + (count_ready_sources i true);
+- sindirectlist := !sindirectlist @ [
+- ("", "sr ar", (pos_to_string nindirect_per_queue.(i))); ] ;
+- anindirect := !anindirect + nindirect_per_queue.(i);
+- sinvalidlist := !sinvalidlist @ [
+- ("", "sr ar", (pos_to_string ninvalid_per_queue.(i))); ] ;
+- aninvalid := !aninvalid + ninvalid_per_queue.(i);
+- speriodlist := !speriodlist @ [
+- ("", "sr ar", (pos_to_string queue_period.(i))); ] ;
+- end
+- else
+- begin
+- Printf.bprintf buf "%4d " nsources_per_queue.(i);
+- sready := Printf.sprintf "%s%4d " !sready nready_per_queue.(i);
+- anready := !anready + nready_per_queue.(i);
+- stready := Printf.sprintf "%s%4d " !stready (count_ready_sources i true);
+- antready := !antready + (count_ready_sources i true);
+- sindirect := Printf.sprintf "%s%4d " !sindirect nindirect_per_queue.(i);
+- anindirect := !anindirect + nindirect_per_queue.(i);
+- sinvalid := Printf.sprintf "%s%4d " !sinvalid ninvalid_per_queue.(i);
+- aninvalid := !aninvalid + ninvalid_per_queue.(i);
+- speriod := Printf.sprintf "%s%4d " !speriod queue_period.(i);
+- end;
+- done; (* end Queues *)
+-
+- let nsources = ref 0 in
+- let nroq = ref 0 in
+- HS.iter (fun s ->
+- incr nsources;
+- List.iter (fun r ->
+- if r.request_queue = outside_queue then
+- incr nroq;
+- ) s.source_files;
+- ) sources_by_uid;
+-
+- if output_type = HTML then
+- begin
+- html_tr();
+- html_mods_td buf (
+- !slist
+- @ [ ("", "sr ar", Printf.sprintf "%d" !nall); ]
+- @ [("", "sr", Printf.sprintf "all source managers (%d by UID) (%d ROQ)" !nsources !nroq);]
+- );
+- Printf.bprintf buf "\\</tr\\>\n";
+-
+- html_tr ();
+- html_mods_td buf (
+- !sreadylist
+- @ [ ("", "sr ar", Printf.sprintf "%d" !anready); ]
+- @ [ ("", "sr", Printf.sprintf "ready with %d active and %i need sources" !naact !naneed); ]
+- );
+- Printf.bprintf buf "\\</tr\\>\n";
+-
+- html_tr();
+- html_mods_td buf (
+- !streadylist
+- @ [ ("", "sr ar", Printf.sprintf "%d" !antready); ]
+- @ [ ("", "sr", "throttled ready"); ]
+- );
+- Printf.bprintf buf "\\</tr\\>\n";
+-
+- (if !anindirect <> 0 then
+- begin
+- html_tr ();
+- html_mods_td buf (
+- !sindirectlist
+- @ [ ("", "sr ar", Printf.sprintf "%d" !anindirect); ]
+- @ [ ("", "sr", "indirect"); ]
+- );
+- Printf.bprintf buf "\\</tr\\>\n";
+- end
+- );
+-
+- (if !aninvalid <> 0 then
+- begin
+- html_tr ();
+- html_mods_td buf (
+- !sinvalidlist
+- @ [ ("", "sr ar", Printf.sprintf "%d" !aninvalid); ]
+- @ [ ("", "sr", "invalid"); ]
+- );
+- Printf.bprintf buf "\\</tr\\>\n";
+- end
+- );
+-
+- html_tr ();
+- html_mods_td buf (
+- !speriodlist
+- @ [ ("", "sr", "") ]
+- @ [("", "sr", "period"); ]
+- );
+- Printf.bprintf buf "\\</tr\\>\n";
+-
+- Printf.bprintf buf "\\</table\\>\\</div\\>\n";
+- end
+- else
+- begin
+- Printf.bprintf buf "%4d all source managers (%d by UID) (%d ROQ)\n" !nall !nsources !nroq;
+- Printf.bprintf buf "%s%4d ready %d active %i need sources\n" !sready !anready !naact !naneed;
+- Printf.bprintf buf "%s%4d throttled ready\n" !stready !antready;
+- if !anindirect <> 0 then
+- Printf.bprintf buf "%s%4d indirect\n" !sindirect !anindirect;
+- if !aninvalid <> 0 then
+- Printf.bprintf buf "%s%4d invalid\n" !sinvalid !aninvalid;
+- Printf.bprintf buf "%s period\n" !speriod;
+- end;
+- let nconnected = ref 0 in
+- Fifo.iter
+- (fun (_,s) ->
+- if s.source_last_attempt = 0 then incr nconnected;
+- ) connecting_sources;
+- if output_type = HTML then
+- begin
+- html_mods_table_header buf "sourcesTable" "sources" [
+- ( "0", "srh", "Connecting sources", "Connecting sources" );
+- ( "0", "srh", "Next direct sources", "Next direct sources" );
+- ( "0", "srh", "Next indirect sources", "Next indirect sources" ); ];
+- Printf.bprintf buf "\\<tr class=\\\"dl-1\\\"\\>";
+- html_mods_td buf [
+- ("", "sr", (Printf.sprintf "%d entries" (Fifo.length connecting_sources)) ^
+- (if !nconnected > 0 then Printf.sprintf " (connected: %d)" !nconnected else ("")));
+- ("", "sr", Printf.sprintf "%d entries" (Fifo.length next_direct_sources));
+- ("", "sr", Printf.sprintf "%d entries" (List.length !next_indirect_sources)); ];
+- Printf.bprintf buf "\\</tr\\>\\</table\\>\\</div\\>\n\\</div\\>"
+- end
+- else
+- begin
+- Printf.bprintf buf "Connecting Sources: %d entries"
+- (Fifo.length connecting_sources);
+- if !nconnected > 0 then Printf.bprintf buf " (connected: %d)" !nconnected;
+- Printf.bprintf buf "\n";
+- Printf.bprintf buf "Next Direct Sources: %d entries\n"
+- (Fifo.length next_direct_sources);
+- Printf.bprintf buf "Next Indirect Sources: %d entries\n"
+- (List.length !next_indirect_sources)
+- end
++ let print buf output_type =
++ let pos_to_string v =
++ if v > 0 then string_of_int v else "-" in
++
++ html_mods_cntr_init ();
++ let mycntr = ref 1 in
++
++ let html_tr () =
++ mycntr := html_mods_cntr ();
++ Printf.bprintf buf "\\<tr class=\\\"dl-%d\\\"\\>" !mycntr in
++
++ let html_tr_same () =
++ Printf.bprintf buf "\\<tr class=\\\"dl-%d\\\"\\>" !mycntr in
++
++ (* Header *)
++ if output_type = HTML then
++ let header = Printf.sprintf "File sources per manager queue (%d)"
++ (List.length !file_sources_managers) in
++
++ Printf.bprintf buf "\\<div class=results\\>";
++ html_mods_table_header buf "sourcesTable" "sources" [];
++ Printf.bprintf buf "\\<tr\\>";
++ html_mods_td buf [
++ ("", "srh", "Statistics on sources ");
++ ("", "srh", "@ " ^ log_time ());
++ ("", "srh", header); ];
++ Printf.bprintf buf "\\</tr\\>\\</table\\>\\</div\\>\n";
++
++ html_mods_table_header buf "sourcesTable" "sources" [
++ ( "0", "srh br", "New sources",
++ Printf.sprintf "New(%d)" new_sources_queue );
++ ( "0", "srh br", "Good sources",
++ Printf.sprintf "Good(%d)" good_sources_queue );
++ ( "0", "srh br", "Ready saved sources",
++ Printf.sprintf "Ready(%d)" ready_saved_sources_queue);
++ ( "0", "srh br", "Waiting saved sources",
++ Printf.sprintf "Wait(%d)" waiting_saved_sources_queue);
++ ( "0", "srh br", "Old sources 1",
++ Printf.sprintf "Old1(%d)" old_sources1_queue );
++ ( "0", "srh br", "Old sources 2",
++ Printf.sprintf "Old2(%d)" old_sources2_queue );
++ ( "0", "srh br", "Old sources 3",
++ Printf.sprintf "Old3(%d)" old_sources3_queue );
++ ( "0", "srh br", "Do not try sources",
++ Printf.sprintf "nTry(%d)" do_not_try_queue );
++ ( "0", "srh br", "Connected sources",
++ Printf.sprintf "Conn(%d)" connected_sources_queue );
++ ( "0", "srh br", "Connecting sources",
++ Printf.sprintf "Cing(%d)" connecting_sources_queue );
++ ( "0", "srh br", "Busy sources",
++ Printf.sprintf "Busy(%d)" busy_sources_queue );
++ ( "0", "srh br", "Total sources", "All" );
++ ( "0", "srh br", "Filename", "Name" ); ];
++ else begin
++ Printf.bprintf buf "Statistics on sources: time %d\n" (last_time ());
++ Printf.bprintf buf "File sources per manager queue(%d):\n"
++ (List.length !file_sources_managers);
++ Printf.bprintf buf "new good redy wait old1 old2 old3 ntry conn cing busy all\n";
++ (* "9999 9999 9999 9999 9999 9999 9999 9999 9999 9999 9999 9999"
++ 11*5 chars
++ one row each: all,indirect,ready *)
++ end;
++
++ let list_sum = List.fold_left (+) 0 in
++
++ let nsources_per_queue = Array.create nqueues 0 in
++ let nready_per_queue = Array.create nqueues 0 in
++ let nindirect_per_queue = Array.create nqueues 0 in
++ let ninvalid_per_queue = Array.create nqueues 0 in
++ let nall = ref 0 in
++ let naact = ref 0 in
++ let naneed = ref 0 in
++ let downloading_managers =
++ List.filter (fun m ->
++ file_state (m.manager_file ()) = FileDownloading
++ ) !file_sources_managers in
++ let my_file_sources_managers =
++ List.sort (fun f1 f2 ->
++ let best_name1 = file_best_name (f1.manager_file ()) in
++ let best_name2 = file_best_name (f2.manager_file ()) in
++ String.compare best_name1 best_name2
++ ) downloading_managers in
++ (* Files *)
++ let ready_threshold = last_time () - !!min_reask_delay in
++ List.iter (fun m ->
++ let name = file_best_name (m.manager_file ()) in
++ let need_sources = need_new_sources m in
++ if need_sources then incr naneed;
++
++ if m.manager_all_sources <> 0 then begin
++ let slist = ref [] in
++ let sreadylist = ref [] in
++ let streadylist = ref [] in
++ let sindirectlist = ref [] in
++ let sinvalidlist = ref [] in
++ (* Queues *)
++ Array.iteri (fun i q ->
++ let nready = ref 0 in
++ let ntready = count_file_ready_sources m i true in
++ let nindirect = ref 0 in
++ let ninvalid = ref 0 in
++ let nsources = ref 0 in
++ (* Sources *)
++ Queue.iter (fun (time, s) ->
++ incr nsources;
++ if M.indirect_source s.source_uid then incr nindirect
++ else if not (M.direct_source s.source_uid) then incr ninvalid;
++ if time < ready_threshold then incr nready
++ else if i = new_sources_queue then begin
++ Printf.bprintf buf "ERROR: Source is not ready in new_sources_queue !\n";
++ print_source buf s
++ end
++ ) q;
++
++ slist := Queue.length q :: !slist;
++ sreadylist := !nready :: !sreadylist;
++ streadylist := ntready :: !streadylist;
++ sindirectlist := !nindirect :: !sindirectlist;
++ sinvalidlist := !ninvalid :: !sinvalidlist;
++
++ nready_per_queue.(i) <- nready_per_queue.(i) + !nready;
++ nindirect_per_queue.(i) <- nindirect_per_queue.(i) + !nindirect;
++ ninvalid_per_queue.(i) <- ninvalid_per_queue.(i) + !ninvalid;
++ nsources_per_queue.(i) <- nsources_per_queue.(i) + !nsources;
++ ) m.manager_sources; (* end Queues *)
++
++ let slist = List.rev !slist in
++ let sreadylist = List.rev !sreadylist in
++ let streadylist = List.rev !streadylist in
++ let sindirectlist = List.rev !sindirectlist in
++ let sinvalidlist = List.rev !sinvalidlist in
++
++ if output_type = HTML then begin
++ html_tr ();
++ html_mods_td buf (
++ (List.map (fun qlength ->
++ ("", "sr ar br", pos_to_string qlength)) slist) @
++ [ ("", "sr ar br", string_of_int m.manager_all_sources);
++ ("Filename", "sr", shorten name !!max_name_len); ] );
++
++ Printf.bprintf buf "\\</tr\\>\n";
++
++ html_tr_same ();
++ html_mods_td buf (
++ (List.map (fun sready ->
++ ("", "sr ar br", pos_to_string sready)) sreadylist) @
++ [ ("", "sr ar br", Printf.sprintf "%d" (list_sum sreadylist));
++ ("", "sr", Printf.sprintf "ready with %d active%s"
++ m.manager_active_sources
++ (if need_sources then " and needs sources"
++ else "")) ] );
++ Printf.bprintf buf "\\</tr\\>\n";
++
++ html_tr_same ();
++ html_mods_td buf (
++ (List.map (fun sready ->
++ ("", "sr ar br", pos_to_string sready)) streadylist) @
++ [ ("", "sr ar br", string_of_int (list_sum streadylist));
++ ("", "sr", "throttled ready"); ] );
++ Printf.bprintf buf "\\</tr\\>\n";
++
++ let anindirect = list_sum sindirectlist in
++ if anindirect <> 0 then begin
++ html_tr_same ();
++ html_mods_td buf (
++ (List.map (fun sready ->
++ ("", "sr ar br", pos_to_string sready)) sindirectlist) @
++ [ ("", "sr ar br", string_of_int anindirect);
++ ("", "sr", "indirect"); ] );
++ Printf.bprintf buf "\\</tr\\>\n";
++ end;
++
++ let aninvalid = list_sum sinvalidlist in
++ if aninvalid <> 0 then begin
++ html_tr_same ();
++ html_mods_td buf (
++ (List.map (fun sready ->
++ ("", "sr ar br", pos_to_string sready)) sinvalidlist) @
++ [ ("", "sr ar br", string_of_int aninvalid);
++ ("", "sr", "invalid"); ] );
++ Printf.bprintf buf "\\</tr\\>\n";
++ end;
++ end
++ else begin
++ List.iter (Printf.bprintf buf "%4d ") slist;
++ Printf.bprintf buf "%4d %s\n" m.manager_all_sources name;
++ List.iter (Printf.bprintf buf "%4d ") sreadylist;
++ Printf.bprintf buf "%4d ready %d active%s\n"
++ (list_sum sreadylist) m.manager_active_sources
++ (if need_sources then " needs sources"
++ else "");
++ List.iter (Printf.bprintf buf "%4d ") streadylist;
++ Printf.bprintf buf "%4d throttled ready\n"
++ (list_sum streadylist);
++ let anindirect = list_sum sindirectlist in
++ if anindirect <> 0 then begin
++ List.iter (Printf.bprintf buf "%4d ") sindirectlist;
++ Printf.bprintf buf "%4d indirect\n" anindirect;
++ end;
++ let aninvalid = list_sum sinvalidlist in
++ if aninvalid <> 0 then begin
++ List.iter (Printf.bprintf buf "%4d ") sinvalidlist;
++ Printf.bprintf buf "%4d invalid\n" aninvalid;
++ end
++ end;
++
++ nall := !nall + m.manager_all_sources;
++ naact := !naact + m.manager_active_sources;
++ end
++ else begin (* m.manager_all_sources = 0 *)
++ if output_type = HTML then begin
++ html_tr ();
++
++ html_mods_td buf [
++ ("", "sr ar br", "-"); ("", "sr ar br", "");
++ ("", "sr ar br", ""); ("", "sr ar br", "");
++ ("", "sr ar br", ""); ("", "sr ar br", "");
++ ("", "sr ar br", ""); ("", "sr ar br", "");
++ ("", "sr ar br", ""); ("", "sr ar br", "");
++ ("", "sr ar br", ""); ("", "sr ar br", "");
++ ("", "sr br", shorten name !!max_name_len); ];
++ Printf.bprintf buf "\\</tr\\>\n";
++ end
++ else Printf.bprintf buf "None %55s%s\n" "" name;
++ end
++ ) my_file_sources_managers; (* end Files *)
++
++ (* next Header *)
++ if output_type = HTML then begin
++ Printf.bprintf buf "\\</table\\>\\</div\\>\n";
++
++ html_mods_table_header buf "sourcesTable" "sources" [
++ ( "0", "srh", "New sources", "New" );
++ ( "0", "srh", "Good sources", "Good" );
++ ( "0", "srh", "Ready sources", "Ready" );
++ ( "0", "srh", "Waiting sources", "Wait" );
++ ( "0", "srh", "Old sources 1", "Old1" );
++ ( "0", "srh", "Old sources 2", "Old2" );
++ ( "0", "srh", "Old sources 3", "Old3" );
++ ( "0", "srh", "Do not try", "nTry" );
++ ( "0", "srh", "Connected sources", "Conn" );
++ ( "0", "srh", "Connecting sources", "Cing" );
++ ( "0", "srh", "Busy sources", "Busy" );
++ ( "0", "srh", "Total sources", "All" );
++ ( "0", "srh", "Type", "Type" ); ];
++
++ end
++ else
++ Printf.bprintf buf "new good redy wait old1 old2 old3 ntry conn cing busy all\n";
++
++ let slist = ref [] in
++ let sreadylist = ref [] in
++ let streadylist = ref [] in
++ let sindirectlist = ref [] in
++ let sinvalidlist = ref [] in
++ let speriodlist = ref [] in
++ (* Queues *)
++ for i = 0 to nqueues - 1 do
++ slist := nsources_per_queue.(i) :: !slist;
++ sreadylist := nready_per_queue.(i) :: !sreadylist;
++ streadylist := count_ready_sources i true :: !streadylist;
++ sindirectlist := nindirect_per_queue.(i) :: !sindirectlist;
++ sinvalidlist := ninvalid_per_queue.(i) :: !sinvalidlist;
++ speriodlist := queue_period.(i) :: !speriodlist;
++ done; (* end Queues *)
++
++ let nsources = ref 0 in
++ let nroq = ref 0 in
++ HS.iter (fun s ->
++ incr nsources;
++ List.iter (fun r ->
++ if r.request_queue = outside_queue then
++ incr nroq;
++ ) s.source_files;
++ ) sources_by_uid;
++
++ let slist = List.rev !slist in
++ let sreadylist = List.rev !sreadylist in
++ let streadylist = List.rev !streadylist in
++ let sindirectlist = List.rev !sindirectlist in
++ let sinvalidlist = List.rev !sinvalidlist in
++ let speriodlist = List.rev !speriodlist in
++
++ if output_type = HTML then begin
++ html_tr ();
++ html_mods_td buf (
++ (List.map (fun q ->
++ ("", "sr ar", pos_to_string q)) slist) @
++ [ ("", "sr ar", Printf.sprintf "%d" !nall);
++ ("", "sr",
++ Printf.sprintf "all source managers (%d by UID) (%d ROQ)"
++ !nsources !nroq);] );
++ Printf.bprintf buf "\\</tr\\>\n";
++
++ html_tr ();
++ html_mods_td buf (
++ (List.map (fun sready ->
++ ("", "sr ar", pos_to_string sready)) sreadylist) @
++ [ ("", "sr ar", Printf.sprintf "%d" (list_sum sreadylist));
++ ("", "sr",
++ Printf.sprintf "ready with %d active and %i need sources"
++ !naact !naneed); ] );
++ Printf.bprintf buf "\\</tr\\>\n";
++
++ html_tr ();
++ html_mods_td buf (
++ (List.map (fun sready ->
++ ("", "sr ar", pos_to_string sready)) streadylist) @
++ [ ("", "sr ar", Printf.sprintf "%d" (list_sum streadylist));
++ ("", "sr", "throttled ready"); ] );
++ Printf.bprintf buf "\\</tr\\>\n";
++
++ let anindirect = list_sum sindirectlist in
++ if anindirect <> 0 then begin
++ html_tr ();
++ html_mods_td buf (
++ (List.map (fun sready ->
++ ("", "sr ar", pos_to_string sready)) sindirectlist) @
++ [ ("", "sr ar", Printf.sprintf "%d" anindirect);
++ ("", "sr", "indirect"); ] );
++ Printf.bprintf buf "\\</tr\\>\n";
++ end;
++
++ let aninvalid = list_sum sinvalidlist in
++ if aninvalid <> 0 then begin
++ html_tr ();
++ html_mods_td buf (
++ (List.map (fun sready ->
++ ("", "sr ar", pos_to_string sready)) sinvalidlist) @
++ [ ("", "sr ar", Printf.sprintf "%d" aninvalid);
++ ("", "sr", "invalid"); ] );
++ Printf.bprintf buf "\\</tr\\>\n";
++ end;
++
++ html_tr ();
++ html_mods_td buf (
++ (List.map (fun sready ->
++ ("", "sr ar", pos_to_string sready)) speriodlist) @
++ [ ("", "sr", "");
++ ("", "sr", "period"); ] );
++ Printf.bprintf buf "\\</tr\\>\n";
++
++ Printf.bprintf buf "\\</table\\>\\</div\\>\n";
++ end
++ else begin
++ List.iter (Printf.bprintf buf "%4d ") slist;
++ Printf.bprintf buf "%4d all source managers (%d by UID) (%d ROQ)\n"
++ !nall !nsources !nroq;
++ List.iter (Printf.bprintf buf "%4d ") sreadylist;
++ Printf.bprintf buf "%4d ready %d active %i need sources\n"
++ (list_sum sreadylist) !naact !naneed;
++ List.iter (Printf.bprintf buf "%4d ") streadylist;
++ Printf.bprintf buf "%4d throttled ready\n" (list_sum streadylist);
++ let anindirect = list_sum sindirectlist in
++ if anindirect <> 0 then begin
++ List.iter (Printf.bprintf buf "%4d ") sindirectlist;
++ Printf.bprintf buf "%4d indirect\n" anindirect;
++ end;
++ let aninvalid = list_sum sinvalidlist in
++ if aninvalid <> 0 then begin
++ List.iter (Printf.bprintf buf "%4d ") sinvalidlist;
++ Printf.bprintf buf "%4d invalid\n" aninvalid;
++ end;
++ List.iter (Printf.bprintf buf "%4d ") speriodlist;
++ Printf.bprintf buf " period\n";
++ end;
++
++ let nconnected = ref 0 in
++ Fifo.iter (fun (_, s) ->
++ if s.source_last_attempt = 0 then incr nconnected;
++ ) connecting_sources;
++ if output_type = HTML then begin
++ html_mods_table_header buf "sourcesTable" "sources" [
++ ( "0", "srh", "Connecting sources", "Connecting sources" );
++ ( "0", "srh", "Next direct sources", "Next direct sources" );
++ ( "0", "srh", "Next indirect sources", "Next indirect sources" ); ];
++ Printf.bprintf buf "\\<tr class=\\\"dl-1\\\"\\>";
++ html_mods_td buf [
++ ("", "sr", (Printf.sprintf "%d entries"
++ (Fifo.length connecting_sources)) ^
++ (if !nconnected > 0 then
++ Printf.sprintf " (connected: %d)" !nconnected else ""));
++ ("", "sr", Printf.sprintf "%d entries"
++ (Fifo.length next_direct_sources));
++ ("", "sr", Printf.sprintf "%d entries"
++ (List.length !next_indirect_sources)); ];
++ Printf.bprintf buf "\\</tr\\>\\</table\\>\\</div\\>\n\\</div\\>"
++ end
++ else begin
++ Printf.bprintf buf "Connecting Sources: %d entries"
++ (Fifo.length connecting_sources);
++ if !nconnected > 0 then
++ Printf.bprintf buf " (connected: %d)" !nconnected;
++ Printf.bprintf buf "\n";
++ Printf.bprintf buf "Next Direct Sources: %d entries\n"
++ (Fifo.length next_direct_sources);
++ Printf.bprintf buf "Next Indirect Sources: %d entries\n"
++ (List.length !next_indirect_sources)
++ end
+
+
+ (*************************************************************************)
+@@ -911,55 +867,41 @@
+ (* *)
+ (*************************************************************************)
+
+- let reschedule_source_for_file saved s r =
+- if r.request_queue = outside_queue then
+- let queue =
+- if r.request_score = not_found_score then
+- do_not_try_queue
+- else if s.source_last_attempt <> 0 then
+- connecting_sources_queue
+- else
+- match s.source_sock with
+- | (NoConnection | ConnectionWaiting _) ->
+- (* State (1) *)
+- (* Two things matter: the global score and the local score *)
+- if s.source_score < 1 then
+- (* 2.5.25, replaced expected_score by
+- found_score, so that sources which
+- only have the file are not put in
+- good_sources_queue, unless they have
+- an interesting chunk AND not a bad
+- rank. *)
+- if r.request_score > found_score then
+- if saved then
+- if
+- r.request_time + !!min_reask_delay < last_time ()
+- then
+- ready_saved_sources_queue
+- else
+- waiting_saved_sources_queue
+- else
+- if r.request_score = initial_new_source_score then
+- new_sources_queue
+- else
+- good_sources_queue
+- else
+- if r.request_score >= new_source_score then
+- old_sources1_queue
+- else
+- old_sources2_queue
+- else
+- if s.source_score < 5 then
+- old_sources3_queue
+- else
+- do_not_try_queue
+-
+- | Connection _ ->
+- (* State (3) *)
+- if r.request_time = 0 then
+- busy_sources_queue
+- else
+- connected_sources_queue
++ let reschedule_source_for_file saved s r =
++ if r.request_queue = outside_queue then
++ let queue =
++ if r.request_score = not_found_score then do_not_try_queue
++ else if s.source_last_attempt <> 0 then connecting_sources_queue
++ else
++ match s.source_sock with
++ | (NoConnection | ConnectionWaiting _) ->
++ (* State (1) *)
++ (* Two things matter: the global score and the local score *)
++ if s.source_score < 1 then
++ (* 2.5.25, replaced expected_score by
++ found_score, so that sources which
++ only have the file are not put in
++ good_sources_queue, unless they have
++ an interesting chunk AND not a bad
++ rank. *)
++ if r.request_score > found_score then
++ if saved then
++ if r.request_time + !!min_reask_delay < last_time () then
++ ready_saved_sources_queue
++ else waiting_saved_sources_queue
++ else if r.request_score = initial_new_source_score then
++ new_sources_queue
++ else good_sources_queue
++ else if r.request_score >= new_source_score then
++ old_sources1_queue
++ else old_sources2_queue
++ else if s.source_score < 5 then old_sources3_queue
++ else do_not_try_queue
++
++ | Connection _ ->
++ (* State (3) *)
++ if r.request_time = 0 then busy_sources_queue
++ else connected_sources_queue
+ in
+ let m = r.request_file in
+ if !verbose_sources > 1 then
+@@ -977,18 +919,18 @@
+ (* *)
+ (*************************************************************************)
+
+- let iter_all_sources f m =
+- Array.iter (fun q ->
+- Queue.iter (fun (_,s) -> f s) q
+- ) m.manager_sources
++ let iter_all_sources f m =
++ Array.iter (fun q ->
++ Queue.iter (fun (_, s) -> f s) q
++ ) m.manager_sources
+
+ (*************************************************************************)
+ (* iter_qualified_sources *)
+ (* Only these sources should be used in sourceexchage *)
+ (*************************************************************************)
+- let iter_qualified_sources f m =
+- let q = m.manager_sources.(good_sources_queue) in
+- Queue.iter (fun (_,s) -> f s) q
++ let iter_qualified_sources f m =
++ let q = m.manager_sources.(good_sources_queue) in
++ Queue.iter (fun (_, s) -> f s) q
+
+ (*************************************************************************)
+ (* *)
+@@ -996,23 +938,23 @@
+ (* *)
+ (*************************************************************************)
+
+- let iter_active_sources f m =
+- for i = connected_sources_queue to busy_sources_queue do
+- let q = m.manager_sources.(i) in
+- Queue.iter (fun (_,s) -> f s) q
+- done
++ let iter_active_sources f m =
++ for i = connected_sources_queue to busy_sources_queue do
++ let q = m.manager_sources.(i) in
++ Queue.iter (fun (_, s) -> f s) q
++ done
+
+ (*************************************************************************)
+ (* *)
+ (* iter_relevant_sources *)
+ (* *)
+ (*************************************************************************)
+- let iter_relevant_sources f m =
+- List.iter (fun i ->
+- if i < nqueues then
+- let q = m.manager_sources.(i) in
+- Queue.iter (fun (_,s) -> f s) q
+- ) !!relevant_queues
++ let iter_relevant_sources f m =
++ List.iter (fun i ->
++ if i < nqueues then
++ let q = m.manager_sources.(i) in
++ Queue.iter (fun (_, s) -> f s) q
++ ) !!relevant_queues
+
+ (*************************************************************************)
+ (* *)
+@@ -1020,8 +962,8 @@
+ (* *)
+ (*************************************************************************)
+
+- let set_source_brand s brand =
+- s.source_brand <- brand
++ let set_source_brand s brand =
++ s.source_brand <- brand
+
+ (*************************************************************************)
+ (* *)
+@@ -1029,7 +971,7 @@
+ (* *)
+ (*************************************************************************)
+
+- let source_brand s = s.source_brand
++ let source_brand s = s.source_brand
+
+ (*************************************************************************)
+ (* *)
+@@ -1037,20 +979,20 @@
+ (* *)
+ (*************************************************************************)
+
+- let remove_from_queue s r =
+- if r.request_queue <> outside_queue then begin
+- if !verbose_sources > 1 then
+- lprintf_nl "[cSrc] Remove source %d from queue %s" s.source_num
+- queue_name.(r.request_queue);
+-
+- let m = r.request_file in
+- if active_queue r.request_queue then
+- m.manager_active_sources <- m.manager_active_sources - 1;
+- Queue.remove r.request_file.manager_sources.(r.request_queue)
+- (r.request_time, s);
+- r.request_queue <- outside_queue;
+- m.manager_all_sources <- m.manager_all_sources - 1
+- end
++ let remove_from_queue s r =
++ if r.request_queue <> outside_queue then begin
++ if !verbose_sources > 1 then
++ lprintf_nl "[cSrc] Remove source %d from queue %s" s.source_num
++ queue_name.(r.request_queue);
++
++ let m = r.request_file in
++ if active_queue r.request_queue then
++ m.manager_active_sources <- m.manager_active_sources - 1;
++ Queue.remove r.request_file.manager_sources.(r.request_queue)
++ (r.request_time, s);
++ r.request_queue <- outside_queue;
++ m.manager_all_sources <- m.manager_all_sources - 1
++ end
+
+ (*************************************************************************)
+ (* *)
+@@ -1059,15 +1001,15 @@
+ (*************************************************************************)
+
+ (* From state (1) to state (2) *)
+- let source_connecting s =
+- s.source_last_attempt <- last_time ();
+- Fifo.put connecting_sources (s.source_last_attempt, s);
+- List.iter (fun r ->
+- if r.request_queue <> outside_queue then begin
+- remove_from_queue s r;
+- reschedule_source_for_file false s r;
+- end
+- ) s.source_files
++ let source_connecting s =
++ s.source_last_attempt <- last_time ();
++ Fifo.put connecting_sources (s.source_last_attempt, s);
++ List.iter (fun r ->
++ if r.request_queue <> outside_queue then begin
++ remove_from_queue s r;
++ reschedule_source_for_file false s r;
++ end
++ ) s.source_files
+
+
+ (*************************************************************************)
+@@ -1076,18 +1018,17 @@
+ (* *)
+ (*************************************************************************)
+
+- let source_query s r =
+- remove_from_queue s r;
+- if r.request_score > not_found_score then
+- (* query_files will query all files for a source, check that we are
+- realy downloading! example source s has file f1 and file f2,
+- file f2 is paused we connect because of f1 and then query both
+- files f1 and f2 ... and yes, we do a cleanup ... but a timed one,
+- so we can't be sure *)
+- if r.request_score > not_found_score
+- && file_state (r.request_file.manager_file ()) = FileDownloading
+- then
+- begin
++ let source_query s r =
++ remove_from_queue s r;
++ if r.request_score > not_found_score then
++ (* query_files will query all files for a source, check that we are
++ realy downloading! example source s has file f1 and file f2,
++ file f2 is paused we connect because of f1 and then query both
++ files f1 and f2 ... and yes, we do a cleanup ... but a timed one,
++ so we can't be sure *)
++ if r.request_score > not_found_score &&
++ file_state (r.request_file.manager_file ()) = FileDownloading
++ then begin
+ r.request_time <- 0; (* The source is ready for this request *)
+ reschedule_source_for_file false s r; (* put it in busy_sources_queue *)
+ (try
+@@ -1104,30 +1045,30 @@
+ (*************************************************************************)
+
+ (* From state (2) to state (3) *)
+- let source_connected s =
+- s.source_score <- 0;
+- s.source_age <- last_time ();
+- s.source_last_attempt <- 0;
+- List.iter (fun r ->
++ let source_connected s =
++ s.source_score <- 0;
++ s.source_age <- last_time ();
++ s.source_last_attempt <- 0;
++ List.iter (fun r ->
+ (* lprintf "SOURCE> request: "; *)
+- if r.request_queue <> outside_queue then begin
++ if r.request_queue <> outside_queue then begin
+ (* lprintf "score %d/%d last query %s\n"
+ r.request_score possible_score
+ (if r.request_time = 0 then "never" else
+ Printf.sprintf "%d secs"
+ (last_time () - r.request_time)); *)
+- remove_from_queue s r;
+- if r.request_score > possible_score &&
+- r.request_time + !!min_reask_delay < last_time () then
+- source_query s r;
+- (try
+- let m = r.request_file in
+- functions.function_add_location s.source_uid
+- m.manager_uid with _ -> ());
+- reschedule_source_for_file false s r
+- end (* else
+- lprintf "outside queue\n" *)
+- ) s.source_files
++ remove_from_queue s r;
++ if r.request_score > possible_score &&
++ r.request_time + !!min_reask_delay < last_time () then
++ source_query s r;
++ (try
++ let m = r.request_file in
++ functions.function_add_location s.source_uid
++ m.manager_uid with _ -> ());
++ reschedule_source_for_file false s r
++ end
++ (* else lprintf "outside queue\n" *)
++ ) s.source_files
+
+ (*************************************************************************)
+ (* *)
+@@ -1136,53 +1077,49 @@
+ (*************************************************************************)
+
+ (* From states (1) or (2) to state (3) *)
+- let source_disconnected s =
+- (match s.source_sock with
+- NoConnection -> ()
+- | ConnectionWaiting token ->
+- cancel_token token;
+- s.source_sock <- NoConnection
+- | Connection sock ->
+- close sock Closed_for_timeout
+- );
+- let connecting = s.source_last_attempt <> 0 in
+- (* source_last_attempt set to time, on connect_reply set
+- to zero. if we never reached connect_reply, the ip is
+- dead. Then we think we were *not* trying to connect
+- later on ...
+- *)
+- s.source_last_attempt <- 0;
+- List.iter (fun r ->
+- if r.request_queue <> outside_queue then
+- begin
+- remove_from_queue s r;
+- if connecting then
+- begin
+- r.request_time <- last_time ();
+- if r.request_score = initial_new_source_score then
+- set_score_part r new_source_score
+- end
+- else
+- begin
+- if r.request_time = 0 then
+- (* we think we were not connecting,
+- but in some cases we were! and
+- now we imidiately reconnect for
+- that file, on a dead IP??
+- r.request_time <- last_time () - 600;
+- try this instead:
+- *)
+- r.request_time <- last_time ();
+- (try
+- let m = r.request_file in
+- functions.function_remove_location s.source_uid
+- m.manager_uid
+- with _ -> ()
+- )
+- end;
+- reschedule_source_for_file false s r;
+- end;
+- ) s.source_files
++ let source_disconnected s =
++ (match s.source_sock with
++ | NoConnection -> ()
++ | ConnectionWaiting token ->
++ cancel_token token;
++ s.source_sock <- NoConnection
++ | Connection sock ->
++ close sock Closed_for_timeout
++ );
++ let connecting = s.source_last_attempt <> 0 in
++ (* source_last_attempt set to time, on connect_reply set
++ to zero. if we never reached connect_reply, the ip is
++ dead. Then we think we were *not* trying to connect
++ later on ...
++ *)
++ s.source_last_attempt <- 0;
++ List.iter (fun r ->
++ if r.request_queue <> outside_queue then begin
++ remove_from_queue s r;
++ if connecting then begin
++ r.request_time <- last_time ();
++ if r.request_score = initial_new_source_score then
++ set_score_part r new_source_score
++ end
++ else begin
++ if r.request_time = 0 then
++ (* we think we were not connecting,
++ but in some cases we were! and
++ now we imidiately reconnect for
++ that file, on a dead IP??
++ r.request_time <- last_time () - 600;
++ try this instead:
++ *)
++ r.request_time <- last_time ();
++ (try
++ let m = r.request_file in
++ functions.function_remove_location s.source_uid
++ m.manager_uid
++ with _ -> ())
++ end;
++ reschedule_source_for_file false s r;
++ end;
++ ) s.source_files
+
+ (*************************************************************************)
+ (* *)
+@@ -1190,11 +1127,11 @@
+ (* *)
+ (*************************************************************************)
+
+- let connect_source s =
+- if !verbose_sources > 1 then
+- lprintf_nl "[cSrc] connect_source";
+- s.source_score <- s.source_score + 1;
+- functions.function_connect s.source_uid
++ let connect_source s =
++ if !verbose_sources > 1 then
++ lprintf_nl "[cSrc] connect_source";
++ s.source_score <- s.source_score + 1;
++ functions.function_connect s.source_uid
+
+ (*************************************************************************)
+ (* *)
+@@ -1202,40 +1139,40 @@
+ (* *)
+ (*************************************************************************)
+
+- let create_queues () =
+- let queues = [|
+- (* New sources *)
+- (* We should change this to 'oldest_last' to improve Queue.remove *)
+- (* instead of lifo *)
+- SourcesQueueCreate.oldest_last ();
+- (* Good sources *)
+- (* We should change this to 'oldest_first' to improve Queue.remove *)
+- (* instead of fifo *)
+- SourcesQueueCreate.oldest_first ();
+- (* Ready saved sources *)
+- SourcesQueueCreate.oldest_last ();
+- (* Waiting saved sources *)
+- SourcesQueueCreate.oldest_first ();
+- (* Old sources *)
+- (* We should change this to 'oldest_first' to improve Queue.remove *)
+- (* instead of fifo *)
+- SourcesQueueCreate.oldest_first ();
+- SourcesQueueCreate.oldest_first ();
+- SourcesQueueCreate.oldest_first ();
+- (* do_not_try *)
+- SourcesQueueCreate.oldest_first ();
+- (* Connected Sources *)
+- SourcesQueueCreate.oldest_first ();
+- (* Connecting Sources *)
+- SourcesQueueCreate.oldest_first ();
+- (* Busy Sources *)
+- SourcesQueueCreate.oldest_first ();
+- |] in
+- if Array.length queues <> Array.length queue_name then begin
+- lprintf_nl "[cSrc] Fatal error in CommonSources.create_queues";
+- exit 2;
+- end;
+- queues
++ let create_queues () =
++ let queues = [|
++ (* New sources *)
++ (* We should change this to 'oldest_last' to improve Queue.remove *)
++ (* instead of lifo *)
++ SourcesQueueCreate.oldest_last ();
++ (* Good sources *)
++ (* We should change this to 'oldest_first' to improve Queue.remove *)
++ (* instead of fifo *)
++ SourcesQueueCreate.oldest_first ();
++ (* Ready saved sources *)
++ SourcesQueueCreate.oldest_last ();
++ (* Waiting saved sources *)
++ SourcesQueueCreate.oldest_first ();
++ (* Old sources *)
++ (* We should change this to 'oldest_first' to improve Queue.remove *)
++ (* instead of fifo *)
++ SourcesQueueCreate.oldest_first ();
++ SourcesQueueCreate.oldest_first ();
++ SourcesQueueCreate.oldest_first ();
++ (* do_not_try *)
++ SourcesQueueCreate.oldest_first ();
++ (* Connected Sources *)
++ SourcesQueueCreate.oldest_first ();
++ (* Connecting Sources *)
++ SourcesQueueCreate.oldest_first ();
++ (* Busy Sources *)
++ SourcesQueueCreate.oldest_first ();
++ |] in
++ if Array.length queues <> Array.length queue_name then begin
++ lprintf_nl "[cSrc] Fatal error in CommonSources.create_queues";
++ exit 2;
++ end;
++ queues
+
+ (*************************************************************************)
+ (* *)
+@@ -1243,16 +1180,16 @@
+ (* *)
+ (*************************************************************************)
+
+- let create_file_sources_manager file_uid =
+- let m = {
+- manager_uid = file_uid;
+- manager_file = not_implemented "manager_file";
+- manager_all_sources = 0;
+- manager_active_sources = 0;
+- manager_sources = create_queues ();
+- } in
+- file_sources_managers := m :: !file_sources_managers;
+- m
++ let create_file_sources_manager file_uid =
++ let m = {
++ manager_uid = file_uid;
++ manager_file = not_implemented "manager_file";
++ manager_all_sources = 0;
++ manager_active_sources = 0;
++ manager_sources = create_queues ();
++ } in
++ file_sources_managers := m :: !file_sources_managers;
++ m
+
+ (*************************************************************************)
+ (* *)
+@@ -1260,17 +1197,13 @@
+ (* *)
+ (*************************************************************************)
+
+- let remove_file_sources_manager m =
+-
+- iter_all_sources (fun s ->
+- s.source_files <- List.filter (fun r ->
+- r.request_file != m
+- ) s.source_files;
+- ) m;
+-
+- m.manager_sources <- create_queues ();
+-
+- file_sources_managers := List2.removeq m !file_sources_managers
++ let remove_file_sources_manager m =
++ iter_all_sources (fun s ->
++ s.source_files <-
++ List.filter (fun r -> r.request_file != m) s.source_files;
++ ) m;
++ m.manager_sources <- create_queues ();
++ file_sources_managers := List2.removeq m !file_sources_managers
+
+
+ (*************************************************************************)
+@@ -1278,9 +1211,9 @@
+ (* number_of_sources *)
+ (* *)
+ (*************************************************************************)
+-(* get number of sources for a file*)
+- let number_of_sources f =
+- f.manager_all_sources
++ (* get number of sources for a file*)
++ let number_of_sources f =
++ f.manager_all_sources
+
+ (*************************************************************************)
+ (* *)
+@@ -1288,27 +1221,24 @@
+ (* *)
+ (*************************************************************************)
+
+- let find_source_by_uid uid =
+- try
+- let finder = { dummy_source with source_uid = uid } in
+- let s = HS.find sources_by_uid finder in
+- s
+-
+- with _ ->
+- if !verbose_sources > 1 then
+- lprintf_nl "[cSrc] Creating new source";
+- let n = CommonClient.book_client_num () in
+- let s = { dummy_source with
+- source_uid = uid;
+- source_age = 0;
+- source_num = n;
+- source_files = [];
+- } in
+-
+-
+- HS.add sources_by_uid s;
+- H.add sources_by_num s;
+- s
++ let find_source_by_uid uid =
++ try
++ let finder = { dummy_source with source_uid = uid } in
++ HS.find sources_by_uid finder
++
++ with Not_found ->
++ if !verbose_sources > 1 then
++ lprintf_nl "[cSrc] Creating new source";
++ let n = CommonClient.book_client_num () in
++ let s = { dummy_source with
++ source_uid = uid;
++ source_age = 0;
++ source_num = n;
++ source_files = [];
++ } in
++ HS.add sources_by_uid s;
++ H.add sources_by_num s;
++ s
+
+ (*************************************************************************)
+ (* *)
+@@ -1316,10 +1246,9 @@
+ (* *)
+ (*************************************************************************)
+
+- let find_source_by_num num =
+- let finder = { dummy_source with source_num = num } in
+- let s = H.find sources_by_num finder in
+- s
++ let find_source_by_num num =
++ let finder = { dummy_source with source_num = num } in
++ H.find sources_by_num finder
+
+ (*************************************************************************)
+ (* *)
+@@ -1327,15 +1256,15 @@
+ (* *)
+ (*************************************************************************)
+
+- let rec iter_has_request rs file =
+- match rs with
+- [] -> raise Not_found
+- | r :: tail ->
+- if r.request_file == file then r else
+- iter_has_request tail file
++ let rec iter_has_request rs file =
++ match rs with
++ | [] -> raise Not_found
++ | r :: tail ->
++ if r.request_file == file then r
++ else iter_has_request tail file
+
+- let find_request s file =
+- iter_has_request s.source_files file
++ let find_request s file =
++ iter_has_request s.source_files file
+
+ (*************************************************************************)
+ (* *)
+@@ -1343,15 +1272,15 @@
+ (* *)
+ (*************************************************************************)
+
+- let find_request_result s file =
+- let r = find_request s file in
+- let score = r.request_score in
+- if score <= not_found_score then File_not_found else
+- if score <= possible_score then File_possible else
+- if score <= found_score then File_found else
+- if score <= chunk_score then File_chunk else
+- if score <= initial_new_source_score then File_new_source else
+- assert false
++ let find_request_result s file =
++ let r = find_request s file in
++ let score = r.request_score in
++ if score <= not_found_score then File_not_found
++ else if score <= possible_score then File_possible
++ else if score <= found_score then File_found
++ else if score <= chunk_score then File_chunk
++ else if score <= initial_new_source_score then File_new_source
++ else assert false
+
+ (*************************************************************************)
+ (* *)
+@@ -1359,35 +1288,31 @@
+ (* *)
+ (*************************************************************************)
+
+- let check_time time =
+- if time = 0 then
+- last_time () - 650
+- else
+- time (* changed 2.5.24 *)
+-
+- let add_request s file time =
+- let r =
+- try
+- let r = find_request s file in
+- remove_from_queue s r;
+- set_score_part r (if r.request_score = initial_new_source_score then
+- new_source_score
+- else
+- r.request_score - 1);
+- r.request_time <- check_time time;
+- r
+- with Not_found ->
+- let r = {
+- request_file = file;
+- request_time = check_time time;
+- request_score = possible_score;
+- request_queue = outside_queue;
+- } in
+- s.source_files <- r :: s.source_files;
+- r
+- in
+- reschedule_source_for_file false s r;
+- r
++ let check_time time =
++ if time = 0 then last_time () - 650
++ else time (* changed 2.5.24 *)
++
++ let add_request s file time =
++ let r =
++ try
++ let r = find_request s file in
++ remove_from_queue s r;
++ set_score_part r (if r.request_score = initial_new_source_score then
++ new_source_score
++ else r.request_score - 1);
++ r.request_time <- check_time time;
++ r
++ with Not_found ->
++ let r = {
++ request_file = file;
++ request_time = check_time time;
++ request_score = possible_score;
++ request_queue = outside_queue;
++ } in
++ s.source_files <- r :: s.source_files;
++ r in
++ reschedule_source_for_file false s r;
++ r
+
+ (*************************************************************************)
+ (* *)
+@@ -1395,40 +1320,39 @@
+ (* *)
+ (*************************************************************************)
+
+- let rec set_request_score s file score =
+- try
+- let r = find_request s file in
+- if (not (
++ let rec set_request_score s file score =
++ try
++ let r = find_request s file in
++ if (not (
+ (* If a request has been done in the last half-hour, and the source is
+ announced as new, just forget it. : why half-hour? - trying min_reask_delay *)
+- score = initial_new_source_score &&
+- r.request_time + !!min_reask_delay > last_time ()
+- ))
++ score = initial_new_source_score &&
++ r.request_time + !!min_reask_delay > last_time ()
++ )) ||
+ (* If a file has been paused, and resumed, it is flagged outside_queue / not_found_score in
+ clean_sources, but really should be re-added to the queues as soon as possible (while retaining
+ its request_time) or it is skipped for far too long (if it is even found again) - reschedule
+ now puts new_source_score in old1 *)
+- || (score = initial_new_source_score
+- && r.request_queue = outside_queue) then
+- let score =
+- if score = initial_new_source_score
+- then new_source_score
+- else score
+- in
+- if r.request_queue < connected_sources_queue then
+- remove_from_queue s r;
+- set_score_part r score;
+- reschedule_source_for_file false s r;
+- with Not_found ->
+- let r = {
+- request_file = file;
+- request_time = check_time 0;
+- request_score = possible_score;
+- request_queue = outside_queue;
+- } in
+- set_score_part r score;
+- s.source_files <- r :: s.source_files;
+- reschedule_source_for_file false s r
++ (score = initial_new_source_score &&
++ r.request_queue = outside_queue) then
++ let score =
++ if score = initial_new_source_score
++ then new_source_score
++ else score in
++ if r.request_queue < connected_sources_queue then
++ remove_from_queue s r;
++ set_score_part r score;
++ reschedule_source_for_file false s r;
++ with Not_found ->
++ let r = {
++ request_file = file;
++ request_time = check_time 0;
++ request_score = possible_score;
++ request_queue = outside_queue;
++ } in
++ set_score_part r score;
++ s.source_files <- r :: s.source_files;
++ reschedule_source_for_file false s r
+
+ (*************************************************************************)
+ (* *)
+@@ -1436,9 +1360,10 @@
+ (* *)
+ (*************************************************************************)
+
+- let set_request_result s file result =
+- set_request_score s file (match result with
+- File_not_found -> not_found_score
++ let set_request_result s file result =
++ set_request_score s file
++ (match result with
++ | File_not_found -> not_found_score
+ | File_found -> found_score
+ | File_chunk -> chunk_score
+ | File_upload -> upload_score
+@@ -1451,29 +1376,27 @@
+ (* *)
+ (*************************************************************************)
+
+- let source_to_value s assocs =
+- let requests = ref [] in
+- List.iter (fun r ->
+- if r.request_score > possible_score then
+-
+- requests :=
+- (SmallList
+- [once_value (string_to_value r.request_file.manager_uid);
+- int_to_value r.request_score;
+- int_to_value r.request_time]
+- ) ::
+- !requests
+- ) s.source_files;
+- if !requests = [] then raise Exit;
+- (
+- ("sscore", int_to_value s.source_score ) ::
+- ("addr", M.source_uid_to_value s.source_uid ) ::
+- ("brand", M.source_brand_to_value s.source_brand ) ::
+- ("files", smalllist_to_value (fun s -> s)
+- !requests) ::
+- ("age", int_to_value s.source_age ) ::
+- assocs
+- )
++ let source_to_value s assocs =
++ let requests = ref [] in
++ List.iter (fun r ->
++ if r.request_score > possible_score then
++ requests :=
++ (SmallList
++ [once_value (string_to_value r.request_file.manager_uid);
++ int_to_value r.request_score;
++ int_to_value r.request_time]
++ ) :: !requests
++ ) s.source_files;
++ if !requests = [] then raise Exit;
++ (
++ ("sscore", int_to_value s.source_score ) ::
++ ("addr", M.source_uid_to_value s.source_uid ) ::
++ ("brand", M.source_brand_to_value s.source_brand ) ::
++ ("files", smalllist_to_value (fun s -> s)
++ !requests) ::
++ ("age", int_to_value s.source_age ) ::
++ assocs
++ )
+
+
+ (*************************************************************************)
+@@ -1482,15 +1405,15 @@
+ (* *)
+ (*************************************************************************)
+
+- let query_file s file =
+- if file_state (file.manager_file ()) = FileDownloading then
+- let r = find_request s file in
+- if r.request_time + !!min_reask_delay <= last_time () then
+-
+- (* There is really no need to query a not found source again
+- for the file ... not even after an hour! *)
+- if r.request_score > not_found_score then
+- source_query s r
++ let query_file s file =
++ if file_state (file.manager_file ()) = FileDownloading then
++ let r = find_request s file in
++ if r.request_time + !!min_reask_delay <= last_time () then
++
++ (* There is really no need to query a not found source again
++ for the file ... not even after an hour! *)
++ if r.request_score > not_found_score then
++ source_query s r
+
+
+ (*************************************************************************)
+@@ -1498,11 +1421,11 @@
+ (* query_files *)
+ (* *)
+ (*************************************************************************)
+-(* Query a source for all of its known files*)
+- let query_files s =
+- List.iter (fun f ->
+- query_file s f.request_file;
+- ) s.source_files
++ (* Query a source for all of its known files*)
++ let query_files s =
++ List.iter (fun f ->
++ query_file s f.request_file;
++ ) s.source_files
+
+
+ (*************************************************************************)
+@@ -1511,23 +1434,23 @@
+ (* *)
+ (*************************************************************************)
+
+- let add_saved_source_request s uid score time =
+- if !verbose_sources > 1 then
+- lprintf_nl "[cSrc] Request %s %d %d" uid score time;
+- let file =
+- try
+- functions.function_string_to_manager uid
+- with e ->
+- if !verbose_sources > 0 then
+- lprintf_nl "[cSrc] CommonSources: add_saved_source_request -> %s not found" uid;
+- raise e
+- in
+- let r = add_request s file time in
+- set_score_part r score;
+- reschedule_source_for_file true s r;
+- if !verbose_sources > 1 then
+- lprintf_nl "[cSrc] Put saved source %d in queue %s" s.source_num
+- queue_name.(r.request_queue)
++ let add_saved_source_request s uid score time =
++ if !verbose_sources > 1 then
++ lprintf_nl "[cSrc] Request %s %d %d" uid score time;
++ let file =
++ try
++ functions.function_string_to_manager uid
++ with e ->
++ if !verbose_sources > 0 then
++ lprintf_nl "[cSrc] CommonSources: add_saved_source_request -> %s not found" uid;
++ raise e
++ in
++ let r = add_request s file time in
++ set_score_part r score;
++ reschedule_source_for_file true s r;
++ if !verbose_sources > 1 then
++ lprintf_nl "[cSrc] Put saved source %d in queue %s" s.source_num
++ queue_name.(r.request_queue)
+
+ (*************************************************************************)
+ (* *)
+@@ -1535,79 +1458,73 @@
+ (* *)
+ (*************************************************************************)
+
+- let value_to_source assocs =
++ let value_to_source assocs =
+ (* lprintf "(1) value_to_source\n"; *)
+- let get_value name conv = conv (List.assoc name assocs) in
++ let get_value name conv = conv (List.assoc name assocs) in
+
+- let addr = get_value "addr" M.value_to_source_uid in
+- let files = get_value "files"
+- (value_to_list (fun s -> s)) in
+-
+- let last_conn =
+- try get_value "age" value_to_int with _ -> 0
+- in
+-
+- let score = try get_value "sscore" value_to_int with _ -> 0 in
+- let brand = try get_value "brand" M.value_to_source_brand with _ ->
+- M.dummy_source_brand in
+-
+- if !verbose_sources > 1 then
+- lprintf_nl "[cSrc] New source from value";
+- let s = find_source_by_uid addr in
+- s.source_score <- score;
+- s.source_age <- last_conn;
+- s.source_brand <- brand;
++ let addr = get_value "addr" M.value_to_source_uid in
++ let files = get_value "files"
++ (value_to_list (fun s -> s)) in
++
++ let last_conn =
++ try get_value "age" value_to_int with _ -> 0 in
++
++ let score = try get_value "sscore" value_to_int with _ -> 0 in
++ let brand = try get_value "brand" M.value_to_source_brand with _ ->
++ M.dummy_source_brand in
++
++ if !verbose_sources > 1 then
++ lprintf_nl "[cSrc] New source from value";
++ let s = find_source_by_uid addr in
++ s.source_score <- score;
++ s.source_age <- last_conn;
++ s.source_brand <- brand;
+
+ (* lprintf "(2) value_to_source \n"; *)
+
+- let rec iter v =
+- match v with
+- OnceValue v -> iter v
+- | List [uid; score; time] | SmallList [uid; score; time] ->
+- (try
+- let uid = value_to_string uid in
+- let score = value_to_int score in
+- let time = value_to_int time in
++ let rec iter v =
++ match v with
++ | OnceValue v -> iter v
++ | List [uid; score; time] | SmallList [uid; score; time] ->
++ (try
++ let uid = value_to_string uid in
++ let score = value_to_int score in
++ let time = value_to_int time in
+
+ (* added in 2.5.27 to fix a bug introduced in 2.5.25 *)
+- let score =
+- if score land 0xffff = 0 then score asr 16 else score
+- in
++ let score =
++ if score land 0xffff = 0 then score asr 16 else score in
+
+ (* lprintf "(3) value_to_source \n"; *)
+
+- add_saved_source_request s uid score time
++ add_saved_source_request s uid score time
+
+- with e ->
+- if !verbose_sources > 1 then begin
+- lprintf_nl "[cSrc] CommonSources.value_to_source: exception %s in iter request"
+- (Printexc2.to_string e);
+- end
+- )
+- | (StringValue _) as uid ->
+- (try
+- let uid = value_to_string uid in
++ with e ->
++ if !verbose_sources > 1 then
++ lprintf_nl "[cSrc] CommonSources.value_to_source: exception %s in iter request"
++ (Printexc2.to_string e))
++
++ | (StringValue _) as uid ->
++ (try
++ let uid = value_to_string uid in
+ (* lprintf "(4) value_to_source \n"; *)
+
+- let score = 0 in
+- let time = 0 in
+- add_saved_source_request s uid score time
+-
+- with e ->
+- if !verbose_sources > 1 then begin
+- lprintf_nl "[cSrc] CommonSources.value_to_source: exception %s in iter request"
+- (Printexc2.to_string e);
+- end
+- )
+- | _ -> assert false
+-
+- in
++ let score = 0 in
++ let time = 0 in
++ add_saved_source_request s uid score time
++
++ with e ->
++ if !verbose_sources > 1 then
++ lprintf_nl "[cSrc] CommonSources.value_to_source: exception %s in iter request"
++ (Printexc2.to_string e))
++
++ | _ -> assert false
++
++ in
+ (* lprintf "(5) value_to_source \n"; *)
+-
+- List.iter iter files;
++ List.iter iter files;
+ (* lprintf "(6) value_to_source \n"; *)
+-
+- raise SideEffectOption
++ raise SideEffectOption
+
+ (*************************************************************************)
+ (* *)
+@@ -1615,7 +1532,7 @@
+ (* *)
+ (*************************************************************************)
+
+- let refill_sources () =
++ let refill_sources () =
+
+ (* Wait for 9 seconds before refilling, since we put at least 10 seconds
+ of clients in the previous bucket.
+@@ -1624,279 +1541,257 @@
+ we may have failed to fill the queue with what was available
+ if !last_refill + 8 < last_time () then
+ *)
+- try
+- last_refill := last_time ();
+- if !verbose_sources > 0 then begin
+- lprintf_nl "[cSrc] CommonSources.refill_sources BEFORE:";
+- let buf = Buffer.create 100 in
+- print buf TEXT;
+- lprintf "%s\n" (Buffer.contents buf);
+- end;
+-
+- (*
+- how much consecutive sources in the queue a file can have
+- source_f1|source_f1|source_f1|source_f2...
+- <- - - - - - - 3 - - - - - ->
+- 10 for finer priority scaling
+- *)
+- let max_consecutive = 10 in
+-
+- (*
+- get at most nsources direct sources from a file
+- return number of sources found,new queue position
+- *)
+- let rec get_sources nsource m queue took =
+- (* do_not_try == avoid source bounceback, i.e. a dustbin *)
+- if queue >= do_not_try_queue || nsource <= 0 then
+- (* we tried all queue or found enough sources, good bye!*)
+- took
+- else
+- let q = m.manager_sources.(queue) in
+- if Queue.length q > 0 then
+- let (request_time, s) = Queue.head q in
+- let throttled = queue_period.(queue) > 0 && nsource > 1 in
+- let throttle_delay = get_throttle_delay m queue throttled in
+- if request_time + !!min_reask_delay + throttle_delay < last_time () then
+- begin
+- if !verbose_sources > 1 then
+- lprintf_nl "[cSrc] Sources: take source from Queue[%s] for %s"
+- queue_name.(queue)
+- (file_best_name (m.manager_file ()));
+- (* put in the connecting queue*)
+- source_connecting s;
+- if M.direct_source s.source_uid then
+- begin
+- Fifo.put next_direct_sources s;
+- (* we found a direct source try again in the _same_ queue *)
+- get_sources (nsource-1) m queue (took+1)
+- end
+- else
+- begin
+- next_indirect_sources := s :: !next_indirect_sources;
+- (* we found an indirect source try again in the _same_
+- queue. indirect sources are "for free". *)
+- get_sources nsource m queue took
+- end
+- end
+- else
+- begin
+- if !verbose_sources > 1 then
+- lprintf_nl "[cSrc] Source of queue %s is not ready for %s"
+- queue_name.(queue) (file_best_name (m.manager_file ()));
+- (* too early to take sources in this queue try again in the _next_ queue*)
+- if queue_period.(queue) = 0 then
+- (* queue not throttled, try next queue *)
+- let to_take =
+- (* a maximum of just one source from old3 queue *)
+- if queue+1 >= old_sources3_queue then
+- (min 1 nsource)
+- else
+- nsource
+- in
+- get_sources to_take m (queue+1) took
+- else
+- (* throttled queue, and no ready sources ... *)
+- if nsource = 1 then
+- (* nsource = 1 not even a ready source without throttle-delay *)
+- get_sources 0 m (queue) took
+- (* exit here *)
+- else
+- (* finaly try to take at least one source, regardless of throttles *)
+- get_sources 1 m (queue) took
+- end
+- else
+- begin
+- if !verbose_sources > 1 then
+- lprintf_nl "[cSrc] Queue %s is empty for %s"
+- queue_name.(queue) (file_best_name (m.manager_file ()));
+- (* no sources in this queue try again in the _next_ queue *)
+- let to_take =
+- (* a maximum of just one source from old3 queue *)
+- if queue+1 >= old_sources3_queue then
+- (min 1 nsource)
+- else
+- nsource
+- in
+- get_sources to_take m (queue+1) took
+- end
+- in
+-
+- (* recalc list if there's no new file*)
+- (* Fill only with sources from files being downloaded *)
++ try
++ last_refill := last_time ();
++ if !verbose_sources > 0 then begin
++ lprintf_nl "[cSrc] CommonSources.refill_sources BEFORE:";
++ let buf = Buffer.create 100 in
++ print buf TEXT;
++ lprintf "%s\n" (Buffer.contents buf);
++ end;
++
++ (*
++ how much consecutive sources in the queue a file can have
++ source_f1|source_f1|source_f1|source_f2...
++ <- - - - - - - 3 - - - - - ->
++ 10 for finer priority scaling
++ *)
++ let max_consecutive = 10 in
+
+- let nfiles = ref 0 in
+- let files = ref [] in
+- let min_priority = ref 0 in
+- let sum_priority = ref 0 in
+- List.iter (fun m ->
+- match file_state (m.manager_file ()) with
+- FileDownloading ->
+- let priority = file_priority (m.manager_file ()) in
+- min_priority := min !min_priority priority;
+- sum_priority := !sum_priority + priority;
+- files := (priority, m ) :: !files;
+- incr nfiles
+- | _ -> ()
+- ) !file_sources_managers;
+-
+- if !files <> [] then begin
+-
+- (* 'normalize' to 0 priorities*)
+- sum_priority := !sum_priority + (!nfiles * (-(!min_priority)));
+- (* update priorities to be > 0 *)
+- files := List.map ( fun (p,f) ->
+- let np = p - (!min_priority) in
+- if np==0 then
+- begin
+- sum_priority := !sum_priority + 1;
+- (1,f)
++ (*
++ get at most nsources direct sources from a file
++ return number of sources found,new queue position
++ *)
++ let rec get_sources nsource m queue took =
++ (* do_not_try == avoid source bounceback, i.e. a dustbin *)
++ if queue >= do_not_try_queue || nsource <= 0 then
++ (* we tried all queue or found enough sources, good bye!*)
++ took
++ else
++ let q = m.manager_sources.(queue) in
++ if Queue.length q > 0 then
++ let (request_time, s) = Queue.head q in
++ let throttled = queue_period.(queue) > 0 && nsource > 1 in
++ let throttle_delay = get_throttle_delay m queue throttled in
++ if request_time + !!min_reask_delay + throttle_delay < last_time () then begin
++ if !verbose_sources > 1 then
++ lprintf_nl "[cSrc] Sources: take source from Queue[%s] for %s"
++ queue_name.(queue)
++ (file_best_name (m.manager_file ()));
++ (* put in the connecting queue*)
++ source_connecting s;
++ if M.direct_source s.source_uid then begin
++ Fifo.put next_direct_sources s;
++ (* we found a direct source try again in the _same_ queue *)
++ get_sources (nsource-1) m queue (took+1)
+ end
+- else
+- (np,f)
+- ) !files;
+-
+- (*sort by highest priority*)
+- files := List.sort (fun (p1,_) (p2,_) -> compare p2 p1) !files;
+-
+- (* calc sources queue size
+- at least 3 sources per file*)
+- let nsources = max (!nfiles*3)
+- (functions.function_max_connections_per_second () * 10) in
+-
+- (* calc how much sources a file can get according to its priority*)
+- let sources_per_prio = (float_of_int nsources) /. (float_of_int !sum_priority) in
+-
+-
+- (*
+- iter through files to queue sources
+- flist_todo : next files to test
+- assigned : number of sources already queued
+- looped : number of times we allow to loop try to fill queue of sources
++ else begin
++ next_indirect_sources := s :: !next_indirect_sources;
++ (* we found an indirect source try again in the _same_
++ queue. indirect sources are "for free". *)
++ get_sources nsource m queue took
++ end
++ end
++ else begin
++ if !verbose_sources > 1 then
++ lprintf_nl "[cSrc] Source of queue %s is not ready for %s"
++ queue_name.(queue) (file_best_name (m.manager_file ()));
++ (* too early to take sources in this queue try again in the _next_ queue*)
++ if queue_period.(queue) = 0 then
++ (* queue not throttled, try next queue *)
++ let to_take =
++ (* a maximum of just one source from old3 queue *)
++ if queue+1 >= old_sources3_queue then min 1 nsource
++ else nsource in
++ get_sources to_take m (queue+1) took
++ else
++ (* throttled queue, and no ready sources ... *)
++ if nsource = 1 then
++ (* nsource = 1 not even a ready source without throttle-delay *)
++ get_sources 0 m (queue) took
++ (* exit here *)
++ else
++ (* finaly try to take at least one source, regardless of throttles *)
++ get_sources 1 m (queue) took
++ end
++ else begin
++ if !verbose_sources > 1 then
++ lprintf_nl "[cSrc] Queue %s is empty for %s"
++ queue_name.(queue) (file_best_name (m.manager_file ()));
++ (* no sources in this queue try again in the _next_ queue *)
++ let to_take =
++ (* a maximum of just one source from old3 queue *)
++ if queue+1 >= old_sources3_queue then min 1 nsource
++ else nsource in
++ get_sources to_take m (queue+1) took
++ end in
++
++ (* recalc list if there's no new file*)
++ (* Fill only with sources from files being downloaded *)
++
++ let nfiles = ref 0 in
++ let files = ref [] in
++ let min_priority = ref 0 in
++ let sum_priority = ref 0 in
++ List.iter (fun m ->
++ match file_state (m.manager_file ()) with
++ | FileDownloading ->
++ let priority = file_priority (m.manager_file ()) in
++ min_priority := min !min_priority priority;
++ sum_priority := !sum_priority + priority;
++ files := (priority, m ) :: !files;
++ incr nfiles
++ | _ -> () ) !file_sources_managers;
++
++ if !files <> [] then begin
++
++ (* 'normalize' to 0 priorities*)
++ sum_priority := !sum_priority + (!nfiles * (-(!min_priority)));
++ (* update priorities to be > 0 *)
++ files := List.map (fun (p, f) ->
++ let np = p - (!min_priority) in
++ if np = 0 then begin
++ incr sum_priority;
++ (1, f)
++ end
++ else (np, f) ) !files;
++
++ (*sort by highest priority*)
++ files := List.sort (fun (p1,_) (p2,_) -> compare p2 p1) !files;
++
++ (* calc sources queue size
++ at least 3 sources per file*)
++ let nsources = max (!nfiles * 3)
++ (functions.function_max_connections_per_second () * 10) in
++
++ (* calc how much sources a file can get according to its priority*)
++ let sources_per_prio =
++ (float_of_int nsources) /. (float_of_int !sum_priority) in
++
++
++ (*
++ iter through files to queue sources
++ flist_todo : next files to test
++ assigned : number of sources already queued
++ looped : number of times we allow to loop try to fill queue of sources
+ (how hard we try to fill queue)
+- *)
+- let rec iter_files assigned looped =
++ *)
++ let rec iter_files assigned looped =
+
+- (* throw in new sources at high pace and do not care
+- about them in get_sources, this avoids "locking" a
+- file's queue sources with thousands of new sources
+- from SE *)
+- let try_some_new_sources () =
+- let extr = ref 0 in
+- List.iter
+- (fun m ->
+- let f = m.manager_file () in
+- let q = m.manager_sources.(new_sources_queue) in
+- if file_state f = FileDownloading && Queue.length q > 0 then
++ (* throw in new sources at high pace and do not care
++ about them in get_sources, this avoids "locking" a
++ file's queue sources with thousands of new sources
++ from SE *)
++ let try_some_new_sources () =
++ let extr = ref 0 in
++ List.iter (fun m ->
++ let f = m.manager_file () in
++ let q = m.manager_sources.(new_sources_queue) in
++ if file_state f = FileDownloading && Queue.length q > 0 then
++ let (request_time, s) = Queue.head q in
++ source_connecting s;
++ if M.direct_source s.source_uid then begin
++ incr extr;
++ Fifo.put next_direct_sources s
++ end
++ else
++ next_indirect_sources := s :: !next_indirect_sources
++ ) !file_sources_managers;
++ !extr in
++
++ let cleanup_some_old_sources () =
++ (* Cleanup some sources *)
++ List.iter (fun m ->
++ let f = m.manager_file () in
++ if file_state f = FileDownloading then
++ let remove_old q t =
++ if Queue.length q > 0 then
+ let (request_time, s) = Queue.head q in
+- source_connecting s;
+- if M.direct_source s.source_uid then begin
+- incr extr;
+- Fifo.put next_direct_sources s
+- end
+- else
+- next_indirect_sources := s :: !next_indirect_sources
+- ) !file_sources_managers;
+- !extr in
+-
+- let cleanup_some_old_sources () =
+- (* Cleanup some sources *)
+- List.iter
+- (fun m ->
+- let f = m.manager_file () in
+- if file_state f = FileDownloading then
+- let remove_old q t =
+- if Queue.length q > 0 then
+- let (request_time, s) = Queue.head q in
+- if request_time + t < last_time () then
+- remove_from_queue s (find_request s m) in
++ if request_time + t < last_time () then
++ remove_from_queue s (find_request s m) in
+
+- remove_old m.manager_sources.(do_not_try_queue) 14400;
+- remove_old m.manager_sources.(old_sources3_queue) 2400;
+- remove_old m.manager_sources.(old_sources2_queue) 1200
+- ) !file_sources_managers in
+-
+- let rec aux flist_todo assigned =
+- if assigned >= nsources then
+- cleanup_some_old_sources ()
+- else
+- match flist_todo with
+- | (prio, file) :: t ->
+- let tt = min (truncate (sources_per_prio *. (float_of_int prio)))
+- max_consecutive in
+- let to_take = max tt 1 in
+- (* allow at least one source per file :
+- we will overflow a bit the expected next_direct_sources length
+- but it's for the good cause : not 'starving' some files
+- *)
+- let took = get_sources to_take file good_sources_queue 0 in
+- aux t (assigned + took)
++ remove_old m.manager_sources.(do_not_try_queue) 14400;
++ remove_old m.manager_sources.(old_sources3_queue) 2400;
++ remove_old m.manager_sources.(old_sources2_queue) 1200
++ ) !file_sources_managers in
++
++ let rec aux flist_todo assigned =
++ if assigned >= nsources then cleanup_some_old_sources ()
++ else
++ match flist_todo with
++ | (prio, file) :: t ->
++ let tt =
++ min (truncate (sources_per_prio *. (float_of_int prio)))
++ max_consecutive in
++ let to_take = max tt 1 in
++ (* allow at least one source per file :
++ we will overflow a bit the expected next_direct_sources length
++ but it's for the good cause : not 'starving' some files
++ *)
++ let took = get_sources to_take file good_sources_queue 0 in
++ aux t (assigned + took)
+
+- | [] ->
+- cleanup_some_old_sources ();
++ | [] ->
++ cleanup_some_old_sources ();
+
+- (* more power to the "runaway" (most overloaded) file, pick extra sources *)
+- let em =
+- let q = find_throttled_queue good_sources_queue in
+- if queue_period.(q) > 0 then
+- let max_overloaded =
+- List.hd (find_max_overloaded q !file_sources_managers) in
+- let overhead =
+- count_file_ready_sources max_overloaded q true in
+- if overhead > 0 then
+- get_sources max_consecutive max_overloaded good_sources_queue 0
+- else 0
+- else 0 in
++ (* more power to the "runaway" (most overloaded) file, pick extra sources *)
++ let em =
++ let q = find_throttled_queue good_sources_queue in
++ if queue_period.(q) > 0 then
++ let max_overloaded =
++ List.hd (find_max_overloaded q !file_sources_managers) in
++ let overhead =
++ count_file_ready_sources max_overloaded q true in
++ if overhead > 0 then
++ get_sources max_consecutive max_overloaded good_sources_queue 0
++ else 0
++ else 0 in
+
+- if looped > 0 then
+- (* allow at most looped re-iter of list to not
+- loop endlessly *)
+- iter_files (assigned + em) (looped - 1)
+- in
+- let extr = try_some_new_sources () in
+- aux !files (assigned + extr)
+-
+- in
+- iter_files 0 3;
+-
+- (* adjust queue throttling *)
+- let all_ready = ref 0 in
+- List.iter
+- (fun q ->
+- let queue_throttled_ready = count_ready_sources q true in
+- let queue_ready = count_ready_sources q false in
+- all_ready := !all_ready + queue_throttled_ready;
+- if !all_ready > nsources && queue_throttled_ready > 0 then
+- (* no need, to increase period on a queue without ready sources *)
+- begin
+- (* lprintf "commonSources: increasing queue throttling for (ar=%d rc=%d qr=%d) %s\n" !allReady nsources queueReady queue_name.(q); *)
+- queue_period.( q ) <- queue_period.( q ) + 1
+- end
+- else
+- begin
+- if queue_ready = 0 then
+- begin
+- (* lprintf "commonSources: resetting queue throttling to 0 (ar=%d rc=%d qr=%d) %s\n" !allReady nsources queueReady queue_name.(q); *)
+- queue_period.( q ) <- 0
+- end
+- else
+- begin
+- (* lprintf "commonSources: decreasing queue throttling for (ar=%d rc=%d qr=%d) %s\n" !allReady nsources queueReady queue_name.(q); *)
+- queue_period.( q ) <- max 0 (queue_period.( q ) - 1)
+- end
+- end
+- ) [ good_sources_queue; old_sources1_queue; old_sources2_queue; old_sources3_queue ];
+-
+- end;
+-
+- if !verbose_sources > 0 then begin
+- lprintf_nl "[cSrc] CommonSources.refill_sources AFTER:";
+- let buf = Buffer.create 100 in
+- print buf TEXT;
+- lprintf "%s\n" (Buffer.contents buf);
+- end;
+- with e ->
+- lprintf_nl "[cSrc] Exception %s in refill_sources"
+- (Printexc2.to_string e)
++ if looped > 0 then
++ (* allow at most looped re-iter of list to not
++ loop endlessly *)
++ iter_files (assigned + em) (looped - 1)
++ in
++ let extr = try_some_new_sources () in
++ aux !files (assigned + extr)
++
++ in
++ iter_files 0 3;
++
++ (* adjust queue throttling *)
++ let all_ready = ref 0 in
++ List.iter (fun q ->
++ let queue_throttled_ready = count_ready_sources q true in
++ let queue_ready = count_ready_sources q false in
++ all_ready := !all_ready + queue_throttled_ready;
++ if !all_ready > nsources && queue_throttled_ready > 0 then begin
++ (* no need, to increase period on a queue without ready sources *)
++ (* lprintf "commonSources: increasing queue throttling for (ar=%d rc=%d qr=%d) %s\n" !allReady nsources queueReady queue_name.(q); *)
++ queue_period.( q ) <- queue_period.( q ) + 1
++ end
++ else begin
++ if queue_ready = 0 then begin
++ (* lprintf "commonSources: resetting queue throttling to 0 (ar=%d rc=%d qr=%d) %s\n" !allReady nsources queueReady queue_name.(q); *)
++ queue_period.( q ) <- 0
++ end
++ else begin
++ (* lprintf "commonSources: decreasing queue throttling for (ar=%d rc=%d qr=%d) %s\n" !allReady nsources queueReady queue_name.(q); *)
++ queue_period.( q ) <- max 0 (queue_period.( q ) - 1)
++ end
++ end
++ ) [ good_sources_queue; old_sources1_queue; old_sources2_queue; old_sources3_queue ];
++
++ end;
++
++ if !verbose_sources > 0 then begin
++ lprintf_nl "[cSrc] CommonSources.refill_sources AFTER:";
++ let buf = Buffer.create 100 in
++ print buf TEXT;
++ lprintf "%s\n" (Buffer.contents buf);
++ end;
++ with e ->
++ lprintf_nl "[cSrc] Exception %s in refill_sources"
++ (Printexc2.to_string e)
+
+
+ (*************************************************************************)
+@@ -1904,19 +1799,17 @@
+ (* clean_sources helper *)
+ (* *)
+ (*************************************************************************)
+-let put_all_outside_queue m q queue =
+- let _, s = Queue.take q in
+- m.manager_all_sources <- m.manager_all_sources - 1;
+- if active_queue queue then
+- m.manager_active_sources <- m.manager_active_sources - 1;
+- List.iter
+- (fun r ->
+- if r.request_file == m then
+- begin
+- r.request_queue <- outside_queue;
+- set_score_part r not_found_score
+- end
+- ) s.source_files
++ let put_all_outside_queue m q queue =
++ let _, s = Queue.take q in
++ m.manager_all_sources <- m.manager_all_sources - 1;
++ if active_queue queue then
++ m.manager_active_sources <- m.manager_active_sources - 1;
++ List.iter (fun r ->
++ if r.request_file == m then begin
++ r.request_queue <- outside_queue;
++ set_score_part r not_found_score
++ end
++ ) s.source_files
+
+ (*************************************************************************)
+ (* *)
+@@ -1924,48 +1817,44 @@
+ (* *)
+ (*************************************************************************)
+
+- let clean_sources () =
+- (* Maybe this should be dependant on the file (priority, state,...) ? *)
+- let max_sources_per_file = functions.function_max_sources_per_file () in
+- List.iter
+- (fun m ->
+- match file_state (m.manager_file ()) with
+- FileDownloading ->
+- let nsources = m.manager_all_sources in
+- if nsources > max_sources_per_file then
+- let rec iter nsources q queue =
+- if nsources > 0 then
+- if Queue.length q > 0
+- && queue <> good_sources_queue
+- then
+- begin
+- put_all_outside_queue m q queue;
+- iter (nsources-1) q queue
+- end
+- else
+- let do_iter q = iter nsources m.manager_sources.(q) q in
++ let clean_sources () =
++ (* Maybe this should be dependant on the file (priority, state,...) ? *)
++ let max_sources_per_file = functions.function_max_sources_per_file () in
++ List.iter (fun m ->
++ match file_state (m.manager_file ()) with
++ | FileDownloading ->
++ let nsources = m.manager_all_sources in
++ if nsources > max_sources_per_file then
++ let rec iter nsources q queue =
++ if nsources > 0 then
++ if Queue.length q > 0 &&
++ queue <> good_sources_queue then begin
++ put_all_outside_queue m q queue;
++ iter (nsources-1) q queue
++ end
++ else
++ let do_iter q = iter nsources m.manager_sources.(q) q in
+
+- if queue = old_sources1_queue then do_iter do_not_try_queue else
+- if queue = do_not_try_queue then do_iter new_sources_queue else
+- if queue = new_sources_queue then do_iter waiting_saved_sources_queue else
+- if queue > good_sources_queue then do_iter (queue-1)
+-
+- in
+- iter (nsources - max_sources_per_file) (m.manager_sources.(old_sources3_queue)) old_sources3_queue
+-
+- | _ ->
+- let rec iter q queue =
+- if Queue.length q > 0 then
+- begin
+- put_all_outside_queue m q queue;
+- iter q queue
+- end
+- else
+- if queue > 0 then
+- iter m.manager_sources.(queue-1) (queue-1)
+- in
+- iter (m.manager_sources.(do_not_try_queue)) do_not_try_queue
+- ) !file_sources_managers
++ if queue = old_sources1_queue then do_iter do_not_try_queue
++ else if queue = do_not_try_queue then do_iter new_sources_queue
++ else if queue = new_sources_queue then do_iter waiting_saved_sources_queue
++ else if queue > good_sources_queue then do_iter (queue-1)
++
++ in
++ iter (nsources - max_sources_per_file) (m.manager_sources.(old_sources3_queue)) old_sources3_queue
++
++ | _ ->
++ let rec iter q queue =
++ if Queue.length q > 0 then begin
++ put_all_outside_queue m q queue;
++ iter q queue
++ end
++ else
++ if queue > 0 then
++ iter m.manager_sources.(queue-1) (queue-1)
++ in
++ iter (m.manager_sources.(do_not_try_queue)) do_not_try_queue
++ ) !file_sources_managers
+
+ (*************************************************************************)
+ (* *)
+@@ -1973,101 +1862,98 @@
+ (* *)
+ (*************************************************************************)
+
+- let connect_sources connection_manager =
++ let connect_sources connection_manager =
+
+- if !verbose_sources > 1 then
+- lprintf_nl "[cSrc] connect_sources";
++ if !verbose_sources > 1 then
++ lprintf_nl "[cSrc] connect_sources";
+ (* After 2 minutes, consider that connections attempted should be revoked. *)
+
+- if !verbose_sources > 1 then
+- lprintf_nl "[cSrc] revoke connecting sources...";
+- let rec iter () =
+- if not (Fifo.empty connecting_sources) then
+- let (time, s) = Fifo.head connecting_sources in
+- if time <> s.source_last_attempt then begin
+- ignore (Fifo.take connecting_sources);
+- iter ()
+- end else
+- if time + 120 < last_time () then begin
+- ignore (Fifo.take connecting_sources);
+- if s.source_last_attempt <> 0 then source_disconnected s;
+- iter ()
+- end
+- in
+- iter ();
++ if !verbose_sources > 1 then
++ lprintf_nl "[cSrc] revoke connecting sources...";
++ let rec iter () =
++ if not (Fifo.empty connecting_sources) then
++ let (time, s) = Fifo.head connecting_sources in
++ if time <> s.source_last_attempt then begin
++ ignore (Fifo.take connecting_sources);
++ iter ()
++ end
++ else if time + 120 < last_time () then begin
++ ignore (Fifo.take connecting_sources);
++ if s.source_last_attempt <> 0 then source_disconnected s;
++ iter ()
++ end
++ in
++ iter ();
+
+ (* First, require !!max_connections_per_second sources to connect to us.
+ The probability is very high they won't be able to connect to us. *)
+
+- if !verbose_sources > 1 then
+- lprintf_nl "[cSrc] connect indirect sources...";
+- let (first_sources, last_sources) =
+- List2.cut !!max_connections_per_second !next_indirect_sources in
+- next_indirect_sources := last_sources;
+- List.iter (fun s ->
+- ignore (connect_source s)) first_sources;
++ if !verbose_sources > 1 then
++ lprintf_nl "[cSrc] connect indirect sources...";
++ let (first_sources, last_sources) =
++ List2.cut !!max_connections_per_second !next_indirect_sources in
++ next_indirect_sources := last_sources;
++ List.iter (fun s ->
++ ignore (connect_source s)) first_sources;
+
+ (* Second, for every file being downloaded, query sources that are already
+ connected if needed *)
+- if !verbose_sources > 1 then
+- lprintf_nl "[cSrc] query connected sources...";
+- List.iter (fun m ->
+- match file_state (m.manager_file ()) with
+- FileDownloading ->
+- let q = m.manager_sources.(connected_sources_queue) in
+- let rec iter () =
+- if Queue.length q > 0 then
+- let (time, s) = Queue.head q in
+- if time + !!min_reask_delay < last_time () then begin
+-
+- let r = find_request s m in
+- (* lprintf "commonSources: connect_sources: second place for source_query !?\n"; *)
+- (* isn't that here pretty useless? *)
+- source_query s r;
+- (* After this step, the source is
+- either in 'busy_sources_queue',
+- if for some reason, the request
+- could not be sent, or in
+- 'connected_sources_queue' at the
+- tail if the request could be sent.
+- This seems thus safe.
+- *)
+- iter ()
+- end
+- in
+- iter ()
+- | _ -> ()
+- ) !file_sources_managers;
+-
+- if !verbose_sources > 1 then
+- lprintf_nl "[cSrc] connect to sources...";
+-(* Finally, connect to available sources *)
+- try
+- let max_sources = functions.function_max_connections_per_second () in
+- if !verbose_sources > 1 then
+- lprintf_nl "[cSrc] max_sources: %d" max_sources;
+- let rec iter nsources refilled =
+- if nsources > 0 && can_open_connection connection_manager then
+- if Fifo.length next_direct_sources > 0 then
+- let s = Fifo.take next_direct_sources in
+- connect_source s;
+- let nsources = match s.source_sock with
+- NoConnection ->
+- if !verbose_sources > 1 then
+- lprintf_nl "[cSrc] not connected"; nsources
+- | _ -> nsources-1
+- in
+- iter nsources refilled
+- else
+- if not refilled then begin
+- refill_sources ();
+- iter nsources true
+- end
+- in
+- iter max_sources false;
+- if !verbose_sources > 1 then
+- lprintf_nl "[cSrc] done connect_sources";
+- with Exit -> ()
++ if !verbose_sources > 1 then
++ lprintf_nl "[cSrc] query connected sources...";
++ List.iter (fun m ->
++ match file_state (m.manager_file ()) with
++ | FileDownloading ->
++ let q = m.manager_sources.(connected_sources_queue) in
++ let rec iter () =
++ if Queue.length q > 0 then
++ let (time, s) = Queue.head q in
++ if time + !!min_reask_delay < last_time () then begin
++
++ let r = find_request s m in
++ (* lprintf "commonSources: connect_sources: second place for source_query !?\n"; *)
++ (* isn't that here pretty useless? *)
++ source_query s r;
++ (* After this step, the source is
++ either in 'busy_sources_queue',
++ if for some reason, the request
++ could not be sent, or in
++ 'connected_sources_queue' at the
++ tail if the request could be sent.
++ This seems thus safe.
++ *)
++ iter ()
++ end in
++ iter ()
++ | _ -> ()
++ ) !file_sources_managers;
++
++ if !verbose_sources > 1 then
++ lprintf_nl "[cSrc] connect to sources...";
++ (* Finally, connect to available sources *)
++ try
++ let max_sources = functions.function_max_connections_per_second () in
++ if !verbose_sources > 1 then
++ lprintf_nl "[cSrc] max_sources: %d" max_sources;
++ let rec iter nsources refilled =
++ if nsources > 0 && can_open_connection connection_manager then
++ if Fifo.length next_direct_sources > 0 then
++ let s = Fifo.take next_direct_sources in
++ connect_source s;
++ let nsources =
++ match s.source_sock with
++ | NoConnection ->
++ if !verbose_sources > 1 then
++ lprintf_nl "[cSrc] not connected"; nsources
++ | _ -> nsources - 1 in
++ iter nsources refilled
++ else if not refilled then begin
++ refill_sources ();
++ iter nsources true
++ end in
++ iter max_sources false;
++ if !verbose_sources > 1 then
++ lprintf_nl "[cSrc] done connect_sources";
++ with Exit -> ()
+
+
+
+@@ -2077,36 +1963,34 @@
+ (* *)
+ (*************************************************************************)
+
+- let value_to_module f v =
+- match v with
+- Module list -> f list
+- | _ -> failwith "Option should be a module"
++ let value_to_module f v =
++ match v with
++ | Module list -> f list
++ | _ -> failwith "Option should be a module"
+
+- let option = define_option_class "Source"
+- (fun v ->
++ let option = define_option_class "Source"
++ (fun v ->
+ (* lprintf "(n) source !!\n"; *)
+- value_to_module value_to_source v)
+- (fun s -> Module (source_to_value s []))
++ value_to_module value_to_source v)
++ (fun s -> Module (source_to_value s []))
+
+- let file_sources_option = ref None
++ let file_sources_option = ref None
+
+- let attach_sources_to_file section =
++ let attach_sources_to_file section =
+ (* lprintf "attach_sources_to_file\n"; *)
+- let sources = match !file_sources_option with
+- None ->
++ let sources = match !file_sources_option with
++ | None ->
+ (* lprintf "attaching sources this time\n"; *)
+- let sources = define_option section
+- ["sources"] "" (listiter_option option) []
+- in
++ let sources = define_option section
++ ["sources"] "" (listiter_option option) [] in
+ (* lprintf "done\n"; *)
+- file_sources_option := Some sources;
+- sources
+- | Some sources -> sources
+- in
+- sources =:= [];
+- HS.iter (fun s -> sources =:= s :: !!sources) sources_by_uid;
++ file_sources_option := Some sources;
++ sources
++ | Some sources -> sources in
++ sources =:= [];
++ HS.iter (fun s -> sources =:= s :: !!sources) sources_by_uid;
+
+- (fun _ -> sources =:= [])
++ (fun _ -> sources =:= [])
+
+
+ (*************************************************************************)
+@@ -2115,82 +1999,70 @@
+ (* *)
+ (*************************************************************************)
+
+- let _ =
+- Heap.add_memstat M.module_name (fun level buf ->
++ let () =
++ Heap.add_memstat M.module_name (fun level buf ->
+
+- let nsources_per_queue = Array.create nqueues 0 in
+- let nready_per_queue = Array.create nqueues 0 in
+- List.iter (fun m ->
+- for i = 0 to nqueues -1 do
+- let q = m.manager_sources.(i) in
+- let nready = ref 0 in
+- let nsources = ref 0 in
+- let ready_threshold = last_time () - !!min_reask_delay in
+- Queue.iter (fun (time, s) ->
+- incr nsources;
+- if time < ready_threshold then
+- incr nready
+- else
+- if i = new_sources_queue then begin
+- Printf.bprintf buf "ERROR: Source is not ready in new_sources_queue !\n";
+- print_source buf s
+- end
+- ) q;
+- nsources_per_queue.(i) <- nsources_per_queue.(i) + !nsources;
+- nready_per_queue.(i) <- nready_per_queue.(i) + !nready;
+- done
+- ) !file_sources_managers;
+-
+- Printf.bprintf buf "\nFor all managers (%d):\n" (List.length !file_sources_managers);
+- for i = 0 to nqueues - 1 do
+- Printf.bprintf buf " Queue[%s]: %d entries (%d ready)\n"
+- queue_name.(i) nsources_per_queue.(i) nready_per_queue.(i);
+-
+- done;
+-
+- let nsources = ref 0 in
+- HS.iter (fun _ -> incr nsources) sources_by_uid;
+- Printf.bprintf buf "Sources by UID table: %d entries\n" !nsources;
+- Printf.bprintf buf "Sources by UID table stats: %d %d %d %d %d %d\n"
+- ((fun (n,_,_,_,_,_) -> n)(HS.stats sources_by_uid))
+- ((fun (_,n,_,_,_,_) -> n)(HS.stats sources_by_uid))
+- ((fun (_,_,n,_,_,_) -> n)(HS.stats sources_by_uid))
+- ((fun (_,_,_,n,_,_) -> n)(HS.stats sources_by_uid))
+- ((fun (_,_,_,_,n,_) -> n)(HS.stats sources_by_uid))
+- ((fun (_,_,_,_,_,n) -> n)(HS.stats sources_by_uid))
+- ;
++ let nsources_per_queue = Array.create nqueues 0 in
++ let nready_per_queue = Array.create nqueues 0 in
++ List.iter (fun m ->
++ for i = 0 to nqueues -1 do
++ let q = m.manager_sources.(i) in
++ let nready = ref 0 in
++ let nsources = ref 0 in
++ let ready_threshold = last_time () - !!min_reask_delay in
++ Queue.iter (fun (time, s) ->
++ incr nsources;
++ if time < ready_threshold then incr nready
++ else if i = new_sources_queue then begin
++ Printf.bprintf buf "ERROR: Source is not ready in new_sources_queue !\n";
++ print_source buf s
++ end
++ ) q;
++ nsources_per_queue.(i) <- nsources_per_queue.(i) + !nsources;
++ nready_per_queue.(i) <- nready_per_queue.(i) + !nready;
++ done
++ ) !file_sources_managers;
++
++ Printf.bprintf buf "\nFor all managers (%d):\n" (List.length !file_sources_managers);
++ for i = 0 to nqueues - 1 do
++ Printf.bprintf buf " Queue[%s]: %d entries (%d ready)\n"
++ queue_name.(i) nsources_per_queue.(i) nready_per_queue.(i);
++ done;
++
++ let nsources = ref 0 in
++ HS.iter (fun _ -> incr nsources) sources_by_uid;
++ Printf.bprintf buf "Sources by UID table: %d entries\n" !nsources;
++ let a1, a2, a3, a4, a5, a6 = HS.stats sources_by_uid in
++ Printf.bprintf buf "Sources by UID table stats: %d %d %d %d %d %d\n"
++ a1 a2 a3 a4 a5 a6;
+
+- nsources := 0;
+- H.iter (fun _ -> incr nsources) sources_by_num;
+- Printf.bprintf buf "Sources by NUM table: %d entries\n" !nsources;
+- Printf.bprintf buf "Sources by NUM table stats: %d %d %d %d %d %d\n"
+- ((fun (n,_,_,_,_,_) -> n)(H.stats sources_by_num))
+- ((fun (_,n,_,_,_,_) -> n)(H.stats sources_by_num))
+- ((fun (_,_,n,_,_,_) -> n)(H.stats sources_by_num))
+- ((fun (_,_,_,n,_,_) -> n)(H.stats sources_by_num))
+- ((fun (_,_,_,_,n,_) -> n)(H.stats sources_by_num))
+- ((fun (_,_,_,_,_,n) -> n)(H.stats sources_by_num))
+- ;
+-
+- Printf.bprintf buf "Used indirect connections: %d\n"
+- !indirect_connections;
+-
+- let nconnected = ref 0 in
+- Fifo.iter (fun (_,s) ->
+- if s.source_last_attempt = 0 then incr nconnected;
+- ) connecting_sources;
+- Printf.bprintf buf "Connecting Sources: %d entries"
+- (Fifo.length connecting_sources);
+- if !nconnected > 0 then Printf.bprintf buf " (connected: %d)" !nconnected;
+- Printf.bprintf buf "\n";
+-
+- Printf.bprintf buf "Next Direct Sources: %d entries\n"
+- (Fifo.length next_direct_sources);
+-
+- Printf.bprintf buf "Next Indirect Sources: %d entries\n"
+- (List.length !next_indirect_sources)
+- )
++ nsources := 0;
++ H.iter (fun _ -> incr nsources) sources_by_num;
++ Printf.bprintf buf "Sources by NUM table: %d entries\n" !nsources;
++ let a1, a2, a3, a4, a5, a6 = H.stats sources_by_num in
++ Printf.bprintf buf "Sources by NUM table stats: %d %d %d %d %d %d\n"
++ a1 a2 a3 a4 a5 a6;
++
++ Printf.bprintf buf "Used indirect connections: %d\n"
++ !indirect_connections;
++
++ let nconnected = ref 0 in
++ Fifo.iter (fun (_, s) ->
++ if s.source_last_attempt = 0 then incr nconnected;
++ ) connecting_sources;
++ Printf.bprintf buf "Connecting Sources: %d entries"
++ (Fifo.length connecting_sources);
++ if !nconnected > 0 then
++ Printf.bprintf buf " (connected: %d)" !nconnected;
++ Printf.bprintf buf "\n";
++
++ Printf.bprintf buf "Next Direct Sources: %d entries\n"
++ (Fifo.length next_direct_sources);
++
++ Printf.bprintf buf "Next Indirect Sources: %d entries\n"
++ (List.length !next_indirect_sources)
++ )
+
+- end)
++ end)
+
+
+Index: src/daemon/common/commonSources.mli
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonSources.mli,v
+retrieving revision 1.10
+retrieving revision 1.11
+diff -u -r1.10 -r1.11
+--- src/daemon/common/commonSources.mli 8 Apr 2006 02:16:21 -0000 1.10
++++ src/daemon/common/commonSources.mli 3 Dec 2006 20:47:12 -0000 1.11
+@@ -16,18 +16,7 @@
+ along with mldonkey; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *)
+-
+-open Queues
+-open Printf2
+-open Md4
+-open Options
+-open BasicSocket
+-
+-open TcpBufferedSocket
+-open CommonFile
+-open CommonOptions
+ open CommonTypes
+-
+
+ type request_result =
+ | File_possible (* we asked, but didn't know *)
+@@ -38,17 +27,16 @@
+ | File_upload (* we uploaded from this client *)
+ (* | File_unknown We don't know anything *)
+
+- (*
++(*
+ val initial_new_source_score : int
+ val new_source_score : int
+ val not_found_score : int
+-val possible_score : int
+ val found_score : int
+ val chunk_score : int
+ val upload_score : int
+ *)
+ val possible_score : int
+-
++
+ module Make(M:
+
+
+@@ -62,24 +50,25 @@
+ (*************************************************************************)
+ (*************************************************************************)
+
+- sig
+-
+- val module_name : string
+-
+- type source_uid
+- val dummy_source_uid : source_uid
+- val source_uid_to_value: source_uid -> Options.option_value
+- val value_to_source_uid: Options.option_value -> source_uid
+-
+- type source_brand
+- val dummy_source_brand : source_brand
+- val source_brand_to_value: source_brand -> Options.option_value
+- val value_to_source_brand: Options.option_value -> source_brand
++ sig
++ val module_name : string
++
++ type source_uid
++
++ val dummy_source_uid : source_uid
++ val source_uid_to_value: source_uid -> Options.option_value
++ val value_to_source_uid: Options.option_value -> source_uid
++
++ type source_brand
++
++ val dummy_source_brand : source_brand
++ val source_brand_to_value: source_brand -> Options.option_value
++ val value_to_source_brand: Options.option_value -> source_brand
+
+- val direct_source : source_uid -> bool
+- val indirect_source : source_uid -> bool
+- end) : (
+- sig
++ val direct_source : source_uid -> bool
++ val indirect_source : source_uid -> bool
++ end) : (
++ sig
+
+ (*************************************************************************)
+ (*************************************************************************)
+@@ -91,95 +80,95 @@
+ (*************************************************************************)
+ (*************************************************************************)
+
+- type source = {
+- source_uid : M.source_uid;
+- mutable source_files : file_request list;
+- mutable source_score : int;
+- mutable source_num : int;
+- mutable source_age : int;
+- mutable source_last_attempt : int;
+- mutable source_sock : tcp_connection;
+- mutable source_brand : M.source_brand;
+- }
+-
+- and file_request = {
+- request_file : file_sources_manager;
+- mutable request_queue : int;
+- mutable request_time : int;
+- mutable request_score : int;
+- }
+-
+- and file_sources_manager = {
+- manager_uid : string;
+- mutable manager_sources : source Queues.Queue.t array;
+- mutable manager_active_sources : int;
+- mutable manager_all_sources : int;
+- mutable manager_file : (unit -> file);
+- }
++ type source = {
++ source_uid : M.source_uid;
++ mutable source_files : file_request list;
++ mutable source_score : int;
++ mutable source_num : int;
++ mutable source_age : int;
++ mutable source_last_attempt : int;
++ mutable source_sock : tcp_connection;
++ mutable source_brand : M.source_brand;
++ }
++
++ and file_request = {
++ request_file : file_sources_manager;
++ mutable request_queue : int;
++ mutable request_time : int;
++ mutable request_score : int;
++ }
++
++ and file_sources_manager = {
++ manager_uid : string;
++ mutable manager_sources : source Queues.Queue.t array;
++ mutable manager_active_sources : int;
++ mutable manager_all_sources : int;
++ mutable manager_file : (unit -> file);
++ }
++
++ and functions = {
++ mutable function_connect: (M.source_uid -> unit);
++ mutable function_query: (M.source_uid -> string -> unit);
++ mutable function_string_to_manager: (string -> file_sources_manager);
++ mutable function_max_connections_per_second : (unit -> int);
++ mutable function_max_sources_per_file : (unit -> int);
+
+- and functions = {
+- mutable function_connect: (M.source_uid -> unit);
+- mutable function_query: (M.source_uid -> string -> unit);
+- mutable function_string_to_manager: (string -> file_sources_manager);
+- mutable function_max_connections_per_second : (unit -> int);
+- mutable function_max_sources_per_file : (unit -> int);
+-
+- mutable function_add_location :
+- (M.source_uid -> string -> unit);
+- mutable function_remove_location :
+- (M.source_uid -> string -> unit);
+- }
+-
+- val functions : functions
+-
+- val create_file_sources_manager :
+- string -> file_sources_manager
+- val remove_file_sources_manager :
+- file_sources_manager -> unit
+- val number_of_sources :
+- file_sources_manager -> int
+-
++ mutable function_add_location :
++ (M.source_uid -> string -> unit);
++ mutable function_remove_location :
++ (M.source_uid -> string -> unit);
++ }
++
++ val functions : functions
++
++ val create_file_sources_manager : string -> file_sources_manager
++ val remove_file_sources_manager : file_sources_manager -> unit
++(*
++ val number_of_sources : file_sources_manager -> int
++*)
+ (* Find a given source *)
+- val find_source_by_uid : M.source_uid -> source
+- val find_source_by_num : int -> source
+
++ val find_source_by_uid : M.source_uid -> source
++(*
++ val find_source_by_num : int -> source
++*)
+ (* Feed-back on sources *)
+- val source_connected : source -> unit
+- val source_disconnected : source -> unit
+- val add_request :
+- source -> file_sources_manager -> int -> file_request
+-
+- val set_request_result :
+- source -> file_sources_manager -> request_result -> unit
+- val find_request :
+- source -> file_sources_manager -> file_request
+- val find_request_result :
+- source -> file_sources_manager -> request_result
++ val source_connected : source -> unit
++ val source_disconnected : source -> unit
++
++ val add_request : source -> file_sources_manager -> int -> file_request
++ val set_request_result :
++ source -> file_sources_manager -> request_result -> unit
++ val find_request : source -> file_sources_manager -> file_request
++ val find_request_result : source -> file_sources_manager -> request_result
++
++ val need_new_sources : file_sources_manager -> bool
+
+- val need_new_sources : file_sources_manager -> bool
+-
+ (* Connect sources every second *)
+- val connect_sources : TcpBufferedSocket.connection_manager -> unit
+-
+- val attach_sources_to_file : Options.options_section -> (unit -> unit)
+-
+- val print : Buffer.t -> CommonTypes.output_type -> unit
+-
+- val indirect_connections : int ref
+-
+- val dummy_source : source
+-
+- val query_file : source -> file_sources_manager -> unit
+- val query_files : source -> unit
+-
+- val clean_sources : unit -> unit
+-
+- val iter_all_sources : (source -> unit) -> file_sources_manager -> unit
+- val iter_active_sources : (source -> unit) -> file_sources_manager -> unit
+- val iter_qualified_sources : (source -> unit) -> file_sources_manager -> unit
+- val iter_relevant_sources : (source -> unit) -> file_sources_manager -> unit
+-
+- val source_brand : source -> M.source_brand
+- val set_source_brand : source -> M.source_brand -> unit
+- end)
+-
++ val connect_sources : TcpBufferedSocket.connection_manager -> unit
++
++ val attach_sources_to_file : Options.options_section -> (unit -> unit)
++
++ val print : Buffer.t -> CommonTypes.output_type -> unit
++
++ val indirect_connections : int ref
++
++ val dummy_source : source
++(*
++ val query_file : source -> file_sources_manager -> unit
++*)
++ val query_files : source -> unit
++
++ val clean_sources : unit -> unit
++
++ val iter_all_sources : (source -> unit) -> file_sources_manager -> unit
++ val iter_active_sources : (source -> unit) -> file_sources_manager -> unit
++ val iter_qualified_sources :
++ (source -> unit) -> file_sources_manager -> unit
++ val iter_relevant_sources :
++ (source -> unit) -> file_sources_manager -> unit
++
++ val source_brand : source -> M.source_brand
++ val set_source_brand : source -> M.source_brand -> unit
++ end)
++
+Index: src/daemon/common/commonTypes.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonTypes.ml,v
+retrieving revision 1.64
+retrieving revision 1.65
+diff -u -r1.64 -r1.65
+--- src/daemon/common/commonTypes.ml 26 Nov 2006 16:36:29 -0000 1.64
++++ src/daemon/common/commonTypes.ml 3 Dec 2006 20:49:42 -0000 1.65
+@@ -265,6 +265,7 @@
+ | Field_Lastseencomplete
+ | Field_Mediacodec
+ | Field_Medialength
++| Field_KNOWN of string
+ | Field_UNKNOWN of string
+
+ type tag = {
+Index: src/daemon/common/commonUploads.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonUploads.ml,v
+retrieving revision 1.52
+retrieving revision 1.53
+diff -u -r1.52 -r1.53
+--- src/daemon/common/commonUploads.ml 26 Nov 2006 13:54:09 -0000 1.52
++++ src/daemon/common/commonUploads.ml 3 Dec 2006 20:57:56 -0000 1.53
+@@ -687,7 +687,7 @@
+ impl_shared_ops = shared_ops;
+ impl_shared_val = sh;
+ impl_shared_requests = 0;
+- impl_shared_magic = None;
++ impl_shared_file = None;
+ impl_shared_servers = [];
+ }
+ and sh = {
+Index: src/daemon/common/guiDecoding.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/daemon/common/guiDecoding.ml,v
+retrieving revision 1.66
+retrieving revision 1.67
+diff -u -r1.66 -r1.67
+--- src/daemon/common/guiDecoding.ml 26 Nov 2006 13:54:09 -0000 1.66
++++ src/daemon/common/guiDecoding.ml 2 Dec 2006 12:35:45 -0000 1.67
+@@ -816,8 +816,10 @@
+ client_os = None;
+ client_release = "";
+ client_emulemod = "";
+- client_downloaded = zero;
+- client_uploaded = zero;
++ client_total_downloaded = zero;
++ client_total_uploaded = zero;
++ client_session_downloaded = zero;
++ client_session_uploaded = zero;
+ client_upload = None;
+ client_sui_verified = None;
+ (* client_sock_addr = ""; *)
+@@ -875,8 +877,10 @@
+ client_os = None;
+ client_release = release;
+ client_emulemod = emulemod;
+- client_downloaded = downloaded;
+- client_uploaded = uploaded;
++ client_total_downloaded = downloaded;
++ client_total_uploaded = uploaded;
++ client_session_downloaded = 0L;
++ client_session_uploaded = 0L;
+ client_upload = upload;
+ client_sui_verified = verified;
+ (* client_sock_addr = sock_addr; *)
+Index: src/daemon/common/guiEncoding.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/daemon/common/guiEncoding.ml,v
+retrieving revision 1.61
+retrieving revision 1.62
+diff -u -r1.61 -r1.62
+--- src/daemon/common/guiEncoding.ml 26 Nov 2006 16:36:29 -0000 1.61
++++ src/daemon/common/guiEncoding.ml 2 Dec 2006 12:35:45 -0000 1.62
+@@ -669,8 +669,8 @@
+ end else
+ begin
+ buf_string buf (client_software_short c.client_software c.client_os);
+- buf_int64 buf c.client_downloaded;
+- buf_int64 buf c.client_uploaded;
++ buf_int64 buf c.client_session_downloaded;
++ buf_int64 buf c.client_session_uploaded;
+ (match c.client_upload with
+ Some s -> buf_string buf s
+ | None -> buf_string buf "");
+Index: src/daemon/common/guiTypes.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/daemon/common/guiTypes.ml,v
+retrieving revision 1.34
+retrieving revision 1.35
+diff -u -r1.34 -r1.35
+--- src/daemon/common/guiTypes.ml 14 Nov 2006 18:42:59 -0000 1.34
++++ src/daemon/common/guiTypes.ml 2 Dec 2006 12:35:45 -0000 1.35
+@@ -219,8 +219,10 @@
+ mutable client_os : string option;
+ mutable client_release : string;
+ mutable client_emulemod : string;
+- mutable client_downloaded : int64;
+- mutable client_uploaded : int64;
++ mutable client_total_downloaded : int64;
++ mutable client_total_uploaded : int64;
++ mutable client_session_downloaded : int64;
++ mutable client_session_uploaded : int64;
+ mutable client_upload : string option;
+ mutable client_sui_verified : bool option;
+ (* mutable client_sock_addr : string; *)
+Index: src/daemon/driver/driverCommands.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/daemon/driver/driverCommands.ml,v
+retrieving revision 1.202
+retrieving revision 1.209
+diff -u -r1.202 -r1.209
+--- src/daemon/driver/driverCommands.ml 28 Nov 2006 23:15:21 -0000 1.202
++++ src/daemon/driver/driverCommands.ml 8 Dec 2006 12:26:24 -0000 1.209
+@@ -343,7 +343,7 @@
+ web_infos_add kind period url;
+ CommonWeb.load_url true kind url;
+ "url added to web_infos. downloading now"
+- ), "<kind> <url> [<period>]:\t\tload this file from the web\n"
++ ), "<kind> <url> [<period>] :\tload this file from the web\n"
+ ^"\t\t\t\t\tkind is either server.met (if the downloaded file is a server.met)\n"
+ ^"\t\t\t\t\tperiod is the period between updates (in hours, default 0 = only loaded at startup)";
+
+@@ -390,7 +390,12 @@
+ ( "0", "srh", "Client brand", "CB" ) ;
+ ( "0", "srh", "Client release", "CR" ) ;
+ ] @
+- (if !!emule_mods_count then [( "0", "srh", "eMule MOD", "EM" )] else []));
++ (if !!emule_mods_count then [( "0", "srh", "eMule MOD", "EM" )] else [])
++ @ [
++ ( "1", "srh ar", "Total UL bytes to this client for all files", "tUL" ) ;
++ ( "1", "srh ar br", "Total DL bytes from this client for all files", "tDL" ) ;
++ ( "1", "srh ar", "Session UL bytes to this client for all files", "sUL" ) ;
++ ( "1", "srh ar", "Session DL bytes from this client for all files", "sDL" )]);
+
+ let counter = ref 0 in
+ let all_clients_list = clients_get_all () in
+@@ -409,7 +414,12 @@
+ (client_software i.client_software i.client_os, "sr", client_software_short i.client_software i.client_os);
+ ("", "sr", i.client_release);
+ ] @
+- (if !!emule_mods_count then [("", "sr", i.client_emulemod)] else []));
++ (if !!emule_mods_count then [("", "sr", i.client_emulemod)] else [])
++ @ [
++ ("", "sr ar", (size_of_int64 i.client_total_uploaded));
++ ("", "sr ar br", (size_of_int64 i.client_total_downloaded));
++ ("", "sr ar", (size_of_int64 i.client_session_uploaded));
++ ("", "sr ar", (size_of_int64 i.client_session_downloaded))]);
+ if use_html_mods o then Printf.bprintf buf "\\</tr\\>"
+ else Printf.bprintf buf "\n";
+ incr counter;
+@@ -423,7 +433,7 @@
+ client_print c o;
+ ) args;
+ ""
+- ), "<num> :\t\t\t\tview client (use arg 'all' for all clients)";
++ ), "<num|all> :\t\t\t\tview client (use arg 'all' for all clients)";
+
+ "version", Arg_none (fun o ->
+ print_command_result o o.conn_buf (CommonGlobals.version ());
+@@ -848,7 +858,7 @@
+ ) args;
+ print_result !counter;
+ ""
+- ), "<server numbers|all> :\t\t\t\tdisconnect from server(s)";
++ ), "<server numbers|all> :\t\tdisconnect from server(s)";
+
+ ]
+
+@@ -896,7 +906,7 @@
+ ) args;
+ Printf.sprintf (_b "%d friends removed") (List.length args)
+ end
+- ), "<client numbers> :\tremove friend (use arg 'all' for all friends)";
++ ), "<client numbers|all> :\tremove friend (use arg 'all' for all friends)";
+
+ "friends", Arg_none (fun o ->
+ let buf = o.conn_buf in
+@@ -1362,7 +1372,7 @@
+ (if s.search_waiting = 0 then _s "done" else
+ string_of_int s.search_waiting)
+ s.search_nresults
+- ) (Sort.list (fun f1 f2 -> f1.search_num < f2.search_num)
++ ) (List.sort (fun f1 f2 -> compare f1.search_num f2.search_num)
+ user.ui_user_searches)
+ end;
+ ""
+@@ -1767,6 +1777,7 @@
+ [
+ strings_of_option previewer;
+ strings_of_option temp_directory;
++ strings_of_option share_scan_interval;
+ strings_of_option hdd_temp_minfree;
+ strings_of_option hdd_temp_stop_core;
+ strings_of_option hdd_coredir_minfree;
+@@ -1777,7 +1788,8 @@
+ strings_of_option allow_browse_share;
+ strings_of_option auto_commit;
+ strings_of_option pause_new_downloads;
+- strings_of_option create_dir_mask;
++ strings_of_option create_file_mode;
++ strings_of_option create_dir_mode;
+ strings_of_option create_file_sparse;
+ strings_of_option log_file;
+ strings_of_option log_file_size;
+@@ -2415,8 +2427,10 @@
+ ] @
+ (if !!emule_mods_count then [( "0", "srh", "eMule MOD", "EM" )] else [])
+ @ [
+- ( "0", "srh ar", "Total DL bytes from this client for all files", "DL" ) ;
+- ( "0", "srh ar", "Total UL bytes to this client for all files", "UL" ) ;
++ ( "0", "srh ar", "Total DL bytes from this client for all files", "tDL" ) ;
++ ( "0", "srh ar", "Total UL bytes to this client for all files", "tUL" ) ;
++ ( "0", "srh ar", "Session DL bytes from this client for all files", "sDL" ) ;
++ ( "0", "srh ar", "Session UL bytes to this client for all files", "sUL" ) ;
+ ( "0", "srh ar", "Slot kind", "Slot" ) ;
+ ( "0", "srh", "Filename", "Filename" ) ]);
+
+@@ -2432,7 +2446,7 @@
+ onMouseOut=\\\"mOut(this);\\\"
+ onClick=\\\"parent.fstatus.location.href='submit?q=friend_add+%d'\\\"\\>"
+ ( if (!counter mod 2 == 0) then "dl-1" else "dl-2";) (client_num c)
+- ( float_of_int (Int64.to_int i.client_uploaded / 1024) /.
++ ( float_of_int (Int64.to_int i.client_session_uploaded / 1024) /.
+ float_of_int (max 1 ((last_time ()) - i.client_connect_time)) )
+ (client_num c);
+
+@@ -2455,8 +2469,10 @@
+ ] @
+ (if !!emule_mods_count then [("", "sr", i.client_emulemod)] else [])
+ @ [
+- ("", "sr ar", size_of_int64 i.client_downloaded);
+- ("", "sr ar", size_of_int64 i.client_uploaded);
++ ("", "sr ar", size_of_int64 i.client_total_downloaded);
++ ("", "sr ar", size_of_int64 i.client_total_uploaded);
++ ("", "sr ar", size_of_int64 i.client_session_downloaded);
++ ("", "sr ar", size_of_int64 i.client_session_uploaded);
+ (let text1, text2 =
+ match client_slot c with
+ | FriendSlot -> "Friend", "F"
+@@ -2494,8 +2510,10 @@
+ ] @
+ (if !!emule_mods_count then [( "0", "srh", "eMule MOD", "EM" )] else [])
+ @ [
+- ( "0", "srh ar", "Total DL bytes from this client for all files", "DL" ) ;
+- ( "0", "srh ar", "Total UL bytes to this client for all files", "UL" ) ;
++ ( "0", "srh ar", "Total DL bytes from this client for all files", "tDL" ) ;
++ ( "0", "srh ar", "Total UL bytes to this client for all files", "tUL" ) ;
++ ( "0", "srh ar", "Session DL bytes from this client for all files", "sDL" ) ;
++ ( "0", "srh ar", "Session UL bytes to this client for all files", "sUL" ) ;
+ ( "0", "srh", "Filename", "Filename" ) ]);
+
+ Intmap.iter (fun cnum c ->
+@@ -2527,8 +2545,10 @@
+ ] @
+ (if !!emule_mods_count then [("", "sr", i.client_emulemod )] else [])
+ @ [
+- ("", "sr ar", size_of_int64 i.client_downloaded);
+- ("", "sr ar", size_of_int64 i.client_uploaded);
++ ("", "sr ar", size_of_int64 i.client_total_downloaded);
++ ("", "sr ar", size_of_int64 i.client_total_uploaded);
++ ("", "sr ar", size_of_int64 i.client_session_downloaded);
++ ("", "sr ar", size_of_int64 i.client_session_uploaded);
+ ("", "sr", (match i.client_upload with
+ Some f -> shorten f !!max_name_len
+ | None -> "") ) ]);
+@@ -2547,7 +2567,7 @@
+ try
+ let i = client_info c in
+ client_print c o;
+- Printf.bprintf buf "client: %s downloaded: %s uploaded: %s\n" i.client_software (Int64.to_string i.client_downloaded) (Int64.to_string i.client_uploaded);
++ Printf.bprintf buf "client: %s downloaded: %s uploaded: %s\n" i.client_software (Int64.to_string i.client_total_downloaded) (Int64.to_string i.client_total_uploaded);
+ match i.client_upload with
+ Some cu ->
+ Printf.bprintf buf " filename: %s\n" cu
+@@ -2658,7 +2678,7 @@
+ end
+ ) !!files) args;
+ files_to_cancel o
+- ), "<num> :\t\t\t\tcancel download (use arg 'all' for all files)";
++ ), "<num|all> :\t\t\tcancel download (use arg 'all' for all files)";
+
+ "downloaders", Arg_none (fun o ->
+ let buf = o.conn_buf in
+@@ -2679,8 +2699,10 @@
+ ( "0", "srh", "Secure User Identification [N]one, [P]assed, [F]ailed", "S" ) ;
+ ( "0", "srh", "IP address", "IP address" ) ;
+ ] @ (if !Geoip.active then [( "0", "srh", "Country Code/Name", "CC" )] else []) @ [
+- ( "1", "srh ar", "Total UL bytes to this client for all files", "UL" ) ;
+- ( "1", "srh ar", "Total DL bytes from this client for all files", "DL" ) ;
++ ( "1", "srh ar", "Total UL bytes to this client for all files", "tUL");
++ ( "1", "srh ar", "Total DL bytes from this client for all files", "tDL");
++ ( "1", "srh ar", "Session UL bytes to this client for all files", "sUL");
++ ( "1", "srh ar", "Session DL bytes from this client for all files", "sDL");
+ ( "0", "srh", "Filename", "Filename" ) ]);
+
+ let counter = ref 0 in
+@@ -2725,7 +2747,7 @@
+ if (as_file_impl file).impl_file_num = num then
+ file_pause file o.conn_user.ui_user
+ ) !!files) args; ""
+- ), "<num> :\t\t\t\tpause a download (use arg 'all' for all files)";
++ ), "<num|all> :\t\t\tpause a download (use arg 'all' for all files)";
+
+ "resume", Arg_multiple (fun args o ->
+ if args = ["all"] && user2_is_admin o.conn_user.ui_user then
+@@ -2739,7 +2761,7 @@
+ if (as_file_impl file).impl_file_num = num then
+ file_resume file o.conn_user.ui_user
+ ) !!files) args; ""
+- ), "<num> :\t\t\t\tresume a paused download (use arg 'all' for all files)";
++ ), "<num|all> :\t\t\tresume a paused download (use arg 'all' for all files)";
+
+ "release", Arg_one (fun arg o ->
+ let num = int_of_string arg in
+@@ -3080,7 +3102,7 @@
+ else
+ print_command_result o buf "You are not allowed to add a group";
+ _s ""
+- ), "<group> <admin: true | false>: add new mldonkey group";
++ ), "<group> <admin: true|false> :\tadd new mldonkey group";
+
+ "groupdel", Arg_one (fun group o ->
+ let buf = o.conn_buf in
+@@ -3345,22 +3367,22 @@
+ end
+ end else print_command_result o buf "You are not allowed to list users";
+ _s ""
+- ), "\t\t\t\t\tprint users";
++ ), ":\t\t\t\t\tprint users";
+
+ "whoami", Arg_none (fun o ->
+ print_command_result o o.conn_buf o.conn_user.ui_user.user_name;
+ _s ""
+- ), "\t\t\t\t\tprint logged-in user name";
++ ), ":\t\t\t\tprint logged-in user name";
+
+ "groups", Arg_none (fun o ->
+ print_command_result o o.conn_buf (user2_print_user_groups " " o.conn_user.ui_user);
+ _s ""
+- ), "\t\t\t\t\tprint groups of logged-in user";
++ ), ":\t\t\t\tprint groups of logged-in user";
+
+ "dgroup", Arg_none (fun o ->
+ print_command_result o o.conn_buf (user2_print_user_default_group o.conn_user.ui_user);
+ _s ""
+- ), "\t\t\t\t\tprint default group of logged-in user";
++ ), ":\t\t\t\tprint default group of logged-in user";
+
+ "chgrp", Arg_two (fun group filenum o ->
+ let num = int_of_string filenum in
+@@ -3368,8 +3390,13 @@
+ let file = file_find num in
+ if String.lowercase group = "none" then
+ begin
+- set_file_group file None;
+- print_command_result o o.conn_buf (Printf.sprintf (_b "Changed group of download %d to %s") num group)
++ if user2_allow_file_admin file o.conn_user.ui_user then
++ begin
++ set_file_group file None;
++ print_command_result o o.conn_buf (Printf.sprintf (_b "Changed group of download %d to %s") num group)
++ end
++ else
++ print_command_result o o.conn_buf (Printf.sprintf (_b "You are not allowed to change group of download %d to %s") num group)
+ end
+ else
+ begin
+@@ -3401,7 +3428,19 @@
+ if user2_allow_file_admin file o.conn_user.ui_user then
+ begin
+ set_file_owner file u;
+- print_command_result o o.conn_buf (Printf.sprintf (_b "Changed owner of download %d to %s") num user)
++ match file_group file with
++ | None ->
++ print_command_result o o.conn_buf (Printf.sprintf (_b "Changed owner of download %d to %s") num user)
++ | Some g ->
++ if List.mem g u.user_groups then
++ print_command_result o o.conn_buf (Printf.sprintf (_b "Changed owner of download %d to %s") num user)
++ else
++ begin
++ set_file_group file u.user_default_group;
++ print_command_result o o.conn_buf (Printf.sprintf
++ (_b "owner %s is not member of file_group %s, changing file_group to user_default_group %s")
++ user g.group_name (user2_print_user_default_group u))
++ end
+ end
+ else
+ print_command_result o o.conn_buf (Printf.sprintf (_b "You are not allowed to change owner of download %d to %s") num user)
+Index: src/daemon/driver/driverInteractive.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/daemon/driver/driverInteractive.ml,v
+retrieving revision 1.118
+retrieving revision 1.122
+diff -u -r1.118 -r1.122
+--- src/daemon/driver/driverInteractive.ml 28 Nov 2006 23:17:31 -0000 1.118
++++ src/daemon/driver/driverInteractive.ml 3 Dec 2006 20:57:56 -0000 1.122
+@@ -1115,7 +1115,8 @@
+
+ if o.conn_output <> HTML && !!improved_telnet then
+ begin
+- let list = Sort.list (fun f1 f2 -> percent f1 >= percent f2) list in
++ let list =
++ List.sort (fun f1 f2 -> compare (percent f2) (percent f1)) list in
+ simple_print_file_list false buf list o
+ end
+ else
+@@ -1124,29 +1125,37 @@
+ let sorter =
+ match o.conn_sortvd with
+
+- | BySize -> (fun f1 f2 -> f1.file_size >= f2.file_size)
++ | BySize -> (fun f1 f2 -> compare f2.file_size f1.file_size)
+ | ByRate -> (fun f1 f2 ->
+- if stalled f1 then false else
+- if stalled f2 then true else
+- f1.file_download_rate >= f2.file_download_rate
+- )
+- | ByName -> (fun f1 f2 -> String.lowercase f1.file_name <= String.lowercase f2.file_name)
+- | ByDone -> (fun f1 f2 -> f1.file_downloaded >= f2.file_downloaded)
+- | ByPriority -> (fun f1 f2 -> f1.file_priority >= f2.file_priority)
+- | BySources -> (fun f1 f2 -> (number_of_sources f1) >= (number_of_sources f2))
+- | ByASources -> (fun f1 f2 -> (number_of_active_sources f1) >= (number_of_active_sources f2))
+- | ByPercent -> (fun f1 f2 -> percent f1 >= percent f2)
+- | ByETA -> (fun f1 f2 -> calc_file_eta f1 <= calc_file_eta f2)
+- | ByAge -> (fun f1 f2 -> f1.file_age >= f2.file_age)
+- | ByLast -> (fun f1 f2 -> f1.file_last_seen >= f2.file_last_seen)
+- | ByNet -> (fun f1 f2 -> net_name f1 <= net_name f2)
+- | ByAvail -> (fun f1 f2 -> get_file_availability f1 >= get_file_availability f2)
+- | ByComments -> (fun f1 f2 -> (number_of_comments f1) >= (number_of_comments f2))
+- | ByUser -> (fun f1 f2 -> f1.file_user <= f2.file_user)
+- | ByGroup -> (fun f1 f2 -> f1.file_group <= f2.file_group)
++ if stalled f1 then 1 else
++ if stalled f2 then -1 else
++ compare f2.file_download_rate f1.file_download_rate)
++ | ByName -> (fun f1 f2 -> String.compare
++ (String.lowercase f1.file_name)
++ (String.lowercase f2.file_name))
++ | ByDone -> (fun f1 f2 ->
++ compare f2.file_downloaded f1.file_downloaded)
++ | ByPriority -> (fun f1 f2 ->
++ compare f2.file_priority f1.file_priority)
++ | BySources -> (fun f1 f2 -> compare
++ (number_of_sources f2) (number_of_sources f1))
++ | ByASources -> (fun f1 f2 ->
++ compare (number_of_active_sources f2)
++ (number_of_active_sources f1))
++ | ByPercent -> (fun f1 f2 -> compare (percent f2) (percent f1))
++ | ByETA -> (fun f1 f2 -> compare (calc_file_eta f1) (calc_file_eta f2))
++ | ByAge -> (fun f1 f2 -> compare f2.file_age f1.file_age)
++ | ByLast -> (fun f1 f2 -> compare f2.file_last_seen f1.file_last_seen)
++ | ByNet -> (fun f1 f2 -> compare (net_name f1) (net_name f2))
++ | ByAvail -> (fun f1 f2 -> compare
++ (get_file_availability f2) (get_file_availability f1))
++ | ByComments -> (fun f1 f2 -> compare
++ (number_of_comments f2) (number_of_comments f1))
++ | ByUser -> (fun f1 f2 -> compare f1.file_user f2.file_user)
++ | ByGroup -> (fun f1 f2 -> compare f1.file_group f2.file_group)
+ | NotSorted -> raise Not_found
+ in
+- Sort.list sorter list
++ List.sort sorter list
+ with _ -> list
+ in
+ simple_print_file_list false buf list o
+@@ -1259,7 +1268,7 @@
+ let nl = ref false in
+ List.iter (fun t ->
+ match t.tag_name with
+- | Field_UNKNOWN "FTH" | Field_UNKNOWN "urn" -> ()
++ | Field_KNOWN "FTH" | Field_KNOWN "urn" -> ()
+ | _ ->
+ Buffer.add_string buf ((if !nl then "<br>" else begin nl := true;"" end) ^
+ escaped_string_of_field t ^ ": " ^ get_tag_value t);
+@@ -1275,7 +1284,7 @@
+ let nl = ref false in
+ List.iter (fun t ->
+ match t.tag_name with
+- | Field_UNKNOWN "FTH" | Field_UNKNOWN "urn" -> ()
++ | Field_KNOWN "FTH" | Field_KNOWN "urn" -> ()
+ | _ ->
+ Buffer.add_string buf ((if !nl then "\n" else begin nl := true;"" end) ^
+ "|| (" ^
+@@ -1331,8 +1340,8 @@
+ let cformat = ref "" in
+ List.iter (fun t ->
+ (match t.tag_name with
+- | Field_UNKNOWN "urn"
+- | Field_UNKNOWN "FTH" -> hash := get_tag_value t
++ | Field_KNOWN "urn"
++ | Field_KNOWN "FTH" -> hash := get_tag_value t
+ | Field_Availability -> cavail := get_tag_value t
+ | Field_Completesources -> csource := get_tag_value t
+ | Field_Length -> clength := get_tag_value t
+@@ -1383,9 +1392,9 @@
+ | Field_Format
+ | Field_Bitrate
+ (* TODO : "urn" shouldn't be some kind of Field_Uid of Gnutella ? *)
+- | Field_UNKNOWN "urn"
++ | Field_KNOWN "urn"
+ (* TODO : "FTH" shouldn't be some kind of Field_Uid of Fasttrack ? *)
+- | Field_UNKNOWN "FTH" -> ()
++ | Field_KNOWN "FTH" -> ()
+ | _ ->
+ Buffer.add_string buf ("\\<span title=\\\"" ^
+ get_tag_value t ^ "\\\"\\>(" ^
+@@ -1490,9 +1499,9 @@
+ user.ui_last_results <- (!counter, rs) :: user.ui_last_results;
+ files := [|
+
++ (Printf.sprintf "[%5d]\\<input name=d type=checkbox value=%d\\>" !counter r.result_num);
+ (Int64.to_string r.result_size);
+ (string_of_int avail);
+- (Printf.sprintf "[%5d]\\<input name=d type=checkbox value=%d\\>" !counter r.result_num);
+
+ (
+ let names = r.result_names in
+@@ -1704,8 +1713,8 @@
+ Intmap.iter (fun r_num (avail,rs) ->
+ let r = IndexedResults.get_result rs in
+ results := (rs, r, !avail) :: !results) s.search_results;
+- let results = Sort.list (fun (_, r1,_) (_, r2,_) ->
+- r1.result_size > r2.result_size
++ let results = List.sort (fun (_, r1,_) (_, r2,_) ->
++ compare r2.result_size r1.result_size
+ ) !results in
+
+ Printf.bprintf buf "Result of search %d\n" s.search_num;
+@@ -2448,7 +2457,9 @@
+ ( "0", "srh", "Preview", "P" ) ;
+ ( "0", "srh", "Filename", "Filename" );
+ ( "0", "srh", "Statistic links", "Stats" );
+- ( "0", "srh", "Published on servers", "Publ" ) ]
++ ( "0", "srh", "Published on servers", "Publ" );
++ ( "0", "srh", "Share status", "Status" )
++ ]
+ else
+ begin
+ Printf.bprintf buf " Requests | Bytes | Uploaded | File\n";
+@@ -2456,10 +2467,10 @@
+ end;
+
+ html_mods_cntr_init ();
+- let list = Sort.list (fun f1 f2 ->
+- (f1.impl_shared_requests = f2.impl_shared_requests &&
+- f1.impl_shared_uploaded > f2.impl_shared_uploaded) ||
+- (f1.impl_shared_requests > f2.impl_shared_requests )
++ let list = List.sort (fun f1 f2 ->
++ let c = compare f2.impl_shared_requests f1.impl_shared_requests in
++ if c <> 0 then c else
++ compare f2.impl_shared_uploaded f1.impl_shared_uploaded
+ ) list in
+
+ List.iter (fun impl ->
+@@ -2474,8 +2485,9 @@
+ (if !!html_mods_use_js_tooltips then
+ Printf.bprintf buf " onMouseOver=\\\"mOvr(this);setTimeout('popLayer(\\\\\'%s<br>%s%s\\\\\')',%d);setTimeout('hideLayer()',%d);return true;\\\" onMouseOut=\\\"mOut(this);hideLayer();setTimeout('hideLayer()',%d)\\\"\\>"
+ (Http_server.html_real_escaped (Filename.basename (Charset.to_utf8 impl.impl_shared_codedname)))
+- (match impl.impl_shared_magic with
+- None -> ""
++ (match impl.impl_shared_file with
++ None -> "no file info"
++ | Some file -> match file_magic file with | None -> "no magic"
+ | Some magic -> "File type: " ^ (Http_server.html_real_escaped magic) ^ "<br>")
+ (if impl.impl_shared_servers = [] then "" else
+ Printf.sprintf "<br>Published on %d %s<br>%s"
+@@ -2497,7 +2509,6 @@
+
+ let uploaded = Int64.to_float impl.impl_shared_uploaded in
+ let size = Int64.to_float impl.impl_shared_size in
+-
+ html_mods_td buf [
+ ("", "sr ar", Printf.sprintf "%d" impl.impl_shared_requests);
+ ("", "sr ar", size_of_int64 impl.impl_shared_uploaded);
+@@ -2515,7 +2526,9 @@
+ (Md4.to_string impl.impl_shared_id) "T1"
+ (Md4.to_string impl.impl_shared_id) "T2"
+ (Md4.to_string impl.impl_shared_id) "B"));
+- ("", "sr ar", Printf.sprintf "%d" published ) ];
++ ("", "sr ar", Printf.sprintf "%d" published);
++ ("", "sr", shared_state (as_shared impl) o);
++ ];
+ Printf.bprintf buf "\\</tr\\>\n";
+ end
+ else
+Index: src/daemon/driver/driverMain.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/daemon/driver/driverMain.ml,v
+retrieving revision 1.133
+retrieving revision 1.134
+diff -u -r1.133 -r1.134
+--- src/daemon/driver/driverMain.ml 28 Nov 2006 23:15:21 -0000 1.133
++++ src/daemon/driver/driverMain.ml 8 Dec 2006 12:26:25 -0000 1.134
+@@ -54,7 +54,6 @@
+
+ let minute_timer () =
+ DriverInteractive.hdd_check ();
+- CommonShared.shared_check_files ();
+ CommonUploads.upload_credit_timer ();
+ CommonInteractive.force_download_quotas ();
+ CommonResult.dummy_result.result_time <- last_time ();
+@@ -446,6 +445,10 @@
+ add_infinite_timer 0.1 CommonUploads.upload_download_timer;
+ add_infinite_timer !!buffer_writes_delay (fun _ -> Unix32.flush ());
+
++ add_infinite_timer ((float_of_int !!share_scan_interval) *. 60.)
++ (fun _ -> CommonShared.shared_check_files ());
++ CommonShared.shared_check_files ();
++
+ history_timeflag := (Unix.time());
+ update_download_history ();
+ update_upload_history ();
+Index: src/gtk/newgui/gui_downloads.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/gtk/newgui/gui_downloads.ml,v
+retrieving revision 1.18
+retrieving revision 1.19
+diff -u -r1.18 -r1.19
+--- src/gtk/newgui/gui_downloads.ml 28 Nov 2006 12:58:11 -0000 1.18
++++ src/gtk/newgui/gui_downloads.ml 2 Dec 2006 12:35:46 -0000 1.19
+@@ -1389,8 +1389,8 @@
+ else (c.client_software ^
+ " - " ^
+ c.client_emulemod))];
+- child.data.gfile_size <- c.client_uploaded;
+- child.data.gfile_downloaded <- c.client_downloaded;
++ child.data.gfile_size <- c.client_total_uploaded;
++ child.data.gfile_downloaded <- c.client_total_downloaded;
+ child.data.gfile_state <- client_to_general_state c.client_state (List.hd f.data.gfile_num);
+ child.data.gfile_chunks <- f.data.gfile_chunks;
+ child.data.gfile_name <-
+@@ -1412,8 +1412,8 @@
+ " - " ^
+ c.client_emulemod];
+ f.data.gfile_state <- client_to_general_state c.client_state file_num;
+- f.data.gfile_size <- c.client_uploaded;
+- f.data.gfile_downloaded <- c.client_downloaded;
++ f.data.gfile_size <- c.client_total_uploaded;
++ f.data.gfile_downloaded <- c.client_total_downloaded;
+ if f.data.gfile_type <> c.client_type then
+ begin
+ f.data.gfile_type <- c.client_type;
+Index: src/gtk/newgui/gui_friends.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/gtk/newgui/gui_friends.ml,v
+retrieving revision 1.20
+retrieving revision 1.21
+diff -u -r1.20 -r1.21
+--- src/gtk/newgui/gui_friends.ml 28 Nov 2006 12:58:11 -0000 1.20
++++ src/gtk/newgui/gui_friends.ml 2 Dec 2006 12:35:46 -0000 1.21
+@@ -435,8 +435,10 @@
+ client_os = None;
+ client_release = c.gclient_release;
+ client_emulemod = c.gclient_emulemod;
+- client_downloaded = c.gclient_downloaded;
+- client_uploaded = c.gclient_uploaded;
++ client_total_downloaded = c.gclient_downloaded;
++ client_total_uploaded = c.gclient_uploaded;
++ client_session_downloaded = 0L;
++ client_session_uploaded = 0L;
+ client_upload = c.gclient_upload;
+ client_sui_verified = None;
+ (* client_sock_addr = c.gclient_sock_addr;*)
+@@ -457,8 +459,8 @@
+ gclient_software = c.client_software;
+ gclient_release = c.client_release;
+ gclient_emulemod = c.client_emulemod;
+- gclient_downloaded = c.client_downloaded;
+- gclient_uploaded = c.client_uploaded;
++ gclient_downloaded = c.client_total_downloaded;
++ gclient_uploaded = c.client_total_uploaded;
+ gclient_upload = c.client_upload;
+ gclient_sock_addr = string_of_kind c.client_kind;
+ gclient_net_pixmap =
+@@ -494,8 +496,8 @@
+ f.gclient_software <- f_new.client_software;
+ f.gclient_release <- f_new.client_release;
+ f.gclient_emulemod <- f_new.client_emulemod;
+- f.gclient_downloaded <- f_new.client_downloaded;
+- f.gclient_uploaded <- f_new.client_uploaded;
++ f.gclient_downloaded <- f_new.client_total_downloaded;
++ f.gclient_uploaded <- f_new.client_total_uploaded;
+ f.gclient_upload <- f_new.client_upload;
+ f.gclient_sock_addr <- string_of_kind f_new.client_kind;
+ if box_friends_is_visible then self#update_row f row
+@@ -643,8 +645,10 @@
+ client_os = None;
+ client_release = c.gclient_release;
+ client_emulemod = c.gclient_emulemod;
+- client_downloaded = c.gclient_downloaded;
+- client_uploaded = c.gclient_uploaded;
++ client_total_downloaded = c.gclient_downloaded;
++ client_total_uploaded = c.gclient_uploaded;
++ client_session_downloaded = 0L;
++ client_session_uploaded = 0L;
+ client_upload = c.gclient_upload;
+ client_sui_verified = None;
+ (* client_sock_addr = string_of_kind c.gclient_kind; *)
+@@ -665,8 +669,8 @@
+ gclient_software = c.client_software;
+ gclient_release = c.client_release;
+ gclient_emulemod = c.client_emulemod;
+- gclient_downloaded = c.client_downloaded;
+- gclient_uploaded = c.client_uploaded;
++ gclient_downloaded = c.client_total_downloaded;
++ gclient_uploaded = c.client_total_uploaded;
+ gclient_upload = c.client_upload;
+ gclient_sock_addr = string_of_kind c.client_kind;
+ gclient_net_pixmap =
+@@ -711,9 +715,9 @@
+ c.gclient_kind <- c_new.client_kind;
+ c.gclient_tags <- c_new.client_tags;
+ c.gclient_software <- c_new.client_software;
+- c.gclient_downloaded <- c_new.client_downloaded;
++ c.gclient_downloaded <- c_new.client_total_downloaded;
+ c.gclient_emulemod <- c_new.client_emulemod;
+- c.gclient_uploaded <- c_new.client_uploaded;
++ c.gclient_uploaded <- c_new.client_total_uploaded;
+ c.gclient_upload <- c_new.client_upload;
+ c.gclient_sock_addr <- string_of_kind c_new.client_kind;
+ (if icons_are_used && (c.gclient_type <> c_new.client_type)
+Index: src/gtk/newgui/gui_results.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/gtk/newgui/gui_results.ml,v
+retrieving revision 1.10
+retrieving revision 1.11
+diff -u -r1.10 -r1.11
+--- src/gtk/newgui/gui_results.ml 20 Jul 2006 16:56:42 -0000 1.10
++++ src/gtk/newgui/gui_results.ml 3 Dec 2006 20:49:42 -0000 1.11
+@@ -289,7 +289,7 @@
+ let value = ref "" in
+ List.iter (fun t ->
+ match t.tag_name with
+- Field_UNKNOWN "codec" -> value := string_of_tag_value t.tag_value
++ Field_KNOWN "codec" -> value := string_of_tag_value t.tag_value
+ | _ -> ()
+ ) tags;
+ !value
+@@ -298,7 +298,7 @@
+ let value = ref 0 in
+ List.iter (fun t ->
+ match t.tag_name with
+- Field_UNKNOWN "bitrate" -> value := int_of_tag_value t.tag_value
++ Field_KNOWN "bitrate" -> value := int_of_tag_value t.tag_value
+ | _ -> ()
+ ) tags;
+ !value
+Index: src/gtk2/gui/guiMisc.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/gtk2/gui/guiMisc.ml,v
+retrieving revision 1.20
+retrieving revision 1.22
+diff -u -r1.20 -r1.22
+--- src/gtk2/gui/guiMisc.ml 28 Nov 2006 12:58:11 -0000 1.20
++++ src/gtk2/gui/guiMisc.ml 3 Dec 2006 20:49:42 -0000 1.22
+@@ -1055,7 +1055,7 @@
+ | Field_Mediacodec -> "codec"
+ | Field_Lastseencomplete -> "lastseencompl"
+ | Field_Filerating -> "rating"
+- | Field_UNKNOWN s -> U.simple_utf8_of s
++ | Field_KNOWN s -> U.simple_utf8_of s
+
+ let tags_to_string tags =
+ let s = ref "" in
+@@ -1276,8 +1276,8 @@
+ source_connect_time = BasicSocket.last_time () - c.client_connect_time;
+ source_last_seen = BasicSocket.current_time ();
+ source_software = concat_strings c.client_software (concat_strings c.client_emulemod c.client_release);
+- source_downloaded = c.client_downloaded;
+- source_uploaded = c.client_uploaded;
++ source_downloaded = c.client_total_downloaded;
++ source_uploaded = c.client_total_uploaded;
+ source_upload_rate = 0.;
+ source_download_rate = 0.;
+ source_upload = c.client_upload;
+Index: src/networks/bittorrent/bTClients.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/bittorrent/bTClients.ml,v
+retrieving revision 1.84
+retrieving revision 1.85
+diff -u -r1.84 -r1.85
+--- src/networks/bittorrent/bTClients.ml 5 Nov 2006 14:09:38 -0000 1.84
++++ src/networks/bittorrent/bTClients.ml 2 Dec 2006 12:35:46 -0000 1.85
+@@ -272,6 +272,8 @@
+ try
+ (* List.iter (fun r -> CommonSwarming.free_range r) c.client_ranges; *)
+ set_client_disconnected c reason;
++ c.client_session_downloaded <- 0L;
++ c.client_session_uploaded <- 0L;
+ (try if c.client_good then count_seen c with _ -> ());
+ (* this is not useful already done in the match
+ (try close sock reason with _ -> ()); *)
+Index: src/networks/bittorrent/bTGlobals.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/bittorrent/bTGlobals.ml,v
+retrieving revision 1.72
+retrieving revision 1.74
+diff -u -r1.72 -r1.74
+--- src/networks/bittorrent/bTGlobals.ml 26 Nov 2006 13:19:31 -0000 1.72
++++ src/networks/bittorrent/bTGlobals.ml 3 Dec 2006 20:57:56 -0000 1.74
+@@ -124,7 +124,7 @@
+ impl_shared_ops = shared_ops;
+ impl_shared_val = file;
+ impl_shared_requests = 0;
+- impl_shared_magic = None;
++ impl_shared_file = Some (as_file file);
+ impl_shared_servers = [];
+ } in
+ file.file_shared <- Some impl;
+@@ -786,8 +786,10 @@
+ client_release = release;
+ client_bitmap = None;
+ client_allowed_to_write = zero;
+- client_uploaded = zero;
+- client_downloaded = zero;
++ client_total_uploaded = zero;
++ client_total_downloaded = zero;
++ client_session_uploaded = zero;
++ client_session_downloaded = zero;
+ client_upload_rate = Rate.new_rate ();
+ client_downloaded_rate = Rate.new_rate ();
+ client_connect_time = last_time ();
+Index: src/networks/bittorrent/bTInteractive.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/bittorrent/bTInteractive.ml,v
+retrieving revision 1.123
+retrieving revision 1.125
+diff -u -r1.123 -r1.125
+--- src/networks/bittorrent/bTInteractive.ml 12 Nov 2006 14:17:45 -0000 1.123
++++ src/networks/bittorrent/bTInteractive.ml 3 Dec 2006 20:57:56 -0000 1.125
+@@ -406,8 +406,10 @@
+ ( "0", "srh", "IP address", "IP address" ) ;
+ ( "0", "srh br ar", "Port", "Port" ) ;
+ ] @ (if !Geoip.active then [( "0", "srh br ar", "Country Code/Name", "CC" )] else []) @ [
+- ( "1", "srh ar", "Total UL bytes to this client for all files", "UL" ) ;
+- ( "1", "srh ar br", "Total DL bytes from this client for all files", "DL" ) ;
++ ( "1", "srh ar", "Total UL bytes to this client for all files", "tUL" ) ;
++ ( "1", "srh ar br", "Total DL bytes from this client for all files", "tDL" ) ;
++ ( "1", "srh ar", "Session UL bytes to this client for all files", "sUL" ) ;
++ ( "1", "srh ar br", "Session DL bytes from this client for all files", "sDL" ) ;
+ ( "0", "srh ar", "Interested [T]rue, [F]alse", "I" ) ;
+ ( "0", "srh ar", "Choked [T]rue, [F]alse", "C" ) ;
+ ( "1", "srh br ar", "Allowed to write", "A" ) ;
+@@ -458,8 +460,10 @@
+ ("", "sr", (Ip.to_string (fst c.client_host)));
+ ("", "sr br ar", Printf.sprintf "%d" (snd c.client_host));
+ ] @ (if !Geoip.active then [( cn, "sr br", cc)] else []) @ [
+- ("", "sr ar", (size_of_int64 c.client_uploaded));
+- ("", "sr ar br", (size_of_int64 c.client_downloaded));
++ ("", "sr ar", (size_of_int64 c.client_total_uploaded));
++ ("", "sr ar br", (size_of_int64 c.client_total_downloaded));
++ ("", "sr ar", (size_of_int64 c.client_session_uploaded));
++ ("", "sr ar br", (size_of_int64 c.client_session_downloaded));
+ ("", "sr", (btos c.client_interested));
+ ("", "sr", (btos c.client_choked));
+ ("", "sr br ar", (Int64.to_string c.client_allowed_to_write));
+@@ -880,8 +884,10 @@
+ P.client_name = (Printf.sprintf "%s:%d" (Ip.to_string ip) port);
+ P.client_software = (brand_to_string c.client_brand);
+ P.client_release = c.client_release;
+- P.client_downloaded = c.client_downloaded;
+- P.client_uploaded = c.client_uploaded;
++ P.client_total_downloaded = c.client_total_downloaded;
++ P.client_total_uploaded = c.client_total_uploaded;
++ P.client_session_downloaded = c.client_session_downloaded;
++ P.client_session_uploaded = c.client_session_uploaded;
+ P.client_upload = Some (c.client_file.file_name);
+ P.client_connect_time = c.client_connect_time;
+
+@@ -906,11 +912,11 @@
+ let cc = as_client c in
+ client_print cc o;
+ Printf.bprintf buf (_b "\n%18sDown : %-10s Uploaded: %-10s Ratio: %s%1.1f (%s)\n") ""
+- (Int64.to_string c.client_downloaded)
+- (Int64.to_string c.client_uploaded)
+- (if c.client_downloaded > c.client_uploaded then "-" else "+")
+- (if c.client_uploaded > Int64.zero then
+- Int64.to_float (c.client_downloaded // c.client_uploaded)
++ (Int64.to_string c.client_total_downloaded)
++ (Int64.to_string c.client_total_uploaded)
++ (if c.client_total_downloaded > c.client_total_uploaded then "-" else "+")
++ (if c.client_total_uploaded > Int64.zero then
++ Int64.to_float (c.client_total_downloaded // c.client_total_uploaded)
+ else 1.)
+ ("BT");
+ (Printf.bprintf buf (_b "%18sFile : %s\n") "" info.GuiTypes.file_name)
+@@ -948,8 +954,10 @@
+ ("", "sr", "N");
+ ("", "sr", (Ip.to_string (fst c.client_host)));
+ ] @ (if !Geoip.active then [(cn, "sr", cc)] else []) @ [
+- ("", "sr ar", (size_of_int64 c.client_uploaded));
+- ("", "sr ar", (size_of_int64 c.client_downloaded));
++ ("", "sr ar", (size_of_int64 c.client_total_uploaded));
++ ("", "sr ar", (size_of_int64 c.client_total_downloaded));
++ ("", "sr ar", (size_of_int64 c.client_session_uploaded));
++ ("", "sr ar", (size_of_int64 c.client_session_downloaded));
+ ("", "sr", info.GuiTypes.file_name); ]);
+ true
+
+@@ -1263,6 +1271,9 @@
+
+ CommonNetwork.register_commands commands;
+
++ shared_ops.op_shared_state <- (fun file o ->
++ "no BT data"
++ );
+ shared_ops.op_shared_unshare <- (fun file ->
+ (if !verbose_share then lprintf_file_nl (as_file file) "unshare file");
+ BTGlobals.unshare_file file);
+Index: src/networks/bittorrent/bTStats.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/bittorrent/bTStats.ml,v
+retrieving revision 1.8
+retrieving revision 1.9
+diff -u -r1.8 -r1.9
+--- src/networks/bittorrent/bTStats.ml 23 Sep 2006 20:29:47 -0000 1.8
++++ src/networks/bittorrent/bTStats.ml 2 Dec 2006 12:35:46 -0000 1.9
+@@ -57,7 +57,8 @@
+ stats_array.(i).brand_download <- stats_array.(i).brand_download ++ v;
+ !!gstats_array.(i).brand_download <- !!gstats_array.(i).brand_download ++ v;
+
+- c.client_downloaded <- c.client_downloaded ++ v;
++ c.client_total_downloaded <- c.client_total_downloaded ++ v;
++ c.client_session_downloaded <- c.client_session_downloaded ++ v;
+ bt_download_counter := !bt_download_counter ++ v;
+ global_count_download network v
+
+@@ -66,7 +67,8 @@
+ stats_array.(i).brand_upload <- stats_array.(i).brand_upload ++ v;
+ !!gstats_array.(i).brand_upload <- !!gstats_array.(i).brand_upload ++ v;
+
+- c.client_uploaded <- c.client_uploaded ++ v;
++ c.client_total_uploaded <- c.client_total_uploaded ++ v;
++ c.client_session_uploaded <- c.client_session_uploaded ++ v;
+ bt_upload_counter := !bt_upload_counter ++ v;
+ global_count_upload network v
+
+Index: src/networks/bittorrent/bTTypes.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/bittorrent/bTTypes.ml,v
+retrieving revision 1.40
+retrieving revision 1.41
+diff -u -r1.40 -r1.41
+--- src/networks/bittorrent/bTTypes.ml 26 Nov 2006 13:19:31 -0000 1.40
++++ src/networks/bittorrent/bTTypes.ml 2 Dec 2006 12:35:46 -0000 1.41
+@@ -227,8 +227,10 @@
+ mutable client_allowed_to_write : int64;
+ mutable client_upload_rate : Rate.t;
+ mutable client_downloaded_rate : Rate.t;
+- mutable client_downloaded : int64;
+- mutable client_uploaded : int64;
++ mutable client_total_downloaded : int64;
++ mutable client_total_uploaded : int64;
++ mutable client_session_downloaded : int64;
++ mutable client_session_uploaded : int64;
+ mutable client_connect_time : int;
+
+ mutable client_blocks_sent : int list;
+Index: src/networks/direct_connect/dcInteractive.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/direct_connect/dcInteractive.ml,v
+retrieving revision 1.28
+retrieving revision 1.29
+diff -u -r1.28 -r1.29
+--- src/networks/direct_connect/dcInteractive.ml 1 Oct 2006 17:54:00 -0000 1.28
++++ src/networks/direct_connect/dcInteractive.ml 3 Dec 2006 20:49:42 -0000 1.29
+@@ -248,13 +248,13 @@
+ P.user_tags = (
+ let list = if user.user_data > 1. then
+ [
+- { tag_name = Field_UNKNOWN "link"; tag_value = String user.user_link };
+- { tag_name = Field_UNKNOWN "shared"; tag_value = String (
++ { tag_name = Field_KNOWN "link"; tag_value = String user.user_link };
++ { tag_name = Field_KNOWN "shared"; tag_value = String (
+ Printf.sprintf "%12.0f" user.user_data) }
+ ] else []
+ in
+ if user.user_admin then
+- { tag_name = Field_UNKNOWN "admin"; tag_value = String "admin" } :: list
++ { tag_name = Field_KNOWN "admin"; tag_value = String "admin" } :: list
+ else list
+ );
+
+Index: src/networks/donkey/donkeyClient.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyClient.ml,v
+retrieving revision 1.110
+retrieving revision 1.114
+diff -u -r1.110 -r1.114
+--- src/networks/donkey/donkeyClient.ml 26 Nov 2006 16:36:29 -0000 1.110
++++ src/networks/donkey/donkeyClient.ml 3 Dec 2006 20:49:42 -0000 1.114
+@@ -68,40 +68,43 @@
+ (*************************************************************************)
+ (* adding a source to the source-management *)
+ (*************************************************************************)
+-let add_source file ip port serverIP serverPort =
+- (* man, we are receiving sources from some clients even when we release *)
+- if (file_state file) = FileDownloading then
+- try
+- let uid =
+- if low_id ip then
+- (* indirect address *)
+- begin
+- try
+- (* without server, we can't request a callback *)
+- let s = Hashtbl.find servers_by_key serverIP in
+- if serverPort = s.server_port then
+- Indirect_address ( serverIP, serverPort, id_of_ip ip, 0, Ip.null )
+- else
+- raise Not_found
+- with _ ->
+- raise Not_found
+- end
++let add_source file ip tcp_port serverIP serverPort =
++ (* man, we are receiving sources from some clients even when we release *)
++ if (file_state file) = FileDownloading then
++ try
++ let uid =
++ if low_id ip then
++ begin
++ try
++ (* without server, we can't request a callback *)
++ let s = Hashtbl.find servers_by_key serverIP in
++ if serverPort = s.server_port then
++ Indirect_address (serverIP, serverPort, id_of_ip ip, 0, Ip.null)
+ else
+- (* direct adsdess *)
+- if Ip.usable ip then
+- if not ( is_black_address ip port ) then
+- if not ( Hashtbl.mem banned_ips ip) then
+- Direct_address ( ip, port )
+- else
+- raise Not_found
+- else
+- raise Not_found
+- else
+- raise Not_found
+- in
+- let s = DonkeySources.find_source_by_uid uid in
+- DonkeySources.set_request_result s file.file_sources File_new_source;
+- with Not_found -> ()
++ raise Not_found
++ with Not_found ->
++ if !!update_server_list_client then
++ begin
++ ignore (check_add_server serverIP serverPort);
++ Indirect_address (serverIP, serverPort, id_of_ip ip, 0, Ip.null)
++ end
++ else raise Not_found
++ end
++ else
++ if Ip.usable ip then
++ if not ( is_black_address ip tcp_port ) then
++ if not ( Hashtbl.mem banned_ips ip) then
++ Direct_address ( ip, tcp_port )
++ else
++ raise Not_found
++ else
++ raise Not_found
++ else
++ raise Not_found
++ in
++ let s = DonkeySources.find_source_by_uid uid in
++ DonkeySources.set_request_result s file.file_sources File_new_source;
++ with Not_found -> ()
+
+ let is_banned c sock =
+ c.client_banned <- Hashtbl.mem banned_ips (fst (peer_addr sock))
+@@ -245,18 +248,22 @@
+ c.client_source.DonkeySources.source_sock <- NoConnection
+ | Connection sock ->
+ (try
+- let log_print cc =
+- lprintf_nl "Client[%d] %s disconnected, connected %s%s%s"
+- (client_num cc)
+- (full_client_identifier cc)
+- (Date.time_to_string (last_time () - cc.client_connect_time) "verbose")
+- (if cc.client_uploaded > 0L then
+- Printf.sprintf ", send %s" (size_of_int64 cc.client_uploaded) else "")
+- (if cc.client_downloaded > 0L then
+- Printf.sprintf ", rec %s" (size_of_int64 cc.client_downloaded) else "")
++ let log_print cc = lprintf_nl "Client[%d] %s disconnected, connected %s%s%s"
++ (client_num c) (full_client_identifier c)
++ (Date.time_to_string (last_time () - c.client_connect_time) "verbose")
++ (if c.client_total_uploaded > 0L then
++ Printf.sprintf ", send %s (%s)%s"
++ (size_of_int64 c.client_session_uploaded)
++ (size_of_int64 c.client_total_uploaded)
++ (match client_upload (as_client c) with | None -> ""
++ | Some f -> " of " ^ (CommonFile.file_best_name f)) else "")
++ (if c.client_total_downloaded > 0L then
++ Printf.sprintf ", rec %s (%s)"
++ (size_of_int64 c.client_session_downloaded)
++ (size_of_int64 c.client_total_downloaded) else "")
+ in
+ if c.client_debug ||
+- (!verbose && (c.client_uploaded > 0L || c.client_downloaded > 0L)) then
++ (!verbose && (c.client_session_uploaded > 0L || c.client_session_downloaded > 0L)) then
+ log_print c;
+
+ c.client_comp <- None;
+@@ -599,7 +606,7 @@
+ List.iter (fun tag ->
+ let s = to_lowercase (string_of_tag_value tag.tag_value) in
+ match tag.tag_name with
+- Field_UNKNOWN "mod_version" ->
++ Field_KNOWN "mod_version" ->
+ begin
+ let rec iter i len =
+ if i < len then
+@@ -661,33 +668,40 @@
+ iter 0 (Array.length mod_array)
+
+ let update_client_from_tags c tags =
++ let module M = DonkeyProtoClient in
+ List.iter (fun tag ->
+ match tag.tag_name with
+- | Field_UNKNOWN "name" -> ()
+- | Field_UNKNOWN "version" -> ()
+- | Field_UNKNOWN "emule_udpports" ->
++ | Field_KNOWN "emule_udpports" ->
+ for_two_int16_tag tag (fun ed2k_port kad_port ->
+ (* Kademlia: we should use this client to bootstrap Kademlia *)
+ if kad_port <> 0 && !!enable_kademlia then
+ DonkeyProtoKademlia.Kademlia.bootstrap
+ c.client_ip kad_port
+ )
+- | Field_UNKNOWN "emule_miscoptions1" ->
++ | Field_KNOWN "emule_miscoptions1" ->
+ for_int64_tag tag (fun i ->
+- DonkeyProtoClient.update_emule_proto_from_miscoptions1
+- c.client_emule_proto i
++ M.update_emule_proto_from_miscoptions1
++ c.client_emule_proto i;
++ if !verbose_msg_clients || c.client_debug then
++ lprintf_nl "miscoptions1 from client %s\n%s"
++ (full_client_identifier c)
++ (M.print_emule_proto_miscoptions1 c.client_emule_proto)
+ )
+- | Field_UNKNOWN "emule_miscoptions2" ->
++ | Field_KNOWN "emule_miscoptions2" ->
+ for_int64_tag tag (fun i ->
+- DonkeyProtoClient.update_emule_proto_from_miscoptions2
+- c.client_emule_proto i
++ M.update_emule_proto_from_miscoptions2
++ c.client_emule_proto i;
++ if !verbose_msg_clients || c.client_debug then
++ lprintf_nl "miscoptions2 from client %s\n%s"
++ (full_client_identifier c)
++ (M.print_emule_proto_miscoptions2 c.client_emule_proto)
+ )
+- | Field_UNKNOWN "emule_compatoptions" ->
++ | Field_KNOWN "emule_compatoptions" ->
+ for_int_tag tag (fun i ->
+- DonkeyProtoClient.update_emule_proto_from_compatoptions
++ M.update_emule_proto_from_compatoptions
+ c.client_emule_proto i
+ )
+- | Field_UNKNOWN "emule_version" ->
++ | Field_KNOWN "emule_version" ->
+ for_int_tag tag (fun i ->
+ c.client_emule_proto.emule_version <- i;
+ let compatibleclient = (i lsr 24) in
+@@ -697,60 +711,62 @@
+ if c.client_brand = Brand_unknown then
+ lprintf_nl "[emule_version] Brand_unknown %s" (full_client_identifier c);
+ )
+- | Field_UNKNOWN "mod_version" ->
++ | Field_KNOWN "mod_version" ->
+ let s = to_lowercase (string_of_tag_value tag.tag_value) in
+ parse_mod_version s c
+- | _ ->
+- if !verbose_msg_clienttags then
+- lprintf_nl "Unknown Emule tag: [%s] (update_client_from_tags)" (escaped_string_of_field tag)
++ | Field_KNOWN _ -> if !verbose_unknown_messages then
++ lprintf_nl "update_client_from_tags, known tag: [%s] (%s)" (string_of_tag tag) (full_client_identifier c)
++ | _ -> if not (DonkeySources.source_brand c.client_source) then
++ lprintf_nl "update_client_from_tags, unknown tag: [%s] (%s) %s"
++ (hexstring_of_tag tag) (full_client_identifier c) (string_of_tags_list tags)
+ ) tags
+
+ let update_emule_proto_from_tags c tags =
+ List.iter (fun tag ->
+ match tag.tag_name with
+- Field_UNKNOWN "compatibleclient" ->
++ Field_KNOWN "compatibleclient" ->
+ for_int_tag tag (fun i ->
+ c.client_brand <- parse_compatible_client i c.client_brand;
+ if c.client_brand = Brand_unknown then
+ lprintf_nl "unknown compatibleclient %d (%s) (please report to dev team)" i (full_client_identifier c)
+ )
+- | Field_UNKNOWN "compression" ->
++ | Field_KNOWN "compression" ->
+ for_int_tag tag (fun i ->
+ c.client_emule_proto.emule_compression <- i
+ )
+- | Field_UNKNOWN "udpver" ->
++ | Field_KNOWN "udpver" ->
+ for_int_tag tag (fun i ->
+ c.client_emule_proto.emule_udpver <- i
+ )
+- | Field_UNKNOWN "udpport" -> ()
+- | Field_UNKNOWN "sourceexchange" ->
++ | Field_KNOWN "sourceexchange" ->
+ for_int_tag tag (fun i ->
+ c.client_emule_proto.emule_sourceexchange <- i
+ )
+- | Field_UNKNOWN "comments" ->
++ | Field_KNOWN "comments" ->
+ for_int_tag tag (fun i ->
+ c.client_emule_proto.emule_comments <- i
+ )
+- | Field_UNKNOWN "extendedrequest" ->
++ | Field_KNOWN "extendedrequest" ->
+ for_int_tag tag (fun i ->
+ c.client_emule_proto.emule_extendedrequest <- i
+ )
+- | Field_UNKNOWN "features" ->
++ | Field_KNOWN "features" ->
+ for_int_tag tag (fun i ->
+ c.client_emule_proto.emule_secident <- i land 0x3
+ )
+- | Field_UNKNOWN "mod_version" ->
+- let s = to_lowercase (string_of_tag_value tag.tag_value) in
+- parse_mod_version s c;
++ | Field_KNOWN "mod_version" ->
++ parse_mod_version (to_lowercase (string_of_tag_value tag.tag_value)) c;
+
+- | Field_UNKNOWN "os_info" ->
++ | Field_KNOWN "os_info" ->
+ let s = to_lowercase (string_of_tag_value tag.tag_value) in
+ (match c.client_osinfo with
+ Some _ -> ()
+ | _ -> if s <> "" then c.client_osinfo <- Some s)
+- | _ ->
+- if !verbose_msg_clienttags then
+- lprintf_nl "Unknown Emule tag: [%s] (update_emule_proto_from_tags)" (escaped_string_of_field tag)
++ | Field_KNOWN _ -> if !verbose_unknown_messages then
++ lprintf_nl "update_emule_proto_from_tags, known tag: [%s] (%s)" (string_of_tag tag) (full_client_identifier c)
++ | _ -> if not (DonkeySources.source_brand c.client_source) then
++ lprintf_nl "update_emule_proto_from_tags, unknown tag: [%s] (%s) %s"
++ (hexstring_of_tag tag) (full_client_identifier c) (string_of_tags_list tags)
+ ) tags
+
+ let fight_disguised_mods c =
+@@ -771,7 +787,7 @@
+ emule_info with
+ DonkeyProtoClient.EmuleClientInfo.protversion = 255;
+ DonkeyProtoClient.EmuleClientInfo.tags = [
+- string_tag (Field_UNKNOWN "os_info") (String2.upp_initial Autoconf.system);
++ string_tag (Field_KNOWN "os_info") (String2.upp_initial Autoconf.system);
+ ]} in
+ client_send c (DonkeyProtoClient.EmuleClientInfoReq emule_osinfo);
+ c.client_osinfo_sent <- true
+@@ -1160,7 +1176,7 @@
+
+ List.iter (fun tag ->
+ match tag with
+- { tag_name = Field_UNKNOWN "name"; tag_value = String s } ->
++ { tag_name = Field_KNOWN "name"; tag_value = String s } ->
+ set_client_name c s t.CR.md4
+ | _ -> ()
+ ) c.client_tags;
+@@ -2018,13 +2034,13 @@
+ begin
+
+ if !!dynamic_upload_lifetime
+- && c.client_uploaded > c.client_downloaded
+- && c.client_uploaded > Int64.of_int !!dynamic_upload_threshold ** zone_size
++ && c.client_session_uploaded > c.client_session_downloaded
++ && c.client_session_uploaded > Int64.of_int !!dynamic_upload_threshold ** zone_size
+ then
+ client_upload_lifetime :=
+ Int64.to_int
+ (Int64.of_int !client_upload_lifetime
+- ** c.client_downloaded // c.client_uploaded);
++ ** c.client_session_downloaded // c.client_session_uploaded);
+ if last_time() > c.client_connect_time +
+ !client_upload_lifetime + 5 * prio then
+ begin
+@@ -2193,7 +2209,7 @@
+ let name = ref "" in
+ List.iter (fun tag ->
+ match tag with
+- { tag_name = Field_UNKNOWN "name"; tag_value = String s } -> name := s
++ { tag_name = Field_KNOWN "name"; tag_value = String s } -> name := s
+ | _ -> ()
+ ) t.CR.tags;
+
+Index: src/networks/donkey/donkeyGlobals.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyGlobals.ml,v
+retrieving revision 1.110
+retrieving revision 1.112
+diff -u -r1.110 -r1.112
+--- src/networks/donkey/donkeyGlobals.ml 26 Nov 2006 16:36:29 -0000 1.110
++++ src/networks/donkey/donkeyGlobals.ml 4 Dec 2006 12:00:19 -0000 1.112
+@@ -595,8 +595,10 @@
+ client_osinfo = None;
+ client_checked = false;
+ client_connected = false;
+- client_downloaded = Int64.zero;
+- client_uploaded = Int64.zero;
++ client_session_downloaded = Int64.zero;
++ client_session_uploaded = Int64.zero;
++ client_total_downloaded = Int64.zero;
++ client_total_uploaded = Int64.zero;
+ client_banned = false;
+ client_score = 0;
+ client_next_queue = 0;
+@@ -650,8 +652,10 @@
+ client_osinfo = None;
+ client_checked = false;
+ client_connected = false;
+- client_downloaded = Int64.zero;
+- client_uploaded = Int64.zero;
++ client_total_downloaded = Int64.zero;
++ client_total_uploaded = Int64.zero;
++ client_session_downloaded = Int64.zero;
++ client_session_uploaded = Int64.zero;
+ client_banned = false;
+ client_score = 0;
+ client_next_queue = 0;
+@@ -1018,6 +1022,6 @@
+ let full_client_identifier c =
+ Printf.sprintf "%s (%s%s) '%s'"
+ (Ip.to_string c.client_ip)
+- (brand_to_string_short c.client_brand)
++ (GuiTypes.client_software_short (brand_to_string_short c.client_brand) c.client_osinfo)
+ (if c.client_emule_proto.emule_release = "" then "" else " " ^ c.client_emule_proto.emule_release)
+ (String.escaped c.client_name)
+Index: src/networks/donkey/donkeyImport.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyImport.ml,v
+retrieving revision 1.10
+retrieving revision 1.12
+diff -u -r1.10 -r1.12
+--- src/networks/donkey/donkeyImport.ml 14 Nov 2006 18:42:59 -0000 1.10
++++ src/networks/donkey/donkeyImport.ml 6 Dec 2006 00:49:14 -0000 1.12
+@@ -56,26 +56,32 @@
+ let names_of_tag =
+ (* eMule sourcefile opcodes.h //server.met *)
+ [
+- "\001", Field_UNKNOWN "name"; (* 0x01 string *)
+- "\011", Field_UNKNOWN "description"; (* 0x0B string *)
+- "\012", Field_UNKNOWN "ping"; (* 0x0C uint32 *)
+- "\013", Field_UNKNOWN "history"; (* 0x0D ST_FAIL *)
+- "\014", Field_UNKNOWN "prof"; (* 0x0E ST_PREFERENCE *)
+- "\015", Field_UNKNOWN "port"; (* 0x0F uint32 *)
+- "\016", Field_UNKNOWN "ip"; (* 0x10 uint32 *)
+- "\133", Field_UNKNOWN "dynip"; (* 0x85 string *)
+- "\135", Field_UNKNOWN "maxusers"; (* 0x87 uint32 *)
+- "\136", Field_UNKNOWN "softfiles"; (* 0x88 uint32 *)
+- "\137", Field_UNKNOWN "hardfiles"; (* 0x89 uint32 *)
+- "\144", Field_UNKNOWN "lastping"; (* 0x90 uint32 *)
+- "\145", Field_UNKNOWN "version"; (* 0x91 string|uint32 *)
+- "\146", Field_UNKNOWN "udpflags"; (* 0x92 uint32 *)
+- "\147", Field_UNKNOWN "auxportslist"; (* 0x93 string *)
+- "\148", Field_UNKNOWN "lowidusers"; (* 0x94 uint32 *)
+- "\149", Field_UNKNOWN "udpkey"; (* 0x95 uint32 *)
+- "\150", Field_UNKNOWN "udpkeyip"; (* 0x96 uint32 *)
+- "\151", Field_UNKNOWN "tcpportobfuscation"; (* 0x97 uint16 *)
+- "\152", Field_UNKNOWN "udpportobfuscation"; (* 0x98 uint16 *)
++ "\001", Field_KNOWN "name"; (* 0x01 string *)
++ "\011", Field_KNOWN "description"; (* 0x0B string *)
++ "\012", Field_KNOWN "ping"; (* 0x0C uint32 *)
++ "\013", Field_KNOWN "history"; (* 0x0D ST_FAIL *)
++ "\014", Field_KNOWN "prof"; (* 0x0E ST_PREFERENCE *)
++ "\015", Field_KNOWN "port"; (* 0x0F uint32 *)
++ "\016", Field_KNOWN "ip"; (* 0x10 uint32 *)
++ "\133", Field_KNOWN "dynip"; (* 0x85 string *)
++ "\135", Field_KNOWN "maxusers"; (* 0x87 uint32 *)
++ "maxusers", Field_KNOWN "maxusers";
++ "\136", Field_KNOWN "softfiles"; (* 0x88 uint32 *)
++ "\137", Field_KNOWN "hardfiles"; (* 0x89 uint32 *)
++ "\144", Field_KNOWN "lastping"; (* 0x90 uint32 *)
++ "\145", Field_KNOWN "version"; (* 0x91 string|uint32 *)
++ "\146", Field_KNOWN "udpflags"; (* 0x92 uint32 *)
++ "\147", Field_KNOWN "auxportslist"; (* 0x93 string *)
++ "\148", Field_KNOWN "lowusers"; (* 0x94 uint32 *)
++ "lowusers", Field_KNOWN "lowusers";
++ "\149", Field_KNOWN "udpkey"; (* 0x95 uint32 *)
++ "\150", Field_KNOWN "udpkeyip"; (* 0x96 uint32 *)
++ "\151", Field_KNOWN "tcpportobfuscation"; (* 0x97 uint16 *)
++ "\152", Field_KNOWN "udpportobfuscation"; (* 0x98 uint16 *)
++ "files", Field_KNOWN "files";
++ "users", Field_KNOWN "users";
++ "country", Field_KNOWN "country";
++ "refs", Field_KNOWN "refs";
+ ]
+
+
+@@ -204,12 +210,12 @@
+
+ let names_of_tag =
+ [
+- "\008", Field_UNKNOWN "downloaded";
+- "\018", Field_UNKNOWN "diskname";
+- "\019", Field_UNKNOWN "priority";
+- "\020", Field_UNKNOWN "status";
+- "\t", Field_UNKNOWN "start_pos";
+- "\n", Field_UNKNOWN "absent";
++ "\008", Field_KNOWN "downloaded";
++ "\018", Field_KNOWN "diskname";
++ "\019", Field_KNOWN "priority";
++ "\020", Field_KNOWN "status";
++ "\t", Field_KNOWN "start_pos";
++ "\n", Field_KNOWN "absent";
+ ] @ file_common_tags
+
+
+@@ -231,8 +237,8 @@
+ List.iter (fun tag ->
+ let s = tag.tag_name in
+ match s, tag.tag_value with
+- Field_UNKNOWN "start_pos", Uint64 p -> start_pos := p;
+- | Field_UNKNOWN "absent", Uint64 p ->
++ Field_KNOWN "start_pos", Uint64 p -> start_pos := p;
++ | Field_KNOWN "absent", Uint64 p ->
+ absents := (!start_pos, p) :: !absents;
+ | _ -> ()
+ ) tags;
+@@ -285,9 +291,9 @@
+
+ let names_of_client_tag =
+ [
+- "\001", Field_UNKNOWN "name";
+- "\017", Field_UNKNOWN "version";
+- "\015", Field_UNKNOWN "port";
++ "\001", Field_KNOWN "name";
++ "\017", Field_KNOWN "version";
++ "\015", Field_KNOWN "port";
+ ]
+
+ let names_of_option_tag = []
+Index: src/networks/donkey/donkeyInteractive.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyInteractive.ml,v
+retrieving revision 1.140
+retrieving revision 1.145
+diff -u -r1.140 -r1.145
+--- src/networks/donkey/donkeyInteractive.ml 26 Nov 2006 17:27:40 -0000 1.140
++++ src/networks/donkey/donkeyInteractive.ml 6 Dec 2006 22:33:05 -0000 1.145
+@@ -113,44 +113,44 @@
+ let server = check_add_server r.S.ip r.S.port in
+ List.iter (fun tag ->
+ match tag with
+- | { tag_name = Field_UNKNOWN "name"; tag_value = String s } ->
++ | { tag_name = Field_KNOWN "name"; tag_value = String s } ->
+ server.server_name <- s;
+- | { tag_name = Field_UNKNOWN "description" ; tag_value = String s } ->
++ | { tag_name = Field_KNOWN "description" ; tag_value = String s } ->
+ server.server_description <- s
+- | { tag_name = Field_UNKNOWN "version" ; tag_value = Uint64 s } ->
++ | { tag_name = Field_KNOWN "version" ; tag_value = Uint64 s } ->
+ server.server_version <- Printf.sprintf "%d.%d"
+ ((Int64.to_int s) lsr 16) ((Int64.to_int s) land 0xFFFF)
+- | { tag_name = Field_UNKNOWN "ping" ; tag_value = Uint64 s } ->
++ | { tag_name = Field_KNOWN "ping" ; tag_value = Uint64 s } ->
+ server.server_ping <- (Int64.to_int s)
+- | { tag_name = Field_UNKNOWN "dynip" ; tag_value = String s } ->
++ | { tag_name = Field_KNOWN "dynip" ; tag_value = String s } ->
+ server.server_dynip <- s
+- | { tag_name = Field_UNKNOWN "users" ; tag_value = Uint64 s } ->
++ | { tag_name = Field_KNOWN "users" ; tag_value = Uint64 s } ->
+ (match server.server_nusers with
+ | None -> server.server_nusers <- Some s | _ -> ())
+- | { tag_name = Field_UNKNOWN "files" ; tag_value = Uint64 s } ->
++ | { tag_name = Field_KNOWN "files" ; tag_value = Uint64 s } ->
+ (match server.server_nfiles with
+ | None -> server.server_nfiles <- Some s | _ -> ())
+- | { tag_name = Field_UNKNOWN "maxusers" ; tag_value = Uint64 s } ->
++ | { tag_name = Field_KNOWN "maxusers" ; tag_value = Uint64 s } ->
+ (match server.server_max_users with
+ | None -> server.server_max_users <- Some s | _ -> ())
+- | { tag_name = Field_UNKNOWN "softfiles" ; tag_value = Uint64 s } ->
++ | { tag_name = Field_KNOWN "softfiles" ; tag_value = Uint64 s } ->
+ (match server.server_soft_limit with
+ | None -> server.server_soft_limit <- Some s | _ -> ())
+- | { tag_name = Field_UNKNOWN "hardfiles" ; tag_value = Uint64 s } ->
++ | { tag_name = Field_KNOWN "hardfiles" ; tag_value = Uint64 s } ->
+ (match server.server_hard_limit with
+ | None -> server.server_hard_limit <- Some s | _ -> ())
+- | { tag_name = Field_UNKNOWN "auxportslist" ; tag_value = String s } ->
++ | { tag_name = Field_KNOWN "auxportslist" ; tag_value = String s } ->
+ server.server_auxportslist <- s
+- | { tag_name = Field_UNKNOWN "lowusers" ; tag_value = Uint64 s } ->
++ | { tag_name = Field_KNOWN "lowusers" ; tag_value = Uint64 s } ->
+ (match server.server_lowid_users with
+ | None -> server.server_lowid_users <- Some s | _ -> ())
+- | { tag_name = Field_UNKNOWN "tcpportobfuscation" ; tag_value = Uint64 s } ->
++ | { tag_name = Field_KNOWN "tcpportobfuscation" ; tag_value = Uint64 s } ->
+ server.server_obfuscation_tcp <- Some (Int64.to_int s)
+- | { tag_name = Field_UNKNOWN "udpportobfuscation" ; tag_value = Uint64 s } ->
++ | { tag_name = Field_KNOWN "udpportobfuscation" ; tag_value = Uint64 s } ->
+ server.server_obfuscation_udp <- Some (Int64.to_int s)
+- | { tag_name = Field_UNKNOWN "country" ; tag_value = String s } -> ()
+- | { tag_name = Field_UNKNOWN "udpflags" ; tag_value = Uint64 s } -> ()
+- | { tag_name = Field_UNKNOWN "refs" ; tag_value = Uint64 s } -> ()
++ | { tag_name = Field_KNOWN "country" ; tag_value = String s } -> ()
++ | { tag_name = Field_KNOWN "udpflags" ; tag_value = Uint64 s } -> ()
++ | { tag_name = Field_KNOWN "refs" ; tag_value = Uint64 s } -> ()
+ | _ -> lprintf_nl "parsing server.met, unknown field %s" (string_of_tag tag)
+ ) r.S.tags;
+ server_must_update server
+@@ -275,7 +275,8 @@
+ match file.file_swarmer with
+ None -> assert false
+ | Some swarmer ->
+- let absents = Sort.list (fun (p1,_) (p2,_) -> p1 <= p2) absents in
++ let absents =
++ List.sort (fun (p1, _) (p2, _) -> compare p1 p2) absents in
+ CommonSwarming.set_absent swarmer absents
+ end;
+
+@@ -447,16 +448,16 @@
+
+ List.iter (fun tag ->
+ match tag with
+- | { tag_name = Field_UNKNOWN "name"; tag_value = String s } ->
++ | { tag_name = Field_KNOWN "name"; tag_value = String s } ->
+ login =:= s
+- | { tag_name = Field_UNKNOWN "port"; tag_value = Uint64 v } ->
++ | { tag_name = Field_KNOWN "port"; tag_value = Uint64 v } ->
+ donkey_port =:= Int64.to_int v
+ | _ -> ()
+ ) ct;
+
+ List.iter (fun tag ->
+ match tag with
+- | { tag_name = Field_UNKNOWN "temp"; tag_value = String s } ->
++ | { tag_name = Field_KNOWN "temp"; tag_value = String s } ->
+ if Sys.file_exists s then (* be careful on that *)
+ temp_dir := s
+ else (lprintf_nl "Bad temp directory, using default";
+@@ -797,7 +798,7 @@
+ ) !current_files
+ ) args;
+ ""
+- ) , "<f1> < f2> ... :\t\ttry to recover these files at byte level";
++ ) , "<f1> <f2> ... :\t\ttry to recover these files at byte level";
+
+ "preferred", Arg_two (fun arg1 arg2 o ->
+ let preferred = bool_of_string arg1 in
+@@ -809,7 +810,7 @@
+ end
+ ) servers_by_key;
+ "ok"
+- ), "<true/false> <ip> :\t\tset the server with this IP as preferred";
++ ), "<true|false> <ip> :\t\tset the server with this IP as preferred";
+
+ "bs", Arg_multiple (fun args o ->
+ List.iter (fun arg ->
+@@ -817,7 +818,7 @@
+ server_black_list =:= range :: !!server_black_list;
+ ) args;
+ "done"
+- ), "<range1> <range2> ... :\t\t\tadd these IPs to the servers black list (can be single IPs, CIDR ranges or begin-end ranges)";
++ ), "<range1> <range2> ... :\t\tadd these IPs to the servers black list (can be single IPs, CIDR ranges or begin-end ranges)";
+
+ "port", Arg_one (fun arg o ->
+ donkey_port =:= int_of_string arg;
+@@ -1195,9 +1196,10 @@
+ P.client_os = c.client_osinfo;
+ P.client_release = c.client_emule_proto.emule_release;
+ P.client_emulemod = brand_mod_to_string_short c.client_brand_mod;
+- P.client_downloaded = c.client_downloaded;
+- P.client_uploaded = c.client_uploaded;
+-(* P.client_source.source_sock_addr = (); *)
++ P.client_total_downloaded = c.client_total_downloaded;
++ P.client_total_uploaded = c.client_total_uploaded;
++ P.client_session_downloaded = c.client_session_downloaded;
++ P.client_session_uploaded = c.client_session_uploaded;
+ P.client_upload =
+ (match client_upload (as_client c) with
+ Some f -> Some (CommonFile.file_best_name f)
+@@ -1396,8 +1398,10 @@
+ ( "0", "srh", "Secure User Identification [N]one, [P]assed, [F]ailed", "S" ) ;
+ ( "0", "srh br", "IP address", "IP address" ) ;
+ ] @ (if !Geoip.active then [( "0", "srh br", "Country Code/Name", "CC" )] else []) @ [
+- ( "1", "srh ar", "Total UL bytes to this client for all files", "UL" ) ;
+- ( "1", "srh ar br", "Total DL bytes from this client for all files", "DL" ) ;
++ ( "1", "srh ar", "Total UL bytes to this client for all files", "tUL" ) ;
++ ( "1", "srh ar br", "Total DL bytes from this client for all files", "tDL" ) ;
++ ( "1", "srh ar", "Session UL bytes to this client for all files", "sUL" ) ;
++ ( "1", "srh ar br", "Session DL bytes from this client for all files", "sDL" ) ;
+ ( "1", "srh ar", "Your queue rank on this client", "Rnk" ) ;
+ ( "1", "srh ar br", "Source score", "Scr" ) ;
+ ( "1", "srh ar br", "Last ok", "LO" ) ;
+@@ -1476,8 +1480,10 @@
+ ));
+ ("", "sr br", ip_string);
+ ] @ (if !Geoip.active then [(cn, "sr br", cc)] else []) @ [
+- ("", "sr ar", (size_of_int64 c.client_uploaded));
+- ("", "sr ar br", (size_of_int64 c.client_downloaded));
++ ("", "sr ar", (size_of_int64 c.client_total_uploaded));
++ ("", "sr ar br", (size_of_int64 c.client_total_downloaded));
++ ("", "sr ar", (size_of_int64 c.client_session_uploaded));
++ ("", "sr ar br", (size_of_int64 c.client_session_downloaded));
+ ("", "sr ar", Printf.sprintf "%d" c.client_rank);
+ ("", "sr ar br", Printf.sprintf "%d" c.client_source.DonkeySources.source_score);
+ ("", "sr ar br", (string_of_date (c.client_source.DonkeySources.source_age)));
+@@ -1698,10 +1704,10 @@
+ Direct_address (ip,port) -> (Ip.to_string ip)
+ | _ -> (string_of_client_addr c));
+ Printf.bprintf buf "\n%14sDown : %-10s Uploaded: %-10s Ratio: %s%1.1f (%s)\n" ""
+- (Int64.to_string c.client_downloaded)
+- (Int64.to_string c.client_uploaded)
+- (if c.client_downloaded > c.client_uploaded then "-" else "+")
+- (if c.client_uploaded > Int64.zero then (Int64.to_float (Int64.div c.client_downloaded c.client_uploaded)) else (1.))
++ (Int64.to_string c.client_total_downloaded)
++ (Int64.to_string c.client_total_uploaded)
++ (if c.client_total_downloaded > c.client_total_uploaded then "-" else "+")
++ (if c.client_total_uploaded > Int64.zero then (Int64.to_float (Int64.div c.client_total_downloaded c.client_total_uploaded)) else (1.))
+ (brand_to_string c.client_brand);
+ (Printf.bprintf buf "%14sFile : %s\n" "" info.GuiTypes.file_name);
+ end;
+@@ -1754,8 +1760,10 @@
+ ));
+ ("", "sr", ip_string);
+ ] @ (if !Geoip.active then [(cn, "sr", cc)] else []) @ [
+- ("", "sr ar", (size_of_int64 c.client_uploaded));
+- ("", "sr ar", (size_of_int64 c.client_downloaded));
++ ("", "sr ar", (size_of_int64 c.client_total_uploaded));
++ ("", "sr ar", (size_of_int64 c.client_total_downloaded));
++ ("", "sr ar", (size_of_int64 c.client_session_uploaded));
++ ("", "sr ar", (size_of_int64 c.client_session_downloaded));
+ ("", "sr", info.GuiTypes.file_name) ]);
+
+ Printf.bprintf buf "\\</tr\\>";
+@@ -1774,6 +1782,29 @@
+ )
+
+ let _ =
++ shared_ops.op_shared_state <- (fun f o ->
++ match CommonFile.file_state f with
++ | FileShared ->
++ (match file_shared f with
++ | None -> "no file_shared info"
++ | Some f ->
++ let pre_share1_dir =
++ String2.replace (Filename2.dirname (as_shared_impl f).impl_shared_fullname) '\\' "/" in
++ let pre_share2_dir =
++ try
++ String2.after pre_share1_dir
++ (String2.search_from
++ (Filename2.dirname (as_shared_impl f).impl_shared_fullname) 0 (Sys.getcwd ()) +
++ String.length (Sys.getcwd ()))
++ with Not_found -> pre_share1_dir
++ in
++ let dir =
++ if String2.check_prefix pre_share2_dir "/" then String2.after pre_share2_dir 1 else pre_share2_dir in
++ if o.conn_output = HTML then
++ Printf.sprintf "\\<a href=\\\"submit?q=debug_dir+%s\\\"\\>%s\\</a\\>" (Http_server.html_real_escaped dir) (Http_server.html_real_escaped dir)
++ else Printf.sprintf "Shared in %s" dir)
++ | state -> string_of_state state
++ );
+ shared_ops.op_shared_unshare <- (fun file ->
+ unshare_file file;
+ (* Should we or not ??? *)
+Index: src/networks/donkey/donkeyMain.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyMain.ml,v
+retrieving revision 1.63
+retrieving revision 1.64
+diff -u -r1.63 -r1.64
+--- src/networks/donkey/donkeyMain.ml 26 Nov 2006 16:36:29 -0000 1.63
++++ src/networks/donkey/donkeyMain.ml 3 Dec 2006 20:49:42 -0000 1.64
+@@ -137,14 +137,14 @@
+ let emule_compatoptions = D.emule_compatoptions m in
+ client_to_client_tags :=
+ [
+- string_tag (Field_UNKNOWN "name") (local_login ());
+- int_tag (Field_UNKNOWN "port") !!donkey_port;
+- int_tag (Field_UNKNOWN "version") protocol_version;
+- int_tag (Field_UNKNOWN "emule_udpports") (!!donkey_port+4);
+- int_tag (Field_UNKNOWN "emule_version") m.emule_version;
+- int64_tag (Field_UNKNOWN "emule_miscoptions1") emule_miscoptions1;
+- int64_tag (Field_UNKNOWN "emule_miscoptions2") emule_miscoptions2;
+- int_tag (Field_UNKNOWN "emule_compatoptions") emule_compatoptions;
++ string_tag (Field_KNOWN "name") (local_login ());
++ int_tag (Field_KNOWN "port") !!donkey_port;
++ int_tag (Field_KNOWN "version") protocol_version;
++ int_tag (Field_KNOWN "emule_udpports") (!!donkey_port+4);
++ int_tag (Field_KNOWN "emule_version") m.emule_version;
++ int64_tag (Field_KNOWN "emule_miscoptions1") emule_miscoptions1;
++ int64_tag (Field_KNOWN "emule_miscoptions2") emule_miscoptions2;
++ int_tag (Field_KNOWN "emule_compatoptions") emule_compatoptions;
+ ];
+
+ (* server capabilities *)
+@@ -161,42 +161,42 @@
+
+ client_to_server_tags :=
+ [
+- string_tag (Field_UNKNOWN "name") (local_login ());
+- int_tag (Field_UNKNOWN "version") protocol_version;
+- int_tag (Field_UNKNOWN "extended") !extended;
+- int_tag (Field_UNKNOWN "emule_version") m.emule_version;
++ string_tag (Field_KNOWN "name") (local_login ());
++ int_tag (Field_KNOWN "version") protocol_version;
++ int_tag (Field_KNOWN "extended") !extended;
++ int_tag (Field_KNOWN "emule_version") m.emule_version;
+ ];
+
+ client_to_server_reply_tags :=
+ [
+- string_tag (Field_UNKNOWN "name") (local_login ());
+- int_tag (Field_UNKNOWN "version") protocol_version;
+- int_tag (Field_UNKNOWN "emule_udpports") (!!donkey_port+4);
+- int64_tag (Field_UNKNOWN "emule_miscoptions1") emule_miscoptions1;
+- int64_tag (Field_UNKNOWN "emule_miscoptions2") emule_miscoptions2;
+- int_tag (Field_UNKNOWN "emule_version") m.emule_version;
++ string_tag (Field_KNOWN "name") (local_login ());
++ int_tag (Field_KNOWN "version") protocol_version;
++ int_tag (Field_KNOWN "emule_udpports") (!!donkey_port+4);
++ int64_tag (Field_KNOWN "emule_miscoptions1") emule_miscoptions1;
++ int64_tag (Field_KNOWN "emule_miscoptions2") emule_miscoptions2;
++ int_tag (Field_KNOWN "emule_version") m.emule_version;
+ ];
+
+ emule_info.DonkeyProtoClient.EmuleClientInfo.tags <- [
+- int_tag (Field_UNKNOWN "compression") m.emule_compression;
+- int_tag (Field_UNKNOWN "udpver") m.emule_udpver;
+- int_tag (Field_UNKNOWN "udpport") (!!donkey_port+4);
+- int_tag (Field_UNKNOWN "sourceexchange") m.emule_sourceexchange;
+- int_tag (Field_UNKNOWN "comments") m.emule_comments;
+- int_tag (Field_UNKNOWN "compatibleclient") !DonkeyProtoClient.compatibleclient;
+- int_tag (Field_UNKNOWN "extendedrequest") m.emule_extendedrequest;
+- int_tag (Field_UNKNOWN "features") m.emule_features;
++ int_tag (Field_KNOWN "compression") m.emule_compression;
++ int_tag (Field_KNOWN "udpver") m.emule_udpver;
++ int_tag (Field_KNOWN "udpport") (!!donkey_port+4);
++ int_tag (Field_KNOWN "sourceexchange") m.emule_sourceexchange;
++ int_tag (Field_KNOWN "comments") m.emule_comments;
++ int_tag (Field_KNOWN "compatibleclient") !DonkeyProtoClient.compatibleclient;
++ int_tag (Field_KNOWN "extendedrequest") m.emule_extendedrequest;
++ int_tag (Field_KNOWN "features") m.emule_features;
+
+ ];
+ overnet_connect_tags :=
+ [
+- string_tag (Field_UNKNOWN "name") (local_login ());
+- int_tag (Field_UNKNOWN "version") !!DonkeyProtoOvernet.overnet_protocol_connect_version;
++ string_tag (Field_KNOWN "name") (local_login ());
++ int_tag (Field_KNOWN "version") !!DonkeyProtoOvernet.overnet_protocol_connect_version;
+ ];
+ overnet_connectreply_tags :=
+ [
+- string_tag (Field_UNKNOWN "name") (local_login ());
+- int_tag (Field_UNKNOWN "version") !!DonkeyProtoOvernet.overnet_protocol_connectreply_version;
++ string_tag (Field_KNOWN "name") (local_login ());
++ int_tag (Field_KNOWN "version") !!DonkeyProtoOvernet.overnet_protocol_connectreply_version;
+ ]
+
+ let enable () =
+Index: src/networks/donkey/donkeyMftp.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyMftp.ml,v
+retrieving revision 1.13
+retrieving revision 1.15
+diff -u -r1.13 -r1.15
+--- src/networks/donkey/donkeyMftp.ml 9 Feb 2006 11:45:12 -0000 1.13
++++ src/networks/donkey/donkeyMftp.ml 4 Dec 2006 12:00:19 -0000 1.15
+@@ -179,7 +179,9 @@
+ List.assoc name names_of_tag
+ with Not_found ->
+ (* lprintf "Unknown tag \"%s\"\n" (String.escaped name); *)
+- field_of_string name);
++ match field_of_string name with
++ | Field_KNOWN s -> Field_UNKNOWN s
++ | field -> field);
+ tag_value = v
+ }, pos
+
+@@ -223,3 +225,75 @@
+ "Album", Field_Album;
+ "Title", Field_Title;
+ ]
++
++let client_common_tags =
++ [
++ "\001", "name";
++ "\015", "port";
++ "\017", "version";
++ "\031", "udpport";
++ "\032", "compression";
++ "\033", "udpport";
++ "\034", "udpver";
++ "\035", "sourceexchange";
++ "\036", "comments";
++ "\037", "extendedrequest";
++ "\038", "compatibleclient";
++ "\039", "features";
++ "\059", "extrainfo";
++ "\060", "downloadtime";
++ "\061", "incompleteparts";
++ "\062", "l2hac";
++ "\063", "realparts";
++ "\065", "mod_unknown41";
++ "\066", "mod_unknown42";
++ "\067", "mod_unknown43";
++ "\078", "neo_features";
++ "\084", "mod_featureset";
++ "\085", "mod_version";
++ "\086", "mod_protocol";
++ "\090", "mod_bowlfish";
++ "\092", "mod_secure_community";
++ "\093", "mod_unknown0x5d";
++ "\096", "mod_unknown0x60";
++ "\102", "mod_fusion";
++ "\103", "mod_fusion_version";
++
++(* http://forums.shareaza.com/showthread.php?threadid=37323&perpage=15&pagenumber=2 *)
++ "\105", "edonkeyclc serverip?";
++ "\106", "edonkeyclc serverport?";
++
++ "\117", "mod_unknown0x75"; (* http://emule-project.net @ NewMule *)
++ "\118", "mod_unknown0x76";
++ "\119", "mod_tarod";
++ "\120", "mod_tarod_version";
++ "\121", "mod_morph";
++ "\128", "mod_morph_version";
++ "\130", "mod_mortillo";
++ "\131", "mod_mortillo_version";
++ "\132", "chanblard_version";
++ "\133", "signature";
++ "\134", "cache";
++ "\135", "mod_lsd";
++ "\136", "mod_lsd_version";
++ "\144", "mod_lovelace_version";
++ "\148", "os_info"; (* reused by aMule to transfer client OS type *)
++ "\153", "mod_plus";
++ "\160", "mod_wombat";
++ "\161", "dev_wombat";
++ "\170", "koizo"; (* http://sourceforge.net/projects/koizo *)
++ "\205", "mod_unknown0xcd";
++ "\224", "isp_bypass";
++ "\225", "nat_tunneling";
++ "\239", "emule_compatoptions";
++ "\240", "nat_security";
++ "\249", "emule_udpports";
++ "\250", "emule_miscoptions1";
++ "\251", "emule_version";
++ "\252", "buddy_ip";
++ "\253", "buddy_udp";
++ "\254", "emule_miscoptions2";
++ "pr", "edonkeyclc horde";
++ "wombia", "wombat a";
++ "wombib", "wombat b";
++ ]
+Index: src/networks/donkey/donkeyMftp.mli
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyMftp.mli,v
+retrieving revision 1.6
+retrieving revision 1.7
+diff -u -r1.6 -r1.7
+--- src/networks/donkey/donkeyMftp.mli 19 Jan 2006 00:44:47 -0000 1.6
++++ src/networks/donkey/donkeyMftp.mli 3 Dec 2006 20:49:42 -0000 1.7
+@@ -51,4 +51,5 @@
+ val print : t -> unit
+ val write : Buffer.t -> t -> unit
+ end
+-val file_common_tags : (string * CommonTypes.field) list
+\ No newline at end of file
++val file_common_tags : (string * CommonTypes.field) list
++val client_common_tags : (string * string) list
+Index: src/networks/donkey/donkeyPandora.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyPandora.ml,v
+retrieving revision 1.7
+retrieving revision 1.8
+diff -u -r1.7 -r1.8
+--- src/networks/donkey/donkeyPandora.ml 3 Apr 2006 20:50:09 -0000 1.7
++++ src/networks/donkey/donkeyPandora.ml 3 Dec 2006 20:49:42 -0000 1.8
+@@ -98,23 +98,23 @@
+ let update_emule_proto_from_tags e tags =
+ List.iter (fun tag ->
+ match tag.tag_name with
+- | Field_UNKNOWN "compression" ->
++ | Field_KNOWN "compression" ->
+ for_int_tag tag (fun i ->
+ e.emule_compression <- i)
+- | Field_UNKNOWN "udpver" ->
++ | Field_KNOWN "udpver" ->
+ for_int_tag tag (fun i ->
+ e.emule_udpver <- i)
+- | Field_UNKNOWN "udpport" -> ()
+- | Field_UNKNOWN "sourceexchange" ->
++ | Field_KNOWN "udpport" -> ()
++ | Field_KNOWN "sourceexchange" ->
+ for_int_tag tag (fun i ->
+ e.emule_sourceexchange <- i)
+- | Field_UNKNOWN "comments" ->
++ | Field_KNOWN "comments" ->
+ for_int_tag tag (fun i ->
+ e.emule_comments <- i)
+- | Field_UNKNOWN "extendedrequest" ->
++ | Field_KNOWN "extendedrequest" ->
+ for_int_tag tag (fun i ->
+ e.emule_extendedrequest <- i)
+- | Field_UNKNOWN "features" ->
++ | Field_KNOWN "features" ->
+ for_int_tag tag (fun i ->
+ e.emule_secident <- i land 0x3)
+ | s ->
+@@ -138,7 +138,7 @@
+
+ begin
+ try
+- let options = find_tag (Field_UNKNOWN "emule_miscoptions1") tags in
++ let options = find_tag (Field_KNOWN "emule_miscoptions1") tags in
+ match options with
+ Uint64 v | Fint64 v ->
+ update_emule_proto_from_miscoptions1 emule v
+Index: src/networks/donkey/donkeyProtoClient.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyProtoClient.ml,v
+retrieving revision 1.40
+retrieving revision 1.42
+diff -u -r1.40 -r1.42
+--- src/networks/donkey/donkeyProtoClient.ml 26 Nov 2006 16:36:29 -0000 1.40
++++ src/networks/donkey/donkeyProtoClient.ml 3 Dec 2006 20:49:42 -0000 1.42
+@@ -39,41 +39,84 @@
+ (int_of_string(Autoconf.minor_version) lsl 10) lor
+ (int_of_string(Autoconf.sub_version) lsl 7)
+
+-(* TODO : update this
+-I downgraded some of those to get better results :
+-We don't use emule udp extension, client_md4 in sourceexchange or complete sources in
+-file request *)
+ let mldonkey_emule_proto =
+ {
+- emule_comments = 1;
+ emule_version = get_emule_version ();
+ emule_release = "";
+- emule_secident = 3; (* Emule uses v1 if advertising both, v2 if only advertising 2 *)
+- emule_noviewshared = 0;
+- emule_supportpreview = 0;
+ emule_osinfosupport = 1;
+- emule_compression = 1; (* 1 *)
++ emule_features = 3;
++
++(* emule_miscoptions1 *)
++ emule_aich = 0;
++ emule_unicode = 0;
++ emule_udpver = 0;
++ emule_compression = 1;
++ emule_secident = 3; (* Emule uses v1 if advertising both, v2 if only advertising 2 *)
+ emule_sourceexchange = 2; (* 2 : +client_md4 3 : +IdHybrid (emule Kademlia?)*)
+- emule_multipacket = 0; (* 1 *)
+ emule_extendedrequest = 1; (* 1: +file_status 2: +ncomplete_sources*)
+- emule_features = 3; (* 3 *)
+- emule_udpver = 0; (* 4 *)
++ emule_comments = 1;
++ emule_peercache = 0;
++ emule_noviewshared = 0;
++ emule_multipacket = 0;
++ emule_supportpreview = 0;
++
++(* emule_miscoptions2 *)
++ emule_require_crypt = 0;
++ emule_request_crypt = 0;
++ emule_support_crypt = 0;
++ emule_extmultipacket = 0;
++ emule_largefiles = 0;
++ emule_kad_version = 0;
+ }
+
+ let emule_miscoptions1 m =
+ let o =
++ (m.emule_aich lsl 29) lor
++ (m.emule_unicode lsl 28) lor
+ (m.emule_udpver lsl 24) lor
+ (m.emule_compression lsl 20) lor
+ (m.emule_secident lsl 16) lor
+ (m.emule_sourceexchange lsl 12) lor
+ (m.emule_extendedrequest lsl 8) lor
+ (m.emule_comments lsl 4) lor
++ (m.emule_peercache lsl 3) lor
+ (m.emule_noviewshared lsl 2) lor
+ (m.emule_multipacket lsl 1) lor
+ (m.emule_supportpreview lsl 0)
+ in
+ Int64.of_int o
+
++let update_emule_proto_from_miscoptions1 m o =
++ let o = Int64.to_int o in
++ m.emule_aich <- (o lsr 29) land 0x7;
++ m.emule_unicode <- (o lsr 28) land 0xf;
++ m.emule_udpver <- (o lsr 24) land 0xf;
++ m.emule_compression <- (o lsr 20) land 0xf;
++ m.emule_secident <- (o lsr 16) land 0xf;
++ m.emule_sourceexchange <- (o lsr 12) land 0xf;
++ m.emule_extendedrequest <- (o lsr 8) land 0xf;
++ m.emule_comments <- (o lsr 4) land 0xf;
++ m.emule_peercache <- (o lsr 3) land 0x1;
++ m.emule_noviewshared <- (o lsr 2) land 0x1;
++ m.emule_multipacket <- (o lsr 1) land 0x1;
++ m.emule_supportpreview <- (o lsr 0) land 0x1
++
++let print_emule_proto_miscoptions1 m =
++ let buf = Buffer.create 50 in
++ if m.emule_aich <> 0 then Printf.bprintf buf " aich %d\n" m.emule_aich;
++ if m.emule_unicode <> 0 then Printf.bprintf buf " unicode %d\n" m.emule_unicode;
++ if m.emule_udpver <> 0 then Printf.bprintf buf " udpver %d\n" m.emule_udpver;
++ if m.emule_compression <> 0 then Printf.bprintf buf " compression %d\n" m.emule_compression;
++ if m.emule_secident <> 0 then Printf.bprintf buf " secident %d\n" m.emule_secident;
++ if m.emule_sourceexchange <> 0 then Printf.bprintf buf " sourceexchange %d\n" m.emule_sourceexchange;
++ if m.emule_extendedrequest <> 0 then Printf.bprintf buf " extendedrequest %d\n" m.emule_extendedrequest;
++ if m.emule_comments <> 0 then Printf.bprintf buf " comments %d\n" m.emule_comments;
++ if m.emule_peercache <> 0 then Printf.bprintf buf " peercache %d\n" m.emule_peercache;
++ if m.emule_noviewshared <> 0 then Printf.bprintf buf " noviewshared %d\n" m.emule_noviewshared;
++ if m.emule_multipacket <> 0 then Printf.bprintf buf " multipacket %d\n" m.emule_multipacket;
++ if m.emule_supportpreview <> 0 then Printf.bprintf buf " supportpreview %d\n" m.emule_supportpreview;
++ Buffer.contents buf
++
+ let emule_miscoptions2 m =
+ (*
+ let o =
+@@ -83,23 +126,24 @@
+ *)
+ Int64.zero
+
+-let update_emule_proto_from_miscoptions1 m o =
+- let o = Int64.to_int o in
+- m.emule_udpver <- (o lsr 24) land 0xf;
+- m.emule_compression <- (o lsr 20) land 0xf;
+- m.emule_secident <- (o lsr 16) land 0xf;
+- m.emule_sourceexchange <- (o lsr 12) land 0xf;
+- m.emule_extendedrequest <- (o lsr 8) land 0xf;
+- m.emule_comments <- (o lsr 4) land 0xf;
+- m.emule_noviewshared <- (o lsr 2) land 0x1;
+- m.emule_multipacket <- (o lsr 1) land 0x1;
+- m.emule_supportpreview <- (o lsr 0) land 0x1
+-
+-let update_emule_proto_from_miscoptions2 m o = ()
+-(*
++let update_emule_proto_from_miscoptions2 m o =
+ let o = Int64.to_int o in
+- m.emule_largefiles <- (o lsr 4) land 0x1
+-*)
++ m.emule_require_crypt <- (o lsr 9) land 0x1;
++ m.emule_request_crypt <- (o lsr 8) land 0x1;
++ m.emule_support_crypt <- (o lsr 7) land 0x1;
++ m.emule_extmultipacket <- (o lsr 5) land 0x1;
++ m.emule_largefiles <- (o lsr 4) land 0x1;
++ m.emule_kad_version <- (o lsr 0) land 0xf
++
++let print_emule_proto_miscoptions2 m =
++ let buf = Buffer.create 50 in
++ if m.emule_require_crypt <> 0 then Printf.bprintf buf " require_crypt %d\n" m.emule_require_crypt;
++ if m.emule_request_crypt <> 0 then Printf.bprintf buf " request_crypt %d\n" m.emule_request_crypt;
++ if m.emule_support_crypt <> 0 then Printf.bprintf buf " support_crypt %d\n" m.emule_support_crypt;
++ if m.emule_extmultipacket <> 0 then Printf.bprintf buf " extmultipacket %d\n" m.emule_extmultipacket;
++ if m.emule_largefiles <> 0 then Printf.bprintf buf " largefiles %d\n" m.emule_largefiles;
++ if m.emule_kad_version <> 0 then Printf.bprintf buf " kad_version %d\n" m.emule_kad_version;
++ Buffer.contents buf
+
+ let emule_compatoptions m =
+ (m.emule_osinfosupport lsl 0)
+@@ -146,23 +190,10 @@
+ left_bytes : string;
+ }
+
++ let names_of_tag = client_common_tags
++
+ let names_of_tag =
+- [
+- "\001", Field_UNKNOWN "name";
+- "\015", Field_UNKNOWN "port";
+- "\017", Field_UNKNOWN "version";
+- "\031", Field_UNKNOWN "udpport";
+- "\060", Field_UNKNOWN "downloadtime";
+- "\061", Field_UNKNOWN "incompleteparts";
+- "\085", Field_UNKNOWN "mod_version";
+- "\239", Field_UNKNOWN "emule_compatoptions";
+- "\249", Field_UNKNOWN "emule_udpports";
+- "\250", Field_UNKNOWN "emule_miscoptions1";
+- "\251", Field_UNKNOWN "emule_version";
+- "\252", Field_UNKNOWN "buddy_ip";
+- "\253", Field_UNKNOWN "buddy_udp";
+- "\254", Field_UNKNOWN "emule_miscoptions2";
+- ]
++ List.map (fun (v, name) -> (v, Field_KNOWN name)) names_of_tag
+
+ let parse reply len s =
+ let hash_len, pos = if not reply then get_uint8 s 1, 2 else -1, 1 in
+@@ -787,49 +818,10 @@
+ mutable tags : tag list;
+ }
+
+- let names_of_tag =
+- [
+- "\032", "compression";
+- "\033", "udpport";
+- "\034", "udpver";
+- "\035", "sourceexchange";
+- "\036", "comments";
+- "\037", "extendedrequest";
+- "\038", "compatibleclient";
+- "\039", "features";
+- "\060", "downloadtime";
+- "\061", "incompleteparts";
+- "\062", "l2hac";
+- "\065", "mod_unknown41";
+- "\066", "mod_unknown42";
+- "\067", "mod_unknown43";
+- "\084", "mod_featureset";
+- "\086", "mod_protocol";
+- "\085", "mod_version";
+- "\090", "mod_bowlfish";
+- "\092", "mod_secure_community";
+- "\102", "mod_fusion";
+- "\103", "mod_fusion_version";
+- "\119", "mod_tarod";
+- "\120", "mod_tarod_version";
+- "\121", "mod_morph";
+- "\128", "mod_morph_version";
+- "\130", "mod_mortillo";
+- "\131", "mod_mortillo_version";
+- "\132", "chanblard_version";
+- "\133", "signature";
+- "\134", "cache";
+- "\135", "mod_lsd";
+- "\136", "mod_lsd_version";
+- "\144", "mod_lovelace_version";
+- "\148", "os_info"; (* reused by aMule to transfer client OS type *)
+- "\153", "mod_plus";
+- "\160", "mod_wombat";
+- "\161", "dev_wombat";
+- ]
++ let names_of_tag = client_common_tags
+
+ let names_of_tag =
+- List.map (fun (v, name) -> (v, Field_UNKNOWN name)) names_of_tag
++ List.map (fun (v, name) -> (v, Field_KNOWN name)) names_of_tag
+
+ let parse len s =
+ let version = get_uint8 s 1 in
+Index: src/networks/donkey/donkeyProtoCom.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyProtoCom.ml,v
+retrieving revision 1.33
+retrieving revision 1.34
+diff -u -r1.33 -r1.34
+--- src/networks/donkey/donkeyProtoCom.ml 8 Oct 2006 14:20:22 -0000 1.33
++++ src/networks/donkey/donkeyProtoCom.ml 2 Dec 2006 12:35:46 -0000 1.34
+@@ -339,8 +339,8 @@
+ str_int s 0 nfiles;
+ let s = String.sub s 0 prev_len in
+ if !verbose_share || !verbose then
+- lprintf_nl "Sending %d share(s) to server %s:%d%s"
+- nfiles (Ip.to_string (peer_ip sock)) (peer_port sock)
++ lprintf_nl "Sending %d share%s to server %s:%d%s"
++ nfiles (Printf2.print_plural_s nfiles) (Ip.to_string (peer_ip sock)) (peer_port sock)
+ (if compressed then " (zlib)" else "");
+ Buffer.reset buf;
+ let s_c =
+Index: src/networks/donkey/donkeyProtoKademlia.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyProtoKademlia.ml,v
+retrieving revision 1.21
+retrieving revision 1.22
+diff -u -r1.21 -r1.22
+--- src/networks/donkey/donkeyProtoKademlia.ml 31 Oct 2006 15:42:48 -0000 1.21
++++ src/networks/donkey/donkeyProtoKademlia.ml 3 Dec 2006 20:49:42 -0000 1.22
+@@ -45,15 +45,15 @@
+
+ let names_of_tag =
+ [
+- "\243", Field_UNKNOWN "encryption"; (* 0xF3 *)
+- "\248", Field_UNKNOWN "buddyhash"; (* 0xF8 *)
+- "\249", Field_UNKNOWN "clientlowid"; (* 0xF9 *)
+- "\250", Field_UNKNOWN "serverport"; (* 0xFA *)
+- "\251", Field_UNKNOWN "serverip"; (* 0xFB *)
+- "\252", Field_UNKNOWN "sourceuport"; (* 0xFC *)
+- "\253", Field_UNKNOWN "sourceport"; (* 0xFD *)
+- "\254", Field_UNKNOWN "sourceip"; (* 0xFE *)
+- "\255", Field_UNKNOWN "sourcetype"; (* 0xFF *)
++ "\243", Field_KNOWN "encryption"; (* 0xF3 *)
++ "\248", Field_KNOWN "buddyhash"; (* 0xF8 *)
++ "\249", Field_KNOWN "clientlowid"; (* 0xF9 *)
++ "\250", Field_KNOWN "serverport"; (* 0xFA *)
++ "\251", Field_KNOWN "serverip"; (* 0xFB *)
++ "\252", Field_KNOWN "sourceuport"; (* 0xFC *)
++ "\253", Field_KNOWN "sourceport"; (* 0xFD *)
++ "\254", Field_KNOWN "sourceip"; (* 0xFE *)
++ "\255", Field_KNOWN "sourcetype"; (* 0xFF *)
+ ] @ file_common_tags
+
+ (* This fucking Emule implementation uses 4 32-bits integers instead of
+@@ -248,17 +248,17 @@
+ let peer_kind = ref 0 in
+ List.iter (fun tag ->
+ match tag.tag_name with
+- Field_UNKNOWN "sourceport" ->
++ Field_KNOWN "sourceport" ->
+ for_int_tag tag (fun port ->
+ peer_tcpport := port)
+- | Field_UNKNOWN "sourceuport" ->
++ | Field_KNOWN "sourceuport" ->
+ for_int_tag tag (fun port ->
+ peer_udpport := port)
+- | Field_UNKNOWN "sourceip" ->
++ | Field_KNOWN "sourceip" ->
+ for_int64_tag tag (fun ip ->
+ peer_ip := Ip.of_int64 ip
+ )
+- | Field_UNKNOWN "sourcetype" ->
++ | Field_KNOWN "sourcetype" ->
+ for_int_tag tag (fun kind ->
+ peer_kind := 3)
+ | _ ->
+@@ -333,7 +333,7 @@
+ (_, first_tags) :: _ ->
+ let sources = ref false in
+ List.iter (fun tag ->
+- if tag.tag_name = Field_UNKNOWN "sourceport" then sources := true;
++ if tag.tag_name = Field_KNOWN "sourceport" then sources := true;
+ ) first_tags;
+ if !sources then
+ let peers = get_peers_from_results Ip.null 0 answers in
+@@ -359,7 +359,7 @@
+ (_, first_tags) :: _ ->
+ let sources = ref false in
+ List.iter (fun tag ->
+- if tag.tag_name = Field_UNKNOWN "sourceport" then sources := true;
++ if tag.tag_name = Field_KNOWN "sourceport" then sources := true;
+ ) first_tags;
+ if !sources then
+ let peers = get_peers_from_results ip port answers in
+Index: src/networks/donkey/donkeyProtoOvernet.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyProtoOvernet.ml,v
+retrieving revision 1.31
+retrieving revision 1.32
+diff -u -r1.31 -r1.32
+--- src/networks/donkey/donkeyProtoOvernet.ml 5 Nov 2006 14:13:51 -0000 1.31
++++ src/networks/donkey/donkeyProtoOvernet.ml 3 Dec 2006 20:49:42 -0000 1.32
+@@ -40,7 +40,9 @@
+ let lprintf_n fmt =
+ lprintf2 log_prefix fmt
+
+- let names_of_tag = file_common_tags
++ let names_of_tag = [
++ "loc", Field_KNOWN "loc";
++ ] @ file_common_tags
+
+ let buf_peer buf p =
+ buf_md4 buf p.peer_md4;
+@@ -187,7 +189,7 @@
+ let peer_tcpport = ref 0 in
+ List.iter (fun tag ->
+ match tag.tag_name with
+- Field_UNKNOWN "loc" ->
++ Field_KNOWN "loc" ->
+ for_string_tag tag (fun bcp ->
+ if !verbose_overnet then lprintf_nl "loc tag : [%s]" bcp;
+ if String2.starts_with bcp "bcp://" then
+@@ -295,7 +297,7 @@
+ let r_tags, pos = get_tags s 32 names_of_tag in
+ let sources = ref false in
+ List.iter (fun tag ->
+- if tag.tag_name = Field_UNKNOWN "loc" then sources := true;
++ if tag.tag_name = Field_KNOWN "loc" then sources := true;
+ ) r_tags;
+ if !sources then
+ let peer = get_peer_from_result ip port r_md4 r_tags in
+@@ -311,7 +313,7 @@
+ let r_tags, pos = get_tags s 32 names_of_tag in
+ let sources = ref false in
+ List.iter (fun tag ->
+- if tag.tag_name = Field_UNKNOWN "loc" then sources := true;
++ if tag.tag_name = Field_KNOWN "loc" then sources := true;
+ ) r_tags;
+ if !sources then
+ let peer = get_peer_from_result ip port r_md4 r_tags in
+Index: src/networks/donkey/donkeyProtoServer.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyProtoServer.ml,v
+retrieving revision 1.23
+retrieving revision 1.25
+diff -u -r1.23 -r1.25
+--- src/networks/donkey/donkeyProtoServer.ml 26 Nov 2006 16:36:29 -0000 1.23
++++ src/networks/donkey/donkeyProtoServer.ml 3 Dec 2006 20:49:42 -0000 1.25
+@@ -28,31 +28,6 @@
+ open DonkeyTypes
+ open DonkeyMftp
+
+-(*
+-let field_of_tagname s =
+- match s with
+- | "size" -> Field_Size
+- | "filename" -> Field_Filename
+- | "Artist" -> Field_Artist
+- | "Album" -> Field_Album
+- | "Title" -> Field_Title
+- | "format" -> Field_Format
+- | "type" -> Field_Type
+- | s -> Field_UNKNOWN s
+-
+-let tagname_of_field field =
+- match field with
+- Field_Size -> "size"
+- | Field_Filename -> "filename"
+- | Field_Artist -> "Artist"
+- | Field_Album -> "Album"
+- | Field_Title -> "Title"
+- | Field_Format -> "format"
+- | Field_Type -> "type"
+- | Field_Uid -> "uid"
+- | Field_unknown s -> s
+-*)
+-
+ module Connect = struct
+ type t = {
+ md4 : Md4.t;
+@@ -63,10 +38,10 @@
+
+ let names_of_tag =
+ [
+- "\001", Field_UNKNOWN "name"; (* CT_NAME 0x01 *)
+- "\017", Field_UNKNOWN "version"; (* CT_VERSION 0x11 *)
+- "\032", Field_UNKNOWN "extended"; (* CT_SERVER_FLAGS 0x20 *)
+- "\251", Field_UNKNOWN "emule_version"; (* CT_EMULE_VERSION 0xfb *)
++ "\001", Field_KNOWN "name"; (* CT_NAME 0x01 *)
++ "\017", Field_KNOWN "version"; (* CT_VERSION 0x11 *)
++ "\032", Field_KNOWN "extended"; (* CT_SERVER_FLAGS 0x20 *)
++ "\251", Field_KNOWN "emule_version"; (* CT_EMULE_VERSION 0xfb *)
+ ]
+
+ let parse len s =
+@@ -388,8 +363,8 @@
+
+ let names_of_tag =
+ [
+- "\001", Field_UNKNOWN "name";
+- "\011", Field_UNKNOWN "description";
++ "\001", Field_KNOWN "name";
++ "\011", Field_KNOWN "description";
+ ]
+
+ let parse len s =
+@@ -760,9 +735,9 @@
+
+ let names_of_tag =
+ [
+- "\001", Field_UNKNOWN "name";
+- "\017", Field_UNKNOWN "version";
+- "\015", Field_UNKNOWN "port";
++ "\001", Field_KNOWN "name";
++ "\017", Field_KNOWN "version";
++ "\015", Field_KNOWN "port";
+ ]
+
+ let rec parse_clients s pos nclients left =
+Index: src/networks/donkey/donkeyProtoUdp.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyProtoUdp.ml,v
+retrieving revision 1.16
+retrieving revision 1.17
+diff -u -r1.16 -r1.17
+--- src/networks/donkey/donkeyProtoUdp.ml 26 Nov 2006 16:36:29 -0000 1.16
++++ src/networks/donkey/donkeyProtoUdp.ml 3 Dec 2006 20:49:42 -0000 1.17
+@@ -233,22 +233,22 @@
+ }
+
+ let names_of_tag = [
+- "\001", Field_UNKNOWN "servername";
+- "\011", Field_UNKNOWN "description";
+- "\012", Field_UNKNOWN "ping";
+- "\013", Field_UNKNOWN "fail";
+- "\014", Field_UNKNOWN "preference";
+- "\015", Field_UNKNOWN "port";
+- "\016", Field_UNKNOWN "ip";
+- "\133", Field_UNKNOWN "dynip";
+- "\135", Field_UNKNOWN "maxusers";
+- "\136", Field_UNKNOWN "softfiles";
+- "\137", Field_UNKNOWN "hardfiles";
+- "\144", Field_UNKNOWN "lastping";
+- "\145", Field_UNKNOWN "version";
+- "\146", Field_UNKNOWN "udpflags";
+- "\147", Field_UNKNOWN "auxportslist";
+- "\148", Field_UNKNOWN "lowidusers";
++ "\001", Field_KNOWN "servername";
++ "\011", Field_KNOWN "description";
++ "\012", Field_KNOWN "ping";
++ "\013", Field_KNOWN "fail";
++ "\014", Field_KNOWN "preference";
++ "\015", Field_KNOWN "port";
++ "\016", Field_KNOWN "ip";
++ "\133", Field_KNOWN "dynip";
++ "\135", Field_KNOWN "maxusers";
++ "\136", Field_KNOWN "softfiles";
++ "\137", Field_KNOWN "hardfiles";
++ "\144", Field_KNOWN "lastping";
++ "\145", Field_KNOWN "version";
++ "\146", Field_KNOWN "udpflags";
++ "\147", Field_KNOWN "auxportslist";
++ "\148", Field_KNOWN "lowidusers";
+ ]
+
+ let parse1 len s challenge =
+@@ -267,9 +267,9 @@
+ let desc = ref "" in
+ List.iter (fun tag ->
+ match tag with
+- | { tag_name = Field_UNKNOWN "servername"; tag_value = String v } ->
++ | { tag_name = Field_KNOWN "servername"; tag_value = String v } ->
+ name := v
+- | { tag_name = Field_UNKNOWN "description"; tag_value = String v } ->
++ | { tag_name = Field_KNOWN "description"; tag_value = String v } ->
+ desc := v
+ | _ -> ()
+ ) stags;
+Index: src/networks/donkey/donkeyServers.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyServers.ml,v
+retrieving revision 1.68
+retrieving revision 1.69
+diff -u -r1.68 -r1.69
+--- src/networks/donkey/donkeyServers.ml 26 Nov 2006 16:36:29 -0000 1.68
++++ src/networks/donkey/donkeyServers.ml 3 Dec 2006 20:49:42 -0000 1.69
+@@ -399,9 +399,9 @@
+ List.iter (
+ fun tag ->
+ match tag with
+- { tag_name = Field_UNKNOWN "name"; tag_value = String name } ->
++ { tag_name = Field_KNOWN "name"; tag_value = String name } ->
+ s.server_name <- name
+- | { tag_name = Field_UNKNOWN "description"; tag_value = String desc } ->
++ | { tag_name = Field_KNOWN "description"; tag_value = String desc } ->
+ s.server_description <- desc
+ | _ -> lprintf_nl "parsing donkeyServers.ServerInfo, unknown field %s" (string_of_tag tag)
+ ) s.server_tags
+@@ -504,7 +504,7 @@
+ user_add user_impl;
+ List.iter (fun tag ->
+ match tag with
+- { tag_name = Field_UNKNOWN "name"; tag_value = String s } ->
++ { tag_name = Field_KNOWN "name"; tag_value = String s } ->
+ user.user_name <- s
+ | _ -> ()
+ ) user.user_tags;
+Index: src/networks/donkey/donkeyShare.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyShare.ml,v
+retrieving revision 1.55
+retrieving revision 1.56
+diff -u -r1.55 -r1.56
+--- src/networks/donkey/donkeyShare.ml 9 Oct 2006 16:17:19 -0000 1.55
++++ src/networks/donkey/donkeyShare.ml 3 Dec 2006 20:57:56 -0000 1.56
+@@ -44,12 +44,7 @@
+ | Some _ -> ()
+ | None ->
+ let full_name = file_disk_name file in
+- let magic =
+- match Magic.M.magic_fileinfo full_name false with
+- None -> None
+- | Some magic -> Some (intern magic)
+- in
+-
++ check_magic (as_file file);
+ let impl = {
+ impl_shared_update = 1;
+ impl_shared_fullname = full_name;
+@@ -61,7 +56,7 @@
+ impl_shared_ops = shared_ops;
+ impl_shared_val = file;
+ impl_shared_requests = 0;
+- impl_shared_magic = magic;
++ impl_shared_file = Some (as_file file);
+ impl_shared_servers = []
+ } in
+ file.file_shared <- Some impl;
+@@ -333,12 +328,6 @@
+ let found = ref false in
+ List.iter (fun sh -> if sh.shared_name = fullname then found := true) !shared_files;
+ if not !found then begin
+- let magic =
+- match Magic.M.magic_fileinfo fullname false with
+- None -> None
+- | Some magic -> Some (intern magic)
+- in
+-
+ let rec impl = {
+ impl_shared_update = 1;
+ impl_shared_fullname = fullname;
+@@ -350,7 +339,7 @@
+ impl_shared_id = Md4.null;
+ impl_shared_val = pre_shared;
+ impl_shared_requests = 0;
+- impl_shared_magic = magic;
++ impl_shared_file = None;
+ impl_shared_servers = [];
+ } and
+ pre_shared = {
+Index: src/networks/donkey/donkeyStats.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyStats.ml,v
+retrieving revision 1.25
+retrieving revision 1.26
+diff -u -r1.25 -r1.26
+--- src/networks/donkey/donkeyStats.ml 23 Sep 2006 20:29:47 -0000 1.25
++++ src/networks/donkey/donkeyStats.ml 2 Dec 2006 12:35:46 -0000 1.26
+@@ -85,7 +85,8 @@
+ !!gstats_mod_array.(i).brand_download <- !!gstats_mod_array.(i).brand_download ++ v;
+ end;
+
+- c.client_downloaded <- c.client_downloaded ++ v;
++ c.client_total_downloaded <- c.client_total_downloaded ++ v;
++ c.client_session_downloaded <- c.client_session_downloaded ++ v;
+ donkey_download_counter := !donkey_download_counter ++ v;
+ global_count_download network v
+
+@@ -100,7 +101,8 @@
+ !!gstats_mod_array.(i).brand_upload <- !!gstats_mod_array.(i).brand_upload ++ v;
+ end;
+
+- c.client_uploaded <- c.client_uploaded ++ v;
++ c.client_total_uploaded <- c.client_total_uploaded ++ v;
++ c.client_session_uploaded <- c.client_session_uploaded ++ v;
+ donkey_upload_counter := !donkey_upload_counter ++ v;
+ global_count_upload network v
+
+Index: src/networks/donkey/donkeyTypes.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyTypes.ml,v
+retrieving revision 1.52
+retrieving revision 1.54
+diff -u -r1.52 -r1.54
+--- src/networks/donkey/donkeyTypes.ml 26 Nov 2006 16:36:29 -0000 1.52
++++ src/networks/donkey/donkeyTypes.ml 2 Dec 2006 12:35:46 -0000 1.54
+@@ -33,20 +33,32 @@
+ lprintf2 log_prefix fmt
+
+ type emule_proto = {
+- mutable emule_comments : int;
+ mutable emule_version : int;
+ mutable emule_release : string;
+- mutable emule_secident : int;
+- mutable emule_noviewshared : int;
+- mutable emule_supportpreview : int;
+ mutable emule_osinfosupport : int;
++ mutable emule_features : int;
+
++(* emule_miscoptions1 *)
++ mutable emule_aich : int;
++ mutable emule_unicode : int;
++ mutable emule_udpver : int;
+ mutable emule_compression : int;
++ mutable emule_secident : int;
+ mutable emule_sourceexchange : int;
+- mutable emule_multipacket : int;
+ mutable emule_extendedrequest : int;
+- mutable emule_features : int;
+- mutable emule_udpver : int;
++ mutable emule_comments : int;
++ mutable emule_peercache : int;
++ mutable emule_noviewshared : int;
++ mutable emule_multipacket : int;
++ mutable emule_supportpreview : int;
++
++(* emule_miscoptions2 *)
++ mutable emule_require_crypt : int;
++ mutable emule_request_crypt : int;
++ mutable emule_support_crypt : int;
++ mutable emule_extmultipacket : int;
++ mutable emule_largefiles : int;
++ mutable emule_kad_version : int;
+ }
+
+ type emule_tag_name =
+@@ -557,8 +569,10 @@
+ mutable client_checked : bool;
+ mutable client_connected : bool;
+ (* statistics *)
+- mutable client_downloaded : Int64.t;
+- mutable client_uploaded : Int64.t;
++ mutable client_session_downloaded : Int64.t;
++ mutable client_session_uploaded : Int64.t;
++ mutable client_total_downloaded : Int64.t;
++ mutable client_total_uploaded : Int64.t;
+ mutable client_brand : brand;
+ mutable client_brand_mod : brand_mod;
+ mutable client_osinfo_sent : bool;
+@@ -688,20 +702,32 @@
+ CommonServer.server_state (as_server server.server_server)
+
+ let dummy_emule_proto = {
+- emule_comments = 0;
+ emule_version = 0;
+ emule_release = "";
+- emule_secident = 0;
+- emule_noviewshared = 0;
+- emule_supportpreview = 0;
+ emule_osinfosupport = 0;
++ emule_features = 0;
+
++(* emule_miscoptions1 *)
++ emule_aich = 0;
++ emule_unicode = 0;
++ emule_udpver = 0;
+ emule_compression = 0; (* 1 *)
++ emule_secident = 0;
+ emule_sourceexchange = 0; (* 3 *)
+- emule_multipacket = 0; (* 1 *)
+ emule_extendedrequest = 0; (* 2 *)
+- emule_features = 0; (* 3 *)
+- emule_udpver = 0; (* 4 *)
++ emule_comments = 0;
++ emule_peercache = 0;
++ emule_noviewshared = 0;
++ emule_multipacket = 0;
++ emule_supportpreview = 0;
++
++(* emule_miscoptions2 *)
++ emule_require_crypt = 0;
++ emule_request_crypt = 0;
++ emule_support_crypt = 0;
++ emule_extmultipacket = 0;
++ emule_largefiles = 0;
++ emule_kad_version = 0;
+ }
+
+ let emule_proto () =
+Index: src/networks/donkey/donkeyUdp.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/donkey/donkeyUdp.ml,v
+retrieving revision 1.26
+retrieving revision 1.27
+diff -u -r1.26 -r1.27
+--- src/networks/donkey/donkeyUdp.ml 26 Nov 2006 16:36:29 -0000 1.26
++++ src/networks/donkey/donkeyUdp.ml 3 Dec 2006 20:49:42 -0000 1.27
+@@ -322,12 +322,12 @@
+ s.server_udp_desc_challenge <- None;
+ List.iter (fun tag ->
+ match tag with
+- { tag_name = Field_UNKNOWN "version"; tag_value = Uint64 i } ->
++ { tag_name = Field_KNOWN "version"; tag_value = Uint64 i } ->
+ let i = Int64.to_int i in
+ s.server_version <- Printf.sprintf "%d.%d" (i lsr 16) (i land 0xFFFF);
+- | { tag_name = Field_UNKNOWN "auxportslist" ; tag_value = String aux } ->
++ | { tag_name = Field_KNOWN "auxportslist" ; tag_value = String aux } ->
+ s.server_auxportslist <- aux
+- | { tag_name = Field_UNKNOWN "dynip" ; tag_value = String dynip } ->
++ | { tag_name = Field_KNOWN "dynip" ; tag_value = String dynip } ->
+ s.server_dynip <- dynip
+ | _ -> ()
+ ) t.M.tags;
+Index: src/networks/fasttrack/fasttrackNetwork.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/fasttrack/fasttrackNetwork.ml,v
+retrieving revision 1.2
+retrieving revision 1.3
+diff -u -r1.2 -r1.3
+--- src/networks/fasttrack/fasttrackNetwork.ml 7 Aug 2005 12:57:22 -0000 1.2
++++ src/networks/fasttrack/fasttrackNetwork.ml 3 Dec 2006 20:49:42 -0000 1.3
+@@ -34,30 +34,30 @@
+ (* any = 0 *)
+ let name_of_tag =
+ [
+- Field_UNKNOWN "any", 0;
+- Field_UNKNOWN "year", 1;
++ Field_KNOWN "any", 0;
++ Field_KNOWN "year", 1;
+ Field_Filename, 2;
+ Field_Uid, 3;
+ Field_Title, 4;
+- Field_UNKNOWN "time", 5;
++ Field_KNOWN "time", 5;
+ Field_Artist, 6;
+ Field_Album, 8;
+- Field_UNKNOWN "language", 0x0A;
+- Field_UNKNOWN "keywords", 0x0C;
+- Field_UNKNOWN "resolution", 0x0D;
+- Field_UNKNOWN "genre", 0x0E;
+- Field_UNKNOWN "OS", 0x10;
+- Field_UNKNOWN "bitdepth", 0x11;
++ Field_KNOWN "language", 0x0A;
++ Field_KNOWN "keywords", 0x0C;
++ Field_KNOWN "resolution", 0x0D;
++ Field_KNOWN "genre", 0x0E;
++ Field_KNOWN "OS", 0x10;
++ Field_KNOWN "bitdepth", 0x11;
+ Field_Type, 0x12;
+- Field_UNKNOWN "quality", 0x15;
+- Field_UNKNOWN "version", 0x18;
+- Field_UNKNOWN "comment", 0x1A;
++ Field_KNOWN "quality", 0x15;
++ Field_KNOWN "version", 0x18;
++ Field_KNOWN "comment", 0x1A;
+ Field_Codec, 0x1C; (* "divx" *)
+- Field_UNKNOWN "rating", 0x1D;
++ Field_KNOWN "rating", 0x1D;
+ Field_Size, 0x21;
+ Field_Type, 0x22; (* "movie", "video clip",... *)
+- Field_UNKNOWN "49", 49;
+- Field_UNKNOWN "53", 53;
++ Field_KNOWN "49", 49;
++ Field_KNOWN "53", 53;
+ ]
+
+ type cipher
+Index: src/networks/fasttrack/fasttrackProto.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/fasttrack/fasttrackProto.ml,v
+retrieving revision 1.17
+retrieving revision 1.18
+diff -u -r1.17 -r1.18
+--- src/networks/fasttrack/fasttrackProto.ml 28 Aug 2006 18:19:16 -0000 1.17
++++ src/networks/fasttrack/fasttrackProto.ml 3 Dec 2006 20:49:42 -0000 1.18
+@@ -108,30 +108,30 @@
+
+ let tag_of_tag tag s =
+ match tag with
+- | Field_UNKNOWN "any"
++ | Field_KNOWN "any"
+ | Field_Filename
+ | Field_Uid
+ | Field_Title
+- | Field_UNKNOWN "time"
++ | Field_KNOWN "time"
+ | Field_Artist
+ | Field_Album
+- | Field_UNKNOWN "language"
+- | Field_UNKNOWN "keywords"
+- | Field_UNKNOWN "genre"
+- | Field_UNKNOWN "OS"
++ | Field_KNOWN "language"
++ | Field_KNOWN "keywords"
++ | Field_KNOWN "genre"
++ | Field_KNOWN "OS"
+ | Field_Type
+- | Field_UNKNOWN "version"
+- | Field_UNKNOWN "comment"
++ | Field_KNOWN "version"
++ | Field_KNOWN "comment"
+ | Field_Codec ->
+ string_tag tag s
+- | Field_UNKNOWN "bitdepth"
+- | Field_UNKNOWN "year"
+- | Field_UNKNOWN "rating"
+- | Field_UNKNOWN "quality"
++ | Field_KNOWN "bitdepth"
++ | Field_KNOWN "year"
++ | Field_KNOWN "rating"
++ | Field_KNOWN "quality"
+ | Field_Size ->
+ let s, _ = get_dynint s 0 in
+ int64_tag tag s
+- | Field_UNKNOWN "resolution" ->
++ | Field_KNOWN "resolution" ->
+ let n1, pos = get_dynint s 0 in
+ let n2, pos = get_dynint s pos in
+ { tag_name = tag; tag_value = Pair (n1, n2) }
+@@ -145,7 +145,8 @@
+ | Field_Lastseencomplete
+ | Field_Mediacodec
+ | Field_Medialength
+- | Field_UNKNOWN _ ->
++ | Field_UNKNOWN _
++ | Field_KNOWN _ ->
+ string_tag tag s
+
+
+@@ -433,7 +434,7 @@
+
+ let tags =
+ if words <> "" then
+- (Substring, string_tag (Field_UNKNOWN "any") words) :: tags
++ (Substring, string_tag (Field_KNOWN "any") words) :: tags
+ else tags in
+ buf_int8 b (List.length tags);
+
+@@ -458,7 +459,7 @@
+ buf_int8 b (
+ try List.assoc tag name_of_tag with
+ _ -> match tag with
+- Field_UNKNOWN n -> int_of_string n
++ Field_KNOWN n -> int_of_string n
+ | _ -> assert false);
+ buf_string b s;
+ ) tags;
+@@ -869,7 +870,7 @@
+ let tag = try
+ List2.assoc_inv tag name_of_tag
+ with _ ->
+- Field_UNKNOWN (string_of_int tag)
++ Field_KNOWN (string_of_int tag)
+ in
+ iter_tags (pos + tag_len) (n-1)
+ ((new_tag tag tagdata) :: tags)
+@@ -916,7 +917,7 @@
+ List2.assoc_inv tag name_of_tag
+ with Not_found ->
+ lprintf "WARNING Unknown tag %d\n" tag;
+- Field_UNKNOWN (string_of_int tag)
++ Field_KNOWN (string_of_int tag)
+ in
+ let v, pos = get_string m (pos+2) in
+ let tag = tag_of_tag tag v in
+@@ -1939,6 +1940,7 @@
+ | Field_Artist
+ | Field_Title
+ | Field_Codec
++ | Field_KNOWN _
+ | Field_UNKNOWN _
+ | Field_Filename ->
+ tags := (Substring, string_tag field w) :: !tags
+@@ -1957,14 +1959,14 @@
+ begin
+ match field with
+ | Field_Size
+- | Field_UNKNOWN _
++ | Field_KNOWN _
+ -> tags := (AtLeast, int64_tag field value) :: !tags
+ | _ -> ()
+ end
+ | QHasMaxVal (field, value) ->
+ begin
+ match field with
+- | Field_UNKNOWN _
++ | Field_KNOWN _
+ | Field_Size ->
+ tags := (AtMost, int64_tag field value) :: !tags
+ | _ -> ()
+Index: src/networks/fileTP/fileTPClients.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/fileTP/fileTPClients.ml,v
+retrieving revision 1.23
+retrieving revision 1.24
+diff -u -r1.23 -r1.24
+--- src/networks/fileTP/fileTPClients.ml 19 Sep 2006 17:07:43 -0000 1.23
++++ src/networks/fileTP/fileTPClients.ml 2 Dec 2006 12:35:46 -0000 1.24
+@@ -74,6 +74,7 @@
+ if !verbose_msg_clients then
+ lprintf_nl "Disconnected from source";
+ c.client_requests <- [];
++ c.client_session_downloaded <- 0L;
+ connection_failed c.client_connection_control;
+ set_client_disconnected c r;
+ close sock r;
+Index: src/networks/fileTP/fileTPFTP.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/fileTP/fileTPFTP.ml,v
+retrieving revision 1.14
+retrieving revision 1.15
+diff -u -r1.14 -r1.15
+--- src/networks/fileTP/fileTPFTP.ml 19 Sep 2006 17:07:43 -0000 1.14
++++ src/networks/fileTP/fileTPFTP.ml 2 Dec 2006 12:35:46 -0000 1.15
+@@ -108,7 +108,8 @@
+ CommonSwarming.received up !counter_pos b.buf b.pos to_read_int;
+ let new_downloaded = CommonSwarming.downloaded swarmer in
+
+- c.client_downloaded <- c.client_downloaded ++ (new_downloaded -- old_downloaded);
++ c.client_total_downloaded <- c.client_total_downloaded ++ (new_downloaded -- old_downloaded);
++ c.client_session_downloaded <- c.client_session_downloaded ++ (new_downloaded -- old_downloaded);
+ client_must_update (as_client c);
+
+ if new_downloaded = file_size file then
+Index: src/networks/fileTP/fileTPGlobals.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/fileTP/fileTPGlobals.ml,v
+retrieving revision 1.30
+retrieving revision 1.31
+diff -u -r1.30 -r1.31
+--- src/networks/fileTP/fileTPGlobals.ml 9 Nov 2006 21:32:27 -0000 1.30
++++ src/networks/fileTP/fileTPGlobals.ml 2 Dec 2006 12:35:46 -0000 1.31
+@@ -192,7 +192,8 @@
+ client_hostname = hostname;
+ client_referer = referer;
+ client_port = port;
+- client_downloaded = zero;
++ client_total_downloaded = zero;
++ client_session_downloaded = zero;
+ client_reconnect = false;
+ client_in_queues = [];
+ client_connected_for = None;
+Index: src/networks/fileTP/fileTPHTTP.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/fileTP/fileTPHTTP.ml,v
+retrieving revision 1.26
+retrieving revision 1.27
+diff -u -r1.26 -r1.27
+--- src/networks/fileTP/fileTPHTTP.ml 19 Sep 2006 17:07:43 -0000 1.26
++++ src/networks/fileTP/fileTPHTTP.ml 2 Dec 2006 12:35:46 -0000 1.27
+@@ -288,7 +288,8 @@
+ CommonSwarming.received up !counter_pos b.buf b.pos to_read_int;
+ let new_downloaded = CommonSwarming.downloaded swarmer in
+
+- c.client_downloaded <- c.client_downloaded ++ (new_downloaded -- old_downloaded);
++ c.client_total_downloaded <- c.client_total_downloaded ++ (new_downloaded -- old_downloaded);
++ c.client_session_downloaded <- c.client_session_downloaded ++ (new_downloaded -- old_downloaded);
+ client_must_update (as_client c);
+
+ if new_downloaded = file_size file then
+Index: src/networks/fileTP/fileTPInteractive.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/fileTP/fileTPInteractive.ml,v
+retrieving revision 1.52
+retrieving revision 1.53
+diff -u -r1.52 -r1.53
+--- src/networks/fileTP/fileTPInteractive.ml 12 Nov 2006 12:44:24 -0000 1.52
++++ src/networks/fileTP/fileTPInteractive.ml 2 Dec 2006 12:35:46 -0000 1.53
+@@ -123,7 +123,8 @@
+ P.client_num = (client_num (as_client c));
+ P.client_connect_time = BasicSocket.last_time ();
+ P.client_software = c.client_software;
+- P.client_downloaded = c.client_downloaded;
++ P.client_total_downloaded = c.client_total_downloaded;
++ P.client_session_downloaded = c.client_session_downloaded;
+ }
+ );
+ client_ops.op_client_bprint <- (fun c buf ->
+@@ -141,8 +142,8 @@
+ client_print cc o;
+ Printf.bprintf buf "client: %s downloaded: %s uploaded: %s"
+ cinfo.GuiTypes.client_software
+- (Int64.to_string cinfo.GuiTypes.client_downloaded)
+- (Int64.to_string cinfo.GuiTypes.client_uploaded);
++ (Int64.to_string cinfo.GuiTypes.client_total_downloaded)
++ (Int64.to_string cinfo.GuiTypes.client_total_uploaded);
+ Printf.bprintf buf "\nfilename: %s\n\n" info.GuiTypes.file_name;
+ );
+ client_ops.op_client_dprint_html <- (fun c o file str ->
+@@ -183,8 +184,10 @@
+ ("", "sr", "N");
+ ("", "sr", Printf.sprintf "%s:%d" (Ip.to_string client_ip) client_port);
+ ] @ (if !Geoip.active then [(cname, "sr", ccode)] else []) @ [
+- ("", "sr ar", (size_of_int64 cinfo.GuiTypes.client_uploaded));
+- ("", "sr ar", (size_of_int64 cinfo.GuiTypes.client_downloaded));
++ ("", "sr ar", (size_of_int64 cinfo.GuiTypes.client_total_uploaded));
++ ("", "sr ar", (size_of_int64 cinfo.GuiTypes.client_total_downloaded));
++ ("", "sr ar", (size_of_int64 cinfo.GuiTypes.client_session_uploaded));
++ ("", "sr ar", (size_of_int64 cinfo.GuiTypes.client_session_downloaded));
+ ("", "sr", info.GuiTypes.file_name); ]);
+ true
+ )
+Index: src/networks/fileTP/fileTPSSH.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/fileTP/fileTPSSH.ml,v
+retrieving revision 1.10
+retrieving revision 1.11
+diff -u -r1.10 -r1.11
+--- src/networks/fileTP/fileTPSSH.ml 30 May 2006 10:54:14 -0000 1.10
++++ src/networks/fileTP/fileTPSSH.ml 2 Dec 2006 12:35:46 -0000 1.11
+@@ -103,7 +103,8 @@
+ let new_downloaded =
+ CommonSwarming.downloaded swarmer in
+
+- c.client_downloaded <- c.client_downloaded ++ (new_downloaded -- old_downloaded);
++ c.client_session_downloaded <- c.client_session_downloaded ++ (new_downloaded -- old_downloaded);
++ c.client_total_downloaded <- c.client_total_downloaded ++ (new_downloaded -- old_downloaded);
+ client_must_update (as_client c);
+
+ if new_downloaded = file_size file then
+Index: src/networks/fileTP/fileTPTypes.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/fileTP/fileTPTypes.ml,v
+retrieving revision 1.13
+retrieving revision 1.14
+diff -u -r1.13 -r1.14
+--- src/networks/fileTP/fileTPTypes.ml 1 Sep 2006 16:22:15 -0000 1.13
++++ src/networks/fileTP/fileTPTypes.ml 2 Dec 2006 12:35:46 -0000 1.14
+@@ -32,7 +32,8 @@
+ mutable client_referer : string;
+ mutable client_downloads : download list;
+ mutable client_in_queues : file list;
+- mutable client_downloaded : int64;
++ mutable client_total_downloaded : int64;
++ mutable client_session_downloaded : int64;
+ mutable client_connection_control : connection_control;
+ mutable client_sock : tcp_connection;
+ mutable client_requests : download list;
+Index: src/networks/gnutella/gnutellaInteractive.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/gnutella/gnutellaInteractive.ml,v
+retrieving revision 1.67
+retrieving revision 1.68
+diff -u -r1.67 -r1.68
+--- src/networks/gnutella/gnutellaInteractive.ml 12 Nov 2006 12:44:24 -0000 1.67
++++ src/networks/gnutella/gnutellaInteractive.ml 2 Dec 2006 12:35:46 -0000 1.68
+@@ -442,8 +442,8 @@
+ client_print cc o;
+ Printf.bprintf buf "client: %s downloaded: %s uploaded: %s"
+ "gN" (* cinfo.GuiTypes.client_software *)
+- (Int64.to_string cinfo.GuiTypes.client_downloaded)
+- (Int64.to_string cinfo.GuiTypes.client_uploaded);
++ (Int64.to_string cinfo.GuiTypes.client_total_downloaded)
++ (Int64.to_string cinfo.GuiTypes.client_total_uploaded);
+ Printf.bprintf buf "\nfilename: %s\n\n" info.GuiTypes.file_name;
+ );
+ client_ops.op_client_dprint_html <- (fun c o file str ->
+@@ -477,8 +477,10 @@
+ ("", "sr", "N");
+ ("", "sr", (string_of_kind cinfo.GuiTypes.client_kind));
+ ] @ (if !Geoip.active then [("?", "sr", "?")] else []) @ [
+- ("", "sr ar", (size_of_int64 cinfo.GuiTypes.client_uploaded));
+- ("", "sr ar", (size_of_int64 cinfo.GuiTypes.client_downloaded));
++ ("", "sr ar", (size_of_int64 cinfo.GuiTypes.client_total_uploaded));
++ ("", "sr ar", (size_of_int64 cinfo.GuiTypes.client_total_downloaded));
++ ("", "sr ar", (size_of_int64 cinfo.GuiTypes.client_session_uploaded));
++ ("", "sr ar", (size_of_int64 cinfo.GuiTypes.client_session_downloaded));
+ ("", "sr", info.GuiTypes.file_name); ]);
+ true
+ )
+Index: src/networks/opennap/opennapInteractive.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/opennap/opennapInteractive.ml,v
+retrieving revision 1.26
+retrieving revision 1.27
+diff -u -r1.26 -r1.27
+--- src/networks/opennap/opennapInteractive.ml 1 Oct 2006 17:54:00 -0000 1.26
++++ src/networks/opennap/opennapInteractive.ml 3 Dec 2006 20:49:42 -0000 1.27
+@@ -78,7 +78,7 @@
+ | QHasMinVal (field, value) ->
+ begin
+ match field with
+- Field_UNKNOWN "bitrate" ->
++ Field_KNOWN "bitrate" ->
+ { t with S.bitrate = Some (Int64.to_int value, OP.AtLeast) };
+ | Field_Size -> t
+ | _ -> t
+@@ -86,7 +86,7 @@
+ | QHasMaxVal (field, value) ->
+ begin
+ match field with
+- Field_UNKNOWN "bitrate" ->
++ Field_KNOWN "bitrate" ->
+ { t with S.bitrate = Some (Int64.to_int value, OP.AtBest) };
+ | Field_Size -> t
+ | _ -> t
+Index: src/networks/server/serverUdp.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/networks/server/serverUdp.ml,v
+retrieving revision 1.2
+retrieving revision 1.3
+diff -u -r1.2 -r1.3
+--- src/networks/server/serverUdp.ml 16 Oct 2005 20:42:54 -0000 1.2
++++ src/networks/server/serverUdp.ml 28 Nov 2006 23:58:02 -0000 1.3
+@@ -431,7 +431,7 @@
+ else
+ dead_servers := s :: !dead_servers
+ ) DonkeyGlobals.servers_by_key;
+- let alive_servers = Sort.list (fun s1 s2 ->
++ let alive_servers = List.sort (fun s1 s2 ->
+ s1.DonkeyTypes.server_last_message >=
+ s2.DonkeyTypes.server_last_message
+ ) !alive_servers in
+Index: src/utils/cdk/sort2.ml
+===================================================================
+RCS file: src/utils/cdk/sort2.ml
+diff -N src/utils/cdk/sort2.ml
+--- src/utils/cdk/sort2.ml 22 Apr 2003 22:33:39 -0000 1.1
++++ /dev/null 1 Jan 1970 00:00:00 -0000
+@@ -1,97 +0,0 @@
+-(***********************************************************************)
+-(* *)
+-(* Objective Caml *)
+-(* *)
+-(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
+-(* *)
+-(* Copyright 1996 Institut National de Recherche en Informatique et *)
+-(* en Automatique. All rights reserved. This file is distributed *)
+-(* under the terms of the GNU Library General Public License, with *)
+-(* the special exception on linking described in file ../LICENSE. *)
+-(* *)
+-(***********************************************************************)
+-
+-(* Merging and sorting *)
+-
+-open Array
+-
+- (*
+-let rec merge order l1 l2 =
+- match l1 with
+- [] -> l2
+- | h1 :: t1 ->
+- match l2 with
+- [] -> l1
+- | h2 :: t2 ->
+- if order h1 h2
+- then h1 :: merge order t1 l2
+- else h2 :: merge order l1 t2
+-
+-let list order l =
+- let rec initlist = function
+- [] -> []
+- | [e] -> [[e]]
+- | e1::e2::rest ->
+- (if order e1 e2 then [e1;e2] else [e2;e1]) :: initlist rest in
+- let rec merge2 = function
+- l1::l2::rest -> merge order l1 l2 :: merge2 rest
+- | x -> x in
+- let rec mergeall = function
+- [] -> []
+- | [l] -> l
+- | llist -> mergeall (merge2 llist) in
+- mergeall(initlist l)
+- *)
+-
+-let swap arr i j =
+- let tmp = unsafe_get arr i in
+- unsafe_set arr i (unsafe_get arr j);
+- unsafe_set arr j tmp
+-
+-let subarray cmp arr pos len =
+- let rec qsort lo hi =
+- if hi - lo >= 6 then begin
+- let mid = (lo + hi) lsr 1 in
+- (* Select median value from among LO, MID, and HI. Rearrange
+- LO and HI so the three values are sorted. This lowers the
+- probability of picking a pathological pivot. It also
+- avoids extra comparisons on i and j in the two tight "while"
+- loops below. *)
+- if cmp (unsafe_get arr mid) (unsafe_get arr lo) <= 0 then swap arr mid lo;
+- if cmp (unsafe_get arr hi) (unsafe_get arr mid) <= 0 then begin
+- swap arr mid hi;
+- if cmp (unsafe_get arr mid) (unsafe_get arr lo) <= 0 then swap arr mid lo
+- end;
+- let pivot = unsafe_get arr mid in
+- let i = ref (lo + 1) and j = ref (hi - 1) in
+- if not (cmp pivot (unsafe_get arr hi) <= 0)
+- || not (cmp (unsafe_get arr lo) pivot <= 0)
+- then raise (Invalid_argument "Sort.array");
+- while !i < !j do
+- while not (cmp pivot (unsafe_get arr !i) <= 0) do incr i done;
+- while not (cmp (unsafe_get arr !j) pivot <= 0) do decr j done;
+- if !i < !j then swap arr !i !j;
+- incr i; decr j
+- done;
+- (* Recursion on smaller half, tail-call on larger half *)
+- if !j - lo <= hi - !i then begin
+- qsort lo !j; qsort !i hi
+- end else begin
+- qsort !i hi; qsort lo !j
+- end
+- end in
+- qsort pos (pos+len-1);
+- (* Finish sorting by insertion sort *)
+- for i = pos+1 to pos+len - 1 do
+- let val_i = (unsafe_get arr i) in
+- if not (cmp (unsafe_get arr (i - 1)) val_i <= 0) then begin
+- unsafe_set arr i (unsafe_get arr (i - 1));
+- let j = ref (i - 1) in
+- while !j >= 1 && not (cmp (unsafe_get arr (!j - 1)) val_i <= 0) do
+- unsafe_set arr !j (unsafe_get arr (!j - 1));
+- decr j
+- done;
+- unsafe_set arr !j val_i
+- end
+- done
+-
+Index: src/utils/cdk/sort2.mli
+===================================================================
+RCS file: src/utils/cdk/sort2.mli
+diff -N src/utils/cdk/sort2.mli
+--- src/utils/cdk/sort2.mli 22 Apr 2003 22:33:39 -0000 1.1
++++ /dev/null 1 Jan 1970 00:00:00 -0000
+@@ -1,43 +0,0 @@
+-(***********************************************************************)
+-(* *)
+-(* Objective Caml *)
+-(* *)
+-(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
+-(* *)
+-(* Copyright 1996 Institut National de Recherche en Informatique et *)
+-(* en Automatique. All rights reserved. This file is distributed *)
+-(* under the terms of the GNU Library General Public License, with *)
+-(* the special exception on linking described in file ../LICENSE. *)
+-(* *)
+-(***********************************************************************)
+-
+-(** Sorting and merging lists.
+-
+- @deprecated This module is obsolete and exists only for backward
+- compatibility.
+- The sorting functions in {!Array} and {!List} should be used instead.
+- The new functions are faster and use less memory.
+-*)
+-
+-(*
+-val list : ('a -> 'a -> bool) -> 'a list -> 'a list
+-(** Sort a list in increasing order according to an ordering predicate.
+- The predicate should return [true] if its first argument is
+- less than or equal to its second argument. *)
+-*)
+-
+-val subarray : ('a -> 'a -> int) -> 'a array -> int -> int -> unit
+-(** Sort an array in increasing order according to an
+- ordering predicate.
+- The predicate should return [true] if its first argument is
+- less than or equal to its second argument.
+- The array is sorted in place. *)
+-
+- (*
+-val merge : ('a -> 'a -> bool) -> 'a list -> 'a list -> 'a list
+-(** Merge two lists according to the given predicate.
+- Assuming the two argument lists are sorted according to the
+- predicate, [merge] returns a sorted list containing the elements
+- from the two lists. The behavior is undefined if the two
+- argument lists were not sorted. *)
+-*)
+Index: src/utils/cdk/string2.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/utils/cdk/string2.ml,v
+retrieving revision 1.9
+retrieving revision 1.10
+diff -u -r1.9 -r1.10
+--- src/utils/cdk/string2.ml 20 Jul 2006 15:30:21 -0000 1.9
++++ src/utils/cdk/string2.ml 3 Dec 2006 20:49:43 -0000 1.10
+@@ -322,3 +322,9 @@
+ i >= l || p s.[i] && aux (i+1) in
+ aux 0
+
++let hex_string_of_string s =
++ let buf = Buffer.create 100 in
++ String.iter (fun c ->
++ Printf.bprintf buf "%02x " (int_of_char c)
++ ) s;
++ Buffer.contents buf
+Index: src/utils/cdk/string2.mli
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/utils/cdk/string2.mli,v
+retrieving revision 1.10
+retrieving revision 1.11
+diff -u -r1.10 -r1.11
+--- src/utils/cdk/string2.mli 20 Jul 2006 15:30:21 -0000 1.10
++++ src/utils/cdk/string2.mli 3 Dec 2006 20:49:43 -0000 1.11
+@@ -103,3 +103,4 @@
+ val exists: (char -> bool) -> string -> bool
+ val existsi: (int -> char -> bool) -> string -> bool
+ val for_all: (char -> bool) -> string -> bool
++val hex_string_of_string : string -> string
+Index: src/utils/cdk/unix2.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/utils/cdk/unix2.ml,v
+retrieving revision 1.31
+retrieving revision 1.32
+diff -u -r1.31 -r1.32
+--- src/utils/cdk/unix2.ml 12 Aug 2006 20:36:14 -0000 1.31
++++ src/utils/cdk/unix2.ml 28 Nov 2006 23:52:17 -0000 1.32
+@@ -89,7 +89,7 @@
+ with e ->
+ lprintf_nl "warning: chmod failed on %s: %s" f (Printexc2.to_string e)
+
+-let rec safe_mkdir dir =
++let rec safe_mkdir ?(mode = 0o775) dir =
+ if Sys.file_exists dir then begin
+ if not (is_directory dir) then
+ failwith (Printf.sprintf "%s already exists but is not a directory" dir)
+@@ -112,7 +112,7 @@
+ let predir = Filename.dirname dir in
+ if predir <> dir then safe_mkdir predir;
+ try
+- Unix.mkdir dir 0o775
++ Unix.mkdir dir mode
+ with
+ Unix.Unix_error (EEXIST, _, _) -> ()
+ | e -> lprintf_nl "error %s for directory %s" (Printexc2.to_string e) dir; exit 73
+@@ -136,7 +136,13 @@
+
+ let copy oldname newname =
+ tryopen_read_bin oldname (fun ic ->
++ let stats = Unix.fstat (Unix.descr_of_in_channel ic) in
+ tryopen_write_bin newname (fun oc ->
++ let descr = Unix.descr_of_out_channel oc in
++ (try Unix.fchown descr stats.Unix.st_uid stats.Unix.st_gid
++ with e -> lprintf_nl "copy: failed to preserve owner");
++ (try Unix.fchmod descr stats.Unix.st_perm
++ with e -> lprintf_nl "copy: failed to preserve mode");
+ let buffer_len = 8192 in
+ let buffer = String.create buffer_len in
+ let rec copy_file () =
+Index: src/utils/lib/unix32.ml
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/utils/lib/unix32.ml,v
+retrieving revision 1.65
+retrieving revision 1.66
+diff -u -r1.65 -r1.66
+--- src/utils/lib/unix32.ml 15 Jul 2006 11:52:54 -0000 1.65
++++ src/utils/lib/unix32.ml 28 Nov 2006 23:52:18 -0000 1.66
+@@ -31,15 +31,14 @@
+
+ let max_buffered = ref (Int64.of_int (1024 * 1024))
+
+-let create_dir_mask = ref "755"
++let create_file_mode = ref 0o664
++let create_dir_mode = ref 0o755
+ let verbose = ref false
+ let max_cache_size = ref 50
+
+ let mini (x: int) (y: int) =
+ if x > y then y else x
+
+-let rights = 0o664
+-
+ let ro_flag = [Unix.O_RDONLY]
+ let rw_flag = [Unix.O_RDWR]
+ let rw_creat_flag = [Unix.O_CREAT; Unix.O_RDWR]
+@@ -121,7 +120,8 @@
+ try
+ if t.writable then
+ Unix.openfile t.filename
+- (if creat then rw_creat_flag else rw_flag) rights
++ (if creat then rw_creat_flag else rw_flag)
++ !create_file_mode
+ else
+ Unix.openfile t.filename ro_flag 0o400
+ with e ->
+@@ -254,9 +254,9 @@
+ check_destroyed t;
+ close t;
+ (let d = (Filename.dirname (Filename.concat f file)) in
+- Unix2.safe_mkdir d;
+- Unix2.chmod d (Misc.int_of_octal_string !create_dir_mask);
+- Unix2.can_write_to_directory d);
++ Unix2.safe_mkdir d;
++ Unix2.chmod d !create_dir_mode;
++ Unix2.can_write_to_directory d);
+ (try
+ Unix2.rename t.filename (Filename.concat f file);
+ with
+Index: src/utils/lib/unix32.mli
+===================================================================
+RCS file: /sources/mldonkey/mldonkey/src/utils/lib/unix32.mli,v
+retrieving revision 1.23
+retrieving revision 1.24
+diff -u -r1.23 -r1.24
+--- src/utils/lib/unix32.mli 6 Mar 2006 18:02:16 -0000 1.23
++++ src/utils/lib/unix32.mli 28 Nov 2006 23:52:18 -0000 1.24
+@@ -26,7 +26,8 @@
+ val uname : unit -> string
+ val os_supported : unit -> bool
+
+-val create_dir_mask : string ref
++val create_file_mode : int ref
++val create_dir_mode : int ref
+ val close : t -> unit
+ (* val force_fd : t -> Unix.file_descr *)
+