/[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 379 - (hide annotations)
Tue May 8 12:16:24 2007 UTC (17 years ago) by iklaric
File size: 28981 byte(s)
foo

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

  ViewVC Help
Powered by ViewVC 1.1.26