/[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 304 - (show annotations)
Sat Jan 28 19:49:03 2006 UTC (18 years, 3 months ago) by dpavlin
File size: 28126 byte(s)
fix total number of hits from Hyper Estraier
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_node_url = $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 my $sort_def = {
124 search => {
125 default => 'date_a',
126 sql => {
127 share_d => 'shares.name DESC',
128 share_a => 'shares.name ASC',
129 path_d => 'files.path DESC',
130 path_a => 'files.path ASC',
131 num_d => 'files.backupnum DESC',
132 num_a => 'files.backupnum ASC',
133 size_d => 'files.size DESC',
134 size_a => 'files.size ASC',
135 date_d => 'files.date DESC',
136 date_a => 'files.date ASC',
137 },
138 est => {
139 share_d => 'sname STRD',
140 share_a => 'sname STRA',
141 path_d => 'filepath STRD',
142 path_a => 'filepath STRA',
143 num_d => 'backupnum NUMD',
144 num_a => 'backupnum NUMA',
145 size_d => 'size NUMD',
146 size_a => 'size NUMA',
147 date_d => 'date NUMD',
148 date_a => 'date NUMA',
149 }
150 }, burn => {
151 default => 'date_a',
152 sql => {
153 share_d => 'host DESC, share DESC',
154 share_a => 'host ASC, share ASC',
155 num_d => 'backupnum DESC',
156 num_a => 'backupnum ASC',
157 date_d => 'date DESC',
158 date_a => 'date ASC',
159 age_d => 'age DESC',
160 age_a => 'age ASC',
161 size_d => 'size DESC',
162 size_a => 'size ASC',
163 incsize_d => 'inc_size DESC',
164 incsize_a => 'inc_size ASC',
165 }
166 }
167 };
168
169 sub getSort($$$) {
170 my ($part,$type, $sort_order) = @_;
171
172 die "unknown part: $part" unless ($sort_def->{$part});
173 die "unknown type: $type" unless ($sort_def->{$part}->{$type});
174
175 $sort_order ||= $sort_def->{$part}->{'default'};
176
177 if (my $ret = $sort_def->{$part}->{$type}->{$sort_order}) {
178 return $ret;
179 } else {
180 # fallback to default sort order
181 return $sort_def->{$part}->{$type}->{ $sort_def->{$part}->{'default'} };
182 }
183 }
184
185 sub getFiles($) {
186 my ($param) = @_;
187
188 my $offset = $param->{'offset'} || 0;
189 $offset *= $on_page;
190
191 my $dbh = get_dbh();
192
193 my $sql_cols = qq{
194 files.id AS fid,
195 hosts.name AS hname,
196 shares.name AS sname,
197 files.backupnum AS backupnum,
198 files.path AS filepath,
199 files.date AS date,
200 files.type AS type,
201 files.size AS size
202 };
203
204 my $sql_from = qq{
205 FROM files
206 INNER JOIN shares ON files.shareID=shares.ID
207 INNER JOIN hosts ON hosts.ID = shares.hostID
208 INNER JOIN backups ON backups.num = files.backupnum and backups.hostID = hosts.ID AND backups.shareID = files.shareID
209 };
210
211 my $sql_where;
212 my $where = getWhere($param);
213 $sql_where = " WHERE ". $where if ($where);
214
215 my $order = getSort('search', 'sql', $param->{'sort'});
216
217 my $sql_order = qq{
218 ORDER BY $order
219 LIMIT $on_page
220 OFFSET ?
221 };
222
223 my $sql_count = qq{ select count(files.id) $sql_from $sql_where };
224 my $sql_results = qq{ select $sql_cols $sql_from $sql_where $sql_order };
225
226 my $sth = $dbh->prepare($sql_count);
227 $sth->execute();
228 my ($results) = $sth->fetchrow_array();
229
230 $sth = $dbh->prepare($sql_results);
231 $sth->execute( $offset );
232
233 if ($sth->rows != $results) {
234 my $bug = "$0 BUG: [[ $sql_count ]] = $results while [[ $sql_results ]] = " . $sth->rows;
235 $bug =~ s/\s+/ /gs;
236 print STDERR "$bug\n";
237 }
238
239 my @ret;
240
241 while (my $row = $sth->fetchrow_hashref()) {
242 push @ret, $row;
243 }
244
245 $sth->finish();
246 return ($results, \@ret);
247 }
248
249 sub getHyperEstraier_url($) {
250 my ($use_hest) = @_;
251
252 return unless $use_hest;
253
254 use Search::Estraier 0.04;
255 die "direct access to Hyper Estraier datatase is no longer supported. Please use estmaster\n"
256 unless ($use_hest =~ m#^http://#);
257
258 return $use_hest;
259 }
260
261 sub getFilesHyperEstraier($) {
262 my ($param) = @_;
263
264 my $offset = $param->{'offset'} || 0;
265 $offset *= $on_page;
266
267 die "no Hyper Estraier node URL?" unless ($hest_node_url);
268
269 # open the database
270 my $db;
271 if ($hest_node_url) {
272 $db ||= Search::Estraier::Node->new($hest_node_url);
273 $db->set_auth('admin', 'admin');
274 } else {
275 die "BUG: unimplemented";
276 }
277
278 # create a search condition object
279 my $cond = Search::Estraier::Condition->new();
280
281 my $q = $param->{'search_filename'};
282 my $shareid = $param->{'search_share'};
283
284 if (length($q) > 0) {
285 # exact match
286 $cond->add_attr("filepath ISTRINC $q");
287
288 $q =~ s/(.)/$1 /g;
289 # set the search phrase to the search condition object
290 $cond->set_phrase($q);
291 }
292
293 my ($backup_from, $backup_to, $files_from, $files_to) = dates_from_form($param);
294
295 $cond->add_attr("backup_date NUMGE $backup_from") if ($backup_from);
296 $cond->add_attr("backup_date NUMLE $backup_to") if ($backup_to);
297
298 $cond->add_attr("date NUMGE $files_from") if ($files_from);
299 $cond->add_attr("date NUMLE $files_to") if ($files_to);
300
301 $cond->add_attr("shareid NUMEQ $shareid") if ($shareid);
302
303 $cond->set_max( $offset + $on_page );
304 $cond->set_options( 'SURE' );
305 $cond->set_order( getSort('search', 'est', $param->{'sort'} ) );
306
307 # get the result of search
308 my @res;
309 my ($result, $hits);
310
311 if ($hest_node_url) {
312 $result = $db->search($cond, 0);
313 if ($result) {
314 $hits = $result->hits;
315 } else {
316 $hits = 0;
317 }
318 } else {
319 die "BUG: unimplemented";
320 }
321
322 # for each document in result
323 for my $i ($offset .. ($offset + $on_page - 1)) {
324 last if ($i >= $result->doc_num);
325
326 my $doc;
327 if ($hest_node_url) {
328 $doc = $result->get_doc($i);
329 } else {
330 die "BUG: unimplemented";
331 }
332
333 my $row;
334 foreach my $c (qw/fid hname sname backupnum filepath date type size/) {
335 $row->{$c} = $doc->attr($c);
336 }
337 push @res, $row;
338 }
339
340 return ($hits, \@res);
341 }
342
343 sub getGzipName($$$)
344 {
345 my ($host, $share, $backupnum) = @_;
346 my $ret = $Conf{GzipSchema};
347
348 $share =~ s/\//_/g;
349 $ret =~ s/\\h/$host/ge;
350 $ret =~ s/\\s/$share/ge;
351 $ret =~ s/\\n/$backupnum/ge;
352
353 $ret =~ s/__+/_/g;
354
355 return $ret;
356
357 }
358
359 sub get_tgz_size_by_name($) {
360 my $name = shift;
361
362 my $tgz = $Conf{InstallDir}.'/'.$Conf{GzipTempDir}.'/'.$name;
363
364 my $size = -1;
365
366 if (-f "${tgz}.tar.gz") {
367 $size = (stat("${tgz}.tar.gz"))[7];
368 } elsif (-d $tgz) {
369 opendir(my $dir, $tgz) || die "can't opendir $tgz: $!";
370 my @parts = grep { !/^\./ && !/md5/ && -f "$tgz/$_" } readdir($dir);
371 $size = 0;
372 foreach my $part (@parts) {
373 $size += (stat("$tgz/$part"))[7] || die "can't stat $tgz/$part: $!";
374 }
375 closedir $dir;
376 } else {
377 return -1;
378 }
379
380 return $size;
381 }
382
383 sub getGzipSize($$)
384 {
385 my ($hostID, $backupNum) = @_;
386 my $sql;
387 my $dbh = get_dbh();
388
389 $sql = q{
390 SELECT hosts.name as host,
391 shares.name as share,
392 backups.num as backupnum
393 FROM hosts, backups, shares
394 WHERE shares.id=backups.shareid AND
395 hosts.id =backups.hostid AND
396 hosts.id=? AND
397 backups.num=?
398 };
399 my $sth = $dbh->prepare($sql);
400 $sth->execute($hostID, $backupNum);
401
402 my $row = $sth->fetchrow_hashref();
403
404 return get_tgz_size_by_name(
405 getGzipName($row->{'host'}, $row->{share}, $row->{'backupnum'})
406 );
407 }
408
409 sub getVolumes($) {
410 my $id = shift;
411
412 my $max_archive_size = $Conf{MaxArchiveSize} || die "no MaxArchiveSize";
413
414 my $sth = $dbh->prepare(qq{
415 select
416 size
417 from backup_parts
418 where backup_id = ?
419 order by part_nr asc
420 });
421
422 $sth->execute($id);
423
424 my $cumulative_size = 0;
425 my $volumes = 1;
426
427 while(my ($size) = $sth->fetchrow_array) {
428 if ($cumulative_size + $size > $max_archive_size) {
429 $volumes++;
430 $cumulative_size = $size;
431 } else {
432 $cumulative_size += $size;
433 }
434 }
435
436 return ($volumes,$cumulative_size);
437 }
438
439 sub getBackupsNotBurned($) {
440
441 my $param = shift;
442 my $dbh = get_dbh();
443
444 my $order = getSort('burn', 'sql', $param->{'sort'});
445
446 print STDERR "## sort=". ($param->{'sort'} || 'no sort param') . " burn sql order: $order\n";
447
448 my $sql = qq{
449 SELECT
450 backups.hostID AS hostID,
451 hosts.name AS host,
452 shares.name AS share,
453 backups.num AS backupnum,
454 backups.type AS type,
455 backups.date AS date,
456 date_part('epoch',now()) - backups.date as age,
457 backups.size AS size,
458 backups.id AS id,
459 backups.inc_size AS inc_size,
460 backups.parts AS parts
461 FROM backups
462 INNER JOIN shares ON backups.shareID=shares.ID
463 INNER JOIN hosts ON backups.hostID = hosts.ID
464 LEFT OUTER JOIN archive_backup ON archive_backup.backup_id = backups.id
465 WHERE backups.inc_size > 0 AND backups.inc_deleted is false AND archive_backup.backup_id IS NULL
466 GROUP BY
467 backups.hostID,
468 hosts.name,
469 shares.name,
470 backups.num,
471 backups.shareid,
472 backups.id,
473 backups.type,
474 backups.date,
475 backups.size,
476 backups.inc_size,
477 backups.parts
478 ORDER BY $order
479 };
480 my $sth = $dbh->prepare( $sql );
481 my @ret;
482 $sth->execute();
483
484 while ( my $row = $sth->fetchrow_hashref() ) {
485 $row->{'age'} = sprintf("%0.1f", ( $row->{'age'} / 86400 ) );
486 #$row->{'age'} = sprintf("%0.1f", ( (time() - $row->{'date'}) / 86400 ) );
487
488 my $max_archive_size = $Conf{MaxArchiveSize} || die "no MaxArchiveSize";
489 if ($row->{size} > $max_archive_size) {
490 ($row->{volumes}, $row->{inc_size_calc}) = getVolumes($row->{id});
491 }
492
493 $row->{size} = sprintf("%0.2f", $row->{size} / 1024 / 1024);
494
495 # do some cluster calculation (approximate)
496 $row->{inc_size} = int(( ($row->{inc_size} + 1023 ) / 2 ) * 2);
497 $row->{inc_size_calc} ||= $row->{inc_size};
498 push @ret, $row;
499 }
500
501 return @ret;
502 }
503
504 sub displayBackupsGrid($) {
505
506 my $param = shift;
507
508 my $max_archive_size = $Conf{MaxArchiveSize} || die "no MaxArchiveSize";
509 my $max_archive_file_size = $Conf{MaxArchiveFileSize} || die "no MaxFileInSize";
510
511 my $retHTML .= q{
512 <form id="forma" method="POST" action="}.$MyURL.q{?action=burn">
513 };
514
515 $retHTML .= <<'EOF3';
516 <style type="text/css">
517 <!--
518 DIV#fixedBox {
519 position: absolute;
520 top: 50em;
521 left: -24%;
522 padding: 0.5em;
523 width: 20%;
524 background-color: #E0F0E0;
525 border: 1px solid #00C000;
526 }
527
528 DIV#fixedBox, DIV#fixedBox INPUT, DIV#fixedBox TEXTAREA {
529 font-size: 10pt;
530 }
531
532 FORM>DIV#fixedBox {
533 position: fixed !important;
534 left: 0.5em !important;
535 top: auto !important;
536 bottom: 1em !important;
537 width: 15% !important;
538 }
539
540 DIV#fixedBox INPUT[type=text], DIV#fixedBox TEXTAREA {
541 border: 1px solid #00C000;
542 }
543
544 DIV#fixedBox #note {
545 display: block;
546 width: 100%;
547 }
548
549 DIV#fixedBox #submitBurner {
550 display: block;
551 width: 100%;
552 margin-top: 0.5em;
553 cursor: pointer;
554 }
555
556 * HTML {
557 overflow-y: hidden;
558 }
559
560 * HTML BODY {
561 overflow-y: auto;
562 height: 100%;
563 font-size: 100%;
564 }
565
566 * HTML DIV#fixedBox {
567 position: absolute;
568 }
569
570 #mContainer, #gradient, #mask, #progressIndicator {
571 display: block;
572 width: 100%;
573 font-size: 10pt;
574 font-weight: bold;
575 text-align: center;
576 vertical-align: middle;
577 padding: 1px;
578 }
579
580 #gradient, #mask, #progressIndicator {
581 left: 0;
582 border-width: 1px;
583 border-style: solid;
584 border-color: #000000;
585 color: #404040;
586 margin: 0.4em;
587 position: absolute;
588 margin-left: -1px;
589 margin-top: -1px;
590 margin-bottom: -1px;
591 overflow: hidden;
592 }
593
594 #mContainer {
595 display: block;
596 position: relative;
597 padding: 0px;
598 margin-top: 0.4em;
599 margin-bottom: 0.5em;
600 }
601
602 #gradient {
603 z-index: 1;
604 background-color: #FFFF00;
605 }
606
607 #mask {
608 z-index: 2;
609 background-color: #FFFFFF;
610 }
611
612 #progressIndicator {
613 z-index: 3;
614 background-color: transparent;
615 }
616
617 #volumes {
618 padding: 0.4em;
619 display: none;
620 width: 100%;
621 font-size: 80%;
622 color: #ff0000;
623 text-align: center;
624 }
625 -->
626 </style>
627 <script type="text/javascript">
628 <!--
629
630 var debug_div = null;
631 EOF3
632
633 # take maximum archive size from configuration
634 $retHTML .= qq{
635 var media_size = $max_archive_size ;
636 var max_file_size = $max_archive_file_size;
637
638 };
639
640 $retHTML .= <<'EOF3';
641
642 function debug(msg) {
643 // return; // Disable debugging
644
645 if (! debug_div) debug_div = document.getElementById('debug');
646
647 // this will create debug div if it doesn't exist.
648 if (! debug_div) {
649 debug_div = document.createElement('div');
650 if (document.body) document.body.appendChild(debug_div);
651 else debug_div = null;
652 }
653 if (debug_div) {
654 debug_div.appendChild(document.createTextNode(msg));
655 debug_div.appendChild(document.createElement("br"));
656 }
657 }
658
659
660 var element_id_cache = Array();
661
662 function element_id(name,element) {
663 if (! element_id_cache[name]) {
664 element_id_cache[name] = self.document.getElementById(name);
665 }
666 return element_id_cache[name];
667 }
668
669 function checkAll(location) {
670 var f = element_id('forma') || null;
671 if (!f) return false;
672
673 var len = f.elements.length;
674 var check_all = element_id('allFiles');
675 var suma = check_all.checked ? (parseInt(f.elements['totalsize'].value) || 0) : 0;
676
677 for (var i = 0; i < len; i++) {
678 var e = f.elements[i];
679 if (e.name != 'all' && e.name.substr(0, 3) == 'fcb') {
680 if (check_all.checked) {
681 if (e.checked) continue;
682 var el = element_id("fss" + e.name.substr(3));
683 var size = parseInt(el.value) || 0;
684 debug('suma: '+suma+' size: '+size);
685 if ((suma + size) < media_size) {
686 suma += size;
687 e.checked = true;
688 } else {
689 break;
690 }
691 } else {
692 e.checked = false;
693 }
694 }
695 }
696 update_sum(suma);
697 }
698
699 function update_sum(suma, suma_disp) {
700 if (! suma_disp) suma_disp = suma;
701 suma_disp = Math.floor(suma_disp / 1024);
702 element_id('forma').elements['totalsize_kb'].value = suma_disp;
703 element_id('forma').elements['totalsize'].value = suma;
704 pbar_set(suma, media_size);
705 debug('total size: ' + suma);
706 }
707
708 function update_size(name, checked, suma) {
709 var size = parseInt( element_id("fss" + name).value);
710
711 if (checked) {
712 suma += size;
713 } else {
714 suma -= size;
715 }
716
717 var volumes = parseInt( element_id("prt" + name).value);
718 debug('update_size('+name+','+checked+') suma: '+suma+' volumes: '+volumes);
719 if (volumes > 1) {
720 if (checked) {
721 element_id("volumes").innerHTML = "This will take "+volumes+" mediums!";
722 element_id("volumes").style.display = 'block';
723 suma = size;
724 update_sum(suma);
725 } else {
726 suma -= size;
727 element_id("volumes").style.display = 'none';
728 }
729 }
730
731 return suma;
732 }
733
734 function sumiraj(e) {
735 var suma = parseInt(element_id('forma').elements['totalsize'].value) || 0;
736 var len = element_id('forma').elements.length;
737 if (e) {
738 suma = update_size(e.name.substr(3), e.checked, suma);
739 if (suma < 0) suma = 0;
740 } else {
741 suma = 0;
742 for (var i = 0; i < len; i++) {
743 var fel = element_id('forma').elements[i];
744 if (fel.name != 'all' && fel.checked && fel.name.substr(0,3) == 'fcb') {
745 suma = update_size(fel.name.substr(3), fel.checked, suma);
746 }
747 }
748 }
749 update_sum(suma);
750 return suma;
751 }
752
753 /* progress bar */
754
755 var _pbar_width = null;
756 var _pbar_warn = 10; // change color in last 10%
757
758 function pbar_reset() {
759 element_id("mask").style.left = "0px";
760 _pbar_width = element_id("mContainer").offsetWidth - 2;
761 element_id("mask").style.width = _pbar_width + "px";
762 element_id("mask").style.display = "block";
763 element_id("progressIndicator").style.zIndex = 10;
764 element_id("progressIndicator").innerHTML = "0";
765 }
766
767 function dec2hex(d) {
768 var hch = '0123456789ABCDEF';
769 var a = d % 16;
770 var q = (d - a) / 16;
771 return hch.charAt(q) + hch.charAt(a);
772 }
773
774 function pbar_set(amount, max) {
775 debug('pbar_set('+amount+', '+max+')');
776
777 if (_pbar_width == null) {
778 var _mc = element_id("mContainer");
779 if (_pbar_width == null) _pbar_width = parseInt(_mc.offsetWidth ? (_mc.offsetWidth - 2) : 0) || null;
780 if (_pbar_width == null) _pbar_width = parseInt(_mc.clientWidth ? (_mc.clientWidth + 2) : 0) || null;
781 if (_pbar_width == null) _pbar_width = 0;
782 }
783
784 var pcnt = Math.floor(amount * 100 / max);
785 var p90 = 100 - _pbar_warn;
786 var pcol = pcnt - p90;
787 if (Math.round(pcnt) <= 100) {
788 if (pcol < 0) pcol = 0;
789 var e = element_id("submitBurner");
790 debug('enable_button');
791 e.disabled = false;
792 var a = e.getAttributeNode('disabled') || null;
793 if (a) e.removeAttributeNode(a);
794 } else {
795 debug('disable button');
796 pcol = _pbar_warn;
797 var e = element_id("submitBurner");
798 if (!e.disabled) e.disabled = true;
799 }
800 var col_g = Math.floor((_pbar_warn - pcol) * 255 / _pbar_warn);
801 var col = '#FF' + dec2hex(col_g) + '00';
802
803 //debug('pcol: '+pcol+' g:'+col_g+' _pbar_warn:'+ _pbar_warn + ' color: '+col);
804 element_id("gradient").style.backgroundColor = col;
805
806 element_id("progressIndicator").innerHTML = pcnt + '%';
807 //element_id("progressIndicator").innerHTML = amount;
808
809 element_id("mask").style.clip = 'rect(' + Array(
810 '0px',
811 element_id("mask").offsetWidth + 'px',
812 element_id("mask").offsetHeight + 'px',
813 Math.round(_pbar_width * amount / max) + 'px'
814 ).join(' ') + ')';
815 }
816
817 if (!self.body) self.body = new Object();
818 self.onload = self.document.onload = self.body.onload = function() {
819 //pbar_reset();
820 sumiraj();
821 };
822
823 // -->
824 </script>
825 <div id="fixedBox">
826
827 <input type="hidden" name="totalsize"/>
828 Size: <input type="text" name="totalsize_kb" size="7" readonly="readonly" style="text-align:right;" value="0" /> kB
829
830 <div id="mContainer">
831 <div id="gradient">&nbsp;</div>
832 <div id="mask">&nbsp;</div>
833 <div id="progressIndicator">0%</div>
834 </div>
835 <br/>
836
837 <div id="volumes">&nbsp;</div>
838
839 Note:
840 <textarea name="note" cols="10" rows="5" id="note"></textarea>
841
842 <input type="submit" id="submitBurner" value="Burn selected" name="submitBurner" />
843
844 </div>
845 <!--
846 <div id="debug" style="float: right; width: 10em; border: 1px #ff0000 solid; background-color: #ffe0e0; -moz-opacity: 0.7;">
847 no debug output yet
848 </div>
849 -->
850 EOF3
851 $retHTML .= q{
852 <input type="hidden" value="burn" name="action">
853 <input type="hidden" value="results" name="search_results">
854 <table style="fview" border="0" cellspacing="0" cellpadding="2">
855 <tr class="tableheader">
856 <td class="tableheader">
857 <input type="checkbox" name="allFiles" id="allFiles" onClick="checkAll('allFiles');">
858 </td>
859 } .
860 sort_header($param, 'Share', 'share', 'center') .
861 sort_header($param, '#', 'num', 'center') .
862 qq{
863 <td align="center">Type</td>
864 } .
865 sort_header($param, 'Date', 'date', 'center') .
866 sort_header($param, 'Age/days', 'age', 'center') .
867 sort_header($param, 'Size/Mb', 'size', 'center') .
868 sort_header($param, 'gzip size/Kb', 'incsize', 'center') .
869 qq{
870 <td align="center">medias</td></tr>
871 };
872
873 my @color = (' bgcolor="#e0e0e0"', '');
874
875 my $i = 0;
876 my $host = '';
877
878 foreach my $backup ( getBackupsNotBurned($param) ) {
879
880 if ($host ne $backup->{'host'}) {
881 $i++;
882 $host = $backup->{'host'};
883 }
884 my $ftype = "";
885
886 my $checkbox_key = $backup->{'hostid'}. '_' .$backup->{'backupnum'} . '_' . $backup->{'id'};
887
888 $retHTML .=
889 '<tr' . $color[$i %2 ] . '>
890 <td class="fview">';
891
892 if (($backup->{'inc_size'} || 0) > 0) {
893 $retHTML .= '
894 <input type="checkbox" name="fcb' . $checkbox_key . '" value="' . $checkbox_key . '" onClick="sumiraj(this);">';
895 }
896
897 my $img_url = $Conf{CgiImageDirURL};
898
899 $retHTML .=
900 '</td>' .
901 '<td align="right">' . $backup->{'host'} . ':' . $backup->{'share'} . '</td>' .
902 '<td align="center">' . $backup->{'backupnum'} . '</td>' .
903 '<td align="center">' . $backup->{'type'} . '</td>' .
904 '<td align="center">' . epoch_to_iso( $backup->{'date'} ) . '</td>' .
905 '<td align="center">' . $backup->{'age'} . '</td>' .
906 '<td align="right">' . $backup->{'size'} . '</td>' .
907 '<td align="right">' . sprintf("%0.1f", $backup->{'inc_size'} / 1024 ) .
908 '<input type="hidden" id="fss'.$checkbox_key .'" value="'. $backup->{'inc_size_calc'} .'"></td>' .
909 '<input type="hidden" id="prt'.$checkbox_key .'" value="'. $backup->{'volumes'} .'"></td>' .
910 '<td align="left">' . ( qq{<img src="$img_url/icon-cd.gif" alt="media">} x $backup->{volumes} ) . '</td>' .
911
912 "</tr>\n";
913 }
914
915 $retHTML .= "</table>";
916 $retHTML .= "</form>";
917
918 return $retHTML;
919 }
920
921 sub displayGrid($) {
922 my ($param) = @_;
923
924 my $offset = $param->{'offset'};
925 my $hilite = $param->{'search_filename'};
926
927 my $retHTML = "";
928
929 my $start_t = time();
930
931 my ($results, $files);
932 if ($param->{'use_hest'} && length($hilite) > 0) {
933 ($results, $files) = getFilesHyperEstraier($param);
934 } else {
935 ($results, $files) = getFiles($param);
936 }
937
938 my $dur_t = time() - $start_t;
939 my $dur = sprintf("%0.4fs", $dur_t);
940
941 my ($from, $to) = (($offset * $on_page) + 1, ($offset * $on_page) + $on_page);
942
943 if ($results <= 0) {
944 $retHTML .= qq{
945 <p style="color: red;">No results found...</p>
946 };
947 return $retHTML;
948 } else {
949 # DEBUG
950 #use Data::Dumper;
951 #$retHTML .= '<pre>' . Dumper($files) . '</pre>';
952 }
953
954
955 $retHTML .= qq{
956 <div>
957 Found <b>$results files</b> showing <b>$from - $to</b> (took $dur)
958 </div>
959 <table style="fview" width="100%" border="0" cellpadding="2" cellspacing="0">
960 <tr class="fviewheader">
961 <td></td>
962 };
963
964 sub sort_header($$$$) {
965 my ($param, $display, $name, $align) = @_;
966
967 my ($sort_what, $sort_direction) = split(/_/,$param->{'sort'},2);
968
969 my $old_sort = $param->{'sort'};
970
971 my $html = qq{<td align="$align"};
972 my $arrow = '';
973
974 if (lc($sort_what) eq lc($name)) {
975 my $direction = lc($sort_direction);
976
977 # swap direction or fallback to default
978 $direction =~ tr/ad/da/;
979 $direction = 'a' unless ($direction =~ /[ad]/);
980
981 $param->{'sort'} = $name . '_' . $direction;
982 $html .= ' style="border: 1px solid #808080;"';
983
984 # add unicode arrow for direction
985 $arrow .= '&nbsp;';
986 $arrow .= $direction eq 'a' ? '&#9650;'
987 : $direction eq 'd' ? '&#9660;'
988 : ''
989 ;
990
991 } else {
992 $param->{'sort'} = $name . '_a';
993 }
994
995 $html .= '><a href="' . page_uri($param) . '">' . $display . '</a>' . $arrow . '</td>';
996 $param->{'sort'} = $old_sort;
997
998 return $html;
999 }
1000
1001 $retHTML .=
1002 sort_header($param, 'Share', 'share', 'center') .
1003 sort_header($param, 'Type and Name', 'path', 'center') .
1004 sort_header($param, '#', 'num', 'center') .
1005 sort_header($param, 'Size', 'size', 'center') .
1006 sort_header($param, 'Date', 'date', 'center');
1007
1008 $retHTML .= qq{
1009 <td align="center">Media</td>
1010 </tr>
1011 };
1012
1013 my $file;
1014
1015 sub hilite_html($$) {
1016 my ($html, $search) = @_;
1017 $html =~ s#($search)#<b>$1</b>#gis;
1018 return $html;
1019 }
1020
1021 sub restore_link($$$$$$) {
1022 my $type = shift;
1023 my $action = 'RestoreFile';
1024 $action = 'browse' if (lc($type) eq 'dir');
1025 return sprintf(qq{<a href="?action=%s&host=%s&num=%d&share=%s&dir=%s">%s</a>}, $action, @_);
1026 }
1027
1028 my $sth_archived;
1029 my %archived_cache;
1030
1031 sub check_archived($$$) {
1032 my ($host, $share, $num) = @_;
1033
1034 if (my $html = $archived_cache{"$host $share $num"}) {
1035 return $html;
1036 }
1037
1038 $sth_archived ||= $dbh->prepare(qq{
1039 select
1040 dvd_nr, note,
1041 count(archive_burned.copy) as copies
1042 from archive
1043 inner join archive_burned on archive_burned.archive_id = archive.id
1044 inner join archive_backup on archive.id = archive_backup.archive_id
1045 inner join backups on backups.id = archive_backup.backup_id
1046 inner join hosts on hosts.id = backups.hostid
1047 inner join shares on shares.id = backups.shareid
1048 where hosts.name = ? and shares.name = ? and backups.num = ?
1049 group by dvd_nr, note
1050 });
1051
1052 my @mediums;
1053
1054 $sth_archived->execute($host, $share, $num);
1055 while (my $row = $sth_archived->fetchrow_hashref()) {
1056 push @mediums, '<abbr title="' .
1057 $row->{'note'} .
1058 ' [' . $row->{'copies'} . ']' .
1059 '">' .$row->{'dvd_nr'} .
1060 '</abbr>';
1061 }
1062
1063 my $html = join(", ",@mediums);
1064 $archived_cache{"$host $share $num"} = $html;
1065 return $html;
1066 }
1067
1068 my $i = $offset * $on_page;
1069
1070 foreach $file (@{ $files }) {
1071 $i++;
1072
1073 my $typeStr = BackupPC::Attrib::fileType2Text(undef, $file->{'type'});
1074 $retHTML .= qq{<tr class="fviewborder">};
1075
1076 $retHTML .= qq{<td class="fviewborder">$i</td>};
1077
1078 $retHTML .=
1079 qq{<td class="fviewborder" align="right">} . $file->{'hname'} . ':' . $file->{'sname'} . qq{</td>} .
1080 qq{<td class="fviewborder"><img src="$Conf{CgiImageDirURL}/icon-$typeStr.gif" alt="$typeStr" align="middle">&nbsp;} . hilite_html( $file->{'filepath'}, $hilite ) . qq{</td>} .
1081 qq{<td class="fviewborder" align="center">} . restore_link( $typeStr, ${EscURI( $file->{'hname'} )}, $file->{'backupnum'}, ${EscURI( $file->{'sname'})}, ${EscURI( $file->{'filepath'} )}, $file->{'backupnum'} ) . qq{</td>} .
1082 qq{<td class="fviewborder" align="right">} . $file->{'size'} . qq{</td>} .
1083 qq{<td class="fviewborder">} . epoch_to_iso( $file->{'date'} ) . qq{</td>} .
1084 qq{<td class="fviewborder">} . check_archived( $file->{'hname'}, $file->{'sname'}, $file->{'backupnum'} ) . qq{</td>};
1085
1086 $retHTML .= "</tr>";
1087 }
1088 $retHTML .= "</table>";
1089
1090 # all variables which has to be transfered
1091 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/) {
1092 $retHTML .= qq{<INPUT TYPE="hidden" NAME="$n" VALUE="$In{$n}">\n};
1093 }
1094
1095 my $del = '';
1096 my $max_page = int( $results / $on_page );
1097 my $page = 0;
1098
1099 sub page_uri($) {
1100 my $param = shift || die "no param?";
1101
1102 my $uri = $MyURL;
1103 my $del = '?';
1104 foreach my $k (keys %{ $param }) {
1105 if ($param->{$k}) {
1106 $uri .= $del . $k . '=' . ${EscURI( $param->{$k} )};
1107 $del = '&';
1108 }
1109 }
1110 return $uri;
1111 }
1112
1113 sub page_link($$$) {
1114 my ($param,$page,$display) = @_;
1115
1116 $param->{'offset'} = $page if (defined($page));
1117
1118 my $html = '<a href = "' . page_uri($param) . '">' . $display . '</a>';
1119 }
1120
1121 $retHTML .= '<div style="text-align: center;">';
1122
1123 if ($offset > 0) {
1124 $retHTML .= page_link($param, $offset - 1, '&lt;&lt;') . ' ';
1125 }
1126
1127 while ($page <= $max_page) {
1128 if ($page == $offset) {
1129 $retHTML .= $del . '<b>' . ($page + 1) . '</b>';
1130 } else {
1131 $retHTML .= $del . page_link($param, $page, $page + 1);
1132 }
1133
1134 if ($page < $offset - $pager_pages && $page != 0) {
1135 $retHTML .= " ... ";
1136 $page = $offset - $pager_pages;
1137 $del = '';
1138 } elsif ($page > $offset + $pager_pages && $page != $max_page) {
1139 $retHTML .= " ... ";
1140 $page = $max_page;
1141 $del = '';
1142 } else {
1143 $del = ' | ';
1144 $page++;
1145 }
1146 }
1147
1148 if ($offset < $max_page) {
1149 $retHTML .= ' ' . page_link($param, $offset + 1, '&gt;&gt;');
1150 }
1151
1152 $retHTML .= "</div>";
1153
1154 return $retHTML;
1155 }
1156
1157 1;

  ViewVC Help
Powered by ViewVC 1.1.26