/[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 59 - (show annotations)
Sun Aug 21 15:29:24 2005 UTC (18 years, 8 months ago) by dpavlin
File size: 11153 byte(s)
Add permantent serach form using HTML::FillInForm, fixed offset+1 bug,
added no results message

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
12 my $on_page = 100;
13 my $pager_pages = 10;
14
15 my $dsn = $Conf{SearchDSN};
16 my $db_user = $Conf{SearchUser} || '';
17
18 sub getUnits() {
19 my @ret;
20
21 my $dbh = DBI->connect($dsn, $db_user, "", { RaiseError => 1, AutoCommit => 1 } );
22 my $sth = $dbh->prepare(qq{ SELECT id, share FROM shares} );
23 $sth->execute();
24 push @ret, { 'id' => '', 'share' => '-'}; # dummy any
25
26 while ( my $row = $sth->fetchrow_hashref() ) {
27 push @ret, $row;
28 }
29 $dbh->disconnect();
30 return @ret;
31 }
32
33 sub epoch_to_iso {
34 my $t = shift || return;
35 my $dt = DateTime->from_epoch( epoch => $t ) || return;
36 print STDERR "BUG: $t != " . $dt->epoch . "\n" unless ($t == $dt->epoch);
37 return $dt->ymd . ' ' . $dt->hms;
38 }
39
40 sub getWhere($) {
41 my ($param) = @_;
42 my @conditions;
43
44 sub mk_epoch_date($$) {
45 my ($name,$suffix) = @_;
46
47 my $yyyy = $param->{ $name . '_year_' . $suffix} || return;
48 my $mm .= $param->{ $name . '_month_' . $suffix} ||
49 ( $suffix eq 'from' ? 1 : 12);
50 my $dd .= $param->{ $name . '_day_' . $suffix} ||
51 ( $suffix eq 'from' ? 1 : 31);
52 my $dt = new DateTime(
53 year => $yyyy,
54 month => $mm,
55 day => $dd
56 );
57 return $dt->epoch || 'NULL';
58 }
59
60 my $backup_from = mk_epoch_date('search_backup', 'from');
61 push @conditions, qq{ backups.date >= $backup_from } if ($backup_from);
62 my $backup_to = mk_epoch_date('search_backup', 'to');
63 push @conditions, qq{ backups.date <= $backup_to } if ($backup_to);
64
65 my $files_from = mk_epoch_date('search', 'from');
66 push @conditions, qq{ files.date >= $files_from } if ($files_from);
67 my $files_to = mk_epoch_date('search', 'to');
68 push @conditions, qq{ files.date <= $files_to } if ($files_to);
69
70 print STDERR "backup: $backup_from - $backup_to files: $files_from - $files_to cond:" . join(" | ",@conditions);
71
72 push( @conditions, ' backups.hostID = ' . $param->{'search_host'} ) if ($param->{'search_host'});
73
74 push (@conditions, " upper(files.name) LIKE upper('%".$param->{'search_filename'}."%')") if ($param->{'search_filename'});
75
76 return (
77 join(" and ", @conditions),
78 $files_from, $files_to,
79 $backup_from, $backup_to
80 );
81 }
82
83
84 sub getFiles($$) {
85 my ($where, $offset) = @_;
86
87 my $dbh = DBI->connect($dsn, $db_user, "", { RaiseError => 1, AutoCommit => 1 } );
88
89 my $sql_cols = qq{
90 files.id AS fid,
91 hosts.name AS hname,
92 shares.name AS sname,
93 shares.share AS sharename,
94 files.backupNum AS backupNum,
95 files.name AS filename,
96 files.path AS filepath,
97 shares.share||files.fullpath AS networkPath,
98 files.date AS date,
99 files.type AS filetype,
100 files.size AS size,
101 dvds.name AS dvd
102 };
103
104 my $sql_from = qq{
105 FROM files
106 INNER JOIN shares ON files.shareID=shares.ID
107 INNER JOIN hosts ON hosts.ID = shares.hostID
108 INNER JOIN backups ON backups.num = files.backupNum and backups.hostID = hosts.ID
109 };
110
111 my $sql_dvd_from = qq{
112 LEFT JOIN dvds ON dvds.ID = files.dvdid
113 };
114
115 my $sql_where;
116 $sql_where = " WHERE ". $where if ($where);
117
118 my $sql_order = qq{
119 ORDER BY files.id
120 LIMIT $on_page
121 OFFSET ?
122 };
123
124 my $sql_count = qq{ select count(files.id) $sql_from $sql_where };
125 my $sql_results = qq{ select $sql_cols $sql_from $sql_dvd_from $sql_where $sql_order };
126
127 $offset ||= 0;
128 $offset = ($offset * $on_page);
129
130 my $sth = $dbh->prepare($sql_count);
131 $sth->execute();
132 my ($results) = $sth->fetchrow_array();
133
134 $sth = $dbh->prepare($sql_results);
135 $sth->execute( $offset );
136
137 if ($sth->rows != $results) {
138 my $bug = "$0 BUG: [[ $sql_count ]] = $results while [[ $sql_results ]] = " . $sth->rows;
139 $bug =~ s/\s+/ /gs;
140 print STDERR "$bug\n";
141 }
142
143 my @ret;
144
145 while (my $row = $sth->fetchrow_hashref()) {
146 push(@ret, {
147 'hname' => $row->{'hname'},
148 'sname' => $row->{'sname'},
149 'sharename' => $row->{'sharename'},
150 'backupno' => $row->{'backupnum'},
151 'fname' => $row->{'filename'},
152 'fpath' => $row->{'filepath'},
153 'networkpath' => $row->{'networkpath'},
154 'date' => $row->{'date'},
155 'type' => $row->{'filetype'},
156 'size' => $row->{'size'},
157 'id' => $row->{'fid'},
158 'dvd' => $row->{'dvd'}
159 });
160 }
161
162 $sth->finish();
163 $dbh->disconnect();
164 return ($results, \@ret);
165 }
166
167 sub getBackupsNotBurned() {
168
169 my $dbh = DBI->connect($dsn, $db_user, "", { RaiseError => 1, AutoCommit => 1 } );
170 my $sql = q{
171 SELECT
172 hosts.ID AS hostid,
173 min(hosts.name) AS host,
174 backups.num AS backupno,
175 min(backups.type) AS type,
176 min(backups.date) AS date
177 FROM backups, shares, files, hosts
178 WHERE
179 backups.num = files.backupNum AND
180 shares.ID = files.shareID AND
181 backups.hostID = shares.hostID AND
182 hosts.ID = backups.hostID AND
183 files.dvdid IS NULL
184 GROUP BY
185 backups.hostID, backups.num, hosts.id
186 ORDER BY min(backups.date)
187 };
188 my $sth = $dbh->prepare( $sql );
189 my @ret;
190 $sth->execute();
191
192 while ( my $row = $sth->fetchrow_hashref() ) {
193 push(@ret, {
194 'host' => $row->{'host'},
195 'hostid' => $row->{'hostid'},
196 'backupno' => $row->{'backupno'},
197 'type' => $row->{'type'},
198 'date' => $row->{'date'},
199 'age' => sprintf("%0.1f", ( (time() - $row->{'date'}) / 86400 ) ),
200 }
201 );
202 }
203
204 return @ret;
205 }
206
207 sub displayBackupsGrid()
208 {
209 my $retHTML = "";
210 my $addForm = 1;
211
212 if ($addForm) {
213
214 $retHTML .= <<EOF3;
215 <script language="javascript" type="text/javascript">
216 <!--
217
218 function checkAll(location)
219 {
220 for (var i=0;i<document.forma.elements.length;i++)
221 {
222 var e = document.forma.elements[i];
223 if ((e.checked || !e.checked) && e.name != \'all\') {
224 if (eval("document.forma."+location+".checked")) {
225 e.checked = true;
226 } else {
227 e.checked = false;
228 }
229 }
230 }
231 }
232 //-->
233 </script>
234 EOF3
235 $retHTML .= q{<form name="forma" method="GET" action="}."$MyURL"."?action=burn\"";
236 $retHTML.= q{<input type="hidden" value="burn" name="action">};
237 $retHTML .= q{<input type="hidden" value="results" name="search_results">};
238 }
239 $retHTML .= qq{<table style="fview"><tr>};
240
241 if ($addForm) {
242 $retHTML .= "<td class=\"tableheader\"><input type=\"checkbox\" name=\"allFiles\" onClick=\"checkAll('allFiles');\"></td>";
243 }
244 $retHTML .= qq{
245 <td class="tableheader">Host</td>
246 <td class="tableheader">Backup no</td>
247 <td class="tableheader">Type</td>
248 <td class="tableheader">date</td>
249 <td class="tableheader">age/days</td>
250 </tr>
251 };
252
253 my @backups = getBackupsNotBurned();
254 my $backup;
255
256 if ($addForm) {
257 $retHTML .= qq{
258 <tr><td colspan=7 style="tableheader">
259 <input type="submit" value="Burn selected backups on medium" name="submitBurner">
260 </td></tr>
261 };
262 }
263
264 foreach $backup(@backups) {
265
266 my $ftype = "";
267
268 $retHTML .= "<tr>";
269 if ($addForm) {
270 $retHTML .= '<td class="fview"><input type="checkbox" name="fcb' .
271 $backup->{'hostid'}.'_'.$backup->{'backupno'} .
272 '" value="' . $backup->{'hostid'}.'_'.$backup->{'backupno'} .
273 '"></td>';
274 }
275
276 $retHTML .= '<td class="fviewborder">' . $backup->{'host'} . '</td>' .
277 '<td class="fviewborder">' . $backup->{'backupno'} . '</td>' .
278 '<td class="fviewborder">' . $backup->{'type'} . '</td>' .
279 '<td class="fviewborder">' . epoch_to_iso( $backup->{'date'} ) . '</td>' .
280 '<td class="fviewborder">' . $backup->{'age'} . '</td>' .
281 '</tr>';
282 }
283
284 $retHTML .= "</table>";
285
286 if ($addForm) {
287 $retHTML .= "</form>";
288 }
289
290 return $retHTML;
291 }
292
293 sub displayGrid($$$$) {
294 my ($where, $addForm, $offset, $hilite) = @_;
295 my $retHTML = "";
296
297 my $start_t = time();
298
299 my ($results, $files) = getFiles($where, $offset);
300
301 my $dur_t = time() - $start_t;
302 my $dur = sprintf("%0.4fs", $dur_t);
303
304 my ($from, $to) = (($offset * $on_page) + 1, ($offset * $on_page) + $on_page);
305
306 if ($results <= 0) {
307 $retHTML .= qq{
308 <p style="color: red;">No results found...</p>
309 };
310 return $retHTML;
311 } else {
312 # DEBUG
313 #use Data::Dumper;
314 #$retHTML .= '<pre>' . Dumper($files) . '</pre>';
315 }
316
317
318 if ($addForm) {
319 $retHTML .= qq{<form name="forma" method="GET" action="$MyURL">};
320 $retHTML.= qq{<input type="hidden" value="search" name="action">};
321 $retHTML .= qq{<input type="hidden" value="results" name="search_results">};
322 }
323
324
325 $retHTML .= qq{
326 <br/>Found <b>$results files</b> showing <b>$from - $to</b> (took $dur)
327 <table style="fview" width="100%">
328 <tr>
329 <td class="tableheader">Share</td>
330 <td class="tableheader">Name</td>
331 <td class="tableheader">Type</td>
332 <td class="tableheader">#</td>
333 <td class="tableheader">Size</td>
334 <td class="tableheader">Date</td>
335 <td class="tableheader">Media</td>
336 </tr>
337 };
338
339 my $file;
340
341 sub hilite_html($$) {
342 my ($html, $search) = @_;
343 $html =~ s#($search)#<b>$1</b>#gis;
344 return $html;
345 }
346
347 sub restore_link($$$$$$) {
348 my $type = shift;
349 my $action = 'RestoreFile';
350 $action = 'browse' if (lc($type) eq 'dir');
351 return sprintf(qq{<a href="?action=%s&host=%s&num=%d&share=%s&dir=%s">%s</a>}, $action, @_);
352 }
353
354 foreach $file (@{ $files }) {
355 my $typeStr = BackupPC::Attrib::fileType2Text(undef, $file->{'type'});
356 $retHTML .= "<tr>";
357
358 foreach my $v ((
359 $file->{'sharename'},
360 qq{<img src="$Conf{CgiImageDirURL}/icon-$typeStr.gif" align="center">&nbsp;} . hilite_html( $file->{'fpath'}, $hilite ),
361 $typeStr,
362 restore_link( $typeStr, $file->{'hname'}, $file->{'backupno'}, $file->{'sname'}, $file->{'fpath'}, $file->{'backupno'} ),
363 $file->{'size'},
364 epoch_to_iso( $file->{'date'} ),
365 $file->{'dvd'}
366 )) {
367 $retHTML .= qq{<td class="fviewborder">$v</td>};
368 }
369
370 $retHTML .= "</tr>";
371 }
372 $retHTML .= "</table>";
373
374 # all variables which has to be transfered
375 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/) {
376 $retHTML .= qq{<INPUT TYPE="hidden" NAME="$n" VALUE="$In{$n}">\n};
377 }
378
379 my $del = '';
380 my $max_page = int( $results / $on_page );
381 my $page = 0;
382
383 my $link_fmt = '<a href = "#" onclick="document.forma.offset.value=%d;document.forma.submit();">%s</a>';
384
385 $retHTML .= '<div style="text-align: center;">';
386
387 if ($offset > 0) {
388 $retHTML .= sprintf($link_fmt, $offset - 1, '&lt;&lt;') . ' ';
389 }
390
391 while ($page <= $max_page) {
392 if ($page == $offset) {
393 $retHTML .= $del . '<b>' . ($page + 1) . '</b>';
394 } else {
395 $retHTML .= $del . sprintf($link_fmt, $page, $page + 1);
396 }
397
398 if ($page < $offset - $pager_pages && $page != 0) {
399 $retHTML .= " ... ";
400 $page = $offset - $pager_pages;
401 $del = '';
402 } elsif ($page > $offset + $pager_pages && $page != $max_page) {
403 $retHTML .= " ... ";
404 $page = $max_page;
405 $del = '';
406 } else {
407 $del = ' | ';
408 $page++;
409 }
410 }
411
412 if ($offset < $max_page) {
413 $retHTML .= ' ' . sprintf($link_fmt, $offset + 1, '&gt;&gt;');
414 }
415
416 $retHTML .= "</div>";
417
418 $retHTML .= "</form>" if ($addForm);
419
420 return $retHTML;
421 }
422
423 1;

  ViewVC Help
Powered by ViewVC 1.1.26