diff -urN -x cvs config/Makefile.in config/Makefile.in
--- config/Makefile.in	Sun Mar 20 09:41:28 2005
+++ config/Makefile.in	Mon Mar 28 12:06:09 2005
@@ -449,6 +449,7 @@
   $(SRC_BITTORRENT)/bTComplexOptions.ml \
   $(SRC_BITTORRENT)/bTTracker.ml \
   $(SRC_BITTORRENT)/bTChooser.ml \
+  $(SRC_BITTORRENT)/bTShare.ml \
   $(SRC_BITTORRENT)/bTClients.ml \
   $(SRC_BITTORRENT)/bTInteractive.ml \
   $(BROOSNET) \
diff -urN -x cvs src/daemon/common/commonShared.ml src/daemon/common/commonShared.ml
--- src/daemon/common/commonShared.ml	Sun Mar 20 09:41:29 2005
+++ src/daemon/common/commonShared.ml	Sat Mar 26 17:18:01 2005
@@ -318,7 +318,7 @@
     T.shared_size = impl.impl_shared_size;
     T.shared_uploaded = impl.impl_shared_uploaded;
     T.shared_requests = impl.impl_shared_requests; 
-    T.shared_id = Md4.null;
+    T.shared_uids = [];
   }
   
 let shared_info s =
diff -urN -x cvs src/daemon/common/commonTypes.ml src/daemon/common/commonTypes.ml
--- src/daemon/common/commonTypes.ml	Thu Mar  3 03:28:14 2005
+++ src/daemon/common/commonTypes.ml	Sat Mar 26 18:01:50 2005
@@ -42,6 +42,7 @@
 | TigerTree of TigerTree.t
 | Md5Ext of Md5Ext.t     (* for Fasttrack *)
 | BTUrl of Sha1.t
+| Ftp of Md4.t
 | NoUid
   
 and file_uid_id = 
@@ -51,6 +52,7 @@
 | MD5
 | MD5EXT
 | TIGER
+| FTP
 
 let string_of_uid_sep uid sep =
   match uid with
@@ -71,6 +73,8 @@
         (Md5Ext.to_base32 md5)
   | BTUrl url ->
       "urn" ^ sep ^ "bt" ^ sep ^ (Sha1.to_string url)
+  | Ftp ftp ->
+      "urn" ^ sep ^ "ftp" ^ sep ^ (Md4.to_string ftp)
   | NoUid -> ""
 
 let string_of_uid uid =
@@ -113,6 +117,7 @@
   | "sig2dat" -> Md5Ext (Md5Ext.of_base32 rem)
   | "bt" | "bittorrent" -> 
       BTUrl (Sha1.of_string rem)
+  | "ftp" -> Ftp (Md4.of_string rem)
   | _ -> raise (Illegal_urn (s ^ " at " ^ sign ^ " is not known"))
 
 module Uid : sig
diff -urN -x cvs src/daemon/common/guiDecoding.ml src/daemon/common/guiDecoding.ml
--- src/daemon/common/guiDecoding.ml	Sun Mar 20 09:41:29 2005
+++ src/daemon/common/guiDecoding.ml	Sat Mar 26 17:16:36 2005
@@ -404,7 +404,12 @@
     else "", pos in
   let names = List.map (fun name -> name, noips()) names in
   let last_seen = BasicSocket.last_time () - last_seen in
-  
+  let uids, pos = 
+    if proto < 31 then
+      [], pos
+    else
+      get_list (get_uid charset) s pos
+  in
   (*
   assert (num = file_info_test.file_num);
   assert (net = file_info_test.file_network);
@@ -448,7 +453,7 @@
     file_name = name;
     file_last_seen = last_seen;
     file_priority = priority;
-    file_uids = [];
+    file_uids = uids;
   }, pos
 
 let get_host_state proto s pos =
@@ -731,7 +736,7 @@
     shared_size = size;
     shared_uploaded = uploaded;
     shared_requests = requests;
-    shared_id = Md4.null;
+    shared_uids = [];
   }
 
 let get_shared_info_version_10 proto charset s pos =
@@ -741,7 +746,12 @@
   let size,pos = get_uint64_2 proto s pos in
   let uploaded = get_int64 s pos in
   let requests = get_int s (pos+8) in
-  let md4 = get_md4 s (pos+12) in
+  let uids, pos = 
+    if proto < 31 then
+      [], pos+12
+    else
+      get_list (get_uid charset) s (pos+12)
+  in
   {
     shared_num = num;
     shared_network = network;
@@ -749,7 +759,7 @@
     shared_size = size;
     shared_uploaded = uploaded;
     shared_requests = requests;
-    shared_id = md4;
+    shared_uids = uids;
   }
 
   
diff -urN -x cvs src/daemon/common/guiEncoding.ml src/daemon/common/guiEncoding.ml
--- src/daemon/common/guiEncoding.ml	Sun Mar 20 09:41:29 2005
+++ src/daemon/common/guiEncoding.ml	Sat Mar 26 17:11:21 2005
@@ -490,7 +490,9 @@
     if proto >= 12 then
       buf_int buf f.file_priority;
     if proto > 21 then
-      buf_string charset buf f.file_comment
+      buf_string charset buf f.file_comment;
+    if proto > 30 then
+      buf_list buf (buf_uid charset) f.file_uids
       
 let buf_addr charset buf addr =
   match addr with
@@ -594,9 +596,11 @@
   buf_int64 buf s.shared_uploaded;
   buf_int buf s.shared_requests;
   if proto >= 10 then
