def test_thread(self): self.assertEqual(parse.thread("asdf"), (None, 'Untitled.')) self.assertEqual( parse.thread(""" <html> <head> <title>Foo!</title> </head> <body> <header> <h1>generic website title.</h1> <h2>subtile title.</h2> </header> <article> <header> <h1>Can you find me?</h1> </header> <section id="isso-thread"> </section> </article> </body> </html>"""), (None, 'Can you find me?')) self.assertEqual( parse.thread(""" <html> <body> <h1>I'm the real title!1 <section data-title="No way%21" id="isso-thread"> """), (None, 'No way!')) self.assertEqual( parse.thread(""" <section id="isso-thread" data-title="Test" data-isso-id="test"> """), ('test', 'Test')) self.assertEqual( parse.thread('<section id="isso-thread" data-isso-id="Fuu.">'), ('Fuu.', 'Untitled.'))
def test_thread(self): self.assertEqual(parse.thread("asdf"), (None, 'Untitled.')) self.assertEqual(parse.thread(""" <html> <head> <title>Foo!</title> </head> <body> <header> <h1>generic website title.</h1> <h2>subtile title.</h2> </header> <article> <header> <h1>Can you find me?</h1> </header> <section id="isso-thread"> </section> </article> </body> </html>"""), (None, 'Can you find me?')) self.assertEqual(parse.thread(""" <html> <body> <h1>I'm the real title!1 <section data-title="No way%21" id="isso-thread"> """), (None, 'No way!')) self.assertEqual(parse.thread(""" <section id="isso-thread" data-title="Test" data-isso-id="test"> """), ('test', 'Test')) self.assertEqual(parse.thread('<section id="isso-thread" data-isso-id="Fuu.">'), ('Fuu.', 'Untitled.'))
def new(self, environ, request, uri): data = request.get_json() for field in set(data.keys()) - API.ACCEPT: data.pop(field) for key in ("author", "email", "website", "parent"): data.setdefault(key, None) valid, reason = API.verify(data) if not valid: return BadRequest(reason) for field in ("author", "email"): if data.get(field) is not None: data[field] = cgi.escape(data[field]) data['mode'] = 2 if self.moderated else 1 data['remote_addr'] = utils.anonymize(str(request.remote_addr)) with self.isso.lock: if uri not in self.threads: with http.curl('GET', local("origin"), uri) as resp: if resp and resp.status == 200: uri, title = parse.thread(resp.read(), id=uri) else: return NotFound('URI does not exist') thread = self.threads.new(uri, title) self.signal("comments.new:new-thread", thread) else: thread = self.threads[uri] # notify extensions that the new comment is about to save self.signal("comments.new:before-save", thread, data) valid, reason = self.guard.validate(uri, data) if not valid: self.signal("comments.new:guard", reason) raise Forbidden(reason) with self.isso.lock: rv = self.comments.add(uri, data) # notify extension, that the new comment has been successfully saved self.signal("comments.new:after-save", thread, rv) cookie = functools.partial(dump_cookie, value=self.isso.sign([rv["id"], sha1(rv["text"])]), max_age=self.conf.getint('max-age')) rv["text"] = self.isso.render(rv["text"]) rv["hash"] = pbkdf2(rv['email'] or rv['remote_addr'], self.isso.salt, 1000, 6).decode("utf-8") self.cache.set('hash', (rv['email'] or rv['remote_addr']).encode('utf-8'), rv['hash']) for key in set(rv.keys()) - API.FIELDS: rv.pop(key) # success! self.signal("comments.new:finish", thread, rv) resp = JSON(rv, 202 if rv["mode"] == 2 else 201) resp.headers.add("Set-Cookie", cookie(str(rv["id"]))) resp.headers.add("X-Set-Cookie", cookie("isso-%i" % rv["id"])) return resp
def new(self, environ, request, uri): data = request.get_json() for field in set(data.keys()) - API.ACCEPT: data.pop(field) for key in ("author", "email", "website", "parent"): data.setdefault(key, None) valid, reason = API.verify(data) if not valid: return BadRequest(reason) for field in ("author", "email", "website"): if data.get(field) is not None: data[field] = cgi.escape(data[field]) if data.get("website"): data["website"] = normalize(data["website"]) data['mode'] = 2 if self.moderated else 1 data['remote_addr'] = utils.anonymize(str(request.remote_addr)) with self.isso.lock: if uri not in self.threads: if 'title' not in data: with http.curl('GET', local("origin"), uri) as resp: if resp and resp.status == 200: uri, title = parse.thread(resp.read(), id=uri) else: return NotFound('URI does not exist %s') else: title = data['title'] thread = self.threads.new(uri, title) self.signal("comments.new:new-thread", thread) else: thread = self.threads[uri] # notify extensions that the new comment is about to save self.signal("comments.new:before-save", thread, data) valid, reason = self.guard.validate(uri, data) if not valid: self.signal("comments.new:guard", reason) raise Forbidden(reason) with self.isso.lock: rv = self.comments.add(uri, data) # notify extension, that the new comment has been successfully saved self.signal("comments.new:after-save", thread, rv) cookie = functools.partial(dump_cookie, value=self.isso.sign( [rv["id"], sha1(rv["text"])]), max_age=self.conf.getint('max-age')) rv["text"] = self.isso.render(rv["text"]) rv["hash"] = self.hash(rv['email'] or rv['remote_addr']) self.cache.set( 'hash', (rv['email'] or rv['remote_addr']).encode('utf-8'), rv['hash']) rv = self._add_gravatar_image(rv) for key in set(rv.keys()) - API.FIELDS: rv.pop(key) # success! self.signal("comments.new:finish", thread, rv) resp = JSON(rv, 202 if rv["mode"] == 2 else 201) resp.headers.add("Set-Cookie", cookie(str(rv["id"]))) resp.headers.add("X-Set-Cookie", cookie("isso-%i" % rv["id"])) return resp
def new(self, environ, request, uri, key): data = request.get_json() # check access keys rv = self.db.execute(['SELECT uri FROM access WHERE key = ? ;'], (key, )).fetchall() if not rv or rv[0][0] != uri: raise Forbidden for field in set(data.keys()) - API.ACCEPT: data.pop(field) for key in ("author", "parent"): data.setdefault(key, None) if data['parent'] is not None: data.setdefault('place', None) valid, reason = API.verify(data) if not valid: return BadRequest(reason) escaped = dict((key, cgi.escape(value) if value is not None else None) for key, value in data.items()) added = {} if escaped.get("website") is not None: added["website"] = normalize(escaped["website"]) added['mode'] = 2 if self.moderated else 1 prepared = dict(escaped) prepared.update(added) with self.isso.lock: if uri in self._threads: thread = self._threads[uri] else: if 'title' in prepared: title = prepared['title'] else: with http.curl('GET', local("origin"), uri) as resp: if resp and resp.status == 200: uri, title = parse.thread(resp.read(), id=uri) else: return NotFound('URI does not exist %s') thread = self._threads.new(uri, title) self.signal("comments.new:new-thread", thread) # notify extensions that the new comment is about to save self.signal("comments.new:before-save", thread, prepared) valid, reason = self.guard.validate(uri, prepared) if not valid: self.signal("comments.new:guard", reason) raise Forbidden(reason) with self.isso.lock: rv = self.comments.add(uri, prepared) # notify extension, that the new comment has been successfully saved self.signal("comments.new:after-save", thread, rv) cookie = functools.partial(dump_cookie, value=self.isso.sign( [rv["id"], sha1(rv["text"])]), max_age=self.conf.getint('max-age')) rv["text"] = self.isso.render(rv["text"]) rv["hash"] = self.hash(rv['remote_addr']) self.cache.set('hash', (rv['remote_addr']).encode('utf-8'), rv['hash']) for key in set(rv.keys()) - API.FIELDS: rv.pop(key) # success! self.signal("comments.new:finish", thread, rv) resp = JSON(rv, 202 if rv["mode"] == 2 else 201) resp.headers.add("Set-Cookie", cookie(str(rv["id"]))) resp.headers.add("X-Set-Cookie", cookie("isso-%i" % rv["id"])) return resp
def new(self, environ, request, uri): logger.debug("got uri :%s" % uri) logger.debug("got eviron :%s" % str(environ)) logger.debug("got request :%s" % pprint.pformat(request.__dict__)) data = request.get_json() logger.debug("got data :%s" % data) for field in set(data.keys()) - API.ACCEPT: f = data.pop(field) logger.debug("skip data %s:%s" % (field, f )) for key in ("author", "email", "website", "parent"): data.setdefault(key, None) valid, reason = API.verify(data) if not valid: return BadRequest(reason) for field in ("author", "email", "website"): if data.get(field) is not None: data[field] = cgi.escape(data[field]) if data.get("website"): data["website"] = normalize(data["website"]) data['mode'] = 2 if self.moderated else 1 logger.debug("request.remote_addr %s" % (request.remote_addr )) data['remote_addr'] = utils.anonymize(str(request.remote_addr)) with self.isso.lock: if uri not in self.threads: org = str(local("origin")) if org == '<LocalProxy unbound>': org = environ['HTTP_ORIGIN'] logger.debug("got origin %s" % (org)) with http.curl('GET', org, uri) as resp: if resp and resp.status == 200: uri, title = parse.thread(resp.read(), id=uri) else: return NotFound('URI does not exist') thread = self.threads.new(uri, title) self.signal("comments.new:new-thread", thread) else: thread = self.threads[uri] # notify extensions that the new comment is about to save self.signal("comments.new:before-save", thread, data) valid, reason = self.guard.validate(uri, data) if not valid: self.signal("comments.new:guard", reason) raise Forbidden(reason) with self.isso.lock: rv = self.comments.add(uri, data) # notify extension, that the new comment has been successfully saved self.signal("comments.new:after-save", thread, rv) cookie = functools.partial(dump_cookie, value=self.isso.sign([rv["id"], sha1(rv["text"])]), max_age=self.conf.getint('max-age')) rv["text"] = self.isso.render(rv["text"]) rv["hash"] = self.hash(rv['email'] or rv['remote_addr']) self.cache.set('hash', (rv['email'] or rv['remote_addr']).encode('utf-8'), rv['hash']) for key in set(rv.keys()) - API.FIELDS: rv.pop(key) # success! self.signal("comments.new:finish", thread, rv) resp = JSON(rv, 202 if rv["mode"] == 2 else 201) resp.headers.add("Set-Cookie", cookie(str(rv["id"]))) resp.headers.add("X-Set-Cookie", cookie("isso-%i" % rv["id"])) return resp