fix archive to backup medium (but it still doesn't have functionality)
[BackupPC.git] / lib / BackupPC / SearchLib.pm
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
11 my $on_page = 100;
12 my $pager_pages = 10;
13
14 my $dsn = $Conf{SearchDSN};
15 my $db_user = $Conf{SearchUser} || '';
16
17 sub getUnits() {
18     my @ret = ();
19     my $tmp;
20     my $dbh = DBI->connect($dsn, $db_user, "", { RaiseError => 1, AutoCommit => 1 } );
21     my $st =
22       $dbh->prepare(
23         " SELECT shares.ID AS ID, shares.share AS name FROM shares;");
24     $st->execute();
25     push (@ret, { 'ID' => '', 'name' => '-'});
26     while ( $tmp = $st->fetchrow_hashref() ) {
27         push( @ret, { 'ID' => $tmp->{'ID'}, 'name' => $tmp->{'name'} } );
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 "$t == ",$dt->epoch,"\n";
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                         LEFT  JOIN dvds         ON dvds.ID = files.dvdid
110         };
111
112         my $sql_where;
113         $sql_where = " WHERE ". $where if ($where);
114
115         my $sql_order = qq{
116                 ORDER BY files.id
117                         LIMIT $on_page
118                         OFFSET ?
119         };
120
121         $offset ||= 0;
122         $offset = ($offset * $on_page) + 1;
123
124         my $sth = $dbh->prepare(qq{ select count(files.id) $sql_from $sql_where });
125         $sth->execute();
126
127         my ($results) = $sth->fetchrow_array();
128
129         $sth = $dbh->prepare(qq{ select $sql_cols $sql_from $sql_where $sql_order });
130         $sth->execute( $offset );
131
132         my @ret;
133       
134         while (my $row = $sth->fetchrow_hashref()) {
135                 push(@ret, { 
136                         'hname'         => $row->{'hname'}, 
137                         'sname'         => $row->{'sname'},
138                         'sharename'     => $row->{'sharename'},
139                         'backupno'      => $row->{'backupnum'},
140                         'fname'         => $row->{'filename'},
141                         'fpath'         => $row->{'filepath'},
142                         'networkpath'   => $row->{'networkpath'},
143                         'date'          => $row->{'date'},
144                         'type'          => $row->{'filetype'},
145                         'size'          => $row->{'size'},
146                         'id'            => $row->{'fid'},
147                         'dvd'           => $row->{'dvd'}
148                 });
149         }
150       
151         $sth->finish();
152         $dbh->disconnect();
153         return ($results, \@ret);
154 }
155
156 sub getBackupsNotBurned() {
157
158         my $dbh = DBI->connect($dsn, $db_user, "", { RaiseError => 1, AutoCommit => 1 } );
159         my $sql = q{ 
160         SELECT
161                 hosts.ID                AS hostid,
162                 min(hosts.name)         AS host,
163                 backups.num             AS backupno,
164                 min(backups.type)       AS type,
165                 min(backups.date)       AS date
166         FROM backups, shares, files, hosts
167         WHERE 
168                 backups.num     = files.backupNum       AND
169                 shares.ID       = files.shareID         AND         
170                 backups.hostID  = shares.hostID         AND
171                 hosts.ID        = backups.hostID        AND
172                 files.dvdid     IS NULL
173         GROUP BY 
174                 backups.hostID, backups.num, hosts.id
175         };
176         my $sth = $dbh->prepare( $sql );
177         my @ret;
178         $sth->execute();
179
180         while ( my $row = $sth->fetchrow_hashref() ) {      
181                 push(@ret, { 
182                          'host'     => $row->{'host'},
183                          'hostid'   => $row->{'hostid'},
184                          'backupno' => $row->{'backupno'},
185                          'type'     => $row->{'type'},
186                          'date'     => $row->{'date'}
187                        }
188                 );
189         }
190       
191         return @ret;      
192 }
193
194 sub displayBackupsGrid()
195   {
196       my $retHTML = "";
197       my $addForm = 1;
198       
199       if ($addForm) {
200
201             $retHTML .= <<EOF3;
202 <script language="javascript" type="text/javascript">
203 <!--
204
205     function checkAll(location)
206     {
207       for (var i=0;i<document.forma.elements.length;i++)
208       {
209         var e = document.forma.elements[i];
210         if ((e.checked || !e.checked) && e.name != \'all\') {
211             if (eval("document.forma."+location+".checked")) {
212                 e.checked = true;
213             } else {
214                 e.checked = false;
215             }
216         }
217       }
218     }
219 //-->
220 </script>      
221 EOF3
222               $retHTML .= q{<form name="forma" method="GET" action="}."$MyURL"."?action=burn\"";
223               $retHTML.= q{<input type="hidden" value="burn" name="action">};
224               $retHTML .= q{<input type="hidden" value="results" name="search_results">};
225         }
226         $retHTML .= qq{<table style="fview"><tr>};
227
228         if ($addForm) {
229             $retHTML .= "<td class=\"tableheader\"><input type=\"checkbox\" name=\"allFiles\" onClick=\"checkAll('allFiles');\"></td>";
230         }
231         $retHTML .=  qq{<td class="tableheader">Host</td><td class="tableheader">Backup no</td><td class="tableheader">Type</td><td class="tableheader">date</td></tr>};
232
233         my @backups = getBackupsNotBurned();
234         my $backup;
235
236         if ($addForm) {
237                 $retHTML .= qq{<tr><td colspan=7 style="tableheader">
238                         <input type="submit" value="Burn selected backups on medium" name="submitBurner">
239                         </td></tr>};
240         }
241
242         foreach $backup(@backups) {
243
244                 my $ftype = "";
245             
246                 $retHTML .= "<tr>";
247                 if ($addForm) {
248                         $retHTML .= qq{<td class="fview"><input type="checkbox" name="fcb} .
249                                 $backup->{'hostid'}."_".$backup->{'backupno'} . 
250                                 qq{" value="} . $backup->{'hostid'}."_".$backup->{'backupno'} .
251                                 qq{"></td>};
252                 }           
253             
254                 $retHTML .= '<td class="fviewborder">' . $backup->{'host'} . '</td>' .
255                         '<td class="fviewborder">' . $backup->{'backupno'} . '</td>' .
256                         '<td class="fviewborder">' . $backup->{'type'} . '</td>' .
257                         '<td class="fviewborder">' . epoch_to_iso( $backup->{'date'} ) . '<td>' .
258                         '</tr>';
259         }
260
261         $retHTML .= "</table>";
262
263         if ($addForm) {
264                 $retHTML .= "</form>";
265         }
266       
267         return $retHTML;
268 }      
269
270 sub displayGrid($$$$) {
271         my ($where, $addForm, $offset, $hilite) = @_;
272         my $retHTML = "";
273  
274         if ($addForm) {
275                 $retHTML .= qq{<form name="forma" method="GET" action="$MyURL">};
276                 $retHTML.= qq{<input type="hidden" value="search" name="action">};
277                 $retHTML .= qq{<input type="hidden" value="results" name="search_results">};
278         }
279
280         my ($results, $files) = getFiles($where, $offset);
281
282         my ($from, $to) = (($offset * $on_page) + 1, ($offset * $on_page) + $on_page);
283
284         $retHTML .= qq{
285         <br/>Found $results files, showing $from - $to
286         <table style="fview" width="100%">
287                 <tr> 
288                 <td class="tableheader">Share</td>
289                 <td class="tableheader">Name</td>
290                 <td class="tableheader">Type</td>
291                 <td class="tableheader">#</td>
292                 <td class="tableheader">Size</td>
293                 <td class="tableheader">Date</td>
294                 <td class="tableheader">Media</td>
295                 </tr>
296         };
297
298         my $file;
299
300         sub hilite_html($$) {
301                 my ($html, $search) = @_;
302                 $html =~ s#($search)#<b>$1</b>#gis;
303                 return $html;
304         }
305
306         sub restore_link($$$$$$) {
307                 my $type = shift;
308                 my $action = 'RestoreFile';
309                 $action = 'browse' if (lc($type) eq 'dir');
310                 return sprintf(qq{<a href="?action=%s&host=%s&num=%d&share=%s&dir=%s">%s</a>}, $action, @_);
311         }
312
313         foreach $file (@{ $files }) {
314                 my $typeStr  = BackupPC::Attrib::fileType2Text(undef, $file->{'type'});
315                 $retHTML .= "<tr>";
316
317                 foreach my $v ((
318                         $file->{'sharename'},
319                         qq{<img src="$Conf{CgiImageDirURL}/icon-$typeStr.gif" align="center">&nbsp;} . hilite_html( $file->{'fpath'}, $hilite ),
320                         $typeStr,
321                         restore_link( $typeStr, $file->{'hname'}, $file->{'backupno'}, $file->{'sname'}, $file->{'fpath'}, $file->{'backupno'} ),
322                         $file->{'size'},
323                         epoch_to_iso( $file->{'date'} ),
324                         $file->{'dvd'}
325                 )) {
326                         $retHTML .= qq{<td class="fviewborder">$v</td>};
327                 }
328
329                 $retHTML .= "</tr>";
330         }
331         $retHTML .= "</table>";
332
333         # all variables which has to be transfered
334         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/) {
335                 $retHTML .= qq{<INPUT TYPE="hidden" NAME="$n" VALUE="$In{$n}">\n};
336         }
337
338         my $del = '';
339         my $max_page = int( $results / $on_page );
340         my $page = 0;
341
342         my $link_fmt = '<a href = "#" onclick="document.forma.offset.value=%d;document.forma.submit();">%s</a>';
343
344         $retHTML .= '<div style="text-align: center;">';
345
346         if ($offset > 0) {
347                 $retHTML .= sprintf($link_fmt, $offset - 1, '&lt;&lt;') . ' ';
348         }
349
350         while ($page <= $max_page) {
351                 if ($page == $offset) {
352                         $retHTML .= $del . '<b>' . ($page + 1) . '</b>';
353                 } else {
354                         $retHTML .= $del . sprintf($link_fmt, $page, $page + 1);
355                 }
356
357                 if ($page < $offset - $pager_pages && $page != 0) {
358                         $retHTML .= " ... ";
359                         $page = $offset - $pager_pages;
360                         $del = '';
361                 } elsif ($page > $offset + $pager_pages && $page != $max_page) {
362                         $retHTML .= " ... ";
363                         $page = $max_page;
364                         $del = '';
365                 } else {
366                         $del = ' | ';
367                         $page++;
368                 }
369         }
370
371         if ($offset < $max_page) {
372                 $retHTML .= ' ' . sprintf($link_fmt, $offset + 1, '&gt;&gt;');
373         }
374
375         $retHTML .= "</div>";
376
377         $retHTML .= "</form>" if ($addForm);
378
379         return $retHTML;
380 }
381
382 1;