-    buf_md4 buf s.shared_id
-    
-  
+    if proto < 31 then
+      buf_md4 buf Md4.null
+    else
+      buf_list buf (buf_uid charset) s.shared_uids
+
 (***************
 
        Encoding of messages from the Core to the GUI 
diff -urN -x cvs src/daemon/common/guiProto.ml src/daemon/common/guiProto.ml
--- src/daemon/common/guiProto.ml	Mon Nov  1 19:22:59 2004
+++ src/daemon/common/guiProto.ml	Sat Mar 26 17:14:48 2005
@@ -31,7 +31,7 @@
   
 let to_gui_last_opcode = 58
 let from_gui_last_opcode = 65
-let best_gui_version = 30
+let best_gui_version = 31
   
 (* I will try to report all changes to the protocol here: send me patches
 if I don't !
@@ -45,7 +45,14 @@
   GUI -> Core: new message [INTERESTED_IN_SOURCES]
     By sending (INTERESTED_IN_SOURCES interestedp), a GUI can declare
      whether it wants or not to receive information on sources.
-  
+
+Version 31:
+  Core -> GUI: message 52 [FILE_INFO]
+    Field file_uids is now encoded (string list) for protocol > 30
+  Core -> GUI: message 48 [SHARED_FILE_INFO]
+    Field shared_id (md4 - 16 bytes) has been replaced by shared_uids (string list)
+    For protocols < 31, the MD4 sent is now invalid (filled with zeroes). Don't use it !
+
   *)
   
   
diff -urN -x cvs src/daemon/common/guiTypes.ml src/daemon/common/guiTypes.ml
--- src/daemon/common/guiTypes.ml	Tue Aug 10 22:47:25 2004
+++ src/daemon/common/guiTypes.ml	Sat Mar 26 17:01:54 2005
@@ -234,7 +234,7 @@
     mutable shared_size : int64;
     mutable shared_uploaded : int64;
     mutable shared_requests : int;
-    mutable shared_id : Md4.t;
+    mutable shared_uids : Uid.t list; (* net file UID *)
   }
   
   
diff -urN -x cvs src/gtk2/gui/guiColumns.ml src/gtk2/gui/guiColumns.ml
--- src/gtk2/gui/guiColumns.ml	Thu Mar  3 03:45:11 2005
+++ src/gtk2/gui/guiColumns.ml	Sat Mar 26 18:14:33 2005
@@ -88,7 +88,7 @@
 (* The different columns which can be displayed for a file. *)
 type file_column = 
   Col_file_name
-| Col_file_md4
+| Col_file_uid
 | Col_file_size
 | Col_file_downloaded
 | Col_file_percent
