/[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 262 - (hide annotations)
Tue Dec 13 00:10:44 2005 UTC (18 years, 5 months ago) by dpavlin
File size: 28533 byte(s)
 r11655@llin:  dpavlin | 2005-12-13 00:23:11 +0100
 various improvements and fixes. Might even work now.

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

  ViewVC Help
Powered by ViewVC 1.1.26