diff --git a/.circleci/checksetup_answers.txt b/.circleci/checksetup_answers.txt index 272c436c04..029f67cc8e 100644 --- a/.circleci/checksetup_answers.txt +++ b/.circleci/checksetup_answers.txt @@ -13,3 +13,12 @@ $answer{'urlbase'} = 'http://bmo.test/'; $answer{'mail_delivery_method'} = 'Test'; $answer{'auth_delegation'} = 1; $answer{'utf8'} = 'utf8mb4'; +$answer{'oauth2_client_enabled'} = 1, +$answer{'oauth2_client_id'} = 'client_id'; +$answer{'oauth2_client_secret'} = 'client_secret'; +$answer{'oauth2_client_authorize_url'} = '/oauth/test/authorize'; +$answer{'oauth2_client_scopes'} = 'openid profile email'; +$answer{'mozilla_iam_enabled'} = 1; +$answer{'mozilla_iam_person_api_client_id'} = 'client_id'; +$answer{'mozilla_iam_person_api_client_secret'} = 'client_secret'; +$answer{'mozilla_iam_mandatory_domains'} = 'mozilla.com'; diff --git a/.circleci/config.yml b/.circleci/config.yml index 9dd20fc450..49424267cc 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -193,8 +193,8 @@ jobs: name: run sanity tests command: | [[ -f build_info/only_version_changed.txt ]] && exit 0 - docker-compose -f docker-compose.test.yml run --no-deps bmo.test \ - test_sanity $(circleci tests glob 't/*.t' 'extensions/*/t/*.t' | \ + docker-compose -f docker-compose.test.yml run -e CIRCLE_JOB=$CIRCLE_JOB \ + --no-deps bmo.test test_sanity $(circleci tests glob 't/*.t' 'extensions/*/t/*.t' | \ circleci tests split) | tee artifacts/$CIRCLE_JOB.txt - store_artifacts: path: /app/artifacts @@ -222,8 +222,8 @@ jobs: at: /app/build_info - run: | [[ -f build_info/only_version_changed.txt ]] && exit 0 - docker-compose -f docker-compose.test.yml run bmo.test test_webservices | \ - tee artifacts/$CIRCLE_JOB.txt + docker-compose -f docker-compose.test.yml run -e CIRCLE_JOB=$CIRCLE_JOB \ + bmo.test test_webservices | tee artifacts/$CIRCLE_JOB.txt - store_artifacts: path: /app/artifacts - *store_log @@ -250,8 +250,8 @@ jobs: at: /app/build_info - run: | [[ -f build_info/only_version_changed.txt ]] && exit 0 - docker-compose -f docker-compose.test.yml run bmo.test test_selenium | \ - tee artifacts/$CIRCLE_JOB.txt + docker-compose -f docker-compose.test.yml run -e CIRCLE_JOB=$CIRCLE_JOB \ + bmo.test test_selenium | tee artifacts/$CIRCLE_JOB.txt - store_artifacts: path: /app/artifacts - *store_log @@ -276,9 +276,13 @@ jobs: [[ -d artifacts ]] || mkdir artifacts - attach_workspace: at: /app/build_info - - run: | - [[ -f build_info/only_version_changed.txt ]] && exit 0 - docker-compose -f docker-compose.test.yml run bmo.test test_bmo -q -f t/bmo/*.t + - run: + name: run bmo specific tests + command: | + [[ -f build_info/only_version_changed.txt ]] && exit 0 + docker-compose -f docker-compose.test.yml run -e CI=1 -e CIRCLE_JOB=$CIRCLE_JOB \ + bmo.test test_bmo -q -f $(circleci tests glob 't/bmo/*.t' 'extensions/*/t/bmo/*.t' | \ + circleci tests split) | tee artifacts/$CIRCLE_JOB.txt - *store_log workflows: diff --git a/Bugzilla.pm b/Bugzilla.pm index 7397a7611c..c7a358bbc8 100644 --- a/Bugzilla.pm +++ b/Bugzilla.pm @@ -206,15 +206,15 @@ sub page_requires_login { return request_cache->{page_requires_login}; } -sub github_secret { +sub github_token { my ($class) = @_; my $cache = request_cache; my $cgi = $class->cgi; - $cache->{github_secret} //= $cgi->cookie('github_secret') + $cache->{github_token} //= $cgi->cookie('github_token') // generate_random_password(256); - return $cache->{github_secret}; + return $cache->{github_token}; } sub passwdqc { diff --git a/Bugzilla/API/V1/User.pm b/Bugzilla/API/V1/User.pm index 23f6392473..3ffba98899 100644 --- a/Bugzilla/API/V1/User.pm +++ b/Bugzilla/API/V1/User.pm @@ -31,6 +31,7 @@ sub user_profile { groups => [map { $_->name } @{$user->groups}], mfa => lc($user->mfa), mfa_required_by_group => $user->in_mfa_group ? true : false, + iam_username => $user->iam_username, } ); } diff --git a/Bugzilla/App.pm b/Bugzilla/App.pm index b6ff12c5d4..b92d5bc455 100644 --- a/Bugzilla/App.pm +++ b/Bugzilla/App.pm @@ -25,7 +25,7 @@ use Bugzilla::App::API; use Bugzilla::App::BouncedEmails; use Bugzilla::App::CGI; use Bugzilla::App::Main; -use Bugzilla::App::OAuth2::Clients; +use Bugzilla::App::OAuth2::Provider::Clients; use Bugzilla::App::SES; use Bugzilla::App::Static; use Mojo::Loader qw( find_modules ); @@ -53,7 +53,8 @@ sub startup { unless $ENV{BUGZILLA_DISABLE_SIZELIMIT}; $self->plugin('ForwardedFor') if Bugzilla->has_feature('better_xff'); $self->plugin('Bugzilla::App::Plugin::Helpers'); - $self->plugin('Bugzilla::App::Plugin::OAuth2'); + $self->plugin('Bugzilla::App::Plugin::OAuth2::Client'); + $self->plugin('Bugzilla::App::Plugin::OAuth2::Provider'); push @{$self->commands->namespaces}, 'Bugzilla::App::Command'; push @{$self->renderer->paths}, @{ Bugzilla::Template::_include_path() }; @@ -201,7 +202,7 @@ sub setup_routes { Bugzilla::App::BouncedEmails->setup_routes($r); Bugzilla::App::CGI->setup_routes($r); Bugzilla::App::Main->setup_routes($r); - Bugzilla::App::OAuth2::Clients->setup_routes($r); + Bugzilla::App::OAuth2::Provider::Clients->setup_routes($r); Bugzilla::App::SES->setup_routes($r); $r->static_file('/__lbheartbeat__'); diff --git a/Bugzilla/App/API.pm b/Bugzilla/App/API.pm index b971df783b..c0027c5faf 100644 --- a/Bugzilla/App/API.pm +++ b/Bugzilla/App/API.pm @@ -10,6 +10,7 @@ package Bugzilla::App::API; use 5.10.1; use Mojo::Base qw( Mojolicious::Controller ); +use File::Basename qw(basename); use Mojo::Loader qw( find_modules ); use Module::Runtime qw(require_module); use Try::Tiny; @@ -22,18 +23,20 @@ use constant SUPPORTED_VERSIONS => qw(V1); sub setup_routes { my ($class, $r) = @_; - # Add Bugzilla::API to namespaces for searching for controllers + # Add Bugzilla::API and Bugzilla::Extension to + # namespaces for searching for API controllers my $namespaces = $r->namespaces; - push @$namespaces, 'Bugzilla::API'; + push @$namespaces, 'Bugzilla::API', 'Bugzilla::Extension'; $r->namespaces($namespaces); # Backwards compat with /api/user/profile which Phabricator requires - $r->under('/api' => sub { - my ($c) = @_; - _insert_rest_headers($c); - Bugzilla->usage_mode(USAGE_MODE_REST); - }) - ->get('/user/profile')->to('V1::User#user_profile'); + $r->under( + '/api' => sub { + my ($c) = @_; + _insert_rest_headers($c); + Bugzilla->usage_mode(USAGE_MODE_REST); + } + )->get('/user/profile')->to('V1::User#user_profile'); # Other backwards compat routes $r->under( @@ -60,22 +63,46 @@ sub setup_routes { } ); + # Standard API support foreach my $version (SUPPORTED_VERSIONS) { foreach my $module (find_modules("Bugzilla::API::$version")) { - try { - require_module($module); - my $controller = $module->new; - if ($controller->can('setup_routes')) { - $controller->setup_routes($rest_routes); - } + _load_api_module($rest_routes, $module); + } + } + + # Extension API support + my @ext_paths = glob bz_locations()->{'extensionsdir'} . '/*'; + my @ext_api_paths = grep { !-e "$_/disabled" && -d "$_/lib/API" } @ext_paths; + + foreach my $version (SUPPORTED_VERSIONS) { + foreach my $ext_path (@ext_api_paths) { + my $ext_name = $ext_path; + $ext_name =~ s|^.*extensions/||; + + my @module_paths = glob "$ext_path/lib/API/$version/*"; + foreach my $module_path (@module_paths) { + my $module = "Bugzilla::Extension::${ext_name}::API::${version}::" + . basename($module_path, '.pm'); + _load_api_module($rest_routes, $module); } - catch { - WARN("$module could not be loaded"); - }; } } } +sub _load_api_module { + my ($routes, $module) = @_; + try { + require_module($module); + my $controller = $module->new; + if ($controller->can('setup_routes')) { + $controller->setup_routes($routes); + } + } + catch { + WARN("$module could not be loaded"); + }; +} + sub _insert_rest_headers { my ($c) = @_; @@ -83,8 +110,10 @@ sub _insert_rest_headers { my @allowed_headers = qw(accept authorization content-type origin user-agent x-bugzilla-api-key x-requested-with); $c->res->headers->header('Access-Control-Allow-Origin' => '*'); - $c->res->headers->header('Access-Control-Allow-Headers' => - join ', ', @allowed_headers); + $c->res->headers->header( + 'Access-Control-Allow-Headers' => join ', ', + @allowed_headers + ); } 1; diff --git a/Bugzilla/App/Main.pm b/Bugzilla/App/Main.pm index 5c06b55f36..6909c98b8c 100644 --- a/Bugzilla/App/Main.pm +++ b/Bugzilla/App/Main.pm @@ -26,7 +26,7 @@ sub setup_routes { sub root { my ($c) = @_; $c->res->headers->cache_control('public, max-age=3600, immutable'); - $c->render(handler => 'bugzilla'); + $c->render('index', handler => 'bugzilla'); } sub testagent { diff --git a/Bugzilla/App/OAuth2/Clients.pm b/Bugzilla/App/OAuth2/Provider/Clients.pm similarity index 85% rename from Bugzilla/App/OAuth2/Clients.pm rename to Bugzilla/App/OAuth2/Provider/Clients.pm index 11d8b53777..25d7c411b9 100644 --- a/Bugzilla/App/OAuth2/Clients.pm +++ b/Bugzilla/App/OAuth2/Provider/Clients.pm @@ -5,7 +5,7 @@ # This Source Code Form is "Incompatible With Secondary Licenses", as # defined by the Mozilla Public License, v. 2.0. -package Bugzilla::App::OAuth2::Clients; +package Bugzilla::App::OAuth2::Provider::Clients; use 5.10.1; use Mojo::Base 'Mojolicious::Controller'; @@ -20,7 +20,7 @@ sub setup_routes { # Manage the client list my $client_route = $r->under( - '/admin/oauth' => sub { + '/admin/oauth/provider' => sub { my ($c) = @_; Bugzilla->usage_mode(USAGE_MODE_MOJO); my $user = $c->bugzilla->login(LOGIN_REQUIRED) || return undef; @@ -30,12 +30,12 @@ sub setup_routes { return 1; } ); - $client_route->any('/list')->to('OAuth2::Clients#list')->name('list_clients'); - $client_route->any('/create')->to('OAuth2::Clients#create') + $client_route->any('/list')->to('OAuth2::Provider::Clients#list')->name('list_clients'); + $client_route->any('/create')->to('OAuth2::Provider::Clients#create') ->name('create_client'); - $client_route->any('/delete')->to('OAuth2::Clients#delete') + $client_route->any('/delete')->to('OAuth2::Provider::Clients#delete') ->name('delete_client'); - $client_route->any('/edit')->to('OAuth2::Clients#edit')->name('edit_client'); + $client_route->any('/edit')->to('OAuth2::Provider::Clients#edit')->name('edit_client'); } # Show list of clients @@ -44,7 +44,7 @@ sub list { my $clients = Bugzilla->dbh->selectall_arrayref('SELECT * FROM oauth2_client', {Slice => {}}); $self->stash(clients => $clients); - return $self->render(template => 'admin/oauth/list', handler => 'bugzilla'); + return $self->render(template => 'admin/oauth/provider/list', handler => 'bugzilla'); } # Create new client @@ -60,7 +60,7 @@ sub create { $vars->{scopes} = $dbh->selectall_arrayref('SELECT * FROM oauth2_scope', {Slice => {}}); $self->stash(%{$vars}); - return $self->render(template => 'admin/oauth/create', handler => 'bugzilla'); + return $self->render(template => 'admin/oauth/provider/create', handler => 'bugzilla'); } $dbh->bz_start_transaction; @@ -107,7 +107,7 @@ sub create { $vars->{'client'} = {description => $description}; $vars->{'clients'} = $clients; $self->stash(%{$vars}); - return $self->render(template => 'admin/oauth/list', handler => 'bugzilla'); + return $self->render(template => 'admin/oauth/provider/list', handler => 'bugzilla'); } # Delete client @@ -126,7 +126,7 @@ sub delete { $vars->{'token'} = issue_session_token('delete_oauth_client'); $self->stash(%{$vars}); return $self->render( - template => 'admin/oauth/confirm-delete', + template => 'admin/oauth/provider/confirm-delete', handler => 'bugzilla' ); } @@ -149,7 +149,7 @@ sub delete { $vars->{'client'} = {description => $client_data->{description}}; $vars->{'clients'} = $clients; $self->stash(%{$vars}); - return $self->render(template => 'admin/oauth/list', handler => 'bugzilla'); + return $self->render(template => 'admin/oauth/provider/list', handler => 'bugzilla'); } # Edit client @@ -177,7 +177,7 @@ sub edit { if ($self->req->method ne 'POST') { $vars->{token} = issue_session_token('edit_oauth_client'); $self->stash(%{$vars}); - return $self->render(template => 'admin/oauth/edit', handler => 'bugzilla'); + return $self->render(template => 'admin/oauth/provider/edit', handler => 'bugzilla'); } $dbh->bz_start_transaction; @@ -216,7 +216,7 @@ sub edit { $vars->{'client'} = {description => $description}; $vars->{'clients'} = $clients; $self->stash(%{$vars}); - return $self->render(template => 'admin/oauth/list', handler => 'bugzilla'); + return $self->render(template => 'admin/oauth/provider/list', handler => 'bugzilla'); } 1; diff --git a/Bugzilla/App/Plugin/OAuth2/Client.pm b/Bugzilla/App/Plugin/OAuth2/Client.pm new file mode 100644 index 0000000000..4d8da58f21 --- /dev/null +++ b/Bugzilla/App/Plugin/OAuth2/Client.pm @@ -0,0 +1,145 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. + +package Bugzilla::App::Plugin::OAuth2::Client; +use 5.10.1; +use Mojo::Base 'Mojolicious::Plugin'; + +use Bugzilla; +use Bugzilla::Constants; +use Bugzilla::Logging; +use Bugzilla::Hook; +use Bugzilla::Util qw(mojo_user_agent); + +use Mojo::Parameters; +use Mojo::URL; +use Try::Tiny; + +sub register { + my ($self, $app) = @_; + my $params = Bugzilla->params; + + return unless $params->{oauth2_client_enabled}; + + $app->helper( + 'oauth2.auth_url' => sub { + my ($c, $type, $args) = @_; + my $params = Bugzilla->params; + + $args->{scope} ||= $params->{oauth2_client_scopes}; + $args->{redirect_uri} ||= $c->url_for->to_abs->to_string; + + my $authorize_url = Mojo::URL->new($params->{oauth2_client_authorize_url}); + $authorize_url->query->append( + client_id => $params->{oauth2_client_id}, + redirect_uri => $args->{redirect_uri}, + response_type => 'code', + ); + if (defined $args->{scope}) { + $authorize_url->query->append(scope => $args->{scope}); + } + if (defined $args->{state}) { + $authorize_url->query->append(state => $args->{state}); + } + + return $authorize_url; + } + ); + + $app->helper( + 'oauth2.get_token' => sub { + my ($c, $args) = @_; + my $params = Bugzilla->params; + + if ($ENV{CI}) { + return { + access_token => 'fake_access_token', + expires_in => 3600, + refresh_token => 'fake_refresh_token', + scope => 'openid profile email', + token_type => 'bearer', + }; + } + + my $data = { + client_id => $params->{oauth2_client_id}, + client_secret => $params->{oauth2_client_secret}, + code => scalar($c->param('code')), + grant_type => 'authorization_code', + redirect_uri => $c->url_for->to_abs->to_string, + }; + + my $token_url = Mojo::URL->new($params->{oauth2_client_token_url}); + $token_url = $token_url->to_abs; + + try { + my $tx = mojo_user_agent()->post($token_url, form => $data); + die $tx->result->message if !$tx->result->is_success; + return $tx->res->headers->content_type =~ /^application\/json/ + ? $tx->res->json + : Mojo::Parameters->new($tx->res->body)->to_hash; + } + catch { + WARN("ERROR: Could not get oauth2 token: $_"); + return {}; + }; + } + ); + + # Get information about user from OAuth2 provider + $app->helper( + 'oauth2.userinfo' => sub { + my ($c, $access_token) = @_; + my $params = Bugzilla->params; + + if ($ENV{CI} && $ENV{BZ_TEST_OAUTH2_NORMAL_USER}) { + return { + email => $ENV{BZ_TEST_OAUTH2_NORMAL_USER}, + name => 'OAuth2 Test User', + email_verified => 1, + }; + } + + try { + my $tx = mojo_user_agent()->get( + $params->{'oauth2_client_userinfo_url'}, + {Authorization => 'Bearer ' . $access_token}, + ); + die $tx->result->message if !$tx->result->is_success; + return $tx->result->json || {}; + } + catch { + WARN("ERROR: Could not get userinfo: $_"); + return {}; + }; + } + ); + + $app->helper( + 'oauth2.redirect_uri' => sub { + my ($c, $redirect) = @_; + return Bugzilla->localconfig->urlbase . 'oauth2.cgi?redirect=' . $redirect; + } + ); + + # Add special routes for CI testing that mocks a providers login + if ($ENV{CI}) { + $app->routes->get( + '/oauth/test/authorize' => sub { + my $c = shift; + my $url = Mojo::URL->new($c->param('redirect_uri')); + $url->query->append(code => 'fake_return_code'); + $url->query->append(state => $c->param('state')); + $c->render(text => $c->tag('a', href => $url, sub {'Connect'})); + }, + ); + } + + Bugzilla::Hook::process('oauth2_client_register', {app => $app}); +} + +1; diff --git a/Bugzilla/App/Plugin/OAuth2.pm b/Bugzilla/App/Plugin/OAuth2/Provider.pm similarity index 99% rename from Bugzilla/App/Plugin/OAuth2.pm rename to Bugzilla/App/Plugin/OAuth2/Provider.pm index 6afa29c304..951a22a14a 100644 --- a/Bugzilla/App/Plugin/OAuth2.pm +++ b/Bugzilla/App/Plugin/OAuth2/Provider.pm @@ -5,7 +5,7 @@ # This Source Code Form is "Incompatible With Secondary Licenses", as # defined by the Mozilla Public License, v. 2.0. -package Bugzilla::App::Plugin::OAuth2; +package Bugzilla::App::Plugin::OAuth2::Provider; use 5.10.1; use Mojo::Base 'Mojolicious::Plugin::OAuth2::Server'; diff --git a/Bugzilla/Auth/Login/OAuth2.pm b/Bugzilla/Auth/Login/OAuth2.pm new file mode 100644 index 0000000000..64552fb451 --- /dev/null +++ b/Bugzilla/Auth/Login/OAuth2.pm @@ -0,0 +1,46 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. + +package Bugzilla::Auth::Login::OAuth2; + +use 5.10.1; +use strict; +use warnings; + +use base qw(Bugzilla::Auth::Login); + +use Bugzilla::Constants; +use Bugzilla::Token qw(issue_hash_token); + +use constant can_logout => 0; +use constant can_login => 0; +use constant requires_verification => 0; +use constant is_automatic => 1; + +sub get_login_info { + my ($self) = @_; + my $cache = Bugzilla->request_cache; + my $params = Bugzilla->params; + my $cgi = Bugzilla->cgi; + + return {failure => AUTH_NODATA} if !$params->{oauth2_client_enabled}; + + my $userinfo = delete $cache->{oauth2_client_userinfo}; + + Bugzilla::Hook::process('oauth2_client_handle_redirect', + {userinfo => $userinfo}); + + return {failure => AUTH_NODATA} if !$userinfo; + + if ($userinfo->{email} && $userinfo->{email_verified}) { + return {username => $userinfo->{email}, realname => $userinfo->{name}}; + } + + return {failure => AUTH_NODATA}; +} + +1; diff --git a/Bugzilla/Auth/Persist/Cookie.pm b/Bugzilla/Auth/Persist/Cookie.pm index 12c882b25d..fc32845039 100644 --- a/Bugzilla/Auth/Persist/Cookie.pm +++ b/Bugzilla/Auth/Persist/Cookie.pm @@ -71,7 +71,7 @@ sub persist_login { $cookieargs{'-secure'} = 1; } - $cgi->remove_cookie('github_secret'); + $cgi->remove_cookie('github_token'); $cgi->remove_cookie('Bugzilla_login_request_cookie'); $cgi->send_cookie(-name => 'Bugzilla_login', -value => $user->id, %cookieargs); $cgi->send_cookie( diff --git a/Bugzilla/CGI.pm b/Bugzilla/CGI.pm index 6df5571b4b..4d7a55efab 100644 --- a/Bugzilla/CGI.pm +++ b/Bugzilla/CGI.pm @@ -389,12 +389,12 @@ sub header { # We generate a cookie and store it in the request cache # To initiate GitHub login, a form POSTs to github.cgi with the - # github_secret as a parameter. It must match the github_secret cookie. + # github_token as a parameter. It must match the github_token cookie. # this prevents some types of redirection attacks. unless ($user->id || $self->{bz_redirecting}) { $self->send_cookie( - -name => 'github_secret', - -value => Bugzilla->github_secret, + -name => 'github_token', + -value => Bugzilla->github_token, -httponly => 1 ); } diff --git a/Bugzilla/Config/Auth.pm b/Bugzilla/Config/Auth.pm index 664c1b2639..c451494d57 100644 --- a/Bugzilla/Config/Auth.pm +++ b/Bugzilla/Config/Auth.pm @@ -37,7 +37,7 @@ sub get_param_list { { name => 'user_info_class', type => 's', - choices => ['CGI', 'Env', 'Env,CGI'], + choices => ['CGI', 'OAuth2,CGI', 'Env', 'Env,CGI', 'Env,OAuth2,CGI'], default => 'CGI', checker => \&check_multi }, diff --git a/Bugzilla/Config/OAuth2Client.pm b/Bugzilla/Config/OAuth2Client.pm new file mode 100644 index 0000000000..1b007d7877 --- /dev/null +++ b/Bugzilla/Config/OAuth2Client.pm @@ -0,0 +1,35 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. + +package Bugzilla::Config::OAuth2Client; + +use 5.10.1; +use strict; +use warnings; + +use Bugzilla::Config::Common; + +our $sortkey = 1350; + +sub get_param_list { + my ($class) = @_; + + my @params = ( + {name => 'oauth2_client_enabled', type => 'b', default => 0,}, + {name => 'oauth2_client_domain', type => 't', default => '',}, + {name => 'oauth2_client_id', type => 't', default => '',}, + {name => 'oauth2_client_secret', type => 't', default => '',}, + {name => 'oauth2_client_token_url', type => 't', default => '',}, + {name => 'oauth2_client_authorize_url', type => 't', default => '',}, + {name => 'oauth2_client_userinfo_url', type => 't', default => '',}, + {name => 'oauth2_client_scopes', type => 't', default => '',}, + ); + + return @params; +} + +1; diff --git a/Bugzilla/Report/Ping/Simple.pm b/Bugzilla/Report/Ping/Simple.pm index f879124fa0..105fa1793e 100644 --- a/Bugzilla/Report/Ping/Simple.pm +++ b/Bugzilla/Report/Ping/Simple.pm @@ -9,7 +9,7 @@ package Bugzilla::Report::Ping::Simple; use 5.10.1; use Moo; -use JSON::Validator qw(joi); +use JSON::Validator::Joi qw(joi); our $VERSION = '1'; diff --git a/Bugzilla/Template.pm b/Bugzilla/Template.pm index 5b9f6606c4..8010273eed 100644 --- a/Bugzilla/Template.pm +++ b/Bugzilla/Template.pm @@ -539,9 +539,7 @@ our $is_processing = 0; sub process { my ($self, $input, $vars, $output) = @_; $vars //= {}; - if (($ENV{SERVER_SOFTWARE} // '') eq 'Bugzilla::App::CGI') { - $vars->{self} = $vars->{c} = Bugzilla->request_cache->{mojo_controller}; - } + $vars->{self} = $vars->{c} = Bugzilla->request_cache->{mojo_controller}; # All of this current_langs stuff allows template_inner to correctly # determine what-language Template object it should instantiate. diff --git a/Bugzilla/Test/MockParams.pm b/Bugzilla/Test/MockParams.pm index 8ad21920c9..0580cb2b79 100644 --- a/Bugzilla/Test/MockParams.pm +++ b/Bugzilla/Test/MockParams.pm @@ -51,7 +51,7 @@ sub import { (override => [closed_bug_statuses => sub { die "no database" },],); # prod-like defaults - $answers{user_info_class} //= 'GitHubAuth,CGI'; + $answers{user_info_class} //= 'GitHubAuth,OAuth2,CGI'; $answers{user_verify_class} //= 'GitHubAuth,DB'; if ($first_time++) { diff --git a/Bugzilla/Test/Selenium.pm b/Bugzilla/Test/Selenium.pm index da658f1070..48e531256f 100644 --- a/Bugzilla/Test/Selenium.pm +++ b/Bugzilla/Test/Selenium.pm @@ -23,11 +23,16 @@ has 'driver' => ( handles => [qw( add_cookie alert_text_like + body_text_contains + body_text_lacks + click_element_ok get_all_cookies get_ok get_title go_back_ok refresh + send_keys_to_active_element + set_implicit_wait_timeout title_is title_isnt title_like @@ -390,7 +395,7 @@ sub submit { my ($self, $locator) = @_; TRACE("submit: $locator"); $locator = $self->_fix_locator($locator); - $self->find_element($locator)->submit(); + my $element = $self->find_element($locator)->submit(); } sub is_editable { @@ -464,4 +469,115 @@ sub _toggle_check { return 0; } +# New utility methods used by t/bmo/*.t tests +# Use these for any new scripts + +sub get_token { + my $token; + my $count = 0; + do { + sleep 1 if $count++; + open my $fh, '<', '/app/data/mailer.testfile'; + my $content = do { + local $/ = undef; + <$fh>; + }; + ($token) = $content =~ m!/token\.cgi\?t=3D([^&]+)&a=3Dcfmpw!s; + close $fh; + } until $token || $count > 60; + return $token; +} + +sub search_mailer_testfile { + my ($self, $regexp) = @_; + my $content = ""; + my @result; + my $count = 0; + do { + sleep 1 if $count++; + open my $fh, '<', '/app/data/mailer.testfile'; + $content .= do { + local $/ = undef; + <$fh>; + }; + close $fh; + my $decoded = $content; + $decoded =~ s/\r\n/\n/gs; + $decoded =~ s/=\n//gs; + $decoded =~ s/=([[:xdigit:]]{2})/chr(hex($1))/ges; + @result = $decoded =~ $regexp; + } until @result || $count > 60; + return @result; +} + +sub click_and_type { + my ($self, $name, $text) = @_; + $self->click_ok(qq{//*[\@id="bugzilla-body"]//input[\@name="$name"]}, "Click on $name"); + $self->send_keys_to_active_element($text); +} + +sub click_link { + my ($self, $text) = @_; + my $el = $self->find_element($text, 'link_text'); + $el->click(); +} + +sub change_password { + my ($self, $old, $new1, $new2) = @_; + $self->get_ok('/userprefs.cgi?tab=account', 'Go to user preferences'); + $self->title_is('User Preferences', 'User preferences loaded'); + $self->click_and_type('old_password', $old); + $self->click_and_type('new_password1', $new1); + $self->click_and_type('new_password2', $new2); + $self->click_ok('//input[@value="Submit Changes"]'); +} + +sub toggle_require_password_change { + my ($self, $login) = @_; + $self->get_ok('/editusers.cgi', 'Go to edit users'); + $self->title_is('Search users', 'Edit users loaded'); + $self->type_ok('matchstr', $login, "Type $login for search"); + $self->click_ok('//input[@id="search"]'); + $self->title_is('Select user', 'Select a user loaded'); + $self->click_link($login); + $self->find_element('//input[@id="password_change_required"]')->click; + $self->click_ok('//input[@id="update"]'); + $self->title_is("User $login updated", "User $login updated"); +} + +sub enable_user_account { + my ($self, $login) = @_; + $self->get_ok('/editusers.cgi', 'Go to edit users'); + $self->title_is('Search users', 'Edit users loaded'); + $self->type_ok('matchstr', $login, "Type $login for search"); + $self->click_ok('//input[@id="search"]'); + $self->title_is('Select user', 'Select a user loaded'); + $self->click_link($login); + $self->type_ok('disabledtext', '', 'Clear disabled text'); + $self->uncheck_ok('disable_mail'); + $self->click_ok('//input[@id="update"]'); + $self->title_is("User $login updated", "User $login updated"); +} + +sub login { + my ($self, $username, $password) = @_; + $self->get_ok('/login', undef, 'Go to the home page'); + $self->title_is('Log in to Bugzilla', 'Log in to Bugzilla'); + $self->type_ok('Bugzilla_login', $username, "Enter login name $username"); + $self->type_ok('Bugzilla_password', $password, "Enter password $password"); + $self->click_ok('log_in', undef, 'Submit credentials'); +} + +sub login_ok { + my $self = shift; + $self->login(@_); + $self->title_is('Bugzilla Main Page', 'User is logged in'); +} + +sub logout_ok { + my ($self) = @_; + $self->get_ok('/index.cgi?logout=1', 'Logout current user'); + $self->title_is('Logged Out', 'Logged Out'); +} + 1; diff --git a/Bugzilla/Test/Util.pm b/Bugzilla/Test/Util.pm index fa6dd3686d..16abd9ce5d 100644 --- a/Bugzilla/Test/Util.pm +++ b/Bugzilla/Test/Util.pm @@ -13,8 +13,9 @@ use warnings; use base qw(Exporter); our @EXPORT - = qw(create_user create_bug create_oauth_client issue_api_key mock_useragent_tx); + = qw(create_user create_bug create_group create_oauth_client issue_api_key mock_useragent_tx); +use Bugzilla::Group; use Bugzilla::User; use Bugzilla::Bug; use Bugzilla::User::APIKey; @@ -43,6 +44,16 @@ sub create_user { }); } +sub create_group { + my ($group, %extra) = @_; + require Bugzilla; + return Bugzilla::Group->create({ + name => $group, + description => "$group Group Description", + %extra, + }); +} + sub create_oauth_client { my ($description, $scopes) = @_; my $dbh = Bugzilla->dbh; diff --git a/Bugzilla/User.pm b/Bugzilla/User.pm index fa55d33e0f..70f89802d8 100644 --- a/Bugzilla/User.pm +++ b/Bugzilla/User.pm @@ -261,9 +261,9 @@ sub new { sub super_user { my $invocant = shift; my $class = ref($invocant) || $invocant; - my ($param) = @_; - my $user = {%{DEFAULT_USER()}}; + my $user = Bugzilla::User->new({name => 'automation@bmo.tld'}); + $user ||= {%{DEFAULT_USER()}}; $user->{groups} = [Bugzilla::Group->get_all]; $user->{bless_groups} = [Bugzilla::Group->get_all]; bless $user, $class; @@ -368,30 +368,34 @@ sub update { # IAM usernames are stored separately from normal profiles # data so we update them here instead - my $new_iam_username = delete $self->{new_iam_username}; - my $old_iam_username = $self->iam_username; + if (exists $self->{new_iam_username}) { + my $new_iam_username = delete $self->{new_iam_username}; + my $old_iam_username = $self->iam_username; - $dbh->bz_start_transaction(); - if (!defined $old_iam_username && $new_iam_username) { - $dbh->do('INSERT INTO profiles_iam (user_id, iam_username) VALUES (?, ?)', - undef, $self->id, $new_iam_username); - $changes->{iam_username} = ['', $new_iam_username]; - } - elsif ($old_iam_username && !$new_iam_username) { - $dbh->do('DELETE FROM profiles_iam WHERE user_id = ?', undef, $self->id); - $changes->{iam_username} = [$old_iam_username, '']; - } - elsif ($old_iam_username ne $new_iam_username) { - $dbh->do('UPDATE profiles_iam SET iam_username = ? WHERE user_id = ?', - undef, $new_iam_username, $self->id); - $changes->{iam_username} = [$old_iam_username, $new_iam_username]; - } - if (exists $changes->{iam_username}) { - $self->audit_log({iam_username => $changes->{iam_username}}) - if $self->AUDIT_UPDATES; - $self->{iam_username} = defined $new_iam_username ? $new_iam_username : undef; + $dbh->bz_start_transaction(); + + if (!defined $old_iam_username && $new_iam_username) { + $dbh->do('INSERT INTO profiles_iam (user_id, iam_username) VALUES (?, ?)', + undef, $self->id, $new_iam_username); + $changes->{iam_username} = ['', $new_iam_username]; + } + elsif ($old_iam_username && !$new_iam_username) { + $dbh->do('DELETE FROM profiles_iam WHERE user_id = ?', undef, $self->id); + $changes->{iam_username} = [$old_iam_username, '']; + } + elsif ($old_iam_username ne $new_iam_username) { + $dbh->do('UPDATE profiles_iam SET iam_username = ? WHERE user_id = ?', + undef, $new_iam_username, $self->id); + $changes->{iam_username} = [$old_iam_username, $new_iam_username]; + } + if (exists $changes->{iam_username}) { + $self->audit_log({iam_username => $changes->{iam_username}}) + if $self->AUDIT_UPDATES; + $self->{iam_username} = defined $new_iam_username ? $new_iam_username : undef; + } + + $dbh->bz_commit_transaction(); } - $dbh->bz_commit_transaction(); # Logout the user if necessary. Bugzilla->logout_user($self) @@ -446,7 +450,7 @@ sub check_login_name_for_creation { # Check the name if it's a new user, or if we're changing the name. if (!ref($invocant) || $invocant->login ne $name) { - is_available_username($name) + is_available_username($name, (ref $invocant ? $invocant->login : undef)) || ThrowUserError('account_exists', {email => $name}); } @@ -521,7 +525,8 @@ sub _check_iam_username { validate_email_syntax($username) || ThrowUserError('iam_illegal_username', {username => $username}); - if ($username ne $self->iam_username) { + my $iam_username = $self->iam_username || ''; + if ($username && $username ne $iam_username) { my $existing_username = Bugzilla->dbh->selectrow_array( 'SELECT iam_username FROM profiles_iam WHERE iam_username = ?', @@ -649,8 +654,6 @@ sub _set_groups { my $changes = shift; my $dbh = Bugzilla->dbh; - use Data::Dumper; - # The person making the change is $user, $self is the person being changed my $user = Bugzilla->user; @@ -768,8 +771,9 @@ sub password_change_reason { $_[0]->{password_change_reason}; } sub iam_username { my $self = shift; + return $self->{iam_username} if exists $self->{iam_username}; return $self->{iam_username} - ||= Bugzilla->dbh->selectrow_array( + = Bugzilla->dbh->selectrow_array( 'SELECT iam_username FROM profiles_iam WHERE user_id = ?', undef, $self->id); } diff --git a/Bugzilla/Util.pm b/Bugzilla/Util.pm index 8853df05c9..e0cbec2907 100644 --- a/Bugzilla/Util.pm +++ b/Bugzilla/Util.pm @@ -28,7 +28,7 @@ use base qw(Exporter); validate_email_syntax clean_text get_text template_var disable_utf8 enable_utf8 detect_encoding email_filter - round extract_nicks); + round extract_nicks mojo_user_agent); use Bugzilla::Logging; use Bugzilla::Constants; use Bugzilla::RNG qw(irand); @@ -971,6 +971,21 @@ sub extract_nicks { return grep { defined $_ } @nicks; } +sub mojo_user_agent { + my $ua = Mojo::UserAgent->new( + request_timeout => 5, + connect_timeout => 5, + inactivity_timesout => 30 + ); + if (my $proxy = Bugzilla->params->{proxy_url}) { + $ua->proxy->http($proxy)->https($proxy); + } + else { + $ua->proxy->detect(); + } + $ua->transactor->name('Bugzilla'); + return $ua; +} 1; diff --git a/Bugzilla/WebService/User.pm b/Bugzilla/WebService/User.pm index c2acfb33de..bce1fa412a 100644 --- a/Bugzilla/WebService/User.pm +++ b/Bugzilla/WebService/User.pm @@ -509,13 +509,14 @@ sub whoami { return filter( $params, { - id => $self->type('int', $user->id), - real_name => $self->type('string', $user->name), - nick => $self->type('string', $user->nick), - name => $self->type('email', $user->login), - mfa_status => $self->type('boolean', !!$user->mfa), - groups => [map { $_->name } @{$user->groups}], - uuid => $self->type('string', 'bmo-who:' . $uuid), + id => $self->type('int', $user->id), + real_name => $self->type('string', $user->name), + nick => $self->type('string', $user->nick), + name => $self->type('email', $user->login), + mfa_status => $self->type('boolean', !!$user->mfa), + groups => [map { $_->name } @{$user->groups}], + uuid => $self->type('string', 'bmo-who:' . $uuid), + iam_username => $self->type('string', $user->iam_username), } ); } diff --git a/Dockerfile b/Dockerfile index 653c48fe5a..c6cc173ef9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM mozillabteam/bmo-perl-slim:20200505.1 +FROM mozillabteam/bmo-perl-slim:20210105.1 ENV DEBIAN_FRONTEND noninteractive diff --git a/Dockerfile.bmo-slim b/Dockerfile.bmo-slim index 15c93afdd0..dc60e2b3d9 100644 --- a/Dockerfile.bmo-slim +++ b/Dockerfile.bmo-slim @@ -1,4 +1,4 @@ -FROM perl:5.30.2-slim AS builder +FROM perl:5.32.0-slim AS builder RUN apt-get update RUN apt-get install -y \ @@ -33,7 +33,7 @@ RUN find local -name '*.so' -exec ldd {} \; \ | xargs -IFILE apt-file search -l FILE \ | sort -u > PACKAGES -FROM perl:5.30.2-slim +FROM perl:5.32.0-slim ENV DEBIAN_FRONTEND noninteractive diff --git a/Dockerfile.cpanfile b/Dockerfile.cpanfile index c5c0ad842c..41c4cf5cb5 100644 --- a/Dockerfile.cpanfile +++ b/Dockerfile.cpanfile @@ -1,4 +1,4 @@ -FROM perl:5.30.2-slim +FROM perl:5.32.0-slim RUN apt-get update RUN apt-get install -y \ diff --git a/Makefile.PL b/Makefile.PL index 8cadfe6a5d..cd526e9780 100755 --- a/Makefile.PL +++ b/Makefile.PL @@ -46,6 +46,8 @@ my %requires = ( 'CPAN::Meta::Prereqs' => '2.132830', 'CPAN::Meta::Requirements' => '2.121', 'Class::XSAccessor' => '1.18', + 'Crypt::OpenSSL::Bignum' => 0, + 'Crypt::OpenSSL::RSA' => 0, 'DBI' => '1.614', 'DBIx::Connector' => 0, 'DBIx::Class' => 0, @@ -80,6 +82,7 @@ my %requires = ( 'Mojo::JWT' => '0.07', 'MojoX::Log::Log4perl' => '0.04', 'Mojolicious' => '8.42', + 'Mojolicious::Plugin::OAuth2' => '1.58', 'Mojolicious::Plugin::OAuth2::Server' => '0.44', 'Moo' => '2.002004', 'MooX::StrictConstructor' => '0.008', diff --git a/conf/checksetup_answers.txt b/conf/checksetup_answers.txt index b83f6d0ba3..b2faf8432c 100644 --- a/conf/checksetup_answers.txt +++ b/conf/checksetup_answers.txt @@ -11,7 +11,7 @@ $answer{'db_check'} = 1; $answer{'diffpath'} = '/usr/bin'; $answer{'index_html'} = 0; $answer{'interdiffbin'} = '/usr/bin/interdiff'; -$answer{'user_info_class'} = 'GitHubAuth,CGI'; +$answer{'user_info_class'} = 'GitHubAuth,OAuth2,CGI'; $answer{'user_verify_class'} = 'GitHubAuth,DB'; $answer{'use_mailer_queue'} = 1; $answer{'useclassification'} = 1; diff --git a/cpanfile b/cpanfile index 58dca6c0cf..41cdba93b5 100644 --- a/cpanfile +++ b/cpanfile @@ -18,6 +18,8 @@ requires 'Crypt::CBC'; requires 'Crypt::DES'; requires 'Crypt::DES_EDE3'; requires 'Crypt::OpenPGP', '1.12'; +requires 'Crypt::OpenSSL::Bignum'; +requires 'Crypt::OpenSSL::RSA'; requires 'Crypt::SMIME'; requires 'DBD::mysql', '4.037'; requires 'DBI', '1.614'; @@ -81,6 +83,7 @@ requires 'Mojo::JWT', '0.07'; requires 'MojoX::Log::Log4perl', '0.04'; requires 'Mojolicious', '8.42'; requires 'Mojolicious::Plugin::ForwardedFor'; +requires 'Mojolicious::Plugin::OAuth2', '1.58'; requires 'Mojolicious::Plugin::OAuth2::Server', '0.44'; requires 'Moo', '2.002004'; requires 'MooX::StrictConstructor', '0.008'; diff --git a/cpanfile.snapshot b/cpanfile.snapshot index 3082704500..6a4910622e 100644 --- a/cpanfile.snapshot +++ b/cpanfile.snapshot @@ -7,101 +7,101 @@ DISTRIBUTIONS requirements: ExtUtils::MakeMaker 0 List::Util 0 - Algorithm-C3-0.10 - pathname: H/HA/HAARG/Algorithm-C3-0.10.tar.gz + Algorithm-C3-0.11 + pathname: H/HA/HAARG/Algorithm-C3-0.11.tar.gz provides: - Algorithm::C3 0.10 + Algorithm::C3 0.11 requirements: Carp 0.01 ExtUtils::MakeMaker 0 - Test::More 0.47 perl 5.006 - Algorithm-Diff-1.1903 - pathname: T/TY/TYEMQ/Algorithm-Diff-1.1903.tar.gz - provides: - Algorithm::Diff 1.1903 - Algorithm::Diff::_impl 1.1903 - requirements: - ExtUtils::MakeMaker 0 - Alien-Build-2.22 - pathname: P/PL/PLICEASE/Alien-Build-2.22.tar.gz - provides: - Alien::Base 2.22 - Alien::Base::PkgConfig 2.22 - Alien::Base::Wrapper 2.22 - Alien::Build 2.22 - Alien::Build::CommandSequence 2.22 - Alien::Build::Helper 2.22 - Alien::Build::Interpolate 2.22 - Alien::Build::Interpolate::Default 2.22 - Alien::Build::Interpolate::Helper 2.22 - Alien::Build::Log 2.22 - Alien::Build::Log::Abbreviate 2.22 - Alien::Build::Log::Default 2.22 - Alien::Build::MM 2.22 - Alien::Build::Meta 2.22 - Alien::Build::Plugin 2.22 - Alien::Build::Plugin::Build::Autoconf 2.22 - Alien::Build::Plugin::Build::CMake 2.22 - Alien::Build::Plugin::Build::Copy 2.22 - Alien::Build::Plugin::Build::MSYS 2.22 - Alien::Build::Plugin::Build::Make 2.22 - Alien::Build::Plugin::Build::SearchDep 2.22 - Alien::Build::Plugin::Core::CleanInstall 2.22 - Alien::Build::Plugin::Core::Download 2.22 - Alien::Build::Plugin::Core::FFI 2.22 - Alien::Build::Plugin::Core::Gather 2.22 - Alien::Build::Plugin::Core::Legacy 2.22 - Alien::Build::Plugin::Core::Override 2.22 - Alien::Build::Plugin::Core::Setup 2.22 - Alien::Build::Plugin::Core::Tail 2.22 - Alien::Build::Plugin::Decode::DirListing 2.22 - Alien::Build::Plugin::Decode::DirListingFtpcopy 2.22 - Alien::Build::Plugin::Decode::HTML 2.22 - Alien::Build::Plugin::Decode::Mojo 2.22 - Alien::Build::Plugin::Download::Negotiate 2.22 - Alien::Build::Plugin::Extract::ArchiveTar 2.22 - Alien::Build::Plugin::Extract::ArchiveZip 2.22 - Alien::Build::Plugin::Extract::CommandLine 2.22 - Alien::Build::Plugin::Extract::Directory 2.22 - Alien::Build::Plugin::Extract::Negotiate 2.22 - Alien::Build::Plugin::Fetch::CurlCommand 2.22 - Alien::Build::Plugin::Fetch::HTTPTiny 2.22 - Alien::Build::Plugin::Fetch::LWP 2.22 - Alien::Build::Plugin::Fetch::Local 2.22 - Alien::Build::Plugin::Fetch::LocalDir 2.22 - Alien::Build::Plugin::Fetch::NetFTP 2.22 - Alien::Build::Plugin::Fetch::Wget 2.22 - Alien::Build::Plugin::Gather::IsolateDynamic 2.22 - Alien::Build::Plugin::PkgConfig::CommandLine 2.22 - Alien::Build::Plugin::PkgConfig::LibPkgConf 2.22 - Alien::Build::Plugin::PkgConfig::MakeStatic 2.22 - Alien::Build::Plugin::PkgConfig::Negotiate 2.22 - Alien::Build::Plugin::PkgConfig::PP 2.22 - Alien::Build::Plugin::Prefer::BadVersion 2.22 - Alien::Build::Plugin::Prefer::GoodVersion 2.22 - Alien::Build::Plugin::Prefer::SortVersions 2.22 - Alien::Build::Plugin::Probe::CBuilder 2.22 - Alien::Build::Plugin::Probe::CommandLine 2.22 - Alien::Build::Plugin::Probe::Vcpkg 2.22 - Alien::Build::Plugin::Test::Mock 2.22 - Alien::Build::PluginMeta 2.22 - Alien::Build::Temp 2.22 - Alien::Build::TempDir 2.22 - Alien::Build::Util 2.22 - Alien::Build::Version::Basic 2.22 - Alien::Build::rc 2.22 - Alien::Role 2.22 - Test::Alien 2.22 - Test::Alien::Build 2.22 - Test::Alien::CanCompile 2.22 - Test::Alien::CanPlatypus 2.22 - Test::Alien::Diag 2.22 - Test::Alien::Run 2.22 - Test::Alien::Synthetic 2.22 - alienfile 2.22 + Algorithm-Diff-1.201 + pathname: R/RJ/RJBS/Algorithm-Diff-1.201.tar.gz + provides: + Algorithm::Diff 1.201 + Algorithm::Diff::_impl 1.201 + requirements: + ExtUtils::MakeMaker 0 + Alien-Build-2.38 + pathname: P/PL/PLICEASE/Alien-Build-2.38.tar.gz + provides: + Alien::Base 2.38 + Alien::Base::PkgConfig 2.38 + Alien::Base::Wrapper 2.38 + Alien::Build 2.38 + Alien::Build::CommandSequence 2.38 + Alien::Build::Helper 2.38 + Alien::Build::Interpolate 2.38 + Alien::Build::Interpolate::Default 2.38 + Alien::Build::Interpolate::Helper 2.38 + Alien::Build::Log 2.38 + Alien::Build::Log::Abbreviate 2.38 + Alien::Build::Log::Default 2.38 + Alien::Build::MM 2.38 + Alien::Build::Meta 2.38 + Alien::Build::Plugin 2.38 + Alien::Build::Plugin::Build::Autoconf 2.38 + Alien::Build::Plugin::Build::CMake 2.38 + Alien::Build::Plugin::Build::Copy 2.38 + Alien::Build::Plugin::Build::MSYS 2.38 + Alien::Build::Plugin::Build::Make 2.38 + Alien::Build::Plugin::Build::SearchDep 2.38 + Alien::Build::Plugin::Core::CleanInstall 2.38 + Alien::Build::Plugin::Core::Download 2.38 + Alien::Build::Plugin::Core::FFI 2.38 + Alien::Build::Plugin::Core::Gather 2.38 + Alien::Build::Plugin::Core::Legacy 2.38 + Alien::Build::Plugin::Core::Override 2.38 + Alien::Build::Plugin::Core::Setup 2.38 + Alien::Build::Plugin::Core::Tail 2.38 + Alien::Build::Plugin::Decode::DirListing 2.38 + Alien::Build::Plugin::Decode::DirListingFtpcopy 2.38 + Alien::Build::Plugin::Decode::HTML 2.38 + Alien::Build::Plugin::Decode::Mojo 2.38 + Alien::Build::Plugin::Download::Negotiate 2.38 + Alien::Build::Plugin::Extract::ArchiveTar 2.38 + Alien::Build::Plugin::Extract::ArchiveZip 2.38 + Alien::Build::Plugin::Extract::CommandLine 2.38 + Alien::Build::Plugin::Extract::Directory 2.38 + Alien::Build::Plugin::Extract::Negotiate 2.38 + Alien::Build::Plugin::Fetch::CurlCommand 2.38 + Alien::Build::Plugin::Fetch::HTTPTiny 2.38 + Alien::Build::Plugin::Fetch::LWP 2.38 + Alien::Build::Plugin::Fetch::Local 2.38 + Alien::Build::Plugin::Fetch::LocalDir 2.38 + Alien::Build::Plugin::Fetch::NetFTP 2.38 + Alien::Build::Plugin::Fetch::Wget 2.38 + Alien::Build::Plugin::Gather::IsolateDynamic 2.38 + Alien::Build::Plugin::PkgConfig::CommandLine 2.38 + Alien::Build::Plugin::PkgConfig::LibPkgConf 2.38 + Alien::Build::Plugin::PkgConfig::MakeStatic 2.38 + Alien::Build::Plugin::PkgConfig::Negotiate 2.38 + Alien::Build::Plugin::PkgConfig::PP 2.38 + Alien::Build::Plugin::Prefer::BadVersion 2.38 + Alien::Build::Plugin::Prefer::GoodVersion 2.38 + Alien::Build::Plugin::Prefer::SortVersions 2.38 + Alien::Build::Plugin::Probe::CBuilder 2.38 + Alien::Build::Plugin::Probe::CommandLine 2.38 + Alien::Build::Plugin::Probe::Vcpkg 2.38 + Alien::Build::Plugin::Test::Mock 2.38 + Alien::Build::PluginMeta 2.38 + Alien::Build::Temp 2.38 + Alien::Build::TempDir 2.38 + Alien::Build::Util 2.38 + Alien::Build::Version::Basic 2.38 + Alien::Build::rc 2.38 + Alien::Role 2.38 + Test::Alien 2.38 + Test::Alien::Build 2.38 + Test::Alien::CanCompile 2.38 + Test::Alien::CanPlatypus 2.38 + Test::Alien::Diag 2.38 + Test::Alien::Run 2.38 + Test::Alien::Synthetic 2.38 + alienfile 2.38 requirements: Capture::Tiny 0.17 + Digest::SHA 0 ExtUtils::CBuilder 0 ExtUtils::MakeMaker 6.64 ExtUtils::ParseXS 3.30 @@ -113,7 +113,7 @@ DISTRIBUTIONS Path::Tiny 0.077 Test2::API 1.302096 Text::ParseWords 3.26 - perl 5.008001 + perl 5.008004 Alien-Build-Git-0.08 pathname: P/PL/PLICEASE/Alien-Build-Git-0.08.tar.gz provides: @@ -145,7 +145,6 @@ DISTRIBUTIONS Alien::Base 0.92 Alien::Build 1.19 Alien::Build::MM 0.32 - Alien::Build::Plugin::Fetch::CurlCommand 1.19 Capture::Tiny 0 ExtUtils::MakeMaker 6.52 File::Which 0 @@ -305,10 +304,10 @@ DISTRIBUTIONS IO::Seekable 0 Time::Local 0 perl 5.006 - Auth-GoogleAuth-1.02 - pathname: G/GR/GRYPHON/Auth-GoogleAuth-1.02.tar.gz + Auth-GoogleAuth-1.03 + pathname: G/GR/GRYPHON/Auth-GoogleAuth-1.03.tar.gz provides: - Auth::GoogleAuth 1.02 + Auth::GoogleAuth 1.03 requirements: Carp 0 Class::Accessor 0 @@ -378,19 +377,19 @@ DISTRIBUTIONS Scalar::Util 1.21 Test::More 0.98 perl 5.006000 - CGI-4.47 - pathname: L/LE/LEEJO/CGI-4.47.tar.gz + CGI-4.51 + pathname: L/LE/LEEJO/CGI-4.51.tar.gz provides: - CGI 4.47 - CGI::Carp 4.47 - CGI::Cookie 4.47 - CGI::File::Temp 4.47 + CGI 4.51 + CGI::Carp 4.51 + CGI::Cookie 4.51 + CGI::File::Temp 4.51 CGI::HTML::Functions undef - CGI::MultipartBuffer 4.47 - CGI::Pretty 4.47 - CGI::Push 4.47 - CGI::Util 4.47 - Fh 4.47 + CGI::MultipartBuffer 4.51 + CGI::Pretty 4.51 + CGI::Push 4.51 + CGI::Util 4.51 + Fh 4.51 requirements: Carp 0 Config 0 @@ -407,10 +406,10 @@ DISTRIBUTIONS strict 0 utf8 0 warnings 0 - CGI-Compile-0.24 - pathname: R/RK/RKITOVER/CGI-Compile-0.24.tar.gz + CGI-Compile-0.25 + pathname: R/RK/RKITOVER/CGI-Compile-0.25.tar.gz provides: - CGI::Compile 0.24 + CGI::Compile 0.25 requirements: File::pushd 0 Module::Build::Tiny 0.034 @@ -433,10 +432,10 @@ DISTRIBUTIONS requirements: ExtUtils::MakeMaker 0 Test::More 0 - Cairo-1.107 - pathname: X/XA/XAOC/Cairo-1.107.tar.gz + Cairo-1.109 + pathname: X/XA/XAOC/Cairo-1.109.tar.gz provides: - Cairo 1.107 + Cairo 1.109 Cairo::Install::Files undef requirements: ExtUtils::Depends 0.2 @@ -601,14 +600,6 @@ DISTRIBUTIONS requirements: ExtUtils::MakeMaker 0 base 1.01 - Class-Accessor-Chained-0.01 - pathname: R/RC/RCLAMP/Class-Accessor-Chained-0.01.tar.gz - provides: - Class::Accessor::Chained 0.01 - Class::Accessor::Chained::Fast undef - requirements: - Class::Accessor 0 - Test::More 0 Class-Accessor-Grouped-0.10014 pathname: H/HA/HAARG/Class-Accessor-Grouped-0.10014.tar.gz provides: @@ -627,10 +618,10 @@ DISTRIBUTIONS Class::Accessor::Lite 0.08 requirements: ExtUtils::MakeMaker 6.36 - Class-C3-0.34 - pathname: H/HA/HAARG/Class-C3-0.34.tar.gz + Class-C3-0.35 + pathname: H/HA/HAARG/Class-C3-0.35.tar.gz provides: - Class::C3 0.34 + Class::C3 0.35 requirements: Algorithm::C3 0.07 ExtUtils::MakeMaker 0 @@ -713,17 +704,20 @@ DISTRIBUTIONS perl 5.006 strict 0 warnings 0 - Class-Singleton-1.5 - pathname: S/SH/SHAY/Class-Singleton-1.5.tar.gz + Class-Singleton-1.6 + pathname: S/SH/SHAY/Class-Singleton-1.6.tar.gz provides: - Class::Singleton 1.5 + Class::Singleton 1.6 requirements: - ExtUtils::MakeMaker 0 - Class-Tiny-1.006 - pathname: D/DA/DAGOLDEN/Class-Tiny-1.006.tar.gz + ExtUtils::MakeMaker 6.64 + perl 5.008001 + strict 0 + warnings 0 + Class-Tiny-1.008 + pathname: D/DA/DAGOLDEN/Class-Tiny-1.008.tar.gz provides: - Class::Tiny 1.006 - Class::Tiny::Object 1.006 + Class::Tiny 1.008 + Class::Tiny::Object 1.008 requirements: Carp 0 ExtUtils::MakeMaker 6.17 @@ -874,10 +868,10 @@ DISTRIBUTIONS Module::Build::Tiny 0.035 URI::Escape 0 perl 5.008001 - Cpanel-JSON-XS-4.19 - pathname: R/RU/RURBAN/Cpanel-JSON-XS-4.19.tar.gz + Cpanel-JSON-XS-4.25 + pathname: R/RU/RURBAN/Cpanel-JSON-XS-4.25.tar.gz provides: - Cpanel::JSON::XS 4.19 + Cpanel::JSON::XS 4.25 Cpanel::JSON::XS::Type undef requirements: Carp 0 @@ -964,17 +958,17 @@ DISTRIBUTIONS IDEA 1.10 requirements: ExtUtils::MakeMaker 0 - Crypt-JWT-0.026 - pathname: M/MI/MIK/Crypt-JWT-0.026.tar.gz + Crypt-JWT-0.031 + pathname: M/MI/MIK/Crypt-JWT-0.031.tar.gz provides: - Crypt::JWT 0.026 - Crypt::KeyWrap 0.026 + Crypt::JWT 0.031 + Crypt::KeyWrap 0.031 requirements: Compress::Raw::Zlib 0 CryptX 0.067 Exporter 5.57 ExtUtils::MakeMaker 0 - JSON::MaybeXS 1.003005 + JSON 0 Scalar::Util 0 Test::More 0 perl 5.006 @@ -1063,11 +1057,46 @@ DISTRIBUTIONS MIME::Base64 0 Math::BigInt 0 URI::Escape 0 - Crypt-RIPEMD160-0.06 - pathname: T/TO/TODDR/Crypt-RIPEMD160-0.06.tar.gz + Crypt-OpenSSL-Bignum-0.09 + pathname: K/KM/KMX/Crypt-OpenSSL-Bignum-0.09.tar.gz provides: - Crypt::RIPEMD160 0.06 - Crypt::RIPEMD160::MAC 0.01 + Crypt::OpenSSL::Bignum 0.09 + Crypt::OpenSSL::Bignum::CTX undef + requirements: + ExtUtils::MakeMaker 0 + perl 5.006002 + Crypt-OpenSSL-Guess-0.11 + pathname: A/AK/AKIYM/Crypt-OpenSSL-Guess-0.11.tar.gz + provides: + Crypt::OpenSSL::Guess 0.11 + requirements: + Config 0 + Exporter 5.57 + ExtUtils::MakeMaker 6.64 + File::Spec 0 + Symbol 0 + perl 5.008001 + Crypt-OpenSSL-RSA-0.31 + pathname: T/TO/TODDR/Crypt-OpenSSL-RSA-0.31.tar.gz + provides: + Crypt::OpenSSL::RSA 0.31 + requirements: + Crypt::OpenSSL::Random 0 + ExtUtils::MakeMaker 0 + Test::More 0 + perl 5.006 + Crypt-OpenSSL-Random-0.15 + pathname: R/RU/RURBAN/Crypt-OpenSSL-Random-0.15.tar.gz + provides: + Crypt::OpenSSL::Random 0.15 + requirements: + Crypt::OpenSSL::Guess 0.11 + ExtUtils::MakeMaker 0 + Crypt-RIPEMD160-0.08 + pathname: T/TO/TODDR/Crypt-RIPEMD160-0.08.tar.gz + provides: + Crypt::RIPEMD160 0.08 + Crypt::RIPEMD160::MAC 0.08 requirements: ExtUtils::MakeMaker 0 Test::More 0 @@ -1099,17 +1128,17 @@ DISTRIBUTIONS Time::HiRes 1.9711 base 0 perl 5.006002 - Crypt-Rijndael-1.14 - pathname: L/LE/LEONT/Crypt-Rijndael-1.14.tar.gz + Crypt-Rijndael-1.15 + pathname: L/LE/LEONT/Crypt-Rijndael-1.15.tar.gz provides: - Crypt::Rijndael 1.14 + Crypt::Rijndael 1.15 requirements: ExtUtils::MakeMaker 0 perl 5.006 - Crypt-SMIME-0.25 - pathname: M/MI/MIKAGE/Crypt-SMIME-0.25.tar.gz + Crypt-SMIME-0.27 + pathname: M/MI/MIKAGE/Crypt-SMIME-0.27.tar.gz provides: - Crypt::SMIME 0.25 + Crypt::SMIME 0.27 requirements: ExtUtils::CChecker 0 ExtUtils::Constant 0.23 @@ -1118,136 +1147,136 @@ DISTRIBUTIONS Test::Exception 0 Test::More 0 XSLoader 0 - Crypt-Twofish-2.17 - pathname: A/AM/AMS/Crypt-Twofish-2.17.tar.gz + Crypt-Twofish-2.18 + pathname: A/AM/AMS/Crypt-Twofish-2.18.tar.gz provides: - Crypt::Twofish 2.17 + Crypt::Twofish 2.18 requirements: ExtUtils::MakeMaker 0 strict 0 - CryptX-0.068 - pathname: M/MI/MIK/CryptX-0.068.tar.gz - provides: - Crypt::AuthEnc 0.068 - Crypt::AuthEnc::CCM 0.068 - Crypt::AuthEnc::ChaCha20Poly1305 0.068 - Crypt::AuthEnc::EAX 0.068 - Crypt::AuthEnc::GCM 0.068 - Crypt::AuthEnc::OCB 0.068 - Crypt::Checksum 0.068 - Crypt::Checksum::Adler32 0.068 - Crypt::Checksum::CRC32 0.068 - Crypt::Cipher 0.068 - Crypt::Cipher::AES 0.068 - Crypt::Cipher::Anubis 0.068 - Crypt::Cipher::Blowfish 0.068 - Crypt::Cipher::CAST5 0.068 - Crypt::Cipher::Camellia 0.068 - Crypt::Cipher::DES 0.068 - Crypt::Cipher::DES_EDE 0.068 - Crypt::Cipher::IDEA 0.068 - Crypt::Cipher::KASUMI 0.068 - Crypt::Cipher::Khazad 0.068 - Crypt::Cipher::MULTI2 0.068 - Crypt::Cipher::Noekeon 0.068 - Crypt::Cipher::RC2 0.068 - Crypt::Cipher::RC5 0.068 - Crypt::Cipher::RC6 0.068 - Crypt::Cipher::SAFERP 0.068 - Crypt::Cipher::SAFER_K128 0.068 - Crypt::Cipher::SAFER_K64 0.068 - Crypt::Cipher::SAFER_SK128 0.068 - Crypt::Cipher::SAFER_SK64 0.068 - Crypt::Cipher::SEED 0.068 - Crypt::Cipher::Serpent 0.068 - Crypt::Cipher::Skipjack 0.068 - Crypt::Cipher::Twofish 0.068 - Crypt::Cipher::XTEA 0.068 - Crypt::Digest 0.068 - Crypt::Digest::BLAKE2b_160 0.068 - Crypt::Digest::BLAKE2b_256 0.068 - Crypt::Digest::BLAKE2b_384 0.068 - Crypt::Digest::BLAKE2b_512 0.068 - Crypt::Digest::BLAKE2s_128 0.068 - Crypt::Digest::BLAKE2s_160 0.068 - Crypt::Digest::BLAKE2s_224 0.068 - Crypt::Digest::BLAKE2s_256 0.068 - Crypt::Digest::CHAES 0.068 - Crypt::Digest::Keccak224 0.068 - Crypt::Digest::Keccak256 0.068 - Crypt::Digest::Keccak384 0.068 - Crypt::Digest::Keccak512 0.068 - Crypt::Digest::MD2 0.068 - Crypt::Digest::MD4 0.068 - Crypt::Digest::MD5 0.068 - Crypt::Digest::RIPEMD128 0.068 - Crypt::Digest::RIPEMD160 0.068 - Crypt::Digest::RIPEMD256 0.068 - Crypt::Digest::RIPEMD320 0.068 - Crypt::Digest::SHA1 0.068 - Crypt::Digest::SHA224 0.068 - Crypt::Digest::SHA256 0.068 - Crypt::Digest::SHA384 0.068 - Crypt::Digest::SHA3_224 0.068 - Crypt::Digest::SHA3_256 0.068 - Crypt::Digest::SHA3_384 0.068 - Crypt::Digest::SHA3_512 0.068 - Crypt::Digest::SHA512 0.068 - Crypt::Digest::SHA512_224 0.068 - Crypt::Digest::SHA512_256 0.068 - Crypt::Digest::SHAKE 0.068 - Crypt::Digest::Tiger192 0.068 - Crypt::Digest::Whirlpool 0.068 - Crypt::KeyDerivation 0.068 - Crypt::Mac 0.068 - Crypt::Mac::BLAKE2b 0.068 - Crypt::Mac::BLAKE2s 0.068 - Crypt::Mac::F9 0.068 - Crypt::Mac::HMAC 0.068 - Crypt::Mac::OMAC 0.068 - Crypt::Mac::PMAC 0.068 - Crypt::Mac::Pelican 0.068 - Crypt::Mac::Poly1305 0.068 - Crypt::Mac::XCBC 0.068 - Crypt::Misc 0.068 - Crypt::Mode 0.068 - Crypt::Mode::CBC 0.068 - Crypt::Mode::CFB 0.068 - Crypt::Mode::CTR 0.068 - Crypt::Mode::ECB 0.068 - Crypt::Mode::OFB 0.068 - Crypt::PK 0.068 - Crypt::PK::DH 0.068 - Crypt::PK::DSA 0.068 - Crypt::PK::ECC 0.068 - Crypt::PK::Ed25519 0.068 - Crypt::PK::RSA 0.068 - Crypt::PK::X25519 0.068 - Crypt::PRNG 0.068 - Crypt::PRNG::ChaCha20 0.068 - Crypt::PRNG::Fortuna 0.068 - Crypt::PRNG::RC4 0.068 - Crypt::PRNG::Sober128 0.068 - Crypt::PRNG::Yarrow 0.068 - Crypt::Stream::ChaCha 0.068 - Crypt::Stream::RC4 0.068 - Crypt::Stream::Rabbit 0.068 - Crypt::Stream::Salsa20 0.068 - Crypt::Stream::Sober128 0.068 - Crypt::Stream::Sosemanuk 0.068 - CryptX 0.068 - Math::BigInt::LTM 0.068 + CryptX-0.069 + pathname: M/MI/MIK/CryptX-0.069.tar.gz + provides: + Crypt::AuthEnc 0.069 + Crypt::AuthEnc::CCM 0.069 + Crypt::AuthEnc::ChaCha20Poly1305 0.069 + Crypt::AuthEnc::EAX 0.069 + Crypt::AuthEnc::GCM 0.069 + Crypt::AuthEnc::OCB 0.069 + Crypt::Checksum 0.069 + Crypt::Checksum::Adler32 0.069 + Crypt::Checksum::CRC32 0.069 + Crypt::Cipher 0.069 + Crypt::Cipher::AES 0.069 + Crypt::Cipher::Anubis 0.069 + Crypt::Cipher::Blowfish 0.069 + Crypt::Cipher::CAST5 0.069 + Crypt::Cipher::Camellia 0.069 + Crypt::Cipher::DES 0.069 + Crypt::Cipher::DES_EDE 0.069 + Crypt::Cipher::IDEA 0.069 + Crypt::Cipher::KASUMI 0.069 + Crypt::Cipher::Khazad 0.069 + Crypt::Cipher::MULTI2 0.069 + Crypt::Cipher::Noekeon 0.069 + Crypt::Cipher::RC2 0.069 + Crypt::Cipher::RC5 0.069 + Crypt::Cipher::RC6 0.069 + Crypt::Cipher::SAFERP 0.069 + Crypt::Cipher::SAFER_K128 0.069 + Crypt::Cipher::SAFER_K64 0.069 + Crypt::Cipher::SAFER_SK128 0.069 + Crypt::Cipher::SAFER_SK64 0.069 + Crypt::Cipher::SEED 0.069 + Crypt::Cipher::Serpent 0.069 + Crypt::Cipher::Skipjack 0.069 + Crypt::Cipher::Twofish 0.069 + Crypt::Cipher::XTEA 0.069 + Crypt::Digest 0.069 + Crypt::Digest::BLAKE2b_160 0.069 + Crypt::Digest::BLAKE2b_256 0.069 + Crypt::Digest::BLAKE2b_384 0.069 + Crypt::Digest::BLAKE2b_512 0.069 + Crypt::Digest::BLAKE2s_128 0.069 + Crypt::Digest::BLAKE2s_160 0.069 + Crypt::Digest::BLAKE2s_224 0.069 + Crypt::Digest::BLAKE2s_256 0.069 + Crypt::Digest::CHAES 0.069 + Crypt::Digest::Keccak224 0.069 + Crypt::Digest::Keccak256 0.069 + Crypt::Digest::Keccak384 0.069 + Crypt::Digest::Keccak512 0.069 + Crypt::Digest::MD2 0.069 + Crypt::Digest::MD4 0.069 + Crypt::Digest::MD5 0.069 + Crypt::Digest::RIPEMD128 0.069 + Crypt::Digest::RIPEMD160 0.069 + Crypt::Digest::RIPEMD256 0.069 + Crypt::Digest::RIPEMD320 0.069 + Crypt::Digest::SHA1 0.069 + Crypt::Digest::SHA224 0.069 + Crypt::Digest::SHA256 0.069 + Crypt::Digest::SHA384 0.069 + Crypt::Digest::SHA3_224 0.069 + Crypt::Digest::SHA3_256 0.069 + Crypt::Digest::SHA3_384 0.069 + Crypt::Digest::SHA3_512 0.069 + Crypt::Digest::SHA512 0.069 + Crypt::Digest::SHA512_224 0.069 + Crypt::Digest::SHA512_256 0.069 + Crypt::Digest::SHAKE 0.069 + Crypt::Digest::Tiger192 0.069 + Crypt::Digest::Whirlpool 0.069 + Crypt::KeyDerivation 0.069 + Crypt::Mac 0.069 + Crypt::Mac::BLAKE2b 0.069 + Crypt::Mac::BLAKE2s 0.069 + Crypt::Mac::F9 0.069 + Crypt::Mac::HMAC 0.069 + Crypt::Mac::OMAC 0.069 + Crypt::Mac::PMAC 0.069 + Crypt::Mac::Pelican 0.069 + Crypt::Mac::Poly1305 0.069 + Crypt::Mac::XCBC 0.069 + Crypt::Misc 0.069 + Crypt::Mode 0.069 + Crypt::Mode::CBC 0.069 + Crypt::Mode::CFB 0.069 + Crypt::Mode::CTR 0.069 + Crypt::Mode::ECB 0.069 + Crypt::Mode::OFB 0.069 + Crypt::PK 0.069 + Crypt::PK::DH 0.069 + Crypt::PK::DSA 0.069 + Crypt::PK::ECC 0.069 + Crypt::PK::Ed25519 0.069 + Crypt::PK::RSA 0.069 + Crypt::PK::X25519 0.069 + Crypt::PRNG 0.069 + Crypt::PRNG::ChaCha20 0.069 + Crypt::PRNG::Fortuna 0.069 + Crypt::PRNG::RC4 0.069 + Crypt::PRNG::Sober128 0.069 + Crypt::PRNG::Yarrow 0.069 + Crypt::Stream::ChaCha 0.069 + Crypt::Stream::RC4 0.069 + Crypt::Stream::Rabbit 0.069 + Crypt::Stream::Salsa20 0.069 + Crypt::Stream::Sober128 0.069 + Crypt::Stream::Sosemanuk 0.069 + CryptX 0.069 + Math::BigInt::LTM 0.069 requirements: ExtUtils::MakeMaker 0 perl 5.006 - DBD-SQLite-1.64 - pathname: I/IS/ISHIGAKI/DBD-SQLite-1.64.tar.gz + DBD-SQLite-1.66 + pathname: I/IS/ISHIGAKI/DBD-SQLite-1.66.tar.gz provides: - DBD::SQLite 1.64 + DBD::SQLite 1.66 DBD::SQLite::Constants undef DBD::SQLite::GetInfo undef - DBD::SQLite::VirtualTable 1.64 - DBD::SQLite::VirtualTable::Cursor 1.64 + DBD::SQLite::VirtualTable 1.66 + DBD::SQLite::VirtualTable::Cursor 1.66 DBD::SQLite::VirtualTable::FileContent undef DBD::SQLite::VirtualTable::FileContent::Cursor undef DBD::SQLite::VirtualTable::PerlData undef @@ -1376,10 +1405,10 @@ DISTRIBUTIONS ExtUtils::MakeMaker 6.48 Test::Simple 0.90 perl 5.008001 - DBIx-Class-0.082841 - pathname: R/RI/RIBASUSHI/DBIx-Class-0.082841.tar.gz + DBIx-Class-0.082842 + pathname: R/RI/RIBASUSHI/DBIx-Class-0.082842.tar.gz provides: - DBIx::Class 0.082841 + DBIx::Class 0.082842 DBIx::Class::AccessorGroup undef DBIx::Class::Admin undef DBIx::Class::CDBICompat undef @@ -1399,6 +1428,7 @@ DISTRIBUTIONS DBIx::Class::Relationship::Base undef DBIx::Class::ResultClass::HashRefInflator undef DBIx::Class::ResultSet undef + DBIx::Class::ResultSet::Pager undef DBIx::Class::ResultSetColumn undef DBIx::Class::ResultSetManager undef DBIx::Class::ResultSource undef @@ -1408,6 +1438,7 @@ DISTRIBUTIONS DBIx::Class::ResultSourceProxy::Table undef DBIx::Class::Row undef DBIx::Class::SQLMaker undef + DBIx::Class::SQLMaker::ClassicExtensions undef DBIx::Class::SQLMaker::LimitDialects undef DBIx::Class::SQLMaker::OracleJoins undef DBIx::Class::Schema undef @@ -1461,6 +1492,7 @@ DISTRIBUTIONS DBIx::Class::Storage::DBI::Sybase::Microsoft_SQL_Server::NoBindVars undef DBIx::Class::Storage::DBI::UniqueIdentifier undef DBIx::Class::Storage::DBI::mysql undef + DBIx::Class::Storage::Debug::PrettyTrace undef DBIx::Class::Storage::Statistics undef DBIx::Class::Storage::TxnScopeGuard undef DBIx::Class::UTF8Columns undef @@ -1475,18 +1507,16 @@ DISTRIBUTIONS DBD::SQLite 1.29 DBI 1.57 Data::Dumper::Concise 2.020 - Data::Page 2.00 Devel::GlobalDestruction 0.09 ExtUtils::MakeMaker 6.59 File::Temp 0.22 Hash::Merge 0.12 - List::Util 1.16 MRO::Compat 0.12 Module::Find 0.07 Moo 2.000 Package::Stash 0.28 Path::Class 0.18 - SQL::Abstract 1.81 + SQL::Abstract::Classic 1.91 Scope::Guard 0.03 Sub::Name 0.04 Test::Deep 0.101 @@ -1677,10 +1707,10 @@ DISTRIBUTIONS Exporter 0 ExtUtils::MakeMaker 0 perl 5.006 - Data-ObjectDriver-0.19 - pathname: S/SI/SIXAPART/Data-ObjectDriver-0.19.tar.gz + Data-ObjectDriver-0.21 + pathname: S/SI/SIXAPART/Data-ObjectDriver-0.21.tar.gz provides: - Data::ObjectDriver 0.19 + Data::ObjectDriver 0.21 Data::ObjectDriver::BaseObject undef Data::ObjectDriver::BaseView undef Data::ObjectDriver::Driver::BaseCache undef @@ -1689,6 +1719,7 @@ DISTRIBUTIONS Data::ObjectDriver::Driver::Cache::Memcached undef Data::ObjectDriver::Driver::Cache::RAM undef Data::ObjectDriver::Driver::DBD undef + Data::ObjectDriver::Driver::DBD::MariaDB undef Data::ObjectDriver::Driver::DBD::Oracle undef Data::ObjectDriver::Driver::DBD::Oracle::db undef Data::ObjectDriver::Driver::DBD::Pg undef @@ -1727,18 +1758,6 @@ DISTRIBUTIONS Sub::Install 0.921 strict 0 warnings 0 - Data-Page-2.03 - pathname: E/ET/ETHER/Data-Page-2.03.tar.gz - provides: - Data::Page 2.03 - requirements: - Carp 0 - Class::Accessor::Chained::Fast 0 - ExtUtils::MakeMaker 0 - base 0 - integer 0 - perl 5.006 - strict 0 Data-Password-passwdqc-0.09 pathname: S/SH/SHERWIN/Data-Password-passwdqc-0.09.tar.gz provides: @@ -1760,18 +1779,25 @@ DISTRIBUTIONS Scalar::Util 1.01 Storable 0 perl 5.008 - Data-Visitor-0.30 - pathname: D/DO/DOY/Data-Visitor-0.30.tar.gz + Data-Visitor-0.31 + pathname: E/ET/ETHER/Data-Visitor-0.31.tar.gz provides: - Data::Visitor 0.30 - Data::Visitor::Callback 0.30 + Data::Visitor 0.31 + Data::Visitor::Callback 0.31 requirements: - Class::Load 0.06 - ExtUtils::MakeMaker 6.30 + Carp 0 + ExtUtils::MakeMaker 0 Moose 0.89 - Task::Weaken 0 + Scalar::Util 0 + Sub::Name 0 + Symbol 0 Tie::ToObject 0.01 + constant 0 namespace::clean 0.19 + overload 0 + perl 5.006 + strict 0 + warnings 0 DataDog-DogStatsd-0.06 pathname: B/BI/BINARY/DataDog-DogStatsd-0.06.tar.gz provides: @@ -1780,23 +1806,23 @@ DISTRIBUTIONS requirements: ExtUtils::MakeMaker 0 IO::Socket::INET 0 - DateTime-1.52 - pathname: D/DR/DROLSKY/DateTime-1.52.tar.gz - provides: - DateTime 1.52 - DateTime::Duration 1.52 - DateTime::Helpers 1.52 - DateTime::Infinite 1.52 - DateTime::Infinite::Future 1.52 - DateTime::Infinite::Past 1.52 - DateTime::LeapSecond 1.52 - DateTime::PP 1.52 - DateTime::PPExtra 1.52 - DateTime::Types 1.52 + DateTime-1.54 + pathname: D/DR/DROLSKY/DateTime-1.54.tar.gz + provides: + DateTime 1.54 + DateTime::Duration 1.54 + DateTime::Helpers 1.54 + DateTime::Infinite 1.54 + DateTime::Infinite::Future 1.54 + DateTime::Infinite::Past 1.54 + DateTime::LeapSecond 1.54 + DateTime::PP 1.54 + DateTime::PPExtra 1.54 + DateTime::Types 1.54 requirements: Carp 0 DateTime::Locale 1.06 - DateTime::TimeZone 2.02 + DateTime::TimeZone 2.44 Dist::CheckConflicts 0.02 ExtUtils::MakeMaker 0 POSIX 0 @@ -1819,16 +1845,16 @@ DISTRIBUTIONS strict 0 warnings 0 warnings::register 0 - DateTime-Format-Builder-0.82 - pathname: D/DR/DROLSKY/DateTime-Format-Builder-0.82.tar.gz + DateTime-Format-Builder-0.83 + pathname: D/DR/DROLSKY/DateTime-Format-Builder-0.83.tar.gz provides: - DateTime::Format::Builder 0.82 - DateTime::Format::Builder::Parser 0.82 - DateTime::Format::Builder::Parser::Dispatch 0.82 - DateTime::Format::Builder::Parser::Quick 0.82 - DateTime::Format::Builder::Parser::Regex 0.82 - DateTime::Format::Builder::Parser::Strptime 0.82 - DateTime::Format::Builder::Parser::generic 0.82 + DateTime::Format::Builder 0.83 + DateTime::Format::Builder::Parser 0.83 + DateTime::Format::Builder::Parser::Dispatch 0.83 + DateTime::Format::Builder::Parser::Quick 0.83 + DateTime::Format::Builder::Parser::Regex 0.83 + DateTime::Format::Builder::Parser::Strptime 0.83 + DateTime::Format::Builder::Parser::generic 0.83 requirements: Carp 0 DateTime 1.00 @@ -1838,7 +1864,6 @@ DISTRIBUTIONS Scalar::Util 0 parent 0 strict 0 - vars 0 warnings 0 DateTime-Format-MySQL-0.06 pathname: X/XM/XMIKEW/DateTime-Format-MySQL-0.06.tar.gz @@ -1857,15 +1882,15 @@ DISTRIBUTIONS DateTime::Format::Builder 0.6 ExtUtils::MakeMaker 0 perl 5.003 - DateTime-Format-Strptime-1.77 - pathname: D/DR/DROLSKY/DateTime-Format-Strptime-1.77.tar.gz + DateTime-Format-Strptime-1.78 + pathname: D/DR/DROLSKY/DateTime-Format-Strptime-1.78.tar.gz provides: - DateTime::Format::Strptime 1.77 - DateTime::Format::Strptime::Types 1.77 + DateTime::Format::Strptime 1.78 + DateTime::Format::Strptime::Types 1.78 requirements: Carp 0 DateTime 1.00 - DateTime::Locale 1.23 + DateTime::Locale 1.30 DateTime::Locale::Base 0 DateTime::Locale::FromData 0 DateTime::TimeZone 2.09 @@ -1882,26 +1907,28 @@ DISTRIBUTIONS parent 0 strict 0 warnings 0 - DateTime-Locale-1.25 - pathname: D/DR/DROLSKY/DateTime-Locale-1.25.tar.gz + DateTime-Locale-1.31 + pathname: D/DR/DROLSKY/DateTime-Locale-1.31.tar.gz provides: - DateTime::Locale 1.25 - DateTime::Locale::Base 1.25 - DateTime::Locale::Catalog 1.25 - DateTime::Locale::Data 1.25 - DateTime::Locale::FromData 1.25 - DateTime::Locale::Util 1.25 + DateTime::Locale 1.31 + DateTime::Locale::Base 1.31 + DateTime::Locale::Catalog 1.31 + DateTime::Locale::Data 1.31 + DateTime::Locale::FromData 1.31 + DateTime::Locale::Util 1.31 requirements: Carp 0 Dist::CheckConflicts 0.02 Exporter 0 ExtUtils::MakeMaker 0 File::ShareDir 0 - File::ShareDir::Install 0.03 + File::ShareDir::Install 0.06 + File::Spec 0 List::Util 1.45 Params::ValidationCompiler 0.13 Specio::Declare 0 Specio::Library::String 0 + Storable 0 namespace::autoclean 0.19 perl 5.008004 strict 0 @@ -1918,382 +1945,381 @@ DISTRIBUTIONS Params::Validate 0 Set::Infinite 0.59 Test::More 0 - DateTime-TimeZone-2.39 - pathname: D/DR/DROLSKY/DateTime-TimeZone-2.39.tar.gz - provides: - DateTime::TimeZone 2.39 - DateTime::TimeZone::Africa::Abidjan 2.39 - DateTime::TimeZone::Africa::Accra 2.39 - DateTime::TimeZone::Africa::Algiers 2.39 - DateTime::TimeZone::Africa::Bissau 2.39 - DateTime::TimeZone::Africa::Cairo 2.39 - DateTime::TimeZone::Africa::Casablanca 2.39 - DateTime::TimeZone::Africa::Ceuta 2.39 - DateTime::TimeZone::Africa::El_Aaiun 2.39 - DateTime::TimeZone::Africa::Johannesburg 2.39 - DateTime::TimeZone::Africa::Juba 2.39 - DateTime::TimeZone::Africa::Khartoum 2.39 - DateTime::TimeZone::Africa::Lagos 2.39 - DateTime::TimeZone::Africa::Maputo 2.39 - DateTime::TimeZone::Africa::Monrovia 2.39 - DateTime::TimeZone::Africa::Nairobi 2.39 - DateTime::TimeZone::Africa::Ndjamena 2.39 - DateTime::TimeZone::Africa::Sao_Tome 2.39 - DateTime::TimeZone::Africa::Tripoli 2.39 - DateTime::TimeZone::Africa::Tunis 2.39 - DateTime::TimeZone::Africa::Windhoek 2.39 - DateTime::TimeZone::America::Adak 2.39 - DateTime::TimeZone::America::Anchorage 2.39 - DateTime::TimeZone::America::Araguaina 2.39 - DateTime::TimeZone::America::Argentina::Buenos_Aires 2.39 - DateTime::TimeZone::America::Argentina::Catamarca 2.39 - DateTime::TimeZone::America::Argentina::Cordoba 2.39 - DateTime::TimeZone::America::Argentina::Jujuy 2.39 - DateTime::TimeZone::America::Argentina::La_Rioja 2.39 - DateTime::TimeZone::America::Argentina::Mendoza 2.39 - DateTime::TimeZone::America::Argentina::Rio_Gallegos 2.39 - DateTime::TimeZone::America::Argentina::Salta 2.39 - DateTime::TimeZone::America::Argentina::San_Juan 2.39 - DateTime::TimeZone::America::Argentina::San_Luis 2.39 - DateTime::TimeZone::America::Argentina::Tucuman 2.39 - DateTime::TimeZone::America::Argentina::Ushuaia 2.39 - DateTime::TimeZone::America::Asuncion 2.39 - DateTime::TimeZone::America::Atikokan 2.39 - DateTime::TimeZone::America::Bahia 2.39 - DateTime::TimeZone::America::Bahia_Banderas 2.39 - DateTime::TimeZone::America::Barbados 2.39 - DateTime::TimeZone::America::Belem 2.39 - DateTime::TimeZone::America::Belize 2.39 - DateTime::TimeZone::America::Blanc_Sablon 2.39 - DateTime::TimeZone::America::Boa_Vista 2.39 - DateTime::TimeZone::America::Bogota 2.39 - DateTime::TimeZone::America::Boise 2.39 - DateTime::TimeZone::America::Cambridge_Bay 2.39 - DateTime::TimeZone::America::Campo_Grande 2.39 - DateTime::TimeZone::America::Cancun 2.39 - DateTime::TimeZone::America::Caracas 2.39 - DateTime::TimeZone::America::Cayenne 2.39 - DateTime::TimeZone::America::Chicago 2.39 - DateTime::TimeZone::America::Chihuahua 2.39 - DateTime::TimeZone::America::Costa_Rica 2.39 - DateTime::TimeZone::America::Creston 2.39 - DateTime::TimeZone::America::Cuiaba 2.39 - DateTime::TimeZone::America::Curacao 2.39 - DateTime::TimeZone::America::Danmarkshavn 2.39 - DateTime::TimeZone::America::Dawson 2.39 - DateTime::TimeZone::America::Dawson_Creek 2.39 - DateTime::TimeZone::America::Denver 2.39 - DateTime::TimeZone::America::Detroit 2.39 - DateTime::TimeZone::America::Edmonton 2.39 - DateTime::TimeZone::America::Eirunepe 2.39 - DateTime::TimeZone::America::El_Salvador 2.39 - DateTime::TimeZone::America::Fort_Nelson 2.39 - DateTime::TimeZone::America::Fortaleza 2.39 - DateTime::TimeZone::America::Glace_Bay 2.39 - DateTime::TimeZone::America::Goose_Bay 2.39 - DateTime::TimeZone::America::Grand_Turk 2.39 - DateTime::TimeZone::America::Guatemala 2.39 - DateTime::TimeZone::America::Guayaquil 2.39 - DateTime::TimeZone::America::Guyana 2.39 - DateTime::TimeZone::America::Halifax 2.39 - DateTime::TimeZone::America::Havana 2.39 - DateTime::TimeZone::America::Hermosillo 2.39 - DateTime::TimeZone::America::Indiana::Indianapolis 2.39 - DateTime::TimeZone::America::Indiana::Knox 2.39 - DateTime::TimeZone::America::Indiana::Marengo 2.39 - DateTime::TimeZone::America::Indiana::Petersburg 2.39 - DateTime::TimeZone::America::Indiana::Tell_City 2.39 - DateTime::TimeZone::America::Indiana::Vevay 2.39 - DateTime::TimeZone::America::Indiana::Vincennes 2.39 - DateTime::TimeZone::America::Indiana::Winamac 2.39 - DateTime::TimeZone::America::Inuvik 2.39 - DateTime::TimeZone::America::Iqaluit 2.39 - DateTime::TimeZone::America::Jamaica 2.39 - DateTime::TimeZone::America::Juneau 2.39 - DateTime::TimeZone::America::Kentucky::Louisville 2.39 - DateTime::TimeZone::America::Kentucky::Monticello 2.39 - DateTime::TimeZone::America::La_Paz 2.39 - DateTime::TimeZone::America::Lima 2.39 - DateTime::TimeZone::America::Los_Angeles 2.39 - DateTime::TimeZone::America::Maceio 2.39 - DateTime::TimeZone::America::Managua 2.39 - DateTime::TimeZone::America::Manaus 2.39 - DateTime::TimeZone::America::Martinique 2.39 - DateTime::TimeZone::America::Matamoros 2.39 - DateTime::TimeZone::America::Mazatlan 2.39 - DateTime::TimeZone::America::Menominee 2.39 - DateTime::TimeZone::America::Merida 2.39 - DateTime::TimeZone::America::Metlakatla 2.39 - DateTime::TimeZone::America::Mexico_City 2.39 - DateTime::TimeZone::America::Miquelon 2.39 - DateTime::TimeZone::America::Moncton 2.39 - DateTime::TimeZone::America::Monterrey 2.39 - DateTime::TimeZone::America::Montevideo 2.39 - DateTime::TimeZone::America::Nassau 2.39 - DateTime::TimeZone::America::New_York 2.39 - DateTime::TimeZone::America::Nipigon 2.39 - DateTime::TimeZone::America::Nome 2.39 - DateTime::TimeZone::America::Noronha 2.39 - DateTime::TimeZone::America::North_Dakota::Beulah 2.39 - DateTime::TimeZone::America::North_Dakota::Center 2.39 - DateTime::TimeZone::America::North_Dakota::New_Salem 2.39 - DateTime::TimeZone::America::Nuuk 2.39 - DateTime::TimeZone::America::Ojinaga 2.39 - DateTime::TimeZone::America::Panama 2.39 - DateTime::TimeZone::America::Pangnirtung 2.39 - DateTime::TimeZone::America::Paramaribo 2.39 - DateTime::TimeZone::America::Phoenix 2.39 - DateTime::TimeZone::America::Port_au_Prince 2.39 - DateTime::TimeZone::America::Port_of_Spain 2.39 - DateTime::TimeZone::America::Porto_Velho 2.39 - DateTime::TimeZone::America::Puerto_Rico 2.39 - DateTime::TimeZone::America::Punta_Arenas 2.39 - DateTime::TimeZone::America::Rainy_River 2.39 - DateTime::TimeZone::America::Rankin_Inlet 2.39 - DateTime::TimeZone::America::Recife 2.39 - DateTime::TimeZone::America::Regina 2.39 - DateTime::TimeZone::America::Resolute 2.39 - DateTime::TimeZone::America::Rio_Branco 2.39 - DateTime::TimeZone::America::Santarem 2.39 - DateTime::TimeZone::America::Santiago 2.39 - DateTime::TimeZone::America::Santo_Domingo 2.39 - DateTime::TimeZone::America::Sao_Paulo 2.39 - DateTime::TimeZone::America::Scoresbysund 2.39 - DateTime::TimeZone::America::Sitka 2.39 - DateTime::TimeZone::America::St_Johns 2.39 - DateTime::TimeZone::America::Swift_Current 2.39 - DateTime::TimeZone::America::Tegucigalpa 2.39 - DateTime::TimeZone::America::Thule 2.39 - DateTime::TimeZone::America::Thunder_Bay 2.39 - DateTime::TimeZone::America::Tijuana 2.39 - DateTime::TimeZone::America::Toronto 2.39 - DateTime::TimeZone::America::Vancouver 2.39 - DateTime::TimeZone::America::Whitehorse 2.39 - DateTime::TimeZone::America::Winnipeg 2.39 - DateTime::TimeZone::America::Yakutat 2.39 - DateTime::TimeZone::America::Yellowknife 2.39 - DateTime::TimeZone::Antarctica::Casey 2.39 - DateTime::TimeZone::Antarctica::Davis 2.39 - DateTime::TimeZone::Antarctica::DumontDUrville 2.39 - DateTime::TimeZone::Antarctica::Macquarie 2.39 - DateTime::TimeZone::Antarctica::Mawson 2.39 - DateTime::TimeZone::Antarctica::Palmer 2.39 - DateTime::TimeZone::Antarctica::Rothera 2.39 - DateTime::TimeZone::Antarctica::Syowa 2.39 - DateTime::TimeZone::Antarctica::Troll 2.39 - DateTime::TimeZone::Antarctica::Vostok 2.39 - DateTime::TimeZone::Asia::Almaty 2.39 - DateTime::TimeZone::Asia::Amman 2.39 - DateTime::TimeZone::Asia::Anadyr 2.39 - DateTime::TimeZone::Asia::Aqtau 2.39 - DateTime::TimeZone::Asia::Aqtobe 2.39 - DateTime::TimeZone::Asia::Ashgabat 2.39 - DateTime::TimeZone::Asia::Atyrau 2.39 - DateTime::TimeZone::Asia::Baghdad 2.39 - DateTime::TimeZone::Asia::Baku 2.39 - DateTime::TimeZone::Asia::Bangkok 2.39 - DateTime::TimeZone::Asia::Barnaul 2.39 - DateTime::TimeZone::Asia::Beirut 2.39 - DateTime::TimeZone::Asia::Bishkek 2.39 - DateTime::TimeZone::Asia::Brunei 2.39 - DateTime::TimeZone::Asia::Chita 2.39 - DateTime::TimeZone::Asia::Choibalsan 2.39 - DateTime::TimeZone::Asia::Colombo 2.39 - DateTime::TimeZone::Asia::Damascus 2.39 - DateTime::TimeZone::Asia::Dhaka 2.39 - DateTime::TimeZone::Asia::Dili 2.39 - DateTime::TimeZone::Asia::Dubai 2.39 - DateTime::TimeZone::Asia::Dushanbe 2.39 - DateTime::TimeZone::Asia::Famagusta 2.39 - DateTime::TimeZone::Asia::Gaza 2.39 - DateTime::TimeZone::Asia::Hebron 2.39 - DateTime::TimeZone::Asia::Ho_Chi_Minh 2.39 - DateTime::TimeZone::Asia::Hong_Kong 2.39 - DateTime::TimeZone::Asia::Hovd 2.39 - DateTime::TimeZone::Asia::Irkutsk 2.39 - DateTime::TimeZone::Asia::Jakarta 2.39 - DateTime::TimeZone::Asia::Jayapura 2.39 - DateTime::TimeZone::Asia::Jerusalem 2.39 - DateTime::TimeZone::Asia::Kabul 2.39 - DateTime::TimeZone::Asia::Kamchatka 2.39 - DateTime::TimeZone::Asia::Karachi 2.39 - DateTime::TimeZone::Asia::Kathmandu 2.39 - DateTime::TimeZone::Asia::Khandyga 2.39 - DateTime::TimeZone::Asia::Kolkata 2.39 - DateTime::TimeZone::Asia::Krasnoyarsk 2.39 - DateTime::TimeZone::Asia::Kuala_Lumpur 2.39 - DateTime::TimeZone::Asia::Kuching 2.39 - DateTime::TimeZone::Asia::Macau 2.39 - DateTime::TimeZone::Asia::Magadan 2.39 - DateTime::TimeZone::Asia::Makassar 2.39 - DateTime::TimeZone::Asia::Manila 2.39 - DateTime::TimeZone::Asia::Nicosia 2.39 - DateTime::TimeZone::Asia::Novokuznetsk 2.39 - DateTime::TimeZone::Asia::Novosibirsk 2.39 - DateTime::TimeZone::Asia::Omsk 2.39 - DateTime::TimeZone::Asia::Oral 2.39 - DateTime::TimeZone::Asia::Pontianak 2.39 - DateTime::TimeZone::Asia::Pyongyang 2.39 - DateTime::TimeZone::Asia::Qatar 2.39 - DateTime::TimeZone::Asia::Qostanay 2.39 - DateTime::TimeZone::Asia::Qyzylorda 2.39 - DateTime::TimeZone::Asia::Riyadh 2.39 - DateTime::TimeZone::Asia::Sakhalin 2.39 - DateTime::TimeZone::Asia::Samarkand 2.39 - DateTime::TimeZone::Asia::Seoul 2.39 - DateTime::TimeZone::Asia::Shanghai 2.39 - DateTime::TimeZone::Asia::Singapore 2.39 - DateTime::TimeZone::Asia::Srednekolymsk 2.39 - DateTime::TimeZone::Asia::Taipei 2.39 - DateTime::TimeZone::Asia::Tashkent 2.39 - DateTime::TimeZone::Asia::Tbilisi 2.39 - DateTime::TimeZone::Asia::Tehran 2.39 - DateTime::TimeZone::Asia::Thimphu 2.39 - DateTime::TimeZone::Asia::Tokyo 2.39 - DateTime::TimeZone::Asia::Tomsk 2.39 - DateTime::TimeZone::Asia::Ulaanbaatar 2.39 - DateTime::TimeZone::Asia::Urumqi 2.39 - DateTime::TimeZone::Asia::Ust_Nera 2.39 - DateTime::TimeZone::Asia::Vladivostok 2.39 - DateTime::TimeZone::Asia::Yakutsk 2.39 - DateTime::TimeZone::Asia::Yangon 2.39 - DateTime::TimeZone::Asia::Yekaterinburg 2.39 - DateTime::TimeZone::Asia::Yerevan 2.39 - DateTime::TimeZone::Atlantic::Azores 2.39 - DateTime::TimeZone::Atlantic::Bermuda 2.39 - DateTime::TimeZone::Atlantic::Canary 2.39 - DateTime::TimeZone::Atlantic::Cape_Verde 2.39 - DateTime::TimeZone::Atlantic::Faroe 2.39 - DateTime::TimeZone::Atlantic::Madeira 2.39 - DateTime::TimeZone::Atlantic::Reykjavik 2.39 - DateTime::TimeZone::Atlantic::South_Georgia 2.39 - DateTime::TimeZone::Atlantic::Stanley 2.39 - DateTime::TimeZone::Australia::Adelaide 2.39 - DateTime::TimeZone::Australia::Brisbane 2.39 - DateTime::TimeZone::Australia::Broken_Hill 2.39 - DateTime::TimeZone::Australia::Currie 2.39 - DateTime::TimeZone::Australia::Darwin 2.39 - DateTime::TimeZone::Australia::Eucla 2.39 - DateTime::TimeZone::Australia::Hobart 2.39 - DateTime::TimeZone::Australia::Lindeman 2.39 - DateTime::TimeZone::Australia::Lord_Howe 2.39 - DateTime::TimeZone::Australia::Melbourne 2.39 - DateTime::TimeZone::Australia::Perth 2.39 - DateTime::TimeZone::Australia::Sydney 2.39 - DateTime::TimeZone::CET 2.39 - DateTime::TimeZone::CST6CDT 2.39 - DateTime::TimeZone::Catalog 2.39 - DateTime::TimeZone::EET 2.39 - DateTime::TimeZone::EST 2.39 - DateTime::TimeZone::EST5EDT 2.39 - DateTime::TimeZone::Europe::Amsterdam 2.39 - DateTime::TimeZone::Europe::Andorra 2.39 - DateTime::TimeZone::Europe::Astrakhan 2.39 - DateTime::TimeZone::Europe::Athens 2.39 - DateTime::TimeZone::Europe::Belgrade 2.39 - DateTime::TimeZone::Europe::Berlin 2.39 - DateTime::TimeZone::Europe::Brussels 2.39 - DateTime::TimeZone::Europe::Bucharest 2.39 - DateTime::TimeZone::Europe::Budapest 2.39 - DateTime::TimeZone::Europe::Chisinau 2.39 - DateTime::TimeZone::Europe::Copenhagen 2.39 - DateTime::TimeZone::Europe::Dublin 2.39 - DateTime::TimeZone::Europe::Gibraltar 2.39 - DateTime::TimeZone::Europe::Helsinki 2.39 - DateTime::TimeZone::Europe::Istanbul 2.39 - DateTime::TimeZone::Europe::Kaliningrad 2.39 - DateTime::TimeZone::Europe::Kiev 2.39 - DateTime::TimeZone::Europe::Kirov 2.39 - DateTime::TimeZone::Europe::Lisbon 2.39 - DateTime::TimeZone::Europe::London 2.39 - DateTime::TimeZone::Europe::Luxembourg 2.39 - DateTime::TimeZone::Europe::Madrid 2.39 - DateTime::TimeZone::Europe::Malta 2.39 - DateTime::TimeZone::Europe::Minsk 2.39 - DateTime::TimeZone::Europe::Monaco 2.39 - DateTime::TimeZone::Europe::Moscow 2.39 - DateTime::TimeZone::Europe::Oslo 2.39 - DateTime::TimeZone::Europe::Paris 2.39 - DateTime::TimeZone::Europe::Prague 2.39 - DateTime::TimeZone::Europe::Riga 2.39 - DateTime::TimeZone::Europe::Rome 2.39 - DateTime::TimeZone::Europe::Samara 2.39 - DateTime::TimeZone::Europe::Saratov 2.39 - DateTime::TimeZone::Europe::Simferopol 2.39 - DateTime::TimeZone::Europe::Sofia 2.39 - DateTime::TimeZone::Europe::Stockholm 2.39 - DateTime::TimeZone::Europe::Tallinn 2.39 - DateTime::TimeZone::Europe::Tirane 2.39 - DateTime::TimeZone::Europe::Ulyanovsk 2.39 - DateTime::TimeZone::Europe::Uzhgorod 2.39 - DateTime::TimeZone::Europe::Vienna 2.39 - DateTime::TimeZone::Europe::Vilnius 2.39 - DateTime::TimeZone::Europe::Volgograd 2.39 - DateTime::TimeZone::Europe::Warsaw 2.39 - DateTime::TimeZone::Europe::Zaporozhye 2.39 - DateTime::TimeZone::Europe::Zurich 2.39 - DateTime::TimeZone::Floating 2.39 - DateTime::TimeZone::HST 2.39 - DateTime::TimeZone::Indian::Chagos 2.39 - DateTime::TimeZone::Indian::Christmas 2.39 - DateTime::TimeZone::Indian::Cocos 2.39 - DateTime::TimeZone::Indian::Kerguelen 2.39 - DateTime::TimeZone::Indian::Mahe 2.39 - DateTime::TimeZone::Indian::Maldives 2.39 - DateTime::TimeZone::Indian::Mauritius 2.39 - DateTime::TimeZone::Indian::Reunion 2.39 - DateTime::TimeZone::Local 2.39 - DateTime::TimeZone::Local::Android 2.39 - DateTime::TimeZone::Local::Unix 2.39 - DateTime::TimeZone::Local::VMS 2.39 - DateTime::TimeZone::MET 2.39 - DateTime::TimeZone::MST 2.39 - DateTime::TimeZone::MST7MDT 2.39 - DateTime::TimeZone::OffsetOnly 2.39 - DateTime::TimeZone::OlsonDB 2.39 - DateTime::TimeZone::OlsonDB::Change 2.39 - DateTime::TimeZone::OlsonDB::Observance 2.39 - DateTime::TimeZone::OlsonDB::Rule 2.39 - DateTime::TimeZone::OlsonDB::Zone 2.39 - DateTime::TimeZone::PST8PDT 2.39 - DateTime::TimeZone::Pacific::Apia 2.39 - DateTime::TimeZone::Pacific::Auckland 2.39 - DateTime::TimeZone::Pacific::Bougainville 2.39 - DateTime::TimeZone::Pacific::Chatham 2.39 - DateTime::TimeZone::Pacific::Chuuk 2.39 - DateTime::TimeZone::Pacific::Easter 2.39 - DateTime::TimeZone::Pacific::Efate 2.39 - DateTime::TimeZone::Pacific::Enderbury 2.39 - DateTime::TimeZone::Pacific::Fakaofo 2.39 - DateTime::TimeZone::Pacific::Fiji 2.39 - DateTime::TimeZone::Pacific::Funafuti 2.39 - DateTime::TimeZone::Pacific::Galapagos 2.39 - DateTime::TimeZone::Pacific::Gambier 2.39 - DateTime::TimeZone::Pacific::Guadalcanal 2.39 - DateTime::TimeZone::Pacific::Guam 2.39 - DateTime::TimeZone::Pacific::Honolulu 2.39 - DateTime::TimeZone::Pacific::Kiritimati 2.39 - DateTime::TimeZone::Pacific::Kosrae 2.39 - DateTime::TimeZone::Pacific::Kwajalein 2.39 - DateTime::TimeZone::Pacific::Majuro 2.39 - DateTime::TimeZone::Pacific::Marquesas 2.39 - DateTime::TimeZone::Pacific::Nauru 2.39 - DateTime::TimeZone::Pacific::Niue 2.39 - DateTime::TimeZone::Pacific::Norfolk 2.39 - DateTime::TimeZone::Pacific::Noumea 2.39 - DateTime::TimeZone::Pacific::Pago_Pago 2.39 - DateTime::TimeZone::Pacific::Palau 2.39 - DateTime::TimeZone::Pacific::Pitcairn 2.39 - DateTime::TimeZone::Pacific::Pohnpei 2.39 - DateTime::TimeZone::Pacific::Port_Moresby 2.39 - DateTime::TimeZone::Pacific::Rarotonga 2.39 - DateTime::TimeZone::Pacific::Tahiti 2.39 - DateTime::TimeZone::Pacific::Tarawa 2.39 - DateTime::TimeZone::Pacific::Tongatapu 2.39 - DateTime::TimeZone::Pacific::Wake 2.39 - DateTime::TimeZone::Pacific::Wallis 2.39 - DateTime::TimeZone::UTC 2.39 - DateTime::TimeZone::WET 2.39 + DateTime-TimeZone-2.46 + pathname: D/DR/DROLSKY/DateTime-TimeZone-2.46.tar.gz + provides: + DateTime::TimeZone 2.46 + DateTime::TimeZone::Africa::Abidjan 2.46 + DateTime::TimeZone::Africa::Accra 2.46 + DateTime::TimeZone::Africa::Algiers 2.46 + DateTime::TimeZone::Africa::Bissau 2.46 + DateTime::TimeZone::Africa::Cairo 2.46 + DateTime::TimeZone::Africa::Casablanca 2.46 + DateTime::TimeZone::Africa::Ceuta 2.46 + DateTime::TimeZone::Africa::El_Aaiun 2.46 + DateTime::TimeZone::Africa::Johannesburg 2.46 + DateTime::TimeZone::Africa::Juba 2.46 + DateTime::TimeZone::Africa::Khartoum 2.46 + DateTime::TimeZone::Africa::Lagos 2.46 + DateTime::TimeZone::Africa::Maputo 2.46 + DateTime::TimeZone::Africa::Monrovia 2.46 + DateTime::TimeZone::Africa::Nairobi 2.46 + DateTime::TimeZone::Africa::Ndjamena 2.46 + DateTime::TimeZone::Africa::Sao_Tome 2.46 + DateTime::TimeZone::Africa::Tripoli 2.46 + DateTime::TimeZone::Africa::Tunis 2.46 + DateTime::TimeZone::Africa::Windhoek 2.46 + DateTime::TimeZone::America::Adak 2.46 + DateTime::TimeZone::America::Anchorage 2.46 + DateTime::TimeZone::America::Araguaina 2.46 + DateTime::TimeZone::America::Argentina::Buenos_Aires 2.46 + DateTime::TimeZone::America::Argentina::Catamarca 2.46 + DateTime::TimeZone::America::Argentina::Cordoba 2.46 + DateTime::TimeZone::America::Argentina::Jujuy 2.46 + DateTime::TimeZone::America::Argentina::La_Rioja 2.46 + DateTime::TimeZone::America::Argentina::Mendoza 2.46 + DateTime::TimeZone::America::Argentina::Rio_Gallegos 2.46 + DateTime::TimeZone::America::Argentina::Salta 2.46 + DateTime::TimeZone::America::Argentina::San_Juan 2.46 + DateTime::TimeZone::America::Argentina::San_Luis 2.46 + DateTime::TimeZone::America::Argentina::Tucuman 2.46 + DateTime::TimeZone::America::Argentina::Ushuaia 2.46 + DateTime::TimeZone::America::Asuncion 2.46 + DateTime::TimeZone::America::Atikokan 2.46 + DateTime::TimeZone::America::Bahia 2.46 + DateTime::TimeZone::America::Bahia_Banderas 2.46 + DateTime::TimeZone::America::Barbados 2.46 + DateTime::TimeZone::America::Belem 2.46 + DateTime::TimeZone::America::Belize 2.46 + DateTime::TimeZone::America::Blanc_Sablon 2.46 + DateTime::TimeZone::America::Boa_Vista 2.46 + DateTime::TimeZone::America::Bogota 2.46 + DateTime::TimeZone::America::Boise 2.46 + DateTime::TimeZone::America::Cambridge_Bay 2.46 + DateTime::TimeZone::America::Campo_Grande 2.46 + DateTime::TimeZone::America::Cancun 2.46 + DateTime::TimeZone::America::Caracas 2.46 + DateTime::TimeZone::America::Cayenne 2.46 + DateTime::TimeZone::America::Chicago 2.46 + DateTime::TimeZone::America::Chihuahua 2.46 + DateTime::TimeZone::America::Costa_Rica 2.46 + DateTime::TimeZone::America::Creston 2.46 + DateTime::TimeZone::America::Cuiaba 2.46 + DateTime::TimeZone::America::Curacao 2.46 + DateTime::TimeZone::America::Danmarkshavn 2.46 + DateTime::TimeZone::America::Dawson 2.46 + DateTime::TimeZone::America::Dawson_Creek 2.46 + DateTime::TimeZone::America::Denver 2.46 + DateTime::TimeZone::America::Detroit 2.46 + DateTime::TimeZone::America::Edmonton 2.46 + DateTime::TimeZone::America::Eirunepe 2.46 + DateTime::TimeZone::America::El_Salvador 2.46 + DateTime::TimeZone::America::Fort_Nelson 2.46 + DateTime::TimeZone::America::Fortaleza 2.46 + DateTime::TimeZone::America::Glace_Bay 2.46 + DateTime::TimeZone::America::Goose_Bay 2.46 + DateTime::TimeZone::America::Grand_Turk 2.46 + DateTime::TimeZone::America::Guatemala 2.46 + DateTime::TimeZone::America::Guayaquil 2.46 + DateTime::TimeZone::America::Guyana 2.46 + DateTime::TimeZone::America::Halifax 2.46 + DateTime::TimeZone::America::Havana 2.46 + DateTime::TimeZone::America::Hermosillo 2.46 + DateTime::TimeZone::America::Indiana::Indianapolis 2.46 + DateTime::TimeZone::America::Indiana::Knox 2.46 + DateTime::TimeZone::America::Indiana::Marengo 2.46 + DateTime::TimeZone::America::Indiana::Petersburg 2.46 + DateTime::TimeZone::America::Indiana::Tell_City 2.46 + DateTime::TimeZone::America::Indiana::Vevay 2.46 + DateTime::TimeZone::America::Indiana::Vincennes 2.46 + DateTime::TimeZone::America::Indiana::Winamac 2.46 + DateTime::TimeZone::America::Inuvik 2.46 + DateTime::TimeZone::America::Iqaluit 2.46 + DateTime::TimeZone::America::Jamaica 2.46 + DateTime::TimeZone::America::Juneau 2.46 + DateTime::TimeZone::America::Kentucky::Louisville 2.46 + DateTime::TimeZone::America::Kentucky::Monticello 2.46 + DateTime::TimeZone::America::La_Paz 2.46 + DateTime::TimeZone::America::Lima 2.46 + DateTime::TimeZone::America::Los_Angeles 2.46 + DateTime::TimeZone::America::Maceio 2.46 + DateTime::TimeZone::America::Managua 2.46 + DateTime::TimeZone::America::Manaus 2.46 + DateTime::TimeZone::America::Martinique 2.46 + DateTime::TimeZone::America::Matamoros 2.46 + DateTime::TimeZone::America::Mazatlan 2.46 + DateTime::TimeZone::America::Menominee 2.46 + DateTime::TimeZone::America::Merida 2.46 + DateTime::TimeZone::America::Metlakatla 2.46 + DateTime::TimeZone::America::Mexico_City 2.46 + DateTime::TimeZone::America::Miquelon 2.46 + DateTime::TimeZone::America::Moncton 2.46 + DateTime::TimeZone::America::Monterrey 2.46 + DateTime::TimeZone::America::Montevideo 2.46 + DateTime::TimeZone::America::Nassau 2.46 + DateTime::TimeZone::America::New_York 2.46 + DateTime::TimeZone::America::Nipigon 2.46 + DateTime::TimeZone::America::Nome 2.46 + DateTime::TimeZone::America::Noronha 2.46 + DateTime::TimeZone::America::North_Dakota::Beulah 2.46 + DateTime::TimeZone::America::North_Dakota::Center 2.46 + DateTime::TimeZone::America::North_Dakota::New_Salem 2.46 + DateTime::TimeZone::America::Nuuk 2.46 + DateTime::TimeZone::America::Ojinaga 2.46 + DateTime::TimeZone::America::Panama 2.46 + DateTime::TimeZone::America::Pangnirtung 2.46 + DateTime::TimeZone::America::Paramaribo 2.46 + DateTime::TimeZone::America::Phoenix 2.46 + DateTime::TimeZone::America::Port_au_Prince 2.46 + DateTime::TimeZone::America::Port_of_Spain 2.46 + DateTime::TimeZone::America::Porto_Velho 2.46 + DateTime::TimeZone::America::Puerto_Rico 2.46 + DateTime::TimeZone::America::Punta_Arenas 2.46 + DateTime::TimeZone::America::Rainy_River 2.46 + DateTime::TimeZone::America::Rankin_Inlet 2.46 + DateTime::TimeZone::America::Recife 2.46 + DateTime::TimeZone::America::Regina 2.46 + DateTime::TimeZone::America::Resolute 2.46 + DateTime::TimeZone::America::Rio_Branco 2.46 + DateTime::TimeZone::America::Santarem 2.46 + DateTime::TimeZone::America::Santiago 2.46 + DateTime::TimeZone::America::Santo_Domingo 2.46 + DateTime::TimeZone::America::Sao_Paulo 2.46 + DateTime::TimeZone::America::Scoresbysund 2.46 + DateTime::TimeZone::America::Sitka 2.46 + DateTime::TimeZone::America::St_Johns 2.46 + DateTime::TimeZone::America::Swift_Current 2.46 + DateTime::TimeZone::America::Tegucigalpa 2.46 + DateTime::TimeZone::America::Thule 2.46 + DateTime::TimeZone::America::Thunder_Bay 2.46 + DateTime::TimeZone::America::Tijuana 2.46 + DateTime::TimeZone::America::Toronto 2.46 + DateTime::TimeZone::America::Vancouver 2.46 + DateTime::TimeZone::America::Whitehorse 2.46 + DateTime::TimeZone::America::Winnipeg 2.46 + DateTime::TimeZone::America::Yakutat 2.46 + DateTime::TimeZone::America::Yellowknife 2.46 + DateTime::TimeZone::Antarctica::Casey 2.46 + DateTime::TimeZone::Antarctica::Davis 2.46 + DateTime::TimeZone::Antarctica::DumontDUrville 2.46 + DateTime::TimeZone::Antarctica::Macquarie 2.46 + DateTime::TimeZone::Antarctica::Mawson 2.46 + DateTime::TimeZone::Antarctica::Palmer 2.46 + DateTime::TimeZone::Antarctica::Rothera 2.46 + DateTime::TimeZone::Antarctica::Syowa 2.46 + DateTime::TimeZone::Antarctica::Troll 2.46 + DateTime::TimeZone::Antarctica::Vostok 2.46 + DateTime::TimeZone::Asia::Almaty 2.46 + DateTime::TimeZone::Asia::Amman 2.46 + DateTime::TimeZone::Asia::Anadyr 2.46 + DateTime::TimeZone::Asia::Aqtau 2.46 + DateTime::TimeZone::Asia::Aqtobe 2.46 + DateTime::TimeZone::Asia::Ashgabat 2.46 + DateTime::TimeZone::Asia::Atyrau 2.46 + DateTime::TimeZone::Asia::Baghdad 2.46 + DateTime::TimeZone::Asia::Baku 2.46 + DateTime::TimeZone::Asia::Bangkok 2.46 + DateTime::TimeZone::Asia::Barnaul 2.46 + DateTime::TimeZone::Asia::Beirut 2.46 + DateTime::TimeZone::Asia::Bishkek 2.46 + DateTime::TimeZone::Asia::Brunei 2.46 + DateTime::TimeZone::Asia::Chita 2.46 + DateTime::TimeZone::Asia::Choibalsan 2.46 + DateTime::TimeZone::Asia::Colombo 2.46 + DateTime::TimeZone::Asia::Damascus 2.46 + DateTime::TimeZone::Asia::Dhaka 2.46 + DateTime::TimeZone::Asia::Dili 2.46 + DateTime::TimeZone::Asia::Dubai 2.46 + DateTime::TimeZone::Asia::Dushanbe 2.46 + DateTime::TimeZone::Asia::Famagusta 2.46 + DateTime::TimeZone::Asia::Gaza 2.46 + DateTime::TimeZone::Asia::Hebron 2.46 + DateTime::TimeZone::Asia::Ho_Chi_Minh 2.46 + DateTime::TimeZone::Asia::Hong_Kong 2.46 + DateTime::TimeZone::Asia::Hovd 2.46 + DateTime::TimeZone::Asia::Irkutsk 2.46 + DateTime::TimeZone::Asia::Jakarta 2.46 + DateTime::TimeZone::Asia::Jayapura 2.46 + DateTime::TimeZone::Asia::Jerusalem 2.46 + DateTime::TimeZone::Asia::Kabul 2.46 + DateTime::TimeZone::Asia::Kamchatka 2.46 + DateTime::TimeZone::Asia::Karachi 2.46 + DateTime::TimeZone::Asia::Kathmandu 2.46 + DateTime::TimeZone::Asia::Khandyga 2.46 + DateTime::TimeZone::Asia::Kolkata 2.46 + DateTime::TimeZone::Asia::Krasnoyarsk 2.46 + DateTime::TimeZone::Asia::Kuala_Lumpur 2.46 + DateTime::TimeZone::Asia::Kuching 2.46 + DateTime::TimeZone::Asia::Macau 2.46 + DateTime::TimeZone::Asia::Magadan 2.46 + DateTime::TimeZone::Asia::Makassar 2.46 + DateTime::TimeZone::Asia::Manila 2.46 + DateTime::TimeZone::Asia::Nicosia 2.46 + DateTime::TimeZone::Asia::Novokuznetsk 2.46 + DateTime::TimeZone::Asia::Novosibirsk 2.46 + DateTime::TimeZone::Asia::Omsk 2.46 + DateTime::TimeZone::Asia::Oral 2.46 + DateTime::TimeZone::Asia::Pontianak 2.46 + DateTime::TimeZone::Asia::Pyongyang 2.46 + DateTime::TimeZone::Asia::Qatar 2.46 + DateTime::TimeZone::Asia::Qostanay 2.46 + DateTime::TimeZone::Asia::Qyzylorda 2.46 + DateTime::TimeZone::Asia::Riyadh 2.46 + DateTime::TimeZone::Asia::Sakhalin 2.46 + DateTime::TimeZone::Asia::Samarkand 2.46 + DateTime::TimeZone::Asia::Seoul 2.46 + DateTime::TimeZone::Asia::Shanghai 2.46 + DateTime::TimeZone::Asia::Singapore 2.46 + DateTime::TimeZone::Asia::Srednekolymsk 2.46 + DateTime::TimeZone::Asia::Taipei 2.46 + DateTime::TimeZone::Asia::Tashkent 2.46 + DateTime::TimeZone::Asia::Tbilisi 2.46 + DateTime::TimeZone::Asia::Tehran 2.46 + DateTime::TimeZone::Asia::Thimphu 2.46 + DateTime::TimeZone::Asia::Tokyo 2.46 + DateTime::TimeZone::Asia::Tomsk 2.46 + DateTime::TimeZone::Asia::Ulaanbaatar 2.46 + DateTime::TimeZone::Asia::Urumqi 2.46 + DateTime::TimeZone::Asia::Ust_Nera 2.46 + DateTime::TimeZone::Asia::Vladivostok 2.46 + DateTime::TimeZone::Asia::Yakutsk 2.46 + DateTime::TimeZone::Asia::Yangon 2.46 + DateTime::TimeZone::Asia::Yekaterinburg 2.46 + DateTime::TimeZone::Asia::Yerevan 2.46 + DateTime::TimeZone::Atlantic::Azores 2.46 + DateTime::TimeZone::Atlantic::Bermuda 2.46 + DateTime::TimeZone::Atlantic::Canary 2.46 + DateTime::TimeZone::Atlantic::Cape_Verde 2.46 + DateTime::TimeZone::Atlantic::Faroe 2.46 + DateTime::TimeZone::Atlantic::Madeira 2.46 + DateTime::TimeZone::Atlantic::Reykjavik 2.46 + DateTime::TimeZone::Atlantic::South_Georgia 2.46 + DateTime::TimeZone::Atlantic::Stanley 2.46 + DateTime::TimeZone::Australia::Adelaide 2.46 + DateTime::TimeZone::Australia::Brisbane 2.46 + DateTime::TimeZone::Australia::Broken_Hill 2.46 + DateTime::TimeZone::Australia::Darwin 2.46 + DateTime::TimeZone::Australia::Eucla 2.46 + DateTime::TimeZone::Australia::Hobart 2.46 + DateTime::TimeZone::Australia::Lindeman 2.46 + DateTime::TimeZone::Australia::Lord_Howe 2.46 + DateTime::TimeZone::Australia::Melbourne 2.46 + DateTime::TimeZone::Australia::Perth 2.46 + DateTime::TimeZone::Australia::Sydney 2.46 + DateTime::TimeZone::CET 2.46 + DateTime::TimeZone::CST6CDT 2.46 + DateTime::TimeZone::Catalog 2.46 + DateTime::TimeZone::EET 2.46 + DateTime::TimeZone::EST 2.46 + DateTime::TimeZone::EST5EDT 2.46 + DateTime::TimeZone::Europe::Amsterdam 2.46 + DateTime::TimeZone::Europe::Andorra 2.46 + DateTime::TimeZone::Europe::Astrakhan 2.46 + DateTime::TimeZone::Europe::Athens 2.46 + DateTime::TimeZone::Europe::Belgrade 2.46 + DateTime::TimeZone::Europe::Berlin 2.46 + DateTime::TimeZone::Europe::Brussels 2.46 + DateTime::TimeZone::Europe::Bucharest 2.46 + DateTime::TimeZone::Europe::Budapest 2.46 + DateTime::TimeZone::Europe::Chisinau 2.46 + DateTime::TimeZone::Europe::Copenhagen 2.46 + DateTime::TimeZone::Europe::Dublin 2.46 + DateTime::TimeZone::Europe::Gibraltar 2.46 + DateTime::TimeZone::Europe::Helsinki 2.46 + DateTime::TimeZone::Europe::Istanbul 2.46 + DateTime::TimeZone::Europe::Kaliningrad 2.46 + DateTime::TimeZone::Europe::Kiev 2.46 + DateTime::TimeZone::Europe::Kirov 2.46 + DateTime::TimeZone::Europe::Lisbon 2.46 + DateTime::TimeZone::Europe::London 2.46 + DateTime::TimeZone::Europe::Luxembourg 2.46 + DateTime::TimeZone::Europe::Madrid 2.46 + DateTime::TimeZone::Europe::Malta 2.46 + DateTime::TimeZone::Europe::Minsk 2.46 + DateTime::TimeZone::Europe::Monaco 2.46 + DateTime::TimeZone::Europe::Moscow 2.46 + DateTime::TimeZone::Europe::Oslo 2.46 + DateTime::TimeZone::Europe::Paris 2.46 + DateTime::TimeZone::Europe::Prague 2.46 + DateTime::TimeZone::Europe::Riga 2.46 + DateTime::TimeZone::Europe::Rome 2.46 + DateTime::TimeZone::Europe::Samara 2.46 + DateTime::TimeZone::Europe::Saratov 2.46 + DateTime::TimeZone::Europe::Simferopol 2.46 + DateTime::TimeZone::Europe::Sofia 2.46 + DateTime::TimeZone::Europe::Stockholm 2.46 + DateTime::TimeZone::Europe::Tallinn 2.46 + DateTime::TimeZone::Europe::Tirane 2.46 + DateTime::TimeZone::Europe::Ulyanovsk 2.46 + DateTime::TimeZone::Europe::Uzhgorod 2.46 + DateTime::TimeZone::Europe::Vienna 2.46 + DateTime::TimeZone::Europe::Vilnius 2.46 + DateTime::TimeZone::Europe::Volgograd 2.46 + DateTime::TimeZone::Europe::Warsaw 2.46 + DateTime::TimeZone::Europe::Zaporozhye 2.46 + DateTime::TimeZone::Europe::Zurich 2.46 + DateTime::TimeZone::Floating 2.46 + DateTime::TimeZone::HST 2.46 + DateTime::TimeZone::Indian::Chagos 2.46 + DateTime::TimeZone::Indian::Christmas 2.46 + DateTime::TimeZone::Indian::Cocos 2.46 + DateTime::TimeZone::Indian::Kerguelen 2.46 + DateTime::TimeZone::Indian::Mahe 2.46 + DateTime::TimeZone::Indian::Maldives 2.46 + DateTime::TimeZone::Indian::Mauritius 2.46 + DateTime::TimeZone::Indian::Reunion 2.46 + DateTime::TimeZone::Local 2.46 + DateTime::TimeZone::Local::Android 2.46 + DateTime::TimeZone::Local::Unix 2.46 + DateTime::TimeZone::Local::VMS 2.46 + DateTime::TimeZone::MET 2.46 + DateTime::TimeZone::MST 2.46 + DateTime::TimeZone::MST7MDT 2.46 + DateTime::TimeZone::OffsetOnly 2.46 + DateTime::TimeZone::OlsonDB 2.46 + DateTime::TimeZone::OlsonDB::Change 2.46 + DateTime::TimeZone::OlsonDB::Observance 2.46 + DateTime::TimeZone::OlsonDB::Rule 2.46 + DateTime::TimeZone::OlsonDB::Zone 2.46 + DateTime::TimeZone::PST8PDT 2.46 + DateTime::TimeZone::Pacific::Apia 2.46 + DateTime::TimeZone::Pacific::Auckland 2.46 + DateTime::TimeZone::Pacific::Bougainville 2.46 + DateTime::TimeZone::Pacific::Chatham 2.46 + DateTime::TimeZone::Pacific::Chuuk 2.46 + DateTime::TimeZone::Pacific::Easter 2.46 + DateTime::TimeZone::Pacific::Efate 2.46 + DateTime::TimeZone::Pacific::Enderbury 2.46 + DateTime::TimeZone::Pacific::Fakaofo 2.46 + DateTime::TimeZone::Pacific::Fiji 2.46 + DateTime::TimeZone::Pacific::Funafuti 2.46 + DateTime::TimeZone::Pacific::Galapagos 2.46 + DateTime::TimeZone::Pacific::Gambier 2.46 + DateTime::TimeZone::Pacific::Guadalcanal 2.46 + DateTime::TimeZone::Pacific::Guam 2.46 + DateTime::TimeZone::Pacific::Honolulu 2.46 + DateTime::TimeZone::Pacific::Kiritimati 2.46 + DateTime::TimeZone::Pacific::Kosrae 2.46 + DateTime::TimeZone::Pacific::Kwajalein 2.46 + DateTime::TimeZone::Pacific::Majuro 2.46 + DateTime::TimeZone::Pacific::Marquesas 2.46 + DateTime::TimeZone::Pacific::Nauru 2.46 + DateTime::TimeZone::Pacific::Niue 2.46 + DateTime::TimeZone::Pacific::Norfolk 2.46 + DateTime::TimeZone::Pacific::Noumea 2.46 + DateTime::TimeZone::Pacific::Pago_Pago 2.46 + DateTime::TimeZone::Pacific::Palau 2.46 + DateTime::TimeZone::Pacific::Pitcairn 2.46 + DateTime::TimeZone::Pacific::Pohnpei 2.46 + DateTime::TimeZone::Pacific::Port_Moresby 2.46 + DateTime::TimeZone::Pacific::Rarotonga 2.46 + DateTime::TimeZone::Pacific::Tahiti 2.46 + DateTime::TimeZone::Pacific::Tarawa 2.46 + DateTime::TimeZone::Pacific::Tongatapu 2.46 + DateTime::TimeZone::Pacific::Wake 2.46 + DateTime::TimeZone::Pacific::Wallis 2.46 + DateTime::TimeZone::UTC 2.46 + DateTime::TimeZone::WET 2.46 requirements: Class::Singleton 1.03 Cwd 3 @@ -2501,19 +2527,19 @@ DISTRIBUTIONS Time::Local 0 strict 0 warnings 0 - Email-MIME-1.946 - pathname: R/RJ/RJBS/Email-MIME-1.946.tar.gz + Email-MIME-1.949 + pathname: R/RJ/RJBS/Email-MIME-1.949.tar.gz provides: - Email::MIME 1.946 - Email::MIME::Creator 1.946 - Email::MIME::Encode 1.946 - Email::MIME::Header 1.946 - Email::MIME::Header::AddressList 1.946 - Email::MIME::Modifier 1.946 + Email::MIME 1.949 + Email::MIME::Creator 1.949 + Email::MIME::Encode 1.949 + Email::MIME::Header 1.949 + Email::MIME::Header::AddressList 1.949 + Email::MIME::Modifier 1.949 requirements: Carp 0 Email::Address::XS 0 - Email::MIME::ContentType 1.022 + Email::MIME::ContentType 1.023 Email::MIME::Encodings 1.314 Email::MessageID 0 Email::Simple 2.212 @@ -2541,15 +2567,16 @@ DISTRIBUTIONS ExtUtils::MakeMaker 6.30 strict 0 warnings 0 - Email-MIME-ContentType-1.022 - pathname: R/RJ/RJBS/Email-MIME-ContentType-1.022.tar.gz + Email-MIME-ContentType-1.026 + pathname: R/RJ/RJBS/Email-MIME-ContentType-1.026.tar.gz provides: - Email::MIME::ContentType 1.022 + Email::MIME::ContentType 1.026 requirements: Carp 0 Encode 2.87 Exporter 5.57 ExtUtils::MakeMaker 0 + Text::Unidecode 0 strict 0 warnings 0 Email-MIME-Encodings-1.315 @@ -2769,60 +2796,59 @@ DISTRIBUTIONS ExtUtils::PkgConfig 1.16 requirements: ExtUtils::MakeMaker 0 - FFI-CheckLib-0.26 - pathname: P/PL/PLICEASE/FFI-CheckLib-0.26.tar.gz + FFI-CheckLib-0.27 + pathname: P/PL/PLICEASE/FFI-CheckLib-0.27.tar.gz provides: - FFI::CheckLib 0.26 + FFI::CheckLib 0.27 requirements: ExtUtils::MakeMaker 0 perl 5.006 - FFI-Platypus-1.24 - pathname: P/PL/PLICEASE/FFI-Platypus-1.24.tar.gz - provides: - FFI::Build 1.24 - FFI::Build::File::Base 1.24 - FFI::Build::File::C 1.24 - FFI::Build::File::CXX 1.24 - FFI::Build::File::Library 1.24 - FFI::Build::File::Object 1.24 - FFI::Build::MM 1.24 - FFI::Build::MM::FBX 1.24 - FFI::Build::Platform 1.24 - FFI::Platypus 1.24 - FFI::Platypus::API 1.24 - FFI::Platypus::Buffer 1.24 - FFI::Platypus::Bundle 1.24 - FFI::Platypus::Closure 1.24 - FFI::Platypus::ClosureData 1.24 - FFI::Platypus::Constant 1.24 - FFI::Platypus::DL 1.24 - FFI::Platypus::Declare 1.24 - FFI::Platypus::Function 1.24 - FFI::Platypus::Function::Function 1.24 - FFI::Platypus::Function::Wrapper 1.24 - FFI::Platypus::Internal 1.24 - FFI::Platypus::Lang 1.24 - FFI::Platypus::Lang::ASM 1.24 - FFI::Platypus::Lang::C 1.24 - FFI::Platypus::Lang::Win32 1.24 - FFI::Platypus::Legacy 1.24 - FFI::Platypus::Memory 1.24 - FFI::Platypus::Record 1.24 - FFI::Platypus::Record::Meta 1.24 - FFI::Platypus::Record::TieArray 1.24 - FFI::Platypus::ShareConfig 1.24 - FFI::Platypus::Type 1.24 - FFI::Platypus::Type::PointerSizeBuffer 1.24 - FFI::Platypus::Type::StringArray 1.24 - FFI::Platypus::Type::StringPointer 1.24 - FFI::Platypus::TypeParser 1.24 - FFI::Platypus::TypeParser::Version0 1.24 - FFI::Platypus::TypeParser::Version1 1.24 - FFI::Probe 1.24 - FFI::Probe::Runner 1.24 - FFI::Probe::Runner::Builder 1.24 - FFI::Probe::Runner::Result 1.24 - FFI::Temp 1.24 + FFI-Platypus-1.34 + pathname: P/PL/PLICEASE/FFI-Platypus-1.34.tar.gz + provides: + FFI::Build 1.34 + FFI::Build::File::Base 1.34 + FFI::Build::File::C 1.34 + FFI::Build::File::CXX 1.34 + FFI::Build::File::Library 1.34 + FFI::Build::File::Object 1.34 + FFI::Build::MM 1.34 + FFI::Build::MM::FBX 1.34 + FFI::Build::Platform 1.34 + FFI::Platypus 1.34 + FFI::Platypus::API 1.34 + FFI::Platypus::Buffer 1.34 + FFI::Platypus::Bundle 1.34 + FFI::Platypus::Closure 1.34 + FFI::Platypus::ClosureData 1.34 + FFI::Platypus::Constant 1.34 + FFI::Platypus::DL 1.34 + FFI::Platypus::Function 1.34 + FFI::Platypus::Function::Function 1.34 + FFI::Platypus::Function::Wrapper 1.34 + FFI::Platypus::Internal 1.34 + FFI::Platypus::Lang 1.34 + FFI::Platypus::Lang::ASM 1.34 + FFI::Platypus::Lang::C 1.34 + FFI::Platypus::Lang::Win32 1.34 + FFI::Platypus::Legacy 1.34 + FFI::Platypus::Memory 1.34 + FFI::Platypus::Record 1.34 + FFI::Platypus::Record::Meta 1.34 + FFI::Platypus::Record::TieArray 1.34 + FFI::Platypus::ShareConfig 1.34 + FFI::Platypus::Type 1.34 + FFI::Platypus::Type::PointerSizeBuffer 1.34 + FFI::Platypus::Type::StringArray 1.34 + FFI::Platypus::Type::StringPointer 1.34 + FFI::Platypus::TypeParser 1.34 + FFI::Platypus::TypeParser::Version0 1.34 + FFI::Platypus::TypeParser::Version1 1.34 + FFI::Probe 1.34 + FFI::Probe::Runner 1.34 + FFI::Probe::Runner::Builder 1.34 + FFI::Probe::Runner::Result 1.34 + FFI::Temp 1.34 requirements: Capture::Tiny 0 ExtUtils::CBuilder 0 @@ -2833,7 +2859,7 @@ DISTRIBUTIONS JSON::PP 0 List::Util 1.45 constant 1.32 - perl 5.008001 + perl 5.008004 File-BaseDir-0.08 pathname: K/KI/KIMRYAN/File-BaseDir-0.08.tar.gz provides: @@ -2887,19 +2913,19 @@ DISTRIBUTIONS IO::Event 0.812 Test::SharedFork 0 Time::HiRes 0 - File-HomeDir-1.004 - pathname: R/RE/REHSACK/File-HomeDir-1.004.tar.gz - provides: - File::HomeDir 1.004 - File::HomeDir::Darwin 1.004 - File::HomeDir::Darwin::Carbon 1.004 - File::HomeDir::Darwin::Cocoa 1.004 - File::HomeDir::Driver 1.004 - File::HomeDir::FreeDesktop 1.004 - File::HomeDir::MacOS9 1.004 - File::HomeDir::Test 1.004 - File::HomeDir::Unix 1.004 - File::HomeDir::Windows 1.004 + File-HomeDir-1.006 + pathname: R/RE/REHSACK/File-HomeDir-1.006.tar.gz + provides: + File::HomeDir 1.006 + File::HomeDir::Darwin 1.006 + File::HomeDir::Darwin::Carbon 1.006 + File::HomeDir::Darwin::Cocoa 1.006 + File::HomeDir::Driver 1.006 + File::HomeDir::FreeDesktop 1.006 + File::HomeDir::MacOS9 1.006 + File::HomeDir::Test 1.006 + File::HomeDir::Unix 1.006 + File::HomeDir::Windows 1.006 requirements: Carp 0 Cwd 3.12 @@ -2911,28 +2937,33 @@ DISTRIBUTIONS File::Which 0.05 POSIX 0 perl 5.008003 - File-Listing-6.04 - pathname: G/GA/GAAS/File-Listing-6.04.tar.gz + File-Listing-6.14 + pathname: P/PL/PLICEASE/File-Listing-6.14.tar.gz provides: - File::Listing 6.04 - File::Listing::apache 6.04 - File::Listing::dosftp 6.04 - File::Listing::netware 6.04 - File::Listing::unix 6.04 - File::Listing::vms 6.04 + File::Listing 6.14 + File::Listing::apache 6.14 + File::Listing::dosftp 6.14 + File::Listing::netware 6.14 + File::Listing::unix 6.14 + File::Listing::vms 6.14 requirements: + Carp 0 + Exporter 0 ExtUtils::MakeMaker 0 - HTTP::Date 6 - perl 5.006002 - File-MimeInfo-0.29 - pathname: M/MI/MICHIELB/File-MimeInfo-0.29.tar.gz + HTTP::Date 0 + Time::Local 0 + base 0 + perl 5.006 + File-MimeInfo-0.30 + pathname: M/MI/MICHIELB/File-MimeInfo-0.30.tar.gz provides: - File::MimeInfo 0.29 - File::MimeInfo::Applications 0.29 - File::MimeInfo::Magic 0.29 - File::MimeInfo::Rox 0.29 + File::MimeInfo 0.30 + File::MimeInfo::Applications 0.30 + File::MimeInfo::Magic 0.30 + File::MimeInfo::Rox 0.30 requirements: Carp 0 + Encode::Locale 0 Exporter 0 ExtUtils::MakeMaker 6.30 Fcntl 0 @@ -2940,10 +2971,10 @@ DISTRIBUTIONS File::DesktopEntry 0.04 Pod::Usage 0 perl 5.006001 - File-ShareDir-1.116 - pathname: R/RE/REHSACK/File-ShareDir-1.116.tar.gz + File-ShareDir-1.118 + pathname: R/RE/REHSACK/File-ShareDir-1.118.tar.gz provides: - File::ShareDir 1.116 + File::ShareDir 1.118 requirements: Carp 0 Class::Inspector 1.12 @@ -2965,10 +2996,10 @@ DISTRIBUTIONS perl 5.006 strict 0 warnings 0 - File-Slurp-9999.30 - pathname: C/CA/CAPOEIRAB/File-Slurp-9999.30.tar.gz + File-Slurp-9999.32 + pathname: C/CA/CAPOEIRAB/File-Slurp-9999.32.tar.gz provides: - File::Slurp 9999.30 + File::Slurp 9999.32 requirements: B 0 Carp 0 @@ -3061,29 +3092,29 @@ DISTRIBUTIONS Scalar::Util 1.17 Test::Exception 0 Test::More 0 - Future-0.45 - pathname: P/PE/PEVANS/Future-0.45.tar.gz + Future-0.47 + pathname: P/PE/PEVANS/Future-0.47.tar.gz provides: - Future 0.45 - Future::Exception 0.45 - Future::Mutex 0.45 - Future::Queue 0.45 - Future::Utils 0.45 - Test::Future 0.45 - Test::Future::Deferred 0.45 + Future 0.47 + Future::Exception 0.47 + Future::Mutex 0.47 + Future::Queue 0.47 + Future::Utils 0.47 + Test::Future 0.47 + Test::Future::Deferred 0.47 requirements: Carp 1.25 Module::Build 0.4004 Test::Builder::Module 0 Time::HiRes 0 perl 5.010 - GD-2.71 - pathname: R/RU/RURBAN/GD-2.71.tar.gz + GD-2.73 + pathname: R/RU/RURBAN/GD-2.73.tar.gz provides: - GD 2.71 + GD 2.73 GD::Group 1 - GD::Image 2.71 - GD::Polygon 2.71 + GD::Image 2.73 + GD::Polygon 2.73 GD::Polyline 0.2 GD::Simple undef requirements: @@ -3259,21 +3290,28 @@ DISTRIBUTIONS XSLoader 0 parent 0 perl 5.008008 - HTML-Parser-3.72 - pathname: G/GA/GAAS/HTML-Parser-3.72.tar.gz + HTML-Parser-3.75 + pathname: C/CA/CAPOEIRAB/HTML-Parser-3.75.tar.gz provides: - HTML::Entities 3.69 - HTML::Filter 3.72 - HTML::HeadParser 3.71 - HTML::LinkExtor 3.69 - HTML::Parser 3.72 - HTML::PullParser 3.57 - HTML::TokeParser 3.69 + HTML::Entities 3.75 + HTML::Filter 3.75 + HTML::HeadParser 3.75 + HTML::LinkExtor 3.75 + HTML::Parser 3.75 + HTML::PullParser 3.75 + HTML::TokeParser 3.75 requirements: - ExtUtils::MakeMaker 0 - HTML::Tagset 3 + Carp 0 + Exporter 0 + ExtUtils::MakeMaker 6.52 + HTML::Tagset 0 + HTTP::Headers 0 + IO::File 0 + URI 0 + URI::URL 0 XSLoader 0 - perl 5.008 + strict 0 + vars 0 HTML-Scrubber-0.19 pathname: N/NI/NIGELM/HTML-Scrubber-0.19.tar.gz provides: @@ -3316,12 +3354,12 @@ DISTRIBUTIONS base 0 integer 0 perl 5.008 - HTTP-Cookies-6.08 - pathname: O/OA/OALDERS/HTTP-Cookies-6.08.tar.gz + HTTP-Cookies-6.10 + pathname: O/OA/OALDERS/HTTP-Cookies-6.10.tar.gz provides: - HTTP::Cookies 6.08 - HTTP::Cookies::Microsoft 6.08 - HTTP::Cookies::Netscape 6.08 + HTTP::Cookies 6.10 + HTTP::Cookies::Microsoft 6.10 + HTTP::Cookies::Netscape 6.10 requirements: Carp 0 ExtUtils::MakeMaker 0 @@ -3331,10 +3369,10 @@ DISTRIBUTIONS locale 0 perl 5.008001 strict 0 - HTTP-Daemon-6.06 - pathname: O/OA/OALDERS/HTTP-Daemon-6.06.tar.gz + HTTP-Daemon-6.12 + pathname: O/OA/OALDERS/HTTP-Daemon-6.12.tar.gz provides: - HTTP::Daemon 6.06 + HTTP::Daemon 6.12 requirements: Carp 0 ExtUtils::MakeMaker 0 @@ -3342,11 +3380,10 @@ DISTRIBUTIONS HTTP::Request 6 HTTP::Response 6 HTTP::Status 6 - IO::Socket::IP 0 + IO::Socket::IP 0.25 LWP::MediaTypes 6 Module::Build::Tiny 0.034 Socket 0 - Sys::Hostname 0 perl 5.006 strict 0 warnings 0 @@ -3361,10 +3398,10 @@ DISTRIBUTIONS Time::Zone 0 perl 5.006002 strict 0 - HTTP-Entity-Parser-0.22 - pathname: K/KA/KAZEBURO/HTTP-Entity-Parser-0.22.tar.gz + HTTP-Entity-Parser-0.25 + pathname: K/KA/KAZEBURO/HTTP-Entity-Parser-0.25.tar.gz provides: - HTTP::Entity::Parser 0.22 + HTTP::Entity::Parser 0.25 HTTP::Entity::Parser::JSON undef HTTP::Entity::Parser::MultiPart undef HTTP::Entity::Parser::OctetStream undef @@ -3388,19 +3425,19 @@ DISTRIBUTIONS HTTP::Date 0 Module::Build::Tiny 0.035 perl 5.008001 - HTTP-Message-6.22 - pathname: O/OA/OALDERS/HTTP-Message-6.22.tar.gz - provides: - HTTP::Config 6.22 - HTTP::Headers 6.22 - HTTP::Headers::Auth 6.22 - HTTP::Headers::ETag 6.22 - HTTP::Headers::Util 6.22 - HTTP::Message 6.22 - HTTP::Request 6.22 - HTTP::Request::Common 6.22 - HTTP::Response 6.22 - HTTP::Status 6.22 + HTTP-Message-6.27 + pathname: O/OA/OALDERS/HTTP-Message-6.27.tar.gz + provides: + HTTP::Config 6.27 + HTTP::Headers 6.27 + HTTP::Headers::Auth 6.27 + HTTP::Headers::ETag 6.27 + HTTP::Headers::Util 6.27 + HTTP::Message 6.27 + HTTP::Request 6.27 + HTTP::Request::Common 6.27 + HTTP::Response 6.27 + HTTP::Status 6.27 requirements: Carp 0 Compress::Raw::Zlib 0 @@ -3420,7 +3457,6 @@ DISTRIBUTIONS LWP::MediaTypes 6 MIME::Base64 2.1 MIME::QuotedPrint 0 - Storable 0 URI 1.10 base 0 perl 5.008001 @@ -3445,10 +3481,10 @@ DISTRIBUTIONS ExtUtils::MakeMaker 0 HTTP::Headers 6 perl 5.008001 - Hash-Merge-0.300 - pathname: R/RE/REHSACK/Hash-Merge-0.300.tar.gz + Hash-Merge-0.302 + pathname: H/HE/HERMES/Hash-Merge-0.302.tar.gz provides: - Hash::Merge 0.300 + Hash::Merge 0.302 requirements: Clone::Choose 0.008 ExtUtils::MakeMaker 6.64 @@ -3474,45 +3510,45 @@ DISTRIBUTIONS perl 5.006 strict 0 warnings 0 - IO-Async-0.76 - pathname: P/PE/PEVANS/IO-Async-0.76.tar.gz + IO-Async-0.78 + pathname: P/PE/PEVANS/IO-Async-0.78.tar.gz provides: Future::IO::Impl::IOAsync undef - IO::Async 0.76 - IO::Async::Channel 0.76 - IO::Async::Debug 0.76 - IO::Async::File 0.76 - IO::Async::FileStream 0.76 - IO::Async::Function 0.76 - IO::Async::Future 0.76 - IO::Async::Handle 0.76 - IO::Async::Internals::ChildManager 0.76 - IO::Async::Listener 0.76 - IO::Async::Loop 0.76 - IO::Async::Loop::Poll 0.76 - IO::Async::Loop::Select 0.76 - IO::Async::LoopTests 0.76 + IO::Async 0.78 + IO::Async::Channel 0.78 + IO::Async::Debug 0.78 + IO::Async::File 0.78 + IO::Async::FileStream 0.78 + IO::Async::Function 0.78 + IO::Async::Future 0.78 + IO::Async::Handle 0.78 + IO::Async::Internals::ChildManager 0.78 + IO::Async::Listener 0.78 + IO::Async::Loop 0.78 + IO::Async::Loop::Poll 0.78 + IO::Async::Loop::Select 0.78 + IO::Async::LoopTests 0.78 IO::Async::Metrics undef - IO::Async::Notifier 0.76 - IO::Async::OS 0.76 - IO::Async::OS::MSWin32 0.76 - IO::Async::OS::cygwin 0.76 - IO::Async::OS::linux 0.76 - IO::Async::PID 0.76 - IO::Async::Process 0.76 - IO::Async::Protocol 0.76 - IO::Async::Protocol::LineStream 0.76 - IO::Async::Protocol::Stream 0.76 - IO::Async::Resolver 0.76 - IO::Async::Routine 0.76 - IO::Async::Signal 0.76 - IO::Async::Socket 0.76 - IO::Async::Stream 0.76 - IO::Async::Test 0.76 - IO::Async::Timer 0.76 - IO::Async::Timer::Absolute 0.76 - IO::Async::Timer::Countdown 0.76 - IO::Async::Timer::Periodic 0.76 + IO::Async::Notifier 0.78 + IO::Async::OS 0.78 + IO::Async::OS::MSWin32 0.78 + IO::Async::OS::cygwin 0.78 + IO::Async::OS::linux 0.78 + IO::Async::PID 0.78 + IO::Async::Process 0.78 + IO::Async::Protocol 0.78 + IO::Async::Protocol::LineStream 0.78 + IO::Async::Protocol::Stream 0.78 + IO::Async::Resolver 0.78 + IO::Async::Routine 0.78 + IO::Async::Signal 0.78 + IO::Async::Socket 0.78 + IO::Async::Stream 0.78 + IO::Async::Test 0.78 + IO::Async::Timer 0.78 + IO::Async::Timer::Absolute 0.78 + IO::Async::Timer::Countdown 0.78 + IO::Async::Timer::Periodic 0.78 requirements: Exporter 5.57 File::stat 0 @@ -3546,15 +3582,16 @@ DISTRIBUTIONS Test::Simple 0 Time::HiRes 0 diagnostics 0 - IO-HTML-1.001 - pathname: C/CJ/CJM/IO-HTML-1.001.tar.gz + IO-HTML-1.004 + pathname: C/CJ/CJM/IO-HTML-1.004.tar.gz provides: - IO::HTML 1.001 + IO::HTML 1.004 requirements: Carp 0 Encode 2.10 Exporter 5.57 - ExtUtils::MakeMaker 6.30 + ExtUtils::MakeMaker 0 + perl 5.008 IO-SessionData-1.03 pathname: P/PH/PHRED/IO-SessionData-1.03.tar.gz provides: @@ -3562,17 +3599,17 @@ DISTRIBUTIONS IO::SessionSet undef requirements: ExtUtils::MakeMaker 0 - IO-Socket-SSL-2.068 - pathname: S/SU/SULLR/IO-Socket-SSL-2.068.tar.gz + IO-Socket-SSL-2.069 + pathname: S/SU/SULLR/IO-Socket-SSL-2.069.tar.gz provides: - IO::Socket::SSL 2.068 + IO::Socket::SSL 2.069 IO::Socket::SSL::Intercept 2.056 - IO::Socket::SSL::OCSP_Cache 2.068 - IO::Socket::SSL::OCSP_Resolver 2.068 + IO::Socket::SSL::OCSP_Cache 2.069 + IO::Socket::SSL::OCSP_Resolver 2.069 IO::Socket::SSL::PublicSuffix undef - IO::Socket::SSL::SSL_Context 2.068 - IO::Socket::SSL::SSL_HANDLE 2.068 - IO::Socket::SSL::Session_Cache 2.068 + IO::Socket::SSL::SSL_Context 2.069 + IO::Socket::SSL::SSL_HANDLE 2.069 + IO::Socket::SSL::Session_Cache 2.069 IO::Socket::SSL::Utils 2.014 requirements: ExtUtils::MakeMaker 0 @@ -3625,10 +3662,10 @@ DISTRIBUTIONS re 0 strict 0 warnings 0 - Importer-0.025 - pathname: E/EX/EXODIST/Importer-0.025.tar.gz + Importer-0.026 + pathname: E/EX/EXODIST/Importer-0.026.tar.gz provides: - Importer 0.025 + Importer 0.026 requirements: ExtUtils::MakeMaker 0 perl 5.008001 @@ -3651,10 +3688,10 @@ DISTRIBUTIONS perl 5.008 strict 0 warnings 0 - JSON-MaybeXS-1.004001 - pathname: E/ET/ETHER/JSON-MaybeXS-1.004001.tar.gz + JSON-MaybeXS-1.004003 + pathname: E/ET/ETHER/JSON-MaybeXS-1.004003.tar.gz provides: - JSON::MaybeXS 1.004001 + JSON::MaybeXS 1.004003 requirements: Carp 0 Cpanel::JSON::XS 2.3310 @@ -3694,25 +3731,31 @@ DISTRIBUTIONS Router::Simple 0 Test::More 0 parent 0 - JSON-Validator-3.25 - pathname: J/JH/JHTHORSEN/JSON-Validator-3.25.tar.gz + JSON-Validator-4.10 + pathname: J/JH/JHTHORSEN/JSON-Validator-4.10.tar.gz provides: - JSON::Validator 3.25 + JSON::Validator 4.10 JSON::Validator::Error undef JSON::Validator::Formats undef JSON::Validator::Joi undef JSON::Validator::Ref undef + JSON::Validator::Schema undef + JSON::Validator::Schema::Draft201909 undef + JSON::Validator::Schema::Draft4 undef + JSON::Validator::Schema::Draft6 undef + JSON::Validator::Schema::Draft7 undef + JSON::Validator::Store undef JSON::Validator::Util undef requirements: ExtUtils::MakeMaker 0 List::Util 1.45 Mojolicious 7.28 - YAML::XS 0.80 + YAML::PP 0.020 perl 5.010001 - JSON-XS-4.02 - pathname: M/ML/MLEHMANN/JSON-XS-4.02.tar.gz + JSON-XS-4.03 + pathname: M/ML/MLEHMANN/JSON-XS-4.03.tar.gz provides: - JSON::XS 4.02 + JSON::XS 4.03 requirements: Canary::Stability 0 ExtUtils::MakeMaker 6.52 @@ -3730,18 +3773,21 @@ DISTRIBUTIONS Scalar::Util 0 perl 5.006002 strict 0 - LWP-Protocol-https-6.07 - pathname: O/OA/OALDERS/LWP-Protocol-https-6.07.tar.gz + LWP-Protocol-https-6.10 + pathname: O/OA/OALDERS/LWP-Protocol-https-6.10.tar.gz provides: - LWP::Protocol::https 6.07 - LWP::Protocol::https::Socket 6.07 + LWP::Protocol::https 6.10 + LWP::Protocol::https::Socket 6.10 requirements: ExtUtils::MakeMaker 0 IO::Socket::SSL 1.54 + LWP::Protocol::http 0 LWP::UserAgent 6.06 - Mozilla::CA 20110101 + Mozilla::CA 20180117 Net::HTTPS 6 + base 0 perl 5.008001 + strict 0 LWP-UserAgent-Determined-1.07 pathname: A/AL/ALEXMV/LWP-UserAgent-Determined-1.07.tar.gz provides: @@ -3765,10 +3811,10 @@ DISTRIBUTIONS Graphics::Primitive 0.43 Moose 0.79 Test::More 0 - Lingua-EN-Inflect-1.904 - pathname: D/DC/DCONWAY/Lingua-EN-Inflect-1.904.tar.gz + Lingua-EN-Inflect-1.905 + pathname: D/DC/DCONWAY/Lingua-EN-Inflect-1.905.tar.gz provides: - Lingua::EN::Inflect 1.904 + Lingua::EN::Inflect 1.905 requirements: ExtUtils::MakeMaker 0 Test::More 0 @@ -3795,19 +3841,19 @@ DISTRIBUTIONS XSLoader 0 strict 0 warnings 0 - List-MoreUtils-0.428 - pathname: R/RE/REHSACK/List-MoreUtils-0.428.tar.gz + List-MoreUtils-0.430 + pathname: R/RE/REHSACK/List-MoreUtils-0.430.tar.gz provides: - List::MoreUtils 0.428 - List::MoreUtils::PP 0.428 + List::MoreUtils 0.430 + List::MoreUtils::PP 0.430 requirements: Exporter::Tiny 0.038 ExtUtils::MakeMaker 0 - List::MoreUtils::XS 0.426 - List-MoreUtils-XS-0.428 - pathname: R/RE/REHSACK/List-MoreUtils-XS-0.428.tar.gz + List::MoreUtils::XS 0.430 + List-MoreUtils-XS-0.430 + pathname: R/RE/REHSACK/List-MoreUtils-XS-0.430.tar.gz provides: - List::MoreUtils::XS 0.428 + List::MoreUtils::XS 0.430 requirements: Carp 0 ExtUtils::MakeMaker 0 @@ -3855,27 +3901,27 @@ DISTRIBUTIONS constant 0 strict 0 warnings 0 - Log-Dispatch-2.69 - pathname: D/DR/DROLSKY/Log-Dispatch-2.69.tar.gz - provides: - Log::Dispatch 2.69 - Log::Dispatch::ApacheLog 2.69 - Log::Dispatch::Base 2.69 - Log::Dispatch::Code 2.69 - Log::Dispatch::Email 2.69 - Log::Dispatch::Email::MIMELite 2.69 - Log::Dispatch::Email::MailSend 2.69 - Log::Dispatch::Email::MailSender 2.69 - Log::Dispatch::Email::MailSendmail 2.69 - Log::Dispatch::File 2.69 - Log::Dispatch::File::Locked 2.69 - Log::Dispatch::Handle 2.69 - Log::Dispatch::Null 2.69 - Log::Dispatch::Output 2.69 - Log::Dispatch::Screen 2.69 - Log::Dispatch::Syslog 2.69 - Log::Dispatch::Types 2.69 - Log::Dispatch::Vars 2.69 + Log-Dispatch-2.70 + pathname: D/DR/DROLSKY/Log-Dispatch-2.70.tar.gz + provides: + Log::Dispatch 2.70 + Log::Dispatch::ApacheLog 2.70 + Log::Dispatch::Base 2.70 + Log::Dispatch::Code 2.70 + Log::Dispatch::Email 2.70 + Log::Dispatch::Email::MIMELite 2.70 + Log::Dispatch::Email::MailSend 2.70 + Log::Dispatch::Email::MailSender 2.70 + Log::Dispatch::Email::MailSendmail 2.70 + Log::Dispatch::File 2.70 + Log::Dispatch::File::Locked 2.70 + Log::Dispatch::Handle 2.70 + Log::Dispatch::Null 2.70 + Log::Dispatch::Output 2.70 + Log::Dispatch::Screen 2.70 + Log::Dispatch::Syslog 2.70 + Log::Dispatch::Types 2.70 + Log::Dispatch::Vars 2.70 requirements: Carp 0 Devel::GlobalDestruction 0 @@ -3902,11 +3948,11 @@ DISTRIBUTIONS perl 5.006 strict 0 warnings 0 - Log-Log4perl-1.49 - pathname: M/MS/MSCHILLI/Log-Log4perl-1.49.tar.gz + Log-Log4perl-1.53 + pathname: E/ET/ETJ/Log-Log4perl-1.53.tar.gz provides: L4pResurrectable 0.01 - Log::Log4perl 1.49 + Log::Log4perl 1.53 Log::Log4perl::Appender undef Log::Log4perl::Appender::Buffer undef Log::Log4perl::Appender::DBI undef @@ -3958,9 +4004,10 @@ DISTRIBUTIONS Log::Log4perl::Util::TimeTracker undef requirements: ExtUtils::MakeMaker 0 - File::Path 2.0606 + File::Path 2.07 File::Spec 0.82 Test::More 0.45 + perl 5.006 Log-Log4perl-Appender-Raven-0.006 pathname: J/JE/JETEVE/Log-Log4perl-Appender-Raven-0.006.tar.gz provides: @@ -3987,12 +4034,12 @@ DISTRIBUTIONS ExtUtils::MakeMaker 6.42 Test::More 0 perl 5.005 - MIME-Types-2.17 - pathname: M/MA/MARKOV/MIME-Types-2.17.tar.gz + MIME-Types-2.18 + pathname: M/MA/MARKOV/MIME-Types-2.18.tar.gz provides: - MIME::Type 2.17 - MIME::Types 2.17 - MojoX::MIME::Types 2.17 + MIME::Type 2.18 + MIME::Types 2.18 + MojoX::MIME::Types 2.18 requirements: ExtUtils::MakeMaker 0 File::Basename 0 @@ -4086,17 +4133,6 @@ DISTRIBUTIONS Net::Domain 1.05 Net::SMTP 1.03 Test::More 0 - Math-BigInt-1.999818 - pathname: P/PJ/PJACKLAM/Math-BigInt-1.999818.tar.gz - provides: - Math::BigFloat 1.999818 - Math::BigInt 1.999818 - Math::BigInt::Calc 1.999818 - Math::BigInt::Lib 1.999818 - requirements: - ExtUtils::MakeMaker 6.58 - Math::Complex 1.39 - perl 5.006001 Math-BigInt-GMP-1.6007 pathname: P/PJ/PJACKLAM/Math-BigInt-GMP-1.6007.tar.gz provides: @@ -4130,10 +4166,10 @@ DISTRIBUTIONS base 0 constant 0 perl 5.006002 - Math-Prime-Util-GMP-0.51 - pathname: D/DA/DANAJ/Math-Prime-Util-GMP-0.51.tar.gz + Math-Prime-Util-GMP-0.52 + pathname: D/DA/DANAJ/Math-Prime-Util-GMP-0.52.tar.gz provides: - Math::Prime::Util::GMP 0.51 + Math::Prime::Util::GMP 0.52 requirements: Carp 0 Exporter 5.57 @@ -4339,10 +4375,10 @@ DISTRIBUTIONS perl 5.006 strict 0 warnings 0 - Mojo-JWT-0.08 - pathname: J/JB/JBERGER/Mojo-JWT-0.08.tar.gz + Mojo-JWT-0.09 + pathname: J/JB/JBERGER/Mojo-JWT-0.09.tar.gz provides: - Mojo::JWT 0.08 + Mojo::JWT 0.09 requirements: Digest::SHA 0 MIME::Base64 3.11 @@ -4359,8 +4395,8 @@ DISTRIBUTIONS Mojolicious 2 Test::More 0.94 perl 5.010001 - Mojolicious-8.42 - pathname: S/SR/SRI/Mojolicious-8.42.tar.gz + Mojolicious-8.71 + pathname: S/SR/SRI/Mojolicious-8.71.tar.gz provides: Mojo undef Mojo::Asset undef @@ -4429,11 +4465,12 @@ DISTRIBUTIONS Mojo::UserAgent::Transactor undef Mojo::Util undef Mojo::WebSocket undef - Mojolicious 8.42 + Mojolicious 8.71 Mojolicious::Command undef Mojolicious::Command::Author::cpanify undef Mojolicious::Command::Author::generate undef Mojolicious::Command::Author::generate::app undef + Mojolicious::Command::Author::generate::dockerfile undef Mojolicious::Command::Author::generate::lite_app undef Mojolicious::Command::Author::generate::makefile undef Mojolicious::Command::Author::generate::plugin undef @@ -4457,6 +4494,7 @@ DISTRIBUTIONS Mojolicious::Plugin::HeaderCondition undef Mojolicious::Plugin::JSONConfig undef Mojolicious::Plugin::Mount undef + Mojolicious::Plugin::NotYAMLConfig undef Mojolicious::Plugin::TagHelpers undef Mojolicious::Plugins undef Mojolicious::Renderer undef @@ -4474,10 +4512,8 @@ DISTRIBUTIONS requirements: ExtUtils::MakeMaker 0 IO::Socket::IP 0.37 - JSON::PP 2.27103 - List::Util 1.41 - Time::Local 1.2 - perl 5.010001 + Sub::Util 1.41 + perl 5.016 Mojolicious-Plugin-ForwardedFor-0.001 pathname: D/DB/DBOOK/Mojolicious-Plugin-ForwardedFor-0.001.tar.gz provides: @@ -4486,10 +4522,18 @@ DISTRIBUTIONS Module::Build::Tiny 0.034 Mojolicious 7.0 perl 5.010001 - Mojolicious-Plugin-OAuth2-Server-0.44 - pathname: L/LE/LEEJO/Mojolicious-Plugin-OAuth2-Server-0.44.tar.gz + Mojolicious-Plugin-OAuth2-1.58 + pathname: J/JH/JHTHORSEN/Mojolicious-Plugin-OAuth2-1.58.tar.gz + provides: + Mojolicious::Plugin::OAuth2 1.58 + requirements: + ExtUtils::MakeMaker 0 + IO::Socket::SSL 1.94 + Mojolicious 7.53 + Mojolicious-Plugin-OAuth2-Server-0.47 + pathname: L/LE/LEEJO/Mojolicious-Plugin-OAuth2-Server-0.47.tar.gz provides: - Mojolicious::Plugin::OAuth2::Server 0.44 + Mojolicious::Plugin::OAuth2::Server 0.47 requirements: Carp 0 ExtUtils::MakeMaker 0 @@ -4497,26 +4541,26 @@ DISTRIBUTIONS FindBin 0 Mojo::JWT 0.08 Mojolicious 7.76 - Net::OAuth2::AuthorizationServer 0.21 + Net::OAuth2::AuthorizationServer 0.26 Test::Deep 0.113 Test::Exception 0.32 Test::Mojo 0 Test::More 0 perl 5.010001 - Moo-2.004000 - pathname: H/HA/HAARG/Moo-2.004000.tar.gz + Moo-2.004004 + pathname: H/HA/HAARG/Moo-2.004004.tar.gz provides: Method::Generate::Accessor undef Method::Generate::BuildAll undef Method::Generate::Constructor undef Method::Generate::DemolishAll undef - Moo 2.004000 + Moo 2.004004 Moo::HandleMoose undef Moo::HandleMoose::FakeConstructor undef Moo::HandleMoose::FakeMetaClass undef Moo::HandleMoose::_TypeMap undef Moo::Object undef - Moo::Role 2.004000 + Moo::Role 2.004004 Moo::_Utils undef Moo::_mro undef Moo::_strictures undef @@ -4526,7 +4570,6 @@ DISTRIBUTIONS Class::Method::Modifiers 1.10 Exporter 5.57 ExtUtils::MakeMaker 0 - Module::Runtime 0.014 Role::Tiny 2.001004 Scalar::Util 1.00 Sub::Defer 2.006006 @@ -4555,356 +4598,446 @@ DISTRIBUTIONS requirements: ExtUtils::MakeMaker 0 Module::Runtime 0.014 - Moose-2.2012 - pathname: E/ET/ETHER/Moose-2.2012.tar.gz - provides: - Class::MOP 2.2012 - Class::MOP::Attribute 2.2012 - Class::MOP::Class 2.2012 - Class::MOP::Instance 2.2012 - Class::MOP::Method 2.2012 - Class::MOP::Method::Accessor 2.2012 - Class::MOP::Method::Constructor 2.2012 - Class::MOP::Method::Generated 2.2012 - Class::MOP::Method::Inlined 2.2012 - Class::MOP::Method::Meta 2.2012 - Class::MOP::Method::Wrapped 2.2012 - Class::MOP::Module 2.2012 - Class::MOP::Object 2.2012 - Class::MOP::Overload 2.2012 - Class::MOP::Package 2.2012 - Moose 2.2012 - Moose::Cookbook 2.2012 - Moose::Cookbook::Basics::BankAccount_MethodModifiersAndSubclassing 2.2012 - Moose::Cookbook::Basics::BinaryTree_AttributeFeatures 2.2012 - Moose::Cookbook::Basics::BinaryTree_BuilderAndLazyBuild 2.2012 - Moose::Cookbook::Basics::Company_Subtypes 2.2012 - Moose::Cookbook::Basics::DateTime_ExtendingNonMooseParent 2.2012 - Moose::Cookbook::Basics::Document_AugmentAndInner 2.2012 - Moose::Cookbook::Basics::Genome_OverloadingSubtypesAndCoercion 2.2012 - Moose::Cookbook::Basics::HTTP_SubtypesAndCoercion 2.2012 - Moose::Cookbook::Basics::Immutable 2.2012 - Moose::Cookbook::Basics::Person_BUILDARGSAndBUILD 2.2012 - Moose::Cookbook::Basics::Point_AttributesAndSubclassing 2.2012 - Moose::Cookbook::Extending::Debugging_BaseClassRole 2.2012 - Moose::Cookbook::Extending::ExtensionOverview 2.2012 - Moose::Cookbook::Extending::Mooseish_MooseSugar 2.2012 - Moose::Cookbook::Legacy::Debugging_BaseClassReplacement 2.2012 - Moose::Cookbook::Legacy::Labeled_AttributeMetaclass 2.2012 - Moose::Cookbook::Legacy::Table_ClassMetaclass 2.2012 - Moose::Cookbook::Meta::GlobRef_InstanceMetaclass 2.2012 - Moose::Cookbook::Meta::Labeled_AttributeTrait 2.2012 - Moose::Cookbook::Meta::PrivateOrPublic_MethodMetaclass 2.2012 - Moose::Cookbook::Meta::Table_MetaclassTrait 2.2012 - Moose::Cookbook::Meta::WhyMeta 2.2012 - Moose::Cookbook::Roles::ApplicationToInstance 2.2012 - Moose::Cookbook::Roles::Comparable_CodeReuse 2.2012 - Moose::Cookbook::Roles::Restartable_AdvancedComposition 2.2012 - Moose::Cookbook::Snack::Keywords 2.2012 - Moose::Cookbook::Snack::Types 2.2012 - Moose::Cookbook::Style 2.2012 - Moose::Exception 2.2012 - Moose::Exception::AccessorMustReadWrite 2.2012 - Moose::Exception::AddParameterizableTypeTakesParameterizableType 2.2012 - Moose::Exception::AddRoleTakesAMooseMetaRoleInstance 2.2012 - Moose::Exception::AddRoleToARoleTakesAMooseMetaRole 2.2012 - Moose::Exception::ApplyTakesABlessedInstance 2.2012 - Moose::Exception::AttachToClassNeedsAClassMOPClassInstanceOrASubclass 2.2012 - Moose::Exception::AttributeConflictInRoles 2.2012 - Moose::Exception::AttributeConflictInSummation 2.2012 - Moose::Exception::AttributeExtensionIsNotSupportedInRoles 2.2012 - Moose::Exception::AttributeIsRequired 2.2012 - Moose::Exception::AttributeMustBeAnClassMOPMixinAttributeCoreOrSubclass 2.2012 - Moose::Exception::AttributeNamesDoNotMatch 2.2012 - Moose::Exception::AttributeValueIsNotAnObject 2.2012 - Moose::Exception::AttributeValueIsNotDefined 2.2012 - Moose::Exception::AutoDeRefNeedsArrayRefOrHashRef 2.2012 - Moose::Exception::BadOptionFormat 2.2012 - Moose::Exception::BothBuilderAndDefaultAreNotAllowed 2.2012 - Moose::Exception::BuilderDoesNotExist 2.2012 - Moose::Exception::BuilderMethodNotSupportedForAttribute 2.2012 - Moose::Exception::BuilderMethodNotSupportedForInlineAttribute 2.2012 - Moose::Exception::BuilderMustBeAMethodName 2.2012 - Moose::Exception::CallingMethodOnAnImmutableInstance 2.2012 - Moose::Exception::CallingReadOnlyMethodOnAnImmutableInstance 2.2012 - Moose::Exception::CanExtendOnlyClasses 2.2012 - Moose::Exception::CanOnlyConsumeRole 2.2012 - Moose::Exception::CanOnlyWrapBlessedCode 2.2012 - Moose::Exception::CanReblessOnlyIntoASubclass 2.2012 - Moose::Exception::CanReblessOnlyIntoASuperclass 2.2012 - Moose::Exception::CannotAddAdditionalTypeCoercionsToUnion 2.2012 - Moose::Exception::CannotAddAsAnAttributeToARole 2.2012 - Moose::Exception::CannotApplyBaseClassRolesToRole 2.2012 - Moose::Exception::CannotAssignValueToReadOnlyAccessor 2.2012 - Moose::Exception::CannotAugmentIfLocalMethodPresent 2.2012 - Moose::Exception::CannotAugmentNoSuperMethod 2.2012 - Moose::Exception::CannotAutoDerefWithoutIsa 2.2012 - Moose::Exception::CannotAutoDereferenceTypeConstraint 2.2012 - Moose::Exception::CannotCalculateNativeType 2.2012 - Moose::Exception::CannotCallAnAbstractBaseMethod 2.2012 - Moose::Exception::CannotCallAnAbstractMethod 2.2012 - Moose::Exception::CannotCoerceAWeakRef 2.2012 - Moose::Exception::CannotCoerceAttributeWhichHasNoCoercion 2.2012 - Moose::Exception::CannotCreateHigherOrderTypeWithoutATypeParameter 2.2012 - Moose::Exception::CannotCreateMethodAliasLocalMethodIsPresent 2.2012 - Moose::Exception::CannotCreateMethodAliasLocalMethodIsPresentInClass 2.2012 - Moose::Exception::CannotDelegateLocalMethodIsPresent 2.2012 - Moose::Exception::CannotDelegateWithoutIsa 2.2012 - Moose::Exception::CannotFindDelegateMetaclass 2.2012 - Moose::Exception::CannotFindType 2.2012 - Moose::Exception::CannotFindTypeGivenToMatchOnType 2.2012 - Moose::Exception::CannotFixMetaclassCompatibility 2.2012 - Moose::Exception::CannotGenerateInlineConstraint 2.2012 - Moose::Exception::CannotInitializeMooseMetaRoleComposite 2.2012 - Moose::Exception::CannotInlineTypeConstraintCheck 2.2012 - Moose::Exception::CannotLocatePackageInINC 2.2012 - Moose::Exception::CannotMakeMetaclassCompatible 2.2012 - Moose::Exception::CannotOverrideALocalMethod 2.2012 - Moose::Exception::CannotOverrideBodyOfMetaMethods 2.2012 - Moose::Exception::CannotOverrideLocalMethodIsPresent 2.2012 - Moose::Exception::CannotOverrideNoSuperMethod 2.2012 - Moose::Exception::CannotRegisterUnnamedTypeConstraint 2.2012 - Moose::Exception::CannotUseLazyBuildAndDefaultSimultaneously 2.2012 - Moose::Exception::CircularReferenceInAlso 2.2012 - Moose::Exception::ClassDoesNotHaveInitMeta 2.2012 - Moose::Exception::ClassDoesTheExcludedRole 2.2012 - Moose::Exception::ClassNamesDoNotMatch 2.2012 - Moose::Exception::CloneObjectExpectsAnInstanceOfMetaclass 2.2012 - Moose::Exception::CodeBlockMustBeACodeRef 2.2012 - Moose::Exception::CoercingWithoutCoercions 2.2012 - Moose::Exception::CoercionAlreadyExists 2.2012 - Moose::Exception::CoercionNeedsTypeConstraint 2.2012 - Moose::Exception::ConflictDetectedInCheckRoleExclusions 2.2012 - Moose::Exception::ConflictDetectedInCheckRoleExclusionsInToClass 2.2012 - Moose::Exception::ConstructClassInstanceTakesPackageName 2.2012 - Moose::Exception::CouldNotCreateMethod 2.2012 - Moose::Exception::CouldNotCreateWriter 2.2012 - Moose::Exception::CouldNotEvalConstructor 2.2012 - Moose::Exception::CouldNotEvalDestructor 2.2012 - Moose::Exception::CouldNotFindTypeConstraintToCoerceFrom 2.2012 - Moose::Exception::CouldNotGenerateInlineAttributeMethod 2.2012 - Moose::Exception::CouldNotLocateTypeConstraintForUnion 2.2012 - Moose::Exception::CouldNotParseType 2.2012 - Moose::Exception::CreateMOPClassTakesArrayRefOfAttributes 2.2012 - Moose::Exception::CreateMOPClassTakesArrayRefOfSuperclasses 2.2012 - Moose::Exception::CreateMOPClassTakesHashRefOfMethods 2.2012 - Moose::Exception::CreateTakesArrayRefOfRoles 2.2012 - Moose::Exception::CreateTakesHashRefOfAttributes 2.2012 - Moose::Exception::CreateTakesHashRefOfMethods 2.2012 - Moose::Exception::DefaultToMatchOnTypeMustBeCodeRef 2.2012 - Moose::Exception::DelegationToAClassWhichIsNotLoaded 2.2012 - Moose::Exception::DelegationToARoleWhichIsNotLoaded 2.2012 - Moose::Exception::DelegationToATypeWhichIsNotAClass 2.2012 - Moose::Exception::DoesRequiresRoleName 2.2012 - Moose::Exception::EnumCalledWithAnArrayRefAndAdditionalArgs 2.2012 - Moose::Exception::EnumValuesMustBeString 2.2012 - Moose::Exception::ExtendsMissingArgs 2.2012 - Moose::Exception::HandlesMustBeAHashRef 2.2012 - Moose::Exception::IllegalInheritedOptions 2.2012 - Moose::Exception::IllegalMethodTypeToAddMethodModifier 2.2012 - Moose::Exception::IncompatibleMetaclassOfSuperclass 2.2012 - Moose::Exception::InitMetaRequiresClass 2.2012 - Moose::Exception::InitializeTakesUnBlessedPackageName 2.2012 - Moose::Exception::InstanceBlessedIntoWrongClass 2.2012 - Moose::Exception::InstanceMustBeABlessedReference 2.2012 - Moose::Exception::InvalidArgPassedToMooseUtilMetaRole 2.2012 - Moose::Exception::InvalidArgumentToMethod 2.2012 - Moose::Exception::InvalidArgumentsToTraitAliases 2.2012 - Moose::Exception::InvalidBaseTypeGivenToCreateParameterizedTypeConstraint 2.2012 - Moose::Exception::InvalidHandleValue 2.2012 - Moose::Exception::InvalidHasProvidedInARole 2.2012 - Moose::Exception::InvalidNameForType 2.2012 - Moose::Exception::InvalidOverloadOperator 2.2012 - Moose::Exception::InvalidRoleApplication 2.2012 - Moose::Exception::InvalidTypeConstraint 2.2012 - Moose::Exception::InvalidTypeGivenToCreateParameterizedTypeConstraint 2.2012 - Moose::Exception::InvalidValueForIs 2.2012 - Moose::Exception::IsaDoesNotDoTheRole 2.2012 - Moose::Exception::IsaLacksDoesMethod 2.2012 - Moose::Exception::LazyAttributeNeedsADefault 2.2012 - Moose::Exception::Legacy 2.2012 - Moose::Exception::MOPAttributeNewNeedsAttributeName 2.2012 - Moose::Exception::MatchActionMustBeACodeRef 2.2012 - Moose::Exception::MessageParameterMustBeCodeRef 2.2012 - Moose::Exception::MetaclassIsAClassNotASubclassOfGivenMetaclass 2.2012 - Moose::Exception::MetaclassIsARoleNotASubclassOfGivenMetaclass 2.2012 - Moose::Exception::MetaclassIsNotASubclassOfGivenMetaclass 2.2012 - Moose::Exception::MetaclassMustBeASubclassOfMooseMetaClass 2.2012 - Moose::Exception::MetaclassMustBeASubclassOfMooseMetaRole 2.2012 - Moose::Exception::MetaclassMustBeDerivedFromClassMOPClass 2.2012 - Moose::Exception::MetaclassNotLoaded 2.2012 - Moose::Exception::MetaclassTypeIncompatible 2.2012 - Moose::Exception::MethodExpectedAMetaclassObject 2.2012 - Moose::Exception::MethodExpectsFewerArgs 2.2012 - Moose::Exception::MethodExpectsMoreArgs 2.2012 - Moose::Exception::MethodModifierNeedsMethodName 2.2012 - Moose::Exception::MethodNameConflictInRoles 2.2012 - Moose::Exception::MethodNameNotFoundInInheritanceHierarchy 2.2012 - Moose::Exception::MethodNameNotGiven 2.2012 - Moose::Exception::MustDefineAMethodName 2.2012 - Moose::Exception::MustDefineAnAttributeName 2.2012 - Moose::Exception::MustDefineAnOverloadOperator 2.2012 - Moose::Exception::MustHaveAtLeastOneValueToEnumerate 2.2012 - Moose::Exception::MustPassAHashOfOptions 2.2012 - Moose::Exception::MustPassAMooseMetaRoleInstanceOrSubclass 2.2012 - Moose::Exception::MustPassAPackageNameOrAnExistingClassMOPPackageInstance 2.2012 - Moose::Exception::MustPassEvenNumberOfArguments 2.2012 - Moose::Exception::MustPassEvenNumberOfAttributeOptions 2.2012 - Moose::Exception::MustProvideANameForTheAttribute 2.2012 - Moose::Exception::MustSpecifyAtleastOneMethod 2.2012 - Moose::Exception::MustSpecifyAtleastOneRole 2.2012 - Moose::Exception::MustSpecifyAtleastOneRoleToApplicant 2.2012 - Moose::Exception::MustSupplyAClassMOPAttributeInstance 2.2012 - Moose::Exception::MustSupplyADelegateToMethod 2.2012 - Moose::Exception::MustSupplyAMetaclass 2.2012 - Moose::Exception::MustSupplyAMooseMetaAttributeInstance 2.2012 - Moose::Exception::MustSupplyAnAccessorTypeToConstructWith 2.2012 - Moose::Exception::MustSupplyAnAttributeToConstructWith 2.2012 - Moose::Exception::MustSupplyArrayRefAsCurriedArguments 2.2012 - Moose::Exception::MustSupplyPackageNameAndName 2.2012 - Moose::Exception::NeedsTypeConstraintUnionForTypeCoercionUnion 2.2012 - Moose::Exception::NeitherAttributeNorAttributeNameIsGiven 2.2012 - Moose::Exception::NeitherClassNorClassNameIsGiven 2.2012 - Moose::Exception::NeitherRoleNorRoleNameIsGiven 2.2012 - Moose::Exception::NeitherTypeNorTypeNameIsGiven 2.2012 - Moose::Exception::NoAttributeFoundInSuperClass 2.2012 - Moose::Exception::NoBodyToInitializeInAnAbstractBaseClass 2.2012 - Moose::Exception::NoCasesMatched 2.2012 - Moose::Exception::NoConstraintCheckForTypeConstraint 2.2012 - Moose::Exception::NoDestructorClassSpecified 2.2012 - Moose::Exception::NoImmutableTraitSpecifiedForClass 2.2012 - Moose::Exception::NoParentGivenToSubtype 2.2012 - Moose::Exception::OnlyInstancesCanBeCloned 2.2012 - Moose::Exception::OperatorIsRequired 2.2012 - Moose::Exception::OverloadConflictInSummation 2.2012 - Moose::Exception::OverloadRequiresAMetaClass 2.2012 - Moose::Exception::OverloadRequiresAMetaMethod 2.2012 - Moose::Exception::OverloadRequiresAMetaOverload 2.2012 - Moose::Exception::OverloadRequiresAMethodNameOrCoderef 2.2012 - Moose::Exception::OverloadRequiresAnOperator 2.2012 - Moose::Exception::OverloadRequiresNamesForCoderef 2.2012 - Moose::Exception::OverrideConflictInComposition 2.2012 - Moose::Exception::OverrideConflictInSummation 2.2012 - Moose::Exception::PackageDoesNotUseMooseExporter 2.2012 - Moose::Exception::PackageNameAndNameParamsNotGivenToWrap 2.2012 - Moose::Exception::PackagesAndModulesAreNotCachable 2.2012 - Moose::Exception::ParameterIsNotSubtypeOfParent 2.2012 - Moose::Exception::ReferencesAreNotAllowedAsDefault 2.2012 - Moose::Exception::RequiredAttributeLacksInitialization 2.2012 - Moose::Exception::RequiredAttributeNeedsADefault 2.2012 - Moose::Exception::RequiredMethodsImportedByClass 2.2012 - Moose::Exception::RequiredMethodsNotImplementedByClass 2.2012 - Moose::Exception::Role::Attribute 2.2012 - Moose::Exception::Role::AttributeName 2.2012 - Moose::Exception::Role::Class 2.2012 - Moose::Exception::Role::EitherAttributeOrAttributeName 2.2012 - Moose::Exception::Role::Instance 2.2012 - Moose::Exception::Role::InstanceClass 2.2012 - Moose::Exception::Role::InvalidAttributeOptions 2.2012 - Moose::Exception::Role::Method 2.2012 - Moose::Exception::Role::ParamsHash 2.2012 - Moose::Exception::Role::Role 2.2012 - Moose::Exception::Role::RoleForCreate 2.2012 - Moose::Exception::Role::RoleForCreateMOPClass 2.2012 - Moose::Exception::Role::TypeConstraint 2.2012 - Moose::Exception::RoleDoesTheExcludedRole 2.2012 - Moose::Exception::RoleExclusionConflict 2.2012 - Moose::Exception::RoleNameRequired 2.2012 - Moose::Exception::RoleNameRequiredForMooseMetaRole 2.2012 - Moose::Exception::RolesDoNotSupportAugment 2.2012 - Moose::Exception::RolesDoNotSupportExtends 2.2012 - Moose::Exception::RolesDoNotSupportInner 2.2012 - Moose::Exception::RolesDoNotSupportRegexReferencesForMethodModifiers 2.2012 - Moose::Exception::RolesInCreateTakesAnArrayRef 2.2012 - Moose::Exception::RolesListMustBeInstancesOfMooseMetaRole 2.2012 - Moose::Exception::SingleParamsToNewMustBeHashRef 2.2012 - Moose::Exception::TriggerMustBeACodeRef 2.2012 - Moose::Exception::TypeConstraintCannotBeUsedForAParameterizableType 2.2012 - Moose::Exception::TypeConstraintIsAlreadyCreated 2.2012 - Moose::Exception::TypeParameterMustBeMooseMetaType 2.2012 - Moose::Exception::UnableToCanonicalizeHandles 2.2012 - Moose::Exception::UnableToCanonicalizeNonRolePackage 2.2012 - Moose::Exception::UnableToRecognizeDelegateMetaclass 2.2012 - Moose::Exception::UndefinedHashKeysPassedToMethod 2.2012 - Moose::Exception::UnionCalledWithAnArrayRefAndAdditionalArgs 2.2012 - Moose::Exception::UnionTakesAtleastTwoTypeNames 2.2012 - Moose::Exception::ValidationFailedForInlineTypeConstraint 2.2012 - Moose::Exception::ValidationFailedForTypeConstraint 2.2012 - Moose::Exception::WrapTakesACodeRefToBless 2.2012 - Moose::Exception::WrongTypeConstraintGiven 2.2012 - Moose::Exporter 2.2012 - Moose::Intro 2.2012 - Moose::Manual 2.2012 - Moose::Manual::Attributes 2.2012 - Moose::Manual::BestPractices 2.2012 - Moose::Manual::Classes 2.2012 - Moose::Manual::Concepts 2.2012 - Moose::Manual::Construction 2.2012 - Moose::Manual::Contributing 2.2012 - Moose::Manual::Delegation 2.2012 - Moose::Manual::Delta 2.2012 - Moose::Manual::Exceptions 2.2012 - Moose::Manual::Exceptions::Manifest 2.2012 - Moose::Manual::FAQ 2.2012 - Moose::Manual::MOP 2.2012 - Moose::Manual::MethodModifiers 2.2012 - Moose::Manual::MooseX 2.2012 - Moose::Manual::Resources 2.2012 - Moose::Manual::Roles 2.2012 - Moose::Manual::Support 2.2012 - Moose::Manual::Types 2.2012 - Moose::Manual::Unsweetened 2.2012 - Moose::Meta::Attribute 2.2012 - Moose::Meta::Attribute::Native 2.2012 - Moose::Meta::Attribute::Native::Trait::Array 2.2012 - Moose::Meta::Attribute::Native::Trait::Bool 2.2012 - Moose::Meta::Attribute::Native::Trait::Code 2.2012 - Moose::Meta::Attribute::Native::Trait::Counter 2.2012 - Moose::Meta::Attribute::Native::Trait::Hash 2.2012 - Moose::Meta::Attribute::Native::Trait::Number 2.2012 - Moose::Meta::Attribute::Native::Trait::String 2.2012 - Moose::Meta::Class 2.2012 - Moose::Meta::Instance 2.2012 - Moose::Meta::Method 2.2012 - Moose::Meta::Method::Accessor 2.2012 - Moose::Meta::Method::Augmented 2.2012 - Moose::Meta::Method::Constructor 2.2012 - Moose::Meta::Method::Delegation 2.2012 - Moose::Meta::Method::Destructor 2.2012 - Moose::Meta::Method::Meta 2.2012 - Moose::Meta::Method::Overridden 2.2012 - Moose::Meta::Role 2.2012 - Moose::Meta::Role::Application 2.2012 - Moose::Meta::Role::Application::RoleSummation 2.2012 - Moose::Meta::Role::Application::ToClass 2.2012 - Moose::Meta::Role::Application::ToInstance 2.2012 - Moose::Meta::Role::Application::ToRole 2.2012 - Moose::Meta::Role::Attribute 2.2012 - Moose::Meta::Role::Composite 2.2012 - Moose::Meta::Role::Method 2.2012 - Moose::Meta::Role::Method::Conflicting 2.2012 - Moose::Meta::Role::Method::Required 2.2012 - Moose::Meta::TypeCoercion 2.2012 - Moose::Meta::TypeCoercion::Union 2.2012 - Moose::Meta::TypeConstraint 2.2012 - Moose::Meta::TypeConstraint::Class 2.2012 - Moose::Meta::TypeConstraint::DuckType 2.2012 - Moose::Meta::TypeConstraint::Enum 2.2012 - Moose::Meta::TypeConstraint::Parameterizable 2.2012 - Moose::Meta::TypeConstraint::Parameterized 2.2012 - Moose::Meta::TypeConstraint::Registry 2.2012 - Moose::Meta::TypeConstraint::Role 2.2012 - Moose::Meta::TypeConstraint::Union 2.2012 - Moose::Object 2.2012 - Moose::Role 2.2012 - Moose::Spec::Role 2.2012 - Moose::Unsweetened 2.2012 - Moose::Util 2.2012 - Moose::Util::MetaRole 2.2012 - Moose::Util::TypeConstraints 2.2012 - Test::Moose 2.2012 - metaclass 2.2012 - oose 2.2012 + Moose-2.2014 + pathname: E/ET/ETHER/Moose-2.2014.tar.gz + provides: + Class::MOP 2.2014 + Class::MOP::Attribute 2.2014 + Class::MOP::Class 2.2014 + Class::MOP::Class::Immutable::Trait 2.2014 + Class::MOP::Deprecated 2.2014 + Class::MOP::Instance 2.2014 + Class::MOP::Method 2.2014 + Class::MOP::Method::Accessor 2.2014 + Class::MOP::Method::Constructor 2.2014 + Class::MOP::Method::Generated 2.2014 + Class::MOP::Method::Inlined 2.2014 + Class::MOP::Method::Meta 2.2014 + Class::MOP::Method::Wrapped 2.2014 + Class::MOP::MiniTrait 2.2014 + Class::MOP::Mixin 2.2014 + Class::MOP::Mixin::AttributeCore 2.2014 + Class::MOP::Mixin::HasAttributes 2.2014 + Class::MOP::Mixin::HasMethods 2.2014 + Class::MOP::Mixin::HasOverloads 2.2014 + Class::MOP::Module 2.2014 + Class::MOP::Object 2.2014 + Class::MOP::Overload 2.2014 + Class::MOP::Package 2.2014 + Moose 2.2014 + Moose::Cookbook 2.2014 + Moose::Cookbook::Basics::BankAccount_MethodModifiersAndSubclassing 2.2014 + Moose::Cookbook::Basics::BinaryTree_AttributeFeatures 2.2014 + Moose::Cookbook::Basics::BinaryTree_BuilderAndLazyBuild 2.2014 + Moose::Cookbook::Basics::Company_Subtypes 2.2014 + Moose::Cookbook::Basics::DateTime_ExtendingNonMooseParent 2.2014 + Moose::Cookbook::Basics::Document_AugmentAndInner 2.2014 + Moose::Cookbook::Basics::Genome_OverloadingSubtypesAndCoercion 2.2014 + Moose::Cookbook::Basics::HTTP_SubtypesAndCoercion 2.2014 + Moose::Cookbook::Basics::Immutable 2.2014 + Moose::Cookbook::Basics::Person_BUILDARGSAndBUILD 2.2014 + Moose::Cookbook::Basics::Point_AttributesAndSubclassing 2.2014 + Moose::Cookbook::Extending::Debugging_BaseClassRole 2.2014 + Moose::Cookbook::Extending::ExtensionOverview 2.2014 + Moose::Cookbook::Extending::Mooseish_MooseSugar 2.2014 + Moose::Cookbook::Legacy::Debugging_BaseClassReplacement 2.2014 + Moose::Cookbook::Legacy::Labeled_AttributeMetaclass 2.2014 + Moose::Cookbook::Legacy::Table_ClassMetaclass 2.2014 + Moose::Cookbook::Meta::GlobRef_InstanceMetaclass 2.2014 + Moose::Cookbook::Meta::Labeled_AttributeTrait 2.2014 + Moose::Cookbook::Meta::PrivateOrPublic_MethodMetaclass 2.2014 + Moose::Cookbook::Meta::Table_MetaclassTrait 2.2014 + Moose::Cookbook::Meta::WhyMeta 2.2014 + Moose::Cookbook::Roles::ApplicationToInstance 2.2014 + Moose::Cookbook::Roles::Comparable_CodeReuse 2.2014 + Moose::Cookbook::Roles::Restartable_AdvancedComposition 2.2014 + Moose::Cookbook::Snack::Keywords 2.2014 + Moose::Cookbook::Snack::Types 2.2014 + Moose::Cookbook::Style 2.2014 + Moose::Deprecated 2.2014 + Moose::Exception 2.2014 + Moose::Exception::AccessorMustReadWrite 2.2014 + Moose::Exception::AddParameterizableTypeTakesParameterizableType 2.2014 + Moose::Exception::AddRoleTakesAMooseMetaRoleInstance 2.2014 + Moose::Exception::AddRoleToARoleTakesAMooseMetaRole 2.2014 + Moose::Exception::ApplyTakesABlessedInstance 2.2014 + Moose::Exception::AttachToClassNeedsAClassMOPClassInstanceOrASubclass 2.2014 + Moose::Exception::AttributeConflictInRoles 2.2014 + Moose::Exception::AttributeConflictInSummation 2.2014 + Moose::Exception::AttributeExtensionIsNotSupportedInRoles 2.2014 + Moose::Exception::AttributeIsRequired 2.2014 + Moose::Exception::AttributeMustBeAnClassMOPMixinAttributeCoreOrSubclass 2.2014 + Moose::Exception::AttributeNamesDoNotMatch 2.2014 + Moose::Exception::AttributeValueIsNotAnObject 2.2014 + Moose::Exception::AttributeValueIsNotDefined 2.2014 + Moose::Exception::AutoDeRefNeedsArrayRefOrHashRef 2.2014 + Moose::Exception::BadOptionFormat 2.2014 + Moose::Exception::BothBuilderAndDefaultAreNotAllowed 2.2014 + Moose::Exception::BuilderDoesNotExist 2.2014 + Moose::Exception::BuilderMethodNotSupportedForAttribute 2.2014 + Moose::Exception::BuilderMethodNotSupportedForInlineAttribute 2.2014 + Moose::Exception::BuilderMustBeAMethodName 2.2014 + Moose::Exception::CallingMethodOnAnImmutableInstance 2.2014 + Moose::Exception::CallingReadOnlyMethodOnAnImmutableInstance 2.2014 + Moose::Exception::CanExtendOnlyClasses 2.2014 + Moose::Exception::CanOnlyConsumeRole 2.2014 + Moose::Exception::CanOnlyWrapBlessedCode 2.2014 + Moose::Exception::CanReblessOnlyIntoASubclass 2.2014 + Moose::Exception::CanReblessOnlyIntoASuperclass 2.2014 + Moose::Exception::CannotAddAdditionalTypeCoercionsToUnion 2.2014 + Moose::Exception::CannotAddAsAnAttributeToARole 2.2014 + Moose::Exception::CannotApplyBaseClassRolesToRole 2.2014 + Moose::Exception::CannotAssignValueToReadOnlyAccessor 2.2014 + Moose::Exception::CannotAugmentIfLocalMethodPresent 2.2014 + Moose::Exception::CannotAugmentNoSuperMethod 2.2014 + Moose::Exception::CannotAutoDerefWithoutIsa 2.2014 + Moose::Exception::CannotAutoDereferenceTypeConstraint 2.2014 + Moose::Exception::CannotCalculateNativeType 2.2014 + Moose::Exception::CannotCallAnAbstractBaseMethod 2.2014 + Moose::Exception::CannotCallAnAbstractMethod 2.2014 + Moose::Exception::CannotCoerceAWeakRef 2.2014 + Moose::Exception::CannotCoerceAttributeWhichHasNoCoercion 2.2014 + Moose::Exception::CannotCreateHigherOrderTypeWithoutATypeParameter 2.2014 + Moose::Exception::CannotCreateMethodAliasLocalMethodIsPresent 2.2014 + Moose::Exception::CannotCreateMethodAliasLocalMethodIsPresentInClass 2.2014 + Moose::Exception::CannotDelegateLocalMethodIsPresent 2.2014 + Moose::Exception::CannotDelegateWithoutIsa 2.2014 + Moose::Exception::CannotFindDelegateMetaclass 2.2014 + Moose::Exception::CannotFindType 2.2014 + Moose::Exception::CannotFindTypeGivenToMatchOnType 2.2014 + Moose::Exception::CannotFixMetaclassCompatibility 2.2014 + Moose::Exception::CannotGenerateInlineConstraint 2.2014 + Moose::Exception::CannotInitializeMooseMetaRoleComposite 2.2014 + Moose::Exception::CannotInlineTypeConstraintCheck 2.2014 + Moose::Exception::CannotLocatePackageInINC 2.2014 + Moose::Exception::CannotMakeMetaclassCompatible 2.2014 + Moose::Exception::CannotOverrideALocalMethod 2.2014 + Moose::Exception::CannotOverrideBodyOfMetaMethods 2.2014 + Moose::Exception::CannotOverrideLocalMethodIsPresent 2.2014 + Moose::Exception::CannotOverrideNoSuperMethod 2.2014 + Moose::Exception::CannotRegisterUnnamedTypeConstraint 2.2014 + Moose::Exception::CannotUseLazyBuildAndDefaultSimultaneously 2.2014 + Moose::Exception::CircularReferenceInAlso 2.2014 + Moose::Exception::ClassDoesNotHaveInitMeta 2.2014 + Moose::Exception::ClassDoesTheExcludedRole 2.2014 + Moose::Exception::ClassNamesDoNotMatch 2.2014 + Moose::Exception::CloneObjectExpectsAnInstanceOfMetaclass 2.2014 + Moose::Exception::CodeBlockMustBeACodeRef 2.2014 + Moose::Exception::CoercingWithoutCoercions 2.2014 + Moose::Exception::CoercionAlreadyExists 2.2014 + Moose::Exception::CoercionNeedsTypeConstraint 2.2014 + Moose::Exception::ConflictDetectedInCheckRoleExclusions 2.2014 + Moose::Exception::ConflictDetectedInCheckRoleExclusionsInToClass 2.2014 + Moose::Exception::ConstructClassInstanceTakesPackageName 2.2014 + Moose::Exception::CouldNotCreateMethod 2.2014 + Moose::Exception::CouldNotCreateWriter 2.2014 + Moose::Exception::CouldNotEvalConstructor 2.2014 + Moose::Exception::CouldNotEvalDestructor 2.2014 + Moose::Exception::CouldNotFindTypeConstraintToCoerceFrom 2.2014 + Moose::Exception::CouldNotGenerateInlineAttributeMethod 2.2014 + Moose::Exception::CouldNotLocateTypeConstraintForUnion 2.2014 + Moose::Exception::CouldNotParseType 2.2014 + Moose::Exception::CreateMOPClassTakesArrayRefOfAttributes 2.2014 + Moose::Exception::CreateMOPClassTakesArrayRefOfSuperclasses 2.2014 + Moose::Exception::CreateMOPClassTakesHashRefOfMethods 2.2014 + Moose::Exception::CreateTakesArrayRefOfRoles 2.2014 + Moose::Exception::CreateTakesHashRefOfAttributes 2.2014 + Moose::Exception::CreateTakesHashRefOfMethods 2.2014 + Moose::Exception::DefaultToMatchOnTypeMustBeCodeRef 2.2014 + Moose::Exception::DelegationToAClassWhichIsNotLoaded 2.2014 + Moose::Exception::DelegationToARoleWhichIsNotLoaded 2.2014 + Moose::Exception::DelegationToATypeWhichIsNotAClass 2.2014 + Moose::Exception::DoesRequiresRoleName 2.2014 + Moose::Exception::EnumCalledWithAnArrayRefAndAdditionalArgs 2.2014 + Moose::Exception::EnumValuesMustBeString 2.2014 + Moose::Exception::ExtendsMissingArgs 2.2014 + Moose::Exception::HandlesMustBeAHashRef 2.2014 + Moose::Exception::IllegalInheritedOptions 2.2014 + Moose::Exception::IllegalMethodTypeToAddMethodModifier 2.2014 + Moose::Exception::IncompatibleMetaclassOfSuperclass 2.2014 + Moose::Exception::InitMetaRequiresClass 2.2014 + Moose::Exception::InitializeTakesUnBlessedPackageName 2.2014 + Moose::Exception::InstanceBlessedIntoWrongClass 2.2014 + Moose::Exception::InstanceMustBeABlessedReference 2.2014 + Moose::Exception::InvalidArgPassedToMooseUtilMetaRole 2.2014 + Moose::Exception::InvalidArgumentToMethod 2.2014 + Moose::Exception::InvalidArgumentsToTraitAliases 2.2014 + Moose::Exception::InvalidBaseTypeGivenToCreateParameterizedTypeConstraint 2.2014 + Moose::Exception::InvalidHandleValue 2.2014 + Moose::Exception::InvalidHasProvidedInARole 2.2014 + Moose::Exception::InvalidNameForType 2.2014 + Moose::Exception::InvalidOverloadOperator 2.2014 + Moose::Exception::InvalidRoleApplication 2.2014 + Moose::Exception::InvalidTypeConstraint 2.2014 + Moose::Exception::InvalidTypeGivenToCreateParameterizedTypeConstraint 2.2014 + Moose::Exception::InvalidValueForIs 2.2014 + Moose::Exception::IsaDoesNotDoTheRole 2.2014 + Moose::Exception::IsaLacksDoesMethod 2.2014 + Moose::Exception::LazyAttributeNeedsADefault 2.2014 + Moose::Exception::Legacy 2.2014 + Moose::Exception::MOPAttributeNewNeedsAttributeName 2.2014 + Moose::Exception::MatchActionMustBeACodeRef 2.2014 + Moose::Exception::MessageParameterMustBeCodeRef 2.2014 + Moose::Exception::MetaclassIsAClassNotASubclassOfGivenMetaclass 2.2014 + Moose::Exception::MetaclassIsARoleNotASubclassOfGivenMetaclass 2.2014 + Moose::Exception::MetaclassIsNotASubclassOfGivenMetaclass 2.2014 + Moose::Exception::MetaclassMustBeASubclassOfMooseMetaClass 2.2014 + Moose::Exception::MetaclassMustBeASubclassOfMooseMetaRole 2.2014 + Moose::Exception::MetaclassMustBeDerivedFromClassMOPClass 2.2014 + Moose::Exception::MetaclassNotLoaded 2.2014 + Moose::Exception::MetaclassTypeIncompatible 2.2014 + Moose::Exception::MethodExpectedAMetaclassObject 2.2014 + Moose::Exception::MethodExpectsFewerArgs 2.2014 + Moose::Exception::MethodExpectsMoreArgs 2.2014 + Moose::Exception::MethodModifierNeedsMethodName 2.2014 + Moose::Exception::MethodNameConflictInRoles 2.2014 + Moose::Exception::MethodNameNotFoundInInheritanceHierarchy 2.2014 + Moose::Exception::MethodNameNotGiven 2.2014 + Moose::Exception::MustDefineAMethodName 2.2014 + Moose::Exception::MustDefineAnAttributeName 2.2014 + Moose::Exception::MustDefineAnOverloadOperator 2.2014 + Moose::Exception::MustHaveAtLeastOneValueToEnumerate 2.2014 + Moose::Exception::MustPassAHashOfOptions 2.2014 + Moose::Exception::MustPassAMooseMetaRoleInstanceOrSubclass 2.2014 + Moose::Exception::MustPassAPackageNameOrAnExistingClassMOPPackageInstance 2.2014 + Moose::Exception::MustPassEvenNumberOfArguments 2.2014 + Moose::Exception::MustPassEvenNumberOfAttributeOptions 2.2014 + Moose::Exception::MustProvideANameForTheAttribute 2.2014 + Moose::Exception::MustSpecifyAtleastOneMethod 2.2014 + Moose::Exception::MustSpecifyAtleastOneRole 2.2014 + Moose::Exception::MustSpecifyAtleastOneRoleToApplicant 2.2014 + Moose::Exception::MustSupplyAClassMOPAttributeInstance 2.2014 + Moose::Exception::MustSupplyADelegateToMethod 2.2014 + Moose::Exception::MustSupplyAMetaclass 2.2014 + Moose::Exception::MustSupplyAMooseMetaAttributeInstance 2.2014 + Moose::Exception::MustSupplyAnAccessorTypeToConstructWith 2.2014 + Moose::Exception::MustSupplyAnAttributeToConstructWith 2.2014 + Moose::Exception::MustSupplyArrayRefAsCurriedArguments 2.2014 + Moose::Exception::MustSupplyPackageNameAndName 2.2014 + Moose::Exception::NeedsTypeConstraintUnionForTypeCoercionUnion 2.2014 + Moose::Exception::NeitherAttributeNorAttributeNameIsGiven 2.2014 + Moose::Exception::NeitherClassNorClassNameIsGiven 2.2014 + Moose::Exception::NeitherRoleNorRoleNameIsGiven 2.2014 + Moose::Exception::NeitherTypeNorTypeNameIsGiven 2.2014 + Moose::Exception::NoAttributeFoundInSuperClass 2.2014 + Moose::Exception::NoBodyToInitializeInAnAbstractBaseClass 2.2014 + Moose::Exception::NoCasesMatched 2.2014 + Moose::Exception::NoConstraintCheckForTypeConstraint 2.2014 + Moose::Exception::NoDestructorClassSpecified 2.2014 + Moose::Exception::NoImmutableTraitSpecifiedForClass 2.2014 + Moose::Exception::NoParentGivenToSubtype 2.2014 + Moose::Exception::OnlyInstancesCanBeCloned 2.2014 + Moose::Exception::OperatorIsRequired 2.2014 + Moose::Exception::OverloadConflictInSummation 2.2014 + Moose::Exception::OverloadRequiresAMetaClass 2.2014 + Moose::Exception::OverloadRequiresAMetaMethod 2.2014 + Moose::Exception::OverloadRequiresAMetaOverload 2.2014 + Moose::Exception::OverloadRequiresAMethodNameOrCoderef 2.2014 + Moose::Exception::OverloadRequiresAnOperator 2.2014 + Moose::Exception::OverloadRequiresNamesForCoderef 2.2014 + Moose::Exception::OverrideConflictInComposition 2.2014 + Moose::Exception::OverrideConflictInSummation 2.2014 + Moose::Exception::PackageDoesNotUseMooseExporter 2.2014 + Moose::Exception::PackageNameAndNameParamsNotGivenToWrap 2.2014 + Moose::Exception::PackagesAndModulesAreNotCachable 2.2014 + Moose::Exception::ParameterIsNotSubtypeOfParent 2.2014 + Moose::Exception::ReferencesAreNotAllowedAsDefault 2.2014 + Moose::Exception::RequiredAttributeLacksInitialization 2.2014 + Moose::Exception::RequiredAttributeNeedsADefault 2.2014 + Moose::Exception::RequiredMethodsImportedByClass 2.2014 + Moose::Exception::RequiredMethodsNotImplementedByClass 2.2014 + Moose::Exception::Role::Attribute 2.2014 + Moose::Exception::Role::AttributeName 2.2014 + Moose::Exception::Role::Class 2.2014 + Moose::Exception::Role::EitherAttributeOrAttributeName 2.2014 + Moose::Exception::Role::Instance 2.2014 + Moose::Exception::Role::InstanceClass 2.2014 + Moose::Exception::Role::InvalidAttributeOptions 2.2014 + Moose::Exception::Role::Method 2.2014 + Moose::Exception::Role::ParamsHash 2.2014 + Moose::Exception::Role::Role 2.2014 + Moose::Exception::Role::RoleForCreate 2.2014 + Moose::Exception::Role::RoleForCreateMOPClass 2.2014 + Moose::Exception::Role::TypeConstraint 2.2014 + Moose::Exception::RoleDoesTheExcludedRole 2.2014 + Moose::Exception::RoleExclusionConflict 2.2014 + Moose::Exception::RoleNameRequired 2.2014 + Moose::Exception::RoleNameRequiredForMooseMetaRole 2.2014 + Moose::Exception::RolesDoNotSupportAugment 2.2014 + Moose::Exception::RolesDoNotSupportExtends 2.2014 + Moose::Exception::RolesDoNotSupportInner 2.2014 + Moose::Exception::RolesDoNotSupportRegexReferencesForMethodModifiers 2.2014 + Moose::Exception::RolesInCreateTakesAnArrayRef 2.2014 + Moose::Exception::RolesListMustBeInstancesOfMooseMetaRole 2.2014 + Moose::Exception::SingleParamsToNewMustBeHashRef 2.2014 + Moose::Exception::TriggerMustBeACodeRef 2.2014 + Moose::Exception::TypeConstraintCannotBeUsedForAParameterizableType 2.2014 + Moose::Exception::TypeConstraintIsAlreadyCreated 2.2014 + Moose::Exception::TypeParameterMustBeMooseMetaType 2.2014 + Moose::Exception::UnableToCanonicalizeHandles 2.2014 + Moose::Exception::UnableToCanonicalizeNonRolePackage 2.2014 + Moose::Exception::UnableToRecognizeDelegateMetaclass 2.2014 + Moose::Exception::UndefinedHashKeysPassedToMethod 2.2014 + Moose::Exception::UnionCalledWithAnArrayRefAndAdditionalArgs 2.2014 + Moose::Exception::UnionTakesAtleastTwoTypeNames 2.2014 + Moose::Exception::ValidationFailedForInlineTypeConstraint 2.2014 + Moose::Exception::ValidationFailedForTypeConstraint 2.2014 + Moose::Exception::WrapTakesACodeRefToBless 2.2014 + Moose::Exception::WrongTypeConstraintGiven 2.2014 + Moose::Exporter 2.2014 + Moose::Intro 2.2014 + Moose::Manual 2.2014 + Moose::Manual::Attributes 2.2014 + Moose::Manual::BestPractices 2.2014 + Moose::Manual::Classes 2.2014 + Moose::Manual::Concepts 2.2014 + Moose::Manual::Construction 2.2014 + Moose::Manual::Contributing 2.2014 + Moose::Manual::Delegation 2.2014 + Moose::Manual::Delta 2.2014 + Moose::Manual::Exceptions 2.2014 + Moose::Manual::Exceptions::Manifest 2.2014 + Moose::Manual::FAQ 2.2014 + Moose::Manual::MOP 2.2014 + Moose::Manual::MethodModifiers 2.2014 + Moose::Manual::MooseX 2.2014 + Moose::Manual::Resources 2.2014 + Moose::Manual::Roles 2.2014 + Moose::Manual::Support 2.2014 + Moose::Manual::Types 2.2014 + Moose::Manual::Unsweetened 2.2014 + Moose::Meta::Attribute 2.2014 + Moose::Meta::Attribute::Native 2.2014 + Moose::Meta::Attribute::Native::Trait 2.2014 + Moose::Meta::Attribute::Native::Trait::Array 2.2014 + Moose::Meta::Attribute::Native::Trait::Bool 2.2014 + Moose::Meta::Attribute::Native::Trait::Code 2.2014 + Moose::Meta::Attribute::Native::Trait::Counter 2.2014 + Moose::Meta::Attribute::Native::Trait::Hash 2.2014 + Moose::Meta::Attribute::Native::Trait::Number 2.2014 + Moose::Meta::Attribute::Native::Trait::String 2.2014 + Moose::Meta::Class 2.2014 + Moose::Meta::Class::Immutable::Trait 2.2014 + Moose::Meta::Instance 2.2014 + Moose::Meta::Method 2.2014 + Moose::Meta::Method::Accessor 2.2014 + Moose::Meta::Method::Accessor::Native 2.2014 + Moose::Meta::Method::Accessor::Native::Array 2.2014 + Moose::Meta::Method::Accessor::Native::Array::Writer 2.2014 + Moose::Meta::Method::Accessor::Native::Array::accessor 2.2014 + Moose::Meta::Method::Accessor::Native::Array::clear 2.2014 + Moose::Meta::Method::Accessor::Native::Array::count 2.2014 + Moose::Meta::Method::Accessor::Native::Array::delete 2.2014 + Moose::Meta::Method::Accessor::Native::Array::elements 2.2014 + Moose::Meta::Method::Accessor::Native::Array::first 2.2014 + Moose::Meta::Method::Accessor::Native::Array::first_index 2.2014 + Moose::Meta::Method::Accessor::Native::Array::get 2.2014 + Moose::Meta::Method::Accessor::Native::Array::grep 2.2014 + Moose::Meta::Method::Accessor::Native::Array::insert 2.2014 + Moose::Meta::Method::Accessor::Native::Array::is_empty 2.2014 + Moose::Meta::Method::Accessor::Native::Array::join 2.2014 + Moose::Meta::Method::Accessor::Native::Array::map 2.2014 + Moose::Meta::Method::Accessor::Native::Array::natatime 2.2014 + Moose::Meta::Method::Accessor::Native::Array::pop 2.2014 + Moose::Meta::Method::Accessor::Native::Array::push 2.2014 + Moose::Meta::Method::Accessor::Native::Array::reduce 2.2014 + Moose::Meta::Method::Accessor::Native::Array::set 2.2014 + Moose::Meta::Method::Accessor::Native::Array::shallow_clone 2.2014 + Moose::Meta::Method::Accessor::Native::Array::shift 2.2014 + Moose::Meta::Method::Accessor::Native::Array::shuffle 2.2014 + Moose::Meta::Method::Accessor::Native::Array::sort 2.2014 + Moose::Meta::Method::Accessor::Native::Array::sort_in_place 2.2014 + Moose::Meta::Method::Accessor::Native::Array::splice 2.2014 + Moose::Meta::Method::Accessor::Native::Array::uniq 2.2014 + Moose::Meta::Method::Accessor::Native::Array::unshift 2.2014 + Moose::Meta::Method::Accessor::Native::Bool::not 2.2014 + Moose::Meta::Method::Accessor::Native::Bool::set 2.2014 + Moose::Meta::Method::Accessor::Native::Bool::toggle 2.2014 + Moose::Meta::Method::Accessor::Native::Bool::unset 2.2014 + Moose::Meta::Method::Accessor::Native::Code::execute 2.2014 + Moose::Meta::Method::Accessor::Native::Code::execute_method 2.2014 + Moose::Meta::Method::Accessor::Native::Collection 2.2014 + Moose::Meta::Method::Accessor::Native::Counter::Writer 2.2014 + Moose::Meta::Method::Accessor::Native::Counter::dec 2.2014 + Moose::Meta::Method::Accessor::Native::Counter::inc 2.2014 + Moose::Meta::Method::Accessor::Native::Counter::reset 2.2014 + Moose::Meta::Method::Accessor::Native::Counter::set 2.2014 + Moose::Meta::Method::Accessor::Native::Hash 2.2014 + Moose::Meta::Method::Accessor::Native::Hash::Writer 2.2014 + Moose::Meta::Method::Accessor::Native::Hash::accessor 2.2014 + Moose::Meta::Method::Accessor::Native::Hash::clear 2.2014 + Moose::Meta::Method::Accessor::Native::Hash::count 2.2014 + Moose::Meta::Method::Accessor::Native::Hash::defined 2.2014 + Moose::Meta::Method::Accessor::Native::Hash::delete 2.2014 + Moose::Meta::Method::Accessor::Native::Hash::elements 2.2014 + Moose::Meta::Method::Accessor::Native::Hash::exists 2.2014 + Moose::Meta::Method::Accessor::Native::Hash::get 2.2014 + Moose::Meta::Method::Accessor::Native::Hash::is_empty 2.2014 + Moose::Meta::Method::Accessor::Native::Hash::keys 2.2014 + Moose::Meta::Method::Accessor::Native::Hash::kv 2.2014 + Moose::Meta::Method::Accessor::Native::Hash::set 2.2014 + Moose::Meta::Method::Accessor::Native::Hash::shallow_clone 2.2014 + Moose::Meta::Method::Accessor::Native::Hash::values 2.2014 + Moose::Meta::Method::Accessor::Native::Number::abs 2.2014 + Moose::Meta::Method::Accessor::Native::Number::add 2.2014 + Moose::Meta::Method::Accessor::Native::Number::div 2.2014 + Moose::Meta::Method::Accessor::Native::Number::mod 2.2014 + Moose::Meta::Method::Accessor::Native::Number::mul 2.2014 + Moose::Meta::Method::Accessor::Native::Number::set 2.2014 + Moose::Meta::Method::Accessor::Native::Number::sub 2.2014 + Moose::Meta::Method::Accessor::Native::Reader 2.2014 + Moose::Meta::Method::Accessor::Native::String::append 2.2014 + Moose::Meta::Method::Accessor::Native::String::chomp 2.2014 + Moose::Meta::Method::Accessor::Native::String::chop 2.2014 + Moose::Meta::Method::Accessor::Native::String::clear 2.2014 + Moose::Meta::Method::Accessor::Native::String::inc 2.2014 + Moose::Meta::Method::Accessor::Native::String::length 2.2014 + Moose::Meta::Method::Accessor::Native::String::match 2.2014 + Moose::Meta::Method::Accessor::Native::String::prepend 2.2014 + Moose::Meta::Method::Accessor::Native::String::replace 2.2014 + Moose::Meta::Method::Accessor::Native::String::substr 2.2014 + Moose::Meta::Method::Accessor::Native::Writer 2.2014 + Moose::Meta::Method::Augmented 2.2014 + Moose::Meta::Method::Constructor 2.2014 + Moose::Meta::Method::Delegation 2.2014 + Moose::Meta::Method::Destructor 2.2014 + Moose::Meta::Method::Meta 2.2014 + Moose::Meta::Method::Overridden 2.2014 + Moose::Meta::Mixin::AttributeCore 2.2014 + Moose::Meta::Object::Trait 2.2014 + Moose::Meta::Role 2.2014 + Moose::Meta::Role::Application 2.2014 + Moose::Meta::Role::Application::RoleSummation 2.2014 + Moose::Meta::Role::Application::ToClass 2.2014 + Moose::Meta::Role::Application::ToInstance 2.2014 + Moose::Meta::Role::Application::ToRole 2.2014 + Moose::Meta::Role::Attribute 2.2014 + Moose::Meta::Role::Composite 2.2014 + Moose::Meta::Role::Method 2.2014 + Moose::Meta::Role::Method::Conflicting 2.2014 + Moose::Meta::Role::Method::Required 2.2014 + Moose::Meta::TypeCoercion 2.2014 + Moose::Meta::TypeCoercion::Union 2.2014 + Moose::Meta::TypeConstraint 2.2014 + Moose::Meta::TypeConstraint::Class 2.2014 + Moose::Meta::TypeConstraint::DuckType 2.2014 + Moose::Meta::TypeConstraint::Enum 2.2014 + Moose::Meta::TypeConstraint::Parameterizable 2.2014 + Moose::Meta::TypeConstraint::Parameterized 2.2014 + Moose::Meta::TypeConstraint::Registry 2.2014 + Moose::Meta::TypeConstraint::Role 2.2014 + Moose::Meta::TypeConstraint::Union 2.2014 + Moose::Object 2.2014 + Moose::Role 2.2014 + Moose::Spec::Role 2.2014 + Moose::Unsweetened 2.2014 + Moose::Util 2.2014 + Moose::Util::MetaRole 2.2014 + Moose::Util::TypeConstraints 2.2014 + Moose::Util::TypeConstraints::Builtins 2.2014 + Test::Moose 2.2014 + metaclass 2.2014 + oose 2.2014 requirements: Carp 1.22 Class::Load 0.09 @@ -4926,7 +5059,6 @@ DISTRIBUTIONS Params::Util 1.00 Scalar::Util 1.19 Sub::Exporter 0.980 - Sub::Identify 0 Sub::Name 0.20 Try::Tiny 0.17 parent 0.223 @@ -5039,137 +5171,145 @@ DISTRIBUTIONS perl 5.008 strict 0 warnings 0 - Mozilla-CA-20180117 - pathname: A/AB/ABH/Mozilla-CA-20180117.tar.gz + Mozilla-CA-20200520 + pathname: A/AB/ABH/Mozilla-CA-20200520.tar.gz provides: - Mozilla::CA 20180117 + Mozilla::CA 20200520 requirements: ExtUtils::MakeMaker 0 Test 0 perl 5.006 - Net-DNS-1.23 - pathname: N/NL/NLNETLABS/Net-DNS-1.23.tar.gz - provides: - Net::DNS 1.23 - Net::DNS::Domain 1726 - Net::DNS::DomainName 1605 - Net::DNS::DomainName1035 1605 - Net::DNS::DomainName2535 1605 - Net::DNS::Header 1709 - Net::DNS::Mailbox 1605 - Net::DNS::Mailbox1035 1605 - Net::DNS::Mailbox2535 1605 - Net::DNS::Nameserver 1761 - Net::DNS::Packet 1761 - Net::DNS::Parameters 1761 - Net::DNS::Question 1726 - Net::DNS::RR 1762 - Net::DNS::RR::A 1597 - Net::DNS::RR::AAAA 1597 - Net::DNS::RR::AFSDB 1597 - Net::DNS::RR::APL 1741 - Net::DNS::RR::APL::Item 1741 - Net::DNS::RR::CAA 1771 - Net::DNS::RR::CDNSKEY 1586 - Net::DNS::RR::CDS 1586 - Net::DNS::RR::CERT 1773 - Net::DNS::RR::CNAME 1597 - Net::DNS::RR::CSYNC 1741 - Net::DNS::RR::DHCID 1597 - Net::DNS::RR::DNAME 1597 - Net::DNS::RR::DNSKEY 1773 - Net::DNS::RR::DS 1774 - Net::DNS::RR::EUI48 1597 - Net::DNS::RR::EUI64 1597 - Net::DNS::RR::GPOS 1528 - Net::DNS::RR::HINFO 1597 - Net::DNS::RR::HIP 1749 - Net::DNS::RR::IPSECKEY 1718 - Net::DNS::RR::ISDN 1597 - Net::DNS::RR::KEY 1528 - Net::DNS::RR::KX 1597 - Net::DNS::RR::L32 1597 - Net::DNS::RR::L64 1597 - Net::DNS::RR::LOC 1597 - Net::DNS::RR::LP 1597 - Net::DNS::RR::MB 1528 - Net::DNS::RR::MG 1528 - Net::DNS::RR::MINFO 1597 - Net::DNS::RR::MR 1528 - Net::DNS::RR::MX 1597 - Net::DNS::RR::NAPTR 1597 - Net::DNS::RR::NID 1597 - Net::DNS::RR::NS 1597 - Net::DNS::RR::NSEC 1749 - Net::DNS::RR::NSEC3 1749 - Net::DNS::RR::NSEC3PARAM 1741 - Net::DNS::RR::NULL 1528 - Net::DNS::RR::OPENPGPKEY 1597 - Net::DNS::RR::OPT 1773 - Net::DNS::RR::OPT::CHAIN 1773 - Net::DNS::RR::OPT::CLIENT_SUBNET 1773 - Net::DNS::RR::OPT::COOKIE 1773 - Net::DNS::RR::OPT::DAU 1773 - Net::DNS::RR::OPT::DHU 1773 - Net::DNS::RR::OPT::EXPIRE 1773 - Net::DNS::RR::OPT::KEY_TAG 1773 - Net::DNS::RR::OPT::N3U 1773 - Net::DNS::RR::OPT::PADDING 1773 - Net::DNS::RR::OPT::TCP_KEEPALIVE 1773 - Net::DNS::RR::PTR 1597 - Net::DNS::RR::PX 1597 - Net::DNS::RR::RP 1597 - Net::DNS::RR::RRSIG 1754 - Net::DNS::RR::RT 1597 - Net::DNS::RR::SIG 1754 - Net::DNS::RR::SMIMEA 1741 - Net::DNS::RR::SOA 1597 - Net::DNS::RR::SPF 1593 - Net::DNS::RR::SRV 1597 - Net::DNS::RR::SSHFP 1741 - Net::DNS::RR::TKEY 1528 - Net::DNS::RR::TLSA 1741 - Net::DNS::RR::TSIG 1774 - Net::DNS::RR::TXT 1597 - Net::DNS::RR::URI 1597 - Net::DNS::RR::X25 1597 - Net::DNS::RR::ZONEMD 1771 - Net::DNS::Resolver 1740 - Net::DNS::Resolver::Base 1771 - Net::DNS::Resolver::MSWin32 1568 - Net::DNS::Resolver::Recurse 1748 - Net::DNS::Resolver::UNIX 1573 - Net::DNS::Resolver::android 1568 - Net::DNS::Resolver::cygwin 1719 - Net::DNS::Resolver::os2 1568 - Net::DNS::Resolver::os390 1719 - Net::DNS::Text 1762 - Net::DNS::Update 1774 - Net::DNS::ZoneFile 1769 - Net::DNS::ZoneFile::Generator 1769 - Net::DNS::ZoneFile::Text 1769 - requirements: + Net-DNS-1.29 + pathname: N/NL/NLNETLABS/Net-DNS-1.29.tar.gz + provides: + Net::DNS 1.29 + Net::DNS::Domain 1825 + Net::DNS::DomainName 1813 + Net::DNS::DomainName1035 1813 + Net::DNS::DomainName2535 1813 + Net::DNS::Header 1812 + Net::DNS::Mailbox 1813 + Net::DNS::Mailbox1035 1813 + Net::DNS::Mailbox2535 1813 + Net::DNS::Nameserver 1813 + Net::DNS::Packet 1818 + Net::DNS::Parameters 1823 + Net::DNS::Question 1812 + Net::DNS::RR 1812 + Net::DNS::RR::A 1814 + Net::DNS::RR::AAAA 1814 + Net::DNS::RR::AFSDB 1814 + Net::DNS::RR::AMTRELAY 1814 + Net::DNS::RR::APL 1814 + Net::DNS::RR::APL::Item 1814 + Net::DNS::RR::CAA 1814 + Net::DNS::RR::CDNSKEY 1814 + Net::DNS::RR::CDS 1814 + Net::DNS::RR::CERT 1814 + Net::DNS::RR::CNAME 1814 + Net::DNS::RR::CSYNC 1814 + Net::DNS::RR::DHCID 1814 + Net::DNS::RR::DNAME 1814 + Net::DNS::RR::DNSKEY 1814 + Net::DNS::RR::DS 1814 + Net::DNS::RR::EUI48 1814 + Net::DNS::RR::EUI64 1814 + Net::DNS::RR::GPOS 1814 + Net::DNS::RR::HINFO 1814 + Net::DNS::RR::HIP 1814 + Net::DNS::RR::HTTPS 1814 + Net::DNS::RR::IPSECKEY 1814 + Net::DNS::RR::ISDN 1814 + Net::DNS::RR::KEY 1814 + Net::DNS::RR::KX 1814 + Net::DNS::RR::L32 1814 + Net::DNS::RR::L64 1814 + Net::DNS::RR::LOC 1814 + Net::DNS::RR::LP 1814 + Net::DNS::RR::MB 1814 + Net::DNS::RR::MG 1814 + Net::DNS::RR::MINFO 1814 + Net::DNS::RR::MR 1814 + Net::DNS::RR::MX 1814 + Net::DNS::RR::NAPTR 1814 + Net::DNS::RR::NID 1814 + Net::DNS::RR::NS 1814 + Net::DNS::RR::NSEC 1812 + Net::DNS::RR::NSEC3 1814 + Net::DNS::RR::NSEC3PARAM 1814 + Net::DNS::RR::NULL 1814 + Net::DNS::RR::OPENPGPKEY 1814 + Net::DNS::RR::OPT 1823 + Net::DNS::RR::OPT::CHAIN 1823 + Net::DNS::RR::OPT::CLIENT_SUBNET 1823 + Net::DNS::RR::OPT::COOKIE 1823 + Net::DNS::RR::OPT::DAU 1823 + Net::DNS::RR::OPT::DHU 1823 + Net::DNS::RR::OPT::EXPIRE 1823 + Net::DNS::RR::OPT::EXTENDED_ERROR 1823 + Net::DNS::RR::OPT::KEY_TAG 1823 + Net::DNS::RR::OPT::N3U 1823 + Net::DNS::RR::OPT::PADDING 1823 + Net::DNS::RR::OPT::TCP_KEEPALIVE 1823 + Net::DNS::RR::PTR 1814 + Net::DNS::RR::PX 1814 + Net::DNS::RR::RP 1814 + Net::DNS::RR::RRSIG 1819 + Net::DNS::RR::RT 1814 + Net::DNS::RR::SIG 1819 + Net::DNS::RR::SMIMEA 1814 + Net::DNS::RR::SOA 1819 + Net::DNS::RR::SPF 1814 + Net::DNS::RR::SRV 1814 + Net::DNS::RR::SSHFP 1814 + Net::DNS::RR::SVCB 1823 + Net::DNS::RR::TKEY 1814 + Net::DNS::RR::TLSA 1814 + Net::DNS::RR::TSIG 1814 + Net::DNS::RR::TXT 1814 + Net::DNS::RR::URI 1814 + Net::DNS::RR::X25 1814 + Net::DNS::RR::ZONEMD 1814 + Net::DNS::Resolver 1818 + Net::DNS::Resolver::Base 1818 + Net::DNS::Resolver::MSWin32 1812 + Net::DNS::Resolver::Recurse 1811 + Net::DNS::Resolver::UNIX 1811 + Net::DNS::Resolver::android 1811 + Net::DNS::Resolver::cygwin 1811 + Net::DNS::Resolver::os2 1811 + Net::DNS::Resolver::os390 1811 + Net::DNS::Text 1813 + Net::DNS::Update 1814 + Net::DNS::ZoneFile 1813 + Net::DNS::ZoneFile::Generator 1813 + Net::DNS::ZoneFile::Text 1813 + requirements: + Carp 1.1 Digest::HMAC 1.03 Digest::MD5 2.13 Digest::SHA 5.23 - ExtUtils::MakeMaker 0 + Encode 2.26 + Exporter 5.56 + ExtUtils::MakeMaker 6.66 File::Spec 0.86 + Getopt::Long 2.43 IO::File 1.08 IO::Select 1.14 + IO::Socket 1.26 IO::Socket::IP 0.38 MIME::Base64 2.13 PerlIO 1.05 Scalar::Util 1.25 - Test::More 0.52 Time::Local 1.19 - perl 5.006 - Net-HTTP-6.19 - pathname: O/OA/OALDERS/Net-HTTP-6.19.tar.gz + perl 5.008008 + Net-HTTP-6.20 + pathname: O/OA/OALDERS/Net-HTTP-6.20.tar.gz provides: - Net::HTTP 6.19 - Net::HTTP::Methods 6.19 - Net::HTTP::NB 6.19 - Net::HTTPS 6.19 + Net::HTTP 6.20 + Net::HTTP::Methods 6.20 + Net::HTTP::NB 6.20 + Net::HTTPS 6.20 requirements: Carp 0 Compress::Raw::Zlib 0 @@ -5180,7 +5320,6 @@ DISTRIBUTIONS base 0 perl 5.006002 strict 0 - vars 0 warnings 0 Net-IP-1.26 pathname: M/MA/MANU/Net-IP-1.26.tar.gz @@ -5188,10 +5327,10 @@ DISTRIBUTIONS Net::IP 1.26 requirements: ExtUtils::MakeMaker 0 - Net-OAuth2-AuthorizationServer-0.24 - pathname: L/LE/LEEJO/Net-OAuth2-AuthorizationServer-0.24.tar.gz + Net-OAuth2-AuthorizationServer-0.28 + pathname: L/LE/LEEJO/Net-OAuth2-AuthorizationServer-0.28.tar.gz provides: - Net::OAuth2::AuthorizationServer 0.24 + Net::OAuth2::AuthorizationServer 0.28 Net::OAuth2::AuthorizationServer::AuthorizationCodeGrant undef Net::OAuth2::AuthorizationServer::ClientCredentialsGrant undef Net::OAuth2::AuthorizationServer::Defaults undef @@ -5211,23 +5350,23 @@ DISTRIBUTIONS Try::Tiny 0.22 Types::Standard 1.000005 perl 5.010001 - Net-SSLeay-1.88 - pathname: C/CH/CHRISN/Net-SSLeay-1.88.tar.gz + Net-SSLeay-1.90 + pathname: C/CH/CHRISN/Net-SSLeay-1.90.tar.gz provides: - Net::SSLeay 1.88 - Net::SSLeay::Handle 1.88 + Net::SSLeay 1.90 + Net::SSLeay::Handle 1.90 requirements: ExtUtils::MakeMaker 0 MIME::Base64 0 perl 5.008001 - POSIX-strftime-Compiler-0.42 - pathname: K/KA/KAZEBURO/POSIX-strftime-Compiler-0.42.tar.gz + POSIX-strftime-Compiler-0.44 + pathname: K/KA/KAZEBURO/POSIX-strftime-Compiler-0.44.tar.gz provides: - POSIX::strftime::Compiler 0.42 + POSIX::strftime::Compiler 0.44 requirements: Carp 0 Exporter 0 - Module::Build 0.38 + Module::Build::Tiny 0.035 POSIX 0 Time::Local 0 perl 5.008001 @@ -5343,21 +5482,21 @@ DISTRIBUTIONS overload 0 perl 5.006 strict 0 - PPIx-QuoteLike-0.011 - pathname: W/WY/WYANT/PPIx-QuoteLike-0.011.tar.gz - provides: - PPIx::QuoteLike 0.011 - PPIx::QuoteLike::Constant 0.011 - PPIx::QuoteLike::Dumper 0.011 - PPIx::QuoteLike::Token 0.011 - PPIx::QuoteLike::Token::Control 0.011 - PPIx::QuoteLike::Token::Delimiter 0.011 - PPIx::QuoteLike::Token::Interpolation 0.011 - PPIx::QuoteLike::Token::String 0.011 - PPIx::QuoteLike::Token::Structure 0.011 - PPIx::QuoteLike::Token::Unknown 0.011 - PPIx::QuoteLike::Token::Whitespace 0.011 - PPIx::QuoteLike::Utils 0.011 + PPIx-QuoteLike-0.014 + pathname: W/WY/WYANT/PPIx-QuoteLike-0.014.tar.gz + provides: + PPIx::QuoteLike 0.014 + PPIx::QuoteLike::Constant 0.014 + PPIx::QuoteLike::Dumper 0.014 + PPIx::QuoteLike::Token 0.014 + PPIx::QuoteLike::Token::Control 0.014 + PPIx::QuoteLike::Token::Delimiter 0.014 + PPIx::QuoteLike::Token::Interpolation 0.014 + PPIx::QuoteLike::Token::String 0.014 + PPIx::QuoteLike::Token::Structure 0.014 + PPIx::QuoteLike::Token::Unknown 0.014 + PPIx::QuoteLike::Token::Whitespace 0.014 + PPIx::QuoteLike::Utils 0.014 requirements: Carp 0 Encode 0 @@ -5374,75 +5513,73 @@ DISTRIBUTIONS perl 5.006 strict 0 warnings 0 - PPIx-Regexp-0.071 - pathname: W/WY/WYANT/PPIx-Regexp-0.071.tar.gz - provides: - PPIx::Regexp 0.071 - PPIx::Regexp::Constant 0.071 - PPIx::Regexp::Dumper 0.071 - PPIx::Regexp::Element 0.071 - PPIx::Regexp::Lexer 0.071 - PPIx::Regexp::Node 0.071 - PPIx::Regexp::Node::Range 0.071 - PPIx::Regexp::Node::Unknown 0.071 - PPIx::Regexp::StringTokenizer 0.071 - PPIx::Regexp::Structure 0.071 - PPIx::Regexp::Structure::Assertion 0.071 - PPIx::Regexp::Structure::BranchReset 0.071 - PPIx::Regexp::Structure::Capture 0.071 - PPIx::Regexp::Structure::CharClass 0.071 - PPIx::Regexp::Structure::Code 0.071 - PPIx::Regexp::Structure::Main 0.071 - PPIx::Regexp::Structure::Modifier 0.071 - PPIx::Regexp::Structure::NamedCapture 0.071 - PPIx::Regexp::Structure::Quantifier 0.071 - PPIx::Regexp::Structure::RegexSet 0.071 - PPIx::Regexp::Structure::Regexp 0.071 - PPIx::Regexp::Structure::Replacement 0.071 - PPIx::Regexp::Structure::Subexpression 0.071 - PPIx::Regexp::Structure::Switch 0.071 - PPIx::Regexp::Structure::Unknown 0.071 - PPIx::Regexp::Support 0.071 - PPIx::Regexp::Token 0.071 - PPIx::Regexp::Token::Assertion 0.071 - PPIx::Regexp::Token::Backreference 0.071 - PPIx::Regexp::Token::Backtrack 0.071 - PPIx::Regexp::Token::CharClass 0.071 - PPIx::Regexp::Token::CharClass::POSIX 0.071 - PPIx::Regexp::Token::CharClass::POSIX::Unknown 0.071 - PPIx::Regexp::Token::CharClass::Simple 0.071 - PPIx::Regexp::Token::Code 0.071 - PPIx::Regexp::Token::Comment 0.071 - PPIx::Regexp::Token::Condition 0.071 - PPIx::Regexp::Token::Control 0.071 - PPIx::Regexp::Token::Delimiter 0.071 - PPIx::Regexp::Token::Greediness 0.071 - PPIx::Regexp::Token::GroupType 0.071 - PPIx::Regexp::Token::GroupType::Assertion 0.071 - PPIx::Regexp::Token::GroupType::BranchReset 0.071 - PPIx::Regexp::Token::GroupType::Code 0.071 - PPIx::Regexp::Token::GroupType::Modifier 0.071 - PPIx::Regexp::Token::GroupType::NamedCapture 0.071 - PPIx::Regexp::Token::GroupType::Subexpression 0.071 - PPIx::Regexp::Token::GroupType::Switch 0.071 - PPIx::Regexp::Token::Interpolation 0.071 - PPIx::Regexp::Token::Literal 0.071 - PPIx::Regexp::Token::Modifier 0.071 - PPIx::Regexp::Token::NoOp 0.071 - PPIx::Regexp::Token::Operator 0.071 - PPIx::Regexp::Token::Quantifier 0.071 - PPIx::Regexp::Token::Recursion 0.071 - PPIx::Regexp::Token::Reference 0.071 - PPIx::Regexp::Token::Structure 0.071 - PPIx::Regexp::Token::Unknown 0.071 - PPIx::Regexp::Token::Unmatched 0.071 - PPIx::Regexp::Token::Whitespace 0.071 - PPIx::Regexp::Tokenizer 0.071 - PPIx::Regexp::Util 0.071 + PPIx-Regexp-0.077 + pathname: W/WY/WYANT/PPIx-Regexp-0.077.tar.gz + provides: + PPIx::Regexp 0.077 + PPIx::Regexp::Constant 0.077 + PPIx::Regexp::Dumper 0.077 + PPIx::Regexp::Element 0.077 + PPIx::Regexp::Lexer 0.077 + PPIx::Regexp::Node 0.077 + PPIx::Regexp::Node::Range 0.077 + PPIx::Regexp::Node::Unknown 0.077 + PPIx::Regexp::Structure 0.077 + PPIx::Regexp::Structure::Assertion 0.077 + PPIx::Regexp::Structure::BranchReset 0.077 + PPIx::Regexp::Structure::Capture 0.077 + PPIx::Regexp::Structure::CharClass 0.077 + PPIx::Regexp::Structure::Code 0.077 + PPIx::Regexp::Structure::Main 0.077 + PPIx::Regexp::Structure::Modifier 0.077 + PPIx::Regexp::Structure::NamedCapture 0.077 + PPIx::Regexp::Structure::Quantifier 0.077 + PPIx::Regexp::Structure::RegexSet 0.077 + PPIx::Regexp::Structure::Regexp 0.077 + PPIx::Regexp::Structure::Replacement 0.077 + PPIx::Regexp::Structure::Subexpression 0.077 + PPIx::Regexp::Structure::Switch 0.077 + PPIx::Regexp::Structure::Unknown 0.077 + PPIx::Regexp::Support 0.077 + PPIx::Regexp::Token 0.077 + PPIx::Regexp::Token::Assertion 0.077 + PPIx::Regexp::Token::Backreference 0.077 + PPIx::Regexp::Token::Backtrack 0.077 + PPIx::Regexp::Token::CharClass 0.077 + PPIx::Regexp::Token::CharClass::POSIX 0.077 + PPIx::Regexp::Token::CharClass::POSIX::Unknown 0.077 + PPIx::Regexp::Token::CharClass::Simple 0.077 + PPIx::Regexp::Token::Code 0.077 + PPIx::Regexp::Token::Comment 0.077 + PPIx::Regexp::Token::Condition 0.077 + PPIx::Regexp::Token::Control 0.077 + PPIx::Regexp::Token::Delimiter 0.077 + PPIx::Regexp::Token::Greediness 0.077 + PPIx::Regexp::Token::GroupType 0.077 + PPIx::Regexp::Token::GroupType::Assertion 0.077 + PPIx::Regexp::Token::GroupType::BranchReset 0.077 + PPIx::Regexp::Token::GroupType::Code 0.077 + PPIx::Regexp::Token::GroupType::Modifier 0.077 + PPIx::Regexp::Token::GroupType::NamedCapture 0.077 + PPIx::Regexp::Token::GroupType::Subexpression 0.077 + PPIx::Regexp::Token::GroupType::Switch 0.077 + PPIx::Regexp::Token::Interpolation 0.077 + PPIx::Regexp::Token::Literal 0.077 + PPIx::Regexp::Token::Modifier 0.077 + PPIx::Regexp::Token::NoOp 0.077 + PPIx::Regexp::Token::Operator 0.077 + PPIx::Regexp::Token::Quantifier 0.077 + PPIx::Regexp::Token::Recursion 0.077 + PPIx::Regexp::Token::Reference 0.077 + PPIx::Regexp::Token::Structure 0.077 + PPIx::Regexp::Token::Unknown 0.077 + PPIx::Regexp::Token::Unmatched 0.077 + PPIx::Regexp::Token::Whitespace 0.077 + PPIx::Regexp::Tokenizer 0.077 + PPIx::Regexp::Util 0.077 requirements: Carp 0 Exporter 0 - List::MoreUtils 0 List::Util 0 PPI::Document 1.117 Scalar::Util 0 @@ -5491,18 +5628,16 @@ DISTRIBUTIONS Sub::Name 0 strict 0 warnings 0 - Package-Stash-0.38 - pathname: E/ET/ETHER/Package-Stash-0.38.tar.gz + Package-Stash-0.39 + pathname: E/ET/ETHER/Package-Stash-0.39.tar.gz provides: - Package::Stash 0.38 - Package::Stash::PP 0.38 + Package::Stash 0.39 + Package::Stash::PP 0.39 requirements: B 0 Carp 0 - Config 0 Dist::CheckConflicts 0.02 ExtUtils::MakeMaker 0 - File::Spec 0 Getopt::Long 0 Module::Implementation 0.06 Package::Stash::XS 0.26 @@ -5523,29 +5658,34 @@ DISTRIBUTIONS perl 5.008001 strict 0 warnings 0 - Params-Util-1.07 - pathname: A/AD/ADAMK/Params-Util-1.07.tar.gz + Params-Util-1.102 + pathname: R/RE/REHSACK/Params-Util-1.102.tar.gz provides: - Params::Util 1.07 + Params::Util 1.102 + Params::Util::PP 1.102 requirements: - ExtUtils::CBuilder 0.27 - ExtUtils::MakeMaker 6.52 - File::Spec 0.80 + Carp 0 + ExtUtils::MakeMaker 0 + File::Basename 0 + File::Copy 0 + File::Path 0 + File::Spec 0 + IPC::Cmd 0 Scalar::Util 1.18 - Test::More 0.42 - perl 5.00503 - Params-Validate-1.29 - pathname: D/DR/DROLSKY/Params-Validate-1.29.tar.gz + XSLoader 0.22 + parent 0 + Params-Validate-1.30 + pathname: D/DR/DROLSKY/Params-Validate-1.30.tar.gz provides: - Params::Validate 1.29 - Params::Validate::Constants 1.29 - Params::Validate::PP 1.29 - Params::Validate::XS 1.29 + Params::Validate 1.30 + Params::Validate::Constants 1.30 + Params::Validate::PP 1.30 + Params::Validate::XS 1.30 requirements: Carp 0 Exporter 0 ExtUtils::CBuilder 0 - Module::Build 0.28 + Module::Build 0.4227 Module::Implementation 0 Scalar::Util 1.10 XSLoader 0 @@ -5614,11 +5754,11 @@ DISTRIBUTIONS overload 0 parent 0 strict 0 - Path-Tiny-0.114 - pathname: D/DA/DAGOLDEN/Path-Tiny-0.114.tar.gz + Path-Tiny-0.116 + pathname: D/DA/DAGOLDEN/Path-Tiny-0.116.tar.gz provides: - Path::Tiny 0.114 - Path::Tiny::Error 0.114 + Path::Tiny 0.116 + Path::Tiny::Error 0.116 requirements: Carp 0 Cwd 0 @@ -5894,37 +6034,37 @@ DISTRIBUTIONS strict 0 version 0.77 warnings 0 - Perl-Critic-Freenode-0.032 - pathname: D/DB/DBOOK/Perl-Critic-Freenode-0.032.tar.gz - provides: - Perl::Critic::Freenode 0.032 - Perl::Critic::Freenode::Utils 0.032 - Perl::Critic::Policy::Freenode::AmpersandSubCalls 0.032 - Perl::Critic::Policy::Freenode::ArrayAssignAref 0.032 - Perl::Critic::Policy::Freenode::BarewordFilehandles 0.032 - Perl::Critic::Policy::Freenode::ConditionalDeclarations 0.032 - Perl::Critic::Policy::Freenode::ConditionalImplicitReturn 0.032 - Perl::Critic::Policy::Freenode::DeprecatedFeatures 0.032 - Perl::Critic::Policy::Freenode::DiscouragedModules 0.032 - Perl::Critic::Policy::Freenode::DollarAB 0.032 - Perl::Critic::Policy::Freenode::Each 0.032 - Perl::Critic::Policy::Freenode::EmptyReturn 0.032 - Perl::Critic::Policy::Freenode::IndirectObjectNotation 0.032 - Perl::Critic::Policy::Freenode::LexicalForeachIterator 0.032 - Perl::Critic::Policy::Freenode::LoopOnHash 0.032 - Perl::Critic::Policy::Freenode::ModPerl 0.032 - Perl::Critic::Policy::Freenode::MultidimensionalArrayEmulation 0.032 - Perl::Critic::Policy::Freenode::OpenArgs 0.032 - Perl::Critic::Policy::Freenode::OverloadOptions 0.032 - Perl::Critic::Policy::Freenode::POSIXImports 0.032 - Perl::Critic::Policy::Freenode::PackageMatchesFilename 0.032 - Perl::Critic::Policy::Freenode::PreferredAlternatives 0.032 - Perl::Critic::Policy::Freenode::Prototypes 0.032 - Perl::Critic::Policy::Freenode::StrictWarnings 0.032 - Perl::Critic::Policy::Freenode::Threads 0.032 - Perl::Critic::Policy::Freenode::Wantarray 0.032 - Perl::Critic::Policy::Freenode::WarningsSwitch 0.032 - Perl::Critic::Policy::Freenode::WhileDiamondDefaultAssignment 0.032 + Perl-Critic-Freenode-0.033 + pathname: D/DB/DBOOK/Perl-Critic-Freenode-0.033.tar.gz + provides: + Perl::Critic::Freenode 0.033 + Perl::Critic::Freenode::Utils 0.033 + Perl::Critic::Policy::Freenode::AmpersandSubCalls 0.033 + Perl::Critic::Policy::Freenode::ArrayAssignAref 0.033 + Perl::Critic::Policy::Freenode::BarewordFilehandles 0.033 + Perl::Critic::Policy::Freenode::ConditionalDeclarations 0.033 + Perl::Critic::Policy::Freenode::ConditionalImplicitReturn 0.033 + Perl::Critic::Policy::Freenode::DeprecatedFeatures 0.033 + Perl::Critic::Policy::Freenode::DiscouragedModules 0.033 + Perl::Critic::Policy::Freenode::DollarAB 0.033 + Perl::Critic::Policy::Freenode::Each 0.033 + Perl::Critic::Policy::Freenode::EmptyReturn 0.033 + Perl::Critic::Policy::Freenode::IndirectObjectNotation 0.033 + Perl::Critic::Policy::Freenode::LexicalForeachIterator 0.033 + Perl::Critic::Policy::Freenode::LoopOnHash 0.033 + Perl::Critic::Policy::Freenode::ModPerl 0.033 + Perl::Critic::Policy::Freenode::MultidimensionalArrayEmulation 0.033 + Perl::Critic::Policy::Freenode::OpenArgs 0.033 + Perl::Critic::Policy::Freenode::OverloadOptions 0.033 + Perl::Critic::Policy::Freenode::POSIXImports 0.033 + Perl::Critic::Policy::Freenode::PackageMatchesFilename 0.033 + Perl::Critic::Policy::Freenode::PreferredAlternatives 0.033 + Perl::Critic::Policy::Freenode::Prototypes 0.033 + Perl::Critic::Policy::Freenode::StrictWarnings 0.033 + Perl::Critic::Policy::Freenode::Threads 0.033 + Perl::Critic::Policy::Freenode::Wantarray 0.033 + Perl::Critic::Policy::Freenode::WarningsSwitch 0.033 + Perl::Critic::Policy::Freenode::WhileDiamondDefaultAssignment 0.033 requirements: Carp 0 Exporter 0 @@ -6033,33 +6173,33 @@ DISTRIBUTIONS Test::More 0 perl 5.006 version 0 - Perl-Tidy-20200110 - pathname: S/SH/SHANCOCK/Perl-Tidy-20200110.tar.gz - provides: - Perl::Tidy 20200110 - Perl::Tidy::Debugger 20200110 - Perl::Tidy::DevNull 20200110 - Perl::Tidy::Diagnostics 20200110 - Perl::Tidy::FileWriter 20200110 - Perl::Tidy::Formatter 20200110 - Perl::Tidy::HtmlWriter 20200110 - Perl::Tidy::IOScalar 20200110 - Perl::Tidy::IOScalarArray 20200110 - Perl::Tidy::IndentationItem 20200110 - Perl::Tidy::LineBuffer 20200110 - Perl::Tidy::LineSink 20200110 - Perl::Tidy::LineSource 20200110 - Perl::Tidy::Logger 20200110 - Perl::Tidy::Tokenizer 20200110 - Perl::Tidy::VerticalAligner 20200110 - Perl::Tidy::VerticalAligner::Alignment 20200110 - Perl::Tidy::VerticalAligner::Line 20200110 - requirements: - ExtUtils::MakeMaker 0 - PerlIO-utf8_strict-0.007 - pathname: L/LE/LEONT/PerlIO-utf8_strict-0.007.tar.gz - provides: - PerlIO::utf8_strict 0.007 + Perl-Tidy-20210111 + pathname: S/SH/SHANCOCK/Perl-Tidy-20210111.tar.gz + provides: + Perl::Tidy 20210111 + Perl::Tidy::Debugger 20210111 + Perl::Tidy::DevNull 20210111 + Perl::Tidy::Diagnostics 20210111 + Perl::Tidy::FileWriter 20210111 + Perl::Tidy::Formatter 20210111 + Perl::Tidy::HtmlWriter 20210111 + Perl::Tidy::IOScalar 20210111 + Perl::Tidy::IOScalarArray 20210111 + Perl::Tidy::IndentationItem 20210111 + Perl::Tidy::LineBuffer 20210111 + Perl::Tidy::LineSink 20210111 + Perl::Tidy::LineSource 20210111 + Perl::Tidy::Logger 20210111 + Perl::Tidy::Tokenizer 20210111 + Perl::Tidy::VerticalAligner 20210111 + Perl::Tidy::VerticalAligner::Alignment 20210111 + Perl::Tidy::VerticalAligner::Line 20210111 + requirements: + ExtUtils::MakeMaker 0 + PerlIO-utf8_strict-0.008 + pathname: L/LE/LEONT/PerlIO-utf8_strict-0.008.tar.gz + provides: + PerlIO::utf8_strict 0.008 requirements: ExtUtils::MakeMaker 0 XSLoader 0 @@ -6075,12 +6215,12 @@ DISTRIBUTIONS ExtUtils::MakeMaker 6.17 Scalar::Util 0 perl 5.006 - Plack-1.0047 - pathname: M/MI/MIYAGAWA/Plack-1.0047.tar.gz + Plack-1.0048 + pathname: M/MI/MIYAGAWA/Plack-1.0048.tar.gz provides: HTTP::Message::PSGI undef HTTP::Server::PSGI undef - Plack 1.0047 + Plack 1.0048 Plack::App::CGIBin undef Plack::App::Cascade undef Plack::App::Directory undef @@ -6139,9 +6279,9 @@ DISTRIBUTIONS Plack::Middleware::XFramework undef Plack::Middleware::XSendfile undef Plack::Recursive::ForwardRequest undef - Plack::Request 1.0047 + Plack::Request 1.0048 Plack::Request::Upload undef - Plack::Response 1.0047 + Plack::Response 1.0048 Plack::Runner undef Plack::TempBuffer undef Plack::Test undef @@ -6161,7 +6301,7 @@ DISTRIBUTIONS File::ShareDir 1.00 File::ShareDir::Install 0.06 Filesys::Notify::Simple 0 - HTTP::Entity::Parser 0.17 + HTTP::Entity::Parser 0.25 HTTP::Headers::Fast 0.18 HTTP::Message 5.814 HTTP::Tiny 0.034 @@ -6225,6 +6365,28 @@ DISTRIBUTIONS Test 0 perl 5.004 version 0 + Pod-Parser-1.63 + pathname: M/MA/MAREKR/Pod-Parser-1.63.tar.gz + provides: + Pod::Cache 1.63 + Pod::Cache::Item 1.63 + Pod::Find 1.63 + Pod::Hyperlink 1.63 + Pod::InputObjects 1.63 + Pod::InputSource 1.63 + Pod::InteriorSequence 1.63 + Pod::List 1.63 + Pod::Paragraph 1.63 + Pod::ParseTree 1.63 + Pod::ParseUtils 1.63 + Pod::Parser 1.63 + Pod::PlainText 2.07 + Pod::Select 1.63 + requirements: + Cwd 0 + ExtUtils::MakeMaker 0 + File::Basename 0 + Test::More 0.6 Pod-Spell-1.20 pathname: D/DO/DOLMEN/Pod-Spell-1.20.tar.gz provides: @@ -6313,11 +6475,11 @@ DISTRIBUTIONS overload 0 strict 0 warnings 0 - Role-Tiny-2.001004 - pathname: H/HA/HAARG/Role-Tiny-2.001004.tar.gz + Role-Tiny-2.002003 + pathname: H/HA/HAARG/Role-Tiny-2.002003.tar.gz provides: - Role::Tiny 2.001004 - Role::Tiny::With 2.001004 + Role::Tiny 2.002003 + Role::Tiny::With 2.002003 requirements: Exporter 5.57 perl 5.006 @@ -6424,10 +6586,18 @@ DISTRIBUTIONS XML::Parser 2.23 constant 0 perl 5.006000 - SQL-Abstract-1.86 - pathname: I/IL/ILMARI/SQL-Abstract-1.86.tar.gz - provides: - SQL::Abstract 1.86 + SQL-Abstract-2.000000 + pathname: M/MS/MSTROUT/SQL-Abstract-2.000000.tar.gz + provides: + Chunkstrumenter undef + DBIx::Class::SQLMaker::Role::SQLA2Passthrough undef + SQL::Abstract 2.000000 + SQL::Abstract::Formatter undef + SQL::Abstract::Parts undef + SQL::Abstract::Plugin::BangOverrides undef + SQL::Abstract::Plugin::ExtraClauses undef + SQL::Abstract::Reference undef + SQL::Abstract::Role::Plugin undef SQL::Abstract::Test undef SQL::Abstract::Tree undef requirements: @@ -6439,6 +6609,27 @@ DISTRIBUTIONS Moo 2.000001 Scalar::Util 0 Sub::Quote 2.000001 + Test::Builder::Module 0.84 + Test::Deep 0.101 + Text::Balanced 2.00 + perl 5.006 + SQL-Abstract-Classic-1.91 + pathname: R/RI/RIBASUSHI/SQL-Abstract-Classic-1.91.tar.gz + provides: + SQL::Abstract::Classic 1.91 + SQL::Abstract::Util undef + requirements: + Exporter 5.57 + ExtUtils::MakeMaker 6.59 + List::Util 0 + MRO::Compat 0.12 + SQL::Abstract 1.79 + Scalar::Util 0 + Storable 0 + Test::Deep 0.101 + Test::Exception 0.31 + Test::More 0.88 + Test::Warn 0 Text::Balanced 2.00 perl 5.006 SUPER-1.20190531 @@ -6467,67 +6658,67 @@ DISTRIBUTIONS ExtUtils::MakeMaker 0 Test::More 0 perl 5.006001 - Search-Elasticsearch-6.80 - pathname: E/EZ/EZIMUEL/Search-Elasticsearch-6.80.tar.gz - provides: - Search::Elasticsearch 6.80 - Search::Elasticsearch::Client::6_0 6.80 - Search::Elasticsearch::Client::6_0::Bulk 6.80 - Search::Elasticsearch::Client::6_0::Direct 6.80 - Search::Elasticsearch::Client::6_0::Direct::CCR 6.80 - Search::Elasticsearch::Client::6_0::Direct::Cat 6.80 - Search::Elasticsearch::Client::6_0::Direct::Cluster 6.80 - Search::Elasticsearch::Client::6_0::Direct::ILM 6.80 - Search::Elasticsearch::Client::6_0::Direct::Indices 6.80 - Search::Elasticsearch::Client::6_0::Direct::Ingest 6.80 - Search::Elasticsearch::Client::6_0::Direct::Nodes 6.80 - Search::Elasticsearch::Client::6_0::Direct::Snapshot 6.80 - Search::Elasticsearch::Client::6_0::Direct::Tasks 6.80 - Search::Elasticsearch::Client::6_0::Direct::XPack 6.80 - Search::Elasticsearch::Client::6_0::Direct::XPack::Graph 6.80 - Search::Elasticsearch::Client::6_0::Direct::XPack::License 6.80 - Search::Elasticsearch::Client::6_0::Direct::XPack::ML 6.80 - Search::Elasticsearch::Client::6_0::Direct::XPack::Migration 6.80 - Search::Elasticsearch::Client::6_0::Direct::XPack::Monitoring 6.80 - Search::Elasticsearch::Client::6_0::Direct::XPack::Rollup 6.80 - Search::Elasticsearch::Client::6_0::Direct::XPack::SQL 6.80 - Search::Elasticsearch::Client::6_0::Direct::XPack::SSL 6.80 - Search::Elasticsearch::Client::6_0::Direct::XPack::Security 6.80 - Search::Elasticsearch::Client::6_0::Direct::XPack::Watcher 6.80 - Search::Elasticsearch::Client::6_0::Role::API 6.80 - Search::Elasticsearch::Client::6_0::Role::Bulk 6.80 - Search::Elasticsearch::Client::6_0::Role::Scroll 6.80 - Search::Elasticsearch::Client::6_0::Scroll 6.80 - Search::Elasticsearch::Client::6_0::TestServer 6.80 - Search::Elasticsearch::Cxn::Factory 6.80 - Search::Elasticsearch::Cxn::HTTPTiny 6.80 - Search::Elasticsearch::Cxn::Hijk 6.80 - Search::Elasticsearch::Cxn::LWP 6.80 - Search::Elasticsearch::CxnPool::Sniff 6.80 - Search::Elasticsearch::CxnPool::Static 6.80 - Search::Elasticsearch::CxnPool::Static::NoPing 6.80 - Search::Elasticsearch::Error 6.80 - Search::Elasticsearch::Logger::LogAny 6.80 - Search::Elasticsearch::Role::API 6.80 - Search::Elasticsearch::Role::Client 6.80 - Search::Elasticsearch::Role::Client::Direct 6.80 - Search::Elasticsearch::Role::Cxn 6.80 - Search::Elasticsearch::Role::CxnPool 6.80 - Search::Elasticsearch::Role::CxnPool::Sniff 6.80 - Search::Elasticsearch::Role::CxnPool::Static 6.80 - Search::Elasticsearch::Role::CxnPool::Static::NoPing 6.80 - Search::Elasticsearch::Role::Is_Sync 6.80 - Search::Elasticsearch::Role::Logger 6.80 - Search::Elasticsearch::Role::Serializer 6.80 - Search::Elasticsearch::Role::Serializer::JSON 6.80 - Search::Elasticsearch::Role::Transport 6.80 - Search::Elasticsearch::Serializer::JSON 6.80 - Search::Elasticsearch::Serializer::JSON::Cpanel 6.80 - Search::Elasticsearch::Serializer::JSON::PP 6.80 - Search::Elasticsearch::Serializer::JSON::XS 6.80 - Search::Elasticsearch::TestServer 6.80 - Search::Elasticsearch::Transport 6.80 - Search::Elasticsearch::Util 6.80 + Search-Elasticsearch-7.30 + pathname: E/EZ/EZIMUEL/Search-Elasticsearch-7.30.tar.gz + provides: + Search::Elasticsearch 7.30 + Search::Elasticsearch::Client::7_0 7.30 + Search::Elasticsearch::Client::7_0::Bulk 7.30 + Search::Elasticsearch::Client::7_0::Direct 7.30 + Search::Elasticsearch::Client::7_0::Direct::CCR 7.30 + Search::Elasticsearch::Client::7_0::Direct::Cat 7.30 + Search::Elasticsearch::Client::7_0::Direct::Cluster 7.30 + Search::Elasticsearch::Client::7_0::Direct::DataFrame 7.30 + Search::Elasticsearch::Client::7_0::Direct::Graph 7.30 + Search::Elasticsearch::Client::7_0::Direct::ILM 7.30 + Search::Elasticsearch::Client::7_0::Direct::Indices 7.30 + Search::Elasticsearch::Client::7_0::Direct::Ingest 7.30 + Search::Elasticsearch::Client::7_0::Direct::License 7.30 + Search::Elasticsearch::Client::7_0::Direct::ML 7.30 + Search::Elasticsearch::Client::7_0::Direct::Migration 7.30 + Search::Elasticsearch::Client::7_0::Direct::Monitoring 7.30 + Search::Elasticsearch::Client::7_0::Direct::Nodes 7.30 + Search::Elasticsearch::Client::7_0::Direct::Rollup 7.30 + Search::Elasticsearch::Client::7_0::Direct::SQL 7.30 + Search::Elasticsearch::Client::7_0::Direct::SSL 7.30 + Search::Elasticsearch::Client::7_0::Direct::Security 7.30 + Search::Elasticsearch::Client::7_0::Direct::Snapshot 7.30 + Search::Elasticsearch::Client::7_0::Direct::Tasks 7.30 + Search::Elasticsearch::Client::7_0::Direct::Watcher 7.30 + Search::Elasticsearch::Client::7_0::Direct::XPack 7.30 + Search::Elasticsearch::Client::7_0::Role::API 7.30 + Search::Elasticsearch::Client::7_0::Role::Bulk 7.30 + Search::Elasticsearch::Client::7_0::Role::Scroll 7.30 + Search::Elasticsearch::Client::7_0::Scroll 7.30 + Search::Elasticsearch::Client::7_0::TestServer 7.30 + Search::Elasticsearch::Cxn::Factory 7.30 + Search::Elasticsearch::Cxn::HTTPTiny 7.30 + Search::Elasticsearch::Cxn::LWP 7.30 + Search::Elasticsearch::CxnPool::Sniff 7.30 + Search::Elasticsearch::CxnPool::Static 7.30 + Search::Elasticsearch::CxnPool::Static::NoPing 7.30 + Search::Elasticsearch::Error 7.30 + Search::Elasticsearch::Logger::LogAny 7.30 + Search::Elasticsearch::Role::API 7.30 + Search::Elasticsearch::Role::Client 7.30 + Search::Elasticsearch::Role::Client::Direct 7.30 + Search::Elasticsearch::Role::Cxn 7.30 + Search::Elasticsearch::Role::CxnPool 7.30 + Search::Elasticsearch::Role::CxnPool::Sniff 7.30 + Search::Elasticsearch::Role::CxnPool::Static 7.30 + Search::Elasticsearch::Role::CxnPool::Static::NoPing 7.30 + Search::Elasticsearch::Role::Is_Sync 7.30 + Search::Elasticsearch::Role::Logger 7.30 + Search::Elasticsearch::Role::Serializer 7.30 + Search::Elasticsearch::Role::Serializer::JSON 7.30 + Search::Elasticsearch::Role::Transport 7.30 + Search::Elasticsearch::Serializer::JSON 7.30 + Search::Elasticsearch::Serializer::JSON::Cpanel 7.30 + Search::Elasticsearch::Serializer::JSON::PP 7.30 + Search::Elasticsearch::Serializer::JSON::XS 7.30 + Search::Elasticsearch::TestServer 7.30 + Search::Elasticsearch::Transport 7.30 + Search::Elasticsearch::Util 7.30 requirements: Any::URI::Escape 0 Data::Dumper 0 @@ -6537,7 +6728,7 @@ DISTRIBUTIONS File::Temp 0 HTTP::Headers 0 HTTP::Request 0 - HTTP::Tiny 0.043 + HTTP::Tiny 0.076 IO::Compress::Deflate 0 IO::Compress::Gzip 0 IO::Select 0 @@ -6566,41 +6757,41 @@ DISTRIBUTIONS overload 0 strict 0 warnings 0 - Selenium-Remote-Driver-1.37 - pathname: T/TE/TEODESIAN/Selenium-Remote-Driver-1.37.tar.gz - provides: - Selenium::ActionChains 1.37 - Selenium::CanStartBinary 1.37 - Selenium::CanStartBinary::FindBinary 1.37 - Selenium::CanStartBinary::ProbePort 1.37 - Selenium::Chrome 1.37 - Selenium::Edge 1.37 - Selenium::Firefox 1.37 - Selenium::Firefox::Binary 1.37 - Selenium::Firefox::Profile 1.37 - Selenium::InternetExplorer 1.37 - Selenium::PhantomJS 1.37 - Selenium::Remote::Commands 1.37 - Selenium::Remote::Driver 1.37 - Selenium::Remote::Driver::CanSetWebdriverContext 1.37 - Selenium::Remote::Driver::Firefox::Profile 1.37 - Selenium::Remote::ErrorHandler 1.37 - Selenium::Remote::Finders 1.37 - Selenium::Remote::Mock::Commands 1.37 - Selenium::Remote::Mock::RemoteConnection 1.37 - Selenium::Remote::RemoteConnection 1.37 - Selenium::Remote::Spec 1.37 - Selenium::Remote::WDKeys 1.37 - Selenium::Remote::WebElement 1.37 - Selenium::Waiter 1.37 - Test::Selenium::Chrome 1.37 - Test::Selenium::Edge 1.37 - Test::Selenium::Firefox 1.37 - Test::Selenium::InternetExplorer 1.37 - Test::Selenium::PhantomJS 1.37 - Test::Selenium::Remote::Driver 1.37 - Test::Selenium::Remote::Role::DoesTesting 1.37 - Test::Selenium::Remote::WebElement 1.37 + Selenium-Remote-Driver-1.39 + pathname: T/TE/TEODESIAN/Selenium-Remote-Driver-1.39.tar.gz + provides: + Selenium::ActionChains 1.39 + Selenium::CanStartBinary 1.39 + Selenium::CanStartBinary::FindBinary 1.39 + Selenium::CanStartBinary::ProbePort 1.39 + Selenium::Chrome 1.39 + Selenium::Edge 1.39 + Selenium::Firefox 1.39 + Selenium::Firefox::Binary 1.39 + Selenium::Firefox::Profile 1.39 + Selenium::InternetExplorer 1.39 + Selenium::PhantomJS 1.39 + Selenium::Remote::Commands 1.39 + Selenium::Remote::Driver 1.39 + Selenium::Remote::Driver::CanSetWebdriverContext 1.39 + Selenium::Remote::Driver::Firefox::Profile 1.39 + Selenium::Remote::ErrorHandler 1.39 + Selenium::Remote::Finders 1.39 + Selenium::Remote::Mock::Commands 1.39 + Selenium::Remote::Mock::RemoteConnection 1.39 + Selenium::Remote::RemoteConnection 1.39 + Selenium::Remote::Spec 1.39 + Selenium::Remote::WDKeys 1.39 + Selenium::Remote::WebElement 1.39 + Selenium::Waiter 1.39 + Test::Selenium::Chrome 1.39 + Test::Selenium::Edge 1.39 + Test::Selenium::Firefox 1.39 + Test::Selenium::InternetExplorer 1.39 + Test::Selenium::PhantomJS 1.39 + Test::Selenium::Remote::Driver 1.39 + Test::Selenium::Remote::Role::DoesTesting 1.39 + Test::Selenium::Remote::WebElement 1.39 requirements: Archive::Zip 0 Carp 0 @@ -6641,10 +6832,10 @@ DISTRIBUTIONS perl 5.010 strict 0 warnings 0 - Sentry-Raven-1.12 - pathname: Q/QR/QRRY/Sentry-Raven-1.12.tar.gz + Sentry-Raven-1.14 + pathname: Q/QR/QRRY/Sentry-Raven-1.14.tar.gz provides: - Sentry::Raven 1.12 + Sentry::Raven 1.14 Sentry::Raven::Processor::RemoveStackVariables undef requirements: Data::Dump 0 @@ -6652,11 +6843,13 @@ DISTRIBUTIONS English 0 ExtUtils::MakeMaker 0 File::Basename 0 + File::Slurp 0 HTTP::Request::Common 0 HTTP::Status 0 JSON::XS 0 LWP::Protocol::https 0 LWP::UserAgent 0 + List::Util 0 Moo 0 MooX::Types::MooseLike::Base 0 Sys::Hostname 0 @@ -6664,38 +6857,40 @@ DISTRIBUTIONS URI 0 UUID::Tiny 0 perl 5.008 - Sereal-4.011 - pathname: Y/YV/YVES/Sereal-4.011.tar.gz + Sereal-4.018 + pathname: Y/YV/YVES/Sereal-4.018.tar.gz provides: - Sereal 4.011 + Sereal 4.018 requirements: ExtUtils::MakeMaker 0 - Sereal::Decoder 4.011 - Sereal::Encoder 4.011 + Sereal::Decoder 4.018 + Sereal::Encoder 4.018 perl 5.008 - Sereal-Decoder-4.011 - pathname: Y/YV/YVES/Sereal-Decoder-4.011.tar.gz + Sereal-Decoder-4.018 + pathname: Y/YV/YVES/Sereal-Decoder-4.018.tar.gz provides: - Sereal::Decoder 4.011 - Sereal::Decoder::Constants 4.011 + Sereal::Decoder 4.018 + Sereal::Decoder::Constants 4.018 Sereal::Performance undef requirements: ExtUtils::MakeMaker 7.0 ExtUtils::ParseXS 2.21 File::Find 0 File::Path 0 + Test::LongString 0 XSLoader 0 perl 5.008 - Sereal-Encoder-4.011 - pathname: Y/YV/YVES/Sereal-Encoder-4.011.tar.gz + Sereal-Encoder-4.018 + pathname: Y/YV/YVES/Sereal-Encoder-4.018.tar.gz provides: - Sereal::Encoder 4.011 - Sereal::Encoder::Constants 4.011 + Sereal::Encoder 4.018 + Sereal::Encoder::Constants 4.018 requirements: ExtUtils::MakeMaker 7.0 ExtUtils::ParseXS 2.21 File::Find 0 File::Path 0 + Test::LongString 0 XSLoader 0 perl 5.008 Set-Infinite-0.65 @@ -6946,60 +7141,60 @@ DISTRIBUTIONS ExtUtils::MakeMaker 0 GD 1.14 Template 2.14 - Template-Toolkit-3.008 - pathname: A/AT/ATOOMIC/Template-Toolkit-3.008.tar.gz - provides: - Template 3.008 - Template::Base 3.008 - Template::Config 3.008 - Template::Constants 3.008 - Template::Context 3.008 - Template::Directive 3.008 - Template::Document 3.008 - Template::Exception 3.008 - Template::Filters 3.008 - Template::Grammar 3.008 - Template::Iterator 3.008 - Template::Monad::Assert 3.008 - Template::Monad::Scalar 3.008 - Template::Namespace::Constants 3.008 - Template::Parser 3.008 - Template::Perl 3.008 - Template::Plugin 3.008 - Template::Plugin::Assert 3.008 - Template::Plugin::CGI 3.008 - Template::Plugin::Datafile 3.008 - Template::Plugin::Date 3.008 - Template::Plugin::Date::Calc 3.008 - Template::Plugin::Date::Manip 3.008 - Template::Plugin::Directory 3.008 - Template::Plugin::Dumper 3.008 - Template::Plugin::File 3.008 - Template::Plugin::Filter 3.008 - Template::Plugin::Format 3.008 - Template::Plugin::HTML 3.008 - Template::Plugin::Image 3.008 - Template::Plugin::Iterator 3.008 - Template::Plugin::Math 3.008 - Template::Plugin::Pod 3.008 - Template::Plugin::Procedural 3.008 - Template::Plugin::Scalar 3.008 - Template::Plugin::String 3.008 - Template::Plugin::Table 3.008 - Template::Plugin::URL 3.008 - Template::Plugin::View 3.008 - Template::Plugin::Wrap 3.008 - Template::Plugins 3.008 - Template::Provider 3.008 - Template::Service 3.008 - Template::Stash 3.008 - Template::Stash::Context 3.008 + Template-Toolkit-3.009 + pathname: A/AT/ATOOMIC/Template-Toolkit-3.009.tar.gz + provides: + Template 3.009 + Template::Base 3.009 + Template::Config 3.009 + Template::Constants 3.009 + Template::Context 3.009 + Template::Directive 3.009 + Template::Document 3.009 + Template::Exception 3.009 + Template::Filters 3.009 + Template::Grammar 3.009 + Template::Iterator 3.009 + Template::Monad::Assert 3.009 + Template::Monad::Scalar 3.009 + Template::Namespace::Constants 3.009 + Template::Parser 3.009 + Template::Perl 3.009 + Template::Plugin 3.009 + Template::Plugin::Assert 3.009 + Template::Plugin::CGI 3.009 + Template::Plugin::Datafile 3.009 + Template::Plugin::Date 3.009 + Template::Plugin::Date::Calc 3.009 + Template::Plugin::Date::Manip 3.009 + Template::Plugin::Directory 3.009 + Template::Plugin::Dumper 3.009 + Template::Plugin::File 3.009 + Template::Plugin::Filter 3.009 + Template::Plugin::Format 3.009 + Template::Plugin::HTML 3.009 + Template::Plugin::Image 3.009 + Template::Plugin::Iterator 3.009 + Template::Plugin::Math 3.009 + Template::Plugin::Pod 3.009 + Template::Plugin::Procedural 3.009 + Template::Plugin::Scalar 3.009 + Template::Plugin::String 3.009 + Template::Plugin::Table 3.009 + Template::Plugin::URL 3.009 + Template::Plugin::View 3.009 + Template::Plugin::Wrap 3.009 + Template::Plugins 3.009 + Template::Provider 3.009 + Template::Service 3.009 + Template::Stash 3.009 + Template::Stash::Context 3.009 Template::Stash::XS undef - Template::Test 3.008 - Template::TieString 3.008 - Template::Toolkit 3.008 - Template::VMethods 3.008 - Template::View 3.008 + Template::Test 3.009 + Template::TieString 3.009 + Template::Toolkit 3.009 + Template::VMethods 3.009 + Template::View 3.009 requirements: AppConfig 1.56 ExtUtils::MakeMaker 0 @@ -7120,10 +7315,10 @@ DISTRIBUTIONS perl 5.006001 strict 0 warnings 0 - Test-Fatal-0.014 - pathname: R/RJ/RJBS/Test-Fatal-0.014.tar.gz + Test-Fatal-0.016 + pathname: R/RJ/RJBS/Test-Fatal-0.016.tar.gz provides: - Test::Fatal 0.014 + Test::Fatal 0.016 requirements: Carp 0 Exporter 5.57 @@ -7140,10 +7335,10 @@ DISTRIBUTIONS ExtUtils::MakeMaker 0 Test::Builder 0.12 Test::Builder::Tester 1.04 - Test-MockModule-v0.172.0 - pathname: G/GF/GFRANKS/Test-MockModule-v0.172.0.tar.gz + Test-MockModule-v0.176.0 + pathname: G/GF/GFRANKS/Test-MockModule-v0.176.0.tar.gz provides: - Test::MockModule v0.172.0 + Test::MockModule v0.176.0 requirements: Carp 0 Module::Build 0.38 @@ -7230,10 +7425,10 @@ DISTRIBUTIONS perl 5.006 strict 0 warnings 0 - Test-Requires-0.10 - pathname: T/TO/TOKUHIROM/Test-Requires-0.10.tar.gz + Test-Requires-0.11 + pathname: T/TO/TOKUHIROM/Test-Requires-0.11.tar.gz provides: - Test::Requires 0.10 + Test::Requires 0.11 requirements: ExtUtils::MakeMaker 6.64 Test::Builder::Module 0 @@ -7253,6 +7448,89 @@ DISTRIBUTIONS Test::Builder::Module 0 Test::More 0.88 perl 5.008_001 + Test-Simple-1.302183 + pathname: E/EX/EXODIST/Test-Simple-1.302183.tar.gz + provides: + Test2 1.302183 + Test2::API 1.302183 + Test2::API::Breakage 1.302183 + Test2::API::Context 1.302183 + Test2::API::Instance 1.302183 + Test2::API::InterceptResult 1.302183 + Test2::API::InterceptResult::Event 1.302183 + Test2::API::InterceptResult::Facet 1.302183 + Test2::API::InterceptResult::Hub 1.302183 + Test2::API::InterceptResult::Squasher 1.302183 + Test2::API::Stack 1.302183 + Test2::Event 1.302183 + Test2::Event::Bail 1.302183 + Test2::Event::Diag 1.302183 + Test2::Event::Encoding 1.302183 + Test2::Event::Exception 1.302183 + Test2::Event::Fail 1.302183 + Test2::Event::Generic 1.302183 + Test2::Event::Note 1.302183 + Test2::Event::Ok 1.302183 + Test2::Event::Pass 1.302183 + Test2::Event::Plan 1.302183 + Test2::Event::Skip 1.302183 + Test2::Event::Subtest 1.302183 + Test2::Event::TAP::Version 1.302183 + Test2::Event::V2 1.302183 + Test2::Event::Waiting 1.302183 + Test2::EventFacet 1.302183 + Test2::EventFacet::About 1.302183 + Test2::EventFacet::Amnesty 1.302183 + Test2::EventFacet::Assert 1.302183 + Test2::EventFacet::Control 1.302183 + Test2::EventFacet::Error 1.302183 + Test2::EventFacet::Hub 1.302183 + Test2::EventFacet::Info 1.302183 + Test2::EventFacet::Info::Table 1.302183 + Test2::EventFacet::Meta 1.302183 + Test2::EventFacet::Parent 1.302183 + Test2::EventFacet::Plan 1.302183 + Test2::EventFacet::Render 1.302183 + Test2::EventFacet::Trace 1.302183 + Test2::Formatter 1.302183 + Test2::Formatter::TAP 1.302183 + Test2::Hub 1.302183 + Test2::Hub::Interceptor 1.302183 + Test2::Hub::Interceptor::Terminator 1.302183 + Test2::Hub::Subtest 1.302183 + Test2::IPC 1.302183 + Test2::IPC::Driver 1.302183 + Test2::IPC::Driver::Files 1.302183 + Test2::Tools::Tiny 1.302183 + Test2::Util 1.302183 + Test2::Util::ExternalMeta 1.302183 + Test2::Util::Facets2Legacy 1.302183 + Test2::Util::HashBase 1.302183 + Test2::Util::Trace 1.302183 + Test::Builder 1.302183 + Test::Builder::Formatter 1.302183 + Test::Builder::IO::Scalar 2.114 + Test::Builder::Module 1.302183 + Test::Builder::Tester 1.302183 + Test::Builder::Tester::Color 1.302183 + Test::Builder::Tester::Tie 1.302183 + Test::Builder::TodoDiag 1.302183 + Test::More 1.302183 + Test::Simple 1.302183 + Test::Tester 1.302183 + Test::Tester::Capture 1.302183 + Test::Tester::CaptureRunner 1.302183 + Test::Tester::Delegate 1.302183 + Test::use::ok 1.302183 + ok 1.302183 + requirements: + ExtUtils::MakeMaker 0 + File::Spec 0 + File::Temp 0 + Scalar::Util 1.13 + Storable 0 + perl 5.006002 + utf8 0 Test-TCP-2.22 pathname: M/MI/MIYAGAWA/Test-TCP-2.22.tar.gz provides: @@ -7328,124 +7606,126 @@ DISTRIBUTIONS perl 5.006 strict 0 warnings 0 - Test2-Suite-0.000129 - pathname: E/EX/EXODIST/Test2-Suite-0.000129.tar.gz - provides: - Test2::AsyncSubtest 0.000129 - Test2::AsyncSubtest::Event::Attach 0.000129 - Test2::AsyncSubtest::Event::Detach 0.000129 - Test2::AsyncSubtest::Formatter 0.000129 - Test2::AsyncSubtest::Hub 0.000129 - Test2::Bundle 0.000129 - Test2::Bundle::Extended 0.000129 - Test2::Bundle::More 0.000129 - Test2::Bundle::Simple 0.000129 - Test2::Compare 0.000129 - Test2::Compare::Array 0.000129 - Test2::Compare::Bag 0.000129 - Test2::Compare::Base 0.000129 - Test2::Compare::Bool 0.000129 - Test2::Compare::Custom 0.000129 - Test2::Compare::DeepRef 0.000129 - Test2::Compare::Delta 0.000129 - Test2::Compare::Event 0.000129 - Test2::Compare::EventMeta 0.000129 - Test2::Compare::Float 0.000129 - Test2::Compare::Hash 0.000129 - Test2::Compare::Meta 0.000129 - Test2::Compare::Negatable 0.000129 - Test2::Compare::Number 0.000129 - Test2::Compare::Object 0.000129 - Test2::Compare::OrderedSubset 0.000129 - Test2::Compare::Pattern 0.000129 - Test2::Compare::Ref 0.000129 - Test2::Compare::Regex 0.000129 - Test2::Compare::Scalar 0.000129 - Test2::Compare::Set 0.000129 - Test2::Compare::String 0.000129 - Test2::Compare::Undef 0.000129 - Test2::Compare::Wildcard 0.000129 - Test2::Manual 0.000129 - Test2::Manual::Anatomy 0.000129 - Test2::Manual::Anatomy::API 0.000129 - Test2::Manual::Anatomy::Context 0.000129 - Test2::Manual::Anatomy::EndToEnd 0.000129 - Test2::Manual::Anatomy::Event 0.000129 - Test2::Manual::Anatomy::Hubs 0.000129 - Test2::Manual::Anatomy::IPC 0.000129 - Test2::Manual::Anatomy::Utilities 0.000129 - Test2::Manual::Contributing 0.000129 - Test2::Manual::Testing 0.000129 - Test2::Manual::Testing::Introduction 0.000129 - Test2::Manual::Testing::Migrating 0.000129 - Test2::Manual::Testing::Planning 0.000129 - Test2::Manual::Testing::Todo 0.000129 - Test2::Manual::Tooling 0.000129 - Test2::Manual::Tooling::FirstTool 0.000129 - Test2::Manual::Tooling::Formatter 0.000129 - Test2::Manual::Tooling::Nesting 0.000129 - Test2::Manual::Tooling::Plugin::TestExit 0.000129 - Test2::Manual::Tooling::Plugin::TestingDone 0.000129 - Test2::Manual::Tooling::Plugin::ToolCompletes 0.000129 - Test2::Manual::Tooling::Plugin::ToolStarts 0.000129 - Test2::Manual::Tooling::Subtest 0.000129 - Test2::Manual::Tooling::TestBuilder 0.000129 - Test2::Manual::Tooling::Testing 0.000129 - Test2::Mock 0.000129 - Test2::Plugin 0.000129 - Test2::Plugin::BailOnFail 0.000129 - Test2::Plugin::DieOnFail 0.000129 - Test2::Plugin::ExitSummary 0.000129 - Test2::Plugin::SRand 0.000129 - Test2::Plugin::Times 0.000129 - Test2::Plugin::UTF8 0.000129 - Test2::Require 0.000129 - Test2::Require::AuthorTesting 0.000129 - Test2::Require::EnvVar 0.000129 - Test2::Require::Fork 0.000129 - Test2::Require::Module 0.000129 - Test2::Require::Perl 0.000129 - Test2::Require::RealFork 0.000129 - Test2::Require::Threads 0.000129 - Test2::Suite 0.000129 - Test2::Todo 0.000129 - Test2::Tools 0.000129 - Test2::Tools::AsyncSubtest 0.000129 - Test2::Tools::Basic 0.000129 - Test2::Tools::Class 0.000129 - Test2::Tools::ClassicCompare 0.000129 - Test2::Tools::Compare 0.000129 - Test2::Tools::Defer 0.000129 - Test2::Tools::Encoding 0.000129 - Test2::Tools::Event 0.000129 - Test2::Tools::Exception 0.000129 - Test2::Tools::Exports 0.000129 - Test2::Tools::GenTemp 0.000129 - Test2::Tools::Grab 0.000129 - Test2::Tools::Mock 0.000129 - Test2::Tools::Ref 0.000129 - Test2::Tools::Spec 0.000129 - Test2::Tools::Subtest 0.000129 - Test2::Tools::Target 0.000129 - Test2::Tools::Tester 0.000129 - Test2::Tools::Warnings 0.000129 - Test2::Util::Grabber 0.000129 - Test2::Util::Ref 0.000129 - Test2::Util::Stash 0.000129 - Test2::Util::Sub 0.000129 - Test2::Util::Table 0.000129 - Test2::Util::Table::Cell 0.000129 - Test2::Util::Table::LineBreak 0.000129 - Test2::Util::Term 0.000129 - Test2::Util::Times 0.000129 - Test2::V0 0.000129 - Test2::Workflow 0.000129 - Test2::Workflow::BlockBase 0.000129 - Test2::Workflow::Build 0.000129 - Test2::Workflow::Runner 0.000129 - Test2::Workflow::Task 0.000129 - Test2::Workflow::Task::Action 0.000129 - Test2::Workflow::Task::Group 0.000129 + Test2-Suite-0.000139 + pathname: E/EX/EXODIST/Test2-Suite-0.000139.tar.gz + provides: + Test2::AsyncSubtest 0.000139 + Test2::AsyncSubtest::Event::Attach 0.000139 + Test2::AsyncSubtest::Event::Detach 0.000139 + Test2::AsyncSubtest::Formatter 0.000139 + Test2::AsyncSubtest::Hub 0.000139 + Test2::Bundle 0.000139 + Test2::Bundle::Extended 0.000139 + Test2::Bundle::More 0.000139 + Test2::Bundle::Simple 0.000139 + Test2::Compare 0.000139 + Test2::Compare::Array 0.000139 + Test2::Compare::Bag 0.000139 + Test2::Compare::Base 0.000139 + Test2::Compare::Bool 0.000139 + Test2::Compare::Custom 0.000139 + Test2::Compare::DeepRef 0.000139 + Test2::Compare::Delta 0.000139 + Test2::Compare::Event 0.000139 + Test2::Compare::EventMeta 0.000139 + Test2::Compare::Float 0.000139 + Test2::Compare::Hash 0.000139 + Test2::Compare::Isa 0.000139 + Test2::Compare::Meta 0.000139 + Test2::Compare::Negatable 0.000139 + Test2::Compare::Number 0.000139 + Test2::Compare::Object 0.000139 + Test2::Compare::OrderedSubset 0.000139 + Test2::Compare::Pattern 0.000139 + Test2::Compare::Ref 0.000139 + Test2::Compare::Regex 0.000139 + Test2::Compare::Scalar 0.000139 + Test2::Compare::Set 0.000139 + Test2::Compare::String 0.000139 + Test2::Compare::Undef 0.000139 + Test2::Compare::Wildcard 0.000139 + Test2::Manual 0.000139 + Test2::Manual::Anatomy 0.000139 + Test2::Manual::Anatomy::API 0.000139 + Test2::Manual::Anatomy::Context 0.000139 + Test2::Manual::Anatomy::EndToEnd 0.000139 + Test2::Manual::Anatomy::Event 0.000139 + Test2::Manual::Anatomy::Hubs 0.000139 + Test2::Manual::Anatomy::IPC 0.000139 + Test2::Manual::Anatomy::Utilities 0.000139 + Test2::Manual::Concurrency 0.000139 + Test2::Manual::Contributing 0.000139 + Test2::Manual::Testing 0.000139 + Test2::Manual::Testing::Introduction 0.000139 + Test2::Manual::Testing::Migrating 0.000139 + Test2::Manual::Testing::Planning 0.000139 + Test2::Manual::Testing::Todo 0.000139 + Test2::Manual::Tooling 0.000139 + Test2::Manual::Tooling::FirstTool 0.000139 + Test2::Manual::Tooling::Formatter 0.000139 + Test2::Manual::Tooling::Nesting 0.000139 + Test2::Manual::Tooling::Plugin::TestExit 0.000139 + Test2::Manual::Tooling::Plugin::TestingDone 0.000139 + Test2::Manual::Tooling::Plugin::ToolCompletes 0.000139 + Test2::Manual::Tooling::Plugin::ToolStarts 0.000139 + Test2::Manual::Tooling::Subtest 0.000139 + Test2::Manual::Tooling::TestBuilder 0.000139 + Test2::Manual::Tooling::Testing 0.000139 + Test2::Mock 0.000139 + Test2::Plugin 0.000139 + Test2::Plugin::BailOnFail 0.000139 + Test2::Plugin::DieOnFail 0.000139 + Test2::Plugin::ExitSummary 0.000139 + Test2::Plugin::SRand 0.000139 + Test2::Plugin::Times 0.000139 + Test2::Plugin::UTF8 0.000139 + Test2::Require 0.000139 + Test2::Require::AuthorTesting 0.000139 + Test2::Require::EnvVar 0.000139 + Test2::Require::Fork 0.000139 + Test2::Require::Module 0.000139 + Test2::Require::Perl 0.000139 + Test2::Require::RealFork 0.000139 + Test2::Require::Threads 0.000139 + Test2::Suite 0.000139 + Test2::Todo 0.000139 + Test2::Tools 0.000139 + Test2::Tools::AsyncSubtest 0.000139 + Test2::Tools::Basic 0.000139 + Test2::Tools::Class 0.000139 + Test2::Tools::ClassicCompare 0.000139 + Test2::Tools::Compare 0.000139 + Test2::Tools::Defer 0.000139 + Test2::Tools::Encoding 0.000139 + Test2::Tools::Event 0.000139 + Test2::Tools::Exception 0.000139 + Test2::Tools::Exports 0.000139 + Test2::Tools::GenTemp 0.000139 + Test2::Tools::Grab 0.000139 + Test2::Tools::Mock 0.000139 + Test2::Tools::Ref 0.000139 + Test2::Tools::Spec 0.000139 + Test2::Tools::Subtest 0.000139 + Test2::Tools::Target 0.000139 + Test2::Tools::Tester 0.000139 + Test2::Tools::Warnings 0.000139 + Test2::Util::Grabber 0.000139 + Test2::Util::Ref 0.000139 + Test2::Util::Stash 0.000139 + Test2::Util::Sub 0.000139 + Test2::Util::Table 0.000139 + Test2::Util::Table::Cell 0.000139 + Test2::Util::Table::LineBreak 0.000139 + Test2::Util::Term 0.000139 + Test2::Util::Times 0.000139 + Test2::V0 0.000139 + Test2::Workflow 0.000139 + Test2::Workflow::BlockBase 0.000139 + Test2::Workflow::Build 0.000139 + Test2::Workflow::Runner 0.000139 + Test2::Workflow::Task 0.000139 + Test2::Workflow::Task::Action 0.000139 + Test2::Workflow::Task::Group 0.000139 requirements: B 0 Carp 0 @@ -7458,7 +7738,7 @@ DISTRIBUTIONS Scope::Guard 0 Sub::Info 0.002 Term::Table 0.013 - Test2::API 1.302158 + Test2::API 1.302176 Time::HiRes 0 overload 0 perl 5.008001 @@ -7470,10 +7750,10 @@ DISTRIBUTIONS requirements: ExtUtils::MakeMaker 0 Test::More 0 - Text-CSV_XS-1.41 - pathname: H/HM/HMBRAND/Text-CSV_XS-1.41.tgz + Text-CSV_XS-1.45 + pathname: H/HM/HMBRAND/Text-CSV_XS-1.45.tgz provides: - Text::CSV_XS 1.41 + Text::CSV_XS 1.45 requirements: Config 0 ExtUtils::MakeMaker 0 @@ -7532,11 +7812,11 @@ DISTRIBUTIONS Test::More 0.42 Text::Markdown v1.0.26 perl 5.008 - Text-Template-1.58 - pathname: M/MS/MSCHOUT/Text-Template-1.58.tar.gz + Text-Template-1.59 + pathname: M/MS/MSCHOUT/Text-Template-1.59.tar.gz provides: - Text::Template 1.58 - Text::Template::Preprocess 1.58 + Text::Template 1.59 + Text::Template::Preprocess 1.59 requirements: Carp 0 Encode 0 @@ -7546,6 +7826,13 @@ DISTRIBUTIONS perl 5.008 strict 0 warnings 0 + Text-Unidecode-1.30 + pathname: S/SB/SBURKE/Text-Unidecode-1.30.tar.gz + provides: + Text::Unidecode 1.30 + requirements: + ExtUtils::MakeMaker 0 + perl 5.008 TheSchwartz-1.15 pathname: A/AK/AKIYM/TheSchwartz-1.15.tar.gz provides: @@ -7605,8 +7892,8 @@ DISTRIBUTIONS Test::More 0 Test::use::ok 0 Tie::RefHash 0 - TimeDate-2.32 - pathname: A/AT/ATOOMIC/TimeDate-2.32.tar.gz + TimeDate-2.33 + pathname: A/AT/ATOOMIC/TimeDate-2.33.tar.gz provides: Date::Format 2.24 Date::Format::Generic 2.24 @@ -7645,7 +7932,7 @@ DISTRIBUTIONS Date::Language::TigrinyaEritrean 1.00 Date::Language::TigrinyaEthiopian 1.00 Date::Language::Turkish 1.0 - Date::Parse 2.32 + Date::Parse 2.33 Time::Zone 2.24 TimeDate 1.21 requirements: @@ -7662,107 +7949,110 @@ DISTRIBUTIONS perl 5.006 strict 0 warnings 0 - Type-Tiny-1.010002 - pathname: T/TO/TOBYINK/Type-Tiny-1.010002.tar.gz - provides: - Devel::TypeTiny::Perl56Compat 1.010002 - Devel::TypeTiny::Perl58Compat 1.010002 - Error::TypeTiny 1.010002 - Error::TypeTiny::Assertion 1.010002 - Error::TypeTiny::Compilation 1.010002 - Error::TypeTiny::WrongNumberOfParameters 1.010002 - Eval::TypeTiny 1.010002 - Reply::Plugin::TypeTiny 1.010002 - Test::TypeTiny 1.010002 - Type::Coercion 1.010002 - Type::Coercion::FromMoose 1.010002 - Type::Coercion::Union 1.010002 - Type::Library 1.010002 - Type::Params 1.010002 - Type::Parser 1.010002 - Type::Registry 1.010002 - Type::Tiny 1.010002 - Type::Tiny::Class 1.010002 - Type::Tiny::ConstrainedObject 1.010002 - Type::Tiny::Duck 1.010002 - Type::Tiny::Enum 1.010002 - Type::Tiny::Intersection 1.010002 - Type::Tiny::Role 1.010002 - Type::Tiny::Union 1.010002 - Type::Utils 1.010002 - Types::Common::Numeric 1.010002 - Types::Common::String 1.010002 - Types::Standard 1.010002 - Types::Standard::ArrayRef 1.010002 - Types::Standard::CycleTuple 1.010002 - Types::Standard::Dict 1.010002 - Types::Standard::HashRef 1.010002 - Types::Standard::Map 1.010002 - Types::Standard::ScalarRef 1.010002 - Types::Standard::StrMatch 1.010002 - Types::Standard::Tied 1.010002 - Types::Standard::Tuple 1.010002 - Types::TypeTiny 1.010002 + Type-Tiny-1.012001 + pathname: T/TO/TOBYINK/Type-Tiny-1.012001.tar.gz + provides: + Devel::TypeTiny::Perl56Compat 1.012001 + Devel::TypeTiny::Perl58Compat 1.012001 + Error::TypeTiny 1.012001 + Error::TypeTiny::Assertion 1.012001 + Error::TypeTiny::Compilation 1.012001 + Error::TypeTiny::WrongNumberOfParameters 1.012001 + Eval::TypeTiny 1.012001 + Reply::Plugin::TypeTiny 1.012001 + Test::TypeTiny 1.012001 + Type::Coercion 1.012001 + Type::Coercion::FromMoose 1.012001 + Type::Coercion::Union 1.012001 + Type::Library 1.012001 + Type::Params 1.012001 + Type::Parser 1.012001 + Type::Parser::AstBuilder undef + Type::Parser::Token undef + Type::Parser::TokenStream undef + Type::Registry 1.012001 + Type::Tiny 1.012001 + Type::Tiny::Class 1.012001 + Type::Tiny::ConstrainedObject 1.012001 + Type::Tiny::Duck 1.012001 + Type::Tiny::Enum 1.012001 + Type::Tiny::Intersection 1.012001 + Type::Tiny::Role 1.012001 + Type::Tiny::Union 1.012001 + Type::Utils 1.012001 + Types::Common::Numeric 1.012001 + Types::Common::String 1.012001 + Types::Standard 1.012001 + Types::Standard::ArrayRef 1.012001 + Types::Standard::CycleTuple 1.012001 + Types::Standard::Dict 1.012001 + Types::Standard::HashRef 1.012001 + Types::Standard::Map 1.012001 + Types::Standard::ScalarRef 1.012001 + Types::Standard::StrMatch 1.012001 + Types::Standard::Tied 1.012001 + Types::Standard::Tuple 1.012001 + Types::TypeTiny 1.012001 requirements: Exporter::Tiny 1.000000 ExtUtils::MakeMaker 6.17 perl 5.006001 - Types-Serialiser-1.0 - pathname: M/ML/MLEHMANN/Types-Serialiser-1.0.tar.gz + Types-Serialiser-1.01 + pathname: M/ML/MLEHMANN/Types-Serialiser-1.01.tar.gz provides: - JSON::PP::Boolean 1.0 - Types::Serialiser 1.0 - Types::Serialiser::BooleanBase 1.0 - Types::Serialiser::Error 1.0 + JSON::PP::Boolean 1.01 + Types::Serialiser 1.01 + Types::Serialiser::BooleanBase 1.01 + Types::Serialiser::Error 1.01 requirements: ExtUtils::MakeMaker 0 common::sense 0 - URI-1.76 - pathname: O/OA/OALDERS/URI-1.76.tar.gz - provides: - URI 1.76 - URI::Escape 3.31 - URI::Heuristic 4.20 - URI::IRI 1.76 - URI::QueryParam 1.76 - URI::Split 1.76 - URI::URL 5.04 - URI::WithBase 2.20 - URI::data 1.76 - URI::file 4.21 - URI::file::Base 1.76 - URI::file::FAT 1.76 - URI::file::Mac 1.76 - URI::file::OS2 1.76 - URI::file::QNX 1.76 - URI::file::Unix 1.76 - URI::file::Win32 1.76 - URI::ftp 1.76 - URI::gopher 1.76 - URI::http 1.76 - URI::https 1.76 - URI::ldap 1.76 - URI::ldapi 1.76 - URI::ldaps 1.76 - URI::mailto 1.76 - URI::mms 1.76 - URI::news 1.76 - URI::nntp 1.76 - URI::pop 1.76 - URI::rlogin 1.76 - URI::rsync 1.76 - URI::rtsp 1.76 - URI::rtspu 1.76 - URI::sftp 1.76 - URI::sip 1.76 - URI::sips 1.76 - URI::snews 1.76 - URI::ssh 1.76 - URI::telnet 1.76 - URI::tn3270 1.76 - URI::urn 1.76 - URI::urn::isbn 1.76 - URI::urn::oid 1.76 + URI-5.06 + pathname: O/OA/OALDERS/URI-5.06.tar.gz + provides: + URI 5.06 + URI::Escape 5.06 + URI::Heuristic 5.06 + URI::IRI 5.06 + URI::QueryParam 5.06 + URI::Split 5.06 + URI::URL 5.06 + URI::WithBase 5.06 + URI::data 5.06 + URI::file 5.06 + URI::file::Base 5.06 + URI::file::FAT 5.06 + URI::file::Mac 5.06 + URI::file::OS2 5.06 + URI::file::QNX 5.06 + URI::file::Unix 5.06 + URI::file::Win32 5.06 + URI::ftp 5.06 + URI::gopher 5.06 + URI::http 5.06 + URI::https 5.06 + URI::ldap 5.06 + URI::ldapi 5.06 + URI::ldaps 5.06 + URI::mailto 5.06 + URI::mms 5.06 + URI::news 5.06 + URI::nntp 5.06 + URI::pop 5.06 + URI::rlogin 5.06 + URI::rsync 5.06 + URI::rtsp 5.06 + URI::rtspu 5.06 + URI::sftp 5.06 + URI::sip 5.06 + URI::sips 5.06 + URI::snews 5.06 + URI::ssh 5.06 + URI::telnet 5.06 + URI::tn3270 5.06 + URI::urn 5.06 + URI::urn::isbn 5.06 + URI::urn::oid 5.06 requirements: Carp 0 Cwd 0 @@ -7979,13 +8269,13 @@ DISTRIBUTIONS ExtUtils::MakeMaker 0 SOAP::Lite 0.716 SOAP::Transport::TCP 0.715 - XString-0.002 - pathname: A/AT/ATOOMIC/XString-0.002.tar.gz + XString-0.005 + pathname: A/AT/ATOOMIC/XString-0.005.tar.gz provides: - XString 0.002 + XString 0.005 requirements: ExtUtils::MakeMaker 0 - perl 5.010 + perl 5.008 YAML-1.30 pathname: T/TI/TINITA/YAML-1.30.tar.gz provides: @@ -8014,15 +8304,62 @@ DISTRIBUTIONS requirements: ExtUtils::MakeMaker 0 perl 5.008001 - YAML-LibYAML-0.82 - pathname: T/TI/TINITA/YAML-LibYAML-0.82.tar.gz - provides: - YAML::LibYAML 0.82 - YAML::XS 0.82 - YAML::XS::LibYAML undef + YAML-PP-0.026 + pathname: T/TI/TINITA/YAML-PP-0.026.tar.gz + provides: + YAML::PP 0.026 + YAML::PP::Common 0.026 + YAML::PP::Constructor 0.026 + YAML::PP::Dumper 0.026 + YAML::PP::Emitter 0.026 + YAML::PP::Exception 0.026 + YAML::PP::Grammar 0.026 + YAML::PP::Highlight 0.026 + YAML::PP::Lexer 0.026 + YAML::PP::Loader 0.026 + YAML::PP::Parser 0.026 + YAML::PP::Perl 0.026 + YAML::PP::Preserve::Array 0.026 + YAML::PP::Preserve::Hash 0.026 + YAML::PP::Preserve::Scalar 0.026 + YAML::PP::Reader 0.026 + YAML::PP::Reader::File 0.026 + YAML::PP::Render 0.026 + YAML::PP::Representer 0.026 + YAML::PP::Schema 0.026 + YAML::PP::Schema::Binary 0.026 + YAML::PP::Schema::Core 0.026 + YAML::PP::Schema::Failsafe 0.026 + YAML::PP::Schema::Include 0.026 + YAML::PP::Schema::JSON 0.026 + YAML::PP::Schema::Merge 0.026 + YAML::PP::Schema::Perl 0.026 + YAML::PP::Schema::Tie::IxHash 0.026 + YAML::PP::Schema::YAML1_1 0.026 + YAML::PP::Type::MergeKey 0.026 + YAML::PP::Writer 0.026 + YAML::PP::Writer::File 0.026 requirements: + B 0 + B::Deparse 0 + Carp 0 + Data::Dumper 0 + Encode 0 + Exporter 0 ExtUtils::MakeMaker 0 - perl 5.008001 + File::Basename 0 + Getopt::Long 0 + MIME::Base64 0 + Module::Load 0 + Scalar::Util 1.07 + Tie::Array 0 + Tie::Hash 0 + base 0 + constant 0 + overload 0 + perl 5.008000 + strict 0 + warnings 0 bareword-filehandles-0.007 pathname: I/IL/ILMARI/bareword-filehandles-0.007.tar.gz provides: @@ -8061,32 +8398,32 @@ DISTRIBUTIONS XSLoader 0 lib 0 perl 5.008001 - libwww-perl-6.44 - pathname: O/OA/OALDERS/libwww-perl-6.44.tar.gz - provides: - LWP 6.44 - LWP::Authen::Basic 6.44 - LWP::Authen::Digest 6.44 - LWP::Authen::Ntlm 6.44 - LWP::ConnCache 6.44 - LWP::Debug 6.44 - LWP::Debug::TraceHTTP 6.44 - LWP::DebugFile 6.44 - LWP::MemberMixin 6.44 - LWP::Protocol 6.44 - LWP::Protocol::cpan 6.44 - LWP::Protocol::data 6.44 - LWP::Protocol::file 6.44 - LWP::Protocol::ftp 6.44 - LWP::Protocol::gopher 6.44 - LWP::Protocol::http 6.44 - LWP::Protocol::loopback 6.44 - LWP::Protocol::mailto 6.44 - LWP::Protocol::nntp 6.44 - LWP::Protocol::nogo 6.44 - LWP::RobotUA 6.44 - LWP::Simple 6.44 - LWP::UserAgent 6.44 + libwww-perl-6.52 + pathname: O/OA/OALDERS/libwww-perl-6.52.tar.gz + provides: + LWP 6.52 + LWP::Authen::Basic 6.52 + LWP::Authen::Digest 6.52 + LWP::Authen::Ntlm 6.52 + LWP::ConnCache 6.52 + LWP::Debug 6.52 + LWP::Debug::TraceHTTP 6.52 + LWP::DebugFile 6.52 + LWP::MemberMixin 6.52 + LWP::Protocol 6.52 + LWP::Protocol::cpan 6.52 + LWP::Protocol::data 6.52 + LWP::Protocol::file 6.52 + LWP::Protocol::ftp 6.52 + LWP::Protocol::gopher 6.52 + LWP::Protocol::http 6.52 + LWP::Protocol::loopback 6.52 + LWP::Protocol::mailto 6.52 + LWP::Protocol::nntp 6.52 + LWP::Protocol::nogo 6.52 + LWP::RobotUA 6.52 + LWP::Simple 6.52 + LWP::UserAgent 6.52 libwww::perl undef requirements: CPAN::Meta::Requirements 2.120620 @@ -8106,7 +8443,7 @@ DISTRIBUTIONS HTTP::Request 6 HTTP::Request::Common 6 HTTP::Response 6 - HTTP::Status 6 + HTTP::Status 6.07 IO::Select 0 IO::Socket 0 LWP::MediaTypes 6 diff --git a/docker-compose.yml b/docker-compose.yml index 2bfedb8955..12d9b16c0a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -91,6 +91,25 @@ services: - bmo.db - memcached + bmo.iamd: + build: *bmo_build + command: + - perl + - extensions/MozillaIAM/bin/person_update.pl + - start + - '-d' + - '-f' + volumes: + - bmo-data-dir:/app/data + tmpfs: + - /tmp + - /run + environment: *bmo_env + restart: always + depends_on: + - bmo.db + - memcached + bmo.db: image: mysql:5.7 volumes: diff --git a/extensions/BMO/Extension.pm b/extensions/BMO/Extension.pm index 85990926a0..0718a5c67d 100755 --- a/extensions/BMO/Extension.pm +++ b/extensions/BMO/Extension.pm @@ -844,7 +844,8 @@ sub object_end_of_create { my $user = $args->{object}; # Log real IP addresses for auditing - Bugzilla->audit(sprintf('<%s> created user %s', remote_ip(), $user->login)); + Bugzilla->audit( + sprintf('%s <%s> created user %s', Bugzilla->user->login, remote_ip(), $user->login)); # Add default searches to new user's footer my $dbh = Bugzilla->dbh; diff --git a/extensions/BMO/template/en/default/pages/group_members.html.tmpl b/extensions/BMO/template/en/default/pages/group_members.html.tmpl index 20fbee5c12..64342829de 100644 --- a/extensions/BMO/template/en/default/pages/group_members.html.tmpl +++ b/extensions/BMO/template/en/default/pages/group_members.html.tmpl @@ -50,7 +50,7 @@ Count Members [% IF privileged %] - 2FA, Last Seen (days ago) + IAM Username, 2FA, Last Seen (days ago) [% END %] @@ -93,6 +93,13 @@ [% IF privileged %] + + [% IF member.iam_username %] + [% member.iam_username FILTER html %] + [% ELSE %] + - + [% END %] + [% IF member.mfa %] [% member.mfa FILTER html %] diff --git a/extensions/GitHubAuth/Extension.pm b/extensions/GitHubAuth/Extension.pm index 46523d2fcf..0b6131bd88 100644 --- a/extensions/GitHubAuth/Extension.pm +++ b/extensions/GitHubAuth/Extension.pm @@ -79,7 +79,7 @@ sub config_modify_panels { my $user_info_class = first { $_->{name} eq 'user_info_class' } @$auth_panel_params; if ($user_info_class) { - push @{$user_info_class->{choices}}, "GitHubAuth,CGI"; + push @{$user_info_class->{choices}}, "GitHubAuth,CGI", "GitHubAuth,OAuth2,CGI"; } my $user_verify_class diff --git a/extensions/GitHubAuth/lib/Client.pm b/extensions/GitHubAuth/lib/Client.pm index a084b14443..a94960d7ab 100644 --- a/extensions/GitHubAuth/lib/Client.pm +++ b/extensions/GitHubAuth/lib/Client.pm @@ -95,10 +95,11 @@ sub get_access_token { sub get_user_emails { my ($self, $access_token) = @_; - my $uri = URI->new(GH_USER_EMAILS_URI); - $uri->query_form(access_token => $access_token); - my $response = $self->user_agent->get($uri, Accept => 'application/json'); + my $response = $self->user_agent->get(GH_USER_EMAILS_URI, + 'Accept' => 'application/json', + 'Authorization' => "token $access_token" + ); return $self->_handle_response($response); } diff --git a/extensions/GitHubAuth/template/en/default/hook/account/auth/login-additional_methods.html.tmpl b/extensions/GitHubAuth/template/en/default/hook/account/auth/login-additional_methods.html.tmpl index f5e5ab11b2..6ac3c744d9 100644 --- a/extensions/GitHubAuth/template/en/default/hook/account/auth/login-additional_methods.html.tmpl +++ b/extensions/GitHubAuth/template/en/default/hook/account/auth/login-additional_methods.html.tmpl @@ -8,11 +8,10 @@ [% USE Bugzilla %] [% IF Param('user_info_class').split(',').contains('GitHubAuth') %]
- + - +
[% END %] diff --git a/extensions/GitHubAuth/template/en/default/hook/account/auth/login-small-additional_methods.html.tmpl b/extensions/GitHubAuth/template/en/default/hook/account/auth/login-small-additional_methods.html.tmpl index ba69911758..8e23dccc57 100644 --- a/extensions/GitHubAuth/template/en/default/hook/account/auth/login-small-additional_methods.html.tmpl +++ b/extensions/GitHubAuth/template/en/default/hook/account/auth/login-small-additional_methods.html.tmpl @@ -8,13 +8,11 @@ [% USE Bugzilla %] [% IF Param('user_info_class').split(',').contains('GitHubAuth') %] - -
- - - or -
-
+
+ + + +
[% END %] diff --git a/extensions/MozillaIAM/Config.pm b/extensions/MozillaIAM/Config.pm new file mode 100644 index 0000000000..e759efe415 --- /dev/null +++ b/extensions/MozillaIAM/Config.pm @@ -0,0 +1,17 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. + +package Bugzilla::Extension::MozillaIAM; +use 5.10.1; +use strict; +use warnings; + +use constant NAME => 'MozillaIAM'; +use constant REQUIRED_MODULES => []; +use constant OPTIONAL_MODULES => []; + +__PACKAGE__->NAME; diff --git a/extensions/MozillaIAM/Extension.pm b/extensions/MozillaIAM/Extension.pm new file mode 100644 index 0000000000..5267543c69 --- /dev/null +++ b/extensions/MozillaIAM/Extension.pm @@ -0,0 +1,171 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. + +package Bugzilla::Extension::MozillaIAM; + +use 5.10.1; +use strict; +use warnings; + +use base qw(Bugzilla::Extension); + +use Bugzilla::Constants; +use Bugzilla::Logging; +use Bugzilla::Token qw(issue_hash_token); +use Bugzilla::User; +use Bugzilla::Util qw(trim); + +use Bugzilla::Extension::MozillaIAM::Util + qw(add_staff_member get_access_token get_profile_by_email remove_staff_member); + +use Try::Tiny; + +our $VERSION = '1'; + +sub config_add_panels { + my ($self, $args) = @_; + my $modules = $args->{panel_modules}; + $modules->{MozillaIAM} = "Bugzilla::Extension::MozillaIAM::Config"; +} + +sub oauth2_client_pre_login { + my ($self, $args) = @_; + + return if !Bugzilla->params->{mozilla_iam_enabled}; + + my $userinfo = $args->{userinfo}; + my $iam_username = $userinfo->{email}; + + # First check to see if we are already linked with this account + my $bmo_email = Bugzilla->dbh->selectrow_array( + 'SELECT profiles.login_name + FROM profiles JOIN profiles_iam ON profiles.userid = profiles_iam.user_id + WHERE profiles_iam.iam_username = ?', undef, $iam_username + ); + + # If not, query the IAM system to see if they have a BMO address set + if (!$bmo_email) { + my $profile = get_profile_by_email($iam_username); + if ($profile && $profile->{bmo_email}) { + $bmo_email = $profile->{bmo_email}; + + # Save profile data for post login + $userinfo->{iam_profile_data} = $profile; + } + } + + if ($bmo_email && $bmo_email ne $iam_username) { + $userinfo->{email} = $bmo_email; + $userinfo->{iam_username} = $iam_username; + } +} + +sub oauth2_client_post_login { + my ($self, $args) = @_; + + return if !Bugzilla->params->{mozilla_iam_enabled}; + + my $userinfo = $args->{userinfo}; + my $iam_username = $userinfo->{iam_username} || $userinfo->{email}; + + my $profile = $userinfo->{iam_profile_data} + ||= get_profile_by_email($iam_username); + + if ($profile->{is_staff}) { + add_staff_member({ + bmo_email => $profile->{bmo_email}, + iam_username => $profile->{iam_username}, + real_name => $profile->{first_name} . ' ' . $profile->{last_name}, + is_staff => $profile->{is_staff}, + }); + } +} + + +sub oauth2_client_handle_redirect { + my ($self, $args) = @_; + my $cgi = Bugzilla->cgi; + my $userinfo = $args->{userinfo}; + + return if !Bugzilla->params->{mozilla_iam_enabled}; + + # Return if this request already came from the Mozilla IAM provider + # or the user is not logging in through the CGI login form. + return + if $userinfo + || !($cgi->param('Bugzilla_login') && $cgi->param('GoAheadAndLogIn')); + + my $login = $cgi->param('Bugzilla_login'); + my $user = Bugzilla::User->new({name => $login}); + + my $must_redirect = 0; + + # If the user has an IAM account associated then automatically redirect to + # Mozilla IAM provider. + if ($user && $user->iam_username) { + $must_redirect = 1; + } + + # If the users login matches a mandatory domain, then also redirect + my @mandatory_domains = split /\n/, + Bugzilla->params->{mozilla_iam_mandatory_domains}; + foreach my $domain (@mandatory_domains) { + $domain = trim($domain); + if ($login =~ /@\Q$domain\E$/) { + $must_redirect = 1; + last; + } + } + + if ($must_redirect) { + my $script_name = $cgi->script_name; + $script_name =~ s{^/}{}; + my $query = $cgi->canonicalize_query( + 'Bugzilla_login', 'Bugzilla_password', + 'GoAheadAndLogIn', 'Bugzilla_login_token' + ); + my $target + = Bugzilla->localconfig->basepath . $script_name . ($query ? "?$query" : ''); + + my $c = Bugzilla->request_cache->{mojo_controller}; + my $redirect_uri = $c->oauth2->redirect_uri($target); + my $authorize_url = $c->oauth2->auth_url('oauth2', + {state => issue_hash_token(['oauth2']), redirect_uri => $redirect_uri}); + + $cgi->redirect($authorize_url); + } + + return; +} + +sub object_end_of_update { + my ($self, $args) = @_; + my ($object, $old_object, $changes) = @$args{qw(object old_object changes)}; + + return + if !Bugzilla->params->{mozilla_iam_enabled} + || !$object->isa('Bugzilla::User'); + + # Remove mapping of profile_iam to profiles if a user has changed their email + if ($old_object->login ne $object->login && $old_object->iam_username) { + remove_staff_member({iam_username => $old_object->iam_username}); + } +} + +sub db_schema_abstract_schema { + my ($self, $args) = @_; + $args->{'schema'}->{'mozilla_iam_updates'} = { + FIELDS => [ + id => {TYPE => 'INTSERIAL', NOTNULL => 1, PRIMARYKEY => 1}, + type => {TYPE => 'VARCHAR(255)', NOTNULL => 1}, + value => {TYPE => 'MEDIUMTEXT', NOTNULL => 1}, + mod_time => {TYPE => 'DATETIME', NOTNULL => 1} + ], + }; +} + +__PACKAGE__->NAME; diff --git a/extensions/MozillaIAM/bin/person_update.pl b/extensions/MozillaIAM/bin/person_update.pl new file mode 100644 index 0000000000..e285589c93 --- /dev/null +++ b/extensions/MozillaIAM/bin/person_update.pl @@ -0,0 +1,50 @@ +#!/usr/bin/env perl + +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. + +use 5.10.1; +use strict; +use warnings; + +use lib qw(. lib local/lib/perl5); + +BEGIN { + use Bugzilla; + Bugzilla->extensions; +} + +use Bugzilla::Extension::MozillaIAM::Daemon; +Bugzilla::Extension::MozillaIAM::Daemon->start(); + +=head1 NAME + +person_update.pl - Query MozillaIAM for interesting changes to Mozilla tracked accounts. + +=head1 SYNOPSIS + + person_update.pl [OPTIONS] COMMAND + + OPTIONS: + -f Run in the foreground (don't detach) + -d Output a lot of debugging information + -p file Specify the file where person_update.pl should store its current + process id. Defaults to F. + -n name What should this process call itself in the system log? + Defaults to the full path you used to invoke the script. + + COMMANDS: + start Starts a new person_update daemon if there isn't one running already + stop Stops a running person_update daemon + restart Stops a running person_update if one is running, and then + starts a new one. + check Report the current status of the daemon. + install On some *nix systems, this automatically installs and + configures person_update.pl as a system service so that it will + start every time the machine boots. + uninstall Removes the system service for person_update.pl. + help Display this usage info diff --git a/extensions/MozillaIAM/lib/API/V1/User.pm b/extensions/MozillaIAM/lib/API/V1/User.pm new file mode 100644 index 0000000000..3af0e0021a --- /dev/null +++ b/extensions/MozillaIAM/lib/API/V1/User.pm @@ -0,0 +1,69 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. + +package Bugzilla::Extension::MozillaIAM::API::V1::User; + +use 5.10.1; +use Mojo::Base qw( Mojolicious::Controller ); + +use Bugzilla::Extension::MozillaIAM::Util qw(verify_token); +use Bugzilla::Logging; + +use Date::Format; +use JSON::Validator::Joi qw(joi); + +sub setup_routes { + my ($class, $r) = @_; + $r->post('/mozillaiam/user/update')->to('MozillaIAM::API::V1::User#update'); + $r->post('/mozillaiam/v1/user/update')->to('MozillaIAM::API::V1::User#update'); +} + +# { +# "operation": update, +# "id": ad|Mozilla-LDAP|dinomcvouch, +# "time": {epoch timestamp}, +# } + +sub update { + my ($self) = @_; + + return $self->render(status => 200, text => 'OK!') + if !Bugzilla->params->{mozilla_iam_enabled}; + + # Verify JWT token + unless ($ENV{CI} || $ENV{NO_VERIFY_TOKEN}) { + my $authorization_header = $self->tx->req->headers->header('Authorization'); + verify_token($authorization_header) + || return $self->user_error('mozilla_iam_token_error'); + } + + # Validate JSON input + my $params = $self->req->json; + my @errors = joi->object->props( + operation => joi->string->enum(['create', 'update', 'delete'])->required, + id => joi->string->required, + time => joi->integer->required, + )->validate($params); + return $self->user_error('api_input_schema_error', {errors => \@errors}) + if @errors; + + my $operation = $params->{operation}; + my $user_id = $params->{id}; + my $mod_time = $params->{time}; + + DEBUG("operation: $operation user_id: $user_id, mod_time: $mod_time"); + + # Queue up the id to be processed by the person server + $mod_time = time2str('%Y-%m-%d %k-%M-S', $mod_time); + Bugzilla->dbh->do( + 'INSERT INTO mozilla_iam_updates (type, value, mod_time) VALUES (?, ?, ?)', + undef, $operation, $user_id, $mod_time); + + return $self->render(status => 200, text => 'OK!'); +} + +1; diff --git a/extensions/MozillaIAM/lib/Config.pm b/extensions/MozillaIAM/lib/Config.pm new file mode 100644 index 0000000000..2aa95e9e30 --- /dev/null +++ b/extensions/MozillaIAM/lib/Config.pm @@ -0,0 +1,32 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. + +package Bugzilla::Extension::MozillaIAM::Config; + +use 5.10.1; +use strict; +use warnings; + +use Bugzilla::Config::Common; + +our $sortkey = 1350; + +sub get_param_list { + my ($class) = @_; + + my @params = ( + {name => 'mozilla_iam_enabled', type => 'b', default => 0,}, + {name => 'mozilla_iam_person_api_uri', type => 't', default => '',}, + {name => 'mozilla_iam_person_api_client_id', type => 't', default => '',}, + {name => 'mozilla_iam_person_api_client_secret', type => 't', default => '',}, + {name => 'mozilla_iam_mandatory_domains', type => 'l', default => '',}, + ); + + return @params; +} + +1; diff --git a/extensions/MozillaIAM/lib/Constants.pm b/extensions/MozillaIAM/lib/Constants.pm new file mode 100644 index 0000000000..7813c8fa30 --- /dev/null +++ b/extensions/MozillaIAM/lib/Constants.pm @@ -0,0 +1,25 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. + +package Bugzilla::Extension::MozillaIAM::Constants; + +use 5.10.1; +use strict; +use warnings; + +use base qw(Exporter); +our @EXPORT = qw( + CIS_UPDATE_SECONDS + MANUAL_UPDATE_SECONDS + POLL_TIMEOUT +); + +use constant CIS_UPDATE_SECONDS => $ENV{CIS_UPDATE_SECONDS} // 10; +use constant MANUAL_UPDATE_SECONDS => $ENV{MANUAL_UPDATE_SECONDS} // 3600; +use constant POLL_TIMEOUT => $ENV{POLL_TIMEOUT} // 3600; + +1; diff --git a/extensions/MozillaIAM/lib/Daemon.pm b/extensions/MozillaIAM/lib/Daemon.pm new file mode 100644 index 0000000000..6629a9f0fe --- /dev/null +++ b/extensions/MozillaIAM/lib/Daemon.pm @@ -0,0 +1,100 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. + +package Bugzilla::Extension::MozillaIAM::Daemon; + +use 5.10.1; +use strict; +use warnings; + +use Bugzilla::Constants; +use Bugzilla::Extension::MozillaIAM::Person; + +use Carp qw(confess); +use Daemon::Generic; +use File::Basename; +use File::Spec; +use Pod::Usage; + +sub start { + newdaemon(); +} + +# +# daemon::generic config +# + +sub gd_preconfig { + my $self = shift; + my $pidfile = $self->{gd_args}{pidfile}; + if (!$pidfile) { + $pidfile = File::Spec->catfile(bz_locations()->{datadir}, + $self->{gd_progname} . ".pid"); + } + return (pidfile => $pidfile); +} + +sub gd_getopt { + my $self = shift; + $self->SUPER::gd_getopt(); + if ($self->{gd_args}{progname}) { + $self->{gd_progname} = $self->{gd_args}{progname}; + } + else { + $self->{gd_progname} = basename($0); + } + $self->{_original_zero} = $0; + $0 = $self->{gd_progname}; +} + +sub gd_postconfig { + my $self = shift; + $0 = delete $self->{_original_zero}; +} + +sub gd_more_opt { + my $self = shift; + return ( + 'pidfile=s' => \$self->{gd_args}{pidfile}, + 'n=s' => \$self->{gd_args}{progname}, + ); +} + +sub gd_usage { + pod2usage({-verbose => 0, -exitval => 'NOEXIT'}); + return 0; +} + +sub gd_redirect_output { + my $self = shift; + + my $filename = File::Spec->catfile(bz_locations()->{datadir}, + $self->{gd_progname} . ".log"); + open(STDERR, ">>", $filename) or (print "could not open stderr: $!" && exit(1)); + close(STDOUT); + open(STDOUT, ">&", STDERR) or die "redirect STDOUT -> STDERR: $!"; + $SIG{HUP} = sub { + close(STDERR); + open(STDERR, ">>", $filename) or (print "could not open stderr: $!" && exit(1)); + }; +} + +sub gd_setup_signals { + my $self = shift; + $self->SUPER::gd_setup_signals(); + $SIG{TERM} = sub { $self->gd_quit_event(); } +} + +sub gd_run { + my $self = shift; + $SIG{__DIE__} = \&Carp::confess if $self->{debug}; + my $phabbugz = Bugzilla::Extension::MozillaIAM::Person->new(); + $phabbugz->is_daemon(1); + $phabbugz->start(); +} + +1; diff --git a/extensions/MozillaIAM/lib/Person.pm b/extensions/MozillaIAM/lib/Person.pm new file mode 100644 index 0000000000..5eff24876a --- /dev/null +++ b/extensions/MozillaIAM/lib/Person.pm @@ -0,0 +1,210 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. + +package Bugzilla::Extension::MozillaIAM::Person; + +use 5.10.1; +use Moo; + +use IO::Async::Timer::Periodic; +use IO::Async::Loop; +use IO::Async::Signal; +use Try::Tiny; + +use Bugzilla::Logging; +use Bugzilla::User; +use Bugzilla::Util qw(with_writable_database); +use Bugzilla::Extension::MozillaIAM::Constants; +use Bugzilla::Extension::MozillaIAM::Util qw( + add_staff_member + get_access_token + get_profile_by_email + get_profile_by_id + remove_staff_member +); + +has 'is_daemon' => (is => 'rw', default => 0); + +my $CURRENT_QUERY = 'none'; + +sub run_query { + my ($self, $name) = @_; + my $method = $name . '_query'; + try { + with_writable_database { + alarm POLL_TIMEOUT; + $CURRENT_QUERY = $name; + $self->$method; + }; + } + catch { + FATAL($_); + } + finally { + alarm(0); + $CURRENT_QUERY = 'none'; + try { + Bugzilla->_cleanup(); + } + catch { + FATAL("Error in _cleanup: $_"); + exit 1; + } + }; +} + +sub start { + my ($self) = @_; + + my $sig_alarm = IO::Async::Signal->new( + name => 'ALRM', + on_receipt => sub { + FATAL("Timeout reached while executing $CURRENT_QUERY query"); + exit 1; + }, + ); + + # Look for Mozilla accounts changes add by the CIS webhook + my $cis_update_timer = IO::Async::Timer::Periodic->new( + first_interval => 0, + interval => CIS_UPDATE_SECONDS, + reschedule => 'drift', + on_tick => sub { $self->run_query('cis_update') }, + ); + + # Manually query for Mozilla account changes + my $manual_update_timer = IO::Async::Timer::Periodic->new( + first_interval => 0, + interval => MANUAL_UPDATE_SECONDS, + reschedule => 'drift', + on_tick => sub { $self->run_query('manual_update') }, + ); + + my $loop = IO::Async::Loop->new; + $loop->add($cis_update_timer); + $loop->add($manual_update_timer); + $loop->add($sig_alarm); + + $cis_update_timer->start; + $manual_update_timer->start; + + $loop->run; +} + +sub cis_update_query { + my ($self) = @_; + my $dbh = Bugzilla->dbh; + + local Bugzilla::Logging->fields->{type} = 'PERSON_API'; + + # Ensure Mozilla IAM syncing is enabled + if (!Bugzilla->params->{mozilla_iam_enabled}) { + WARN('MOZILLA IAM SYNC DISABLED'); + return; + } + + DEBUG('RUNNING CIS UPDATE QUERY'); + + # We need to make the below changes as an empowered user + my $restore_prev_user + = Bugzilla->set_user(Bugzilla::User->super_user, scope_guard => 1); + + # Obtain access token for accessing the Person API + my $access_token = get_access_token(); + if (!$access_token) { + FATAL('Error obtaining access token'); + return; + } + + # Find any updates that were inserted by the CIS system using a webhook + my $cis_ids + = $dbh->selectcol_arrayref( + "SELECT value FROM mozilla_iam_updates WHERE type = 'update' ORDER BY mod_time" + ); + + foreach my $cis_id (@{$cis_ids}) { + + DEBUG("Processing updated user $cis_id"); + + try { + my $profile = get_profile_by_id($cis_id, $access_token); + + if ($profile && $profile->{iam_username}) { + if (!$profile->{is_staff} || !$profile->{bmo_email}) { + remove_staff_member({iam_username => $profile->{iam_username}}); + } + + if ($profile->{is_staff} && $profile->{bmo_email}) { + add_staff_member({ + bmo_email => $profile->{bmo_email}, + iam_username => $profile->{iam_username}, + real_name => $profile->{first_name} . ' ' . $profile->{last_name}, + is_staff => $profile->{is_staff}, + }); + } + } + } + catch { + WARN($_); + } + finally { + # Remove from queue + $dbh->do("DELETE FROM mozilla_iam_updates WHERE type = 'update' AND value = ?", + undef, $cis_id); + }; + } +} + +sub manual_update_query { + my ($self) = @_; + my $dbh = Bugzilla->dbh; + + local Bugzilla::Logging->fields->{type} = 'PERSON_API'; + + # Ensure Mozilla IAM syncing is enabled + if (!Bugzilla->params->{mozilla_iam_enabled}) { + WARN('MOZILLA IAM SYNC DISABLED'); + return; + } + + DEBUG('RUNNING MANUAL UPDATE QUERY'); + + # We need to make the below changes as an empowered user + my $restore_prev_user + = Bugzilla->set_user(Bugzilla::User->super_user, scope_guard => 1); + + # Obtain access token for accessing the Person API + my $access_token = get_access_token(); + if (!$access_token) { + FATAL('Error obtaining access token'); + return; + } + + # Update current members + my $rows = $dbh->selectall_arrayref( + 'SELECT user_id, iam_username FROM profiles_iam ORDER BY user_id'); + + foreach my $row (@{$rows}) { + my ($user_id, $iam_username) = @{$row}; + + my $user = Bugzilla::User->new($user_id); + DEBUG('Processing current user ' . $user->login); + + try { + my $profile = get_profile_by_email($iam_username, $access_token); + + if ($profile && (!$profile->{is_staff} || !$profile->{bmo_email})) { + remove_staff_member({user => $user}); + } + } + catch { + WARN($_); + }; + } +} + +1; diff --git a/extensions/MozillaIAM/lib/Util.pm b/extensions/MozillaIAM/lib/Util.pm new file mode 100644 index 0000000000..7ee05b3432 --- /dev/null +++ b/extensions/MozillaIAM/lib/Util.pm @@ -0,0 +1,219 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. + +package Bugzilla::Extension::MozillaIAM::Util; + +use 5.10.1; +use strict; +use warnings; + +use Bugzilla::Logging; +use Bugzilla::Token; +use Bugzilla::User; +use Bugzilla::Util qw(url_quote); + +use Mojo::JWT; +use Mojo::UserAgent; +use Try::Tiny; + +use base qw(Exporter); +our @EXPORT_OK = qw( + add_staff_member + get_access_token + get_profile_by_email + get_profile_by_id + remove_staff_member + user_agent + verify_token +); + +sub add_staff_member { + my $params = shift; + my $bmo_email = $params->{bmo_email}; + my $iam_username = $params->{iam_username}; + my $real_name = $params->{real_name}; + my $is_staff = $params->{is_staff}; + + # We need to make the below changes as an empowered user + my $empowered_user + = Bugzilla->set_user(Bugzilla::User->super_user, scope_guard => 1); + + # If user does not have an account, create one + my $user = Bugzilla::User->new({name => $bmo_email}); + + return 0 if !$user; + + # Update iam_username value with email from Mozilla IAM + # Also set password to * to disallow local login. + if ($user->iam_username ne $iam_username) { + $user->set_iam_username($iam_username); + $user->set_password('*') if $user->cryptpassword ne '*'; + $user->set_mfa(''); + } + + # Update group permissions if user is staff + if (!$user->in_group('mozilla-employee-confidential') && $is_staff) { + $user->set_groups({add => ['mozilla-employee-confidential']}); + } + + $user->update({keep_session => 1, keep_tokens => 1}); # Do not log user out + + return 1; +} + +sub remove_staff_member { + my $params = shift; + + # We need to make the below changes as an empowered user + my $empowered_user + = Bugzilla->set_user(Bugzilla::User->super_user, scope_guard => 1); + + my $user = $params->{user}; + if (!$user) { + my $user_id + = Bugzilla->dbh->selectrow_array( + 'SELECT user_id FROM profiles_iam WHERE iam_username = ?', + undef, $params->{iam_username}); + $user = Bugzilla::User->new($user_id); + } + + if ($user && $user->iam_username) { + $user->set_iam_username(''); + $user->set_password('*') if $user->cryptpassword ne '*'; + $user->set_mfa(''); + + if ($user->in_group('mozilla-employee-confidential')) { + $user->set_groups({remove => ['mozilla-employee-confidential']}); + } + + # Issue email allowing user to set their password + Bugzilla::Token::IssuePasswordToken($user); + + $user->update(); # Do not keep_session so user is logged out + } + + return 1; +} + +sub get_access_token { + my $params = Bugzilla->params; + + # Return fake token for CI tests + return 'fake_access_token' if $ENV{CI}; + + my $access_token; + try { + $access_token = user_agent()->post( + $params->{oauth2_client_token_url} => {'Content-Type' => 'application/json'} => + json => { + client_id => $params->{mozilla_iam_person_api_client_id}, + client_secret => $params->{mozilla_iam_person_api_client_secret}, + audience => 'api.sso.mozilla.com', + grant_type => 'client_credentials', + }, + )->result->json('/access_token'); + } + catch { + WARN($_); + ThrowCodeError('mozilla_iam_access_token_error'); + }; + + return $access_token; +} + +sub get_profile_by_email { + my ($email, $access_token) = @_; + return _get_profile('/v2/user/primary_email/' . url_quote($email), + $access_token); +} + +sub get_profile_by_id { + my ($id, $access_token) = @_; + return _get_profile('/v2/user/user_id/' . url_quote($id), $access_token); +} + +sub _get_profile { + my ($query_path, $access_token) = @_; + + # For CI, return test data that mocks the PersonAPI + if ( $ENV{CI} + && $ENV{BZ_TEST_OAUTH2_NORMAL_USER} + && $ENV{BZ_TEST_OAUTH2_MOZILLA_USER}) + { + return { + bmo_email => $ENV{BZ_TEST_OAUTH2_NORMAL_USER}, + first_name => 'Mozilla', + last_name => 'IAM User', + iam_username => $ENV{BZ_TEST_OAUTH2_MOZILLA_USER}, + is_staff => 1, + }; + } + + $access_token ||= get_access_token(); + return {} if !$access_token; + + my $url = Bugzilla->params->{mozilla_iam_person_api_uri} . $query_path; + + my $data = {}; + try { + $data = user_agent()->get($url => {'Authorization' => "Bearer ${access_token}"}) + ->result->json; + } + catch { + WARN($_); + ThrowCodeError('mozilla_iam_get_profile_error'); + }; + + return {} if !$data; + + return { + is_staff => $data->{staff_information}->{staff}->{value}, + iam_username => $data->{primary_email}->{value}, + bmo_email => $data->{identities}->{bugzilla_mozilla_org_primary_email}->{value}, + first_name => $data->{first_name}->{value}, + last_name => $data->{last_name}->{value}, + }; +} + +sub user_agent { + my $ua = Mojo::UserAgent->new( + request_timeout => 5, + connect_timeout => 5, + inactivity_timesout => 30 + ); + if (my $proxy = Bugzilla->params->{proxy_url}) { + $ua->proxy->http($proxy)->https($proxy); + } + else { + $ua->proxy->detect(); + } + $ua->transactor->name('Bugzilla'); + return $ua; +} + +sub verify_token { + my $authorization_header = shift; + my ($bearer, $token) = split /\s+/, $authorization_header; + + return 0 if $bearer !~ /bearer/i || !$token; + + try { + my $jwks + = user_agent() + ->get(Bugzilla->params->{oauth2_client_domain} . '/.well-known/jwks.json') + ->result->json('/keys'); + $token = Mojo::JWT->new(jwks => $jwks)->decode($token); + } + catch { + WARN($_); + ThrowCodeError('mozilla_iam_verify_token_error'); + }; + + return 1; +} + +1; diff --git a/extensions/MozillaIAM/t/bmo/moz_iam_cis_ping.t b/extensions/MozillaIAM/t/bmo/moz_iam_cis_ping.t new file mode 100644 index 0000000000..9bcb24859b --- /dev/null +++ b/extensions/MozillaIAM/t/bmo/moz_iam_cis_ping.t @@ -0,0 +1,104 @@ +#!/usr/bin/env perl +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. + +use strict; +use warnings; +use 5.10.1; +use lib qw( . lib local/lib/perl5 ); + +use Bugzilla; + +BEGIN { + Bugzilla->extensions; + $ENV{LOG4PERL_CONFIG_FILE} = 'log4perl-t.conf'; + $ENV{BUGZILLA_DISABLE_HOSTAGE} = 1; +} + +use Bugzilla::Extension::MozillaIAM::Person; +use Bugzilla::Logging; +use Bugzilla::Test::Selenium; +use Bugzilla::Test::Util qw(create_user mock_useragent_tx); +use Bugzilla::User; + +use Mojo::JSON qw(encode_json false true); +use Test::Mojo; +use Test2::Tools::Mock; +use Test2::V0; + +my $bmo_email = $ENV{BZ_TEST_OAUTH2_NORMAL_USER}; +my $iam_username = $ENV{BZ_TEST_OAUTH2_MOZILLA_USER}; + +my $t = Test::Mojo->new('Bugzilla::App'); + +# Simulate ping from CIS system about a user change +$t->post_ok( + '/rest/mozillaiam/user/update' => json => { + id => 'ad|Mozilla-LDAP|mozilla-user-1', + operation => 'update', + time => 10000 + } +)->status_is(200)->content_is('OK!'); + +# Process the new change from CIS +Bugzilla::Extension::MozillaIAM::Person->cis_update_query(); + +my $user = Bugzilla::User->new({name => $bmo_email}); + +ok($user->login eq $bmo_email, "User $bmo_email was created"); +ok( + $user->iam_username eq $iam_username, + "User iam_username is set to $iam_username" +); +ok( + $user->in_group('mozilla-employee-confidential'), + 'User was added to the mozilla-employee-confidential group' +); + +# Remove bmo linkage from their CIS account. This should remove +# them from Mozilla confidential +local $ENV{CI} = 0, $ENV{NO_VERIFY_TOKEN} = 1; +my $mocked_data = { + first_name => {value => 'Mozilla'}, + last_name => {value => 'IAM User'}, + primary_email => {value => $iam_username}, + staff_information => {staff => {value => false}}, +}; +my $user_agent = mock 'Mojo::UserAgent' => ( + override => [ + post => + sub { return mock_useragent_tx('{"access_token":"fake_access_token"}'); }, + get => sub { return mock_useragent_tx(encode_json($mocked_data)); } + ] +); + +# Simulate ping from CIS system about a user change +$t->post_ok( + '/rest/mozillaiam/user/update' => json => { + id => 'ad|Mozilla-LDAP|mozilla-user-1', + operation => 'update', + time => 20000 + } +)->status_is(200)->content_is('OK!'); + +# Process the new change from CIS +Bugzilla::Extension::MozillaIAM::Person->cis_update_query(); + +$user = Bugzilla::User->new({name => $bmo_email}); + +ok($user->iam_username ne $iam_username, 'User iam_username is unset'); +ok(!$user->in_group('mozilla-employee-confidential'), + 'User was removed from the mozilla-employee-confidential group'); + +# Check that password reset token was sent and clean up +my $token = Bugzilla::Test::Selenium->get_token(); +ok($token, "got a token for resetting password"); +Bugzilla->dbh->do('DELETE FROM tokens WHERE token = ?', undef, $token); +open my $fh, '>', '/app/data/mailer.testfile'; +close $fh; + +done_testing; diff --git a/extensions/MozillaIAM/t/bmo/moz_iam_email_change.t b/extensions/MozillaIAM/t/bmo/moz_iam_email_change.t new file mode 100644 index 0000000000..8a1fde9081 --- /dev/null +++ b/extensions/MozillaIAM/t/bmo/moz_iam_email_change.t @@ -0,0 +1,75 @@ +#!/usr/bin/env perl +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. +use strict; +use warnings; +use 5.10.1; +use lib qw( . lib local/lib/perl5 ); + +BEGIN { + $ENV{LOG4PERL_CONFIG_FILE} = 'log4perl-t.conf'; + $ENV{BUGZILLA_DISABLE_HOSTAGE} = 1; +} + +use Bugzilla; +use Bugzilla::Logging; +use Bugzilla::Test::Selenium; +use Bugzilla::User; + +use Test2::V0; + +my $bmo_email = 'bmo-user-2@mozilla.com'; +my $iam_username = 'mozilla-user-2@mozilla.com'; +my $real_name = 'Mozilla IAM User'; +my $new_bmo_email = 'bmo-user-2-new@mozilla.com'; + +# We need to make the below changes as an empowered user +my $empowered_user + = Bugzilla->set_user(Bugzilla::User->super_user, scope_guard => 1); + +my $user = Bugzilla::User->create({ + login_name => $bmo_email, + realname => $real_name, + cryptpassword => '*', + iam_username => $iam_username, +}); + +$user->set_groups({add => ['mozilla-employee-confidential']}); +$user->update(); + +ok( + $user->iam_username eq $iam_username, + "User iam_username is set to $iam_username" +); +ok( + $user->in_group('mozilla-employee-confidential'), + 'User was added to the mozilla-employee-confidential group' +); + +# Change users email address. Should automatically remove iam_username and +# mozilla group membership +$user->set_login($new_bmo_email); +$user->update(); + +undef $user; +$user = Bugzilla::User->new({name => $new_bmo_email}); + +ok( + $user->iam_username ne $iam_username, + "User iam_username is not $iam_username" +); +ok(!$user->in_group('mozilla-employee-confidential'), + 'User was removed from the mozilla-employee-confidential group'); + +# Check that password reset token was sent and clean up +my $token = Bugzilla::Test::Selenium->get_token(); +ok($token, "got a token for resetting password"); +Bugzilla->dbh->do('DELETE FROM tokens WHERE token = ?', undef, $token); +open my $fh, '>', '/app/data/mailer.testfile'; +close $fh; + +done_testing; diff --git a/extensions/MozillaIAM/t/bmo/moz_iam_oauth_login.t b/extensions/MozillaIAM/t/bmo/moz_iam_oauth_login.t new file mode 100644 index 0000000000..539bf979ee --- /dev/null +++ b/extensions/MozillaIAM/t/bmo/moz_iam_oauth_login.t @@ -0,0 +1,68 @@ +#!/usr/bin/env perl +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. + +use strict; +use warnings; +use 5.10.1; +use lib qw( . qa/t/lib local/lib/perl5 ); + +use Mojo::Base -strict; +use QA::Util; +use Test::More; + +my $bmo_login = $ENV{BZ_TEST_OAUTH2_NORMAL_USER}; +my $iam_username = $ENV{BZ_TEST_OAUTH2_MOZILLA_USER}; +my $password = $ENV{BZ_TEST_OAUTH2_PASSWORD}; + +my ($sel, $config) = get_selenium(); + +$sel->set_implicit_wait_timeout(600); + +# Logging in with Mozilla.com account should automatically redirect to OAuth2 login +$sel->login($iam_username, $password); +$sel->is_element_present_ok('//a[contains(text(),"Connect")]', + 'Mozilla IAM provider login present'); +$sel->logout_ok(); + +# Click on Mozilla IAM login button +$sel->get_ok('/login', undef, 'Go to the home page'); +$sel->title_is('Log in to Bugzilla', 'Log in to Bugzilla'); +$sel->is_element_present_ok( + '//div[@id="main-inner"]/div[@class="oauth2-login"]/a/button', + 'OAuth2 login button is present'); +$sel->click_ok('//div[@id="main-inner"]/div[@class="oauth2-login"]/a/button', + 'Click OAuth2 login button'); +$sel->click_ok('//a[contains(text(),"Connect")]', + 'Click OAuth2 provider login'); +$sel->title_is('Bugzilla Main Page', 'User is logged into Bugzilla'); +$sel->logout_ok(); + +# Make sure IAM username is correct and user is added to mozilla group +$sel->login($config->{admin_user_login}, $config->{admin_user_passwd}); + +# First we need to get the group id of the mozilla employee group. +$sel->get_ok('/editgroups.cgi', 'Go to edit groups'); +$sel->title_is('Edit Groups', 'Edit groups loaded'); +$sel->click_ok('link=mozilla-employee-confidential'); +my $group_id + = $sel->get_value("//input[\@name='group_id' and \@type='hidden']"); + +# Now check to make sure the user values are set properly +$sel->get_ok('/editusers.cgi', 'Go to edit users'); +$sel->title_is('Search users', 'Edit users loaded'); +$sel->type_ok('matchstr', $bmo_login, "Type $bmo_login for search"); +$sel->click_ok('//input[@id="search"]'); +$sel->title_is('Select user', 'Select a user loaded'); +$sel->click_link($bmo_login); +$sel->title_like(qr/^Edit user/, "Edit user"); +my $actual_iam_username = $sel->get_value('//input[@id="iam_username"]'); +ok($actual_iam_username eq $iam_username, 'IAM username correct'); +ok($sel->is_checked("//input[\@type='checkbox' and \@id='group_$group_id']"), + 'Mozilla employee group is selected'); + +done_testing; diff --git a/extensions/MozillaIAM/template/en/default/account/auth/oauth2_login_button.html.tmpl b/extensions/MozillaIAM/template/en/default/account/auth/oauth2_login_button.html.tmpl new file mode 100644 index 0000000000..dd4e30dbb4 --- /dev/null +++ b/extensions/MozillaIAM/template/en/default/account/auth/oauth2_login_button.html.tmpl @@ -0,0 +1,19 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] +[% + redirect_uri = c.oauth2.redirect_uri(target); + authorize_url = c.oauth2.auth_url('oauth2', + {state => issue_hash_token(['oauth2']), redirect_uri => redirect_uri }); +%] +
+ + + +
diff --git a/extensions/MozillaIAM/template/en/default/admin/params/mozillaiam.html.tmpl b/extensions/MozillaIAM/template/en/default/admin/params/mozillaiam.html.tmpl new file mode 100644 index 0000000000..8d3854dfe6 --- /dev/null +++ b/extensions/MozillaIAM/template/en/default/admin/params/mozillaiam.html.tmpl @@ -0,0 +1,22 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[% + title = "Mozilla IAM" + desc = "Configure as an Mozilla IAM Client for Authentication (Requires OAuth2 Client Enabled)" +%] + +[% + param_descs = { + mozilla_iam_enabled => "Mozilla IAM Client Enabled", + mozilla_iam_person_api_uri => "Mozilla IAM Person API URI", + mozilla_iam_person_api_client_id => "Mozilla IAM Person API Client ID", + mozilla_iam_person_api_client_secret => "Mozilla IAM Person API Client Secret" + mozilla_iam_mandatory_domains => "Account domains that must use Mozilla IAM to authenticate (one per line)" + } +%] diff --git a/extensions/MozillaIAM/template/en/default/hook/account/email/confirm-end.html.tmpl b/extensions/MozillaIAM/template/en/default/hook/account/email/confirm-end.html.tmpl new file mode 100644 index 0000000000..706f9f2e8e --- /dev/null +++ b/extensions/MozillaIAM/template/en/default/hook/account/email/confirm-end.html.tmpl @@ -0,0 +1,19 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[% IF user.iam_username %] +
+
+ You are currently using Mozilla IAM to sign on to [% terms.Bugzilla %]. + If you change your email and want the new address linked to your Mozilla + IAM account, you will need to update your Bugzilla email at + people.mozilla.org. If not, then + you will then need to + reset your password to login again. +
+[% END %] diff --git a/extensions/MozillaIAM/template/en/default/hook/global/code-error-errors.html.tmpl b/extensions/MozillaIAM/template/en/default/hook/global/code-error-errors.html.tmpl new file mode 100644 index 0000000000..39fbde1ac4 --- /dev/null +++ b/extensions/MozillaIAM/template/en/default/hook/global/code-error-errors.html.tmpl @@ -0,0 +1,20 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[% IF error == "mozilla_iam_access_token_error" %] + An error was encountered while obtaining an access token from IAM. + Please contact [% Param("maintainer") %] describing the steps taken to obtain this message. + +[% ELSIF error == "mozilla_iam_get_profile_error" %] + An error was encountered retrieving profile information from IAM. + Please contact [% Param("maintainer") %] describing the steps taken to obtain this message. + +[% ELSIF error == "mozilla_iam_verify_token_error" %] + The token provided was not valid or missing during verification with IAM. + Please contact [% Param("maintainer") %] describing the steps taken to obtain this message. +[% END %] diff --git a/extensions/MozillaIAM/template/en/default/hook/global/user-error-errors.html.tmpl b/extensions/MozillaIAM/template/en/default/hook/global/user-error-errors.html.tmpl new file mode 100644 index 0000000000..a21d5f28f0 --- /dev/null +++ b/extensions/MozillaIAM/template/en/default/hook/global/user-error-errors.html.tmpl @@ -0,0 +1,18 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[% IF error == "api_input_schema_error" %] + [% title = "API Input Schema Error" %] + The following errors occurred when validating input data: + [%+ FOREACH e = errors %] + [% e.message FILTER html %] => [% e.path FILTER html %][% ", " UNLESS loop.last() %] + [% END %] + +[% ELSIF error == "mozilla_iam_token_error" %] + The authentication token provided was not valid or missing. +[% END %] diff --git a/github.cgi b/github.cgi index e93ae09adb..229979f248 100755 --- a/github.cgi +++ b/github.cgi @@ -36,12 +36,12 @@ if (lc($cgi->request_method) eq 'post') { my $user = Bugzilla->login(LOGIN_OPTIONAL); my $target_uri = $cgi->param('target_uri') or ThrowCodeError("github_invalid_target"); - my $github_secret = $cgi->param('github_secret') + my $github_token = $cgi->param('github_token') or ThrowCodeError("github_invalid_request", {reason => 'invalid secret'}); - my $github_secret2 = Bugzilla->github_secret + my $github_token2 = Bugzilla->github_token or ThrowCodeError("github_invalid_request", {reason => 'invalid secret'}); - if ($github_secret ne $github_secret2) { + if ($github_token ne $github_token2) { Bugzilla->check_rate_limit('github', remote_ip()); ThrowCodeError("github_invalid_request", {reason => 'invalid secret'}); } diff --git a/oauth2.cgi b/oauth2.cgi new file mode 100644 index 0000000000..bcb385f696 --- /dev/null +++ b/oauth2.cgi @@ -0,0 +1,72 @@ +#!/usr/bin/env perl +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. + +use 5.10.1; +use strict; +use warnings; + +use lib qw(. lib local/lib/perl5); + +use Bugzilla; +use Bugzilla::Constants; +use Bugzilla::Error; +use Bugzilla::Hook; +use Bugzilla::Logging; +use Bugzilla::Token qw(check_hash_token delete_token); + +use Mojo::JWT; +use Mojo::UserAgent; +use Try::Tiny; + +my $cache = Bugzilla->request_cache; +my $cgi = Bugzilla->cgi; +my $c = $cache->{mojo_controller}; + +# GET requests come from OAuth2 provider, +# with this script acting as the OAuth2 callback. + +# Verify state value is valid +my $token = $cgi->param('state'); +check_hash_token($token, ['oauth2']); +delete_token($token); + +# Get access token from OAuth2 provider; +my $resp = $c->oauth2->get_token(); + +# Store user information for use by OAuth2 login info getter +my $userinfo; +if ($resp && $resp->{id_token}) { + try { + my $jwks + = Mojo::UserAgent->new->get( + Bugzilla->params->{oauth2_client_domain} . '/.well-known/jwks.json') + ->result->json('/keys'); + $userinfo = Mojo::JWT->new(jwks => $jwks)->decode($resp->{id_token}); + } + catch { + WARN($_); + }; +} + +if (!$userinfo && $resp && $resp->{access_token}) { + $userinfo = $c->oauth2->userinfo($resp->{access_token}); +} + +$userinfo || ThrowUserError('oauth2_userinfo_error'); + +Bugzilla::Hook::process('oauth2_client_pre_login', {userinfo => $userinfo}); + +$cache->{oauth2_client_userinfo} = $userinfo; + +my $user = Bugzilla->login(LOGIN_REQUIRED); + +Bugzilla::Hook::process('oauth2_client_post_login', + {user => $user, userinfo => $userinfo}); + +# Go back where we came from +$cgi->redirect($cgi->param('redirect')); diff --git a/qa/t/lib/QA/Util.pm b/qa/t/lib/QA/Util.pm index 9c1f53c50b..c32377dec2 100644 --- a/qa/t/lib/QA/Util.pm +++ b/qa/t/lib/QA/Util.pm @@ -123,14 +123,14 @@ sub get_selenium { my $sel = Bugzilla::Test::Selenium->new({ driver_args => { - base_url => $config->{browser_url}, + base_url => $ENV{BZ_BASE_URL} || $config->{browser_url}, browser => 'firefox', version => '', javascript => 1 } - }); + }); - $sel->driver->set_timeout('implicit', 600); + $sel->driver->set_timeout('implicit', 600); $sel->driver->set_timeout('page load', 60000); return ($sel, $config); diff --git a/qa/t/test_bug_edit.t b/qa/t/test_bug_edit.t index 2a3c21b4b8..e322e6bfa1 100644 --- a/qa/t/test_bug_edit.t +++ b/qa/t/test_bug_edit.t @@ -40,7 +40,7 @@ check_page_load($sel, q{http://HOSTNAME/editgroups.cgi}); $sel->title_is("Edit Groups"); $sel->click_ok("link=Master"); check_page_load($sel, - q{http://HOSTNAME/editgroups.cgi?action=changeform&group=26}); + q{http://HOSTNAME/editgroups.cgi?action=changeform&group=27}); $sel->title_is("Change Group: Master"); my $group_url = $sel->get_location(); $group_url =~ /group=(\d+)$/; diff --git a/qa/t/webservice_user_create.t b/qa/t/webservice_user_create.t index e52cfd34da..ba09044fcb 100644 --- a/qa/t/webservice_user_create.t +++ b/qa/t/webservice_user_create.t @@ -140,7 +140,7 @@ foreach my $rpc ($jsonrpc, $xmlrpc) { user => 'admin', args => {email => new_login(), full_name => NEW_FULLNAME, iam_username => $rpc->TYPE}, error => "The IAM username '" . $rpc->TYPE . "' you entered did not pass syntax checking for a legal email address.", - test => 'Adding a duplicate IAM username fails.', + test => 'Adding an invalid IAM username fails.', }, ); diff --git a/scripts/c9-install b/scripts/c9-install index aabe457820..a83b08eb6c 100755 --- a/scripts/c9-install +++ b/scripts/c9-install @@ -42,7 +42,7 @@ $answer{'diffpath'} = '/usr/bin'; $answer{'index_html'} = 0; $answer{'interdiffbin'} = '/usr/bin/interdiff'; $answer{'password_complexity'} = 'bmo'; -$answer{'user_info_class'} = 'GitHubAuth,CGI'; +$answer{'user_info_class'} = 'GitHubAuth,OAuth2,CGI'; $answer{'user_verify_class'} = 'GitHubAuth,DB'; $answer{'memcached_namespace'} = 'bmo:'; $answer{'memcached_servers'} = ''; diff --git a/scripts/entrypoint.pl b/scripts/entrypoint.pl index dead761a2b..533fa0ba36 100755 --- a/scripts/entrypoint.pl +++ b/scripts/entrypoint.pl @@ -211,15 +211,33 @@ sub cmd_test_bmo { assert_database()->get; assert_selenium('selenium')->get; - $ENV{BZ_TEST_NEWBIE} = 'newbie@mozilla.example'; + + $ENV{BZ_TEST_OAUTH2_NORMAL_USER} = 'oauth2-user@example.com'; + $ENV{BZ_TEST_OAUTH2_MOZILLA_USER} = 'oauth2-user@mozilla.com'; + $ENV{BZ_TEST_OAUTH2_PASSWORD} = 'non-working-password'; + create_user( + $ENV{BZ_TEST_OAUTH2_NORMAL_USER}, + $ENV{BZ_TEST_OAUTH2_PASSWORD}, + realname => 'OAuth2 User' + ); + + $ENV{BZ_TEST_BOUNCE_USER} = 'bouncer@mozilla.example'; + $ENV{BZ_TEST_BOUNCE_PASS} = 'captain.space.bagel.ROBOT!'; + create_user( + $ENV{BZ_TEST_BOUNCE_USER}, + $ENV{BZ_TEST_BOUNCE_PASS}, + realname => 'Bouncing User' + ); + + $ENV{BZ_TEST_NEWBIE_USER} = 'newbie@mozilla.example'; $ENV{BZ_TEST_NEWBIE_PASS} = 'captain.space.bagel.ROBOT!'; create_user( - $ENV{BZ_TEST_NEWBIE}, + $ENV{BZ_TEST_NEWBIE_USER}, $ENV{BZ_TEST_NEWBIE_PASS}, realname => 'Newbie User' ); - $ENV{BZ_TEST_NEWBIE2} = 'newbie2@mozilla.example'; + $ENV{BZ_TEST_NEWBIE2_USER} = 'newbie2@mozilla.example'; $ENV{BZ_TEST_NEWBIE2_PASS} = 'captain.space.pants.time.lord'; my $httpd_exit_f = run_cereal_and_httpd('-DACCESS_LOGS'); diff --git a/scripts/generate_bmo_data.pl b/scripts/generate_bmo_data.pl index 0e7d41e3b7..c2b19d3b6e 100755 --- a/scripts/generate_bmo_data.pl +++ b/scripts/generate_bmo_data.pl @@ -390,6 +390,13 @@ all_products => 0, bug_group => 0, }, + { + name => 'mozilla-employee-confidential', + description => 'mozilla-employee-confidential Description', + no_admin => 0, + all_products => 0, + bug_group => 1, + }, ); print "creating groups...\n"; @@ -524,7 +531,7 @@ usebugaliases => 1, useqacontact => 1, use_mailer_queue => 1, - user_info_class => 'GitHubAuth,CGI', + user_info_class => 'GitHubAuth,OAuth2,CGI', user_verify_class => 'GitHubAuth,DB', %opt_param, ); diff --git a/skins/lib/fontawesome-brands.min.css b/skins/lib/fontawesome-brands.min.css new file mode 100644 index 0000000000..4fd4403b85 --- /dev/null +++ b/skins/lib/fontawesome-brands.min.css @@ -0,0 +1,5 @@ +/*! + * Font Awesome Free 5.15.3 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +@font-face{font-family:"Font Awesome 5 Brands";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-brands-400.eot);src:url(../webfonts/fa-brands-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.woff) format("woff"),url(../webfonts/fa-brands-400.ttf) format("truetype"),url(../webfonts/fa-brands-400.svg#fontawesome) format("svg")}.fab{font-family:"Font Awesome 5 Brands";font-weight:400} \ No newline at end of file diff --git a/skins/lib/fontawesome-solid.min.css b/skins/lib/fontawesome-solid.min.css new file mode 100644 index 0000000000..a9ec9ea627 --- /dev/null +++ b/skins/lib/fontawesome-solid.min.css @@ -0,0 +1,5 @@ +/*! + * Font Awesome Free 5.15.3 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.eot);src:url(../webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.woff) format("woff"),url(../webfonts/fa-solid-900.ttf) format("truetype"),url(../webfonts/fa-solid-900.svg#fontawesome) format("svg")}.fa,.fas{font-family:"Font Awesome 5 Free";font-weight:900} \ No newline at end of file diff --git a/skins/lib/fontawesome.min.css b/skins/lib/fontawesome.min.css new file mode 100644 index 0000000000..2592f48e33 --- /dev/null +++ b/skins/lib/fontawesome.min.css @@ -0,0 +1,5 @@ +/*! + * Font Awesome Free 5.15.3 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +.fa,.fab,.fad,.fal,.far,.fas{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-.0667em}.fa-xs{font-size:.75em}.fa-sm{font-size:.875em}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:2.5em;padding-left:0}.fa-ul>li{position:relative}.fa-li{left:-2em;position:absolute;text-align:center;width:2em;line-height:inherit}.fa-border{border:.08em solid #eee;border-radius:.1em;padding:.2em .25em .15em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.fab.fa-pull-left,.fal.fa-pull-left,.far.fa-pull-left,.fas.fa-pull-left{margin-right:.3em}.fa.fa-pull-right,.fab.fa-pull-right,.fal.fa-pull-right,.far.fa-pull-right,.fas.fa-pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-webkit-transform:scaleY(-1);transform:scaleY(-1)}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical,.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"}.fa-flip-both,.fa-flip-horizontal.fa-flip-vertical{-webkit-transform:scale(-1);transform:scale(-1)}:root .fa-flip-both,:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{-webkit-filter:none;filter:none}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2.5em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-500px:before{content:"\f26e"}.fa-accessible-icon:before{content:"\f368"}.fa-accusoft:before{content:"\f369"}.fa-acquisitions-incorporated:before{content:"\f6af"}.fa-ad:before{content:"\f641"}.fa-address-book:before{content:"\f2b9"}.fa-address-card:before{content:"\f2bb"}.fa-adjust:before{content:"\f042"}.fa-adn:before{content:"\f170"}.fa-adversal:before{content:"\f36a"}.fa-affiliatetheme:before{content:"\f36b"}.fa-air-freshener:before{content:"\f5d0"}.fa-airbnb:before{content:"\f834"}.fa-algolia:before{content:"\f36c"}.fa-align-center:before{content:"\f037"}.fa-align-justify:before{content:"\f039"}.fa-align-left:before{content:"\f036"}.fa-align-right:before{content:"\f038"}.fa-alipay:before{content:"\f642"}.fa-allergies:before{content:"\f461"}.fa-amazon:before{content:"\f270"}.fa-amazon-pay:before{content:"\f42c"}.fa-ambulance:before{content:"\f0f9"}.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-amilia:before{content:"\f36d"}.fa-anchor:before{content:"\f13d"}.fa-android:before{content:"\f17b"}.fa-angellist:before{content:"\f209"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-down:before{content:"\f107"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angry:before{content:"\f556"}.fa-angrycreative:before{content:"\f36e"}.fa-angular:before{content:"\f420"}.fa-ankh:before{content:"\f644"}.fa-app-store:before{content:"\f36f"}.fa-app-store-ios:before{content:"\f370"}.fa-apper:before{content:"\f371"}.fa-apple:before{content:"\f179"}.fa-apple-alt:before{content:"\f5d1"}.fa-apple-pay:before{content:"\f415"}.fa-archive:before{content:"\f187"}.fa-archway:before{content:"\f557"}.fa-arrow-alt-circle-down:before{content:"\f358"}.fa-arrow-alt-circle-left:before{content:"\f359"}.fa-arrow-alt-circle-right:before{content:"\f35a"}.fa-arrow-alt-circle-up:before{content:"\f35b"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-down:before{content:"\f063"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrows-alt:before{content:"\f0b2"}.fa-arrows-alt-h:before{content:"\f337"}.fa-arrows-alt-v:before{content:"\f338"}.fa-artstation:before{content:"\f77a"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asterisk:before{content:"\f069"}.fa-asymmetrik:before{content:"\f372"}.fa-at:before{content:"\f1fa"}.fa-atlas:before{content:"\f558"}.fa-atlassian:before{content:"\f77b"}.fa-atom:before{content:"\f5d2"}.fa-audible:before{content:"\f373"}.fa-audio-description:before{content:"\f29e"}.fa-autoprefixer:before{content:"\f41c"}.fa-avianex:before{content:"\f374"}.fa-aviato:before{content:"\f421"}.fa-award:before{content:"\f559"}.fa-aws:before{content:"\f375"}.fa-baby:before{content:"\f77c"}.fa-baby-carriage:before{content:"\f77d"}.fa-backspace:before{content:"\f55a"}.fa-backward:before{content:"\f04a"}.fa-bacon:before{content:"\f7e5"}.fa-bacteria:before{content:"\e059"}.fa-bacterium:before{content:"\e05a"}.fa-bahai:before{content:"\f666"}.fa-balance-scale:before{content:"\f24e"}.fa-balance-scale-left:before{content:"\f515"}.fa-balance-scale-right:before{content:"\f516"}.fa-ban:before{content:"\f05e"}.fa-band-aid:before{content:"\f462"}.fa-bandcamp:before{content:"\f2d5"}.fa-barcode:before{content:"\f02a"}.fa-bars:before{content:"\f0c9"}.fa-baseball-ball:before{content:"\f433"}.fa-basketball-ball:before{content:"\f434"}.fa-bath:before{content:"\f2cd"}.fa-battery-empty:before{content:"\f244"}.fa-battery-full:before{content:"\f240"}.fa-battery-half:before{content:"\f242"}.fa-battery-quarter:before{content:"\f243"}.fa-battery-three-quarters:before{content:"\f241"}.fa-battle-net:before{content:"\f835"}.fa-bed:before{content:"\f236"}.fa-beer:before{content:"\f0fc"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-bell:before{content:"\f0f3"}.fa-bell-slash:before{content:"\f1f6"}.fa-bezier-curve:before{content:"\f55b"}.fa-bible:before{content:"\f647"}.fa-bicycle:before{content:"\f206"}.fa-biking:before{content:"\f84a"}.fa-bimobject:before{content:"\f378"}.fa-binoculars:before{content:"\f1e5"}.fa-biohazard:before{content:"\f780"}.fa-birthday-cake:before{content:"\f1fd"}.fa-bitbucket:before{content:"\f171"}.fa-bitcoin:before{content:"\f379"}.fa-bity:before{content:"\f37a"}.fa-black-tie:before{content:"\f27e"}.fa-blackberry:before{content:"\f37b"}.fa-blender:before{content:"\f517"}.fa-blender-phone:before{content:"\f6b6"}.fa-blind:before{content:"\f29d"}.fa-blog:before{content:"\f781"}.fa-blogger:before{content:"\f37c"}.fa-blogger-b:before{content:"\f37d"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-bold:before{content:"\f032"}.fa-bolt:before{content:"\f0e7"}.fa-bomb:before{content:"\f1e2"}.fa-bone:before{content:"\f5d7"}.fa-bong:before{content:"\f55c"}.fa-book:before{content:"\f02d"}.fa-book-dead:before{content:"\f6b7"}.fa-book-medical:before{content:"\f7e6"}.fa-book-open:before{content:"\f518"}.fa-book-reader:before{content:"\f5da"}.fa-bookmark:before{content:"\f02e"}.fa-bootstrap:before{content:"\f836"}.fa-border-all:before{content:"\f84c"}.fa-border-none:before{content:"\f850"}.fa-border-style:before{content:"\f853"}.fa-bowling-ball:before{content:"\f436"}.fa-box:before{content:"\f466"}.fa-box-open:before{content:"\f49e"}.fa-box-tissue:before{content:"\e05b"}.fa-boxes:before{content:"\f468"}.fa-braille:before{content:"\f2a1"}.fa-brain:before{content:"\f5dc"}.fa-bread-slice:before{content:"\f7ec"}.fa-briefcase:before{content:"\f0b1"}.fa-briefcase-medical:before{content:"\f469"}.fa-broadcast-tower:before{content:"\f519"}.fa-broom:before{content:"\f51a"}.fa-brush:before{content:"\f55d"}.fa-btc:before{content:"\f15a"}.fa-buffer:before{content:"\f837"}.fa-bug:before{content:"\f188"}.fa-building:before{content:"\f1ad"}.fa-bullhorn:before{content:"\f0a1"}.fa-bullseye:before{content:"\f140"}.fa-burn:before{content:"\f46a"}.fa-buromobelexperte:before{content:"\f37f"}.fa-bus:before{content:"\f207"}.fa-bus-alt:before{content:"\f55e"}.fa-business-time:before{content:"\f64a"}.fa-buy-n-large:before{content:"\f8a6"}.fa-buysellads:before{content:"\f20d"}.fa-calculator:before{content:"\f1ec"}.fa-calendar:before{content:"\f133"}.fa-calendar-alt:before{content:"\f073"}.fa-calendar-check:before{content:"\f274"}.fa-calendar-day:before{content:"\f783"}.fa-calendar-minus:before{content:"\f272"}.fa-calendar-plus:before{content:"\f271"}.fa-calendar-times:before{content:"\f273"}.fa-calendar-week:before{content:"\f784"}.fa-camera:before{content:"\f030"}.fa-camera-retro:before{content:"\f083"}.fa-campground:before{content:"\f6bb"}.fa-canadian-maple-leaf:before{content:"\f785"}.fa-candy-cane:before{content:"\f786"}.fa-cannabis:before{content:"\f55f"}.fa-capsules:before{content:"\f46b"}.fa-car:before{content:"\f1b9"}.fa-car-alt:before{content:"\f5de"}.fa-car-battery:before{content:"\f5df"}.fa-car-crash:before{content:"\f5e1"}.fa-car-side:before{content:"\f5e4"}.fa-caravan:before{content:"\f8ff"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-caret-square-down:before{content:"\f150"}.fa-caret-square-left:before{content:"\f191"}.fa-caret-square-right:before{content:"\f152"}.fa-caret-square-up:before{content:"\f151"}.fa-caret-up:before{content:"\f0d8"}.fa-carrot:before{content:"\f787"}.fa-cart-arrow-down:before{content:"\f218"}.fa-cart-plus:before{content:"\f217"}.fa-cash-register:before{content:"\f788"}.fa-cat:before{content:"\f6be"}.fa-cc-amazon-pay:before{content:"\f42d"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-apple-pay:before{content:"\f416"}.fa-cc-diners-club:before{content:"\f24c"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-cc-visa:before{content:"\f1f0"}.fa-centercode:before{content:"\f380"}.fa-centos:before{content:"\f789"}.fa-certificate:before{content:"\f0a3"}.fa-chair:before{content:"\f6c0"}.fa-chalkboard:before{content:"\f51b"}.fa-chalkboard-teacher:before{content:"\f51c"}.fa-charging-station:before{content:"\f5e7"}.fa-chart-area:before{content:"\f1fe"}.fa-chart-bar:before{content:"\f080"}.fa-chart-line:before{content:"\f201"}.fa-chart-pie:before{content:"\f200"}.fa-check:before{content:"\f00c"}.fa-check-circle:before{content:"\f058"}.fa-check-double:before{content:"\f560"}.fa-check-square:before{content:"\f14a"}.fa-cheese:before{content:"\f7ef"}.fa-chess:before{content:"\f439"}.fa-chess-bishop:before{content:"\f43a"}.fa-chess-board:before{content:"\f43c"}.fa-chess-king:before{content:"\f43f"}.fa-chess-knight:before{content:"\f441"}.fa-chess-pawn:before{content:"\f443"}.fa-chess-queen:before{content:"\f445"}.fa-chess-rook:before{content:"\f447"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-down:before{content:"\f078"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-chevron-up:before{content:"\f077"}.fa-child:before{content:"\f1ae"}.fa-chrome:before{content:"\f268"}.fa-chromecast:before{content:"\f838"}.fa-church:before{content:"\f51d"}.fa-circle:before{content:"\f111"}.fa-circle-notch:before{content:"\f1ce"}.fa-city:before{content:"\f64f"}.fa-clinic-medical:before{content:"\f7f2"}.fa-clipboard:before{content:"\f328"}.fa-clipboard-check:before{content:"\f46c"}.fa-clipboard-list:before{content:"\f46d"}.fa-clock:before{content:"\f017"}.fa-clone:before{content:"\f24d"}.fa-closed-captioning:before{content:"\f20a"}.fa-cloud:before{content:"\f0c2"}.fa-cloud-download-alt:before{content:"\f381"}.fa-cloud-meatball:before{content:"\f73b"}.fa-cloud-moon:before{content:"\f6c3"}.fa-cloud-moon-rain:before{content:"\f73c"}.fa-cloud-rain:before{content:"\f73d"}.fa-cloud-showers-heavy:before{content:"\f740"}.fa-cloud-sun:before{content:"\f6c4"}.fa-cloud-sun-rain:before{content:"\f743"}.fa-cloud-upload-alt:before{content:"\f382"}.fa-cloudflare:before{content:"\e07d"}.fa-cloudscale:before{content:"\f383"}.fa-cloudsmith:before{content:"\f384"}.fa-cloudversify:before{content:"\f385"}.fa-cocktail:before{content:"\f561"}.fa-code:before{content:"\f121"}.fa-code-branch:before{content:"\f126"}.fa-codepen:before{content:"\f1cb"}.fa-codiepie:before{content:"\f284"}.fa-coffee:before{content:"\f0f4"}.fa-cog:before{content:"\f013"}.fa-cogs:before{content:"\f085"}.fa-coins:before{content:"\f51e"}.fa-columns:before{content:"\f0db"}.fa-comment:before{content:"\f075"}.fa-comment-alt:before{content:"\f27a"}.fa-comment-dollar:before{content:"\f651"}.fa-comment-dots:before{content:"\f4ad"}.fa-comment-medical:before{content:"\f7f5"}.fa-comment-slash:before{content:"\f4b3"}.fa-comments:before{content:"\f086"}.fa-comments-dollar:before{content:"\f653"}.fa-compact-disc:before{content:"\f51f"}.fa-compass:before{content:"\f14e"}.fa-compress:before{content:"\f066"}.fa-compress-alt:before{content:"\f422"}.fa-compress-arrows-alt:before{content:"\f78c"}.fa-concierge-bell:before{content:"\f562"}.fa-confluence:before{content:"\f78d"}.fa-connectdevelop:before{content:"\f20e"}.fa-contao:before{content:"\f26d"}.fa-cookie:before{content:"\f563"}.fa-cookie-bite:before{content:"\f564"}.fa-copy:before{content:"\f0c5"}.fa-copyright:before{content:"\f1f9"}.fa-cotton-bureau:before{content:"\f89e"}.fa-couch:before{content:"\f4b8"}.fa-cpanel:before{content:"\f388"}.fa-creative-commons:before{content:"\f25e"}.fa-creative-commons-by:before{content:"\f4e7"}.fa-creative-commons-nc:before{content:"\f4e8"}.fa-creative-commons-nc-eu:before{content:"\f4e9"}.fa-creative-commons-nc-jp:before{content:"\f4ea"}.fa-creative-commons-nd:before{content:"\f4eb"}.fa-creative-commons-pd:before{content:"\f4ec"}.fa-creative-commons-pd-alt:before{content:"\f4ed"}.fa-creative-commons-remix:before{content:"\f4ee"}.fa-creative-commons-sa:before{content:"\f4ef"}.fa-creative-commons-sampling:before{content:"\f4f0"}.fa-creative-commons-sampling-plus:before{content:"\f4f1"}.fa-creative-commons-share:before{content:"\f4f2"}.fa-creative-commons-zero:before{content:"\f4f3"}.fa-credit-card:before{content:"\f09d"}.fa-critical-role:before{content:"\f6c9"}.fa-crop:before{content:"\f125"}.fa-crop-alt:before{content:"\f565"}.fa-cross:before{content:"\f654"}.fa-crosshairs:before{content:"\f05b"}.fa-crow:before{content:"\f520"}.fa-crown:before{content:"\f521"}.fa-crutch:before{content:"\f7f7"}.fa-css3:before{content:"\f13c"}.fa-css3-alt:before{content:"\f38b"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-cut:before{content:"\f0c4"}.fa-cuttlefish:before{content:"\f38c"}.fa-d-and-d:before{content:"\f38d"}.fa-d-and-d-beyond:before{content:"\f6ca"}.fa-dailymotion:before{content:"\e052"}.fa-dashcube:before{content:"\f210"}.fa-database:before{content:"\f1c0"}.fa-deaf:before{content:"\f2a4"}.fa-deezer:before{content:"\e077"}.fa-delicious:before{content:"\f1a5"}.fa-democrat:before{content:"\f747"}.fa-deploydog:before{content:"\f38e"}.fa-deskpro:before{content:"\f38f"}.fa-desktop:before{content:"\f108"}.fa-dev:before{content:"\f6cc"}.fa-deviantart:before{content:"\f1bd"}.fa-dharmachakra:before{content:"\f655"}.fa-dhl:before{content:"\f790"}.fa-diagnoses:before{content:"\f470"}.fa-diaspora:before{content:"\f791"}.fa-dice:before{content:"\f522"}.fa-dice-d20:before{content:"\f6cf"}.fa-dice-d6:before{content:"\f6d1"}.fa-dice-five:before{content:"\f523"}.fa-dice-four:before{content:"\f524"}.fa-dice-one:before{content:"\f525"}.fa-dice-six:before{content:"\f526"}.fa-dice-three:before{content:"\f527"}.fa-dice-two:before{content:"\f528"}.fa-digg:before{content:"\f1a6"}.fa-digital-ocean:before{content:"\f391"}.fa-digital-tachograph:before{content:"\f566"}.fa-directions:before{content:"\f5eb"}.fa-discord:before{content:"\f392"}.fa-discourse:before{content:"\f393"}.fa-disease:before{content:"\f7fa"}.fa-divide:before{content:"\f529"}.fa-dizzy:before{content:"\f567"}.fa-dna:before{content:"\f471"}.fa-dochub:before{content:"\f394"}.fa-docker:before{content:"\f395"}.fa-dog:before{content:"\f6d3"}.fa-dollar-sign:before{content:"\f155"}.fa-dolly:before{content:"\f472"}.fa-dolly-flatbed:before{content:"\f474"}.fa-donate:before{content:"\f4b9"}.fa-door-closed:before{content:"\f52a"}.fa-door-open:before{content:"\f52b"}.fa-dot-circle:before{content:"\f192"}.fa-dove:before{content:"\f4ba"}.fa-download:before{content:"\f019"}.fa-draft2digital:before{content:"\f396"}.fa-drafting-compass:before{content:"\f568"}.fa-dragon:before{content:"\f6d5"}.fa-draw-polygon:before{content:"\f5ee"}.fa-dribbble:before{content:"\f17d"}.fa-dribbble-square:before{content:"\f397"}.fa-dropbox:before{content:"\f16b"}.fa-drum:before{content:"\f569"}.fa-drum-steelpan:before{content:"\f56a"}.fa-drumstick-bite:before{content:"\f6d7"}.fa-drupal:before{content:"\f1a9"}.fa-dumbbell:before{content:"\f44b"}.fa-dumpster:before{content:"\f793"}.fa-dumpster-fire:before{content:"\f794"}.fa-dungeon:before{content:"\f6d9"}.fa-dyalog:before{content:"\f399"}.fa-earlybirds:before{content:"\f39a"}.fa-ebay:before{content:"\f4f4"}.fa-edge:before{content:"\f282"}.fa-edge-legacy:before{content:"\e078"}.fa-edit:before{content:"\f044"}.fa-egg:before{content:"\f7fb"}.fa-eject:before{content:"\f052"}.fa-elementor:before{content:"\f430"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-ello:before{content:"\f5f1"}.fa-ember:before{content:"\f423"}.fa-empire:before{content:"\f1d1"}.fa-envelope:before{content:"\f0e0"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-text:before{content:"\f658"}.fa-envelope-square:before{content:"\f199"}.fa-envira:before{content:"\f299"}.fa-equals:before{content:"\f52c"}.fa-eraser:before{content:"\f12d"}.fa-erlang:before{content:"\f39d"}.fa-ethereum:before{content:"\f42e"}.fa-ethernet:before{content:"\f796"}.fa-etsy:before{content:"\f2d7"}.fa-euro-sign:before{content:"\f153"}.fa-evernote:before{content:"\f839"}.fa-exchange-alt:before{content:"\f362"}.fa-exclamation:before{content:"\f12a"}.fa-exclamation-circle:before{content:"\f06a"}.fa-exclamation-triangle:before{content:"\f071"}.fa-expand:before{content:"\f065"}.fa-expand-alt:before{content:"\f424"}.fa-expand-arrows-alt:before{content:"\f31e"}.fa-expeditedssl:before{content:"\f23e"}.fa-external-link-alt:before{content:"\f35d"}.fa-external-link-square-alt:before{content:"\f360"}.fa-eye:before{content:"\f06e"}.fa-eye-dropper:before{content:"\f1fb"}.fa-eye-slash:before{content:"\f070"}.fa-facebook:before{content:"\f09a"}.fa-facebook-f:before{content:"\f39e"}.fa-facebook-messenger:before{content:"\f39f"}.fa-facebook-square:before{content:"\f082"}.fa-fan:before{content:"\f863"}.fa-fantasy-flight-games:before{content:"\f6dc"}.fa-fast-backward:before{content:"\f049"}.fa-fast-forward:before{content:"\f050"}.fa-faucet:before{content:"\e005"}.fa-fax:before{content:"\f1ac"}.fa-feather:before{content:"\f52d"}.fa-feather-alt:before{content:"\f56b"}.fa-fedex:before{content:"\f797"}.fa-fedora:before{content:"\f798"}.fa-female:before{content:"\f182"}.fa-fighter-jet:before{content:"\f0fb"}.fa-figma:before{content:"\f799"}.fa-file:before{content:"\f15b"}.fa-file-alt:before{content:"\f15c"}.fa-file-archive:before{content:"\f1c6"}.fa-file-audio:before{content:"\f1c7"}.fa-file-code:before{content:"\f1c9"}.fa-file-contract:before{content:"\f56c"}.fa-file-csv:before{content:"\f6dd"}.fa-file-download:before{content:"\f56d"}.fa-file-excel:before{content:"\f1c3"}.fa-file-export:before{content:"\f56e"}.fa-file-image:before{content:"\f1c5"}.fa-file-import:before{content:"\f56f"}.fa-file-invoice:before{content:"\f570"}.fa-file-invoice-dollar:before{content:"\f571"}.fa-file-medical:before{content:"\f477"}.fa-file-medical-alt:before{content:"\f478"}.fa-file-pdf:before{content:"\f1c1"}.fa-file-powerpoint:before{content:"\f1c4"}.fa-file-prescription:before{content:"\f572"}.fa-file-signature:before{content:"\f573"}.fa-file-upload:before{content:"\f574"}.fa-file-video:before{content:"\f1c8"}.fa-file-word:before{content:"\f1c2"}.fa-fill:before{content:"\f575"}.fa-fill-drip:before{content:"\f576"}.fa-film:before{content:"\f008"}.fa-filter:before{content:"\f0b0"}.fa-fingerprint:before{content:"\f577"}.fa-fire:before{content:"\f06d"}.fa-fire-alt:before{content:"\f7e4"}.fa-fire-extinguisher:before{content:"\f134"}.fa-firefox:before{content:"\f269"}.fa-firefox-browser:before{content:"\e007"}.fa-first-aid:before{content:"\f479"}.fa-first-order:before{content:"\f2b0"}.fa-first-order-alt:before{content:"\f50a"}.fa-firstdraft:before{content:"\f3a1"}.fa-fish:before{content:"\f578"}.fa-fist-raised:before{content:"\f6de"}.fa-flag:before{content:"\f024"}.fa-flag-checkered:before{content:"\f11e"}.fa-flag-usa:before{content:"\f74d"}.fa-flask:before{content:"\f0c3"}.fa-flickr:before{content:"\f16e"}.fa-flipboard:before{content:"\f44d"}.fa-flushed:before{content:"\f579"}.fa-fly:before{content:"\f417"}.fa-folder:before{content:"\f07b"}.fa-folder-minus:before{content:"\f65d"}.fa-folder-open:before{content:"\f07c"}.fa-folder-plus:before{content:"\f65e"}.fa-font:before{content:"\f031"}.fa-font-awesome:before{content:"\f2b4"}.fa-font-awesome-alt:before{content:"\f35c"}.fa-font-awesome-flag:before{content:"\f425"}.fa-font-awesome-logo-full:before{content:"\f4e6"}.fa-fonticons:before{content:"\f280"}.fa-fonticons-fi:before{content:"\f3a2"}.fa-football-ball:before{content:"\f44e"}.fa-fort-awesome:before{content:"\f286"}.fa-fort-awesome-alt:before{content:"\f3a3"}.fa-forumbee:before{content:"\f211"}.fa-forward:before{content:"\f04e"}.fa-foursquare:before{content:"\f180"}.fa-free-code-camp:before{content:"\f2c5"}.fa-freebsd:before{content:"\f3a4"}.fa-frog:before{content:"\f52e"}.fa-frown:before{content:"\f119"}.fa-frown-open:before{content:"\f57a"}.fa-fulcrum:before{content:"\f50b"}.fa-funnel-dollar:before{content:"\f662"}.fa-futbol:before{content:"\f1e3"}.fa-galactic-republic:before{content:"\f50c"}.fa-galactic-senate:before{content:"\f50d"}.fa-gamepad:before{content:"\f11b"}.fa-gas-pump:before{content:"\f52f"}.fa-gavel:before{content:"\f0e3"}.fa-gem:before{content:"\f3a5"}.fa-genderless:before{content:"\f22d"}.fa-get-pocket:before{content:"\f265"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-ghost:before{content:"\f6e2"}.fa-gift:before{content:"\f06b"}.fa-gifts:before{content:"\f79c"}.fa-git:before{content:"\f1d3"}.fa-git-alt:before{content:"\f841"}.fa-git-square:before{content:"\f1d2"}.fa-github:before{content:"\f09b"}.fa-github-alt:before{content:"\f113"}.fa-github-square:before{content:"\f092"}.fa-gitkraken:before{content:"\f3a6"}.fa-gitlab:before{content:"\f296"}.fa-gitter:before{content:"\f426"}.fa-glass-cheers:before{content:"\f79f"}.fa-glass-martini:before{content:"\f000"}.fa-glass-martini-alt:before{content:"\f57b"}.fa-glass-whiskey:before{content:"\f7a0"}.fa-glasses:before{content:"\f530"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-globe:before{content:"\f0ac"}.fa-globe-africa:before{content:"\f57c"}.fa-globe-americas:before{content:"\f57d"}.fa-globe-asia:before{content:"\f57e"}.fa-globe-europe:before{content:"\f7a2"}.fa-gofore:before{content:"\f3a7"}.fa-golf-ball:before{content:"\f450"}.fa-goodreads:before{content:"\f3a8"}.fa-goodreads-g:before{content:"\f3a9"}.fa-google:before{content:"\f1a0"}.fa-google-drive:before{content:"\f3aa"}.fa-google-pay:before{content:"\e079"}.fa-google-play:before{content:"\f3ab"}.fa-google-plus:before{content:"\f2b3"}.fa-google-plus-g:before{content:"\f0d5"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-wallet:before{content:"\f1ee"}.fa-gopuram:before{content:"\f664"}.fa-graduation-cap:before{content:"\f19d"}.fa-gratipay:before{content:"\f184"}.fa-grav:before{content:"\f2d6"}.fa-greater-than:before{content:"\f531"}.fa-greater-than-equal:before{content:"\f532"}.fa-grimace:before{content:"\f57f"}.fa-grin:before{content:"\f580"}.fa-grin-alt:before{content:"\f581"}.fa-grin-beam:before{content:"\f582"}.fa-grin-beam-sweat:before{content:"\f583"}.fa-grin-hearts:before{content:"\f584"}.fa-grin-squint:before{content:"\f585"}.fa-grin-squint-tears:before{content:"\f586"}.fa-grin-stars:before{content:"\f587"}.fa-grin-tears:before{content:"\f588"}.fa-grin-tongue:before{content:"\f589"}.fa-grin-tongue-squint:before{content:"\f58a"}.fa-grin-tongue-wink:before{content:"\f58b"}.fa-grin-wink:before{content:"\f58c"}.fa-grip-horizontal:before{content:"\f58d"}.fa-grip-lines:before{content:"\f7a4"}.fa-grip-lines-vertical:before{content:"\f7a5"}.fa-grip-vertical:before{content:"\f58e"}.fa-gripfire:before{content:"\f3ac"}.fa-grunt:before{content:"\f3ad"}.fa-guilded:before{content:"\e07e"}.fa-guitar:before{content:"\f7a6"}.fa-gulp:before{content:"\f3ae"}.fa-h-square:before{content:"\f0fd"}.fa-hacker-news:before{content:"\f1d4"}.fa-hacker-news-square:before{content:"\f3af"}.fa-hackerrank:before{content:"\f5f7"}.fa-hamburger:before{content:"\f805"}.fa-hammer:before{content:"\f6e3"}.fa-hamsa:before{content:"\f665"}.fa-hand-holding:before{content:"\f4bd"}.fa-hand-holding-heart:before{content:"\f4be"}.fa-hand-holding-medical:before{content:"\e05c"}.fa-hand-holding-usd:before{content:"\f4c0"}.fa-hand-holding-water:before{content:"\f4c1"}.fa-hand-lizard:before{content:"\f258"}.fa-hand-middle-finger:before{content:"\f806"}.fa-hand-paper:before{content:"\f256"}.fa-hand-peace:before{content:"\f25b"}.fa-hand-point-down:before{content:"\f0a7"}.fa-hand-point-left:before{content:"\f0a5"}.fa-hand-point-right:before{content:"\f0a4"}.fa-hand-point-up:before{content:"\f0a6"}.fa-hand-pointer:before{content:"\f25a"}.fa-hand-rock:before{content:"\f255"}.fa-hand-scissors:before{content:"\f257"}.fa-hand-sparkles:before{content:"\e05d"}.fa-hand-spock:before{content:"\f259"}.fa-hands:before{content:"\f4c2"}.fa-hands-helping:before{content:"\f4c4"}.fa-hands-wash:before{content:"\e05e"}.fa-handshake:before{content:"\f2b5"}.fa-handshake-alt-slash:before{content:"\e05f"}.fa-handshake-slash:before{content:"\e060"}.fa-hanukiah:before{content:"\f6e6"}.fa-hard-hat:before{content:"\f807"}.fa-hashtag:before{content:"\f292"}.fa-hat-cowboy:before{content:"\f8c0"}.fa-hat-cowboy-side:before{content:"\f8c1"}.fa-hat-wizard:before{content:"\f6e8"}.fa-hdd:before{content:"\f0a0"}.fa-head-side-cough:before{content:"\e061"}.fa-head-side-cough-slash:before{content:"\e062"}.fa-head-side-mask:before{content:"\e063"}.fa-head-side-virus:before{content:"\e064"}.fa-heading:before{content:"\f1dc"}.fa-headphones:before{content:"\f025"}.fa-headphones-alt:before{content:"\f58f"}.fa-headset:before{content:"\f590"}.fa-heart:before{content:"\f004"}.fa-heart-broken:before{content:"\f7a9"}.fa-heartbeat:before{content:"\f21e"}.fa-helicopter:before{content:"\f533"}.fa-highlighter:before{content:"\f591"}.fa-hiking:before{content:"\f6ec"}.fa-hippo:before{content:"\f6ed"}.fa-hips:before{content:"\f452"}.fa-hire-a-helper:before{content:"\f3b0"}.fa-history:before{content:"\f1da"}.fa-hive:before{content:"\e07f"}.fa-hockey-puck:before{content:"\f453"}.fa-holly-berry:before{content:"\f7aa"}.fa-home:before{content:"\f015"}.fa-hooli:before{content:"\f427"}.fa-hornbill:before{content:"\f592"}.fa-horse:before{content:"\f6f0"}.fa-horse-head:before{content:"\f7ab"}.fa-hospital:before{content:"\f0f8"}.fa-hospital-alt:before{content:"\f47d"}.fa-hospital-symbol:before{content:"\f47e"}.fa-hospital-user:before{content:"\f80d"}.fa-hot-tub:before{content:"\f593"}.fa-hotdog:before{content:"\f80f"}.fa-hotel:before{content:"\f594"}.fa-hotjar:before{content:"\f3b1"}.fa-hourglass:before{content:"\f254"}.fa-hourglass-end:before{content:"\f253"}.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-start:before{content:"\f251"}.fa-house-damage:before{content:"\f6f1"}.fa-house-user:before{content:"\e065"}.fa-houzz:before{content:"\f27c"}.fa-hryvnia:before{content:"\f6f2"}.fa-html5:before{content:"\f13b"}.fa-hubspot:before{content:"\f3b2"}.fa-i-cursor:before{content:"\f246"}.fa-ice-cream:before{content:"\f810"}.fa-icicles:before{content:"\f7ad"}.fa-icons:before{content:"\f86d"}.fa-id-badge:before{content:"\f2c1"}.fa-id-card:before{content:"\f2c2"}.fa-id-card-alt:before{content:"\f47f"}.fa-ideal:before{content:"\e013"}.fa-igloo:before{content:"\f7ae"}.fa-image:before{content:"\f03e"}.fa-images:before{content:"\f302"}.fa-imdb:before{content:"\f2d8"}.fa-inbox:before{content:"\f01c"}.fa-indent:before{content:"\f03c"}.fa-industry:before{content:"\f275"}.fa-infinity:before{content:"\f534"}.fa-info:before{content:"\f129"}.fa-info-circle:before{content:"\f05a"}.fa-innosoft:before{content:"\e080"}.fa-instagram:before{content:"\f16d"}.fa-instagram-square:before{content:"\e055"}.fa-instalod:before{content:"\e081"}.fa-intercom:before{content:"\f7af"}.fa-internet-explorer:before{content:"\f26b"}.fa-invision:before{content:"\f7b0"}.fa-ioxhost:before{content:"\f208"}.fa-italic:before{content:"\f033"}.fa-itch-io:before{content:"\f83a"}.fa-itunes:before{content:"\f3b4"}.fa-itunes-note:before{content:"\f3b5"}.fa-java:before{content:"\f4e4"}.fa-jedi:before{content:"\f669"}.fa-jedi-order:before{content:"\f50e"}.fa-jenkins:before{content:"\f3b6"}.fa-jira:before{content:"\f7b1"}.fa-joget:before{content:"\f3b7"}.fa-joint:before{content:"\f595"}.fa-joomla:before{content:"\f1aa"}.fa-journal-whills:before{content:"\f66a"}.fa-js:before{content:"\f3b8"}.fa-js-square:before{content:"\f3b9"}.fa-jsfiddle:before{content:"\f1cc"}.fa-kaaba:before{content:"\f66b"}.fa-kaggle:before{content:"\f5fa"}.fa-key:before{content:"\f084"}.fa-keybase:before{content:"\f4f5"}.fa-keyboard:before{content:"\f11c"}.fa-keycdn:before{content:"\f3ba"}.fa-khanda:before{content:"\f66d"}.fa-kickstarter:before{content:"\f3bb"}.fa-kickstarter-k:before{content:"\f3bc"}.fa-kiss:before{content:"\f596"}.fa-kiss-beam:before{content:"\f597"}.fa-kiss-wink-heart:before{content:"\f598"}.fa-kiwi-bird:before{content:"\f535"}.fa-korvue:before{content:"\f42f"}.fa-landmark:before{content:"\f66f"}.fa-language:before{content:"\f1ab"}.fa-laptop:before{content:"\f109"}.fa-laptop-code:before{content:"\f5fc"}.fa-laptop-house:before{content:"\e066"}.fa-laptop-medical:before{content:"\f812"}.fa-laravel:before{content:"\f3bd"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-laugh:before{content:"\f599"}.fa-laugh-beam:before{content:"\f59a"}.fa-laugh-squint:before{content:"\f59b"}.fa-laugh-wink:before{content:"\f59c"}.fa-layer-group:before{content:"\f5fd"}.fa-leaf:before{content:"\f06c"}.fa-leanpub:before{content:"\f212"}.fa-lemon:before{content:"\f094"}.fa-less:before{content:"\f41d"}.fa-less-than:before{content:"\f536"}.fa-less-than-equal:before{content:"\f537"}.fa-level-down-alt:before{content:"\f3be"}.fa-level-up-alt:before{content:"\f3bf"}.fa-life-ring:before{content:"\f1cd"}.fa-lightbulb:before{content:"\f0eb"}.fa-line:before{content:"\f3c0"}.fa-link:before{content:"\f0c1"}.fa-linkedin:before{content:"\f08c"}.fa-linkedin-in:before{content:"\f0e1"}.fa-linode:before{content:"\f2b8"}.fa-linux:before{content:"\f17c"}.fa-lira-sign:before{content:"\f195"}.fa-list:before{content:"\f03a"}.fa-list-alt:before{content:"\f022"}.fa-list-ol:before{content:"\f0cb"}.fa-list-ul:before{content:"\f0ca"}.fa-location-arrow:before{content:"\f124"}.fa-lock:before{content:"\f023"}.fa-lock-open:before{content:"\f3c1"}.fa-long-arrow-alt-down:before{content:"\f309"}.fa-long-arrow-alt-left:before{content:"\f30a"}.fa-long-arrow-alt-right:before{content:"\f30b"}.fa-long-arrow-alt-up:before{content:"\f30c"}.fa-low-vision:before{content:"\f2a8"}.fa-luggage-cart:before{content:"\f59d"}.fa-lungs:before{content:"\f604"}.fa-lungs-virus:before{content:"\e067"}.fa-lyft:before{content:"\f3c3"}.fa-magento:before{content:"\f3c4"}.fa-magic:before{content:"\f0d0"}.fa-magnet:before{content:"\f076"}.fa-mail-bulk:before{content:"\f674"}.fa-mailchimp:before{content:"\f59e"}.fa-male:before{content:"\f183"}.fa-mandalorian:before{content:"\f50f"}.fa-map:before{content:"\f279"}.fa-map-marked:before{content:"\f59f"}.fa-map-marked-alt:before{content:"\f5a0"}.fa-map-marker:before{content:"\f041"}.fa-map-marker-alt:before{content:"\f3c5"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-markdown:before{content:"\f60f"}.fa-marker:before{content:"\f5a1"}.fa-mars:before{content:"\f222"}.fa-mars-double:before{content:"\f227"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mask:before{content:"\f6fa"}.fa-mastodon:before{content:"\f4f6"}.fa-maxcdn:before{content:"\f136"}.fa-mdb:before{content:"\f8ca"}.fa-medal:before{content:"\f5a2"}.fa-medapps:before{content:"\f3c6"}.fa-medium:before{content:"\f23a"}.fa-medium-m:before{content:"\f3c7"}.fa-medkit:before{content:"\f0fa"}.fa-medrt:before{content:"\f3c8"}.fa-meetup:before{content:"\f2e0"}.fa-megaport:before{content:"\f5a3"}.fa-meh:before{content:"\f11a"}.fa-meh-blank:before{content:"\f5a4"}.fa-meh-rolling-eyes:before{content:"\f5a5"}.fa-memory:before{content:"\f538"}.fa-mendeley:before{content:"\f7b3"}.fa-menorah:before{content:"\f676"}.fa-mercury:before{content:"\f223"}.fa-meteor:before{content:"\f753"}.fa-microblog:before{content:"\e01a"}.fa-microchip:before{content:"\f2db"}.fa-microphone:before{content:"\f130"}.fa-microphone-alt:before{content:"\f3c9"}.fa-microphone-alt-slash:before{content:"\f539"}.fa-microphone-slash:before{content:"\f131"}.fa-microscope:before{content:"\f610"}.fa-microsoft:before{content:"\f3ca"}.fa-minus:before{content:"\f068"}.fa-minus-circle:before{content:"\f056"}.fa-minus-square:before{content:"\f146"}.fa-mitten:before{content:"\f7b5"}.fa-mix:before{content:"\f3cb"}.fa-mixcloud:before{content:"\f289"}.fa-mixer:before{content:"\e056"}.fa-mizuni:before{content:"\f3cc"}.fa-mobile:before{content:"\f10b"}.fa-mobile-alt:before{content:"\f3cd"}.fa-modx:before{content:"\f285"}.fa-monero:before{content:"\f3d0"}.fa-money-bill:before{content:"\f0d6"}.fa-money-bill-alt:before{content:"\f3d1"}.fa-money-bill-wave:before{content:"\f53a"}.fa-money-bill-wave-alt:before{content:"\f53b"}.fa-money-check:before{content:"\f53c"}.fa-money-check-alt:before{content:"\f53d"}.fa-monument:before{content:"\f5a6"}.fa-moon:before{content:"\f186"}.fa-mortar-pestle:before{content:"\f5a7"}.fa-mosque:before{content:"\f678"}.fa-motorcycle:before{content:"\f21c"}.fa-mountain:before{content:"\f6fc"}.fa-mouse:before{content:"\f8cc"}.fa-mouse-pointer:before{content:"\f245"}.fa-mug-hot:before{content:"\f7b6"}.fa-music:before{content:"\f001"}.fa-napster:before{content:"\f3d2"}.fa-neos:before{content:"\f612"}.fa-network-wired:before{content:"\f6ff"}.fa-neuter:before{content:"\f22c"}.fa-newspaper:before{content:"\f1ea"}.fa-nimblr:before{content:"\f5a8"}.fa-node:before{content:"\f419"}.fa-node-js:before{content:"\f3d3"}.fa-not-equal:before{content:"\f53e"}.fa-notes-medical:before{content:"\f481"}.fa-npm:before{content:"\f3d4"}.fa-ns8:before{content:"\f3d5"}.fa-nutritionix:before{content:"\f3d6"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-octopus-deploy:before{content:"\e082"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-oil-can:before{content:"\f613"}.fa-old-republic:before{content:"\f510"}.fa-om:before{content:"\f679"}.fa-opencart:before{content:"\f23d"}.fa-openid:before{content:"\f19b"}.fa-opera:before{content:"\f26a"}.fa-optin-monster:before{content:"\f23c"}.fa-orcid:before{content:"\f8d2"}.fa-osi:before{content:"\f41a"}.fa-otter:before{content:"\f700"}.fa-outdent:before{content:"\f03b"}.fa-page4:before{content:"\f3d7"}.fa-pagelines:before{content:"\f18c"}.fa-pager:before{content:"\f815"}.fa-paint-brush:before{content:"\f1fc"}.fa-paint-roller:before{content:"\f5aa"}.fa-palette:before{content:"\f53f"}.fa-palfed:before{content:"\f3d8"}.fa-pallet:before{content:"\f482"}.fa-paper-plane:before{content:"\f1d8"}.fa-paperclip:before{content:"\f0c6"}.fa-parachute-box:before{content:"\f4cd"}.fa-paragraph:before{content:"\f1dd"}.fa-parking:before{content:"\f540"}.fa-passport:before{content:"\f5ab"}.fa-pastafarianism:before{content:"\f67b"}.fa-paste:before{content:"\f0ea"}.fa-patreon:before{content:"\f3d9"}.fa-pause:before{content:"\f04c"}.fa-pause-circle:before{content:"\f28b"}.fa-paw:before{content:"\f1b0"}.fa-paypal:before{content:"\f1ed"}.fa-peace:before{content:"\f67c"}.fa-pen:before{content:"\f304"}.fa-pen-alt:before{content:"\f305"}.fa-pen-fancy:before{content:"\f5ac"}.fa-pen-nib:before{content:"\f5ad"}.fa-pen-square:before{content:"\f14b"}.fa-pencil-alt:before{content:"\f303"}.fa-pencil-ruler:before{content:"\f5ae"}.fa-penny-arcade:before{content:"\f704"}.fa-people-arrows:before{content:"\e068"}.fa-people-carry:before{content:"\f4ce"}.fa-pepper-hot:before{content:"\f816"}.fa-perbyte:before{content:"\e083"}.fa-percent:before{content:"\f295"}.fa-percentage:before{content:"\f541"}.fa-periscope:before{content:"\f3da"}.fa-person-booth:before{content:"\f756"}.fa-phabricator:before{content:"\f3db"}.fa-phoenix-framework:before{content:"\f3dc"}.fa-phoenix-squadron:before{content:"\f511"}.fa-phone:before{content:"\f095"}.fa-phone-alt:before{content:"\f879"}.fa-phone-slash:before{content:"\f3dd"}.fa-phone-square:before{content:"\f098"}.fa-phone-square-alt:before{content:"\f87b"}.fa-phone-volume:before{content:"\f2a0"}.fa-photo-video:before{content:"\f87c"}.fa-php:before{content:"\f457"}.fa-pied-piper:before{content:"\f2ae"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-pied-piper-hat:before{content:"\f4e5"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-square:before{content:"\e01e"}.fa-piggy-bank:before{content:"\f4d3"}.fa-pills:before{content:"\f484"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-p:before{content:"\f231"}.fa-pinterest-square:before{content:"\f0d3"}.fa-pizza-slice:before{content:"\f818"}.fa-place-of-worship:before{content:"\f67f"}.fa-plane:before{content:"\f072"}.fa-plane-arrival:before{content:"\f5af"}.fa-plane-departure:before{content:"\f5b0"}.fa-plane-slash:before{content:"\e069"}.fa-play:before{content:"\f04b"}.fa-play-circle:before{content:"\f144"}.fa-playstation:before{content:"\f3df"}.fa-plug:before{content:"\f1e6"}.fa-plus:before{content:"\f067"}.fa-plus-circle:before{content:"\f055"}.fa-plus-square:before{content:"\f0fe"}.fa-podcast:before{content:"\f2ce"}.fa-poll:before{content:"\f681"}.fa-poll-h:before{content:"\f682"}.fa-poo:before{content:"\f2fe"}.fa-poo-storm:before{content:"\f75a"}.fa-poop:before{content:"\f619"}.fa-portrait:before{content:"\f3e0"}.fa-pound-sign:before{content:"\f154"}.fa-power-off:before{content:"\f011"}.fa-pray:before{content:"\f683"}.fa-praying-hands:before{content:"\f684"}.fa-prescription:before{content:"\f5b1"}.fa-prescription-bottle:before{content:"\f485"}.fa-prescription-bottle-alt:before{content:"\f486"}.fa-print:before{content:"\f02f"}.fa-procedures:before{content:"\f487"}.fa-product-hunt:before{content:"\f288"}.fa-project-diagram:before{content:"\f542"}.fa-pump-medical:before{content:"\e06a"}.fa-pump-soap:before{content:"\e06b"}.fa-pushed:before{content:"\f3e1"}.fa-puzzle-piece:before{content:"\f12e"}.fa-python:before{content:"\f3e2"}.fa-qq:before{content:"\f1d6"}.fa-qrcode:before{content:"\f029"}.fa-question:before{content:"\f128"}.fa-question-circle:before{content:"\f059"}.fa-quidditch:before{content:"\f458"}.fa-quinscape:before{content:"\f459"}.fa-quora:before{content:"\f2c4"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-quran:before{content:"\f687"}.fa-r-project:before{content:"\f4f7"}.fa-radiation:before{content:"\f7b9"}.fa-radiation-alt:before{content:"\f7ba"}.fa-rainbow:before{content:"\f75b"}.fa-random:before{content:"\f074"}.fa-raspberry-pi:before{content:"\f7bb"}.fa-ravelry:before{content:"\f2d9"}.fa-react:before{content:"\f41b"}.fa-reacteurope:before{content:"\f75d"}.fa-readme:before{content:"\f4d5"}.fa-rebel:before{content:"\f1d0"}.fa-receipt:before{content:"\f543"}.fa-record-vinyl:before{content:"\f8d9"}.fa-recycle:before{content:"\f1b8"}.fa-red-river:before{content:"\f3e3"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-alien:before{content:"\f281"}.fa-reddit-square:before{content:"\f1a2"}.fa-redhat:before{content:"\f7bc"}.fa-redo:before{content:"\f01e"}.fa-redo-alt:before{content:"\f2f9"}.fa-registered:before{content:"\f25d"}.fa-remove-format:before{content:"\f87d"}.fa-renren:before{content:"\f18b"}.fa-reply:before{content:"\f3e5"}.fa-reply-all:before{content:"\f122"}.fa-replyd:before{content:"\f3e6"}.fa-republican:before{content:"\f75e"}.fa-researchgate:before{content:"\f4f8"}.fa-resolving:before{content:"\f3e7"}.fa-restroom:before{content:"\f7bd"}.fa-retweet:before{content:"\f079"}.fa-rev:before{content:"\f5b2"}.fa-ribbon:before{content:"\f4d6"}.fa-ring:before{content:"\f70b"}.fa-road:before{content:"\f018"}.fa-robot:before{content:"\f544"}.fa-rocket:before{content:"\f135"}.fa-rocketchat:before{content:"\f3e8"}.fa-rockrms:before{content:"\f3e9"}.fa-route:before{content:"\f4d7"}.fa-rss:before{content:"\f09e"}.fa-rss-square:before{content:"\f143"}.fa-ruble-sign:before{content:"\f158"}.fa-ruler:before{content:"\f545"}.fa-ruler-combined:before{content:"\f546"}.fa-ruler-horizontal:before{content:"\f547"}.fa-ruler-vertical:before{content:"\f548"}.fa-running:before{content:"\f70c"}.fa-rupee-sign:before{content:"\f156"}.fa-rust:before{content:"\e07a"}.fa-sad-cry:before{content:"\f5b3"}.fa-sad-tear:before{content:"\f5b4"}.fa-safari:before{content:"\f267"}.fa-salesforce:before{content:"\f83b"}.fa-sass:before{content:"\f41e"}.fa-satellite:before{content:"\f7bf"}.fa-satellite-dish:before{content:"\f7c0"}.fa-save:before{content:"\f0c7"}.fa-schlix:before{content:"\f3ea"}.fa-school:before{content:"\f549"}.fa-screwdriver:before{content:"\f54a"}.fa-scribd:before{content:"\f28a"}.fa-scroll:before{content:"\f70e"}.fa-sd-card:before{content:"\f7c2"}.fa-search:before{content:"\f002"}.fa-search-dollar:before{content:"\f688"}.fa-search-location:before{content:"\f689"}.fa-search-minus:before{content:"\f010"}.fa-search-plus:before{content:"\f00e"}.fa-searchengin:before{content:"\f3eb"}.fa-seedling:before{content:"\f4d8"}.fa-sellcast:before{content:"\f2da"}.fa-sellsy:before{content:"\f213"}.fa-server:before{content:"\f233"}.fa-servicestack:before{content:"\f3ec"}.fa-shapes:before{content:"\f61f"}.fa-share:before{content:"\f064"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-share-square:before{content:"\f14d"}.fa-shekel-sign:before{content:"\f20b"}.fa-shield-alt:before{content:"\f3ed"}.fa-shield-virus:before{content:"\e06c"}.fa-ship:before{content:"\f21a"}.fa-shipping-fast:before{content:"\f48b"}.fa-shirtsinbulk:before{content:"\f214"}.fa-shoe-prints:before{content:"\f54b"}.fa-shopify:before{content:"\e057"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-shopping-cart:before{content:"\f07a"}.fa-shopware:before{content:"\f5b5"}.fa-shower:before{content:"\f2cc"}.fa-shuttle-van:before{content:"\f5b6"}.fa-sign:before{content:"\f4d9"}.fa-sign-in-alt:before{content:"\f2f6"}.fa-sign-language:before{content:"\f2a7"}.fa-sign-out-alt:before{content:"\f2f5"}.fa-signal:before{content:"\f012"}.fa-signature:before{content:"\f5b7"}.fa-sim-card:before{content:"\f7c4"}.fa-simplybuilt:before{content:"\f215"}.fa-sink:before{content:"\e06d"}.fa-sistrix:before{content:"\f3ee"}.fa-sitemap:before{content:"\f0e8"}.fa-sith:before{content:"\f512"}.fa-skating:before{content:"\f7c5"}.fa-sketch:before{content:"\f7c6"}.fa-skiing:before{content:"\f7c9"}.fa-skiing-nordic:before{content:"\f7ca"}.fa-skull:before{content:"\f54c"}.fa-skull-crossbones:before{content:"\f714"}.fa-skyatlas:before{content:"\f216"}.fa-skype:before{content:"\f17e"}.fa-slack:before{content:"\f198"}.fa-slack-hash:before{content:"\f3ef"}.fa-slash:before{content:"\f715"}.fa-sleigh:before{content:"\f7cc"}.fa-sliders-h:before{content:"\f1de"}.fa-slideshare:before{content:"\f1e7"}.fa-smile:before{content:"\f118"}.fa-smile-beam:before{content:"\f5b8"}.fa-smile-wink:before{content:"\f4da"}.fa-smog:before{content:"\f75f"}.fa-smoking:before{content:"\f48d"}.fa-smoking-ban:before{content:"\f54d"}.fa-sms:before{content:"\f7cd"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-snowboarding:before{content:"\f7ce"}.fa-snowflake:before{content:"\f2dc"}.fa-snowman:before{content:"\f7d0"}.fa-snowplow:before{content:"\f7d2"}.fa-soap:before{content:"\e06e"}.fa-socks:before{content:"\f696"}.fa-solar-panel:before{content:"\f5ba"}.fa-sort:before{content:"\f0dc"}.fa-sort-alpha-down:before{content:"\f15d"}.fa-sort-alpha-down-alt:before{content:"\f881"}.fa-sort-alpha-up:before{content:"\f15e"}.fa-sort-alpha-up-alt:before{content:"\f882"}.fa-sort-amount-down:before{content:"\f160"}.fa-sort-amount-down-alt:before{content:"\f884"}.fa-sort-amount-up:before{content:"\f161"}.fa-sort-amount-up-alt:before{content:"\f885"}.fa-sort-down:before{content:"\f0dd"}.fa-sort-numeric-down:before{content:"\f162"}.fa-sort-numeric-down-alt:before{content:"\f886"}.fa-sort-numeric-up:before{content:"\f163"}.fa-sort-numeric-up-alt:before{content:"\f887"}.fa-sort-up:before{content:"\f0de"}.fa-soundcloud:before{content:"\f1be"}.fa-sourcetree:before{content:"\f7d3"}.fa-spa:before{content:"\f5bb"}.fa-space-shuttle:before{content:"\f197"}.fa-speakap:before{content:"\f3f3"}.fa-speaker-deck:before{content:"\f83c"}.fa-spell-check:before{content:"\f891"}.fa-spider:before{content:"\f717"}.fa-spinner:before{content:"\f110"}.fa-splotch:before{content:"\f5bc"}.fa-spotify:before{content:"\f1bc"}.fa-spray-can:before{content:"\f5bd"}.fa-square:before{content:"\f0c8"}.fa-square-full:before{content:"\f45c"}.fa-square-root-alt:before{content:"\f698"}.fa-squarespace:before{content:"\f5be"}.fa-stack-exchange:before{content:"\f18d"}.fa-stack-overflow:before{content:"\f16c"}.fa-stackpath:before{content:"\f842"}.fa-stamp:before{content:"\f5bf"}.fa-star:before{content:"\f005"}.fa-star-and-crescent:before{content:"\f699"}.fa-star-half:before{content:"\f089"}.fa-star-half-alt:before{content:"\f5c0"}.fa-star-of-david:before{content:"\f69a"}.fa-star-of-life:before{content:"\f621"}.fa-staylinked:before{content:"\f3f5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-steam-symbol:before{content:"\f3f6"}.fa-step-backward:before{content:"\f048"}.fa-step-forward:before{content:"\f051"}.fa-stethoscope:before{content:"\f0f1"}.fa-sticker-mule:before{content:"\f3f7"}.fa-sticky-note:before{content:"\f249"}.fa-stop:before{content:"\f04d"}.fa-stop-circle:before{content:"\f28d"}.fa-stopwatch:before{content:"\f2f2"}.fa-stopwatch-20:before{content:"\e06f"}.fa-store:before{content:"\f54e"}.fa-store-alt:before{content:"\f54f"}.fa-store-alt-slash:before{content:"\e070"}.fa-store-slash:before{content:"\e071"}.fa-strava:before{content:"\f428"}.fa-stream:before{content:"\f550"}.fa-street-view:before{content:"\f21d"}.fa-strikethrough:before{content:"\f0cc"}.fa-stripe:before{content:"\f429"}.fa-stripe-s:before{content:"\f42a"}.fa-stroopwafel:before{content:"\f551"}.fa-studiovinari:before{content:"\f3f8"}.fa-stumbleupon:before{content:"\f1a4"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-subscript:before{content:"\f12c"}.fa-subway:before{content:"\f239"}.fa-suitcase:before{content:"\f0f2"}.fa-suitcase-rolling:before{content:"\f5c1"}.fa-sun:before{content:"\f185"}.fa-superpowers:before{content:"\f2dd"}.fa-superscript:before{content:"\f12b"}.fa-supple:before{content:"\f3f9"}.fa-surprise:before{content:"\f5c2"}.fa-suse:before{content:"\f7d6"}.fa-swatchbook:before{content:"\f5c3"}.fa-swift:before{content:"\f8e1"}.fa-swimmer:before{content:"\f5c4"}.fa-swimming-pool:before{content:"\f5c5"}.fa-symfony:before{content:"\f83d"}.fa-synagogue:before{content:"\f69b"}.fa-sync:before{content:"\f021"}.fa-sync-alt:before{content:"\f2f1"}.fa-syringe:before{content:"\f48e"}.fa-table:before{content:"\f0ce"}.fa-table-tennis:before{content:"\f45d"}.fa-tablet:before{content:"\f10a"}.fa-tablet-alt:before{content:"\f3fa"}.fa-tablets:before{content:"\f490"}.fa-tachometer-alt:before{content:"\f3fd"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-tape:before{content:"\f4db"}.fa-tasks:before{content:"\f0ae"}.fa-taxi:before{content:"\f1ba"}.fa-teamspeak:before{content:"\f4f9"}.fa-teeth:before{content:"\f62e"}.fa-teeth-open:before{content:"\f62f"}.fa-telegram:before{content:"\f2c6"}.fa-telegram-plane:before{content:"\f3fe"}.fa-temperature-high:before{content:"\f769"}.fa-temperature-low:before{content:"\f76b"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-tenge:before{content:"\f7d7"}.fa-terminal:before{content:"\f120"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-th:before{content:"\f00a"}.fa-th-large:before{content:"\f009"}.fa-th-list:before{content:"\f00b"}.fa-the-red-yeti:before{content:"\f69d"}.fa-theater-masks:before{content:"\f630"}.fa-themeco:before{content:"\f5c6"}.fa-themeisle:before{content:"\f2b2"}.fa-thermometer:before{content:"\f491"}.fa-thermometer-empty:before{content:"\f2cb"}.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-think-peaks:before{content:"\f731"}.fa-thumbs-down:before{content:"\f165"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbtack:before{content:"\f08d"}.fa-ticket-alt:before{content:"\f3ff"}.fa-tiktok:before{content:"\e07b"}.fa-times:before{content:"\f00d"}.fa-times-circle:before{content:"\f057"}.fa-tint:before{content:"\f043"}.fa-tint-slash:before{content:"\f5c7"}.fa-tired:before{content:"\f5c8"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-toilet:before{content:"\f7d8"}.fa-toilet-paper:before{content:"\f71e"}.fa-toilet-paper-slash:before{content:"\e072"}.fa-toolbox:before{content:"\f552"}.fa-tools:before{content:"\f7d9"}.fa-tooth:before{content:"\f5c9"}.fa-torah:before{content:"\f6a0"}.fa-torii-gate:before{content:"\f6a1"}.fa-tractor:before{content:"\f722"}.fa-trade-federation:before{content:"\f513"}.fa-trademark:before{content:"\f25c"}.fa-traffic-light:before{content:"\f637"}.fa-trailer:before{content:"\e041"}.fa-train:before{content:"\f238"}.fa-tram:before{content:"\f7da"}.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-trash:before{content:"\f1f8"}.fa-trash-alt:before{content:"\f2ed"}.fa-trash-restore:before{content:"\f829"}.fa-trash-restore-alt:before{content:"\f82a"}.fa-tree:before{content:"\f1bb"}.fa-trello:before{content:"\f181"}.fa-tripadvisor:before{content:"\f262"}.fa-trophy:before{content:"\f091"}.fa-truck:before{content:"\f0d1"}.fa-truck-loading:before{content:"\f4de"}.fa-truck-monster:before{content:"\f63b"}.fa-truck-moving:before{content:"\f4df"}.fa-truck-pickup:before{content:"\f63c"}.fa-tshirt:before{content:"\f553"}.fa-tty:before{content:"\f1e4"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-tv:before{content:"\f26c"}.fa-twitch:before{content:"\f1e8"}.fa-twitter:before{content:"\f099"}.fa-twitter-square:before{content:"\f081"}.fa-typo3:before{content:"\f42b"}.fa-uber:before{content:"\f402"}.fa-ubuntu:before{content:"\f7df"}.fa-uikit:before{content:"\f403"}.fa-umbraco:before{content:"\f8e8"}.fa-umbrella:before{content:"\f0e9"}.fa-umbrella-beach:before{content:"\f5ca"}.fa-uncharted:before{content:"\e084"}.fa-underline:before{content:"\f0cd"}.fa-undo:before{content:"\f0e2"}.fa-undo-alt:before{content:"\f2ea"}.fa-uniregistry:before{content:"\f404"}.fa-unity:before{content:"\e049"}.fa-universal-access:before{content:"\f29a"}.fa-university:before{content:"\f19c"}.fa-unlink:before{content:"\f127"}.fa-unlock:before{content:"\f09c"}.fa-unlock-alt:before{content:"\f13e"}.fa-unsplash:before{content:"\e07c"}.fa-untappd:before{content:"\f405"}.fa-upload:before{content:"\f093"}.fa-ups:before{content:"\f7e0"}.fa-usb:before{content:"\f287"}.fa-user:before{content:"\f007"}.fa-user-alt:before{content:"\f406"}.fa-user-alt-slash:before{content:"\f4fa"}.fa-user-astronaut:before{content:"\f4fb"}.fa-user-check:before{content:"\f4fc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-clock:before{content:"\f4fd"}.fa-user-cog:before{content:"\f4fe"}.fa-user-edit:before{content:"\f4ff"}.fa-user-friends:before{content:"\f500"}.fa-user-graduate:before{content:"\f501"}.fa-user-injured:before{content:"\f728"}.fa-user-lock:before{content:"\f502"}.fa-user-md:before{content:"\f0f0"}.fa-user-minus:before{content:"\f503"}.fa-user-ninja:before{content:"\f504"}.fa-user-nurse:before{content:"\f82f"}.fa-user-plus:before{content:"\f234"}.fa-user-secret:before{content:"\f21b"}.fa-user-shield:before{content:"\f505"}.fa-user-slash:before{content:"\f506"}.fa-user-tag:before{content:"\f507"}.fa-user-tie:before{content:"\f508"}.fa-user-times:before{content:"\f235"}.fa-users:before{content:"\f0c0"}.fa-users-cog:before{content:"\f509"}.fa-users-slash:before{content:"\e073"}.fa-usps:before{content:"\f7e1"}.fa-ussunnah:before{content:"\f407"}.fa-utensil-spoon:before{content:"\f2e5"}.fa-utensils:before{content:"\f2e7"}.fa-vaadin:before{content:"\f408"}.fa-vector-square:before{content:"\f5cb"}.fa-venus:before{content:"\f221"}.fa-venus-double:before{content:"\f226"}.fa-venus-mars:before{content:"\f228"}.fa-vest:before{content:"\e085"}.fa-vest-patches:before{content:"\e086"}.fa-viacoin:before{content:"\f237"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-vial:before{content:"\f492"}.fa-vials:before{content:"\f493"}.fa-viber:before{content:"\f409"}.fa-video:before{content:"\f03d"}.fa-video-slash:before{content:"\f4e2"}.fa-vihara:before{content:"\f6a7"}.fa-vimeo:before{content:"\f40a"}.fa-vimeo-square:before{content:"\f194"}.fa-vimeo-v:before{content:"\f27d"}.fa-vine:before{content:"\f1ca"}.fa-virus:before{content:"\e074"}.fa-virus-slash:before{content:"\e075"}.fa-viruses:before{content:"\e076"}.fa-vk:before{content:"\f189"}.fa-vnv:before{content:"\f40b"}.fa-voicemail:before{content:"\f897"}.fa-volleyball-ball:before{content:"\f45f"}.fa-volume-down:before{content:"\f027"}.fa-volume-mute:before{content:"\f6a9"}.fa-volume-off:before{content:"\f026"}.fa-volume-up:before{content:"\f028"}.fa-vote-yea:before{content:"\f772"}.fa-vr-cardboard:before{content:"\f729"}.fa-vuejs:before{content:"\f41f"}.fa-walking:before{content:"\f554"}.fa-wallet:before{content:"\f555"}.fa-warehouse:before{content:"\f494"}.fa-watchman-monitoring:before{content:"\e087"}.fa-water:before{content:"\f773"}.fa-wave-square:before{content:"\f83e"}.fa-waze:before{content:"\f83f"}.fa-weebly:before{content:"\f5cc"}.fa-weibo:before{content:"\f18a"}.fa-weight:before{content:"\f496"}.fa-weight-hanging:before{content:"\f5cd"}.fa-weixin:before{content:"\f1d7"}.fa-whatsapp:before{content:"\f232"}.fa-whatsapp-square:before{content:"\f40c"}.fa-wheelchair:before{content:"\f193"}.fa-whmcs:before{content:"\f40d"}.fa-wifi:before{content:"\f1eb"}.fa-wikipedia-w:before{content:"\f266"}.fa-wind:before{content:"\f72e"}.fa-window-close:before{content:"\f410"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-windows:before{content:"\f17a"}.fa-wine-bottle:before{content:"\f72f"}.fa-wine-glass:before{content:"\f4e3"}.fa-wine-glass-alt:before{content:"\f5ce"}.fa-wix:before{content:"\f5cf"}.fa-wizards-of-the-coast:before{content:"\f730"}.fa-wodu:before{content:"\e088"}.fa-wolf-pack-battalion:before{content:"\f514"}.fa-won-sign:before{content:"\f159"}.fa-wordpress:before{content:"\f19a"}.fa-wordpress-simple:before{content:"\f411"}.fa-wpbeginner:before{content:"\f297"}.fa-wpexplorer:before{content:"\f2de"}.fa-wpforms:before{content:"\f298"}.fa-wpressr:before{content:"\f3e4"}.fa-wrench:before{content:"\f0ad"}.fa-x-ray:before{content:"\f497"}.fa-xbox:before{content:"\f412"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-y-combinator:before{content:"\f23b"}.fa-yahoo:before{content:"\f19e"}.fa-yammer:before{content:"\f840"}.fa-yandex:before{content:"\f413"}.fa-yandex-international:before{content:"\f414"}.fa-yarn:before{content:"\f7e3"}.fa-yelp:before{content:"\f1e9"}.fa-yen-sign:before{content:"\f157"}.fa-yin-yang:before{content:"\f6ad"}.fa-yoast:before{content:"\f2b1"}.fa-youtube:before{content:"\f167"}.fa-youtube-square:before{content:"\f431"}.fa-zhihu:before{content:"\f63f"}.sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto} \ No newline at end of file diff --git a/skins/standard/global.css b/skins/standard/global.css index 1f11f784a8..4d484b0a35 100644 --- a/skins/standard/global.css +++ b/skins/standard/global.css @@ -2818,6 +2818,15 @@ pre.comment-text { vertical-align: bottom; } +/* OAuth2 */ +div.oauth2-login { + margin-bottom: 10px; +} + +#mini_login_top div.oauth2-login { + margin: 0; +} + /** * Print media */ diff --git a/skins/webfonts/fa-brands-400.eot b/skins/webfonts/fa-brands-400.eot new file mode 100644 index 0000000000..d05ea581fb Binary files /dev/null and b/skins/webfonts/fa-brands-400.eot differ diff --git a/skins/webfonts/fa-brands-400.woff2 b/skins/webfonts/fa-brands-400.woff2 new file mode 100644 index 0000000000..b8a8f656e1 Binary files /dev/null and b/skins/webfonts/fa-brands-400.woff2 differ diff --git a/skins/webfonts/fa-solid-900.eot b/skins/webfonts/fa-solid-900.eot new file mode 100644 index 0000000000..afe315244f Binary files /dev/null and b/skins/webfonts/fa-solid-900.eot differ diff --git a/skins/webfonts/fa-solid-900.woff2 b/skins/webfonts/fa-solid-900.woff2 new file mode 100644 index 0000000000..dc52d954d8 Binary files /dev/null and b/skins/webfonts/fa-solid-900.woff2 differ diff --git a/t/bmo/bounced-emails.t b/t/bmo/bounced-emails.t index b61e066a49..39420a8ced 100644 --- a/t/bmo/bounced-emails.t +++ b/t/bmo/bounced-emails.t @@ -8,7 +8,7 @@ use strict; use warnings; use 5.10.1; -use lib qw( . lib local/lib/perl5 ); +use lib qw( . lib qa/t/lib local/lib/perl5 ); BEGIN { $ENV{LOG4PERL_CONFIG_FILE} = 'log4perl-t.conf'; @@ -17,8 +17,8 @@ BEGIN { use Mojo::URL; use Mojo::UserAgent; -use Test2::V0; -use Test::Selenium::Remote::Driver; +use QA::Util; +use Test::More; my $ADMIN_LOGIN = $ENV{BZ_TEST_ADMIN} // 'admin@mozilla.bugs'; my $ADMIN_PW_OLD = $ENV{BZ_TEST_ADMIN_PASS} // 'Te6Oovohch'; @@ -27,8 +27,8 @@ my $SES_PASSWORD = $ENV{BMO_ses_password} // 'password123456789!'; my @require_env = qw( BZ_BASE_URL - BZ_TEST_NEWBIE - BZ_TEST_NEWBIE_PASS + BZ_TEST_BOUNCE_USER + BZ_TEST_BOUNCE_PASS TWD_HOST TWD_PORT ); @@ -36,12 +36,7 @@ my @require_env = qw( my @missing_env = grep { !exists $ENV{$_} } @require_env; BAIL_OUT("Missing env: @missing_env") if @missing_env; -my $sel = Test::Selenium::Remote::Driver->new( - base_url => $ENV{BZ_BASE_URL}, - browser => 'firefox', - version => '', - javascript => 1 -); +my ($sel, $config) = get_selenium(); my $ua = Mojo::UserAgent->new; $ua->on( @@ -61,21 +56,21 @@ ok($result->is_success, 'Posting first bounce was successful'); # Allow user to reset their email $sel->set_implicit_wait_timeout(600); -login_ok($sel, $ENV{BZ_TEST_NEWBIE}, $ENV{BZ_TEST_NEWBIE_PASS}); +$sel->login_ok($ENV{BZ_TEST_BOUNCE_USER}, $ENV{BZ_TEST_BOUNCE_PASS}); $sel->body_text_contains('Change notification emails have been disabled', 'Email disabled warning is displayed'); $sel->click_element_ok('//a[@id="bounced_emails_link"]'); sleep(2); $sel->title_is('Bounced Emails'); $sel->click_element_ok('//input[@id="enable_email"]'); -submit($sel, '//input[@value="Submit"]'); +$sel->submit('//input[@value="Submit"]'); sleep(2); $sel->title_is('Bugzilla Main Page'); $sel->body_text_lacks( 'Change notification emails have been disabled', 'Email disabled warning is no longer displayed' ); -logout_ok($sel); +$sel->logout_ok(); # Bounce 4 more times causing account to be locked $result = $ua->post($ses_url => $ses_data)->result; @@ -88,7 +83,7 @@ $result = $ua->post($ses_url => $ses_data)->result; ok($result->is_success, 'Posting fifth bounce was successful'); # User should not be able to login again -login($sel, $ENV{BZ_TEST_NEWBIE}, $ENV{BZ_TEST_NEWBIE_PASS}); +$sel->login($ENV{BZ_TEST_BOUNCE_USER}, $ENV{BZ_TEST_BOUNCE_PASS}); $sel->title_is('Account Disabled'); $sel->body_text_contains( 'Your Bugzilla account has been disabled due to issues delivering emails to your address.', @@ -97,47 +92,5 @@ $sel->body_text_contains( done_testing; -sub submit { - my ($sel, $xpath) = @_; - $sel->find_element($xpath, 'xpath')->click_ok('Submit OK'); -} - -sub click_and_type { - my ($sel, $name, $text) = @_; - - eval { - my $el - = $sel->find_element(qq{//*[\@id="bugzilla-body"]//input[\@name="$name"]}, - 'xpath'); - $el->click(); - $sel->send_keys_to_active_element($text); - pass("found $name and typed $text"); - }; - if ($@) { - fail("failed to find $name"); - } -} - -sub login { - my ($sel, $login, $password) = @_; - $sel->get_ok("/login"); - $sel->title_is("Log in to Bugzilla"); - click_and_type($sel, 'Bugzilla_login', $login); - click_and_type($sel, 'Bugzilla_password', $password); - submit($sel, '//input[@id="log_in"]'); -} - -sub login_ok { - my ($sel) = @_; - login(@_); - $sel->title_is('Bugzilla Main Page'); -} - -sub logout_ok { - my ($sel) = @_; - $sel->get_ok('/index.cgi?logout=1'); - $sel->title_is("Logged Out"); -} - __DATA__ -{"Type":"Notification","Message":"{\"eventType\":\"Bounce\",\"bounce\":{\"bounceType\":\"Permanent\",\"bounceSubType\":\"General\",\"bouncedRecipients\":[{\"emailAddress\":\"newbie@mozilla.example\",\"action\":\"failed\",\"status\":\"5.1.1\",\"diagnosticCode\":\"smtp;5505.1.1userunknown\"}],\"timestamp\":\"2017-08-05T00:41:02.669Z\",\"feedbackId\":\"01000157c44f053b-61b59c11-9236-11e6-8f96-7be8aexample-000000\",\"reportingMTA\":\"dsn;mta.example.com\"},\"mail\":{\"timestamp\":\"2017-08-05T00:40:02.012Z\",\"source\":\"BugzillaDaemon\",\"sourceArn\":\"arn:aws:ses:us-east-1:123456789012:identity/bugzilla@mozilla.bugs\",\"sendingAccountId\":\"123456789012\",\"messageId\":\"EXAMPLE7c191be45-e9aedb9a-02f9-4d12-a87d-dd0099a07f8a-000000\",\"destination\":[\"newbie@mozilla.example\"],\"headersTruncated\":false,\"headers\":[{\"name\":\"From\",\"value\":\"BugzillaDaemon\"},{\"name\":\"To\",\"value\":\"newbie@mozilla.example\"},{\"name\":\"Subject\",\"value\":\"MessagesentfromAmazonSES\"},{\"name\":\"MIME-Version\",\"value\":\"1.0\"},{\"name\":\"Content-Type\",\"value\":\"multipart/alternative;boundary=\"}],\"commonHeaders\":{\"from\":[\"BugzillaDaemon\"],\"to\":[\"newbie@mozilla.example\"],\"messageId\":\"EXAMPLE7c191be45-e9aedb9a-02f9-4d12-a87d-dd0099a07f8a-000000\",\"subject\":\"MessagesentfromAmazonSES\"},\"tags\":{\"ses:configuration-set\":[\"ConfigSet\"],\"ses:source-ip\":[\"192.0.2.0\"],\"ses:from-domain\":[\"example.com\"],\"ses:caller-identity\":[\"ses_user\"]}}}"} +{"Type":"Notification","Message":"{\"eventType\":\"Bounce\",\"bounce\":{\"bounceType\":\"Permanent\",\"bounceSubType\":\"General\",\"bouncedRecipients\":[{\"emailAddress\":\"bouncer@mozilla.example\",\"action\":\"failed\",\"status\":\"5.1.1\",\"diagnosticCode\":\"smtp;5505.1.1userunknown\"}],\"timestamp\":\"2017-08-05T00:41:02.669Z\",\"feedbackId\":\"01000157c44f053b-61b59c11-9236-11e6-8f96-7be8aexample-000000\",\"reportingMTA\":\"dsn;mta.example.com\"},\"mail\":{\"timestamp\":\"2017-08-05T00:40:02.012Z\",\"source\":\"BugzillaDaemon\",\"sourceArn\":\"arn:aws:ses:us-east-1:123456789012:identity/bugzilla@mozilla.bugs\",\"sendingAccountId\":\"123456789012\",\"messageId\":\"EXAMPLE7c191be45-e9aedb9a-02f9-4d12-a87d-dd0099a07f8a-000000\",\"destination\":[\"bouncer@mozilla.example\"],\"headersTruncated\":false,\"headers\":[{\"name\":\"From\",\"value\":\"BugzillaDaemon\"},{\"name\":\"To\",\"value\":\"bouncer@mozilla.example\"},{\"name\":\"Subject\",\"value\":\"MessagesentfromAmazonSES\"},{\"name\":\"MIME-Version\",\"value\":\"1.0\"},{\"name\":\"Content-Type\",\"value\":\"multipart/alternative;boundary=\"}],\"commonHeaders\":{\"from\":[\"BugzillaDaemon\"],\"to\":[\"bouncer@mozilla.example\"],\"messageId\":\"EXAMPLE7c191be45-e9aedb9a-02f9-4d12-a87d-dd0099a07f8a-000000\",\"subject\":\"MessagesentfromAmazonSES\"},\"tags\":{\"ses:configuration-set\":[\"ConfigSet\"],\"ses:source-ip\":[\"192.0.2.0\"],\"ses:from-domain\":[\"example.com\"],\"ses:caller-identity\":[\"ses_user\"]}}}"} diff --git a/t/bmo/oauth2-client.t b/t/bmo/oauth2-client.t new file mode 100644 index 0000000000..9eeb3f2e9e --- /dev/null +++ b/t/bmo/oauth2-client.t @@ -0,0 +1,57 @@ +#!/usr/bin/env perl +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. +use strict; +use warnings; +use 5.10.1; +use lib qw( . qa/t/lib local/lib/perl5 ); + +use Mojo::Base -strict; +use QA::Util; +use Test::More; + +BEGIN { + plan skip_all => "these tests only run in CI" + unless $ENV{CI} && $ENV{CIRCLE_JOB} eq 'test_bmo'; +} + +my ($sel, $config) = get_selenium(); + +$sel->set_implicit_wait_timeout(600); + +### Non-Mozilla normal user tests + +# Clicking the OAuth2 login button and then creating a new account automatically +$sel->get_ok('/login', undef, 'Go to the home page'); +$sel->title_is('Log in to Bugzilla', 'Log in to Bugzilla'); +$sel->is_element_present_ok( + '//div[@id="main-inner"]/div[@class="oauth2-login"]/a/button', + 'OAuth2 login button is present'); +$sel->click_ok('//div[@id="main-inner"]/div[@class="oauth2-login"]/a/button', + 'Click OAuth2 login button'); +$sel->click_ok('//a[contains(text(),"Connect")]', + 'Click OAuth2 provider login'); +$sel->title_is('Bugzilla Main Page', 'User is logged into Bugzilla'); +$sel->logout_ok(); + +# Trying to login using normal username and password should redirect automatically +$sel->login($ENV{BZ_TEST_OAUTH2_NORMAL_USER}, $ENV{BZ_TEST_OAUTH2_PASSWORD}); +$sel->click_ok('//a[contains(text(),"Connect")]', + 'Click OAuth2 provider login'); +$sel->title_is('Bugzilla Main Page', 'User is logged into Bugzilla'); +$sel->logout_ok(); + +### Mozilla user tests + +# Logging in with Mozilla.com account should automatically redirect to OAuth2 login +$sel->login($ENV{BZ_TEST_OAUTH2_MOZILLA_USER}, $ENV{BZ_TEST_OAUTH2_PASSWORD}); +$sel->click_ok('//a[contains(text(),"Connect")]', + 'Click OAuth2 provider login'); +$sel->title_is('Bugzilla Main Page', 'User is logged into Bugzilla'); +$sel->logout_ok(); + +done_testing; diff --git a/t/bmo/passwords.t b/t/bmo/passwords.t index 9e4deedc05..e4cbf9a55f 100644 --- a/t/bmo/passwords.t +++ b/t/bmo/passwords.t @@ -4,22 +4,24 @@ use strict; use warnings; use autodie; +use lib qw( . qa/t/lib local/lib/perl5 ); + use Mojo::Base -strict; +use QA::Util; use Test::More; -use Test::Selenium::Remote::Driver; BEGIN { plan skip_all => "these tests only run in CI" unless $ENV{CI} && $ENV{CIRCLE_JOB} eq 'test_bmo'; } -my $ADMIN_LOGIN = $ENV{BZ_TEST_ADMIN} // 'admin@mozilla.bugs'; -my $ADMIN_PW_OLD = $ENV{BZ_TEST_ADMIN_PASS} // 'Te6Oovohch'; +my $ADMIN_LOGIN = $ENV{BZ_TEST_ADMIN} // 'admin@mozilla.bugs'; +my $ADMIN_PW_OLD = $ENV{BZ_TEST_ADMIN_PASS} // 'Te6Oovohch'; my $ADMIN_PW_NEW = $ENV{BZ_TEST_ADMIN_NEWPASS} // 'she7Ka8t'; my @require_env = qw( BZ_BASE_URL - BZ_TEST_NEWBIE + BZ_TEST_NEWBIE_USER BZ_TEST_NEWBIE_PASS TWD_HOST TWD_PORT @@ -28,239 +30,120 @@ my @require_env = qw( my @missing_env = grep { !exists $ENV{$_} } @require_env; BAIL_OUT("Missing env: @missing_env") if @missing_env; -my $sel = Test::Selenium::Remote::Driver->new( - base_url => $ENV{BZ_BASE_URL}, - browser => 'firefox', - version => '', - javascript => 1 -); - -eval { - $sel->set_implicit_wait_timeout(600); - - login_ok($sel, $ADMIN_LOGIN, $ADMIN_PW_OLD); +my ($sel, $config) = get_selenium(); - change_password($sel, $ADMIN_PW_OLD . "x", "newpassword2", "newpassword2"); - $sel->title_is("Incorrect Old Password"); +$sel->set_implicit_wait_timeout(600); - change_password($sel, $ADMIN_PW_OLD, "password", "password"); - $sel->title_is("Password Fails Requirements"); +$sel->login_ok($ADMIN_LOGIN, $ADMIN_PW_OLD); - change_password($sel, $ADMIN_PW_OLD, $ADMIN_PW_NEW, $ADMIN_PW_NEW); - $sel->title_is("User Preferences"); - logout_ok($sel); +$sel->change_password($ADMIN_PW_OLD . "x", "newpassword2", "newpassword2"); +$sel->title_is("Incorrect Old Password"); - login_ok($sel, $ADMIN_LOGIN, $ADMIN_PW_NEW); +$sel->change_password($ADMIN_PW_OLD, "password", "password"); +$sel->title_is("Password Fails Requirements"); - # we don't protect against password re-use - change_password($sel, $ADMIN_PW_NEW, $ADMIN_PW_OLD, $ADMIN_PW_OLD); - $sel->title_is("User Preferences"); - logout_ok($sel); +$sel->change_password($ADMIN_PW_OLD, $ADMIN_PW_NEW, $ADMIN_PW_NEW); +$sel->title_is("User Preferences"); +$sel->logout_ok(); - login_ok($sel, $ENV{BZ_TEST_NEWBIE}, $ENV{BZ_TEST_NEWBIE_PASS}); +$sel->login_ok($ADMIN_LOGIN, $ADMIN_PW_NEW); - $sel->get_ok("/editusers.cgi"); - $sel->title_is("Authorization Required"); - logout_ok($sel); +# we don't protect against password re-use +$sel->change_password($ADMIN_PW_NEW, $ADMIN_PW_OLD, $ADMIN_PW_OLD); +$sel->title_is("User Preferences"); +$sel->logout_ok(); - login_ok($sel, $ADMIN_LOGIN, $ADMIN_PW_OLD); +$sel->login_ok($ENV{BZ_TEST_NEWBIE_USER}, $ENV{BZ_TEST_NEWBIE_PASS}); - toggle_require_password_change($sel, $ENV{BZ_TEST_NEWBIE}); - logout_ok($sel); +$sel->get_ok("/editusers.cgi"); +$sel->title_is("Authorization Required"); +$sel->logout_ok(); - login($sel, $ENV{BZ_TEST_NEWBIE}, $ENV{BZ_TEST_NEWBIE_PASS}); - $sel->title_is('Password change required'); - click_and_type($sel, "old_password", $ENV{BZ_TEST_NEWBIE_PASS}); - click_and_type($sel, "new_password1", "password"); - click_and_type($sel, "new_password2", "password"); - submit($sel, '//input[@id="submit"]'); - $sel->title_is('Password Fails Requirements'); +$sel->login_ok($ADMIN_LOGIN, $ADMIN_PW_OLD); - $sel->go_back_ok(); - $sel->title_is('Password change required'); - click_and_type($sel, "old_password", $ENV{BZ_TEST_NEWBIE_PASS}); - click_and_type($sel, "new_password1", "!!" . $ENV{BZ_TEST_NEWBIE_PASS}); - click_and_type($sel, "new_password2", "!!" . $ENV{BZ_TEST_NEWBIE_PASS}); - submit($sel, '//input[@id="submit"]'); - $sel->title_is('Password Changed'); - change_password( - $sel, - "!!" . $ENV{BZ_TEST_NEWBIE_PASS}, - $ENV{BZ_TEST_NEWBIE_PASS}, - $ENV{BZ_TEST_NEWBIE_PASS} - ); - $sel->title_is("User Preferences"); +$sel->toggle_require_password_change($ENV{BZ_TEST_NEWBIE_USER}); +$sel->logout_ok(); - $sel->get_ok("/userprefs.cgi?tab=account"); - $sel->title_is("User Preferences"); - click_link($sel, "I forgot my password"); - $sel->body_text_contains( - [ - "A token for changing your password has been emailed to you.", - "Follow the instructions in that email to change your password." - ], - ); - my $token = get_token(); - ok($token, "got a token from resetting password"); - $sel->get_ok("/token.cgi?t=$token&a=cfmpw"); - $sel->title_is('Change Password'); - click_and_type($sel, "password", "nopandas"); - click_and_type($sel, "matchpassword", "nopandas"); - submit($sel, '//input[@id="update"]'); - $sel->title_is('Password Fails Requirements'); - $sel->go_back_ok(); - $sel->title_is('Change Password'); - click_and_type($sel, "password", '??' . $ENV{BZ_TEST_NEWBIE_PASS}); - click_and_type($sel, "matchpassword", '??' . $ENV{BZ_TEST_NEWBIE_PASS}); - submit($sel, '//input[@id="update"]'); - $sel->title_is('Password Changed'); - $sel->get_ok("/token.cgi?t=$token&a=cfmpw"); - $sel->title_is('Token Does Not Exist'); - $sel->get_ok("/login"); - $sel->title_is('Log in to Bugzilla'); - login_ok($sel, $ENV{BZ_TEST_NEWBIE}, "??" . $ENV{BZ_TEST_NEWBIE_PASS}); - change_password( - $sel, - "??" . $ENV{BZ_TEST_NEWBIE_PASS}, - $ENV{BZ_TEST_NEWBIE_PASS}, - $ENV{BZ_TEST_NEWBIE_PASS} - ); - $sel->title_is("User Preferences"); +$sel->login($ENV{BZ_TEST_NEWBIE_USER}, $ENV{BZ_TEST_NEWBIE_PASS}); +$sel->title_is('Password change required'); +$sel->click_and_type("old_password", $ENV{BZ_TEST_NEWBIE_PASS}); +$sel->click_and_type("new_password1", "password"); +$sel->click_and_type("new_password2", "password"); +$sel->click_ok('//input[@id="submit"]'); +$sel->title_is('Password Fails Requirements'); - logout_ok($sel); - open my $fh, '>', '/app/data/mailer.testfile'; - close $fh; - - $sel->get('/createaccount.cgi'); - $sel->title_is('Create a new Bugzilla account'); - click_and_type($sel, 'login', $ENV{BZ_TEST_NEWBIE2}); - $sel->find_element('//input[@id="etiquette"]', 'xpath')->click(); - submit($sel, '//input[@value="Create Account"]'); - $sel->title_is( - "Request for new user account '$ENV{BZ_TEST_NEWBIE2}' submitted"); - my ($create_token) - = search_mailer_testfile(qr{/token\.cgi\?t=([^&]+)&a=request_new_account}xs); - $sel->get("/token.cgi?t=$create_token&a=request_new_account"); - click_and_type($sel, 'passwd1', $ENV{BZ_TEST_NEWBIE2_PASS}); - click_and_type($sel, 'passwd2', $ENV{BZ_TEST_NEWBIE2_PASS}); - submit($sel, '//input[@value="Create"]'); +$sel->go_back_ok(); +$sel->title_is('Password change required'); +$sel->click_and_type("old_password", $ENV{BZ_TEST_NEWBIE_PASS}); +$sel->click_and_type("new_password1", "!!" . $ENV{BZ_TEST_NEWBIE_PASS}); +$sel->click_and_type("new_password2", "!!" . $ENV{BZ_TEST_NEWBIE_PASS}); +$sel->click_ok('//input[@id="submit"]'); +$sel->title_is('Password Changed'); +$sel->change_password( + "!!" . $ENV{BZ_TEST_NEWBIE_PASS}, + $ENV{BZ_TEST_NEWBIE_PASS}, + $ENV{BZ_TEST_NEWBIE_PASS} +); +$sel->title_is("User Preferences"); + +$sel->get_ok("/userprefs.cgi?tab=account"); +$sel->title_is("User Preferences"); +$sel->click_link("I forgot my password"); +$sel->body_text_contains( + [ + "A token for changing your password has been emailed to you.", + "Follow the instructions in that email to change your password." + ], +); +my $token = $sel->get_token(); +ok($token, "got a token from resetting password"); +$sel->get_ok("/token.cgi?t=$token&a=cfmpw"); +$sel->title_is('Change Password'); +$sel->click_and_type("password", "nopandas"); +$sel->click_and_type("matchpassword", "nopandas"); +$sel->click_ok('//input[@id="update"]'); +$sel->title_is('Password Fails Requirements'); +$sel->go_back_ok(); +$sel->title_is('Change Password'); +$sel->click_and_type("password", '??' . $ENV{BZ_TEST_NEWBIE_PASS}); +$sel->click_and_type("matchpassword", '??' . $ENV{BZ_TEST_NEWBIE_PASS}); +$sel->click_ok('//input[@id="update"]'); +$sel->title_is('Password Changed'); +$sel->get_ok("/token.cgi?t=$token&a=cfmpw"); +$sel->title_is('Token Does Not Exist'); +$sel->get_ok("/login"); +$sel->title_is('Log in to Bugzilla'); +$sel->login_ok($ENV{BZ_TEST_NEWBIE_USER}, "??" . $ENV{BZ_TEST_NEWBIE_PASS}); +$sel->change_password( + "??" . $ENV{BZ_TEST_NEWBIE_PASS}, + $ENV{BZ_TEST_NEWBIE_PASS}, + $ENV{BZ_TEST_NEWBIE_PASS} +); +$sel->title_is("User Preferences"); + +$sel->logout_ok(); +open my $fh, '>', '/app/data/mailer.testfile'; +close $fh; + +$sel->get_ok('/createaccount.cgi'); +$sel->title_is('Create a new Bugzilla account'); +$sel->click_and_type('login', $ENV{BZ_TEST_NEWBIE2_USER}); +$sel->find_element('//input[@id="etiquette"]', 'xpath')->click(); +$sel->click_ok('//input[@value="Create Account"]'); +$sel->title_is( + "Request for new user account '$ENV{BZ_TEST_NEWBIE2_USER}' submitted"); +my ($create_token) + = $sel->search_mailer_testfile( + qr{/token\.cgi\?t=([^&]+)&a=request_new_account}xs); +$sel->get_ok("/token.cgi?t=$create_token&a=request_new_account"); +$sel->click_and_type('passwd1', $ENV{BZ_TEST_NEWBIE2_PASS}); +$sel->click_and_type('passwd2', $ENV{BZ_TEST_NEWBIE2_PASS}); +$sel->click_ok('//input[@value="Create"]'); + +$sel->title_is('Bugzilla Main Page'); +$sel->body_text_contains([ + "The user account $ENV{BZ_TEST_NEWBIE2_USER} has been created", "successfully" +]); - $sel->title_is('Bugzilla Main Page'); - $sel->body_text_contains([ - "The user account $ENV{BZ_TEST_NEWBIE2} has been created", "successfully" - ]); -}; -if ($@) { - fail("got exception $@"); -} done_testing(); -sub submit { - my ($sel, $xpath) = @_; - $sel->find_element($xpath, 'xpath')->click_ok('Submit OK'); -} - -sub get_token { - my $token; - my $count = 0; - do { - sleep 1 if $count++; - open my $fh, '<', '/app/data/mailer.testfile'; - my $content = do { - local $/ = undef; - <$fh>; - }; - ($token) = $content =~ m!/token\.cgi\?t=3D([^&]+)&a=3Dcfmpw!s; - close $fh; - } until $token || $count > 60; - return $token; -} - -sub search_mailer_testfile { - my ($regexp) = @_; - my $content = ""; - my @result; - my $count = 0; - do { - sleep 1 if $count++; - open my $fh, '<', '/app/data/mailer.testfile'; - $content .= do { - local $/ = undef; - <$fh>; - }; - close $fh; - my $decoded = $content; - $decoded =~ s/\r\n/\n/gs; - $decoded =~ s/=\n//gs; - $decoded =~ s/=([[:xdigit:]]{2})/chr(hex($1))/ges; - @result = $decoded =~ $regexp; - } until @result || $count > 60; - return @result; -} - -sub click_and_type { - my ($sel, $name, $text) = @_; - - eval { - my $el - = $sel->find_element(qq{//*[\@id="bugzilla-body"]//input[\@name="$name"]}, - 'xpath'); - $el->click(); - $sel->send_keys_to_active_element($text); - pass("found $name and typed $text"); - }; - if ($@) { - fail("failed to find $name"); - } -} - -sub click_link { - my ($sel, $text) = @_; - my $el = $sel->find_element($text, 'link_text'); - $el->click(); -} - -sub change_password { - my ($sel, $old, $new1, $new2) = @_; - $sel->get_ok("/userprefs.cgi?tab=account"); - $sel->title_is("User Preferences"); - click_and_type($sel, "old_password", $old); - click_and_type($sel, "new_password1", $new1); - click_and_type($sel, "new_password2", $new2); - submit($sel, '//input[@value="Submit Changes"]'); -} - -sub toggle_require_password_change { - my ($sel, $login) = @_; - $sel->get_ok("/editusers.cgi"); - $sel->title_is("Search users"); - click_and_type($sel, 'matchstr', $login); - submit($sel, '//input[@id="search"]'); - $sel->title_is("Select user"); - click_link($sel, $login); - $sel->find_element('//input[@id="password_change_required"]')->click; - submit($sel, '//input[@id="update"]'); - $sel->title_is("User $login updated"); -} - -sub login { - my ($sel, $login, $password) = @_; - - $sel->get_ok("/login"); - $sel->title_is("Log in to Bugzilla"); - click_and_type($sel, 'Bugzilla_login', $login); - click_and_type($sel, 'Bugzilla_password', $password); - submit($sel, '//input[@id="log_in"]'); -} - -sub login_ok { - my ($sel) = @_; - login(@_); - $sel->title_is('Bugzilla Main Page'); -} - -sub logout_ok { - my ($sel) = @_; - $sel->get_ok('/index.cgi?logout=1'); - $sel->title_is("Logged Out"); -} diff --git a/t/mojo-oauth2.t b/t/mojo-oauth2-provider.t similarity index 100% rename from t/mojo-oauth2.t rename to t/mojo-oauth2-provider.t diff --git a/template/en/default/account/auth/login-small.html.tmpl b/template/en/default/account/auth/login-small.html.tmpl index a860d071c1..5f4d24a663 100644 --- a/template/en/default/account/auth/login-small.html.tmpl +++ b/template/en/default/account/auth/login-small.html.tmpl @@ -40,6 +40,13 @@ class='show_mini_login_form' data-qs-suffix="[% qs_suffix FILTER html %]">Log In +[% IF Param('oauth2_client_enabled') %] + [% INCLUDE account/auth/oauth2_login_button.html.tmpl + target => target + %] +[% END %] + [% Hook.process('additional_methods') %] [%# Allow the user to create a new account, or request a token to change diff --git a/template/en/default/account/auth/oauth2_login_button.html.tmpl b/template/en/default/account/auth/oauth2_login_button.html.tmpl new file mode 100644 index 0000000000..c33f571a08 --- /dev/null +++ b/template/en/default/account/auth/oauth2_login_button.html.tmpl @@ -0,0 +1,19 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] +[% + redirect_uri = c.oauth2.redirect_uri(target); + authorize_url = c.oauth2.auth_url('oauth2', + {state => issue_hash_token(['oauth2']), redirect_uri => redirect_uri }); +%] + diff --git a/template/en/default/account/email/confirm.html.tmpl b/template/en/default/account/email/confirm.html.tmpl index 4c119d3b0c..c9a8571e37 100644 --- a/template/en/default/account/email/confirm.html.tmpl +++ b/template/en/default/account/email/confirm.html.tmpl @@ -44,4 +44,6 @@ +[% Hook.process('end') %] + [% PROCESS global/footer.html.tmpl %] diff --git a/template/en/default/admin/admin.html.tmpl b/template/en/default/admin/admin.html.tmpl index 57eab09b87..aa2f2d0f92 100644 --- a/template/en/default/admin/admin.html.tmpl +++ b/template/en/default/admin/admin.html.tmpl @@ -145,8 +145,8 @@ [% END %] [% class = user.in_group('admin') ? "" : "forbidden" %] -
OAuth2 Clients
-
Add, modify or remove OAuth2 clients.
+
OAuth2 Provider Clients
+
Add, modify or remove OAuth2 provider clients.
[% Hook.process('end_links_right') %] diff --git a/template/en/default/admin/oauth/confirm-delete.html.tmpl b/template/en/default/admin/oauth/provider/confirm-delete.html.tmpl similarity index 97% rename from template/en/default/admin/oauth/confirm-delete.html.tmpl rename to template/en/default/admin/oauth/provider/confirm-delete.html.tmpl index afc6f8dfbe..207edf8a14 100644 --- a/template/en/default/admin/oauth/confirm-delete.html.tmpl +++ b/template/en/default/admin/oauth/provider/confirm-delete.html.tmpl @@ -21,7 +21,7 @@

Do you really want to delete this client?

-

+ diff --git a/template/en/default/admin/oauth/create.html.tmpl b/template/en/default/admin/oauth/provider/create.html.tmpl similarity index 98% rename from template/en/default/admin/oauth/create.html.tmpl rename to template/en/default/admin/oauth/provider/create.html.tmpl index 147827a046..667130d8ee 100644 --- a/template/en/default/admin/oauth/create.html.tmpl +++ b/template/en/default/admin/oauth/provider/create.html.tmpl @@ -3,7 +3,7 @@ onload = "document.forms['f'].client_id.focus()" %] - + diff --git a/template/en/default/admin/oauth/edit.html.tmpl b/template/en/default/admin/oauth/provider/edit.html.tmpl similarity index 98% rename from template/en/default/admin/oauth/edit.html.tmpl rename to template/en/default/admin/oauth/provider/edit.html.tmpl index 899d63882f..07501ec12a 100644 --- a/template/en/default/admin/oauth/edit.html.tmpl +++ b/template/en/default/admin/oauth/provider/edit.html.tmpl @@ -3,7 +3,7 @@ onload = "document.forms['f'].client_id.select()" %] - +
diff --git a/template/en/default/admin/oauth/list.html.tmpl b/template/en/default/admin/oauth/provider/list.html.tmpl similarity index 78% rename from template/en/default/admin/oauth/list.html.tmpl rename to template/en/default/admin/oauth/provider/list.html.tmpl index 35b1c416b8..af083255cb 100644 --- a/template/en/default/admin/oauth/list.html.tmpl +++ b/template/en/default/admin/oauth/provider/list.html.tmpl @@ -6,7 +6,7 @@ { name => "description" heading => "Edit client..." - contentlink => "admin/oauth/edit?id=%%id%%" + contentlink => "admin/oauth/provider/edit?id=%%id%%" }, { name => "active" @@ -17,7 +17,7 @@ name => "action" heading => "Action" content => "Delete" - contentlink => "admin/oauth/delete?id=%%id%%" + contentlink => "admin/oauth/provider/delete?id=%%id%%" } ] %] @@ -30,6 +30,6 @@ overrides = overrides %] -Add a client. +Add a client. [% PROCESS global/footer.html.tmpl %] diff --git a/template/en/default/admin/params/oauth2client.html.tmpl b/template/en/default/admin/params/oauth2client.html.tmpl new file mode 100644 index 0000000000..9608420fff --- /dev/null +++ b/template/en/default/admin/params/oauth2client.html.tmpl @@ -0,0 +1,25 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[% + title = "OAuth2 Client" + desc = "Configure as an OAuth2 Client for Authentication" +%] + +[% + param_descs = { + oauth2_client_enabled => "OAuth2 Client Enabled", + oauth2_client_domain => "OAuth2 Client Domain", + oauth2_client_id => "OAuth2 Client ID", + oauth2_client_secret => "Oauth2 Client Secret" + oauth2_client_token_url => "OAuth2 Client Access Token URL", + oauth2_client_authorize_url => "OAuth2 Client Authorize URL", + oauth2_client_userinfo_url => "OAuth2 Client User Information URL", + oauth2_client_scopes => "OAuth2 Client Scopes Requested (space separated)", + } +%] diff --git a/template/en/default/global/header.html.tmpl b/template/en/default/global/header.html.tmpl index 7747dab91b..6358f197f6 100644 --- a/template/en/default/global/header.html.tmpl +++ b/template/en/default/global/header.html.tmpl @@ -220,6 +220,11 @@ href="[% atomlink FILTER html %]"> [% END %] + [%# Required for login button icons %] + + + + [%# Required for the 'Auto-discovery' feature in Firefox 2 and IE 7. %] diff --git a/template/en/default/global/user-error.html.tmpl b/template/en/default/global/user-error.html.tmpl index 6127063d28..277be778ac 100644 --- a/template/en/default/global/user-error.html.tmpl +++ b/template/en/default/global/user-error.html.tmpl @@ -305,6 +305,11 @@ The token is not valid. It could be because you loaded this page more than [%= constants.MAX_TOKEN_AGE FILTER html %] days ago. + [% ELSIF error == "oauth2_userinfo_error" %] + [% title = 'Error Occurred Logging In' %] + An error occurred completing the login process using the single signon provider. + Contact an administrator explaining the problem. + [% ELSIF error == "attachment_deletion_disabled" %] [% title = "Attachment Deletion Disabled" %] Attachment deletion is disabled on this installation. diff --git a/token.cgi b/token.cgi index 9ce010aa65..bfda03b2fa 100755 --- a/token.cgi +++ b/token.cgi @@ -301,12 +301,12 @@ sub changeEmail { # Update the user's login name in the profiles table and delete the token # from the tokens table. $dbh->bz_start_transaction(); - $dbh->do( - q{UPDATE profiles - SET login_name = ? - WHERE userid = ?}, undef, ($new_email, $userid) - ); + + my $user = Bugzilla::User->new({name => $old_email}); + $user->set_login($new_email); + $user->update({keep_session => 1}); Bugzilla->memcached->clear({table => 'profiles', id => $userid}); + $dbh->do('DELETE FROM tokens WHERE token = ?', undef, $token); $dbh->do( q{DELETE FROM tokens WHERE userid = ? @@ -314,7 +314,6 @@ sub changeEmail { ); # The email address has been changed, so we need to rederive the groups - my $user = new Bugzilla::User($userid); $user->derive_regexp_groups; $dbh->bz_commit_transaction();