Browse Source

More cleanup; cookie fixes, Flask integration.

pull/24/head
Ben Kurtovic 10 years ago
parent
commit
56a79cc8d1
10 changed files with 100 additions and 84 deletions
  1. +20
    -12
      app.fcgi
  2. +5
    -10
      copyvios/background.py
  3. +13
    -10
      copyvios/cookies.py
  4. +8
    -6
      copyvios/misc.py
  5. +15
    -12
      copyvios/settings.py
  6. +4
    -5
      templates/debug.mako
  7. +2
    -2
      templates/index.mako
  8. +18
    -14
      templates/settings.mako
  9. +3
    -4
      templates/support/footer.mako
  10. +12
    -9
      templates/support/header.mako

+ 20
- 12
app.fcgi View File

@@ -5,7 +5,7 @@ from time import asctime
from logging import DEBUG from logging import DEBUG
from logging.handlers import TimedRotatingFileHandler from logging.handlers import TimedRotatingFileHandler


from flask import Flask, request
from flask import Flask, g, request
from flask.ext.mako import MakoTemplates, render_template from flask.ext.mako import MakoTemplates, render_template
from flup.server.fcgi import WSGIServer from flup.server.fcgi import WSGIServer


@@ -15,10 +15,24 @@ app = Flask(__name__)
MakoTemplates(app) MakoTemplates(app)


app.logger.setLevel(DEBUG) app.logger.setLevel(DEBUG)
app.logger.addHandler(TimedRotatingFileHandler("logs/app.log", when="D",
interval=1, backupCount=7))
app.logger.addHandler(TimedRotatingFileHandler(
"logs/app.log", when="D", interval=1, backupCount=7))
app.logger.info(u"Flask server started " + asctime()) app.logger.info(u"Flask server started " + asctime())


@app.before_request
def prepare_cookies():
cookie_string = request.environ.get("HTTP_COOKIE")
g.cookies = parse_cookies(request.script_root, cookie_string)
g.new_cookies = []

@app.after_request
def add_new_cookies(response):
if g.new_cookies:
if "Set-Cookie" in response.headers:
g.new_cookies.insert(0, response.headers["Set-Cookie"])
response.headers["Set-Cookie"] = "; ".join(g.new_cookies)
return response

@app.after_request @app.after_request
def write_access_log(response): def write_access_log(response):
msg = u"%s %s -> %s" msg = u"%s %s -> %s"
@@ -27,21 +41,15 @@ def write_access_log(response):


@app.route("/") @app.route("/")
def index(): def index():
root = request.environ["SCRIPT_NAME"]
cookies = parse_cookies(root, request.environ.get("HTTP_COOKIE"))
return render_template("index.mako", root=root, environ=request.environ, cookies=cookies)
return render_template("index.mako")


@app.route("/settings", methods=["GET", "POST"]) @app.route("/settings", methods=["GET", "POST"])
def settings(): def settings():
root = request.environ["SCRIPT_NAME"]
cookies = parse_cookies(root, request.environ.get("HTTP_COOKIE"))
return render_template("settings.mako", root=root, environ=request.environ, cookies=cookies)
return render_template("settings.mako")


@app.route("/debug") @app.route("/debug")
def debug(): def debug():
root = request.environ["SCRIPT_NAME"]
cookies = parse_cookies(root, request.environ.get("HTTP_COOKIE"))
return render_template("debug.mako", root=root, environ=request.environ, cookies=cookies)
return render_template("debug.mako")


if __name__ == '__main__': if __name__ == '__main__':
WSGIServer(app).run() WSGIServer(app).run()

+ 5
- 10
copyvios/background.py View File

@@ -7,16 +7,14 @@ import re
from time import time from time import time


from earwigbot import exceptions from earwigbot import exceptions
from flask import g


from .misc import get_bot, open_sql_connection from .misc import get_bot, open_sql_connection


_descurl = None

def set_background(context, cookies, selected):
global _descurl
def set_background(context, selected):
conn = open_sql_connection(get_bot(), "globals") conn = open_sql_connection(get_bot(), "globals")
if "CopyviosScreenCache" in cookies:
cache = cookies["CopyviosScreenCache"].value
if "CopyviosScreenCache" in g.cookies:
cache = g.cookies["CopyviosScreenCache"].value
try: try:
screen = loads(cache) screen = loads(cache)
int(screen["width"]) int(screen["width"])
@@ -32,12 +30,9 @@ def set_background(context, cookies, selected):
info = _update_url(conn, "background_list", 2, _get_fresh_list) info = _update_url(conn, "background_list", 2, _get_fresh_list)
filename, url, descurl, width, height = info filename, url, descurl, width, height = info
bg_url = _build_url(screen, filename, url, width, height) bg_url = _build_url(screen, filename, url, width, height)
_descurl = descurl
g.descurl = descurl
return bg_url return bg_url


