summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAndreas Brachold <vdr07@deltab.de>2008-01-01 18:08:52 +0000
committerAndreas Brachold <vdr07@deltab.de>2008-01-01 18:08:52 +0000
commit8222d826a768795076a655fcc057a218b7f8e933 (patch)
treed0ee5e644afb288ab61d1d86f3a6856b5a6e4fef /lib
parent8d11e5ef702eb4e7a0448eb43d39f28c9670954e (diff)
downloadxxv-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.pm50
-rw-r--r--lib/XXV/MODULES/CHANNELS.pm16
-rw-r--r--lib/XXV/MODULES/HTTPD.pm3
-rw-r--r--lib/XXV/MODULES/RECORDS.pm76
-rw-r--r--lib/XXV/MODULES/STREAM.pm144
-rw-r--r--lib/XXV/MODULES/TIMERS.pm43
-rw-r--r--lib/XXV/OUTPUT/Html.pm146
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));