/[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 380 - (show annotations)
Wed May 9 07:07:02 2007 UTC (17 years ago) by iklaric
File size: 28768 byte(s)
- fixed problem with determining file size of tgz on disk: if there is no file, it's size is declared as zero than

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

  ViewVC Help
Powered by ViewVC 1.1.26