def get_desc_url(context):
return _descurl

def _update_url(conn, service, bg_id, callback): def _update_url(conn, service, bg_id, callback):
query1 = "SELECT update_time FROM updates WHERE update_service = ?" query1 = "SELECT update_time FROM updates WHERE update_service = ?"
query2 = "SELECT 1 FROM background WHERE background_id = ?" query2 = "SELECT 1 FROM background WHERE background_id = ?"


+ 13
- 10
copyvios/cookies.py View File

@@ -4,6 +4,8 @@ import base64
from Cookie import CookieError, SimpleCookie from Cookie import CookieError, SimpleCookie
from datetime import datetime, timedelta from datetime import datetime, timedelta


from flask import g

class _CookieManager(SimpleCookie): class _CookieManager(SimpleCookie):
MAGIC = "--cpv2" MAGIC = "--cpv2"


@@ -40,14 +42,15 @@ class _CookieManager(SimpleCookie):
def parse_cookies(path, cookies): def parse_cookies(path, cookies):
return _CookieManager(path, cookies) return _CookieManager(path, cookies)


def set_cookie(headers, cookies, key, value, days=0):
cookies[key] = value
def set_cookie(key, value, days=0):
g.cookies[key] = value
if days: if days:
expires = datetime.utcnow() + timedelta(days=days)
cookies[key]["expires"] = expires.strftime("%a, %d %b %Y %H:%M:%S GMT")
cookies[key]["path"] = cookies.path
headers.append(("Set-Cookie", cookies[key].OutputString()))

def delete_cookie(headers, cookies, key):
set_cookie(headers, cookies, key, u"", days=-1)
del cookies[key]
expire_dt = datetime.utcnow() + timedelta(days=days)
expires = expire_dt.strftime("%a, %d %b %Y %H:%M:%S GMT")
g.cookies[key]["expires"] = expires
g.cookies[key]["path"] = g.cookies.path
g.new_cookies.append(g.cookies[key].OutputString())

def delete_cookie(key):
set_cookie(key, u"", days=-1)
del g.cookies[key]

+ 8
- 6
copyvios/misc.py View File

@@ -4,19 +4,20 @@ from os.path import expanduser
from urlparse import parse_qs from urlparse import parse_qs


from earwigbot.bot import Bot from earwigbot.bot import Bot
from flask import request
import oursql import oursql


_bot = None _bot = None
_connections = {} _connections = {}


class Query(object): class Query(object):
def __init__(self, environ, method="GET"):
def __init__(self, method="GET"):
self.query = {} self.query = {}
if method == "GET": if method == "GET":
parsed = parse_qs(environ["QUERY_STRING"])
parsed = parse_qs(request.environ["QUERY_STRING"])
elif method == "POST": elif method == "POST":
size = int(environ.get("CONTENT_LENGTH", 0))
parsed = parse_qs(environ["wsgi.input"].read(size))
size = int(request.environ.get("CONTENT_LENGTH", 0))
parsed = parse_qs(request.environ["wsgi.input"].read(size))
else: else:
parsed = {} parsed = {}
for key, value in parsed.iteritems(): for key, value in parsed.iteritems():
@@ -50,8 +51,9 @@ def open_sql_connection(bot, dbname):
conn_args = bot.config.wiki["_copyviosSQL"][dbname] conn_args = bot.config.wiki["_copyviosSQL"][dbname]
if "read_default_file" not in conn_args and "user" not in conn_args and "passwd" not in conn_args: if "read_default_file" not in conn_args and "user" not in conn_args and "passwd" not in conn_args:
conn_args["read_default_file"] = expanduser("~/.my.cnf") conn_args["read_default_file"] = expanduser("~/.my.cnf")
elif "read_default_file" in args:
args["read_default_file"] = expanduser(args["read_default_file"])
elif "read_default_file" in conn_args:
default_file = expanduser(conn_args["read_default_file"])
conn_args["read_default_file"] = default_file
if "autoping" not in conn_args: if "autoping" not in conn_args:
conn_args["autoping"] = True conn_args["autoping"] = True
if "autoreconnect" not in conn_args: if "autoreconnect" not in conn_args:


+ 15
- 12
copyvios/settings.py View File

@@ -1,17 +1,18 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-


from flask import g
from markupsafe import escape from markupsafe import escape


from .cookies import set_cookie, delete_cookie from .cookies import set_cookie, delete_cookie
from .misc import get_bot, Query from .misc import get_bot, Query
from .sites import get_sites from .sites import get_sites


