/[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 382 - (show annotations)
Mon May 14 08:06:52 2007 UTC (17 years ago) by iklaric
File size: 29280 byte(s)
- fixed bug that occured while calculating total dvd size

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

  ViewVC Help
Powered by ViewVC 1.1.26