/[BackupPC]/trunk/lib/BackupPC/SearchLib.pm
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/lib/BackupPC/SearchLib.pm

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 24 by dpavlin, Mon Jul 11 16:48:33 2005 UTC revision 229 by dpavlin, Tue Oct 25 09:30:51 2005 UTC
# Line 4  package BackupPC::SearchLib; Line 4  package BackupPC::SearchLib;
4  use strict;  use strict;
5  use BackupPC::CGI::Lib qw(:all);  use BackupPC::CGI::Lib qw(:all);
6  use BackupPC::Attrib qw(:all);  use BackupPC::Attrib qw(:all);
 use Data::Dumper;  
7  use DBI;  use DBI;
8    use DateTime;
9    use vars qw(%In $MyURL);
10    use Time::HiRes qw/time/;
11    use XML::Writer;
12    use IO::File;
13    
14    my $on_page = 100;
15    my $pager_pages = 10;
16    
17    my $dsn = $Conf{SearchDSN};
18    my $db_user = $Conf{SearchUser} || '';
19    
20    my $hest_index_path = $Conf{HyperEstraierIndex};
21    
22    my $dbh;
23    
24    sub get_dbh {
25            $dbh ||= DBI->connect($dsn, $db_user, "", { RaiseError => 1, AutoCommit => 1 } );
26            return $dbh;
27    }
28    
29  sub getUnits() {  sub getUnits() {
30      my @ret = ();          my @ret;
31      my $tmp;  
32      my $dbh = DBI->connect( "dbi:SQLite:dbname=${TopDir}/$Conf{SearchDB}",          my $dbh = get_dbh();
33          "", "", { RaiseError => 1, AutoCommit => 1 } );          my $sth = $dbh->prepare(qq{
34      my $st =                  SELECT
35        $dbh->prepare(                          shares.id       as id,
36          " SELECT shares.ID AS ID, shares.share AS name FROM shares;");                          hosts.name || ':' || shares.name as share
37      $st->execute();                  FROM shares
38      push (@ret, { 'ID' => '', 'name' => '-'});                  JOIN hosts on hostid = hosts.id
39      while ( $tmp = $st->fetchrow_hashref() ) {                  ORDER BY share
40          push( @ret, { 'ID' => $tmp->{'ID'}, 'name' => $tmp->{'name'} } );          } );
41      }          $sth->execute();
42      $dbh->disconnect();          push @ret, { 'id' => '', 'share' => '-'};       # dummy any
43      return @ret;  
44            while ( my $row = $sth->fetchrow_hashref() ) {
45                    push @ret, $row;
46            }
47            return @ret;
48  }  }
49    
50  sub getWhere($) {  sub epoch_to_iso {
51          my ($param)    = @_;          my $t = shift || return;
52          my @conditions;          my $iso = BackupPC::Lib::timeStamp(undef, $t);
53            $iso =~ s/\s/ /g;
54            return $iso;
55    }
56    
57    sub dates_from_form($) {
58            my $param = shift || return;
59    
60          sub mk_iso_date($$) {          sub mk_epoch_date($$) {
61                  my ($name,$suffix) = @_;                  my ($name,$suffix) = @_;
62    
63                  my $yyyy = $param->{ $name . '_year_' . $suffix} || return;                  my $yyyy = $param->{ $name . '_year_' . $suffix} || return undef;
64                  my $mm .= $param->{ $name . '_month_' . $suffix} ||                  my $mm .= $param->{ $name . '_month_' . $suffix} ||
65                          ( $suffix eq 'from' ? 1 : 12);                          ( $suffix eq 'from' ? 1 : 12);
66                  my $dd .= $param->{ $name . '_day_' . $suffix} ||                  my $dd .= $param->{ $name . '_day_' . $suffix} ||
67                          ( $suffix eq 'from' ? 1 : 31);                          ( $suffix eq 'from' ? 1 : 31);
68                  return sprintf("%04d-%02d-%02d", $yyyy, $mm, $dd);  
69                    $yyyy =~ s/\D//g;
70                    $mm =~ s/\D//g;
71                    $dd =~ s/\D//g;
72    
73                    my $h = my $m = my $s = 0;
74                    if ($suffix eq 'to') {
75                            $h = 23;
76                            $m = 59;
77                            $s = 59;
78                    }
79    
80                    my $dt = new DateTime(
81                            year => $yyyy,
82                            month => $mm,
83                            day => $dd,
84                            hour => $h,
85                            minute => $m,
86                            second => $s,
87                    );
88                    print STDERR "mk_epoch_date($name,$suffix) [$yyyy-$mm-$dd] = " . $dt->ymd . " " . $dt->hms . "\n";
89                    return $dt->epoch || 'NULL';
90          }          }
91    
92          my $backup_from = mk_iso_date('search_backup', 'from');          my @ret = (
93          push @conditions, qq{ date(backups.date, 'unixepoch','localtime') >= '$backup_from' } if ($backup_from);                  mk_epoch_date('search_backup', 'from'),
94          my $backup_to = mk_iso_date('search_backup', 'to');                  mk_epoch_date('search_backup', 'to'),
95          push @conditions, qq{ date(backups.date, 'unixepoch','localtime') <= '$backup_to' } if ($backup_to);                  mk_epoch_date('search', 'from'),
96                    mk_epoch_date('search', 'to'),
97            );
98    
99            return @ret;
100    
101          my $files_from = mk_iso_date('search', 'from');  }
         push @conditions, qq{ date(files.date, 'unixepoch','localtime') >= '$files_from' } if ($files_from);  
         my $files_to = mk_iso_date('search', 'to');  
         push @conditions, qq{ date(files.date, 'unixepoch','localtime') <= '$files_to' } if ($files_to);  
102    
         print STDERR "backup: $backup_from - $backup_to files: $files_from - $files_to cond:",join(" | ",@conditions);  
       
         push( @conditions, ' backups.hostID = ' . $param->{'search_host'} ) if ($param->{'search_host'});  
103    
104          push (@conditions, " files.name LIKE '".$param->{'search_filename'}."%'") if ($param->{'search_filename'});  sub getWhere($) {
105            my $param = shift || return;
106    
107          return (          my ($backup_from, $backup_to, $files_from, $files_to) = dates_from_form($param);
108                  join(" and ", @conditions),  
109                  $files_from, $files_to,          my @conditions;
110                  $backup_from, $backup_to          push @conditions, qq{ backups.date >= $backup_from } if ($backup_from);
111          );          push @conditions, qq{ backups.date <= $backup_to } if ($backup_to);
112            push @conditions, qq{ files.date >= $files_from } if ($files_from);
113            push @conditions, qq{ files.date <= $files_to } if ($files_to);
114    
115            print STDERR "backup: $backup_from - $backup_to files: $files_from - $files_to cond:" . join(" and ",@conditions);
116    
117            push( @conditions, ' files.shareid = ' . $param->{'search_share'} ) if ($param->{'search_share'});
118            push (@conditions, " upper(files.path) LIKE upper('%".$param->{'search_filename'}."%')") if ($param->{'search_filename'});
119    
120            return join(" and ", @conditions);
121  }  }
122    
123    my $sort_def = {
124            search => {
125                    default => 'date_a',
126                    sql => {
127                            share_d => 'shares.name DESC',
128                            share_a => 'shares.name ASC',
129                            path_d => 'files.path DESC',
130                            path_a => 'files.path ASC',
131                            num_d => 'files.backupnum DESC',
132                            num_a => 'files.backupnum ASC',
133                            size_d => 'files.size DESC',
134                            size_a => 'files.size ASC',
135                            date_d => 'files.date DESC',
136                            date_a => 'files.date ASC',
137                    },
138                    est => {
139                            share_d => 'sname STRD',
140                            share_a => 'sname STRA',
141                            path_d => 'filepath STRD',
142                            path_a => 'filepath STRA',
143                            num_d => 'backupnum NUMD',
144                            num_a => 'backupnum NUMA',
145                            size_d => 'size NUMD',
146                            size_a => 'size NUMA',
147                            date_d => 'date NUMD',
148                            date_a => 'date NUMA',
149                    }
150            }, burn => {
151                    default => 'date_a',
152                    sql => {
153                            share_d => 'host DESC, share DESC',
154                            share_a => 'host ASC, share ASC',
155                            num_d => 'backupnum DESC',
156                            num_a => 'backupnum ASC',
157                            date_d => 'date DESC',
158                            date_a => 'date ASC',
159                            age_d => 'age DESC',
160                            age_a => 'age ASC',
161                            size_d => 'size DESC',
162                            size_a => 'size ASC',
163                            incsize_d => 'inc_size DESC',
164                            incsize_a => 'inc_size ASC',
165                    }
166            }
167    };
168    
169  sub getFiles($$)  sub getSort($$$) {
170    {          my ($part,$type, $sort_order) = @_;
171        my ($where, $offset) = @_;  
172                  die "unknown part: $part" unless ($sort_def->{$part});
173                  die "unknown type: $type" unless ($sort_def->{$part}->{$type});
174        my $dbh = DBI->connect( "dbi:SQLite:dbname=${TopDir}/$Conf{SearchDB}",  
175          "", "", { RaiseError => 1, AutoCommit => 1 } );          $sort_order ||= $sort_def->{$part}->{'default'};
176        my $sql =            
177          q{            if (my $ret = $sort_def->{$part}->{$type}->{$sort_order}) {
178                  SELECT  files.id                        AS fid,                  return $ret;
179                          hosts.name                      AS hname,          } else {
180                          shares.name                     AS sname,                  # fallback to default sort order
181                          shares.share                    AS sharename,                  return $sort_def->{$part}->{$type}->{ $sort_def->{$part}->{'default'} };
182                          files.backupNum                 AS backupNum,          }
183                          files.name                      AS filename,  }
184                          files.path                      AS filepath,  
185                          shares.share||files.fullpath    AS networkPath,  sub getFiles($) {
186                          date(files.date, 'unixepoch', 'localtime') AS date,          my ($param) = @_;
187                          files.type                      AS filetype,  
188                          files.size                      AS size,          my $offset = $param->{'offset'} || 0;
189                          dvds.name                       AS dvd          $offset *= $on_page;
190    
191            my $dbh = get_dbh();
192    
193            my $sql_cols = qq{
194                    files.id                        AS fid,
195                    hosts.name                      AS hname,
196                    shares.name                     AS sname,
197                    files.backupnum                 AS backupnum,
198                    files.path                      AS filepath,
199                    files.date                      AS date,
200                    files.type                      AS type,
201                    files.size                      AS size
202            };
203    
204            my $sql_from = qq{
205                  FROM files                  FROM files
206                          INNER JOIN shares       ON files.shareID=shares.ID                          INNER JOIN shares       ON files.shareID=shares.ID
207                          INNER JOIN hosts        ON hosts.ID = shares.hostID                          INNER JOIN hosts        ON hosts.ID = shares.hostID
208                          INNER JOIN backups      ON backups.num = files.backupNum and backups.hostID = hosts.ID                          INNER JOIN backups      ON backups.num = files.backupnum and backups.hostID = hosts.ID AND backups.shareID = files.shareID
209                          LEFT  JOIN dvds         ON dvds.ID = files.dvdid          };
           };  
   
       if (defined($where) && $where ne "")  
         {  
             $sql .= " WHERE ". $where;        
         }  
210    
211        $sql .=          my $sql_where;
212          q{                    my $where = getWhere($param);
213              ORDER BY files.id          $sql_where = " WHERE ". $where if ($where);
214                LIMIT 100  
215                OFFSET ? * 100 + 1          my $order = getSort('search', 'sql', $param->{'sort'});
216    
217            my $sql_order = qq{
218                    ORDER BY $order
219                    LIMIT $on_page
220                    OFFSET ?
221          };          };
222          
223                  my $sql_count = qq{ select count(files.id) $sql_from $sql_where };
224                  my $sql_results = qq{ select $sql_cols $sql_from $sql_where $sql_order };
225        my $st = $dbh->prepare(  
226            $sql          my $sth = $dbh->prepare($sql_count);
227            );              $sth->execute();
228        if (!defined($offset) && $offset ne "")          my ($results) = $sth->fetchrow_array();
229        {  
230          $st->bind_param(1, $offset);          $sth = $dbh->prepare($sql_results);
231        }          $sth->execute( $offset );
232        else  
233        {          if ($sth->rows != $results) {
234          $st->bind_param(1,0);                  my $bug = "$0 BUG: [[ $sql_count ]] = $results while [[ $sql_results ]] = " . $sth->rows;
235        }                  $bug =~ s/\s+/ /gs;
236        $st->execute;                  print STDERR "$bug\n";
         
       my @ret = ();  
       my $tmp;  
         
       while ($tmp = $st->fetchrow_hashref())  
         {  
             push(@ret, {  
                            'hname'       => $tmp->{'hname'},  
                            'sname'       => $tmp->{'sname'},  
                            'sharename'   => $tmp->{'sharename'},  
                            'backupno'    => $tmp->{'backupNum'},  
                            'fname'       => $tmp->{'filename'},  
                            'fpath'       => $tmp->{'filepath'},  
                            'networkpath' => $tmp->{'networkPath'},  
                            'date'        => $tmp->{'date'},  
                            'type'        => $tmp->{'filetype'},  
                            'size'        => $tmp->{'size'},  
                            'id'          => $tmp->{'fid'},  
                            'dvd'         => $tmp->{'dvd'}  
                        }  
             );  
                                   
237          }          }
238    
239            my @ret;
240                
241        $st->finish();          while (my $row = $sth->fetchrow_hashref()) {
242        $dbh->disconnect();                  push @ret, $row;
       return @ret;  
   }  
   
 sub getBackupsNotBurned()  
   {  
       my $dbh = DBI->connect( "dbi:SQLite:dbname=${TopDir}/$Conf{SearchDB}",  
         "", "", { RaiseError => 1, AutoCommit => 1 } );        
       my $sql = q{  
           SELECT  
             hosts.ID         AS hostID,  
             hosts.name       AS host,  
             backups.num      AS backupno,  
             backups.type     AS type,  
             backups.date     AS date  
           FROM backups, shares, files, hosts  
           WHERE  
             backups.num    = files.backupNum  AND  
             shares.ID      = files.shareID    AND            
             backups.hostID = shares.hostID    AND  
             hosts.ID       = backups.hostID   AND  
             files.dvdid    IS NULL  
           GROUP BY  
             backups.hostID, backups.num  
       };  
       my $st = $dbh -> prepare( $sql );  
       my @ret = ();  
       $st -> execute();  
   
       while ( my $tmp = $st -> fetchrow_hashref() )  
         {            
             push(@ret, {  
                          'host'     => $tmp->{'host'},  
                          'hostid'   => $tmp->{'hostID'},  
                          'backupno' => $tmp->{'backupno'},  
                          'type'     => $tmp->{'type'},  
                          'date'     => $tmp->{'date'}  
                        }  
             );  
243          }          }
244              
245        return @ret;                $sth->finish();
246    }          return ($results, \@ret);
247    }
248    
249    sub getHyperEstraier_url($) {
250            my ($use_hest) = @_;
251    
252            return unless $use_hest;
253    
254            use HyperEstraier;
255            my ($index_path, $index_node_url);
256    
257            if ($use_hest =~ m#^http://#) {
258                    $index_node_url = $use_hest;
259            } else {
260                    $index_path = $TopDir . '/' . $index_path;
261                    $index_path =~ s#//#/#g;
262            }
263            return ($index_path, $index_node_url);
264    }
265    
266    sub getFilesHyperEstraier($) {
267            my ($param) = @_;
268    
269            my $offset = $param->{'offset'} || 0;
270            $offset *= $on_page;
271    
272            die "no index_path?" unless ($hest_index_path);
273    
274            use HyperEstraier;
275    
276            my ($index_path, $index_node_url) = getHyperEstraier_url($hest_index_path);
277    
278            # open the database
279            my $db;
280            if ($index_path) {
281                    $db = HyperEstraier::Database->new();
282                    $db->open($index_path, $HyperEstraier::ESTDBREADER);
283            } elsif ($index_node_url) {
284                    $db ||= HyperEstraier::Node->new($index_node_url);
285                    $db->set_auth('admin', 'admin');
286            } else {
287                    die "BUG: unimplemented";
288            }
289    
290            # create a search condition object
291            my $cond = HyperEstraier::Condition->new();
292    
293            my $q = $param->{'search_filename'};
294            my $shareid = $param->{'search_share'};
295    
296  sub displayBackupsGrid()          if (length($q) > 0) {
297    {                  # exact match
298        my $retHTML = "";                  $cond->add_attr("filepath ISTRINC $q");
299        my $addForm = 1;  
300                    $q =~ s/(.)/$1 /g;
301                    # set the search phrase to the search condition object
302                    $cond->set_phrase($q);
303            }
304    
305            my ($backup_from, $backup_to, $files_from, $files_to) = dates_from_form($param);
306    
307            $cond->add_attr("backup_date NUMGE $backup_from") if ($backup_from);
308            $cond->add_attr("backup_date NUMLE $backup_to") if ($backup_to);
309    
310            $cond->add_attr("date NUMGE $files_from") if ($files_from);
311            $cond->add_attr("date NUMLE $files_to") if ($files_to);
312    
313            $cond->add_attr("shareid NUMEQ $shareid") if ($shareid);
314    
315    #       $cond->set_max( $offset + $on_page );
316            $cond->set_options( $HyperEstraier::Condition::SURE );
317            $cond->set_order( getSort('search', 'est', $param->{'sort'} ) );
318    
319            # get the result of search
320            my @res;
321            my ($result, $hits);
322    
323            if ($index_path) {
324                    $result = $db->search($cond, 0);
325                    $hits = $result->size;
326            } elsif ($index_node_url) {
327                    $result = $db->search($cond, 0);
328                    $hits = $result->doc_num;
329            } else {
330                    die "BUG: unimplemented";
331            }
332    
333            # for each document in result
334            for my $i ($offset .. ($offset + $on_page - 1)) {
335                    last if ($i >= $hits);
336    
337                    my $doc;
338                    if ($index_path) {
339                            my $id = $result->get($i);
340                            $doc = $db->get_doc($id, 0);
341                    } elsif ($index_node_url) {
342                            $doc = $result->get_doc($i);
343                    } else {
344                            die "BUG: unimplemented";
345                    }
346    
347                    my $row;
348                    foreach my $c (qw/fid hname sname backupnum filepath date type size/) {
349                            $row->{$c} = $doc->attr($c);
350                    }
351                    push @res, $row;
352            }
353    
354            return ($hits, \@res);
355    }
356    
357    sub getGzipName($$$)
358    {
359            my ($host, $share, $backupnum) = @_;
360            my $ret = $Conf{GzipSchema};
361            
362            $share =~ s/\//_/g;
363            $ret =~ s/\\h/$host/ge;
364            $ret =~ s/\\s/$share/ge;
365            $ret =~ s/\\n/$backupnum/ge;
366    
367            $ret =~ s/__+/_/g;
368    
369            return $ret;
370            
371    }
372    
373    sub get_tgz_size_by_name($) {
374            my $name = shift;
375    
376            my $tgz = $Conf{InstallDir}.'/'.$Conf{GzipTempDir}.'/'.$name;
377    
378            my $size = -1;
379    
380            if (-f $tgz) {
381                    $size = (stat($tgz))[7];
382            } elsif (-d $tgz) {
383                    opendir(my $dir, $tgz) || die "can't opendir $tgz: $!";
384                    my @parts = grep { !/^\./ && -f "$tgz/$_" } readdir($dir);
385                    $size = 0;
386                    foreach my $part (@parts) {
387                            $size += (stat("$tgz/$part"))[7] || die "can't stat $tgz/$part: $!";
388                    }
389                    closedir $dir;
390            }
391    
392            return $size;
393    }
394    
395    sub getGzipSize($$)
396    {
397            my ($hostID, $backupNum) = @_;
398            my $sql;
399            my $dbh = get_dbh();
400            
401            $sql = q{
402                                    SELECT hosts.name  as host,
403                                               shares.name as share,
404                                               backups.num as backupnum
405                                    FROM hosts, backups, shares
406                                    WHERE shares.id=backups.shareid AND
407                                              hosts.id =backups.hostid AND
408                                              hosts.id=? AND
409                                              backups.num=?
410                            };
411            my $sth = $dbh->prepare($sql);
412            $sth->execute($hostID, $backupNum);
413    
414            my $row = $sth->fetchrow_hashref();
415    
416            return get_tgz_size_by_name(
417                    getGzipName($row->{'host'}, $row->{share}, $row->{'backupnum'})
418            );
419    }
420    
421    sub getBackupsNotBurned($) {
422    
423            my $param = shift;
424            my $dbh = get_dbh();
425    
426            my $order = getSort('burn', 'sql', $param->{'sort'});
427    
428    print STDERR "## sort=". ($param->{'sort'} || 'no sort param') . " burn sql order: $order\n";
429    
430            my $sql = qq{
431                    SELECT
432                            backups.hostID AS hostID,
433                            hosts.name AS host,
434                            shares.name AS share,
435                            backups.num AS backupnum,
436                            backups.type AS type,
437                            backups.date AS date,
438                            date_part('epoch',now()) - backups.date as age,
439                            backups.size AS size,
440                            backups.id AS id,
441                            backups.inc_size AS inc_size,
442                            backups.parts AS parts
443                    FROM backups
444                    INNER JOIN shares       ON backups.shareID=shares.ID
445                    INNER JOIN hosts        ON backups.hostID = hosts.ID
446                    LEFT OUTER JOIN archive_backup ON archive_backup.backup_id = backups.id
447                    WHERE backups.inc_size > 0 AND backups.inc_deleted is false AND archive_backup.backup_id IS NULL
448                    GROUP BY
449                            backups.hostID,
450                            hosts.name,
451                            shares.name,
452                            backups.num,
453                            backups.shareid,
454                            backups.id,
455                            backups.type,
456                            backups.date,
457                            backups.size,
458                            backups.inc_size,
459                            backups.parts
460                    ORDER BY $order
461            };
462            my $sth = $dbh->prepare( $sql );
463            my @ret;
464            $sth->execute();
465    
466            while ( my $row = $sth->fetchrow_hashref() ) {
467                    $row->{'age'} = sprintf("%0.1f", ( $row->{'age'} / 86400 ) );
468                    #$row->{'age'} = sprintf("%0.1f", ( (time() - $row->{'date'}) / 86400 ) );
469                    $row->{'size'} = sprintf("%0.2f", $row->{'size'} / 1024 / 1024);
470    
471                    # do some cluster calculation (approximate) and convert to kB
472                    $row->{'inc_size'} = int(($row->{'inc_size'} + 1023 ) / ( 2 * 1024 ) * 2);
473                    push @ret, $row;
474            }
475                
476        if ($addForm)          return @ret;      
477          {  }
478    
479    sub displayBackupsGrid($) {
480    
481            my $param = shift;
482    
483            my $retHTML .= q{
484                    <form id="forma" method="POST" action="}.$MyURL.q{?action=burn">
485            };
486    
487            $retHTML .= <<'EOF3';
488    <style type="text/css">
489    <!--
490    DIV#fixedBox {
491            position: absolute;
492            top: 50em;
493            left: -24%;
494            padding: 0.5em;
495            width: 20%;
496            background-color: #E0F0E0;
497            border: 1px solid #00C000;
498    }
499    
500    DIV#fixedBox, DIV#fixedBox INPUT, DIV#fixedBox TEXTAREA {
501            font-size: 10pt;
502    }
503    
504    FORM>DIV#fixedBox {
505            position: fixed !important;
506            left: 0.5em !important;
507            top: auto !important;
508            bottom: 1em !important;
509            width: 15% !important;
510    }
511    
512    DIV#fixedBox INPUT[type=text], DIV#fixedBox TEXTAREA {
513            border: 1px solid #00C000;
514    }
515    
516    DIV#fixedBox #note {
517            display: block;
518            width: 100%;
519    }
520    
521    DIV#fixedBox #submitBurner {
522            display: block;
523            width: 100%;
524            margin-top: 0.5em;
525            cursor: pointer;
526    }
527    
528    * HTML {
529            overflow-y: hidden;
530    }
531    
532    * HTML BODY {
533            overflow-y: auto;
534            height: 100%;
535            font-size: 100%;
536    }
537    
538    * HTML DIV#fixedBox {
539            position: absolute;
540    }
541    
542    #mContainer, #gradient, #mask, #progressIndicator {
543            display: block;
544            width: 100%;
545            font-size: 10pt;
546            font-weight: bold;
547            text-align: center;
548            vertical-align: middle;
549            padding: 1px;
550    }
551    
552    #gradient, #mask, #progressIndicator {
553            left: 0;
554            border-width: 1px;
555            border-style: solid;
556            border-color: #000000;
557            color: #404040;
558            margin: 0.4em;
559            position: absolute;
560            margin-left: -1px;
561            margin-top: -1px;
562            margin-bottom: -1px;
563            overflow: hidden;
564    }
565    
566    #mContainer {
567            display: block;
568            position: relative;
569            padding: 0px;
570            margin-top: 0.4em;
571            margin-bottom: 0.5em;
572    }
573    
574    #gradient {
575            z-index: 1;
576            background-color: #FFFF00;
577    }
578    
579    #mask {
580            z-index: 2;
581            background-color: #FFFFFF;
582    }
583    
584              $retHTML .= <<EOF3;  #progressIndicator {
585  <script language="javascript" type="text/javascript">          z-index: 3;
586            background-color: transparent;
587    }
588    
589    #parts {
590            padding: 0.4em;
591            display: none;
592            width: 100%;
593            font-size: 80%;
594            color: #ff0000;
595            text-align: center;
596    }
597    -->
598    </style>
599    <script type="text/javascript">
600  <!--  <!--
601    
602      function checkAll(location)  var debug_div = null;
     {  
       for (var i=0;i<document.forma.elements.length;i++)  
       {  
         var e = document.forma.elements[i];  
         if ((e.checked || !e.checked) && e.name != \'all\') {  
             if (eval("document.forma."+location+".checked")) {  
                 e.checked = true;  
             } else {  
                 e.checked = false;  
             }  
         }  
       }  
     }  
 //-->  
 </script>        
