/[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 253 - (show annotations)
Mon Dec 12 13:41:08 2005 UTC (18 years, 5 months ago) by dpavlin
File size: 27313 byte(s)
 r11637@llin:  dpavlin | 2005-12-12 15:40:59 +0100
 create increments using new BackupPC_tarIncCreate

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

  ViewVC Help
Powered by ViewVC 1.1.26