@@ -106,7 +106,7 @@
 
 let file_column_strings = [
     Col_file_name         , M.c_name       , 0  ;
-    Col_file_md4          , M.c_md4        , 1  ;
+    Col_file_uid          , M.c_uid        , 1  ;
     Col_file_size         , M.c_size       , 2  ;
     Col_file_downloaded   , M.c_downloaded , 3  ;
     Col_file_percent      , M.c_percent    , 4  ;
@@ -300,7 +300,7 @@
 | Col_shared_upsize
 | Col_shared_requests
 | Col_shared_size
-| Col_shared_md4
+| Col_shared_uid
 
 let shared_file_up_column_strings = [
     Col_shared_file     , M.c_filename , 0 ;
@@ -308,7 +308,7 @@
     Col_shared_upsize   , M.c_uploaded , 2 ;
     Col_shared_requests , M.c_requests , 3 ;
     Col_shared_size     , M.c_size     , 4 ;
-    Col_shared_md4      , M.c_md4      , 5 ;
+    Col_shared_uid      , M.c_uid      , 5 ;
   ] 
   
 module Shared_files_up = Column
diff -urN -x cvs src/gtk2/gui/guiConfig.ml src/gtk2/gui/guiConfig.ml
--- src/gtk2/gui/guiConfig.ml	Thu Mar  3 03:45:11 2005
+++ src/gtk2/gui/guiConfig.ml	Mon Mar 28 13:26:03 2005
@@ -583,28 +583,45 @@
 
 (*************************************************************************)
 (*                                                                       *)
-(*                         clear                                         *)
+(*                         add_option                                    *)
 (*                                                                       *)
 (*************************************************************************)
 
-let clear = Config.clear
+
+let add_option (section, o) = add_preference (section, o) Config.preferences_values
 
 (*************************************************************************)
 (*                                                                       *)
-(*                         add_option                                    *)
+(*                         update_options                                *)
 (*                                                                       *)
 (*************************************************************************)
 
+let update_options options_list = update_preferences options_list Config.preferences_values
 
-let add_option (section, o) = add_preference (section, o) Config.preferences_values
+(*************************************************************************)
+(*                                                                       *)
+(*                         load_gui_options                              *)
+(*                                                                       *)
+(*************************************************************************)
+
+let load_gui_options () =
+  List.iter (fun opt_section ->
+    let section = Options.section_name opt_section in
+    List.iter (fun o ->
+      add_option (section, o)
+    ) (Options.strings_of_section_options "" opt_section)
+  ) (Options.sections O.gui_ini)
 
 (*************************************************************************)
 (*                                                                       *)
-(*                         update_options                                *)
+(*                         clear                                         *)
 (*                                                                       *)
 (*************************************************************************)
 
-let update_options options_list = update_preferences options_list Config.preferences_values
+let clear =
+  (fun _ ->
+     Config.clear ();
+     load_gui_options ())
 
 (*************************************************************************)
 (*                                                                       *)
@@ -627,7 +644,7 @@
           iter tail
         end
 
-let config_window gui f =
+let config_window gui value_reader f =
   let use_icons = !!O.gtk_look_use_icons in
   let use_avail_bars = !!O.gtk_look_graphical_availability in
   let language = !!O.gtk_client_lang in
@@ -635,8 +652,11 @@
   let small_icon = !!O.gtk_look_lists_icon_size in
   let medium_icon = !!O.gtk_look_toolbars_icon_size in
   let large_icon = !!O.gtk_look_main_toolbar_icon_size in
+  let (hostname, port) = (!!O.gtk_client_hostname, !!O.gtk_client_port) in
   let on_ok () =
     G.get_metrics_from_gtk_font_list ();
+    (if (hostname, port) <> (!!O.gtk_client_hostname, !!O.gtk_client_port)
+       then GuiCom.reconnect gui value_reader gui BasicSocket.Closed_by_user);
     (if use_icons <> !!O.gtk_look_use_icons ||
         saturation <> !!O.gtk_look_icon_saturation ||
         small_icon <> !!O.gtk_look_lists_icon_size ||
@@ -696,3 +716,21 @@
     gui.update_current_page ();
   in
   Config.config_window ~on_ok
+
+
+let _ =
+  (try Options.load O.gui_ini with _ -> ());
+  (try Options.save O.gui_ini with _ -> ());
+  let args = Options.simple_args "" O.gui_ini in
+  Arg.parse args (Arg.usage args)  "mlgui: the GUI to use with mldonkey";
+  load_gui_options () (* ;
+  match !!O.gtk_client_lang with
+      U.EN -> ()
+    | _ ->
+      begin
+        let s = U.lang_to_string !!O.gtk_client_lang in
+        let ext = String.lowercase s in
+        Gettext.set_strings_file M.filename ~ext ();
+        M.load_messages ()
+      end
+*)
diff -urN -x cvs src/gtk2/gui/guiDownloads.ml src/gtk2/gui/guiDownloads.ml
--- src/gtk2/gui/guiDownloads.ml	Thu Mar  3 03:45:11 2005
+++ src/gtk2/gui/guiDownloads.ml	Mon Mar 28 13:54:22 2005
@@ -78,6 +78,7 @@
      source_rating = 0;
      source_chat_port = 0;
      source_connect_time = 0;
+     source_last_seen = BasicSocket.current_time ();
      source_software = "tML";
      source_downloaded = Int64.zero;
      source_uploaded = Int64.zero;
@@ -121,7 +122,7 @@
   let download_network_pixb      = download_cols#add Gobject.Data.gobject_option in
   let download_name              = download_cols#add Gobject.Data.string in
   let download_name_pixb         = download_cols#add Gobject.Data.gobject_option in
-  let download_md4               = download_cols#add Gobject.Data.string in
+  let download_uid               = download_cols#add Gobject.Data.string in
   let download_size              = download_cols#add Gobject.Data.string in
   let download_downloaded        = download_cols#add Gobject.Data.string in
   let download_percent           = download_cols#add Gobject.Data.string in
@@ -155,7 +156,7 @@
               store#set ~row ~column:download_network_pixb (Mi.network_pixb f.file_network ~size:A.SMALL ());
               store#set ~row ~column:download_name (U.utf8_of f.file_name);
               store#set ~row ~column:download_name_pixb (Mi.file_type_of_name f.file_name ~size:A.SMALL);
-              store#set ~row ~column:download_md4 (U.utf8_of (Md4.to_string f.file_md4));
+              store#set ~row ~column:download_uid (Mi.uid_list_to_string f.file_uids);
               store#set ~row ~column:download_size (Mi.size_of_int64 f.file_size);
               store#set ~row ~column:download_downloaded (Mi.size_of_int64 f.file_downloaded);
               store#set ~row ~column:download_percent (Mi.get_percent_of f.file_downloaded f.file_size);
@@ -216,9 +217,9 @@
                       store#set ~row ~column:download_name_pixb (Mi.file_type_of_name f_new.file_name ~size:A.SMALL);
                     end
                 end;
-              if f.file_md4 <> f_new.file_md4
+              if f.file_uids <> f_new.file_uids
                 then begin
-                  store#set ~row ~column:download_md4 (U.utf8_of (Md4.to_string f_new.file_md4));
+                  store#set ~row ~column:download_uid (Mi.uid_list_to_string f.file_uids);
                 end;
               if (f.file_size, f.file_downloaded, f.file_download_rate, f.file_age) <>
                  (f_new.file_size, f_new.file_downloaded, f_new.file_download_rate, f_new.file_age)
@@ -415,11 +416,11 @@
                 end
             end
 
-        | Col_file_md4 ->
+        | Col_file_uid ->
             begin
               let renderer = GTree.cell_renderer_text [`XALIGN 0.] in
               col#pack renderer;
-              col#add_attribute renderer "text" download_md4
+              col#add_attribute renderer "text" download_uid
             end
 
         | Col_file_format ->
@@ -508,7 +509,7 @@
                  | Col_file_state -> compare (Mi.string_of_file_state f1.file_state f1.file_download_rate)
                                              (Mi.string_of_file_state f2.file_state f2.file_download_rate)
                  | Col_file_availability -> compare f1.file_availability f2.file_availability
-                 | Col_file_md4 -> compare f1.file_md4 f2.file_md4
+                 | Col_file_uid -> compare (Mi.uid_list_to_string f1.file_uids) (Mi.uid_list_to_string f2.file_uids)
                  | Col_file_format -> compare f1.file_format f2.file_format
                  | Col_file_network -> compare f1.file_network f2.file_network
                  | Col_file_age -> compare f1.file_age f2.file_age
diff -urN -x cvs src/gtk2/gui/guiInfoWindow.ml src/gtk2/gui/guiInfoWindow.ml
--- src/gtk2/gui/guiInfoWindow.ml	Thu Mar  3 03:45:11 2005
+++ src/gtk2/gui/guiInfoWindow.ml	Sat Mar 26 18:27:03 2005
@@ -132,7 +132,7 @@
         let avail = Mi.main_availability_of f.file_network f.file_availability in
         [
          [!M.fW_lb_file_format; Mi.format_to_string f.file_format];
-         [!M.fW_lb_file_hash;   Md4.to_string f.file_md4];
+         [!M.fW_lb_file_hash;   Mi.uid_list_to_string f.file_uids];
          [!M.fW_lb_file_size;   Mi.size_of_int64 f.file_size;
           !M.fW_lb_file_state;  Mi.string_of_file_state f.file_state f.file_download_rate];
          [!M.fW_lb_file_chunks; Mi.chunks_to_string f.file_chunks;
@@ -165,7 +165,7 @@
           !M.fW_lb_file_complete_chunks; Mi.completed_chunks_to_string f.file_chunks];
          [!M.fW_lb_last_seen;            Mi.time_to_string f.file_last_seen;
           !M.fW_lb_file_eta;            (Mi.calc_eta_inst f.file_size f.file_downloaded f.file_download_rate) ^ " / " ^
-                                       (Mi.calc_eta_average f.file_size f.file_downloaded f.file_age)]
+                                        (Mi.calc_eta_average f.file_size f.file_downloaded f.file_age)]
         ]
 
     | Source (s, files) ->
diff -urN -x cvs src/gtk2/gui/guiMain.ml src/gtk2/gui/guiMain.ml
--- src/gtk2/gui/guiMain.ml	Thu Mar  3 03:45:11 2005
+++ src/gtk2/gui/guiMain.ml	Mon Mar 28 13:56:09 2005
@@ -65,43 +65,6 @@
       ()
   end
 
-(*************************************************************************)
-(*                                                                       *)
-(*                         load_gui_options                              *)
-(*                                                                       *)
-(*************************************************************************)
-
-let load_gui_options () =
-  List.iter (fun opt_section ->
-    let section = Options.section_name opt_section in
-    List.iter (fun o ->
-      GuiConfig.add_option (section, o)
-    ) (Options.strings_of_section_options "" opt_section)
-  ) (Options.sections O.gui_ini)
-
-let _ =
-  (try Options.load O.gui_ini with
-      Sys_error _ ->
-	(try Options.save O.gui_ini with _ -> ())
-     | e ->
-        Printf2.lprintf "Exception %s in load options %s\n" 
-	 (Printexc2.to_string e)
-	 (Options.options_file_name O.gui_ini);
-  );
-  let args = Options.simple_args "" O.gui_ini in
-  Arg.parse args (Arg.usage args)  "mlgui: the GUI to use with mldonkey";
-  load_gui_options () (* ;
-  match !!O.gtk_client_lang with
-      U.EN -> ()
-    | _ ->
-      begin
-        let s = U.lang_to_string !!O.gtk_client_lang in
-        let ext = String.lowercase s in
-        Gettext.set_strings_file M.filename ~ext ();
-        M.load_messages ()
-      end
-*)
-
 (* {2 Handling core messages} *)
 
 open CommonTypes
@@ -137,7 +100,6 @@
         done;
         ( if !!verbose then lprintf' "Using protocol %d for communications\n" version);
         gui.set_corestatus Core_Connected;
-        load_gui_options ();
         if version >= G.interested_in_sources_version
           then begin
             ( if !!verbose then lprintf' "-----  not interested in sources -----\n");
@@ -395,21 +357,18 @@
              end
           );
           let source = Mi.client_to_source client in
-          let source_new =
-            {source with source_connect_time = (BasicSocket.last_time () - source.source_connect_time)}
-          in
           let s_new =
             try
-              let s = Hashtbl.find G.sources source_new.source_num in
-              { source_new with
+              let s = Hashtbl.find G.sources source.source_num in
+              { source with
                 source_files = s.source_files;
                 source_has_upload = s.source_has_upload;
                 source_availability = s.source_availability;
                 source_files_requested = s.source_files_requested;
-                source_upload_rate = Mi.source_upload_rate source_new s;
-                source_download_rate =Mi.source_download_rate source_new s;
+                source_upload_rate = Mi.source_upload_rate source s;
+                source_download_rate = Mi.source_download_rate source s;
               }
-            with _ -> source_new
+            with _ -> source
           in
           GuiDownloads.h_update_source s_new;
           GuiUploads.h_update_uploader s_new;
@@ -509,7 +468,7 @@
       let label = U.utf8_of (Printf.sprintf "%s:%d" hostname port) in
       GMenu.menu_item ~label
       ~packing:menu#add ()
-      in
+    in
     ignore (menu_item#connect#activate ~callback:(fun _ ->
           O.gtk_client_hostname =:= hostname;
           O.gtk_client_port =:= port;
@@ -553,13 +512,16 @@
           ~packing:menu#add ()
       in
       let reconnect_to_menu = GMenu.menu ~packing:(reconnect_to#set_submenu) () in
-      generate_connect_menu gui reconnect_to_menu;
+      ignore (reconnect_to#connect#activate ~callback:
+        (fun _ ->
+           generate_connect_menu gui reconnect_to_menu
+      ));
       ignore (GMenu.separator_item ~packing:menu#add ());
       ignore (reconnect#connect#activate 
         (fun _ -> GuiCom.reconnect gui value_reader gui BasicSocket.Closed_by_user
       ));
-      ignore (disconnect#connect#activate 
-        (fun _ -> GuiCom.disconnect gui BasicSocket.Closed_by_user
+      ignore (disconnect#connect#activate
+        (fun _ -> (try GuiCom.disconnect gui BasicSocket.Closed_by_user with _ -> ())
       ));
       ignore (scanports#connect#activate
         (fun _ -> GuiCom.scan_ports ()
@@ -593,7 +555,7 @@
     (fun _ -> GuiWindow.display_im gui ()
   ));
   ignore (settings#connect#activate 
-    (fun _ -> GuiWindow.display_settings gui ()
+    (fun _ -> GuiWindow.display_settings gui value_reader ()
   ));
   ignore (quit#connect#activate 
     (fun _ -> on_quit ()
@@ -648,7 +610,7 @@
         (fun _ -> GuiCom.reconnect gui value_reader gui BasicSocket.Closed_by_user
       ));
       ignore (disconnect#connect#activate 
-        (fun _ -> GuiCom.disconnect gui BasicSocket.Closed_by_user
+        (fun _ -> (try GuiCom.disconnect gui BasicSocket.Closed_by_user with _ -> ())
       ));
       ignore (scanports#connect#activate
         (fun _ -> GuiCom.scan_ports ()
@@ -676,7 +638,7 @@
     (fun _ -> GuiWindow.display_im gui ()
   ));
   ignore (settings#connect#activate 
-    (fun _ -> GuiWindow.display_settings gui ()
+    (fun _ -> GuiWindow.display_settings gui value_reader ()
   ));
   ignore (quit#connect#activate 
     (fun _ -> on_quit ()
@@ -844,7 +806,7 @@
        if Autoconf.system = "windows"
          then begin
            w#misc#hide ();
-           let icon = A.get_icon ~icon:M.icon_type_source_normal ~size:A.SMALL () in
+           let icon = A.get_icon ~icon:M.icon_type_source_normal ~size:A.LARGE () in
            G.tray.create_tray icon "MLDonkey";
            true
          end else begin
@@ -908,8 +870,8 @@
 
   (* connection with core *)
 
-  GuiCom.reconnect gui value_reader gui BasicSocket.Closed_by_user ;
-
+  GuiCom.reconnect gui value_reader gui BasicSocket.Closed_by_user
+(*
   let never_connected = ref true in
   BasicSocket.add_timer 1.0 (fun timer ->
       if !never_connected && not (GuiCom.connected ()) then  begin
@@ -918,6 +880,7 @@
         end else
         never_connected := false
   )
+*)
 
 let _ = 
   CommonGlobals.gui_included := true;
diff -urN -x cvs src/gtk2/gui/guiMisc.ml src/gtk2/gui/guiMisc.ml
--- src/gtk2/gui/guiMisc.ml	Thu Mar  3 03:45:11 2005
+++ src/gtk2/gui/guiMisc.ml	Mon Mar 28 13:44:59 2005
@@ -729,20 +729,20 @@
     else ""
 
 let source_upload_rate s_new s =
-  if (s_new.source_connect_time - s.source_connect_time) <= 0 ||
+  if (s_new.source_last_seen -. s.source_last_seen) <= 0. ||
       Int64.to_int s_new.source_uploaded = 0
   then 0.
   else max 0.
     ((Int64.to_float s_new.source_uploaded -. Int64.to_float s.source_uploaded) /.
-     (float_of_int s_new.source_connect_time -. float_of_int s.source_connect_time))
+     (s_new.source_last_seen -. s.source_last_seen))
 
 let source_download_rate s_new s =
-  if (s_new.source_connect_time - s.source_connect_time) <= 0 ||
+  if (s_new.source_last_seen -. s.source_last_seen) <= 0. ||
       Int64.to_int s_new.source_downloaded = 0
   then 0.
   else max 0.
     ((Int64.to_float s_new.source_downloaded -. Int64.to_float s.source_downloaded) /.
-     (float_of_int s_new.source_connect_time -. float_of_int s.source_connect_time))
+     (s_new.source_last_seen -. s.source_last_seen))
 
 (*************************************************************************)
 (*                                                                       *)
@@ -1231,7 +1231,8 @@
      source_files = None;
      source_rating = c.client_rating;
      source_chat_port = c.client_chat_port;
-     source_connect_time = c.client_connect_time;
+     source_connect_time = BasicSocket.last_time () - c.client_connect_time;
+     source_last_seen = BasicSocket.current_time ();
      source_software = concat_strings c.client_software c.client_emulemod;
      source_downloaded = c.client_downloaded;
      source_uploaded = c.client_uploaded;
@@ -1244,3 +1245,14 @@
     }
   in
   s
+
+(*************************************************************************)
+(*                                                                       *)
+(*                        uid_list_to_string                             *)
+(*                                                                       *)
+(*************************************************************************)
+
+let uid_list_to_string l =
+  match l with
+      [] -> ""
+    | uid :: _ -> U.simple_utf8_of (Uid.to_string uid)
diff -urN -x cvs src/gtk2/gui/guiOptions.ml src/gtk2/gui/guiOptions.ml
--- src/gtk2/gui/guiOptions.ml	Thu Mar  3 03:45:11 2005
+++ src/gtk2/gui/guiOptions.ml	Sat Mar 26 17:33:24 2005
@@ -548,7 +548,7 @@
    (C.Col_shared_size     , 0.1);
    (C.Col_shared_requests , 0.1);
    (C.Col_shared_upsize   , 0.1);
-   (C.Col_shared_md4      , 0.1);
+   (C.Col_shared_uid      , 0.1);
   ] 
 
 let account_columns = define_option current_section
diff -urN -x cvs src/gtk2/gui/guiResults.ml src/gtk2/gui/guiResults.ml
--- src/gtk2/gui/guiResults.ml	Thu Mar  3 03:45:11 2005
+++ src/gtk2/gui/guiResults.ml	Sat Mar 26 17:31:36 2005
@@ -390,7 +390,7 @@
          res_network_pixb = Mi.network_pixb net_num ~size:A.SMALL ();
          res_name = name;
          res_name_pixb = Mi.file_type_of_name name ~size:A.SMALL;
-         res_uid = U.simple_utf8_of (Uid.to_string (List.hd r.result_uids));
+         res_uid = Mi.uid_list_to_string r.result_uids;
          res_size = r.result_size;
          res_format = U.simple_utf8_of r.result_format;
          res_type = U.simple_utf8_of r.result_type;
diff -urN -x cvs src/gtk2/gui/guiTools.ml src/gtk2/gui/guiTools.ml
--- src/gtk2/gui/guiTools.ml	Thu Mar  3 03:45:12 2005
+++ src/gtk2/gui/guiTools.ml	Sat Mar 26 18:25:42 2005
@@ -384,13 +384,14 @@
 *)
 
 let create_bold_markup s =
-  let str = U.utf8_of s in
+  let str = Glib.Markup.escape_text (U.utf8_of s) in
   Printf.sprintf "<span foreground=\"%s\" weight=\"bold\">%s</span>" 
     "#0000FF" str
 
-let create_default_bold_markup s = 
+let create_default_bold_markup s =
+  let str = Glib.Markup.escape_text (U.utf8_of s) in
   Printf.sprintf "<span foreground=\"%s\" weight=\"bold\">%s</span>" 
-      !!O.gtk_color_default s
+      !!O.gtk_color_default str
 
 (* **
    [create_markup s] returns a string which is
diff -urN -x cvs src/gtk2/gui/guiTypes2.ml src/gtk2/gui/guiTypes2.ml
--- src/gtk2/gui/guiTypes2.ml	Thu Mar  3 03:45:12 2005
+++ src/gtk2/gui/guiTypes2.ml	Mon Mar 28 13:36:11 2005
@@ -195,6 +195,7 @@
     mutable source_rating : int;
     mutable source_chat_port : int;
     mutable source_connect_time : int;
+    mutable source_last_seen : float;
     mutable source_software : string;
     mutable source_downloaded : int64;
     mutable source_uploaded : int64;
diff -urN -x cvs src/gtk2/gui/guiUploads.ml src/gtk2/gui/guiUploads.ml
--- src/gtk2/gui/guiUploads.ml	Thu Mar  3 03:45:12 2005
+++ src/gtk2/gui/guiUploads.ml	Sat Mar 26 18:04:51 2005
@@ -86,7 +86,7 @@
   let shared_size_str     = shared_cols#add Gobject.Data.string in
   let shared_uploaded_str = shared_cols#add Gobject.Data.string in
   let shared_requests     = shared_cols#add Gobject.Data.int in
-  let shared_md4          = shared_cols#add Gobject.Data.string in
+  let shared_uid          = shared_cols#add Gobject.Data.string in
   object (self)
 
     inherit Uploads.g_list shared_cols
@@ -105,7 +105,7 @@
       store#set ~row ~column:shared_size_str (Mi.size_of_int64 si.shared_size);
       store#set ~row ~column:shared_uploaded_str (Mi.size_of_int64 si.shared_uploaded);
       store#set ~row ~column:shared_requests si.shared_requests;
-      store#set ~row ~column:shared_md4 (U.utf8_of (Md4.to_string si.shared_id))
+      store#set ~row ~column:shared_uid (Mi.uid_list_to_string si.shared_uids)
 
 (*************************************************************************)
 (*                                                                       *)
@@ -134,9 +134,9 @@
         then begin
           store#set ~row ~column:shared_requests si_new.shared_requests;
         end;
-      if si.shared_id <> si_new.shared_id
+      if si.shared_uids <> si_new.shared_uids
         then begin
-          store#set ~row ~column:shared_md4 (U.utf8_of (Md4.to_string si_new.shared_id))
+          store#set ~row ~column:shared_uid (Mi.uid_list_to_string si_new.shared_uids)
         end
 
 (*************************************************************************)
@@ -196,11 +196,11 @@
               col#add_attribute renderer "text" shared_size_str
             end
 
-        | Col_shared_md4 ->
+        | Col_shared_uid ->
             begin
               let renderer = GTree.cell_renderer_text [`XALIGN 0.] in
               col#pack renderer;
-              col#add_attribute renderer "text" shared_md4
+              col#add_attribute renderer "text" shared_uid
             end
 
         | Col_shared_network ->
@@ -230,7 +230,7 @@
         | Col_shared_upsize -> compare si1.shared_uploaded si2.shared_uploaded
         | Col_shared_requests -> compare si1.shared_requests si2.shared_requests
         | Col_shared_size -> compare si1.shared_size si2.shared_size
-        | Col_shared_md4 -> compare si1.shared_id si2.shared_id
+        | Col_shared_uid -> compare (Mi.uid_list_to_string si1.shared_uids) (Mi.uid_list_to_string si2.shared_uids)
 
 (*************************************************************************)
 (*                                                                       *)
@@ -601,12 +601,21 @@
 let copy_ed2k_links sel () = 
   let buf = Buffer.create 100 in
   List.iter (fun s ->
-    let link = Printf.sprintf "ed2k://|file|%s|%Ld|%s|" 
-                (Filename.basename s.shared_filename)
-                 s.shared_size
-                (Md4.to_string s.shared_id)
-    in
-    Printf.bprintf buf "%s\n" link;
+    match s.shared_uids with
+        uid :: _ -> (
+          match (Uid.to_uid uid) with
+              Ed2k md4 ->
+                begin
+                  let link = Printf.sprintf "ed2k://|file|%s|%Ld|%s|" 
+                             (Filename.basename s.shared_filename)
+                             s.shared_size
+                             (Md4.to_string md4)
+                  in
+                  Printf.bprintf buf "%s\n" link;
+                end
+            | _ -> ())
+
+      | _ -> ()
   ) sel;
   let link = Buffer.contents buf in
   GuiConsole.insert link;
diff -urN -x cvs src/gtk2/gui/guiWindow.ml src/gtk2/gui/guiWindow.ml
--- src/gtk2/gui/guiWindow.ml	Thu Mar  3 03:45:12 2005
+++ src/gtk2/gui/guiWindow.ml	Fri Mar 25 19:11:29 2005
@@ -165,8 +165,8 @@
 (*                                                                       *)
 (*************************************************************************)
 
-let rec display_settings gui =
-  GuiConfig.config_window gui fill_tool_bar
+let rec display_settings gui value_reader =
+  GuiConfig.config_window gui value_reader fill_tool_bar
 
 and fill_tool_bar gui =
   let bNetworks = gui.wtool#add_toggle_button
diff -urN -x cvs src/networks/bittorrent/bTClients.ml src/networks/bittorrent/bTClients.ml
--- src/networks/bittorrent/bTClients.ml	Sun Mar 20 09:41:29 2005
+++ src/networks/bittorrent/bTClients.ml	Mon Mar 28 12:16:26 2005
@@ -949,6 +949,14 @@
                   | _ -> ());
                 c.client_upload_requests <- 
                   c.client_upload_requests @ [n,pos,len];
+                let file = c.client_file in
+                match file.file_shared with
+                    None -> ()
+                  | Some s ->
+                      begin
+                        s.impl_shared_requests <- s.impl_shared_requests + 1;
+                        shared_must_update (as_shared s)
+                      end
               end
             else
               begin
@@ -1340,6 +1348,15 @@
 (*update uploade rate from len bytes*)
           Rate.update c.client_upload_rate  (float_of_int len);
           file.file_uploaded <- file.file_uploaded ++ (Int64.of_int len);
+          let _ =
+            match file.file_shared with
+                None -> ()
+              | Some s ->
+                  begin
+                    s.impl_shared_uploaded <- file.file_uploaded;
+                    shared_must_update (as_shared s)
+                  end
+          in
 (*          lprintf "sending piece\n"; *)
           send_client c (Piece (num, pos, upload_buffer, 0, len));
           iter_upload sock c
diff -urN -x cvs src/networks/bittorrent/bTGlobals.ml src/networks/bittorrent/bTGlobals.ml
--- src/networks/bittorrent/bTGlobals.ml	Sun Mar 20 09:41:29 2005
+++ src/networks/bittorrent/bTGlobals.ml	Mon Mar 28 12:12:42 2005
@@ -85,6 +85,9 @@
 
 let connection_manager = network.network_connection_manager
 
+let (shared_ops : file CommonShared.shared_ops) = 
+  CommonShared.new_shared_ops network
+
 let (server_ops : server CommonServer.server_ops) = 
   CommonServer.new_server_ops network
 
@@ -199,6 +202,7 @@
           file_uploaded = Int64.zero;
           file_torrent_diskname = torrent_diskname;
           file_completed_hook = (fun _ -> ());
+          file_shared = None;
         } and file_impl =  {
           dummy_file_impl with
           impl_file_fd = file_fd;
diff -urN -x cvs src/networks/bittorrent/bTInteractive.ml src/networks/bittorrent/bTInteractive.ml
--- src/networks/bittorrent/bTInteractive.ml	Sun Mar 20 09:41:29 2005
+++ src/networks/bittorrent/bTInteractive.ml	Mon Mar 28 12:18:56 2005
@@ -34,6 +34,7 @@
 open CommonComplexOptions
 open CommonFile
 open CommonDownloads
+open CommonShared
 open CommonInteractive
 open Autoconf
   
@@ -284,7 +285,7 @@
     P.file_age = file_age file;
     P.file_last_seen = BasicSocket.last_time ();
     P.file_priority = file_priority (as_file file);
-    P.file_uids = [];
+    P.file_uids = [Uid.create (BTUrl file.file_id)];
   }    
 
 let op_ft_info ft =
