/[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 186 - (show annotations)
Wed Oct 12 12:53:27 2005 UTC (18 years, 6 months ago) by dpavlin
File size: 21659 byte(s)
 r8484@llin:  dpavlin | 2005-10-12 14:53:21 +0200
 fix bug with same dates in from and to field

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

  ViewVC Help
Powered by ViewVC 1.1.26