1 (* Copyright 2001, 2002 b8_bavard, b8_fee_carabine, INRIA *)
3 This file is part of mldonkey.
5 mldonkey is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 mldonkey is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with mldonkey; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 open CommonInteractive
31 open CommonComplexOptions
51 let log_prefix = "[dcInt]"
54 lprintf_nl2
log_prefix fmt
56 (* Start new dowload from result *)
57 let start_new_download u tth fdir fname fsize
=
59 ignore
(Hashtbl.find dc_shared_files_by_hash tth
);
60 if !verbose_download
then lprintf_nl "Shared file with same hash exists (%s) (%s)" fname tth
;
63 let f = new_file tth fdir fname fsize
in (* ...create new file *)
64 (match (file_state
f) with
65 | FileDownloaded
| FileShared
-> if !verbose_download
then lprintf_nl "File already downloaded"; None
66 | FileDownloading
-> if !verbose_download
then lprintf_nl "File being downloaded"; None
67 | FilePaused
-> if !verbose_download
then lprintf_nl "File paused"; None
68 | FileAborted _
| FileCancelled
| FileQueued
->
69 if !verbose_download
then lprintf_nl "File state invalid"; None
71 file_add
f.file_file FileDownloading
;
72 let c = new_client_to_user_with_file u
f in
73 c.client_state
<- DcDownloadWaiting
f;
74 if (can_user_start_downloading u
) then begin
75 u
.user_state
<- TryingToSendFirstContact
;
76 c.client_state
<- DcDownloadConnecting
(f,current_time
());
77 ignore
(DcClients.try_connect_client
c)
81 (* Start downloading of a file by user selection from resultlist *)
82 let start_result_download r
=
83 let filename = List.hd r
.result_names
in
84 let rinfo = Hashtbl.find dc_result_info r
.result_num
in
85 let newfile = start_new_download rinfo.user
rinfo.tth
rinfo.directory
filename r
.result_size
in
87 | Some
f -> as_file
f.file_file
(* return CommonFile.file *)
88 | _
-> raise Not_found
)
90 (* register DC commands *)
91 let register_commands list
=
92 register_commands (List2.tail_map
(fun (n
,f,h
) -> (n
, "Direct Connect", f,h
)) list
)
94 (* Print DC hubs header *)
95 let dc_hublist_print_html_header buf ext
=
96 html_mods_table_header buf
"serversTable" (Printf.sprintf
"servers%s" ext
) [
97 ( "1", "srh", "Hub number", "#" ) ;
98 ( "0", "srh", "Add hub to servers", "Add" ) ;
99 ( "0", "srh", "Hub name", "Hub name" ) ;
100 ( "0", "srh", "IP address", "IP address" ) ;
101 ( "1", "srh", "Users in hub", "Users" ) ;
102 ( "0", "srh", "Hub info", "Info" ) ]
104 (* print in html or txt list of hubs *)
105 let hublist_print h hnum o
=
106 let buf = o
.conn_buf
in
107 let hname = if (String.length h
.dc_name
> 50) then String.sub h
.dc_name
0 49
109 let hinfo = if (String.length h
.dc_info
> 50) then String.sub h
.dc_info
0 49
111 if use_html_mods o
then begin
113 \\<tr class=\\\"dl-%d\\\"\\>
114 \\<td class=\\\"srb\\\" \\>%d\\</td\\>
116 \\<td class=\\\"sr\\\"\\>%s\\</td\\>
117 \\<td class=\\\"sr\\\"\\>%s:%d\\</td\\>
118 \\<td class=\\\"sr\\\"\\>%d\\</td\\>
119 \\<td width=\\\"100%%\\\" class=\\\"sr\\\"\\>%s\\</td\\>\\</tr\\>\n"
123 "\\<td class=\\\"srb\\\" onMouseOver=\\\"mOvr(this);\\\"
124 onMouseOut=\\\"mOut(this);\\\" title=\\\"Add\\\"
125 onClick=\\\"parent.fstatus.location.href='submit?q=dcn+%s+%d'\\\"\\>Add\\</td\\>"
126 (Ip.string_of_addr h
.dc_ip
) h
.dc_port
)
128 (Ip.string_of_addr h
.dc_ip
) h
.dc_port
131 Printf.bprintf
buf "[%5d] %20s %25s:%-10d Users:%-8d %20s\n"
134 (Ip.string_of_addr h
.dc_ip
) h
.dc_port
139 (* Print DC users header *)
140 let dc_user_print_html_header buf =
141 html_mods_table_header
buf "serversTable" "servers" [
142 ( "1", "srh", "User number", "#" );
143 ( "1", "srh", "User name", "Name" );
144 ( "1", "srh", "User type", "Type" );
145 ( "1", "srh", "Users slots (all/free)", "Slots" );
146 ( "1", "srh", "Users connected hubs (Normal/Vipped/Opped)", "Hubs" );
147 ( "1", "srh", "Users mode", "Mode" );
148 ( "1", "srh", "Users shared size", "Shared" );
149 ( "1", "srh", "User state", "State" );
150 ( "1", "srh", "User description field", "Description" );
151 ( "1", "srh", "User clients number", "Clients" );
152 ( "1", "srh", "Users servers number", "Servers" );
153 ( "0", "srh", "Download this clients filelist", "Filelist" );
154 ( "0", "srh", "Open chat window with this user. Blinking tells there are new unread messages", "Chat");
155 ( "1", "srh", "User total uploaded bytes", "Up" );
156 ( "1", "srh", "User total downloaded bytes", "Down" );
157 ( "1", "srh", "User client supports", "Supports" ); ];
160 (* print in html or txt list of users *)
161 let user_print user num o
=
162 let buf = o
.conn_buf
in
164 (match user
.user_type
with
171 (match user
.user_state
with
172 | UserIdle
-> "NotDefined"
173 | TryingToSendFirstContact
-> "TryingToSendFirstContact"
174 | UserActiveMeInitiating
-> "UserActiveMeInitiating"
175 | UserActiveUserInitiating
-> "UserActiveUserInitiating"
176 | UserPassiveUserInitiating _
-> "UserPassiveUserInitiating" )
178 let clients = List.length user
.user_clients
in
179 let servers = List.length user
.user_servers
in
180 let messages = user_has_new_messages user
in
181 let hasmynick = has_my_nick user
in
183 let a,b
,c = user
.user_myinfo
.hubs in
184 Printf.sprintf
"(%d/%d/%d)" a b
c
187 if (List.length user
.user_clients
> 0) then begin
188 let c = List.hd user
.user_clients
in
189 (match c.client_supports
with
191 DcProtocol.Supports.create_supports_string
(ClientSupports
supports)
192 | _
-> empty_string
)
193 end else empty_string
195 if use_html_mods o
then begin
197 \\<tr class=\\\"dl-%d\\\"\\>
198 \\<td class=\\\"srb\\\" \\>%d\\</td\\>
199 \\<td class=\\\"sr\\\"\\>%s\\</td\\>
200 \\<td class=\\\"sr\\\"\\>%s\\</td\\>
201 \\<td class=\\\"sr\\\"\\>%d\\</td\\>
202 \\<td class=\\\"sr\\\"\\>%s\\</td\\>
203 \\<td class=\\\"sr\\\"\\>%c\\</td\\>
204 \\<td class=\\\"sr\\\"\\>%s\\</td\\>
205 \\<td class=\\\"sr\\\"\\>%s\\</td\\>
206 \\<td class=\\\"sr\\\"\\>%s\\</td\\>
207 \\<td class=\\\"sr\\\"\\>%d\\</td\\>
208 \\<td class=\\\"sr\\\"\\>%d\\</td\\>
210 \\<td class=\\\"sr\\\"\\>%s\\</td\\>
211 \\<td class=\\\"sr\\\"\\>%s\\</td\\>
212 \\<td class=\\\"sr\\\"\\>%s\\</td\\>\\</tr\\>\n"
213 (html_mods_cntr
()) num user
.user_nick
utype user
.user_myinfo
.slots
hubs user
.user_myinfo
.mode
214 (size_of_int64 user
.user_myinfo
.sharesize
) state user
.user_myinfo
.description
clients servers
215 (if not
hasmynick && (servers > 0) then (* is connected to any servers with us *)
216 (Printf.sprintf
"\\<td class=\\\"srb\\\" onMouseOver=\\\"mOvr(this);\\\"
217 onMouseOut=\\\"mOut(this);\\\" title=\\\"Download user filelist\\\"
218 onClick=\\\"parent.fstatus.location.href='submit?q=dcloadfilelist+%s'\\\"\\>Get List\\</td\\>"
222 if hasmynick then "Me"
225 Printf.sprintf
"\\<td class=\\\"sr\\\"\\>%s\\</td\\>" txt
227 (if not
hasmynick then (* not me *)
228 (Printf.sprintf
"\\<td class=\\\"srb\\\" %sonMouseOver=\\\"mOvr(this);\\\"
229 onMouseOut=\\\"mOut(this);\\\" title=\\\"Open message window to this user\\\"
230 onClick=\\\"parent.output.location.href='submit?q=dcmessages+%s'\\\"\\>Open chat\\</td\\>"
231 (if messages then "style=\\\"text-decoration:blink\\\" " else "") user
.user_nick
)
232 else "\\<td class=\\\"sr\\\"\\>\\</td\\>" )
233 (size_of_int64 user
.user_uploaded
) (size_of_int64 user
.user_downloaded
) supports
235 Printf.bprintf
buf "[%5d] %-20s %8s %20s\n" num user
.user_nick
utype state
237 (* Print DC hubs header *)
238 let dc_hub_print_html_header buf =
239 html_mods_table_header
buf "serversTable" "servers" [
240 ( "1", "srh", "Hub number", "#" ) ;
241 ( "0", "srh", "Set/UnSet server autoconnection state", "Auto" ) ;
242 ( "0", "srh", "Hub name", "Hub name" ) ;
243 ( "0", "srh", "IP address", "IP address" ) ;
244 ( "0", "srh", "My state in this hub", "State" ) ;
245 ( "1", "srh", "Users in hub", "Users" ) ;
246 ( "0", "srh", "Hub info", "Info" );
247 ( "0", "srh", "Open chat window with this hub. Blinking tells there are new unread message", "Chat" ) ]
249 (* Print list of connected hubs *)
250 let hub_print s num o
=
251 let buf = o
.conn_buf
in
252 let sinfo = shorten_string s
.server_info
50 in
253 let sname = shorten_string s
.server_name
50 in
254 let sip = Ip.to_string s
.server_ip
in
255 let sport = s
.server_port
in
256 let susers = List.length s
.server_users
in
257 let smessages = ((List.length s
.server_messages
) > s
.server_read_messages
) in
258 let sstate = dc_hubstate_to_text s
in
259 if use_html_mods o
then begin
261 \\<tr class=\\\"dl-%d\\\"\\>
262 \\<td class=\\\"srb\\\" \\>%d\\</td\\>
264 \\<td class=\\\"sr\\\"\\>%s\\</td\\>
265 \\<td class=\\\"sr\\\"\\>%s:%d\\</td\\>
266 \\<td class=\\\"sr\\\"\\>%s\\</td\\>
268 \\<td class=\\\"sr\\\"\\>%s\\</td\\>
273 "\\<td class=\\\"srb\\\" onMouseOver=\\\"mOvr(this);\\\"
274 onMouseOut=\\\"mOut(this);\\\" title=\\\"Set this server/hub autoconnection state\\\"
275 onClick=\\\"parent.output.location.href='submit?q=dcautoconnect+%s+%s'\\\"\\>%s\\</td\\>"
276 (if s
.server_autoconnect
then "false" else "true") sip (if s
.server_autoconnect
then "UnSet" else "Set") )
277 sname sip sport sstate
279 "\\<td class=\\\"srb\\\" onMouseOver=\\\"mOvr(this);\\\"
280 onMouseOut=\\\"mOut(this);\\\" title=\\\"Click to show users for this hub only\\\"
281 onClick=\\\"parent.output.location.href='submit?q=dcusers+%s'\\\"\\>%d\\</td\\>"
285 "\\<td class=\\\"srb\\\" %sonMouseOver=\\\"mOvr(this);\\\"
286 onMouseOut=\\\"mOut(this);\\\" title=\\\"Open this hubs chat windows\\\"
287 onClick=\\\"parent.output.location.href='submit?q=dcmessages+%s+%d'\\\"\\>Open chat\\</td\\>"
288 (if smessages then "style=\\\"text-decoration:blink\\\" " else "") sip sport)
290 Printf.bprintf
buf "[%5d] %20s %25s:%-10d Users:%-8d %20s\n"
298 (* Print DC clients header *)
299 let dc_client_print_html_header buf =
300 html_mods_table_header
buf "serversTable" "servers" [
301 ( "1", "srh", "Client number", "#" );
302 ( "1", "srh", "Remove Client", "Rem" );
303 ( "1", "srh", "Clientname", "Name" );
304 ( "1", "srh", "Client ip/port", "Ip:Port" );
305 ( "1", "srh", "Client state", "State" );
306 ( "1", "srh", "Client connection", "Conn" );
307 ( "1", "srh", "Client last error/count", "Error" );
308 ( "1", "srh", "Client file", "File" ); ];
311 (* print in html or txt list of clients *)
312 let client_print name client num o
=
313 let buf = o
.conn_buf
in
315 (match client
.client_addr
with
316 | Some
(ip,port
) -> Ip.to_string
ip,port
320 (match client
.client_sock
with
321 | Connection _
-> "Connected"
322 | ConnectionWaiting _
-> "Connecting..."
323 | NoConnection
-> "NoConnection" )
325 let state = client_state_to_string client
in
327 (match client
.client_error
with
328 | NoError
-> empty_string
329 | NoFreeSlots
-> Printf.sprintf
"NoFreeSlots %d" client
.client_error_count
330 | FileNotAvailable
-> Printf.sprintf
"FileNotAvailable %d" client
.client_error_count
331 | UserNotReachable
-> Printf.sprintf
"UserNotReachable %d" client
.client_error_count
332 | ClosedOnInit
-> Printf.sprintf
"ClosedOnInit %d" client
.client_error_count
333 | ConnectionResetByPeer
-> Printf.sprintf
"ConnectionResetByPeer %d" client
.client_error_count
334 | UploadError
-> Printf.sprintf
"UploadError %d" client
.client_error_count
335 | UserDontReplyOnTime
-> Printf.sprintf
"UserDontReplyOnTime %d" client
.client_error_count
)
338 (match client
.client_state
with
339 | DcDownloadWaiting file
340 | DcDownloadConnecting
(file
,_
)
341 | DcDownload file
-> file
.file_name
342 | DcUpload
(_
,fd_file
,_
,_
)
343 | DcUploadList fd_file
344 | DcDownloadList fd_file
-> Unix32.filename fd_file
345 | DcUploadListStarting
filename -> filename
346 | DcUploadStarting
(dcsh
,_
,_
) -> dcsh
.dc_shared_codedname
349 if use_html_mods o
then begin
351 \\<tr class=\\\"dl-%d\\\"\\>
352 \\<td class=\\\"sr\\\" \\>%d\\</td\\>
354 \\<td class=\\\"sr\\\"\\>%s\\</td\\>
355 \\<td class=\\\"sr\\\"\\>%s:%d\\</td\\>
356 \\<td class=\\\"sr\\\" \\>%s\\</td\\>
357 \\<td class=\\\"sr\\\" \\>%s\\</td\\>
358 \\<td class=\\\"sr\\\" \\>%s\\</td\\>
359 \\<td class=\\\"sr\\\" \\>%s\\</td\\>\\</tr\\>\n"
360 (html_mods_cntr
()) num
362 "\\<td class=\\\"srb\\\" onMouseOver=\\\"mOvr(this);\\\"
363 onMouseOut=\\\"mOut(this);\\\" title=\\\"Remove client\\\"
364 onClick=\\\"parent.fstatus.location.href='submit?q=dcremclient+%d'\\\"\\>Rem\\</td\\>"
365 (client_num
(as_client client
.client_client
)) )
366 name
ip port
state conn error fil
368 Printf.bprintf
buf "[%5d] %25s %25s:%-10d S:%15s C:%15s F:%15s\n"
369 num name
ip port
state conn fil
371 (* Print DC files header *)
372 let dc_file_print_html_header buf =
373 html_mods_table_header
buf "serversTable" "servers" [
374 ( "1", "srh", "File number", "#" );
375 ( "1", "srh", "File name/path", "File" );
376 ( "1", "srh", "File size", "Size" );
377 ( "1", "srh", "TTH Hash", "Hash" );
378 ( "1", "srh", "Files clients number (sources)", "Clients" );
379 ( "1", "srh", "Autosearches done", "Searches" );
380 ( "1", "srh", "Find new source by tth", "Find TTH" );
381 ( "1", "srh", "Find new source by similar name context", "Find similar" ); ];
384 (* print in html or txt list of files *)
385 let file_print file num o
=
386 let buf = o
.conn_buf
in
387 let fname = ref (String.copy file
.file_name
) in
388 String2.replace_char
!fname char32 char42
; (* to * *)
389 String2.replace_char
!fname char39 char58
; (* ' to : *)
390 String2.replace_char
!fname char60 char38
; (* & to < *)
391 if use_html_mods o
then begin
393 \\<tr class=\\\"dl-%d\\\"\\>
394 \\<td class=\\\"srb\\\" \\>%d\\</td\\>
395 \\<td class=\\\"sr\\\"\\>%s\\</td\\>
396 \\<td class=\\\"srb\\\" \\>%Ld\\</td\\>
397 \\<td class=\\\"srb\\\" \\>%s\\</td\\>
398 \\<td class=\\\"srb\\\" \\>%d\\</td\\>
399 \\<td class=\\\"srb\\\" \\>%d\\</td\\>
402 (html_mods_cntr
()) num file
.file_name file
.file_file
.impl_file_size
403 (file
.file_unchecked_tiger_root
) (List.length file
.file_clients
) file
.file_autosearch_count
405 "\\<td class=\\\"srb\\\" onMouseOver=\\\"mOvr(this);\\\"
406 onMouseOut=\\\"mOut(this);\\\" title=\\\"Find new client for this file by TTH\\\"
407 onClick=\\\"parent.output.location.href='submit?q=dcfindsource+%s'\\\"\\>Find TTH\\</td\\>"
408 file
.file_unchecked_tiger_root
)
410 "\\<td class=\\\"srb\\\" onMouseOver=\\\"mOvr(this);\\\"
411 onMouseOut=\\\"mOut(this);\\\" title=\\\"Find new client for this file by similar name\\\"
412 onClick=\\\"parent.output.location.href='submit?q=dcfindsource+%s'\\\"\\>Find similar\\</td\\>"
415 Printf.bprintf
buf "[%5d] %40s %-15Ld %5d\n"
416 num file
.file_name file
.file_file
.impl_file_size
(List.length file
.file_clients
)
418 (* Print DC shared files header *)
419 let dc_shared_print_html_header buf =
420 html_mods_table_header
buf "serversTable" "servers" [
421 ( "1", "srh", "File number", "#" );
422 ( "1", "srh", "Shared file codedname", "Codedname" );
423 ( "1", "srh", "Shared file size", "Size" );
424 ( "1", "srh", "TTH Hash", "Hash" );
425 (*( "1", "srh", "Shared files Tiger tree array length", "TTree #" );*) ];
429 (* print in html or txt list of shared files *)
430 let shared_print dcsh num o
=
431 let buf = o
.conn_buf
in
432 if use_html_mods o
then begin
434 \\<tr class=\\\"dl-%d\\\"\\>
435 \\<td class=\\\"srb\\\" \\>%d\\</td\\>
436 \\<td class=\\\"sr\\\"\\>%s\\</td\\>
437 \\<td class=\\\"srb\\\" \\>%Ld\\</td\\>
438 \\<td class=\\\"srb\\\" \\>%s\\</td\\>\\</tr\\>\n"
439 (html_mods_cntr
()) num dcsh
.dc_shared_codedname dcsh
.dc_shared_size
440 dcsh
.dc_shared_tiger_root
(*(Array.length dcsh.dc_shared_tiger_array)*)
442 Printf.bprintf
buf "[%5d] %40s %-15Ld %24s\n"
443 num dcsh
.dc_shared_codedname dcsh
.dc_shared_size dcsh
.dc_shared_tiger_root
444 (*(Array.length dcsh.dc_shared_tiger_array)*)
446 type dc_int_groups
= G_users
|G_hubs
|G_clients
|G_files
|G_shared
448 (* register users,clients,files *)
449 let dc_list o group_type group_name
=
450 let buf = o
.conn_buf
in
452 html_mods_cntr_init
();
453 if use_html_mods o
then begin
455 (match group_type
with
457 let new_messages_list = ref [] in (* lets order users with unread messages to the top *)
458 let others_list = ref [] in
459 Hashtbl.iter
(fun _ user
->
460 if user_has_new_messages user
then new_messages_list := user
:: !new_messages_list
461 else others_list := user
:: !others_list
463 dc_user_print_html_header buf;
464 List.iter
(fun user
-> user_print user
!num o
; incr
num) !new_messages_list;
465 List.iter
(fun user
-> user_print user
!num o
; incr
num) !others_list;
467 dc_hub_print_html_header buf;
468 Hashtbl.iter
(fun _ s
-> hub_print s
!num o
; incr
num) servers_by_ip
469 (*List.iter (fun s -> hub_print s !num o; incr num) !connected_servers*)
471 dc_client_print_html_header buf;
473 (match c.client_name
with
474 | Some n
-> client_print n
c !num o
; incr
num
478 dc_file_print_html_header buf;
479 List.iter
(fun file
-> file_print file
!num o
; incr
num) !current_files
;
481 dc_shared_print_html_header buf;
482 Hashtbl.iter
(fun _ dcsh
-> shared_print dcsh
!num o
; incr
num) dc_shared_files_by_codedname
;
483 Printf.bprintf
buf "\\</table\\>\\</div\\>";
485 dc_shared_print_html_header buf;
486 Hashtbl.iter
(fun _ dcsh
-> shared_print dcsh
!num o
; incr
num) dc_shared_files_by_hash
; )
487 with e
-> lprintf_nl "Exception %s in printing %s" (Printexc2.to_string e
) group_name
);
488 Printf.bprintf
buf "\\</table\\>\\</div\\>";
492 (* Print DC filelist header *)
493 let dc_filelist_print_html_header buf =
494 html_mods_table_header
buf "serversTable" "servers" [
495 ( "1", "srh", "Number", "#" ) ;
496 ( "0", "srh", "Filelist name", "Filelist" ) ]
498 (* Print one line from filelist *)
499 let filelist_print fname line o
=
500 let buf = o
.conn_buf
in
501 if use_html_mods o
then begin
503 \\<tr class=\\\"dl-%d\\\"\\>
504 \\<td class=\\\"srb\\\" \\>%d\\</td\\>
509 "\\<td class=\\\"srb\\\" onMouseOver=\\\"mOvr(this);\\\"
510 onMouseOut=\\\"mOut(this);\\\" title=\\\"Click to open filelist\\\"
511 onClick=\\\"parent.output.location.href='submit?q=dcshowfilelist+%s'\\\"\\>%s\\</td\\>\\</tr\\>\n"
514 Printf.bprintf
buf "[%5d] %s\n" line
fname
517 (* Print DC filelist files header *)
518 let dc_filelist_files_print_html_header buf =
519 html_mods_table_header
buf "serversTable" (Printf.sprintf
"servers") [
520 ( "1", "srh", "Number", "#" );
521 ( "0", "srh", "File/Firectory name", "File/Directory name" );
522 ( "0", "srh", "File Size", "Size" );
523 ( "0", "srh", "Files TTH", "TTH" ) ]
525 (* Print one line from filelist file *)
526 let filelist_file_print is_file spaces username dir
fname fsize ftth line o
=
527 (* is_file = if true, make the whole filename a link with submit command to load a file
529 username = username to submit in command
530 dir = current directory path to submit in command
531 fname = filename from mylist
532 fsize = filesize from mylist
533 ftth = tth from mylist *)
534 let buf = o
.conn_buf
in
535 let sdir = ref (String.copy dir
) in
536 let sname = ref (String.copy
fname) in
537 String2.replace_char
!sdir char32 char42
; (* to * *)
538 String2.replace_char
!sdir char39 char58
; (* ' to : *)
539 String2.replace_char
!sdir char38 char60
; (* & to < *)
540 String2.replace_char
!sdir char43 char62
; (* + to > *)
541 String2.replace_char
!sname char32 char42
;
542 String2.replace_char
!sname char39 char58
;
543 String2.replace_char
!sname char38 char60
;
544 String2.replace_char
!sname char43 char62
;
545 if use_html_mods o
then begin
547 \\<tr class=\\\"dl-%d\\\"\\>
548 \\<td class=\\\"srb\\\" \\>%d\\</td\\>
550 \\<td class=\\\"srb\\\" \\>%s\\</td\\>
551 \\<td class=\\\"srb\\\" \\>%s\\</td\\>\\</tr\\>\n"
556 "\\<td class=\\\"srb\\\" onMouseOver=\\\"mOvr(this);\\\"
557 onMouseOut=\\\"mOut(this);\\\" title=\\\"Click to start loading \\\"
558 onClick=\\\"parent.fstatus.location.href='submit?q=dcloadfile+%s+%s+%s+%s+%s'\\\"\\>%s%s\\</td\\>"
559 username ftth
!sdir !sname fsize spaces
fname )
561 (Printf.sprintf
"\\<td class=\\\"srb\\\" \\>\\<b\\>%s%s\\</b\\>\\</td\\>" spaces
fname)
566 Printf.bprintf
buf "%30s %10s %30s\n" fname fsize ftth
569 (* Print DC info header *)
570 let dc_info_html_header buf =
571 html_mods_table_header
buf "sharesTable" "shares" [
572 ( "0", "srh", "Direct Connect information", "DC Info" ) ;
573 ( "0", "srh", empty_string
, empty_string
) ]
576 let dc_info_print info data line o
=
577 let buf = o
.conn_buf
in
578 if use_html_mods o
then begin
580 \\<tr class=\\\"dl-%d\\\"\\>
581 \\<td class=\\\"sr\\\"\\>%s\\</td\\>
582 \\<td class=\\\"sr\\\"\\>%s\\</td\\>\\</tr\\>"
583 (html_mods_cntr
()) info data
585 Printf.bprintf
buf "%s: %s\n" info data
589 (* List of commands to register *)
592 "dc", Arg_none
(fun o
->
593 let buf = o
.conn_buf
in
594 if use_html_mods o
then begin
595 Printf.bprintf
buf "\\<table\\>\\<tr\\>\\<form style=\\\"margin: 0px;\\\" id=\\\"users\\\" name=\\\"users\\\"
596 action=\\\"javascript:parent.output.location.href='submit?q=dcusers+all'\\\"\\>
597 \\<td\\>\\<input style=\\\"font-family: verdana; font-size: 12px;\\\" type=submit
598 Value=\\\"Users\\\"\\>\\</td\\>\\</form\\>";
599 Printf.bprintf
buf "\\<form style=\\\"margin: 0px;\\\" id=\\\"clients\\\" name=\\\"clients\\\"
600 action=\\\"javascript:parent.output.location.href='submit?q=dcclients'\\\"\\>
601 \\<td\\>\\<input style=\\\"font-family: verdana; font-size: 12px;\\\" type=submit
602 Value=\\\"Clients\\\"\\>\\</td\\>\\</form\\>";
603 Printf.bprintf
buf "\\<form style=\\\"margin: 0px;\\\" id=\\\"hubs\\\" name=\\\"hubs\\\"
604 action=\\\"javascript:parent.output.location.href='submit?q=dchubs'\\\"\\>
605 \\<td\\>\\<input style=\\\"font-family: verdana; font-size: 12px;\\\" type=submit
606 Value=\\\"Hubs\\\"\\>\\</td\\>\\</form\\>";
607 Printf.bprintf
buf "\\<form style=\\\"margin: 0px;\\\" id=\\\"shared\\\" name=\\\"shared\\\"
608 action=\\\"javascript:parent.output.location.href='submit?q=dcshared'\\\"\\>
609 \\<td\\>\\<input style=\\\"font-family: verdana; font-size: 12px;\\\" type=submit
610 Value=\\\"Shared\\\"\\>\\</td\\>\\</form\\>";
611 Printf.bprintf
buf "\\<form style=\\\"margin: 0px;\\\" id=\\\"files\\\" name=\\\"files\\\"
612 action=\\\"javascript:parent.output.location.href='submit?q=dcfiles'\\\"\\>
613 \\<td\\>\\<input style=\\\"font-family: verdana; font-size: 12px;\\\" type=submit
614 Value=\\\"Files\\\"\\>\\</td\\>\\</form\\>";
615 Printf.bprintf
buf "\\<form style=\\\"margin: 0px;\\\" id=\\\"info\\\" name=\\\"info\\\"
616 action=\\\"javascript:parent.output.location.href='submit?q=dcinfo'\\\"\\>
617 \\<td\\>\\<input style=\\\"font-family: verdana; font-size: 12px;\\\" type=submit
618 Value=\\\"DC Info\\\"\\>\\</td\\>\\</form\\>";
619 Printf.bprintf
buf "\\<form style=\\\"margin: 0px;\\\" id=\\\"hublistshow\\\" name=\\\"hublistshow\\\"
620 action=\\\"javascript:parent.output.location.href='submit?q=dchublist'\\\"\\>
621 \\<td\\>\\<input style=\\\"font-family: verdana; font-size: 12px;\\\" type=submit
622 Value=\\\"Show hublist\\\"\\>\\</td\\>\\</form\\>";
623 Printf.bprintf
buf "\\<form style=\\\"margin: 0px;\\\" id=\\\"filelists\\\" name=\\\"filelists\\\"
624 action=\\\"javascript:parent.output.location.href='submit?q=dcfilelists'\\\"\\>
625 \\<td\\>\\<input style=\\\"font-family: verdana; font-size: 12px;\\\" type=submit
626 Value=\\\"Filelists\\\"\\>\\</td\\>\\</form\\>";
627 Printf.bprintf
buf "\\</tr\\>\\</table\\>";
629 Printf.bprintf
buf "Received command dc\n";
631 ), ": Show direct connect buttons";
633 (* 'dcn address [port]' Add a new DC server with optional port (default 411) *)
634 "dcn", Arg_multiple
(fun args o
->
637 | [ip ; port
] -> ip, port
639 | _
-> failwith
"dcn <ip> [<port>]: bad argument number" )
641 let ip_addr = Ip.addr_of_string
ip in
642 Ip.async_ip_of_addr
ip_addr (fun t
-> (* do DNS check here *)
643 let port = int_of_string
port in
644 if !verbose_msg_servers
then lprintf_nl "New server being added: (%s) (%s) (%d)" ip (Ip.to_string t
) port;
645 if (Ip.valid t
) && (port>0) && (port<65536) then
646 ignore
(new_server
ip_addr t
port) ) (fun _
-> ());
648 ), "<ip> [<port>] : Add a server. Default port number is 411";
650 (* List connected hubs for chatting *)
651 "dchubs", Arg_none
(fun o
-> dc_list o G_hubs
"hubs"
652 ), ": Show connected DC hubs";
654 (* List all DC users *)
655 "dcusers", Arg_one
(fun args o
->
656 let buf = o
.conn_buf
in
658 | "all" -> dc_list o G_users
"users"
661 let s = Hashtbl.find servers_by_ip
ip in
663 let new_messages_list = ref [] in (* lets order users with unread messages to the top *)
664 let others_list = ref [] in
665 List.iter
(fun user
->
666 if user_has_new_messages user
then new_messages_list := user
:: !new_messages_list
667 else others_list := user
:: !others_list
669 dc_user_print_html_header buf;
670 List.iter
(fun user
-> user_print user
!num o
; incr
num) !new_messages_list;
671 List.iter
(fun user
-> user_print user
!num o
; incr
num) !others_list;
673 with _
-> "dcusers <ip> : ip not valid" ) );
674 ), "<all>|<ip> :Show DC users";
676 (* List all DC clients *)
677 "dcclients", Arg_none
(fun o
-> dc_list o G_clients
"clients"
678 ), ": Show all DC clients";
680 (* List all DC files *)
681 "dcfiles", Arg_none
(fun o
-> dc_list o G_files
"files"
682 ), ": Show all DC files";
684 (* List all DC shared files *)
685 "dcshared", Arg_none
(fun o
-> dc_list o G_shared
"shared"
686 ), ": Show all DC shared files. All/Hashed ";
688 (* 'dchubs [args]' - Show dchub list with optional filters args (max 5) *)
689 "dchublist", Arg_multiple
(fun args o
->
690 let buf = o
.conn_buf
in
691 let filter = ref [] in
692 let print_hublist () =
693 if use_html_mods o
then
695 html_mods_table_one_row
buf "serversTable" "servers" [
696 (empty_string
, "srh", Printf.sprintf
"Showing hublist"); ];
697 Printf.bprintf
buf "\\</table\\>\\</div\\>"
700 Printf.bprintf
buf "Showing hublist";
701 html_mods_cntr_init
();
702 let nb_hubs = ref 0 in
703 if use_html_mods o
then dc_hublist_print_html_header buf empty_string
;
704 let show_all = if (!filter = []) then true else false in
706 let hub_has_string searched
=
707 if String2.contains
(Ip.string_of_addr h
.dc_ip
) searched
||
708 String2.contains
(string_of_int h
.dc_port
) searched
||
709 String2.contains h
.dc_info searched
||
710 String2.contains h
.dc_name searched
then true
714 hublist_print h
!nb_hubs o
;
717 if !verbose_msg_servers
then
718 lprintf_nl "Exception %s in hub_print\n" (Printexc2.to_string e
))
724 let print = ref false in
725 let finished = ref false in
726 let counter = ref 0 in
727 let filters_length = List.length
!filter in
728 while (!print = false) && (!finished = false) do
729 if (!counter = filters_length) || (!counter > 5) then
732 if (hub_has_string (List.nth
!filter !counter)) then print := true;
735 if (!print = true) then print_hub ()
738 let txt = if show_all then "(showing all hubs from hublist)" else "(filtered)" in
739 if use_html_mods o
then
741 Printf.bprintf
buf "\\</table\\>\\</div\\>";
742 html_mods_table_one_row
buf "serversTable" "servers" [
743 (empty_string
, "srh", Printf.sprintf
"Hubs: %d known %s" !nb_hubs txt); ]
746 Printf.bprintf
buf "Hubs: %d known %s" !nb_hubs txt
750 | rest_args
-> filter := rest_args
754 ), "[filtertext]: dchublist fin - filters hubs with text fin";
756 (* 'dcuserip name' query user-ip from hub *)
757 "dcuserip", Arg_multiple
(fun args o
->
758 let buf = o
.conn_buf
in
760 | [hub
; port ; name
] ->
762 let s = Hashtbl.find servers_by_ip hub
in
763 (match s.server_sock
with
764 | Connection sock
-> dc_send_msg sock
( UserIPReq
( [name
] ))
767 if !verbose_unexpected_messages
then
768 lprintf_nl "dcuserip: No server found by ip (%s) (%s) (%s)" hub
port name
)
769 | _
-> if !verbose_unexpected_messages
then lprintf_nl "dcuserip: Invalid args count (%d)" (List.length args
) );
770 Printf.bprintf
buf "User query sent to hubs\n";
772 ), "<user> : Query users ip from hub";
774 "dcmsglog", Arg_multiple
(fun args o
->
775 let buf = o
.conn_buf
in
776 let counter = ref 0 in
777 let messages,name
,topic
=
779 | delay
:: ip :: port :: _
->
781 let s = Hashtbl.find servers_by_ip
ip in
783 (match s.server_sock
with
784 | Connection _
-> s.server_topic
785 | _
-> "NOT CONNECTED TO SERVER" )
787 s.server_read_messages
<- List.length
s.server_messages
; (* messages are set as read before *)
788 s.server_messages
, (* they are actually printed to user *)
789 (if (String.length
s.server_name
> 50) then String.sub
s.server_name
0 49 else s.server_name
),
792 if !verbose_unexpected_messages
then lprintf_nl "dcmsglog: No server with address found";
796 let u = search_user_by_name n
in
797 let connected = ((List.length
u.user_servers
) > 0) in
798 u.user_read_messages
<- List.length
u.user_messages
; (* messages are set as read before *)
799 u.user_messages
, u.user_nick
, (* they are actually printed to user *)
800 (if connected then empty_string
801 else "User not connected to any servers at the moment...")
803 if !verbose_unexpected_messages
then lprintf_nl "dcmsglog: No user found";
806 if !verbose_unexpected_messages
then lprintf_nl "dcmsglog: Invalid args count (%d)" (List.length args
);
809 if use_html_mods o
then begin
810 Printf.bprintf
buf "\\<div class=\\\"messages\\\"\\>";
811 Printf.bprintf
buf "\\<div\\>Chatting with \\<b\\>%s\\</b\\> - %d logged messages\\</div\\>"
812 name
(List.length
messages);
813 Printf.bprintf
buf "\\<div\\>\\<i\\>%s\\</i\\>\\</div\\>" topic
815 Printf.bprintf
buf "%d logged messages\n" (List.length
messages);
816 if use_html_mods o
then html_mods_table_header
buf "serversTable" "servers" [
817 ( "0", "srh", "Timestamp", "Time" );
818 ( "0", "srh", "Who message is from", "From" );
819 ( "0", "srh", "Message text", "Message" ) ];
820 List.iter
(fun (t
,f,m
) ->
823 | PrivateMessage
(_
, msg) -> msg
824 | PublicMessage
(_
, msg) -> msg
825 | ServerMessage
msg -> msg )
827 if use_html_mods o
then begin
828 Printf.bprintf
buf "\\<tr class=\\\"%s\\\"\\>"
829 (if (!counter mod 2 == 0) then "dl-1" else "dl-2");
831 (empty_string
, "sr", Date.simple
(BasicSocket.date_of_int t
));
832 (empty_string
, "sr", f);
833 (empty_string
, "srw", msg) ];
834 Printf.bprintf
buf "\\</tr\\>"
836 Printf.bprintf
buf "\n%s [%s] : %s\n" (Date.simple
(BasicSocket.date_of_int t
)) f msg
840 if use_html_mods o
then Printf.bprintf
buf "\\</table\\>\\</div\\>\\</div\\>";
842 ), "<refresh> <user> | <refresh> <serverip> <serverport>";
844 "dcmessages", Arg_multiple
(fun args o
->
845 let buf = o
.conn_buf
in
850 let s = Hashtbl.find servers_by_ip
ip in
853 if !verbose_unexpected_messages
then lprintf_nl "dcmessages: No server with address found";
857 let u = search_user_by_name n
in
860 if !verbose_unexpected_messages
then lprintf_nl "dcmessages: No user found";
863 if !verbose_unexpected_messages
then lprintf_nl "dcmessages: No user or server";
866 if use_html_mods o
then begin
867 Printf.bprintf
buf "\\<script type=\\\"text/javascript\\\"\\>
869 function submitCmd() {
870 var formID = document.getElementById(\\\"msgForm\\\")
871 parent.output.location.href='submit?q=dcmessages+'+formID.sendCmd.value
873 function submitMessageForm() {
874 var formID = document.getElementById(\\\"msgForm\\\")
875 var regExp = new RegExp (' ', 'gi')
876 var msgTextOut = formID.msgText.value.replace(regExp, '+')
877 parent.fstatus.location.href='submit?q=dcsendmsg+'+formID.sendCmd.value+\\\"+\\\"+msgTextOut
878 formID.msgText.value=\\\"\\\"
879 msgWindow.location.reload();
883 let sendmsg,namelist
,first
=
886 let ip,port = (Ip.to_string
s.server_ip
),(string_of_int
s.server_port
) in
887 Printf.sprintf
"dcmsglog+20+%s+%s" ip port, s.server_users
, Printf.sprintf
"%s %s" ip port
891 Printf.sprintf
"dcmsglog+20+%s" u.user_nick
, [], u.user_nick
893 if !verbose_unexpected_messages
then lprintf_nl "dcmessages: No user or server";
897 Printf.bprintf
buf "\\<iframe id=\\\"msgWindow\\\" name=\\\"msgWindow\\\" height=\\\"80%%\\\"
898 width=\\\"100%%\\\" scrolling=yes src=\\\"submit?q=%s\\\"\\>\\</iframe\\>" sendmsg;
899 Printf.bprintf
buf "\\<form style=\\\"margin: 0px;\\\" name=\\\"msgForm\\\" id=\\\"msgForm\\\" action=\\\"javascript:submitMessageForm()\\\"\\>";
900 Printf.bprintf
buf "\\<table width=100%% cellspacing=0 cellpadding=0 border=0\\>\\<tr\\>\\<td\\>";
901 Printf.bprintf
buf "\\<select style=\\\"font-family: verdana; font-size: 12px; width: 150px;\\\" id=\\\"sendCmd\\\" name=\\\"sendCmd\\\" \\>";
902 Printf.bprintf
buf "\\<option value=\\\"%s\\\"\\>%s" first first
;
904 if not
(has_my_nick
u) then
905 Printf.bprintf
buf "\\<option value=\\\"%s\\\"\\>%s" u.user_nick
u.user_nick
907 Printf.bprintf
buf "\\</select\\>\\</td\\>";
908 Printf.bprintf
buf "\\<td width=100%%\\>\\<input style=\\\"width: 99%%; font-family: verdana; font-size: 12px;\\\"
909 type=text id=\\\"msgText\\\" name=\\\"msgText\\\" size=50 \\>\\</td\\>";
910 Printf.bprintf
buf "\\<td\\>\\<input style=\\\"font-family: verdana;
911 font-size: 12px;\\\" type=submit value=\\\"Send\\\"\\>\\</td\\>\\</form\\>";
912 Printf.bprintf
buf "\\<form style=\\\"margin: 0px;\\\" id=\\\"refresh\\\" name=\\\"refresh\\\"
913 action=\\\"javascript:msgWindow.location.reload();\\\"\\>
914 \\<td\\>\\<input style=\\\"font-family: verdana; font-size: 12px;\\\" type=submit
915 Value=\\\"Refresh\\\"\\>\\</td\\>\\</form\\>\\</tr\\>\\</table\\>";
916 Printf.bprintf
buf "\\<table\\>\\<tr\\>\\<form style=\\\"margin: 0px;\\\" id=\\\"users\\\" name=\\\"users\\\"
917 action=\\\"javascript:parent.output.location.href='submit?q=dcusers'\\\"\\>
918 \\<td\\>\\<input style=\\\"font-family: verdana; font-size: 12px;\\\" type=submit
919 Value=\\\"Users\\\"\\>\\</td\\>\\</form\\>";
920 Printf.bprintf
buf "\\<form style=\\\"margin: 0px;\\\" id=\\\"hubs\\\" name=\\\"hubs\\\"
921 action=\\\"javascript:parent.output.location.href='submit?q=dchubs'\\\"\\>
922 \\<td\\>\\<input style=\\\"font-family: verdana; font-size: 12px;\\\" type=submit
923 Value=\\\"Hubs\\\"\\>\\</td\\>\\</form\\>";
924 Printf.bprintf
buf "\\<form style=\\\"margin: 0px;\\\" id=\\\"hubs\\\" name=\\\"hubs\\\"
925 action=\\\"javascript:submitCmd()\\\"\\>
926 \\<td\\>\\<input style=\\\"font-family: verdana; font-size: 12px;\\\" type=submit
927 Value=\\\"Open chat\\\"\\>\\</td\\>\\</form\\>";
928 Printf.bprintf
buf "\\</tr\\>\\</table\\>";
931 _s
"Usage: dcmessages <username> | <serverip> <serverport>\n"
932 ), "<username> | <serverip> <serverport> : Show user or server messages ";
935 (* message type = (int * room_message) list
936 room_message type = | ServerMessage of string
937 | PublicMessage of int * string
938 | PrivateMessage of int * string *)
939 (* 'dcsendmsg hub port user message' - send message to specific user *)
940 "dcsendmsg", Arg_multiple
(fun args o
->
941 let buf = o
.conn_buf
in
942 (*let failtxt = "dcsendmsg <user> <message> | <serverip> <serverport> <message> : bad arguments" in*)
943 let u = (* check if first argument is valid user *)
945 let u = search_user_by_name
(List.hd args
) in
951 let s = Hashtbl.find servers_by_ip
(List.hd args
) in
956 | Some
u -> (* message is private usermessage *)
959 if not
(has_my_nick
u) && ((List.length
u.user_servers
) > 0) then begin
960 let sent = ref false in
961 List.iter
(fun s -> (* find a server we are connected to with this user *)
962 (match s.server_sock
with
964 if not
!sent then begin
965 let msg = String2.unsplit
messages ' '
in
967 ToReq
{ To.dest
= u.user_nick
;
968 To.from
= s.server_last_nick
;
969 To.message
= msg } );
971 u.user_messages
<- u.user_messages
@ [
972 (int_of_float
(current_time
()), s.server_last_nick
, PrivateMessage
(0, msg))];
979 (match s with (* message is probably hub chatmessage but check ip *)
980 | None
-> if !verbose_unexpected_messages
then lprintf_nl "dcsendmsg: No User or Server found"
983 | _
:: _
:: messages ->
984 (match s.server_sock
with
986 let msg = String2.unsplit
messages ' '
in
987 dc_send_msg sock
( MessageReq
{ Message.from
= s.server_last_nick
; Message.message
= msg } );
988 (* don't save this message, it is echoed from hub back to us and saved then *)
989 (* message window is refreshed too quickly to show this *)
994 Printf.bprintf
buf "User query sent to hubs\n";
996 ), "<user> <message> : Send message to user";
998 (* Try to load file from filelist *)
999 "dcloadfile", Arg_multiple
(fun args o
->
1000 let buf = o
.conn_buf
in
1002 | [uname
; tth
; dir
; fname ; fsize
] -> (* convert filenames back to normal *)
1003 if !verbose_download
then lprintf_nl "dcloadfile: (%s) (%s) (%s)" dir
fname tth
;
1004 let sdir = ref (String.copy dir
) in
1005 let sname = ref (String.copy
fname) in
1006 String2.replace_char
!sdir char42 char32
; (* * to *)
1007 String2.replace_char
!sdir char58 char39
; (* : to ' *)
1008 String2.replace_char
!sdir char60 char38
; (* < to & *)
1009 String2.replace_char
!sdir char62 char43
; (* > to + *)
1010 String2.replace_char
!sname char42 char32
;
1011 String2.replace_char
!sname char58 char39
;
1012 String2.replace_char
!sname char60 char38
;
1013 String2.replace_char
!sname char62 char43
;
1014 Printf.bprintf
buf "Trying to download file: %s from user: %s\n" !sname uname
;
1016 let u = search_user_by_name uname
in
1017 ignore
(start_new_download u tth
!sdir !sname (Int64.of_string fsize
))
1018 with _
-> if !verbose_download
then lprintf_nl "dcloadfile: No user found" )
1020 if !verbose_unexpected_messages
then
1021 lprintf_nl "dcloadfile: bad arguments count (%d)" (List.length args
) );
1023 ), "<username> <tth> <directory> <filename> : Load a file";
1025 (* load filelist from user *)
1026 "dcloadfilelist", Arg_one
(fun args o
->
1027 let buf = o
.conn_buf
in
1031 let u = search_user_by_name name
in
1032 if ((List.length
u.user_servers
) > 0) then begin
1033 if not
(filelist_already_downloading
u) then begin (* and is connected to server with us *)
1034 if !verbose_msg_clients
|| !verbose_download
then
1035 lprintf_nl "Loading filelist from user %s" name
; (* not already loading filelist *)
1036 let c = new_client
() in
1037 c.client_name
<- Some
u.user_nick
;
1038 add_client_to_user
c u;
1039 c.client_state
<- DcDownloadListWaiting
;
1040 if (can_user_start_downloading
u) then begin
1041 u.user_state
<- TryingToSendFirstContact
;
1042 c.client_state
<- DcDownloadListConnecting
(0,!!firewalled
,current_time
()); (* level is set later *)
1043 ignore
(DcClients.try_connect_client
c);
1048 if !verbose_unexpected_messages
then lprintf_nl "dcloadfilelist: No user (%s) found" name
) );
1049 Printf.bprintf
buf "Trying to download filelist\n";
1051 ), "<name> : Download filelist from user";
1053 "dcfilelists", Arg_none
(fun o
->
1054 let buf = o
.conn_buf
in
1055 html_mods_cntr_init
();
1057 if use_html_mods o
then dc_filelist_print_html_header buf;
1058 let filelist = Unix2.list_directory filelist_directory
in
1059 List.iter
(fun fname ->
1060 filelist_print fname !line o
;
1063 if use_html_mods o
then Printf.bprintf
buf "\\</table\\>\\</div\\>";
1065 ), ": List all filelists on disk";
1067 "dcremclient", Arg_one
(fun args o
->
1068 let buf = o
.conn_buf
in
1072 let cc = CommonClient.client_find
(int_of_string
num) in
1073 let impl = as_client_impl
cc in
1074 let c = impl.impl_client_val
in
1075 (match c.client_state
with
1076 | DcDownloadWaiting _
| DcDownloadListWaiting
->
1077 Printf.bprintf
buf "Removing one client by name %s" (clients_username
c);
1081 if !verbose_msg_clients
then lprintf_nl "dcremclient: bad arguments (internal command)" ) );
1083 ), "<num> : Remove client by num";
1085 "dcfindsource", Arg_one
(fun args o
->
1087 | tth_or_filename
->
1088 (*lprintf_nl "Got dcfindsource command: (%s)" tth_or_filename;*)
1089 let tth_or_filename = ref (String.copy
tth_or_filename) in
1090 String2.replace_char
!tth_or_filename char42 char32
;
1091 String2.replace_char
!tth_or_filename char58 char39
;
1092 String2.replace_char
!tth_or_filename char38 char60
;
1093 if (is_valid_tiger_hash
!tth_or_filename) then begin
1094 let query = QAnd
(QHasField
(Field_Type
, "TTH") , (QHasWord
!tth_or_filename)) in
1095 let search = CommonSearch.new_search o
.conn_user
1096 (let module G
= GuiTypes
in
1098 G.search_query
= query;
1099 G.search_max_hits
= 10000;
1100 G.search_type
= RemoteSearch
;
1101 G.search_network
= network
.network_num
;
1104 dc_with_connected_servers
(fun s -> DcClients.server_send_search
s search 9 !tth_or_filename);
1105 dc_last_manual_search
:= current_time
();
1107 let fname = Filename.basename
!tth_or_filename in
1108 let words = clean_string
fname in
1109 let words_list = String2.split_simplify
words ' '
in
1110 let rec add_query list
=
1112 | hd
:: [] -> QHasWord hd
1113 | hd
:: tail
-> QAnd
((QHasWord hd
) , (add_query tail
))
1114 | [] -> failwith
"No words to search")
1116 let query = add_query words_list in
1117 let search = CommonSearch.new_search o
.conn_user
1118 (let module G
= GuiTypes
in
1120 G.search_query
= query;
1121 G.search_max_hits
= 10000;
1122 G.search_type
= RemoteSearch
;
1123 G.search_network
= network
.network_num
;
1126 dc_with_connected_servers
(fun s -> DcClients.server_send_search
s search 1 !tth_or_filename);
1127 dc_last_manual_search
:= current_time
();
1130 ), ": Find new source for a file";
1132 "dcinfo", Arg_none
(fun o
->
1133 let buf = o
.conn_buf
in
1138 String.sub
s.server_name
0 (if (String.length
s.server_name
> 20) then 20 else
1139 String.length
s.server_name
) ^
" (nick = " ^
s.server_last_nick ^
") (uptime = " ^
1140 (Date.time_to_string
(int_of_float
(current_time
()) -
1141 int_of_float
(s.server_connection_time
)) "verbose") ^
1142 (string_of_int
(List.length
s.server_users
)) ^
")"
1144 lst := !lst @ [ (empty_string
, data) ]
1145 ) !connected_servers
;
1148 let norm_hubs,reg_hubs
,opped_hubs
= get_myhubs_info
() in
1149 html_mods_cntr_init
();
1150 if use_html_mods o
then dc_info_html_header buf;
1151 let nservers = List.length
!connected_servers
in
1153 ("Hub supports", (DcProtocol.Supports.create_supports_string
(HubSupports mldonkey_dc_hub_supports
)) );
1154 ("Client supports", (DcProtocol.Supports.create_supports_string
(ClientSupports mldonkey_dc_client_supports
)) );
1155 ("All/Open slots", Printf.sprintf
"%d / %d" (open_slots
()) (current_slots
()) );
1156 ("Mode", (if !!firewalled
then "Passive" else "Active") );
1157 ("Connected servers", (if nservers > 0 then string_of_int
nservers else ""));
1158 (" Server list:", empty_string
); ]
1160 ("Hubs", (Printf.sprintf
"Normal:%d Vipped:%d Opped:%d" norm_hubs reg_hubs opped_hubs
) ); ]
1162 let counter = ref 0 in
1163 List.iter
(fun (info
,data) ->
1164 dc_info_print info
data line o
;
1167 if use_html_mods o
then Printf.bprintf
buf "\\</table\\>\\</div\\>";
1169 ), ": Direct Connect info";
1171 (* load filelist from user *)
1172 "dcshowfilelist", Arg_one
(fun args o
->
1173 let buf = o
.conn_buf
in
1176 let username, extension
=
1178 if (Filename.check_suffix
filename mylist_ext
) then (* if extension is DcLst ... *)
1179 Filename.chop_suffix
filename mylist_ext
,mylist_ext
(* return filename without it and ext *)
1180 else if (Filename.check_suffix
filename bz2_ext
) then begin (* else if extension is bz2 ... *)
1181 let filename = Filename.chop_suffix
filename bz2_ext
in (* chop it off *)
1182 if (Filename.check_suffix
filename xml_ext
) then (* check if there is extension xml ...*)
1183 Filename.chop_suffix
filename xml_ext
,mylistxmlbz2_ext
(* return filename without it and ext *)
1184 else raise Not_found
1185 end else raise Not_found
1186 with _
-> filename, empty_string
)
1188 let spaces num = (* add as many "...":s to string that counter num *)
1191 if (num <> 0) then begin
1198 if (extension
= mylist_ext
) then begin (* parse MyList.DcLst *)
1200 let s = file_to_che3_to_string
(Filename.concat filelist_directory
filename) in
1201 if not
(Charset.is_utf8
s) then lprintf_nl "not utf8 : %S" s;
1202 let s = Charset.Locale.to_utf8
s in (* really needed? *)
1204 String2.replace_char
s char13 '
\n'
;
1205 let lines = String2.split_simplify
s '
\n'
in
1206 let mlist = ref ([] : dc_mylistnode
list) in (* root node of the MyList *)
1207 let tablist = ref [(-1, mlist)] in (* list of previous open directory node for every tab *)
1208 (* [(0 , list ref); (1 , list ref) ... *)
1209 let rec count_tabs line pos
= (* count current lines tabs *)
1210 if line.[pos
] <> '
\t'
then pos
else
1211 count_tabs line (pos
+1)
1213 let add_dir name tabs
list =
1214 let newlist = ref ([] : dc_mylistnode
list) in
1215 list := !list @ [MylistDirectory
(name
, newlist)]; (* add this dir node to current list *)
1216 if (List.mem_assq tabs
!tablist) then begin (* check if a directory exists already for this tab *)
1217 tablist := List.remove_assq tabs
!tablist; (* remove existing previous tab *)
1219 tablist := !tablist @ [(tabs
, newlist)]; (* add current list to this tab *)
1221 let add_file name size
list =
1222 list := !list @ [MylistFile
(name
, size
)]; (*add this file to current node *)
1224 let find_tab_dir tabs
= (* find the node of last directory for this tab *)
1225 let nlist = List.assq tabs
!tablist in
1226 nlist (* return list ref *)
1228 let rec parse lines ctabs clist
=
1231 let ltabs = count_tabs first
0 in (* count lines tabs *)
1232 (match (String2.split first '
|'
) with
1233 | dir
:: [] -> (* if line is directory *)
1234 let dir = String2.after
dir ltabs in
1235 if ltabs = ctabs
then begin
1236 let nlist = find_tab_dir (ltabs-1) in
1237 add_dir dir ltabs nlist;
1238 if (tail
<> []) then begin
1239 let nlist = find_tab_dir ltabs in
1240 parse tail
ltabs nlist
1242 end else if ltabs > ctabs
then begin
1243 add_dir dir ltabs clist
;
1244 let nlist = find_tab_dir ltabs in
1245 if (tail
<> []) then parse tail
ltabs nlist
1247 let nlist = find_tab_dir ltabs in
1248 parse lines ltabs nlist
1250 | name
:: size
:: [] -> (* if line is file *)
1251 let name = String2.after
name ltabs in
1252 if ltabs > ctabs
then begin
1253 add_file name size clist
;
1254 if (tail
<> []) then parse tail ctabs clist
1255 end else if ltabs <= ctabs
then begin
1256 let nlist = find_tab_dir (ltabs-1) in
1257 add_file name size
nlist;
1258 parse tail
(ltabs-1) nlist
1260 | _
-> failwith
(Printf.sprintf
"Unknown line (%s)" first
) )
1263 parse lines (pred
0) mlist;
1265 html_mods_cntr_init
();
1267 if use_html_mods o
then dc_filelist_files_print_html_header buf;
1268 let rec print node
dir tabs
=
1271 | MylistFile
(name, size
) ->
1272 filelist_file_print true (spaces tabs
) username dir name size empty_string
!line o
;
1273 (*lprintf_nl "(%s) (%s)" (!spaces ^ name) (Int64.to_string size);*)
1274 | MylistDirectory
(name, nlist) ->
1276 if dir = "" then name
1277 else dir ^
"/" ^
name
1279 filelist_file_print false (spaces tabs
) username dir name empty_string empty_string
!line o
;
1280 (*lprintf_nl "(%s) list_count=(%d)" (!spaces ^ dir) (List.length !nlist);*)
1282 List.iter (fun node
-> print node
dir (tabs
+1)) !nlist )
1284 List.iter (fun node
-> print node empty_string
0) !mlist;
1285 if use_html_mods o
then Printf.bprintf
buf "\\</table\\>\\</div\\>";
1287 if !verbose_unexpected_messages
then
1288 lprintf_nl "dcshowfilelist: (%s) in .DcLst parsing" (Printexc2.to_string e
) )
1289 with _
-> if !verbose_unexpected_messages
then lprintf_nl "Error in che3 decompressing" )
1291 end else if (extension
= mylistxmlbz2_ext
) then begin (* parse .xml.bz2 *)
1292 (try (* try to unzip *)
1293 let s = Buffer.contents
(file_to_bz2_to_buffer
(Filename.concat filelist_directory
filename)) in
1294 (try (* try to parse xml and make a www page *)
1295 let xml = Xml.parse_string
s in
1296 let parse_xml_chars s = (* in xml there are html-escapes mixed in *)
1297 let s = dc_replace_str_to_str
s "&" "&" in
1300 if ((Xml.tag
xml) <> "FileListing") then failwith
"Xml-file don't start with FileListing";
1301 html_mods_cntr_init
();
1303 if use_html_mods o
then dc_filelist_files_print_html_header buf;
1304 let rec parse x
dir ndirs
= (* iterate this with all xml elements (one node with tag and attributes *)
1305 let tag = Xml.tag x
in
1307 if tag = "File" then dir (* if tag of element is file, return existing dir name *)
1308 else begin (* else this is "probably" a directory *)
1309 let newdir = Xml.attrib x
"Name" in (* get dir name *)
1310 if dir = "" then newdir (* if this is first dir to add, don't add the "/" *)
1311 else dir ^
"/" ^
newdir (* else add this new dir path name to existing dir *)
1315 | "File" -> (* is this xml element is a file element, add its line to http-page *)
1316 let fname = Xml.attrib x
"Name" in
1317 let fname = parse_xml_chars fname in
1318 let fsize = Xml.attrib x
"Size" in
1319 let ftth = Xml.attrib x
"TTH" in
1321 filelist_file_print true (spaces ndirs
) username dir fname fsize ftth !line o
;
1322 | "Directory" -> (* or if it is a directory element, add its line to http-page *)
1323 let fname = Xml.attrib x
"Name" in
1324 let fname = parse_xml_chars fname in
1325 let fsize = empty_string
in
1326 let ftth = empty_string
in
1328 filelist_file_print false (spaces ndirs
) username dir fname fsize ftth !line o
;
1329 | _
-> failwith
"Tag not File or Directory" );
1331 Xml.iter (fun x
-> parse x
dir (ndirs
+1)) x
1333 Xml.iter (fun x
-> parse x empty_string
0) xml;
1334 if use_html_mods o
then Printf.bprintf
buf "\\</table\\>\\</div\\>";
1336 | Error e
-> if !verbose_unexpected_messages
then lprintf_nl "%s" (Xml.error e
)
1337 | e
-> if !verbose_unexpected_messages
then
1338 lprintf_nl "dcshowfilelist: (%s) in xml parsing" (Printexc2.to_string e
) )
1339 with _
-> if !verbose_unexpected_messages
then lprintf_nl "Error in bz2 unzipping" )
1340 end else if !verbose_unexpected_messages
then lprintf_nl "dcshowfilelist: Filelist extension not valid" );
1342 ), "<name> : Show filelist for user";
1344 "dcautoconnect", Arg_two
(fun arg1 arg2 o
->
1346 let s = Hashtbl.find servers_by_ip arg2
in
1347 let auto = bool_of_string arg1
in
1348 s.server_autoconnect
<- auto;
1349 server_must_update
s
1352 ), "<true/false> <ip> : Set/unset the server autoconnection state";
1354 ] (* end of let commands = *)
1358 (* register user operations *)
1360 register_commands commands;
1362 user_ops
.op_user_info
<- (fun user
-> (* CHECK *)
1364 P.user_num
= user
.user_user
.impl_user_num
;
1365 P.user_md4
= Md4.null
;
1366 P.user_name
= user
.user_nick
;
1367 P.user_ip
= Ip.null
;
1371 if user
.user_data
> 1. then
1372 [ { tag_name
= Field_UNKNOWN
"link"; tag_value
= String user
.user_link
};
1373 { tag_name
= Field_UNKNOWN
"shared"; tag_value
= String
(
1374 Printf.sprintf
"%12.0f" user
.user_data
) } ]
1377 (match user
.user_type
with
1378 | Normal
| Vip
-> list
1379 | Op
-> { tag_name
= Field_UNKNOWN
"admin"; tag_value
= String
"admin" } :: list ) );
1381 (match user
.user_servers
with
1383 | s :: _ -> s.server_server
.impl_server_num
);
1386 user_ops
.op_user_remove
<- (fun user
-> () )
1388 user_ops.op_user_browse_files <- (fun user ->
1389 let c = client_of_user user in
1390 contact_add (as_client c.client_client)
1392 user_ops.op_user_set_friend <- (fun user ->
1393 let c = client_of_user user in
1394 friend_add (as_client c.client_client)
1397 mutable op_user_network : network;
1398 mutable op_user_set_friend : ('a -> unit);
1399 mutable op_user_browse_files : ('a -> unit);
1404 (*module C = CommonTypes
1406 result_ops.op_result_info <- (fun r ->
1408 C.result_num = r.result_result.impl_result_num;
1409 C.result_network = network.network_num;
1411 C.result_names = [r.result_name];
1412 C.result_md4 = Md4.null;
1413 C.result_size = r.result_size;
1414 C.result_format = result_format_of_name r.result_name;
1415 C.result_type = result_media_of_name r.result_name;
1417 C.result_comment = "";
1418 C.result_done = false;
1424 (* register file operations *)
1426 file_ops
.op_file_info
<- (fun file
->
1428 P.file_fields
= Fields_file_info.all
;
1429 P.file_comment
= empty_string
;
1430 P.file_name
= file
.file_name
;
1431 P.file_num
= (file_num file
);
1432 P.file_network
= network
.network_num
;
1433 P.file_names
= [file
.file_name
];
1434 P.file_md4
= Md4.null
;
1435 P.file_size
= file_size file
;
1436 P.file_downloaded
= file_downloaded file
;
1437 P.file_all_sources
= 0;
1438 P.file_active_sources
= 0;
1439 P.file_state
= file_state file
;
1440 P.file_sources
= None
;
1441 P.file_download_rate
= file_download_rate file
.file_file
;
1442 P.file_chunks
= None
;
1443 P.file_chunk_size
= None
;
1444 P.file_availability
= [network
.network_num
, "0"];
1445 P.file_format
= FormatUnknown
;
1446 P.file_chunks_age
= [|0|];
1447 P.file_age
= file_age file
;
1448 P.file_last_seen
= BasicSocket.last_time
();
1449 P.file_priority
= file_priority
(as_file file
.file_file
);
1451 P.file_sub_files
= [];
1452 P.file_comments
= [];
1453 P.file_magic
= None
;
1454 P.file_user
= empty_string
;
1455 P.file_group
= empty_string
;
1456 P.file_release
= false;
1459 file_ops
.op_file_all_sources
<- (fun file
->
1460 List2.tail_map
(fun c -> as_client
c.client_client
)
1463 file_ops
.op_file_active_sources
<- file_ops
.op_file_all_sources
;
1464 file_ops
.op_file_cancel
<- (fun file
->
1465 let remove_files_clients_not_downloading () =
1467 (match c.client_state
with
1468 | DcDownload
f -> () (* only one client should be in this state *)
1471 ) file
.file_clients
;
1474 List.iter (fun c -> (* find one files client that is currently downloading *)
1475 (match c.client_state
with
1476 | DcDownload
_ -> raise
(Found_client
c)
1478 ) file
.file_clients
;
1481 | Found_client
c -> (* found a download slot tried to continue *)
1482 (match (DcClients.find_next_client
c) with (* try to continue slot *)
1484 (match c.client_sock
with
1485 | Connection sock
->
1486 remove_files_clients_not_downloading ();
1487 remove_file_not_clients file
;
1488 c.client_receiving
<- Int64.zero
;
1489 c.client_pos
<- Int64.zero
;
1490 TcpBufferedSocket.set_rtimeout sock
30.;
1491 DcClients.next_download
false c sock cl
(* try to change downloading *)
1494 remove_files_clients_not_downloading ();
1495 remove_file_not_clients file
;
1496 c.client_state
<- DcIdle
;
1497 (match c.client_sock
with
1498 | Connection sock
-> TcpBufferedSocket.close sock
(Closed_for_error
"File cancelled")
1502 remove_file_with_clients file
);
1503 if !verbose_download
then lprintf_nl "File %s cancelled" file
.file_name
;
1505 file_ops
.op_file_commit
<- (fun file
name ->
1506 remove_file_with_clients file
;
1508 file_ops
.op_file_pause
<- (fun file
->
1511 (match c.client_state
with
1512 | DcDownload
f -> if file
== f then raise
(Found_client
c)
1514 ) file
.file_clients
;
1518 (match (DcClients.find_next_client
c) with (* try to continue slot *)
1520 (match c.client_sock
with
1521 | Connection sock
->
1522 DcClients.next_download
true c sock cl
(* try to change downloading *)
1524 | None
-> c.client_state
<- DcIdle
(* DcPaused ? *))
1525 | Not_found
-> () ) (* Should not happen *)
1529 file_ops.op_file_files <- (fun file impl ->
1530 match file.file_swarmer with
1531 None -> [CommonFile.as_file impl]
1533 CommonSwarming.subfiles swarmer)
1536 file_ops.op_file_save_as <- (fun file new_name ->
1537 match file_state file with
1538 FileDownloaded | FileShared ->
1539 DcClients.save_file_as file new_name
1544 (*let client_of_user user =
1545 let c = new_client user.user_nick in
1551 mutable op_file_network : network; *)
1552 file_ops
.op_file_save_as
<- (fun _ _ -> ());
1553 file_ops
.op_file_resume
<- (fun _ -> ());
1554 file_ops
.op_file_set_format
<- (fun _ _ -> ());
1555 file_ops
.op_file_check
<- (fun _ -> ());
1556 file_ops
.op_file_recover
<- (fun _ -> ())
1557 (*file_ops.op_file_print_html <- (fun _ _ -> lprintf_nl "Received (op_file_print_html)"; ());*)
1558 (*file_ops.op_file_print_sources_html <- (fun _ _ -> lprintf_nl "Received (op_file_print_sources_html)"; ())*)
1559 (* mutable op_file_files : ('a -> 'a file_impl -> file list);
1560 mutable op_file_debug : ('a -> string);
1561 mutable op_file_proposed_filenames : ('a -> string list);
1565 CommonWeb.add_web_kind
"hublist" "DirectConnect hublist"
1566 (fun url
filename ->
1567 if !!enable_directconnect
then
1571 match List.rev
(String2.split
filename '
.'
) with
1572 | "bz2"::"xml"::_ -> DcServers.make_hublist_from_xml
(Xml.parse_file
(Misc2.bz2_extract
filename))
1573 | "xml"::_ -> DcServers.make_hublist_from_xml
(Xml.parse_file
filename)
1574 | "bz2"::_ -> DcServers.make_hublist_from_file
(Misc2.bz2_extract
filename)
1575 | _ -> DcServers.make_hublist_from_file
filename);
1576 lprintf_nl "loaded dc++ hublist, %d entries" (List.length
!dc_hublist
)
1578 if !verbose_msg_servers
then
1579 lprintf_nl "(%s) in loading/parsing serverlist" (Printexc2.to_string e
);
1584 lprintf_nl "DirectConnect module is disabled, ignoring...";