@@ -335,6 +336,7 @@
         torrent_diskname;
   let file = new_download file_id torrent torrent_diskname in
   BTClients.get_sources_from_tracker file;
+  BTShare.must_share_file file;
   file
 
 let load_torrent_file filename =
@@ -402,6 +404,7 @@
     
     let file = new_file file_id torrent torrent_diskname 
         filename FileShared in
+    BTShare.must_share_file file;
     if !verbose_share then lprintf "Sharing file %s\n" filename;
     BTClients.connect_trackers file "started" 
       (parse_tracker_reply file)
@@ -737,3 +740,18 @@
   client_ops.op_client_dprint_html <- op_client_dprint_html;
   
   CommonNetwork.register_commands commands;
+
+  shared_ops.op_shared_unshare <- (fun file ->
+      (if !verbose_share then lprintf "************ UNSHARE FILE ************\n");
+      BTShare.unshare_file file);
+  shared_ops.op_shared_info <- (fun file ->
+   let module T = GuiTypes in
+     match file.file_shared with
+        None -> assert false
+      | Some impl ->
+          { (impl_shared_info impl) with 
+            T.shared_network = network.network_num;
+            T.shared_filename = file_best_name (as_file file);
+            T.shared_uids = [Uid.create (Sha1 file.file_id)];
+            }
+  )
diff -urN -x cvs src/networks/bittorrent/bTShare.ml src/networks/bittorrent/bTShare.ml
--- src/networks/bittorrent/bTShare.ml	Thu Jan  1 08:00:00 1970
+++ src/networks/bittorrent/bTShare.ml	Mon Mar 28 12:05:40 2005
@@ -0,0 +1,66 @@
+(* 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 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;
+        } 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
diff -urN -x cvs src/networks/bittorrent/bTTypes.ml src/networks/bittorrent/bTTypes.ml
--- src/networks/bittorrent/bTTypes.ml	Sun Mar 20 09:41:29 2005
+++ src/networks/bittorrent/bTTypes.ml	Mon Mar 28 09:05:44 2005
@@ -98,6 +98,7 @@
     mutable file_trackers : tracker_info list;
     mutable file_tracker_connected : bool;
     mutable file_completed_hook : (file -> unit);
