/[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 194 - (show annotations)
Thu Oct 13 17:11:59 2005 UTC (18 years, 7 months ago) by dpavlin
File size: 22016 byte(s)
 r8502@llin:  dpavlin | 2005-10-13 19:05:29 +0200
 split archives which are larger than MaxArchiveSize to multiple parts

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

  ViewVC Help
Powered by ViewVC 1.1.26