use strict;
use BackupPC::CGI::Lib qw(:all);
use BackupPC::Attrib qw(:all);
-use Data::Dumper;
use DBI;
+use DateTime;
+use vars qw(%In $MyURL);
+use Time::HiRes qw/time/;
+
+my $on_page = 100;
+my $pager_pages = 10;
+
+my $dsn = $Conf{SearchDSN};
+my $db_user = $Conf{SearchUser} || '';
sub getUnits() {
- my @ret = ();
- my $tmp;
- my $dbh = DBI->connect( "dbi:SQLite:dbname=$Conf{SearchDB}",
- "", "", { RaiseError => 1, AutoCommit => 1 } );
- my $st =
- $dbh->prepare(
- " SELECT shares.ID AS ID, shares.share AS name FROM shares;");
- $st->execute();
- push (@ret, { 'ID' => '', 'name' => '-'});
- while ( $tmp = $st->fetchrow_hashref() ) {
- push( @ret, { 'ID' => $tmp->{'ID'}, 'name' => $tmp->{'name'} } );
- }
- $dbh->disconnect();
- return @ret;
+ my @ret;
+
+ my $dbh = DBI->connect($dsn, $db_user, "", { RaiseError => 1, AutoCommit => 1 } );
+ my $sth = $dbh->prepare(qq{ SELECT id, share FROM shares} );
+ $sth->execute();
+ push @ret, { 'id' => '', 'share' => '-'}; # dummy any
+
+ while ( my $row = $sth->fetchrow_hashref() ) {
+ push @ret, $row;
+ }
+ $dbh->disconnect();
+ return @ret;
+}
+
+sub epoch_to_iso {
+ my $t = shift || return;
+ my $dt = DateTime->from_epoch( epoch => $t ) || return;
+ print STDERR "BUG: $t != " . $dt->epoch . "\n" unless ($t == $dt->epoch);
+ return $dt->ymd . ' ' . $dt->hms;
}
sub getWhere($) {
- my ($param) = @_;
- my $retSQL = "";
- my @conditions = ();
- my $cond;
+ my ($param) = @_;
+ my @conditions;
-
-
-
- if ( defined( $param->{'search_backup_day_from'} ) && $param->{'search_backup_day_from'} ne "") {
- push( @conditions,
- ' strftime("%d", datetime(backups.date, "unixepoch","localtime")) >= "'
- . $param->{'search_backup_day_from'} ."\"");
- }
- if ( defined( $param->{'search_backup_day_to'} ) && $param->{'search_backup_day_to'} ne "") {
- push( @conditions,
- ' strftime("%d", datetime(backups.date, "unixepoch","localtime")) <= "'
- . $param->{'search_backup_day_from'} ."\"");
- }
- if ( defined( $param->{'search_backup_month_from'} ) && $param->{'search_backup_month_from'} ne "") {
- push( @conditions,
- ' strftime("%m", datetime(backups.date, "unixepoch","localtime")) >= "'
- . $param->{'search_backup_month_from'} ."\"");
- }
- if ( defined( $param->{'search_backup_month_to'} ) && $param->{'search_backup_month_to'} ne "") {
- push( @conditions,
- ' strftime("%m", datetime(backups.date, "unixepoch","localtime")) <= "'
- . $param->{'search_backup_month_to'} ."\"");
- }
- if ( defined( $param->{'search_backup_year_from'} ) && $param->{'search_backup_year_from'} ne "") {
- push( @conditions,
- ' strftime("%Y", datetime(backups.date, "unixepoch","localtime")) >= "'
- . $param->{'search_backup_year_from'} ."\"");
- }
- if ( defined( $param->{'search_backup_year_to'} ) && $param->{'search_backup_year_to'} ne "") {
- push( @conditions,
- ' strftime("%Y", datetime(backups.date, "unixepoch","localtime")) <= "'
- . $param->{'search_backup_year_to'} ."\"");
- }
+ sub mk_epoch_date($$) {
+ my ($name,$suffix) = @_;
- if ( defined( $param->{'search_day_from'} ) && $param->{'search_day_from'} ne "" ) {
- push( @conditions,
- ' strftime("%d", datetime(files.date, "unixepoch","localtime")) >= "'
- . $param->{'search_day_from'} ."\"");
- }
- if ( defined( $param->{'search_month_from'} ) && $param->{'search_month_from'} ne "") {
- push( @conditions,
- ' strftime("%m", datetime(files.date, "unixepoch","localtime")) >= "'
- . $param->{'search_month_from'} ."\"");
- }
- if ( defined( $param->{'search_year_from'} ) && $param->{'search_year_from'} ne "") {
- push( @conditions,
- ' strftime("%Y", datetime(files.date, "unixepoch","localtime")) >= "'
- . $param->{'search_year_from'} ."\"");
- }
- if ( defined( $param->{'search_day_to'} ) && $param->{'search_day_to'} ne "" ) {
- push( @conditions,
- ' strftime("%d", datetime(files.date, "unixepoch","localtime")) <= "'
- . $param->{'search_day_to'} ."\"");
- }
- if ( defined( $param->{'search_month_to'} ) && $param->{'search_month_to'} ne "" ) {
- 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'} ."\"");
- }
+ my $yyyy = $param->{ $name . '_year_' . $suffix} || return;
+ my $mm .= $param->{ $name . '_month_' . $suffix} ||
+ ( $suffix eq 'from' ? 1 : 12);
+ my $dd .= $param->{ $name . '_day_' . $suffix} ||
+ ( $suffix eq 'from' ? 1 : 31);
+ my $dt = new DateTime(
+ year => $yyyy,
+ month => $mm,
+ day => $dd
+ );
+ return $dt->epoch || 'NULL';
+ }
- if ( defined( $param->{'search_host'} ) && $param->{'search_host'} ne "") {
- push( @conditions, ' backups.hostID = ' . $param->{'search_host'} );
- }
+ my $backup_from = mk_epoch_date('search_backup', 'from');
+ push @conditions, qq{ backups.date >= $backup_from } if ($backup_from);
+ my $backup_to = mk_epoch_date('search_backup', 'to');
+ push @conditions, qq{ backups.date <= $backup_to } if ($backup_to);
- 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;
- }
+ my $files_from = mk_epoch_date('search', 'from');
+ push @conditions, qq{ files.date >= $files_from } if ($files_from);
+ my $files_to = mk_epoch_date('search', 'to');
+ push @conditions, qq{ files.date <= $files_to } if ($files_to);
+ print STDERR "backup: $backup_from - $backup_to files: $files_from - $files_to cond:" . join(" | ",@conditions);
- return $retSQL;
+ push( @conditions, ' files.shareid = ' . $param->{'search_share'} ) if ($param->{'search_share'});
+
+ push (@conditions, " upper(files.name) LIKE upper('%".$param->{'search_filename'}."%')") if ($param->{'search_filename'});
+
+ return (
+ join(" and ", @conditions),
+ $files_from, $files_to,
+ $backup_from, $backup_to
+ );
}
-sub getFiles($)
- {
- my ($where) = @_;
-
- my $dbh = DBI->connect( "dbi:SQLite:dbname=$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;
- }
-
- my $st = $dbh->prepare(
- $sql
- );
+sub getFiles($$) {
+ my ($where, $offset) = @_;
- $st->execute;
-
- my @ret = ();
- my $tmp;
-
- while ($tmp = $st->fetchrow_hashref())
- {
- push(@ret, {
- 'hname' => $tmp->{'hname'},
- 'sname' => $tmp->{'sname'},
- 'sharename' => $tmp->{'sharename'},
- 'backupno' => $tmp->{'backupNum'},
- 'fname' => $tmp->{'filename'},
- 'fpath' => $tmp->{'filepath'},
- 'networkpath' => $tmp->{'networkPath'},
- 'date' => $tmp->{'date'},
- 'type' => $tmp->{'filetype'},
- 'size' => $tmp->{'size'},
- 'id' => $tmp->{'fid'},
- 'dvd' => $tmp->{'dvd'}
- }
- );
-
+ my $dbh = DBI->connect($dsn, $db_user, "", { RaiseError => 1, AutoCommit => 1 } );
+
+ my $sql_cols = qq{
+ files.id AS fid,
+ hosts.name AS hname,
+ shares.name AS sname,
+ shares.share AS sharename,
+ files.backupNum AS backupNum,
+ files.name AS filename,
+ files.path AS filepath,
+ shares.share||files.fullpath AS networkPath,
+ files.date AS date,
+ files.type AS filetype,
+ files.size AS size,
+ dvds.name AS dvd
+ };
+
+ my $sql_from = qq{
+ FROM files
+ INNER JOIN shares ON files.shareID=shares.ID
+ INNER JOIN hosts ON hosts.ID = shares.hostID
+ INNER JOIN backups ON backups.num = files.backupNum and backups.hostID = hosts.ID
+ };
+
+ my $sql_dvd_from = qq{
+ LEFT JOIN dvds ON dvds.ID = files.dvdid
+ };
+
+ my $sql_where;
+ $sql_where = " WHERE ". $where if ($where);
+
+ my $sql_order = qq{
+ ORDER BY files.id
+ LIMIT $on_page
+ OFFSET ?
+ };
+
+ my $sql_count = qq{ select count(files.id) $sql_from $sql_where };
+ my $sql_results = qq{ select $sql_cols $sql_from $sql_dvd_from $sql_where $sql_order };
+
+ $offset ||= 0;
+ $offset = ($offset * $on_page);
+
+ my $sth = $dbh->prepare($sql_count);
+ $sth->execute();
+ my ($results) = $sth->fetchrow_array();
+
+ $sth = $dbh->prepare($sql_results);
+ $sth->execute( $offset );
+
+ if ($sth->rows != $results) {
+ my $bug = "$0 BUG: [[ $sql_count ]] = $results while [[ $sql_results ]] = " . $sth->rows;
+ $bug =~ s/\s+/ /gs;
+ print STDERR "$bug\n";
}
+
+ my @ret;
- $st->finish();
- $dbh->disconnect();
- return @ret;
- }
+ while (my $row = $sth->fetchrow_hashref()) {
+ push(@ret, {
+ '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'}
+ });
+ }
+
+ $sth->finish();
+ $dbh->disconnect();
+ return ($results, \@ret);
+}
-sub getBackupsNotBurned()
- {
- my $dbh = DBI->connect( "dbi:SQLite:dbname=$Conf{SearchDB}",
- "", "", { RaiseError => 1, AutoCommit => 1 } );
- my $sql = q{
- SELECT
- hosts.ID AS hostID,
- hosts.name AS host,
- backups.num AS backupno,
- backups.type AS type,
- backups.date AS date
- FROM backups, shares, files, hosts
- WHERE
- backups.num = files.backupNum AND
- shares.ID = files.shareID AND
- backups.hostID = shares.hostID AND
- hosts.ID = backups.hostID AND
- files.dvdid IS NULL
- GROUP BY
- backups.hostID, backups.num
- };
- my $st = $dbh -> prepare( $sql );
- my @ret = ();
- $st -> execute();
-
- while ( my $tmp = $st -> fetchrow_hashref() )
- {
- push(@ret, {
- 'host' => $tmp->{'host'},
- 'hostid' => $tmp->{'hostID'},
- 'backupno' => $tmp->{'backupno'},
- 'type' => $tmp->{'type'},
- 'date' => $tmp->{'date'}
+sub getBackupsNotBurned() {
+
+ my $dbh = DBI->connect($dsn, $db_user, "", { RaiseError => 1, AutoCommit => 1 } );
+ my $sql = q{
+ SELECT
+ hosts.ID AS hostid,
+ min(hosts.name) AS host,
+ backups.num AS backupno,
+ min(backups.type) AS type,
+ min(backups.date) AS date
+ FROM backups, shares, files, hosts
+ WHERE
+ backups.num = files.backupNum AND
+ shares.ID = files.shareID AND
+ backups.hostID = shares.hostID AND
+ hosts.ID = backups.hostID AND
+ files.dvdid IS NULL
+ GROUP BY
+ backups.hostID, backups.num, hosts.id
+ ORDER BY min(backups.date)
+ };
+ my $sth = $dbh->prepare( $sql );
+ my @ret;
+ $sth->execute();
+
+ while ( my $row = $sth->fetchrow_hashref() ) {
+ push(@ret, {
+ 'host' => $row->{'host'},
+ 'hostid' => $row->{'hostid'},
+ 'backupno' => $row->{'backupno'},
+ 'type' => $row->{'type'},
+ 'date' => $row->{'date'},
+ 'age' => sprintf("%0.1f", ( (time() - $row->{'date'}) / 86400 ) ),
}
- );
+ );
}
- return @ret;
- }
+ return @ret;
+}
sub displayBackupsGrid()
{
my $retHTML = "";
my $addForm = 1;
- if ($addForm)
- {
+ if ($addForm) {
$retHTML .= <<EOF3;
<script language="javascript" type="text/javascript">
//-->
</script>
EOF3
- $retHTML .= q{<form name="forma" method="POST" action="}."$MyURL"."?action=burn\"";
+ $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 .= "<table style=\"fview\">";
- $retHTML .= "<tr> ";
- if ($addForm)
- {
+ $retHTML .= qq{<table style="fview"><tr>};
+
+ if ($addForm) {
$retHTML .= "<td class=\"tableheader\"><input type=\"checkbox\" name=\"allFiles\" onClick=\"checkAll('allFiles');\"></td>";
}
- $retHTML .= "<td class=\"tableheader\">Host</td> <td class=\"tableheader\">Backup no</td> <td class=\"tableheader\">Type</td> <td class=\"tableheader\">date</td></tr>";
- my @backups = getBackupsNotBurned();
- my $backup;
-
- if ($addForm)
- {
- $retHTML .= "<tr>";
- $retHTML .= "<td colspan=7 style=\"tableheader\">";
- $retHTML .= "<input type=\"submit\" value=\"Burn selected backups on medium\" name=\"submitBurner\">";
- $retHTML .= "</td>";
- $retHTML .= "</tr>";
-
+ $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>
+ };
+
+ my @backups = getBackupsNotBurned();
+ my $backup;
+
+ if ($addForm) {
+ $retHTML .= qq{
+ <tr><td colspan=7 style="tableheader">
+ <input type="submit" value="Burn selected backups on medium" name="submitBurner">
+ </td></tr>
+ };
}
- foreach $backup(@backups)
- {
- my $ftype = "";
+
+ foreach $backup(@backups) {
+
+ my $ftype = "";
- $retHTML .= "<tr>";
- if ($addForm)
- {
- $retHTML .= "<td class=\"fview\"> <input type=\"checkbox\" name=\"fcb"
- .$backup->{'hostid'}."_".$backup->{'backupno'}
- ."\" value=\"".$backup->{'hostid'}."_".$backup->{'backupno'}."\"> </td>";
- }
+ $retHTML .= "<tr>";
+ if ($addForm) {
+ $retHTML .= '<td class="fview"><input type="checkbox" name="fcb' .
+ $backup->{'hostid'}.'_'.$backup->{'backupno'} .
+ '" value="' . $backup->{'hostid'}.'_'.$backup->{'backupno'} .
+ '"></td>';
+ }
- $retHTML .= "<td class=\"fviewborder\">" . $backup->{'host'} . "</td>";
- $retHTML .= "<td class=\"fviewborder\">" . $backup->{'backupno'} . "</td>";
- $retHTML .= "<td class=\"fviewborder\">" . $backup->{'type'} . "</td>";
- $retHTML .= "<td class=\"fviewborder\">" . $backup->{'date'} . "<td>";
- $retHTML .= "</tr>";
+ $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>';
}
- $retHTML .= "</table>";
- if ($addForm)
- {
- $retHTML .= "</form>";
- }
-
- return $retHTML;
-
-
- }
-sub displayGrid($$)
- {
- my ($where, $addForm) = @_;
- my $retHTML = "";
+ $retHTML .= "</table>";
+
+ if ($addForm) {
+ $retHTML .= "</form>";
+ }
- if ($addForm)
- {
- $retHTML .= <<EOF3;
-<script language="javascript" type="text/javascript">
-<!--
+ return $retHTML;
+}
- function checkAll(location)
- {
- for (var i=0;i<document.forma.elements.length;i++)
- {
- var e = document.forma.elements[i];
- if ((e.checked || !e.checked) && e.name != \'all\') {
- if (eval("document.forma."+location+".checked")) {
- e.checked = true;
- } else {
- e.checked = false;
- }
- }
- }
- }
+sub displayGrid($$$$) {
+ my ($where, $addForm, $offset, $hilite) = @_;
+ my $retHTML = "";
+
+ my $start_t = time();
+ my ($results, $files) = getFiles($where, $offset);
-//-->
-</script>
-EOF3
- $retHTML .= q{<form name="forma" method="POST" action="}."$MyURL"."?action=burn\"";
- $retHTML.= q{<input type="hidden" value="burn" name="action">};
- $retHTML .= q{<input type="hidden" value="results" name="search_results">};
+ my $dur_t = time() - $start_t;
+ my $dur = sprintf("%0.4fs", $dur_t);
+
+ my ($from, $to) = (($offset * $on_page) + 1, ($offset * $on_page) + $on_page);
+
+ if ($results <= 0) {
+ $retHTML .= qq{
+ <p style="color: red;">No results found...</p>
+ };
+ return $retHTML;
+ } else {
+ # DEBUG
+ #use Data::Dumper;
+ #$retHTML .= '<pre>' . Dumper($files) . '</pre>';
}
- $retHTML .= "<table style=\"fview\">";
- $retHTML .= "<tr> ";
- if ($addForm)
- {
- $retHTML .= "<td class=\"tableheader\"><input type=\"checkbox\" name=\"allFiles\" onClick=\"checkAll('allFiles');\"></td>";
+
+
+ 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">};
}
- $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>";
- my @files = getFiles($where);
- my $file;
-
- if ($addForm)
- {
- $retHTML .= "<tr>";
- $retHTML .= "<td colspan=7 style=\"tableheader\">";
- $retHTML .= "<input type=\"submit\" value=\"Burn selected files on medium\" name=\"submitBurner\">";
- $retHTML .= "</td>";
- $retHTML .= "</tr>";
-
+
+
+ $retHTML .= qq{
+ <br/>Found <b>$results files</b> showing <b>$from - $to</b> (took $dur)
+ <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>
+ </tr>
+ };
+
+ my $file;
+
+ sub hilite_html($$) {
+ my ($html, $search) = @_;
+ $html =~ s#($search)#<b>$1</b>#gis;
+ return $html;
}
- foreach $file(@files)
- {
- my $ftype = "";
-
- if ($file->{'type'} == BPC_FTYPE_DIR)
- {
- $ftype = "dir";
- }
- else
- {
- $ftype = "file";
- }
- $retHTML .= "<tr>";
- if ($addForm)
- {
- $retHTML .= "<td class=\"fview\"> <input type=\"checkbox\" name=\"fcb"
- .$file->{'id'}
- ."\" value=\"".$file->{'id'}."\"> </td>";
- }
-
- $retHTML .= "<td class=\"fviewborder\">" . $file->{'hname'} ."</td>";
- $retHTML .= "<td class=\"fviewborder\">" . $file->{'fname'} . "</td>";
- $retHTML .= "<td class=\"fviewborder\">" . $ftype . "</td>";
- $retHTML .= "<td class=\"fviewborder\">" . $file->{'backupno'} . "</td>";
- $retHTML .= "<td class=\"fviewborder\">" . $file->{'size'} . "</td>";
- $retHTML .= "<td class=\"fviewborder\">" . $file->{'date'} . "</td>";
- $retHTML .= "<td class=\"fviewborder\">" . $file->{'dvd'} . "</td>";
- $retHTML .= "</tr>";
+
+ sub restore_link($$$$$$) {
+ my $type = shift;
+ my $action = 'RestoreFile';
+ $action = 'browse' if (lc($type) eq 'dir');
+ return sprintf(qq{<a href="?action=%s&host=%s&num=%d&share=%s&dir=%s">%s</a>}, $action, @_);
}
- $retHTML .= "</table>";
- if ($addForm)
- {
- $retHTML .= "</form>";
- }
-
- return $retHTML;
- }
+
+ foreach $file (@{ $files }) {
+ my $typeStr = BackupPC::Attrib::fileType2Text(undef, $file->{'type'});
+ $retHTML .= "<tr>";
+
+ foreach my $v ((
+ $file->{'sharename'},
+ qq{<img src="$Conf{CgiImageDirURL}/icon-$typeStr.gif" align="center"> } . hilite_html( $file->{'fpath'}, $hilite ),
+ $typeStr,
+ restore_link( $typeStr, $file->{'hname'}, $file->{'backupno'}, $file->{'sname'}, $file->{'fpath'}, $file->{'backupno'} ),
+ $file->{'size'},
+ epoch_to_iso( $file->{'date'} ),
+ $file->{'dvd'}
+ )) {
+ $retHTML .= qq{<td class="fviewborder">$v</td>};
+ }
+
+ $retHTML .= "</tr>";
+ }
+ $retHTML .= "</table>";
+
+ # all variables which has to be transfered
+ 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/) {
+ $retHTML .= qq{<INPUT TYPE="hidden" NAME="$n" VALUE="$In{$n}">\n};
+ }
+
+ my $del = '';
+ my $max_page = int( $results / $on_page );
+ my $page = 0;
+
+ my $link_fmt = '<a href = "#" onclick="document.forma.offset.value=%d;document.forma.submit();">%s</a>';
+
+ $retHTML .= '<div style="text-align: center;">';
+
+ if ($offset > 0) {
+ $retHTML .= sprintf($link_fmt, $offset - 1, '<<') . ' ';
+ }
+
+ while ($page <= $max_page) {
+ if ($page == $offset) {
+ $retHTML .= $del . '<b>' . ($page + 1) . '</b>';
+ } else {
+ $retHTML .= $del . sprintf($link_fmt, $page, $page + 1);
+ }
+
+ if ($page < $offset - $pager_pages && $page != 0) {
+ $retHTML .= " ... ";
+ $page = $offset - $pager_pages;
+ $del = '';
+ } elsif ($page > $offset + $pager_pages && $page != $max_page) {
+ $retHTML .= " ... ";
+ $page = $max_page;
+ $del = '';
+ } else {
+ $del = ' | ';
+ $page++;
+ }
+ }
+
+ if ($offset < $max_page) {
+ $retHTML .= ' ' . sprintf($link_fmt, $offset + 1, '>>');
+ }
+
+ $retHTML .= "</div>";
+
+ $retHTML .= "</form>" if ($addForm);
+
+ return $retHTML;
+}
1;