Firestorage.jp を Perl スクリプトから使う

| 0 Comments | 0 TrackBacks

LWP::UserAgent をつかってファイルをアップロードしてみましたよ!

コマンドラインからサクっと使えて便利ですよ!


あと、人には絶対見られたくない恥ずかしい写真とか動画とか送るとき用に、AES かけれるようにしてみたよ!

一時ファイルを作らずに、AES で暗号化しながらアップロード、ダウンロードしながら AES で解読とかしてみました。

どう考えても汚い書き方なので、なんかもっとキレイかつ楽ちんに書ける方法あったらおしえてください。

ふつうに使う

firestorage-put.pl

usage:
# 2 つめのパラメータは省略可
$ firestorage-put.pl "/path/to/your/file.avi" label.avi
#!/usr/bin/perl

use strict;
use HTTP::Request::Common;
use LWP::UserAgent ();

{
    sub HTTP::Request::Common::boundary {
        my @chr = ('A' .. 'Z', 'a' .. 'z', '0' .. '9');
        my @buf;
        push(@buf, $chr[int(rand(@chr))]) for (1..30);
        return '-' x 10 . join(q{}, @buf);
    }
}

sub upload {
    my $filebody = shift;
    my $filename = shift || $filebody;

    local $HTTP::Request::Common::DYNAMIC_FILE_UPLOAD = 1;

    my $ua = LWP::UserAgent->new(agent => "Shockwave Flash");
    my ($sec, $min, $hour, $mday, $mon, $year) = localtime(time);
    my $id = sprintf("%4d%02d%02d%02d%02d%02d%d", $year + 1900, $mon + 1, $mday, $hour, $min, $sec, $$);

    my $exp = 7;

    my $url = "http://firestorage.jp/upload.cgi";
    my $res = $ua->post($url,
                        Content_Type => 'form-data',
                        Content => [
                            Filename => $filename,
                            processid => $id,
                            exp => $exp,
                            Filedata => [$filebody, $filename],
                            Upload => "Submit Query",
                        ]);
    if ($res->content =~ m!(http://firestorage.jp/download/\w+)!s) {
        return $1;
    }
    undef;
}

die unless @ARGV;
my $res = upload(@ARGV);
print $res ? $res : "failed";
print "\n";

AES で暗号化しながらつかう

usage:

$ dd if=/dev/zero of=2048 bs=2048 count=1
1+0 records in
1+0 records out
2048 bytes (2.0 kB) copied, 0.0172761 s, 119 kB/s

$ perl firestorage-aes-put.pl 2048
url: http://firestorage.jp/download/c56e...
key: 88c0f6d8a4e6aca71ccee0b2b022bf0c

$ perl firestorage-aes-get.pl http://firestorage.jp/download/c56e...
AES key: (キー 88c0f6d8a4e6aca71ccee0b2b022bf0c を入力)
saving 2048 ...done

firestorage-aes-put.pl

#!/usr/bin/perl

use strict;
use HTTP::Request::Common;
use LWP::UserAgent ();
use Crypt::CBC;
use Digest::MD5;

{
    sub HTTP::Request::Common::boundary {
        my @chr = ('A' .. 'Z', 'a' .. 'z', '0' .. '9');
        my @buf;
        push(@buf, $chr[int(rand(@chr))]) for (1..30);
        return '-' x 10 . join(q{}, @buf);
    }
}

sub upload {
    my $filebody = shift;
    my $filename = shift || $filebody;

    local $HTTP::Request::Common::DYNAMIC_FILE_UPLOAD = 1;

    my $ua = LWP::UserAgent->new(agent => "Shockwave Flash");
    my ($sec, $min, $hour, $mday, $mon, $year) = localtime(time);
    my $id = sprintf("%4d%02d%02d%02d%02d%02d%d", $year + 1900, $mon + 1, $mday, $hour, $min, $sec, $$);

    my $exp = 7;

    require HTTP::Request::Common;
    my $url = "http://firestorage.jp/upload.cgi";
    my $request = HTTP::Request::Common::POST($url,
                        Content_Type => 'form-data',
                        Content => [
                            Filename => $filename,
                            processid => $id,
                            exp => $exp,
                            Filedata => [$filebody, $filename],
                            Upload => "Submit Query",
                        ]);
    my $code = $request->{_content};
    my $in_cd = 0;
    my $cb_looping;

    my $md5_inst;
    my $crypt_inst;

    my $len = $request->header('Content-Length');
    my $file_len = -s $filebody;
    my $new_len = $file_len + ($file_len % 16 ? 16 - $file_len % 16 : 16);
    $len += $new_len - $file_len;
    $request->header('Content-Length', $len);

    my $key;
    $request->{_content} = sub {
        my $coderes = $code->();
        unless ($cb_looping) {
            if ($coderes =~ /^(.*?)\015\012/) {
                $cb_looping = $1;
            }
        }
        my $payload;
        my $finish = 0;
        my $header_of_payload;
        if (!$in_cd && $coderes =~ /^Content-Disposition[^\012]+?; filename=/) {
            $in_cd++;
            my $loc = index($coderes, "\015\012\015\012");
            $header_of_payload = substr($coderes, 0, $loc + 4);
            $payload = substr($coderes, $loc + 4);
        } elsif ($in_cd && $coderes =~ /$cb_looping/) {
            $in_cd = 0;
            $finish++;
        } elsif ($in_cd) {
            $payload = $coderes;
        }

        if (length($payload)) {
            unless($md5_inst) {
                $key = Digest::MD5->md5_hex(time().$$.$payload);
                $crypt_inst = Crypt::CBC->new({
                    key            => $key,
                    cipher         => 'Rijndael',
                    iv             => Digest::MD5->md5('woremacx'),
                    regenerate_key => 0,
                    padding        => 'standard',
                    prepend_iv     => 0,
                });
                $crypt_inst->start('encrypt');
                $md5_inst = Digest::MD5->new;
            }
            $md5_inst->add($payload);
            $coderes = $crypt_inst->crypt($payload);
            if (length($header_of_payload)) {
                $coderes = $header_of_payload . $coderes;
            }
        }
        if ($finish) {
            # warn $md5_inst->hexdigest;
            my $left = $crypt_inst->finish;
            $coderes = $left . $coderes;
            $finish = 0;
        }
        $coderes;
    };

    my $res = $ua->request($request);
    if ($res->content =~ m!(http://firestorage.jp/download/\w+)!s) {
        return "url: $1\nkey: $key";
    }
    undef;
}

die unless @ARGV;
my $res = upload(@ARGV);
print $res ? $res : "failed";
print "\n";

firestorage-aes-get.pl

#!/usr/bin/perl

use strict;
use LWP::UserAgent;
use Digest::MD5;
use Crypt::CBC;

my $ua = LWP::UserAgent->new;
for my $url (@ARGV) {
    my $res = $ua->get($url);
    my $content = $res->content;
    while ($content =~ m!"(http://\w+\.firestorage\.jp/download[^\"]+?act=download_file[^\"]+)".*?>(.*?)</a>!g) {
        my ($url, $saveto) = ($1, $2);
        unless (-e $saveto) {
            my $key = get_key();
            # warn $key;
            my $cipher = Crypt::CBC->new({
                    key            => $key,
                    cipher         => 'Rijndael',
                    iv             => Digest::MD5->md5('woremacx'),
                    regenerate_key => 0,
                    padding        => 'standard',
                    prepend_iv     => 0,
                }) or die;
                $cipher->start('decrypt');

            open(my $fh, "> $saveto");
            my $total_len;
            my $recieved;
            my $decrypt = sub {
                my ($payload, $pp, $qq) = @_;
                $total_len ||= $pp->{_headers}->{'content-length'};
                $recieved += length($payload);
                print $fh $cipher->crypt($payload);
                if ($total_len == $recieved) {
                    print $fh $cipher->finish;
                }
            };
            print "saving $saveto ...";
            $ua->get($url, ':content_cb'   => $decrypt);
            close($fh);
            print "done\n";

        } else {
            print "$saveto already exists\n";
        }
    }
}

sub get_key {
    local($|) = 1;
    local(*TTY);
    open(TTY,"/dev/tty");
    my ($key1,$key2);
    system "stty -echo </dev/tty";
    do {
        print STDERR "AES key: ";
        chomp($key1 = <TTY>);
    } until $key1 =~ /^[a-f0-9]{32}$/;
    system "stty echo </dev/tty";
    close(TTY);
    $key1;
}

No TrackBacks

TrackBack URL: http://blog.woremacx.com/MT/mt-tb.cgi/251

Leave a comment