+    mutable file_shared : file CommonShared.shared_impl option;
   }
 
 and ft = {
diff -urN -x cvs src/networks/donkey/donkeyInteractive.ml src/networks/donkey/donkeyInteractive.ml
--- src/networks/donkey/donkeyInteractive.ml	Sun Mar 20 09:41:30 2005
+++ src/networks/donkey/donkeyInteractive.ml	Sat Mar 26 17:46:53 2005
@@ -918,7 +918,7 @@
             P.file_chunks_age = last_seen;
             P.file_age = file_age file;
             P.file_last_seen = file.file_file.impl_file_last_seen;
-            P.file_uids = [];
+            P.file_uids = [Uid.create (Ed2k file.file_md4)];
           } in
         v
       with e ->
@@ -1523,7 +1523,7 @@
           { (impl_shared_info impl) with 
             T.shared_network = network.network_num;
             T.shared_filename = file_best_name file;
-            T.shared_id = file.file_md4;
+            T.shared_uids = [Uid.create (Ed2k file.file_md4)];
             }
   );
   pre_shared_ops.op_shared_info <- (fun s ->
diff -urN -x cvs src/networks/fileTP/fileTPInteractive.ml src/networks/fileTP/fileTPInteractive.ml
--- src/networks/fileTP/fileTPInteractive.ml	Sun Mar 20 09:41:30 2005
+++ src/networks/fileTP/fileTPInteractive.ml	Sat Mar 26 18:02:27 2005
@@ -99,7 +99,7 @@
         P.file_age = file_age file;
         P.file_last_seen = BasicSocket.last_time ();
         P.file_priority = file_priority (as_file file);
-        P.file_uids = [];
+        P.file_uids = [Uid.create (Ftp file.file_id)];
       }    
   )
 
