/[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 259 - (show annotations)
Mon Dec 12 20:59:58 2005 UTC (18 years, 5 months ago) by dpavlin
File size: 28423 byte(s)
 r11645@llin:  dpavlin | 2005-12-12 22:57:51 +0100
 added getVolumes to calculate number of media required, convert to bytes,
 added images of medias required (but it's broken!)

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

  ViewVC Help
Powered by ViewVC 1.1.26