pingback-server.pl 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  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 3 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, see <http://www.gnu.org/licenses/>.
  15. use strict;
  16. use v5.10;
  17. use LWP::UserAgent; # This one will one day be eliminated! Hopefully!
  18. # Need these to do pingback
  19. use RPC::XML;
  20. use RPC::XML::Parser;
  21. AddModuleDescription('pingback-server.pl', 'Pingback Server Extension');
  22. our ($CommentsPrefix);
  23. *OldPingbackServerGetHtmlHeader = \&GetHtmlHeader;
  24. *GetHtmlHeader = \&NewPingbackServerGetHtmlHeader;
  25. # Add the <link ...> to the header
  26. sub NewPingbackServerGetHtmlHeader {
  27. my ($title, $id) = @_;
  28. my $header = OldPingbackServerGetHtmlHeader($title,$id);
  29. my $pingbackLink =
  30. '<link rel="pingback" '
  31. . 'href="http://thelackthereof.org/wiki.pl?action=pingback;id='
  32. . $id . '">';
  33. $header =~ s/<head>/<head>$pingbackLink/;
  34. return $header;
  35. }
  36. *OldPingbackServerInitRequest = \&InitRequest;
  37. *InitRequest = \&NewPingbackServerInitRequest;
  38. sub NewPingbackServerInitRequest {
  39. if($ENV{'QUERY_STRING'} =~ /action=pingback;id=(.*)/) {
  40. my $id = $1;
  41. DoPingbackServer($id);
  42. exit 0;
  43. } else {
  44. return OldPingbackServerInitRequest(@_);
  45. }
  46. }
  47. sub DoPingbackServer {
  48. my $id = FreeToNormal(shift);
  49. if ($ENV{'REQUEST_METHOD'} ne 'POST') {
  50. result('405 Method Not Allowed', -32300,
  51. 'Only XML-RPC POST requests recognised.', 'Allow: POST');
  52. }
  53. if ($ENV{'CONTENT_TYPE'} ne 'text/xml') {
  54. result('415 Unsupported Media Type', -32300,
  55. 'Only XML-RPC POST requests recognised.');
  56. }
  57. local $/ = undef;
  58. my $input = <STDIN>;
  59. # parse it
  60. my $parser = RPC::XML::Parser->new();
  61. my $request = $parser->parse($input);
  62. if (not ref($request)) {
  63. result('400 Bad Request', -32700, $request);
  64. }
  65. # handle it
  66. my $name = $request->name;
  67. my $arguments = $request->args;
  68. if ($name ne 'pingback.ping') {
  69. result('501 Not Implemented', -32601, "Method $name not supported");
  70. }
  71. if (@$arguments != 2) {
  72. result('400 Bad Request', -32602,
  73. "Wrong number of arguments (arguments must be in the form 'from', 'to')");
  74. }
  75. my $source = $arguments->[0]->value;
  76. my $target = $arguments->[1]->value;
  77. # TODO: Since we are _inside_ the wiki seems like we shouldn't have to use LWP
  78. # So comment out all the LWP stuff once the DoPost thingie works
  79. # DoPost($id);
  80. my $ua = LWP::UserAgent->new;
  81. $ua->agent("OddmusePingbackServer/0.1 ");
  82. # Create a request
  83. my $req = HTTP::Request->new(POST => 'http://thelackthereof.org/wiki.pl');
  84. $req->content_type('application/x-www-form-urlencoded');
  85. $req->content("title=$CommentsPrefix$id"
  86. . "&summary=new%20comment"
  87. . "&aftertext=Pingback:%20$source"
  88. . "&save=save"
  89. . "&username=pingback");
  90. my $res = $ua->request($req);
  91. my $out = '';
  92. # Check the outcome of the response
  93. if ($res->is_success) {
  94. $out = $res->content;
  95. } else {
  96. $out = $res->status_line . "\n";
  97. }
  98. result('200 OK', 0, "Oddmuse PingbackServer! $id OK");
  99. }
  100. sub result {
  101. my($status, $error, $data, $extra) = @_;
  102. my $response;
  103. if ($error) {
  104. $response = RPC::XML::response->new(
  105. RPC::XML::fault->new($error, $data));
  106. } else {
  107. $response = RPC::XML::response->new(RPC::XML::string->new($data));
  108. }
  109. print "Status: $status\n";
  110. if (defined($extra)) {
  111. print "$extra\n";
  112. }
  113. print "Content-Type: text/xml\n\n";
  114. print $response->as_string;
  115. exit;
  116. }
  117. =pod
  118. # This doesn't work... but might be a basis for an in-wiki update system
  119. sub DoPost {
  120. my $id = FreeToNormal(shift);
  121. my $source = shift;
  122. ValidIdOrDie($id);
  123. # Lock before getting old page to prevent races
  124. RequestLockOrError(); # fatal
  125. OpenPage($id);
  126. my $string = $Page{text};
  127. my $comment = "Pingback: $source";
  128. $comment =~ s/\r//g; # Remove "\r"-s (0x0d) from the string
  129. $comment =~ s/\s+$//g; # Remove whitespace at the end
  130. $string .= "----\n" if $string and $string ne "\n";
  131. $string .= $comment . "\n\n-- Pingback"
  132. . ' ' . TimeToText(time) . "\n\n";
  133. my $summary = "new pingback"
  134. $Page{summary} = $summary;
  135. $Page{username} = $user;
  136. $Page{text} = $string;
  137. SavePage();
  138. ReleaseLock();
  139. }
  140. =cut