def main(context, environ, headers, cookies):
query = Query(environ, method="POST")
def main(context):
query = Query(method="POST")
if query.action == "set": if query.action == "set":
status = _do_set(query, headers, cookies)
status = _do_set(query)
elif query.action == "delete": elif query.action == "delete":
status = _do_delete(query, headers, cookies)
status = _do_delete(query)
else: else:
status = None status = None


@@ -19,37 +20,39 @@ def main(context, environ, headers, cookies):
langs, projects = get_sites(bot) langs, projects = get_sites(bot)
return bot, status, langs, projects return bot, status, langs, projects


def _do_set(query, headers, cookies):
def _do_set(query):
cookies = g.cookies
changes = set() changes = set()
if query.lang: if query.lang:
key = "CopyviosDefaultLang" key = "CopyviosDefaultLang"
if key not in cookies or cookies[key].value != query.lang: if key not in cookies or cookies[key].value != query.lang:
set_cookie(headers, cookies, key, query.lang, 1095)
set_cookie(key, query.lang, 1095)
changes.add("site") changes.add("site")
if query.project: if query.project:
key = "CopyviosDefaultProject" key = "CopyviosDefaultProject"
if key not in cookies or cookies[key].value != query.project: if key not in cookies or cookies[key].value != query.project:
set_cookie(headers, cookies, key, query.project, 1095)
set_cookie(key, query.project, 1095)
changes.add("site") changes.add("site")
if query.background: if query.background:
key = "CopyviosBackground" key = "CopyviosBackground"
if key not in cookies or cookies[key].value != query.background: if key not in cookies or cookies[key].value != query.background:
set_cookie(headers, cookies, key, query.background, 1095)
delete_cookie(headers, cookies, "EarwigBackgroundCache")
set_cookie(key, query.background, 1095)
delete_cookie("EarwigBackgroundCache")
changes.add("background") changes.add("background")
if changes: if changes:
changes = ", ".join(sorted(list(changes))) changes = ", ".join(sorted(list(changes)))
return "Updated {0}.".format(changes) return "Updated {0}.".format(changes)
return None return None


def _do_delete(query, headers, cookies):
def _do_delete(query):
cookies = g.cookies
if query.cookie in cookies: if query.cookie in cookies:
delete_cookie(headers, cookies, query.cookie.encode("utf8"))
delete_cookie(query.cookie.encode("utf8"))
template = u'Deleted cookie <b><span class="mono">{0}</span></b>.' template = u'Deleted cookie <b><span class="mono">{0}</span></b>.'
return template.format(escape(query.cookie)) return template.format(escape(query.cookie))
elif query.all: elif query.all:
number = len(cookies) number = len(cookies)
for cookie in cookies.values(): for cookie in cookies.values():
delete_cookie(headers, cookies, cookie.key)
delete_cookie(cookie.key)
return "Deleted <b>{0}</b> cookies.".format(number) return "Deleted <b>{0}</b> cookies.".format(number)
return None return None

+ 4
- 5
templates/debug.mako View File

@@ -1,11 +1,10 @@
<%include file="/support/header.mako" args="title='Debug - Earwig\'s Copyvio Detector', root=root, cookies=cookies"/>
<%include file="/support/header.mako" args="title='Debug - Earwig\'s Copyvio Detector'"/>
<%! from flask import request %>\
<ul> <ul>
% for key, value in environ.items():
% for key, value in request.environ.items():
% if key not in ["wsgi.input", "wsgi.errors", "PATH"]: % if key not in ["wsgi.input", "wsgi.errors", "PATH"]:
<li><b>${key}</b>: ${value | h}</li> <li><b>${key}</b>: ${value | h}</li>
% elif key == "wsgi.input":
<li><b>${key}</b>: ${value.read(int(environ.get("CONTENT_LENGTH", 0))) | h}</li>
% endif % endif
% endfor % endfor
</ul> </ul>
<%include file="/support/footer.mako" args="cookies=cookies"/>
<%include file="/support/footer.mako"/>

+ 2
- 2
templates/index.mako View File

@@ -1,4 +1,4 @@
<%include file="/support/header.mako" args="title='Earwig\'s Copyvio Detector', root=root, cookies=cookies"/>
<%include file="/support/header.mako" args="title='Earwig\'s Copyvio Detector'"/>
<%namespace module="copyvios" import="main, highlight_delta"/>\ <%namespace module="copyvios" import="main, highlight_delta"/>\
<%namespace module="copyvios.misc" import="urlstrip"/>\ <%namespace module="copyvios.misc" import="urlstrip"/>\
<% <%
@@ -158,4 +158,4 @@
</div> </div>
</div> </div>
% endif % endif
<%include file="/support/footer.mako" args="cookies=cookies"/>
<%include file="/support/footer.mako"/>

+ 18
- 14
templates/settings.mako View File

@@ -1,21 +1,25 @@
<%namespace module="copyvios.settings" import="main"/>\
<% bot, status, langs, projects = main(environ, headers, cookies) %>\
<%include file="/support/header.mako" args="title='Settings - Earwig\'s Copyvio Detector', root=root, cookies=cookies"/>
<%! from json import dumps, loads %>\
<%!
from json import dumps, loads

from flask import g, request
from copyvios.settings import main
%>\
<% bot, status, langs, projects = main() %>\
<%include file="/support/header.mako" args="title='Settings - Earwig\'s Copyvio Detector'"/>
% if status: % if status:
<div id="info-box" class="green-box"> <div id="info-box" class="green-box">
<p>${status}</p> <p>${status}</p>
</div> </div>
% endif % endif
<p>This page contains some configurable options for the copyvio detector. Settings are saved as cookies. You can view and delete all cookies generated by this site at the bottom of this page.</p> <p>This page contains some configurable options for the copyvio detector. Settings are saved as cookies. You can view and delete all cookies generated by this site at the bottom of this page.</p>
<form action="${environ['REQUEST_URI']}" method="post">
<form action="${request.base_url}" method="post">
<table> <table>
<tr> <tr>
<td>Default site:</td> <td>Default site:</td>
<td> <td>
<span class="mono">http://</span> <span class="mono">http://</span>
<select name="lang"> <select name="lang">
<% selected_lang = cookies["CopyviosDefaultLang"].value if "CopyviosDefaultLang" in cookies else bot.wiki.get_site().lang %>\
<% selected_lang = g.cookies["CopyviosDefaultLang"].value if "CopyviosDefaultLang" in g.cookies else bot.wiki.get_site().lang %>\
% for code, name in langs: % for code, name in langs:
% if code == selected_lang: % if code == selected_lang:
<option value="${code | h}" selected="selected">${name}</option> <option value="${code | h}" selected="selected">${name}</option>
@@ -26,7 +30,7 @@
</select> </select>
<span class="mono">.</span> <span class="mono">.</span>
<select name="project"> <select name="project">
<% selected_project = cookies["CopyviosDefaultProject"].value if "CopyviosDefaultProject" in cookies else bot.wiki.get_site().project %>\
<% selected_project = g.cookies["CopyviosDefaultProject"].value if "CopyviosDefaultProject" in g.cookies else bot.wiki.get_site().project %>\
% for code, name in projects: % for code, name in projects:
% if code == selected_project: % if code == selected_project:
<option value="${code | h}" selected="selected">${name}</option> <option value="${code | h}" selected="selected">${name}</option>
@@ -44,7 +48,7 @@
("potd", 'Use the current Commons Picture of the Day, unfiltered. Certain POTDs may be unsuitable as backgrounds due to their aspect ratio or subject matter.'), ("potd", 'Use the current Commons Picture of the Day, unfiltered. Certain POTDs may be unsuitable as backgrounds due to their aspect ratio or subject matter.'),
("plain", "Use a plain background."), ("plain", "Use a plain background."),
] ]
selected = cookies["CopyviosBackground"].value if "CopyviosBackground" in cookies else "list"
selected = g.cookies["CopyviosBackground"].value if "CopyviosBackground" in g.cookies else "list"
%>\ %>\
% for i, (value, desc) in enumerate(background_options): % for i, (value, desc) in enumerate(background_options):
<tr> <tr>
@@ -67,11 +71,11 @@
</table> </table>
</form> </form>
<h2>Cookies</h2> <h2>Cookies</h2>
% if cookies:
% if g.cookies:
<table> <table>
<% cookie_order = ["CopyviosDefaultProject", "CopyviosDefaultLang", "CopyviosBackground", "CopyviosShowDetails", "CopyviosScreenCache"] %>\ <% cookie_order = ["CopyviosDefaultProject", "CopyviosDefaultLang", "CopyviosBackground", "CopyviosShowDetails", "CopyviosScreenCache"] %>\
% for key in [key for key in cookie_order if key in cookies]:
<% cookie = cookies[key] %>\
% for key in [key for key in cookie_order if key in g.cookies]:
<% cookie = g.cookies[key] %>\
<tr> <tr>
<td><b><span class="mono">${key | h}</span></b></td> <td><b><span class="mono">${key | h}</span></b></td>
% try: % try:
@@ -85,7 +89,7 @@
<td><span class="mono">${cookie.value | h}</span></td> <td><span class="mono">${cookie.value | h}</span></td>
% endtry % endtry
<td> <td>
<form action="${environ['REQUEST_URI']}" method="post">
<form action="${request.base_url}" method="post">
<input type="hidden" name="action" value="delete"> <input type="hidden" name="action" value="delete">
<input type="hidden" name="cookie" value="${key | h}"> <input type="hidden" name="cookie" value="${key | h}">
<button type="submit">Delete</button> <button type="submit">Delete</button>
@@ -95,7 +99,7 @@
% endfor % endfor
<tr> <tr>
<td> <td>
<form action="${environ['REQUEST_URI']}" method="post">
<form action="${request.base_url}" method="post">
<input type="hidden" name="action" value="delete"> <input type="hidden" name="action" value="delete">
<input type="hidden" name="all" value="1"> <input type="hidden" name="all" value="1">
<button type="submit">Delete all</button> <button type="submit">Delete all</button>
@@ -106,4 +110,4 @@
% else: % else:
<p>No cookies!</p> <p>No cookies!</p>
% endif % endif
<%include file="/support/footer.mako" args="cookies=cookies"/>
<%include file="/support/footer.mako"/>