diff -urN -x cvs src/networks/gnutella/gnutellaInteractive.ml src/networks/gnutella/gnutellaInteractive.ml
--- src/networks/gnutella/gnutellaInteractive.ml	Sun Mar 20 09:41:30 2005
+++ src/networks/gnutella/gnutellaInteractive.ml	Mon Mar 28 12:20:52 2005
@@ -306,7 +306,7 @@
         P.file_age = file_age file;
         P.file_last_seen = BasicSocket.last_time ();
         P.file_priority = file_priority (as_file file);
-        P.file_uids = [];
+        P.file_uids = file.file_uids;
       }    
   )
   
@@ -411,12 +411,15 @@
         P.client_state = client_state (as_client c);
         P.client_type = client_type c;
         P.client_tags = [];
-        P.client_name = (match c.client_user.user_kind with
+        P.client_name = c.client_user.user_nick;
+(*
+          (match c.client_user.user_kind with
           | Known_location (ip, port) ->
               Printf.sprintf "%s:%d" (Ip.to_string ip) port
           | Indirect_location (_, id) -> 
               Printf.sprintf "UID[%s...]" (String.sub (Md4.to_string id) 0 12)
         );
+*)
         P.client_files = None;
         P.client_num = (client_num (as_client c));
         P.client_rating = 0;
