PageRenderTime 56ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/pingback/client.pl

https://bitbucket.org/cmauch/ikiwiki
Perl | 122 lines | 86 code | 10 blank | 26 comment | 6 complexity | 5a1491370caf0cfcd9c034542f9a3f01 MD5 | raw file
  1. #!/usr/bin/perl -wT
  2. # -*- Mode: perl; tab-width: 4; indent-tabs-mode: nil; -*-
  3. #
  4. # Pingback Client: HTML to Pingback
  5. #
  6. # Copyright (c) 2002 by Ian Hickson
  7. #
  8. # This program is free software; you can redistribute it and/or modify
  9. # it under the terms of the GNU General Public License as published by
  10. # the Free Software Foundation; either version 2 of the License, or
  11. # (at your option) any later version.
  12. #
  13. # This program is distributed in the hope that it will be useful, but
  14. # WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. # General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU General Public License
  19. # along with this program; if not, write to the Free Software
  20. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21. use strict;
  22. use diagnostics;
  23. use lib '/home/ianh/lib/perl';
  24. use CGI;
  25. use LWP::UserAgent;
  26. use RPC::XML::Client;
  27. use HTML::Entities;
  28. print STDERR "\npingback client invoked\n";
  29. # set up HTTP client
  30. my $query = CGI->new();
  31. my $ua = LWP::UserAgent->new();
  32. $ua->agent($ua->agent . ' (Hixie\'s pingback client)');
  33. $ua->timeout(5);
  34. $ua->env_proxy();
  35. $ua->protocols_allowed(['http', 'https']);
  36. # get permalink
  37. my $permalink = $query->param('permalink');
  38. if (not defined($permalink)) {
  39. result('400 Bad Request', 'Client Error',
  40. 'You must provide a permalink.');
  41. }
  42. print STDERR "permalink: $permalink\n";
  43. # get source content
  44. my $content = $query->param('content');
  45. if (not defined($content) or $content eq '') {
  46. my $request = HTTP::Request->new('GET', $permalink);
  47. $request->referer('http://point-defiance.rhcloud.com/ping/client.pl');
  48. $content = $ua->request($request)->content;
  49. }
  50. #print STDERR "content:\n$content\n";
  51. # scan $content for links
  52. my $links = {};
  53. while ($content =~ s/href=\"([^\"]+)\"//os) {
  54. next if ( $1 =~ /^https:\/\/bitbucket/ ); # Static Link on Page Template
  55. next if ( $1 =~ /^http:\/\/www\.livefyre\.com/ ); # Static Link on Page Template
  56. next if ( $1 =~ /^http:\/\/www\.openshift\.com/ ); # Static Link on Page Template
  57. next if ( $1 =~ /^http:\/\/ikiwiki\.info/ ); # Static Link on Page Template
  58. next if ( $1 =~ /^http:\/\/www\.gnu\.org/ ); # Document Licensing
  59. next if ( $1 =~ /^http:\/\/software\.hixie\.ch/ ); # Just because
  60. next if ( $1 =~ /^http:\/\/point-defiance\.rhcloud\.com/ ); # Prevent Selfpings
  61. next if ( $1 =~ /^\.\./ ); # Prevent Self Relative Path Links
  62. next if ( $1 =~ /^\// ); # Prevent Self Absolute Path Links
  63. next if ( $1 =~ /^#/ ); # Prevent Self Anchors
  64. next if ( $1 =~ /ikiwiki\.cgi/ ); # Prevent Self CGI Links
  65. $links->{decode_entities($1)}++;
  66. # using a hash instead of an array avoids duplicates
  67. }
  68. # send pingbacks
  69. my $result = '';
  70. foreach my $link (keys(%$links)) {
  71. # fetch the page
  72. my $request = HTTP::Request->new('GET', $link);
  73. $request->referer($permalink);
  74. my $headers = $ua->request($request);
  75. my $page = $headers->content;
  76. # scan for a pingback link
  77. my $pingbackServer;
  78. if (my @pingbackServers = $headers->header('X-Pingback')) {
  79. # XXX check that there is only one?
  80. $pingbackServer = $pingbackServers[0];
  81. } elsif ($page =~ m/<link\s+rel=\"pingback\"\s+href=\"([^\"]+)\"\s*\/?>/os) {
  82. $pingbackServer = decode_entities($1);
  83. } else {
  84. $result .= "No pingback server at $link\n";
  85. next;
  86. }
  87. # send pingback
  88. my $client = RPC::XML::Client->new($pingbackServer);
  89. my $response = $client->send_request('pingback.ping', $permalink, $link);
  90. if (not ref $response) {
  91. $result .= "Failed to ping back '$pingbackServer': $response\n";
  92. } else {
  93. $result .= "Got a response from '$pingbackServer': \n" . $response->as_string . "\n";
  94. }
  95. }
  96. result('200 Done', 'Done', $result);
  97. sub result {
  98. my($status, $line1, $data) = @_;
  99. my $length = length("$line1\n$data");
  100. print <<EOF;
  101. Status: $status
  102. Content-Type: text/plain
  103. Content-Length: $length
  104. $line1
  105. $data
  106. EOF
  107. print STDERR "result=$status ($line1)\n$data\n\n";
  108. exit;
  109. }