Skip to content

Instantly share code, notes, and snippets.

@walkure
Last active December 10, 2015 21:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save walkure/4494797 to your computer and use it in GitHub Desktop.
Save walkure/4494797 to your computer and use it in GitHub Desktop.
気象庁の防災情報PuSH試行試行配信を受信するサブスクライバCGIの例 (cf. http://d.hatena.ne.jp/W53SA/20130109/1357750514 )
#!/usr/bin/env perl
#cf. http://d.hatena.ne.jp/W53SA/20130109/1357750514
use strict;
use LWP::Simple;
use XML::Atom::Feed;
use URI;
use File::Basename;
use Digest::HMAC_SHA1;
# this directory has permission to create file by this cgi
my $xmldir = '/path/to/data/directory/';
# hub.verify_token
my $verify_token = 'keykey';
# hub.secret
my $hmac_key = 'keykey';
my $atom_limit = 1024*1024;
# (un)subscribe
if($ENV{REQUEST_METHOD} eq 'GET'){
my $q = parse_query($ENV{QUERY_STRING});
if($q->{'hub.mode'} eq 'subscribe' || $q->{'hub.mode'} eq 'unsubscribe'){
my $challenge = $q->{'hub.challenge'};
my $topic = URI->new($q->{'hub.topic'});
if( ($q->{'hub.verify_token'} eq $verify_token)
&& ($topic->host =~ /xml\.kishou\.go\.jp$/) ){
print "Status: 200 OK\n";
print "Content-Type:text/plain\n\n";
print $challenge;
}else{
http_response(404,'unknown feed (un)subscribe reques');
}
}else{
http_response(403,'invalid access');
}
exit;
}
#receive PuSH
my $length = $ENV{CONTENT_LENGTH};
if($length > $atom_limit){
http_response(403,'too large data');
exit;
}
my $data;
if($length > 0){
read(STDIN,$data, $length);
if(defined $ENV{HTTP_X_HUB_SIGNATURE}){
my $hmac = Digest::HMAC_SHA1->new($hmac_key);
$hmac->add($data);
my $digest = 'sha1='.$hmac->hexdigest;
if($ENV{HTTP_X_HUB_SIGNATURE} ne $digest){
http_response(404,'Invalid X-Hub-Signature');
exit;
}
}
my $atom = eval{XML::Atom::Feed->new(\$data);};
process_atom($atom) if defined $atom;
}else{
http_response(200,'no data');
exit;
}
http_response(200,'OK');
exit;
sub http_response
{
my($code,$body) = @_;
my %msg = (
200 => 'OK',
403 => 'Forbidden',
404 => 'Not Found',
);
print << "_HTTP_";
Content-Type:text/plain
Status: $code $msg{$code}
$body
_HTTP_
}
sub parse_query
{
my $q = shift;
my @ps = split('&',$q);
my %query;
foreach my $p(@ps){
my($n,$v) = split('=',$p);
$v =~ tr/+/ /;
$v =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$query{$n} = $v;
}
\%query;
}
sub process_atom
{
my $atom = shift;
foreach my $it($atom->entries){
my $uri = URI->new($it->link->href);
next unless($uri->host =~ /xml\.kishou\.go\.jp$/);
getstore($uri,$xmldir.basename($uri->path()));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment