/[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 254 - (show annotations)
Mon Dec 12 16:07:27 2005 UTC (18 years, 5 months ago) by dpavlin
File size: 27346 byte(s)
 r11640@llin:  dpavlin | 2005-12-12 18:07:17 +0100
 tar_check works again and creates missing md5 sum files (if needed)

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

  ViewVC Help
Powered by ViewVC 1.1.26