def handle_exception(self, e, request): """ handle_exception is a callback that decorators all deferreds in render It responds to properly handled GL Exceptions by pushing the error msgs to the client and it spools a mail in the case the exception is unknown and unhandled. :param e: A `Twisted.python.Failure` instance that wraps a `GLException` or a normal `Exception` :param request: A `twisted.web.Request` """ if isinstance(e, NoResultFound): e = errors.ResourceNotFound() elif isinstance(e, errors.GLException): pass elif isinstance(e.value, errors.GLException): e = e.value else: e.tid = request.tid e.url = request.hostname + request.path extract_exception_traceback_and_schedule_email(e) e = errors.InternalServerError('Unexpected') request.setResponseCode(e.status_code) request.setHeader(b'content-type', b'application/json') response = json.dumps({ 'error_message': e.reason, 'error_code': e.error_code, 'arguments': getattr(e, 'arguments', []) }) request.write(response.encode())
def get(self): """ Get the sitemap.xml """ if not GLSettings.memory_copy.allow_indexing: raise errors.ResourceNotFound() site = 'https://' + GLSettings.memory_copy.hostname self.request.setHeader('Content-Type', 'text/xml') data = "<?xml version='1.0' encoding='UTF-8' ?>\n" + \ "<urlset xmlns='http://www.sitemaps.org/schemas/sitemap/0.9' xmlns:xhtml='http://www.w3.org/1999/xhtml'>\n" for url in ['/#/', '/#/submission']: data += " <url>\n" + \ " <loc>" + site + url + "</loc>\n" + \ " <changefreq>weekly</changefreq>\n" + \ " <priority>1.00</priority>\n" for lang in sorted(GLSettings.memory_copy.languages_enabled): if lang != GLSettings.memory_copy.default_language: l = lang.lower() l = l.replace('_', '-') data += "<xhtml:link rel='alternate' hreflang='" + l + "' href='" + site + "/#/?lang=" + lang + "' />\n" data += " </url>\n" data += "</urlset>" return data
def get(self): """ Get the sitemap.xml """ if not State.tenant_cache[self.request.tid].allow_indexing: raise errors.ResourceNotFound() self.request.setHeader(b'Content-Type', b'text/xml') data = "<?xml version='1.0' encoding='UTF-8' ?>\n" + \ "<urlset xmlns='http://www.sitemaps.org/schemas/sitemap/0.9' xmlns:xhtml='http://www.w3.org/1999/xhtml'>\n" if State.tenant_cache[self.request.tid].hostname: site = 'https://' + State.tenant_cache[self.request.tid].hostname data += " <url>\n" + \ " <loc>" + site + "/#/</loc>\n" + \ " <changefreq>weekly</changefreq>\n" + \ " <priority>1.00</priority>\n" for lang in sorted( State.tenant_cache[self.request.tid].languages_enabled): if lang != State.tenant_cache[ self.request.tid].default_language: hreflang = lang.lower().replace('_', '-') data += " <xhtml:link rel='alternate' hreflang='" + hreflang + "' href='" + site + "/#/?lang=" + lang + "' />\n" data += " </url>\n" data += "</urlset>" return data
def translate_shorturl(session, tid, shorturl): shorturl = session.query(models.ShortURL).filter( models.ShortURL.shorturl == shorturl, models.ShortURL.tid == tid).one_or_none() if shorturl is None: raise errors.ResourceNotFound() return shorturl.longurl
def write_file(self, filepath): if not os.path.exists(filepath) or not os.path.isfile(filepath): raise errors.ResourceNotFound() mime_type, encoding = mimetypes.guess_type(filepath) if mime_type: self.request.setHeader("Content-Type", mime_type) return StaticFileProducer(self.request, filepath).start()
def force_file_download(self, filename, filepath): if not os.path.exists(filepath) or not os.path.isfile(filepath): raise errors.ResourceNotFound() self.request.setHeader('X-Download-Options', 'noopen') self.request.setHeader('Content-Type', 'application/octet-stream') self.request.setHeader('Content-Disposition', 'attachment; filename=\"%s\"' % filename) return FileProducer(self.request, filepath).start()
def get(self, filename): if not filename: filename = 'index.html' abspath = os.path.abspath(os.path.join(self.root, filename)) directory_traversal_check(self.root, abspath) if os.path.exists(abspath) and os.path.isfile(abspath): return self.write_file(filename, abspath) raise errors.ResourceNotFound()
def write_file(self, filename, filepath): if not os.path.exists(filepath) or not os.path.isfile(filepath): raise errors.ResourceNotFound() if filename.endswith('.gz'): self.request.setHeader("Content-encoding", "gzip") filename = filename[:-3] mime_type, _ = mimetypes.guess_type(filename) if mime_type: self.request.setHeader("Content-Type", mime_type) return FileProducer(self.request, filepath).start()
def download_wbfile(self, session, tid, file_id): wbfile, wbtip = db_get( session, (models.WhistleblowerFile, models.WhistleblowerTip), (models.WhistleblowerFile.id == file_id, models.WhistleblowerFile.receivertip_id == models.ReceiverTip.id, models.ReceiverTip.internaltip_id == models.WhistleblowerTip.id)) if not self.user_can_access(session, tid, wbfile): raise errors.ResourceNotFound() self.access_wbfile(session, wbfile) return serializers.serialize_wbfile(session, wbfile), base64.b64decode( wbtip.crypto_tip_prv_key)
def download_wbfile(self, session, tid, file_id): wbfile, wbtip, = db_get( session, (models.WhistleblowerFile, models.WhistleblowerTip), (models.WhistleblowerFile.id == file_id, models.WhistleblowerFile.receivertip_id == models.ReceiverTip.id, models.ReceiverTip.internaltip_id == models.WhistleblowerTip.id)) rtip = session.query(models.ReceiverTip) \ .filter(models.ReceiverTip.receiver_id == self.current_user.user_id, models.ReceiverTip.internaltip_id == wbtip.id).one_or_none() if not rtip: raise errors.ResourceNotFound() self.access_wbfile(session, wbfile) return serializers.serialize_wbfile(session, wbfile), base64.b64decode( rtip.crypto_tip_prv_key)
def get_l10n(session, tid, lang): path = langfile_path(lang) directory_traversal_check(Settings.client_path, path) if not os.path.exists(path): raise errors.ResourceNotFound() texts = read_json_file(path) custom_texts = session.query(models.CustomTexts).filter( models.CustomTexts.lang == lang, models.CustomTexts.tid == tid).one_or_none() custom_texts = custom_texts.texts if custom_texts is not None else {} texts.update(custom_texts) return texts
def get(self): """ Get the sitemap.xml """ if not State.tenant_cache[self.request.tid].allow_indexing: raise errors.ResourceNotFound() self.request.setHeader(b'Content-Type', b'text/xml') data = "<?xml version='1.0' encoding='UTF-8' ?>\n" + \ "<urlset xmlns='http://www.sitemaps.org/schemas/sitemap/0.9' xmlns:xhtml='http://www.w3.org/1999/xhtml'>\n" tids = [self.request.tid] if self.request.tid == 1: tids = State.tenant_cache.keys() for tid in tids: urls = ['/#/'] site = 'https://' + State.tenant_cache[tid].hostname if tid == 1 and State.tenant_cache[1].enable_signup: urls.append('/#/signup') else: urls.append('/#/submission') for url in urls: data += " <url>\n" + \ " <loc>" + site + url + "</loc>\n" + \ " <changefreq>weekly</changefreq>\n" + \ " <priority>1.00</priority>\n" for lang in sorted(State.tenant_cache[tid].languages_enabled): if lang != State.tenant_cache[tid].default_language: l = lang.lower() l = l.replace('_', '-') data += "<xhtml:link rel='alternate' hreflang='" + l + "' href='" + site + url + "?lang=" + lang + "' />\n" data += " </url>\n" data += "</urlset>" return data
def get_l10n(session, tid, lang): if tid != 1: config = ConfigFactory(session, 1) if config.get_val(u'mode') == u'whistleblowing.it': tid = 1 path = langfile_path(lang) directory_traversal_check(Settings.client_path, path) if not os.path.exists(path): raise errors.ResourceNotFound() texts = read_json_file(path) custom_texts = session.query(models.CustomTexts).filter(models.CustomTexts.lang == lang, models.CustomTexts.tid == tid).one_or_none() custom_texts = custom_texts.texts if custom_texts is not None else {} texts.update(custom_texts) return texts
def render(self, request): """ :param request: `twisted.web.Request` :return: empty `str` or `NOT_DONE_YET` """ request_finished = [False] def _finish(ret): request_finished[0] = True request.notifyFinish().addBoth(_finish) self.preprocess(request) if request.tid is None: # Tentative domain correction in relation to presence / absence of 'www.' prefix if not request.hostname.startswith(b'www.'): tentative_hostname = b'www.' + request.hostname else: tentative_hostname = request.hostname[4:] if tentative_hostname in State.tenant_hostname_id_map: request.tid = State.tenant_hostname_id_map[tentative_hostname] if State.tenant_cache[request.tid].https_enabled: request.redirect(b'https://' + tentative_hostname + b'/') else: request.redirect(b'http://' + tentative_hostname + b'/') else: # Fallback on root tenant with error 400 request.tid = 1 request.setResponseCode(400) self.set_headers(request) return b'' self.set_headers(request) if self.should_redirect_tor(request): self.redirect_tor(request) return b'' if self.should_redirect_https(request): self.redirect_https(request) return b'' request_path = request.path.decode() if request_path in State.tenant_cache[request.tid]['redirects']: request.redirect( State.tenant_cache[request.tid]['redirects'][request_path]) return b'' match = None for regexp, handler, args in self._registry: try: match = regexp.match(request_path) except UnicodeDecodeError: match = None if match: break if match is None: self.handle_exception(errors.ResourceNotFound(), request) return b'' method = request.method.lower().decode() if method == 'head': method = 'get' elif method == 'options': request.setResponseCode(200) return b'' if method not in self.method_map.keys() or not hasattr( handler, method): self.handle_exception(errors.MethodNotImplemented(), request) return b'' f = getattr(handler, method) groups = match.groups() self.handler = handler(State, request, **args) request.setResponseCode(self.method_map[method]) if self.handler.root_tenant_only and request.tid != 1: self.handle_exception(errors.ForbiddenOperation(), request) return b'' if self.handler.upload_handler and method == 'post': self.handler.process_file_upload() if self.handler.uploaded_file is None: return b'' @defer.inlineCallbacks def concludeHandlerFailure(err): self.handle_exception(err, request) yield self.handler.execution_check() if not request_finished[0]: request.finish() @defer.inlineCallbacks def concludeHandlerSuccess(ret): """ Concludes successful execution of a `BaseHandler` instance :param ret: A `dict`, `list`, `str`, `None` or something unexpected """ yield self.handler.execution_check() if not request_finished[0]: if ret is not None: if isinstance(ret, (dict, list)): ret = json.dumps(ret, cls=JSONEncoder, separators=(',', ':')) request.setHeader(b'content-type', b'application/json') if isinstance(ret, str): ret = ret.encode() request.write(ret) request.finish() defer.maybeDeferred(f, self.handler, *groups).addCallbacks(concludeHandlerSuccess, concludeHandlerFailure) return NOT_DONE_YET
def render(self, request): """ @param request: `twisted.web.Request` @return: empty `str` or `NOT_DONE_YET` """ self.set_default_headers(request) request_finished = [False] def _finish(_): request_finished[0] = True request.notifyFinish().addBoth(_finish) match = None for regexp, handler, args in self._registry: match = regexp.match(request.path) if match: break if match is None: self.handle_exception(errors.ResourceNotFound(), request) return b'' method = request.method.lower() if not method in ['get', 'post', 'put', 'delete'] or not hasattr( handler, method): self.handle_exception(errors.MethodNotImplemented(), request) return b'' f = getattr(handler, method) groups = [unicode(g) for g in match.groups()] h = handler(request, **args) d = defer.maybeDeferred(f, h, *groups) @defer.inlineCallbacks def concludeHandlerFailure(err): yield h.execution_check() self.handle_exception(err, request) if not request_finished[0]: request.finish() @defer.inlineCallbacks def concludeHandlerSuccess(ret): """Concludes successful execution of a `BaseHandler` instance @param ret: A `dict`, `str`, `None` or something unexpected """ yield h.execution_check() if not ret is None: h.write(ret) if not request_finished[0]: request.finish() d.addErrback(concludeHandlerFailure) d.addCallback(concludeHandlerSuccess) return NOT_DONE_YET
def render(self, request): """ @param request: `twisted.web.Request` @return: empty `str` or `NOT_DONE_YET` """ request_finished = [False] def _finish(ret): request_finished[0] = True request.notifyFinish().addBoth(_finish) self.preprocess(request) self.set_headers(request) if request.tid is None: self.handle_exception(errors.ResourceNotFound(), request) return b'' if self.should_redirect_tor(request): self.redirect_tor(request) return b'' if self.should_redirect_https(request): self.redirect_https(request) return b'' request.path = request.path.decode('utf-8') if request.tid == 1: match = re.match(r'^/t/([0-9]+)(/.*)', request.path) if match is not None: groups = match.groups() request.tid, request.path = int(groups[0]), groups[1] match = None for regexp, handler, args in self._registry: try: match = regexp.match(request.path) except UnicodeDecodeError: match = None if match: break if match is None: self.handle_exception(errors.ResourceNotFound(), request) return b'' method = request.method.lower().decode('utf-8') if method == 'head': # HEAD method is not really implemented # as trick we use the same approch of Twisted of # mapping the HEAD method on the GET method. method = 'get' if method not in self.method_map.keys() or not hasattr(handler, method): self.handle_exception(errors.MethodNotImplemented(), request) return b'' f = getattr(handler, method) groups = [text_type(g) for g in match.groups()] self.handler = handler(State, request, **args) request.setResponseCode(self.method_map[method]) if self.handler.root_tenant_only and request.tid != 1: self.handle_exception(errors.ForbiddenOperation(), request) return b'' if self.handler.upload_handler and method == 'post': self.handler.process_file_upload() if self.handler.uploaded_file is None: return b'' @defer.inlineCallbacks def concludeHandlerFailure(err): yield self.handler.execution_check() self.handle_exception(err, request) if not request_finished[0]: request.finish() @defer.inlineCallbacks def concludeHandlerSuccess(ret): """ Concludes successful execution of a `BaseHandler` instance @param ret: A `dict`, `list`, `str`, `None` or something unexpected """ yield self.handler.execution_check() if not request_finished[0]: if ret is not None: if isinstance(ret, (dict, list)): ret = json.dumps(ret, separators=(',', ':')) request.setHeader(b'content-type', b'application/json') if isinstance(ret, text_type): ret = ret.encode() request.write(ret) request.finish() defer.maybeDeferred(f, self.handler, *groups).addCallbacks(concludeHandlerSuccess, concludeHandlerFailure) return NOT_DONE_YET
def check_file_presence(self, filepath): if not os.path.exists(filepath) or not os.path.isfile(filepath): raise errors.ResourceNotFound()
def render(self, request): """ @param request: `twisted.web.Request` @return: empty `str` or `NOT_DONE_YET` """ request_finished = [False] def _finish(ret): request_finished[0] = True request.notifyFinish().addBoth(_finish) self.preprocess(request) if self.should_redirect_tor(request): self.redirect_tor(request) return b'' if self.should_redirect_https(request): self.redirect_https(request) return b'' match = None for regexp, handler, args in self._registry: match = regexp.match(request.path) if match: break if match is None: self.handle_exception(errors.ResourceNotFound(), request) return b'' method = request.method.lower() if not method in self.method_map or not hasattr(handler, method): self.handle_exception(errors.MethodNotImplemented(), request) return b'' else: request.setResponseCode(self.method_map[method]) f = getattr(handler, method) groups = [unicode(g) for g in match.groups()] h = handler(State, request, **args) d = defer.maybeDeferred(f, h, *groups) @defer.inlineCallbacks def concludeHandlerFailure(err): yield h.execution_check() self.handle_exception(err, request) if not request_finished[0]: request.finish() @defer.inlineCallbacks def concludeHandlerSuccess(ret): """ Concludes successful execution of a `BaseHandler` instance @param ret: A `dict`, `list`, `str`, `None` or something unexpected """ yield h.execution_check() if not request_finished[0]: if ret is not None: if isinstance(ret, (types.DictType, types.ListType)): ret = json.dumps(ret, separators=(',', ':')) request.setHeader(b'content-type', b'application/json') request.write(bytes(ret)) request.finish() d.addErrback(concludeHandlerFailure) d.addCallback(concludeHandlerSuccess) return NOT_DONE_YET