App-MHFS

 view release on metacpan or  search on metacpan

lib/MHFS/FD/Reader.pm  view on Meta::CPAN

package MHFS::FD::Reader v0.7.0;
use 5.014;
use strict; use warnings;
use feature 'say';
use Time::HiRes qw( usleep clock_gettime CLOCK_MONOTONIC);
use IO::Poll qw(POLLIN POLLOUT POLLHUP);
use Scalar::Util qw(looks_like_number weaken);
sub new {
    my ($class, $process, $fd, $func) = @_;
    my %self = ('time' => clock_gettime(CLOCK_MONOTONIC), 'process' => $process, 'fd' => $fd, 'onReadReady' => $func);
    say "PID " . $self{'process'}{'pid'} . 'FD ' . $self{'fd'};
    weaken($self{'process'});
    return bless \%self, $class;
}

sub onReadReady {
    my ($self) = @_;
    my $ret = $self->{'onReadReady'}($self->{'fd'});
    if($ret == 0) {
        $self->{'process'}->remove($self->{'fd'});
        return 1;
    }

lib/MHFS/FD/Writer.pm  view on Meta::CPAN

package MHFS::FD::Writer v0.7.0;
use 5.014;
use strict; use warnings;
use feature 'say';
use Time::HiRes qw( usleep clock_gettime CLOCK_MONOTONIC);
use IO::Poll qw(POLLIN POLLOUT POLLHUP);
use Scalar::Util qw(looks_like_number weaken);
sub new {
    my ($class, $process, $fd, $func) = @_;
    my %self = ('time' => clock_gettime(CLOCK_MONOTONIC), 'process' => $process, 'fd' => $fd, 'onWriteReady' => $func);
    say "PID " . $self{'process'}{'pid'} . 'FD ' . $self{'fd'};
    weaken($self{'process'});
    return bless \%self, $class;
}

sub onWriteReady {
    my ($self) = @_;
    my $ret = $self->{'onWriteReady'}($self->{'fd'});
    if($ret == 0) {
        $self->{'process'}->remove($self->{'fd'});
        return 1;
    }

lib/MHFS/HTTP/Server.pm  view on Meta::CPAN

package MHFS::HTTP::Server v0.7.0;
use 5.014;
use strict; use warnings;
use feature 'say';
use IO::Socket::INET;
use Socket qw(IPPROTO_TCP TCP_KEEPALIVE TCP_NODELAY);
use IO::Poll qw(POLLIN POLLOUT POLLHUP);
use Scalar::Util qw(weaken);
use Feature::Compat::Try;
use File::Path qw(make_path);
use Data::Dumper;
use Carp ();
use Config;
use MHFS::EventLoop::Poll;
use MHFS::FS;
use MHFS::HTTP::Server::Client;
use MHFS::Settings;
use MHFS::Util qw(parse_ipv4 read_text_file);

lib/MHFS/HTTP/Server/Client.pm  view on Meta::CPAN

package MHFS::HTTP::Server::Client v0.7.0;
use 5.014;
use strict; use warnings;
use feature 'say';
use Time::HiRes qw( usleep clock_gettime CLOCK_REALTIME CLOCK_MONOTONIC);
use IO::Socket::INET;
use Errno qw(EINTR EIO :POSIX);
use Fcntl qw(:seek :mode);
use File::stat;
use IO::Poll qw(POLLIN POLLOUT POLLHUP);
use Scalar::Util qw(looks_like_number weaken);
use Data::Dumper;
use Carp;
use MHFS::HTTP::Server::Client::Request;

sub new {
    my ($class, $sock, $server, $serverhostinfo, $ip) = @_;
    $sock->blocking(0);
    my %self = ('sock' => $sock, 'server' => $server, 'time' => clock_gettime(CLOCK_MONOTONIC), 'inbuf' => '', 'serverhostname' => $serverhostinfo->{'hostname'}, 'absurl' => $serverhostinfo->{'absurl'}, 'ip' => $ip, 'X-MHFS-PROXY-KEY' => $serverhosti...
    $self{'CONN-ID'} = int($self{'time'} * rand()); # insecure uid
    $self{'outheaders'}{'X-MHFS-CONN-ID'} = sprintf("%X", $self{'CONN-ID'});
    bless \%self, $class;
    $self{'request'} = MHFS::HTTP::Server::Client::Request->new(\%self);
    return \%self;
}

# add a connection timeout timer
sub AddClientCloseTimer {
    my ($self, $timelength, $id, $is_requesttimeout) = @_;
    weaken($self); #don't allow this timer to keep the client object alive
    my $server = $self->{'server'};
    say "CCT | add timer: $id";
    $server->{'evp'}->add_timer($timelength, 0, sub {
        if(! defined $self) {
            say "CCT | $id self undef";
            return undef;
        }
        # Commented out as with connection reuse on, Apache 2.4.10 seems sometimes
        # pass 408 on to the next client.
        #if($is_requesttimeout) {

lib/MHFS/HTTP/Server/Client/Request.pm  view on Meta::CPAN

use strict; use warnings;
use feature 'say';
use Time::HiRes qw( usleep clock_gettime CLOCK_REALTIME CLOCK_MONOTONIC);
use URI::Escape;
use Cwd qw(abs_path getcwd);
use Feature::Compat::Try;
use File::Basename;
use File::stat;
use IO::Poll qw(POLLIN POLLOUT POLLHUP);
use Data::Dumper;
use Scalar::Util qw(weaken);
use List::Util qw[min max];
use Symbol 'gensym';
use Devel::Peek;
use Encode qw(decode encode);
use constant {
    MAX_REQUEST_SIZE => 8192,
};
use FindBin;
use File::Spec;
use MHFS::EventLoop::Poll;

lib/MHFS/HTTP/Server/Client/Request.pm  view on Meta::CPAN

    use constant HAS_Alien_Tar_Size => (eval "use Alien::Tar::Size; 1");
    if(! HAS_Alien_Tar_Size) {
        warn "Alien::Tar::Size is not available";
    }
}

sub new {
    my ($class, $client) = @_;
    my %self = ( 'client' => $client);
    bless \%self, $class;
    weaken($self{'client'}); #don't allow Request to keep client alive
    $self{'on_read_ready'} = \&want_request_line;
    $self{'outheaders'}{'X-MHFS-CONN-ID'} = $client->{'outheaders'}{'X-MHFS-CONN-ID'};
    $self{'rl'} = 0;
    # we want the request
    $client->SetEvents(POLLIN | MHFS::EventLoop::Poll->ALWAYSMASK );
    $self{'recvrequesttimerid'} = $client->AddClientCloseTimer($client->{'server'}{'settings'}{'recvrequestimeout'}, $client->{'CONN-ID'}, 1);
    return \%self;
}

# on ready ready handlers

lib/MHFS/Plugin/GetVideo.pm  view on Meta::CPAN

package MHFS::Plugin::GetVideo v0.7.0;
use 5.014;
use strict; use warnings;
use feature 'say';
use Data::Dumper qw (Dumper);
use Fcntl qw(:seek);
use Feature::Compat::Try;
use Scalar::Util qw(weaken);
use URI::Escape qw (uri_escape);
use Devel::Peek qw(Dump);
no warnings "portable";
use Config;
use MHFS::Process;
use MHFS::Util qw(space2us LOCK_WRITE round shellcmd_unlock ASYNC pid_running read_text_file write_text_file ceil_div);

sub new {
    my ($class, $settings) = @_;

lib/MHFS/Plugin/GetVideo.pm  view on Meta::CPAN

        #return undef;

        if($fmt eq 'hls') {
            $video{'on_exists'} = \&video_hls_write_master_playlist;
        }

        # deprecated
        $video{'pid'} = ASYNC(\&shellcmd_unlock, \@cmd, $video{'out_filepath'});

        # our file isn't ready yet, so create a timer to check the progress and act
        weaken($request); # the only one who should be keeping $request alive is the client
        $request->{'client'}{'server'}{'evp'}->add_timer(0, 0, sub {
            if(! defined $request) {
                say "\$request undef, ignoring CB";
                return undef;
            }
            # test if its ready to send
            while(1) {
                    my $filename = $video{'out_filepath'};
                    if(! -e $filename) {
                        last;

lib/MHFS/Plugin/Kodi.pm  view on Meta::CPAN

package MHFS::Plugin::Kodi v0.7.0;
use 5.014;
use strict; use warnings;
use feature 'say';
use File::Basename qw(basename);
use Cwd qw(abs_path getcwd);
use URI::Escape qw(uri_escape);
use Encode qw(decode encode_utf8);
use File::Path qw(make_path);
use Data::Dumper qw(Dumper);
use Scalar::Util qw(weaken);
use MIME::Base64 qw(encode_base64url decode_base64url);
use Devel::Peek qw(Dump);
use MHFS::Kodi::TVShows;
use MHFS::Kodi::Movie;
use MHFS::Kodi::MovieEdition;
use MHFS::Kodi::MovieEditions;
use MHFS::Kodi::MoviePart;
use MHFS::Kodi::Movies;
use MHFS::Kodi::MovieSubtitle;
use MHFS::Kodi::Season;

lib/MHFS/Plugin/Kodi.pm  view on Meta::CPAN

    }
    # slow path, download it
    $request->{client}{server}{settings}{TMDB} or do {
        $request->Send404;
        return;
    };
    # find the movie or tv show
    my $searchname = $medianame;
    $searchname =~ s/\s\(\d\d\d\d\)// if($mediatype eq 'movies');
    say "searchname $searchname";
    weaken($request);
    _TMDB_api_promise($request->{client}{server}, 'search/'.$params->{search}, {'query' => $searchname})->then(sub {
        my $json = $_[0]->{results}[0];
        $json or die "Failed to find item";
        $season // return $json;
        # find the season and then the episode if applicable
        my $showid = $json->{id} // die "showid not available";
        _TMDB_api_promise($request->{client}{server}, "tv/$showid/season/$season")->then(sub {
            if ($metadatatype eq 'plot' || ! -f $b_plotfile) {
                make_path($b_metadir);
                my $bytes = encode_json($_[0]);

lib/MHFS/Plugin/MusicLibrary.pm  view on Meta::CPAN

    if( ! (eval "use JSON; 1")) {
        eval "use JSON::PP; 1" or die "No implementation of JSON available";
        warn __PACKAGE__.": Using PurePerl version of JSON (JSON::PP)";
    }
}
use Encode qw(decode encode);
use URI::Escape;
use Storable qw(dclone);
use Fcntl ':mode';
use Time::HiRes qw( usleep clock_gettime CLOCK_REALTIME CLOCK_MONOTONIC);
use Scalar::Util qw(looks_like_number weaken);
use POSIX qw/ceil/;
use Storable qw( freeze thaw);
#use ExtUtils::testlib;
use FindBin;
use File::Spec;
use List::Util qw[min max];
use HTML::Template;
use MHFS::Process;

# Optional dependency, MHFS::XS

lib/MHFS/Plugin/Youtube.pm  view on Meta::CPAN

package MHFS::Plugin::Youtube v0.7.0;
use 5.014;
use strict; use warnings;
use feature 'say';
use Data::Dumper;
use feature 'state';
use Encode;
use URI::Escape;
use Scalar::Util qw(looks_like_number weaken);
use File::stat;
use MHFS::Process;
use MHFS::Util qw(escape_html LOCK_WRITE UNLOCK_WRITE);
BEGIN {
    if( ! (eval "use JSON; 1")) {
        eval "use JSON::PP; 1" or die "No implementation of JSON available";
        warn __PACKAGE__.": Using PurePerl version of JSON (JSON::PP)";
    }
}
sub searchbox {

lib/MHFS/Plugin/Youtube.pm  view on Meta::CPAN

            else {
                $self->sendAsHTML($request, $tosend);
            }
        },
    });
    $request->{'process'} = $tprocess;
    return -1;
}
sub downloadAndServe {
    my ($self, $request, $video) = @_;
    weaken($request);
    my $filename = $video->{'out_filepath'};
    my $sendit = sub {
        # we can send the file
        if(! $request) {
            return;
        }
        say "sending!!!!";
        $request->SendLocalFile($filename);
    };
    my $qs = $request->{'qs'};

lib/MHFS/Process.pm  view on Meta::CPAN

use feature 'say';
use Symbol 'gensym';
use Time::HiRes qw( usleep clock_gettime CLOCK_REALTIME CLOCK_MONOTONIC);
use POSIX ":sys_wait_h";
use IO::Socket::INET;
use IO::Poll qw(POLLIN POLLOUT POLLHUP);
use Errno qw(EINTR EIO :POSIX);
use Fcntl qw(:seek :mode);
use File::stat;
use IPC::Open3;
use Scalar::Util qw(looks_like_number weaken);
use Data::Dumper;
use Devel::Peek;
use MHFS::FD::Reader;
use MHFS::FD::Writer;
use MHFS::EventLoop::Poll;
use Carp;

#my %CHILDREN;
#$SIG{CHLD} = sub {
#    while((my $child = waitpid(-1, WNOHANG)) > 0) {



( run in 1.015 second using v1.01-cache-2.11-cpan-39bf76dae61 )