/[BackupPC]/trunk/lib/BackupPC/SearchLib.pm
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 187 - (show annotations)
Wed Oct 12 13:14:06 2005 UTC (18 years, 7 months ago) by iklaric
File size: 24921 byte(s)
 r201@klaxLaptop:  klax | 2005-10-12 15:13:36 +0200
 - added dumpArchive2XML() sub

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

  ViewVC Help
Powered by ViewVC 1.1.26