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

Legend:
Removed from v.58  
changed lines
  Added in v.379

  ViewVC Help
Powered by ViewVC 1.1.26