/[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 149 - (show annotations)
Fri Oct 7 12:27:07 2005 UTC (18 years, 7 months ago) by dpavlin
File size: 21582 byte(s)
 r8390@llin:  dpavlin | 2005-10-07 14:27:00 +0200
 use MaxArchiveSize from configuration in JavaScript

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

  ViewVC Help
Powered by ViewVC 1.1.26