source: xmlrpcplugin/0.10/tracrpc/wiki.py

Last change on this file was 1735, checked in by Alec Thomas, 17 years ago

XmlRpcPlugin:

Applied patches from gotoh and stp, thanks. Closes #434 and #845.

File size: 7.1 KB
RevLine 
[225]1try:
2    from cStringIO import StringIO
3except ImportError:
4    from StringIO import StringIO
5import xmlrpclib
6import posixpath
7
8from trac.core import *
9from trac.perm import IPermissionRequestor
[222]10from trac.wiki.api import WikiSystem
[225]11from trac.wiki.model import WikiPage
12from trac.wiki.formatter import wiki_to_html
13from trac.attachment import Attachment
[229]14from tracrpc.api import IXMLRPCHandler, expose_rpc
[1188]15from tracrpc.util import to_timestamp
[222]16
[229]17class WikiRPC(Component):
[225]18    """ Implementation of the [http://www.jspwiki.org/Wiki.jsp?page=WikiRPCInterface2 WikiRPC API]. """
[224]19
[229]20    implements(IXMLRPCHandler)
21
[222]22    def __init__(self):
23        self.wiki = WikiSystem(self.env)
24
[225]25    def xmlrpc_namespace(self):
26        return 'wiki'
[222]27
[229]28    def xmlrpc_methods(self):
29        yield ('WIKI_VIEW', ((dict, xmlrpclib.DateTime),), self.getRecentChanges)
30        yield ('WIKI_VIEW', ((int,),), self.getRPCVersionSupported)
31        yield ('WIKI_VIEW', ((str, str), (str, str, int),), self.getPage)
32        yield ('WIKI_VIEW', ((str, str, int),), self.getPage, 'getPageVersion')
33        yield ('WIKI_VIEW', ((str, str), (str, str, int)), self.getPageHTML)
34        yield ('WIKI_VIEW', ((str, str), (str, str, int)), self.getPageHTML, 'getPageHTMLVersion')
35        yield ('WIKI_VIEW', ((list,),), self.getAllPages)
36        yield ('WIKI_VIEW', ((dict, str), (dict, str, int)), self.getPageInfo)
37        yield ('WIKI_VIEW', ((dict, str, int),), self.getPageInfo, 'getPageInfoVersion')
[478]38        yield ('WIKI_CREATE', ((bool, str, str, dict),), self.putPage)
[229]39        yield ('WIKI_VIEW', ((list, str),), self.listAttachments)
40        yield ('WIKI_VIEW', ((xmlrpclib.Binary, str),), self.getAttachment)
[1188]41        yield ('WIKI_MODIFY', ((bool, str, xmlrpclib.Binary),), self.putAttachment)
42        yield ('WIKI_MODIFY', ((bool, str, str, str, xmlrpclib.Binary),
43                               (bool, str, str, str, xmlrpclib.Binary, bool)),
44                               self.putAttachmentEx)
[820]45        yield ('WIKI_DELETE', ((bool, str),), self.deleteAttachment)
[229]46        yield ('WIKI_VIEW', ((list, str),), self.listLinks)
[1161]47        yield ('WIKI_VIEW', ((str, str),), self.wikiToHtml)
[229]48
[222]49    def _page_info(self, name, time, author, version):
50        return dict(name=name, lastModified=xmlrpclib.DateTime(int(time)),
51                    author=author, version=int(version))
52
[808]53    def getRecentChanges(self, req, since):
[225]54        """ Get list of changed pages since timestamp """
[1188]55        since = to_timestamp(since)
[222]56        db = self.env.get_db_cnx()
57        cursor = db.cursor()
58        cursor.execute('SELECT name, max(time), author, version FROM wiki'
[291]59                       ' WHERE time >= %s GROUP BY name ORDER BY max(time) DESC', (since,))
[222]60        result = []
61        for name, time, author, version in cursor:
62            result.append(self._page_info(name, time, author, version))
63        return result
64
[808]65    def getRPCVersionSupported(self, req):
[225]66        """ Returns 2 with this version of the Trac API. """
[222]67        return 2
68
[808]69    def getPage(self, req, pagename, version=None):
[223]70        """ Get the raw Wiki text of page, latest version. """
[222]71        page = WikiPage(self.env, pagename, version)
72        if page.exists:
73            return page.text
74        else:
75            msg = 'Wiki page "%s" does not exist' % pagename
76            if version is not None:
77                msg += ' at version %s' % version
78            raise xmlrpclib.Fault(0, msg)
79
[225]80    def getPageHTML(self, req, pagename, version=None):
[223]81        """ Return page in rendered HTML, latest version. """
[1070]82        text = self.getPage(req, pagename, version)
[225]83        html = wiki_to_html(text, self.env, req, absurls=1)
84        return '<html><body>%s</body></html>' % html
[222]85
[808]86    def getAllPages(self, req):
[225]87        """ Returns a list of all pages. The result is an array of utf8 pagenames. """
[222]88        return list(self.wiki.get_pages())
89
[808]90    def getPageInfo(self, req, pagename, version=None):
[225]91        """ Returns information about the given page. """
[222]92        page = WikiPage(self.env, pagename, version)
93        if page.exists:
[292]94            last_update = page.get_history().next()
95            return self._page_info(page.name, last_update[1], last_update[2],
[222]96                                   page.version)
97
[225]98    def putPage(self, req, pagename, content, attributes):
99        """ writes the content of the page. """
100        page = WikiPage(self.env, pagename)
101        if page.readonly:
102            req.perm.assert_permission('WIKI_ADMIN')
103        elif not page.exists:
104            req.perm.assert_permission('WIKI_CREATE')
105        else:
106            req.perm.assert_permission('WIKI_MODIFY')
107
108        page.text = content
109        if req.perm.has_permission('WIKI_ADMIN'):
110            page.readonly = attributes.get('readonly') and 1 or 0
111
112        page.save(attributes.get('author', req.authname),
113                  attributes.get('comment'),
114                  req.remote_addr)
115        return True
116
[808]117    def listAttachments(self, req, pagename):
[225]118        """ Lists attachments on a given page. """
119        return [pagename + '/' + a.filename for a in Attachment.select(self.env, 'wiki', pagename)]
120
[808]121    def getAttachment(self, req, path):
[225]122        """ returns the content of an attachment. """
123        pagename, filename = posixpath.split(path)
124        attachment = Attachment(self.env, 'wiki', pagename, filename)
125        return xmlrpclib.Binary(attachment.open().read())
126
[1188]127    def putAttachment(self, req, path, data):
128        """ (over)writes an attachment. Returns True if successful.
129       
130        This method is compatible with WikiRPC.  `putAttachmentEx` has a more
131        extensive set of (Trac-specific) features. """
[225]132        pagename, filename = posixpath.split(path)
[1188]133        self.putAttachmentEx(req, pagename, filename, None, data)
134        return True
135
136    def putAttachmentEx(self, req, pagename, filename, description, data, replace=True):
137        """ Attach a file to a Wiki page. Returns the (possibly transformed)
138        filename of the attachment.
139       
140        Use this method if you don't care about WikiRPC compatibility. """
[225]141        if not WikiPage(self.env, pagename).exists:
142            raise TracError, 'Wiki page "%s" does not exist' % pagename
[820]143        if replace:
144            try:
145                attachment = Attachment(self.env, 'wiki', pagename, filename)
146                attachment.delete()
147            except TracError:
148                pass
[225]149        attachment = Attachment(self.env, 'wiki', pagename)
[820]150        attachment.author = req.authname or 'anonymous'
[1188]151        attachment.description = description
[225]152        attachment.insert(filename, StringIO(data.data), len(data.data))
[1188]153        return attachment.filename
[820]154
155    def deleteAttachment(self, req, path):
156        """ Delete an attachment. """
157        pagename, filename = posixpath.split(path)
158        if not WikiPage(self.env, pagename).exists:
159            raise TracError, 'Wiki page "%s" does not exist' % pagename
160        attachment = Attachment(self.env, 'wiki', pagename, filename)
161        attachment.delete()
[225]162        return True
163
[808]164    def listLinks(self, req, pagename):
[225]165        """ ''Not implemented'' """
[246]166        return []
[1161]167
168    def wikiToHtml(self, req, text):
169        """ Render arbitrary Wiki text as HTML. """
[1735]170        return unicode(wiki_to_html(text, self.env, req, absurls=1))
Note: See TracBrowser for help on using the repository browser.