package XML::FOAF::Utils; ############################################################################## use strict; use vars qw($VERSION $MAX_DEPTH); use XML::FOAF; $MAX_DEPTH = 7; $VERSION = 0.1; my $Digest; BEGIN { $Digest = 'Digest::SHA'; eval q| require Digest::SHA |; if($@ and $@ =~ /Can't locate/){ require Digest::SHA::PurePerl; $Digest = 'Digest::SHA::PurePerl'; } } BEGIN { *{XML::FOAF::Person::seeAlso} = sub { $_[0]->get("http://www.w3.org/2000/01/rdf-schema#seeAlso"); } unless(XML::FOAF::Person->can('seeAlso')); } ############################################################################## sub new { my $class = shift; my %opt = @_; my $self = {}; bless $self,$class; $self->{_digest} = $Digest->new(1); $self->depth(0); $self->max_depth( defined $opt{MAX_DEPTH} ? $opt{MAX_DEPTH} : $MAX_DEPTH || 0 ); $self; } sub max_depth { $_[0]->{_max_depth} = $_[1] if(@_ > 1); $_[0]->{_max_depth}; } sub depth { $_[0]->{_depth} = $_[1] if(@_ > 1); $_[0]->{_depth}; } sub traverse { my $self = shift; my $code = shift; my @foafs = @_; my $max = $self->max_depth; my $depth = $self->depth; for my $foaf (@foafs){ my $p = $foaf->person; $code->($self,$p) if($p); $self->_traverse($code,$foaf); } $self; } sub _traverse { my $self = shift; my $code = shift; my $foaf = shift; my $max = $self->max_depth; my $depth = $self->depth; $self->depth(++$depth); if($depth > $max){ $self->depth($depth - 1); return; } for my $p ( @{$foaf->person->knows} ){ $code->($self,$p) or next; if(my $ref = $p->seeAlso){ my $foaf = XML::FOAF->new( URI->new($ref) ); $self->_traverse($code,$foaf) if($foaf); } } $self->depth($depth - 1); } sub finger { my $self = shift; my $mbox = shift || return; my @foafs = @_; my $searched = {}; my $sha1sum; my $found; if($mbox !~ /^mailto:/ and $mbox =~ /@/){ $mbox = 'mailto:' . $mbox; $sha1sum = $self->{_digest}->add($mbox)->hexdigest; } else{ $sha1sum = $mbox; $mbox = ''; } $self->traverse(sub { return 0 if($found); my $utils = shift; my $person = shift; my $_mbox = $person->mbox || ''; my $_sha1sum = $person->mbox_sha1sum || ''; my $seeAlso = $person->seeAlso; $searched->{$seeAlso}++ if($seeAlso); return 0 if($searched->{$seeAlso} and $searched->{$seeAlso} > 1); if($sha1sum eq $_sha1sum){ $found = $person; } elsif($mbox and $_mbox eq $mbox){ $found = $person; } ! $found; },@foafs); $found; } 1;