package OpenID::Lite::RelyingParty::Discover::Parser::XRI;
use Any::Moose;
with 'OpenID::Lite::Role::Parser';
with 'OpenID::Lite::Role::ErrorHandler';
use OpenID::Lite::Util::XRI;
use OpenID::Lite::RelyingParty::Discover::Service::Builder;
sub parse {
my ( $self, $result ) = @_;
my $identifier = $result->normalized_identifier;
my $doc = $result->xrds;
my @xrd
= $doc->findnodes(q{*[local-name()='XRDS']/*[local-name()='XRD']});
return $self->ERROR( sprintf q{XRD element not found for iname "%s".},
$identifier )
unless @xrd > 0;
@xrd = reverse @xrd;
my $last_xrd = shift @xrd;
my $canonical_id = $self->_get_canonical_id($last_xrd)
or return $self->ERROR( sprintf q{No CanonicalID found for XRI "%s".},
$identifier );
$self->_validate_canonical_id( \@xrd, $canonical_id, $identifier )
or return $self->ERROR( sprintf q{Invalid XRDS for XRI "%s".},
$identifier );
my $builder = OpenID::Lite::RelyingParty::Discover::Service::Builder->new(
claimed_identifier => $canonical_id, );
my $services = $builder->build_services($last_xrd);
$_->display_identifier($identifier) for @$services;
return $self->ERROR(q{No service found.}) unless @$services > 0;
return $services;
}
sub _validate_canonical_id {
my ( $self, $xrd_list, $canonical_id, $iname ) = @_;
my $child_id = lc $canonical_id;
for my $xrd ( @$xrd_list ) {
my $parent_sought = substr($child_id, rindex($child_id, '!'));
my @cids = $xrd->findnodes(q{*[local-name()='CanonicalID']});
return 0 unless @cids > 0;
my $cid = $cids[0];
my $parent
= OpenID::Lite::Util::XRI->make_xri( $cid->findvalue(q{text()}) );
return 0 unless $parent;
return 0 if ($parent_sought ne lc $parent);
$child_id = $parent_sought;
}
my $root = OpenID::Lite::Util::XRI->root_authority($iname);
return 0 unless
OpenID::Lite::Util::XRI->provider_is_authoritative($root, $child_id);
1;
}
sub _get_canonical_id {
my ( $self, $xrd ) = @_;
my @cids = $xrd->findnodes(q{*[local-name()='CanonicalID']});
return unless @cids > 0;
my $cid = $cids[0];
my $canonical_id
= OpenID::Lite::Util::XRI->make_xri( $cid->findvalue(q{text()}) );
return $canonical_id;
}
no Any::Moose;
__PACKAGE__->meta->make_immutable;
1;