def diff(title, from_rev, to_rev): """Show the differences between specified revisions.""" _ = current_app.gettext p = page.get_page(request, title) build = current_app.get_url from_url = build(view='revision', title=title, rev=from_rev) to_url = build(view='revision', title=title, rev=to_rev) a = werkzeug.html.a links = { 'link1': a(str(from_rev), href=from_url), 'link2': a(str(to_rev), href=to_url), 'link': a(werkzeug.html(title), href=current_app.get_url(title)), } message = werkzeug.html(_( 'Differences between revisions %(link1)s and %(link2)s ' 'of page %(link)s.')) % links diff_content = getattr(p, 'diff_content', None) if diff_content: from_text = current_app.storage.revision_text(p.title, from_rev) to_text = current_app.storage.revision_text(p.title, to_rev) content = diff_content(from_text, to_text, message) else: content = [werkzeug.html.p(werkzeug.html( _("Diff not available for this kind of pages.")))] special_title = _('Diff for "%(title)s"') % {'title': title} html = p.template('page_special.html', content=content, special_title=special_title) resp = response.WikiResponse(html, content_type='text/html') return resp
def view(title=None): _ = current_app.gettext if title is None: title = current_app.front_page p = page.get_page(request, title) try: content = p.view_content() except error.NotFoundErr: if current_app.fallback_url: url = current_app.fallback_url if '%s' in url: url = url % werkzeug.url_quote(title) else: url = "%s/%s" % (url, werkzeug.url_quote(title)) return response.redirect(url, code=303) if current_app.read_only: raise error.NotFoundErr(_("Page not found.")) url = current_app.get_url(title, 'edit', external=True) return response.redirect(url, code=303) html = p.template("page.html", content=content) dependencies = p.dependencies() etag = '/(%s)' % ','.join(dependencies) return response.response(request, title, html, etag=etag)
def history(title): """Display history of changes of a page.""" max_rev = -1 history = [] if title not in current_app.storage: raise error.NotFoundErr("Page not found.") p = page.get_page(request, title) make_url = current_app.get_url for rev, date, author, comment in current_app.storage.page_history(title): if max_rev < rev: max_rev = rev if rev > 0: date_url = make_url(view='diff', title=title, from_rev=rev - 1, to_rev=rev, ) else: date_url = make_url(view='revision', title=title, rev=rev, ) history.append((date, date_url, rev, author, comment)) html = p.template('history.html', history=history, date_html=page.date_html, parent=max_rev) resp = response.response(request, title, html, '/history') return resp
def undo(title): """Revert a change to a page.""" _ = current_app.gettext page.check_lock(current_app, title) rev = None for key in request.form: try: rev = int(key) except ValueError: pass author = request.get_author() if rev is not None: try: parent = int(request.form.get("parent")) except (ValueError, TypeError): parent = None current_app.index.update(current_app) if rev == 0: comment = _('Delete page %(title)s') % {'title': title} data = '' current_app.storage.delete_page(title, author, comment) else: comment = _('Undo of change %(rev)d of page %(title)s') % { 'rev': rev, 'title': title} data = current_app.storage.page_revision(title, rev - 1) current_app.storage.save_data(title, data, author, comment, parent) p = page.get_page(request, title) current_app.index.update_page(p, title, data=data) url = current_app.get_url(view='history', title=title, method='GET', force_external=True) return response.redirect(url, code=303)
def render(title): """Serve a thumbnail or otherwise rendered content.""" p = page.get_page(request, title) try: cache_filename, cache_mime = p.render_mime() render_func = p.render_cache if not current_app.cache: raise NotImplementedError() except (AttributeError, NotImplementedError): return download(title) cache_key = '/render/%s_%s' % (werkzeug.url_quote(title, safe=''), cache_filename) rev, dt, author, comment = current_app.storage.page_meta(title) cache_file = current_app.cache.open(cache_key, 'r') if (cache_file and dt > cache_file.modified) or not cache_file: cache_file = current_app.cache.open(cache_key, 'w') try: result_file = render_func(cache_file) except error.UnsupportedMediaTypeErr: return download(title) else: cache_file = current_app.cache.open(cache_key, 'r') resp = response.response(request, title, werkzeug.wrap_file(request.environ, cache_file), '/render', cache_mime, size=cache_file.length) resp.direct_passthrough = True return resp
def search(): """Serve the search results page.""" _ = current_app.gettext def highlight_html(m): return werkzeug.html.b(m.group(0), class_="highlight") def search_snippet(title, words): """Extract a snippet of text for search results.""" try: text = current_app.storage.page_text(title) except error.NotFoundErr: return '' regexp = re.compile("|".join(re.escape(w) for w in words), re.U | re.I) match = regexp.search(text) if match is None: return "" position = match.start() min_pos = max(position - 60, 0) max_pos = min(position + 60, len(text)) snippet = werkzeug.escape(text[min_pos:max_pos]) html = regexp.sub(highlight_html, snippet) return html def page_search(words, page, request): """Display the search results.""" h = werkzeug.html current_app.index.update(current_app) result = sorted(current_app.index.find(words), key=lambda x: -x[0]) yield werkzeug.html.p(h(_('%d page(s) containing all words:') % len(result))) yield '<ol id="hatta-search-results">' for number, (score, title) in enumerate(result): yield h.li(h.b(page.wiki_link(title)), ' ', h.i(str(score)), h.div(search_snippet(title, words), class_="hatta-snippet"), id_="search-%d" % (number + 1)) yield '</ol>' query = request.values.get('q', '').strip() p = page.get_page(request, '') if not query: url = current_app.get_url(view='all_pages', external=True) return response.redirect(url, code=303) words = tuple(current_app.index.split_text(query)) if not words: words = (query,) title = _('Searching for "%s"') % " ".join(words) content = page_search(words, p, request) html = p.template('page_special.html', content=content, special_title=title) return response.WikiResponse(html, content_type='text/html')
def backlinks(title): """Serve the page with backlinks.""" current_app.index.update(current_app) p = page.get_page(request, title) html = p.template('backlinks.html', pages=current_app.index.page_backlinks(title)) resp = response.WikiResponse(html, content_type='text/html') resp.set_etag('/+search/%d' % current_app.storage.repo_revision()) resp.make_conditional(request) return resp
def reindex(self, wiki, pages): with self.index.index_writer(self.name) as writer: with self.index.index_searcher(self.name) as searcher: for title in pages: writer.delete_by_term('title', title, searcher=searcher) for title in pages: p = page.get_page(None, title, wiki) self.reindex_page(p, title, writer) # print 'INDEXED', title self.empty = False rev = self.storage.repo_revision() self.set_last_revision(rev)
def all_pages(): """Show index of all pages in the current_app.""" _ = current_app.gettext p = page.get_page(request, '') html = p.template('list.html', pages=sorted(current_app.storage.all_pages()), class_='index', message=_('Index of all pages'), special_title=_('Page Index')) resp = response.WikiResponse(html, content_type='text/html') resp.set_etag('/+index/%d' % current_app.storage.repo_revision()) resp.make_conditional(request) return resp
def wanted(): """Show all pages that don't exist yet, but are linked.""" def _wanted_pages_list(): for refs, title in current_app.index.wanted_pages(): if not (parser.external_link(title) or title.startswith('+') or title.startswith(':')): yield refs, title p = page.get_page(request, '') html = p.template('wanted.html', pages=_wanted_pages_list()) resp = response.WikiResponse(html, content_type='text/html') resp.set_etag('/+wanted/%d' % current_app.storage.repo_revision()) resp.make_conditional(request) return resp
def edit(title, preview=None, captcha_error=None): page.check_lock(current_app, title) exists = title in current_app.storage p = page.get_page(request, title, wiki=current_app) html = p.render_editor(preview, captcha_error) if not exists: resp = response.WikiResponse(html, content_type="text/html", status=404) elif preview: resp = response.WikiResponse(html, content_type="text/html") else: resp = response.response(request, title, html, '/edit') resp.headers['Cache-Control'] = 'no-cache' return resp
def revision(title, rev): _ = current_app.gettext text = current_app.storage.revision_text(title, rev) link = werkzeug.html.a(werkzeug.html(title), href=current_app.get_url(title)) content = [ werkzeug.html.p( werkzeug.html( _('Content of revision %(rev)d of page %(title)s:')) % {'rev': rev, 'title': link}), werkzeug.html.pre(werkzeug.html(text)), ] special_title = _('Revision of "%(title)s"') % {'title': title} p = page.get_page(request, title) html = p.template('page_special.html', content=content, special_title=special_title) resp = response.response(request, title, html, rev=rev, etag='/old') return resp
def orphaned(): """Show all pages that don't have backlinks.""" _ = current_app.gettext p = page.get_page(request, '') orphaned = [ title for title in current_app.index.orphaned_pages() if title in current_app.storage ] html = p.template('list.html', pages=orphaned, class_='orphaned', message=_('List of pages with no links to them'), special_title=_('Orphaned pages')) resp = response.WikiResponse(html, content_type='text/html') resp.set_etag('/+orphaned/%d' % current_app.storage.repo_revision()) resp.make_conditional(request) return resp
def recent_changes(): """Serve the recent changes page.""" def _changes_list(): last = {} lastrev = {} count = 0 make_url = current_app.get_url for title, rev, date, author, comment in current_app.storage.history(): if (author, comment) == last.get(title, (None, None)): continue count += 1 if count > 100: break if rev > 0: date_url = make_url(view='diff', title=title, from_rev=rev - 1, to_rev=lastrev.get(title, rev), ) elif rev == 0: date_url = make_url(view='revision', title=title, rev=rev, ) else: date_url = make_url(view='history', title=title) last[title] = author, comment lastrev[title] = rev yield date, date_url, title, author, comment p = page.get_page(request, '') html = p.template('changes.html', changes=_changes_list(), date_html=page.date_html) resp = response.WikiResponse(html, content_type='text/html') resp.set_etag('/history/%d' % current_app.storage.repo_revision()) resp.make_conditional(request) return resp
def save(title): _ = current_app.gettext page.check_lock(current_app, title) url = current_app.get_url(title) if request.form.get('cancel'): if title not in current_app.storage: url = current_app.get_url(current_app.front_page) if request.form.get('preview'): text = request.form.get("text") if text is not None: lines = text.split('\n') else: lines = [werkzeug.html.p(werkzeug.html( _('No preview for binaries.')))] return edit(title, preview=lines) elif request.form.get('save'): if captcha and current_app.recaptcha_private_key: resp = captcha.submit( request.form.get('recaptcha_challenge_field', ''), request.form.get('recaptcha_response_field', ''), current_app.recaptcha_private_key, request.remote_addr) if not resp.is_valid: text = request.form.get("text", '') return edit(request, title, preview=text.split('\n'), captcha_error=response.error_code) comment = request.form.get("comment", "") if 'href="' in comment or 'http:' in comment: raise error.ForbiddenErr() author = request.get_author() text = request.form.get("text") try: parent = int(request.form.get("parent")) except (ValueError, TypeError): parent = None p = page.get_page(request, title) if text is not None: if title == current_app.locked_page: for link, label in p.extract_links(text): if title == link: raise error.ForbiddenErr( _("This page is locked.")) if text.strip() == '': current_app.storage.delete_page(title, author, comment) url = current_app.get_url(current_app.front_page) else: current_app.storage.save_text(title, text, author, comment, parent) else: text = '' upload = request.files.get('data') if upload and upload.stream and upload.filename: f = upload.stream current_app.storage.save_data(title, f.read(), author, comment, parent) else: current_app.storage.delete_page(title, author, comment) url = current_app.get_url(current_app.front_page) current_app.index.update(current_app) resp = response.redirect(url, code=303) resp.set_cookie('author', werkzeug.url_quote(request.get_author()), max_age=604800) return resp