diff options
| author | Andreas Brachold <vdr07@deltab.de> | 2008-01-01 18:08:52 +0000 |
|---|---|---|
| committer | Andreas Brachold <vdr07@deltab.de> | 2008-01-01 18:08:52 +0000 |
| commit | 8222d826a768795076a655fcc057a218b7f8e933 (patch) | |
| tree | d0ee5e644afb288ab61d1d86f3a6856b5a6e4fef /lib | |
| parent | 8d11e5ef702eb4e7a0448eb43d39f28c9670954e (diff) | |
| download | xxv-8222d826a768795076a655fcc057a218b7f8e933.tar.gz xxv-8222d826a768795076a655fcc057a218b7f8e933.tar.bz2 | |
* STREAM: Add HTTPD Streaming for recording, with starttime
* RECORDS: Start playback with start time
* TIMERS: drop workaround getOldDeactivTimer - 'Search for old and deactivated Timers and delete this'
cleanup etc/xxvd.cfg.example, skin.cfg
rdisplay: add input field for start time
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/Tools.pm | 50 | ||||
| -rw-r--r-- | lib/XXV/MODULES/CHANNELS.pm | 16 | ||||
| -rw-r--r-- | lib/XXV/MODULES/HTTPD.pm | 3 | ||||
| -rw-r--r-- | lib/XXV/MODULES/RECORDS.pm | 76 | ||||
| -rw-r--r-- | lib/XXV/MODULES/STREAM.pm | 144 | ||||
| -rw-r--r-- | lib/XXV/MODULES/TIMERS.pm | 43 | ||||
| -rw-r--r-- | lib/XXV/OUTPUT/Html.pm | 146 |
7 files changed, 348 insertions, 130 deletions
diff --git a/lib/Tools.pm b/lib/Tools.pm index a588f53..6e2072d 100644 --- a/lib/Tools.pm +++ b/lib/Tools.pm @@ -26,7 +26,7 @@ our $DBH = {}; &getFromSocket &fields &load_file &save_file &tableUpdated &buildsearch &deleteDir &getip &convert &int &entities &reentities &bench &fmttime &getDataByTable &getDataById &getDataBySearch &getDataByFields &touch &url - &con_err &con_msg); + &con_err &con_msg &text2frame &frame2hms); # ------------------ @@ -667,4 +667,52 @@ sub url{ return $s; } +################################################################################ +# Convert text to frame number +# in => frame / HH:MM:SS.FF / HH:MM:SS / MM:SS.FF / MM:SS +# out => frame +sub text2frame() { + my $s = shift; + + my $start = 0; + if($s =~ /^\d+$/sig) { + $start = $s; + } elsif($s =~ /^\d+\:\d+\:\d+\.\d+$/sg) { + my ($hour,$minute,$seconds,$frames) = $s =~ /(\d+)\:(\d+)\:(\d+)\.(\d+)/s; + $start = ($hour * 3600) + ($minute * 60) + $seconds; + $start *= 25; + $start += $frames; + } elsif($s =~ /^\d+\:\d+\:\d+$/sg) { + my ($hour,$minute,$seconds) = $s =~ /(\d+)\:(\d+)\:(\d+)/s; + $start = ($hour * 3600) + ($minute * 60) + $seconds; + $start *= 25; + } elsif($s =~ /^\d+\:\d+\.\d+$/sg) { + my ($minute,$seconds,$frames) = $s =~ /(\d+)\:(\d+)\.(\d+)/s; + $start = ($minute * 60) + $seconds; + $start *= 25; + $start += $frames; + } elsif($s =~ /^\d+\:\d+$/sg) { + my ($minute,$seconds) = $s =~ /(\d+)\:(\d+)/s; + $start = ($minute * 60) + $seconds; + $start *= 25; + } + return $start; +} + +################################################################################ +# Convert frame number to HMS Text +# in => frame +# out => HH:MM:SS.FF +sub frame2hms() { + my $frames = shift; + + my $frame = $frames % 25; + my $time = $frames / 25; + my $sec = $time % 60; + my $min = ($time / 60) % 60; + my $hour = CORE::int($time/3600); + + return sprintf('%d:%02d:%02d.%02d', $hour, $min, $sec, $frame); +} + 1; diff --git a/lib/XXV/MODULES/CHANNELS.pm b/lib/XXV/MODULES/CHANNELS.pm index e150eef..f1e4464 100644 --- a/lib/XXV/MODULES/CHANNELS.pm +++ b/lib/XXV/MODULES/CHANNELS.pm @@ -583,7 +583,21 @@ sub ChannelToPos { return $erg ? $erg->{POS} : undef; } - +# ------------------ +sub ToCID { +# ------------------ + my $obj = shift || return error('No object defined!'); + my $text = shift || return undef; + + if($text =~ /^\d+$/ and (my $pch = $obj->PosToChannel($text) )) { + return $pch; + } elsif((my $nch = $obj->NameToChannel($text) )) { + return $nch; + } elsif(my $name = $obj->ChannelToName($text)) { + return $text; + } + return undef; +} # ------------------ sub getChannelType { # ------------------ diff --git a/lib/XXV/MODULES/HTTPD.pm b/lib/XXV/MODULES/HTTPD.pm index 22f31b1..26fb07c 100644 --- a/lib/XXV/MODULES/HTTPD.pm +++ b/lib/XXV/MODULES/HTTPD.pm @@ -20,6 +20,9 @@ my $mime = { ico => "image/x-icon", js => "application/x-javascript", m3u => "audio/x-mpegurl", + mp3 => "audio/x-mp3", + wav => "audio/x-wav", + ogg => "application/x-ogg", rss => "application/xhtml+xml", avi => "video/avi", mp4 => "video/mp4", diff --git a/lib/XXV/MODULES/RECORDS.pm b/lib/XXV/MODULES/RECORDS.pm index b66fbe3..0b447d3 100644 --- a/lib/XXV/MODULES/RECORDS.pm +++ b/lib/XXV/MODULES/RECORDS.pm @@ -1396,8 +1396,10 @@ sub play { my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); my $recordid = shift || return con_err($console,gettext("No recording defined for playback! Please use rplay 'rid'.")); + my $params = shift; - my $sql = qq|SELECT SQL_CACHE RecordID,RecordMD5 FROM RECORDS WHERE RecordMD5 = ?|; + my $sql = qq|SELECT SQL_CACHE r.RecordID,r.RecordMD5,e.duration as duration FROM + RECORDS as r, OLDEPG as e WHERE e.eventid = r.eventid and r.RecordMD5 = ?|; my $sth = $obj->{dbh}->prepare($sql); my $rec; if(!$sth->execute($recordid) @@ -1405,7 +1407,22 @@ sub play { return con_err($console,sprintf(gettext("Recording '%s' does not exist in the database!"),$recordid)); } - my $cmd = sprintf('PLAY %d begin', $rec->{RecordID}); + my $start = 0; + if($params && exists $params->{start}) { + $start = &text2frame($params->{start}); + } + if($start) { + if($start < 0 or ($start / 25) >= ($rec->{duration})) { + $start = 'begin'; + } else { + $start = &frame2hms($start); + } + } else { + $start = 'begin'; + } + + + my $cmd = sprintf('PLAY %d %s', $rec->{RecordID}, $start); if($obj->{svdrp}->scommand($watcher, $console, $cmd)) { $console->redirect({url => sprintf('?cmd=rdisplay&data=%s',$rec->{RecordMD5}), wait => 1}) @@ -2020,7 +2037,11 @@ sub conv { unless($data) { con_err($console,gettext("Please use rconvert 'cmdid_rid'")); - unshift(@{$obj->{reccmds}}, ['Descr.', 'Command']); + unshift(@{$obj->{reccmds}}, + [ + gettext('Description'), + gettext('Command') + ]); $console->table($obj->{reccmds}); $obj->list($watcher, $console); } @@ -2453,4 +2474,53 @@ sub recover { return 1; } +################################################################################ +# find file and offset from frame +sub frametofile { + my $obj = shift || return error('No object defined!'); + my $path = shift || return error ('Missing path from recording!' ); + my $frame = int (shift); + + use constant FRAMESTRUCTSIZE => 8; + + my $f = sprintf("%s/index.vdr", $path); + unless(open FH,$f) { + error(sprintf("Can't open file '%s': %s",$f,$!)); + return (undef,undef); + } + binmode FH; + + my $offset = FRAMESTRUCTSIZE * $frame; + if($offset != sysseek(FH,$offset,0)) { #SEEK_SET + error(sprintf("Can't seek file '%s': %s",$f,$!)); + close FH; + return (undef,undef); + } + + do { + my $buffer; + my $bytesread = sysread (FH, $buffer, FRAMESTRUCTSIZE); + if($bytesread != FRAMESTRUCTSIZE) { + error(sprintf("Can't read file '%s': %s",$f,$!)); + return (undef,undef); + } + my ($c, $t, $n, $r) = unpack ("I C C S", $buffer); + if($t == 1) { # I-Frame + close FH; + return ($n,$c); # Filenumber, Offset from file begin + } + + $offset -= FRAMESTRUCTSIZE; + if($offset != sysseek(FH,-(FRAMESTRUCTSIZE*2), 1)) { #SEEK_CUR + error(sprintf("Can't seek file '%s': %s",$f,$!)); + close FH; + return (undef,undef); + } + $frame -= 1; + } while($frame >= 0 && $offset >= 0); + + close FH; + + return (undef,undef); +} 1; diff --git a/lib/XXV/MODULES/STREAM.pm b/lib/XXV/MODULES/STREAM.pm index 7a836f2..2267017 100644 --- a/lib/XXV/MODULES/STREAM.pm +++ b/lib/XXV/MODULES/STREAM.pm @@ -6,6 +6,7 @@ use Locale::gettext; use File::Basename; use File::Find; use File::Path; +use File::Glob ':glob'; $SIG{CHLD} = 'IGNORE'; @@ -31,8 +32,29 @@ sub module { type => 'host', required => gettext('This is required!'), }, + streamtyp => { + description => gettext('Typ of streaming'), + default => 1, + type => 'list', + choices => sub { + my $erg = $obj->_get_streamtyp(); + map { my $x = $_->[1]; $_->[1] = $_->[0]; $_->[0] = $x; } @$erg; + return @$erg; + }, + required => gettext('This is required!'), + check => sub { + my $value = int(shift) || 0; + my $erg = $obj->_get_streamtyp(); + unless($value >= $erg->[0]->[0] and $value <= $erg->[-1]->[0]) { + return undef, + sprintf(gettext('Sorry, but value must be between %d and %d'), + $erg->[0]->[0],$erg->[-1]->[0]); + } + return $value; + }, + }, netvideo => { - description => gettext('Path from remote video directory (SambaDir).'), + description => gettext('Base directory of remote SMB/NFS share.'), default => '\\\\vdr\\video', type => 'string', }, @@ -44,16 +66,16 @@ sub module { }, Commands => { playrecord => { - description => gettext("Play recordings via samba or NFS."), + description => gettext("Stream a recordings."), short => 'pre', - callback => sub{ $obj->play_record(@_) }, + callback => sub{ $obj->playrecord(@_) }, DenyClass => 'stream', binary => 'nocache' }, livestream => { description => gettext("Stream a channel 'cid'. This required the streamdev plugin!"), short => 'lst', - callback => sub{ $obj->live_stream(@_) }, + callback => sub{ $obj->livestream(@_) }, DenyClass => 'stream', binary => 'nocache' }, @@ -103,76 +125,118 @@ sub init { # ------------------ -sub live_stream { +sub livestream { # ------------------ 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 $channel = shift || return $console->err(gettext("No ChannelID to Stream! Please use livestream 'cid'")); + my $channel = shift || return con_err($console,gettext("No channel defined for streaming!")); + + return $console->err(gettext("Can't stream files!")) + unless($console->can('datei')); + + my $cmod = main::getModule('CHANNELS'); - debug sprintf('Call live stream with channel "%s"%s', - $channel, + my $ch = $cmod->ToCID($channel); + return $console->err(sprintf(gettext("This channel '%s' does not exist!"),$channel)) + unless($ch); + + my $cpos = $cmod->ChannelToPos($ch); + debug sprintf('Live stream with channel "%s"%s', + $cmod->ChannelToName($ch), ( $console->{USER} && $console->{USER}->{Name} ? sprintf(' from user: %s', $console->{USER}->{Name}) : "" ) ); - if($channel && $console->typ eq 'HTML') { - $console->{nopack} = 1; - - my $data; - $data = "#EXTM3U\r\n"; - $data .= sprintf("http://%s:3000/PES/%d", $obj->{host}, $channel); - $data .= "\r\n"; - - my $arg; - $arg->{'attachment'} = sprintf("livestream%d.m3u", $channel); - $arg->{'Content-Length'} = length($data); + $console->{nopack} = 1; - $console->out($data, $obj->{mimetyp}, %{$arg} ); - } else { - $console->err(gettext("Sorry, this stream is not supported!")); - } + my $data; + $data = "#EXTM3U\r\n"; + $data .= sprintf("http://%s:3000/PES/%d", $obj->{host}, $cpos); + $data .= "\r\n"; + + my $arg; + $arg->{'attachment'} = sprintf("livestream-%s.m3u", $ch); + $arg->{'Content-Length'} = length($data); + + return $console->out($data, $obj->{mimetyp}, %{$arg} ); } # ------------------ -sub play_record { +sub playrecord { # ------------------ 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 $recid = shift || return $console->err(gettext("No RecordID to Play! Please use rplay 'rid'")); + my $recid = shift || return $console->err(gettext("No recording defined for streaming!")); + my $params = shift; my $rmod = main::getModule('RECORDS'); my $videopath = $rmod->{videodir}; my $path = $rmod->IdToPath($recid) or return $console->err(gettext(sprintf("Couldn't find recording: '%s'", $recid))); - debug sprintf('Call play record "%s"%s', + my @files = bsd_glob("$path/[0-9][0-9][0-9].vdr"); + + return $console->err(gettext(sprintf("Couldn't find recording: '%s'", $recid))) + unless scalar(@files); + + my $start = 0; + my $offset = 0; + if($params && exists $params->{start}) { + $start = &text2frame($params->{start}); + } + if($start) { + my ($filenumber,$fileoffset) = $rmod->frametofile($path,$start); + splice(@files, 0, $filenumber-1) if($filenumber && ($filenumber - 1) > 0); + $offset = $fileoffset if($fileoffset && ($fileoffset - 1) > 0); + } + + debug sprintf('Play recording "%s"%s', $path, ( $console->{USER} && $console->{USER}->{Name} ? sprintf(' from user: %s', $console->{USER}->{Name}) : "" ) ); - my $data; - $data = "#EXTM3U\r\n"; - foreach my $file (glob("$path/???.vdr")) { + if($obj->{streamtyp} != 1) { + return $console->err(gettext("Can't stream files!")) + unless($console->can('stream')); + + return $console->stream(\@files, $obj->{mimetyp}, $offset); + + } else { + + return $console->err(gettext("Can't stream files!")) + unless($console->can('datei')); + + my $data; + $data = "#EXTM3U\r\n"; + foreach my $file (@files) { $file =~ s/^$videopath//si; $file =~ s/^[\/|\\]//si; my $URL = sprintf("%s/%s\r\n", $obj->{netvideo}, $file); $URL =~s/\//\\/g - if($URL =~ /^\\\\/sig # Samba \\host/xxx/yyy => \\host\xxx\yyy - || $URL =~ /^[a-z]\:[\/|\\]/sig); # Samba x:/xxx/yyy => x:\xxx\yyy + if($URL =~ /^\\\\/sig # Samba \\host/xxx/yyy => \\host\xxx\yyy + || $URL =~ /^[a-z]\:[\/|\\]/sig); # Samba x:/xxx/yyy => x:\xxx\yyy $data .= $URL; - } + } - if($data && $console->typ eq 'HTML') { - $console->{nopack} = 1; + $console->{nopack} = 1; - my $arg; - $arg->{'attachment'} = sprintf("%s.m3u", $recid); - $arg->{'Content-Length'} = length($data); + my $arg; + $arg->{'attachment'} = sprintf("%s.m3u", $recid); + $arg->{'Content-Length'} = length($data); - $console->out($data, $obj->{mimetyp}, %{$arg} ); - } else { - $console->err(gettext("Sorry, this stream is not supported!")); + return $console->out($data, $obj->{mimetyp}, %{$arg} ); } } + +# ------------------ +sub _get_streamtyp { +# ------------------ + my $obj = shift || return error('No object defined!'); + + return [ + [ 1, gettext('Remote SMB/NFS share') ], + [ 2, gettext('HTTP Streaming') ], + ]; +} 1; diff --git a/lib/XXV/MODULES/TIMERS.pm b/lib/XXV/MODULES/TIMERS.pm index 93b668f..981bafc 100644 --- a/lib/XXV/MODULES/TIMERS.pm +++ b/lib/XXV/MODULES/TIMERS.pm @@ -53,11 +53,6 @@ sub module { default => 1, type => 'integer', }, - deactive => { - description => gettext('Delete inactive timers after end time'), - default => 'n', - type => 'confirm', - }, usevpstime => { description => gettext('Use Programme Delivery Control (PDC) to control start time'), default => 'n', @@ -640,19 +635,14 @@ WHERE msg => gettext('Which channel should recorded'), req => gettext("This is required!"), check => sub{ - my $value = shift || return; + my $value = shift; + return undef, gettext("This is required!") + unless($value); - if(my $name = $mod->ChannelToName($value)) { - $timerData->{Channel} = $value; - return $value; - } elsif(my $ch = $mod->PosToChannel($value) || $mod->NameToChannel($value) ) { - $timerData->{Channel} = $value; - return $ch; - } elsif( ! $mod->NameToChannel($value)) { - return undef, sprintf(gettext("This channel '%s' does not exist!"),$value); - } else { - return undef, gettext("This is required!"); - } + my $ch = $mod->ToCID($value); + return undef, sprintf(gettext("This channel '%s' does not exist!"),$value) + unless($ch); + return $ch; }, }, 'Day' => { @@ -1022,10 +1012,6 @@ sub readData { my $watcher = shift; my $console = shift; - # Search for old and deactivated Timers and delete this - $obj->getOldDeactivTimer() - if($obj->{deactive} eq 'y'); - # Search for correct times $obj->getCheckTimer() if($obj->{adjust} eq 'y'); @@ -1275,21 +1261,6 @@ sub getNewTimers { } # ------------------ -sub getOldDeactivTimer { -# ------------------ - my $obj = shift || return error('No object defined!'); - my $sql = "SELECT SQL_CACHE Id from TIMERS where not (Status & 1) and UNIX_TIMESTAMP(NextStopTime) > UNIX_TIMESTAMP() + (60*60*24*28)"; - my $erg = $obj->{dbh}->selectall_hashref($sql, 'Id'); - - foreach my $t (reverse sort {$a <=> $b} keys %$erg) { - $obj->{svdrp}->queue_cmds("delt $t"); - } - $obj->{svdrp}->queue_cmds("CALL") - if($obj->{svdrp}->queue_cmds("COUNT")); - return $erg; -} - -# ------------------ sub getCheckTimer { # ------------------ my $obj = shift || return error('No object defined!'); diff --git a/lib/XXV/OUTPUT/Html.pm b/lib/XXV/OUTPUT/Html.pm index c0e1053..2d8d1bc 100644 --- a/lib/XXV/OUTPUT/Html.pm +++ b/lib/XXV/OUTPUT/Html.pm @@ -365,8 +365,8 @@ sub header { if($obj->{browser}->{accept_gzip} && ((!defined $obj->{nopack}) || $obj->{nopack} == 0) ); if(defined $obj->{nocache} && $obj->{nocache}) { - $arg->{'Cache-Control'} = 'no-cache, must-revalidate' if(!defined $arg->{'Cache-Control'}); - $arg->{'Pragma'} = 'no-cache' if(!defined $arg->{'Pragma'}); + $arg->{'Cache-Control'} = 'no-cache, must-revalidate' unless(defined $arg->{'Cache-Control'}); + $arg->{'Pragma'} = 'no-cache' unless(defined $arg->{'Pragma'}); } $obj->{header} = 200; @@ -610,18 +610,17 @@ sub datei { my %args = (); - return $obj->status404($file,$!) - if(!-r $file); - my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, - $atime,$mtime,$ctime,$blksize,$blocks) = stat $file; - return $obj->status404($file,$!) - if(!$blocks); + $atime,$mtime,$ctime,$blksize,$blocks) = stat($file); + unless($blocks and ($mode & 00400)) { + error sprintf("Couldn't stat file '%s' : %s",$file,$!); + return $obj->status404($file,$!); + } $typ = $obj->{mime}->{lc((split('\.', $file))[-1])} - if(!$typ); + unless($typ); $typ = "application/octet-stream" - if(!$typ); + unless($typ); $obj->{nopack} = 1 if($typ =~ /image\// || $typ =~ /video\//); @@ -642,40 +641,97 @@ sub datei { if($obj->{nopack}); if($size > (32768 * 16)) { ## Only files bigger then 512k + lg sprintf("stream file : '%s' (%s)",$file,convert($size)); + $obj->_stream([$file],$size, 0, $typ, %args); + } else { + my $data = load_file($file) || ''; + # send data + $obj->out($data, $typ, %args ); + } +} - lg sprintf("stream file : '%s' (%s)",$file,convert($size)); - - $obj->{nopack} = 1; - my $handle = $obj->{handle}; +# ------------------ +sub stream { +# ------------------ + my $obj = shift || return error('No object defined!'); + my $files = shift || return error('No file defined!'); + my $typ = shift; + my $offset = shift || 0; - my $child = fork(); - if ($child < 0) { - error("Couldn't create process for streaming : " . $!); + my %args = (); + my $total = 0; + + foreach my $file (@{$files}) { + + my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, + $atime,$mtime,$ctime,$blksize,$blocks) = stat($file); + unless($blocks and ($mode & 00400)) { + error sprintf("Couldn't stat file '%s' : %s",$file,$!); return $obj->status404($file,$!); } - elsif ($child > 0) { - $obj->{sendbytes} += $size; - } - elsif ($child == 0) { - eval - { - local $SIG{'__DIE__'}; + $total += $size; + } + $args{'Content-Length'} = ($total - $offset); + + return $obj->_stream($files, $total, $offset, $typ, %args); +} + +sub _stream { + my $obj = shift || return error('No object defined!'); + my $files = shift || return error('No file defined!'); + my $size = shift; + my $offset = shift || 0; + my $typ = shift; + my %args = @_; + + $obj->{nopack} = 1; + my $handle = $obj->{handle}; - my $hdr = $obj->header($typ, \%args); - if($obj->{browser}->{Method} eq 'HEAD') { - $handle->print($hdr); - } else { + my $child = fork(); + if ($child < 0) { + error("Couldn't create process for streaming : " . $!); + my $file = join(',',@$files); + return $obj->status404($file,$!); + } + elsif ($child > 0) { + $obj->{header} = 200; + $obj->{sendbytes} += $size; + undef $obj->{handle}; + undef $obj->{output}; + return 1; + } + elsif ($child == 0) { + eval + { + local $SIG{'__DIE__'}; + + my $hdr = $obj->header($typ, \%args); + if($obj->{browser}->{Method} eq 'HEAD') { + $handle->print($hdr); + } else { + foreach my $file (@{$files}) { my $r = 0; - if(sysopen( FH, $file, O_RDONLY|O_BINARY )) { - $handle->print($hdr); + if(sysopen( FH, $file, O_RDONLY|O_BINARY )) { + binmode FH; + if($hdr) { + $handle->print($hdr); + $hdr = undef; + + if($offset && $offset != sysseek(FH,$offset,0)) { #SEEK_SET + error(sprintf("Can't seek file '%s': %s",$file,$!)); + } + } my $bytes; my $data; do { + $r = 0; $bytes = sysread( FH, $data, 4096 ); if($bytes) { - $r = $handle->send($data); + my $peer = $handle->peername; + $r = $handle->send($data,0,$peer) + if($peer); } } while $r && $bytes > 0; close(FH); @@ -683,21 +739,13 @@ sub datei { error sprintf("Could not open file '%s'! : %s", $file,$!); } } - $handle->close(); - }; - error($@) if $@; - exit 0; - } - - undef $obj->{handle}; - undef $obj->{output}; - } else { - - my $data = load_file($file) - or return $obj->status404($file,$!); - # send data - $obj->out($data, $typ, %args ); + } + $handle->close(); + }; + error($@) if $@; + exit 0; } + return 0; } # ------------------ @@ -750,13 +798,13 @@ sub txtfile { my $param = shift || {}; my $txtfile = sprintf('%s/%s', $obj->{paths}->{DOCPATH}, $filename); - if(! -r $txtfile) { + unless( -r $txtfile) { $txtfile = sprintf('%s/%s.txt', $obj->{paths}->{DOCPATH}, $filename); - if(! -r $txtfile) { + unless( -r $txtfile) { my $gzfile = sprintf('%s/%s.gz', $obj->{paths}->{DOCPATH}, $filename); - if(! -r $gzfile) { + unless( -r $gzfile) { $gzfile = sprintf('%s/%s.txt.gz', $obj->{paths}->{DOCPATH}, $filename); - if(! -r $gzfile) { + unless( -r $gzfile) { my $e = $!; error sprintf("Could not open file '%s/%s[.txt .gz txt.gz]! : %s", $obj->{paths}->{DOCPATH}, $filename, $e); return $obj->err(sprintf(gettext("Could not open file '%s'! : %s"), $filename, $e)); |
