API-MailboxOrg

 view release on metacpan or  search on metacpan

MANIFEST  view on Meta::CPAN

lib/API/MailboxOrg/APIBase.pm
lib/API/MailboxOrg/Types.pm
perlcritic.rc
t/001_base.t
t/002_hello-world.t
t/author-critic.t
t/author-no-bom.t
t/author-no-tabs.t
t/author-pod-coverage.t
t/author-pod-syntax.t
t/types/001_hashref_restricted.t
t/types/002_boolean.t

META.json  view on Meta::CPAN

         "version" : "v1.0.2"
      }
   },
   "release_status" : "stable",
   "resources" : {
      "bugtracker" : {
         "web" : "https://github.com/perlservices/API-MailboxOrg/issues"
      },
      "homepage" : "https://github.com/perlservices/API-MailboxOrg",
      "repository" : {
         "type" : "git",
         "url" : "git://github.com/perlservices/API-MailboxOrg.git",
         "web" : "https://github.com/perlservices/API-MailboxOrg"
      }
   },
   "version" : "1.0.2",
   "x_contributors" : [
      "reneeb <info@perl-services.de>"
   ],
   "x_generated_by_perl" : "v5.30.0",
   "x_serialization_backend" : "Cpanel::JSON::XS version 4.19"

Makefile.PL  view on Meta::CPAN

  },
  "TEST_REQUIRES" => {
    "Pod::Coverage::TrustPod" => 0,
    "Test::Exception" => 0,
    "Test::More" => 0,
    "Test::RequiresInternet" => 0,
    "Test::Spec" => 0
  },
  "VERSION" => "1.0.2",
  "test" => {
    "TESTS" => "t/*.t t/types/*.t"
  }
);


