File Coverage

blib/lib/Tk/Mirror.pm
Criterion Covered Total %
statement 4 6 66.6
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 6 8 75.0


line stmt bran cond sub pod time code
1             #*** Mirror.pm ***#
2             # Copyright (C) 2006 - 2008 by Torsten Knorr
3             # create-soft@tiscali.de
4             # All rights reserved!
5             #-------------------------------------------------
6             package Tk::Mirror;
7             #-------------------------------------------------
8 1     1   21278 use strict;
  1         3  
  1         30  
9 1     1   371 use Tk::Frame;
  0            
  0            
10             use Net::UploadMirror 0.13;
11             use Net::DownloadMirror 0.10;
12             use Storable;
13             #-------------------------------------------------
14             @Tk::Mirror::ISA = qw(Tk::Frame);
15             $Tk::Mirror::VERSION = '0.06';
16             #-------------------------------------------------
17             Construct Tk::Widget 'Mirror';
18             #-------------------------------------------------
19             sub Populate
20             {
21             require Tk::Label;
22             require Tk::Entry;
23             require Tk::BrowseEntry;
24             require Tk::Tree;
25             require Tk::Button;
26             require Tk::Dialog;
27             my ($m, $args) = @_;
28             #-------------------------------------------------
29             if(-f 'para')
30             {
31             $m->{para} = retrieve('para');
32             }
33             else
34             {
35             $m->{para} = {};
36             }
37             for(qw/ -localdir
38             -remotedir
39             -ftpserver
40             -user
41             -pass
42             -debug
43             -timeout
44             -delete
45             -connection
46             -exclusions
47             -subset
48             -filename
49             /)
50             {
51             $m->{para}{substr($_, 1)} = delete($args->{$_}) if(defined($args->{$_}));
52             }
53             $m->{upload} = Net::UploadMirror->new(%{$m->{para}});
54             $m->{download} = Net::DownloadMirror->new(%{$m->{para}});
55             $m->{overwrite} = defined($args->{-overwrite}) ? delete($args->{-overwrite}) : 'none';
56             $m->SUPER::Populate($args);
57             #-------------------------------------------------
58             my $label_user = $m->Label(
59             -text => 'Username ->',
60             )->grid(
61             -row => 0,
62             -column => 0,
63             -columnspan => 3,
64             -sticky => 'nswe',
65             );
66             #-------------------------------------------------
67             $m->{bentry_user} = $m->BrowseEntry(
68             -variable => \$m->{para}{user},
69             -browsecmd => [\&UpdateAccess, $m, 'user'],
70             )->grid(
71             -row => 0,
72             -column => 3,
73             -columnspan => 3,
74             -sticky => 'nswe',
75             );
76             #-------------------------------------------------
77             my $label_ftpserver = $m->Label(
78             -text => 'FTP-Server ->',
79             )->grid(
80             -row => 1,
81             -column => 0,
82             -columnspan => 3,
83             -sticky => 'nswe',
84             );
85             #-------------------------------------------------
86             $m->{bentry_ftpserver} = $m->BrowseEntry(
87             -variable => \$m->{para}{ftpserver},
88             -browsecmd => [\&UpdateAccess, $m, 'ftpserver'],
89             )->grid(
90             -row => 1,
91             -column => 3,
92             -columnspan => 3,
93             -sticky => 'nsew',
94             );
95             #-------------------------------------------------
96             my $label_pass = $m->Label(
97             -text => 'Password ->',
98             )->grid(
99             -row => 2,
100             -column => 0,
101             -columnspan => 3,
102             -sticky => 'nsew',
103             );
104             #-------------------------------------------------
105             $m->{entry_pass} = $m->Entry(
106             -textvariable => \$m->{para}{pass},
107             -show => '*',
108             )->grid(
109             -row => 2,
110             -column => 3,
111             -columnspan => 3,
112             -sticky => 'nsew',
113             );
114             #-------------------------------------------------
115             my $label_local_dir = $m->Label(
116             -text => 'Localdirectory',
117             )->grid(
118             -row => 3,
119             -column => 0,
120             -columnspan => 3,
121             -sticky => 'nswe',
122             );
123             #-------------------------------------------------
124             my $label_remote_dir = $m->Label(
125             -text => 'Remotedirectory',
126             )->grid(
127             -row => 3,
128             -column => 3,
129             -columnspan => 3,
130             -sticky => 'nswe',
131             );
132             #-------------------------------------------------
133             $m->{bentry_local_dir} = $m->BrowseEntry(
134             -variable => \$m->{para}{localdir},
135             -browsecmd => [\&UpdateAccess, $m, 'localdir'],
136             )->grid(
137             -row => 4,
138             -column => 0,
139             -columnspan => 3,
140             -sticky => 'nswe',
141             );
142             #-------------------------------------------------
143             $m->{bentry_remote_dir} = $m->BrowseEntry(
144             -variable => \$m->{para}{remotedir},
145             -browsecmd => [\&UpdateAccess, $m, 'remotedir'],
146             )->grid(
147             -row => 4,
148             -column => 3,
149             -columnspan => 3,
150             -sticky => 'nswe',
151             );
152             #-------------------------------------------------
153             $m->{tree_local_dir} = $m->Scrolled(
154             "Tree",
155             -separator => '/',
156             -itemtype => 'text',
157             -selectmode => 'single',
158             )->grid(
159             -row => 5,
160             -column => 0,
161             -columnspan => 3,
162             -sticky => 'nswe',
163             );
164             #-------------------------------------------------
165             $m->{tree_remote_dir} = $m->Scrolled(
166             "Tree",
167             -separator => '/',
168             -itemtype => 'text',
169             -selectmode => 'single'
170             )->grid(
171             -row => 5,
172             -column => 3,
173             -columnspan => 3,
174             -sticky => 'nswe'
175             );
176             #-------------------------------------------------
177             $m->{label_overwrite} = $m->Label(
178             -text => 'overwrite'
179             )->grid(
180             -row => 6,
181             -column => 0,
182             -columnspan => 2,
183             -sticky => 'nswe'
184             );
185             #------------------------------------------------
186             $m->{rbutton_none} = $m->Radiobutton(
187             -text => 'none',
188             -variable => \$m->{overwrite},
189             -value => 'none'
190             )->grid(
191             -row => 6,
192             -column => 2,
193             -sticky => 'nswe'
194             );
195             #-------------------------------------------------
196             $m->{rbutton_all} = $m->Radiobutton(
197             -text => 'all',
198             -variable => \$m->{overwrite},
199             -value => 'all',
200             )->grid(
201             -row => 6,
202             -column => 3,
203             -sticky => 'nwes'
204             );
205             #-------------------------------------------------
206             $m->{rbutton_older} = $m->Radiobutton(
207             -text => 'older',
208             -variable => \$m->{overwrite},
209             -value => 'older'
210             )->grid(
211             -row => 6,
212             -column => 4,
213             -sticky => 'nswe'
214             );
215             #-------------------------------------------------
216             $m->{button_upload} = $m->Button(
217             -text => 'Upload ->',
218             -command => [\&Upload, $m],
219             -state => 'disabled'
220             )->grid(
221             -row => 7,
222             -column => 0,
223             -columnspan => 2,
224             -sticky => 'nswe',
225             );
226             #-------------------------------------------------
227             $m->{button_compare} = $m->Button(
228             -text => 'Compare',
229             -command => [\&CompareDirectories, $m],
230             )->grid(
231             -row => 7,
232             -column => 2,
233             -columnspan => 2,
234             -sticky => 'nsew',
235             );
236             #-------------------------------------------------
237             $m->{button_download} = $m->Button(
238             -text => '<- Download',
239             -command => [\&Download, $m],
240             -state => 'disabled',
241             )->grid(
242             -row => 7,
243             -column => 4,
244             -columnspan => 2,
245             -sticky => 'nswe',
246             );
247             #-------------------------------------------------
248             $m->{childs} = {
249             'LabelUser' => $label_user,
250             'bEntryUser' => $m->{bentry_user},
251             'LabelFtpServer' => $label_ftpserver,
252             'bEntryFtpServer' => $m->{bentry_ftpserver},
253             'LabelPass' => $label_pass,
254             'EntryPass' => $m->{entry_pass},
255             'LabelLocalDir' => $label_local_dir,
256             'LabelRemoteDir' => $label_remote_dir,
257             'bEntryLocalDir' => $m->{bentry_local_dir},
258             'bEntryRemoteDir' => $m->{bentry_remote_dir},
259             'TreeLocalDir' => $m->{tree_local_dir},
260             'TreeRemoteDir' => $m->{tree_remote_dir},
261             'LabelOverwrite' => $m->{label_overwrite},
262             'rButtonNone' => $m->{rbutton_none},
263             'rButtonAll' => $m->{rbutton_all},
264             'rButtonOlder' => $m->{rbutton_older},
265             'ButtonUpload' => $m->{button_upload},
266             'ButtonCompare' => $m->{button_compare},
267             'ButtonDownload' => $m->{button_download},
268             };
269             $m->Advertise($_ => $m->{childs}{$_}) for(keys(%{$m->{childs}}));
270             $m->Delegates(
271             DEFAULT => $m->{tree_local_dir},
272             );
273             $m->InsertStoredValues();
274             }
275             #-------------------------------------------------
276             sub DESTROY
277             {
278             my ($self) = @_;
279             print($self || ref($self) . "object destroyed\n") if($self->{_debug});
280             }
281             #-------------------------------------------------
282             sub GetChilds
283             {
284             return $_[0]->{childs};
285             }
286             #-------------------------------------------------
287             sub SetParams
288             {
289             my ($self) = @_;
290             unless(-d $self->{para}{localdir})
291             {
292             $self->Dialog(
293             -text => "Localdirectory $self->{para}{localdir} not found",
294             -title => 'INPUT-ERROR'
295             )->Show();
296             return;
297             }
298             for(qw/user ftpserver pass remotedir/)
299             {
300             unless($self->{para}{$_})
301             {
302             $self->Dialog(
303             -text => "parameter: $_ undefined",
304             -title => 'INPUT-ERROR'
305             )->Show();
306             return;
307             }
308             }
309             $self->{upload}->SetUser($self->{para}{user});
310             $self->{upload}->SetFtpServer($self->{para}{ftpserver});
311             $self->{upload}->SetPass($self->{para}{pass});
312             $self->{upload}->SetLocalDir($self->{para}{localdir});
313             $self->{upload}->SetRemoteDir($self->{para}{remotedir});
314             $self->{download}->SetUser($self->{para}{user});
315             $self->{download}->SetFtpServer($self->{para}{ftpserver});
316             $self->{download}->SetPass($self->{para}{pass});
317             $self->{download}->SetLocalDir($self->{para}{localdir});
318             $self->{download}->SetRemoteDir($self->{para}{remotedir});
319             return 1;
320             }
321             #-------------------------------------------------
322             sub CompareDirectories
323             {
324             my ($self) = @_;
325             return unless($self->SetParams());
326             return unless($self->{upload}->Connect());
327             my $debug = $self->{upload}->GetDebug();
328             $self->StoreParams();
329             ($self->{rh_lf}, $self->{rh_ld}) = $self->{upload}->ReadLocalDir();
330             if($debug)
331             {
332             print("local files : $_\n") for(sort keys %{$self->{rh_lf}});
333             print("local dirs : $_\n") for(sort keys %{$self->{rh_ld}});
334             }
335             ($self->{rh_rf}, $self->{rh_rd}) = $self->{upload}->ReadRemoteDir();
336             if($debug)
337             {
338             print("remote files : $_\n") for(sort keys %{$self->{rh_rf}});
339             print("remote dirs : $_\n") for(sort keys %{$self->{rh_rd}});
340             };
341             $self->{ra_rfnil} = $self->{upload}->RemoteNotInLocal($self->{rh_lf}, $self->{rh_rf});
342             if($debug)
343             {
344             print("remote files not in local: $_\n") for(@{$self->{ra_rfnil}});
345             }
346             $self->{ra_rdnil} = $self->{upload}->RemoteNotInLocal($self->{rh_ld}, $self->{rh_rd});
347             if($debug)
348             {
349             print("remote dirs not in local: $_\n") for(@{$self->{ra_rdnil}});
350             }
351             $self->{ra_lfnir} = $self->{upload}->LocalNotInRemote($self->{rh_lf}, $self->{rh_rf});
352             if($debug)
353             {
354             print("local files not in remote : $_\n") for(@{$self->{ra_lfnir}});
355             }
356             $self->{ra_ldnir} = $self->{upload}->LocalNotInRemote($self->{rh_ld}, $self->{rh_rd});
357             if($debug)
358             {
359             print("new local dirs : $_\n") for(@{$self->{ra_ldnir}});
360             }
361             my $rh_temp_up = {};
362             %{$rh_temp_up} = %{$self->{rh_lf}};
363             delete(@{$rh_temp_up}{@{$self->{ra_lfnir}}});
364             $self->{ra_mlf} = $self->{upload}->CheckIfModified($rh_temp_up);
365             if($debug)
366             {
367             print("modified local files : $_\n") for(@{$self->{ra_mlf}});
368             }
369             my $rh_temp_down = {};
370             %{$rh_temp_down} = %{$self->{rh_rf}};
371             delete(@{$rh_temp_down}{@{$self->{ra_rfnil}}});
372             $self->{ra_mrf} = $self->{download}->CheckIfModified($rh_temp_down);
373             if($debug)
374             {
375             print("modified remote files : $_\n") for(@{$self->{ra_mrf}});
376             }
377             $self->{upload}->Quit();
378             $self->{button_upload}->configure(-state => 'normal');
379             $self->{button_download}->configure(-state => 'normal');
380             $self->InsertLocalTree();
381             $self->InsertRemoteTree();
382             return 1;
383             }
384             #-------------------------------------------------
385             sub InsertLocalTree
386             {
387             my ($self) = @_;
388             $self->{tree_local_dir}->delete('all');
389             $self->InsertPaths(
390             $self->{tree_local_dir},
391             [keys(%{$self->{rh_ld}}), keys(%{$self->{rh_lf}})]
392             );
393             $self->InsertLocalModifiedTimes([keys(%{$self->{rh_lf}})]);
394             $self->InsertProperties(
395             $self->{tree_local_dir},
396             $self->{ra_ldnir},
397             ''
398             );
399             $self->InsertProperties(
400             $self->{tree_local_dir},
401             $self->{ra_lfnir},
402             ''
403             );
404             $self->InsertProperties(
405             $self->{tree_local_dir},
406             $self->{ra_mlf},
407             ''
408             );
409             return 1;
410             }
411             #-------------------------------------------------
412             sub InsertRemoteTree
413             {
414             my ($self) = @_;
415             $self->{tree_remote_dir}->delete('all');
416             $self->InsertPaths(
417             $self->{tree_remote_dir},
418             [keys(%{$self->{rh_rd}}), keys(%{$self->{rh_rf}})]
419             );
420             $self->InsertRemoteModifiedTimes([keys(%{$self->{rh_rf}})]);
421             $self->InsertProperties(
422             $self->{tree_remote_dir},
423             $self->{ra_rdnil},
424             ''
425             );
426             $self->InsertProperties(
427             $self->{tree_remote_dir},
428             $self->{ra_rfnil},
429             ''
430             );
431             $self->InsertProperties(
432             $self->{tree_remote_dir},
433             $self->{ra_mrf},
434             ''
435             );
436             return 1;
437             }
438             #-------------------------------------------------
439             sub InsertPaths
440             {
441             my ($self, $tree, $ra_paths) = @_;
442             my ($full_path, $temp_path);
443             for(@$ra_paths)
444             {
445             $full_path = $_;
446             $full_path =~ s!^/+!!;
447             $temp_path = '';
448             for(split('/', $full_path))
449             {
450             $temp_path .= $_;
451             unless($tree->infoExists($temp_path))
452             {
453             $tree->add($temp_path, -text => $_,);
454             $tree->setmode($temp_path, 'close');
455             $tree->close($temp_path);
456             }
457             $temp_path .= '/';
458             }
459             }
460             return 1;
461             }
462             #-------------------------------------------------
463             sub InsertProperties
464             {
465             my ($self, $tree, $ra_paths, $pro) = @_;
466             my $path;
467             for(@$ra_paths)
468             {
469             $path = $_;
470             $path =~ s!^/+!!;
471             $tree->addchild($path, -text => $pro);
472             }
473             return 1;
474             }
475             #-------------------------------------------------
476             sub DeleteProperties
477             {
478             my ($self, $tree, $ra_paths) = @_;
479             my $path;
480             for(@$ra_paths)
481             {
482             $path = $_;
483             $path =~ s!^/+!!;
484             $tree->deleteSiblings($path);
485             }
486             return 1;
487             }
488             #-------------------------------------------------
489             sub InsertLocalModifiedTimes
490             {
491             my ($self, $ra_lf) = @_;
492             my $rh_last_mt = $self->{upload}->GetLast_Modified();
493             my $path;
494             for(@$ra_lf)
495             {
496             $path = $_;
497             $path =~ s!^/+!!;
498             if(-e $_)
499             {
500             $self->{tree_local_dir}->addchild(
501             $path,
502             -text => localtime((stat($_))[9]) . ' current'
503             );
504             }
505             if(defined($rh_last_mt->{$_}) && $rh_last_mt->{$_} =~ m/^\d+$/)
506             {
507             $self->{tree_local_dir}->addchild(
508             $path,
509             -text => localtime($rh_last_mt->{$_}) . ' last'
510             );
511             }
512             }
513             return 1;
514             }
515             #-------------------------------------------------
516             sub InsertRemoteModifiedTimes
517             {
518             my ($self, $ra_rf) = @_;
519             my $rh_last_mrt = $self->{download}->GetLast_Modified();
520             my $rh_current_mrt = $self->{download}->GetCurrent_Modified();
521             my $path;
522             for(@$ra_rf)
523             {
524             $path = $_;
525             $path =~ s!^/+!!;
526             if(defined($rh_current_mrt->{$_}) && $rh_current_mrt->{$_} =~ m/^\d+$/)
527             {
528             $self->{tree_remote_dir}->addchild(
529             $path,
530             -text => localtime($rh_current_mrt->{$_}) . ' current'
531             );
532             }
533             if(defined($rh_last_mrt->{$_}) && $rh_last_mrt->{$_} =~ m/^\d+$/)
534             {
535             $self->{tree_remote_dir}->addchild(
536             $path,
537             -text => localtime($rh_last_mrt->{$_}) . ' last'
538             );
539             }
540             }
541             return 1;
542             }
543             #-------------------------------------------------
544             sub DeletePaths
545             {
546             my ($self, $tree, $ra_paths) = @_;
547             my $path;
548             for(@$ra_paths)
549             {
550             $path = $_;
551             $path =~ s!^/+!!;
552             $tree->deleteEntry($path);
553             }
554             return 1;
555             }
556             #-------------------------------------------------
557             sub Download
558             {
559             my ($self) = @_;
560             return unless($self->SetParams());
561             return unless($self->{download}->Connect());
562             $self->{download}->MakeDirs($self->{ra_rdnil});
563             $self->{download}->StoreFiles($self->{ra_rfnil});
564             $self->{upload}->UpdateLastModified($self->{upload}->RtoL($self->{ra_rfnil}));
565             if($self->{overwrite} eq 'none')
566             {
567             $self->{ra_mrf} = [];
568             }
569             elsif($self->{overwrite} eq 'all')
570             {
571             $self->{download}->StoreFiles($self->{ra_mrf});
572             $self->{upload}->UpdateLastModified($self->{upload}->RtoL($self->{ra_mrf}));
573             }
574             elsif($self->{overwrite} eq 'older')
575             {
576             my $rh_current_mrt = $self->{download}->GetCurrent_Modified();
577             my $ra_lf = $self->{download}->RtoL($self->{ra_mrf});
578             my $ra_newer = [];
579             for(my $i = 0; $i <= $#{$self->{ra_mrf}}; $i++)
580             {
581             push(@$ra_newer, $_)
582             if(
583             defined($rh_current_mrt->{$self->{ra_mrf}[$i]})
584             && (-e $ra_lf->[$i])
585             && ($rh_current_mrt->{$self->{ra_mrf}[$i]} > (stat($ra_lf->[$i]))[9])
586             );
587             }
588             $self->{download}->StoreFiles($ra_newer);
589             $self->{upload}->UpdateLastModified($self->{upload}->RtoL($ra_newer));
590             @{$self->{ra_mrf}} = @$ra_newer;
591             }
592             else
593             {
594             $self->Dialog(
595             -text => "overwrite behavior: unknown",
596             -title => 'INPUT-ERROR'
597             )->Show();
598             return;
599             }
600             $self->{download}->Quit();
601             my $rh_ld = {};
602             %$rh_ld = %{$self->{rh_ld}};
603             my $rh_lf = {};
604             %$rh_lf = %{$self->{rh_lf}};
605             if($self->{download}->GetDelete())
606             {
607             $self->{download}->DeleteFiles($self->{ra_lfnir});
608             $self->{download}->RemoveDirs($self->{ra_ldnir});
609             delete(@{$rh_ld}{@{$self->{ra_ldnir}}});
610             delete(@{$rh_lf}{@{$self->{ra_lfnir}}});
611             }
612             # local tree
613             $self->{tree_local_dir}->deleteAll();
614             # old paths
615             $self->InsertPaths(
616             $self->{tree_local_dir},
617             [keys(%$rh_ld), keys(%$rh_lf)]
618             );
619             #new paths
620             $self->InsertPaths(
621             $self->{tree_local_dir},
622             $self->{download}->RtoL($_)
623             ) for($self->{ra_rdnil}, $self->{ra_rfnil});
624             $self->InsertProperties(
625             $self->{tree_local_dir},
626             $self->{download}->RtoL($_),
627             ''
628             ) for($self->{ra_rfnil}, $self->{ra_mrf});
629             $self->InsertProperties(
630             $self->{tree_local_dir},
631             $self->{download}->RtoL($self->{ra_rdnil}),
632             ''
633             );
634             # remote tree
635             $self->{tree_remote_dir}->deleteAll();
636             $self->InsertPaths(
637             $self->{tree_remote_dir},
638             [keys(%{$self->{rh_rd}}), keys(%{$self->{rh_rf}})]
639             );
640             $self->InsertProperties(
641             $self->{tree_remote_dir},
642             $_,
643             ''
644             ) for($self->{ra_rfnil}, $self->{ra_mrf});
645             $self->InsertProperties(
646             $self->{tree_remote_dir},
647             $self->{ra_rdnil},
648             ''
649             );
650             return 1;
651             }
652             #-------------------------------------------------
653             sub Upload
654             {
655             my ($self) = @_;
656             return unless($self->SetParams());
657             return unless($self->{upload}->Connect());
658             $self->{upload}->MakeDirs($self->{ra_ldnir});
659             $self->{upload}->StoreFiles($self->{ra_lfnir});
660             $self->{download}->UpdateLastModified($self->{download}->LtoR($self->{ra_lfnir}));
661             if($self->{overwrite} eq 'none')
662             {
663             $self->{ra_mlf} = [];
664             }
665             elsif($self->{overwrite} eq 'all')
666             {
667             $self->{upload}->StoreFiles($self->{ra_mlf});
668             $self->{download}->UpdateLastModified($self->{download}->LtoR($self->{ra_mlf}));
669             }
670             elsif($self->{overwrite} eq 'older')
671             {
672             my $rh_current_mrt = $self->{download}->GetCurrent_Modified();
673             my $ra_rf = $self->{upload}->LtoR($self->{ra_mlf});
674             my $ra_newer = [];
675             for(my $i = 0; $i <= $#{$self->{ra_mlf}}; $i++)
676             {
677             push(@$ra_newer, $_)
678             if(
679             defined($rh_current_mrt->{$ra_rf->[$i]})
680             && (-e $self->{ra_mlf}[$i])
681             && ($rh_current_mrt->{$ra_rf->[$i]} < (stat($self->{ra_mlf}[$i]))[9])
682             );
683             }
684             $self->{upload}->StoreFiles($ra_newer);
685             $self->{download}->UpdateLastModified($self->{download}->LtoR($ra_newer));
686             @{$self->{ra_mlf}} = @$ra_newer;
687             }
688             else
689             {
690             $self->Dialog(
691             -text => "overwrite behavior: unknown",
692             -title => 'INPUT-ERROR'
693             )->Show();
694             return;
695             }
696             my $rh_rd = {};
697             %$rh_rd = %{$self->{rh_rd}};
698             my $rh_rf = {};
699             %$rh_rf = %{$self->{rh_rf}};
700             if($self->{upload}->GetDelete())
701             {
702             $self->{upload}->DeleteFiles($self->{ra_rfnil});
703             $self->{upload}->RemoveDirs($self->{ra_rdnil});
704             delete(@{$rh_rd}{@{$self->{ra_rdnil}}});
705             delete(@{$rh_rf}{@{$self->{ra_rfnil}}});
706             $self->DeletePaths(
707             $self->{tree_remote_dir},
708             $_
709             ) for($self->{ra_rfnil}, $self->{ra_rdnil});
710             }
711             $self->{upload}->Quit();
712             # remote tree
713             $self->{tree_remote_dir}->deleteAll();
714             # old paths
715             $self->InsertPaths(
716             $self->{tree_remote_dir},
717             [keys(%$rh_rd), keys(%$rh_rf)]
718             );
719             # new paths
720             $self->InsertPaths(
721             $self->{tree_remote_dir},
722             $self->{upload}->LtoR($_)
723             ) for($self->{ra_ldnir}, $self->{ra_lfnir});
724             $self->InsertProperties(
725             $self->{tree_remote_dir},
726             $self->{upload}->LtoR($_),
727             ''
728             ) for($self->{ra_lfnir}, $self->{ra_mlf});
729             $self->InsertProperties(
730             $self->{tree_remote_dir},
731             $self->{upload}->LtoR($self->{ra_ldnir}),
732             ''
733             );
734             # local tree
735             $self->{tree_local_dir}->deleteAll();
736             $self->InsertPaths(
737             $self->{tree_local_dir},
738             [keys(%{$self->{rh_ld}}), keys(%{$self->{rh_lf}})]
739             );
740             $self->InsertProperties(
741             $self->{tree_local_dir},
742             $_,
743             ''
744             ) for($self->{ra_lfnir}, $self->{ra_mlf});
745             $self->InsertProperties(
746             $self->{tree_local_dir},
747             $self->{ra_ldnir},
748             ''
749             );
750             return 1;
751             }
752             #-------------------------------------------------
753             # $self->{para}{access}{attribute}{value} = [user, ftpserver, pass, localdir, remotedir];
754             #-------------------------------------------------
755             sub UpdateAccess
756             {
757             my ($self, $attr, $bentry, $value) = @_;
758             if(defined($self->{para}{access}{$attr}))
759             {
760             $self->{para}{user} = $self->{para}{access}{$attr}{$value}[0];
761             $self->{para}{ftpserver} = $self->{para}{access}{$attr}{$value}[1];
762             $self->{para}{pass} = $self->{para}{access}{$attr}{$value}[2];
763             $self->{para}{localdir} = $self->{para}{access}{$attr}{$value}[3];
764             $self->{para}{remotedir} = $self->{para}{access}{$attr}{$value}[4];
765             }
766             return 1;
767             }
768             #-------------------------------------------------
769             sub StoreParams
770             {
771             my ($self) = @_;
772             for(qw/user ftpserver pass localdir remotedir/)
773             {
774             $self->{para}{access}{$_}{$self->{para}{$_}} =
775             [
776             $self->{para}{user},
777             $self->{para}{ftpserver},
778             $self->{para}{pass},
779             $self->{para}{localdir},
780             $self->{para}{remotedir},
781             ];
782             }
783             store($self->{para}, 'para');
784             return 1;
785             }
786             #-------------------------------------------------
787             sub InsertStoredValues
788             {
789             my ($self) = @_;
790             $self->{bentry_user}->insert( 'end', $_) for(keys(%{$self->{para}{access}{user}}));
791             $self->{bentry_ftpserver}->insert( 'end', $_) for(keys(%{$self->{para}{access}{ftpserver}}));
792             $self->{bentry_local_dir}->insert( 'end', $_) for(keys(%{$self->{para}{access}{localdir}}));
793             $self->{bentry_remote_dir}->insert( 'end', $_) for(keys(%{$self->{para}{access}{remotedir}}));
794             return 1;
795             }
796             #-------------------------------------------------
797             1;
798             #-------------------------------------------------
799             __END__