pmwe 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. #!/usr/bin/perl
  2. # pmwe (pmwikiedit)
  3. # Copyright 2002-2004 Jonathan Scott Duff
  4. # duff@pobox.com
  5. #
  6. # This program is free software; you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation; either version 2 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with this program; if not, write to the Free Software
  18. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19. #
  20. # HISTORY
  21. # April 5, 2004 Added improvements suggested by Tom Hoover
  22. # April 10, 2004 Added some documentation and other improvements
  23. # May 8, 2004 Fixed a couple of small bugs
  24. =pod
  25. =head1 NAME
  26. pmwe - PmWiki Edit - Edit wiki pages using your favorite editor
  27. =head1 SYNPOSIS
  28. pmwe [options] [Abbr:][WikiGroup/]WikiPage -or-
  29. pmwe [options] URL
  30. =head1 DESCRIPTION
  31. Edit wiki pages using your favorite editor. Currently only works
  32. with pmwiki.
  33. =head2 OPTIONS
  34. -a AUTHOR Specify the author of the wiki page
  35. -c FILENAME Name of cookie file to use. Defaults to
  36. $HOME/.pmwe.cookies
  37. -e EDITOR Full path to the editor you wish to use. If
  38. unspecified, uses the value in the EDITOR
  39. environment variable otherwise uses "vi"
  40. -g Grabs the passwords as they are entered and
  41. writes them to the filename specified by the -p
  42. option. This option has no effect if -p is not
  43. specified.
  44. -m FILENAME A file for mapping Intermap-like abbreviations to URLs
  45. The format for this file is "abbreviation URL"
  46. where the space can be any number of whitespace
  47. characters. The URL must be such that adding
  48. "Group/WikiPage" to the end will access the
  49. wiki page.
  50. -p FILENAME File for keeping the passwords for your realms.
  51. The format of the file is "realm:user:password".
  52. When used in conjunction with the -g option,
  53. realms and passwords will be written to the
  54. password file as used.
  55. -u URL Specify a URL for accessing the wiki. The URL
  56. must be such that adding "Group/WikiPage" to the
  57. end will access the wikipage.
  58. =head1 AUTHOR
  59. Jonathan Scott Duff duff@pobox.com
  60. =cut
  61. use strict;
  62. use warnings;
  63. use Getopt::Std;
  64. my %opt; getopts('m:a:e:u:c:p:g', \%opt);
  65. my %passwords;
  66. if ($opt{'p'} && open(P,$opt{'p'})) {
  67. while (<P>) {
  68. chomp; my($realm,$user,$pass) = split /:/,$_,2;
  69. $passwords{$realm}= [ $user, $pass ];
  70. }
  71. close P;
  72. }
  73. package PmWikiAgent;
  74. use base qw(LWP::UserAgent);
  75. use Term::ReadKey;
  76. our $Author;
  77. sub set_author { shift; $Author = shift; }
  78. sub new {
  79. my $self = LWP::UserAgent::new(@_);
  80. $self->agent("pmwikiedit");
  81. return $self;
  82. }
  83. our $Password;
  84. sub get_basic_credentials
  85. {
  86. my($self, $realm) = @_;
  87. return ($passwords{$realm}[0],$passwords{$realm}[1]) if $passwords{$realm};
  88. print "Enter username/password for $realm\n";
  89. print "Username [$Author]: "; chomp(my $author = <STDIN>);
  90. $author = $Author if $author eq '';
  91. if ($Password) { print "Press ENTER to use the same password as before\n"; }
  92. print "Password: ";
  93. ReadMode('noecho'); chomp(my $password = <STDIN>); ReadMode('restore');
  94. print "\n"; # because we disabled echo
  95. if ($password eq '') { $password = $Password; }
  96. else { $Password = $password; }
  97. savepass($realm,$author,$password) if $opt{'g'};
  98. return ($author, $password);
  99. }
  100. use Fcntl ':flock';
  101. sub savepass {
  102. return unless $opt{'p'};
  103. my ($realm,$user,$pass) = @_;
  104. $passwords{$realm} = [ $user, $pass ];
  105. return unless open(P,">",$opt{'p'});
  106. flock(P,LOCK_EX);
  107. for (sort keys %passwords) { print P join(":",$_,@{$passwords{$_}}),"\n"; }
  108. close P;
  109. }
  110. package main;
  111. use HTTP::Cookies;
  112. use File::Temp qw(tempfile);
  113. my $DefaultWikiUrl = 'http://www.pmichaud.com/wiki/';
  114. my $DefaultWikiPage = 'Main/WikiSandbox';
  115. my $DefaultWikiEditor = 'vi';
  116. my $DefaultWikiAuthor = 'pmwikieditor';
  117. my %urlmap;
  118. my $mapfile = $opt{'m'} || "$ENV{'HOME'}/.pmwe.map";
  119. if (open(MAP, $mapfile)) {
  120. while (<MAP>) { my ($n,$url) = split; $urlmap{$n} = $url; }
  121. close MAP;
  122. }
  123. my $cookiefile = $opt{'c'} || "$ENV{'HOME'}/.pmwe.cookies";
  124. my $jar = HTTP::Cookies->new(file => $cookiefile, autosave => 1);
  125. $jar->scan(sub { $DefaultWikiAuthor = $_[2] if $_[1] eq 'author'; });
  126. my $wikipage = shift || $DefaultWikiPage;
  127. my $editor = $opt{'e'} || $ENV{'EDITOR'} || $DefaultWikiEditor;
  128. my $author = $opt{'a'} || $ENV{'WikiAuthor'} || $DefaultWikiAuthor;
  129. my $wikiurl = $opt{'u'} || shift || $DefaultWikiUrl;
  130. my $pageurl;
  131. if ($wikipage =~ /^http/) {
  132. $pageurl = $wikipage;
  133. if ($wikipage =~ /pagename/)
  134. { ($wikipage) = $pageurl =~ /pagename=([^&]+)/; }
  135. else { ($wikipage) = $pageurl =~ m!(\w+/\w+)$!; }
  136. } else {
  137. $wikiurl = $urlmap{$1} if $wikipage=~s/^(\w+):// && $urlmap{$1};
  138. if (not exists $urlmap{$1}) { die "There exists no map for $1\n"; }
  139. $wikipage =~ tr!/!.!;
  140. $wikipage .= ".$wikipage" unless $wikipage =~ /\./;
  141. $wikiurl ||= $DefaultWikiUrl;
  142. $wikiurl .= '/' unless $wikiurl =~ m!/$!;
  143. $pageurl = "$wikiurl$wikipage";
  144. }
  145. my $sep = ($pageurl =~ /\?/) ? '&' : '?';
  146. my $ua = PmWikiAgent->new; $ua->set_author($author); $ua->cookie_jar($jar);
  147. my $req = HTTP::Request->new('GET', "$pageurl${sep}action=source");
  148. my $outfile = (tempfile(UNLINK => 1))[1];
  149. my $res = $ua->request($req,$outfile);
  150. my $mtime0 = (stat($outfile))[9];
  151. system("$editor $outfile");
  152. my $mtime1 = (stat($outfile))[9];
  153. $mtime0 == $mtime1 && die "content unchanged.\n";
  154. open(OUTFILE, $outfile) or die;
  155. $res = $ua->post($pageurl, [
  156. action => 'post',
  157. pagename => $wikipage,
  158. text => do { local $/; <OUTFILE> },
  159. author => $author
  160. ]);
  161. close OUTFILE;
  162. $res->is_error && die "Unable to save content!\n".$res->as_string."\n";