pingback-server.pl 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. # Copyright (C) 2004 Brock Wilcox <awwaiid@thelackthereof.org>
  2. #
  3. # This program is free software; you can redistribute it and/or modify
  4. # it under the terms of the GNU General Public License as published by
  5. # the Free Software Foundation; either version 2 of the License, or
  6. # (at your option) any later version.
  7. #
  8. # This program is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. # GNU General Public License for more details.
  12. #
  13. # You should have received a copy of the GNU General Public License
  14. # along with this program; if not, write to the
  15. # Free Software Foundation, Inc.
  16. # 59 Temple Place, Suite 330
  17. # Boston, MA 02111-1307 USA
  18. #
  19. # History / Notes
  20. # 2004.03.19
  21. # - Created
  22. # - Works!
  23. # - Tried to get rid of LWP but failed :(
  24. # - We have to capture the script before CGI.pm starts to get STDIN
  25. use strict;
  26. use v5.10;
  27. use LWP::UserAgent; # This one will one day be eliminated! Hopefully!
  28. # Need these to do pingback
  29. use RPC::XML;
  30. use RPC::XML::Parser;
  31. AddModuleDescription('pingback-server.pl', 'Pingback Server Extension');
  32. our ($CommentsPrefix);
  33. *OldPingbackServerGetHtmlHeader = \&GetHtmlHeader;
  34. *GetHtmlHeader = \&NewPingbackServerGetHtmlHeader;
  35. # Add the <link ...> to the header
  36. sub NewPingbackServerGetHtmlHeader {
  37. my ($title, $id) = @_;
  38. my $header = OldPingbackServerGetHtmlHeader($title,$id);
  39. my $pingbackLink =
  40. '<link rel="pingback" '
  41. . 'href="http://thelackthereof.org/wiki.pl?action=pingback;id='
  42. . $id . '">';
  43. $header =~ s/<head>/<head>$pingbackLink/;
  44. return $header;
  45. }
  46. *OldPingbackServerInitRequest = \&InitRequest;
  47. *InitRequest = \&NewPingbackServerInitRequest;
  48. sub NewPingbackServerInitRequest {
  49. if($ENV{'QUERY_STRING'} =~ /action=pingback;id=(.*)/) {
  50. my $id = $1;
  51. DoPingbackServer($id);
  52. exit 0;
  53. } else {
  54. return OldPingbackServerInitRequest(@_);
  55. }
  56. }
  57. sub DoPingbackServer {
  58. my $id = FreeToNormal(shift);
  59. if ($ENV{'REQUEST_METHOD'} ne 'POST') {
  60. result('405 Method Not Allowed', -32300,
  61. 'Only XML-RPC POST requests recognised.', 'Allow: POST');
  62. }
  63. if ($ENV{'CONTENT_TYPE'} ne 'text/xml') {
  64. result('415 Unsupported Media Type', -32300,
  65. 'Only XML-RPC POST requests recognised.');
  66. }
  67. local $/ = undef;
  68. my $input = <STDIN>;
  69. # parse it
  70. my $parser = RPC::XML::Parser->new();
  71. my $request = $parser->parse($input);
  72. if (not ref($request)) {
  73. result('400 Bad Request', -32700, $request);
  74. }
  75. # handle it
  76. my $name = $request->name;
  77. my $arguments = $request->args;
  78. if ($name ne 'pingback.ping') {
  79. result('501 Not Implemented', -32601, "Method $name not supported");
  80. }
  81. if (@$arguments != 2) {
  82. result('400 Bad Request', -32602,
  83. "Wrong number of arguments (arguments must be in the form 'from', 'to')");
  84. }
  85. my $source = $arguments->[0]->value;
  86. my $target = $arguments->[1]->value;
  87. # TODO: Since we are _inside_ the wiki seems like we shouldn't have to use LWP
  88. # So comment out all the LWP stuff once the DoPost thingie works
  89. # DoPost($id);
  90. my $ua = LWP::UserAgent->new;
  91. $ua->agent("OddmusePingbackServer/0.1 ");
  92. # Create a request
  93. my $req = HTTP::Request->new(POST => 'http://thelackthereof.org/wiki.pl');
  94. $req->content_type('application/x-www-form-urlencoded');
  95. $req->content("title=$CommentsPrefix$id"
  96. . "&summary=new%20comment"
  97. . "&aftertext=Pingback:%20$source"
  98. . "&save=save"
  99. . "&username=pingback");
  100. my $res = $ua->request($req);
  101. my $out = '';
  102. # Check the outcome of the response
  103. if ($res->is_success) {
  104. $out = $res->content;
  105. } else {
  106. $out = $res->status_line . "\n";
  107. }
  108. result('200 OK', 0, "Oddmuse PingbackServer! $id OK");
  109. }
  110. sub result {
  111. my($status, $error, $data, $extra) = @_;
  112. my $response;
  113. if ($error) {
  114. $response = RPC::XML::response->new(
  115. RPC::XML::fault->new($error, $data));
  116. } else {
  117. $response = RPC::XML::response->new(RPC::XML::string->new($data));
  118. }
  119. print "Status: $status\n";
  120. if (defined($extra)) {
  121. print "$extra\n";
  122. }
  123. print "Content-Type: text/xml\n\n";
  124. print $response->as_string;
  125. exit;
  126. }
  127. =pod
  128. # This doesn't work... but might be a basis for an in-wiki update system
  129. sub DoPost {
  130. my $id = FreeToNormal(shift);
  131. my $source = shift;
  132. ValidIdOrDie($id);
  133. # Lock before getting old page to prevent races
  134. RequestLockOrError(); # fatal
  135. OpenPage($id);
  136. my $string = $Page{text};
  137. my $comment = "Pingback: $source";
  138. $comment =~ s/\r//g; # Remove "\r"-s (0x0d) from the string
  139. $comment =~ s/\s+$//g; # Remove whitespace at the end
  140. $string .= "----\n" if $string and $string ne "\n";
  141. $string .= $comment . "\n\n-- Pingback"
  142. . ' ' . TimeToText(time) . "\n\n";
  143. my $summary = "new pingback"
  144. $Page{summary} = $summary;
  145. $Page{username} = $user;
  146. $Page{text} = $string;
  147. SavePage();
  148. ReleaseLock();
  149. }
  150. =cut