diff options
| author | Andreas Brachold <vdr07@deltab.de> | 2007-11-27 15:22:33 +0000 |
|---|---|---|
| committer | Andreas Brachold <vdr07@deltab.de> | 2007-11-27 15:22:33 +0000 |
| commit | 73ffd898650f6cb75d323cc438845a3aead1b110 (patch) | |
| tree | e92d68f9802fd2ae1e7479d0e02935ac350bb1bf /lib | |
| parent | aacaa350f7da7c154264897da26d15ff38df46bb (diff) | |
| download | xxv-73ffd898650f6cb75d323cc438845a3aead1b110.tar.gz xxv-73ffd898650f6cb75d323cc438845a3aead1b110.tar.bz2 | |
* Database: Change method of version control, use comment from table, instead use table 'VERSION'
* RECORDS: Use MD5 for mapping preview images
* RECORDS: Don't use 2nd try to generate preview images
* Handle field names from table now with special character, remove prior workaround
* TIMER: Search lookup also for description
* buildsearch: redesign avoid SQL-Injection
* AUTOTIMER: Speed up background scan, compare now only changed und added epg-events
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/Tools.pm | 110 | ||||
| -rw-r--r-- | lib/XXV/MODULES/AUTOTIMER.pm | 153 | ||||
| -rw-r--r-- | lib/XXV/MODULES/CHANNELS.pm | 17 | ||||
| -rw-r--r-- | lib/XXV/MODULES/CHRONICLE.pm | 65 | ||||
| -rw-r--r-- | lib/XXV/MODULES/CONFIG.pm | 11 | ||||
| -rw-r--r-- | lib/XXV/MODULES/EPG.pm | 134 | ||||
| -rw-r--r-- | lib/XXV/MODULES/MEDIALIB.pm | 16 | ||||
| -rw-r--r-- | lib/XXV/MODULES/MUSIC.pm | 121 | ||||
| -rw-r--r-- | lib/XXV/MODULES/RECORDS.pm | 124 | ||||
| -rw-r--r-- | lib/XXV/MODULES/TIMERS.pm | 102 | ||||
| -rw-r--r-- | lib/XXV/MODULES/USER.pm | 32 |
11 files changed, 516 insertions, 369 deletions
diff --git a/lib/Tools.pm b/lib/Tools.pm index d73c920..b8d65f0 100644 --- a/lib/Tools.pm +++ b/lib/Tools.pm @@ -22,8 +22,8 @@ our $LOGCALLB = sub{ }; our $DBH = {}; @EXPORT = qw(&datum &stackTrace &lg &event &debug &error &panic &rep2str &dumper &getFromSocket &fields - &load_file &save_file &tableExists &tableUpdated &buildsearch &deleteDir &getip &convert &int &entities &reentities &bench - &fmttime &getDataByTable &getDataById &getDataBySearch &getDataByFields ¨aute &touch); + &load_file &save_file &tableUpdated &buildsearch &deleteDir &getip &convert &int &entities &reentities &bench + &fmttime &getDataByTable &getDataById &getDataBySearch &getDataByFields &touch); # ------------------ @@ -229,7 +229,7 @@ sub tableExists { my $dbh = shift || return error('No database handle defined!'); my $name = shift || return error('No table defined!'); - my $erg = $dbh->selectall_arrayref('show tables'); + my $erg = $dbh->selectall_arrayref("show tables LIKE '$name'"); for(@$erg) { return 1 if($name eq $_->[0]); } @@ -237,17 +237,31 @@ sub tableExists { } # ------------------ +sub tableStatus { +# ------------------ + my $dbh = shift || return error('No database handle defined!'); + my $table = shift || return error('No table defined!'); + my $row = shift || return error('No row defined!'); + + my $erg = $dbh->selectrow_hashref("SHOW TABLE STATUS LIKE '$table'"); + if($erg and exists $erg->{$row}) { + return $erg->{$row}; + } + return 0; +} + +# ------------------ sub tableUpdated { # ------------------ my $dbh = shift || return error('No database handle defined!'); my $table = shift || return error('No table defined!'); - my $rows = shift || return error('No rows defined!'); + my $dbversion = shift || return error('No version of database defined!'); my $drop = shift || 0; # remove old Version, if updated
if(tableExists($dbh, $table)) {
- my $fields = fields($dbh, 'select * from '.$table);
- if(!$fields || scalar @$fields != $rows) { + my $tableversion = tableStatus($dbh, $table,'Comment'); + if(!$tableversion || $tableversion ne $dbversion) { if($drop) { lg sprintf('Remove old version from database table %s',$table);
$dbh->do(sprintf('drop table %s',$table)) @@ -256,13 +270,13 @@ sub tableUpdated { panic sprintf( q|------- !PROBLEM! ---------- Upps, you have a incompatible or corrupted database. -Table %s has %d. It's expected %d rows. +Table %s has version '%s'. It's expected version '%s'. Please check database e.g. with mysqlcheck --all-databases --fast --silent or use the script contrib/upgrade-xxv.sh to upgrade the database! ----------------------------|#' ,$table - ,$fields ? scalar @$fields : 0 - ,$rows); + ,$tableversion ? $tableversion : 0 + ,$dbversion); return 0; }
}
@@ -316,26 +330,33 @@ sub _buildsearchcomma { #-------------------------------------------------------- my ($queryField, $Search) = @_; + my $term; my $out; foreach my $su (split(/\s*,\s*/, $Search)) { -# $su =~ s/\./\\\\\./sg; - $su =~ s/\'/\\\\\'/sg; - $su =~ s/\"/\./sg; - $su =~ s/\+/\\\\\+/sg; - $su =~ s/\?/\\\\\?/sg; - $su =~ s/\(/\\\\\(/sg; - $su =~ s/\)/\\\\\)/sg; + $su =~ s/\./\\\./sg; +# $su =~ s/\'/\\\'/sg; +# $su =~ s/\"/\./sg; + $su =~ s/\*/\\\*/sg; + $su =~ s/\+/\\\+/sg; + $su =~ s/\?/\\\?/sg; + $su =~ s/\(/\\\(/sg; + $su =~ s/\)/\\\)/sg; $out .= ' AND ' if($out); if($su =~ s/^\-+//) { - $out .= qq| ($queryField NOT RLIKE "$su")|; + $out .= qq| ($queryField NOT RLIKE ?)|; + push(@$term,$su); } else { $su =~ s/^\&+//; #remove for backward compatibility - $out .= qq| ($queryField RLIKE "$su")|; + $out .= qq| ($queryField RLIKE ?)|; + push(@$term,$su); } } # dumper($out); - return $out; + return { + query => $out, + term => $term + }; } #-------------------------------------------------------- @@ -344,6 +365,7 @@ sub _buildsearchlogical { my ($queryField, $Search) = @_; my $out; + my $term; my $op = 1; $out = " ("; foreach my $su (split(/( AND NOT | OR | AND )/, $Search)) { @@ -360,22 +382,26 @@ sub _buildsearchlogical { } else { $out .= " AND" unless($op); -# $su =~ s/\./\\\\\./sg; - $su =~ s/\'/\\\\\'/sg; - $su =~ s/\"/\./sg; - $su =~ s/\+/\\\\\+/sg; - $su =~ s/\?/\\\\\?/sg; - $su =~ s/\(/\\\\\(/sg; - $su =~ s/\)/\\\\\)/sg; - - $out .= qq| ($queryField RLIKE "$su")|; - + $su =~ s/\./\\\./sg; +# $su =~ s/\'/\\\'/sg; +# $su =~ s/\"/\./sg; + $su =~ s/\*/\\\*/sg; + $su =~ s/\+/\\\+/sg; + $su =~ s/\?/\\\?/sg; + $su =~ s/\(/\\\(/sg; + $su =~ s/\)/\\\)/sg; + + $out .= qq| ($queryField RLIKE ?)|; + push(@$term,$su); $op = 0; } } $out .= " )"; # dumper($out); - return $out; + return { + query => $out, + term => $term + }; } @@ -384,7 +410,7 @@ sub buildsearch { #-------------------------------------------------------- my ($InFields, $Search) = @_; my @fields = split(/\s*,\s*/, $InFields); - my $queryField = scalar(@fields) > 1 ? qq|CONCAT_WS("~",$InFields)| : qq|$InFields|; + my $queryField = scalar(@fields) > 1 ? qq|CONCAT_WS(" ",$InFields)| : qq|$InFields|; if( grep(/ AND /, $Search) or grep(/ OR /, $Search) @@ -569,28 +595,6 @@ sub bench { } # ------------------ -sub umlaute { -# ------------------ - my $s = shift || return ""; - - my %uml = ( - 'Ä' => 'Ae', - 'Ö' => 'Oe', - 'Ü' => 'Ue', - 'ä' => 'ae', - 'ö' => 'oe', - 'ü' => 'ue', - 'ß' => 'sz' - ); - - my @uml = join("|", keys(%uml)); - - $s =~ s/(@uml)/$uml{$1}/eg; - - return $s; -} - -# ------------------ sub touch { # ------------------ my $file = shift; diff --git a/lib/XXV/MODULES/AUTOTIMER.pm b/lib/XXV/MODULES/AUTOTIMER.pm index f22c60a..04eafbb 100644 --- a/lib/XXV/MODULES/AUTOTIMER.pm +++ b/lib/XXV/MODULES/AUTOTIMER.pm @@ -250,14 +250,18 @@ sub _init { # ------------------ my $obj = shift || return error('No object defined!'); - return 0, panic("Session to database is'nt connected") - unless($obj->{dbh}); + unless($obj->{dbh}) { + panic("Session to database is'nt connected"); + return 0; + } + my $version = main::getDBVersion(); # don't remove old table, if updated rows => warn only - tableUpdated($obj->{dbh},'AUTOTIMER',19,0); + if(!tableUpdated($obj->{dbh},'AUTOTIMER',$version,0)) { + return 0; + } # Look for table or create this table - my $version = main::getVersion; $obj->{dbh}->do(qq| CREATE TABLE IF NOT EXISTS AUTOTIMER ( Id int(11) unsigned auto_increment NOT NULL, @@ -337,6 +341,33 @@ sub autotimer { my $vdrVersion = main::getVdrVersion(); + # Search only for event there added since last runtime. + # and search not with TEMPEPG at manual running + my $addtime = ((not ref $console) && ($obj->{addtime})) ? $obj->{addtime} : 0; + $obj->{addtime} = time unless($autotimerid); + + &bench('AUTOTIMER'); + if($addtime) { + + # Remove old data + $obj->{dbh}->do('DELETE FROM TEMPEPG'); + + # Copy only new events from EPG to TEMPEPG, to speed up search + my $sql = qq|INSERT INTO TEMPEPG SELECT e.* FROM EPG as e, CHANNELS as c + WHERE e.addtime >= FROM_UNIXTIME(?)|; + + # Exclude unwanted channels + if($obj->{exclude}) { + $sql .= sprintf(' AND ( e.channel_id = c.Id ) AND NOT (c.%s)', + $obj->{exclude}); + } + + my $sth = $obj->{dbh}->prepare($sql) + or return error sprintf("Couldn't prepare query: %s.",$sql); + $sth->execute($addtime) + or return error sprintf("Couldn't execute query: %s.",$sth->errstr); + } + # Get Timersmodule my $timermod = main::getModule('TIMERS'); foreach my $id (sort keys %$att) { @@ -351,7 +382,7 @@ sub autotimer { } # Build SQL Command and run it .... - my $events = $obj->_eventsearch($a, $timermod) || next; + my $events = $obj->_eventsearch($a, $timermod, $addtime ) || next; # Only search for one at? if(ref $console && $autotimerid) { @@ -474,6 +505,11 @@ sub autotimer { } } + &bench('AUTOTIMER'); + my $seconds = &bench()->{'AUTOTIMER'}; + lg sprintf("Runtime %s seconds", $seconds); + + $waiter->next(undef,undef,gettext('Read new timers into database.')) if(ref $waiter); @@ -986,39 +1022,43 @@ sub list { my $text = shift || ''; my $params = shift; - my $where = ''; - if($text =~ /^.*?/) { - if($text =~ /^[0-9]+?/) { - $where = "WHERE Id = '$text'"; - } elsif($text) { - $where = 'WHERE '.buildsearch("Search,Dir",$text); - } - } + my $term; + my $search = ''; + if($text and $text =~ /^[0-9,_ ]+$/ ) { + my @timers = split(/[^0-9]/, $text); + $search = sprintf(" WHERE Id in (%s)",join(',' => ('?') x @timers)); + foreach(@timers) { push(@{$term},$_); } + + } elsif($text) { + my $query = buildsearch("Search,Dir",$text); + $search = sprintf('WHERE %s', $query->{query}); + foreach(@{$query->{term}}) { push(@{$term},$_); } + } my %f = ( - 'Id' => umlaute(gettext('Service')), - 'Act' => umlaute(gettext('Act')), - 'Search' => umlaute(gettext('Search')), - 'Channels' => umlaute(gettext('Channels')), - 'Start' => umlaute(gettext('Start')), - 'Stop' => umlaute(gettext('Stop')), - 'Dir' => umlaute(gettext('Dir')), - 'Min' => umlaute(gettext('Min')), + 'Id' => gettext('Service'), + 'Activ' => gettext('Activ'), + 'Search' => gettext('Search'), + 'Channels' => gettext('Channels'), + 'Start' => gettext('Start'), + 'Stop' => gettext('Stop'), + 'Dir' => gettext('Directory'), + 'Min' => gettext('Minimum length'), ); my $sql = qq| SELECT SQL_CACHE - Id as $f{'Id'}, - Activ as $f{'Act'}, - Search as $f{'Search'}, - Channels as $f{'Channels'}, - Dir as $f{'Dir'}, - Start as $f{'Start'}, - Stop as $f{'Stop'}, - MinLength as $f{'Min'} + Id as \'$f{'Id'}\', + Activ as \'$f{'Activ'}\', + Search as \'$f{'Search'}\', + Channels as \'$f{'Channels'}\', + Dir as \'$f{'Dir'}\', + Start as \'$f{'Start'}\', + Stop as \'$f{'Stop'}\', + MinLength as \'$f{'Min'}\' FROM AUTOTIMER - $where + $search |; my $fields = fields($obj->{dbh}, $sql); @@ -1032,7 +1072,10 @@ sub list { else { $sql .= " asc"; } - my $erg = $obj->{dbh}->selectall_arrayref($sql); + my $sth = $obj->{dbh}->prepare($sql); + $sth->execute(@{$term}) + or return error sprintf("Couldn't execute query: %s.",$sth->errstr); + my $erg = $sth->fetchall_arrayref(); unshift(@$erg, $fields); my $channels = main::getModule('CHANNELS')->ChannelHash('Id'); @@ -1054,51 +1097,61 @@ sub _eventsearch { my $obj = shift || return error('No object defined!'); my $a = shift || return error('No data defined!'); my $timermod = shift || main::getModule('TIMERS') || return error ("Couldn't access modul TIMERS!"); + my $addtime = shift; # Searchstrings to Paragraphs Changed $a->{Search} =~ s/\:/\:\.\*/ if($a->{InFields} =~ /description/); - my $search = buildsearch($a->{InFields}, $a->{Search}); + my $query = buildsearch($a->{InFields}, $a->{Search}); + my $search = $query->{query}; + my $term = $query->{term}; # Start and Stop if($a->{Start} and $a->{Stop}) { if($a->{Start} > $a->{Stop}) { - $search .= "\n AND ((DATE_FORMAT(e.starttime, '%H%i') > $a->{Start} AND DATE_FORMAT(e.starttime, '%H%i') < 2359) OR (DATE_FORMAT(e.starttime, '%H%i') >= 0 and DATE_FORMAT(e.starttime, '%H%i') < $a->{Stop}))"; + $search .= "\n AND ((DATE_FORMAT(e.starttime, '%H%i') > ? AND DATE_FORMAT(e.starttime, '%H%i') < 2359) OR (DATE_FORMAT(e.starttime, '%H%i') >= 0 and DATE_FORMAT(e.starttime, '%H%i') < ?))"; } else { - $search .= "\n AND (DATE_FORMAT(e.starttime, '%H%i') > $a->{Start} AND DATE_FORMAT(e.starttime, '%H%i') < $a->{Stop})"; + $search .= "\n AND (DATE_FORMAT(e.starttime, '%H%i') > ? AND DATE_FORMAT(e.starttime, '%H%i') < ?)"; } + push(@{$term},$a->{Start}); + push(@{$term},$a->{Stop}); } # Min Length if(exists $a->{MinLength} and $a->{MinLength}) { - $search .= sprintf(" AND e.duration >= %d ", $a->{MinLength} * 60); + $search .= " AND e.duration >= ?"; + push(@{$term},$a->{MinLength} * 60); } # Channels if($a->{Channels} and my @channelids = split(',', $a->{Channels})) { - @channelids = map {$_ = "'$_'"} @channelids; - $search = sprintf(' %s AND channel_id in (%s)', $search, join(',', @channelids)); + $search .= sprintf(" AND channel_id in (%s)",join(',' => ('?') x @channelids)); + foreach(@channelids) { + push(@{$term},$_); + } } # Weekdays if($a->{Weekdays} and my @weekdays = split(',', $a->{Weekdays})) { if(scalar @weekdays != 7 and scalar @weekdays != 0) { - @weekdays = map {$_ = "'$_'"} @weekdays; - $search = sprintf(' %s AND DATE_FORMAT(e.starttime, \'%%a\') in (%s)', $search, join(',', @weekdays)); + $search .= sprintf(" AND DATE_FORMAT(e.starttime, \'%%a\') in (%s)",join(',' => ('?') x @weekdays)); + foreach(@weekdays) { + push(@{$term},$_); + } } } # Exclude channels, ifn't already lookup for channels - if($obj->{exclude} && not $a->{Channels}) { - $search = sprintf(' %s AND NOT (c.%s)', $search, $obj->{exclude}); + if($obj->{exclude} && not $a->{Channels} && not $addtime) { + $search .= sprintf(' AND NOT (c.%s)', $obj->{exclude}); } # Custom time range my $after = 0; my $prev = 0; # if($a->{VPS} ne 'y') { - if(defined $a->{prevminutes}) { + if(defined $a->{prevminutes}) { $prev = $a->{prevminutes} * 60; } else { $prev = $timermod->{prevminutes} * 60; @@ -1110,6 +1163,8 @@ sub _eventsearch { } # } + my $table = $addtime ? 'TEMPEPG' : 'EPG'; + # Search for events my $sql = qq| SELECT SQL_CACHE @@ -1120,23 +1175,25 @@ SELECT SQL_CACHE e.title as Title, e.subtitle as Subtitle, e.description as Summary, - DATE_FORMAT(FROM_UNIXTIME(UNIX_TIMESTAMP(e.starttime) - $prev ), '%d') as Day, - DATE_FORMAT(FROM_UNIXTIME(UNIX_TIMESTAMP(e.starttime) - $prev ), '%H%i') as Start, - DATE_FORMAT(FROM_UNIXTIME(UNIX_TIMESTAMP(e.starttime) + e.duration + $after ), '%H%i') as Stop, + DATE_FORMAT(FROM_UNIXTIME(UNIX_TIMESTAMP(e.starttime) - ? ), '%d') as Day, + DATE_FORMAT(FROM_UNIXTIME(UNIX_TIMESTAMP(e.starttime) - ? ), '%H%i') as Start, + DATE_FORMAT(FROM_UNIXTIME(UNIX_TIMESTAMP(e.starttime) + e.duration + ? ), '%H%i') as Stop, DATE_FORMAT(FROM_UNIXTIME(UNIX_TIMESTAMP(e.vpstime)), '%d') as VpsDay, DATE_FORMAT(FROM_UNIXTIME(UNIX_TIMESTAMP(e.vpstime)), '%H%i') as VpsStart, DATE_FORMAT(FROM_UNIXTIME(UNIX_TIMESTAMP(e.vpstime) + e.duration), '%H%i') as VpsStop FROM - EPG as e, + $table as e, CHANNELS as c WHERE ( $search ) AND ( e.channel_id = c.Id )|; #dumper $sql; - my $data = $obj->{dbh}->selectall_hashref($sql, 'eventid'); - return $data; + my $sth = $obj->{dbh}->prepare($sql); + $sth->execute($prev,$prev,$after,@{$term}) + or return error sprintf("Couldn't execute query: %s.",$sth->errstr); + return $sth->fetchall_hashref('eventid'); } # ------------------ diff --git a/lib/XXV/MODULES/CHANNELS.pm b/lib/XXV/MODULES/CHANNELS.pm index 1bab6a5..d2f7fe0 100644 --- a/lib/XXV/MODULES/CHANNELS.pm +++ b/lib/XXV/MODULES/CHANNELS.pm @@ -190,15 +190,20 @@ sub _init { # ------------------ my $obj = shift || return error('No object defined!'); - return 0, panic("Session to database is'nt connected") - unless($obj->{dbh}); + unless($obj->{dbh}) { + panic("Session to database is'nt connected"); + return 0; + } - # remove old table, if updated rows - tableUpdated($obj->{dbh},'CHANNELS',16,1); - tableUpdated($obj->{dbh},'CHANNELGROUPS',3,1); + my $version = 26; # Must be increment if rows of table changed + # this tables hasen't handmade user data, + # therefore old table could dropped if updated rows + if(!tableUpdated($obj->{dbh},'CHANNELS',$version,1) + || !tableUpdated($obj->{dbh},'CHANNELGROUPS',$version,1)) { + return 0; + } # Look for table or create this table - my $version = main::getVersion; $obj->{dbh}->do(qq| CREATE TABLE IF NOT EXISTS CHANNELS ( Id varchar(100) NOT NULL, diff --git a/lib/XXV/MODULES/CHRONICLE.pm b/lib/XXV/MODULES/CHRONICLE.pm index 8cfc1ae..a3c177d 100644 --- a/lib/XXV/MODULES/CHRONICLE.pm +++ b/lib/XXV/MODULES/CHRONICLE.pm @@ -92,14 +92,19 @@ sub _init { my $self = shift || return error('No object defined!'); if($self->{active} eq 'y') { - return 0, panic("Session to database is'nt connected") - unless($self->{dbh}); + unless($self->{dbh}) { + panic("Session to database is'nt connected"); + return 0; + } + + my $version = main::getDBVersion(); # don't remove old table, if updated rows => warn only - tableUpdated($self->{dbh},'CHRONICLE',6,0); + if(!tableUpdated($self->{dbh},'CHRONICLE',$version,0)) { + return 0; + } # Look for table or create this table - my $version = main::getVersion; $self->{dbh}->do(qq| CREATE TABLE IF NOT EXISTS CHRONICLE ( id int unsigned auto_increment not NULL, @@ -157,23 +162,23 @@ sub list { my $console = shift || return error('No console defined!'); my %f = ( - 'id' => umlaute(gettext('Service')), - 'title' => umlaute(gettext('Title')), - 'subtitle' => umlaute(gettext('Subtitle')), - 'channel' => umlaute(gettext('Channel')), - 'day' => umlaute(gettext('Day')), - 'start' => umlaute(gettext('Start')), - 'stop' => umlaute(gettext('Stop')) + 'id' => gettext('Service'), + 'title' => gettext('Title'), + 'subtitle' => gettext('Subtitle'), + 'channel' => gettext('Channel'), + 'day' => gettext('Day'), + 'start' => gettext('Start'), + 'stop' => gettext('Stop') ); my $sql = qq| SELECT SQL_CACHE - CHRONICLE.id as $f{'id'}, - CHRONICLE.title as $f{'title'}, - CHRONICLE.channel_id as $f{'channel'}, - DATE_FORMAT(CHRONICLE.starttime, '%d.%m.%Y') as $f{'day'}, - DATE_FORMAT(CHRONICLE.starttime, '%H:%i') as $f{'start'}, - DATE_FORMAT(FROM_UNIXTIME(UNIX_TIMESTAMP(CHRONICLE.starttime) + CHRONICLE.duration), '%H:%i') as $f{'stop'} + CHRONICLE.id as \'$f{'id'}\', + CHRONICLE.title as \'$f{'title'}\', + CHRONICLE.channel_id as \'$f{'channel'}\', + DATE_FORMAT(CHRONICLE.starttime, '%d.%m.%Y') as \'$f{'day'}\', + DATE_FORMAT(CHRONICLE.starttime, '%H:%i') as \'$f{'start'}\', + DATE_FORMAT(FROM_UNIXTIME(UNIX_TIMESTAMP(CHRONICLE.starttime) + CHRONICLE.duration), '%H:%i') as \'$f{'stop'}\' FROM CHRONICLE ORDER BY CHRONICLE.starttime |; @@ -197,23 +202,23 @@ sub search { $quest =~ s/\+/\\\\\+/sg; my %f = ( - 'id' => umlaute(gettext('Service')), - 'title' => umlaute(gettext('Title')), - 'subtitle' => umlaute(gettext('Subtitle')), - 'channel' => umlaute(gettext('Channel')), - 'day' => umlaute(gettext('Day')), - 'start' => umlaute(gettext('Start')), - 'stop' => umlaute(gettext('Stop')) + 'id' => gettext('Service'), + 'title' => gettext('Title'), + 'subtitle' => gettext('Subtitle'), + 'channel' => gettext('Channel'), + 'day' => gettext('Day'), + 'start' => gettext('Start'), + 'stop' => gettext('Stop') ); my $sql = qq| SELECT SQL_CACHE - CHRONICLE.id as $f{'id'}, - CHRONICLE.title as $f{'title'}, - CHRONICLE.channel_id as $f{'channel'}, - DATE_FORMAT(CHRONICLE.starttime, '%d.%m.%Y') as $f{'day'}, - DATE_FORMAT(CHRONICLE.starttime, '%H:%i') as $f{'start'}, - DATE_FORMAT(FROM_UNIXTIME(UNIX_TIMESTAMP(CHRONICLE.starttime) + CHRONICLE.duration), '%H:%i') as $f{'stop'} + CHRONICLE.id as \'$f{'id'}\', + CHRONICLE.title as \'$f{'title'}\', + CHRONICLE.channel_id as \'$f{'channel'}\', + DATE_FORMAT(CHRONICLE.starttime, '%d.%m.%Y') as \'$f{'day'}\', + DATE_FORMAT(CHRONICLE.starttime, '%H:%i') as \'$f{'start'}\', + DATE_FORMAT(FROM_UNIXTIME(UNIX_TIMESTAMP(CHRONICLE.starttime) + CHRONICLE.duration), '%H:%i') as \'$f{'stop'}\' FROM CHRONICLE WHERE CHRONICLE.title RLIKE ? ORDER BY CHRONICLE.starttime diff --git a/lib/XXV/MODULES/CONFIG.pm b/lib/XXV/MODULES/CONFIG.pm index 213cd6d..993abeb 100644 --- a/lib/XXV/MODULES/CONFIG.pm +++ b/lib/XXV/MODULES/CONFIG.pm @@ -108,7 +108,8 @@ sub menu { my $mods = main::getModules; foreach my $module (sort keys %{$mods}) { my $name = $mods->{$module}->{MOD}->{Name}; - next unless(exists $obj->{config}->{$name}); + error(sprintf("Missing real modul name %s",$module)) unless($name); + next unless($name && exists $obj->{config}->{$name}); $ret->{links}->{$name} = { text => $name, @@ -331,8 +332,12 @@ sub usage { # Search for command and display the Description foreach my $modName (sort keys %{$mods}) { my $modCfg = $mods->{$modName}->{MOD}; - push(@realModName, $mods->{$modName}->{MOD}->{Name}); - next if($modulename and uc($modulename) ne $modCfg->{Name}); + + my $name = $modCfg->{Name}; + error(sprintf("Missing real modul name %s",$modName)) unless($name); + push(@realModName, $name) if($name); + + next if($modulename and uc($modulename) ne $name); foreach my $cmdName (sort keys %{$modCfg->{Commands}}) { push(@$ret, [ diff --git a/lib/XXV/MODULES/EPG.pm b/lib/XXV/MODULES/EPG.pm index 440c629..ed0319c 100644 --- a/lib/XXV/MODULES/EPG.pm +++ b/lib/XXV/MODULES/EPG.pm @@ -197,18 +197,29 @@ sub _init { # ------------------ my $obj = shift || return error('No object defined!'); - return 0, panic("Session to database is'nt connected") - unless($obj->{dbh}); + unless($obj->{dbh}) { + panic("Session to database is'nt connected"); + return 0; + } + + my $version = 26; # Must be increment if rows of table changed + # this tables hasen't handmade user data, + # therefore old table could dropped if updated rows # Look for table or create this table - foreach my $table (qw/EPG OLDEPG/) { + foreach my $table (qw/EPG OLDEPG TEMPEPG/) { - # remove old table, if updated rows - tableUpdated($obj->{dbh},$table,14,1); + # remove old table, if updated version + if(!tableUpdated($obj->{dbh},$table,$version,1)) { + return 0; + } + + # Create TEMPEPG as temporary table, + # which only used inside AUTOTIMER and dropped at shutdown + my $temp = $table eq 'TEMPEPG' ? 'TEMPORARY' : ''; - my $version = main::getVersion; $obj->{dbh}->do(qq| - CREATE TABLE IF NOT EXISTS $table ( + CREATE $temp TABLE IF NOT EXISTS $table ( eventid bigint unsigned NOT NULL default '0', title text NOT NULL default '', subtitle text default '', @@ -592,40 +603,35 @@ sub search { } } + my $erg = []; + if($search) { + # Channelsearch if($params->{channel}) { - $search .= ' AND ' - if($search); - $search .= sprintf('c.POS = %lu ', $params->{channel}); + $search->{query} .= ' AND c.POS = ?'; + push(@{$search->{term}},$params->{channel}); } # Videoformat search if($params->{Videoformat} && $params->{Videoformat} eq 'widescreen') { - $search .= ' AND ' - if($search); - $search .= 'e.video like "%%16:9%%" '; + $search->{query} .= ' AND e.video like "%%16:9%%"'; } # Audioformat search # XXX: Leider kann man an den Audioeintrag nicht richtig erkennnen # hab erst zu spät erkannt das diese Info aus dem tvm2vdr kommen ;( # if($params->{Audioformat} eq 'dts') { -# $search .= ' AND ' -# if($search); -# $search .= 'e.audio like "%%Digital%%" '; +# $search->{query} .= ' AND e.audio like "%%Digital%%"'; # } # MinLength search if($params->{MinLength}) { - $search .= ' AND ' - if($search); - $search .= sprintf('e.duration >= %d ', ($params->{MinLength}*60)); + $search->{query} .= ' AND e.duration >= ?'; + push(@{$search->{term}},($params->{MinLength}*60)); } - my $erg = []; - if($search) { - my $sql = qq| + my $sql = qq| SELECT SQL_CACHE e.eventid as Service, e.title as Title, @@ -642,14 +648,16 @@ sub search { CHANNELS as c where e.channel_id = c.Id - AND ( $search ) + AND ( $search->{query} ) order by starttime |; - #dumper($sql); my $fields = fields($obj->{dbh}, $sql); + my $sth = $obj->{dbh}->prepare($sql); + $sth->execute(@{$search->{term}}) + or return error sprintf("Couldn't execute query: %s.",$sth->errstr); + $erg = $sth->fetchall_arrayref(); - $erg = $obj->{dbh}->selectall_arrayref($sql); unshift(@$erg, $fields); } $console->table($erg, { @@ -730,14 +738,14 @@ sub display { } my %f = ( - 'Id' => umlaute(gettext('Service')), - 'Title' => umlaute(gettext('Title')), - 'Subtitle' => umlaute(gettext('Subtitle')), - 'Channel' => umlaute(gettext('Channel')), - 'Start' => umlaute(gettext('Start')), - 'Stop' => umlaute(gettext('Stop')), - 'Description' => umlaute(gettext('Description')), - 'Percent' => umlaute(gettext('Percent')), + 'Id' => gettext('Service'), + 'Title' => gettext('Title'), + 'Subtitle' => gettext('Subtitle'), + 'Channel' => gettext('Channel'), + 'Start' => gettext('Start'), + 'Stop' => gettext('Stop'), + 'Description' => gettext('Description'), + 'Percent' => gettext('Percent') ); my $fields; @@ -754,15 +762,15 @@ sub display { foreach my $table (qw/EPG OLDEPG/) { my $sql = qq| SELECT SQL_CACHE - e.eventid as $f{'Id'}, - e.title as $f{'Title'}, - e.subtitle as $f{'Subtitle'}, - $start as $f{'Start'}, - $stopp as $f{'Stop'}, - c.Name as $f{'Channel'}, - e.description as $f{'Description'}, + e.eventid as \'$f{'Id'}\', + e.title as \'$f{'Title'}\', + e.subtitle as \'$f{'Subtitle'}\', + $start as \'$f{'Start'}\', + $stopp as \'$f{'Stop'}\', + c.Name as \'$f{'Channel'}\', + e.description as \'$f{'Description'}\', e.image as __Image, - (unix_timestamp(e.starttime) + e.duration - unix_timestamp())/duration*100 as $f{'Percent'}, + (unix_timestamp(e.starttime) + e.duration - unix_timestamp())/duration*100 as \'$f{'Percent'}\', e.video as __Video, e.audio as __Audio, IF(e.vpstime!=0,$vps,'') as __VPS @@ -832,23 +840,23 @@ GROUP BY c.Id or return error sprintf("Couldn't execute query: %s.",$sthtemp->errstr); my %f = ( - 'Service' => umlaute(gettext('Service')), - 'Title' => umlaute(gettext('Title')), - 'Channel' => umlaute(gettext('Channel')), - 'Start' => umlaute(gettext('Start')), - 'Stop' => umlaute(gettext('Stop')) + 'Service' => gettext('Service'), + 'Title' => gettext('Title'), + 'Channel' => gettext('Channel'), + 'Start' => gettext('Start'), + 'Stop' => gettext('Stop') ); my $sql = qq| SELECT SQL_CACHE - e.eventid as $f{'Service'}, - e.title as $f{'Title'}, + e.eventid as \'$f{'Service'}\', + e.title as \'$f{'Title'}\', e.subtitle as __Subtitle, - c.Name as $f{'Channel'}, + c.Name as \'$f{'Channel'}\', c.POS as __POS, g.Name as __Channelgroup, - DATE_FORMAT(e.starttime, "%H:%i") as $f{'Start'}, - DATE_FORMAT(FROM_UNIXTIME(UNIX_TIMESTAMP(starttime) + e.duration), "%H:%i") as $f{'Stop'}, + DATE_FORMAT(e.starttime, "%H:%i") as \'$f{'Start'}\', + DATE_FORMAT(FROM_UNIXTIME(UNIX_TIMESTAMP(starttime) + e.duration), "%H:%i") as \'$f{'Stop'}\', e.description as __Description, 999 as __Percent, IF(e.vpstime!=0,DATE_FORMAT(e.vpstime, '%H:%i'),'') as __VPS @@ -906,26 +914,26 @@ sub runningNow { $zeit++; my %f = ( - 'Service' => umlaute(gettext('Service')), - 'Title' => umlaute(gettext('Title')), - 'Channel' => umlaute(gettext('Channel')), - 'Start' => umlaute(gettext('Start')), - 'Stop' => umlaute(gettext('Stop')), - 'Percent' => umlaute(gettext('Percent')), + 'Service' => gettext('Service'), + 'Title' => gettext('Title'), + 'Channel' => gettext('Channel'), + 'Start' => gettext('Start'), + 'Stop' => gettext('Stop'), + 'Percent' => gettext('Percent') ); my $sql = qq| SELECT SQL_CACHE - e.eventid as $f{'Service'}, - e.title as $f{'Title'}, + e.eventid as \'$f{'Service'}\', + e.title as \'$f{'Title'}\', e.subtitle as __Subtitle, - c.Name as $f{'Channel'}, + c.Name as \'$f{'Channel'}\', c.POS as __POS, g.Name as __Channelgroup, - DATE_FORMAT(e.starttime, "%H:%i") as $f{'Start'}, - DATE_FORMAT(FROM_UNIXTIME(UNIX_TIMESTAMP(starttime) + e.duration), "%H:%i") as $f{'Stop'}, + DATE_FORMAT(e.starttime, "%H:%i") as \'$f{'Start'}\', + DATE_FORMAT(FROM_UNIXTIME(UNIX_TIMESTAMP(starttime) + e.duration), "%H:%i") as \'$f{'Stop'}\', e.description as __Description, - (unix_timestamp(e.starttime) + e.duration - unix_timestamp())/e.duration*100 as $f{'Percent'}, + (unix_timestamp(e.starttime) + e.duration - unix_timestamp())/e.duration*100 as \'$f{'Percent'}\', IF(e.vpstime!=0,DATE_FORMAT(e.vpstime, '%H:%i'),'') as __VPS FROM EPG as e, CHANNELS as c, CHANNELGROUPS as g diff --git a/lib/XXV/MODULES/MEDIALIB.pm b/lib/XXV/MODULES/MEDIALIB.pm index b0f78f6..83d5593 100644 --- a/lib/XXV/MODULES/MEDIALIB.pm +++ b/lib/XXV/MODULES/MEDIALIB.pm @@ -193,16 +193,20 @@ sub _init { # ------------------ my $obj = shift || return error('No object defined!'); - return 0, panic("Session to database is'nt connected") - unless($obj->{dbh}); + unless($obj->{dbh}) { + panic("Session to database is'nt connected"); + return 0; + } + my $version = main::getDBVersion(); # don't remove old table, if updated rows => warn only - tableUpdated($obj->{dbh},'MEDIALIB_ACTORS',4,0); - tableUpdated($obj->{dbh},'MEDIALIB_VIDEODATA',33,0); - tableUpdated($obj->{dbh},'MEDIALIB_VIDEOGENRE',2,0); + if(!tableUpdated($obj->{dbh},'MEDIALIB_ACTORS',$version,0) + ||!tableUpdated($obj->{dbh},'MEDIALIB_VIDEODATA',$version,0) + ||!tableUpdated($obj->{dbh},'MEDIALIB_VIDEOGENRE',$version,0)) { + return 0; + } # Look for tables or create this tables - my $version = main::getVersion; $obj->{dbh}->do(qq| CREATE TABLE IF NOT EXISTS MEDIALIB_ACTORS ( name varchar(255) NOT NULL default '', diff --git a/lib/XXV/MODULES/MUSIC.pm b/lib/XXV/MODULES/MUSIC.pm index 3bfc3e9..424f27e 100644 --- a/lib/XXV/MODULES/MUSIC.pm +++ b/lib/XXV/MODULES/MUSIC.pm @@ -280,11 +280,18 @@ sub _init { ); unless($obj->{mdbh}) { - # Look for table or create this table - my $version = main::getVersion; - # don't remove old table, if updated rows => warn only - tableUpdated($obj->{dbh},'MUSIC',12,0); + unless($obj->{dbh}) { + panic("Session to database is'nt connected"); + return 0; + } + + my $version = 26; # Must be increment if rows of table changed + # this tables hasen't handmade user data, + # therefore old table could dropped if updated rows + if(!tableUpdated($obj->{dbh},'MUSIC',$version,1)) { + return 0; + } $obj->{dbh}->do(qq| CREATE TABLE IF NOT EXISTS MUSIC ( @@ -527,7 +534,7 @@ sub list { my $obj = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); - my $search = shift; + my $param = shift; my $dbh = ($obj->{mdbh} ? $obj->{mdbh} : $obj->{dbh}); return 0 @@ -537,17 +544,17 @@ sub list { $obj->{GENRES} = $dbh->selectall_hashref('SELECT SQL_CACHE * from genre', 'id') if($obj->{mdbh} && !$obj->{GENRES}); - if($obj->{mdbh} && ! $search) { + if($obj->{mdbh} && ! $param) { my $eg = $dbh->selectrow_arrayref('SELECT SQL_CACHE title from album limit 1') || return $console->err($obj->{mdbh}->errstr); - $search = sprintf('album:%s', $eg->[0]); - } elsif(! $search) { + $param = sprintf('album:%s', $eg->[0]); + } elsif(! $param) { my $eg = $dbh->selectrow_arrayref('SELECT SQL_CACHE ALBUM from MUSIC limit 1') || return $console->err($dbh->errstr); - $search = sprintf('album:%s', $eg->[0]); + $param = sprintf('album:%s', $eg->[0]); } - my @field = split(':',$search); + my @field = split(':',$param); my $typ = $field[0]; # Muggleübersetzer ;) @@ -574,29 +581,36 @@ sub list { $t = ($obj->{mdbh} ? 'tracks.'.$translate->{$typ} : uc($typ)); } - my $where; + my $search = ''; + my $term; if($typ eq 'search') { if($obj->{mdbh}) { - $where = buildsearch("album.artist,tracks.artist,album.title,tracks.title,album.covertxt",$text); + my $query = buildsearch("album.artist,tracks.artist,album.title,tracks.title,album.covertxt",$text); + $search = $query->{query}; + foreach(@{$query->{term}}) { push(@{$term},$_); } + foreach(@{$query->{term}}) { push(@{$term},$_); } #double for UNION } else { - $where = buildsearch("ALBUM,ARTIST,TITLE,COMMENT",$text); + my $query = buildsearch("ALBUM,ARTIST,TITLE,COMMENT",$text); + $search = $query->{query}; + foreach(@{$query->{term}}) { push(@{$term},$_); } } } elsif($typ eq 'genre' && $obj->{mdbh}) { - $text =~ s/\'/\\'/sg;#' - $where = sprintf("%s LIKE '%s%%'", $t, $text); + $search = sprintf("%s LIKE ?", $t); #?% + push(@{$term},$text.'%'); } else { - $text =~ s/\'/\\'/sg;#' - $where = sprintf("%s LIKE '%%%s%%'", $t, $text); + $search = sprintf("%s RLIKE ?", $t); #%?% + push(@{$term},$text); + push(@{$term},$text) if($obj->{mdbh}); } my %f = ( - 'Id' => umlaute(gettext('Sv')), - 'Artist' => umlaute(gettext('Artist')), - 'Album' => umlaute(gettext('Album')), - 'Title' => umlaute(gettext('Title')), - 'Tracknum' => umlaute(gettext('Tracknum')), - 'Year' => umlaute(gettext('Year')), - 'Length' => umlaute(gettext('Length')), + 'Id' => gettext('Service'), + 'Artist' => gettext('Artist'), + 'Album' => gettext('Album'), + 'Title' => gettext('Title'), + 'Tracknum' => gettext('Number of track'), + 'Year' => gettext('Year'), + 'Length' => gettext('Length') ); my $sql; @@ -604,13 +618,13 @@ sub list { $sql = qq| SELECT SQL_CACHE - tracks.id as $f{'Id'}, - tracks.artist as $f{'Artist'}, - album.title as $f{'Album'}, - tracks.title as $f{'Title'}, - tracks.tracknb as $f{'Tracknum'}, - tracks.year as $f{'Year'}, - IF(tracks.length >= 3600,SEC_TO_TIME(tracks.length),DATE_FORMAT(FROM_UNIXTIME(tracks.length), '%i:%s')) as $f{'Length'}, + tracks.id as \'$f{'Id'}\', + tracks.artist as \'$f{'Artist'}\', + album.title as \'$f{'Album'}\', + tracks.title as \'$f{'Title'}\', + tracks.tracknb as \'$f{'Tracknum'}\', + tracks.year as \'$f{'Year'}\', + IF(tracks.length >= 3600,SEC_TO_TIME(tracks.length),DATE_FORMAT(FROM_UNIXTIME(tracks.length), '%i:%s')) as \'$f{'Length'}\', genre.genre as __GENRE, album.covertxt as __COMMENT FROM @@ -618,20 +632,20 @@ sub list { WHERE tracks.sourceid = album.cddbid and tracks.genre1 = genre.id and - ( $where ) + $search |; $sql .= qq| UNION SELECT SQL_CACHE - tracks.id as $f{'Id'}, - tracks.artist as $f{'Artist'}, - album.title as $f{'Album'}, - tracks.title as $f{'Title'}, - tracks.tracknb as $f{'Tracknum'}, - tracks.year as $f{'Year'}, - IF(tracks.length >= 3600,SEC_TO_TIME(tracks.length),DATE_FORMAT(FROM_UNIXTIME(tracks.length), '%i:%s')) as $f{'Length'}, + tracks.id as \'$f{'Id'}\', + tracks.artist as \'$f{'Artist'}\', + album.title as \'$f{'Album'}\', + tracks.title as \'$f{'Title'}\', + tracks.tracknb as \'$f{'Tracknum'}\', + tracks.year as \'$f{'Year'}\', + IF(tracks.length >= 3600,SEC_TO_TIME(tracks.length),DATE_FORMAT(FROM_UNIXTIME(tracks.length), '%i:%s')) as \'$f{'Length'}\', "" as __GENRE, album.covertxt as __COMMENT FROM @@ -639,41 +653,46 @@ sub list { WHERE tracks.sourceid = album.cddbid and tracks.genre1 = 'NULL' and - ( $where ) + $search + | if($typ ne 'genre'); $sql .= qq| ORDER BY - $f{'Album'}, - $f{'Tracknum'} + \'$f{'Album'}\', + \'$f{'Tracknum'}\' |; } else { $sql = qq| SELECT SQL_CACHE - ID as $f{'Id'}, - ARTIST as $f{'Artist'}, - ALBUM as $f{'Album'}, - TITLE as $f{'Title'}, - TRACKNUM as $f{'Tracknum'}, - YEAR as $f{'Year'}, - IF(SECS >= 3600,SEC_TO_TIME(SECS),DATE_FORMAT(FROM_UNIXTIME(SECS), '%i:%s')) as $f{'Length'}, + ID as \'$f{'Id'}\', + ARTIST as \'$f{'Artist'}\', + ALBUM as \'$f{'Album'}\', + TITLE as \'$f{'Title'}\', + TRACKNUM as \'$f{'Tracknum'}\', + YEAR as \'$f{'Year'}\', + IF(SECS >= 3600,SEC_TO_TIME(SECS),DATE_FORMAT(FROM_UNIXTIME(SECS), '%i:%s')) as \'$f{'Length'}\', GENRE as __GENRE, COMMENT as __COMMENT FROM MUSIC WHERE - ( $where ) + 1 AND + $search ORDER BY FILE |; } my $fields = fields($dbh, $sql); - my $erg = $dbh->selectall_arrayref($sql); + my $sth = $dbh->prepare($sql); + $sth->execute(@{$term}) + or return error sprintf("Couldn't execute query: %s.",$sth->errstr); + my $erg = $sth->fetchall_arrayref(); unshift(@$erg, $fields); my $params = { diff --git a/lib/XXV/MODULES/RECORDS.pm b/lib/XXV/MODULES/RECORDS.pm index 27c7893..792f832 100644 --- a/lib/XXV/MODULES/RECORDS.pm +++ b/lib/XXV/MODULES/RECORDS.pm @@ -22,6 +22,7 @@ sub module { Name => 'RECORDS', Prereq => { 'Time::Local' => 'efficiently compute time from local and GMT time ', + 'Digest::MD5 qw(md5_hex)' => 'Perl interface to the MD5 Algorithm' }, Description => gettext('This module manages recordings.'), Version => (split(/ /, '$Revision$'))[1], @@ -256,11 +257,14 @@ sub _init { return 0; } - # remove old table, if updated rows - tableUpdated($obj->{dbh},'RECORDS',11,1); + my $version = 26; # Must be increment if rows of table changed + # this tables hasen't handmade user data, + # therefore old table could dropped if updated rows + if(!tableUpdated($obj->{dbh},'RECORDS',$version,1)) { + return 0; + } # Look for table or create this table - my $version = main::getVersion; $obj->{dbh}->do(qq| CREATE TABLE IF NOT EXISTS RECORDS ( eventid bigint unsigned NOT NULL, @@ -387,7 +391,8 @@ sub readData { my $watcher = shift; my $console = shift; my $waiter = shift; - my $forceUpdate = shift; + # Read manual or Once at day, make full scan + my $forceUpdate = shift || ($obj->{countReading} % ( $obj->{fullreading} * 3600 / $obj->{interval} ) == 0); # Read recording over SVDRP my $lstr = $obj->{svdrp}->command('lstr'); @@ -424,7 +429,7 @@ sub readData { } - my @merkIds; + my @merkMD5; my $insertedData = 0; my $updatedState = 0; my $l = 0; @@ -439,8 +444,7 @@ sub readData { $obj->{FILES} = undef; my $db_data; - if($forceUpdate || $obj->{countReading} % ( $obj->{fullreading} * 3600 / $obj->{interval} ) == 0) { - # Once at day, make full scan + if($forceUpdate) { $obj->{dbh}->do('DELETE FROM RECORDS'); } else { # read database for compare with vdr data @@ -497,7 +501,7 @@ sub readData { $db_data->{$h}->{addtime} = time; # Make Preview and remove older Preview images - my $command = $obj->videoPreview( $db_data->{$h}->{eventid}, $db_data->{$h}, 1); + my $command = $obj->videoPreview( $db_data->{$h}, 1); push(@{$obj->{JOBS}}, $command) if($command && not grep(/\Q$command/g,@{$obj->{JOBS}})); } @@ -514,7 +518,7 @@ sub readData { $totalDuration += $db_data->{$h}->{duration}; $totalSpace += $db_data->{$h}->{FileSize}; - push(@merkIds,$db_data->{$h}->{eventid}); + push(@merkMD5,$db_data->{$h}->{RecordMD5}); # delete updated rows from hash delete $db_data->{$h}; @@ -536,7 +540,7 @@ sub readData { $totalSpace += $anahash->{FileSize}; if($obj->insert($anahash)) { - push(@merkIds,$anahash->{eventid}); + push(@merkMD5,$anahash->{RecordMD5}); $insertedData++; } else { push(@{$err},$anahash->{title}); @@ -558,9 +562,10 @@ sub readData { $sth->execute(@todel) or return error sprintf("Couldn't execute query: %s.",$sth->errstr); } - + + my $removedData = $db_data ? scalar keys %$db_data : 0; debug sprintf 'Finish .. %d recordings inserted, %d recordings updated, %d recordings removed', - $insertedData, $updatedState, $db_data ? scalar keys %$db_data : 0; + $insertedData, $updatedState, $removedData; error sprintf("Unsupported unit '%s' to calc free capacity",$freeUnit) unless($freeUnit eq 'MB'); @@ -595,19 +600,25 @@ sub readData { # alte PreviewDirs loeschen foreach my $dir (glob(sprintf('%s/*_shot', $obj->{previewimages}))) { - my $oldEventNumber = (split('/', $dir))[-1]; - unless(grep(sprintf('%lu_shot',$_) eq $oldEventNumber, @merkIds)) { + my $basedir = basename($dir); + unless(grep(sprintf('%s_shot',$_) eq $basedir, @merkMD5)) { + lg sprintf("Remove old preview files : '%s'",$dir); deleteDir($dir); } } - # Delete all old EPG entrys without the RecordIds which old as one day. - if(scalar @merkIds) { - my $sql = sprintf('DELETE FROM OLDEPG where (UNIX_TIMESTAMP(starttime) + duration) < (UNIX_TIMESTAMP() - 86400) and eventid not in (%s)', join(',' => ('?') x @merkIds)); - my $sth = $obj->{dbh}->prepare($sql); - $sth->execute(@merkIds) - or return error sprintf("Couldn't execute query: %s.",$sth->errstr); - } + # Delete all old EPG entrys + if($forceUpdate || $removedData) { + my $sqldeleteEvents = qq| +DELETE FROM OLDEPG + WHERE + (UNIX_TIMESTAMP(starttime) + duration) < (UNIX_TIMESTAMP() - 86400) + and eventid not in + ( SELECT eventid FROM RECORDS ) +|; + $obj->{dbh}->do($sqldeleteEvents) + or error sprintf("Couldn't execute query: %s, %s.",$sqldeleteEvents, $DBI::errstr); + } $obj->updated() if($insertedData); @@ -617,9 +628,9 @@ sub readData { if(ref $console) { $console->start() if(ref $waiter); if(scalar @{$err} == 0) { - $console->message(sprintf(gettext("Write %d recordings to the database."), scalar @merkIds)); + $console->message(sprintf(gettext("Write %d recordings to the database."), scalar @merkMD5)); } else { - unshift(@{$err}, sprintf(gettext("Write %d recordings to the database. Couldn't assign %d recordings."), scalar @merkIds , scalar @{$err})); + unshift(@{$err}, sprintf(gettext("Write %d recordings to the database. Couldn't assign %d recordings."), scalar @merkMD5 , scalar @{$err})); lg join("\n", @$err); $console->err($err); } @@ -681,7 +692,7 @@ sub insert { qq| REPLACE INTO RECORDS (eventid, RecordId, RecordMD5, Path, Prio, Lifetime, State, FileSize, Marks, Type ) - VALUES (?,?,md5(?),?,?,?,?,?,?,?) + VALUES (?,?,?,?,?,?,?,?,?,?) |); $attr->{Marks} = "" @@ -690,7 +701,7 @@ sub insert { return $sth->execute( $attr->{eventid}, $attr->{RecordId}, - $attr->{Path}, + $attr->{RecordMD5}, $attr->{Path}, $attr->{Prio}, $attr->{Lifetime}, @@ -785,11 +796,12 @@ sub analyze { } # Make Preview - my $command = $obj->videoPreview( $event->{eventid}, $info ); + my $command = $obj->videoPreview( $info ); push(@{$obj->{JOBS}}, $command) if($command && not grep(/\Q$command/g,@{$obj->{JOBS}})); my $ret = { + RecordMD5 => $info->{RecordMD5}, title => $recattr->{title}, RecordId => $recattr->{id}, Duration => $info->{duration}, @@ -918,6 +930,7 @@ sub videoInfo { } $status->{path} = $path; + $status->{RecordMD5} = md5_hex($path); } return $status; @@ -938,9 +951,8 @@ sub qquote { sub videoPreview { # ------------------ my $obj = shift || return error('No object defined!'); - my $eventid = shift || return error('No eventid defined!'); my $info = shift || return error ('No information defined!'); - my $rebuild = shift || 0; + my $rebuild = shift || 0; if ($obj->{previewcommand} eq 'Nothing') { return 0; @@ -958,7 +970,7 @@ sub videoPreview { # Save dir my $count = $obj->{previewcount}; - my $outdir = sprintf('%s/%lu_shot', $obj->{previewimages}, $eventid); + my $outdir = sprintf('%s/%s_shot', $obj->{previewimages}, $info->{RecordMD5}); # Stop here if enough files present my @images = glob("$outdir/*.jpg"); @@ -967,13 +979,10 @@ sub videoPreview { deleteDir($outdir) if(scalar @images && $rebuild); - # or stop if two log's present, use two logs avoid to early run on current live recording - my $log = sprintf('%s/preview_1st.log', $outdir); + # or stop if log's present + my $log = sprintf('%s/preview.log', $outdir); if(-e $log) { - $log = sprintf('%s/preview_2nd.log', $outdir); - if(-e $log) { return 0; - } } # Mplayer @@ -1218,7 +1227,7 @@ where $obj->_loadreccmds; my $param = { - previews => $obj->getPreviewFiles($rec->{eventid}), + previews => $obj->getPreviewFiles($rec->{RecordId}), reccmds => [@{$obj->{reccmds}}], }; @@ -1301,10 +1310,10 @@ AND ( } my %f = ( - 'Id' => umlaute(gettext('Service')), - 'Title' => umlaute(gettext('Title')), - 'Subtitle' => umlaute(gettext('Subtitle')), - 'Duration' => umlaute(gettext('Duration')), + 'Id' => gettext('Service'), + 'Title' => gettext('Title'), + 'Subtitle' => gettext('Subtitle'), + 'Duration' => gettext('Duration') ); my $start = "e.starttime"; @@ -1312,11 +1321,11 @@ AND ( my $sql = qq| SELECT SQL_CACHE - r.RecordMD5 as $f{'Id'}, + r.RecordMD5 as \'$f{'Id'}\', r.eventid as __EventId, - e.title as $f{'Title'}, - e.subtitle as $f{'Subtitle'}, - SUM(e.duration) as $f{'Duration'}, + e.title as \'$f{'Title'}\', + e.subtitle as \'$f{'Subtitle'}\', + SUM(e.duration) as \'$f{'Duration'}\', $start as __RecordStart, SUM(State) as __New, r.Type as __Type, @@ -1371,13 +1380,15 @@ sub search { my $text = shift || return $obj->list($watcher,$console); my $params = shift; - my $search = buildsearch("e.title,e.subtitle,e.description",$text); + my $query = buildsearch("e.title,e.subtitle,e.description",$text); + my $search = $query->{query}; + my $term = $query->{term}; my %f = ( - 'Id' => umlaute(gettext('Service')), - 'Title' => umlaute(gettext('Title')), - 'Subtitle' => umlaute(gettext('Subtitle')), - 'Duration' => umlaute(gettext('Duration')), + 'Id' => gettext('Service'), + 'Title' => gettext('Title'), + 'Subtitle' => gettext('Subtitle'), + 'Duration' => gettext('Duration') ); my $start = "e.starttime"; @@ -1385,11 +1396,11 @@ sub search { my $sql = qq| SELECT SQL_CACHE - r.RecordMD5 as $f{'Id'}, + r.RecordMD5 as \'$f{'Id'}\', r.eventid as __EventId, - e.title as $f{'Title'}, - e.subtitle as $f{'Subtitle'}, - e.duration as $f{'Duration'}, + e.title as \'$f{'Title'}\', + e.subtitle as \'$f{'Subtitle'}\', + e.duration as \'$f{'Duration'}\', $start as __RecordStart , r.State as __New, r.Type as __Type, @@ -1416,7 +1427,10 @@ WHERE else { $sql .= " asc"; } - my $erg = $obj->{dbh}->selectall_arrayref($sql); + my $sth = $obj->{dbh}->prepare($sql); + $sth->execute(@{$term}) + or return error sprintf("Couldn't execute query: %s.",$sth->errstr); + my $erg = $sth->fetchall_arrayref(); unshift(@$erg, $fields); my $param = { @@ -2002,10 +2016,10 @@ sub IdToPath { sub getPreviewFiles { # ------------------ my $obj = shift || return error('No object defined!'); - my $id = shift || return error('No eventid defined!'); + my $md5 = shift || return error('No eventid defined!'); # look for pictures - my $outdir = sprintf('%s/%lu_shot', $obj->{previewimages}, $id); + my $outdir = sprintf('%s/%s_shot', $obj->{previewimages}, $md5); if(my @previews = glob("$outdir/[0-9]*.jpg")) { splice(@previews,$obj->{previewcount},scalar(@previews)) if(scalar(@previews) > $obj->{previewcount}); diff --git a/lib/XXV/MODULES/TIMERS.pm b/lib/XXV/MODULES/TIMERS.pm index 91e1f09..0db6457 100644 --- a/lib/XXV/MODULES/TIMERS.pm +++ b/lib/XXV/MODULES/TIMERS.pm @@ -360,14 +360,19 @@ sub _init { # ------------------ my $obj = shift || return error('No object defined!'); - return 0, panic("Session to database is'nt connected") - unless($obj->{dbh}); + unless($obj->{dbh}) { + panic("Session to database is'nt connected"); + return 0; + } - # remove old table, if updated rows - tableUpdated($obj->{dbh},'TIMERS',19,1); + my $version = 26; # Must be increment if rows of table changed + # this tables hasen't handmade user data, + # therefore old table could dropped if updated rows + if(!tableUpdated($obj->{dbh},'TIMERS',$version,1)) { + return 0; + } # Look for table or create this table - my $version = main::getVersion; $obj->{dbh}->do(qq| CREATE TABLE IF NOT EXISTS TIMERS ( Id int(11) unsigned NOT NULL, @@ -465,7 +470,7 @@ sub saveTimer { ], $pos); } - event sprintf('Save timer "%s" with id: "%d"', $data->{File}, $pos); + event sprintf('Save timer "%s" with id: "%d"', $data->{File}, $pos || 0); return $erg; } @@ -1064,35 +1069,48 @@ sub list { my $console = shift || return error('No console defined!'); my $text = shift || ''; - my $in = ''; - if($text and $text =~ /^[0-9,_ ]+$/ ) { - my @timers = split(/[^0-9]/, $text); - $in = sprintf("and t.Id in ( %s )",join(',',@timers)); - } elsif($text) { - $in = sprintf('and ( %s )', buildsearch("t.File,t.Summary",$text)); - } + my $term; + my $search1 = ''; + my $search2 = ''; + if($text and $text =~ /^[0-9,_ ]+$/ ) { + my @timers = split(/[^0-9]/, $text); + $search1 = sprintf(" AND t.Id in (%s)",join(',' => ('?') x @timers)); + foreach(@timers) { push(@{$term},$_); } + $search2 = sprintf(" AND t.Id in (%s)",join(',' => ('?') x @timers)); + foreach(@timers) { push(@{$term},$_); } + + } elsif($text) { + my $query1 = buildsearch("t.File,e.description",$text); + $search1 = sprintf('AND ( %s )', $query1->{query}); + foreach(@{$query1->{term}}) { push(@{$term},$_); } + + my $query2 = buildsearch("t.File",$text); + $search2 = sprintf('AND ( %s )', $query2->{query}); + foreach(@{$query2->{term}}) { push(@{$term},$_); } + } + my %f = ( - 'Id' => umlaute(gettext('Sv')), - 'Status' => umlaute(gettext('Status')), - 'Day' => umlaute(gettext('Day')), - 'Channel' => umlaute(gettext('Channel')), - 'Start' => umlaute(gettext('Start')), - 'Stop' => umlaute(gettext('Stop')), - 'Title' => umlaute(gettext('Title')), - 'Priority' => umlaute(gettext('Priority')), + 'Id' => gettext('Service'), + 'Status' => gettext('Status'), + 'Day' => gettext('Day'), + 'Channel' => gettext('Channel'), + 'Start' => gettext('Start'), + 'Stop' => gettext('Stop'), + 'Title' => gettext('Title'), + 'Priority' => gettext('Priority') ); my $sql = qq| SELECT SQL_CACHE - t.Id as $f{'Id'}, - t.Status as $f{'Status'}, - c.Name as $f{'Channel'}, + t.Id as \'$f{'Id'}\', + t.Status as \'$f{'Status'}\', + c.Name as \'$f{'Channel'}\', c.Pos as __Pos, - t.Day as $f{'Day'}, - DATE_FORMAT(t.NextStartTime, '%H:%i') as $f{'Start'}, - DATE_FORMAT(t.NextStopTime, '%H:%i') as $f{'Stop'}, - t.File as $f{'Title'}, - t.Priority as $f{'Priority'}, + t.Day as \'$f{'Day'}\', + DATE_FORMAT(t.NextStartTime, '%H:%i') as \'$f{'Start'}\', + DATE_FORMAT(t.NextStopTime, '%H:%i') as \'$f{'Stop'}\', + t.File as \'$f{'Title'}\', + t.Priority as \'$f{'Priority'}\', UNIX_TIMESTAMP(t.NextStartTime) as __Day, t.Collision as __Collision, t.eventid as __eventid, @@ -1106,20 +1124,20 @@ FROM WHERE t.ChannelID = c.Id and (t.eventid = e.eventid) - $in + $search1 UNION SELECT SQL_CACHE - t.Id as $f{'Id'}, - t.Status as $f{'Status'}, - c.Name as $f{'Channel'}, + t.Id as \'$f{'Id'}\', + t.Status as \'$f{'Status'}\', + c.Name as \'$f{'Channel'}\', c.Pos as __Pos, - t.Day as $f{'Day'}, - DATE_FORMAT(t.NextStartTime, '%H:%i') as $f{'Start'}, - DATE_FORMAT(t.NextStopTime, '%H:%i') as $f{'Stop'}, - t.File as $f{'Title'}, - t.Priority as $f{'Priority'}, + t.Day as \'$f{'Day'}\', + DATE_FORMAT(t.NextStartTime, '%H:%i') as \'$f{'Start'}\', + DATE_FORMAT(t.NextStopTime, '%H:%i') as \'$f{'Stop'}\', + t.File as \'$f{'Title'}\', + t.Priority as \'$f{'Priority'}\', UNIX_TIMESTAMP(t.NextStartTime) as __Day, t.Collision as __Collision, t.eventid as __eventid, @@ -1132,7 +1150,7 @@ FROM WHERE t.ChannelID = c.Id and (t.eventid = 0) - $in + $search2 ORDER BY __Day @@ -1140,8 +1158,12 @@ ORDER BY my $fields = fields($obj->{dbh}, $sql); - my $erg = $obj->{dbh}->selectall_arrayref($sql); + my $sth = $obj->{dbh}->prepare($sql); + $sth->execute(@{$term}) + or return error sprintf("Couldn't execute query: %s.",$sth->errstr); + my $erg = $sth->fetchall_arrayref(); unshift(@$erg, $fields); + $console->table($erg, { runningTimer => $obj->getRunningTimer, cards => $obj->{DVBCards}, diff --git a/lib/XXV/MODULES/USER.pm b/lib/XXV/MODULES/USER.pm index 5043828..52ebdf6 100644 --- a/lib/XXV/MODULES/USER.pm +++ b/lib/XXV/MODULES/USER.pm @@ -186,14 +186,18 @@ sub _init { # ------------------ my $obj = shift || return error('No object defined!'); - return 0, panic("Session to database is'nt connected") - unless($obj->{dbh}); + unless($obj->{dbh}) { + panic("Session to database is'nt connected"); + return 0; + } + my $version = main::getDBVersion(); # don't remove old table, if updated rows => warn only - tableUpdated($obj->{dbh},'USER',9,0); + if(!tableUpdated($obj->{dbh},'USER',$version,0)) { + return 0; + } # Look for table or create this table - my $version = main::getVersion; my $erg = $obj->{dbh}->do(qq| CREATE TABLE IF NOT EXISTS USER ( Id int(11) unsigned auto_increment NOT NULL, @@ -518,20 +522,20 @@ sub list { my $console = shift || return error('No console defined!'); my %f = ( - 'Id' => umlaute(gettext('Service')), - 'Name' => umlaute(gettext('Name')), - 'Level' => umlaute(gettext('Level')), - 'Prefs' => umlaute(gettext('Preferences')), - 'UserPrefs' => umlaute(gettext('UserPreferences')), + 'Id' => gettext('Service'), + 'Name' => gettext('Name'), + 'Level' => gettext('Level'), + 'Prefs' => gettext('Preferences'), + 'UserPrefs' => gettext('User preferences') ); my $sql = qq| SELECT SQL_CACHE - Id as $f{Id}, - Name as $f{Name}, - Level as $f{Level}, - Prefs as $f{Prefs}, - UserPrefs as $f{UserPrefs} + Id as \'$f{Id}\', + Name as \'$f{Name}\', + Level as \'$f{Level}\', + Prefs as \'$f{Prefs}\', + UserPrefs as \'$f{UserPrefs}\' from USER |; |
