def createSyncPage(self, page_name): normalised_name = normalise_pagename(page_name, self.prefix) if normalised_name is None: return None page = Page(self.request, page_name) revno = page.get_real_rev() if revno == 99999999: # I love sane in-band signalling return None return SyncPage(normalised_name, local_rev=revno, local_name=page_name, local_deleted=not page.exists())
def _index_page_rev(self, request, connection, pagename, revno, mode='update'): """ Index a page revision. @param request: request suitable for indexing @param connection: the Indexer connection object @param pagename: the page name @param revno: page revision number (int) @param mode: 'add' = just add, no checks 'update' = check if already in index and update if needed (mtime) """ page = Page(request, pagename, rev=revno) request.page = page # XXX for what is this needed? wikiname = request.cfg.interwikiname or u"Self" revision = str(page.get_real_rev()) itemid = "%s:%s:%s" % (wikiname, pagename, revision) mtime = page.mtime_usecs() doc = self._get_document(connection, itemid, mtime, mode) logging.debug("%s %s %r" % (pagename, revision, doc)) if doc: mimetype = 'text/%s' % page.pi['format'] # XXX improve this fields = {} fields['wikiname'] = wikiname fields['pagename'] = pagename fields['attachment'] = '' # this is a real page, not an attachment fields['mtime'] = str(mtime) fields['revision'] = revision fields['title'] = pagename fields['content'] = page.get_raw_body() fields['lang'], fields['stem_lang'] = self._get_languages(page) fields['author'] = page.edit_info().get('editor', '?') multivalued_fields = {} multivalued_fields['mimetype'] = [ mt for mt in [mimetype] + mimetype.split('/') ] multivalued_fields['domain'] = self._get_domains(page) multivalued_fields['linkto'] = page.getPageLinks(request) multivalued_fields['category'] = self._get_categories(page) self._add_fields_to_document(request, doc, fields, multivalued_fields) try: connection.replace(doc) except xappy.IndexerError, err: logging.warning("IndexerError at %r %r %r (%s)" % (wikiname, pagename, revision, str(err)))
def createSyncPage(self, page_name): normalised_name = normalise_pagename(page_name, self.prefix) if normalised_name is None: return None page = Page(self.request, page_name) revno = page.get_real_rev() if revno == 99999999: # I love sane in-band signalling return None return SyncPage(normalised_name, local_rev=revno, local_name=page_name, local_deleted=not page.exists())
def _index_page_rev(self, request, connection, pagename, revno, mode='update'): """ Index a page revision. @param request: request suitable for indexing @param connection: the Indexer connection object @param pagename: the page name @param revno: page revision number (int) @param mode: 'add' = just add, no checks 'update' = check if already in index and update if needed (mtime) """ page = Page(request, pagename, rev=revno) request.page = page # XXX for what is this needed? wikiname = request.cfg.interwikiname or u"Self" revision = str(page.get_real_rev()) itemid = "%s:%s:%s" % (wikiname, pagename, revision) mtime = page.mtime_usecs() doc = self._get_document(connection, itemid, mtime, mode) logging.debug("%s %s %r" % (pagename, revision, doc)) if doc: mimetype = 'text/%s' % page.pi['format'] # XXX improve this fields = {} fields['wikiname'] = wikiname fields['pagename'] = pagename fields['attachment'] = '' # this is a real page, not an attachment fields['mtime'] = str(mtime) fields['revision'] = revision fields['title'] = pagename fields['content'] = page.get_raw_body() fields['lang'], fields['stem_lang'] = self._get_languages(page) fields['author'] = page.edit_info().get('editor', '?') multivalued_fields = {} multivalued_fields['mimetype'] = [mt for mt in [mimetype] + mimetype.split('/')] multivalued_fields['domain'] = self._get_domains(page) multivalued_fields['linkto'] = page.getPageLinks(request) multivalued_fields['category'] = self._get_categories(page) self._add_fields_to_document(request, doc, fields, multivalued_fields) try: connection.replace(doc) except xappy.IndexerError, err: logging.warning("IndexerError at %r %r %r (%s)" % ( wikiname, pagename, revision, str(err)))
def execute(pagename, request): form = values_to_form(request.values) util = form.get('util', [None])[0] if util == "format": txt = form.get('text', [None])[0] request.write(format_wikitext(request, txt)) elif util == "getTemplate": template = form.get('name', [None])[0] template_page = wikiutil.unquoteWikiname(template) if request.user.may.read(template_page): Page(request, template_page).send_raw() elif util == "newPage": page = form.get('page', [None])[0] content = form.get('content', [""])[0] request.content_type = "application/json" if request.environ['REQUEST_METHOD'] != 'POST': return if not page: msg = "Page name not defined!" json.dump(dict(status="error", msg=msg), request) return if not request.user.may.write(page): msg = "You are not allowed to edit this page" json.dump(dict(status="error", msg=msg), request) return p = Page(request, page) if p.exists(): msg = "Page already exists" json.dump(dict(status="error", msg=msg), request) return editor = PageEditor(request, page) msg = editor.saveText(content, p.get_real_rev()) json.dump(dict(status="ok", msg=msg), request) elif util == "getProperties": request.content_type = "application/json" key = form.get('key', [''])[0] json.dump(get_properties(request, key), request) return elif util == "uploadFile": request.content_type = "application/json" if not request.user.may.write(pagename): msg = u"You are not allowed to edit this page!" json.dump(dict(status="error", msg=msg), request) request.status_code = 403 return from MoinMoin.action.AttachFile import add_attachment, AttachmentAlreadyExists try: overwrite = int(form.get('overwrite', ['0'])[0]) except: overwrite = 0 response = dict(success=list(), failed=list()) for name in request.files: _file = request.files.get(name) filename = _file.filename try: t, s = add_attachment(request, pagename, filename, _file.stream, overwrite=overwrite) response['success'].append(filename) except AttachmentAlreadyExists: response['failed'].append(filename) json.dump(response, request) return elif util == "getAttachments": request.content_type = "application/json" from MoinMoin.action.AttachFile import _get_files, getAttachUrl files = _get_files(request, pagename) response = [] for name in files: response.append( dict(url=getAttachUrl(pagename, name, request), name=name)) json.dump(response, request) return
def execute(pagename, request): """ Handle "action=diff" checking for either a "rev=formerrevision" parameter or rev1 and rev2 parameters """ if not request.user.may.read(pagename): Page(request, pagename).send_page() return try: date = request.values['date'] try: date = long(date) # must be long for py 2.2.x except StandardError: date = 0 except KeyError: date = 0 try: rev1 = int(request.values.get('rev1', -1)) except StandardError: rev1 = 0 try: rev2 = int(request.values.get('rev2', 0)) except StandardError: rev2 = 0 if rev1 == -1 and rev2 == 0: rev1 = request.rev if rev1 is None: rev1 = -1 # spacing flag? ignorews = int(request.values.get('ignorews', 0)) _ = request.getText # get a list of old revisions, and back out if none are available currentpage = Page(request, pagename) currentrev = currentpage.current_rev() if currentrev < 2: request.theme.add_msg(_("No older revisions available!"), "error") currentpage.send_page() return if date: # this is how we get called from RecentChanges rev1 = 0 log = editlog.EditLog(request, rootpagename=pagename) for line in log.reverse(): if date >= line.ed_time_usecs and int(line.rev) != 99999999: rev1 = int(line.rev) break else: rev1 = 1 rev2 = 0 if rev1 > 0 and rev2 > 0 and rev1 > rev2 or rev1 == 0 and rev2 > 0: rev1, rev2 = rev2, rev1 if rev1 == -1: oldrev = currentrev - 1 oldpage = Page(request, pagename, rev=oldrev) elif rev1 == 0: oldrev = currentrev oldpage = currentpage else: oldrev = rev1 oldpage = Page(request, pagename, rev=oldrev) if rev2 == 0: newrev = currentrev newpage = currentpage else: newrev = rev2 newpage = Page(request, pagename, rev=newrev) oldlog = oldpage.editlog_entry() newlog = newpage.editlog_entry() if not oldlog or not newlog: # We use "No log entries found." msg because we already have i18n # for that. Better would "At least one log entry was not found.". request.theme.add_msg(_("No log entries found."), "error") currentpage.send_page() return edit_count = abs(newrev - oldrev) # Start output # This action generates content in the user language request.setContentLanguage(request.lang) request.theme.send_title(_('Diff for "%s"') % (pagename, ), pagename=pagename, allow_doubleclick=1) f = request.formatter request.write(f.div(1, id="content")) oldrev = oldpage.get_real_rev() newrev = newpage.get_real_rev() title = _('Differences between revisions %d and %d') % (oldrev, newrev) if edit_count > 1: title += ' ' + _('(spanning %d versions)') % (edit_count, ) title = f.text(title) page_url = wikiutil.escape(currentpage.url(request), True) def enabled(val): return not val and u' disabled="disabled"' or u'' revert_html = "" if request.user.may.revert(pagename): revert_html = """ <form action="%s" method="get"> <div style="text-align:center"> <input name="action" value="revert" type="hidden"> <input name="rev" value="%d" type="hidden"> <input value="%s" type="submit"%s> </div> </form> """ % (page_url, rev2, _("Revert to this revision"), enabled(newrev < currentrev)) other_diff_button_html = """ <td style="border:0;"> <form action="%s" method="get"> <div style="text-align:%s"> <input name="action" value="diff" type="hidden"> <input name="rev1" value="%d" type="hidden"> <input name="rev2" value="%d" type="hidden"> <input value="%s" type="submit"%s> </div> </form> </td> """ navigation_html = """ <span class="diff-header">%%s</span> <table class="diff"> <tr> %(button)s <td style="border:0"> %%s </td> %(button)s </tr> </table> """ % {'button': other_diff_button_html} prev_oldrev = (oldrev > 1) and (oldrev - 1) or 1 next_oldrev = (oldrev < currentrev) and (oldrev + 1) or currentrev prev_newrev = (newrev > 1) and (newrev - 1) or 1 next_newrev = (newrev < currentrev) and (newrev + 1) or currentrev navigation_html = navigation_html % (title, page_url, "left", prev_oldrev, oldrev, _("Previous change"), enabled(oldrev > 1), revert_html, page_url, "right", newrev, next_newrev, _("Next change"), enabled(newrev < currentrev), ) request.write(f.rawHTML(navigation_html)) def rev_nav_link(enabled, old_rev, new_rev, caption, css_classes, enabled_title, disabled_title): if enabled: return currentpage.link_to(request, on=1, querystr={ 'action': 'diff', 'rev1': old_rev, 'rev2': new_rev, }, css_class="diff-nav-link %s" % css_classes, title=enabled_title) + request.formatter.text(caption) + currentpage.link_to(request, on=0) else: return '<span class="diff-no-nav-link %(css_classes)s" title="%(disabled_title)s">%(caption)s</span>' % { 'css_classes': css_classes, 'disabled_title': disabled_title, 'caption': caption, } rev_info_html = """ <div class="diff-info diff-info-header">%%(rev_first_link)s %%(rev_prev_link)s %(rev_header)s %%(rev_next_link)s %%(rev_last_link)s</div> <div class="diff-info diff-info-rev-size"><span class="diff-info-caption">%(rev_size_caption)s:</span> <span class="diff-info-value">%%(rev_size)d</span></div> <div class="diff-info diff-info-rev-author"><span class="diff-info-caption">%(rev_author_caption)s:</span> <span class="diff-info-value">%%(rev_author)s</span></div> <div class="diff-info diff-info-rev-comment"><span class="diff-info-caption">%(rev_comment_caption)s:</span> <span class="diff-info-value">%%(rev_comment)s</span></div> """ % { 'rev_header': _('Revision %(rev)d as of %(date)s'), 'rev_size_caption': _('Size'), 'rev_author_caption': _('Editor'), 'rev_ts_caption': _('Date'), 'rev_comment_caption': _('Comment'), } rev_info_old_html = rev_info_html % { 'rev_first_link': rev_nav_link(oldrev > 1, 1, newrev, u'\u21e4', 'diff-first-link diff-old-rev', _('Diff with oldest revision in left pane'), _("No older revision available for diff")), 'rev_prev_link': rev_nav_link(oldrev > 1, prev_oldrev, newrev, u'\u2190', 'diff-prev-link diff-old-rev', _('Diff with older revision in left pane'), _("No older revision available for diff")), 'rev_next_link': rev_nav_link((oldrev < currentrev) and (next_oldrev < newrev), next_oldrev, newrev, u'\u2192', 'diff-next-link diff-old-rev', _('Diff with newer revision in left pane'), _("Can't change to revision newer than in right pane")), 'rev_last_link': '', 'rev': oldrev, 'rev_size': oldpage.size(), 'rev_author': oldlog.getEditor(request) or _('N/A'), 'date': request.user.getFormattedDateTime(wikiutil.version2timestamp(oldlog.ed_time_usecs)) or _('N/A'), 'rev_comment': wikiutil.escape(oldlog.comment) or '', } rev_info_new_html = rev_info_html % { 'rev_first_link': '', 'rev_prev_link': rev_nav_link((newrev > 1) and (oldrev < prev_newrev), oldrev, prev_newrev, u'\u2190', 'diff-prev-link diff-new-rev', _('Diff with older revision in right pane'), _("Can't change to revision older than revision in left pane")), 'rev_next_link': rev_nav_link(newrev < currentrev, oldrev, next_newrev, u'\u2192', 'diff-next-link diff-new-rev', _('Diff with newer revision in right pane'), _("No newer revision available for diff")), 'rev_last_link': rev_nav_link(newrev < currentrev, oldrev, currentrev, u'\u21e5', 'diff-last-link diff-old-rev', _('Diff with newest revision in right pane'), _("No newer revision available for diff")), 'rev': newrev, 'rev_size': newpage.size(), 'rev_author': newlog.getEditor(request) or _('N/A'), 'date': request.user.getFormattedDateTime(wikiutil.version2timestamp(newlog.ed_time_usecs)) or _('N/A'), 'rev_comment': wikiutil.escape(newlog.comment) or '', } if request.user.show_fancy_diff: from MoinMoin.util import diff_html request.write(f.rawHTML(diff_html.diff(request, oldpage.get_raw_body(), newpage.get_raw_body(), old_top=rev_info_old_html, new_top=rev_info_new_html, old_top_class="diff-info", new_top_class="diff-info"))) newpage.send_page(count_hit=0, content_only=1, content_id="content-below-diff") else: request.write(f.rawHTML('<table class="diff"><tr><td class="diff-info">%s</td><td class="diff-info">%s</td></tr></table>' % (rev_info_old_html, rev_info_new_html))) from MoinMoin.util import diff_text lines = diff_text.diff(oldpage.getlines(), newpage.getlines()) if not lines: msg = f.text(" - " + _("No differences found!")) if edit_count > 1: msg = msg + f.paragraph(1) + f.text(_('The page was saved %(count)d times, though!') % { 'count': edit_count}) + f.paragraph(0) request.write(msg) else: if ignorews: request.write(f.text(_('(ignoring whitespace)')), f.linebreak()) else: qstr = {'action': 'diff', 'ignorews': '1', } if rev1: qstr['rev1'] = str(rev1) if rev2: qstr['rev2'] = str(rev2) request.write(f.paragraph(1), Page(request, pagename).link_to(request, text=_('Ignore changes in the amount of whitespace'), querystr=qstr, rel='nofollow'), f.paragraph(0)) request.write(f.preformatted(1)) for line in lines: if line[0] == "@": request.write(f.rule(1)) request.write(f.text(line + '\n')) request.write(f.preformatted(0)) request.write(f.div(0)) # end content div request.theme.send_footer(pagename) request.theme.send_closing_html()
def xmlrpc_getDiff(self, pagename, from_rev, to_rev, n_name=None): """ Gets the binary difference between two page revisions. @param pagename: unicode string qualifying the page name @param fromRev: integer specifying the source revision. May be None to refer to a virtual empty revision which leads to a diff containing the whole page. @param toRev: integer specifying the target revision. May be None to refer to the current revision. If the current revision is the same as fromRev, there will be a special error condition "ALREADY_CURRENT" @param n_name: do a tag check verifying that n_name was the normalised name of the last tag If both fromRev and toRev are None, this function acts similar to getPage, i.e. it will diff("",currentRev). @return: Returns a dict: * status (not a field, implicit, returned as Fault if not SUCCESS): * "SUCCESS" - if the diff could be retrieved successfully * "NOT_EXIST" - item does not exist * "FROMREV_INVALID" - the source revision is invalid * "TOREV_INVALID" - the target revision is invalid * "INTERNAL_ERROR" - there was an internal error * "INVALID_TAG" - the last tag does not match the supplied normalised name * "ALREADY_CURRENT" - this not merely an error condition. It rather means that there is no new revision to diff against which is a good thing while synchronisation. * current: the revision number of the current revision (not the one which was diff'ed against) * diff: Binary object that transports a zlib-compressed binary diff (see bdiff.py, taken from Mercurial) * conflict: if there is a conflict on the page currently """ from MoinMoin.util.bdiff import textdiff, compress from MoinMoin.wikisync import TagStore pagename = self._instr(pagename) if n_name is not None: n_name = self._instr(n_name) # User may read page? if not self.request.user.may.read(pagename): return self.notAllowedFault() def allowed_rev_type(data): if data is None: return True return isinstance(data, int) and data > 0 if not allowed_rev_type(from_rev): return xmlrpclib.Fault("FROMREV_INVALID", "Incorrect type for from_rev.") if not allowed_rev_type(to_rev): return xmlrpclib.Fault("TOREV_INVALID", "Incorrect type for to_rev.") currentpage = Page(self.request, pagename) if not currentpage.exists(): return xmlrpclib.Fault("NOT_EXIST", "Page does not exist.") revisions = currentpage.getRevList() if from_rev is not None and from_rev not in revisions: return xmlrpclib.Fault("FROMREV_INVALID", "Unknown from_rev.") if to_rev is not None and to_rev not in revisions: return xmlrpclib.Fault("TOREV_INVALID", "Unknown to_rev.") # use lambda to defer execution in the next lines if from_rev is None: oldcontents = lambda: "" else: oldpage = Page(self.request, pagename, rev=from_rev) oldcontents = lambda: oldpage.get_raw_body_str() if to_rev is None: newpage = currentpage newcontents = lambda: currentpage.get_raw_body_str() else: newpage = Page(self.request, pagename, rev=to_rev) newcontents = lambda: newpage.get_raw_body_str() if oldcontents() and oldpage.get_real_rev() == newpage.get_real_rev(): return xmlrpclib.Fault("ALREADY_CURRENT", "There are no changes.") if n_name is not None: tags = TagStore(newpage) last_tag = tags.get_last_tag() if last_tag is not None and last_tag.normalised_name != n_name: return xmlrpclib.Fault( "INVALID_TAG", "The used tag is incorrect because the normalised name does not match." ) newcontents = newcontents() conflict = wikiutil.containsConflictMarker(newcontents) diffblob = xmlrpclib.Binary( compress(textdiff(oldcontents(), newcontents))) return { "conflict": conflict, "diff": diffblob, "diffversion": 1, "current": currentpage.get_real_rev() }
def do_diff(pagename, request): """ Handle "action=diff" checking for either a "rev=formerrevision" parameter or rev1 and rev2 parameters """ if not request.user.may.read(pagename): Page(request, pagename).send_page(request) return try: date = request.form['date'][0] try: date = long(date) # must be long for py 2.2.x except StandardError: date = 0 except KeyError: date = 0 try: rev1 = request.form['rev1'][0] try: rev1 = int(rev1) except StandardError: rev1 = 0 except KeyError: rev1 = -1 try: rev2 = request.form['rev2'][0] try: rev2 = int(rev2) except StandardError: rev2 = 0 except KeyError: rev2 = 0 if rev1 == -1 and rev2 == 0: try: rev1 = request.form['rev'][0] try: rev1 = int(rev1) except StandardError: rev1 = -1 except KeyError: rev1 = -1 # spacing flag? try: ignorews = int(request.form['ignorews'][0]) except (KeyError, ValueError, TypeError): ignorews = 0 _ = request.getText # get a list of old revisions, and back out if none are available currentpage = Page(request, pagename) revisions = currentpage.getRevList() if len(revisions) < 2: currentpage.send_page(request, msg=_("No older revisions available!")) return if date: # this is how we get called from RecentChanges rev1 = 0 log = editlog.EditLog(request, rootpagename=pagename) for line in log.reverse(): if date >= line.ed_time_usecs and int(line.rev) != 99999999: rev1 = int(line.rev) break else: rev1 = 1 rev2 = 0 # Start output # This action generate content in the user language request.setContentLanguage(request.lang) request.http_headers() wikiutil.send_title(request, _('Diff for "%s"') % (pagename,), pagename=pagename) if (rev1>0 and rev2>0 and rev1>rev2) or (rev1==0 and rev2>0): rev1,rev2 = rev2,rev1 oldrev1,oldcount1 = None,0 oldrev2,oldcount2 = None,0 # get the filename of the version to compare to edit_count = 0 for rev in revisions: edit_count += 1 if rev <= rev1: oldrev1,oldcount1 = rev,edit_count if rev2 and rev >= rev2: oldrev2,oldcount2 = rev,edit_count if (oldrev1 and oldrev2) or (oldrev1 and not rev2): break if rev1 == -1: oldpage = Page(request, pagename, rev=revisions[1]) oldcount1 = oldcount1 - 1 elif rev1 == 0: oldpage = currentpage # oldcount1 is still on init value 0 else: if oldrev1: oldpage = Page(request, pagename, rev=oldrev1) else: oldpage = Page(request, "$EmptyPage$") # hack oldpage.set_raw_body("") # avoid loading from disk oldrev1 = 0 # XXX if rev2 == 0: newpage = currentpage # oldcount2 is still on init value 0 else: if oldrev2: newpage = Page(request, pagename, rev=oldrev2) else: newpage = Page(request, "$EmptyPage$") # hack newpage.set_raw_body("") # avoid loading from disk oldrev2 = 0 # XXX edit_count = abs(oldcount1 - oldcount2) # this should use the formatter, but there is none? request.write('<div id="content">\n') # start content div request.write('<p class="diff-header">') request.write(_('Differences between revisions %d and %d') % (oldpage.get_real_rev(), newpage.get_real_rev())) if edit_count > 1: request.write(' ' + _('(spanning %d versions)') % (edit_count,)) request.write('</p>') if request.user.show_fancy_diff: from MoinMoin.util.diff import diff request.write(diff(request, oldpage.get_raw_body(), newpage.get_raw_body())) newpage.send_page(request, count_hit=0, content_only=1, content_id="content-below-diff") else: lines = wikiutil.linediff(oldpage.getlines(), newpage.getlines()) if not lines: msg = _("No differences found!") if edit_count > 1: msg = msg + '<p>' + _('The page was saved %(count)d times, though!') % { 'count': edit_count} request.write(msg) else: if ignorews: request.write(_('(ignoring whitespace)') + '<br>') else: qstr = 'action=diff&ignorews=1' if rev1: qstr = '%s&rev1=%s' % (qstr, rev1) if rev2: qstr = '%s&rev2=%s' % (qstr, rev2) request.write(Page(request, pagename).link_to(request, text=_('Ignore changes in the amount of whitespace'), querystr=qstr) + '<p>') request.write('<pre>') for line in lines: if line[0] == "@": request.write('<hr>') request.write(wikiutil.escape(line)+'\n') request.write('</pre>') request.write('</div>\n') # end content div wikiutil.send_footer(request, pagename, showpage=1)
def xmlrpc_getDiff(self, pagename, from_rev, to_rev, n_name=None): """ Gets the binary difference between two page revisions. @param pagename: unicode string qualifying the page name @param fromRev: integer specifying the source revision. May be None to refer to a virtual empty revision which leads to a diff containing the whole page. @param toRev: integer specifying the target revision. May be None to refer to the current revision. If the current revision is the same as fromRev, there will be a special error condition "ALREADY_CURRENT" @param n_name: do a tag check verifying that n_name was the normalised name of the last tag If both fromRev and toRev are None, this function acts similar to getPage, i.e. it will diff("",currentRev). @return: Returns a dict: * status (not a field, implicit, returned as Fault if not SUCCESS): * "SUCCESS" - if the diff could be retrieved successfully * "NOT_EXIST" - item does not exist * "FROMREV_INVALID" - the source revision is invalid * "TOREV_INVALID" - the target revision is invalid * "INTERNAL_ERROR" - there was an internal error * "INVALID_TAG" - the last tag does not match the supplied normalised name * "ALREADY_CURRENT" - this not merely an error condition. It rather means that there is no new revision to diff against which is a good thing while synchronisation. * current: the revision number of the current revision (not the one which was diff'ed against) * diff: Binary object that transports a zlib-compressed binary diff (see bdiff.py, taken from Mercurial) * conflict: if there is a conflict on the page currently """ from MoinMoin.util.bdiff import textdiff, compress from MoinMoin.wikisync import TagStore pagename = self._instr(pagename) if n_name is not None: n_name = self._instr(n_name) # User may read page? if not self.request.user.may.read(pagename): return self.notAllowedFault() def allowed_rev_type(data): if data is None: return True return isinstance(data, int) and data > 0 if not allowed_rev_type(from_rev): return xmlrpclib.Fault("FROMREV_INVALID", "Incorrect type for from_rev.") if not allowed_rev_type(to_rev): return xmlrpclib.Fault("TOREV_INVALID", "Incorrect type for to_rev.") currentpage = Page(self.request, pagename) if not currentpage.exists(): return xmlrpclib.Fault("NOT_EXIST", "Page does not exist.") revisions = currentpage.getRevList() if from_rev is not None and from_rev not in revisions: return xmlrpclib.Fault("FROMREV_INVALID", "Unknown from_rev.") if to_rev is not None and to_rev not in revisions: return xmlrpclib.Fault("TOREV_INVALID", "Unknown to_rev.") # use lambda to defer execution in the next lines if from_rev is None: oldcontents = lambda: "" else: oldpage = Page(self.request, pagename, rev=from_rev) oldcontents = lambda: oldpage.get_raw_body_str() if to_rev is None: newpage = currentpage newcontents = lambda: currentpage.get_raw_body_str() else: newpage = Page(self.request, pagename, rev=to_rev) newcontents = lambda: newpage.get_raw_body_str() if oldcontents() and oldpage.get_real_rev() == newpage.get_real_rev(): return xmlrpclib.Fault("ALREADY_CURRENT", "There are no changes.") if n_name is not None: tags = TagStore(newpage) last_tag = tags.get_last_tag() if last_tag is not None and last_tag.normalised_name != n_name: return xmlrpclib.Fault("INVALID_TAG", "The used tag is incorrect because the normalised name does not match.") newcontents = newcontents() conflict = wikiutil.containsConflictMarker(newcontents) diffblob = xmlrpclib.Binary(compress(textdiff(oldcontents(), newcontents))) return {"conflict": conflict, "diff": diffblob, "diffversion": 1, "current": currentpage.get_real_rev()}
def execute(pagename, request): form = values_to_form(request.values) util = form.get('util', [None])[0] if util == "format": txt = form.get('text', [None])[0] request.write(format_wikitext(request, txt)) elif util == "getTemplate": template = form.get('name', [None])[0] template_page = wikiutil.unquoteWikiname(template) if request.user.may.read(template_page): Page(request, template_page).send_raw() elif util == "newPage": page = form.get('page', [None])[0] content = form.get('content', [""])[0] request.content_type = "application/json" if request.environ['REQUEST_METHOD'] != 'POST': return if not page: msg = "Page name not defined!" json.dump(dict(status="error", msg=msg), request) return if not request.user.may.write(page): msg = "You are not allowed to edit this page" json.dump(dict(status="error", msg=msg), request) return p = Page(request, page) if p.exists(): msg = "Page already exists" json.dump(dict(status="error", msg=msg), request) return editor = PageEditor(request, page) msg = editor.saveText(content, p.get_real_rev()) json.dump(dict(status="ok", msg=msg), request) elif util == "getProperties": request.content_type = "application/json" key = form.get('key', [''])[0] json.dump(get_properties(request, key), request) return elif util == "uploadFile": request.content_type = "application/json" if not request.user.may.write(pagename): msg = u"You are not allowed to edit this page!" json.dump(dict(status="error", msg=msg), request) request.status_code = 403 return from MoinMoin.action.AttachFile import add_attachment, AttachmentAlreadyExists try: overwrite = int(form.get('overwrite', ['0'])[0]) except: overwrite = 0 response = dict(success=list(), failed=list()) for name in request.files: _file = request.files.get(name) filename = _file.filename try: t,s = add_attachment(request, pagename, filename, _file.stream, overwrite=overwrite) response['success'].append(filename) except AttachmentAlreadyExists: response['failed'].append(filename) json.dump(response, request) return elif util == "getAttachments": request.content_type = "application/json" from MoinMoin.action.AttachFile import _get_files, getAttachUrl files = _get_files(request, pagename) response = [] for name in files: response.append(dict(url=getAttachUrl(pagename, name, request),name=name)) json.dump(response, request) return
def execute(pagename, request): """ Handle "action=diff" checking for either a "rev=formerrevision" parameter or rev1 and rev2 parameters """ if not request.user.may.read(pagename): Page(request, pagename).send_page() return try: date = request.values['date'] try: date = long(date) # must be long for py 2.2.x except StandardError: date = 0 except KeyError: date = 0 try: rev1 = int(request.values.get('rev1', -1)) except StandardError: rev1 = 0 try: rev2 = int(request.values.get('rev2', 0)) except StandardError: rev2 = 0 if rev1 == -1 and rev2 == 0: rev1 = request.rev if rev1 is None: rev1 = -1 # spacing flag? ignorews = int(request.values.get('ignorews', 0)) _ = request.getText # get a list of old revisions, and back out if none are available currentpage = Page(request, pagename) currentrev = currentpage.current_rev() if currentrev < 2: request.theme.add_msg(_("No older revisions available!"), "error") currentpage.send_page() return if date: # this is how we get called from RecentChanges rev1 = 0 log = editlog.EditLog(request, rootpagename=pagename) for line in log.reverse(): if date >= line.ed_time_usecs and int(line.rev) != 99999999: rev1 = int(line.rev) break else: rev1 = 1 rev2 = 0 if rev1 > 0 and rev2 > 0 and rev1 > rev2 or rev1 == 0 and rev2 > 0: rev1, rev2 = rev2, rev1 if rev1 == -1: oldrev = currentrev - 1 oldpage = Page(request, pagename, rev=oldrev) elif rev1 == 0: oldrev = currentrev oldpage = currentpage else: oldrev = rev1 oldpage = Page(request, pagename, rev=oldrev) if rev2 == 0: newrev = currentrev newpage = currentpage else: newrev = rev2 newpage = Page(request, pagename, rev=newrev) oldlog = oldpage.editlog_entry() newlog = newpage.editlog_entry() if not oldlog or not newlog: # We use "No log entries found." msg because we already have i18n # for that. Better would "At least one log entry was not found.". request.theme.add_msg(_("No log entries found."), "error") currentpage.send_page() return edit_count = abs(newrev - oldrev) # Start output # This action generates content in the user language request.setContentLanguage(request.lang) request.theme.send_title(_('Diff for "%s"') % (pagename, ), pagename=pagename, allow_doubleclick=1) f = request.formatter request.write(f.div(1, id="content")) oldrev = oldpage.get_real_rev() newrev = newpage.get_real_rev() title = _('Differences between revisions %d and %d') % (oldrev, newrev) if edit_count > 1: title += ' ' + _('(spanning %d versions)') % (edit_count, ) title = f.text(title) page_url = wikiutil.escape(currentpage.url(request), True) def enabled(val): return not val and u' disabled="disabled"' or u'' revert_html = "" if request.user.may.revert(pagename): revert_html = """ <form action="%s" method="get"> <div style="text-align:center"> <input name="action" value="revert" type="hidden"> <input name="rev" value="%d" type="hidden"> <input value="%s" type="submit"%s> </div> </form> """ % (page_url, rev2, _("Revert to this revision"), enabled(newrev < currentrev)) other_diff_button_html = """ <td style="border:0;"> <form action="%s" method="get"> <div style="text-align:%s"> <input name="action" value="diff" type="hidden"> <input name="rev1" value="%d" type="hidden"> <input name="rev2" value="%d" type="hidden"> <input value="%s" type="submit"%s> </div> </form> </td> """ navigation_html = """ <span class="diff-header">%%s</span> <table class="diff"> <tr> %(button)s <td style="border:0"> %%s </td> %(button)s </tr> </table> """ % { 'button': other_diff_button_html } prev_oldrev = (oldrev > 1) and (oldrev - 1) or 1 next_oldrev = (oldrev < currentrev) and (oldrev + 1) or currentrev prev_newrev = (newrev > 1) and (newrev - 1) or 1 next_newrev = (newrev < currentrev) and (newrev + 1) or currentrev navigation_html = navigation_html % ( title, page_url, "left", prev_oldrev, oldrev, _("Previous change"), enabled(oldrev > 1), revert_html, page_url, "right", newrev, next_newrev, _("Next change"), enabled(newrev < currentrev), ) request.write(f.rawHTML(navigation_html)) def rev_nav_link(enabled, old_rev, new_rev, caption, css_classes, enabled_title, disabled_title): if enabled: return currentpage.link_to( request, on=1, querystr={ 'action': 'diff', 'rev1': old_rev, 'rev2': new_rev, }, css_class="diff-nav-link %s" % css_classes, title=enabled_title) + request.formatter.text( caption) + currentpage.link_to(request, on=0) else: return '<span class="diff-no-nav-link %(css_classes)s" title="%(disabled_title)s">%(caption)s</span>' % { 'css_classes': css_classes, 'disabled_title': disabled_title, 'caption': caption, } rev_info_html = """ <div class="diff-info diff-info-header">%%(rev_first_link)s %%(rev_prev_link)s %(rev_header)s %%(rev_next_link)s %%(rev_last_link)s</div> <div class="diff-info diff-info-rev-size"><span class="diff-info-caption">%(rev_size_caption)s:</span> <span class="diff-info-value">%%(rev_size)d</span></div> <div class="diff-info diff-info-rev-author"><span class="diff-info-caption">%(rev_author_caption)s:</span> <span class="diff-info-value">%%(rev_author)s</span></div> <div class="diff-info diff-info-rev-comment"><span class="diff-info-caption">%(rev_comment_caption)s:</span> <span class="diff-info-value">%%(rev_comment)s</span></div> """ % { 'rev_header': _('Revision %(rev)d as of %(date)s'), 'rev_size_caption': _('Size'), 'rev_author_caption': _('Editor'), 'rev_ts_caption': _('Date'), 'rev_comment_caption': _('Comment'), } rev_info_old_html = rev_info_html % { 'rev_first_link': rev_nav_link(oldrev > 1, 1, newrev, u'\u21e4', 'diff-first-link diff-old-rev', _('Diff with oldest revision in left pane'), _("No older revision available for diff")), 'rev_prev_link': rev_nav_link(oldrev > 1, prev_oldrev, newrev, u'\u2190', 'diff-prev-link diff-old-rev', _('Diff with older revision in left pane'), _("No older revision available for diff")), 'rev_next_link': rev_nav_link( (oldrev < currentrev) and (next_oldrev < newrev), next_oldrev, newrev, u'\u2192', 'diff-next-link diff-old-rev', _('Diff with newer revision in left pane'), _("Can't change to revision newer than in right pane")), 'rev_last_link': '', 'rev': oldrev, 'rev_size': oldpage.size(), 'rev_author': oldlog.getEditor(request) or _('N/A'), 'date': request.user.getFormattedDateTime( wikiutil.version2timestamp(oldlog.ed_time_usecs)) or _('N/A'), 'rev_comment': wikiutil.escape(oldlog.comment) or '', } rev_info_new_html = rev_info_html % { 'rev_first_link': '', 'rev_prev_link': rev_nav_link( (newrev > 1) and (oldrev < prev_newrev), oldrev, prev_newrev, u'\u2190', 'diff-prev-link diff-new-rev', _('Diff with older revision in right pane'), _("Can't change to revision older than revision in left pane")), 'rev_next_link': rev_nav_link(newrev < currentrev, oldrev, next_newrev, u'\u2192', 'diff-next-link diff-new-rev', _('Diff with newer revision in right pane'), _("No newer revision available for diff")), 'rev_last_link': rev_nav_link(newrev < currentrev, oldrev, currentrev, u'\u21e5', 'diff-last-link diff-old-rev', _('Diff with newest revision in right pane'), _("No newer revision available for diff")), 'rev': newrev, 'rev_size': newpage.size(), 'rev_author': newlog.getEditor(request) or _('N/A'), 'date': request.user.getFormattedDateTime( wikiutil.version2timestamp(newlog.ed_time_usecs)) or _('N/A'), 'rev_comment': wikiutil.escape(newlog.comment) or '', } if request.user.show_fancy_diff: from MoinMoin.util import diff_html request.write( f.rawHTML( diff_html.diff(request, oldpage.get_raw_body(), newpage.get_raw_body(), old_top=rev_info_old_html, new_top=rev_info_new_html, old_top_class="diff-info", new_top_class="diff-info"))) newpage.send_page(count_hit=0, content_only=1, content_id="content-below-diff") else: request.write( f.rawHTML( '<table class="diff"><tr><td class="diff-info">%s</td><td class="diff-info">%s</td></tr></table>' % (rev_info_old_html, rev_info_new_html))) from MoinMoin.util import diff_text lines = diff_text.diff(oldpage.getlines(), newpage.getlines()) if not lines: msg = f.text(" - " + _("No differences found!")) if edit_count > 1: msg = msg + f.paragraph(1) + f.text( _('The page was saved %(count)d times, though!') % {'count': edit_count}) + f.paragraph(0) request.write(msg) else: if ignorews: request.write(f.text(_('(ignoring whitespace)')), f.linebreak()) else: qstr = { 'action': 'diff', 'ignorews': '1', } if rev1: qstr['rev1'] = str(rev1) if rev2: qstr['rev2'] = str(rev2) request.write( f.paragraph(1), Page(request, pagename).link_to( request, text=_('Ignore changes in the amount of whitespace'), querystr=qstr, rel='nofollow'), f.paragraph(0)) request.write(f.preformatted(1)) for line in lines: if line[0] == "@": request.write(f.rule(1)) request.write(f.text(line + '\n')) request.write(f.preformatted(0)) request.write(f.div(0)) # end content div request.theme.send_footer(pagename) request.theme.send_closing_html()
def execute(pagename, request): """ Handle "action=diff" checking for either a "rev=formerrevision" parameter or rev1 and rev2 parameters """ if not request.user.may.read(pagename): Page(request, pagename).send_page() return try: date = request.form['date'][0] try: date = long(date) # must be long for py 2.2.x except StandardError: date = 0 except KeyError: date = 0 try: rev1 = int(request.form.get('rev1', [-1])[0]) except StandardError: rev1 = 0 try: rev2 = int(request.form.get('rev2', [0])[0]) except StandardError: rev2 = 0 if rev1 == -1 and rev2 == 0: rev1 = request.rev if rev1 is None: rev1 = -1 # spacing flag? ignorews = int(request.form.get('ignorews', [0])[0]) _ = request.getText # get a list of old revisions, and back out if none are available currentpage = Page(request, pagename) currentrev = currentpage.current_rev() if currentrev < 2: request.theme.add_msg(_("No older revisions available!"), "error") currentpage.send_page() return if date: # this is how we get called from RecentChanges rev1 = 0 log = editlog.EditLog(request, rootpagename=pagename) for line in log.reverse(): if date >= line.ed_time_usecs and int(line.rev) != 99999999: rev1 = int(line.rev) break else: rev1 = 1 rev2 = 0 # Start output # This action generates content in the user language request.setContentLanguage(request.lang) request.emit_http_headers() request.theme.send_title(_('Diff for "%s"') % (pagename, ), pagename=pagename, allow_doubleclick=1) if rev1 > 0 and rev2 > 0 and rev1 > rev2 or rev1 == 0 and rev2 > 0: rev1, rev2 = rev2, rev1 if rev1 == -1: oldrev = currentrev - 1 oldpage = Page(request, pagename, rev=oldrev) elif rev1 == 0: oldrev = currentrev oldpage = currentpage else: oldrev = rev1 oldpage = Page(request, pagename, rev=oldrev) if rev2 == 0: newrev = currentrev newpage = currentpage else: newrev = rev2 newpage = Page(request, pagename, rev=newrev) edit_count = abs(newrev - oldrev) f = request.formatter request.write(f.div(1, id="content")) oldrev = oldpage.get_real_rev() newrev = newpage.get_real_rev() revlist = currentpage.getRevList() # code below assumes that the page exists and has at least # one revision in the revlist, just bail out if not. Users # shouldn't really run into this anyway. if not revlist: request.write(f.div(0)) # end content div request.theme.send_footer(pagename) request.theme.send_closing_html() return title = _('Differences between revisions %d and %d') % (oldrev, newrev) if edit_count > 1: title += ' ' + _('(spanning %d versions)') % (edit_count, ) title = f.text(title) # Revision list starts from 2... if oldrev == min(revlist): disable_prev = u' disabled="disabled"' else: disable_prev = u'' if newrev == max(revlist): disable_next = u' disabled="disabled"' else: disable_next = u'' page_url = wikiutil.escape(currentpage.url(request), True) revert_html = "" if request.user.may.revert(pagename): revert_html = """ <td style="border:0"> <form action="%s" method="get"> <div style="text-align:center"> <input name="action" value="revert" type="hidden"> <input name="rev" value="%d" type="hidden"> <input value="%s" type="submit"%s> </div> </form> </td> """ % (page_url, rev2, _("Revert to this revision"), disable_next) navigation_html = """ <span class="diff-header">%s</span> <table class="diff"> <tr> <td style="border:0"> <form action="%s" method="get"> <div style="text-align:left"> <input name="action" value="diff" type="hidden"> <input name="rev1" value="%d" type="hidden"> <input name="rev2" value="%d" type="hidden"> <input value="%s" type="submit"%s> </div> </form> </td> %s <td style="border:0"> <form action="%s" method="get"> <div style="text-align:right"> <input name="action" value="diff" type="hidden"> <input name="rev1" value="%d" type="hidden"> <input name="rev2" value="%d" type="hidden"> <input value="%s" type="submit"%s> </div> </form> </td> </tr> </table> """ % (title, page_url, oldrev - 1, oldrev, _("Previous change"), disable_prev, revert_html, page_url, newrev, newrev + 1, _("Next change"), disable_next, ) request.write(f.rawHTML(navigation_html)) if request.user.show_fancy_diff: from MoinMoin.util import diff_html request.write(f.rawHTML(diff_html.diff(request, oldpage.get_raw_body(), newpage.get_raw_body()))) newpage.send_page(count_hit=0, content_only=1, content_id="content-below-diff") else: from MoinMoin.util import diff_text lines = diff_text.diff(oldpage.getlines(), newpage.getlines()) if not lines: msg = f.text(" - " + _("No differences found!")) if edit_count > 1: msg = msg + f.paragraph(1) + f.text(_('The page was saved %(count)d times, though!') % { 'count': edit_count}) + f.paragraph(0) request.write(msg) else: if ignorews: request.write(f.text(_('(ignoring whitespace)')), f.linebreak()) else: qstr = {'action': 'diff', 'ignorews': '1', } if rev1: qstr['rev1'] = str(rev1) if rev2: qstr['rev2'] = str(rev2) request.write(f.paragraph(1), Page(request, pagename).link_to(request, text=_('Ignore changes in the amount of whitespace'), querystr=qstr, rel='nofollow'), f.paragraph(0)) request.write(f.preformatted(1)) for line in lines: if line[0] == "@": request.write(f.rule(1)) request.write(f.text(line + '\n')) request.write(f.preformatted(0)) request.write(f.div(0)) # end content div request.theme.send_footer(pagename) request.theme.send_closing_html()