+ 3
- 4
templates/support/footer.mako View File

@@ -1,11 +1,10 @@
<%page args="cookies"/>\
<%namespace module="copyvios.background" import="get_desc_url"/>\
<%! from flask import g %>\
</div> </div>
<div id="footer"> <div id="footer">
<p>Copyright &copy; 2009&ndash;2014 <a href="//en.wikipedia.org/wiki/User:The_Earwig">Ben Kurtovic</a> &bull; \ <p>Copyright &copy; 2009&ndash;2014 <a href="//en.wikipedia.org/wiki/User:The_Earwig">Ben Kurtovic</a> &bull; \
<a href="https://github.com/earwig/copyvios">View Source</a> &bull; \ <a href="https://github.com/earwig/copyvios">View Source</a> &bull; \
% if ("CopyviosBackground" in cookies and cookies["CopyviosBackground"].value in ["potd", "list"]) or "CopyviosBackground" not in cookies:
<a href="${get_desc_url() | h}">Background</a> &bull; \
% if ("CopyviosBackground" in g.cookies and g.cookies["CopyviosBackground"].value in ["potd", "list"]) or "CopyviosBackground" not in g.cookies:
<a href="${g.descurl | h}">Background</a> &bull; \
% endif % endif
<a href="http://validator.w3.org/check?uri=referer">Valid HTML5</a> <a href="http://validator.w3.org/check?uri=referer">Valid HTML5</a>
</p> </p>


+ 12
- 9
templates/support/header.mako View File

@@ -1,24 +1,27 @@
<%page args="title, root, cookies"/>\
<%namespace module="copyvios.background" import="set_background"/>\
<%page args="title"/>\
<%!
from flask import g, request
from copyvios.background import set_background
%>\
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>${title}</title> <title>${title}</title>
<link rel="stylesheet" href="${root}/static/style.min.css" type="text/css" />
<script src="${root}/static/script.min.js" type="text/javascript"></script>
<link rel="stylesheet" href="${request.script_root}/static/style.min.css" type="text/css" />
<script src="${request.script_root}/static/script.min.js" type="text/javascript"></script>
</head> </head>
<% selected = cookies["CopyviosBackground"].value if "CopyviosBackground" in cookies else "list" %>\
<% selected = g.cookies["CopyviosBackground"].value if "CopyviosBackground" in g.cookies else "list" %>\
% if selected == "plain": % if selected == "plain":
<body style="background-image: url('${root}/static/background.png');">
<body style="background-image: url('${request.script_root}/static/background.png');">
% else: % else:
<body onload="update_screen_size()" style="background-image: url('${set_background(cookies, selected) | h}'); background-size: cover;">
<body onload="update_screen_size()" style="background-image: url('${set_background(selected) | h}'); background-size: cover;">
% endif % endif
<div id="header"> <div id="header">
<table id="heading"> <table id="heading">
<tr> <tr>
<td id="head-home"><a id="a-home" href="${root}">Earwig's Copyvio Detector</a></td>
<td id="head-settings"><a id="a-settings" href="${root}/settings">Settings</a></td>
<td id="head-home"><a id="a-home" href="${request.script_root}">Earwig's Copyvio Detector</a></td>
<td id="head-settings"><a id="a-settings" href="${request.script_root}/settings">Settings</a></td>
</tr> </tr>
</table> </table>
</div> </div>


Loading…
Cancel
Save