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

📄 atomserver.pm

📁 1. 记录每个帖子的访问人情况
💻 PM
📖 第 1 页 / 共 2 页
字号:
# Copyright 2001-2005 Six Apart.# SCRiPTMAFiA 2005 - THE DiRTY HANDS ON YOUR SCRiPTS## $Id: AtomServer.pm 10197 2005-03-09 00:27:57Z ezra $package MT::AtomServer;use strict;use XML::Atom;use XML::Atom::Util qw( first textValue );use base qw( MT::App );use MIME::Base64 ();use Digest::SHA1 ();use MT::Atom;use MT::Util qw( encode_xml );use MT::Author;use constant NS_SOAP => 'http://schemas.xmlsoap.org/soap/envelope/';use constant NS_WSSE => 'http://schemas.xmlsoap.org/ws/2002/07/secext';use constant NS_WSU => 'http://schemas.xmlsoap.org/ws/2002/07/utility';sub init {    my $app = shift;    $app->{no_read_body} = 1        if $app->request_method eq 'POST' || $app->request_method eq 'PUT';    $app->SUPER::init(@_) or return $app->error("Initialization failed");    $app->request_content        if $app->request_method eq 'POST' || $app->request_method eq 'PUT';    $app->add_methods(        handle => \&handle,    );    $app->{default_mode} = 'handle';    $app->{is_admin} = 1;    $app->{warning_trace} = 0;    $app;}sub handle {    my $app = shift;        my $out = eval {	(my $pi = $app->path_info) =~ s!^/!!;	my($subapp, @args) = split /\//, $pi;	$app->{param} = {};	for my $arg (@args) {	    my($k, $v) = split /=/, $arg, 2;	    $app->{param}{$k} = $v;	}	if (my $action = $app->get_header('SOAPAction')) {	    $app->{is_soap} = 1;	    $action =~ s/"//g; # "	    my($method) = $action =~ m!/([^/]+)$!;	    $app->request_method($method);	}	my $apps = $app->{cfg}->AtomApp;	if (my $class = $apps->{$subapp}) {	    bless $app, $class;	}	my $out = $app->handle_request;	return unless defined $out;	if ($app->{is_soap}) {	    $out =~ s!^(<\?xml.*?\?>)!!;	    $out = <<SOAP;$1<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">    <soap:Body>$out</soap:Body></soap:Envelope>SOAP	    }	return $out;    }; if ($@) {	$app->error($@);	$app->show_error("Internal Error");    }    return $out;}sub handle_request {    1;}sub error {    my $app = shift;    my($code, $msg) = @_;    return unless ref($app);    $app->response_code($code);    $app->response_message($msg);    $app->SUPER::error($msg);    return undef;}sub show_error {    my $app = shift;    my($err) = @_;    chomp($err = encode_xml($err));    if ($app->{is_soap}) {        my $code = $app->response_code;        if ($code >= 400) {            $app->response_code(500);            $app->response_message($err);        }        return <<FAULT;<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">  <soap:Body>    <soap:Fault>      <faultcode>$code</faultcode>      <faultstring>$err</faultstring>    </soap:Fault>  </soap:Body></soap:Envelope>FAULT    } else {        return <<ERR;<error>$err</error>ERR    }}sub get_auth_info {    my $app = shift;    my %param;    if ($app->{is_soap}) {        my $xml = $app->xml_body;        my $auth = first($xml, NS_WSSE, 'UsernameToken');        $param{Username} = textValue($auth, NS_WSSE, 'Username');        $param{PasswordDigest} = textValue($auth, NS_WSSE, 'Password');        $param{Nonce} = textValue($auth, NS_WSSE, 'Nonce');        $param{Created} = textValue($auth, NS_WSU, 'Created');    } else {        my $req = $app->get_header('X-WSSE')            or return $app->auth_failure(401, 'X-WSSE authentication required');        $req =~ s/^WSSE //;	my ($profile);	($profile, $req) = $req =~ /(\S+),?\s+(.*)/;	return $app->error(400, "Unsupported WSSE authentication profile") 	    if $profile !~ /\bUsernameToken\b/i;        for my $i (split /,\s*/, $req) {            my($k, $v) = split /=/, $i, 2;            $v =~ s/^"//;            $v =~ s/"$//;            $param{$k} = $v;        }    }    \%param;}use constant TIMEOUT_WINDOW => 120;sub authenticate {    my $app = shift;    my $auth = $app->get_auth_info	or return $app->auth_failure(400, "No authentication info");    for my $f (qw( Username PasswordDigest Nonce Created )) {        return $app->auth_failure(400, "X-WSSE requires $f")            unless $auth->{$f};    }    require MT::Session;    my $nonce_record = MT::Session->load($auth->{Nonce});        if ($nonce_record && $nonce_record->id eq $auth->{Nonce}) {	return $app->auth_failure(403, "Nonce already used");    }    $nonce_record = new MT::Session();    $nonce_record->set_values({id => $auth->{Nonce},			       created_on => time,			       kind => 'AN'});    $nonce_record->save();# xxx Expire sessions on shorter timeout?    my $user = MT::Author->load({ name => $auth->{Username} })        or return $app->auth_failure(403, 'Invalid login');    my $created_on_epoch = $app->iso2epoch($auth->{Created});    if (abs(time - $created_on_epoch) > TIMEOUT_WINDOW) {	return $app->auth_failure(403, 'X-WSSE UsernameToken timed out');    }    $auth->{Nonce} = MIME::Base64::decode_base64($auth->{Nonce});    my $expected = Digest::SHA1::sha1_base64(         $auth->{Nonce} . $auth->{Created} . $user->password);    # Some base64 implementors do it wrong and don't put the =    # padding on the end. This should protect us against that without    # creating any holes.    $expected =~ s/=*$//;    $auth->{PasswordDigest} =~ s/=*$//;    #print STDERR "expected $expected and got " . $auth->{PasswordDigest} . "\n";    return $app->auth_failure(403, 'X-WSSE PasswordDigest is incorrect')        unless $expected eq $auth->{PasswordDigest};    $app->{user} = $user;    return 1;}sub auth_failure {    my $app = shift;    $app->set_header('WWW-Authenticate', 'WSSE profile="UsernameToken"');    return $app->error(@_);}sub xml_body {    my $app = shift;    unless (exists $app->{xml_body}) {        if (LIBXML) {            my $parser = XML::LibXML->new;            $app->{xml_body} = $parser->parse_string($app->request_content);        } else {            my $xp = XML::XPath->new(xml => $app->request_content);            $app->{xml_body} = ($xp->find('/')->get_nodelist)[0];        }    }    $app->{xml_body};}sub atom_body {    my $app = shift;    my $atom;    if ($app->{is_soap}) {        my $xml = $app->xml_body;        $atom = MT::Atom::Entry->new(Elem => first($xml, NS_SOAP, 'Body'))            or return $app->error(500, MT::Atom::Entry->errstr);    } else {        $atom = MT::Atom::Entry->new(Stream => \$app->request_content)            or return $app->error(500, MT::Atom::Entry->errstr);    }    $atom;}# $target_zone is expected to be a number of hours from GMTsub iso2ts {    my $app = shift;    my($ts, $target_zone) = @_;    return unless $ts =~ /^(\d{4})(?:-?(\d{2})(?:-?(\d\d?)(?:T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?(?:Z|([+-]\d{2}:\d{2}))?)?)?)?/;    my($y, $mo, $d, $h, $m, $s, $zone) =        ($1, $2 || 1, $3 || 1, $4 || 0, $5 || 0, $6 || 0, $7);    if ($zone) {	my ($zh, $zm) = $zone =~ /([+-]\d\d):(\d\d)/;        use Time::Local qw( timegm );        my $ts = timegm( $s, $m, $h, $d, $mo - 1, $y - 1900 );        if ($zone ne 'Z') {	    require MT::DateTime;            my $tz_secs = MT::DateTime->tz_offset_as_seconds($zone);            $ts -= $tz_secs;        }	if ($target_zone) {            my $tz_secs = (3600 * int($target_zone) +                            60 * abs($target_zone - int($target_zone)));            $ts += $tz_secs;	} else {	} 	($s, $m, $h, $d, $mo, $y) = gmtime( $ts );        $y += 1900; $mo++;    }    sprintf("%04d%02d%02d%02d%02d%02d", $y, $mo, $d, $h, $m, $s);}sub iso2epoch {    my $app = shift;    my($ts) = @_;    return unless $ts =~ /^(\d{4})(?:-?(\d{2})(?:-?(\d\d?)(?:T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?(?:Z|([+-]\d{2}:\d{2}))?)?)?)?/;    my($y, $mo, $d, $h, $m, $s, $zone) =        ($1, $2 || 1, $3 || 1, $4 || 0, $5 || 0, $6 || 0, $7);    use Time::Local;    my $dt = timegm($s, $m, $h, $d, $mo-1, $y);    if ($zone && $zone ne 'Z') {	 require MT::DateTime;         my $tz_secs = MT::DateTime->tz_offset_as_seconds($zone); 	 $dt -= $tz_secs;    }    $dt;}package MT::AtomServer::Weblog;use strict;use XML::Atom;use XML::Atom::Feed;use base qw( MT::AtomServer );use MT::Blog;use MT::Entry;use MT::Util qw( encode_xml );use MT::Permission;use File::Spec;use File::Basename;use constant NS_CATEGORY => 'http://sixapart.com/atom/category#';use constant NS_DC => 'http://purl.org/dc/elements/1.1/';use constant NS_PHOTOS => 'http://sixapart.com/atom/photo#';sub script { $_[0]->{cfg}->AtomScript . '/weblog' }sub handle_request {

⌨️ 快捷键说明

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