⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 client.pm

📁 网页留言本,比一般的留言簿管用
💻 PM
字号:
# $Id: Client.pm 4536 2004-05-11 05:33:05Z btrott $package XML::Atom::Client;use strict;use XML::Atom;use base qw( XML::Atom::ErrorHandler );use LWP::UserAgent;use XML::Atom::Entry;use XML::Atom::Feed;use XML::Atom::Util qw( first textValue );use Digest::SHA1 qw( sha1 );use MIME::Base64 qw( encode_base64 );use DateTime;use constant NS_ATOM => 'http://purl.org/atom/ns#';use constant NS_SOAP => 'http://schemas.xmlsoap.org/soap/envelope/';sub new {    my $class = shift;    my $client = bless { }, $class;    $client->init(@_) or return $class->error($client->errstr);    $client;}sub init {    my $client = shift;    my %param = @_;    $client->{ua} = LWP::UserAgent::AtomClient->new($client);    $client->{ua}->agent('XML::Atom/' . XML::Atom->VERSION);    $client;}sub username {    my $client = shift;    $client->{username} = shift if @_;    $client->{username};}sub password {    my $client = shift;    $client->{password} = shift if @_;    $client->{password};}sub use_soap {    my $client = shift;    $client->{use_soap} = shift if @_;    $client->{use_soap};}sub auth_digest {    my $client = shift;    $client->{auth_digest} = shift if @_;    $client->{auth_digest};}sub getEntry {    my $client = shift;    my($url) = @_;    my $req = HTTP::Request->new(GET => $url);    my $res = $client->make_request($req);    return $client->error("Error on GET $url: " . $res->status_line)        unless $res->code == 200;    XML::Atom::Entry->new(Stream => \$res->content);}sub createEntry {    my $client = shift;    my($uri, $entry) = @_;    return $client->error("Must pass a PostURI before posting")        unless $uri;    my $req = HTTP::Request->new(POST => $uri);    $req->content_type('application/x.atom+xml');    my $xml = $entry->as_xml;    $req->content_length(length $xml);    $req->content($xml);    my $res = $client->make_request($req);    return $client->error("Error on POST $uri: " . $res->status_line)        unless $res->code == 201;    $res->header('Location') || 1;}sub updateEntry {    my $client = shift;    my($url, $entry) = @_;    my $req = HTTP::Request->new(PUT => $url);    $req->content_type('application/x.atom+xml');    my $xml = $entry->as_xml;    $req->content_length(length $xml);    $req->content($xml);    my $res = $client->make_request($req);    return $client->error("Error on PUT $url: " . $res->status_line)        unless $res->code == 200;    1;}sub deleteEntry {    my $client = shift;    my($url) = @_;    my $req = HTTP::Request->new(DELETE => $url);    my $res = $client->make_request($req);    return $client->error("Error on DELETE $url: " . $res->status_line)        unless $res->code == 200;    1;}sub getFeed {    my $client = shift;    my($uri) = @_;    return $client->error("Must pass a FeedURI before retrieving feed")        unless $uri;    my $req = HTTP::Request->new(GET => $uri);    my $res = $client->make_request($req);    return $client->error("Error on GET $uri: " . $res->status_line)        unless $res->code == 200;    my $feed = XML::Atom::Feed->new(Stream => \$res->content)        or return $client->error(XML::Atom::Feed->errstr);    $feed;}sub make_request {    my $client = shift;    my($req) = @_;    $client->munge_request($req);    my $res = $client->{ua}->request($req);    $client->munge_response($res);    $res;}sub munge_request {    my $client = shift;    my($req) = @_;    $req->header(        Accept => 'application/x.atom+xml, application/xml, text/xml, */*',    );    my $nonce = $client->make_nonce;    my $nonce_enc = encode_base64($nonce, '');    my $now = DateTime->now->iso8601 . 'Z';    my $digest = encode_base64(sha1($nonce . $now . ($client->password || '')), '');    if ($client->use_soap) {        my $xml = $req->content || '';        $xml =~ s!^(<\?xml.*?\?>)!!;        my $method = $req->method;        $xml = ($1 || '') . <<SOAP;<soap:Envelope  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"  xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/07/utility"  xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/07/secext">  <soap:Header>    <wsse:Security>      <wsse:UsernameToken>        <wsse:Username>@{[ $client->username || '' ]}</wsse:Username>        <wsse:Password Type="wsse:PasswordDigest">$digest</wsse:Password>        <wsse:Nonce>$nonce_enc</wsse:Nonce>        <wsu:Created>$now</wsu:Created>      </wsse:UsernameToken>    </wsse:Security>  </soap:Header>  <soap:Body>    <$method xmlns="http://schemas.xmlsoap.org/wsdl/http/">$xml    </$method>  </soap:Body></soap:Envelope>SOAP        $req->content($xml);        $req->content_length(length $xml);        $req->header('SOAPAction', 'http://schemas.xmlsoap.org/wsdl/http/' . $method);        $req->method('POST');        $req->content_type('text/xml');    } else {        $req->header('X-WSSE', sprintf          qq(UsernameToken Username="%s", PasswordDigest="%s", Nonce="%s", Created="%s"),          $client->username || '', $digest, $nonce_enc, $now);        $req->header('Authorization', 'WSSE profile="UsernameToken"');    }}sub munge_response {    my $client = shift;    my($res) = @_;    if ($client->use_soap && (my $xml = $res->content)) {        my $doc;        if (LIBXML) {            my $parser = XML::LibXML->new;            $doc = $parser->parse_string($xml);        } else {            my $xp = XML::XPath->new(xml => $xml);            $doc = ($xp->find('/')->get_nodelist)[0];        }        my $body = first($doc, NS_SOAP, 'Body');        if (my $fault = first($body, NS_SOAP, 'Fault')) {            $res->code(textValue($fault, undef, 'faultcode'));            $res->message(textValue($fault, undef, 'faultstring'));            $res->content('');            $res->content_length(0);        } else {            $xml = join '', map $_->toString(LIBXML ? 1 : 0),                LIBXML ? $body->childNodes : $body->getChildNodes;            $res->content($xml);            $res->content_length(1);        }    }}sub make_nonce { sha1(sha1(time() . {} . rand() . $$)) }package LWP::UserAgent::AtomClient;use strict;use base qw( LWP::UserAgent );my %ClientOf;sub new {    my($class, $client) = @_;    my $ua = $class->SUPER::new;    $ClientOf{$ua} = $client;    $ua;}sub get_basic_credentials {    my($ua, $realm, $url, $proxy) = @_;    my $client = $ClientOf{$ua} or die "Cannot find $ua";    return $client->username, $client->password;}sub DESTROY {    my $self = shift;    delete $ClientOf{$self};}package LWP::Authen::Wsse;use strict;use MIME::Base64;use Digest::SHA1;use DateTime;sub authenticate {    my($class, $ua, $proxy, $auth_param, $res, $req, $arg, $size) = @_;    my($user, $pass) = $ua->get_basic_credentials($auth_param->{realm},        $req->url, $proxy);    return $res unless defined $user && defined $pass;    my $nonce = XML::Atom::Client->make_nonce;    my $nonce_enc = MIME::Base64::encode_base64($nonce, '');    my $now = DateTime->now->iso8601 . 'Z';    my $digest = MIME::Base64::encode_base64(        Digest::SHA1::sha1($nonce . $now . ($pass || '')), ''    );    my $auth_header = $proxy ? "Proxy-Authorization" : "Authorization";    my $wsse_value = sprintf        qq(UsernameToken Username="%s", PasswordDigest="%s", Nonce="%s", Created="%s"),        $user || '', $digest, $nonce_enc, $now;    # Need to check this isn't a repeated fail!    my $r = $res;    while ($r) {        my $wsse = $r->request->header('X-WSSE');        if ($wsse && $wsse eq $wsse_value) {            # here we know this failed before            $res->header("Client-Warning" =>                "Credentials for '$user' failed before");            return $res;        }        $r = $r->previous;    }    my $referral = $req->clone;    $referral->header($auth_header, 'WSSE profile="UsernameToken"');    $referral->header('X-WSSE' => $wsse_value);    return $ua->request($referral, $arg, $size, $res);}1;__END__=head1 NAMEXML::Atom::Client - A client for the Atom API=head1 SYNOPSIS    use XML::Atom::Client;    use XML::Atom::Entry;    my $api = XML::Atom::Client->new;    $api->username('Melody');    $api->password('Nelson');    my $entry = XML::Atom::Entry->new;    $entry->title('New Post');    $entry->content('Content of my post.');    my $EditURI = $api->createEntry($PostURI, $entry);    my $feed = $api->getFeed($FeedURI);    my @entries = $feed->entries;    my $entry = $api->getEntry($EditURI);=head1 DESCRIPTIONI<XML::Atom::Client> implements a client for the Atom API described atI<http://bitworking.org/projects/atom/draft-gregorio-09.html>, with theauthentication scheme described atI<http://www.intertwingly.net/wiki/pie/DifferentlyAbledClients>.B<NOTE:> the API, and particularly the authentication scheme, are stillin flux.=head1 USAGE=head2 XML::Atom::Client->new(%param)=head2 $api->use_soap([ 0 | 1 ])I<XML::Atom::Client> supports both the REST and SOAP-wrapper versions of theAtom API. By default, the REST version of the API will be used, but you canturn on the SOAP wrapper--for example, if you need to connect to a serverthat supports only the SOAP wrapper--by calling I<use_soap> with a value ofC<1>:    $api->use_soap(1);If called without arguments, returns the current value of the flag.=head2 $api->username([ $username ])If called with an argument, sets the username for login to I<$username>.Returns the current username that will be used when logging in to theAtom server.=head2 $api->password([ $password ])If called with an argument, sets the password for login to I<$password>.Returns the current password that will be used when logging in to theAtom server.=head2 $api->createEntry($PostURI, $entry)Creates a new entry.I<$entry> must be an I<XML::Atom::Entry> object.=head2 $api->getEntry($EditURI)Retrieves the entry with the given URL I<$EditURI>.Returns an I<XML::Atom::Entry> object.=head2 $api->updateEntry($EditURI, $entry)Updates the entry at URL I<$EditURI> with the entry I<$entry>, which must bean I<XML::Atom::Entry> object.Returns true on success, false otherwise.=head2 $api->deleteEntry($EditURI)Deletes the entry at URL I<$EditURI>.=head2 $api->getFeed($FeedURI)Retrieves the feed at I<$FeedURI>.Returns an I<XML::Atom::Feed> object representing the feed returnedfrom the server.=head2 ERROR HANDLINGMethods return C<undef> on error, and the error message can be retrievedusing the I<errstr> method.=head1 AUTHOR & COPYRIGHTPlease see the I<XML::Atom> manpage for author, copyright, and licenseinformation.=cut

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -