Group
Extension

VT-API/lib/VT/API.pm

package VT::API;
use strict;
use Carp;

use JSON;
use HTTP::Request::Common;
use LWP::UserAgent;

our $VERSION = '0.12';

sub new {
    croak('Options to VT::API should be key/value pairs, '.
          'not HASH reference') if ref($_[1]) eq 'HASH';

    my ($class, %opts) = @_;
    my $self = {};

    # Public Key.
    $self->{key} = $opts{key} or
        croak('You should specify public API key');

    # LWP::UserAgent Object.
    $self->{ua} = LWP::UserAgent->new(
        agent   => $opts{agent}   || 'Perl/VT-API',
        timeout => $opts{timeout} || 180,
    );

    return bless $self, $class;
}


sub get_file_report {
    my ($self, $resource) = @_;

    croak('You have not specified a resource (md5/sha1/sha256 or permalink '.
          'identifier') if !defined $resource;

    $self->{res} = $self->{ua}->request(
        POST 'https://www.virustotal.com/api/get_file_report.json', [
            resource => $resource,
            key      => $self->{key},
        ],
    );

    return $self->_parse_json();
}


sub scan_file {
    my ($self, $file) = @_;

    croak('You have not specified a file') if !defined $file;

    $self->{res} = $self->{ua}->request(
        POST 'https://www.virustotal.com/api/scan_file.json',
        Content_Type => 'form-data',
        Content      => [
            file => [$file],
            key  => $self->{key},
        ],  
    );

    return $self->_parse_json();
}


sub get_url_report {
    my ($self, $resource) = @_;

    croak('You have not specified a resource (URL or permalink '.
          'identifier') if !defined $resource;

    $self->{res} = $self->{ua}->request(
        POST 'https://www.virustotal.com/api/get_url_report.json', [
            resource => $resource,
            key      => $self->{key},
        ],
    );

    return $self->_parse_json();
}


sub scan_url {
    my ($self, $url) = @_;

    croak('You have not specified a URL that should be '.
          'scanned') if !defined $url;

    $self->{res} = $self->{ua}->request(
        POST 'https://www.virustotal.com/api/scan_url.json', [
            url => $url,
            key => $self->{key},
        ],
    );

    return $self->_parse_json();
}


sub make_comment {
    my ($self, $file_or_url, $comment, $tags) = @_;

    croak('You have not specified a file (md5/sha1/sha256 hash) or URL')
        if !defined $file_or_url;
    croak('You have not specified a comment')
        if !defined $comment;

    $self->{res} = $self->{ua}->request(
        POST 'https://www.virustotal.com/api/make_comment.json', [
            ($file_or_url =~ /^https?:\/\//) ?
                (url  => $file_or_url)       :
                (file => $file_or_url),

            (comment => $comment),

            (defined $tags)                                                   ?
                (tags => (ref($tags) eq 'ARRAY' ? join(',', @$tags) : $tags)) :
                (),

            (key => $self->{key}),
        ],
    );

    return $self->_parse_json();
}


sub _parse_json {
    my ($self) = @_;
    return if !defined $self->{res};

    my $parsed;
    if ($self->{res}->is_success()) {
        undef $self->{errstr};

        eval { $parsed = from_json($self->{res}->content()) };
        if ($@) {
            $@ =~ s/ at .*//;
            $self->{errstr} = $@;
        }
    }
    else {
        $self->{errstr} = $self->{res}->status_line;
    }

    return $parsed;
}


sub errstr {
    my ($self) = @_;
    return $self->{errstr};
}


1;
__END__

=pod

=head1 NAME

VT::API - Perl implementation of VirusTotal Public API


=head1 VERSION

This documentation refers to VT::API version 0.12


=head1 SYNOPSIS

    use VT::API;
    
    # OO-interface.
    my $api = VT::API->new(key => 'YOUR_PUBLIC_KEY');
    
    # Retrieve a file scan report.
    # If query successfull hash reference returned.
    my $res1 = $api->get_file_report('md5/sha1/sha256 or permalink identifier');
    
    # Send and scan a file.
    my $res2 = $api->scan_file('/file/path');
    
    # Retrieve a URL scan report
    my $res3 = $api->get_url_report('http://www.example.com/');
    
    # Submit and scan a URL.
    my $res4 = $api->scan_url('http://www.example.com/');
    my $scan_id;
    
    if ($res4->{result}) {
        $scan_id = $res->{scan_id};
    }
    
    # Make comments on files and URLs.
    my $res5 = $api->make_comment('file hash or URL', 'Comment', ['tag1', 'tag2']);
    
    ...


=head1 DESCRIPTION

VT::API provides unofficial OO interface to VirusTotal Public API.
Please see the terms of use for more information.


=head1 OPTIONS

The options bellow are passed through the constructor of interface.

=head2 C<key =E<gt> I<Your Key>>

Your API key. You will find your personal API key in the inbox of your account.

=head2 C<agent =E<gt> I<string>>

Defines a User-Agent. Default is Perl/VT-API.

=head2 C<timeout =E<gt> I<value>>

Timeout value in seconds. The default value is 180.


=head1 METHODS

VT::API methods.

=head2 my $api = VT::API->new(key => 'Public Key')

=head2 $api->get_file_report($resource)

=head2 $api->scan_file($file)

=head2 $api->get_url_report($resource)

=head2 $api->scan_url($url)

=head2 $api->make_comment($file_or_url, $comment, $tags)

=head2 errstr()


=head1 BUGS AND LIMITATIONS

None known at this time.


=head1 SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc VT::API


=head1 INFORMATION

You can also look for information at:

=over 4

=item * VirusTotal official website

L<http://virustotal.com/>

=item * VirusTotal terms of use

L<http://www.virustotal.com/terms.html>


=back

=head1 AUTHOR

Written by Alexander Nusov.


=head1 COPYRIGHTS AND LICENSE

Copyright (C) 2010, Alexander Nusov <alexander.nusov+cpan <at> gmail.com>

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.

=cut


Powered by Groonga
Maintained by Kenichi Ishigaki <ishigaki@cpan.org>. If you find anything, submit it on GitHub.