/[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 155 - (show annotations)
Mon Oct 10 13:04:48 2005 UTC (18 years, 7 months ago) by dpavlin
File size: 21602 byte(s)
 r8415@llin:  dpavlin | 2005-10-10 15:03:25 +0200
 nicer filenames (remove multiple ___)

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 $ret =~ s/__+/_/g;
293
294 return $ret;
295
296 }
297
298 sub getGzipSize($$)
299 {
300 my ($hostID, $backupNum) = @_;
301 my $ret;
302 my $sql;
303 my $dbh = get_dbh();
304
305 $sql = q{
306 SELECT hosts.name as host,
307 shares.name as share,
308 backups.num as backupnum
309 FROM hosts, backups, shares
310 WHERE shares.id=backups.shareid AND
311 hosts.id =backups.hostid AND
312 hosts.id=? AND
313 backups.num=?
314 };
315 my $sth = $dbh->prepare($sql);
316 $sth->execute($hostID, $backupNum);
317
318 my $row = $sth->fetchrow_hashref();
319
320 my (undef,undef,undef,undef,undef,undef,undef,$ret,undef,undef,undef,undef,undef) =
321 stat( $Conf{InstallDir}.'/'.$Conf{GzipTempDir}.'/'.
322 getGzipName($row->{'host'}, $row->{share}, $row->{'backupnum'}));
323
324 return $ret;
325 }
326
327 sub getBackupsNotBurned() {
328
329 my $dbh = get_dbh();
330
331 my $sql = q{
332 SELECT
333 backups.hostID AS hostID,
334 hosts.name AS host,
335 shares.name AS share,
336 backups.num AS backupnum,
337 backups.type AS type,
338 backups.date AS date,
339 backups.size AS size,
340 backups.id AS id
341 FROM backups
342 INNER JOIN shares ON backups.shareID=shares.ID
343 INNER JOIN hosts ON backups.hostID = hosts.ID
344 LEFT OUTER JOIN archive_backup ON archive_backup.backup_id = backups.id
345 WHERE backups.size > 0 AND archive_backup.backup_id IS NULL
346 GROUP BY
347 backups.hostID,
348 hosts.name,
349 shares.name,
350 backups.num,
351 backups.shareid,
352 backups.id,
353 backups.type,
354 backups.date,
355 backups.size
356 ORDER BY backups.date
357 };
358 my $sth = $dbh->prepare( $sql );
359 my @ret;
360 $sth->execute();
361
362 while ( my $row = $sth->fetchrow_hashref() ) {
363 $row->{'age'} = sprintf("%0.1f", ( (time() - $row->{'date'}) / 86400 ) );
364 $row->{'size'} = sprintf("%0.2f", $row->{'size'} / 1024 / 1024);
365 my (undef,undef,undef,undef,undef,undef,undef,$fs_size,undef,undef,undef,undef,undef) =
366 stat( $Conf{InstallDir}.'/'.$Conf{GzipTempDir}.'/'.
367 getGzipName($row->{'host'}, $row->{share}, $row->{'backupnum'}));
368 $row->{'fs_size'} = $fs_size;
369 push @ret, $row;
370 }
371
372 return @ret;
373 }
374
375 sub displayBackupsGrid() {
376
377 my $retHTML .= q{
378 <form id="forma" method="POST" action="}.$MyURL.q{?action=burn">
379 };
380
381 $retHTML .= <<'EOF3';
382 <style type="text/css">
383 <!--
384 DIV#fixedBox {
385 position: absolute;
386 top: 50em;
387 left: -24%;
388 padding: 0.5em;
389 width: 20%;
390 background-color: #E0F0E0;
391 border: 1px solid #00C000;
392 }
393
394 DIV#fixedBox, DIV#fixedBox INPUT, DIV#fixedBox TEXTAREA {
395 font-size: 10pt;
396 }
397
398 FORM>DIV#fixedBox {
399 position: fixed !important;
400 left: 0.5em !important;
401 top: auto !important;
402 bottom: 1em !important;
403 width: 15% !important;
404 }
405
406 DIV#fixedBox INPUT[type=text], DIV#fixedBox TEXTAREA {
407 border: 1px solid #00C000;
408 }
409
410 DIV#fixedBox #note {
411 display: block;
412 width: 100%;
413 }
414
415 DIV#fixedBox #submitBurner {
416 display: block;
417 width: 100%;
418 margin-top: 0.5em;
419 cursor: pointer;
420 }
421
422 * HTML {
423 overflow-y: hidden;
424 }
425
426 * HTML BODY {
427 overflow-y: auto;
428 height: 100%;
429 font-size: 100%;
430 }
431
432 * HTML DIV#fixedBox {
433 position: absolute;
434 }
435
436 #mContainer, #gradient, #mask, #progressIndicator {
437 display: block;
438 width: 100%;
439 font-size: 10pt;
440 font-weight: bold;
441 text-align: center;
442 vertical-align: middle;
443 padding: 1px;
444 }
445
446 #gradient, #mask, #progressIndicator {
447 left: 0;
448 border-width: 1px;
449 border-style: solid;
450 border-color: #000000;
451 color: #404040;
452 margin: 0.4em;
453 position: absolute;
454 margin-left: -1px;
455 margin-top: -1px;
456 margin-bottom: -1px;
457 overflow: hidden;
458 }
459
460 #mContainer {
461 display: block;
462 position: relative;
463 padding: 0px;
464 margin-top: 0.4em;
465 margin-bottom: 0.5em;
466 }
467
468 #gradient {
469 z-index: 1;
470 background-color: #FFFF00;
471 }
472
473 #mask {
474 z-index: 2;
475 background-color: #FFFFFF;
476 }
477
478 #progressIndicator {
479 z-index: 3;
480 background-color: transparent;
481 }
482 -->
483 </style>
484 <script type="text/javascript">
485 <!--
486
487 var debug_div = null;
488 EOF3
489
490 # take maximum archive size from configuration
491 $retHTML .= 'var media_size = '. $Conf{MaxArchiveSize} .';';
492
493 $retHTML .= <<'EOF3';
494
495 function debug(msg) {
496 // return; // Disable debugging
497
498 if (! debug_div) debug_div = document.getElementById('debug');
499
500 // this will create debug div if it doesn't exist.
501 if (! debug_div) {
502 debug_div = document.createElement('div');
503 if (document.body) document.body.appendChild(debug_div);
504 else debug_div = null;
505 }
506 if (debug_div) {
507 debug_div.appendChild(document.createTextNode(msg));
508 debug_div.appendChild(document.createElement("br"));
509 }
510 }
511
512
513 var element_id_cache = Array();
514
515 function element_id(name,element) {
516 if (! element_id_cache[name]) {
517 element_id_cache[name] = self.document.getElementById(name);
518 }
519 return element_id_cache[name];
520 }
521
522 function checkAll(location) {
523 var f = element_id('forma') || null;
524 if (!f) return false;
525
526 var len = f.elements.length;
527 var check_all = element_id('allFiles');
528 var suma = check_all.checked ? (parseInt(f.elements['totalsize'].value) || 0) : 0;
529
530 for (var i = 0; i < len; i++) {
531 var e = f.elements[i];
532 if (e.name != 'all' && e.name.substr(0, 3) == 'fcb') {
533 if (check_all.checked) {
534 if (e.checked) continue;
535 var el = element_id("fss" + e.name.substr(3));
536 var size = parseInt(el.value) || 0;
537 debug('suma: '+suma+' size: '+size);
538 if ((suma + size) < media_size) {
539 suma += size;
540 e.checked = true;
541 } else {
542 break;
543 }
544 } else {
545 e.checked = false;
546 }
547 }
548 }
549 update_sum(suma);
550 }
551
552 function update_sum(suma) {
553 element_id('forma').elements['totalsize'].value = suma;
554 pbar_set(suma, media_size);
555 debug('total size: ' + suma);
556 }
557
558 function sumiraj(e) {
559 var suma = parseInt(element_id('forma').elements['totalsize'].value) || 0;
560 var len = element_id('forma').elements.length;
561 if (e) {
562 var size = parseInt( element_id("fss" + e.name.substr(3)).value);
563 if (e.checked) {
564 suma += size;
565 } else {
566 suma -= size;
567 }
568 } else {
569 suma = 0;
570 for (var i = 0; i < len; i++) {
571 var e = element_id('forma').elements[i];
572 if (e.name != 'all' && e.checked && e.name.substr(0,3) == 'fcb') {
573 var el = element_id("fss" + e.name.substr(3));
574 if (el && el.value) suma += parseInt(el.value) || 0;
575 }
576 }
577 }
578 update_sum(suma);
579 return suma;
580 }
581
582 /* progress bar */
583
584 var _pbar_width = null;
585 var _pbar_warn = 10; // change color in last 10%
586
587 function pbar_reset() {
588 element_id("mask").style.left = "0px";
589 _pbar_width = element_id("mContainer").offsetWidth - 2;
590 element_id("mask").style.width = _pbar_width + "px";
591 element_id("mask").style.display = "block";
592 element_id("progressIndicator").style.zIndex = 10;
593 element_id("progressIndicator").innerHTML = "0";
594 }
595
596 function dec2hex(d) {
597 var hch = '0123456789ABCDEF';
598 var a = d % 16;
599 var q = (d - a) / 16;
600 return hch.charAt(q) + hch.charAt(a);
601 }
602
603 function pbar_set(amount, max) {
604 debug('pbar_set('+amount+', '+max+')');
605
606 if (_pbar_width == null) {
607 var _mc = element_id("mContainer");
608 if (_pbar_width == null) _pbar_width = parseInt(_mc.offsetWidth ? (_mc.offsetWidth - 2) : 0) || null;
609 if (_pbar_width == null) _pbar_width = parseInt(_mc.clientWidth ? (_mc.clientWidth + 2) : 0) || null;
610 if (_pbar_width == null) _pbar_width = 0;
611 }
612
613 var pcnt = Math.floor(amount * 100 / max);
614 var p90 = 100 - _pbar_warn;
615 var pcol = pcnt - p90;
616 if (Math.round(pcnt) <= 100) {
617 if (pcol < 0) pcol = 0;
618 var e = element_id("submitBurner");
619 debug('enable_button');
620 e.disabled = false;
621 var a = e.getAttributeNode('disabled') || null;
622 if (a) e.removeAttributeNode(a);
623 } else {
624 debug('disable button');
625 pcol = _pbar_warn;
626 var e = element_id("submitBurner");
627 if (!e.disabled) e.disabled = true;
628 }
629 var col_g = Math.floor((_pbar_warn - pcol) * 255 / _pbar_warn);
630 var col = '#FF' + dec2hex(col_g) + '00';
631
632 //debug('pcol: '+pcol+' g:'+col_g+' _pbar_warn:'+ _pbar_warn + ' color: '+col);
633 element_id("gradient").style.backgroundColor = col;
634
635 element_id("progressIndicator").innerHTML = pcnt + '%';
636 //element_id("progressIndicator").innerHTML = amount;
637
638 element_id("mask").style.clip = 'rect(' + Array(
639 '0px',
640 element_id("mask").offsetWidth + 'px',
641 element_id("mask").offsetHeight + 'px',
642 Math.round(_pbar_width * amount / max) + 'px'
643 ).join(' ') + ')';
644 }
645
646 if (!self.body) self.body = new Object();
647 self.onload = self.document.onload = self.body.onload = function() {
648 //pbar_reset();
649 sumiraj();
650 };
651
652 // -->
653 </script>
654 <div id="fixedBox">
655
656 Size: <input type="text" name="totalsize" size="7" readonly="readonly" style="text-align:right;" value="0" /> kB
657
658 <div id="mContainer">
659 <div id="gradient">&nbsp;</div>
660 <div id="mask">&nbsp;</div>
661 <div id="progressIndicator">0%</div>
662 </div>
663 <br/>
664
665 Note:
666 <textarea name="note" cols="10" rows="5" id="note"></textarea>
667
668 <input type="submit" id="submitBurner" value="Burn selected" name="submitBurner" />
669
670 </div>
671 <!--
672 <div id="debug" style="float: right; width: 10em; border: 1px #ff0000 solid; background-color: #ffe0e0; -moz-opacity: 0.7;">
673 no debug output yet
674 </div>
675 -->
676 EOF3
677 $retHTML .= q{
678 <input type="hidden" value="burn" name="action">
679 <input type="hidden" value="results" name="search_results">
680 <table style="fview" border="0" cellspacing="0" cellpadding="2">
681 <tr class="tableheader">
682 <td class="tableheader">
683 <input type="checkbox" name="allFiles" id="allFiles" onClick="checkAll('allFiles');">
684 </td>
685 <td align="center">Share</td>
686 <td align="center">Backup no</td>
687 <td align="center">Type</td>
688 <td align="center">date</td>
689 <td align="center">age/days</td>
690 <td align="center">size/MB</td>
691 <td align="center">gzip size</td>
692 </tr>
693
694 };
695
696 my @color = (' bgcolor="#e0e0e0"', '');
697
698 my $i = 0;
699 my $host = '';
700
701 foreach my $backup ( getBackupsNotBurned() ) {
702
703 if ($host ne $backup->{'host'}) {
704 $i++;
705 $host = $backup->{'host'};
706 }
707 my $ftype = "";
708
709 my $checkbox_key = $backup->{'hostid'}. '_' .$backup->{'backupnum'} . '_' . $backup->{'id'};
710
711 $retHTML .=
712 '<tr' . $color[$i %2 ] . '>
713 <td class="fview">';
714
715 # FIXME
716 $backup->{'fs_size'} = int($backup->{'size'} * 1024);
717
718 if (($backup->{'fs_size'} || 0) > 0) {
719 $retHTML .= '
720 <input type="checkbox" name="fcb' . $checkbox_key . '" value="' . $checkbox_key . '" onClick="sumiraj(this);">';
721 }
722
723 $retHTML .=
724 '</td>' .
725 '<td align="right">' . $backup->{'host'} . ':' . $backup->{'share'} . '</td>' .
726 '<td align="center">' . $backup->{'backupnum'} . '</td>' .
727 '<td align="center">' . $backup->{'type'} . '</td>' .
728 '<td align="center">' . epoch_to_iso( $backup->{'date'} ) . '</td>' .
729 '<td align="center">' . $backup->{'age'} . '</td>' .
730 '<td align="right">' . $backup->{'size'} . '</td>' .
731 '<td align="right">' . $backup->{'fs_size'} .
732 '<input type="hidden" iD="fss'.$checkbox_key .'" value="'. $backup->{'fs_size'} .'"></td>' .
733
734 "</tr>\n";
735 }
736
737 $retHTML .= "</table>";
738 $retHTML .= "</form>";
739
740 return $retHTML;
741 }
742
743 sub displayGrid($) {
744 my ($param) = @_;
745
746 my $offset = $param->{'offset'};
747 my $hilite = $param->{'search_filename'};
748
749 my $retHTML = "";
750
751 my $start_t = time();
752
753 my ($results, $files);
754 if ($param->{'use_hest'} && length($hilite) > 0) {
755 ($results, $files) = getFilesHyperEstraier($param);
756 } else {
757 ($results, $files) = getFiles($param);
758 }
759
760 my $dur_t = time() - $start_t;
761 my $dur = sprintf("%0.4fs", $dur_t);
762
763 my ($from, $to) = (($offset * $on_page) + 1, ($offset * $on_page) + $on_page);
764
765 if ($results <= 0) {
766 $retHTML .= qq{
767 <p style="color: red;">No results found...</p>
768 };
769 return $retHTML;
770 } else {
771 # DEBUG
772 #use Data::Dumper;
773 #$retHTML .= '<pre>' . Dumper($files) . '</pre>';
774 }
775
776
777 $retHTML .= qq{
778 <div>
779 Found <b>$results files</b> showing <b>$from - $to</b> (took $dur)
780 </div>
781 <table style="fview" width="100%" border="0" cellpadding="2" cellspacing="0">
782 <tr class="fviewheader">
783 <td></td>
784 <td align="center">Share</td>
785 <td align="center">Type and Name</td>
786 <td align="center">#</td>
787 <td align="center">Size</td>
788 <td align="center">Date</td>
789 <td align="center">Media</td>
790 </tr>
791 };
792
793 my $file;
794
795 sub hilite_html($$) {
796 my ($html, $search) = @_;
797 $html =~ s#($search)#<b>$1</b>#gis;
798 return $html;
799 }
800
801 sub restore_link($$$$$$) {
802 my $type = shift;
803 my $action = 'RestoreFile';
804 $action = 'browse' if (lc($type) eq 'dir');
805 return sprintf(qq{<a href="?action=%s&host=%s&num=%d&share=%s&dir=%s">%s</a>}, $action, @_);
806 }
807
808 my $i = $offset * $on_page;
809
810 foreach $file (@{ $files }) {
811 $i++;
812
813 my $typeStr = BackupPC::Attrib::fileType2Text(undef, $file->{'type'});
814 $retHTML .= qq{<tr class="fviewborder">};
815
816 $retHTML .= qq{<td class="fviewborder">$i</td>};
817
818 $retHTML .=
819 qq{<td class="fviewborder" align="right">} . $file->{'hname'} . ':' . $file->{'sname'} . qq{</td>} .
820 qq{<td class="fviewborder"><img src="$Conf{CgiImageDirURL}/icon-$typeStr.gif" alt="$typeStr" align="middle">&nbsp;} . hilite_html( $file->{'filepath'}, $hilite ) . qq{</td>} .
821 qq{<td class="fviewborder" align="center">} . restore_link( $typeStr, ${EscURI( $file->{'hname'} )}, $file->{'backupnum'}, ${EscURI( $file->{'sname'})}, ${EscURI( $file->{'filepath'} )}, $file->{'backupnum'} ) . qq{</td>} .
822 qq{<td class="fviewborder" align="right">} . $file->{'size'} . qq{</td>} .
823 qq{<td class="fviewborder">} . epoch_to_iso( $file->{'date'} ) . qq{</td>} .
824 qq{<td class="fviewborder">} . '?' . qq{</td>};
825
826 $retHTML .= "</tr>";
827 }
828 $retHTML .= "</table>";
829
830 # all variables which has to be transfered
831 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/) {
832 $retHTML .= qq{<INPUT TYPE="hidden" NAME="$n" VALUE="$In{$n}">\n};
833 }
834
835 my $del = '';
836 my $max_page = int( $results / $on_page );
837 my $page = 0;
838
839 sub page_link($$$) {
840 my ($param,$page,$display) = @_;
841
842 $param->{'offset'} = $page;
843
844 my $html = '<a href = "' . $MyURL;
845 my $del = '?';
846 foreach my $k (keys %{ $param }) {
847 if ($param->{$k}) {
848 $html .= $del . $k . '=' . ${EscURI( $param->{$k} )};
849 $del = '&';
850 }
851 }
852 $html .= '">' . $display . '</a>';
853 }
854
855 $retHTML .= '<div style="text-align: center;">';
856
857 if ($offset > 0) {
858 $retHTML .= page_link($param, $offset - 1, '&lt;&lt;') . ' ';
859 }
860
861 while ($page <= $max_page) {
862 if ($page == $offset) {
863 $retHTML .= $del . '<b>' . ($page + 1) . '</b>';
864 } else {
865 $retHTML .= $del . page_link($param, $page, $page + 1);
866 }
867
868 if ($page < $offset - $pager_pages && $page != 0) {
869 $retHTML .= " ... ";
870 $page = $offset - $pager_pages;
871 $del = '';
872 } elsif ($page > $offset + $pager_pages && $page != $max_page) {
873 $retHTML .= " ... ";
874 $page = $max_page;
875 $del = '';
876 } else {
877 $del = ' | ';
878 $page++;
879 }
880 }
881
882 if ($offset < $max_page) {
883 $retHTML .= ' ' . page_link($param, $offset + 1, '&gt;&gt;');
884 }
885
886 $retHTML .= "</div>";
887
888 return $retHTML;
889 }
890
891 1;

  ViewVC Help
Powered by ViewVC 1.1.26