/[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

Annotation of /trunk/lib/BackupPC/SearchLib.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 380 - (hide annotations)
Wed May 9 07:07:02 2007 UTC (17 years, 1 month ago) by iklaric
File size: 28768 byte(s)
- fixed problem with determining file size of tgz on disk: if there is no file, it's size is declared as zero than

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

  ViewVC Help
Powered by ViewVC 1.1.26