def _handle(self, req): crawl_delay = wiking.cfg.crawl_delay if crawl_delay is not None: data = ("User-agent: *\n" "Crawl-delay: %d\n" % crawl_delay) return wiking.Response(data, 'text/plain') else: raise NotFound()
def _handle(self, req): """Serve the resource from a file.""" if len(req.unresolved_path) < 1 or '..' in req.unresolved_path: # Avoid direcory traversal attacks. raise Forbidden() filename = os.path.join(*req.unresolved_path) response = self._handle_resource(req, filename) if response.status_code() == http.client.OK and filename.endswith( '.css'): # Substitute the current color theme in stylesheets. theme, theme_mtime = self._theme(req) stylesheet_mtime = response.last_modified() if stylesheet_mtime and theme_mtime: mtime = max(stylesheet_mtime, theme_mtime) if req.cached_since(mtime): raise wiking.NotModified() else: mtime = None data = response.data() if isinstance(data, (list, types.GeneratorType)): data = b''.join(data) if isinstance(data, bytes): data = str(data, 'utf-8') data = self._substitute(data, theme) response = wiking.Response(data, content_type=response.content_type(), last_modified=mtime, filename=response.filename(), headers=response.headers()) max_age = wiking.cfg.resource_client_cache_max_age if ((max_age is not None and response.last_modified() is not None and 'Cache-Control' not in dict(response.headers()))): response.add_header('Cache-Control', 'max-age=%d' % max_age) return response
def _info(self, req, storage, filename): resource = storage.resource(filename) if resource: import json info = self._resource_info(resource) return wiking.Response(json.dumps(info), content_type='application/json') else: raise wiking.NotFound
def _update(self, req, storage, filename): import json values = json.loads(req.param('values')) try: storage.update(filename, values) except Exception as e: response = str(e) else: response = 'OK' return wiking.Response(response, content_type='text/plain')
def _retrieve(self, req, storage, filename): f = storage.retrieve(filename) if f: def proxy(f): try: while True: data = f.read(524288) if not data: break yield data finally: f.close() return wiking.Response(proxy(f), content_type='application/octet-stream') else: raise wiking.NotFound
def _list(self, req, storage): import json result = [[r.filename(), self._resource_info(r)] for r in storage.resources()] return wiking.Response(json.dumps(result), content_type='application/json')
def _handle(self, req): try: try: if wiking.cfg.maintenance and not req.uri().startswith('/_resources/'): # TODO: excluding /_resources/ is here to make stylesheets # available for the maintenance error page. The URI is # however not necassarily correct (application may change # it). Better would most likely be including some basic styles # directly in MinimalExporter. return self._handle_maintenance_mode(req) # Very basic CSRF prevention if req.param('submit') and req.header('Referer'): referer = urllib.parse.urlparse(req.header('Referer')) referer_uri = referer.scheme + '://' + referer.netloc server_uri = req.server_uri(current=True) if referer_uri != server_uri: wiking.debug("Request rejected due to CSRF protection:", referer_uri, server_uri) raise wiking.Redirect(req.server_uri(current=True)) # Regular processing starts here. try: result = self._application.handle(req) except wiking.Abort as abort: result = abort.result() if isinstance(result, (tuple, list)): # Temporary backwards compatibility conversion. content_type, data = result result = wiking.Response(data, content_type=content_type) if req.is_api_request() and isinstance(result, (lcg.Content, wiking.Document)): # This is a very generic detection of invalid API # requests. We just assume, that the clients, which # indicate that they accept JSON responses are API # clients and they are not interested in responses, which # display human readable content. raise wiking.BadRequest(_("This URI does not belong to server API.")) if isinstance(result, wiking.Document): # Perform authentication here if it was not performed before # to handle authentication exceptions now and prevent them in # export time. When the result is a Document, we will always # need to know the authenticated user in order to display the # login control at the top of the page. user = req.user() if user: password_expiration = user.password_expiration() password_change_uri = wiking.module.Application.password_change_uri(req) if ((password_change_uri and password_expiration and password_expiration <= datetime.date.today() and req.uri() != password_change_uri)): req.message(_("Your password expired."), req.ERROR) req.message(_("Access to the application is now restricted " "until you change your password.")) raise wiking.Redirect(password_change_uri) return self._serve_document(req, result) elif isinstance(result, lcg.Content): return self._serve_content(req, result) elif isinstance(result, wiking.Response): last_modified = result.last_modified() if last_modified is not None and req.cached_since(last_modified): raise wiking.NotModified() for header, value in result.headers(): req.set_header(header, value) filename = result.filename() if filename: # When the filename contains non-ascii characters, uwsgi raises: # TypeError: http header must be encodable in latin1 # Some context at: https://stackoverflow.com/questions/93551/ try: filename.encode('latin-1') except UnicodeEncodeError: filename_info = "filename*=UTF-8''" + urllib.parse.quote(filename) else: filename_info = 'filename="%s"' % filename disposition = 'inline' if result.inline() else 'attachment' req.set_header('Content-Disposition', disposition + '; ' + filename_info) return req.send_response(result.data(), content_type=result.content_type(), content_length=result.content_length(), status_code=result.status_code(), last_modified=result.last_modified()) else: raise Exception('Invalid handler result: %s' % type(result)) except wiking.NotModified as error: return req.send_response('', status_code=error.status_code(), content_type=None) except wiking.Redirect as r: return req.redirect(r.uri(), r.args(), status_code=r.status_code()) except wiking.RequestError as error: # Try to authenticate now, but ignore all errors within authentication except # for AuthenticationError. try: req.user() except wiking.RequestError: pass except wiking.AuthenticationError as auth_error: error = auth_error return self._handle_request_error(req, error) except wiking.ClosedConnection: return [] except Exception: # Any other unhandled exception is an Internal Server Error. It is # handled in a separate try/except block to chatch also errors in # except blocks of the inner level. return self._handle_request_error(req, wiking.InternalServerError())