/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 141 - (show annotations)
Fri Oct 7 08:50:23 2005 UTC (18 years, 6 months ago) by ravilov
File size: 20682 byte(s)
fix: checkAll() nije uzimao u obzir vec odabrane backupe

1 #!/usr/bin/perl
2 package BackupPC::SearchLib;
3
4 use strict;
5 use BackupPC::CGI::Lib qw(:all);
6 use BackupPC::Attrib qw(:all);
7 use DBI;
8 use DateTime;
9 use vars qw(%In $MyURL);
10 use Time::HiRes qw/time/;
11
12 my $on_page = 100;
13 my $pager_pages = 10;
14
15 my $dsn = $Conf{SearchDSN};
16 my $db_user = $Conf{SearchUser} || '';
17
18 my $hest_index_path = $Conf{HyperEstraierIndex};
19
20 my $dbh;
21
22 sub get_dbh {
23 $dbh ||= DBI->connect($dsn, $db_user, "", { RaiseError => 1, AutoCommit => 1 } );
24 return $dbh;
25 }
26
27 sub getUnits() {
28 my @ret;
29
30 my $dbh = get_dbh();
31 my $sth = $dbh->prepare(qq{
32 SELECT
33 shares.id as id,
34 hosts.name || ':' || shares.name as share
35 FROM shares
36 JOIN hosts on hostid = hosts.id
37 ORDER BY share
38 } );
39 $sth->execute();
40 push @ret, { 'id' => '', 'share' => '-'}; # dummy any
41
42 while ( my $row = $sth->fetchrow_hashref() ) {
43 push @ret, $row;
44 }
45 return @ret;
46 }
47
48 sub epoch_to_iso {
49 my $t = shift || return;
50 my $iso = BackupPC::Lib::timeStamp(undef, $t);
51 $iso =~ s/\s/ /g;
52 return $iso;
53 }
54
55 sub dates_from_form($) {
56 my $param = shift || return;
57
58 sub mk_epoch_date($$) {
59 my ($name,$suffix) = @_;
60
61 my $yyyy = $param->{ $name . '_year_' . $suffix} || return undef;
62 my $mm .= $param->{ $name . '_month_' . $suffix} ||
63 ( $suffix eq 'from' ? 1 : 12);
64 my $dd .= $param->{ $name . '_day_' . $suffix} ||
65 ( $suffix eq 'from' ? 1 : 31);
66
67 $yyyy =~ s/\D//g;
68 $mm =~ s/\D//g;
69 $dd =~ s/\D//g;
70
71 my $dt = new DateTime(
72 year => $yyyy,
73 month => $mm,
74 day => $dd
75 );
76 print STDERR "mk_epoch_date($name,$suffix) [$yyyy-$mm-$dd] = " . $dt->ymd . " " . $dt->hms . "\n";
77 return $dt->epoch || 'NULL';
78 }
79
80 my @ret = (
81 mk_epoch_date('search_backup', 'from'),
82 mk_epoch_date('search_backup', 'to'),
83 mk_epoch_date('search', 'from'),
84 mk_epoch_date('search', 'to'),
85 );
86
87 return @ret;
88
89 }
90
91
92 sub getWhere($) {
93 my $param = shift || return;
94
95 my ($backup_from, $backup_to, $files_from, $files_to) = dates_from_form($param);
96
97 my @conditions;
98 push @conditions, qq{ backups.date >= $backup_from } if ($backup_from);
99 push @conditions, qq{ backups.date <= $backup_to } if ($backup_to);
100 push @conditions, qq{ files.date >= $files_from } if ($files_from);
101 push @conditions, qq{ files.date <= $files_to } if ($files_to);
102
103 print STDERR "backup: $backup_from - $backup_to files: $files_from - $files_to cond:" . join(" | ",@conditions);
104
105 push( @conditions, ' files.shareid = ' . $param->{'search_share'} ) if ($param->{'search_share'});
106 push (@conditions, " upper(files.path) LIKE upper('%".$param->{'search_filename'}."%')") if ($param->{'search_filename'});
107
108 return join(" and ", @conditions);
109 }
110
111
112 sub getFiles($) {
113 my ($param) = @_;
114
115 my $offset = $param->{'offset'} || 0;
116 $offset *= $on_page;
117
118 my $dbh = get_dbh();
119
120 my $sql_cols = qq{
121 files.id AS fid,
122 hosts.name AS hname,
123 shares.name AS sname,
124 files.backupnum AS backupnum,
125 files.path AS filepath,
126 files.date AS date,
127 files.type AS type,
128 files.size AS size
129 };
130
131 my $sql_from = qq{
132 FROM files
133 INNER JOIN shares ON files.shareID=shares.ID
134 INNER JOIN hosts ON hosts.ID = shares.hostID
135 INNER JOIN backups ON backups.num = files.backupnum and backups.hostID = hosts.ID AND backups.shareID = files.shareID
136 };
137
138 my $sql_where;
139 my $where = getWhere($param);
140 $sql_where = " WHERE ". $where if ($where);
141
142 my $sql_order = qq{
143 ORDER BY files.date
144 LIMIT $on_page
145 OFFSET ?
146 };
147
148 my $sql_count = qq{ select count(files.id) $sql_from $sql_where };
149 my $sql_results = qq{ select $sql_cols $sql_from $sql_where $sql_order };
150
151 my $sth = $dbh->prepare($sql_count);
152 $sth->execute();
153 my ($results) = $sth->fetchrow_array();
154
155 $sth = $dbh->prepare($sql_results);
156 $sth->execute( $offset );
157
158 if ($sth->rows != $results) {
159 my $bug = "$0 BUG: [[ $sql_count ]] = $results while [[ $sql_results ]] = " . $sth->rows;
160 $bug =~ s/\s+/ /gs;
161 print STDERR "$bug\n";
162 }
163
164 my @ret;
165
166 while (my $row = $sth->fetchrow_hashref()) {
167 push @ret, $row;
168 }
169
170 $sth->finish();
171 return ($results, \@ret);
172 }
173
174 sub getHyperEstraier_url($) {
175 my ($use_hest) = @_;
176
177 return unless $use_hest;
178
179 use HyperEstraier;
180 my ($index_path, $index_node_url);
181
182 if ($use_hest =~ m#^http://#) {
183 $index_node_url = $use_hest;
184 } else {
185 $index_path = $TopDir . '/' . $index_path;
186 $index_path =~ s#//#/#g;
187 }
188 return ($index_path, $index_node_url);
189 }
190
191 sub getFilesHyperEstraier($) {
192 my ($param) = @_;
193
194 my $offset = $param->{'offset'} || 0;
195 $offset *= $on_page;
196
197 die "no index_path?" unless ($hest_index_path);
198
199 use HyperEstraier;
200
201 my ($index_path, $index_node_url) = getHyperEstraier_url($hest_index_path);
202
203 # open the database
204 my $db;
205 if ($index_path) {
206 $db = HyperEstraier::Database->new();
207 $db->open($index_path, $HyperEstraier::ESTDBREADER);
208 } elsif ($index_node_url) {
209 $db ||= HyperEstraier::Node->new($index_node_url);
210 $db->set_auth('admin', 'admin');
211 } else {
212 die "BUG: unimplemented";
213 }
214
215 # create a search condition object
216 my $cond = HyperEstraier::Condition->new();
217
218 my $q = $param->{'search_filename'};
219 my $shareid = $param->{'search_share'};
220
221 if (length($q) > 0) {
222 # exact match
223 $cond->add_attr("filepath ISTRINC $q");
224
225 $q =~ s/(.)/$1 /g;
226 # set the search phrase to the search condition object
227 $cond->set_phrase($q);
228 }
229
230 my ($backup_from, $backup_to, $files_from, $files_to) = dates_from_form($param);
231
232 $cond->add_attr("backup_date NUMGE $backup_from") if ($backup_from);
233 $cond->add_attr("backup_date NUMLE $backup_to") if ($backup_to);
234
235 $cond->add_attr("date NUMGE $files_from") if ($files_from);
236 $cond->add_attr("date NUMLE $files_to") if ($files_to);
237
238 $cond->add_attr("shareid NUMEQ $shareid") if ($shareid);
239
240 # $cond->set_max( $offset + $on_page );
241 $cond->set_options( $HyperEstraier::Condition::SURE );
242 $cond->set_order( 'date NUMA' );
243
244 # get the result of search
245 my @res;
246 my ($result, $hits);
247
248 if ($index_path) {
249 $result = $db->search($cond, 0);
250 $hits = $result->size;
251 } elsif ($index_node_url) {
252 $result = $db->search($cond, 0);
253 $hits = $result->doc_num;
254 } else {
255 die "BUG: unimplemented";
256 }
257
258 # for each document in result
259 for my $i ($offset .. ($offset + $on_page - 1)) {
260 last if ($i >= $hits);
261
262 my $doc;
263 if ($index_path) {
264 my $id = $result->get($i);
265 $doc = $db->get_doc($id, 0);
266 } elsif ($index_node_url) {
267 $doc = $result->get_doc($i);
268 } else {
269 die "BUG: unimplemented";
270 }
271
272 my $row;
273 foreach my $c (qw/fid hname sname backupnum fiilename filepath date type size/) {
274 $row->{$c} = $doc->attr($c);
275 }
276 push @res, $row;
277 }
278
279 return ($hits, \@res);
280 }
281
282 sub getGzipName($$$)
283 {
284 my ($host, $share, $backupnum) = @_;
285 my $ret = $Conf{GzipSchema};
286
287 $share =~ s/\//_/g;
288 $ret =~ s/\\h/$host/ge;
289 $ret =~ s/\\s/$share/ge;
290 $ret =~ s/\\n/$backupnum/ge;
291
292 return $ret;
293
294 }
295
296 sub getBackupsNotBurned() {
297
298 my $dbh = get_dbh();
299
300 my $sql = q{
301 SELECT
302 backups.hostID AS hostID,
303 hosts.name AS host,
304 shares.name AS share,
305 backups.id AS backupnum,
306 backups.type AS type,
307 backups.date AS date,
308 backups.size AS size
309 FROM backups
310 INNER JOIN shares ON backups.shareID=shares.ID
311 INNER JOIN hosts ON backups.hostID = hosts.ID
312 LEFT OUTER JOIN archive_backup ON archive_backup.backup_id = backups.id
313 WHERE backups.size > 0 AND archive_backup.backup_id IS NULL
314 GROUP BY
315 backups.hostID,
316 hosts.name,
317 shares.name,
318 backups.num,
319 backups.shareid,
320 backups.id,
321 backups.type,
322 backups.date,
323 backups.size
324 ORDER BY backups.date
325 };
326 my $sth = $dbh->prepare( $sql );
327 my @ret;
328 $sth->execute();
329
330 while ( my $row = $sth->fetchrow_hashref() ) {
331 $row->{'age'} = sprintf("%0.1f", ( (time() - $row->{'date'}) / 86400 ) );
332 $row->{'size'} = sprintf("%0.2f", $row->{'size'} / 1024 / 1024);
333 my (undef,undef,undef,undef,undef,undef,undef,$fs_size,undef,undef,undef,undef,undef) =
334 stat( $Conf{InstallDir}.'/'.$Conf{GzipTempDir}.'/'.
335 getGzipName($row->{'host'}, $row->{share}, $row->{'backupnum'}));
336 $row->{'fs_size'} = $fs_size;
337 push @ret, $row;
338 }
339
340 return @ret;
341 }
342
343 sub displayBackupsGrid() {
344
345 my $retHTML .= q{
346 <form id="forma" method="POST" action="}.$MyURL.q{?action=burn">
347 };
348
349 $retHTML .= <<'EOF3';
350 <style type="text/css">
351 <!--
352 DIV#fixedBox {
353 position: absolute;
354 top: 50em;
355 left: -24%;
356 padding: 0.5em;
357 width: 20%;
358 background-color: #E0F0E0;
359 border: 1px solid #00C000;
360 }
361
362 DIV#fixedBox, DIV#fixedBox INPUT, DIV#fixedBox TEXTAREA {
363 font-size: 10pt;
364 }
365
366 FORM>DIV#fixedBox {
367 position: fixed !important;
368 left: 0.5em !important;
369 top: auto !important;
370 bottom: 1em !important;
371 width: 15% !important;
372 }
373
374 DIV#fixedBox INPUT[type=text], DIV#fixedBox TEXTAREA {
375 border: 1px solid #00C000;
376 }
377
378 DIV#fixedBox #note {
379 display: block;
380 width: 100%;
381 }
382
383 DIV#fixedBox #submitBurner {
384 display: block;
385 width: 100%;
386 margin-top: 0.5em;
387 cursor: pointer;
388 }
389
390 * HTML {
391 overflow-y: hidden;
392 }
393
394 * HTML BODY {
395 overflow-y: auto;
396 height: 100%;
397 font-size: 100%;
398 }
399
400 * HTML DIV#fixedBox {
401 position: absolute;
402 }
403
404 #mContainer, #gradient, #mask, #progressIndicator {
405 display: block;
406 width: 100%;
407 font-size: 10pt;
408 font-weight: bold;
409 text-align: center;
410 vertical-align: middle;
411 padding: 1px;
412 }
413
414 #gradient, #mask, #progressIndicator {
415 left: 0;
416 border-width: 1px;
417 border-style: solid;
418 border-color: #000000;
419 color: #404040;
420 margin: 0.4em;
421 position: absolute;
422 margin-left: -1px;
423 margin-top: -1px;
424 margin-bottom: -1px;
425 overflow: hidden;
426 }
427
428 #mContainer {
429 display: block;
430 position: relative;
431 padding: 0px;
432 margin-top: 0.4em;
433 margin-bottom: 0.5em;
434 }
435
436 #gradient {
437 z-index: 1;
438 background-color: #FFFF00;
439 }
440
441 #mask {
442 z-index: 2;
443 background-color: #FFFFFF;
444 }
445
446 #progressIndicator {
447 z-index: 3;
448 background-color: transparent;
449 }
450 -->
451 </style>
452 <script type="text/javascript">
453 <!--
454
455 var debug_div = null;
456 var media_size = 4400 * 1024;
457
458 function debug(msg) {
459 // return; // Disable debugging
460
461 if (! debug_div) debug_div = document.getElementById('debug');
462
463 // this will create debug div if it doesn't exist.
464 if (! debug_div) {
465 debug_div = document.createElement('div');
466 if (document.body) document.body.appendChild(debug_div);
467 else debug_div = null;
468 }
469 if (debug_div) {
470 debug_div.appendChild(document.createTextNode(msg));
471 debug_div.appendChild(document.createElement("br"));
472 }
473 }
474
475
476 var element_id_cache = Array();
477
478 function element_id(name,element) {
479 if (! element_id_cache[name]) {
480 element_id_cache[name] = self.document.getElementById(name);
481 }
482 return element_id_cache[name];
483 }
484
485 function checkAll(location) {
486 var len = element_id('forma').elements.length;
487 var check_all = element_id('allFiles');
488 var suma = parseInt(element_id('forma').elements['totalsize'].value) || 0;
489
490 for (var i = 0; i < len; i++) {
491
492 var e = element_id('forma').elements[i];
493 if (e.name != 'all' && e.name.substr(0,3) == 'fcb') {
494 if (check_all.checked) {
495 var el = element_id("fss" + e.name.substr(3));
496 var size = parseInt(el.value) || 0;
497 debug('suma: '+suma+' size: '+size);
498 if ((suma + size) < media_size) {
499 suma += size;
500 e.checked = true;
501 } else {
502 break;
503 }
504 } else {
505 e.checked = false;
506 }
507 }
508 }
509 update_sum(suma);
510 }
511
512 function update_sum(suma) {
513 element_id('forma').elements['totalsize'].value = suma;
514 pbar_set(suma, media_size);
515 debug('total size: ' + suma);
516 }
517
518 function sumiraj(e) {
519 var suma = parseInt(element_id('forma').elements['totalsize'].value) || 0;
520 var len = element_id('forma').elements.length;
521 if (e) {
522 var size = parseInt( element_id("fss" + e.name.substr(3)).value);
523 if (e.checked) {
524 suma += size;
525 } else {
526 suma -= size;
527 }
528 } else {
529 suma = 0;
530 for (var i = 0; i < len; i++) {
531 var e = element_id('forma').elements[i];
532 if (e.name != 'all' && e.checked && e.name.substr(0,3) == 'fcb') {
533 var el = element_id("fss" + e.name.substr(3));
534 if (el && el.value) suma += parseInt(el.value) || 0;
535 }
536 }
537 }
538 update_sum(suma);
539 return suma;
540 }
541
542 /* progress bar */
543
544 var _pbar_width = null;
545 var _pbar_warn = 10; // change color in last 10%
546
547 function pbar_reset() {
548 element_id("mask").style.left = "0px";
549 _pbar_width = element_id("mContainer").offsetWidth - 2;
550 element_id("mask").style.width = _pbar_width + "px";
551 element_id("mask").style.display = "block";
552 element_id("progressIndicator").style.zIndex = 10;
553 element_id("progressIndicator").innerHTML = "0";
554 }
555
556 function dec2hex(d) {
557 var hch = '0123456789ABCDEF';
558 var a = d % 16;
559 var q = (d - a) / 16;
560 return hch.charAt(q) + hch.charAt(a);
561 }
562
563 function pbar_set(amount, max) {
564 debug('pbar_set('+amount+', '+max+')');
565
566 if (_pbar_width == null) {
567 var _mc = element_id("mContainer");
568 if (_pbar_width == null) _pbar_width = parseInt(_mc.offsetWidth ? (_mc.offsetWidth - 2) : 0) || null;
569 if (_pbar_width == null) _pbar_width = parseInt(_mc.clientWidth ? (_mc.clientWidth + 2) : 0) || null;
570 if (_pbar_width == null) _pbar_width = 0;
571 }
572
573 var pcnt = Math.floor(amount * 100 / max);
574 var p90 = 100 - _pbar_warn;
575 var pcol = pcnt - p90;
576 if (Math.round(pcnt) <= 100) {
577 if (pcol < 0) pcol = 0;
578 var e = element_id("submitBurner");
579 debug('enable_button');
580 e.disabled = false;
581 var a = e.getAttributeNode('disabled') || null;
582 if (a) e.removeAttributeNode(a);
583 } else {
584 debug('disable button');
585 pcol = _pbar_warn;
586 var e = element_id("submitBurner");
587 if (!e.disabled) e.disabled = true;
588 }
589 var col_g = Math.floor((_pbar_warn - pcol) * 255 / _pbar_warn);
590 var col = '#FF' + dec2hex(col_g) + '00';
591
592 //debug('pcol: '+pcol+' g:'+col_g+' _pbar_warn:'+ _pbar_warn + ' color: '+col);
593 element_id("gradient").style.backgroundColor = col;
594
595 element_id("progressIndicator").innerHTML = pcnt + '%';
596 //element_id("progressIndicator").innerHTML = amount;
597
598 element_id("mask").style.clip = 'rect(' + Array(
599 '0px',
600 element_id("mask").offsetWidth + 'px',
601 element_id("mask").offsetHeight + 'px',
602 Math.round(_pbar_width * amount / max) + 'px'
603 ).join(' ') + ')';
604 }
605
606 if (!self.body) self.body = new Object();
607 self.onload = self.document.onload = self.body.onload = function() {
608 //pbar_reset();
609 sumiraj();
610 };
611
612 // -->
613 </script>
614 <div id="fixedBox">
615
616 Size: <input type="text" name="totalsize" size="7" readonly="readonly" style="text-align:right;" value="0" /> kB
617
618 <div id="mContainer">
619 <div id="gradient">&nbsp;</div>
620 <div id="mask">&nbsp;</div>
621 <div id="progressIndicator">0%</div>
622 </div>
623 <br/>
624
625 Note:
626 <textarea name="note" cols="10" rows="5" id="note"></textarea>
627
628 <input type="submit" id="submitBurner" value="Burn selected" name="submitBurner" />
629
630 </div>
631 <!--
632 <div id="debug" style="float: right; width: 10em; border: 1px #ff0000 solid; background-color: #ffe0e0; -moz-opacity: 0.7;">
633 no debug output yet
634 </div>
635 -->
636 EOF3
637 $retHTML .= q{
638 <input type="hidden" value="burn" name="action">
639 <input type="hidden" value="results" name="search_results">
640 <table style="fview" border="0" cellspacing="0" cellpadding="2">
641 <tr class="tableheader">
642 <td class="tableheader">
643 <input type="checkbox" name="allFiles" id="allFiles" onClick="checkAll('allFiles');">
644 </td>
645 <td align="center">Share</td>
646 <td align="center">Backup no</td>
647 <td align="center">Type</td>
648 <td align="center">date</td>
649 <td align="center">age/days</td>
650 <td align="center">size/MB</td>
651 <td align="center">gzip size</td>
652 </tr>
653
654 };
655
656 my @color = (' bgcolor="#e0e0e0"', '');
657
658 my $i = 0;
659 my $host = '';
660
661 foreach my $backup ( getBackupsNotBurned() ) {
662
663 if ($host ne $backup->{'host'}) {
664 $i++;
665 $host = $backup->{'host'};
666 }
667 my $ftype = "";
668
669 $retHTML .=
670 '<tr' . $color[$i %2 ] . '>
671 <td class="fview">';
672 # FIXME
673 $backup->{'fs_size'} = int($backup->{'size'} * 1024);
674 if (($backup->{'fs_size'} || 0) > 0) {
675 $retHTML .= '
676 <input type="checkbox" name="fcb' .
677 $backup->{'hostid'}.'_'.$backup->{'backupnum'} .
678 '" value="' . $backup->{'hostid'}.'_'.$backup->{'backupnum'} .
679 '" onClick="sumiraj(this);">';
680 }
681 $retHTML .=
682 '</td>' .
683 '<td align="right">' . $backup->{'host'} . ':' . $backup->{'share'} . '</td>' .
684 '<td align="center">' . $backup->{'backupnum'} . '</td>' .
685 '<td align="center">' . $backup->{'type'} . '</td>' .
686 '<td align="center">' . epoch_to_iso( $backup->{'date'} ) . '</td>' .
687 '<td align="center">' . $backup->{'age'} . '</td>' .
688 '<td align="right">' . $backup->{'size'} . '</td>' .
689 '<td align="right">' . $backup->{'fs_size'} .
690 '<input type="hidden" iD="fss'.$backup->{'hostid'}.'_'.$backup->{'backupnum'} . '" value="'. $backup->{'fs_size'} .'"></td>' .
691
692 "</tr>\n";
693 }
694
695 $retHTML .= "</table>";
696 $retHTML .= "</form>";
697
698 return $retHTML;
699 }
700
701 sub displayGrid($) {
702 my ($param) = @_;
703
704 my $offset = $param->{'offset'};
705 my $hilite = $param->{'search_filename'};
706
707 my $retHTML = "";
708
709 my $start_t = time();
710
711 my ($results, $files);
712 if ($param->{'use_hest'} && length($hilite) > 0) {
713 ($results, $files) = getFilesHyperEstraier($param);
714 } else {
715 ($results, $files) = getFiles($param);
716 }
717
718 my $dur_t = time() - $start_t;
719 my $dur = sprintf("%0.4fs", $dur_t);
720
721 my ($from, $to) = (($offset * $on_page) + 1, ($offset * $on_page) + $on_page);
722
723 if ($results <= 0) {
724 $retHTML .= qq{
725 <p style="color: red;">No results found...</p>
726 };
727 return $retHTML;
728 } else {
729 # DEBUG
730 #use Data::Dumper;
731 #$retHTML .= '<pre>' . Dumper($files) . '</pre>';
732 }
733
734
735 $retHTML .= qq{
736 <div>
737 Found <b>$results files</b> showing <b>$from - $to</b> (took $dur)
738 </div>
739 <table style="fview" width="100%" border="0" cellpadding="2" cellspacing="0">
740 <tr class="fviewheader">
741 <td></td>
742 <td align="center">Share</td>
743 <td align="center">Type and Name</td>
744 <td align="center">#</td>
745 <td align="center">Size</td>
746 <td align="center">Date</td>
747 <td align="center">Media</td>
748 </tr>
749 };
750
751 my $file;
752
753 sub hilite_html($$) {
754 my ($html, $search) = @_;
755 $html =~ s#($search)#<b>$1</b>#gis;
756 return $html;
757 }
758
759 sub restore_link($$$$$$) {
760 my $type = shift;
761 my $action = 'RestoreFile';
762 $action = 'browse' if (lc($type) eq 'dir');
763 return sprintf(qq{<a href="?action=%s&host=%s&num=%d&share=%s&dir=%s">%s</a>}, $action, @_);
764 }
765
766 my $i = $offset * $on_page;
767
768 foreach $file (@{ $files }) {
769 $i++;
770
771 my $typeStr = BackupPC::Attrib::fileType2Text(undef, $file->{'type'});
772 $retHTML .= qq{<tr class="fviewborder">};
773
774 $retHTML .= qq{<td class="fviewborder">$i</td>};
775
776 $retHTML .=
777 qq{<td class="fviewborder" align="right">} . $file->{'hname'} . ':' . $file->{'sname'} . qq{</td>} .
778 qq{<td class="fviewborder"><img src="$Conf{CgiImageDirURL}/icon-$typeStr.gif" alt="$typeStr" align="middle">&nbsp;} . hilite_html( $file->{'filepath'}, $hilite ) . qq{</td>} .
779 qq{<td class="fviewborder" align="center">} . restore_link( $typeStr, ${EscURI( $file->{'hname'} )}, $file->{'backupnum'}, ${EscURI( $file->{'sname'})}, ${EscURI( $file->{'filepath'} )}, $file->{'backupnum'} ) . qq{</td>} .
780 qq{<td class="fviewborder" align="right">} . $file->{'size'} . qq{</td>} .
781 qq{<td class="fviewborder">} . epoch_to_iso( $file->{'date'} ) . qq{</td>} .
782 qq{<td class="fviewborder">} . '?' . qq{</td>};
783
784 $retHTML .= "</tr>";
785 }
786 $retHTML .= "</table>";
787
788 # all variables which has to be transfered
789 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/) {
790 $retHTML .= qq{<INPUT TYPE="hidden" NAME="$n" VALUE="$In{$n}">\n};
791 }
792
793 my $del = '';
794 my $max_page = int( $results / $on_page );
795 my $page = 0;
796
797 sub page_link($$$) {
798 my ($param,$page,$display) = @_;
799
800 $param->{'offset'} = $page;
801
802 my $html = '<a href = "' . $MyURL;
803 my $del = '?';
804 foreach my $k (keys %{ $param }) {
805 if ($param->{$k}) {
806 $html .= $del . $k . '=' . ${EscURI( $param->{$k} )};
807 $del = '&';
808 }
809 }
810 $html .= '">' . $display . '</a>';
811 }
812
813 $retHTML .= '<div style="text-align: center;">';
814
815 if ($offset > 0) {
816 $retHTML .= page_link($param, $offset - 1, '&lt;&lt;') . ' ';
817 }
818
819 while ($page <= $max_page) {
820 if ($page == $offset) {
821 $retHTML .= $del . '<b>' . ($page + 1) . '</b>';
822 } else {
823 $retHTML .= $del . page_link($param, $page, $page + 1);
824 }
825
826 if ($page < $offset - $pager_pages && $page != 0) {
827 $retHTML .= " ... ";
828 $page = $offset - $pager_pages;
829 $del = '';
830 } elsif ($page > $offset + $pager_pages && $page != $max_page) {
831 $retHTML .= " ... ";
832 $page = $max_page;
833 $del = '';
834 } else {
835 $del = ' | ';
836 $page++;
837 }
838 }
839
840 if ($offset < $max_page) {
841 $retHTML .= ' ' . page_link($param, $offset + 1, '&gt;&gt;');
842 }
843
844 $retHTML .= "</div>";
845
846 return $retHTML;
847 }
848
849 1;

  ViewVC Help
Powered by ViewVC 1.1.26