App-otfile

 view release on metacpan or  search on metacpan

script/otfile  view on Meta::CPAN

#!/usr/bin/env perl

use 5.0101;
use warnings;
use strict;
use autodie;

use Pod::Usage;
use Getopt::Long;
use File::Basename;
use IO::Socket::INET;

my $port           = 1234;
my $auto_port      = 0;
my $serve_multiple = 0;
my $serve_self     = 0;
my $uuid           = '';

GetOptions(
    'auto'     => \$auto_port,
    'port=i'   => \$port,
    'multiple' => \$serve_multiple,
    'self'     => \$serve_self,
    'uuid=s'   => \$uuid,
    'help'     => sub { pod2usage(1) } ) or pod2usage(2);

unshift @ARGV, __FILE__ if $serve_self;
my $file = shift or do { warn "Must provide file to serve\n"; pod2usage(2) };
die "Unable to read '$file'\n" unless -r $file;

# try loading some optional dependencies
my %opt_depend;

# we try for Mac::Pasteboard first for pre 0.06 people that have it
# but don't have Clipboard installed

eval { require Mac::Pasteboard; $opt_depend{pasteboard} = 1 };
eval { require Clipboard;       $opt_depend{clipboard}  = 1 }
    unless $opt_depend{pasteboard};
eval { require File::MMagic;      $opt_depend{mmagic}     = 1 };
eval { require UUID::Tiny;        $opt_depend{uuid}       = 1 };
eval { require URI::Escape;       $opt_depend{uri_escape} = 1 };
eval { require Term::ProgressBar; $opt_depend{progress}   = 1 };

my $type     = get_file_type($file);
my $size     = -s $file;
my $filename = fileparse($file);
my $ip       = get_local_ip();
$uuid      ||= gen_uniq_string();
my $path     = "/$uuid/" . check_escape($filename);

my $server;
while ( !$server ) {
    $server = IO::Socket::INET->new(
        Listen    => 5,
        LocalAddr => $ip,
        LocalPort => $port,
        Proto     => 'tcp'
    );
    last if $server;
    if ( !$auto_port || $! ne 'Address already in use' ) {
        die "Couldn't open socket for listening: $!\n";
    }
    $port++;
}

my $url = "http://$ip:$port$path";

say "Serving '$file' as '$filename', size $size, type $type";

if ( $opt_depend{pasteboard} ) {
    Mac::Pasteboard::pbcopy($url);
    say "$url copied to clipboard.";
}
elsif ( $opt_depend{clipboard} ) {
    Clipboard->import;    # finds OS driver
    Clipboard->copy($url);
    say "$url copied to clipboard.";
}
else {
    say $url;
}

while ( my $client = $server->accept() ) {
    say 'I: Connect from ' . $client->peerhost;
    my $requested_path;
    LINE: while ( my $line = <$client> ) {
        last if $line =~ m/^\s*$/;
        $requested_path = $1 if $line =~ /^GET (\S+) /;
    }
    if ( $path ne $requested_path ) {
        say "E: Invalid request for $requested_path";
        say $client "HTTP/1.0 403 Forbidden FOAD.\n\n";
        close $client;
        next;
    }
    open my $fh, "<", $file;

    say $client "HTTP/1.0 200 OK";
    say $client "Pragma: no-cache";
    say $client "Content-type: $type";
    say $client "Content-length: $size";
    say $client "Content-disposition: inline; filename=\"$filename\"";
    say $client "";

    my $p;
    if ( $opt_depend{progress} ) {
        $p = Term::ProgressBar->new(
            {   name       => $filename,
                count      => $size,
                ETA        => "linear",
                term_width => 40,
            } );
        $p->minor(0);
    }
    else {
        say "Serving file.";
    }

    my $total = 0;
    while ( my $len = sysread $fh, my $buf, 4096 ) {
        print $client $buf;
        $total += $len;
        $p->update($total) if $opt_depend{progress};
    }
    $p->update($size) if $opt_depend{progress};
    say "\nDone.";

    close $fh;
    $client->close;
    $server->shutdown(2) unless $serve_multiple;
    $server->close unless $serve_multiple;
}

# From Net::Address::IP::Local
sub get_local_ip {
    my $socket = IO::Socket::INET->new(
        Proto    => 'udp',



( run in 2.240 seconds using v1.01-cache-2.11-cpan-2398b32b56e )