]> de.git.xonotic.org Git - xonotic/xonstat.git/blobdiff - xonstat/util.py
Remove braces from the hashkey text template.
[xonotic/xonstat.git] / xonstat / util.py
index 7c2692d45d51651605b2e78ba9ff98929fd7fd50..d8599303c324f332cf3dbbbe38c568989834c002 100644 (file)
@@ -1,7 +1,16 @@
+import logging
+import pyramid.httpexceptions
 import re
 from colorsys import rgb_to_hls, hls_to_rgb
 from cgi import escape as html_escape
 from datetime import datetime, timedelta
+from decimal import Decimal
+from collections import namedtuple
+from xonstat.d0_blind_id import d0_blind_id_verify
+
+
+log = logging.getLogger(__name__)
+
 
 # Map of special chars to ascii from Darkplace's console.c.
 _qfont_table = [
@@ -21,7 +30,7 @@ _qfont_table = [
  'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
  'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
  'x',  'y',  'z',  '{',  '|',  '}',  '~',  '<',
+
  '<',  '=',  '>',  '#',  '#',  '.',  '#',  '#',
  '#',  '#',  ' ',  '#',  ' ',  '>',  '.',  '.',
  '[',  ']',  '0',  '1',  '2',  '3',  '4',  '5',
@@ -101,13 +110,37 @@ def hex_repl(match):
     return '<span style="color:rgb(%d,%d,%d)">' % (255 * r, 255 * g, 255 * b)
 
 
-def html_colors(qstr=''):
-    qstr = html_escape(qfont_decode(qstr).replace('^^', '^'))
+def html_colors(qstr='', limit=None):
+    qstr = html_escape(qfont_decode(qstr))
+    qstr = qstr.replace('^^', '^')
+
+    if limit is not None and limit > 0:
+        qstr = limit_printable_characters(qstr, limit)
+
     html = _dec_colors.sub(lambda match: _dec_spans[int(match.group(1))], qstr)
     html = _hex_colors.sub(hex_repl, html)
     return html + "</span>" * len(_all_colors.findall(qstr))
 
 
+def limit_printable_characters(qstr, limit):
+    # initialize assuming all printable characters
+    pc = [1 for i in range(len(qstr))]
+
+    groups = _all_colors.finditer(qstr)
+    for g in groups:
+        pc[g.start():g.end()] = [0 for i in range(g.end() - g.start())]
+
+    # printable characters in the string is less than or equal to what was requested
+    if limit >= len(qstr) or sum(pc) <= limit:
+        return qstr
+    else:
+        sumpc = 0
+        for i,v in enumerate(pc):
+            sumpc += v
+            if sumpc == limit:
+                return qstr[0:i+1]
+
+
 def page_url(page):
     return current_route_url(request, page=page, _query=request.GET)
 
@@ -155,3 +188,87 @@ def pretty_date(time=False):
 def datetime_seconds(td):
     return float(td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6
 
+def to_json(data):
+    if not type(data) == dict:
+        # assume it's a named tuple
+        data = data._asdict()
+    result = {}
+    for key,value in data.items():
+        if value == None:
+            result[key] = None
+        elif type(value) in [bool,int,long,float,complex,str]:
+            result[key] = value
+        elif type(value) == unicode:
+            result[key] = value.encode('utf-8')
+        elif type(value) == Decimal:
+            result[key] = float(value)
+        elif type(value) == datetime:
+            result[key] = value.strftime('%Y-%m-%dT%H:%M:%SZ')
+        elif type(value) == timedelta:
+            result[key] = datetime_seconds(value)
+        else:
+            result[key] = to_json(value.to_dict())
+    return result
+
+
+def is_leap_year(today_dt=None):
+    if today_dt is None:
+        today_dt = datetime.utcnow()
+
+    if today_dt.year % 400 == 0:
+       leap_year = True
+    elif today_dt.year % 100 == 0:
+       leap_year = False
+    elif today_dt.year % 4 == 0:
+       leap_year = True
+    else:
+       leap_year = False
+
+    return leap_year
+
+
+def is_cake_day(create_dt, today_dt=None):
+    cake_day = False
+
+    if today_dt is None:
+        today_dt = datetime.utcnow()
+
+    # cakes are given on the first anniversary, not the actual create date!
+    if datetime.date(today_dt) != datetime.date(create_dt):
+        if today_dt.day == create_dt.day and today_dt.month == create_dt.month:
+            cake_day = True
+
+        # leap year people get their cakes on March 1
+        if not is_leap_year(today_dt) and create_dt.month == 2 and create_dt.day == 29:
+            if today_dt.month == 3 and today_dt.day == 1:
+                cake_day = True
+
+    return cake_day
+
+
+def verify_request(request):
+    """Verify requests using the d0_blind_id library"""
+
+    # first determine if we should be verifying or not
+    val_verify_requests = request.registry.settings.get('xonstat.verify_requests', 'true')
+    if val_verify_requests == "true":
+        flg_verify_requests = True
+    else:
+        flg_verify_requests = False
+
+    try:
+        (idfp, status) = d0_blind_id_verify(
+                sig=request.headers['X-D0-Blind-Id-Detached-Signature'],
+                querystring='',
+                postdata=request.body)
+
+        log.debug('\nidfp: {0}\nstatus: {1}'.format(idfp, status))
+    except:
+        idfp = None
+        status = None
+
+    if flg_verify_requests and not idfp:
+        log.debug("ERROR: Unverified request")
+        raise pyramid.httpexceptions.HTTPUnauthorized("Unverified request")
+
+    return (idfp, status)