/[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 209 - (show annotations)
Sun Oct 16 10:57:51 2005 UTC (18 years, 7 months ago) by dpavlin
File size: 23895 byte(s)
 r8601@llin:  dpavlin | 2005-10-15 21:00:32 +0200
 added check_archived to lookup (and cache) media on which is file

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

  ViewVC Help
Powered by ViewVC 1.1.26