#!/usr/bin/perl # pmwe (pmwikiedit) # Copyright 2002-2004 Jonathan Scott Duff # duff@pobox.com # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # HISTORY # April 5, 2004 Added improvements suggested by Tom Hoover # April 10, 2004 Added some documentation and other improvements # May 8, 2004 Fixed a couple of small bugs =pod =head1 NAME pmwe - PmWiki Edit - Edit wiki pages using your favorite editor =head1 SYNPOSIS pmwe [options] [Abbr:][WikiGroup/]WikiPage -or- pmwe [options] URL =head1 DESCRIPTION Edit wiki pages using your favorite editor. Currently only works with pmwiki. =head2 OPTIONS -a AUTHOR Specify the author of the wiki page -c FILENAME Name of cookie file to use. Defaults to $HOME/.pmwe.cookies -e EDITOR Full path to the editor you wish to use. If unspecified, uses the value in the EDITOR environment variable otherwise uses "vi" -g Grabs the passwords as they are entered and writes them to the filename specified by the -p option. This option has no effect if -p is not specified. -m FILENAME A file for mapping Intermap-like abbreviations to URLs The format for this file is "abbreviation URL" where the space can be any number of whitespace characters. The URL must be such that adding "Group/WikiPage" to the end will access the wiki page. -p FILENAME File for keeping the passwords for your realms. The format of the file is "realm:user:password". When used in conjunction with the -g option, realms and passwords will be written to the password file as used. -u URL Specify a URL for accessing the wiki. The URL must be such that adding "Group/WikiPage" to the end will access the wikipage. =head1 AUTHOR Jonathan Scott Duff duff@pobox.com =cut use strict; use warnings; use Getopt::Std; my %opt; getopts('m:a:e:u:c:p:g', \%opt); my %passwords; if ($opt{'p'} && open(P,$opt{'p'})) { while (

) { chomp; my($realm,$user,$pass) = split /:/,$_,2; $passwords{$realm}= [ $user, $pass ]; } close P; } package PmWikiAgent; use base qw(LWP::UserAgent); use Term::ReadKey; our $Author; sub set_author { shift; $Author = shift; } sub new { my $self = LWP::UserAgent::new(@_); $self->agent("pmwikiedit"); return $self; } our $Password; sub get_basic_credentials { my($self, $realm) = @_; return ($passwords{$realm}[0],$passwords{$realm}[1]) if $passwords{$realm}; print "Enter username/password for $realm\n"; print "Username [$Author]: "; chomp(my $author = ); $author = $Author if $author eq ''; if ($Password) { print "Press ENTER to use the same password as before\n"; } print "Password: "; ReadMode('noecho'); chomp(my $password = ); ReadMode('restore'); print "\n"; # because we disabled echo if ($password eq '') { $password = $Password; } else { $Password = $password; } savepass($realm,$author,$password) if $opt{'g'}; return ($author, $password); } use Fcntl ':flock'; sub savepass { return unless $opt{'p'}; my ($realm,$user,$pass) = @_; $passwords{$realm} = [ $user, $pass ]; return unless open(P,">",$opt{'p'}); flock(P,LOCK_EX); for (sort keys %passwords) { print P join(":",$_,@{$passwords{$_}}),"\n"; } close P; } package main; use HTTP::Cookies; use File::Temp qw(tempfile); my $DefaultWikiUrl = 'http://www.pmichaud.com/wiki/'; my $DefaultWikiPage = 'Main/WikiSandbox'; my $DefaultWikiEditor = 'vi'; my $DefaultWikiAuthor = 'pmwikieditor'; my %urlmap; my $mapfile = $opt{'m'} || "$ENV{'HOME'}/.pmwe.map"; if (open(MAP, $mapfile)) { while () { my ($n,$url) = split; $urlmap{$n} = $url; } close MAP; } my $cookiefile = $opt{'c'} || "$ENV{'HOME'}/.pmwe.cookies"; my $jar = HTTP::Cookies->new(file => $cookiefile, autosave => 1); $jar->scan(sub { $DefaultWikiAuthor = $_[2] if $_[1] eq 'author'; }); my $wikipage = shift || $DefaultWikiPage; my $editor = $opt{'e'} || $ENV{'EDITOR'} || $DefaultWikiEditor; my $author = $opt{'a'} || $ENV{'WikiAuthor'} || $DefaultWikiAuthor; my $wikiurl = $opt{'u'} || shift || $DefaultWikiUrl; my $pageurl; if ($wikipage =~ /^http/) { $pageurl = $wikipage; if ($wikipage =~ /pagename/) { ($wikipage) = $pageurl =~ /pagename=([^&]+)/; } else { ($wikipage) = $pageurl =~ m!(\w+/\w+)$!; } } else { $wikiurl = $urlmap{$1} if $wikipage=~s/^(\w+):// && $urlmap{$1}; if (not exists $urlmap{$1}) { die "There exists no map for $1\n"; } $wikipage =~ tr!/!.!; $wikipage .= ".$wikipage" unless $wikipage =~ /\./; $wikiurl ||= $DefaultWikiUrl; $wikiurl .= '/' unless $wikiurl =~ m!/$!; $pageurl = "$wikiurl$wikipage"; } my $sep = ($pageurl =~ /\?/) ? '&' : '?'; my $ua = PmWikiAgent->new; $ua->set_author($author); $ua->cookie_jar($jar); my $req = HTTP::Request->new('GET', "$pageurl${sep}action=source"); my $outfile = (tempfile(UNLINK => 1))[1]; my $res = $ua->request($req,$outfile); my $mtime0 = (stat($outfile))[9]; system("$editor $outfile"); my $mtime1 = (stat($outfile))[9]; $mtime0 == $mtime1 && die "content unchanged.\n"; open(OUTFILE, $outfile) or die; $res = $ua->post($pageurl, [ action => 'post', pagename => $wikipage, text => do { local $/; }, author => $author ]); close OUTFILE; $res->is_error && die "Unable to save content!\n".$res->as_string."\n";