From 59afacce691c1815013f5b37a97bef95e2d763a3 Mon Sep 17 00:00:00 2001 From: Kevin Chung Date: Sun, 21 May 2017 12:43:31 -0400 Subject: [PATCH] Fixes #261 and generally supports Unicode better in Python 2 (#263) * Fixing #261 and improving Unicode in Python2 * Fixing PEP8 issues --- .travis.yml | 2 +- CTFd/__init__.py | 6 ++++ CTFd/challenges.py | 16 +++++----- development.txt | 2 +- populate.py | 2 +- tests/helpers.py | 2 +- tests/test_user_facing.py | 63 ++++++++++++++++++++++++++++++++++++++- 7 files changed, 80 insertions(+), 13 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1a5f0f56b1..ceb7bb4467 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: python python: - 2.7 - - 3.5 + - 3.6 install: - pip install -r development.txt script: diff --git a/CTFd/__init__.py b/CTFd/__init__.py index 43a8858fa9..63e0714140 100644 --- a/CTFd/__init__.py +++ b/CTFd/__init__.py @@ -1,3 +1,4 @@ +import sys import os from distutils.version import StrictVersion @@ -11,6 +12,11 @@ from CTFd.utils import cache, migrate, migrate_upgrade, migrate_stamp from CTFd import utils +# Hack to support Unicode in Python 2 properly +if sys.version_info[0] < 3: + reload(sys) + sys.setdefaultencoding("utf-8") + __version__ = '1.0.2' diff --git a/CTFd/challenges.py b/CTFd/challenges.py index 9a139f85da..c386b2aac5 100644 --- a/CTFd/challenges.py +++ b/CTFd/challenges.py @@ -258,21 +258,21 @@ def chal(chalid): db.session.close() logger.warn("[{0}] {1} submitted {2} with kpm {3} [TOO FAST]".format(*data)) # return '3' # Submitting too fast - return jsonify({'status': '3', 'message': "You're submitting keys too fast. Slow down."}) + return jsonify({'status': 3, 'message': "You're submitting keys too fast. Slow down."}) solves = Solves.query.filter_by(teamid=session['id'], chalid=chalid).first() # Challange not solved yet if not solves: chal = Challenges.query.filter_by(id=chalid).first_or_404() - provided_key = unicode(request.form['key'].strip()) + provided_key = request.form['key'].strip() saved_keys = Keys.query.filter_by(chal=chal.id).all() # Hit max attempts max_tries = chal.max_attempts if max_tries and fails >= max_tries > 0: return jsonify({ - 'status': '0', + 'status': 0, 'message': "You have 0 tries remaining" }) @@ -284,7 +284,7 @@ def chal(chalid): db.session.commit() db.session.close() logger.info("[{0}] {1} submitted {2} with kpm {3} [CORRECT]".format(*data)) - return jsonify({'status': '1', 'message': 'Correct'}) + return jsonify({'status': 1, 'message': 'Correct'}) if utils.ctftime(): wrong = WrongKeys(teamid=session['id'], chalid=chalid, flag=provided_key) @@ -298,17 +298,17 @@ def chal(chalid): tries_str = 'tries' if attempts_left == 1: tries_str = 'try' - return jsonify({'status': '0', 'message': 'Incorrect. You have {} {} remaining.'.format(attempts_left, tries_str)}) + return jsonify({'status': 0, 'message': 'Incorrect. You have {} {} remaining.'.format(attempts_left, tries_str)}) else: - return jsonify({'status': '0', 'message': 'Incorrect'}) + return jsonify({'status': 0, 'message': 'Incorrect'}) # Challenge already solved else: logger.info("{0} submitted {1} with kpm {2} [ALREADY SOLVED]".format(*data)) # return '2' # challenge was already solved - return jsonify({'status': '2', 'message': 'You already solved this'}) + return jsonify({'status': 2, 'message': 'You already solved this'}) else: return jsonify({ - 'status': '-1', + 'status': -1, 'message': "You must be logged in to solve a challenge" }) diff --git a/development.txt b/development.txt index 39b4e54317..cfa2035652 100644 --- a/development.txt +++ b/development.txt @@ -3,4 +3,4 @@ coverage>=4.1 mock>=2.0.0 nose>=1.3.7 rednose>=1.1.1 -pep8==1.7.0 +pep8>=1.7.0 diff --git a/populate.py b/populate.py index 223c557400..08809f3ce6 100644 --- a/populate.py +++ b/populate.py @@ -231,7 +231,7 @@ def random_date(start, end): for x in range(AMT_CHALS_WITH_FILES): chal = random.randint(1, CHAL_AMOUNT) filename = gen_file() - md5hash = hashlib.md5(filename).hexdigest() + md5hash = hashlib.md5(filename.encode('utf-8')).hexdigest() db.session.add(Files(chal, md5hash + '/' + filename)) db.session.commit() diff --git a/tests/helpers.py b/tests/helpers.py index b17db88a74..5e9a92cf42 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -86,7 +86,7 @@ def gen_file(): pass -def gen_key(db, chal, flag='flag', key_type=0): +def gen_flag(db, chal, flag='flag', key_type=0): key = Keys(chal, flag, key_type) db.session.add(key) db.session.commit() diff --git a/tests/test_user_facing.py b/tests/test_user_facing.py index 8a489aebec..5a1bc8dedc 100644 --- a/tests/test_user_facing.py +++ b/tests/test_user_facing.py @@ -1,4 +1,7 @@ -from tests.helpers import create_ctfd, register_user, login_as_user, gen_challenge +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from tests.helpers import * from CTFd.models import Teams import json @@ -205,3 +208,61 @@ def test_viewing_challenges(): r = client.get('/chals') chals = json.loads(r.get_data(as_text=True)) assert len(chals['game']) == 1 + + +def test_submitting_correct_flag(): + """Test that correct flags are correct""" + app = create_ctfd() + with app.app_context(): + register_user(app) + client = login_as_user(app) + chal = gen_challenge(app.db) + flag = gen_flag(app.db, chal=chal.id, flag='flag') + with client.session_transaction() as sess: + data = { + "key": 'flag', + "nonce": sess.get('nonce') + } + r = client.post('/chal/{}'.format(chal.id), data=data) + assert r.status_code == 200 + resp = json.loads(r.data.decode('utf8')) + assert resp.get('status') == 1 and resp.get('message') == "Correct" + + +def test_submitting_incorrect_flag(): + """Test that incorrect flags are incorrect""" + app = create_ctfd() + with app.app_context(): + register_user(app) + client = login_as_user(app) + chal = gen_challenge(app.db) + flag = gen_flag(app.db, chal=chal.id, flag='flag') + with client.session_transaction() as sess: + data = { + "key": 'notflag', + "nonce": sess.get('nonce') + } + r = client.post('/chal/{}'.format(chal.id), data=data) + assert r.status_code == 200 + resp = json.loads(r.data.decode('utf8')) + assert resp.get('status') == 0 and resp.get('message') == "Incorrect" + + +def test_submitting_unicode_flag(): + """Test that users can submit a unicode flag""" + print("Test that users can submit a flag") + app = create_ctfd() + with app.app_context(): + register_user(app) + client = login_as_user(app) + chal = gen_challenge(app.db) + flag = gen_flag(app.db, chal=chal.id, flag=u'你好') + with client.session_transaction() as sess: + data = { + "key": '你好', + "nonce": sess.get('nonce') + } + r = client.post('/chal/{}'.format(chal.id), data=data) + assert r.status_code == 200 + resp = json.loads(r.data.decode('utf8')) + assert resp.get('status') == 1 and resp.get('message') == "Correct"