def content_iter(self, lines): last_lines = [] in_header = False in_bug = False attributes = {} title = None for line_no, line in enumerate(lines): if last_lines and line.startswith('----'): title = ''.join(last_lines) last_lines = [] in_header = True attributes = {} elif in_header and ':' in line: attribute, value = line.split(':', 1) attributes[attribute.strip()] = value.strip() else: if in_header: if in_bug: yield '</div>' #tags = [tag.strip() for tag in # attributes.get('tags', '').split() # if tag.strip()] yield '<div id="line_%d">' % (line_no) in_bug = True if title: yield html.h2(html(title)) if attributes: yield '<dl>' for attribute, value in attributes.items(): yield html.dt(html(attribute)) yield html.dd(html(value)) yield '</dl>' in_header = False if not line.strip(): if last_lines: if last_lines[0][0] in ' \t': yield html.pre(html(''.join(last_lines))) else: yield html.p(html(''.join(last_lines))) last_lines = [] else: last_lines.append(line) if last_lines: if last_lines[0][0] in ' \t': yield html.pre(html(''.join(last_lines))) else: yield html.p(html(''.join(last_lines))) if in_bug: yield '</div>'
def diff(request, title, from_rev, to_rev): """Show the differences between specified revisions.""" _ = request.wiki.gettext page = hatta.page.get_page(request, title) build = request.adapter.build from_url = build('revision', {'title': title, 'rev': from_rev}) to_url = build('revision', {'title': title, 'rev': to_rev}) a = html.a links = { 'link1': a(str(from_rev)[:8], href=from_url), 'link2': a(str(to_rev)[:8], href=to_url), 'link': a(html(title), href=request.get_url(title)), } message = html( _('Differences between revisions %(link1)s and %(link2)s ' 'of page %(link)s.')) % links diff_content = getattr(page, 'diff_content', None) if diff_content: from_text = request.wiki.storage.get_revision(page.title, from_rev).text to_text = request.wiki.storage.get_revision(page.title, to_rev).text content = page.diff_content(from_text, to_text, message) else: content = [ html.p(html(_("Diff not available for this kind of pages."))) ] special_title = _('Diff for "%(title)s"') % {'title': title} phtml = page.template('page_special.html', content=content, special_title=special_title) resp = WikiResponse(phtml, mimetype='text/html') return resp
def _block_paragraph(self, block): parts = [] first_line = None for self.line_no, part in block: if first_line is None: first_line = self.line_no parts.append(part) text = "".join(self.parse_line("".join(parts))) yield html.p(text, self.pop_to(""), id="line_%d" % first_line)
def authenticate(token_id: str): """Finalize the authentication process. It will be shown on web browser. :param token_id: token id created by :func:`create_access_token()` :type token_id: :class:`str` :status 400: when authentication is failed :status 404: when the given ``token_id`` doesn't exist :status 403: when the ``token_id`` is already finalized :status 200: when authentication is successfully done """ token_store = get_token_store() team = get_team() token_expire = app.config['TOKEN_EXPIRE'] if not isinstance(token_expire, datetime.timedelta): raise RuntimeError( 'TOKEN_EXPIRE configuration must be an instance of ' 'datetime.timedelta, not {!r}'.format(token_expire) ) try: state = token_store.get(token_id) current_app.logger.debug( 'stored AuthenticationContinuation.state: %r', state ) except TypeError: raise NotFound() if not isinstance(state, tuple) or state[0] != 'auth-state': raise Forbidden() requested_redirect_url = url_for( 'authenticate', token_id=token_id, _external=True ) try: identity = team.authenticate( state[1], requested_redirect_url, request.environ ) except AuthenticationError as e: current_app.logger.debug(e, exc_info=1) raise BadRequest() expires_at = datetime.datetime.now(datetime.timezone.utc) + token_expire token_store.set(token_id, ('token', Token(identity, expires_at)), timeout=int(token_expire.total_seconds())) return '<!DOCTYPE html>\n' + html.html( html.head( html.meta(charset='utf-8'), html.title('Geofront: Authentication success') ), html.body( html.h1(html.dfn('Geofront:'), ' Authentication success'), html.p('You may close the browser, and go back to the CLI.') ) )
def oauth2_callback(): """Finalize the authentication process. It will be shown on web browser. :status 400: when authentication is failed :status 404: when the given ``token_id`` doesn't exist :status 403: when the ``token_id`` is already finalized :status 200: when authentication is successfully done """ token_id = request.args.get('token_id', '') token_store = get_token_store() team = get_team() token_expire = app.config['TOKEN_EXPIRE'] if not isinstance(token_expire, datetime.timedelta): raise RuntimeError('TOKEN_EXPIRE configuration must be an instance of ' 'datetime.timedelta, not {!r}'.format(token_expire)) try: state = token_store.get(token_id) current_app.logger.debug('stored AuthenticationContinuation.state: %r', state) except TypeError: raise NotFound() if not isinstance(state, tuple) or state[0] != 'auth-state': raise Forbidden() if getattr(team, 'allow_callback_url_params', True): requested_redirect_url = url_for('authenticate', token_id=token_id, _external=True) else: requested_redirect_url = url_for('oauth2_callback', token_id=token_id, _external=True) try: identity = team.authenticate(state[1], requested_redirect_url, request.environ) except AuthenticationError as e: current_app.logger.debug(e, exc_info=1) raise BadRequest() expires_at = datetime.datetime.now(datetime.timezone.utc) + token_expire token_store.set(token_id, ('token', Token(identity, expires_at)), timeout=int(token_expire.total_seconds())) return '<!DOCTYPE html>\n' + html.html( html.head(html.meta(charset='utf-8'), html.title('Geofront: Authentication success')), html.body( html.h1(html.dfn('Geofront:'), ' Authentication success'), html.p('You may close the browser, and go back to the CLI.')))
def page_search(words, page, request): """Display the search results.""" h = html request.wiki.index.update(request.wiki) result = sorted(request.wiki.index.find(words), key=lambda x: -x[0]) yield 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>'
def revision(request, title, rev): _ = request.wiki.gettext text = request.wiki.storage.get_revision(title, rev).text link = html.a(html(title), href=request.get_url(title)) content = [ html.p( html(_('Content of revision %(rev)s of page %(title)s:')) % { 'rev': rev[:8], 'title': link }), html.pre(html(text)), ] special_title = _('Revision of "%(title)s"') % {'title': title} page = hatta.page.get_page(request, title) resp = page.template('page_special.html', content=content, special_title=special_title) return response(request, title, resp, rev=rev, etag='/old')
def authenticate(token_id: str): """Finalize the authentication process. It will be shown on web browser. :param token_id: token id created by :func:`create_access_token()` :type token_id: :class:`str` :status 400: when authentication is failed :status 404: when the given ``token_id`` doesn't exist :status 403: when the ``token_id`` is already finalized :status 200: when authentication is successfully done """ token_store = get_token_store() team = get_team() token_expire = app.config['TOKEN_EXPIRE'] if not isinstance(token_expire, datetime.timedelta): raise RuntimeError('TOKEN_EXPIRE configuration must be an instance of ' 'datetime.timedelta, not {!r}'.format(token_expire)) try: auth_nonce = token_store.get(token_id) current_app.logger.debug('stored auth_nonce: %r', auth_nonce) except TypeError: raise NotFound() if not isinstance(auth_nonce, str): raise Forbidden() requested_redirect_url = url_for('authenticate', token_id=token_id, _external=True) try: identity = team.authenticate(auth_nonce, requested_redirect_url, request.environ) except AuthenticationError: raise BadRequest() expires_at = datetime.datetime.now(datetime.timezone.utc) + token_expire token_store.set(token_id, Token(identity, expires_at), timeout=int(token_expire.total_seconds())) return '<!DOCTYPE html>\n' + html.html( html.head(html.meta(charset='utf-8'), html.title('Geofront: Authentication success')), html.body( html.h1(html.dfn('Geofront:'), ' Authentication success'), html.p('You may close the browser, and go back to the CLI.')))
def authenticate(token_id: str): """Finalize the authentication process. It will be shown on web browser. :param token_id: token id created by :func:`create_access_token()` :type token_id: :class:`str` :status 400: when authentication is failed :status 404: when the given ``token_id`` doesn't exist :status 403: when the ``token_id`` is already finalized :status 200: when authentication is successfully done """ token_store = get_token_store() team = get_team() token_expire = app.config["TOKEN_EXPIRE"] if not isinstance(token_expire, datetime.timedelta): raise RuntimeError( "TOKEN_EXPIRE configuration must be an instance of " "datetime.timedelta, not {!r}".format(token_expire) ) try: auth_nonce = token_store.get(token_id) current_app.logger.debug("stored auth_nonce: %r", auth_nonce) except TypeError: raise NotFound() if not isinstance(auth_nonce, str): raise Forbidden() requested_redirect_url = url_for("authenticate", token_id=token_id, _external=True) try: identity = team.authenticate(auth_nonce, requested_redirect_url, request.environ) except AuthenticationError: raise BadRequest() expires_at = datetime.datetime.now(datetime.timezone.utc) + token_expire token_store.set(token_id, Token(identity, expires_at), timeout=int(token_expire.total_seconds())) return "<!DOCTYPE html>\n" + html.html( html.head(html.meta(charset="utf-8"), html.title("Geofront: Authentication success")), html.body( html.h1(html.dfn("Geofront:"), " Authentication success"), html.p("You may close the browser, and go back to the CLI."), ), )
def content_iter(self, lines=None): import csv _ = self.wiki.gettext # XXX Add preview support reader = csv.reader(csv_file) html_title = escape(self.title) yield '<table id="%s" class="csvfile">' % html_title with self.revision.file as csv_file: try: for row in reader: yield '<tr>%s</tr>' % (''.join('<td>%s</td>' % cell for cell in row)) except csv.Error as e: yield '</table>' yield html.p( html( _('Error parsing CSV file %{file}s on ' 'line %{line}d: %{error}s') % { 'file': html_title, 'line': reader.line_num, 'error': e })) yield '</table>'
def render_editor(self, preview=None, captcha_error=None): """Generate the HTML for the editor.""" _ = self.wiki.gettext author = self.request.get_author() lines = [] try: lines = self.revision.text.splitlines(True) rev = self.revision.rev old_author = self.revision.author old_comment = self.revision.comment comment = _('modified') if old_author == author: comment = old_comment except hatta.error.NotFoundErr: comment = _('created') rev = -1 except hatta.error.ForbiddenErr as e: return html.p(html(str(e))) if preview: lines = preview comment = self.request.form.get('comment', comment) if captcha and self.wiki.recaptcha_public_key: recaptcha_html = captcha.displayhtml( self.wiki.recaptcha_public_key, error=captcha_error) else: recaptcha_html = None context = { 'comment': comment, 'preview': preview, 'recaptcha_html': recaptcha_html, 'help': self.get_edit_help(), 'author': author, 'parent': rev, 'lines': lines, } return self.template('edit_text.html', **context)
def save(request, title): _ = request.wiki.gettext hatta.page.check_lock(request.wiki, title) url = request.get_url(title) if request.form.get('cancel'): if title not in request.wiki.storage: url = request.get_url(request.wiki.front_page) if request.form.get('preview'): text = request.form.get("text") if text is not None: lines = text.split('\n') else: lines = [html.p(html(_('No preview for binaries.')))] return edit(request, title, preview=lines) elif request.form.get('save'): if captcha and request.wiki.recaptcha_private_key: response = captcha.submit( request.form.get('recaptcha_challenge_field', ''), request.form.get('recaptcha_response_field', ''), request.wiki.recaptcha_private_key, request.remote_addr) if not response.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 hatta.error.ForbiddenErr() author = request.get_author() text = request.form.get("text") try: parent = request.form.get("parent") except (ValueError, TypeError): parent = None page = hatta.page.get_page(request, title) saved_titles = [title] if text is not None: if title == request.wiki.locked_page: for link, label in page.extract_links(text): if title == link: raise hatta.error.ForbiddenErr( _("This page is locked.")) if text.strip() == '': request.wiki.storage.delete_page(title, author, comment) url = request.get_url(request.wiki.front_page) else: with request.wiki.storage: request.wiki.storage.save_text(title, text, author, comment, parent) elif page.mime == 'application/hatta+zip' and request.wiki.allow_bulk_uploads: # special case for uploading zip file of multiple pages upload = request.files.get('data') import zipfile, tempfile tfname = tempfile.mktemp() upload.save(tfname) try: with open(tfname, 'rb') as tf, zipfile.ZipFile( tf) as zf, request.wiki.storage: for name in zf.namelist(): if name[0] in '._/~!+=-#%&': continue elif name not in request.wiki.storage: # can't replace existing pages hatta.page.check_lock(request.wiki, name) with zf.open(name) as f: data = f.read() if data: request.wiki.storage.save_data( name, data, author, comment) url = request.get_url(name) saved_titles.append(name) finally: os.unlink(tfname) else: text = '' upload = request.files.get('data') with request.wiki.storage: if upload and upload.stream and upload.filename: f = upload.stream request.wiki.storage.save_data(title, f.read(), author, comment, parent) else: request.wiki.storage.delete_page(title, author, comment) url = request.get_url(request.wiki.front_page) request.wiki.index.reindex(request.wiki, saved_titles) response = redirect(url, code=303) response.set_cookie('author', urls.url_quote(request.get_author()), max_age=604800) return response