my %FallbackPrereqs = (
  "Carp" => 0,
  "IO::Socket::SSL" => 0,
  "JSON::PP" => 0,
  "Mojolicious" => 8,
  "Moo" => "1.003001",

dist.ini  view on Meta::CPAN

name             = API-MailboxOrg
author           = Renee Baecker <reneeb@cpan.org>
license          = Artistic_2_0
copyright_holder = Renee Baecker
copyright_year   = 2022
version          = 1.0.2

; in dist.ini
[@PERLSRVDE]
; we are using an internal git repository
repository_type = github
repository_path = perlservices/API-MailboxOrg
is_cpan         = 1

[PruneFiles]
filename = bin/get_mailbox_api.pl

[Prereqs]
Carp            = 0
IO::Socket::SSL = 0
JSON::PP        = 0

lib/API/MailboxOrg/API/Account.pm  view on Meta::CPAN

with 'MooX::Singleton';

use feature 'signatures';
no warnings 'experimental::signatures';

our $VERSION = '1.0.2'; # VERSION

my %validators = (
    'add' => validation_for(
        params => {
            account      => { type => Str, optional => 0 },
            password     => { type => Str, optional => 0 },
            plan         => { type => Enum[qw(basic profi profixl reseller)], optional => 0 },
            tarifflimits => { type => HashRefRestricted[qw(basic profi profixl reseller)], optional => 1 },
            memo         => { type => Str, optional => 1 },

        },
    ),
    'del' => validation_for(
        params => {
            account => { type => Str, optional => 0 },

        },
    ),
    'get' => validation_for(
        params => {
            account => { type => Str, optional => 0 },

        },
    ),
    'set' => validation_for(
        params => {
            account                    => { type => Str, optional => 0 },
            password                   => { type => Str, optional => 1 },
            plan                       => { type => Enum[qw(basic profi profixl reseller)], optional => 1 },
            memo                       => { type => Str, optional => 1 },
            address_payment_first_name => { type => Str, optional => 1 },
            address_payment_last_name  => { type => Str, optional => 1 },
            address_payment_street     => { type => Str, optional => 1 },
            address_payment_zipcode    => { type => Str, optional => 1 },
            address_payment_town       => { type => Str, optional => 1 },
            av_contract_accept_name    => { type => Str, optional => 1 },
            tarifflimits               => { type => HashRefRestricted[qw(basic profi profixl reseller)], optional => 1 },

        },
    ),

);


sub add ($self, %params) {
    my $validator = $validators{'add'};
    %params       = $validator->(%params) if $validator;

lib/API/MailboxOrg/API/Backup.pm  view on Meta::CPAN

with 'MooX::Singleton';

use feature 'signatures';
no warnings 'experimental::signatures';

our $VERSION = '1.0.2'; # VERSION

my %validators = (
    'backup_import' => validation_for(
        params => {
            mail   => { type => Str, optional => 0 },
            id     => { type => Int, optional => 0 },
            time   => { type => Int, optional => 0 },
            filter => { type => Str, optional => 0 },

        },
    ),
    'list' => validation_for(
        params => {
            mail => { type => Str, optional => 0 },

        },
    ),

);


sub backup_import ($self, %params) {
    my $validator = $validators{'backup_import'};
    %params       = $validator->(%params) if $validator;

lib/API/MailboxOrg/API/Base.pm  view on Meta::CPAN

with 'MooX::Singleton';

use feature 'signatures';
no warnings 'experimental::signatures';

our $VERSION = '1.0.2'; # VERSION

my %validators = (
    'auth' => validation_for(
        params => {
            user => { type => Str, optional => 0 },
            pass => { type => Str, optional => 0 },

        },
    ),
    'search' => validation_for(
        params => {
            query => { type => Str, optional => 0 },

        },
    ),

);


sub auth ($self, %params) {
    my $validator = $validators{'auth'};
    %params       = $validator->(%params) if $validator;

lib/API/MailboxOrg/API/Blacklist.pm  view on Meta::CPAN

with 'MooX::Singleton';

use feature 'signatures';
no warnings 'experimental::signatures';

our $VERSION = '1.0.2'; # VERSION

my %validators = (
    'add' => validation_for(
        params => {
            mail        => { type => Str, optional => 0 },
            add_address => { type => Str, optional => 0 },

        },
    ),
    'del' => validation_for(
        params => {
            mail           => { type => Str, optional => 0 },
            delete_address => { type => Str, optional => 0 },

        },
    ),
    'list' => validation_for(
        params => {
            mail => { type => Str, optional => 0 },

        },
    ),

);


sub add ($self, %params) {
    my $validator = $validators{'add'};
    %params       = $validator->(%params) if $validator;

lib/API/MailboxOrg/API/Capabilities.pm  view on Meta::CPAN

with 'MooX::Singleton';

use feature 'signatures';
no warnings 'experimental::signatures';

our $VERSION = '1.0.2'; # VERSION

my %validators = (
    'set' => validation_for(
        params => {
            mail         => { type => Str, optional => 0 },
            capabilities => { type => ArrayRef[Enum[qw(MAIL_SPAMPROTECTION MAIL_BLACKLIST MAIL_BACKUPRECOVER MAIL_OTP MAIL_PASSWORDRESET_SMS BMBO_VIDEOCHAT)]], optional => 0 },

        },
    ),

);


sub set ($self, %params) {
    my $validator = $validators{'set'};
    %params       = $validator->(%params) if $validator;

lib/API/MailboxOrg/API/Context.pm  view on Meta::CPAN

with 'MooX::Singleton';

use feature 'signatures';
no warnings 'experimental::signatures';

our $VERSION = '1.0.2'; # VERSION

my %validators = (
    'list' => validation_for(
        params => {
            account => { type => Str, optional => 0 },

        },
    ),

);


sub list ($self, %params) {
    my $validator = $validators{'list'};
    %params       = $validator->(%params) if $validator;

lib/API/MailboxOrg/API/Domain.pm  view on Meta::CPAN

with 'MooX::Singleton';

use feature 'signatures';
no warnings 'experimental::signatures';

our $VERSION = '1.0.2'; # VERSION

my %validators = (
    'add' => validation_for(
        params => {
            account               => { type => Str, optional => 0 },
            domain                => { type => Str, optional => 0 },
            password              => { type => Str, optional => 0 },
            context_id            => { type => Str, optional => 1 },
            create_new_context_id => { type => Boolean, optional => 1 },
            memo                  => { type => Str, optional => 1 },

        },
    ),
    'del' => validation_for(
        params => {
            account => { type => Str, optional => 0 },
            domain  => { type => Str, optional => 0 },

        },
    ),
    'get' => validation_for(
        params => {
            domain => { type => Str, optional => 0 },

        },
    ),
    'list' => validation_for(
        params => {
            account => { type => Str, optional => 0 },
            filter  => { type => Str, optional => 1 },

        },
    ),
    'set' => validation_for(
        params => {
            domain                => { type => Str, optional => 0 },
            password              => { type => Str, optional => 1 },
            context_id            => { type => Str, optional => 1 },
            create_new_context_id => { type => Boolean, optional => 1 },
            memo                  => { type => Str, optional => 1 },

        },
    ),

);


sub add ($self, %params) {
    my $validator = $validators{'add'};
    %params       = $validator->(%params) if $validator;

lib/API/MailboxOrg/API/Invoice.pm  view on Meta::CPAN

with 'MooX::Singleton';

use feature 'signatures';
no warnings 'experimental::signatures';

our $VERSION = '1.0.2'; # VERSION

my %validators = (
    'get' => validation_for(
        params => {
            token => { type => Str, optional => 0 },

        },
    ),
    'list' => validation_for(
        params => {
            account => { type => Str, optional => 0 },

        },
    ),

);


sub get ($self, %params) {
    my $validator = $validators{'get'};
    %params       = $validator->(%params) if $validator;

lib/API/MailboxOrg/API/Mail.pm  view on Meta::CPAN

with 'MooX::Singleton';

use feature 'signatures';
no warnings 'experimental::signatures';

our $VERSION = '1.0.2'; # VERSION

my %validators = (
    'add' => validation_for(
        params => {
            mail                   => { type => Str, optional => 0 },
            password               => { type => Str, optional => 0 },
            password_hash          => { type => Str, optional => 1 },
            plan                   => { type => Enum[qw(light standard premium)], optional => 0 },
            additional_mail_quota  => { type => Str, optional => 1 },
            additional_cloud_quota => { type => Str, optional => 1 },
            first_name             => { type => Str, optional => 0 },
            last_name              => { type => Str, optional => 0 },
            inboxsave              => { type => Boolean, optional => 0 },
            forwards               => { type => ArrayRef, optional => 0 },
            memo                   => { type => Str, optional => 1 },
            catchall               => { type => Boolean, optional => 1 },
            create_own_context     => { type => Boolean, optional => 1 },
            title                  => { type => Str, optional => 1 },
            birthday               => { type => Str, optional => 1 },
            position               => { type => Str, optional => 1 },
            department             => { type => Str, optional => 1 },
            company                => { type => Str, optional => 1 },
            street                 => { type => Str, optional => 1 },
            postal_code            => { type => Str, optional => 1 },
            city                   => { type => Str, optional => 1 },
            phone                  => { type => Str, optional => 1 },
            fax                    => { type => Str, optional => 1 },
            cell_phone             => { type => Str, optional => 1 },
            recover                => { type => Boolean, optional => 1 },
            skip_welcome_mail      => { type => Boolean, optional => 1 },

        },
    ),
    'del' => validation_for(
        params => {
            mail => { type => Str, optional => 0 },

        },
    ),
    'get' => validation_for(
        params => {
            mail => { type => Str, optional => 0 },

        },
    ),
    'list' => validation_for(
        params => {
            domain => { type => Str, optional => 0 },

        },
    ),
    'register' => validation_for(
        params => {
            token          => { type => Str, optional => 0 },
            mail           => { type => Str, optional => 0 },
            password       => { type => Str, optional => 0 },
            alternate_mail => { type => Str, optional => 1 },
            first_name     => { type => Str, optional => 0 },
            last_name      => { type => Str, optional => 0 },
            lang           => { type => Enum[qw(de en fr)], optional => 1 },

        },
    ),
    'set' => validation_for(
        params => {
            mail                   => { type => Str, optional => 0 },
            password               => { type => Str, optional => 1 },
            password_hash          => { type => Str, optional => 1 },
            plan                   => { type => Enum[qw(MAIL MAILXL MAILXXL MAILXXXL Office OfficeXL OfficeXXL OfficeXXXL light standard premium)], optional => 1 },
            additional_mail_quota  => { type => Str, optional => 1 },
            additional_cloud_quota => { type => Str, optional => 1 },
            first_name             => { type => Str, optional => 1 },
            last_name              => { type => Str, optional => 1 },
            inboxsave              => { type => Boolean, optional => 1 },
            forwards               => { type => ArrayRef, optional => 1 },
            aliases                => { type => ArrayRef, optional => 1 },
            alternate_mail         => { type => Str, optional => 1 },
            memo                   => { type => Str, optional => 1 },
            active                 => { type => Boolean, optional => 1 },
            title                  => { type => Str, optional => 1 },
            birthday               => { type => Str, optional => 1 },
            position               => { type => Str, optional => 1 },
            department             => { type => Str, optional => 1 },
            company                => { type => Str, optional => 1 },
            street                 => { type => Str, optional => 1 },
            postal_code            => { type => Str, optional => 1 },
            city                   => { type => Str, optional => 1 },
            phone                  => { type => Str, optional => 1 },
            fax                    => { type => Str, optional => 1 },
            cell_phone             => { type => Str, optional => 1 },

        },
    ),

);


sub add ($self, %params) {
    my $validator = $validators{'add'};
    %params       = $validator->(%params) if $validator;

lib/API/MailboxOrg/API/Mailinglist.pm  view on Meta::CPAN

with 'MooX::Singleton';

use feature 'signatures';
no warnings 'experimental::signatures';

our $VERSION = '1.0.2'; # VERSION

my %validators = (
    'add' => validation_for(
        params => {
            mailinglist => { type => Str, optional => 0 },
            password    => { type => Str, optional => 0 },
            account     => { type => Str, optional => 0 },
            adminmail   => { type => Str, optional => 1 },

        },
    ),
    'del' => validation_for(
        params => {
            mailinglist => { type => Str, optional => 0 },
            account     => { type => Str, optional => 0 },

        },
    ),
    'get' => validation_for(
        params => {
            mailinglist => { type => Str, optional => 0 },
            account     => { type => Str, optional => 0 },

        },
    ),
    'list' => validation_for(
        params => {
            account => { type => Str, optional => 0 },

        },
    ),
    'set' => validation_for(
        params => {
            mailinglist => { type => Str, optional => 0 },
            account     => { type => Str, optional => 0 },
            password    => { type => Str, optional => 1 },
            adminmail   => { type => Str, optional => 1 },

        },
    ),

);


sub add ($self, %params) {
    my $validator = $validators{'add'};
    %params       = $validator->(%params) if $validator;

lib/API/MailboxOrg/API/Passwordreset.pm  view on Meta::CPAN

with 'MooX::Singleton';

use feature 'signatures';
no warnings 'experimental::signatures';

our $VERSION = '1.0.2'; # VERSION

my %validators = (
    'listmethods' => validation_for(
        params => {
            mail => { type => Str, optional => 0 },

        },
    ),
    'sendsms' => validation_for(
        params => {
            mail       => { type => Str, optional => 0 },
            cell_phone => { type => Str, optional => 0 },

        },
    ),
    'setpassword' => validation_for(
        params => {
            mail     => { type => Str, optional => 0 },
            token    => { type => Str, optional => 0 },
            password => { type => Str, optional => 0 },

        },
    ),

);


sub listmethods ($self, %params) {
    my $validator = $validators{'listmethods'};
    %params       = $validator->(%params) if $validator;

lib/API/MailboxOrg/API/Spamprotect.pm  view on Meta::CPAN

with 'MooX::Singleton';

use feature 'signatures';
no warnings 'experimental::signatures';

our $VERSION = '1.0.2'; # VERSION

my %validators = (
    'get' => validation_for(
        params => {
            mail => { type => Str, optional => 0 },

        },
    ),
    'set' => validation_for(
        params => {
            mail                 => { type => Str, optional => 0 },
            greylist             => { type => Enum[qw(0 1)], optional => 0 },
            smtp_plausibility    => { type => Enum[qw(0 1)], optional => 0 },
            rbl                  => { type => Enum[qw(0 1)], optional => 0 },
            bypass_banned_checks => { type => Enum[qw(0 1)], optional => 0 },
            tag2level            => { type => Str, optional => 0 },
            killevel             => { type => Enum[qw(reject route)], optional => 0 },
            route_to             => { type => Str, optional => 0 },

        },
    ),

);


sub get ($self, %params) {
    my $validator = $validators{'get'};
    %params       = $validator->(%params) if $validator;

lib/API/MailboxOrg/API/Test.pm  view on Meta::CPAN

with 'MooX::Singleton';

use feature 'signatures';
no warnings 'experimental::signatures';

our $VERSION = '1.0.2'; # VERSION

my %validators = (
    'accountallowed' => validation_for(
        params => {
            account => { type => Str, optional => 0 },

        },
    ),
    'domainallowed' => validation_for(
        params => {
            domain => { type => Str, optional => 0 },

        },
    ),

);


sub accountallowed ($self, %params) {
    my $validator = $validators{'accountallowed'};
    %params       = $validator->(%params) if $validator;

lib/API/MailboxOrg/API/Utils.pm  view on Meta::CPAN

with 'MooX::Singleton';

use feature 'signatures';
no warnings 'experimental::signatures';

our $VERSION = '1.0.2'; # VERSION

my %validators = (
    'validator' => validation_for(
        params => {
            value => { type => Str, optional => 0 },
            type  => { type => Enum[qw(hostname domain mailhost mail account pass pass2 memo user contextid name)], optional => 0 },

        },
    ),

);


sub validator ($self, %params) {
    my $validator = $validators{'validator'};
    %params       = $validator->(%params) if $validator;

lib/API/MailboxOrg/API/Utils.pm  view on Meta::CPAN

=head2 validator

Performs a validation

Parameters:

=over 4

=item * value

=item * type

=back

returns: boolean

    $api->utils->validator(%params);

=head1 AUTHOR

Renee Baecker <reneeb@cpan.org>

lib/API/MailboxOrg/API/Validate.pm  view on Meta::CPAN

with 'MooX::Singleton';

use feature 'signatures';
no warnings 'experimental::signatures';

our $VERSION = '1.0.2'; # VERSION

my %validators = (
    'spf' => validation_for(
        params => {
            domain => { type => Str, optional => 0 },

        },
    ),

);


sub spf ($self, %params) {
    my $validator = $validators{'spf'};
    %params       = $validator->(%params) if $validator;

lib/API/MailboxOrg/API/Videochat.pm  view on Meta::CPAN

with 'MooX::Singleton';

use feature 'signatures';
no warnings 'experimental::signatures';

our $VERSION = '1.0.2'; # VERSION

my %validators = (
    'add' => validation_for(
        params => {
            mail      => { type => Str, optional => 0 },
            room_name => { type => Str, optional => 0 },
            room_memo => { type => Str, optional => 1 },

        },
    ),
    'del' => validation_for(
        params => {
            mail    => { type => Str, optional => 0 },
            room_id => { type => Int, optional => 0 },

        },
    ),
    'list' => validation_for(
        params => {
            mail => { type => Str, optional => 0 },

        },
    ),
    'update' => validation_for(
        params => {
            mail                => { type => Str, optional => 0 },
            room_id             => { type => Int, optional => 0 },
            room_name           => { type => Str, optional => 1 },
            room_password       => { type => Str, optional => 1 },
            room_admin_password => { type => Str, optional => 1 },
            room_memo           => { type => Str, optional => 1 },

        },
    ),

);


sub add ($self, %params) {
    my $validator = $validators{'add'};
    %params       = $validator->(%params) if $validator;

lib/API/MailboxOrg/Types.pm  view on Meta::CPAN

use v5.24;

use strict;
use warnings;

use Type::Library
   -base,
   -declare => qw( HashRefRestricted Boolean );

use Type::Utils -all;
use Types::Standard -types;

use Carp;
use JSON::PP;
use Scalar::Util qw(blessed);

our $VERSION = '1.0.2'; # VERSION

my $meta = __PACKAGE__->meta;

$meta->add_type(
    name => 'HashRefRestricted',
    parent => HashRef,
    constraint_generator => sub {
        return $meta->get_type('HashRefRestricted') if !@_;

        my @keys = @_;

        croak "Need a list of valid keys" if !@keys;

        my %valid_keys = map { $_ => 1 } @keys;

        return sub {
            return if ref $_ ne 'HASH';
            return 1 if !$_->%*;

lib/API/MailboxOrg/Types.pm  view on Meta::CPAN

        };
    },
    coercion_generator => sub {
        my ($parent, $child, $param) = @_;
        return $parent->coercion;
    },
    #inline_generator => sub {},
    #deep_explanation => sub {},
);

$meta->add_type(
    name => 'Boolean',
    parent => InstanceOf['JSON::PP::Boolean'],
    constraint_generator => sub {
        return $meta->get_type('Boolean') if !@_;

        return sub {
            return if ! ( blessed $_ and $_->isa('JSON::PP::Boolean') );
            return 1;
        };
    },
    coercion_generator => sub {
        my ($parent, $child, $param) = @_;
        return $parent->coercion;
    },

perlcritic.rc  view on Meta::CPAN

[-Subroutines::ProhibitSubroutinePrototypes]

t/author-no-bom.t  view on Meta::CPAN

    'lib/API/MailboxOrg/API/Passwordreset.pm',
    'lib/API/MailboxOrg/API/Spamprotect.pm',
    'lib/API/MailboxOrg/API/Test.pm',
    'lib/API/MailboxOrg/API/Utils.pm',
    'lib/API/MailboxOrg/API/Validate.pm',
    'lib/API/MailboxOrg/API/Videochat.pm',
    'lib/API/MailboxOrg/APIBase.pm',
    'lib/API/MailboxOrg/Types.pm',
    't/001_base.t',
    't/002_hello-world.t',
    't/types/001_hashref_restricted.t',
    't/types/002_boolean.t'
);

ok(file_hasnt_bom($_)) for @files;

done_testing;

t/author-no-tabs.t  view on Meta::CPAN

    'lib/API/MailboxOrg/API/Passwordreset.pm',
    'lib/API/MailboxOrg/API/Spamprotect.pm',
    'lib/API/MailboxOrg/API/Test.pm',
    'lib/API/MailboxOrg/API/Utils.pm',
    'lib/API/MailboxOrg/API/Validate.pm',
    'lib/API/MailboxOrg/API/Videochat.pm',
    'lib/API/MailboxOrg/APIBase.pm',
    'lib/API/MailboxOrg/Types.pm',
    't/001_base.t',
    't/002_hello-world.t',
    't/types/001_hashref_restricted.t',
    't/types/002_boolean.t'
);

notabs_ok($_) foreach @files;
done_testing;

t/types/001_hashref_restricted.t  view on Meta::CPAN

use Test::Spec;
use Test::Exception;

use File::Basename;
use lib dirname(__FILE__);

use API::MailboxOrg::Types qw(HashRefRestricted);

describe 'HashRefRestricted' => sub {
    it 'allows an empty hash' => sub {
        my $type = HashRefRestricted([qw/a b/]); # allow keys a and b only
        ok $type->( {} );
    };

    it 'allows only the defined keys, using all allowed keys' => sub {
        my $type = HashRefRestricted([qw/a b/]); # allow keys a and b only
        ok $type->( { a => 1, b => 2 } );
    };

    it 'allows only the defined keys, using a subset of the keys' => sub {
        my $type = HashRefRestricted([qw/a b/]); # allow keys a and b only
        ok $type->( { a => 1 } );
    };

    it 'dies on disallowed keys' => sub {
        my $type = HashRefRestricted([qw/a b/]); # allow keys a and b only
        dies_ok { $type->( { c => 1 } ) };
    };

    it 'dies on disallowed keys, even when allowed keys are present' => sub {
        my $type = HashRefRestricted([qw/a b/]); # allow keys a and b only
        dies_ok { $type->( { c => 1, a => 2 } ) };
    };

    it 'dies on non-hashrefs - arrayref' => sub {
        my $type = HashRefRestricted([qw/a b/]); # allow keys a and b only
        dies_ok { $type->( [] ) };
    };
};

runtests if !caller;

t/types/002_boolean.t  view on Meta::CPAN

    use API::MailboxOrg::Types qw(Boolean);

    has true_or_false => ( is => 'rw', isa => Boolean, coerce => 1 );

    1;
}

describe 'Boolean' => sub {

    it 'allows a JSON::PP::true' => sub {
        my $type = Boolean();
        ok $type->( $JSON::PP::true );
    };

    it 'allows a JSON::PP::false' => sub {
        my $type = Boolean();
        is $type->( $JSON::PP::false ), 0;
        isa_ok $type->( $JSON::PP::false ), 'JSON::PP::Boolean';
    };
};

describe "TestClass' true_or_false" => sub {

    it 'allows a JSON::PP::true' => sub {
        my $obj = TestClass->new;

        lives_ok {
            $obj->true_or_false( $JSON::PP::true );



( run in 1.518 second using v1.01-cache-2.11-cpan-df04353d9ac )