| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | #$Id: filelist.pm 1001 2014-05-07 13:08:30Z pro $ $URL: svn://svn.setun.net/dcppp/trunk/lib/Net/DirectConnect/filelist.pm $ | 
| 2 |  |  |  |  |  |  |  | 
| 3 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 4 |  |  |  |  |  |  |  | 
| 5 |  |  |  |  |  |  | generate dc++ xml filelist | 
| 6 |  |  |  |  |  |  |  | 
| 7 |  |  |  |  |  |  | perl filelist.pm /path/to/dir | 
| 8 |  |  |  |  |  |  |  | 
| 9 |  |  |  |  |  |  | =cut | 
| 10 |  |  |  |  |  |  |  | 
| 11 |  |  |  |  |  |  | package    # no cpan | 
| 12 |  |  |  |  |  |  | Net::DirectConnect::filelist; | 
| 13 | 1 |  |  | 1 |  | 1636 | use 5.10.0; | 
|  | 1 |  |  |  |  | 4 |  | 
|  | 1 |  |  |  |  | 55 |  | 
| 14 | 1 |  |  | 1 |  | 6 | use strict; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 42 |  | 
| 15 | 1 |  |  | 1 |  | 6 | no strict qw(refs); | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 27 |  | 
| 16 | 1 |  |  | 1 |  | 5 | use warnings "NONFATAL" => "all"; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 141 |  | 
| 17 | 1 |  |  | 1 |  | 7 | no warnings qw(uninitialized); | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 47 |  | 
| 18 | 1 |  |  | 1 |  | 5 | no if $] >= 5.017011, warnings => 'experimental::smartmatch'; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 9 |  | 
| 19 | 1 |  |  | 1 |  | 60 | use utf8; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 10 |  | 
| 20 | 1 |  |  | 1 |  | 29 | use Encode; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 100 |  | 
| 21 | 1 |  |  | 1 |  | 5 | use Data::Dumper;    #dev only | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 72 |  | 
| 22 |  |  |  |  |  |  | $Data::Dumper::Sortkeys = $Data::Dumper::Useqq = $Data::Dumper::Indent = 1; | 
| 23 |  |  |  |  |  |  | #use Net::DirectConnect; | 
| 24 | 1 |  |  | 1 |  | 7 | use Net::DirectConnect::adc; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 129 |  | 
| 25 |  |  |  |  |  |  | our $VERSION = ( split( ' ', '$Revision: 1001 $' ) )[1]; | 
| 26 |  |  |  |  |  |  |  | 
| 27 |  |  |  |  |  |  | =tofix | 
| 28 |  |  |  |  |  |  | $0 =~ m|^(.+)[/\\].+?$|;                #v0 | 
| 29 |  |  |  |  |  |  | our $root_path ||= $1 . '/' if $1; | 
| 30 |  |  |  |  |  |  | $root_path =~ s|\\|/|g; | 
| 31 |  |  |  |  |  |  | warn "rp[$root_path]"; | 
| 32 |  |  |  |  |  |  |  | 
| 33 |  |  |  |  |  |  | eval "use lib '$root_path./stat/pslib'"; | 
| 34 |  |  |  |  |  |  | eval "use lib '$root_path./../../../examples/stat/pslib'; | 
| 35 |  |  |  |  |  |  | use psmisc; use pssql; | 
| 36 |  |  |  |  |  |  | use Net::DirectConnect; | 
| 37 |  |  |  |  |  |  | use base 'Net::DirectConnect'; | 
| 38 |  |  |  |  |  |  | "; #use Net::DirectConnect; | 
| 39 |  |  |  |  |  |  | #psmisc::use_try ('Net::DirectConnect'); | 
| 40 |  |  |  |  |  |  | =cut | 
| 41 |  |  |  |  |  |  |  | 
| 42 | 1 |  |  | 1 |  | 20 | use base 'Net::DirectConnect'; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 115 |  | 
| 43 |  |  |  |  |  |  | #use lib '../../../examples/stat/pslib';    # REMOVE | 
| 44 |  |  |  |  |  |  | #use lib 'stat/pslib';                      # REMOVE | 
| 45 | 1 |  |  | 1 |  | 7 | use lib::abs('pslib'); | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 11 |  | 
| 46 | 1 |  |  | 1 |  | 816 | use psmisc;    # REMOVE | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 58 |  | 
| 47 | 1 |  |  | 1 |  | 1921 | use pssql;     # REMOVE | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 5679 |  | 
| 48 |  |  |  |  |  |  | our %config; | 
| 49 |  |  |  |  |  |  | *config = *main::config; | 
| 50 |  |  |  |  |  |  | $config{ 'log_' . $_ } //= 0 for qw (dmp dcdmp dcdbg trace); | 
| 51 |  |  |  |  |  |  | $config{ 'log_' . $_ } //= 1 for qw (screen default); | 
| 52 |  |  |  |  |  |  | Net::DirectConnect::use_try 'Sys::Sendfile' unless $^O =~ /win/i; | 
| 53 |  |  |  |  |  |  | Net::DirectConnect::use_try 'Sys::Sendfile::FreeBSD' if $^O =~ /freebsd/i; | 
| 54 |  |  |  |  |  |  | #Net::DirectConnect::use_try 'IO::AIO'; | 
| 55 |  |  |  |  |  |  | my ( $tq, $rq, $vq ); | 
| 56 |  |  |  |  |  |  |  | 
| 57 |  |  |  |  |  |  | sub skip ($$) { | 
| 58 | 0 |  |  | 0 | 0 |  | my ( $file, $match ) = @_; | 
| 59 | 0 | 0 |  |  |  |  | return unless length $match; | 
| 60 |  |  |  |  |  |  | #say join ' ', ('skptst', $file, $match,); | 
| 61 | 0 | 0 |  |  |  |  | for my $m ( ref $match eq 'ARRAY' ? @$match : $match ) { | 
| 62 | 0 | 0 | 0 |  |  |  | return 1 if ref $m eq 'Regexp' and $file =~ $m; | 
| 63 | 0 | 0 | 0 |  |  |  | return 1 if !ref $m and $file eq $m; | 
| 64 |  |  |  |  |  |  | } | 
| 65 |  |  |  |  |  |  | } | 
| 66 |  |  |  |  |  |  |  | 
| 67 |  |  |  |  |  |  | sub new { | 
| 68 | 0 |  |  | 0 | 0 |  | my $standalone = !ref $_[0]; | 
| 69 | 0 | 0 |  |  |  |  | my $self = ref $_[0] ? shift() : bless {}, $_[0]; | 
| 70 | 0 | 0 |  |  |  |  | shift if $_[0] eq __PACKAGE__; | 
| 71 |  |  |  |  |  |  | #local %_ = @_; | 
| 72 |  |  |  |  |  |  | #$self->{$_} = $_{$_} for keys %_; | 
| 73 | 0 |  |  |  |  |  | $self->func(@_); | 
| 74 | 0 |  |  |  |  |  | $self->init_main(@_); | 
| 75 |  |  |  |  |  |  | $self->{'log'} //= sub (@) { | 
| 76 | 0 | 0 | 0 | 0 |  |  | my $dc = ref $_[0] ? shift : $self || {}; | 
| 77 |  |  |  |  |  |  | #print "PL[$_[0]]"; | 
| 78 | 0 |  |  |  |  |  | psmisc::printlog shift(), "[$dc->{'number'}]", @_,; | 
| 79 | 0 |  | 0 |  |  |  | },; | 
| 80 | 0 |  | 0 |  |  |  | $self->{no_sql} //= 0; | 
| 81 |  |  |  |  |  |  | # | 
| 82 |  |  |  |  |  |  | # adjustable | 
| 83 |  |  |  |  |  |  | # | 
| 84 | 0 |  | 0 |  |  |  | $self->{files}             //= 'files.xml'; | 
| 85 | 0 |  | 0 |  |  |  | $self->{tth_cheat}         //= 1_000_000;         #try find file with same name-size-date | 
| 86 | 0 |  | 0 |  |  |  | $self->{tth_cheat_no_date} //= 0;                 #--//-- only name-size | 
| 87 | 0 |  | 0 |  |  |  | $self->{file_min}          //= 0;                 #skip files  smaller | 
| 88 | 0 |  | 0 |  |  |  | $self->{filelist_scan}     //= 3600 * 1;          #every seconds, 0 to disable | 
| 89 | 0 |  | 0 |  |  |  | $self->{filelist_reload}   //= 300;               #check and load filelist if new, every seconds | 
| 90 | 0 |  | 0 |  |  |  | $self->{filelist_fork}     //= 1; | 
| 91 | 0 |  | 0 |  |  |  | $self->{file_send_by}      //= 1024 * 1024 * 1; | 
| 92 | 0 |  | 0 |  |  |  | $self->{skip_hidden}       //= 1; | 
| 93 | 0 |  | 0 |  |  |  | $self->{skip_symlink}      //= 0; | 
| 94 | 0 | 0 | 0 |  |  |  | $self->{skip_dir} //= [ qr'(?:^|/)Incomplete(?:/|$)', ( !$self->{skip_hidden} ? () : qr{(?:^|/)\.} ), ]; | 
| 95 | 0 | 0 | 0 |  |  |  | $self->{skip_file} //= | 
| 96 |  |  |  |  |  |  | [ qr/\.(?:partial|(?:dc)tmp)$/i, qr/^~uTorrentPartFile_/i, ( !$self->{skip_hidden} ? () : qr{(?:^|/)\.} ), ]; | 
| 97 |  |  |  |  |  |  | # $self->{sharesize_mul}  //= 3; # make share bigger * sharefiles_mul | 
| 98 |  |  |  |  |  |  | # $self->{sharesize_add}  //= 10_000_000_000; #add to share size virtual bytes | 
| 99 |  |  |  |  |  |  | # $self->{sharefiles_mul} //=3; #same for files for keeping size/files rate | 
| 100 |  |  |  |  |  |  | # $self->{sharefiles_add} //= 10_000; | 
| 101 |  |  |  |  |  |  | # $self->{no_auto_load_partial} //= 1; | 
| 102 |  |  |  |  |  |  | # | 
| 103 |  |  |  |  |  |  | # ========== | 
| 104 |  |  |  |  |  |  | # | 
| 105 |  |  |  |  |  |  | #$self->{share_full}        //= {}; | 
| 106 |  |  |  |  |  |  | #$self->{share_tth}         //= {}; | 
| 107 |  |  |  |  |  |  | ##$config{share_root} //= ''; | 
| 108 | 0 | 0 |  |  |  |  | $self->{'share'} = [ $self->{'share'} ] unless ref $self->{'share'}; | 
| 109 | 0 | 0 |  |  |  |  | tr{\\}{/} for @{ $self->{'share'} || [] }; | 
|  | 0 |  |  |  |  |  |  | 
| 110 | 0 |  |  |  |  |  | Net::DirectConnect::adc::func($self); | 
| 111 | 0 |  |  |  |  |  | $self->ID_get(); | 
| 112 |  |  |  |  |  |  | #$self->log('idr:', $self->{'INF'}{'ID'}); | 
| 113 |  |  |  |  |  |  | #$self->ID_get(); | 
| 114 | 0 | 0 |  |  |  |  | unless ( $self->{no_sql} ) { | 
| 115 |  |  |  |  |  |  | local %_ = ( | 
| 116 |  |  |  |  |  |  | 'driver' => 'sqlite', | 
| 117 |  |  |  |  |  |  | #'dbname' => 'files', | 
| 118 |  |  |  |  |  |  | 'database' => 'files', | 
| 119 |  |  |  |  |  |  | #'auto_connect'        => 1, | 
| 120 |  |  |  |  |  |  | #'log' => sub { shift if ref $_[0]; $self->log(@_) if $self }, | 
| 121 |  |  |  |  |  |  | 'log' => $self->{'log'}, | 
| 122 |  |  |  |  |  |  | #'cp_in'               => 'cp1251', | 
| 123 |  |  |  |  |  |  | 'connect_tries' => 0, 'connect_chain_tries' => 0, 'error_tries' => 0, 'error_chain_tries' => 0, | 
| 124 |  |  |  |  |  |  | #insert_by => 1000, | 
| 125 |  |  |  |  |  |  | #nav_all => 1, | 
| 126 |  |  |  |  |  |  | #{} | 
| 127 |  |  |  |  |  |  | #}, | 
| 128 |  |  |  |  |  |  | 'upgrade' => sub { | 
| 129 | 0 | 0 |  | 0 |  |  | my $db = shift if ref $_[0]; | 
| 130 |  |  |  |  |  |  | $db->do("ALTER TABLE filelist ADD COLUMN $_") | 
| 131 | 0 |  |  |  |  |  | for 'hit INTEGER UNSIGNED NOT NULL DEFAULT 0 ', 'sch INTEGER UNSIGNED NOT NULL DEFAULT 0 '; | 
| 132 |  |  |  |  |  |  | #$db->do("UPDATE filelist SET hit=0, sch=0 WHERE hit IS NULL"); | 
| 133 |  |  |  |  |  |  | }, | 
| 134 | 0 |  |  |  |  |  | ); | 
| 135 | 0 |  | 0 |  |  |  | $self->{sql}{$_} //= $_{$_} for keys %_; | 
| 136 | 0 |  |  |  |  |  | my ($short) = $self->{sql}{'driver'} =~ /mysql/; | 
| 137 | 0 | 0 |  |  |  |  | my %table = ( | 
|  |  | 0 |  |  |  |  |  | 
| 138 |  |  |  |  |  |  | 'filelist' => { | 
| 139 |  |  |  |  |  |  | 'path' => pssql::row( | 
| 140 |  |  |  |  |  |  | undef, | 
| 141 |  |  |  |  |  |  | 'type'    => 'VARCHAR', | 
| 142 |  |  |  |  |  |  | 'length'  => ( $short ? 150 : 255 ), | 
| 143 |  |  |  |  |  |  | 'default' => '', | 
| 144 |  |  |  |  |  |  | 'index'   => 1, | 
| 145 |  |  |  |  |  |  | 'primary' => 1 | 
| 146 |  |  |  |  |  |  | ), | 
| 147 |  |  |  |  |  |  | 'file' => pssql::row( | 
| 148 |  |  |  |  |  |  | undef, | 
| 149 |  |  |  |  |  |  | 'type'    => 'VARCHAR', | 
| 150 |  |  |  |  |  |  | 'length'  => ( $short ? 150 : 255 ), | 
| 151 |  |  |  |  |  |  | 'default' => '', | 
| 152 |  |  |  |  |  |  | 'index'   => 1, | 
| 153 |  |  |  |  |  |  | 'primary' => 1 | 
| 154 |  |  |  |  |  |  | ), | 
| 155 |  |  |  |  |  |  | 'tth'  => pssql::row( undef, 'type'        => 'VARCHAR', 'length' => 40, 'default' => '', 'index' => 1 ), | 
| 156 |  |  |  |  |  |  | 'size' => pssql::row( undef, 'type'        => 'BIGINT',  'index'  => 1, ), | 
| 157 |  |  |  |  |  |  | 'time' => pssql::row( 'time', ), #'index' => 1, | 
| 158 |  |  |  |  |  |  | #'added'  => pssql::row( 'added', ), | 
| 159 |  |  |  |  |  |  | #'exists' => pssql::row( undef, 'type' => 'SMALLINT', 'index' => 1, ), | 
| 160 |  |  |  |  |  |  | 'hit' => pssql::row( undef, 'type' => 'INTEGER UNSIGNED NOT NULL DEFAULT 0 ', ), | 
| 161 |  |  |  |  |  |  | 'sch' => pssql::row( undef, 'type' => 'INTEGER UNSIGNED NOT NULL DEFAULT 0', ), | 
| 162 |  |  |  |  |  |  | }, | 
| 163 |  |  |  |  |  |  | ); | 
| 164 | 0 | 0 |  |  |  |  | if ( $self->{db} ) { | 
| 165 |  |  |  |  |  |  | #warn 'preFL',Dumper $self->{db}{table}; #$config{'sql'}; | 
| 166 | 0 |  |  |  |  |  | $self->{db}{table}{$_} = $table{$_} for keys %table; | 
| 167 | 0 |  |  |  |  |  | $self->{db}{upgrade} = $_{upgrade}; | 
| 168 |  |  |  |  |  |  | } | 
| 169 | 0 |  |  |  |  |  | local %_ = ( 'table' => \%table, ); | 
| 170 | 0 |  | 0 |  |  |  | $self->{sql}{$_} //= $_{$_} for keys %_; | 
| 171 |  |  |  |  |  |  | #warn ('sqlore:',Data::Dumper::Dumper $self->{'sql'}, \%_), | 
| 172 | 0 | 0 | 0 |  |  |  | $self->{db} ||= pssql->new( %{ $self->{'sql'} || {} }, ); | 
|  | 0 |  |  |  |  |  |  | 
| 173 | 0 |  |  |  |  |  | ( $tq, $rq, $vq ) = $self->{db}->quotes(); | 
| 174 |  |  |  |  |  |  | #$self->log('db', Dumper $self->{db}); | 
| 175 |  |  |  |  |  |  | #$self->log('db', 'flist', $self->{db}); | 
| 176 |  |  |  |  |  |  | } | 
| 177 |  |  |  |  |  |  | $self->{filelist_make} //= sub { | 
| 178 | 0 | 0 |  | 0 |  |  | my $self = shift if ref $_[0]; | 
| 179 | 0 |  |  |  |  |  | my $notth; | 
| 180 | 0 | 0 |  |  |  |  | return unless psmisc::lock( 'sharescan', timeout => 0, old => 86400 ); | 
| 181 |  |  |  |  |  |  | #$self->log( 'err', "sorry, cant load Net::DirectConnect::TigerHash for hashing" ), $notth = 1, | 
| 182 |  |  |  |  |  |  | #  unless Net::DirectConnect::use_try 'Net::DirectConnect::TigerHash';    #( $INC{"Net/DirectConnect/TigerHash.pm"} ); | 
| 183 |  |  |  |  |  |  | #$self->log( 'info',"ntth=[$notth]");    exit; | 
| 184 | 0 | 0 |  |  |  |  | $self->log( 'err', 'forced db upgrade on make' ), $self->{db}->upgrade() if $self->{upgrade_force}; | 
| 185 | 0 |  |  |  |  |  | my $stopscan; | 
| 186 | 0 |  |  |  |  |  | my $level     = 0; | 
| 187 | 0 |  |  |  |  |  | my $levelreal = 0; | 
| 188 | 0 |  |  |  |  |  | my ( $sharesize, $sharefiles ); | 
| 189 | 0 |  |  |  |  |  | my $interrupted; | 
| 190 |  |  |  |  |  |  | my $printinfo = sub () { | 
| 191 | 0 |  |  |  |  |  | $self->log( 'sharesize', psmisc::human( 'size', $sharesize ), $sharefiles, scalar keys %{ $self->{share_full} } ); | 
|  | 0 |  |  |  |  |  |  | 
| 192 | 0 |  |  |  |  |  | }; | 
| 193 | 0 |  |  |  |  |  | local $SIG{INT} = sub { ++$stopscan; ++$interrupted; $self->log( 'warn', "INT rec, stopscan" ) }; | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 194 | 0 |  |  |  |  |  | local $SIG{INFO} = sub { $printinfo->(); }; | 
|  | 0 |  |  |  |  |  |  | 
| 195 |  |  |  |  |  |  | #$self->{'INF'}{'ID'} | 
| 196 | 0 | 0 |  |  |  |  | psmisc::file_rewrite $self->{files}, qq{ | 
| 197 |  |  |  |  |  |  | {'INF'}{'ID'} ? () : qq{CID="$self->{'INF'}{'ID'}" } ), | 
| 198 |  |  |  |  |  |  | qq{Base="/" Generator="Net::DirectConnect $Net::DirectConnect::VERSION"> | 
| 199 |  |  |  |  |  |  | }; | 
| 200 |  |  |  |  |  |  | # | 
| 201 |  |  |  |  |  |  | #}; | 
| 202 | 0 |  |  |  |  |  | my %o; | 
| 203 | 0 |  |  |  |  |  | my $o = sub { our $n; $o{ $_[0] } = ++$n; @_ }; | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 204 | 0 |  |  |  |  |  | our %table2filelist = ( | 
| 205 |  |  |  |  |  |  | $o->( file => 'Name' ), | 
| 206 |  |  |  |  |  |  | $o->( size => 'Size' ), | 
| 207 |  |  |  |  |  |  | $o->( tth  => 'TTH' ), | 
| 208 |  |  |  |  |  |  | $o->( time => 'TS' ), | 
| 209 |  |  |  |  |  |  | $o->( hit  => 'HIT' ), | 
| 210 |  |  |  |  |  |  | $o->( sch  => 'SCH' ) | 
| 211 |  |  |  |  |  |  | ); | 
| 212 |  |  |  |  |  |  | #warn Dumper   \%o, \%table2filelist; | 
| 213 |  |  |  |  |  |  | my $filelist_line = sub($) { | 
| 214 | 0 |  |  |  |  |  | for my $f (@_) { | 
| 215 | 0 | 0 | 0 |  |  |  | next if !length $f->{file} or !length $f->{'tth'}; | 
| 216 |  |  |  |  |  |  | #$f = {%$f}; | 
| 217 | 0 |  |  |  |  |  | $sharesize += $f->{size}; | 
| 218 | 0 | 0 |  |  |  |  | ++$sharefiles if $f->{size}; | 
| 219 |  |  |  |  |  |  | #$f->{file} = Encode::encode( 'utf8', Encode::decode( $self->{charset_fs}, $f->{file} ) ) if $self->{charset_fs}; | 
| 220 | 0 |  |  |  |  |  | psmisc::file_append $self->{files}, "\t" x $level, | 
| 221 |  |  |  |  |  |  | #qq{\n}; | 
| 222 |  |  |  |  |  |  | qq{ | 
| 223 | 0 |  |  |  |  |  | map { qq{ $table2filelist{$_}="} . psmisc::html_chars( $a = $f->{$_} ) . qq{"} } | 
| 224 | 0 | 0 |  |  |  |  | sort { $o{$a} <=> $o{$b} } grep { $table2filelist{$_} and $f->{$_} } keys %$f | 
|  | 0 |  |  |  |  |  |  | 
| 225 |  |  |  |  |  |  | ), | 
| 226 |  |  |  |  |  |  | qq{/>\n}; | 
| 227 |  |  |  |  |  |  | #$self->{share_full}{ $f->{tth} } = $f->{full} if $f->{tth};    $self->{share_full}{ $f->{file} } ||= $f->{full}; | 
| 228 | 0 |  | 0 |  |  |  | $f->{'full'} ||= $f->{'path'} . '/' . $f->{'file'}; | 
| 229 |  |  |  |  |  |  |  | 
| 230 |  |  |  |  |  |  | =cu | 
| 231 |  |  |  |  |  |  | $self->{share_full}{ $f->{'tth'} } = $f->{'full_local'}, $self->{share_tth}{ $f->{'full_local'} } = $f->{'tth'}, | 
| 232 |  |  |  |  |  |  | $self->{share_tth}{ $f->{'file'} } = $f->{'tth'}, | 
| 233 |  |  |  |  |  |  | if $f->{'tth'}; | 
| 234 |  |  |  |  |  |  | $self->{share_full}{ $f->{'file'} } ||= $f->{'full_local'}; | 
| 235 |  |  |  |  |  |  | =cut | 
| 236 |  |  |  |  |  |  |  | 
| 237 |  |  |  |  |  |  | #$self->log 'set share', "[$f->{file}], [$f->{tth}] = [$self->{share_full}{ $f->{tth} }],[$self->{share_full}{ $f->{file} }]"; | 
| 238 |  |  |  |  |  |  | #$self->log Dumper $self->{share_full}; | 
| 239 |  |  |  |  |  |  | } | 
| 240 | 0 |  |  |  |  |  | }; | 
| 241 | 0 |  |  |  |  |  | my $scandir; | 
| 242 |  |  |  |  |  |  | $scandir = sub (@) { | 
| 243 | 0 |  |  |  |  |  | for my $dir (@_) { | 
| 244 |  |  |  |  |  |  | #$self->log( 'scandir', $dir, 'charset', $self->{charset_fs} ); | 
| 245 |  |  |  |  |  |  | #$self->log( 'warn', 'stopscan', $stopscan), | 
| 246 | 0 | 0 |  |  |  |  | last if $stopscan; | 
| 247 | 0 |  |  |  |  |  | $dir =~ tr{\\}{/}; | 
| 248 | 0 |  |  |  |  |  | $dir =~ s{/+$}{}; | 
| 249 | 0 | 0 |  |  |  |  | opendir( my $dh, $dir ) or ( $self->log( 'err', "can't opendir [$dir]: $!\n" ), next ); | 
| 250 |  |  |  |  |  |  | #$self->log( 'dev','sd', __LINE__,$dh); | 
| 251 |  |  |  |  |  |  | #@dots = | 
| 252 | 0 |  |  |  |  |  | ( my $dirname = $dir ); | 
| 253 | 0 | 0 |  |  |  |  | $dirname = | 
| 254 |  |  |  |  |  |  | #Encode::encode 'utf8', | 
| 255 |  |  |  |  |  |  | Encode::decode $self->{charset_fs}, $dirname, Encode::FB_WARN if $self->{charset_fs}; | 
| 256 |  |  |  |  |  |  | #$self->log( 'dev','sd', __LINE__,$dh); | 
| 257 | 0 | 0 | 0 |  |  |  | next if skip( $dirname, $self->{skip_dir} ) or ( $self->{skip_symlink} and -l $dirname ); | 
|  |  |  | 0 |  |  |  |  | 
| 258 | 0 | 0 |  |  |  |  | unless ($level) { | 
| 259 | 0 |  |  |  |  |  | for ( split '/', $dirname ) { | 
| 260 | 0 | 0 |  |  |  |  | psmisc::file_append( $self->{files}, "\t" x $level, qq{\n} ), ++$level, if length $_; | 
| 261 |  |  |  |  |  |  | } | 
| 262 |  |  |  |  |  |  | } else { | 
| 263 | 0 |  |  |  |  |  | $dirname =~ | 
| 264 |  |  |  |  |  |  | #W s/^\w://; | 
| 265 |  |  |  |  |  |  | #$dirname =~ | 
| 266 |  |  |  |  |  |  | s{.*/}{}; | 
| 267 | 0 | 0 |  |  |  |  | psmisc::file_append( $self->{files}, "\t" x $level, qq{\n} ), ++$level, ++$levelreal, | 
| 268 |  |  |  |  |  |  | if length $dirname; | 
| 269 |  |  |  |  |  |  | } | 
| 270 |  |  |  |  |  |  | #$self->log( 'dev','sd', __LINE__,$dh); | 
| 271 |  |  |  |  |  |  | #Net::DirectConnect:: | 
| 272 | 0 |  | 0 |  |  |  | psmisc::schedule( [ 10, 10 ], our $my_every_10sec_sub__ ||= sub { $printinfo->() } ); | 
|  | 0 |  |  |  |  |  |  | 
| 273 |  |  |  |  |  |  | #$self->log( 'readdir', ); | 
| 274 | 0 |  |  |  |  |  | FILE: for my $file ( readdir($dh) ) { | 
| 275 |  |  |  |  |  |  | #$self->log( 'scanfile', $file, ); | 
| 276 |  |  |  |  |  |  | #$self->log( 'warn', 'stopscan', $stopscan), | 
| 277 | 0 | 0 |  |  |  |  | last if $stopscan; | 
| 278 | 0 | 0 |  |  |  |  | next if $file =~ /^\.\.?$/; | 
| 279 |  |  |  |  |  |  | #$file = Encode::encode( 'utf8', Encode::decode( $self->{charset_fs}, $file ) ) if $self->{charset_fs}; | 
| 280 | 0 |  |  |  |  |  | my $f = { path => $dir, path_local => $dir, file => $file, file_local => $file, full_local => "$dir/$file", }; | 
| 281 |  |  |  |  |  |  | #$f->{full_local} = "$f->{path_local}/$f->{file_local}"; | 
| 282 |  |  |  |  |  |  | #print("d $f->{full}:\n"), | 
| 283 | 0 |  |  |  |  |  | $f->{dir} = -d $f->{full_local}; | 
| 284 |  |  |  |  |  |  | #filelist_line($f), | 
| 285 | 0 | 0 |  |  |  |  | if ( $f->{dir} ) { | 
| 286 |  |  |  |  |  |  | #next  FILE if  skip ($f->{file}, $self->{skip_dir}); | 
| 287 | 0 |  |  |  |  |  | $scandir->( $f->{full_local} ); | 
| 288 | 0 |  |  |  |  |  | next; | 
| 289 |  |  |  |  |  |  | } | 
| 290 | 0 | 0 |  |  |  |  | $f->{size} = -s $f->{full_local} if -f $f->{full_local}; | 
| 291 | 0 | 0 |  |  |  |  | next if $f->{size} < $self->{file_min}; | 
| 292 | 0 | 0 |  |  |  |  | $f->{file} =    #Encode::encode 'utf8', | 
| 293 |  |  |  |  |  |  | Encode::decode $self->{charset_fs}, $f->{file}, Encode::FB_WARN if $self->{charset_fs}; | 
| 294 | 0 | 0 |  |  |  |  | $f->{path} =    #Encode::encode 'utf8', | 
| 295 |  |  |  |  |  |  | Encode::decode $self->{charset_fs}, $f->{path}, Encode::FB_WARN if $self->{charset_fs}; | 
| 296 | 0 | 0 | 0 |  |  |  | next FILE if skip( $f->{file}, $self->{skip_file} ) or ( $self->{skip_symlink} and -l $f->{file} ); | 
|  |  |  | 0 |  |  |  |  | 
| 297 |  |  |  |  |  |  | #$self->log( 'encfile', $f->{file} , "chs:$self->{charset_fs}"); | 
| 298 | 0 |  |  |  |  |  | $f->{full} = "$f->{path}/$f->{file}"; | 
| 299 | 0 |  |  |  |  |  | $f->{time} = int( $^T - 86400 * -M $f->{full_local} );    #time() - | 
| 300 |  |  |  |  |  |  | #$self->log 'timed', $f->{time}, psmisc::human('date_time', $f->{time}), -M $f->{full_local}, int (86400 * -M $f->{full_local}), $^T; | 
| 301 |  |  |  |  |  |  | #'res=', | 
| 302 |  |  |  |  |  |  | #join "\n",     grep { !/^\.\.?/ and | 
| 303 |  |  |  |  |  |  | #/^\./ &&     -f "$dir/$_"     } | 
| 304 |  |  |  |  |  |  | #print " ", $file; | 
| 305 |  |  |  |  |  |  | #todo - select not all cols | 
| 306 |  |  |  |  |  |  | #         $self->log('preselect', $self->{no_sql}); | 
| 307 | 0 | 0 |  |  |  |  | unless ( $self->{no_sql} ) { | 
| 308 |  |  |  |  |  |  | #$self->log('select go',);# Dumper $f); | 
| 309 | 0 |  |  |  |  |  | my $indb = | 
| 310 |  |  |  |  |  |  | $self->{db}->line( "SELECT * FROM ${tq}filelist${tq} WHERE" | 
| 311 |  |  |  |  |  |  | . " ${rq}path${rq}=" | 
| 312 |  |  |  |  |  |  | . $self->{db}->quote( $f->{path} ) | 
| 313 |  |  |  |  |  |  | . " AND ${rq}file${rq}=" | 
| 314 |  |  |  |  |  |  | . $self->{db}->quote( $f->{file} ) | 
| 315 |  |  |  |  |  |  | . " AND ${rq}size${rq}=" | 
| 316 |  |  |  |  |  |  | . $self->{db}->quote( $f->{size} ) | 
| 317 |  |  |  |  |  |  | . " AND ${rq}time${rq}=" | 
| 318 |  |  |  |  |  |  | . $self->{db}->quote( $f->{time} ) | 
| 319 |  |  |  |  |  |  | . " LIMIT 1" ); | 
| 320 |  |  |  |  |  |  | #$self->log('select', Dumper $indb); | 
| 321 |  |  |  |  |  |  | #$self->log ('dev', 'already scaned', $indb->{size}), | 
| 322 | 0 | 0 |  |  |  |  | $filelist_line->( { %$f, %$indb } ), next, if $indb->{size} ~~ $f->{size}; | 
| 323 |  |  |  |  |  |  | #$db->select('filelist', {path=>$f->{path},file=>$f->{file}, }); | 
| 324 |  |  |  |  |  |  | #$self->log Dumper ; | 
| 325 |  |  |  |  |  |  | #print "\n"; | 
| 326 |  |  |  |  |  |  | #my $tth; | 
| 327 | 0 | 0 |  |  |  |  | if ( $f->{size} > $self->{tth_cheat} ) { | 
| 328 | 0 | 0 |  |  |  |  | my $indb = | 
| 329 |  |  |  |  |  |  | $self->{db}->line( "SELECT * FROM ${tq}filelist${tq} WHERE " | 
| 330 |  |  |  |  |  |  | . "${rq}file${rq}=" | 
| 331 |  |  |  |  |  |  | . $self->{db}->quote( $f->{file} ) | 
| 332 |  |  |  |  |  |  | . " AND ${rq}size${rq}=" | 
| 333 |  |  |  |  |  |  | . $self->{db}->quote( $f->{size} ) | 
| 334 |  |  |  |  |  |  | . ( $self->{tth_cheat_no_date} ? () : " AND ${rq}time${rq}=" . $self->{db}->quote( $f->{time} ) ) | 
| 335 |  |  |  |  |  |  | . " LIMIT 1" ); | 
| 336 |  |  |  |  |  |  | #$self->log 'sel', Dumper $indb; | 
| 337 | 0 | 0 |  |  |  |  | if ( $indb->{tth} ) { | 
| 338 | 0 |  |  |  |  |  | $self->log( 'dev', "already summed", %$f, '     as    ', %$indb ); | 
| 339 | 0 |  | 0 |  |  |  | $f->{$_} ||= $indb->{$_} for keys %$indb; | 
| 340 |  |  |  |  |  |  | #filelist_line($f); | 
| 341 |  |  |  |  |  |  | #next; | 
| 342 |  |  |  |  |  |  | } | 
| 343 |  |  |  |  |  |  | } | 
| 344 |  |  |  |  |  |  | } | 
| 345 | 0 | 0 | 0 |  |  |  | if ( !$notth and !$f->{tth} ) { | 
| 346 |  |  |  |  |  |  | #$self->log 'calc', $f->{full}, "notth=[$notth]"; | 
| 347 | 0 |  |  |  |  |  | my $time = time(); | 
| 348 | 0 |  |  |  |  |  | $f->{tth} = $self->hash_file( $f->{full_local} ); | 
| 349 | 0 |  |  |  |  |  | my $per = time - $time; | 
| 350 | 0 | 0 | 0 |  |  |  | $self->log( | 
| 351 |  |  |  |  |  |  | 'time', $f->{full}, psmisc::human( 'size', $f->{size} ), | 
| 352 |  |  |  |  |  |  | 'per', psmisc::human( 'time_period', $per ), | 
| 353 |  |  |  |  |  |  | 'speed ps', psmisc::human( 'size', $f->{size} / ( $per or 1 ) ), | 
| 354 |  |  |  |  |  |  | 'total', psmisc::human( 'size', $sharesize ) | 
| 355 |  |  |  |  |  |  | ) | 
| 356 |  |  |  |  |  |  | if | 
| 357 |  |  |  |  |  |  | #$f->{size} > 100_000 or | 
| 358 |  |  |  |  |  |  | $per > 1; | 
| 359 |  |  |  |  |  |  | } | 
| 360 |  |  |  |  |  |  | #$f->{tth} = $f->{size} > 1_000_000 ? 'bigtth' : tthfile( $f->{full} );    #if -f $full; | 
| 361 |  |  |  |  |  |  | #print Dumper $self->{share_full}; | 
| 362 |  |  |  |  |  |  | #next; | 
| 363 |  |  |  |  |  |  | #print ' ', tthfile($full) if -f $full ; #and -s $full < 1_000_000; | 
| 364 |  |  |  |  |  |  | #print ' ', $f->{tth}; | 
| 365 |  |  |  |  |  |  | #print ' ', $f->{size};    #if -f $f->{full}; | 
| 366 |  |  |  |  |  |  | #print join ':',-M $f->{full}, $^T + 86400 * -M $f->{full},$f->{time}; | 
| 367 |  |  |  |  |  |  | #print "\n"; | 
| 368 | 0 |  |  |  |  |  | $filelist_line->($f); | 
| 369 | 0 | 0 | 0 |  |  |  | $self->{db}->insert_hash( 'filelist', $f ) if !$self->{no_sql} and $f->{tth}; | 
| 370 |  |  |  |  |  |  | } | 
| 371 | 0 |  |  |  |  |  | --$level; | 
| 372 | 0 |  |  |  |  |  | --$levelreal; | 
| 373 | 0 |  |  |  |  |  | psmisc::file_append $self->{files}, "\t" x $level, qq{\n};    # | 
| 374 | 0 |  |  |  |  |  | closedir $dh; | 
| 375 |  |  |  |  |  |  | } | 
| 376 | 0 | 0 |  |  |  |  | if ( $levelreal < 0 ) { | 
| 377 |  |  |  |  |  |  | #psmisc::file_append $self->{files}, "\n"; | 
| 378 | 0 |  |  |  |  |  | psmisc::file_append $self->{files}, "\t" x $level, qq{\n} while --$level >= 0; | 
| 379 | 0 |  |  |  |  |  | $levelreal = $level = 0; | 
| 380 |  |  |  |  |  |  | } | 
| 381 |  |  |  |  |  |  | #$level | 
| 382 | 0 |  |  |  |  |  | }; | 
| 383 |  |  |  |  |  |  | #else { | 
| 384 | 0 | 0 |  |  |  |  | $self->log( | 
| 385 |  |  |  |  |  |  | 'info', "making filelist $self->{files} from", | 
| 386 | 0 |  |  |  |  |  | @_, @{ $self->{'share'} || [] }, | 
| 387 |  |  |  |  |  |  | 'EXISTS=', | 
| 388 | 0 | 0 |  |  |  |  | grep { -d } @_, | 
| 389 | 0 |  |  |  |  |  | @{ $self->{'share'} || [] }, | 
| 390 |  |  |  |  |  |  | ); | 
| 391 |  |  |  |  |  |  | #$self->{db}->do('ANALYZE filelist') unless $self->{no_sql}; | 
| 392 | 0 | 0 |  |  |  |  | $self->{db}->analyze('filelist') unless $self->{no_sql}; | 
| 393 | 0 |  |  |  |  |  | local %_; | 
| 394 | 0 | 0 |  |  |  |  | $scandir->($_) for ( grep { !$_{$_}++ and -d } @_, @{ $self->{'share'} || [] }, ); | 
|  | 0 | 0 |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 395 |  |  |  |  |  |  | #undef $SIG{INT}; | 
| 396 |  |  |  |  |  |  | #undef $SIG{INFO}; | 
| 397 | 0 |  |  |  |  |  | psmisc::file_append $self->{files}, qq{}; | 
| 398 | 0 |  |  |  |  |  | psmisc::file_append $self->{files}; | 
| 399 | 0 | 0 |  |  |  |  | $self->{db}->flush_insert() unless $self->{no_sql}; | 
| 400 | 0 |  |  |  |  |  | local $_; | 
| 401 | 0 | 0 | 0 |  |  |  | if ( | 
|  |  |  | 0 |  |  |  |  | 
| 402 |  |  |  |  |  |  | psmisc::use_try 'IO::Compress::Bzip2' | 
| 403 |  |  |  |  |  |  | and ($_ = !IO::Compress::Bzip2::bzip2( $self->{files} => $self->{files} . '.bz2' ) | 
| 404 |  |  |  |  |  |  | or $self->log( "bzip2 failed: ", $IO::Compress::Bzip2::Bzip2Error ) and 0 ) | 
| 405 |  |  |  |  |  |  | ) | 
| 406 |  |  |  |  |  |  | { | 
| 407 |  |  |  |  |  |  | #$self->log('bzip',$self->{files} => $self->{files} . '.bz2'); | 
| 408 | 0 |  |  |  |  |  | () = $IO::Compress::Bzip2::Bzip2Error;    #no warning | 
| 409 |  |  |  |  |  |  | } else { | 
| 410 | 0 |  |  |  |  |  | $self->log( 'dev', 'using system bzip2', $_, $!, ':', `bzip2 --force --keep "$self->{files}"` ); | 
| 411 |  |  |  |  |  |  | } | 
| 412 |  |  |  |  |  |  | #unless $interrupted; | 
| 413 |  |  |  |  |  |  | #$self->{share_full}{ $self->{files} . '.bz2' } = $self->{files} . '.bz2';  $self->{share_full}{ $self->{files} } = $self->{files}; | 
| 414 |  |  |  |  |  |  | #} | 
| 415 | 0 |  |  |  |  |  | psmisc::unlock('sharescan'); | 
| 416 | 0 |  |  |  |  |  | $printinfo->(); | 
| 417 |  |  |  |  |  |  | #$SIG{INT} = $SIG{KILL} = undef; | 
| 418 | 0 |  |  |  |  |  | return ( $sharesize, $sharefiles ); | 
| 419 | 0 |  | 0 |  |  |  | }; | 
| 420 |  |  |  |  |  |  | $self->{share_add_file} //= sub { | 
| 421 | 0 | 0 |  | 0 |  |  | my $self = shift if ref $_[0]; | 
| 422 | 0 |  |  |  |  |  | my ( $full_local, $tth, $file ) = @_; | 
| 423 | 0 | 0 |  |  |  |  | $full_local =~ m{([^/\\]+)$} unless $file; | 
| 424 | 0 |  | 0 |  |  |  | $file //= $1;    # unless length $file; | 
| 425 |  |  |  |  |  |  | #$full_local = Encode::encode $self->{charset_fs}, Encode::decode 'utf8', $full_local; | 
| 426 | 0 | 0 |  |  |  |  | $self->{share_full}{$tth} = $full_local, $self->{share_tth}{$full_local} = $tth, $self->{share_tth}{$file} = $tth, if $tth; | 
| 427 | 0 | 0 | 0 |  |  |  | $self->{share_full}{$file} ||= $full_local if $file; | 
| 428 |  |  |  |  |  |  | #$self->share_changed(); | 
| 429 | 0 |  | 0 |  |  |  | }; | 
| 430 |  |  |  |  |  |  | $self->{share_changed} //= sub { | 
| 431 | 0 | 0 |  | 0 |  |  | my $self = shift if ref $_[0]; | 
| 432 |  |  |  |  |  |  | #$self->log('dev', "share_changed"); | 
| 433 | 0 | 0 |  |  |  |  | if ( $self->{'status'} eq 'connected' ) { | 
| 434 | 0 | 0 |  |  |  |  | if ( $self->{adc} ) { $self->cmd( 'I', 'INF', undef, 'SS', 'SF' ); } | 
|  | 0 |  |  |  |  |  |  | 
| 435 | 0 |  |  |  |  |  | else                { $self->cmd('MyINFO'); } | 
| 436 |  |  |  |  |  |  | } | 
| 437 | 0 |  | 0 |  |  |  | }; | 
| 438 |  |  |  |  |  |  | $self->{filelist_load} //= sub {    #{'cmd'} | 
| 439 | 0 | 0 |  | 0 |  |  | my $self = shift if ref $_[0]; | 
| 440 | 0 | 0 |  |  |  |  | $self->log( 'err', 'forced db upgrade on load' ), $self->{db}->upgrade() if $self->{upgrade_force}; | 
| 441 |  |  |  |  |  |  |  | 
| 442 |  |  |  |  |  |  | =old | 
| 443 |  |  |  |  |  |  | if ( $config{filelist} and open my $f, '<', $config{filelist} ) { | 
| 444 |  |  |  |  |  |  | $self->log "loading filelist.."; | 
| 445 |  |  |  |  |  |  | local $/ = '<'; | 
| 446 |  |  |  |  |  |  | while (<$f>) { | 
| 447 |  |  |  |  |  |  | if ( my ( $file, $time, $tiger ) = /^File Name="([^"]+)" TimeStamp="(\d+)" Root="([^"]+)"/i ) { | 
| 448 |  |  |  |  |  |  | #$self->{'share_tth'}{ $params->{TR} } | 
| 449 |  |  |  |  |  |  | $file =~ tr{\\}{/}; | 
| 450 |  |  |  |  |  |  | $self->{share_full}{$tiger} = $file; | 
| 451 |  |  |  |  |  |  | $self->{share_tth}{$file}   = $tiger; | 
| 452 |  |  |  |  |  |  | } | 
| 453 |  |  |  |  |  |  | # | 
| 454 |  |  |  |  |  |  | } | 
| 455 |  |  |  |  |  |  | close $f; | 
| 456 |  |  |  |  |  |  | $self->log ".done:", ( scalar keys %{ $self->{share_full} } ), "\n"; | 
| 457 |  |  |  |  |  |  | } | 
| 458 |  |  |  |  |  |  | =cut | 
| 459 |  |  |  |  |  |  |  | 
| 460 |  |  |  |  |  |  | #$self->log( "filelist_load try", $global{shareloaded}, -s $self->{files}, );    #ref $_[0] | 
| 461 |  |  |  |  |  |  | return | 
| 462 | 0 | 0 | 0 |  |  |  | if !$self->{files} | 
|  |  |  | 0 |  |  |  |  | 
|  |  |  | 0 |  |  |  |  | 
|  |  |  | 0 |  |  |  |  | 
| 463 |  |  |  |  |  |  | or $Net::DirectConnect::global{shareloaded} == -s $self->{files} | 
| 464 |  |  |  |  |  |  | or | 
| 465 |  |  |  |  |  |  | ( $Net::DirectConnect::global{shareloaded} and !psmisc::lock( 'sharescan', readonly => 1, timeout => 0, old => 86400 ) ) | 
| 466 |  |  |  |  |  |  | or !open my $f, '<:encoding(utf8)', $self->{files}; | 
| 467 | 0 |  |  |  |  |  | my ( $sharesize, $sharefiles ); | 
| 468 |  |  |  |  |  |  | #$self->log( 'info', "loading filelist", -s $f ); | 
| 469 | 0 |  |  |  |  |  | $Net::DirectConnect::global{shareloaded} = -s $f; | 
| 470 | 0 |  |  |  |  |  | local $/ = '<'; | 
| 471 | 0 |  |  |  |  |  | %{ $self->{share_full} } = %{ $self->{share_tth} } = (); | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 472 | 0 |  |  |  |  |  | my $dir; | 
| 473 | 0 |  |  |  |  |  | while (<$f>) { | 
| 474 |  |  |  |  |  |  | # | 
| 475 |  |  |  |  |  |  | # | 
| 476 | 0 | 0 |  |  |  |  | if ( my ( $file, $size, $tth, $ts ) = m{^File Name="([^"]+)" Size="(\d+)" TTH="([^"]+)"}i ) { | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 477 | 0 |  |  |  |  |  | my $full_local = ( my $full = "$dir/$file" ); | 
| 478 |  |  |  |  |  |  | #$self->log 'loaded', $dir, $file  , $full; | 
| 479 |  |  |  |  |  |  | #$full_local = Encode::encode $self->{charset_fs}, $full if $self->{charset_fs}; | 
| 480 | 0 |  |  |  |  |  | $full_local = Encode::encode $self->{charset_fs}, | 
| 481 |  |  |  |  |  |  | #Encode::decode 'utf8', | 
| 482 |  |  |  |  |  |  | $full_local, Encode::FB_WARN; | 
| 483 | 0 |  |  |  |  |  | $self->share_add_file( $full_local, $tth, $file ); | 
| 484 | 0 |  |  |  |  |  | ++$sharefiles; | 
| 485 | 0 |  |  |  |  |  | $sharesize += $size; | 
| 486 |  |  |  |  |  |  | #$self->{'share_tth'}{ $params->{TR} } | 
| 487 |  |  |  |  |  |  | #$file =~ tr{\\}{/}; | 
| 488 |  |  |  |  |  |  | } elsif ( my ($curdir) = m{^Directory Name="([^"]+)">}i ) {    #"mcedit | 
| 489 | 0 | 0 | 0 |  |  |  | $dir .= ( ( !length $dir and $^O ~~ [ 'MSWin32', 'cygwin' ] ) ? () : '/' ) . $curdir; | 
| 490 |  |  |  |  |  |  | #$self->log 'now in', $dir; | 
| 491 |  |  |  |  |  |  | #$self->{files} | 
| 492 |  |  |  |  |  |  | } elsif (m{^/Directory>}i) { | 
| 493 | 0 |  |  |  |  |  | $dir =~ s{(?:^|/)[^/]+$}{}; | 
| 494 |  |  |  |  |  |  | #$self->log 'now ba', $dir; | 
| 495 |  |  |  |  |  |  | } | 
| 496 |  |  |  |  |  |  | } | 
| 497 | 0 |  |  |  |  |  | $self->{share_full}{ $self->{files} . '.bz2' } = $self->{files} . '.bz2'; | 
| 498 | 0 |  |  |  |  |  | $self->{share_full}{ $self->{files} } = $self->{files}; | 
| 499 |  |  |  |  |  |  | #    $self->{'INF'}{'SS'} = $self->{'sharesize'} = $sharesize; | 
| 500 |  |  |  |  |  |  | #    $self->{'INF'}{'SF'} = $sharefiles; | 
| 501 | 0 |  |  |  |  |  | $self->log( | 
| 502 |  |  |  |  |  |  | 'info', | 
| 503 |  |  |  |  |  |  | "loaded filelist size", | 
| 504 |  |  |  |  |  |  | $Net::DirectConnect::global{shareloaded}, | 
| 505 |  |  |  |  |  |  | ' : files=', $sharefiles, 'bytes=', | 
| 506 |  |  |  |  |  |  | psmisc::human( 'size', $sharesize ), | 
| 507 | 0 |  |  |  |  |  | scalar keys %{ $self->{share_full} }, | 
| 508 |  |  |  |  |  |  | "bzsize=", -s $self->{files} . '.bz2', | 
| 509 |  |  |  |  |  |  | ); | 
| 510 | 0 |  |  |  |  |  | psmisc::unlock('sharescan'); | 
| 511 |  |  |  |  |  |  | #$_[0]->( $sharesize, $sharefiles ) if ref $_[0] ~~ 'CODE'; | 
| 512 |  |  |  |  |  |  | #( $self->{share_size} , $self->{share_files} ) = ( $sharesize, $sharefiles ); | 
| 513 | 0 | 0 |  |  |  |  | $sharefiles *= $self->{sharefiles_mul} if $self->{sharefiles_mul}; | 
| 514 | 0 |  |  |  |  |  | $sharefiles += $self->{sharefiles_add}; | 
| 515 | 0 | 0 |  |  |  |  | $sharesize *= $self->{sharesize_mul} if $self->{sharesize_mul}; | 
| 516 | 0 |  |  |  |  |  | $sharesize += $self->{sharesize_add}; | 
| 517 | 0 | 0 |  |  |  |  | $self->{sharefiles} = $self->{INF}{SF} = $sharefiles, $self->{INF}{SS} = $self->{sharesize} = $sharesize, if $sharesize; | 
| 518 | 0 |  |  |  |  |  | $self->share_changed(); | 
| 519 | 0 |  |  |  |  |  | return ( $sharesize, $sharefiles ); | 
| 520 | 0 |  | 0 |  |  |  | }; | 
| 521 |  |  |  |  |  |  | $self->{search_stat_update} = sub { | 
| 522 | 0 | 0 |  | 0 |  |  | my $self = shift if ref $_[0]; | 
| 523 | 0 | 0 |  |  |  |  | my $tth = shift or return; | 
| 524 | 0 |  | 0 |  |  |  | my $field = shift || 'hit'; | 
| 525 | 0 | 0 |  |  |  |  | my $updated = $self->{db}->do( | 
| 526 |  |  |  |  |  |  | "UPDATE ${tq}filelist${tq} SET ${rq}$field${rq}=${rq}$field${rq}+${vq}1${vq} WHERE " | 
| 527 |  |  |  |  |  |  | #$self->{db}->do( "UPDATE ${tq}filelist${tq} SET ${rq}$field${rq}=${rq}$field${rq}+1 WHERE " | 
| 528 |  |  |  |  |  |  | #$self->{db}->do( "UPDATE ${tq}filelist${tq} SET $field=$field+1 WHERE " | 
| 529 |  |  |  |  |  |  | . "${rq}tth${rq}=" . $self->{db}->quote($tth) | 
| 530 |  |  |  |  |  |  | #. ( $self->{db}{no_update_limit} ? () : " LIMIT ${vq}2${vq}" ) ); | 
| 531 |  |  |  |  |  |  | . ( $self->{db}{no_update_limit} ? () : " LIMIT 1" ) | 
| 532 |  |  |  |  |  |  | ); | 
| 533 | 0 | 0 |  |  |  |  | $self->log( 'dev', "counter $field increased[$updated] on [$tth]" ) if $updated; | 
| 534 | 0 |  |  |  |  |  | }; | 
| 535 |  |  |  |  |  |  | $self->{handler_int}{Search} //= sub { | 
| 536 | 0 | 0 |  | 0 |  |  | my $self = shift if ref $_[0]; | 
| 537 |  |  |  |  |  |  | #$self->log ( 'dev', 'Search stat', Dumper @_) ; | 
| 538 |  |  |  |  |  |  | #$self->log ( 'dev', 'Search stat', Dumper $_[1]{tth}) ; | 
| 539 | 0 |  |  |  |  |  | $self->search_stat_update( $_[1]{tth}, 'sch' ); | 
| 540 | 0 |  | 0 |  |  |  | }; | 
| 541 |  |  |  |  |  |  | $self->{handler_int}{SCH} //= sub { | 
| 542 | 0 | 0 |  | 0 |  |  | my $self = shift if ref $_[0]; | 
| 543 |  |  |  |  |  |  | #$self->log ( 'dev', 'SCH stat', Dumper @_) ; | 
| 544 | 0 |  |  |  |  |  | $self->search_stat_update( $_[-1]{TR}, 'sch' ); | 
| 545 | 0 |  | 0 |  |  |  | }; | 
| 546 |  |  |  |  |  |  | $self->{'periodic'}{ __FILE__ . __LINE__ } = sub { | 
| 547 | 0 | 0 |  | 0 |  |  | my $self = shift if ref $_[0]; | 
| 548 |  |  |  |  |  |  | #$self->log (  'periodic in filelist', $self->{filelist_scan}, caller ); | 
| 549 |  |  |  |  |  |  | psmisc::schedule( | 
| 550 |  |  |  |  |  |  | #[10, $self->{filelist_scan}], | 
| 551 |  |  |  |  |  |  | $self->{filelist_scan}, | 
| 552 |  |  |  |  |  |  | our $sharescan_sub__ ||= sub { | 
| 553 | 0 |  |  |  |  |  | my $self = shift; | 
| 554 | 0 |  |  |  |  |  | $self->log( | 
| 555 |  |  |  |  |  |  | 'info', | 
| 556 |  |  |  |  |  |  | 'filelist actual age seconds:', | 
| 557 |  |  |  |  |  |  | ( time - $^T + 86400 * -M $self->{files} ), | 
| 558 |  |  |  |  |  |  | '<', $self->{filelist_scan} | 
| 559 |  |  |  |  |  |  | ); | 
| 560 |  |  |  |  |  |  | return | 
| 561 | 0 | 0 | 0 |  |  |  | if -e $self->{files} | 
|  |  |  | 0 |  |  |  |  | 
| 562 |  |  |  |  |  |  | and -s $self->{files} > 200 | 
| 563 |  |  |  |  |  |  | and $self->{filelist_scan} > time - $^T + 86400 * -M $self->{files}; | 
| 564 |  |  |  |  |  |  | #$self->log( 'starter==','$0=',$0, $INC{'Net/DirectConnect/filelist.pm'}, $^X, 'share=', @{ $self->{'share'} } ); | 
| 565 |  |  |  |  |  |  | #$0 !~ m{(.*\W)?share.pl$} | 
| 566 | 0 |  |  |  |  |  | !$self->{'filelist_fork'} | 
| 567 |  |  |  |  |  |  | ? $self->filelist_make() | 
| 568 | 0 |  |  |  |  |  | : $self->{'filelist_builder'} ? psmisc::start $self->{'filelist_builder'}, @{ $self->{'share'} } : psmisc::start $^X, | 
| 569 | 0 | 0 |  |  |  |  | $INC{'Net/DirectConnect/filelist.pm'}, @{ $self->{'share'} }; | 
|  |  | 0 |  |  |  |  |  | 
| 570 |  |  |  |  |  |  | #: psmisc::startme( 'filelist', grep { -d } @ARGV ); | 
| 571 |  |  |  |  |  |  | }, | 
| 572 | 0 | 0 | 0 |  |  |  | $self | 
| 573 |  |  |  |  |  |  | ) if $self->{filelist_scan}; | 
| 574 |  |  |  |  |  |  | #Net::DirectConnect:: | 
| 575 |  |  |  |  |  |  | psmisc::schedule( | 
| 576 |  |  |  |  |  |  | #10,    #dev! 300! | 
| 577 |  |  |  |  |  |  | $self->{filelist_reload}, | 
| 578 |  |  |  |  |  |  | #our $filelist_load_sub__ ||= | 
| 579 |  |  |  |  |  |  | sub { | 
| 580 | 0 |  |  |  |  |  | my $self = shift; | 
| 581 |  |  |  |  |  |  | #psmisc::startme( 'filelist', grep { -d } @ARGV ); | 
| 582 |  |  |  |  |  |  | #my($sharesize,$sharefiles) = | 
| 583 | 0 |  |  |  |  |  | $self->filelist_load( | 
| 584 |  |  |  |  |  |  | #sub { | 
| 585 |  |  |  |  |  |  | #my ( $sharesize, $sharefiles ) = @_; | 
| 586 |  |  |  |  |  |  | #$dc->{INF}{SS} = $sharesize, $dc->{INF}{SF} = $sharefiles, $dc->{sharesize} = $sharesize, if $sharesize; | 
| 587 |  |  |  |  |  |  | ##todo! change INF cmd or myinfo | 
| 588 |  |  |  |  |  |  | #} | 
| 589 |  |  |  |  |  |  | ); | 
| 590 |  |  |  |  |  |  | }, | 
| 591 | 0 | 0 |  |  |  |  | $self | 
| 592 |  |  |  |  |  |  | ) if $self->{filelist_scan}; | 
| 593 |  |  |  |  |  |  | }, | 
| 594 |  |  |  |  |  |  | #psmisc::startme( 'filelist', grep { -d } @ARGV )  if  !-e $config{files} or !-e $config{files}.'.bz2'; | 
| 595 |  |  |  |  |  |  | $self->{handler_int}{file_recieved} = sub { | 
| 596 | 0 | 0 |  | 0 |  |  | my $self = shift if ref $_[0]; | 
| 597 | 0 |  |  |  |  |  | my ( $full, $filename ) = @_; | 
| 598 |  |  |  |  |  |  | #$self->{'file_recv_tth'} = | 
| 599 | 0 |  |  |  |  |  | my ($tth) = $filename =~ m{^TTH/(\w+)}; | 
| 600 |  |  |  |  |  |  |  | 
| 601 |  |  |  |  |  |  | =z | 
| 602 |  |  |  |  |  |  | return unless $tth; | 
| 603 |  |  |  |  |  |  | $self->{share_full}{$tth} = $as; | 
| 604 |  |  |  |  |  |  | my ($name) = $as =~   m{^([^/\\]+)$}; | 
| 605 |  |  |  |  |  |  | return unless $name; | 
| 606 |  |  |  |  |  |  |  | 
| 607 |  |  |  |  |  |  | $self->{share_full}{$tth} = $full_local, $self->{share_tth}{$full_local} = $tth, $self->{share_tth}{$file} = $tth, | 
| 608 |  |  |  |  |  |  | if $tth; | 
| 609 |  |  |  |  |  |  | $self->{share_full}{$file} ||= $full_local; | 
| 610 |  |  |  |  |  |  | =cut | 
| 611 |  |  |  |  |  |  |  | 
| 612 | 0 | 0 | 0 |  |  |  | $self->log( 'dev', 'adding downloaded file to share', $full, $tth ), | 
| 613 |  |  |  |  |  |  | $self->share_add_file( $full, $tth ), $self->share_changed() | 
| 614 |  |  |  |  |  |  | if !$self->{'file_recv_filelist'} and !$self->{'no_auto_share_downloaded'};  # unless $self->{'no_auto_share_downloaded'}; | 
| 615 |  |  |  |  |  |  | #TODO          $self->{db}->insert_hash( 'filelist', $f ) if !$self->{no_sql} and $f->{tth}; | 
| 616 |  |  |  |  |  |  | ; | 
| 617 | 0 |  |  |  |  |  | }; | 
| 618 | 0 | 0 |  |  |  |  | $self->filelist_load() unless $standalone;    # (caller)[0] ~~ __PACKAGE__; | 
| 619 |  |  |  |  |  |  | #$self->log('initok'); | 
| 620 | 0 |  |  |  |  |  | return $self; | 
| 621 |  |  |  |  |  |  | } | 
| 622 |  |  |  |  |  |  | eval q{ #do | 
| 623 |  |  |  |  |  |  | use lib '../..'; | 
| 624 |  |  |  |  |  |  | use Net::DirectConnect; | 
| 625 |  |  |  |  |  |  | print "making\n"; | 
| 626 |  |  |  |  |  |  | __PACKAGE__->new(@ARGV)->{db}->upgrade(), exit if $ARGV[0] eq 'upgrade'; | 
| 627 |  |  |  |  |  |  | __PACKAGE__->new(@ARGV)->filelist_make(@ARGV),; | 
| 628 |  |  |  |  |  |  | }, print $@ unless caller; | 
| 629 |  |  |  |  |  |  | 1; |