603  EOF3  EOF3
604                $retHTML .= q{<form name="forma" method="POST" action="}."$MyURL"."?action=burn\"";  
605                $retHTML.= q{<input type="hidden" value="burn" name="action">};          # take maximum archive size from configuration
606                $retHTML .= q{<input type="hidden" value="results" name="search_results">};          $retHTML .= 'var media_size = '. $Conf{MaxArchiveSize} .';';
607          }  
608        $retHTML .= "<table style=\"fview\">";          $retHTML .= <<'EOF3';
609        $retHTML .= "<tr> ";  
610        if ($addForm)  function debug(msg) {
611          {          return; // Disable debugging
612              $retHTML .= "<td class=\"tableheader\"><input type=\"checkbox\" name=\"allFiles\" onClick=\"checkAll('allFiles');\"></td>";  
613          }          if (! debug_div) debug_div = document.getElementById('debug');
614        $retHTML .=  "<td class=\"tableheader\">Host</td> <td class=\"tableheader\">Backup no</td> <td class=\"tableheader\">Type</td> <td class=\"tableheader\">date</td></tr>";  
615        my @backups = getBackupsNotBurned();          // this will create debug div if it doesn't exist.
616        my $backup;          if (! debug_div) {
617                    debug_div = document.createElement('div');
618        if ($addForm)                  if (document.body) document.body.appendChild(debug_div);
619          {                  else debug_div = null;
620              $retHTML .= "<tr>";          }
621              $retHTML .= "<td colspan=7 style=\"tableheader\">";          if (debug_div) {
622              $retHTML .= "<input type=\"submit\" value=\"Burn selected backups on medium\" name=\"submitBurner\">";                  debug_div.appendChild(document.createTextNode(msg));
623              $retHTML .= "</td>";                  debug_div.appendChild(document.createElement("br"));
624              $retHTML .= "</tr>";          }
625                }
626          }  
627        foreach $backup(@backups)  
628          {  var element_id_cache = Array();
629              my $ftype = "";  
630                function element_id(name,element) {
631              $retHTML .= "<tr>";          if (! element_id_cache[name]) {
632              if ($addForm)                  element_id_cache[name] = self.document.getElementById(name);
633                {          }
634                    $retHTML .= "<td class=\"fview\"> <input type=\"checkbox\" name=\"fcb"          return element_id_cache[name];
635                      .$backup->{'hostid'}."_".$backup->{'backupno'}  }
636                    ."\" value=\"".$backup->{'hostid'}."_".$backup->{'backupno'}."\"> </td>";  
637                }      function checkAll(location) {
638                        var f = element_id('forma') || null;
639              $retHTML .= "<td class=\"fviewborder\">" . $backup->{'host'} . "</td>";          if (!f) return false;
640              $retHTML .= "<td class=\"fviewborder\">" . $backup->{'backupno'} . "</td>";  
641              $retHTML .= "<td class=\"fviewborder\">" . $backup->{'type'} . "</td>";          var len = f.elements.length;
642              $retHTML .= "<td class=\"fviewborder\">" . $backup->{'date'} . "<td>";          var check_all = element_id('allFiles');
643              $retHTML .= "</tr>";          var suma = check_all.checked ? (parseInt(f.elements['totalsize'].value) || 0) : 0;
644          }  
645        $retHTML .= "</table>";          for (var i = 0; i < len; i++) {
646        if ($addForm)                  var e = f.elements[i];
647         {                  if (e.name != 'all' && e.name.substr(0, 3) == 'fcb') {
648             $retHTML .= "</form>";                          if (check_all.checked) {
649         }                                  if (e.checked) continue;
650                                    var el = element_id("fss" + e.name.substr(3));
651                                    var size = parseInt(el.value) || 0;
652                                    debug('suma: '+suma+' size: '+size);
653                                    if ((suma + size) < media_size) {
654                                            suma += size;
655                                            e.checked = true;
656                                    } else {
657                                            break;
658                                    }
659                            } else {
660                                    e.checked = false;
661                            }
662                    }
663            }
664            update_sum(suma);
665    }
666    
667    function update_sum(suma, suma_disp) {
668            if (! suma_disp) suma_disp = suma;
669            element_id('forma').elements['totalsize'].value = suma_disp;
670            pbar_set(suma, media_size);
671            debug('total size: ' + suma);
672    }
673    
674    function sumiraj(e) {
675            var suma = parseInt(element_id('forma').elements['totalsize'].value) || 0;
676            var len = element_id('forma').elements.length;
677            if (e) {
678                    var size = parseInt( element_id("fss" + e.name.substr(3)).value);
679                    if (e.checked) {
680                            suma += size;
681                    } else {
682                            suma -= size;
683                    }
684    
685                    var parts = parseInt( element_id("prt" + e.name.substr(3)).value);
686                    if (suma > media_size && suma == size && parts > 1) {
687                            element_id("parts").innerHTML = "This will take "+parts+" mediums!";
688                            element_id("parts").style.display = 'block';
689                            update_sum(media_size, suma);
690                            suma = media_size;
691                            return suma;
692                    } else {
693                            element_id("parts").style.display = 'none';
694                    }
695    
696                    if (suma < 0) suma = 0;
697            } else {
698                    suma = 0;
699                    for (var i = 0; i < len; i++) {
700                            var e = element_id('forma').elements[i];
701                            if (e.name != 'all' && e.checked && e.name.substr(0,3) == 'fcb') {
702                                    var el = element_id("fss" + e.name.substr(3));
703                                    if (el && el.value) suma += parseInt(el.value) || 0;
704                            }
705                    }
706            }
707            update_sum(suma);
708            return suma;
709    }
710    
711    /* progress bar */
712    
713    var _pbar_width = null;
714    var _pbar_warn = 10;    // change color in last 10%
715    
716    function pbar_reset() {
717            element_id("mask").style.left = "0px";
718            _pbar_width = element_id("mContainer").offsetWidth - 2;
719            element_id("mask").style.width = _pbar_width + "px";
720            element_id("mask").style.display = "block";
721            element_id("progressIndicator").style.zIndex  = 10;
722            element_id("progressIndicator").innerHTML = "0";
723    }
724    
725    function dec2hex(d) {
726            var hch = '0123456789ABCDEF';
727            var a = d % 16;
728            var q = (d - a) / 16;
729            return hch.charAt(q) + hch.charAt(a);
730    }
731    
732    function pbar_set(amount, max) {
733            debug('pbar_set('+amount+', '+max+')');
734    
735            if (_pbar_width == null) {
736                    var _mc = element_id("mContainer");
737                    if (_pbar_width == null) _pbar_width = parseInt(_mc.offsetWidth ? (_mc.offsetWidth - 2) : 0) || null;
738                    if (_pbar_width == null) _pbar_width = parseInt(_mc.clientWidth ? (_mc.clientWidth + 2) : 0) || null;
739                    if (_pbar_width == null) _pbar_width = 0;
740            }
741    
742            var pcnt = Math.floor(amount * 100 / max);
743            var p90 = 100 - _pbar_warn;
744            var pcol = pcnt - p90;
745            if (Math.round(pcnt) <= 100) {
746                    if (pcol < 0) pcol = 0;
747                    var e = element_id("submitBurner");
748                    debug('enable_button');
749                    e.disabled = false;
750                    var a = e.getAttributeNode('disabled') || null;
751                    if (a) e.removeAttributeNode(a);
752            } else {
753                    debug('disable button');
754                    pcol = _pbar_warn;
755                    var e = element_id("submitBurner");
756                    if (!e.disabled) e.disabled = true;
757            }
758            var col_g = Math.floor((_pbar_warn - pcol) * 255 / _pbar_warn);
759            var col = '#FF' + dec2hex(col_g) + '00';
760    
761            //debug('pcol: '+pcol+' g:'+col_g+' _pbar_warn:'+ _pbar_warn + ' color: '+col);
762            element_id("gradient").style.backgroundColor = col;
763    
764            element_id("progressIndicator").innerHTML = pcnt + '%';
765            //element_id("progressIndicator").innerHTML = amount;
766    
767            element_id("mask").style.clip = 'rect(' + Array(
768                    '0px',
769                    element_id("mask").offsetWidth + 'px',
770                    element_id("mask").offsetHeight + 'px',
771                    Math.round(_pbar_width * amount / max) + 'px'
772            ).join(' ') + ')';
773    }
774    
775    if (!self.body) self.body = new Object();
776    self.onload = self.document.onload = self.body.onload = function() {
777            //pbar_reset();
778            sumiraj();
779    };
780    
781    // -->
782    </script>
783    <div id="fixedBox">
784    
785    Size: <input type="text" name="totalsize" size="7" readonly="readonly" style="text-align:right;" value="0" /> kB
786    
787    <div id="mContainer">
788            <div id="gradient">&nbsp;</div>
789            <div id="mask">&nbsp;</div>
790            <div id="progressIndicator">0%</div>
791    </div>
792    <br/>
793    
794    <div id="parts">&nbsp;</div>
795    
796    Note:
797    <textarea name="note" cols="10" rows="5" id="note"></textarea>
798    
799    <input type="submit" id="submitBurner" value="Burn selected" name="submitBurner" />
800    
801    </div>
802    <!--
803    <div id="debug" style="float: right; width: 10em; border: 1px #ff0000 solid; background-color: #ffe0e0; -moz-opacity: 0.7;">
804    no debug output yet
805    </div>
806    -->
807    EOF3
808            $retHTML .= q{
809                            <input type="hidden" value="burn" name="action">
810                            <input type="hidden" value="results" name="search_results">
811                            <table style="fview" border="0" cellspacing="0" cellpadding="2">
812                            <tr class="tableheader">
813                            <td class="tableheader">
814                                    <input type="checkbox" name="allFiles" id="allFiles" onClick="checkAll('allFiles');">
815                            </td>
816            } .
817                    sort_header($param, 'Share', 'share', 'center') .
818                    sort_header($param, '#', 'num', 'center') .
819            qq{
820                            <td align="center">Type</td>
821            } .
822                    sort_header($param, 'Date', 'date', 'center') .
823                    sort_header($param, 'Age/days', 'age', 'center') .
824                    sort_header($param, 'Size/Mb', 'size', 'center') .
825                    sort_header($param, 'gzip size/Kb', 'incsize', 'center') .
826            qq{
827                            </tr>
828            };
829    
830            my @color = (' bgcolor="#e0e0e0"', '');
831    
832            my $i = 0;
833            my $host = '';
834    
835            foreach my $backup ( getBackupsNotBurned($param) ) {
836    
837                    if ($host ne $backup->{'host'}) {
838                            $i++;
839                            $host = $backup->{'host'};
840                    }
841                    my $ftype = "";
842    
843                    my $checkbox_key = $backup->{'hostid'}. '_' .$backup->{'backupnum'} . '_' . $backup->{'id'};
844    
845                    $retHTML .=
846                            '<tr' . $color[$i %2 ] . '>
847                            <td class="fview">';
848    
849                    if (($backup->{'inc_size'} || 0) > 0) {
850                            $retHTML .= '
851                            <input type="checkbox" name="fcb' . $checkbox_key . '" value="' . $checkbox_key . '" onClick="sumiraj(this);">';
852                    }
853    
854                    $retHTML .=
855                            '</td>' .
856                            '<td align="right">' . $backup->{'host'} . ':' . $backup->{'share'} . '</td>' .
857                            '<td align="center">' . $backup->{'backupnum'} . '</td>' .
858                            '<td align="center">' . $backup->{'type'} . '</td>' .
859                            '<td align="center">' . epoch_to_iso( $backup->{'date'} ) . '</td>' .
860                            '<td align="center">' . $backup->{'age'} . '</td>' .
861                            '<td align="right">' . $backup->{'size'} . '</td>' .
862                            '<td align="right">' . $backup->{'inc_size'} .
863                            '<input type="hidden" id="fss'.$checkbox_key .'" value="'. $backup->{'inc_size'} .'"></td>' .
864                            '<input type="hidden" id="prt'.$checkbox_key .'" value="'. $backup->{'parts'} .'"></td>' .
865    
866                            "</tr>\n";
867            }
868    
869            $retHTML .= "</table>";
870            $retHTML .= "</form>";
871                
872        return $retHTML;          return $retHTML;
873      }      
874      
875    }        sub displayGrid($) {
876            my ($param) = @_;
877    
878            my $offset = $param->{'offset'};
879            my $hilite = $param->{'search_filename'};
880    
 sub displayGrid($$$$) {  
         my ($where, $addForm, $offset, $hilite) = @_;  
881          my $retHTML = "";          my $retHTML = "";
882    
883          if ($addForm) {          my $start_t = time();
884                  $retHTML .= qq{<form name="forma" method="POST" action="}.$MyURL.qq{?action=search">};  
885                  $retHTML.= qq{<input type="hidden" value="search" name="action">};          my ($results, $files);
886                  $retHTML .= qq{<input type="hidden" value="results" name="search_results">};          if ($param->{'use_hest'} && length($hilite) > 0) {
887                    ($results, $files) = getFilesHyperEstraier($param);
888            } else {
889                    ($results, $files) = getFiles($param);
890            }
891    
892            my $dur_t = time() - $start_t;
893            my $dur = sprintf("%0.4fs", $dur_t);
894    
895            my ($from, $to) = (($offset * $on_page) + 1, ($offset * $on_page) + $on_page);
896    
897            if ($results <= 0) {
898                    $retHTML .= qq{
899                            <p style="color: red;">No results found...</p>
900                    };
901                    return $retHTML;
902            } else {
903                    # DEBUG
904                    #use Data::Dumper;
905                    #$retHTML .= '<pre>' . Dumper($files) . '</pre>';
906          }          }
907    
908    
909            $retHTML .= qq{
910            <div>
911            Found <b>$results files</b> showing <b>$from - $to</b> (took $dur)
912            </div>
913            <table style="fview" width="100%" border="0" cellpadding="2" cellspacing="0">
914                    <tr class="fviewheader">
915                    <td></td>
916            };
917    
918            sub sort_header($$$$) {
919                    my ($param, $display, $name, $align) = @_;
920    
921                    my ($sort_what, $sort_direction) = split(/_/,$param->{'sort'},2);
922    
923                    my $old_sort = $param->{'sort'};
924    
925                    my $html = qq{<td align="$align"};
926                    my $arrow = '';
927    
928                    if (lc($sort_what) eq lc($name)) {
929                            my $direction = lc($sort_direction);
930    
931                            # swap direction or fallback to default
932                            $direction =~ tr/ad/da/;
933                            $direction = 'a' unless ($direction =~ /[ad]/);
934    
935                            $param->{'sort'} = $name . '_' . $direction;
936                            $html .= ' style="border: 1px solid #808080;"';
937                    
938                            # add unicode arrow for direction
939                            $arrow .= '&nbsp;';
940                            $arrow .= $direction eq 'a'  ?  '&#9650;'
941                                    : $direction eq 'd'  ?  '&#9660;'
942                                    :                       ''
943                                    ;
944    
945                    } else {
946                            $param->{'sort'} = $name . '_a';
947                    }
948    
949                    $html .= '><a href="' . page_uri($param) . '">' . $display . '</a>' . $arrow . '</td>';
950                    $param->{'sort'} = $old_sort;
951    
952                    return $html;
953            }
954    
955            $retHTML .=
956                    sort_header($param, 'Share', 'share', 'center') .
957                    sort_header($param, 'Type and Name', 'path', 'center') .
958                    sort_header($param, '#', 'num', 'center') .
959                    sort_header($param, 'Size', 'size', 'center') .
960                    sort_header($param, 'Date', 'date', 'center');
961    
962          $retHTML .= qq{          $retHTML .= qq{
963          <table style="fview" width="100%">                  <td align="center">Media</td>
                 <tr>  
                 <td class="tableheader">Host</td>  
                 <td class="tableheader">Name</td>  
                 <td class="tableheader">Type</td>  
                 <td class="tableheader">#</td>  
                 <td class="tableheader">Size</td>  
                 <td class="tableheader">Date</td>  
                 <td class="tableheader">Media</td>  
964                  </tr>                  </tr>
965          };          };
966          my @files = getFiles($where, $offset);  
967          my $file;          my $file;
968    
969          sub hilite_html($$) {          sub hilite_html($$) {
# Line 297  sub displayGrid($$$$) { Line 972  sub displayGrid($$$$) {
972                  return $html;                  return $html;
973          }          }
974    
975          foreach $file (@files) {          sub restore_link($$$$$$) {
976                  my $typeStr  = BackupPC::Attrib::fileType2Text(undef, $file->{'type'});                  my $type = shift;
977                  $retHTML .= "<tr>";                  my $action = 'RestoreFile';
978                    $action = 'browse' if (lc($type) eq 'dir');
979                    return sprintf(qq{<a href="?action=%s&host=%s&num=%d&share=%s&dir=%s">%s</a>}, $action, @_);
980            }
981    
982            my $sth_archived;
983            my %archived_cache;
984    
985                  foreach my $v ((          sub check_archived($$$) {
986                          $file->{'hname'},                  my ($host, $share, $num) = @_;
987                          qq{<img src="$Conf{CgiImageDirURL}/icon-$typeStr.gif" align="center">&nbsp;} . hilite_html( $file->{'fpath'}, $hilite ),  
988                          $typeStr,                  if (my $html = $archived_cache{"$host $share $num"}) {
989                          $file->{'backupno'},                          return $html;
                         $file->{'size'},  
                         $file->{'date'},  
                         $file->{'dvd'}  
                 )) {  
                         $retHTML .= qq{<td class="fviewborder">$v</td>};  
990                  }                  }
991    
992                    $sth_archived ||= $dbh->prepare(qq{
993                            select
994                                    dvd_nr, note,
995                                    count(archive_burned.copy) as copies
996                            from archive
997                            inner join archive_burned on archive_burned.archive_id = archive.id
998                            inner join archive_backup on archive.id = archive_backup.archive_id
999                            inner join backups on backups.id = archive_backup.backup_id
1000                            inner join hosts on hosts.id = backups.hostid
1001                            inner join shares on shares.id = backups.shareid
1002                            where hosts.name = ? and shares.name = ? and backups.num = ?
1003                            group by dvd_nr, note
1004                    });
1005    
1006                    my @mediums;
1007    
1008                    $sth_archived->execute($host, $share, $num);
1009                    while (my $row = $sth_archived->fetchrow_hashref()) {
1010                            push @mediums, '<abbr title="' .
1011                                    $row->{'note'} .
1012                                    ' [' . $row->{'copies'} . ']' .
1013                                    '">' .$row->{'dvd_nr'} .
1014                                    '</abbr>';
1015                    }
1016    
1017                    my $html = join(", ",@mediums);
1018                    $archived_cache{"$host $share $num"} = $html;
1019                    return $html;
1020            }
1021    
1022            my $i = $offset * $on_page;
1023    
1024            foreach $file (@{ $files }) {
1025                    $i++;
1026    
1027                    my $typeStr  = BackupPC::Attrib::fileType2Text(undef, $file->{'type'});
1028                    $retHTML .= qq{<tr class="fviewborder">};
1029    
1030                    $retHTML .= qq{<td class="fviewborder">$i</td>};
1031    
1032                    $retHTML .=
1033                            qq{<td class="fviewborder" align="right">} . $file->{'hname'} . ':' . $file->{'sname'} . qq{</td>} .
1034                            qq{<td class="fviewborder"><img src="$Conf{CgiImageDirURL}/icon-$typeStr.gif" alt="$typeStr" align="middle">&nbsp;} . hilite_html( $file->{'filepath'}, $hilite ) . qq{</td>} .
1035                            qq{<td class="fviewborder" align="center">} . restore_link( $typeStr, ${EscURI( $file->{'hname'} )}, $file->{'backupnum'}, ${EscURI( $file->{'sname'})}, ${EscURI( $file->{'filepath'} )}, $file->{'backupnum'} ) . qq{</td>} .
1036                            qq{<td class="fviewborder" align="right">} . $file->{'size'} . qq{</td>} .
1037                            qq{<td class="fviewborder">} . epoch_to_iso( $file->{'date'} ) . qq{</td>} .
1038                            qq{<td class="fviewborder">} . check_archived( $file->{'hname'}, $file->{'sname'}, $file->{'backupnum'} ) . qq{</td>};
1039    
1040                  $retHTML .= "</tr>";                  $retHTML .= "</tr>";
1041          }          }
1042          $retHTML .= "</table>";          $retHTML .= "</table>";
1043    
1044          # skip pager          # all variables which has to be transfered
1045          return $retHTML;          foreach my $n (qw/search_day_from search_month_from search_year_from search_day_to search_month_to search_year_to search_backup_day_from search_backup_month_from search_backup_year_from search_backup_day_to search_backup_month_to search_backup_year_to search_filename offset/) {
1046                    $retHTML .= qq{<INPUT TYPE="hidden" NAME="$n" VALUE="$In{$n}">\n};
1047            }
1048    
1049          $retHTML .= "<INPUT TYPE=\"hidden\" VALUE=\"\" NAME=\"offset\">";          my $del = '';
1050          for (my $ii = 1; $ii <= $#files; $ii++) {          my $max_page = int( $results / $on_page );
1051                  $retHTML .= "<a href = \"#\" onclick=\"document.forma.offset.value=$ii;document.forma.submit();\">$ii</a>";          my $page = 0;
1052                  if ($ii < $#files) {  
1053                          $retHTML .= " | ";          sub page_uri($) {
1054                    my $param = shift || die "no param?";
1055    
1056                    my $uri = $MyURL;
1057                    my $del = '?';
1058                    foreach my $k (keys %{ $param }) {
1059                            if ($param->{$k}) {
1060                                    $uri .= $del . $k . '=' . ${EscURI( $param->{$k} )};
1061                                    $del = '&';
1062                            }
1063                  }                  }
1064                    return $uri;
1065          }          }
1066    
1067          $retHTML .= "</form>" if ($addForm);          sub page_link($$$) {
1068                          my ($param,$page,$display) = @_;
1069    
1070                    $param->{'offset'} = $page if (defined($page));
1071    
1072                    my $html = '<a href = "' . page_uri($param) . '">' . $display . '</a>';
1073            }
1074    
1075            $retHTML .= '<div style="text-align: center;">';
1076    
1077            if ($offset > 0) {
1078                    $retHTML .= page_link($param, $offset - 1, '&lt;&lt;') . ' ';
1079            }
1080    
1081            while ($page <= $max_page) {
1082                    if ($page == $offset) {
1083                            $retHTML .= $del . '<b>' . ($page + 1) . '</b>';
1084                    } else {
1085                            $retHTML .= $del . page_link($param, $page, $page + 1);
1086                    }
1087    
1088                    if ($page < $offset - $pager_pages && $page != 0) {
1089                            $retHTML .= " ... ";
1090                            $page = $offset - $pager_pages;
1091                            $del = '';
1092                    } elsif ($page > $offset + $pager_pages && $page != $max_page) {
1093                            $retHTML .= " ... ";
1094                            $page = $max_page;
1095                            $del = '';
1096                    } else {
1097                            $del = ' | ';
1098                            $page++;
1099                    }
1100            }
1101    
1102            if ($offset < $max_page) {
1103                    $retHTML .= ' ' . page_link($param, $offset + 1, '&gt;&gt;');
1104            }
1105    
1106            $retHTML .= "</div>";
1107    
1108          return $retHTML;          return $retHTML;
1109  }  }
1110    

Legend:
Removed from v.24  
changed lines
  Added in v.229

  ViewVC Help
Powered by ViewVC 1.1.26