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

Legend:
Removed from v.6  
changed lines
  Added in v.320

  ViewVC Help
Powered by ViewVC 1.1.26