#!/usr/bin/python """ MoinMoin XML-RPC interface Drop-in script which exposes MoinMoin via XML-RPC interface See: http://www.decafbad.com/twiki/bin/view/Main/XmlRpcToWiki Maintained by l.m.orchard http://www.decafbad.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, published at http://www.gnu.org/copyleft/gpl.html """ import os, sys, string, traceback import cgi import cStringIO import xmlrpclib sys.path.append('/home/deusx/lib/python2.0/site-packages') ### Seems like I need this to fake out MoinMoin? (Even though this is ### not a CGI request) os.environ['REQUEST_METHOD'] = 'GET' from MoinMoin import cgimain cgimain.createRequest() from MoinMoin import config, util, version, editlog from MoinMoin import wikiutil from MoinMoin.Page import Page class MoinMoinXmlRpc: """ Component class which provides the XML-RPC methods of the MoinMoin interface. """ def __init__(self): pass def xmlrpc_getRPCVersionSupported(self): """ int getRPCVersionSupported(): Returns 1 with this version of the Wiki API. """ return 1 def xmlrpc_getAllPages(self): """ array getAllPages(): Returns a list of all pages. The result is an array of strings, again UTF-8 in URL encoding. """ return wikiutil.getPageList(config.text_dir) def xmlrpc_getRecentChanges(self, date): """ 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. """ def xmlrpc_getPageInfo(self,pagename): """ 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 """ page = Page(pagename) last_mod = page._last_modified() return { 'name' : pagename, 'lastModified' : last_mod, 'author' : 'anon', 'version' : 1 } def xmlrpc_getPageInfoVersion(self,pagename): """ struct getPageInfoVersion( string pagename, int version ) : returns a struct just like plain getPageInfo(), but this time for a specific version. """ page = Page(pagename) last_mod = page._last_modified() return { 'name' : pagename, 'lastModified' : last_mod, 'author' : 'anon', 'version' : 1 } def xmlrpc_getPage(self, pagename): """ 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. """ page = Page(pagename) result = page.get_raw_body() return xmlrpclib.Binary(result) def xmlrpc_getPageVersion(self, pagename, version): """ base64 getPageVersion( String pagename, int version ): Get the raw Wiki text of page. Returns UTF-8, expects UTF-8 with URL encoding. """ page = Page(pagename) result = page.get_raw_body() return xmlrpclib.Binary(result) def xmlrpc_getPageHTML(self, pagename): """ base64 getPageHTML( String pagename ): Return page in rendered HTML. Returns UTF-8, expects UTF-8 with URL encoding. """ page = Page(pagename) stdout = sys.stdout sys.stdout = cStringIO.StringIO() form = cgi.FieldStorage() page.send_page(cgi.FieldStorage(), content_only=1) result = sys.stdout.getvalue() sys.stdout = stdout return xmlrpclib.Binary(result) def xmlrpc_getPageHTMLVersion(self, pagename, version): """ base64 getPageHTML( String pagename, int version ): Return page in rendered HTML, UTF-8. """ page = Page(pagename) stdout = sys.stdout sys.stdout = cStringIO.StringIO() form = cgi.FieldStorage() page.send_page(cgi.FieldStorage(), content_only=1) result = sys.stdout.getvalue() sys.stdout = stdout return xmlrpclib.Binary(result) def xmlrpc_listLinks(self, pagename): """ 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). """ page = Page(pagename) links_out = [] for link in page.getPageLinks(): links_out.append({ 'name':link, 'type':0 }) return links_out def xmlrpc_putPage(self, pagename, pagetext): """ boolean wiki.putPage( String pagename, base64 text ): Set the text of a page, returning true on success """ page = Page(pagename) page.save_text(pagetext.data, "0") return xmlrpclib.Boolean(1) ########################################################################### def dump_exc(): return "%s : %s : %s" % \ (sys.exc_info()[0], sys.exc_info()[1], string.join(traceback.format_tb(sys.exc_info()[2]), '')) ########################################################################### if __name__ == '__main__': components = { 'wiki' : MoinMoinXmlRpc() } xml_in = sys.stdin.read(int(os.environ.get('CONTENT_LENGTH', 0))) params, method = xmlrpclib.loads(xml_in) component_name, method_name = string.split(method, ".") if components.has_key(component_name): component = components[component_name] elif components.has_key(self.default_component): component = components[self.default_component] else: xml_out = xmlrpclib.dumps(xmlrpclib.Fault(1, "no such component")) comp_method_name = "xmlrpc_%s" % method_name try: method = getattr(component, comp_method_name) except AttributeError: xml_out = xmlrpclib.dumps(xmlrpclib.Fault(1, "no such method")) else: try: result = apply(method, params) try: xml_out = xmlrpclib.dumps((result,), methodresponse=1) except: xml_out = xmlrpclib.dumps( xmlrpclib.Fault(1, "error calling method: %s" % dump_exc())) except: xml_out = xmlrpclib.dumps( xmlrpclib.Fault(1, "error calling method: %s" % dump_exc())) print "Content-type: text/xml" print print xml_out