#!/usr/bin/perl ########################################################################### # usemod_xmlrpc.cgi: # Wiki XML-RPC API for UseModWiki # # Maintained by l.m.orchard http://www.decafbad.com # See: http://www.decafbad.com/twiki/bin/view/Main/XmlRpcToWiki # # 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, published at # http://www.gnu.org/copyleft/gpl.html ########################################################################### use strict; my $wiki_script = 'wiki.pl'; ########################################################################### use Data::Dumper qw(Dumper); $_ = 'nocgi'; package UseModWiki; #require "wiki.pl"; require "$wiki_script"; do "db/config"; $UseModWiki::UseConfig = 0; $UseModWiki::EmbedWiki = 1; $UseModWiki::q = new CGI(''); &UseModWiki::InitLinkPatterns(); our $twiki_web = "Main"; $SOAP::Constants::DO_NOT_USE_XML_PARSER = 1; use XMLRPC::Transport::HTTP; my $server = XMLRPC::Transport::HTTP::CGI->new; $server->dispatch_to('wiki'); $server->handle; package UseModWiki::XMLRPC; use Date::Parse; ########################################################################### ### Wiki XML-RPC API Methods ########################################################################### ########################################################################### # * array getRecentChanges ( Date timestamp ): # Get list of changed pages since timestamp, which should be in # UTC. The result is an array, where each element is a struct: # * name (string) : # Name of the page. The name is UTF-8 with URL encoding # to make it ASCII. # * lastModified (date) : # Date of last modification, in UTC. # * author (string) : # Name of the author (if available). Again, name is # UTF-8 with URL encoding. # * version (int) : # Current version. ########################################################################### sub getRecentChanges { my ($pkg, $date) = @_; my $time = str2time($date); my @changes = (); my ($status, $fileData) = &UseModWiki::ReadFile($UseModWiki::RcFile); my @outrc = split(/\n/, $fileData); @outrc = reverse @outrc; foreach my $rcline (@outrc) { my ($ts, $pagename, $summary, $isEdit, $host, $kind, $extraTemp) = split(/$UseModWiki::FS3/, $rcline); last if ($ts < $time); my %extra = split(/$UseModWiki::FS2/, $extraTemp, -1); my ($sec, $min, $hr, $dd, $mm, $yy, $wd, $yd, $isdst) = localtime($ts); $yy += 1900; $mm++; my $last_modified = sprintf('%04d%02d%02dT%02d:%02d:%02d', $yy,$mm,$dd,$hr,$min,$sec); my $pageinfo = { name => $pagename, lastModified => SOAP::Data->type(dateTime => $last_modified), author => $extra{name} || $host, version => $extra{revision} }; push @changes, $pageinfo; } return \@changes; } ########################################################################### # * int getRPCVersionSupported(): # Returns 1 with this version of the Wiki API. ########################################################################### sub getRPCVersionSupported { return 1; } ########################################################################### # * base64 getPage( String pagename ): # Get the raw Wiki text of page, latest version. Page name must be # UTF-8, with URL encoding. Returned value is a binary object, # with UTF-8 encoded page data. ########################################################################### sub getPage { my ($pkg, $pagename) = @_; &UseModWiki::OpenPage($pagename); &UseModWiki::OpenDefaultText(); my $pagetext = $UseModWiki::Text{'text'}; return SOAP::Data->type(base64 => $pagetext); } ########################################################################### # * base64 getPageVersion( String pagename, int version ): # Get the raw Wiki text of page. Returns UTF-8, expects UTF-8 with # URL encoding. ########################################################################### sub getPageVersion { my ($pkg, $pagename, $version) = @_; &UseModWiki::OpenPage($pagename); &UseModWiki::OpenDefaultText(); &UseModWiki::OpenKeptRevisions('text_default'); if (!defined($UseModWiki::KeptRevisions{$version})) { #$goodRevision = ''; } else { &UseModWiki::OpenKeptRevision($version); } my $pagetext = $UseModWiki::Text{'text'}; return SOAP::Data->type(base64 => $pagetext); } ########################################################################### # * base64 getPageHTML( String pagename ): # Return page in rendered HTML. Returns UTF-8, expects UTF-8 with # URL encoding. ########################################################################### sub getPageHTML { my ($pkg, $pagename) = @_; &UseModWiki::OpenPage($pagename); &UseModWiki::OpenDefaultText(); my $pagetext = $UseModWiki::Text{'text'}; $pagetext = &UseModWiki::WikiToHTML($pagetext); return SOAP::Data->type(base64 => $pagetext); } ########################################################################### # * base64 getPageHTMLVersion( String pagename, int version ): # Return page in rendered HTML, UTF-8. ########################################################################### sub getPageHTMLVersion { my ($pkg, $pagename, $version) = @_; &UseModWiki::OpenPage($pagename); &UseModWiki::OpenDefaultText(); &UseModWiki::OpenKeptRevisions('text_default'); if (!defined($UseModWiki::KeptRevisions{$version})) { #$goodRevision = ''; } else { &UseModWiki::OpenKeptRevision($version); } my $pagetext = $UseModWiki::Text{'text'}; $pagetext = &UseModWiki::WikiToHTML($pagetext); return SOAP::Data->type(base64 => $pagetext); } ########################################################################### # * array getAllPages(): # Returns a list of all pages. The result is an array of strings, # again UTF-8 in URL encoding. ########################################################################### sub getAllPages { my @pages = &UseModWiki::AllPagesList(); return \@pages; } ########################################################################### # * struct getPageInfo( string pagename ) : # returns a struct with elements # * name (string): the canonical page name, URL-encoded UTF-8. # * lastModified (date): Last modification date, UTC. # * author (string): author name, URL-encoded UTF-8. # * version (int): current version ########################################################################### sub getPageInfo { my ($pkg, $pagename) = @_; my ($meta, $pagetext); my $pageinfo = {}; my ($status, $fileData) = &UseModWiki::ReadFile($UseModWiki::RcFile); my @outrc = split(/\n/, $fileData); @outrc = reverse @outrc; foreach my $rcline (@outrc) { my ($ts, $rc_pagename, $summary, $isEdit, $host, $kind, $extraTemp) = split(/$UseModWiki::FS3/, $rcline); my %extra = split(/$UseModWiki::FS2/, $extraTemp, -1); ### Skip if it's not the page we're looking for next if !($pagename eq $rc_pagename); my ($sec, $min, $hr, $dd, $mm, $yy, $wd, $yd, $isdst) = localtime($ts); $yy += 1900; $mm++; my $last_modified = sprintf('%04d%02d%02dT%02d:%02d:%02d', $yy,$mm,$dd,$hr,$min,$sec); return { name => $pagename, lastModified => SOAP::Data->type(dateTime => $last_modified), author => $extra{name} || $host, version => $extra{revision} }; } return {}; } ########################################################################### # * struct getPageInfoVersion( string pagename, int version ) : # returns a struct just like plain getPageInfo(), but this time # for a specific version. ########################################################################### sub getPageInfoVersion { my ($pkg, $pagename, $version) = @_; my ($meta, $pagetext); my $pageinfo = {}; my ($status, $fileData) = &UseModWiki::ReadFile($UseModWiki::RcFile); my @outrc = split(/\n/, $fileData); @outrc = reverse @outrc; foreach my $rcline (@outrc) { my ($ts, $rc_pagename, $summary, $isEdit, $host, $kind, $extraTemp) = split(/$UseModWiki::FS3/, $rcline); my %extra = split(/$UseModWiki::FS2/, $extraTemp, -1); ### Skip if it's not the page we're looking for next if !($pagename eq $rc_pagename); ### Skip if it's not the version we need, given a version to look for. next if ( (defined $version) && ($extra{revision} ne $version) ); my ($sec, $min, $hr, $dd, $mm, $yy, $wd, $yd, $isdst) = localtime($ts); $yy += 1900; $mm++; my $last_modified = sprintf('%04d%02d%02dT%02d:%02d:%02d', $yy,$mm,$dd,$hr,$min,$sec); return { name => $pagename, lastModified => SOAP::Data->type(dateTime => $last_modified), author => $extra{name} || $host, version => $extra{revision} }; } return {}; } ########################################################################### ### * array listLinks( string pagename ): Lists all links for a given ### page. The returned array contains structs, with the following ### elements ### * name (string) : The page name or URL the link is to. ### * type (int) : The link type. Zero (0) for internal Wiki ### link, one (1) for external link (URL - image link, ### whatever). ########################################################################### sub listLinks { my ($pkg, $pagename) = @_; my @int_links = &UseModWiki::GetPageLinks($pagename, 1, 0, 0); my @ext_links = &UseModWiki::GetPageLinks($pagename, 0, 1, 1); my @links_out; push @links_out, map { {name => $_, type => 0} } @int_links; push @links_out, map { {name => $_, type => 1} } @ext_links; return \@links_out; } ########################################################################### ### * boolean wiki.putPage( String pagename, base64 text ): Set the ### text of a page, returning true on success ########################################################################### sub putPage { my ($pkg, $pagename, $pagetext) = @_; eval { my $id = $pagename; my $summary = "XmlRpc edit"; my $string = $pagetext; my $newAuthor = "XmlRpc"; my $isEdit = 0; &UseModWiki::OpenPage($pagename); &UseModWiki::OpenDefaultText(); $UseModWiki::Text{'text'} = $string; $UseModWiki::Text{'minor'} = $isEdit; $UseModWiki::Text{'newauthor'} = $newAuthor; $UseModWiki::Text{'summary'} = $summary; $UseModWiki::Section{'host'} = &UseModWiki::GetRemoteHost(1); &UseModWiki::SaveDefaultText(); &UseModWiki::SavePage(); &UseModWiki::WriteRcLog ($id, $summary, $isEdit, time, $UseModWiki::Section{'revision'}, '', $UseModWiki::Section{'host'}); if ($UseModWiki::UseCache) { UseModWiki::UnlinkHtmlCache($id); # Old cached copy is invalid if ($UseModWiki::Page{'revision'} < 2) { # If this is a new page... &UseModWiki::NewPageCacheClear($id); # ...uncache pages linked to this one. } } if ($UseModWiki::UseIndex && ($UseModWiki::Page{'revision'} == 1)) { unlink($UseModWiki::IndexFile); # Regenerate index on next request } return SOAP::Data->type(boolean => 1); }; if ($@) { return $@; } return SOAP::Data->type(boolean => 1); } package wiki; BEGIN { @wiki::ISA = qw( UseModWiki::XMLRPC ); }