/[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 145 - (show annotations)
Fri Oct 7 11:15:28 2005 UTC (18 years, 7 months ago) by dpavlin
File size: 21472 byte(s)
 r8368@llin:  dpavlin | 2005-10-07 13:15:21 +0200
 refactor code a lot. Probably broken now.

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 var media_size = 4400 * 1024;
487
488 function debug(msg) {
489 // return; // Disable debugging
490
491 if (! debug_div) debug_div = document.getElementById('debug');
492
493 // this will create debug div if it doesn't exist.
494 if (! debug_div) {
495 debug_div = document.createElement('div');
496 if (document.body) document.body.appendChild(debug_div);
497 else debug_div = null;
498 }
499 if (debug_div) {
500 debug_div.appendChild(document.createTextNode(msg));
501 debug_div.appendChild(document.createElement("br"));
502 }
503 }
504
505
506 var element_id_cache = Array();
507
508 function element_id(name,element) {
509 if (! element_id_cache[name]) {
510 element_id_cache[name] = self.document.getElementById(name);
511 }
512 return element_id_cache[name];
513 }
514
515 function checkAll(location) {
516 var f = element_id('forma') || null;
517 if (!f) return false;
518
519 var len = f.elements.length;
520 var check_all = element_id('allFiles');
521 var suma = check_all.checked ? (parseInt(f.elements['totalsize'].value) || 0) : 0;
522
523 for (var i = 0; i < len; i++) {
524 var e = f.elements[i];
525 if (e.name != 'all' && e.name.substr(0, 3) == 'fcb') {
526 if (check_all.checked) {
527 if (e.checked) continue;
528 var el = element_id("fss" + e.name.substr(3));
529 var size = parseInt(el.value) || 0;
530 debug('suma: '+suma+' size: '+size);
531 if ((suma + size) < media_size) {
532 suma += size;
533 e.checked = true;
534 } else {
535 break;
536 }
537 } else {
538 e.checked = false;
539 }
540 }
541 }
542 update_sum(suma);
543 }
544
545 function update_sum(suma) {
546 element_id('forma').elements['totalsize'].value = suma;
547 pbar_set(suma, media_size);
548 debug('total size: ' + suma);
549 }
550
551 function sumiraj(e) {
552 var suma = parseInt(element_id('forma').elements['totalsize'].value) || 0;
553 var len = element_id('forma').elements.length;
554 if (e) {
555 var size = parseInt( element_id("fss" + e.name.substr(3)).value);
556 if (e.checked) {
557 suma += size;
558 } else {
559 suma -= size;
560 }
561 } else {
562 suma = 0;
563 for (var i = 0; i < len; i++) {
564 var e = element_id('forma').elements[i];
565 if (e.name != 'all' && e.checked && e.name.substr(0,3) == 'fcb') {
566 var el = element_id("fss" + e.name.substr(3));
567 if (el && el.value) suma += parseInt(el.value) || 0;
568 }
569 }
570 }
571 update_sum(suma);
572 return suma;
573 }
574
575 /* progress bar */
576
577 var _pbar_width = null;
578 var _pbar_warn = 10; // change color in last 10%
579
580 function pbar_reset() {
581 element_id("mask").style.left = "0px";
582 _pbar_width = element_id("mContainer").offsetWidth - 2;
583 element_id("mask").style.width = _pbar_width + "px";
584 element_id("mask").style.display = "block";
585 element_id("progressIndicator").style.zIndex = 10;
586 element_id("progressIndicator").innerHTML = "0";
587 }
588
589 function dec2hex(d) {
590 var hch = '0123456789ABCDEF';
591 var a = d % 16;
592 var q = (d - a) / 16;
593 return hch.charAt(q) + hch.charAt(a);
594 }
595
596 function pbar_set(amount, max) {
597 debug('pbar_set('+amount+', '+max+')');
598
599 if (_pbar_width == null) {
600 var _mc = element_id("mContainer");
601 if (_pbar_width == null) _pbar_width = parseInt(_mc.offsetWidth ? (_mc.offsetWidth - 2) : 0) || null;
602 if (_pbar_width == null) _pbar_width = parseInt(_mc.clientWidth ? (_mc.clientWidth + 2) : 0) || null;
603 if (_pbar_width == null) _pbar_width = 0;
604 }
605
606 var pcnt = Math.floor(amount * 100 / max);
607 var p90 = 100 - _pbar_warn;
608 var pcol = pcnt - p90;
609 if (Math.round(pcnt) <= 100) {
610 if (pcol < 0) pcol = 0;
611 var e = element_id("submitBurner");
612 debug('enable_button');
613 e.disabled = false;
614 var a = e.getAttributeNode('disabled') || null;
615 if (a) e.removeAttributeNode(a);
616 } else {
617 debug('disable button');
618 pcol = _pbar_warn;
619 var e = element_id("submitBurner");
620 if (!e.disabled) e.disabled = true;
621 }
622 var col_g = Math.floor((_pbar_warn - pcol) * 255 / _pbar_warn);
623 var col = '#FF' + dec2hex(col_g) + '00';
624
625 //debug('pcol: '+pcol+' g:'+col_g+' _pbar_warn:'+ _pbar_warn + ' color: '+col);
626 element_id("gradient").style.backgroundColor = col;
627
628 element_id("progressIndicator").innerHTML = pcnt + '%';
629 //element_id("progressIndicator").innerHTML = amount;
630
631 element_id("mask").style.clip = 'rect(' + Array(
632 '0px',
633 element_id("mask").offsetWidth + 'px',
634 element_id("mask").offsetHeight + 'px',
635 Math.round(_pbar_width * amount / max) + 'px'
636 ).join(' ') + ')';
637 }
638
639 if (!self.body) self.body = new Object();
640 self.onload = self.document.onload = self.body.onload = function() {
641 //pbar_reset();
642 sumiraj();
643 };
644
645 // -->
646 </script>
647 <div id="fixedBox">
648
649 Size: <input type="text" name="totalsize" size="7" readonly="readonly" style="text-align:right;" value="0" /> kB
650
651 <div id="mContainer">
652 <div id="gradient">&nbsp;</div>
653 <div id="mask">&nbsp;</div>
654 <div id="progressIndicator">0%</div>
655 </div>
656 <br/>
657
658 Note:
659 <textarea name="note" cols="10" rows="5" id="note"></textarea>
660
661 <input type="submit" id="submitBurner" value="Burn selected" name="submitBurner" />
662
663 </div>
664 <!--
665 <div id="debug" style="float: right; width: 10em; border: 1px #ff0000 solid; background-color: #ffe0e0; -moz-opacity: 0.7;">
666 no debug output yet
667 </div>
668 -->
669 EOF3
670 $retHTML .= q{
671 <input type="hidden" value="burn" name="action">
672 <input type="hidden" value="results" name="search_results">
673 <table style="fview" border="0" cellspacing="0" cellpadding="2">
674 <tr class="tableheader">
675 <td class="tableheader">
676 <input type="checkbox" name="allFiles" id="allFiles" onClick="checkAll('allFiles');">
677 </td>
678 <td align="center">Share</td>
679 <td align="center">Backup no</td>
680 <td align="center">Type</td>
681 <td align="center">date</td>
682 <td align="center">age/days</td>
683 <td align="center">size/MB</td>
684 <td align="center">gzip size</td>
685 </tr>
686
687 };
688
689 my @color = (' bgcolor="#e0e0e0"', '');
690
691 my $i = 0;
692 my $host = '';
693
694 foreach my $backup ( getBackupsNotBurned() ) {
695
696 if ($host ne $backup->{'host'}) {
697 $i++;
698 $host = $backup->{'host'};
699 }
700 my $ftype = "";
701
702 my $checkbox_key = $backup->{'hostid'}. '_' .$backup->{'backupnum'} . '_' . $backup->{'id'};
703
704 $retHTML .=
705 '<tr' . $color[$i %2 ] . '>
706 <td class="fview">';
707
708 # FIXME
709 $backup->{'fs_size'} = int($backup->{'size'} * 1024);
710
711 if (($backup->{'fs_size'} || 0) > 0) {
712 $retHTML .= '
713 <input type="checkbox" name="fcb' . $checkbox_key . '" value="' . $checkbox_key . '" onClick="sumiraj(this);">';
714 }
715
716 $retHTML .=
717 '</td>' .
718 '<td align="right">' . $backup->{'host'} . ':' . $backup->{'share'} . '</td>' .
719 '<td align="center">' . $backup->{'backupnum'} . '</td>' .
720 '<td align="center">' . $backup->{'type'} . '</td>' .
721 '<td align="center">' . epoch_to_iso( $backup->{'date'} ) . '</td>' .
722 '<td align="center">' . $backup->{'age'} . '</td>' .
723 '<td align="right">' . $backup->{'size'} . '</td>' .
724 '<td align="right">' . $backup->{'fs_size'} .
725 '<input type="hidden" iD="fss'.$checkbox_key .'" value="'. $backup->{'fs_size'} .'"></td>' .
726
727 "</tr>\n";
728 }
729
730 $retHTML .= "</table>";
731 $retHTML .= "</form>";
732
733 return $retHTML;
734 }
735
736 sub displayGrid($) {
737 my ($param) = @_;
738
739 my $offset = $param->{'offset'};
740 my $hilite = $param->{'search_filename'};
741
742 my $retHTML = "";
743
744 my $start_t = time();
745
746 my ($results, $files);
747 if ($param->{'use_hest'} && length($hilite) > 0) {
748 ($results, $files) = getFilesHyperEstraier($param);
749 } else {
750 ($results, $files) = getFiles($param);
751 }
752
753 my $dur_t = time() - $start_t;
754 my $dur = sprintf("%0.4fs", $dur_t);
755
756 my ($from, $to) = (($offset * $on_page) + 1, ($offset * $on_page) + $on_page);
757
758 if ($results <= 0) {
759 $retHTML .= qq{
760 <p style="color: red;">No results found...</p>
761 };
762 return $retHTML;
763 } else {
764 # DEBUG
765 #use Data::Dumper;
766 #$retHTML .= '<pre>' . Dumper($files) . '</pre>';
767 }
768
769
770 $retHTML .= qq{
771 <div>
772 Found <b>$results files</b> showing <b>$from - $to</b> (took $dur)
773 </div>
774 <table style="fview" width="100%" border="0" cellpadding="2" cellspacing="0">
775 <tr class="fviewheader">
776 <td></td>
777 <td align="center">Share</td>
778 <td align="center">Type and Name</td>
779 <td align="center">#</td>
780 <td align="center">Size</td>
781 <td align="center">Date</td>
782 <td align="center">Media</td>
783 </tr>
784 };
785
786 my $file;
787
788 sub hilite_html($$) {
789 my ($html, $search) = @_;
790 $html =~ s#($search)#<b>$1</b>#gis;
791 return $html;
792 }
793
794 sub restore_link($$$$$$) {
795 my $type = shift;
796 my $action = 'RestoreFile';
797 $action = 'browse' if (lc($type) eq 'dir');
798 return sprintf(qq{<a href="?action=%s&host=%s&num=%d&share=%s&dir=%s">%s</a>}, $action, @_);
799 }
800
801 my $i = $offset * $on_page;
802
803 foreach $file (@{ $files }) {
804 $i++;
805
806 my $typeStr = BackupPC::Attrib::fileType2Text(undef, $file->{'type'});
807 $retHTML .= qq{<tr class="fviewborder">};
808
809 $retHTML .= qq{<td class="fviewborder">$i</td>};
810
811 $retHTML .=
812 qq{<td class="fviewborder" align="right">} . $file->{'hname'} . ':' . $file->{'sname'} . qq{</td>} .
813 qq{<td class="fviewborder"><img src="$Conf{CgiImageDirURL}/icon-$typeStr.gif" alt="$typeStr" align="middle">&nbsp;} . hilite_html( $file->{'filepath'}, $hilite ) . qq{</td>} .
814 qq{<td class="fviewborder" align="center">} . restore_link( $typeStr, ${EscURI( $file->{'hname'} )}, $file->{'backupnum'}, ${EscURI( $file->{'sname'})}, ${EscURI( $file->{'filepath'} )}, $file->{'backupnum'} ) . qq{</td>} .
815 qq{<td class="fviewborder" align="right">} . $file->{'size'} . qq{</td>} .
816 qq{<td class="fviewborder">} . epoch_to_iso( $file->{'date'} ) . qq{</td>} .
817 qq{<td class="fviewborder">} . '?' . qq{</td>};
818
819 $retHTML .= "</tr>";
820 }
821 $retHTML .= "</table>";
822
823 # all variables which has to be transfered
824 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/) {
825 $retHTML .= qq{<INPUT TYPE="hidden" NAME="$n" VALUE="$In{$n}">\n};
826 }
827
828 my $del = '';
829 my $max_page = int( $results / $on_page );
830 my $page = 0;
831
832 sub page_link($$$) {
833 my ($param,$page,$display) = @_;
834
835 $param->{'offset'} = $page;
836
837 my $html = '<a href = "' . $MyURL;
838 my $del = '?';
839 foreach my $k (keys %{ $param }) {
840 if ($param->{$k}) {
841 $html .= $del . $k . '=' . ${EscURI( $param->{$k} )};
842 $del = '&';
843 }
844 }
845 $html .= '">' . $display . '</a>';
846 }
847
848 $retHTML .= '<div style="text-align: center;">';
849
850 if ($offset > 0) {
851 $retHTML .= page_link($param, $offset - 1, '&lt;&lt;') . ' ';
852 }
853
854 while ($page <= $max_page) {
855 if ($page == $offset) {
856 $retHTML .= $del . '<b>' . ($page + 1) . '</b>';
857 } else {
858 $retHTML .= $del . page_link($param, $page, $page + 1);
859 }
860
861 if ($page < $offset - $pager_pages && $page != 0) {
862 $retHTML .= " ... ";
863 $page = $offset - $pager_pages;
864 $del = '';
865 } elsif ($page > $offset + $pager_pages && $page != $max_page) {
866 $retHTML .= " ... ";
867 $page = $max_page;
868 $del = '';
869 } else {
870 $del = ' | ';
871 $page++;
872 }
873 }
874
875 if ($offset < $max_page) {
876 $retHTML .= ' ' . page_link($param, $offset + 1, '&gt;&gt;');
877 }
878
879 $retHTML .= "</div>";
880
881 return $retHTML;
882 }
883
884 1;

  ViewVC Help
Powered by ViewVC 1.1.26