/[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 171 - (show annotations)
Mon Oct 10 14:32:31 2005 UTC (18 years, 6 months ago) by dpavlin
File size: 21512 byte(s)
backups.size can be 0 for very small backups (because it's in Mb)

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 backups.inc_size AS inc_size
342 FROM backups
343 INNER JOIN shares ON backups.shareID=shares.ID
344 INNER JOIN hosts ON backups.hostID = hosts.ID
345 LEFT OUTER JOIN archive_backup ON archive_backup.backup_id = backups.id
346 WHERE backups.inc_size > 0 AND backups.inc_deleted is false AND archive_backup.backup_id IS NULL
347 GROUP BY
348 backups.hostID,
349 hosts.name,
350 shares.name,
351 backups.num,
352 backups.shareid,
353 backups.id,
354 backups.type,
355 backups.date,
356 backups.size,
357 backups.inc_size
358 ORDER BY backups.date
359 };
360 my $sth = $dbh->prepare( $sql );
361 my @ret;
362 $sth->execute();
363
364 while ( my $row = $sth->fetchrow_hashref() ) {
365 $row->{'age'} = sprintf("%0.1f", ( (time() - $row->{'date'}) / 86400 ) );
366 $row->{'size'} = sprintf("%0.2f", $row->{'size'} / 1024 / 1024);
367
368 # do some cluster calculation (approximate) and convert to kB
369 $row->{'inc_size'} = int(($row->{'inc_size'} + 1023 ) / ( 2 * 1024 ) * 2);
370 push @ret, $row;
371 }
372
373 return @ret;
374 }
375
376 sub displayBackupsGrid() {
377
378 my $retHTML .= q{
379 <form id="forma" method="POST" action="}.$MyURL.q{?action=burn">
380 };
381
382 $retHTML .= <<'EOF3';
383 <style type="text/css">
384 <!--
385 DIV#fixedBox {
386 position: absolute;
387 top: 50em;
388 left: -24%;
389 padding: 0.5em;
390 width: 20%;
391 background-color: #E0F0E0;
392 border: 1px solid #00C000;
393 }
394
395 DIV#fixedBox, DIV#fixedBox INPUT, DIV#fixedBox TEXTAREA {
396 font-size: 10pt;
397 }
398
399 FORM>DIV#fixedBox {
400 position: fixed !important;
401 left: 0.5em !important;
402 top: auto !important;
403 bottom: 1em !important;
404 width: 15% !important;
405 }
406
407 DIV#fixedBox INPUT[type=text], DIV#fixedBox TEXTAREA {
408 border: 1px solid #00C000;
409 }
410
411 DIV#fixedBox #note {
412 display: block;
413 width: 100%;
414 }
415
416 DIV#fixedBox #submitBurner {
417 display: block;
418 width: 100%;
419 margin-top: 0.5em;
420 cursor: pointer;
421 }
422
423 * HTML {
424 overflow-y: hidden;
425 }
426
427 * HTML BODY {
428 overflow-y: auto;
429 height: 100%;
430 font-size: 100%;
431 }
432
433 * HTML DIV#fixedBox {
434 position: absolute;
435 }
436
437 #mContainer, #gradient, #mask, #progressIndicator {
438 display: block;
439 width: 100%;
440 font-size: 10pt;
441 font-weight: bold;
442 text-align: center;
443 vertical-align: middle;
444 padding: 1px;
445 }
446
447 #gradient, #mask, #progressIndicator {
448 left: 0;
449 border-width: 1px;
450 border-style: solid;
451 border-color: #000000;
452 color: #404040;
453 margin: 0.4em;
454 position: absolute;
455 margin-left: -1px;
456 margin-top: -1px;
457 margin-bottom: -1px;
458 overflow: hidden;
459 }
460
461 #mContainer {
462 display: block;
463 position: relative;
464 padding: 0px;
465 margin-top: 0.4em;
466 margin-bottom: 0.5em;
467 }
468
469 #gradient {
470 z-index: 1;
471 background-color: #FFFF00;
472 }
473
474 #mask {
475 z-index: 2;
476 background-color: #FFFFFF;
477 }
478
479 #progressIndicator {
480 z-index: 3;
481 background-color: transparent;
482 }
483 -->
484 </style>
485 <script type="text/javascript">
486 <!--
487
488 var debug_div = null;
489 EOF3
490
491 # take maximum archive size from configuration
492 $retHTML .= 'var media_size = '. $Conf{MaxArchiveSize} .';';
493
494 $retHTML .= <<'EOF3';
495
496 function debug(msg) {
497 // return; // Disable debugging
498
499 if (! debug_div) debug_div = document.getElementById('debug');
500
501 // this will create debug div if it doesn't exist.
502 if (! debug_div) {
503 debug_div = document.createElement('div');
504 if (document.body) document.body.appendChild(debug_div);
505 else debug_div = null;
506 }
507 if (debug_div) {
508 debug_div.appendChild(document.createTextNode(msg));
509 debug_div.appendChild(document.createElement("br"));
510 }
511 }
512
513
514 var element_id_cache = Array();
515
516 function element_id(name,element) {
517 if (! element_id_cache[name]) {
518 element_id_cache[name] = self.document.getElementById(name);
519 }
520 return element_id_cache[name];
521 }
522
523 function checkAll(location) {
524 var f = element_id('forma') || null;
525 if (!f) return false;
526
527 var len = f.elements.length;
528 var check_all = element_id('allFiles');
529 var suma = check_all.checked ? (parseInt(f.elements['totalsize'].value) || 0) : 0;
530
531 for (var i = 0; i < len; i++) {
532 var e = f.elements[i];
533 if (e.name != 'all' && e.name.substr(0, 3) == 'fcb') {
534 if (check_all.checked) {
535 if (e.checked) continue;
536 var el = element_id("fss" + e.name.substr(3));
537 var size = parseInt(el.value) || 0;
538 debug('suma: '+suma+' size: '+size);
539 if ((suma + size) < media_size) {
540 suma += size;
541 e.checked = true;
542 } else {
543 break;
544 }
545 } else {
546 e.checked = false;
547 }
548 }
549 }
550 update_sum(suma);
551 }
552
553 function update_sum(suma) {
554 element_id('forma').elements['totalsize'].value = suma;
555 pbar_set(suma, media_size);
556 debug('total size: ' + suma);
557 }
558
559 function sumiraj(e) {
560 var suma = parseInt(element_id('forma').elements['totalsize'].value) || 0;
561 var len = element_id('forma').elements.length;
562 if (e) {
563 var size = parseInt( element_id("fss" + e.name.substr(3)).value);
564 if (e.checked) {
565 suma += size;
566 } else {
567 suma -= size;
568 }
569 } else {
570 suma = 0;
571 for (var i = 0; i < len; i++) {
572 var e = element_id('forma').elements[i];
573 if (e.name != 'all' && e.checked && e.name.substr(0,3) == 'fcb') {
574 var el = element_id("fss" + e.name.substr(3));
575 if (el && el.value) suma += parseInt(el.value) || 0;
576 }
577 }
578 }
579 update_sum(suma);
580 return suma;
581 }
582
583 /* progress bar */
584
585 var _pbar_width = null;
586 var _pbar_warn = 10; // change color in last 10%
587
588 function pbar_reset() {
589 element_id("mask").style.left = "0px";
590 _pbar_width = element_id("mContainer").offsetWidth - 2;
591 element_id("mask").style.width = _pbar_width + "px";
592 element_id("mask").style.display = "block";
593 element_id("progressIndicator").style.zIndex = 10;
594 element_id("progressIndicator").innerHTML = "0";
595 }
596
597 function dec2hex(d) {
598 var hch = '0123456789ABCDEF';
599 var a = d % 16;
600 var q = (d - a) / 16;
601 return hch.charAt(q) + hch.charAt(a);
602 }
603
604 function pbar_set(amount, max) {
605 debug('pbar_set('+amount+', '+max+')');
606
607 if (_pbar_width == null) {
608 var _mc = element_id("mContainer");
609 if (_pbar_width == null) _pbar_width = parseInt(_mc.offsetWidth ? (_mc.offsetWidth - 2) : 0) || null;
610 if (_pbar_width == null) _pbar_width = parseInt(_mc.clientWidth ? (_mc.clientWidth + 2) : 0) || null;
611 if (_pbar_width == null) _pbar_width = 0;
612 }
613
614 var pcnt = Math.floor(amount * 100 / max);
615 var p90 = 100 - _pbar_warn;
616 var pcol = pcnt - p90;
617 if (Math.round(pcnt) <= 100) {
618 if (pcol < 0) pcol = 0;
619 var e = element_id("submitBurner");
620 debug('enable_button');
621 e.disabled = false;
622 var a = e.getAttributeNode('disabled') || null;
623 if (a) e.removeAttributeNode(a);
624 } else {
625 debug('disable button');
626 pcol = _pbar_warn;
627 var e = element_id("submitBurner");
628 if (!e.disabled) e.disabled = true;
629 }
630 var col_g = Math.floor((_pbar_warn - pcol) * 255 / _pbar_warn);
631 var col = '#FF' + dec2hex(col_g) + '00';
632
633 //debug('pcol: '+pcol+' g:'+col_g+' _pbar_warn:'+ _pbar_warn + ' color: '+col);
634 element_id("gradient").style.backgroundColor = col;
635
636 element_id("progressIndicator").innerHTML = pcnt + '%';
637 //element_id("progressIndicator").innerHTML = amount;
638
639 element_id("mask").style.clip = 'rect(' + Array(
640 '0px',
641 element_id("mask").offsetWidth + 'px',
642 element_id("mask").offsetHeight + 'px',
643 Math.round(_pbar_width * amount / max) + 'px'
644 ).join(' ') + ')';
645 }
646
647 if (!self.body) self.body = new Object();
648 self.onload = self.document.onload = self.body.onload = function() {
649 //pbar_reset();
650 sumiraj();
651 };
652
653 // -->
654 </script>
655 <div id="fixedBox">
656
657 Size: <input type="text" name="totalsize" size="7" readonly="readonly" style="text-align:right;" value="0" /> kB
658
659 <div id="mContainer">
660 <div id="gradient">&nbsp;</div>
661 <div id="mask">&nbsp;</div>
662 <div id="progressIndicator">0%</div>
663 </div>
664 <br/>
665
666 Note:
667 <textarea name="note" cols="10" rows="5" id="note"></textarea>
668
669 <input type="submit" id="submitBurner" value="Burn selected" name="submitBurner" />
670
671 </div>
672 <!--
673 <div id="debug" style="float: right; width: 10em; border: 1px #ff0000 solid; background-color: #ffe0e0; -moz-opacity: 0.7;">
674 no debug output yet
675 </div>
676 -->
677 EOF3
678 $retHTML .= q{
679 <input type="hidden" value="burn" name="action">
680 <input type="hidden" value="results" name="search_results">
681 <table style="fview" border="0" cellspacing="0" cellpadding="2">
682 <tr class="tableheader">
683 <td class="tableheader">
684 <input type="checkbox" name="allFiles" id="allFiles" onClick="checkAll('allFiles');">
685 </td>
686 <td align="center">Share</td>
687 <td align="center">Backup no</td>
688 <td align="center">Type</td>
689 <td align="center">date</td>
690 <td align="center">age/days</td>
691 <td align="center">size/MB</td>
692 <td align="center">gzip size/kB</td>
693 </tr>
694
695 };
696
697 my @color = (' bgcolor="#e0e0e0"', '');
698
699 my $i = 0;
700 my $host = '';
701
702 foreach my $backup ( getBackupsNotBurned() ) {
703
704 if ($host ne $backup->{'host'}) {
705 $i++;
706 $host = $backup->{'host'};
707 }
708 my $ftype = "";
709
710 my $checkbox_key = $backup->{'hostid'}. '_' .$backup->{'backupnum'} . '_' . $backup->{'id'};
711
712 $retHTML .=
713 '<tr' . $color[$i %2 ] . '>
714 <td class="fview">';
715
716 if (($backup->{'inc_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->{'inc_size'} .
730 '<input type="hidden" iD="fss'.$checkbox_key .'" value="'. $backup->{'inc_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