copy.pl 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. #! /usr/bin/perl
  2. # Copyright (C) 2011–2014 Alex Schroeder <alex@gnu.org>
  3. # This program is free software: you can redistribute it and/or modify it under
  4. # the terms of the GNU General Public License as published by the Free Software
  5. # Foundation, either version 3 of the License, or (at your option) any later
  6. # version.
  7. #
  8. # This program is distributed in the hope that it will be useful, but WITHOUT
  9. # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  10. # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  11. #
  12. # You should have received a copy of the GNU General Public License along with
  13. # this program. If not, see <http://www.gnu.org/licenses/>.
  14. package OddMuse;
  15. use LWP::UserAgent;
  16. use HTML::TreeBuilder;
  17. use utf8;
  18. # load Oddmuse core
  19. $RunCGI = 0;
  20. do "wiki.pl";
  21. $default_namespace = 'NameOfYourWiki';
  22. main();
  23. sub default {
  24. my ($url, $ns) = @_;
  25. print $q->start_multipart_form(-method=>'get', -class=>'copy');
  26. print $q->p("This script helps you copy of a blog post to your Campaign Wiki.");
  27. print $q->p($q->label({-for=>'url', -style=>'display: inline-block; width: 20ex'}, 'Blog post URL:'),
  28. $q->textfield(-name=>'url', -id=>'url', -size=>50),
  29. $q->br(),
  30. $q->label({-for=>'ns', -style=>'display: inline-block; width: 20ex'}, 'Name of your wiki:'),
  31. $q->textfield(-name=>'ns', -id=>'ns', -size=>50, -default=>$default_namespace));
  32. if ($url and not $ns) {
  33. print $q->p($q->em('Please provide the name of your wiki. It is mandatory. Use “NameOfYourWiki” if you just want to test something.'));
  34. }
  35. print $q->submit('go', 'Go!');
  36. print $q->end_form();
  37. print $q->p("Please make sure you’re only submitting your own articles",
  38. "or articles with an appropriate license.");
  39. print $q->p("Drag this bookmarklet to your bookmarks bar for easy access:",
  40. $q->a({-href=>q{javascript:location='http://campaignwiki.org/copy?url='+encodeURIComponent(window.location.href)}}, 'Copy Blog Post') . ".");
  41. }
  42. sub confirm_overwrite {
  43. my ($url, $ns, $name) = @_;
  44. print $q->p("We already have a page with that name: ", GetPageLink($name));
  45. print $q->start_multipart_form(-method=>'get', -class=>'submit');
  46. print $q->p($q->label({-for=>'name'}, T('New name:')) . ' '
  47. . $q->textfield(-name=>'name', -id=>'name', -size=>50, -default=>$name));
  48. print $q->hidden('url', $url);
  49. print $q->hidden('ns', $ns);
  50. print $q->hidden('confirm', 1);
  51. print $q->submit('go', 'Continue');
  52. print $q->end_form();
  53. }
  54. sub confirm_save {
  55. my ($url, $ns, $name) = @_;
  56. my $ns = GetParam('ns', $default_namespace);
  57. print $q->p("Please confirm that you want to copy",
  58. $q->a({-href=>$url}, "this article"), "to", GetPageLink($HomePage, $ns) . ".");
  59. print $q->start_multipart_form(-method=>'get', -class=>'submit');
  60. print $q->p($q->label({-for=>'name'}, T('Name:')) . ' '
  61. . $q->textfield(-name=>'name', -id=>'name', -size=>50, -default=>$name));
  62. print $q->hidden('url', $url);
  63. print $q->hidden('ns', $ns);
  64. print $q->hidden('confirm', 1);
  65. print $q->submit('go', 'Continue');
  66. print $q->end_form();
  67. }
  68. sub get_data {
  69. my $url = shift;
  70. my $tree = HTML::TreeBuilder->new_from_content(GetRaw($url));
  71. my $h = $tree->look_down('_tag', 'h1');
  72. $h = $tree->look_down('_tag', 'title') unless $h;
  73. $h = $h->as_text if $h;
  74. my $b;
  75. if ($b = $tree->look_down('_tag', 'div', 'class', qr/post-body/)) {
  76. # Blogspot
  77. $b = html($b);
  78. } elsif ($b = $tree->look_down('_tag', 'div', 'class', qr/content/)) {
  79. # Oddmuse
  80. $b = html($b);
  81. } else {
  82. # default: get it all
  83. $b = html($tree->look_down('_tag', 'body'));
  84. }
  85. # common illegal character for page names
  86. $h =~ s/:/,/g;
  87. return ($h, $b);
  88. }
  89. sub html {
  90. my ($tree, $p) = @_;
  91. # $p indicates whether we need an empty line or not
  92. my $str;
  93. for my $element ($tree->content_list()) {
  94. if (not ref $element) {
  95. $str .= $element;
  96. } elsif ($element->tag() eq 'p') {
  97. $str .= ($p == 1 ? "\n\n" : "") . html($element);
  98. $p = 1;
  99. } elsif ($element->tag() eq 'br') {
  100. $str .= "\n\n";
  101. } elsif ($element->tag() eq 'span'
  102. and $element->attr('style') =~ /font-weight: *bold/) {
  103. $str .= "[b]" . html($element) . "[/b]";
  104. } elsif ($element->tag() =~ m/^(b|i|h[1-6])$/) {
  105. $str .= "[$1]" . html($element) . "[/$1]";
  106. } elsif ($element->tag() eq 'a'
  107. and $element->attr('href')) {
  108. $str .= "[url=" . $element->attr('href') . "]" . html($element) . "[/url]";
  109. } elsif ($element->tag() eq 'img'
  110. and $element->attr('src')) {
  111. $str .= "[img]" . $element->attr('src') . "[/img]";
  112. } elsif ($element->tag() eq 'pre') {
  113. $str .= "\n\n[code]\n" . $element->as_text() . "\n[/code]";
  114. $p = 1;
  115. } elsif ($element->tag() eq 'div'
  116. and ($element->attr('style') =~ /float: *(left|right)/
  117. or $element->attr('style') =~ /text-align: *(center)/)) {
  118. $str .= "\n[$1]" . html($element) . "[/$1]";
  119. $p = 1;
  120. } else {
  121. $str .= html($element);
  122. }
  123. }
  124. return $str;
  125. }
  126. sub name_exists {
  127. my $id = FreeToNormal(shift);
  128. AllPagesList();
  129. my $string = GetPageContent($id);
  130. return ($IndexHash{$id}
  131. and substr($string, 0, length($DeletedPage)) ne $DeletedPage);
  132. }
  133. sub post_addition {
  134. my ($url, $ns, $name, $data) = @_;
  135. my $id = FreeToNormal($name);
  136. print $q->p("Copying ", $q->a({-href=>$url}, "the blog post") . "…");
  137. my $text = "Based on [$url $name].\n----\n" . $data;
  138. my $ua = LWP::UserAgent->new;
  139. my %params = (text => $text,
  140. title => $id,
  141. summary => $name,
  142. username => GetParam('username'),
  143. ns => $ns,
  144. pwd => GetParam('pwd'));
  145. $params{$QuestionaskerSecretKey} = 1 if $QuestionaskerSecretKey;
  146. my $response = $ua->post($FullUrl, \%params);
  147. if ($response->is_error) {
  148. print $q->p("Copying failed!");
  149. print $q->p($q->strong($response->status_line));
  150. print $response->content;
  151. } else {
  152. print $q->p("Your copy: ", GetPageLink($name) . ".");
  153. }
  154. }
  155. sub main {
  156. Init();
  157. if ($q->path_info eq '/source') {
  158. seek DATA, 0, 0;
  159. print "Content-type: text/plain; charset=UTF-8\r\n\r\n", <DATA>;
  160. } else {
  161. $UserGotoBar .= $q->a({-href=>$q->url . '/source'}, 'Source');
  162. print GetHeader('', 'Copy a blog article');
  163. print $q->start_div({-class=>'content index'});
  164. my $url = GetParam('url');
  165. my $ns = GetParam('ns');
  166. if (not $url or not $ns) {
  167. default($url, $ns);
  168. } else {
  169. my ($name, $data) = get_data($url);
  170. $name = GetParam('name', $name);
  171. if (name_exists($name) and not GetParam('confirm', 0)) {
  172. confirm_overwrite($url, $ns, $name);
  173. } elsif (not GetParam('confirm', 0)) {
  174. confirm_save($url, $ns, $name);
  175. } else {
  176. post_addition($url, $ns, $name, $data);
  177. }
  178. }
  179. print $q->p('Questions? Send mail to Alex Schröder <'
  180. . $q->a({-href=>'mailto:kensanata@gmail.com'},
  181. 'kensanata@gmail.com') . '>');
  182. print $q->end_div();
  183. PrintFooter();
  184. }
  185. }
  186. __DATA__