/[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 267 - (show annotations)
Tue Dec 13 01:24:09 2005 UTC (18 years, 4 months ago) by dpavlin
File size: 28542 byte(s)
remove debug div

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 ) * 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 update_size(name, checked, suma) {
723 var size = parseInt( element_id("fss" + name).value);
724
725 if (checked) {
726 suma += size;
727 } else {
728 suma -= size;
729 }
730
731 var volumes = parseInt( element_id("prt" + name).value);
732 debug('update_size('+name+','+checked+') suma: '+suma+' volumes: '+volumes);
733 if (volumes > 1) {
734 if (checked) {
735 element_id("volumes").innerHTML = "This will take "+volumes+" mediums!";
736 element_id("volumes").style.display = 'block';
737 suma = size;
738 update_sum(suma);
739 } else {
740 suma -= size;
741 element_id("volumes").style.display = 'none';
742 }
743 }
744
745 return suma;
746 }
747
748 function sumiraj(e) {
749 var suma = parseInt(element_id('forma').elements['totalsize'].value) || 0;
750 var len = element_id('forma').elements.length;
751 if (e) {
752 suma = update_size(e.name.substr(3), e.checked, suma);
753 if (suma < 0) suma = 0;
754 } else {
755 suma = 0;
756 for (var i = 0; i < len; i++) {
757 var fel = element_id('forma').elements[i];
758 if (fel.name != 'all' && fel.checked && fel.name.substr(0,3) == 'fcb') {
759 suma = update_size(fel.name.substr(3), fel.checked, suma);
760 }
761 }
762 }
763 update_sum(suma);
764 return suma;
765 }
766
767 /* progress bar */
768
769 var _pbar_width = null;
770 var _pbar_warn = 10; // change color in last 10%
771
772 function pbar_reset() {
773 element_id("mask").style.left = "0px";
774 _pbar_width = element_id("mContainer").offsetWidth - 2;
775 element_id("mask").style.width = _pbar_width + "px";
776 element_id("mask").style.display = "block";
777 element_id("progressIndicator").style.zIndex = 10;
778 element_id("progressIndicator").innerHTML = "0";
779 }
780
781 function dec2hex(d) {
782 var hch = '0123456789ABCDEF';
783 var a = d % 16;
784 var q = (d - a) / 16;
785 return hch.charAt(q) + hch.charAt(a);
786 }
787
788 function pbar_set(amount, max) {
789 debug('pbar_set('+amount+', '+max+')');
790
791 if (_pbar_width == null) {
792 var _mc = element_id("mContainer");
793 if (_pbar_width == null) _pbar_width = parseInt(_mc.offsetWidth ? (_mc.offsetWidth - 2) : 0) || null;
794 if (_pbar_width == null) _pbar_width = parseInt(_mc.clientWidth ? (_mc.clientWidth + 2) : 0) || null;
795 if (_pbar_width == null) _pbar_width = 0;
796 }
797
798 var pcnt = Math.floor(amount * 100 / max);
799 var p90 = 100 - _pbar_warn;
800 var pcol = pcnt - p90;
801 if (Math.round(pcnt) <= 100) {
802 if (pcol < 0) pcol = 0;
803 var e = element_id("submitBurner");
804 debug('enable_button');
805 e.disabled = false;
806 var a = e.getAttributeNode('disabled') || null;
807 if (a) e.removeAttributeNode(a);
808 } else {
809 debug('disable button');
810 pcol = _pbar_warn;
811 var e = element_id("submitBurner");
812 if (!e.disabled) e.disabled = true;
813 }
814 var col_g = Math.floor((_pbar_warn - pcol) * 255 / _pbar_warn);
815 var col = '#FF' + dec2hex(col_g) + '00';
816
817 //debug('pcol: '+pcol+' g:'+col_g+' _pbar_warn:'+ _pbar_warn + ' color: '+col);
818 element_id("gradient").style.backgroundColor = col;
819
820 element_id("progressIndicator").innerHTML = pcnt + '%';
821 //element_id("progressIndicator").innerHTML = amount;
822
823 element_id("mask").style.clip = 'rect(' + Array(
824 '0px',
825 element_id("mask").offsetWidth + 'px',
826 element_id("mask").offsetHeight + 'px',
827 Math.round(_pbar_width * amount / max) + 'px'
828 ).join(' ') + ')';
829 }
830
831 if (!self.body) self.body = new Object();
832 self.onload = self.document.onload = self.body.onload = function() {
833 //pbar_reset();
834 sumiraj();
835 };
836
837 // -->
838 </script>
839 <div id="fixedBox">
840
841 <input type="hidden" name="totalsize"/>
842 Size: <input type="text" name="totalsize_kb" size="7" readonly="readonly" style="text-align:right;" value="0" /> kB
843
844 <div id="mContainer">
845 <div id="gradient">&nbsp;</div>
846 <div id="mask">&nbsp;</div>
847 <div id="progressIndicator">0%</div>
848 </div>
849 <br/>
850
851 <div id="volumes">&nbsp;</div>
852
853 Note:
854 <textarea name="note" cols="10" rows="5" id="note"></textarea>
855
856 <input type="submit" id="submitBurner" value="Burn selected" name="submitBurner" />
857
858 </div>
859 <!--
860 <div id="debug" style="float: right; width: 10em; border: 1px #ff0000 solid; background-color: #ffe0e0; -moz-opacity: 0.7;">
861 no debug output yet
862 </div>
863 -->
864 EOF3
865 $retHTML .= q{
866 <input type="hidden" value="burn" name="action">
867 <input type="hidden" value="results" name="search_results">
868 <table style="fview" border="0" cellspacing="0" cellpadding="2">
869 <tr class="tableheader">
870 <td class="tableheader">
871 <input type="checkbox" name="allFiles" id="allFiles" onClick="checkAll('allFiles');">
872 </td>
873 } .
874 sort_header($param, 'Share', 'share', 'center') .
875 sort_header($param, '#', 'num', 'center') .
876 qq{
877 <td align="center">Type</td>
878 } .
879 sort_header($param, 'Date', 'date', 'center') .
880 sort_header($param, 'Age/days', 'age', 'center') .
881 sort_header($param, 'Size/Mb', 'size', 'center') .
882 sort_header($param, 'gzip size/Kb', 'incsize', 'center') .
883 qq{
884 <td align="center">medias</td></tr>
885 };
886
887 my @color = (' bgcolor="#e0e0e0"', '');
888
889 my $i = 0;
890 my $host = '';
891
892 foreach my $backup ( getBackupsNotBurned($param) ) {
893
894 if ($host ne $backup->{'host'}) {
895 $i++;
896 $host = $backup->{'host'};
897 }
898 my $ftype = "";
899
900 my $checkbox_key = $backup->{'hostid'}. '_' .$backup->{'backupnum'} . '_' . $backup->{'id'};
901
902 $retHTML .=
903 '<tr' . $color[$i %2 ] . '>
904 <td class="fview">';
905
906 if (($backup->{'inc_size'} || 0) > 0) {
907 $retHTML .= '
908 <input type="checkbox" name="fcb' . $checkbox_key . '" value="' . $checkbox_key . '" onClick="sumiraj(this);">';
909 }
910
911 my $img_url = $Conf{CgiImageDirURL};
912
913 $retHTML .=
914 '</td>' .
915 '<td align="right">' . $backup->{'host'} . ':' . $backup->{'share'} . '</td>' .
916 '<td align="center">' . $backup->{'backupnum'} . '</td>' .
917 '<td align="center">' . $backup->{'type'} . '</td>' .
918 '<td align="center">' . epoch_to_iso( $backup->{'date'} ) . '</td>' .
919 '<td align="center">' . $backup->{'age'} . '</td>' .
920 '<td align="right">' . $backup->{'size'} . '</td>' .
921 '<td align="right">' . sprintf("%0.1f", $backup->{'inc_size'} / 1024 ) .
922 '<input type="hidden" id="fss'.$checkbox_key .'" value="'. $backup->{'inc_size_calc'} .'"></td>' .
923 '<input type="hidden" id="prt'.$checkbox_key .'" value="'. $backup->{'volumes'} .'"></td>' .
924 '<td align="left">' . ( qq{<img src="$img_url/icon-cd.gif" alt="media">} x $backup->{volumes} ) . '</td>' .
925
926 "</tr>\n";
927 }
928
929 $retHTML .= "</table>";
930 $retHTML .= "</form>";
931
932 return $retHTML;
933 }
934
935 sub displayGrid($) {
936 my ($param) = @_;
937
938 my $offset = $param->{'offset'};
939 my $hilite = $param->{'search_filename'};
940
941 my $retHTML = "";
942
943 my $start_t = time();
944
945 my ($results, $files);
946 if ($param->{'use_hest'} && length($hilite) > 0) {
947 ($results, $files) = getFilesHyperEstraier($param);
948 } else {
949 ($results, $files) = getFiles($param);
950 }
951
952 my $dur_t = time() - $start_t;
953 my $dur = sprintf("%0.4fs", $dur_t);
954
955 my ($from, $to) = (($offset * $on_page) + 1, ($offset * $on_page) + $on_page);
956
957 if ($results <= 0) {
958 $retHTML .= qq{
959 <p style="color: red;">No results found...</p>
960 };
961 return $retHTML;
962 } else {
963 # DEBUG
964 #use Data::Dumper;
965 #$retHTML .= '<pre>' . Dumper($files) . '</pre>';
966 }
967
968
969 $retHTML .= qq{
970 <div>
971 Found <b>$results files</b> showing <b>$from - $to</b> (took $dur)
972 </div>
973 <table style="fview" width="100%" border="0" cellpadding="2" cellspacing="0">
974 <tr class="fviewheader">
975 <td></td>
976 };
977
978 sub sort_header($$$$) {
979 my ($param, $display, $name, $align) = @_;
980
981 my ($sort_what, $sort_direction) = split(/_/,$param->{'sort'},2);
982
983 my $old_sort = $param->{'sort'};
984
985 my $html = qq{<td align="$align"};
986 my $arrow = '';
987
988 if (lc($sort_what) eq lc($name)) {
989 my $direction = lc($sort_direction);
990
991 # swap direction or fallback to default
992 $direction =~ tr/ad/da/;
993 $direction = 'a' unless ($direction =~ /[ad]/);
994
995 $param->{'sort'} = $name . '_' . $direction;
996 $html .= ' style="border: 1px solid #808080;"';
997
998 # add unicode arrow for direction
999 $arrow .= '&nbsp;';
1000 $arrow .= $direction eq 'a' ? '&#9650;'
1001 : $direction eq 'd' ? '&#9660;'
1002 : ''
1003 ;
1004
1005 } else {
1006 $param->{'sort'} = $name . '_a';
1007 }
1008
1009 $html .= '><a href="' . page_uri($param) . '">' . $display . '</a>' . $arrow . '</td>';
1010 $param->{'sort'} = $old_sort;
1011
1012 return $html;
1013 }
1014
1015 $retHTML .=
1016 sort_header($param, 'Share', 'share', 'center') .
1017 sort_header($param, 'Type and Name', 'path', 'center') .
1018 sort_header($param, '#', 'num', 'center') .
1019 sort_header($param, 'Size', 'size', 'center') .
1020 sort_header($param, 'Date', 'date', 'center');
1021
1022 $retHTML .= qq{
1023 <td align="center">Media</td>
1024 </tr>
1025 };
1026
1027 my $file;
1028
1029 sub hilite_html($$) {
1030 my ($html, $search) = @_;
1031 $html =~ s#($search)#<b>$1</b>#gis;
1032 return $html;
1033 }
1034
1035 sub restore_link($$$$$$) {
1036 my $type = shift;
1037 my $action = 'RestoreFile';
1038 $action = 'browse' if (lc($type) eq 'dir');
1039 return sprintf(qq{<a href="?action=%s&host=%s&num=%d&share=%s&dir=%s">%s</a>}, $action, @_);
1040 }
1041
1042 my $sth_archived;
1043 my %archived_cache;
1044
1045 sub check_archived($$$) {
1046 my ($host, $share, $num) = @_;
1047
1048 if (my $html = $archived_cache{"$host $share $num"}) {
1049 return $html;
1050 }
1051
1052 $sth_archived ||= $dbh->prepare(qq{
1053 select
1054 dvd_nr, note,
1055 count(archive_burned.copy) as copies
1056 from archive
1057 inner join archive_burned on archive_burned.archive_id = archive.id
1058 inner join archive_backup on archive.id = archive_backup.archive_id
1059 inner join backups on backups.id = archive_backup.backup_id
1060 inner join hosts on hosts.id = backups.hostid
1061 inner join shares on shares.id = backups.shareid
1062 where hosts.name = ? and shares.name = ? and backups.num = ?
1063 group by dvd_nr, note
1064 });
1065
1066 my @mediums;
1067
1068 $sth_archived->execute($host, $share, $num);
1069 while (my $row = $sth_archived->fetchrow_hashref()) {
1070 push @mediums, '<abbr title="' .
1071 $row->{'note'} .
1072 ' [' . $row->{'copies'} . ']' .
1073 '">' .$row->{'dvd_nr'} .
1074 '</abbr>';
1075 }
1076
1077 my $html = join(", ",@mediums);
1078 $archived_cache{"$host $share $num"} = $html;
1079 return $html;
1080 }
1081
1082 my $i = $offset * $on_page;
1083
1084 foreach $file (@{ $files }) {
1085 $i++;
1086
1087 my $typeStr = BackupPC::Attrib::fileType2Text(undef, $file->{'type'});
1088 $retHTML .= qq{<tr class="fviewborder">};
1089
1090 $retHTML .= qq{<td class="fviewborder">$i</td>};
1091
1092 $retHTML .=
1093 qq{<td class="fviewborder" align="right">} . $file->{'hname'} . ':' . $file->{'sname'} . qq{</td>} .
1094 qq{<td class="fviewborder"><img src="$Conf{CgiImageDirURL}/icon-$typeStr.gif" alt="$typeStr" align="middle">&nbsp;} . hilite_html( $file->{'filepath'}, $hilite ) . qq{</td>} .
1095 qq{<td class="fviewborder" align="center">} . restore_link( $typeStr, ${EscURI( $file->{'hname'} )}, $file->{'backupnum'}, ${EscURI( $file->{'sname'})}, ${EscURI( $file->{'filepath'} )}, $file->{'backupnum'} ) . qq{</td>} .
1096 qq{<td class="fviewborder" align="right">} . $file->{'size'} . qq{</td>} .
1097 qq{<td class="fviewborder">} . epoch_to_iso( $file->{'date'} ) . qq{</td>} .
1098 qq{<td class="fviewborder">} . check_archived( $file->{'hname'}, $file->{'sname'}, $file->{'backupnum'} ) . qq{</td>};
1099
1100 $retHTML .= "</tr>";
1101 }
1102 $retHTML .= "</table>";
1103
1104 # all variables which has to be transfered
1105 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/) {
1106 $retHTML .= qq{<INPUT TYPE="hidden" NAME="$n" VALUE="$In{$n}">\n};
1107 }
1108
1109 my $del = '';
1110 my $max_page = int( $results / $on_page );
1111 my $page = 0;
1112
1113 sub page_uri($) {
1114 my $param = shift || die "no param?";
1115
1116 my $uri = $MyURL;
1117 my $del = '?';
1118 foreach my $k (keys %{ $param }) {
1119 if ($param->{$k}) {
1120 $uri .= $del . $k . '=' . ${EscURI( $param->{$k} )};
1121 $del = '&';
1122 }
1123 }
1124 return $uri;
1125 }
1126
1127 sub page_link($$$) {
1128 my ($param,$page,$display) = @_;
1129
1130 $param->{'offset'} = $page if (defined($page));
1131
1132 my $html = '<a href = "' . page_uri($param) . '">' . $display . '</a>';
1133 }
1134
1135 $retHTML .= '<div style="text-align: center;">';
1136
1137 if ($offset > 0) {
1138 $retHTML .= page_link($param, $offset - 1, '&lt;&lt;') . ' ';
1139 }
1140
1141 while ($page <= $max_page) {
1142 if ($page == $offset) {
1143 $retHTML .= $del . '<b>' . ($page + 1) . '</b>';
1144 } else {
1145 $retHTML .= $del . page_link($param, $page, $page + 1);
1146 }
1147
1148 if ($page < $offset - $pager_pages && $page != 0) {
1149 $retHTML .= " ... ";
1150 $page = $offset - $pager_pages;
1151 $del = '';
1152 } elsif ($page > $offset + $pager_pages && $page != $max_page) {
1153 $retHTML .= " ... ";
1154 $page = $max_page;
1155 $del = '';
1156 } else {
1157 $del = ' | ';
1158 $page++;
1159 }
1160 }
1161
1162 if ($offset < $max_page) {
1163 $retHTML .= ' ' . page_link($param, $offset + 1, '&gt;&gt;');
1164 }
1165
1166 $retHTML .= "</div>";
1167
1168 return $retHTML;
1169 }
1170
1171 1;

  ViewVC Help
Powered by ViewVC 1.1.26